TUI + CLI tool to manage Caddy configs via SQLite
Project description
caddy-tui
An interactive terminal UI plus CLI toolkit (built with Colorama + Rich) that keeps Caddy configuration in SQLite (~/.caddy-tui/config.db), lets you inspect/import data, offers inline block editing, and safely regenerates validated configs before reloading the Caddy service.
Project structure
caddy-tui/
├── caddy_tui/
│ ├── cli.py # Click-based CLI skeleton & entry points
│ ├── tui_app.py # Rich/Colorama TUI loop
│ ├── db.py # Schema builder + session helpers
│ ├── importer.py # Caddyfile → snapshot pipeline
│ ├── exporter.py # Snapshot → Caddyfile renderer
│ ├── block_editor.py # CRUD helpers for caddy-tui snapshot blocks
│ ├── drift.py, status.py # Diff + reporting utilities
│ └── ... # Additional helpers (config, models, etc.)
├── pyproject.toml # PyPI metadata + console scripts
├── MANIFEST.in # Source distribution manifest
├── README.md # Usage + architecture guide
├── CHANGELOG.md # Release notes
└── LICENSE # MIT terms
The modules are intentionally decoupled so you can script against the importer/exporter hooks or database builder without invoking the CLI.
Quick start
pip install -e .
caddy-tui init # DB schema builder
sudo caddy-tui import --caddyfile /etc/caddy/Caddyfile
caddy-tui tui # Interactive block editor + drift monitor
The CLI prints JSON so it can slot straight into scripts, CI jobs, or other automation.
Core commands
| Command | Purpose |
|---|---|
caddy-tui init |
Create the SQLite schema at ~/.caddy-tui/config.db. |
caddy-tui import --caddyfile PATH |
Parse an existing Caddyfile and load it into the DB. Use sudo when PATH lives under /etc/caddy. |
caddy-tui list-sites / add-site / remove-site |
Manage site definitions directly from the CLI. |
caddy-tui apply |
Regenerate a Caddyfile from the DB, validate it, and reload Caddy via systemctl reload caddy (run with sudo). |
caddy-tui refresh-live |
Force a fresh snapshot of the live Caddyfile via the configured helper (same action as the TUI “Refresh live snapshot” option). |
caddy-tui status [--caddyfile PATH] [--diff] [--refresh-live] |
Compare the DB-rendered config with the specified Caddyfile (defaults to the last imported path). Pass --refresh-live to mirror the live file just before comparing. Exits with code 1 when drift is detected. |
caddy-tui tui |
Launch the interactive scrolling menu for importing files, editing caddy-tui blocks (add/edit/delete), refreshing the live snapshot, reviewing drift, and checking Caddy service health. |
CLI skeleton & starter commands
caddy_tui/cli.pydefines a single Click group (main) plus entry points for init/import/apply/status/refresh-live/tui/validate/version. Each command simply marshals arguments then calls the relevant helper module, so you can copy the file as a starter CLI scaffold for other admin scripts.- Every command emits JSON so shell automation stays predictable—check the
statusfield and inspect payload keys for details. - New commands should live in dedicated helper modules (example:
drift.compare_caddyfile) and then be wired into the CLI via a short@main.command()block.
Status command
Use caddy-tui status --diff (typically with sudo) to verify the live /etc/caddy/Caddyfile still matches the SQLite data. The tool prints hashes, whether everything is in sync, and a truncated unified diff when requested. This is handy in CI or cron to catch manual edits. When --refresh-live is set the helper mirrors /etc/caddy/Caddyfile, computes the comparisons, and immediately purges the live snapshot from SQLite so sensitive data is not stored after the check completes.
Importing system Caddyfiles
Most distro packages restrict /etc/caddy/Caddyfile to root. Keep the TUI unprivileged and run imports as needed via:
sudo /home/alexander_skystamper_com/projects/caddy-tui/.venv/bin/caddy-tui import --caddyfile /etc/caddy/Caddyfile
The database directory honours SUDO_USER, so the sudo-run import updates the same ~/.caddy-tui/config.db that the TUI uses.
Privileged helper (optional)
If you prefer to grant finely scoped permissions instead of full sudo caddy-tui, install the accompanying helper entry point:
sudo visudo -f /etc/sudoers.d/caddy-tui
# Allow your user to run the helper without a password
alexander ALL=(ALL) NOPASSWD: /usr/local/bin/caddy-tui-helper
caddy-tui-helper exposes mirror/install/reload plus two extra commands: status (wraps systemctl is-active caddy by default) and restart (wraps systemctl restart caddy). When the TUI hits a permission error it prints the exact helper command (e.g. sudo caddy-tui-helper mirror --source /etc/caddy/Caddyfile ...) so you can re-run it immediately or let sudoers execute it without a prompt.
The helper runner resolves the executable to an absolute path before invoking sudo, so as long as which caddy-tui-helper works in your shell you do not need to export CADDY_TUI_HELPER_BIN. Just copy that which output into the sudoers entry (alexander ALL=(ALL) NOPASSWD: /home/.../.venv/bin/caddy-tui-helper) so sudo can locate the same binary.
Admin API probe
Set CADDY_TUI_ADMIN_ENDPOINT (defaults to http://127.0.0.1:2019/config) if your Caddy admin API listens elsewhere. The TUI/CLI will fetch live status from this endpoint on every refresh, report whether the service is up, and (when the endpoint returns text/caddyfile) mirror the running config straight into the short-lived caddy_live snapshot before diffing. The snapshot is purged immediately after comparisons so sensitive live data never lingers in SQLite.
Interactive menu overview
caddy-tui tui prints a repeating block in this order:
- Result of the previous selection (e.g. import success, drift diff panel).
- A Rich table that captures database readiness, stored block count, last import path, drift summary for every snapshot source (caddy-tui, Caddyfile, live helper), and a color-coded line for the Caddy service state (green when live+in-sync, orange when live but drifting, red when down, yellow when unknown).
- A context-aware menu. Options currently include:
f– Write the privileged Caddyfile back intocaddy-tui(helper-assisted import so sudo can mirror/etc/caddy/Caddyfile).t– Write the currentcaddy-tuisnapshot over the system Caddyfile (helper-assisted install when write permissions are missing).r– Refresh the live snapshot (polls the Caddy admin API for content first, falling back to the helper mirror only when the API is unavailable).b– Show the block contents for each snapshot side-by-side (caddy-tui, Caddyfile, and live) in a dedicated table with wrapped text so you can visually compare directives.n/e/x– Add, edit, or delete blocks inside the caddy-tui snapshot. The TUI opens your$EDITOR(or nano/vi fallback), validates the single-block snippet, and persists it back to SQLite socaddy-tui tuiis the one-stop shop for CRUD.c– Reload Caddy through the helper and automatically queue a live snapshot refresh afterwards (shown when the helper reports Caddy is live).s– Restart Caddy through the helper when the status probe reports the service is down.d– Show the unified diff between the DB-rendered config and/etc/caddy/Caddyfile(available once an import path exists). The diff is shown inside a Rich panel and can be copied directly from the terminal scrollback.u– When GitHub publishes a newer release, this option appears and prints upgrade instructions plus thepip install --upgrade caddy-tuicommand.q– Quit the session.
Every action prints the exact helper command when elevated access is required, so you can copy/paste or add it to sudoers immediately.
Database schema builder
caddy-tui init (or python -m caddy_tui.db) runs caddy_tui.db.init_db, which:
- Ensures
~/.caddy-tui/exists (or honours--db PATH). - Applies the SQLAlchemy schema declared in
caddy_tui/models.py. - Seeds baseline
Config+ snapshot rows so importer/exporter hooks always have a target.
The command is idempotent, so you can re-run it whenever you ship a new version or want to bootstrap a fresh environment.
Import/export hooks
caddy_tui.importer.import_caddyfilemirrors an existing Caddyfile into SQLite. Passtarget_snapshot(defaults tocaddyfile) andmirror_toto control where parsed blocks land, or passhelper_interactive=Trueto log the helper command when elevated access is required.caddy_tui.exporter.generate_caddyfilerenders thecaddy-tuisnapshot back to a canonical Caddyfile and callscaddy adaptas needed. The helper cooperates withdrift.compare_caddyfileso diffing against arbitrary files stays consistent.caddy_tui.block_editorexposesload_caddy_tui_blocks,save_caddy_tui_blocks, andparse_single_blockfor fine-grained CRUD that matches what the TUI uses.
Integrate those helpers directly from Python (no Click dependency) whenever you need to script imports/exports outside of the bundled CLI.
Example workflow
- Initialise the DB:
caddy-tui init. - Import the live config:
sudo caddy-tui import --caddyfile /etc/caddy/Caddyfile. - Launch
caddy-tui tui, edit sites, and review status messages (userwhenever you need a fresh live snapshot). - Apply and reload:
sudo caddy-tui apply(the CLI auto-queues a live snapshot refresh afterward, or runcaddy-tui refresh-liveto grab a short-lived snapshot of/etc/caddy/Caddyfilethat is purged once the comparison completes). - Keep an eye on drift:
sudo caddy-tui status --diff --refresh-livein CI or a nightly cron.
How to run locally
python3 -m venv .venv
source .venv/bin/activate
pip install -e .[test]
pytest
caddy-tui tui
Run privileged steps (import/apply/status) with sudo, but keep the interactive menu under your normal user account.
Publishing to PyPI
-
Update
CHANGELOG.md,README.md, and bump the version inpyproject.toml. -
Build artifacts using the bundled metadata (the manifest already ships README + license):
python -m build
-
Upload via Twine:
twine upload dist/*
The published wheel exposes the caddy-tui and caddy-tui-helper entry points, includes the CLI skeleton plus all starter modules, and makes the database builder/import-export hooks available for downstream automation.
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 caddy_tui-0.2.0.tar.gz.
File metadata
- Download URL: caddy_tui-0.2.0.tar.gz
- Upload date:
- Size: 52.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64525067036fc6578d227706f2380174fc0ecbbd00da72ae49cd7eba101fb2f5
|
|
| MD5 |
ca53dae26e1efc710a063b9eb9f1a85d
|
|
| BLAKE2b-256 |
14ae4689ac57bb98b37d4b15b8ff7506a18974b10b8d99bdd4d82517926e2c5b
|
File details
Details for the file caddy_tui-0.2.0-py3-none-any.whl.
File metadata
- Download URL: caddy_tui-0.2.0-py3-none-any.whl
- Upload date:
- Size: 48.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3297bc570ed69490a9ada16725f9756c228dcd4e8a67ca05c65fe9aa26648a1e
|
|
| MD5 |
cce75c26af0211fb8901bb455aee0c11
|
|
| BLAKE2b-256 |
980b7796cb48cd785a0a9dd9378186327ea3dd0623332d4ad927a282e52c945f
|