Skip to main content

fastcaddy

Usage

Installation

Install from pypi

$ pip install fastcaddy

Installing Caddy

from fastcore.utils import *

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

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.

fastcaddy talks to caddy’s admin API, and config set that way is ephemeral: it doesn’t survive a caddy restart. So the recommended pattern is a setup script that runs on every deploy (e.g. from systemd): call reset(), then the functions below for everything you host. Each function is safe to re-run – routes are tagged with predictable @ids (the hostname, or wildcard-{domain}), and re-adding one replaces it rather than duplicating it – so the script is the single source of truth for your routing config.

Initial setup

We’ll grab our token from the previous step (assuming here that it’s stored in an env var):

cf_token = os.environ.get('AAI_CF_TOKEN', 'XXX')

source

setup_caddy

setup_caddy (cf_token, srv_name='srv0')

Create SSL config and HTTP app skeleton

We can now setup the basic routes needed for caddy:

setup_caddy(cf_token)

source

gcfg

gcfg (path='/', method='get')

Gets the config at path

To view the configuration created, use gcfg:

# gcfg()

You can also view a sub-path of the configuration:

gcfg('/apps/http/servers')
{'srv0': {'listen': [':80', ':443'], 'routes': []}}

Reverse proxies


source

add_reverse_proxy

add_reverse_proxy (from_host, to_url)

Create a reverse proxy handler

To add a reverse proxy, use add_reverse_proxy:

host = 'jph.answer.ai'
add_reverse_proxy(host, 'localhost:5001')

source

gid

gid (path='/')

Gets the id at path

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[1]
{'handler': 'reverse_proxy', 'upstreams': [{'dial': 'localhost:8000'}]}

source

del_id

del_id (id)

Delete route for id (e.g. a host)

To remove a host, delete its id:

del_id(host)

Wildcard subdomains

Caddy can create a wildcard SSL cert. To do so, add a wildcard route (a no-op if it already exists, so existing subdomains inside it are never destroyed):


source

add_wildcard_route

add_wildcard_route (domain)

Add a wildcard subdomain

add_wildcard_route('something.fast.ai')

Create reverse proxies in a wildcard domain requires using a special function:


source

add_sub_reverse_proxy

add_sub_reverse_proxy (domain, subdomain, port)

Add a reverse proxy to a wildcard subdomain

add_sub_reverse_proxy('something.fast.ai', 'foo', 5001)

These subdomains can be deleted in the usual way:

del_id('foo.something.fast.ai')

Metadata

Release files for fastcaddy 0.0.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastcaddy 0.0.12
File Size Uploaded Provenance Actions
fastcaddy-0.0.12.tar.gz 119.3 kB Without provenance Details for fastcaddy-0.0.12.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for fastcaddy 0.0.12
File Interpreter ABI Platform Actions
fastcaddy-0.0.12-py3-none-any.whl Python 3 none any Details for fastcaddy-0.0.12-py3-none-any.whl

Total release size: 236.6 kB

Release files / fastcaddy-0.0.12.tar.gz

Download URL fastcaddy-0.0.12.tar.gz
Size 119.3 kB
Tags Source
SHA-256 checksum
How to use checksums
8243aaf6bda6b53e5e072ed4bed941edf51a3a99b899bda9d306b5ad3b11ecee
BLAKE2b-256 checksum
How to use checksums
c8af10022e12db606d315ef988f6dfe4eb530b4982c792b2a17bb5c297751098
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / fastcaddy-0.0.12-py3-none-any.whl

Download URL fastcaddy-0.0.12-py3-none-any.whl
Size 117.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9cb11c38b7c542ebf96113f7d680b44b0b4059d4eb0a54d1adbcb1d2fc7ef72f
BLAKE2b-256 checksum
How to use checksums
595deee5ac8278a475db0f065417050d5f00dd76681f3936c6d0606939b1c23d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Security for fastcaddy 0.0.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page