Files
bookhoard/docker-compose.yml
T
john-okeefe 1129fcae6f fix(compose): make BASE_URL/COOKIE_SECURE configurable, drop obsolete version
Address compose issues surfaced on first production deploy:

- Remove obsolete `version: "3.8"` (ignored by Compose v2; caused a warning).
- Fix BASE_URL: it used compose-time interpolation of ${SERVER_PORT}, which is
  only defined as a runtime container env var (invisible to interpolation) and
  absent from .env. This resolved to an empty string, producing a broken
  `http://localhost:` (no port) and a startup warning. Now
  ${BASE_URL:-http://localhost:8765}, overridable per-deployment via .env.
- Move COOKIE_SECURE from the db service to the app service and make it
  configurable (${COOKIE_SECURE:-false}). It controls the session cookie Secure
  flag, an app concern; on the db service it was a no-op, so the app never
  received it and cookies were always non-secure. Set COOKIE_SECURE=true behind
  a TLS-terminating reverse proxy (Caddy/nginx/traefik), where the app speaks
  plain HTTP internally.
- Image reference unchanged: ${IMAGE_TAG:-latest} (no hardcoded version).
2026-07-29 16:02:32 -04:00

82 lines
2.5 KiB
YAML

services:
# PostgreSQL Database
db:
image: postgres:15-alpine
container_name: bookhoard_db
environment:
POSTGRES_DB: bookhoard
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${DBPASS}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./database/schema:/docker-entrypoint-initdb.d
# Make other volumes as needed
- ./uploads:/app/uploads
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
env_file:
- .env
# Bookhoard Application
# In production this image is pulled from the Gitea container registry.
# Override IMAGE_TAG in .env to pin or rollback a specific version (defaults to "latest").
app:
image: git.linuxhg.com/bookhoard/bookhoard:${IMAGE_TAG:-latest}
container_name: bookhoard
environment:
# Database Configuration
DATABASE_HOST: db
DATABASE_PORT: "5432"
DATABASE_USER: postgres
DATABASE_PASSWORD: ${DBPASS}
DATABASE_NAME: bookhoard
# Application Configuration
JWT_SECRET: ${JWT_SECRET}
SERVER_PORT: "8765"
# IMPORTANT: Device sync requires full URL with protocol
# Local: http://localhost:8765
# Local network: http://192.168.1.X:8765
# Domain: https://bookhoard.example.com
BASE_URL: ${BASE_URL:-http://localhost:8765}
# Mark session cookies Secure; set true behind a TLS-terminating reverse proxy (Caddy/nginx/traefik)
COOKIE_SECURE: ${COOKIE_SECURE:-false}
# Rate Limiting Configuration
TEST_MODE: ${TEST_MODE:-false}
RATE_LIMIT_ENABLED: ${RATE_LIMIT_ENABLED:-true}
REQUESTS_PER_MINUTE: ${REQUESTS_PER_MINUTE:-10}
# Conversion Service Configuration
BOOKHOARD_CONVERSION_CACHE_DIR: ${BOOKHOARD_CONVERSION_CACHE_DIR:-/app/cache/kepub}
BOOKHOARD_CONVERSION_TOOL: ${BOOKHOARD_CONVERSION_TOOL:-/usr/bin/kepubify}
BOOKHOARD_CONVERSION_CACHE_TTL: ${BOOKHOARD_CONVERSION_CACHE_TTL:-24h}
# System timezone (fallback for server-side time operations)
TZ: ${TZ:-UTC}
ports:
- "8765:8765"
depends_on:
db:
condition: service_healthy
volumes:
- ./uploads:/app/uploads
- bookhoard_conversion_cache:/app/cache/kepub
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8765/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
# Named Volumes
volumes:
postgres_data:
bookhoard_conversion_cache: