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.1
Internet clients hit Caddy on 443; Caddy proxies JSON to loopback Fleet.

Primary 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:18766 by 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=1 when 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 or LAYOUT=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.