Skip to main content

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

Install from PyPI

You can install the published package directly (recommended inside a virtualenv):

pip install --upgrade caddy-tui

Need a globally available CLI without touching the system Python? Use pipx:

pipx install caddy-tui

This installs both caddy-tui and the optional caddy-tui-helper command. If you want the helper to run via sudo without a password, follow the “Privileged helper” section below to add it to /etc/sudoers.d/caddy-tui.

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.py defines 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 status field 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:

  1. Result of the previous selection (e.g. import success, drift diff panel).
  2. 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).
  3. A context-aware menu. Options currently include:
    • f – Write the privileged Caddyfile back into caddy-tui (helper-assisted import so sudo can mirror /etc/caddy/Caddyfile).
    • t – Write the current caddy-tui snapshot 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).
    • p – Print the live Caddyfile exactly as Caddy is serving it. The TUI refreshes the live snapshot, renders every block, and shows the full text inside a scrollable Rich panel so you can copy/paste or audit directives without leaving the menu.
    • 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 so caddy-tui tui is 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.
    • h – Show an in-app CLI reference table listing every caddy-tui command, its usage string, and a concise description so you can jump into automation or remind yourself of available flags without leaving the interface.
    • u – When GitHub publishes a newer release, this option appears and prints upgrade instructions with both pip install --upgrade caddy-tui and pipx upgrade caddy-tui so you can follow the workflow you originally used.
    • 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:

  1. Ensures ~/.caddy-tui/ exists (or honours --db PATH).
  2. Applies the SQLAlchemy schema declared in caddy_tui/models.py.
  3. 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_caddyfile mirrors an existing Caddyfile into SQLite. Pass target_snapshot (defaults to caddyfile) and mirror_to to control where parsed blocks land, or pass helper_interactive=True to log the helper command when elevated access is required.
  • caddy_tui.exporter.generate_caddyfile renders the caddy-tui snapshot back to a canonical Caddyfile and calls caddy adapt as needed. The helper cooperates with drift.compare_caddyfile so diffing against arbitrary files stays consistent.
  • caddy_tui.block_editor exposes load_caddy_tui_blocks, save_caddy_tui_blocks, and parse_single_block for 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

  1. Initialise the DB: caddy-tui init.
  2. Import the live config: sudo caddy-tui import --caddyfile /etc/caddy/Caddyfile.
  3. Launch caddy-tui tui, edit sites, and review status messages (use r whenever you need a fresh live snapshot).
  4. Apply and reload: sudo caddy-tui apply (the CLI auto-queues a live snapshot refresh afterward, or run caddy-tui refresh-live to grab a short-lived snapshot of /etc/caddy/Caddyfile that is purged once the comparison completes).
  5. Keep an eye on drift: sudo caddy-tui status --diff --refresh-live in 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

CI now handles almost everything:

  1. Update docs/changelog and bump pyproject.toml + caddy_tui/__init__.py.
  2. Commit to main and push. The build job runs plus publish-to-testpypi, so TestPyPI always mirrors main.
  3. Tag the release (git tag v0.2.2 && git push origin v0.2.2). GitHub pauses the publish-to-pypi job until the pypi environment is approved; once approved, PyPI receives the artifacts.

Local uploads are still possible when you need to hotfix outside CI:

python -m build
twine upload dist/*

The wheel exposes both CLI entry points (caddy-tui, caddy-tui-helper) and ships all helper modules for downstream automation.

Wishlist

  • CLI deep dive for AI assistants – expand the Click command surface (status filters, automation-friendly outputs, helper diagnostics) so Copilot/Codex-style agents can treat caddy-tui as a powerful scripting target. Document each addition in the changelog to keep the roadmap transparent.

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

caddy_tui-0.2.5.tar.gz (57.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

caddy_tui-0.2.5-py3-none-any.whl (51.9 kB view details)

Uploaded Python 3

File details

Details for the file caddy_tui-0.2.5.tar.gz.

File metadata

  • Download URL: caddy_tui-0.2.5.tar.gz
  • Upload date:
  • Size: 57.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for caddy_tui-0.2.5.tar.gz
Algorithm Hash digest
SHA256 bf37f93ac9a260fbae097572aee1701afff211661628f278e367b959ef9bcf00
MD5 b6687c57faf2d43e62b18790a52000c1
BLAKE2b-256 1c624a7c9566d73f31ad390c253ab91a49a6387d8d64728f2b42a5509a74f329

See more details on using hashes here.

Provenance

The following attestation bundles were made for caddy_tui-0.2.5.tar.gz:

Publisher: publish.yml on ajphilton/caddy-tui

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file caddy_tui-0.2.5-py3-none-any.whl.

File metadata

  • Download URL: caddy_tui-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 51.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for caddy_tui-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 aab5c7aab5084f78274878b121588a73519edce10682b2c4781a56b7546c55cc
MD5 f8ac50cb61190c6d9f2276a499619951
BLAKE2b-256 64c1c69dd7bca5021920c4ac077c3f8a9c7af562fd6db16cab2e2f71eb8c9559

See more details on using hashes here.

Provenance

The following attestation bundles were made for caddy_tui-0.2.5-py3-none-any.whl:

Publisher: publish.yml on ajphilton/caddy-tui

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page