feat(docker): reorganize compose, add Caddy reverse proxy for prod

Move docker-compose.yaml to the repo root and add docker-compose.prod.yaml
that stands up a Caddy 2 sidecar on 80/443 proxying to the fabro service
on 32276 (the CLI's default port). Auto-HTTPS is handled by Caddy when
FABRO_DOMAIN is set; certs persist in named volumes.

Switch the container's internal listener from 80 to 32276, which lets us
drop libcap2-bin and the CAP_NET_BIND_SERVICE file capability.
This commit is contained in:
Bryan Helmkamp 2026-04-18 00:33:11 -04:00
parent e89192cf1b
commit a00abd8970
No known key found for this signature in database
6 changed files with 32 additions and 11 deletions

4
Caddyfile Normal file
View file

@ -0,0 +1,4 @@
{$FABRO_DOMAIN:localhost} {
reverse_proxy fabro:32276
encode gzip
}

View file

@ -6,7 +6,7 @@
# docker-context/amd64/fabro (x86_64-unknown-linux-gnu)
# docker-context/arm64/fabro (aarch64-unknown-linux-gnu)
#
# The image serves the HTTP API (with embedded web UI) on port 80,
# The image serves the HTTP API (with embedded web UI) on port 32276,
# persists state to /storage, and runs as the unprivileged `fabro` user.
FROM debian:trixie-slim
@ -18,7 +18,6 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
git \
libcap2-bin \
tini \
&& rm -rf /var/lib/apt/lists/*
@ -29,7 +28,6 @@ RUN groupadd --system --gid 1000 fabro \
&& install -d -m 0755 /etc/fabro
COPY --chmod=0755 docker-context/${TARGETARCH}/fabro /usr/local/bin/fabro
RUN setcap cap_net_bind_service=+ep /usr/local/bin/fabro
COPY docker/settings.toml /etc/fabro/settings.toml
COPY --chmod=0755 docker/entrypoint.sh /usr/local/bin/fabro-entrypoint
@ -38,7 +36,7 @@ ENV FABRO_HOME=/var/fabro \
FABRO_CONFIG=/etc/fabro/settings.toml
VOLUME ["/storage"]
EXPOSE 80
EXPOSE 32276
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/fabro-entrypoint"]
CMD ["fabro", "server", "start", "--foreground", "--bind", "0.0.0.0:80"]
CMD ["fabro", "server", "start", "--foreground", "--bind", "0.0.0.0:32276"]

20
docker-compose.prod.yaml Normal file
View file

@ -0,0 +1,20 @@
services:
fabro:
restart: unless-stopped
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- fabro
restart: unless-stopped
volumes:
caddy_data:
caddy_config:

View file

@ -2,10 +2,10 @@ services:
fabro:
image: fabro
build:
context: ..
context: .
dockerfile: Dockerfile
ports:
- "80:80"
- "32276:32276"
volumes:
- fabro-storage:/storage

View file

@ -2,8 +2,7 @@
set -eu
# When started as root (the default), ensure the storage volume is writable
# by the unprivileged fabro user, then drop privileges. File capabilities on
# /usr/local/bin/fabro grant CAP_NET_BIND_SERVICE so it can still bind port 80.
# by the unprivileged fabro user, then drop privileges.
if [ "$(id -u)" = 0 ]; then
chown fabro:fabro /storage
exec runuser -u fabro -- "$@"

View file

@ -16,7 +16,7 @@ Screenshots of the Fabro web UI are embedded in the public docs. This guide cove
## Boot the demo environment
```bash
docker compose -f docker/docker-compose.yaml up -d
docker compose up -d
```
Wait ~5 seconds for the server to be ready, then verify (sending the demo header):
@ -103,7 +103,7 @@ Current placements:
## Cleanup
```bash
docker compose -f docker/docker-compose.yaml down
docker compose down
```
If you also started the docs server: