Handbook
Caddy in front of Fleet (systemd)
Primary installer (interactive prompts for layout, bearer, ports; Ubuntu apt for Caddy):
Updated
Internet -> Caddy TLS :443
Caddy -> Fleet HTTP 127.0.0.1Primary installer (interactive prompts for layout, bearer, ports; Ubuntu apt for Caddy):
Run from the forge-fleet repository root (the directory that contains scripts/, fleet_server/, etc. — clone path is arbitrary: $HOME/forge-fleet, $HOME/src/forge-fleet, or any folder you chose):
cd /path/to/forge-fleet
./scripts/install-caddy-fleet.sh
Or call the script by absolute path without cd:
bash /path/to/forge-fleet/scripts/install-caddy-fleet.sh
Non-interactive (e.g. remote): same cd (or absolute path to the script):
cd /path/to/forge-fleet
# User Fleet (systemctl --user): Fleet 127.0.0.1:18766, Caddy :18767
LAYOUT=user FLEET_BEARER_TOKEN='your-token' bash ./scripts/install-caddy-fleet.sh --non-interactive
# System Fleet (sudo): upstream 127.0.0.1:18765, Caddy :18766
LAYOUT=system FLEET_BEARER_TOKEN='your-token' sudo -E bash ./scripts/install-caddy-fleet.sh --non-interactive
Optional env: FLEET_UPSTREAM_HOST FLEET_UPSTREAM_PORT CADDY_PUBLIC_PORT INSTALL_CADDY_APT=0 (skip apt if Caddy already installed).
Fleet + Ollama on one hostname (e.g. public HTTPS for both LLM and Fleet health): see 04-caddy-unified-granite.md and run scripts/install-caddy-fleet-ollama-unified.sh (optional CADDY_SITE_ADDRESS for a TLS site block instead of :PORT).
Legacy wrappers (same as --non-interactive): scripts/install-forge-fleet-caddy-user-systemd.sh, scripts/install-forge-fleet-caddy-systemd.sh.
User Fleet (install-user.sh)
- Fleet:
127.0.0.1:18766by default. - Caddy:
http://0.0.0.0:18767/by default (change in prompts or env). - Config:
~/.config/forge-fleet/forge-fleet.env,~/.config/forge-fleet/Caddyfile.caddy-fleet,~/.config/systemd/user/forge-fleet-caddy.service. - Add
FLEET_ENFORCE_BEARER=1when prompted so/v1/*checks bearer behind Caddy. - Headless boot:
loginctl enable-linger "$USER"once.
System Fleet (/opt, forge-fleet.service)
- Put Fleet on loopback with
systemctl edit forge-fleet.service(see below), then run installer with layout 2 orLAYOUT=system. - Writes
/etc/forge-fleet/Caddyfile,/etc/forge-fleet/caddy.env,/etc/systemd/system/forge-fleet-caddy.service.
Drop-in for Fleet (loopback + enforce bearer):
[Service]
ExecStart=
ExecStart=/usr/bin/python3 -m fleet_server --host 127.0.0.1 --port 18765 --data-dir /var/lib/forge-fleet
Environment=FLEET_ENFORCE_BEARER=1
TLS later
Use a hostname site block in the Caddyfile and remove plain :port when you want HTTPS (Caddy automatic HTTPS).
Stock caddy.service
Disable it if it conflicts on the same port, or merge the site block into /etc/caddy/Caddyfile and use the distro unit instead of forge-fleet-caddy.service.
The installer inlines FLEET_BEARER_TOKEN into the Caddyfile (with minimal escaping). That avoids caddy validate --environ / caddy run --environ, which are missing on some Ubuntu caddy packages. Keep the Caddyfile mode 0600 (user) or 0640 root:caddy (system) so the token is not world-readable.
If forge-fleet-caddy.service fails to start
journalctl --user -xeu forge-fleet-caddy.service
# or (system layout): sudo journalctl -xeu forge-fleet-caddy.service
Older generated units used Type=notify, which often fails with the Ubuntu caddy package under systemctl --user. Current installer uses Type=simple, admin off, and runs caddy validate before systemctl restart. After git pull, run ./scripts/install-caddy-fleet.sh again (same choices) or systemctl --user daemon-reload && systemctl --user restart forge-fleet-caddy.service once the unit file on disk is updated.