Case Study: deSEC + AdGuard + Python HTTP Service
This walkthrough shows a realistic local setup using:
- DNS provider:
desec - One backend from
python3 -m http.server - One backend from AdGuard Home (Docker)
certify-reversefor wildcard DNS + HTTPS reverse proxy
All tokens/hostnames here are examples.
Note: wildcard CNAME is not required for DNS-01.
1) Prepare config files
cp .env.example .env
cp upstreams.yml.example upstreams.yml
Edit .env:
DOMAIN=fkr.dev
ACME_EMAIL=ops@example.invalid
DNS_PROVIDER=desec
DNS_TOKEN=desec_fake_token_1234567890
# Optional pin
CADDY_VERSION=v2.10.2
# Wildcard DNS target for local clients
DNSMASQ_ADDRESS_MODE=manual
DNSMASQ_ADDRESS_IP=10.0.0.1
2) Start demo backend 1 (python http.server)
mkdir -p /tmp/demo-site
cat >/tmp/demo-site/index.html <<'HTML'
<h1>python demo service</h1>
<p>served by python3 -m http.server</p>
HTML
python3 -m http.server 8080 --bind 0.0.0.0 --directory /tmp/demo-site
Keep it running in a separate terminal.
3) Start demo backend 2 (AdGuard Home)
docker run -d \
--name adguardhome \
--restart unless-stopped \
-v adguard-work:/opt/adguardhome/work \
-v adguard-conf:/opt/adguardhome/conf \
-p 3000:3000 \
-p 8081:80 \
adguard/adguardhome:latest
Notes:
- Port 8081 exposes AdGuard web UI on the host.
- First-run wizard is usually on http://localhost:3000.
4) Configure upstreams
Edit upstreams.yml:
demo:
ip: 10.0.0.1
port: 8080
scheme: http
adguard:
ip: 10.0.0.1
port: 8081
scheme: http
If your host IP is different, replace 10.0.0.1.
5) Start certify-reverse stack
./caddy-docker.sh start
Check runtime:
./caddy-docker.sh status
./caddy-docker.sh logs --follow
./caddy-docker.sh print-caddyfile
6) Test routed HTTPS endpoints
Before testing, choose one DNS client strategy:
Option A (typical): DHCP/network DNS points clients to dnsmasq
Configure your router/DHCP server to advertise the reverse-proxy host (running dnsmasq) as DNS server for clients.
- Pros: closest to production-like LAN behavior.
- Result: all clients on the network resolve
*.fkr.devautomatically.
Option B: local resolver override on one machine
Temporarily point one test machine to the dnsmasq host as DNS resolver.
- Linux (example): set resolver in NetworkManager/systemd-resolved for that interface.
- macOS (example): set DNS server for the active network service.
- Windows (example): set adapter DNS server manually.
Use the reverse-proxy host IP (for example 10.0.0.1) as DNS server.
Option C: /etc/hosts quick single-host checks
For very quick checks without DNS changes, add explicit host entries:
127.0.0.1 status.fkr.dev
127.0.0.1 demo.fkr.dev
127.0.0.1 adguard.fkr.dev
Notes:
- /etc/hosts does not support wildcards.
- If reverse-proxy runs on another host, replace 127.0.0.1 with that host IP.
Then test from a client that can resolve those names:
https://demo.fkr.devhttps://adguard.fkr.devhttps://status.fkr.dev
Quick probe:
curl -kI https://demo.fkr.dev
curl -kI https://adguard.fkr.dev
(-k is only for initial local trust/bootstrap testing.)
7) Trust internal CA for local clients (optional)
Export cert bundle:
./caddy-docker.sh app --export-certs
Then distribute caddy-internal-ca.pem/.crt to local clients or upstream containers as needed.
8) Operational tips
- Rebuild Caddy with provider plugin:
./caddy-docker.sh rebuild-caddy
- Re-check available upgrades:
./caddy-docker.sh check-updates
- Reload dnsmasq after DNS-related changes:
./caddy-docker.sh reload-dnsmasq
9) Cleanup demo services
docker rm -f adguardhome
docker volume rm adguard-work adguard-conf
pkill -f "python3 -m http.server 8080" || true