CLI for managing a home-server hosting platform backed by Cloudflare Tunnel, Traefik, and Docker Compose.
Project description
homesrvctl
MIT licensed.
homesrvctl is a production-oriented Python CLI for managing a home-server hosting platform built around:
- Cloudflare DNS
- a locally managed Cloudflare Tunnel via
cloudflared - Traefik for local hostname routing
- Docker Compose for workloads
- a shared external Docker network named
web
It automates the repetitive parts of:
- adding apex and wildcard tunnel DNS routes for a new domain
- reconciling local
cloudflaredingress entries for new domains - scaffolding static sites and app directories
- starting and stopping per-hostname Compose stacks
- validating the local hosting environment
- diagnosing a specific hostname
Assumptions
homesrvctl intentionally preserves the existing operating model:
- Cloudflare Tunnel handles domain-level ingress
- Traefik handles hostname routing on the server
- Docker Compose runs each site or app
- once
example.comand*.example.comare routed to the tunnel, additional subdomains only need local server changes
The tool assumes:
- Linux on the server
cloudflaredis already installed and configureddockeranddocker composeare already installed- Traefik is already working
- a shared external Docker network such as
webalready exists - the Cloudflare Tunnel is locally managed and already functional
Installation
From the project directory:
python -m venv .venv
source .venv/bin/activate
pip install -e .
From a tagged GitHub release:
pip install "homesrvctl @ https://github.com/Broda/homesrvctl/archive/refs/tags/v0.2.0.tar.gz"
The published Python distribution name is homesrvctl. The CLI command remains homesrvctl.
homesrvctl currently uses GitHub releases as its public release channel. Tagged releases publish to TestPyPI first. Production PyPI publishing is not enabled yet.
Configuration
Initialize the default config:
homesrvctl config init
homesrvctl config init --json
That writes:
~/.config/homesrvctl/config.yml
Default config shape:
tunnel_name: homesrvctl-tunnel
sites_root: /srv/homesrvctl/sites
docker_network: web
traefik_url: http://localhost:8081
cloudflared_config: /etc/cloudflared/config.yml
cloudflare_api_token: ""
cloudflare_api_token may also be supplied via the CLOUDFLARE_API_TOKEN environment variable.
It should have at least Zone:Read and DNS:Edit for the zones you want homesrvctl domain add to manage.
Usage
Create config:
homesrvctl config init
Add DNS tunnel routes for a domain:
homesrvctl domain add example.com
homesrvctl domain status example.com
homesrvctl domain repair example.com --dry-run
homesrvctl domain remove example.com --dry-run
Scaffold and run a static site:
homesrvctl site init example.com
homesrvctl up example.com
Scaffold and run a subdomain site:
homesrvctl site init notes.example.com
homesrvctl up notes.example.com
Scaffold a Node app:
homesrvctl app init app.example.com --template node
Scaffold a Python app:
homesrvctl app init api.example.com --template python
Inspect the stack:
homesrvctl list
homesrvctl cloudflared status
homesrvctl cloudflared config-test
homesrvctl cloudflared logs
homesrvctl validate
homesrvctl doctor test.example.com
Preview without changing anything:
homesrvctl domain add example.com --dry-run
homesrvctl domain add example.com --dry-run --restart-cloudflared
homesrvctl domain add example.com --dry-run --json
homesrvctl domain status example.com
homesrvctl domain status example.com --json
homesrvctl domain repair example.com --dry-run --json
homesrvctl domain remove example.com --dry-run --json
homesrvctl list --json
homesrvctl cloudflared status --json
homesrvctl cloudflared config-test --json
homesrvctl cloudflared logs --follow --json
homesrvctl cloudflared restart --dry-run
homesrvctl cloudflared restart --dry-run --json
homesrvctl up example.com --dry-run --json
homesrvctl down example.com --dry-run --json
homesrvctl restart example.com --dry-run --json
homesrvctl validate --json
homesrvctl doctor example.com --json
homesrvctl site init example.com --dry-run --json
homesrvctl app init app.example.com --template node --dry-run --json
homesrvctl app init api.example.com --template python --dry-run --json
homesrvctl up example.com --dry-run
Command Overview
homesrvctl config init [--path PATH] [--force] [--json]homesrvctl domain add <domain> [--dry-run] [--json] [--restart-cloudflared]homesrvctl domain status <domain> [--json]homesrvctl domain repair <domain> [--dry-run] [--json] [--restart-cloudflared]homesrvctl domain remove <domain> [--dry-run] [--json] [--restart-cloudflared]homesrvctl site init <hostname> [--force] [--dry-run] [--json]homesrvctl app init <hostname> [--template static|placeholder|node|python] [--force] [--dry-run] [--json]homesrvctl up <hostname> [--dry-run] [--json]homesrvctl down <hostname> [--dry-run] [--json]homesrvctl restart <hostname> [--dry-run] [--json]homesrvctl list [--json]homesrvctl cloudflared status [--json]homesrvctl cloudflared config-test [--json]homesrvctl cloudflared logs [--follow] [--json]homesrvctl cloudflared restart [--dry-run] [--json]homesrvctl validate [--json]homesrvctl doctor <hostname> [--json]
Notes
domain adduses the Cloudflare DNS API to manage apex and wildcard records for the requested zone.domain add,domain repair, anddomain removesupport--jsonfor machine-readable mutation results.- all
--jsoncommands include a top-levelschema_versionso automation can pin to a known output shape. config init --jsonreports whether the config file was created or overwritten.domain statusreports expected tunnel target, apex and wildcard DNS state, apex and wildcardcloudflaredingress state, whether a route is being shadowed by an earlier ingress rule, whether Cloudflare DNS is ambiguous or of the wrong type, whether coverage is apex-only or wildcard-only, and whetherhomesrvctl domain repairis likely to fix the current state automatically.list,domain status,validate, anddoctorsupport--jsonfor machine-readable output.up,down, andrestartsupport--jsonfor machine-readable command results.site initandapp initsupport--jsonfor machine-readable scaffold results, including the selected template and rendered template-to-output mapping.cloudflared statusreports the detected runtime mode, whether it is active, and the restart command when one is available.cloudflared config-testpreferscloudflared tunnel ingress validate --config ...when the binary is available and falls back to structural YAML/ingress validation otherwise.cloudflared logsprints the rightjournalctlordocker logscommand for the detected runtime and supports--followplus--json.cloudflared restartalso supports--jsonfor automation-friendly dry-run and failure reporting.domain addalso reconciles apex and wildcard hostname entries in the configuredcloudflaredingress file so new domains route locally to Traefik.domain repairconverges apex and wildcard DNS records and matchingcloudflaredingress entries to the expected state.domain addresolves the tunnel target from the localcloudflaredtunnel configuration and does not depend on the activecloudflared tunnel loginzone.domain removeremoves apex and wildcard DNS records and matchingcloudflaredingress entries for the requested zone.- pass
--restart-cloudflaredto have domain-changing commands restartcloudflaredautomatically when a supported runtime is detected - without that flag, restart
cloudflaredmanually after ingress changes site initandapp initgenerate Traefik-safe router and service identifiers from the hostname.- All generated Compose files join the external Docker network configured in
docker_network. - The
nodeapp template now generates a runnable multi-file scaffold withdocker-compose.yml,Dockerfile,package.json,.env.example, andsrc/server.js. - The
pythonapp template now generates a runnable multi-file scaffold withdocker-compose.yml,Dockerfile,requirements.txt,.env.example, andapp/main.py.
Project details
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file homesrvctl-0.2.0.tar.gz.
File metadata
- Download URL: homesrvctl-0.2.0.tar.gz
- Upload date:
- Size: 38.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1660ee0e11ca367e719996cda7d84efc457e4face2b04562f899066c82aaa97d
|
|
| MD5 |
80d95e185ceb8e00677d7d3f1be763eb
|
|
| BLAKE2b-256 |
18ee6e8b788af182d14514fdf46779cdb9ff689fd485f72552ab87d2ef9ac9a8
|
Provenance
The following attestation bundles were made for homesrvctl-0.2.0.tar.gz:
Publisher:
release.yml on Broda/homesrvctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
homesrvctl-0.2.0.tar.gz -
Subject digest:
1660ee0e11ca367e719996cda7d84efc457e4face2b04562f899066c82aaa97d - Sigstore transparency entry: 1255268800
- Sigstore integration time:
-
Permalink:
Broda/homesrvctl@4e181aa3244cb0a6b74f733b2fffe747989c3485 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Broda
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4e181aa3244cb0a6b74f733b2fffe747989c3485 -
Trigger Event:
push
-
Statement type:
File details
Details for the file homesrvctl-0.2.0-py3-none-any.whl.
File metadata
- Download URL: homesrvctl-0.2.0-py3-none-any.whl
- Upload date:
- Size: 38.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6068ab9422c74c61a705e92f07777d521e5c7534bfaa784ad793be3f9818e16
|
|
| MD5 |
458b576d833b3f283e37566ac905cf2c
|
|
| BLAKE2b-256 |
92e5095dd3c1a5566637752b2f265e130abdf5bc4af49088f1036df7608ce485
|
Provenance
The following attestation bundles were made for homesrvctl-0.2.0-py3-none-any.whl:
Publisher:
release.yml on Broda/homesrvctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
homesrvctl-0.2.0-py3-none-any.whl -
Subject digest:
e6068ab9422c74c61a705e92f07777d521e5c7534bfaa784ad793be3f9818e16 - Sigstore transparency entry: 1255268983
- Sigstore integration time:
-
Permalink:
Broda/homesrvctl@4e181aa3244cb0a6b74f733b2fffe747989c3485 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Broda
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4e181aa3244cb0a6b74f733b2fffe747989c3485 -
Trigger Event:
push
-
Statement type: