Ctrl K
ComunidadGuías…

docker-compose.ghcr.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Compose file using the prebuilt multi-arch image from GHCR
# (published by .github/workflows/docker-publish.yml for amd64 + arm64).
# No local build needed:
#   docker compose -f docker-compose.ghcr.yml up -d
# Defaults to ghcr.io/d0linger/parkrr; override PARKRR_IMAGE only with an image
# you trust. Pin a release with PARKRR_TAG=1.2 or immutable image content with
# PARKRR_TAG=1.2@sha256:<digest> using the published image digest.
#
# IMPORTANT: the `app` service below is kept byte-for-byte in sync with the
# `app` service in docker-compose.yml — same environment, volumes, ports and
# healthcheck, only `build:` swapped for the GHCR `image:`. This standalone shape
# is required for the single-file paste flows (Portainer web editor). The CI test
# TestGHCRComposeParity fails the build if the two drift apart (finding H-11):
# it used to silently miss the backup key, S3, SMTP, /backups and the proxy CIDRs.
services:
  db:
    image: postgres:16-alpine@sha256:f4610795587492cd4fb887c2dc3de301b813278bb6f616992061141b5f15ac36
    container_name: parkrr-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${PARKRR_DB_USER:-parkrr}
      POSTGRES_PASSWORD: ${PARKRR_DB_PASSWORD:?PARKRR_DB_PASSWORD must be set}
      POSTGRES_DB: ${PARKRR_DB_NAME:-parkrr}
    volumes:
      - parkrr-db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${PARKRR_DB_USER:-parkrr} -d ${PARKRR_DB_NAME:-parkrr}"]
      interval: 5s
      timeout: 5s
      retries: 10
    networks:
      - parkrr-net

  app:
    image: ghcr.io/${PARKRR_IMAGE:-d0linger/parkrr}:${PARKRR_TAG:-latest}
    container_name: parkrr-app
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      PARKRR_LISTEN_ADDR: ":8080"
      # --- Database (bundled service) ---
      # Optional full URL for an EXTERNAL database; overrides the PARKRR_DB_* below.
      PARKRR_DATABASE_URL: ${PARKRR_DATABASE_URL:-}
      PARKRR_DB_HOST: db
      PARKRR_DB_PORT: "5432"
      PARKRR_DB_USER: ${PARKRR_DB_USER:-parkrr}
      PARKRR_DB_PASSWORD: ${PARKRR_DB_PASSWORD:?PARKRR_DB_PASSWORD must be set}
      PARKRR_DB_NAME: ${PARKRR_DB_NAME:-parkrr}
      PARKRR_DB_SSLMODE: ${PARKRR_DB_SSLMODE:-disable}
      # --- Admin bootstrap (ADMIN_PASSWORD required) ---
      PARKRR_ADMIN_USERNAME: ${PARKRR_ADMIN_USERNAME:-admin}
      PARKRR_ADMIN_EMAIL: ${PARKRR_ADMIN_EMAIL:-admin@example.com}
      PARKRR_ADMIN_PASSWORD: ${PARKRR_ADMIN_PASSWORD:?PARKRR_ADMIN_PASSWORD must be set}
      # --- Security (SESSION_SECRET required, min. 32 chars) ---
      PARKRR_SESSION_SECRET: ${PARKRR_SESSION_SECRET:?PARKRR_SESSION_SECRET must be set}
      PARKRR_SESSION_MAX_AGE: ${PARKRR_SESSION_MAX_AGE:-604800}
      PARKRR_SESSION_SLIDING: ${PARKRR_SESSION_SLIDING:-false}
      PARKRR_SESSION_ABSOLUTE_MAX_AGE: ${PARKRR_SESSION_ABSOLUTE_MAX_AGE:-7776000}
      PARKRR_SECURE_COOKIES: ${PARKRR_SECURE_COOKIES:-true}
      PARKRR_TRUSTED_PROXY: ${PARKRR_TRUSTED_PROXY:-false}
      # Required when PARKRR_TRUSTED_PROXY=true: the reverse-proxy IP range(s) whose
      # forwarded headers are trusted. Without it the app refuses to start (H-06).
      PARKRR_TRUSTED_PROXY_CIDRS: ${PARKRR_TRUSTED_PROXY_CIDRS:-}
      PARKRR_CHECK_BREACHED_PASSWORDS: ${PARKRR_CHECK_BREACHED_PASSWORDS:-true}
      PARKRR_CHECK_BREACHED_BOOTSTRAP_PASSWORDS: ${PARKRR_CHECK_BREACHED_BOOTSTRAP_PASSWORDS:-false}
      # --- Passkeys (WebAuthn): set RP_ID + ORIGINS to enable ---
      PARKRR_WEBAUTHN_RP_ID: ${PARKRR_WEBAUTHN_RP_ID:-}
      PARKRR_WEBAUTHN_RP_NAME: ${PARKRR_WEBAUTHN_RP_NAME:-Parkrr}
      PARKRR_WEBAUTHN_ORIGINS: ${PARKRR_WEBAUTHN_ORIGINS:-}
      # --- Zweiter Faktor erzwingen (Opt-in, Standard aus) ---
      PARKRR_REQUIRE_2FA: ${PARKRR_REQUIRE_2FA:-false}
      PARKRR_PASSKEY_ONLY: ${PARKRR_PASSKEY_ONLY:-false}
      # --- Ops ---
      # Geschaeftszeitzone: bestimmt, welcher Kalendertag gemeint ist. Leer = Zone
      # des Containers (meist UTC).
      PARKRR_TIMEZONE: ${PARKRR_TIMEZONE:-}
      # Automatischer Rechnungslauf als 5-Feld-Cron. LEER = AUS.
      PARKRR_AUTO_INVOICE_CRON: ${PARKRR_AUTO_INVOICE_CRON:-}
      # Steuerbereich: lesend pruefen; Schreibzugriffe nur nach expliziter Aktivierung.
      PARKRR_TAX_WRITES_ENABLED: ${PARKRR_TAX_WRITES_ENABLED:-false}
      PARKRR_TAX_EXPORT_MAX_RECEIPT_MB: ${PARKRR_TAX_EXPORT_MAX_RECEIPT_MB:-24}
      # Empfaenger fuer Betriebsalarme (fehlgeschlagene Sicherungen). Braucht SMTP.
      PARKRR_ALERT_EMAIL: ${PARKRR_ALERT_EMAIL:-}
      PARKRR_RATE_LIMIT_PER_MIN: ${PARKRR_RATE_LIMIT_PER_MIN:-600}
      PARKRR_AUDIT_RETENTION_DAYS: ${PARKRR_AUDIT_RETENTION_DAYS:-2555}
      PARKRR_AUDIT_RETENTION_SHORT_DAYS: ${PARKRR_AUDIT_RETENTION_SHORT_DAYS:-365}
      # Encrypted backups. Set PARKRR_BACKUP_KEY to enable them (on-demand download
      # + scheduled). Scheduled backups default to the /backups volume below, which
      # lives next to the DB volume — convenient, but a copy beside the database it
      # protects is not an off-site backup: also configure S3 for 3-2-1. The
      # schedule (cron) and retention are edited in the Backup tab, not via env.
      # Large backup temp files (S3 upload/read-back, downloads, the decrypted dump
      # during a restore) also go to <PARKRR_BACKUP_DIR>/.tmp; plan ~2x the
      # archive size of free space on this volume.
      PARKRR_BACKUP_KEY: ${PARKRR_BACKUP_KEY:-}
      PARKRR_BACKUP_DIR: ${PARKRR_BACKUP_DIR:-/backups}
      PARKRR_BROWSER_RESTORE: ${PARKRR_BROWSER_RESTORE:-false}
      # Optional off-site S3-compatible target (AWS S3 / Backblaze B2 / Wasabi / MinIO).
      PARKRR_S3_ENDPOINT: ${PARKRR_S3_ENDPOINT:-}
      PARKRR_S3_BUCKET: ${PARKRR_S3_BUCKET:-}
      PARKRR_S3_ACCESS_KEY: ${PARKRR_S3_ACCESS_KEY:-}
      PARKRR_S3_SECRET_KEY: ${PARKRR_S3_SECRET_KEY:-}
      PARKRR_S3_REGION: ${PARKRR_S3_REGION:-}
      PARKRR_S3_PREFIX: ${PARKRR_S3_PREFIX:-parkrr/}
      PARKRR_S3_USE_SSL: ${PARKRR_S3_USE_SSL:-true}
      PARKRR_METRICS_TOKEN: ${PARKRR_METRICS_TOKEN:-}
      # Compose defaults to true (fail closed): /metrics needs PARKRR_METRICS_TOKEN
      # and is disabled without one. Set false only to opt out of authentication.
      PARKRR_METRICS_REQUIRE_AUTH: ${PARKRR_METRICS_REQUIRE_AUTH:-true}
      # --- E-mail (SMTP): set PARKRR_SMTP_HOST to enable payment reminders. ---
      PARKRR_SMTP_HOST: ${PARKRR_SMTP_HOST:-}
      PARKRR_SMTP_PORT: ${PARKRR_SMTP_PORT:-587}
      PARKRR_SMTP_USERNAME: ${PARKRR_SMTP_USERNAME:-}
      PARKRR_SMTP_PASSWORD: ${PARKRR_SMTP_PASSWORD:-}
      PARKRR_SMTP_FROM: ${PARKRR_SMTP_FROM:-}
      PARKRR_SMTP_FROM_NAME: ${PARKRR_SMTP_FROM_NAME:-Parkrr}
      PARKRR_SMTP_TLS: ${PARKRR_SMTP_TLS:-starttls}
      # Externally reachable base URL, used for links inside e-mail (e.g. reminders).
      PARKRR_PUBLIC_BASE_URL: ${PARKRR_PUBLIC_BASE_URL:-}
      PARKRR_LOG_FORMAT: ${PARKRR_LOG_FORMAT:-json}
      PARKRR_LOG_LEVEL: ${PARKRR_LOG_LEVEL:-info}
    healthcheck:
      test: ["CMD", "/app/parkrr", "healthcheck"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s
    ports:
      - "${PARKRR_HTTP_PORT:-8080}:8080"
    # Scheduled encrypted backups land here, in a named volume next to the DB's.
    volumes:
      - parkrr-backups:/backups
    networks:
      - parkrr-net

volumes:
  parkrr-db-data:
  parkrr-backups:

networks:
  parkrr-net: