A simple python wrapper for using the Caddy API
Project description
fastcaddy
Usage
Installation
Install from pypi
$ pip install fastcaddy
Installing Caddy
This project is to help you use the caddy API, rather than a Caddyfile, to use caddy. To use the API, you need to install a plugin for your domain management service. We use Cloudflare, so we’ll document that here. For other domain services, see the Caddy docs for other plugins.
Cloudflare setup
from fastcore.utils import *
You’ll need a token from Cloudflare with access to modify the necessary settings. Here’s the steps to create a token with the minimal privileges. You’ll need to install the cloudflare pip package, then import:
from cloudflare import Cloudflare
Then you’ll need create a Cloudflare API token for your user, which we’ll then use to create the less privileged token.
cf_token = os.environ['CLOUDFLARE_API_TOKEN']
We can now check that works OK:
cf = Cloudflare(api_token=cf_token)
zones = cf.zones.list()
len(zones.result)
8
Replace this with your domain name:
domain = 'answer.ai'
zones = cf.zones.list(name=domain)
assert len(zones.result)==1
zone_id = zones.result[0].id
Here’s the methods available for modifying DNS records:
client.dns.records.create(*, zone_id, **params) -> Optional
client.dns.records.update(dns_record_id, *, zone_id, **params) -> Optional
client.dns.records.list(*, zone_id, **params) -> SyncV4PagePaginationArray[Record]
client.dns.records.delete(dns_record_id, *, zone_id) -> Optional
client.dns.records.edit(dns_record_id, *, zone_id, **params) -> Optional
client.dns.records.export(*, zone_id) -> str
client.dns.records.get(dns_record_id, *, zone_id) -> Optional
client.dns.records.import\_(*, zone_id, **params) -> Optional
client.dns.records.scan(*, zone_id, **params) -> Optional
…and here’s the methods for tokens:
from cloudflare.types.user import (CIDRList, Policy, Token, TokenCreateResponse, TokenUpdateResponse, TokenListResponse,
TokenDeleteResponse, TokenGetResponse, TokenVerifyResponse)
client.user.tokens.create(**params) -> Optional
client.user.tokens.update(token_id, **params) -> object
client.user.tokens.list(**params) -> SyncV4PagePaginationArray[object]
client.user.tokens.delete(token_id) -> Optional
client.user.tokens.get(token_id) -> object
client.user.tokens.verify() -> Optional
from cloudflare.types.user.tokens import PermissionGroupListResponse
- client.user.tokens.permission_groups.list() -> SyncSinglePage[object]
from cloudflare.types.user.tokens import Value
- client.user.tokens.value.update(token_id, **params) -> str
We need these two permissions in our token:
permission_groups = cf.user.tokens.permission_groups.list()
dns_write = next(group for group in permission_groups if group['name'] == 'DNS Write')
zone_read = next(group for group in permission_groups if group['name'] == 'Zone Read')
Now we can create it:
new_token = cf.user.tokens.create(
name='caddy_dns',
policies=[{
"effect": "allow",
"resources": { f"com.cloudflare.api.account.zone.{zone_id}": "*" },
"permission_groups": [
{"id": zone_read['id'], "name": "Zone Read"},
{"id": dns_write['id'], "name": "DNS Write"}
]
}]
)
print(new_token.value)
Make a copy of this value, which we’ll need for setting up caddy.
Installing caddy
To install caddy, we’ll use a tool called xcaddy
. This is written in
go. So first install go:
- Mac:
brew install go
- Linux:
sudo apt install golang
Note that if you are not on the latest Ubuntu, you’ll need to setup the backport repo before installing go:
sudo add-apt-repository -y ppa:longsleep/golang-backports
sudo apt update
Now we can install xcaddy:
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
Alternatively, you can download the latest xcaddy directly, e.g:
# Change the OS and arch as needed, or remove them to view all options
wget -qO- https://latest.fast.ai/latest/caddyserver/xcaddy/linux_amd64.tar.gz
Then we use that to compile caddy with our desired domain plugin (cloudflare, in this case):
mkdir -p ~/go/bin
cd ~/go/bin
./xcaddy build --with github.com/caddy-dns/cloudflare
This gives us a ~/go/bin/caddy
binary we can run:
./caddy version
./caddy run
Securely run caddy on start
If you’re using a server or running caddy a lot, you’ll want it to run
on start. And if you’re making it publicly accessible, you’ll want it to
be secure. This isn’t needed otherwise – you can just
~/go/bin/caddy run
to run it manually (you may want to add ~/go/bin
to your PATH
env var).
To set this up, run from this repo root:
./setup_service.sh
If all went well, you should see output like this:
● caddy.service - Caddy
Loaded: loaded (/etc/systemd/system/caddy.service; enabled; preset: enabled)
Active: active (running) since Sat 2024-11-09 05:06:47 UTC; 2 days ago
Docs: https://caddyserver.com/docs/
Main PID: 138140 (caddy)
Tasks: 29 (limit: 154166)
Memory: 19.3M (peak: 28.8M)
CPU: 3min 37.216s
CGroup: /system.slice/caddy.service
└─138140 /usr/bin/caddy run --environ
How to use
We will now show how to set up caddy as a reverse proxy for hosts added dynamically. We’ll grab our token from the previous step (assuming here that it’s stored in an env var):
cf_token = os.environ.get('CADDY_CF_TOKEN', 'XXX')
We can now setup the basic routes needed for caddy:
setup_caddy(cf_token)
To view the configuration created, use
gcfg
:
gcfg()
{ 'apps': { 'http': { 'servers': { 'srv0': { 'listen': [':80', ':443'],
'routes': []}}},
'tls': { 'automation': { 'policies': [{'issuers': [{'challenges': {'dns': {'provider': {'api_token': 'XXX', 'name': 'cloudflare'}}}, 'module': 'acme'}]}]}}}}
You can also view a sub-path of the configuration:
gcfg('/apps/http/servers')
{'srv0': {'listen': [':80', ':443'], 'routes': []}}
To add a reverse proxy, use
add_reverse_proxy
:
host = 'jph.answer.ai'
add_reverse_proxy(host, 'localhost:5001')
This is automatically added with an id matching the host, which you can
view with
gid
:
gid('jph.answer.ai')
{ '@id': 'jph.answer.ai',
'handle': [{'handler': 'reverse_proxy', 'upstreams': [{'dial': 'localhost:5001'}]}],
'match': [{'host': ['jph.answer.ai']}],
'terminal': True}
If you call this again with the same host, it will be replaced:
add_reverse_proxy(host, 'localhost:8000')
gid('jph.answer.ai').handle[0]
{'handler': 'reverse_proxy', 'upstreams': [{'dial': 'localhost:8000'}]}
To remove a host, delete its id:
del_id(host)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file fastcaddy-0.0.3.tar.gz
.
File metadata
- Download URL: fastcaddy-0.0.3.tar.gz
- Upload date:
- Size: 12.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.8
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 874d82c29d576a97d5996de971ea333b2ac43d1ba04f429d46c77dac155e7eb9 |
|
MD5 | 27c71cdfd8ea9f9861aad1c1f26fa36d |
|
BLAKE2b-256 | 828add24a1f8e75136215fc59932915a70da690ef36d73b92ab09ecf1708fdf0 |
File details
Details for the file fastcaddy-0.0.3-py3-none-any.whl
.
File metadata
- Download URL: fastcaddy-0.0.3-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.8
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ac0cda0f1238e131e4a4862736372e318be9a0607881dd1b4732082b4647c57a |
|
MD5 | 697815b78ab78e97e9e6cc166b98aa69 |
|
BLAKE2b-256 | 966c3012f5e73f7b5763a94bad919fe7abb9093896425ba6cd716b9019b0d1ed |