{"id":28469788,"url":"https://github.com/answerdotai/fastcaddy","last_synced_at":"2025-07-01T15:30:45.866Z","repository":{"id":262383875,"uuid":"886985958","full_name":"AnswerDotAI/fastcaddy","owner":"AnswerDotAI","description":"A simple python wrapper for using the Caddy API","archived":false,"fork":false,"pushed_at":"2025-05-14T00:52:16.000Z","size":413,"stargazers_count":19,"open_issues_count":5,"forks_count":1,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-06-30T15:59:25.769Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://answerdotai.github.io/fastcaddy/","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AnswerDotAI.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-11-12T01:02:58.000Z","updated_at":"2025-04-18T22:19:35.000Z","dependencies_parsed_at":"2025-04-18T23:41:16.776Z","dependency_job_id":"f71a15c8-b964-4992-897b-a45afcc7451f","html_url":"https://github.com/AnswerDotAI/fastcaddy","commit_stats":null,"previous_names":["answerdotai/fastcaddy"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/AnswerDotAI/fastcaddy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnswerDotAI%2Ffastcaddy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnswerDotAI%2Ffastcaddy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnswerDotAI%2Ffastcaddy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnswerDotAI%2Ffastcaddy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AnswerDotAI","download_url":"https://codeload.github.com/AnswerDotAI/fastcaddy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnswerDotAI%2Ffastcaddy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262989964,"owners_count":23395901,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-07T09:08:40.903Z","updated_at":"2025-07-01T15:30:45.856Z","avatar_url":"https://github.com/AnswerDotAI.png","language":"Jupyter Notebook","readme":"# fastcaddy\n\n\n\u003c!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! --\u003e\n\n## Usage\n\n### Installation\n\nInstall from [pypi](https://pypi.org/project/fastcaddy/)\n\n``` sh\n$ pip install fastcaddy\n```\n\n## Installing Caddy\n\nThis project is to help you use the caddy API, rather than a Caddyfile,\nto use caddy. To use the API, you need to install a plugin for your\ndomain management service. We use Cloudflare, so we’ll document that\nhere. For other domain services, see the Caddy docs for other plugins.\n\n### Cloudflare setup\n\n``` python\nfrom fastcore.utils import *\n```\n\nYou’ll need a token from Cloudflare with access to modify the necessary\nsettings. Here’s the steps to create a token with the minimal\nprivileges. You’ll need to install the cloudflare pip package, then\nimport:\n\n``` python\nfrom cloudflare import Cloudflare\n```\n\nThen you’ll need create a Cloudflare API token for your user, which\nwe’ll then use to create the less privileged token.\n\n``` python\ncf_token = os.environ['CLOUDFLARE_API_TOKEN']\n```\n\nWe can now check that works OK:\n\n``` python\ncf = Cloudflare(api_token=cf_token)\nzones = cf.zones.list()\nlen(zones.result)\n```\n\n    8\n\nReplace this with your domain name:\n\n``` python\ndomain = 'answer.ai'\nzones = cf.zones.list(name=domain)\nassert len(zones.result)==1\n```\n\n``` python\nzone_id = zones.result[0].id\n```\n\nHere’s the methods available for modifying DNS records:\n\n- `client.dns.records.create(*, zone_id, **params) -\u003e Optional`\n- `client.dns.records.update(dns_record_id, *, zone_id, **params) -\u003e Optional`\n- `client.dns.records.list(*, zone_id, **params) -\u003e SyncV4PagePaginationArray[Record]`\n- `client.dns.records.delete(dns_record_id, *, zone_id) -\u003e Optional`\n- `client.dns.records.edit(dns_record_id, *, zone_id, **params) -\u003e Optional`\n- `client.dns.records.export(*, zone_id) -\u003e str`\n- `client.dns.records.get(dns_record_id, *, zone_id) -\u003e Optional`\n- `client.dns.records.import\\_(*, zone_id, **params) -\u003e Optional`\n- `client.dns.records.scan(*, zone_id, **params) -\u003e Optional`\n\n…and here’s the methods for tokens:\n\n``` python\nfrom cloudflare.types.user import (CIDRList, Policy, Token, TokenCreateResponse, TokenUpdateResponse, TokenListResponse,\n                                   TokenDeleteResponse, TokenGetResponse, TokenVerifyResponse)\n```\n\n- `client.user.tokens.create(**params) -\u003e Optional`\n- `client.user.tokens.update(token_id, **params) -\u003e object`\n- `client.user.tokens.list(**params) -\u003e SyncV4PagePaginationArray[object]`\n- `client.user.tokens.delete(token_id) -\u003e Optional`\n- `client.user.tokens.get(token_id) -\u003e object`\n- `client.user.tokens.verify() -\u003e Optional`\n\n``` python\nfrom cloudflare.types.user.tokens import PermissionGroupListResponse\n```\n\n- client.user.tokens.permission_groups.list() -\\\u003e\n  SyncSinglePage\\[object\\]\n\n``` python\nfrom cloudflare.types.user.tokens import Value\n```\n\n- client.user.tokens.value.update(token_id, \\*\\*params) -\\\u003e str\n\nWe need these two permissions in our token:\n\n``` python\npermission_groups = cf.user.tokens.permission_groups.list()\n\ndns_write = next(group for group in permission_groups if group['name'] == 'DNS Write')\nzone_read = next(group for group in permission_groups if group['name'] == 'Zone Read')\n```\n\nNow we can create it:\n\n``` python\nnew_token = cf.user.tokens.create(\n    name='caddy_dns',\n    policies=[{\n        \"effect\": \"allow\",\n        \"resources\": { f\"com.cloudflare.api.account.zone.{zone_id}\": \"*\" },\n        \"permission_groups\": [\n            {\"id\": zone_read['id'], \"name\": \"Zone Read\"},\n            {\"id\": dns_write['id'], \"name\": \"DNS Write\"}\n        ]\n    }]\n)\n\nprint(new_token.value)\n```\n\nMake a copy of this value, which we’ll need for setting up caddy.\n\n### Installing caddy\n\nTo install caddy, we’ll use a tool called `xcaddy`. This is written in\ngo. So first install go:\n\n- Mac: `brew install go`\n- Linux: `sudo apt install golang`\n\nNote that if you are not on the latest Ubuntu, you’ll need to setup the\nbackport repo before installing go:\n\n``` sh\nsudo add-apt-repository -y ppa:longsleep/golang-backports\nsudo apt update\n```\n\nNow we can install xcaddy:\n\n``` sh\ngo install github.com/caddyserver/xcaddy/cmd/xcaddy@latest\n```\n\nAlternatively, you can download the latest xcaddy directly, e.g:\n\n``` sh\n# Change the OS and arch as needed, or remove them to view all options\nwget -qO- https://latest.fast.ai/latest/caddyserver/xcaddy/linux_amd64.tar.gz\n```\n\nThen we use that to compile caddy with our desired domain plugin\n(cloudflare, in this case):\n\n``` sh\nmkdir -p ~/go/bin\ncd ~/go/bin\n./xcaddy build --with github.com/caddy-dns/cloudflare\n```\n\nThis gives us a `~/go/bin/caddy` binary we can run:\n\n``` sh\n./caddy version\n./caddy run\n```\n\n### Securely run caddy on start\n\nIf you’re using a server or running caddy a lot, you’ll want it to run\non start. And if you’re making it publicly accessible, you’ll want it to\nbe secure. This isn’t needed otherwise – you can just\n`~/go/bin/caddy run` to run it manually (you may want to add `~/go/bin`\nto your `PATH` env var).\n\nTo set this up, run from this repo root:\n\n``` sh\n./setup_service.sh\n```\n\nIf all went well, you should see output like this:\n\n``` sh\n● caddy.service - Caddy\n     Loaded: loaded (/etc/systemd/system/caddy.service; enabled; preset: enabled)\n     Active: active (running) since Sat 2024-11-09 05:06:47 UTC; 2 days ago\n       Docs: https://caddyserver.com/docs/\n   Main PID: 138140 (caddy)\n      Tasks: 29 (limit: 154166)\n     Memory: 19.3M (peak: 28.8M)\n        CPU: 3min 37.216s\n     CGroup: /system.slice/caddy.service\n             └─138140 /usr/bin/caddy run --environ\n```\n\n## How to use\n\nWe will now show how to set up caddy as a reverse proxy for hosts added\ndynamically. We’ll grab our token from the previous step (assuming here\nthat it’s stored in an env var):\n\n``` python\ncf_token = os.environ.get('CADDY_CF_TOKEN', 'XXX')\n```\n\nWe can now setup the basic routes needed for caddy:\n\n``` python\nsetup_caddy(cf_token)\n```\n\nTo view the configuration created, use\n[`gcfg`](https://AnswerDotAI.github.io/fastcaddy/core.html#gcfg):\n\n``` python\ngcfg()\n```\n\n``` json\n{ 'apps': { 'http': { 'servers': { 'srv0': { 'listen': [':80', ':443'],\n                                             'routes': []}}},\n            'tls': { 'automation': { 'policies': [{'issuers': [{'challenges': {'dns': {'provider': {'api_token': 'XXX', 'name': 'cloudflare'}}}, 'module': 'acme'}]}]}}}}\n```\n\nYou can also view a sub-path of the configuration:\n\n``` python\ngcfg('/apps/http/servers')\n```\n\n``` json\n{'srv0': {'listen': [':80', ':443'], 'routes': []}}\n```\n\nTo add a reverse proxy, use\n[`add_reverse_proxy`](https://AnswerDotAI.github.io/fastcaddy/core.html#add_reverse_proxy):\n\n``` python\nhost = 'jph.answer.ai'\nadd_reverse_proxy(host, 'localhost:5001')\n```\n\nThis is automatically added with an id matching the host, which you can\nview with\n[`gid`](https://AnswerDotAI.github.io/fastcaddy/core.html#gid):\n\n``` python\ngid('jph.answer.ai')\n```\n\n``` json\n{ '@id': 'jph.answer.ai',\n  'handle': [{'handler': 'reverse_proxy', 'upstreams': [{'dial': 'localhost:5001'}]}],\n  'match': [{'host': ['jph.answer.ai']}],\n  'terminal': True}\n```\n\nIf you call this again with the same host, it will be replaced:\n\n``` python\nadd_reverse_proxy(host, 'localhost:8000')\ngid('jph.answer.ai').handle[0]\n```\n\n``` json\n{'handler': 'reverse_proxy', 'upstreams': [{'dial': 'localhost:8000'}]}\n```\n\nTo remove a host, delete its id:\n\n``` python\ndel_id(host)\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanswerdotai%2Ffastcaddy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanswerdotai%2Ffastcaddy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanswerdotai%2Ffastcaddy/lists"}