edca04868d
Reachability is controlled by the host firewall / compose port publishing, not the bind address. Backend, compose, and docs all now default to 0.0.0.0 so the API is reachable from the frontend container, the host, and the LAN without per-env overrides. Files: - backend/src/cyclone/__main__.py: default host = 0.0.0.0 - docker-compose.yml: refresh the comment to match the new posture - CLAUDE.md / README.md / docs/ARCHITECTURE.md / docs/REQUIREMENTS.md: reframe the bind note accordingly
106 lines
3.7 KiB
YAML
106 lines
3.7 KiB
YAML
name: cyclone
|
|
|
|
# Two-container production stack for Cyclone.
|
|
#
|
|
# backend FastAPI on python:3.11-slim-bookworm, internal port 8000.
|
|
# frontend nginx:1.27-alpine serving the built React SPA + reverse-
|
|
# proxying /api/* to the backend, host port 8080.
|
|
#
|
|
# Tag strategy:
|
|
# - Images are tagged semver from package.json / pyproject.toml.
|
|
# - Two aliases per image: `:latest` (set automatically by `docker
|
|
# compose build`) and `:stable` (manually promoted after a release
|
|
# has been running in prod for >=1 week).
|
|
# - Compose defaults to `:stable` so a fresh `docker compose build`
|
|
# never auto-rolls a new release.
|
|
# - Override with `TAG=0.0.9 docker compose up -d` to roll back.
|
|
|
|
services:
|
|
backend:
|
|
image: cyclone-backend:${TAG:-stable}
|
|
build:
|
|
context: ./backend
|
|
restart: unless-stopped
|
|
environment:
|
|
# SQLite path lives on the named `cyclone_db` volume.
|
|
CYCLONE_DB_URL: "sqlite:////var/lib/cyclone/db/cyclone.db"
|
|
# Wire the existing BackupService (SP17) to autostart on container boot.
|
|
CYCLONE_BACKUP_AUTOSTART: "1"
|
|
CYCLONE_BACKUP_INTERVAL_HOURS: "24"
|
|
CYCLONE_BACKUP_RETENTION_DAYS: "14"
|
|
# Logging — JSON to stdout (collected by `docker logs`) and to the
|
|
# bind-mounted file (collected by host-side logrotate).
|
|
CYCLONE_LOG_LEVEL: "INFO"
|
|
CYCLONE_LOG_FILE: "/var/log/cyclone/cyclone.log"
|
|
CYCLONE_LOG_JSON: "1"
|
|
# Cookie signing key defaults to the SQLCipher key. Override in
|
|
# production if you want to rotate them independently.
|
|
CYCLONE_SECRET_KEY_FILE: "/run/secrets/cyclone_db_key"
|
|
CYCLONE_COOKIE_SECURE: "1"
|
|
# First-admin bootstrap — populated by scripts/cyclone-init.sh.
|
|
# The `_FILE` variants are the standard Docker-secret pattern:
|
|
# the env var points at the mounted secret file rather than
|
|
# embedding the secret in the compose file.
|
|
CYCLONE_ADMIN_USERNAME_FILE: "/run/secrets/cyclone_admin_username"
|
|
CYCLONE_ADMIN_PASSWORD_FILE: "/run/secrets/cyclone_admin_password"
|
|
# Always bind to 0.0.0.0. The compose-managed bridge network
|
|
# isolates the backend from the host's LAN/WAN — only the
|
|
# `frontend` service joins it. Host firewall / port publishing
|
|
# is the layer that controls what reaches us from outside the
|
|
# compose network, not the bind address.
|
|
CYCLONE_HOST: "0.0.0.0"
|
|
secrets:
|
|
- cyclone_db_key
|
|
- cyclone_admin_username
|
|
- cyclone_admin_password
|
|
volumes:
|
|
- cyclone_db:/var/lib/cyclone/db
|
|
- cyclone_backups:/var/lib/cyclone/backups
|
|
- cyclone_prodfiles:/var/lib/cyclone/prodfiles
|
|
- cyclone_sftp_staging:/var/lib/cyclone/sftp_staging
|
|
- cyclone_logs:/var/log/cyclone
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-fs", "http://localhost:8000/api/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 30s
|
|
networks:
|
|
- cyclone_network
|
|
|
|
frontend:
|
|
image: cyclone-frontend:${TAG:-stable}
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile.frontend
|
|
restart: unless-stopped
|
|
ports:
|
|
# LAN-bind: only this port is published to the host. The operator
|
|
# is expected to firewall this to the LAN subnet (or rely on VPN
|
|
# for outside access). NO public TLS in v1.
|
|
- "8080:8080"
|
|
depends_on:
|
|
backend:
|
|
condition: service_healthy
|
|
networks:
|
|
- cyclone_network
|
|
|
|
secrets:
|
|
cyclone_db_key:
|
|
file: /etc/cyclone/secrets/db.key
|
|
cyclone_admin_username:
|
|
file: /etc/cyclone/secrets/admin_username
|
|
cyclone_admin_password:
|
|
file: /etc/cyclone/secrets/admin_pw
|
|
|
|
volumes:
|
|
cyclone_db:
|
|
cyclone_backups:
|
|
cyclone_prodfiles:
|
|
cyclone_sftp_staging:
|
|
cyclone_logs:
|
|
|
|
networks:
|
|
cyclone_network:
|
|
driver: bridge
|