From 51f89454f5709a32c3af57985b72fbdf49e4ba8c Mon Sep 17 00:00:00 2001 From: Pacerino Date: Sun, 14 Jun 2026 02:43:31 +0200 Subject: [PATCH] [Docs] Revise README for clarity and structure; update features and quick start instructions --- README.md | 245 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 161 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index f02d4bd..4db97ff 100644 --- a/README.md +++ b/README.md @@ -1,108 +1,185 @@ -# Caddy Proxy Manager - CPM +
-## Shoutout -Much was copied from the [original Nginx Proxy Manager](https://github.com/NginxProxyManager/nginx-proxy-manager) and implemented for Caddy. The complete basic idea therefore goes back to the repo of [jc21](https://github.com/jc21) and so the honor goes to him! So please have a look at his repo and his Nginx Proxy Manager too! +# Caddy Proxy Manager -
+**A modern web interface for managing [Caddy](https://caddyserver.com/) reverse proxy hosts.** -## Idea -This project tries to implement the basic idea of the Nginx Proxy Manager for Caddy and thus provide a web interface for Caddy. +Add, edit and delete proxy hosts from a clean UI β€” let Caddy handle TLS, HTTP/2, HSTS and automatic certificates for you. -Currently the version is completely unstable and untidy. +[![CI](https://github.com/Pacerino/CaddyProxyManager/actions/workflows/ci.yml/badge.svg)](https://github.com/Pacerino/CaddyProxyManager/actions/workflows/ci.yml) +![Go](https://img.shields.io/badge/Go-1.24+-00ADD8?logo=go&logoColor=white) +![React](https://img.shields.io/badge/React-18-61DAFB?logo=react&logoColor=black) +![Caddy](https://img.shields.io/badge/Caddy-2-1F88C0?logo=caddy&logoColor=white) +![License](https://img.shields.io/badge/license-MIT-green) -Caddy is installed normally on the system and integrates further Caddyfiles via Caddyfile. So a hotreload and caddyfiles per host is possible. +
+--- +> [!WARNING] +> This project is under active development and not yet considered stable. Use at your own risk and review the configuration before exposing it publicly. -## Current features -- Adding, editing and deleting hosts with multiple domains/upstreams -- Two ways to apply config to Caddy, selectable at runtime: - - **Caddyfile mode** (`CPM_CADDY_MODE=caddyfile`, default): renders a per-host - Caddyfile snippet and triggers a reload. - - **API mode** (`CPM_CADDY_MODE=api`): manages Caddy's JSON config through the - admin API, maintaining one route per host (no reload needed). -- Configurable authentication: local email/password or external OIDC/OAuth - (`CPM_AUTH_MODE=local|oidc`) with JIT user provisioning. -- Modern SPA frontend (Vite + React + TypeScript + Tailwind + shadcn/ui), - embedded in the binary by default or served from an external directory. +## ✨ Features -## Configuration +- **Host management** β€” create, edit and delete hosts with multiple domains and upstream backends. +- **Two ways to drive Caddy**, switchable at runtime: + - πŸ“ **Caddyfile mode** *(default)* β€” renders a per-host Caddyfile snippet and reloads Caddy. + - πŸ”Œ **API mode** β€” manages Caddy's JSON config through the admin API, one route per host, no reload required. +- **Flexible authentication** β€” local email/password or external **OIDC/OAuth** (Authelia, Keycloak, Authentik, …) with just-in-time user provisioning. +- **Single binary** β€” a modern SPA (Vite Β· React Β· TypeScript Β· Tailwind Β· shadcn/ui) embedded directly in the Go binary, or served from an external directory. +- **Container-ready** β€” multi-stage Docker image that bundles Caddy and starts everything for you. -All options are environment variables prefixed with `CPM_`: - -| Variable | Default | Description | -| --- | --- | --- | -| `CPM_CADDY_MODE` | `caddyfile` | `caddyfile` or `api` | -| `CPM_CADDY_ADMINURL` | `http://localhost:2019` | Caddy admin API base URL (api mode + api reload) | -| `CPM_CADDY_SERVERNAME` | `srv0` | http server name routes are managed under (api mode) | -| `CPM_CADDY_LISTEN` | `:80,:443` | listen addresses for the bootstrapped server (api mode); use e.g. `:8080` for local non-root testing | -| `CPM_CADDY_RELOADSTRATEGY` | `systemd` | `systemd`, `exec`, `api` or `none` (caddyfile mode) | -| `CPM_CADDY_BINARY` | `caddy` | caddy executable for the `exec` reload strategy | -| `CPM_CADDY_SERVICE` | `caddy.service` | systemd unit for the `systemd` reload strategy | -| `CPM_DATAFOLDER` | `/etc/caddy/` | data + per-host config folder | -| `CPM_LOGFOLDER` | `/var/log/caddy` | per-host log folder | -| `CPM_CADDYFILE` | `/etc/caddy/Caddyfile` | main Caddyfile (used by `exec`/`api` reload) | -| `CPM_FRONTENDDIR` | _(empty)_ | serve the frontend from this directory instead of the embedded assets | -| `CPM_AUTH_MODE` | `local` | `local` or `oidc` | -| `CPM_AUTH_OIDC_ISSUER` | _(empty)_ | OIDC issuer URL (e.g. Keycloak/Authelia) | -| `CPM_AUTH_OIDC_CLIENTID` | _(empty)_ | OIDC client id | -| `CPM_AUTH_OIDC_CLIENTSECRET` | _(empty)_ | OIDC client secret | -| `CPM_AUTH_OIDC_REDIRECTURL` | _(empty)_ | callback URL, e.g. `https://cpm.example.com/api/auth/oidc/callback` | -| `CPM_AUTH_OIDC_SCOPES` | `openid,profile,email` | requested scopes | -| `CPM_AUTH_OIDC_ALLOWEDDOMAINS` | _(empty)_ | optional email-domain allowlist for JIT provisioning | - -## Planned features -- Logview -- Manage Plugins - -## FAQ - -> Can I use the Caddy admin API instead of writing a Caddyfile? - -Yes. Set `CPM_CADDY_MODE=api` and CPM will manage Caddy's JSON config through the -admin API, keeping one route per host. The Caddyfile mode remains the default and -is the simplest setup, since features like HSTS, HTTP/2, SSL etc. come for free. - -> Can I use external SSO (Authelia, Keycloak, etc.)? - -Yes. Set `CPM_AUTH_MODE=oidc` and configure the `CPM_AUTH_OIDC_*` variables. On -first successful login CPM creates the matching user automatically (JIT). Use -`CPM_AUTH_OIDC_ALLOWEDDOMAINS` to restrict which email domains may sign in. - -> How can I use CPM? - -You have to compile CPM yourself. The frontend (Vite + React + TypeScript) is built from the ``frontend`` directory with ``npm install && npm run build``, which outputs straight into ``backend/embed/assets``. The backend is written in Go (1.24+) and can be compiled with ``go build ./cmd/main.go`` from the ``backend`` directory, producing a single binary with the frontend embedded. During development run ``npm run dev`` (Vite proxies ``/api`` to the Go backend on port 3001). - -## Docker - -A multi-stage `Dockerfile` builds the frontend, compiles the backend (CGO is -required by the SQLite driver) and produces a small Alpine runtime image that -bundles Caddy. The container entrypoint starts Caddy with its admin API and then -CPM in `api` mode. +## πŸš€ Quick start (Docker) ```bash -docker build -t caddyproxymanager . docker run -d --name cpm \ -p 3001:3001 -p 80:80 -p 443:443 \ -v cpm-data:/data \ - caddyproxymanager + ghcr.io/pacerino/caddyproxymanager ``` -Published images are available at `ghcr.io/pacerino/caddyproxymanager`. +Then open and sign in with the default credentials: -## Development & testing +| Email | Password | +| --- | --- | +| `admin@example.com` | `changeme` | + +> [!IMPORTANT] +> Change the defaults via `CPM_ADMIN_EMAIL` / `CPM_ADMIN_PASSWORD` on first run. + +The container starts Caddy (with its admin API) and CPM in `api` mode. Mount your own Caddy config at `/data/caddy.json` to customise it. + +## πŸ—οΈ How it works + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Browser β”‚ ───► β”‚ CPM (Go + embedded β”‚ ───► β”‚ Caddy β”‚ +β”‚ (React SPA) β”‚ β”‚ React frontend) β”‚ β”‚ (reverse proxy) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + Caddyfile mode β”‚ writes host_.conf + reload + API mode β”‚ PUT/PATCH/DELETE via admin API +``` + +CPM stores hosts in a local SQLite database and applies each change to Caddy using the selected provider. + +## βš™οΈ Configuration + +All settings are environment variables prefixed with `CPM_`. + +### Caddy + +| Variable | Default | Description | +| --- | --- | --- | +| `CPM_CADDY_MODE` | `caddyfile` | Provider to use: `caddyfile` or `api`. | +| `CPM_CADDY_ADMINURL` | `http://localhost:2019` | Caddy admin API base URL (API mode + `api` reload). | +| `CPM_CADDY_SERVERNAME` | `srv0` | HTTP server name routes are managed under (API mode). | +| `CPM_CADDY_LISTEN` | `:80,:443` | Listen addresses for the bootstrapped server (API mode); use e.g. `:8080` for local non-root testing. | +| `CPM_CADDY_RELOADSTRATEGY` | `systemd` | Reload strategy (Caddyfile mode): `systemd`, `exec`, `api` or `none`. | +| `CPM_CADDY_BINARY` | `caddy` | Caddy executable for the `exec` reload strategy. | +| `CPM_CADDY_SERVICE` | `caddy.service` | systemd unit for the `systemd` reload strategy. | +| `CPM_CADDYFILE` | `/etc/caddy/Caddyfile` | Main Caddyfile (used by `exec`/`api` reload). | + +### Authentication + +| Variable | Default | Description | +| --- | --- | --- | +| `CPM_AUTH_MODE` | `local` | `local` or `oidc`. | +| `CPM_AUTH_OIDC_ISSUER` | β€” | OIDC issuer URL (e.g. Keycloak/Authelia). | +| `CPM_AUTH_OIDC_CLIENTID` | β€” | OIDC client ID. | +| `CPM_AUTH_OIDC_CLIENTSECRET` | β€” | OIDC client secret. | +| `CPM_AUTH_OIDC_REDIRECTURL` | β€” | Callback URL, e.g. `https://cpm.example.com/api/auth/oidc/callback`. | +| `CPM_AUTH_OIDC_SCOPES` | `openid,profile,email` | Requested scopes. | +| `CPM_AUTH_OIDC_ALLOWEDDOMAINS` | β€” | Optional email-domain allowlist for JIT provisioning. | + +### General + +| Variable | Default | Description | +| --- | --- | --- | +| `CPM_DATAFOLDER` | `/etc/caddy/` | Data + per-host config folder. | +| `CPM_LOGFOLDER` | `/var/log/caddy` | Per-host log folder. | +| `CPM_FRONTENDDIR` | β€” | Serve the frontend from this directory instead of the embedded assets. | +| `CPM_ADMIN_EMAIL` | `admin@example.com` | Seed admin email (first run, local mode). | +| `CPM_ADMIN_PASSWORD` | `changeme` | Seed admin password (first run, local mode). | + +## πŸ§‘β€πŸ’» Development + +**Prerequisites:** Go 1.24+, Node 22+, and a local [Caddy](https://caddyserver.com/docs/install) for end-to-end testing. + +Run the backend and frontend in two terminals: ```bash -# Backend tests -cd backend && go test ./... +# Terminal 1 β€” backend on :3001 +cd backend +CPM_DATAFOLDER=./data CPM_LOGFOLDER=./data CPM_CADDY_RELOADSTRATEGY=none \ + go run ./cmd/main.go -# Frontend type-check + build -cd frontend && npm run build +# Terminal 2 β€” frontend dev server on :5173 (proxies /api β†’ :3001) +cd frontend +npm install +npm run dev ``` -CI (GitHub Actions, `.github/workflows/ci.yml`) runs the backend tests with the -race detector, builds the frontend, and on pushes to `master` / version tags -builds and publishes the Docker image to GHCR. +Open and log in with `admin@example.com` / `changeme`. -## Contribution -If you want to help with the development pull requests etc. are welcome! \ No newline at end of file +### Building a single binary + +```bash +cd frontend && npm run build # emits into backend/embed/assets +cd ../backend && go build ./cmd/main.go +``` + +### Testing + +```bash +cd backend && go test ./... # backend (run with -race in CI) +cd frontend && npm run build # frontend type-check + build +``` + +CI ([`.github/workflows/ci.yml`](.github/workflows/ci.yml)) runs the backend tests with the race detector, builds the frontend, and publishes the Docker image to GHCR on pushes to `master` and version tags. + +## 🐳 Building the image yourself + +```bash +docker build -t caddyproxymanager . +``` + +The multi-stage build compiles the frontend and backend (CGO is required by the SQLite driver) into a small Alpine runtime that bundles Caddy. + +## ❓ FAQ + +
+Should I use Caddyfile mode or API mode? + +Use **Caddyfile mode** (the default) for the simplest setup β€” CPM writes snippets that Caddy imports, and you keep all of Caddy's conveniences (automatic HTTPS, HSTS, HTTP/2). Use **API mode** when you want CPM to manage Caddy's live JSON config directly through the admin API, with no reloads. +
+ +
+Can I use external SSO (Authelia, Keycloak, Authentik …)? + +Yes. Set `CPM_AUTH_MODE=oidc` and configure the `CPM_AUTH_OIDC_*` variables. On first successful login CPM provisions the matching user automatically (JIT). Restrict access with `CPM_AUTH_OIDC_ALLOWEDDOMAINS`. +
+ +
+Does CPM run Caddy for me? + +The Docker image does β€” its entrypoint launches Caddy with the admin API and then CPM. For bare-metal installs, run Caddy yourself and point CPM at it (`CPM_CADDYFILE` / `CPM_CADDY_ADMINURL`) with the appropriate reload strategy. +
+ +## πŸ—ΊοΈ Roadmap + +- [ ] Log viewer +- [ ] Plugin management +- [ ] Per-host advanced directives + +## πŸ™Œ Acknowledgements + +Inspired by the excellent [Nginx Proxy Manager](https://github.com/NginxProxyManager/nginx-proxy-manager) by [jc21](https://github.com/jc21) β€” go check it out. CPM brings the same idea to Caddy. + +## 🀝 Contributing + +Pull requests and issues are welcome! Please open an issue to discuss larger changes first. + +## πŸ“„ License + +[MIT](LICENSE)