[Docs] Revise README for clarity and structure; update features and quick start instructions

This commit is contained in:
Pacerino
2026-06-14 02:43:31 +02:00
parent 0baeee0fca
commit 51f89454f5

245
README.md
View File

@@ -1,108 +1,185 @@
# Caddy Proxy Manager - CPM
<div align="center">
## 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
<br>
**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.
</div>
---
> [!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 <http://localhost:3001> 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_<id>.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 <http://localhost:5173> and log in with `admin@example.com` / `changeme`.
## Contribution
If you want to help with the development pull requests etc. are welcome!
### 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
<details>
<summary><strong>Should I use Caddyfile mode or API mode?</strong></summary>
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.
</details>
<details>
<summary><strong>Can I use external SSO (Authelia, Keycloak, Authentik …)?</strong></summary>
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`.
</details>
<details>
<summary><strong>Does CPM run Caddy for me?</strong></summary>
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.
</details>
## 🗺️ 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)