Tots els compose
This commit is contained in:
34
adguard/docker-compose.yml
Normal file
34
adguard/docker-compose.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# /opt/stacks/adguardhome/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
adguardhome:
|
||||||
|
container_name: adguardhome
|
||||||
|
image: adguard/adguardhome:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "53:53/tcp" # DNS TCP — públic (necessari per a tota la xarxa)
|
||||||
|
- "53:53/udp" # DNS UDP — públic (necessari per a tota la xarxa)
|
||||||
|
- "853:853/tcp" # DNS-over-TLS — públic (clients externs)
|
||||||
|
- "3000:3000" # Wizard inicial (només local — tancar després de setup)
|
||||||
|
- "8080:80" # Dashboard web (només local → via Nginx)
|
||||||
|
volumes:
|
||||||
|
- adguard_work:/opt/adguardhome/work # Volum named — evita reset al wizard
|
||||||
|
- adguard_conf:/opt/adguardhome/conf # Volum named — configuració persistent
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
networks:
|
||||||
|
- dns-net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
adguard_work:
|
||||||
|
adguard_conf:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
dns-net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
17
astro/Dockerfile
Normal file
17
astro/Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# ── Fase 1: Compilació amb Node.js ────────
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
# Instal·la dependències primer (aprofita la cache de Docker)
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
# Copia el codi font i compila
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ── Fase 2: Servir amb Nginx (imatge mínima) ──
|
||||||
|
FROM nginx:alpine
|
||||||
|
# Copia NOMÉS la carpeta dist/ de la fase anterior
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
# Configuració Nginx per a SPA i rutes d'Astro
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
EXPOSE 80
|
||||||
28
astro/docker-compose.yml
Normal file
28
astro/docker-compose.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# /opt/stacks/astro-web/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
astro-web:
|
||||||
|
container_name: astro-web
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: astro-web:local # Nom explícit per a la imatge buildada
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
ports:
|
||||||
|
- "8087:80" # Només local → via Nginx Proxy Manager
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:80"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 15s
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
16
astro/nginx.conf
Normal file
16
astro/nginx.conf
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Rutes d'Astro: si no troba el fitxer, retorna 404.html
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ $uri.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache agressiva per a assets compilats (hash al nom)
|
||||||
|
location /_astro/ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
103
authentik/docker-compose.yml
Normal file
103
authentik/docker-compose.yml
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
# /opt/stacks/authentik/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── Base de dades PostgreSQL ─────────────
|
||||||
|
postgresql:
|
||||||
|
container_name: authentik-postgres
|
||||||
|
image: postgres:16-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: '${PG_PASS}'
|
||||||
|
POSTGRES_USER: authentik
|
||||||
|
POSTGRES_DB: authentik
|
||||||
|
volumes:
|
||||||
|
- pg_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U authentik -d authentik"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s # Afegit
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s # Afegit
|
||||||
|
networks: [authentik_net]
|
||||||
|
|
||||||
|
# ── Redis per a sessions ─────────────────
|
||||||
|
redis:
|
||||||
|
container_name: authentik-redis
|
||||||
|
image: redis:7.4-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
command: redis-server --requirepass '${REDIS_PASS}'
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "-a", "${REDIS_PASS}", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s # Afegit
|
||||||
|
retries: 5
|
||||||
|
start_period: 15s # Afegit
|
||||||
|
networks: [authentik_net]
|
||||||
|
|
||||||
|
# ── Authentik Server (API + UI) ───────────
|
||||||
|
server:
|
||||||
|
container_name: authentik-server
|
||||||
|
image: ghcr.io/goauthentik/server:2026.5.3 # Actualitzat a darrera versió estable
|
||||||
|
restart: unless-stopped
|
||||||
|
command: server
|
||||||
|
environment:
|
||||||
|
# ⚠️ NO afegir TZ aquí — trenca OAuth/SAML (doc oficial)
|
||||||
|
AUTHENTIK_REDIS__HOST: redis
|
||||||
|
AUTHENTIK_REDIS__PASSWORD: '${REDIS_PASS}'
|
||||||
|
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||||
|
AUTHENTIK_POSTGRESQL__USER: authentik
|
||||||
|
AUTHENTIK_POSTGRESQL__NAME: authentik
|
||||||
|
AUTHENTIK_POSTGRESQL__PASSWORD: '${PG_PASS}'
|
||||||
|
AUTHENTIK_SECRET_KEY: '${AUTHENTIK_SECRET_KEY}'
|
||||||
|
AUTHENTIK_ERROR_REPORTING__ENABLED: "false" # String, no booleà YAML
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:9000:9000" # HTTP (només local → via Nginx)
|
||||||
|
- "127.0.0.1:9443:9443" # HTTPS (només local → via Nginx)
|
||||||
|
volumes:
|
||||||
|
- authentik_media:/media
|
||||||
|
- authentik_templates:/templates
|
||||||
|
depends_on:
|
||||||
|
postgresql:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [authentik_net, shared_net]
|
||||||
|
|
||||||
|
# ── Authentik Worker (tasques en segon pla) ──
|
||||||
|
worker:
|
||||||
|
container_name: authentik-worker
|
||||||
|
image: ghcr.io/goauthentik/server:2026.5.3 # Mateixa versió que server
|
||||||
|
restart: unless-stopped
|
||||||
|
command: worker
|
||||||
|
environment:
|
||||||
|
# ⚠️ NO afegir TZ aquí — trenca OAuth/SAML (doc oficial)
|
||||||
|
AUTHENTIK_REDIS__HOST: redis
|
||||||
|
AUTHENTIK_REDIS__PASSWORD: '${REDIS_PASS}'
|
||||||
|
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||||
|
AUTHENTIK_POSTGRESQL__USER: authentik
|
||||||
|
AUTHENTIK_POSTGRESQL__NAME: authentik
|
||||||
|
AUTHENTIK_POSTGRESQL__PASSWORD: '${PG_PASS}'
|
||||||
|
AUTHENTIK_SECRET_KEY: '${AUTHENTIK_SECRET_KEY}'
|
||||||
|
volumes:
|
||||||
|
- authentik_media:/media
|
||||||
|
- authentik_templates:/templates # Afegit: worker també necessita templates
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro # Gestió automàtica d'Outposts
|
||||||
|
depends_on:
|
||||||
|
postgresql:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [authentik_net]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pg_data:
|
||||||
|
authentik_media:
|
||||||
|
authentik_templates:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
authentik_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
19
bentopdf/docker-compose.yml
Normal file
19
bentopdf/docker-compose.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# /opt/stacks/bentopdf/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
bentopdf:
|
||||||
|
container_name: bentopdf
|
||||||
|
image: bentopdfteam/bentopdf:latest # Imatge activa — bentopdf/bentopdf és deprecated!
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
ports:
|
||||||
|
- "9999:8080" # Només local → via Nginx Proxy Manager
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
23
beszel/docker-compose.yml
Normal file
23
beszel/docker-compose.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# /opt/stacks/beszel/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
beszel:
|
||||||
|
image: henrygd/beszel:latest
|
||||||
|
container_name: beszel
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8090:8090" # Interfície web (només local)
|
||||||
|
volumes:
|
||||||
|
- beszel_data:/beszel_data # Volum named — més estable que path relatiu
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
beszel_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
30
ddns-go/docker-compose.yml
Normal file
30
ddns-go/docker-compose.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# /opt/stacks/ddns/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
ddns-go:
|
||||||
|
container_name: ddns-go
|
||||||
|
image: jeessy/ddns-go:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "9876:9876" # UI web (només local → via Nginx)
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
- ddns_data:/root # Persisteix la configuració
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-qO-", "http://localhost:9876"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 15s
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
ddns_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
66
flowise/docker-compose.yml
Normal file
66
flowise/docker-compose.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# /opt/stacks/flowise/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: '${POSTGRES_USER}'
|
||||||
|
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
|
||||||
|
POSTGRES_DB: flowise
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d flowise"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s # Afegit: timeout explícit
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s # Afegit: marge per a l'arrencada inicial
|
||||||
|
networks:
|
||||||
|
- flowise-net
|
||||||
|
|
||||||
|
flowise:
|
||||||
|
image: flowiseai/flowise:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "3000:3000" # Interfície web (només local → via Nginx)
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
# Base de dades
|
||||||
|
DATABASE_TYPE: postgres
|
||||||
|
DATABASE_HOST: postgres
|
||||||
|
DATABASE_PORT: 5432
|
||||||
|
DATABASE_NAME: flowise
|
||||||
|
DATABASE_USER: '${POSTGRES_USER}'
|
||||||
|
DATABASE_PASSWORD: '${POSTGRES_PASSWORD}'
|
||||||
|
# Autenticació
|
||||||
|
FLOWISE_USERNAME: '${FLOWISE_USERNAME}'
|
||||||
|
FLOWISE_PASSWORD: '${FLOWISE_PASSWORD}'
|
||||||
|
# Seguretat — CRÍTIC: fes backup d'aquesta clau!
|
||||||
|
FLOWISE_SECRETKEY_OVERWRITE: '${FLOWISE_SECRETKEY}'
|
||||||
|
# Paths i logs
|
||||||
|
APIKEY_PATH: /root/.flowise
|
||||||
|
SECRETKEY_PATH: /root/.flowise
|
||||||
|
LOG_LEVEL: info
|
||||||
|
LOG_PATH: /root/.flowise/logs
|
||||||
|
volumes:
|
||||||
|
- flowise_data:/root/.flowise
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- flowise-net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
flowise_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
flowise-net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
83
gitea/docker-compose.yml
Normal file
83
gitea/docker-compose.yml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# /opt/stacks/gitea/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── MariaDB ──────────────────────────────
|
||||||
|
db:
|
||||||
|
container_name: gitea-db
|
||||||
|
image: mariadb:10.11
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
MYSQL_ROOT_PASSWORD: '${MYSQL_ROOT_PASSWORD}'
|
||||||
|
MYSQL_DATABASE: gitea
|
||||||
|
MYSQL_USER: gitea
|
||||||
|
MYSQL_PASSWORD: '${MYSQL_PASSWORD}'
|
||||||
|
volumes:
|
||||||
|
- gitea_db:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks: [gitea_net]
|
||||||
|
|
||||||
|
# ── Gitea ────────────────────────────────
|
||||||
|
gitea:
|
||||||
|
container_name: gitea
|
||||||
|
image: gitea/gitea:1 # Pinnat a major version — evita trencaments per latest
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid # Substitueix els bind mounts de timezone
|
||||||
|
USER_UID: 1000
|
||||||
|
USER_GID: 1000
|
||||||
|
# Connexió a MariaDB
|
||||||
|
GITEA__database__DB_TYPE: mysql
|
||||||
|
GITEA__database__HOST: db:3306
|
||||||
|
GITEA__database__NAME: gitea
|
||||||
|
GITEA__database__USER: gitea
|
||||||
|
GITEA__database__PASSWD: '${MYSQL_PASSWORD}'
|
||||||
|
# URL pública (obligatori per a clons SSH i web)
|
||||||
|
GITEA__server__ROOT_URL: 'https://git.domini.com/'
|
||||||
|
GITEA__server__SSH_DOMAIN: git.domini.com
|
||||||
|
GITEA__server__SSH_PORT: 2222
|
||||||
|
GITEA__server__DOMAIN: git.domini.com
|
||||||
|
# Desactiva el registre públic
|
||||||
|
GITEA__service__DISABLE_REGISTRATION: 'true'
|
||||||
|
# Seguretat
|
||||||
|
GITEA__security__SECRET_KEY: '${GITEA_SECRET_KEY}'
|
||||||
|
GITEA__security__INTERNAL_TOKEN: '${GITEA_INTERNAL_TOKEN}'
|
||||||
|
# Mailer — descomenta i configura per a notificacions per email
|
||||||
|
# GITEA__mailer__ENABLED: 'true'
|
||||||
|
# GITEA__mailer__SMTP_ADDR: mail.domini.com
|
||||||
|
# GITEA__mailer__SMTP_PORT: '587'
|
||||||
|
# GITEA__mailer__USER: '${GITEA_SMTP_USER}'
|
||||||
|
# GITEA__mailer__PASSWD: '${GITEA_SMTP_PASSWORD}'
|
||||||
|
# GITEA__mailer__FROM: 'Gitea <gitea@domini.com>'
|
||||||
|
volumes:
|
||||||
|
- gitea_data:/data
|
||||||
|
ports:
|
||||||
|
- "3000:3000" # Web UI → via Nginx Proxy Manager
|
||||||
|
- "2222:22" # SSH públic — necessari per a git push/pull directe
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:3000"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [gitea_net, shared_net]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
gitea_db:
|
||||||
|
gitea_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
gitea_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
21
glance/docker-compose.yml
Normal file
21
glance/docker-compose.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# /opt/stacks/glance/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
glance:
|
||||||
|
image: glanceapp/glance:latest
|
||||||
|
container_name: glance
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8080:8080" # Interfície web (només local)
|
||||||
|
volumes:
|
||||||
|
- ./glance.yml:/app/glance.yml:ro # Configuració principal
|
||||||
|
- ./assets:/app/assets:ro # Assets locals (icones, imatges)
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
10
glance/glance.yml
Normal file
10
glance/glance.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
server:
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
pages:
|
||||||
|
- name: Inici
|
||||||
|
columns:
|
||||||
|
- size: full
|
||||||
|
widgets:
|
||||||
|
- type: clock
|
||||||
|
hour-format: 24h
|
||||||
15
headscale/config.yml
Normal file
15
headscale/config.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
server_url: https://headscale.el-teu-domini.com
|
||||||
|
listen_addr: 0.0.0.0:8080
|
||||||
|
metrics_listen_addr: 0.0.0.0:9090
|
||||||
|
private_key_path: /var/lib/headscale/private.key
|
||||||
|
noise:
|
||||||
|
private_key_path: /var/lib/headscale/noise_private.key
|
||||||
|
ip_prefixes:
|
||||||
|
- 100.64.0.0/10 # Rang IPs Tailscale
|
||||||
|
dns_config:
|
||||||
|
magic_dns: true
|
||||||
|
base_domain: homelab.intern
|
||||||
|
nameservers:
|
||||||
|
- 9.9.9.9
|
||||||
|
db_type: sqlite3
|
||||||
|
db_path: /var/lib/headscale/db.sqlite
|
||||||
48
headscale/docker-compose.yml
Normal file
48
headscale/docker-compose.yml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# /opt/stacks/headscale/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
headscale:
|
||||||
|
container_name: headscale
|
||||||
|
image: headscale/headscale:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
command: serve
|
||||||
|
ports:
|
||||||
|
- "8080:8080" # API i clients (només local → via Nginx)
|
||||||
|
- "9090:9090" # Mètriques Prometheus (mai públic)
|
||||||
|
volumes:
|
||||||
|
- headscale_config:/etc/headscale # Configuració persistent
|
||||||
|
- headscale_data:/var/lib/headscale # Dades persistents
|
||||||
|
- headscale_socket:/var/run/headscale # Socket Unix per a la UI
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
networks:
|
||||||
|
- headscale-net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
headscale-ui:
|
||||||
|
container_name: headscale-ui
|
||||||
|
image: ghcr.io/gurucomputing/headscale-ui:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8081:80" # Interfície web (només local → via Nginx)
|
||||||
|
volumes:
|
||||||
|
- headscale_socket:/var/run/headscale # Socket Unix compartit amb headscale
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
depends_on:
|
||||||
|
- headscale
|
||||||
|
networks:
|
||||||
|
- headscale-net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
headscale_config:
|
||||||
|
headscale_data:
|
||||||
|
headscale_socket:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
headscale-net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
28
homarr/docker-compose.yml
Normal file
28
homarr/docker-compose.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# /opt/stacks/homarr/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
homarr:
|
||||||
|
image: ghcr.io/ajnart/homarr:latest
|
||||||
|
container_name: homarr
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "7575:7575" # Interfície web (només local)
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro # :ro = només lectura
|
||||||
|
- homarr_configs:/app/data/configs # Configuració
|
||||||
|
- homarr_icons:/app/public/icons # Icones personalitzades
|
||||||
|
- homarr_data:/data # Dades persistents
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
homarr_configs:
|
||||||
|
homarr_icons:
|
||||||
|
homarr_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
112
immich/docker-compose.yml
Normal file
112
immich/docker-compose.yml
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
# /opt/stacks/immich/docker-compose.yml
|
||||||
|
# Documentació oficial: https://docs.immich.app/install/docker-compose/
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── Immich Server ─────────────────────────
|
||||||
|
immich-server:
|
||||||
|
container_name: immich-server
|
||||||
|
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
DB_URL: "postgresql://${DB_USERNAME}:${DB_PASSWORD}@immich-db:5432/${DB_DATABASE_NAME}"
|
||||||
|
REDIS_HOSTNAME: immich-redis
|
||||||
|
IMMICH_ENV: production
|
||||||
|
UPLOAD_LOCATION: ${UPLOAD_LOCATION}
|
||||||
|
volumes:
|
||||||
|
- ${UPLOAD_LOCATION}:/usr/src/app/upload
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:2283:2283" # Web UI → via Nginx Proxy Manager
|
||||||
|
depends_on:
|
||||||
|
immich-db:
|
||||||
|
condition: service_healthy
|
||||||
|
immich-redis:
|
||||||
|
condition: service_healthy
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:2283/api/server/ping"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s
|
||||||
|
networks:
|
||||||
|
- immich_net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
|
||||||
|
# ── Machine Learning ──────────────────────
|
||||||
|
immich-machine-learning:
|
||||||
|
container_name: immich-machine-learning
|
||||||
|
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
IMMICH_ENV: production
|
||||||
|
volumes:
|
||||||
|
- model-cache:/cache
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:3003/ping')"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 120s # El model triga a carregar-se
|
||||||
|
networks:
|
||||||
|
- immich_net
|
||||||
|
|
||||||
|
|
||||||
|
# ── Redis ─────────────────────────────────
|
||||||
|
immich-redis:
|
||||||
|
container_name: immich-redis
|
||||||
|
image: redis:7-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 10s
|
||||||
|
networks:
|
||||||
|
- immich_net
|
||||||
|
|
||||||
|
|
||||||
|
# ── PostgreSQL + VectorChord ───────────────
|
||||||
|
# Imatge oficial d'Immich — substitueix tensorchord/pgvecto-rs (obsoleta)
|
||||||
|
immich-db:
|
||||||
|
container_name: immich-db
|
||||||
|
image: ghcr.io/immich-app/postgres:17-vectorchord
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
POSTGRES_DB: ${DB_DATABASE_NAME}
|
||||||
|
POSTGRES_USER: ${DB_USERNAME}
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
POSTGRES_INITDB_ARGS: "--data-checksums"
|
||||||
|
volumes:
|
||||||
|
- pgdata:/var/lib/postgresql/data # Volum named — mai network share
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE_NAME}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks:
|
||||||
|
- immich_net
|
||||||
|
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pgdata:
|
||||||
|
model-cache:
|
||||||
|
redis-data:
|
||||||
|
|
||||||
|
|
||||||
|
networks:
|
||||||
|
immich_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
44
jenkins/docker-compose.yml
Normal file
44
jenkins/docker-compose.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# /opt/stacks/jenkins/docker-compose.yml
|
||||||
|
#
|
||||||
|
# SEGURETAT: Jenkins s'executa com a usuari jenkins (uid 1000), no com a root.
|
||||||
|
# Per accedir a Docker des de pipelines, s'usa Docker-in-Docker (dind) o
|
||||||
|
# s'afegeix l'usuari jenkins al grup docker del host (vegeu notes al final).
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
jenkins:
|
||||||
|
container_name: jenkins
|
||||||
|
image: jenkins/jenkins:lts-jdk17
|
||||||
|
restart: unless-stopped
|
||||||
|
# NO usar user: root — risc crític amb docker.sock muntat
|
||||||
|
# L'uid 1000 és l'usuari jenkins per defecte de la imatge oficial
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
JAVA_OPTS: >-
|
||||||
|
-Djenkins.install.runSetupWizard=true
|
||||||
|
-Xmx512m
|
||||||
|
-Xms256m
|
||||||
|
volumes:
|
||||||
|
- jenkins_home:/var/jenkins_home
|
||||||
|
# Docker socket — NOMÉS si has fet: sudo usermod -aG docker <host_user>
|
||||||
|
# i has ajustat els permisos del socket (vegeu notes)
|
||||||
|
# - /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
ports:
|
||||||
|
- "8089:8080" # Web UI → via Nginx Proxy Manager
|
||||||
|
- "50000:50000" # Agents Jenkins (JNLP)
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8080/login"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 90s # Jenkins triga a arrencar
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
jenkins_home:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
27
kavita/docker-compose.yml
Normal file
27
kavita/docker-compose.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# /opt/stacks/kavita/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
kavita:
|
||||||
|
container_name: kavita
|
||||||
|
image: jvmilazz0/kavita:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
# Carpeta amb els teus llibres/còmics/manga (read-only — Kavita no necessita escriure-hi)
|
||||||
|
- /ruta/als/teus/llibres:/manga:ro
|
||||||
|
# Configuració i base de dades SQLite de Kavita
|
||||||
|
- kavita_config:/kavita/config
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5000:5000" # Només local → via Nginx Proxy Manager
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
kavita_config:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
42
localai/docker-compose.yml
Normal file
42
localai/docker-compose.yml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# /opt/stacks/localai/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
localai:
|
||||||
|
container_name: localai
|
||||||
|
image: localai/localai:latest-aio-cpu
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8080:8080" # API LocalAI (només local → via Nginx)
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
# Configuració de rendiment (prefix LOCALAI_ obligatori)
|
||||||
|
LOCALAI_THREADS: 4 # Fils de CPU a usar
|
||||||
|
LOCALAI_CONTEXT_SIZE: 4096 # Context màxim en tokens
|
||||||
|
LOCALAI_MODELS_PATH: /models # Path dels models GGUF
|
||||||
|
# Logs i telemetria
|
||||||
|
LOCALAI_LOG_LEVEL: info
|
||||||
|
LOCALAI_DISABLE_USAGE_STATS: true
|
||||||
|
# Opcionals recomanats
|
||||||
|
LOCALAI_PARALLEL_REQUESTS: true # Permet múltiples peticions simultànies
|
||||||
|
LOCALAI_SINGLE_ACTIVE_BACKEND: true # Allibera memòria quan es canvia de model
|
||||||
|
volumes:
|
||||||
|
- localai_models:/models # Models GGUF persistents
|
||||||
|
- localai_config:/etc/localai # Configuració de models YAML
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8080/readyz"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 120s # LocalAI triga a arrencar la 1a vegada
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
localai_models:
|
||||||
|
localai_config:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
59
mariadb/docker-compose.yml
Normal file
59
mariadb/docker-compose.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# /opt/stacks/mariadb/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── Servei MariaDB ───────────────────────
|
||||||
|
mariadb:
|
||||||
|
container_name: mariadb
|
||||||
|
image: mariadb:11.4 # Pinnat a LTS estable
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
MARIADB_ROOT_PASSWORD: '${MARIADB_ROOT_PASSWORD}'
|
||||||
|
MARIADB_DATABASE: '${MARIADB_DATABASE}'
|
||||||
|
MARIADB_USER: '${MARIADB_USER}'
|
||||||
|
MARIADB_PASSWORD: '${MARIADB_PASSWORD}'
|
||||||
|
MARIADB_CHARACTER_SET_SERVER: utf8mb4
|
||||||
|
MARIADB_COLLATION_SERVER: utf8mb4_unicode_ci
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:3306:3306" # Accés local per eines externes (DBeaver, etc.)
|
||||||
|
volumes:
|
||||||
|
- mariadb_data:/var/lib/mysql
|
||||||
|
- mariadb_init:/docker-entrypoint-initdb.d # Volum named en lloc de bind mount
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s # Afegit: timeout explícit
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s # Afegit: marge per a scripts d'inicialització
|
||||||
|
networks:
|
||||||
|
- db_net
|
||||||
|
|
||||||
|
# ── Adminer: UI web per gestionar la BD ──
|
||||||
|
adminer:
|
||||||
|
container_name: adminer
|
||||||
|
image: adminer:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8090:8080" # UI web (només local → via Nginx)
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
ADMINER_DEFAULT_SERVER: mariadb # Pre-omple el camp servidor a la UI
|
||||||
|
ADMINER_DESIGN: pepa-linha # Tema visual més modern (opcional)
|
||||||
|
depends_on:
|
||||||
|
mariadb:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- db_net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mariadb_data:
|
||||||
|
mariadb_init: # Posa els teus scripts SQL aquí
|
||||||
|
|
||||||
|
networks:
|
||||||
|
db_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
100
mautic/docker-compose.yml
Normal file
100
mautic/docker-compose.yml
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# /opt/stacks/mautic/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── MariaDB per a Mautic ─────────────────
|
||||||
|
db:
|
||||||
|
container_name: mautic-db
|
||||||
|
image: mariadb:10.11
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
MYSQL_ROOT_PASSWORD: '${MYSQL_ROOT_PASSWORD}'
|
||||||
|
MYSQL_DATABASE: mautic
|
||||||
|
MYSQL_USER: mautic
|
||||||
|
MYSQL_PASSWORD: '${MYSQL_PASSWORD}'
|
||||||
|
volumes:
|
||||||
|
- mautic_db:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks: [mautic_net]
|
||||||
|
|
||||||
|
# ── Mautic — Aplicació principal (web) ───
|
||||||
|
mautic_web:
|
||||||
|
container_name: mautic-web
|
||||||
|
image: mautic/mautic:6-apache # Actualitzat a Mautic 6
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .mautic_env # Variables específiques de Mautic
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
MAUTIC_ROLE: mautic_web # Mode natiu de la imatge oficial
|
||||||
|
volumes:
|
||||||
|
- mautic_config:/var/www/html/config # Configuració local.php
|
||||||
|
- mautic_logs:/var/www/html/var/logs # Logs de l'aplicació
|
||||||
|
- mautic_media:/var/www/html/docroot/media # Fitxers pujats i generats
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8083:80"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost/mtc.js"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [mautic_net, shared_net]
|
||||||
|
|
||||||
|
# ── Mautic Worker — processa cues async ──
|
||||||
|
mautic_worker:
|
||||||
|
container_name: mautic-worker
|
||||||
|
image: mautic/mautic:6-apache
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .mautic_env
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
MAUTIC_ROLE: mautic_worker # Mode worker natiu
|
||||||
|
MAUTIC_MESSENGER_CONSUME_OPTS: '--time-limit=300 --memory-limit=128M'
|
||||||
|
volumes:
|
||||||
|
- mautic_config:/var/www/html/config
|
||||||
|
- mautic_logs:/var/www/html/var/logs
|
||||||
|
- mautic_media:/var/www/html/docroot/media
|
||||||
|
depends_on:
|
||||||
|
mautic_web:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [mautic_net]
|
||||||
|
|
||||||
|
# ── Mautic Cron — tasques programades ────
|
||||||
|
mautic_cron:
|
||||||
|
container_name: mautic-cron
|
||||||
|
image: mautic/mautic:6-apache
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .mautic_env
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
MAUTIC_ROLE: mautic_cron # Mode cron natiu — gestiona tots els jobs
|
||||||
|
volumes:
|
||||||
|
- mautic_config:/var/www/html/config
|
||||||
|
- mautic_logs:/var/www/html/var/logs
|
||||||
|
- mautic_media:/var/www/html/docroot/media
|
||||||
|
depends_on:
|
||||||
|
mautic_web:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [mautic_net]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mautic_db:
|
||||||
|
mautic_config:
|
||||||
|
mautic_logs:
|
||||||
|
mautic_media:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
mautic_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
24
mermaid/docker-compose.yml
Normal file
24
mermaid/docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# /opt/stacks/mermaid/docker-compose.yml
|
||||||
|
#
|
||||||
|
# IMPORTANT: mermaid-live-editor NO suporta variables d'entorn en runtime.
|
||||||
|
# Les opcions com MERMAID_RENDERER_URL són build arguments — s'ignoren aquí.
|
||||||
|
# La imatge pre-built usa mermaid.ink com a renderer (requereix internet).
|
||||||
|
# Per a un entorn offline complet, cal fer un build propi (vegeu README).
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
mermaid:
|
||||||
|
container_name: mermaid
|
||||||
|
image: ghcr.io/mermaid-js/mermaid-live-editor:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
ports:
|
||||||
|
- "8088:8080" # Només local → via Nginx Proxy Manager
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
62
moodle/docker-compose.yml
Normal file
62
moodle/docker-compose.yml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# /opt/stacks/moodle/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── MariaDB per a Moodle ─────────────────
|
||||||
|
db:
|
||||||
|
container_name: moodle-db
|
||||||
|
image: mariadb:10.11
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
MYSQL_ROOT_PASSWORD: '${MYSQL_ROOT_PASSWORD}'
|
||||||
|
MYSQL_DATABASE: moodle
|
||||||
|
MYSQL_USER: moodle
|
||||||
|
MYSQL_PASSWORD: '${MYSQL_PASSWORD}'
|
||||||
|
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||||
|
volumes:
|
||||||
|
- moodle_db:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks: [moodle_net]
|
||||||
|
|
||||||
|
# ── Moodle — Aplicació principal ─────────
|
||||||
|
moodle:
|
||||||
|
container_name: moodle
|
||||||
|
image: moodlehq/moodle-php-apache:8.2-bullseye
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
# Codi de Moodle i config.php
|
||||||
|
- moodle_html:/var/www/html
|
||||||
|
# Dades dels usuaris (fitxers pujats, cache, sessions)
|
||||||
|
- moodle_data:/var/www/moodledata
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8084:80" # Només local → via Nginx Proxy Manager
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost/login/index.php"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 120s
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [moodle_net, shared_net]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
moodle_db:
|
||||||
|
moodle_html:
|
||||||
|
moodle_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
moodle_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
64
n8n/docker-compose.yml
Normal file
64
n8n/docker-compose.yml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# /opt/stacks/n8n/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:15
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: '${POSTGRES_USER}'
|
||||||
|
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
|
||||||
|
POSTGRES_DB: '${POSTGRES_DB}'
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
healthcheck: # Crític: n8n espera que postgres estigui llest
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks:
|
||||||
|
- n8n-net
|
||||||
|
|
||||||
|
n8n:
|
||||||
|
image: n8nio/n8n:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "5678:5678" # Interfície web (només local → via Nginx)
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
GENERIC_TIMEZONE: Europe/Madrid # Necessari per a workflows cron
|
||||||
|
# Base de dades
|
||||||
|
DB_TYPE: postgresdb
|
||||||
|
DB_POSTGRESDB_HOST: postgres
|
||||||
|
DB_POSTGRESDB_PORT: 5432
|
||||||
|
DB_POSTGRESDB_DATABASE: '${POSTGRES_DB}'
|
||||||
|
DB_POSTGRESDB_USER: '${POSTGRES_USER}'
|
||||||
|
DB_POSTGRESDB_PASSWORD: '${POSTGRES_PASSWORD}'
|
||||||
|
# Seguretat
|
||||||
|
N8N_ENCRYPTION_KEY: '${N8N_ENCRYPTION_KEY}' # CRÍTIC: mai canviar un cop configurat
|
||||||
|
# URL pública (necessari per a webhooks)
|
||||||
|
N8N_HOST: '${N8N_HOST}'
|
||||||
|
N8N_PORT: 5678
|
||||||
|
N8N_PROTOCOL: https
|
||||||
|
WEBHOOK_URL: 'https://${N8N_HOST}/'
|
||||||
|
volumes:
|
||||||
|
- n8n_data:/home/node/.n8n
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy # Espera que postgres estigui realment llest
|
||||||
|
networks:
|
||||||
|
- n8n-net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
n8n_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
n8n-net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
110
nextcloud/docker-compose.yml
Normal file
110
nextcloud/docker-compose.yml
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# /opt/stacks/nextcloud/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── PostgreSQL per a Nextcloud ───────────
|
||||||
|
db:
|
||||||
|
container_name: nextcloud-db
|
||||||
|
image: postgres:16-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
POSTGRES_DB: nextcloud
|
||||||
|
POSTGRES_USER: nextcloud
|
||||||
|
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
|
||||||
|
volumes:
|
||||||
|
- nc_db:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U nextcloud -d nextcloud"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks: [nc_net]
|
||||||
|
|
||||||
|
# ── Redis per a cache i sessions ─────────
|
||||||
|
redis:
|
||||||
|
container_name: nextcloud-redis
|
||||||
|
image: redis:7.4-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
command: redis-server --requirepass '${REDIS_PASSWORD}'
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 15s
|
||||||
|
networks: [nc_net]
|
||||||
|
|
||||||
|
# ── Nextcloud ────────────────────────────
|
||||||
|
nextcloud:
|
||||||
|
container_name: nextcloud
|
||||||
|
image: nextcloud:33-apache # Actualitzat a darrera versió estable
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
# Connexió a PostgreSQL
|
||||||
|
POSTGRES_HOST: db
|
||||||
|
POSTGRES_DB: nextcloud
|
||||||
|
POSTGRES_USER: nextcloud
|
||||||
|
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
|
||||||
|
# Connexió a Redis
|
||||||
|
REDIS_HOST: redis
|
||||||
|
REDIS_HOST_PASSWORD: '${REDIS_PASSWORD}'
|
||||||
|
# Compte administrador inicial (només s'usa en la primera instal·lació)
|
||||||
|
NEXTCLOUD_ADMIN_USER: '${NC_ADMIN_USER}'
|
||||||
|
NEXTCLOUD_ADMIN_PASSWORD: '${NC_ADMIN_PASSWORD}'
|
||||||
|
# Domini de confiança (obligatori!)
|
||||||
|
NEXTCLOUD_TRUSTED_DOMAINS: 'cloud.el-meu-domini.com'
|
||||||
|
# Configuració per a reverse proxy — genera URLs correctes
|
||||||
|
OVERWRITEPROTOCOL: https
|
||||||
|
OVERWRITECLIURL: 'https://cloud.el-meu-domini.com'
|
||||||
|
TRUSTED_PROXIES: '172.16.0.0/12' # Rang de xarxes Docker internes
|
||||||
|
# PHP — memòria i temps màxim
|
||||||
|
PHP_MEMORY_LIMIT: 512M
|
||||||
|
PHP_UPLOAD_LIMIT: 10G
|
||||||
|
volumes:
|
||||||
|
- nc_html:/var/www/html
|
||||||
|
- nc_data:/var/www/html/data
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8081:80" # Només local → via Nginx Proxy Manager
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost/status.php"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s # Nextcloud triga a instal·lar-se la 1a vegada
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [nc_net, shared_net]
|
||||||
|
|
||||||
|
# ── Cron: tasques programades de Nextcloud ──
|
||||||
|
cron:
|
||||||
|
container_name: nextcloud-cron
|
||||||
|
image: nextcloud:33-apache # Mateixa versió que nextcloud!
|
||||||
|
restart: unless-stopped
|
||||||
|
entrypoint: /cron.sh
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
- nc_html:/var/www/html
|
||||||
|
- nc_data:/var/www/html/data
|
||||||
|
depends_on:
|
||||||
|
nextcloud:
|
||||||
|
condition: service_healthy # Espera que Nextcloud estigui llest
|
||||||
|
networks: [nc_net]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
nc_db:
|
||||||
|
nc_html:
|
||||||
|
nc_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
nc_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
46
ollama/docker-compose.yml
Normal file
46
ollama/docker-compose.yml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# /opt/stacks/ollama/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
ollama:
|
||||||
|
container_name: ollama
|
||||||
|
image: ollama/ollama:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:11434:11434" # API Ollama (només local, open-webui hi accedeix internament)
|
||||||
|
volumes:
|
||||||
|
- ollama_data:/root/.ollama # Models descarregats
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
OLLAMA_HOST: 0.0.0.0 # Necessari perquè open-webui hi accedeixi via xarxa interna
|
||||||
|
networks:
|
||||||
|
- ollama-net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
open-webui:
|
||||||
|
container_name: open-webui
|
||||||
|
image: ghcr.io/open-webui/open-webui:main
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:3000:8080" # Interfície web (només local → via Nginx)
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
OLLAMA_BASE_URL: http://ollama:11434
|
||||||
|
WEBUI_SECRET_KEY: '${WEBUI_SECRET_KEY}' # Via .env
|
||||||
|
volumes:
|
||||||
|
- open_webui_data:/app/backend/data
|
||||||
|
depends_on:
|
||||||
|
- ollama
|
||||||
|
networks:
|
||||||
|
- ollama-net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
ollama_data:
|
||||||
|
open_webui_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
ollama-net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
40
onlyoffice/docker-compose.yml
Normal file
40
onlyoffice/docker-compose.yml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Afegir al docker-compose.yml de Nextcloud
|
||||||
|
# /opt/stacks/nextcloud/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ... (db, redis, nextcloud, cron ja existents) ...
|
||||||
|
|
||||||
|
# ── OnlyOffice Document Server ───────────
|
||||||
|
onlyoffice:
|
||||||
|
container_name: onlyoffice
|
||||||
|
image: onlyoffice/documentserver:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
# JWT — ha de coincidir EXACTAMENT amb el plugin de Nextcloud
|
||||||
|
JWT_ENABLED: "true"
|
||||||
|
JWT_SECRET: '${ONLYOFFICE_JWT_SECRET}'
|
||||||
|
JWT_HEADER: Authorization # Valor per defecte oficial (no AuthorizationJwt)
|
||||||
|
ports:
|
||||||
|
- "8082:80" # Només local → via Nginx Proxy Manager
|
||||||
|
volumes:
|
||||||
|
- oo_data:/var/www/onlyoffice/Data # Certificats i configuració
|
||||||
|
- oo_logs:/var/log/onlyoffice # Logs
|
||||||
|
- oo_cache:/var/lib/onlyoffice # Cache de fitxers (OBLIGATORI!)
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost/healthcheck"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s # OnlyOffice triga a arrencar la 1a vegada
|
||||||
|
networks: [nc_net, shared_net]
|
||||||
|
|
||||||
|
# Afegir als volumes existents:
|
||||||
|
volumes:
|
||||||
|
# ... (nc_db, nc_html, nc_data ja existents) ...
|
||||||
|
oo_data:
|
||||||
|
oo_logs:
|
||||||
|
oo_cache: # Nou — cache de fitxers
|
||||||
|
|
||||||
|
# networks ja definides al compose de Nextcloud
|
||||||
36
pihole/docker-compose.yml
Normal file
36
pihole/docker-compose.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# /opt/stacks/pihole/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
pihole:
|
||||||
|
container_name: pihole
|
||||||
|
image: pihole/pihole:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "53:53/tcp" # DNS TCP — sense 127.0.0.1 (ha de ser accessible a tota la xarxa)
|
||||||
|
- "53:53/udp" # DNS UDP — ídem
|
||||||
|
- "127.0.0.1:8080:80" # Interfície web (només local → via Nginx)
|
||||||
|
environment:
|
||||||
|
TZ: 'Europe/Madrid'
|
||||||
|
WEBPASSWORD: '${PIHOLE_PASSWORD}' # Millor via .env
|
||||||
|
PIHOLE_DNS_: '9.9.9.9;149.112.112.112'
|
||||||
|
DNSSEC: 'true'
|
||||||
|
DNSMASQ_LISTENING: 'all'
|
||||||
|
volumes:
|
||||||
|
- pihole_config:/etc/pihole # Volum named — més estable
|
||||||
|
- pihole_dnsmasq:/etc/dnsmasq.d # Volum named — més estable
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
networks:
|
||||||
|
- dns-net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pihole_config:
|
||||||
|
pihole_dnsmasq:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
dns-net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
431
plex/docker-compose.yml
Normal file
431
plex/docker-compose.yml
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
# /opt/stacks/plex/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# PLEX
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
plex:
|
||||||
|
image: lscr.io/linuxserver/plex:latest
|
||||||
|
container_name: plex
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: host # Necessari per a Plex discovery (mDNS/DLNA)
|
||||||
|
|
||||||
|
group_add:
|
||||||
|
- "${VIDEO_GID:-44}" # grup 'video' per a GPU
|
||||||
|
- "${RENDER_GID:-992}" # grup 'render' per a /dev/dri
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PUID: ${PUID}
|
||||||
|
PGID: ${PGID}
|
||||||
|
TZ: ${TZ}
|
||||||
|
VERSION: docker
|
||||||
|
PLEX_CLAIM: ${PLEX_CLAIM}
|
||||||
|
|
||||||
|
devices:
|
||||||
|
- /dev/dri/renderD128:/dev/dri/renderD128
|
||||||
|
- /dev/dri/card0:/dev/dri/card0
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ${DATA_DIR}/plex/config:/config
|
||||||
|
- ${RIVEN_MOUNT}:/mnt/riven:rslave
|
||||||
|
- ${PD_ZURG_MOUNT}:/mnt/pd_zurg:rslave
|
||||||
|
- ${TORBOX_MOUNT}:/mnt/torbox_zurg:rslave
|
||||||
|
- ${MEDIA_SERIES}:/mnt/media/series:ro
|
||||||
|
- ${MEDIA_MOVIES}:/mnt/media/pelis:ro
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- pd_zurg
|
||||||
|
- torbox_mount
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# PD_ZURG — Real-Debrid + Zurg + rclone
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
pd_zurg:
|
||||||
|
image: iampuid0/pd_zurg:latest
|
||||||
|
container_name: pd_zurg
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
|
||||||
|
devices:
|
||||||
|
- /dev/fuse:/dev/fuse:rwm
|
||||||
|
|
||||||
|
cap_add:
|
||||||
|
- SYS_ADMIN
|
||||||
|
|
||||||
|
security_opt:
|
||||||
|
- apparmor:unconfined
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
ZURG_ENABLED: "true"
|
||||||
|
RD_API_KEY: ${RD_API_KEY}
|
||||||
|
RCLONE_MOUNT_NAME: pd_zurg
|
||||||
|
PD_ENABLED: "true"
|
||||||
|
PLEX_USER: ${PLEX_USER}
|
||||||
|
PLEX_TOKEN: ${PLEX_TOKEN}
|
||||||
|
PLEX_ADDRESS: ${PLEX_ADDRESS}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ${DATA_DIR}/pd_zurg/config:/config
|
||||||
|
- ${DATA_DIR}/pd_zurg/log:/log
|
||||||
|
- ${DATA_DIR}/pd_zurg/cache:/cache
|
||||||
|
- ${DATA_DIR}/pd_zurg/RD:/zurg/RD
|
||||||
|
- ${PD_ZURG_MOUNT}:/data:shared
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# TORBOX MOUNT — Torbox WebDAV via rclone
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
torbox_mount:
|
||||||
|
image: rclone/rclone:latest
|
||||||
|
container_name: torbox_mount
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
devices:
|
||||||
|
- /dev/fuse:/dev/fuse:rwm
|
||||||
|
|
||||||
|
cap_add:
|
||||||
|
- SYS_ADMIN
|
||||||
|
|
||||||
|
security_opt:
|
||||||
|
- apparmor:unconfined
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
|
||||||
|
command: >
|
||||||
|
mount torbox:
|
||||||
|
/data
|
||||||
|
--config /config/rclone.conf
|
||||||
|
--allow-other
|
||||||
|
--allow-non-empty
|
||||||
|
--dir-cache-time 10s
|
||||||
|
--vfs-cache-mode full
|
||||||
|
--vfs-cache-max-size 512M
|
||||||
|
--no-modtime
|
||||||
|
--log-level INFO
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ${DATA_DIR}/torbox_mount/config:/config
|
||||||
|
- ${TORBOX_MOUNT}:/data:shared
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# SEERR — Gestor de peticions
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
seerr:
|
||||||
|
image: ghcr.io/seerr-team/seerr:latest
|
||||||
|
container_name: seerr
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ${DATA_DIR}/seerr/config:/app/config
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "5055:5055" # Web UI → via Nginx Proxy Manager
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# RIVEN — PostgreSQL
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
riven-postgres:
|
||||||
|
image: postgres:17-alpine
|
||||||
|
container_name: riven-postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
POSTGRES_USER: ${RIVEN_POSTGRES_USER}
|
||||||
|
POSTGRES_PASSWORD: ${RIVEN_POSTGRES_PASSWORD}
|
||||||
|
POSTGRES_DB: ${RIVEN_POSTGRES_DB}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- riven_postgres_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${RIVEN_POSTGRES_USER} -d ${RIVEN_POSTGRES_DB}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- riven_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# RIVEN — Redis
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
riven-redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: riven-redis
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- riven_redis_data:/data
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- riven_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# RIVEN — Backend API
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
riven:
|
||||||
|
image: ghcr.io/rivenmedia/riven-ts:sha-a367778 # Pinnat a SHA per estabilitat
|
||||||
|
container_name: riven
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
tty: true
|
||||||
|
|
||||||
|
cap_add:
|
||||||
|
- SYS_ADMIN
|
||||||
|
|
||||||
|
security_opt:
|
||||||
|
- apparmor:unconfined
|
||||||
|
|
||||||
|
devices:
|
||||||
|
- /dev/fuse:/dev/fuse
|
||||||
|
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
NODE_ENV: production # Era 'development' — canviat a production
|
||||||
|
RIVEN_SETTING__databaseUrl: "postgresql://${RIVEN_POSTGRES_USER}:${RIVEN_POSTGRES_PASSWORD}@riven-postgres:5432/${RIVEN_POSTGRES_DB}"
|
||||||
|
RIVEN_SETTING__redisUrl: "redis://riven-redis:6379"
|
||||||
|
RIVEN_SETTING__gqlHost: "0.0.0.0"
|
||||||
|
RIVEN_SETTING__gqlCorsOrigin: ${RIVEN_CORS_ORIGIN}
|
||||||
|
# ⚠️ CSRF desactivat — només acceptable en xarxa privada/VPN
|
||||||
|
RIVEN_SETTING__csrfPrevention: "false"
|
||||||
|
APOLLO_CSRF_PREVENTION_ENABLED: "false"
|
||||||
|
RIVEN_SETTING__enabledPlugins: '["stremthru","plex","tmdb","tvdb","seerr"]'
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_TMDB__apiKey: ${TMDB_API_KEY}
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_TVDB__apiKey: ${TVDB_API_KEY}
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_STREMTHRU__realdebridApiKey: ${RD_API_KEY}
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_STREMTHRU__torboxApiKey: ${TORBOX_API_KEY}
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_PLEX__plexServerUrl: ${PLEX_ADDRESS}
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_PLEX__plexToken: ${PLEX_TOKEN}
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_SEERR__apiKey: ${SEERR_API_KEY}
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_SEERR__url: ${SEERR_URL}
|
||||||
|
RIVEN_PLUGIN_SETTING__REPO_PLUGIN_SEERR__autofixMetadataProviders: "true"
|
||||||
|
RIVEN_SETTING__vfsMountPath: /mnt/riven
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- riven_data:/riven/data
|
||||||
|
- ${RIVEN_MOUNT}:/mnt/riven:shared
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
riven-postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
riven-redis:
|
||||||
|
condition: service_healthy
|
||||||
|
seerr:
|
||||||
|
condition: service_started
|
||||||
|
pd_zurg:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- riven_net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# RIVEN — Frontend UI
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
riven-frontend:
|
||||||
|
image: ghcr.io/rivenmedia/riven-frontend:latest
|
||||||
|
container_name: riven-frontend
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
tty: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
ORIGIN: ${RIVEN_ORIGIN}
|
||||||
|
BACKEND_URL: "http://riven:3000"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- riven_frontend_config:/riven/config
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
riven:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- riven_net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# DMM — MySQL Database
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
dmm-db:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: dmm-db
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
MYSQL_ROOT_PASSWORD: ${DMM_DB_ROOT_PASSWORD}
|
||||||
|
MYSQL_DATABASE: dmm
|
||||||
|
MYSQL_USER: dmm
|
||||||
|
MYSQL_PASSWORD: ${DMM_DB_PASSWORD}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- dmm_db_data:/var/lib/mysql
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DMM_DB_ROOT_PASSWORD}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- dmm_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# DMM — Redis
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
dmm-redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: dmm-redis
|
||||||
|
restart: unless-stopped
|
||||||
|
command: redis-server --appendonly yes --maxmemory 128mb --maxmemory-policy allkeys-lru
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- dmm_redis_data:/data
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- dmm_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# DMM — Tor proxy
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
dmm-tor:
|
||||||
|
image: debridmediamanager/tor
|
||||||
|
container_name: dmm-tor
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- dmm_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# DMM — App (built from source)
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
dmm:
|
||||||
|
build:
|
||||||
|
context: ${DMM_BUILD_CONTEXT} # Era hardcoded /opt/tatsukai/plex/dmm
|
||||||
|
image: dmm-prod:local
|
||||||
|
container_name: dmm
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
DATABASE_URL: ${DATABASE_URL}
|
||||||
|
DMM_ORIGIN: ${DMM_URL}
|
||||||
|
DMMCAST_SALT: ${DMM_SECRET}
|
||||||
|
REDIS_URL: "redis://dmm-redis:6379"
|
||||||
|
TMDB_KEY: ${TMDB_API_KEY}
|
||||||
|
TRAKT_CLIENT_ID: ${TRAKT_CLIENT_ID}
|
||||||
|
TRAKT_CLIENT_SECRET: ${TRAKT_CLIENT_SECRET}
|
||||||
|
NEXT_PUBLIC_ANALYTICS_ENABLED: "false"
|
||||||
|
MDBLIST_KEY: ${MDBLIST_KEY}
|
||||||
|
TOR_PROXY: "socks5://dmm-tor:9050"
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "3000:3000" # Web UI → via Nginx Proxy Manager
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
dmm-db:
|
||||||
|
condition: service_healthy
|
||||||
|
dmm-redis:
|
||||||
|
condition: service_healthy # Era service_started — ara espera healthcheck
|
||||||
|
dmm-tor:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- dmm_net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
# XTEVE — Proxy M3U / Virtual HDHomeRun
|
||||||
|
# ─────────────────────────────────────────
|
||||||
|
xteve:
|
||||||
|
image: alturismo/xteve:latest
|
||||||
|
container_name: xteve
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
TZ: ${TZ}
|
||||||
|
XTEVE_TUNER: ${XTEVE_TUNER:-8}
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "34400:34400" # Web UI → via Nginx Proxy Manager
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ${DATA_DIR}/xteve/config:/root/.xteve
|
||||||
|
- ${DATA_DIR}/xteve/temp:/tmp/xteve
|
||||||
|
- ${DATA_DIR}/epg/xmltv_master.xml:/root/xmltv.xml:ro
|
||||||
|
- ${DATA_DIR}/epg/master.m3u:/root/playlist.m3u:ro
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
riven_data:
|
||||||
|
riven_postgres_data:
|
||||||
|
riven_redis_data:
|
||||||
|
riven_frontend_config:
|
||||||
|
dmm_db_data:
|
||||||
|
dmm_redis_data:
|
||||||
|
|
||||||
|
|
||||||
|
networks:
|
||||||
|
riven_net:
|
||||||
|
driver: bridge
|
||||||
|
dmm_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
24
portainer/docker-compose.yml
Normal file
24
portainer/docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# /opt/stacks/portainer/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
portainer:
|
||||||
|
image: portainer/portainer-ce:latest
|
||||||
|
container_name: portainer
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "9000:9000" # Interfície web HTTP (només local)
|
||||||
|
- "9443:9443" # Interfície web HTTPS (només local)
|
||||||
|
# - "8000:8000" # Agent tunnel — descomenta si uses agents remots
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- portainer_data:/data
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
portainer_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
64
postgres/docker-compose.yml
Normal file
64
postgres/docker-compose.yml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# /opt/stacks/postgres/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── Servei PostgreSQL ────────────────────
|
||||||
|
postgres:
|
||||||
|
container_name: postgres
|
||||||
|
image: postgres:16-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
POSTGRES_USER: '${POSTGRES_USER}'
|
||||||
|
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
|
||||||
|
POSTGRES_DB: '${POSTGRES_DB}'
|
||||||
|
# UTF8 sense locale específic → compatible amb Alpine
|
||||||
|
POSTGRES_INITDB_ARGS: '--encoding=UTF8 --locale=en_US.utf8'
|
||||||
|
ports:
|
||||||
|
- "5432:5432" # Accés local per DBeaver, psql, etc.
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
- postgres_init:/docker-entrypoint-initdb.d # Scripts SQL d'inicialització
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s # Afegit
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s # Afegit: marge per a scripts d'init
|
||||||
|
networks:
|
||||||
|
- pg_net
|
||||||
|
|
||||||
|
# ── pgAdmin: UI web per gestionar Postgres ──
|
||||||
|
pgadmin:
|
||||||
|
container_name: pgadmin
|
||||||
|
image: dpage/pgadmin4:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "5050:80" # UI web (només local → via Nginx)
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
PGADMIN_DEFAULT_EMAIL: '${PGADMIN_EMAIL}'
|
||||||
|
PGADMIN_DEFAULT_PASSWORD: '${PGADMIN_PASSWORD}'
|
||||||
|
PGADMIN_DISABLE_POSTFIX: 'true' # Evita errors de Postfix als logs
|
||||||
|
PGADMIN_CONFIG_SERVER_MODE: 'False' # Mode personal (un sol usuari)
|
||||||
|
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: 'False' # Simplifica l'accés local
|
||||||
|
volumes:
|
||||||
|
- pgadmin_data:/var/lib/pgadmin # Persisteix servidors i preferències
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- pg_net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
postgres_init: # Posa els teus scripts .sql aquí
|
||||||
|
pgadmin_data: # Configuració de pgAdmin persistent
|
||||||
|
|
||||||
|
networks:
|
||||||
|
pg_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
70
redis/docker-compose.yml
Normal file
70
redis/docker-compose.yml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# /opt/stacks/redis/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── Servei Redis ─────────────────────────
|
||||||
|
redis:
|
||||||
|
container_name: redis
|
||||||
|
image: redis:7.4-alpine # Pinnat a LTS estable
|
||||||
|
restart: unless-stopped
|
||||||
|
command:
|
||||||
|
- redis-server
|
||||||
|
- --requirepass
|
||||||
|
- '${REDIS_PASSWORD}'
|
||||||
|
- --appendonly
|
||||||
|
- "yes"
|
||||||
|
- --maxmemory
|
||||||
|
- 256mb
|
||||||
|
- --maxmemory-policy
|
||||||
|
- allkeys-lru
|
||||||
|
- --loglevel
|
||||||
|
- notice
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:6379:6379" # Accés local per a clients externs
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s # Afegit
|
||||||
|
retries: 5
|
||||||
|
start_period: 15s # Afegit
|
||||||
|
networks:
|
||||||
|
- redis_net
|
||||||
|
|
||||||
|
# ── RedisInsight: UI web per gestionar Redis ──
|
||||||
|
redisinsight:
|
||||||
|
container_name: redisinsight
|
||||||
|
image: redis/redisinsight:latest # Imatge oficial actualitzada
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5540:5540" # Port correcte és 5540, no 8001!
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
RI_ENCRYPTION_KEY: '${RI_ENCRYPTION_KEY}' # Xifra contrasenyes guardades
|
||||||
|
# Preconfiguració automàtica de la connexió al Redis local
|
||||||
|
RI_REDIS_HOST: redis
|
||||||
|
RI_REDIS_PORT: 6379
|
||||||
|
RI_REDIS_ALIAS: Redis Local
|
||||||
|
RI_REDIS_PASSWORD: '${REDIS_PASSWORD}'
|
||||||
|
volumes:
|
||||||
|
- redisinsight_data:/data # Persisteix connexions i historial
|
||||||
|
depends_on:
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- redis_net
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
redis_data:
|
||||||
|
redisinsight_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
redis_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
49
vaultwarden/docker-compose.yml
Normal file
49
vaultwarden/docker-compose.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# /opt/stacks/vaultwarden/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
vaultwarden:
|
||||||
|
container_name: vaultwarden
|
||||||
|
image: vaultwarden/server:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
# Domini públic (obligatori per a links d'invitació i 2FA)
|
||||||
|
DOMAIN: 'https://vault.el-meu-domini.com'
|
||||||
|
# Seguretat: registre tancat
|
||||||
|
SIGNUPS_ALLOWED: "false"
|
||||||
|
# Token admin — usa hash argon2id (vegeu .env i instruccions sota)
|
||||||
|
ADMIN_TOKEN: '${VAULTWARDEN_ADMIN_TOKEN}'
|
||||||
|
# Configuració SMTP
|
||||||
|
SMTP_HOST: '${SMTP_HOST}'
|
||||||
|
SMTP_PORT: 587
|
||||||
|
SMTP_SECURITY: starttls # Explícit: starttls | force_tls | off
|
||||||
|
SMTP_FROM: '${SMTP_FROM}'
|
||||||
|
SMTP_USERNAME: '${SMTP_USERNAME}'
|
||||||
|
SMTP_PASSWORD: '${SMTP_PASSWORD}'
|
||||||
|
SMTP_FROM_NAME: Vaultwarden
|
||||||
|
# Logs
|
||||||
|
LOG_LEVEL: warn
|
||||||
|
# WebSockets integrats al port principal des de v1.29.0
|
||||||
|
# WEBSOCKET_ENABLED i port 3012 eliminats des de v1.31.0
|
||||||
|
volumes:
|
||||||
|
- vaultwarden_data:/data
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8080:80" # Port únic — WebSockets inclosos
|
||||||
|
# Port 3012 ELIMINAT — ja no existeix des de v1.31.0
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:80/alive"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 15s
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
vaultwarden_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
38
wg-easy/docker-compose.yml
Normal file
38
wg-easy/docker-compose.yml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# /opt/stacks/wg-easy/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
wg-easy:
|
||||||
|
container_name: wg-easy
|
||||||
|
image: ghcr.io/wg-easy/wg-easy:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
WG_HOST: '${WG_HOST}' # Domini o IP pública — via .env
|
||||||
|
PASSWORD_HASH: '${WG_PASSWORD_HASH}' # Hash bcrypt — via .env
|
||||||
|
WG_PORT: 51820
|
||||||
|
WG_DEFAULT_ADDRESS: '10.0.0.1' # Adreça del servidor VPN (no .x)
|
||||||
|
WG_DEFAULT_DNS: '${WG_DNS}' # AdGuard/Pi-hole — via .env
|
||||||
|
WG_ALLOWED_IPS: '0.0.0.0/0'
|
||||||
|
UI_TRAFFIC_STATS: true
|
||||||
|
UI_CHART_TYPE: 1
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
ports:
|
||||||
|
- "51820:51820/udp" # WireGuard VPN — públic (necessari per a clients)
|
||||||
|
- "51821:51821" # Interfície web (només local → via Nginx)
|
||||||
|
volumes:
|
||||||
|
- wg_easy_data:/etc/wireguard # Volum named — configuració persistent
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
- SYS_MODULE
|
||||||
|
sysctls:
|
||||||
|
- net.ipv4.ip_forward=1
|
||||||
|
- net.ipv4.conf.all.src_valid_mark=1
|
||||||
|
networks:
|
||||||
|
- shared_net
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
wg_easy_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
92
wordpress/docker-compose.yml
Normal file
92
wordpress/docker-compose.yml
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# /opt/stacks/wordpress/docker-compose.yml
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ── MariaDB ──────────────────────────────
|
||||||
|
db:
|
||||||
|
container_name: wordpress-db
|
||||||
|
image: mariadb:10.11
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
MYSQL_ROOT_PASSWORD: '${MYSQL_ROOT_PASSWORD}'
|
||||||
|
MYSQL_DATABASE: wordpress
|
||||||
|
MYSQL_USER: wordpress
|
||||||
|
MYSQL_PASSWORD: '${MYSQL_PASSWORD}'
|
||||||
|
volumes:
|
||||||
|
- wp_db:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks: [wp_net]
|
||||||
|
|
||||||
|
# ── Redis — cache d'objectes ─────────────
|
||||||
|
# Nota: Redis és volàtil per defecte — la cache es perd en reiniciar.
|
||||||
|
# Per a WordPress és acceptable (es reconstrueix automàticament).
|
||||||
|
redis:
|
||||||
|
container_name: wordpress-redis
|
||||||
|
image: redis:7-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 10s
|
||||||
|
networks: [wp_net]
|
||||||
|
|
||||||
|
# ── WordPress ────────────────────────────
|
||||||
|
wordpress:
|
||||||
|
container_name: wordpress
|
||||||
|
image: wordpress:6-apache
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Madrid
|
||||||
|
# Connexió a MariaDB
|
||||||
|
WORDPRESS_DB_HOST: db
|
||||||
|
WORDPRESS_DB_NAME: wordpress
|
||||||
|
WORDPRESS_DB_USER: wordpress
|
||||||
|
WORDPRESS_DB_PASSWORD: '${MYSQL_PASSWORD}'
|
||||||
|
# Claus de seguretat — les 8 obligatòries
|
||||||
|
# Genera-les a: https://api.wordpress.org/secret-key/1.1/salt/
|
||||||
|
WORDPRESS_AUTH_KEY: '${WP_AUTH_KEY}'
|
||||||
|
WORDPRESS_SECURE_AUTH_KEY: '${WP_SECURE_AUTH_KEY}'
|
||||||
|
WORDPRESS_LOGGED_IN_KEY: '${WP_LOGGED_IN_KEY}'
|
||||||
|
WORDPRESS_NONCE_KEY: '${WP_NONCE_KEY}'
|
||||||
|
WORDPRESS_AUTH_SALT: '${WP_AUTH_SALT}'
|
||||||
|
WORDPRESS_SECURE_AUTH_SALT: '${WP_SECURE_AUTH_SALT}'
|
||||||
|
WORDPRESS_LOGGED_IN_SALT: '${WP_LOGGED_IN_SALT}'
|
||||||
|
WORDPRESS_NONCE_SALT: '${WP_NONCE_SALT}'
|
||||||
|
# Configuració addicional via wp-config
|
||||||
|
WORDPRESS_CONFIG_EXTRA: |
|
||||||
|
define('WP_REDIS_HOST', 'redis');
|
||||||
|
define('WP_REDIS_PORT', 6379);
|
||||||
|
define('WP_CACHE', true);
|
||||||
|
define('WP_HOME', '${WP_URL}');
|
||||||
|
define('WP_SITEURL', '${WP_URL}');
|
||||||
|
volumes:
|
||||||
|
- wp_data:/var/www/html
|
||||||
|
ports:
|
||||||
|
- "8086:80"
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy # Afegit — WordPress necessita Redis disponible
|
||||||
|
networks: [wp_net, shared_net]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
wp_db:
|
||||||
|
wp_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
wp_net:
|
||||||
|
driver: bridge
|
||||||
|
shared_net:
|
||||||
|
external: true
|
||||||
|
name: shared_net
|
||||||
Reference in New Issue
Block a user