compose.nextcloud.yaml
Rama main · réplica de lectura del repositorio original.
# Nextcloud on top of the Media Hub storage network. Overlay on compose.yaml; production
# enables it with `COMPOSE_FILE=compose.yaml:compose.nextcloud.yaml` in .env, so plain
# `docker compose ...` (and scripts/backup.sh etc.) include it. Test stack:
# docker compose -p mediahub-e2e --env-file <env> -f compose.yaml -f compose.nextcloud.yaml up -d --wait
#
# Nextcloud is unmodified: its primary storage is the S3 gateway (app/s3gw.py), which stores
# every object as a Media Hub blob (local copy + encrypted replicas on storage nodes).
# Only Caddy publishes a port (HTTPS ${NC_HTTPS_PORT}); s3gw, Nextcloud, its DB and Redis stay
# on the compose network. Object storage is chosen at install time: point a FRESH Nextcloud
# at it, never switch an existing one.
#
# Required in the env file: MEDIAHUB_S3_ACCESS_KEY, MEDIAHUB_S3_SECRET_KEY, NEXTCLOUD_DB_PASSWORD,
# NEXTCLOUD_ADMIN_PASSWORD, NEXTCLOUD_REDIS_PASSWORD, NC_DOMAIN (LAN IP or name).
x-nextcloud-env: &nextcloud-env
POSTGRES_HOST: nextcloud-db
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${NEXTCLOUD_DB_PASSWORD:?set NEXTCLOUD_DB_PASSWORD}
NEXTCLOUD_ADMIN_USER: ${NEXTCLOUD_ADMIN_USER:-admin}
NEXTCLOUD_ADMIN_PASSWORD: ${NEXTCLOUD_ADMIN_PASSWORD:?set NEXTCLOUD_ADMIN_PASSWORD}
NEXTCLOUD_TRUSTED_DOMAINS: ${NC_DOMAIN:?set NC_DOMAIN} localhost
# Behind Caddy (TLS terminated there): generate https URLs with the public host:port and
# trust X-Forwarded-For only from the compose network (brute-force protection sees real IPs).
OVERWRITEPROTOCOL: https
OVERWRITEHOST: ${NC_DOMAIN}:${NC_HTTPS_PORT:-9443}
OVERWRITECLIURL: https://${NC_DOMAIN}:${NC_HTTPS_PORT:-9443}
TRUSTED_PROXIES: ${NC_TRUSTED_PROXIES:-172.16.0.0/12}
REDIS_HOST: nextcloud-redis
REDIS_HOST_PASSWORD: ${NEXTCLOUD_REDIS_PASSWORD:?set NEXTCLOUD_REDIS_PASSWORD}
PHP_UPLOAD_LIMIT: 20G
PHP_MEMORY_LIMIT: 1G
# The image caps request bodies at 1 GiB; single-request WebDAV uploads above that fail
# (the official clients chunk, but curl/rclone PUTs don't).
APACHE_BODY_LIMIT: "0"
OBJECTSTORE_S3_BUCKET: nextcloud
OBJECTSTORE_S3_HOST: s3gw
OBJECTSTORE_S3_PORT: "9000"
OBJECTSTORE_S3_SSL: "false"
OBJECTSTORE_S3_USEPATH_STYLE: "true"
OBJECTSTORE_S3_REGION: us-east-1
OBJECTSTORE_S3_AUTOCREATE: "true"
OBJECTSTORE_S3_KEY: ${MEDIAHUB_S3_ACCESS_KEY:?set MEDIAHUB_S3_ACCESS_KEY}
OBJECTSTORE_S3_SECRET: ${MEDIAHUB_S3_SECRET_KEY:?set MEDIAHUB_S3_SECRET_KEY}
TZ: ${MEDIAHUB_TIMEZONE:-Asia/Taipei}
x-logging: &logging
driver: json-file
options:
max-size: "10m"
max-file: "5"
services:
s3gw:
extends:
file: compose.yaml
service: worker
command: ["uvicorn", "app.s3gw:app", "--host", "0.0.0.0", "--port", "9000", "--workers", "2", "--timeout-keep-alive", "30"]
environment:
MEDIAHUB_S3_ACCESS_KEY: ${MEDIAHUB_S3_ACCESS_KEY}
MEDIAHUB_S3_SECRET_KEY: ${MEDIAHUB_S3_SECRET_KEY}
cpus: 4
mem_limit: 1g
stop_grace_period: 10s
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:9000/_health', timeout=4)"]
interval: 10s
timeout: 5s
retries: 12
start_period: 10s
nextcloud-db:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${NEXTCLOUD_DB_PASSWORD}
POSTGRES_DB: nextcloud
volumes:
- nc_pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U nextcloud -d nextcloud"]
interval: 5s
timeout: 5s
retries: 20
logging: *logging
# Distributed cache + file locking. Also required for chunked upload v2 (chunks written
# straight into an S3 multipart upload instead of being stored twice).
nextcloud-redis:
image: redis:8-alpine
restart: unless-stopped
command: ["redis-server", "--requirepass", "${NEXTCLOUD_REDIS_PASSWORD}", "--save", "", "--appendonly", "no"]
environment:
REDISCLI_AUTH: ${NEXTCLOUD_REDIS_PASSWORD}
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 20
logging: *logging
nextcloud:
image: nextcloud:34-apache
restart: unless-stopped
environment: *nextcloud-env
volumes:
# Code, config.php (instance secrets!), apps. File contents go to the S3 gateway.
- nc_html:/var/www/html
- ./deploy/nextcloud/hooks/before-starting:/docker-entrypoint-hooks.d/before-starting:ro
- ./deploy/nextcloud/hooks/post-upgrade:/docker-entrypoint-hooks.d/post-upgrade:ro
- ./deploy/nextcloud/hooks/post-upgrade:/docker-entrypoint-hooks.d/post-installation:ro
depends_on:
nextcloud-db:
condition: service_healthy
nextcloud-redis:
condition: service_healthy
s3gw:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -fsS -H 'Host: localhost' http://127.0.0.1/status.php | grep -q '\"installed\":true'"]
interval: 15s
timeout: 10s
retries: 20
start_period: 5m
mem_limit: 2g
logging: *logging
# Background jobs (file scans, previews, trash/version expiry) every 5 minutes.
nextcloud-cron:
image: nextcloud:34-apache
restart: unless-stopped
entrypoint: /cron.sh
environment: *nextcloud-env
volumes:
- nc_html:/var/www/html
depends_on:
nextcloud:
condition: service_healthy
mem_limit: 1g
logging: *logging
caddy:
environment:
NC_SITES: https://${NC_DOMAIN}:${NC_HTTPS_PORT:-9443}
ports:
- "${HUB_BIND:-127.0.0.1}:${NC_HTTPS_PORT:-9443}:${NC_HTTPS_PORT:-9443}"
volumes:
- ./deploy/caddy/nextcloud.caddy:/etc/caddy/sites/nextcloud.caddy:ro
volumes:
nc_pgdata:
nc_html: