Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 33 additions & 9 deletions stacks/storage/.env.example
Original file line number Diff line number Diff line change
@@ -1,20 +1,44 @@
# Storage Stack
# ==============================================================================
# Storage Stack �P Nextcloud FPM + MinIO + Filestash
# ==============================================================================



# Domain configuration
DOMAIN=yourdomain.com
TZ=Asia/Shanghai

# Nextcloud admin

# ---------------------------------------------------------------------------
# Nextcloud Admin
# ---------------------------------------------------------------------------

NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=CHANGE_ME_STRONG_PASSWORD

# Database (must match databases stack)
# ----------------------------------------------------------------------------
# Nextcloud Database (PostgreSQL)
# ----------------------------------------------------------------------------
NEXTCLOUD_DB_USER=nextcloud
NEXTCLOUD_DB_PASSWORD=CHANGE_ME
POSTGRES_PASSWORD=CHANGE_ME
REDIS_PASSWORD=CHANGE_ME
NEXTCLOUD_DB_PASSWORD=CHANGE_ME_POSTGRES_PASSWORD



# ----------------------------------------------------------------------------
# Redis Cache Password
# ----------------------------------------------------------------------------
REDIS_PASSWORD=CHANGE_ME_REDIS_PASSWORD

# MinIO
# ----------------------------------------------------------------------------
# MinIO S3 Storage
# ----------------------------------------------------------------------------
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=CHANGE_ME_MINIO_PASSWORD
MINIO_BUCKET=nextcloud
MINIO_REGION=us-east-1

# FileBrowser
FILEBROWSER_ROOT=/data
# ----------------------------------------------------------------------------
# Network
# ---------------------------------------------------------------------------
# The storage-network should be created: docker network create storage-network
# The proxy network should exist from base stack: docker network create proxy
173 changes: 132 additions & 41 deletions stacks/storage/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,144 @@
version: "3.8"

networks:
proxy:
external: true
storage-network:
external: true

services:
nextcloud:
image: nextcloud:29.0.9-apache
container_name: nextcloud
# ---------------------------------------------------------------------------
# Nextcloud FPM with Nginx Web Server
# ---------------------------------------------------------------------------
nextcloud-php:
image: nextcloud:29.0.9-fpm-alpine
container_name: nextcloud-php
restart: unless-stopped
networks:
- proxy
- databases
- storage-network
volumes:
- nextcloud-data:/var/www/html
- nextcloud-nginx-cache:/var/cache/nginx
depends_on:
- nextcloud-db
- nextcloud-redis
environment:
- TZ=${TZ:-Asia/Shanghai}
- NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER:-admin}
- NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD:-changeme}
- NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.${DOMAIN}
- POSTGRES_HOST=homelab-postgres
- POSTGRES_HOST=nextcloud-db
- POSTGRES_DB=nextcloud
- POSTGRES_USER=${POSTGRES_USER:-homelab}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme}
- REDIS_HOST=homelab-redis
- POSTGRES_USER=${NEXTCLOUD_DB_USER:-nextcloud}
- POSTGRES_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
- REDIS_HOST=nextcloud-redis
- REDIS_HOST_PASSWORD=${REDIS_PASSWORD}
- S3_BUCKET=${MINIO_BUCKET:-nextcloud}
- S3_REGION=${MINIO_REGION:-us-east-1}
- S3_ENDPOINT=https://s3.${DOMAIN}
- S3_USE_PATH_STYLE=true
- S3_ACCESS_KEY=${MINIO_ROOT_USER}
- S3_SECRET_KEY=${MINIO_ROOT_PASSWORD}
healthcheck:
test: [CMD-SHELL, "curl -sf http://localhost:9000/status.php || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s

nextcloud-web:
image: nginx:1.27-alpine
container_name: nextcloud-web
restart: unless-stopped
networks:
- proxy
- storage-network
volumes:
- nextcloud-data:/var/www/html:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- nextcloud-nginx-cache:/var/cache/nginx
depends_on:
- nextcloud-php
labels:
- traefik.enable=true
- "traefik.http.routers.nextcloud.rule=Host(`nextcloud.${DOMAIN}`)"
- traefik.http.routers.nextcloud.rule=Host(`nextcloud.${DOMAIN}`)
- traefik.http.routers.nextcloud.entrypoints=websecure
- traefik.http.routers.nextcloud.tls=true
- traefik.http.services.nextcloud.loadbalancer.server.port=80
- "traefik.http.middlewares.nextcloud-dav.redirectregex.regex=https://(.*)/.well-known/(card|cal)dav"
- "traefik.http.middlewares.nextcloud-dav.redirectregex.replacement=https://$${1}/remote.php/dav/"
- traefik.http.routers.nextcloud.middlewares=nextcloud-dav
- traefik.http.middlewares.nextcloud-headers.headers.customRequestHeaders.X-Forwarded-Proto=https
- traefik.http.routers.nextcloud.middlewares=nextcloud-headers
healthcheck:
test: [CMD-SHELL, "curl -sf http://localhost:80/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s

# ---------------------------------------------------------------------------
# Nextcloud Database (PostgreSQL)
# ---------------------------------------------------------------------------
nextcloud-db:
image: postgres:16-alpine
container_name: nextcloud-db
restart: unless-stopped
networks:
- storage-network
volumes:
- nextcloud-db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=nextcloud
- POSTGRES_USER=${NEXTCLOUD_DB_USER:-nextcloud}
- POSTGRES_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
healthcheck:
test: [CMD-SHELL, "curl -sf http://localhost:80/status.php || exit 1"]
test: [CMD-SHELL, "pg_isready -U ${NEXTCLOUD_DB_USER:-nextcloud}"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s

# ---------------------------------------------------------------------------
# Nextcloud Redis Cache
# ---------------------------------------------------------------------------
nextcloud-redis:
image: redis:7-alpine
container_name: nextcloud-redis
restart: unless-stopped
networks:
- storage-network
volumes:
- nextcloud-redis-data:/data
command: redis-server --requirepass ${REDIS_PASSWORD}
healthcheck:
test: [CMD-SHELL, "redis-cli -a ${REDIS_PASSWORD} ping"]
interval: 30s
timeout: 10s
retries: 5

# ---------------------------------------------------------------------------
# MinIO - S3-Compatible Object Storage
# ---------------------------------------------------------------------------
minio:
image: minio/minio:RELEASE.2024-11-07T00-52-20Z
container_name: minio
restart: unless-stopped
networks:
- proxy
- storage-network
volumes:
- minio-data:/data
environment:
- MINIO_ROOT_USER=${MINIO_ROOT_USER:-minioadmin}
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-changeme-minio}
- MINIO_BROWSER_REDIRECT_URL=https://minio.${DOMAIN}
- MINIO_ROOT_USER=${MINIO_ROOT_USER}
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
- MINIO_BROWSER_REDIRECT_URL=https://minio-console.${DOMAIN}
command: server /data --console-address ":9001"
labels:
- traefik.enable=true
- "traefik.http.routers.minio.rule=Host(`minio.${DOMAIN}`)"
- traefik.http.routers.minio.entrypoints=websecure
- traefik.http.routers.minio.tls=true
- traefik.http.services.minio.loadbalancer.server.port=9001
- "traefik.http.routers.minio-api.rule=Host(`s3.${DOMAIN}`)"
# MinIO Console
- traefik.http.routers.minio-console.rule=Host(`minio-console.${DOMAIN}`)
- traefik.http.routers.minio-console.entrypoints=websecure
- traefik.http.routers.minio-console.tls=true
- traefik.http.services.minio-console.loadbalancer.server.port=9001
# MinIO API/S3
- traefik.http.routers.minio-api.rule=Host(`s3.${DOMAIN}`)
- traefik.http.routers.minio-api.entrypoints=websecure
- traefik.http.routers.minio-api.tls=true
- traefik.http.services.minio-api.loadbalancer.server.port=9000
Expand All @@ -64,37 +149,43 @@ services:
retries: 3
start_period: 30s

filebrowser:
image: filebrowser/filebrowser:v2.31.2
container_name: filebrowser
# ---------------------------------------------------------------------------
# Filestash - Web File Browser for MinIO
# ---------------------------------------------------------------------------
filestash:
image: machines/filestash:0.9.4
container_name: filestash
restart: unless-stopped
networks:
- proxy
- storage-network
volumes:
- filebrowser-data:/database
- ${STORAGE_PATH:-/data}:/srv
- filestash-data:/app/data/state
environment:
- TZ=${TZ:-Asia/Shanghai}
- HOME=/app/data
# Filestash configuration for MinIO/S3
- EOF
# Multi-backend support: S3/MinIO
env_file:
- ./filestash.env
labels:
- traefik.enable=true
- "traefik.http.routers.filebrowser.rule=Host(`files.${DOMAIN}`)"
- traefik.http.routers.filebrowser.entrypoints=websecure
- traefik.http.routers.filebrowser.tls=true
- traefik.http.services.filebrowser.loadbalancer.server.port=80
- traefik.http.routers.filestash.rule=Host(`files.${DOMAIN}`)
- traefik.http.routers.filestash.entrypoints=websecure
- traefik.http.routers.filestash.tls=true
- traefik.http.services.filestash.loadbalancer.server.port=8334
healthcheck:
test: [CMD-SHELL, "curl -sf http://localhost:80/ || exit 1"]
test: [CMD-SHELL, "curl -sf http://localhost:8334/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s

networks:
proxy:
external: true
databases:
external: true

volumes:
nextcloud-data:
nextcloud-nginx-cache:
nextcloud-db-data:
nextcloud-redis-data:
minio-data:
filebrowser-data:
filestash-data:
33 changes: 33 additions & 0 deletions stacks/storage/filestash.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Filestash Configuration
# Documentation: https://www.filestash.app/docs/

# Application settings
[FENOM]
allowed_env = [TZ]

# S3/MinIO Backend
[backend]
s3 = {
endpoint = "https://s3.${DOMAIN}",
bucket = "${MINIO_BUCKET}",
region = "${MINIO_REGION}",
access_key_id = "${MINIO_ROOT_USER}",
secret_access_key = "${MINIO_ROOT_PASSWORD}",
force_path_style = true,
}

# Disable other backends for security
[backend/dropbox]
enabled = false

[backend/ftp]
enabled = false

[backend/sftp]
enabled = false

[backend/webdav]
enabled = false

[backend/s3]
enabled = true
Loading