Nextcloud - Docker Compose (Actualizado 08/2025)

Hoy quiero traerte mi docker-compose de Nextcloud 30, lo más completo que tengo, espero que te sirva. (no es para usar en local, aunque puedes modificarlo para ello)

¿Que incluye?

  • Mysql
  • Redis
  • Nextcloud
  • Nextcloud Cron
  • Servidor de alto rendimiento (hpb)
  • Servidor de grabación (talk-recording)
  • Document server
  • Collabora server
  • Whiteboard server
  • Coturn server
  • AppApi (Necesario para instalar las aplicaciones docker de la tienda)

Puede generar sus “SECRETS” con openssl rand -base64 32

O bien, guarde el script que dejo aquí abajo con el nombre gen-secrets.sh para generar el .env completo

script
#!/usr/bin/env bash
# gen-secrets.sh - Genera .env para tu stack de Nextcloud con secretos en Base64/HEX

# Generadores
gen_b64() { openssl rand -base64 24 | tr -d '\n'; }  # ~32 chars base64
gen_hex() { openssl rand -hex 32   | tr -d '\n'; }   # 64 chars hex

echo "🔐 Generador de variables para Nextcloud stack"
echo "---------------------------------------------"

# Preguntas interactivas (con tus textos)
read -p "Nombre de la base de datos (MYSQL_DATABASE): " MYSQL_DATABASE
read -p "Usuario de la base de datos (MYSQL_USER): " MYSQL_USER
read -p "Dominio base (BASE_DOMAIN) ej: tuNextcloud.com: " BASE_DOMAIN
read -p "Dominio principal Nextcloud (OVERWRITEHOST) ej: drive.tuNextcloud.com: " OVERWRITEHOST
read -p "Usuario para Collabora (COLLABORA_USERNAME) [default: admin]: " COLLABORA_USERNAME
COLLABORA_USERNAME=${COLLABORA_USERNAME:-admin}
read -p "Código de ciudad (AR, MX, US, puede encontrar su código aquí https://www.iban.com/country-codes) (PHONE_REGION) [default: AR]: " PHONE_REGION
PHONE_REGION=${PHONE_REGION:-AR}

# Constantes derivadas/no interactivas
REDIS_HOST="nextcloud-redis"
OVERWRITEPROTOCOL="https"
VIRTUAL_HOST="$OVERWRITEHOST"
APACHE_BODY_LIMIT="214748364800"
TALK_PORT="3480"

# Secretos autogenerados
MYSQL_ROOT_PASSWORD=$(gen_b64)
MYSQL_PASSWORD=$(gen_b64)
JWT_SECRET=$(gen_b64)
SIGNALING_SECRET=$(gen_hex)
INTERNAL_SECRET=$(gen_hex)
RECORDING_SECRET=$(gen_hex)
TURN_SECRET=$(gen_b64)
COLLABORA_PASSWORD=$(gen_b64)
NC_HAPROXY_PASSWORD=$(gen_b64)

# Escribir .env
OUTPUT_FILE=".env"
cat > "$OUTPUT_FILE" <<EOF
# =======================
# Nextcloud stack secrets
# Generado: $(date)
# =======================

MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
MYSQL_PASSWORD=$MYSQL_PASSWORD
MYSQL_DATABASE=$MYSQL_DATABASE
MYSQL_USER=$MYSQL_USER
REDIS_HOST=$REDIS_HOST
BASE_DOMAIN=$BASE_DOMAIN
NEXTCLOUD_TRUSTED_DOMAINS=$OVERWRITEHOST
OVERWRITEHOST=$OVERWRITEHOST
OVERWRITEPROTOCOL=$OVERWRITEPROTOCOL
PHONE_REGION=$PHONE_REGION
VIRTUAL_HOST=$VIRTUAL_HOST
APACHE_BODY_LIMIT=$APACHE_BODY_LIMIT
JWT_SECRET=$JWT_SECRET
TALK_PORT=$TALK_PORT
SIGNALING_SECRET=$SIGNALING_SECRET
INTERNAL_SECRET=$INTERNAL_SECRET
RECORDING_SECRET=$RECORDING_SECRET
TURN_SECRET=$TURN_SECRET
COLLABORA_USERNAME=$COLLABORA_USERNAME
COLLABORA_PASSWORD=$COLLABORA_PASSWORD
NC_HAPROXY_PASSWORD=$NC_HAPROXY_PASSWORD
EOF

echo ""
echo "✅ Archivo $OUTPUT_FILE generado."
echo ""

Ejecute el script como se muestra en la imagen
bash gen-script.sh

Completa con tu información los campos comentados con # también debes completar las rutas de tu host tuRuta con las ubicaciones que necesites.

services:
  nextcloud-db:
    image: mariadb:10.11
    container_name: nextcloud-mariadb
    restart: always
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW --log_bin_trust_function_creators=true --innodb-buffer-pool-size=2G
    volumes:
      - tuRuta/db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

  nextcloud-app:
    image: nextcloud:31.0.8
    container_name: nextcloud-nextcloud
    restart: always
    ports:
      - 8081:80
    volumes:
      - tuRuta/nextcloud-app:/var/www/html/
      - tuRuta/data:/var/www/html/data
      # Si querés todo en un mismo lugar elimina la línea que está encima de esta
    environment:
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_HOST=nextcloud-db:3306
      - REDIS_HOST=nextcloud-redis
      - PHP_MEMORY_LIMIT=2G
      - PHP_UPLOAD_LIMIT=200G
      - PHP_OPCACHE_MEMORY_CONSUMPTION=2048M
      - PHP_OPCACHE_MAX_ACCELERATED_FILES=100000
      - PHP_OPCACHE_VALIDATE_TIMESTAMPS=0
      - PHP_OPCACHE_REVALIDATE_FREQ=60
      - OVERWRITEPROTOCOL=https
      - OVERWRITEHOST=${OVERWRITEHOST}
      - OVERWRITECLIURL=https://${OVERWRITEHOST}
      - NEXTCLOUD_TRUSTED_DOMAINS=${OVERWRITEHOST}
      - PHONE_REGION=AR
      - VIRTUAL_HOST=${OVERWRITEHOST}
      - APACHE_BODY_LIMIT=214748364800
      - TRUSTED_PROXIES=${TRUSTED_PROXIES}
    depends_on:
      nextcloud-db:
        condition: service_healthy
      nextcloud-collabora:
        condition: service_started
      nextcloud-redis:
        condition: service_started
      nextcloud-appapi:
        condition: service_started
    devices:
      - "/dev/dri:/dev/dri"
    networks:
      - default
      - nginx-proxy-manager_default

  nextcloud-cron:
    image: nextcloud:31.0.8
    container_name: nextcloud-cron
    restart: always
    volumes:
      - tuRuta/nextcloud-app:/var/www/html/
      - tuRuta/data:/var/www/html/data
      # Si querés todo en un mismo lugar elimina la línea que está encima de esta
    entrypoint: /cron.sh
    environment:
      - PHP_MEMORY_LIMIT=2G
      - PHP_OPCACHE_MEMORY_CONSUMPTION=2048M
    depends_on:
      - nextcloud-db
      - nextcloud-redis
    devices:
      - "/dev/dri:/dev/dri"

  nextcloud-collabora:
    image: collabora/code
    container_name: nextcloud-collabora
    restart: always
    environment:
      - domain=${OVERWRITEHOST}
      - extra_params=--o:ssl.enable=false --o:ssl.termination=true
      - username=${COLLABORA_USERNAME}
      - password=${COLLABORA_PASSWORD}
      - dictionaries=es_ES es_AR es_MX en_US #Coloque los diccionarios que desee
    ports:
      - 9981:9980
    networks:
      - default
      - nginx-proxy-manager_default

  nextcloud-redis:
    image: redis:alpine
    container_name: nextcloud-redis
    restart: unless-stopped
    tmpfs:
      - /data

  documentserver:
    image: onlyoffice/documentserver
    container_name: nextcloud-documentserver
    ports:
      - "8010:80"
    environment:
      - JWT_SECRET=${JWT_SECRET}
    restart: always
    networks:
      - default
      - nginx-proxy-manager_default

  whiteboard-server:
    image: ghcr.io/nextcloud-releases/whiteboard:release
    container_name: nextcloud-whiteboard-server
    ports:
      - "3002:3002"
    environment:
      - NEXTCLOUD_URL=https://${OVERWRITEHOST}
      - JWT_SECRET_KEY=${JWT_SECRET}
    networks:
      - default
      - nginx-proxy-manager_default

  nextcloud-appapi:
    image: ghcr.io/cloud-py-api/nextcloud-appapi-dsp:v1.3.2
    container_name: nextcloud-appapi-dsp
    restart: unless-stopped
    privileged: true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - NC_HAPROXY_PASSWORD=${NC_HAPROXY_PASSWORD}
      - TIMEOUT_SERVER=1800s

  nc-talk:
    container_name: nextcloud-talk_hpb
    image: nextcloud/aio-talk:latest
    init: true
    ports:
      - 3480:3480/tcp
      - 3480:3480/udp
      - 8181:8081/tcp
    environment:
      - NC_DOMAIN=${OVERWRITEHOST}
      - TALK_HOST=signal.${BASE_DOMAIN}
      - TURN_SECRET=${TURN_SECRET}
      - SIGNALING_SECRET=${SIGNALING_SECRET}
      - TZ=America/Argentina/Buenos_Aires #Lo que corresponda a su región
      - TALK_PORT=3480
      - INTERNAL_SECRET=${INTERNAL_SECRET}
    restart: unless-stopped
    networks:
      - default
      - nginx-proxy-manager_default

  aio-talk-recording:
    container_name: nextcloud-talk-rcrd
    environment:
      - NC_DOMAIN=${OVERWRITEHOST}
      - HPB_DOMAIN=signal.${BASE_DOMAIN}
      - INTERNAL_SECRET=${INTERNAL_SECRET}
      - RECORDING_SECRET=${RECORDING_SECRET}
      - HPB_PROTOCOL=https
      - SKIP_VERIFY=false
      - ALLOW_ALL=false
      - HPB_PATH=/standalone-signaling/
      - TZ=America/Argentina/Buenos_Aires
    ports:
      - 1234:1234
    restart: always
    image: nextcloud/aio-talk-recording
    networks:
      - default
      - nginx-proxy-manager_default

  coturn:
    image: coturn/coturn:latest
    container_name: nextcloud-coturn
    restart: unless-stopped
    user: root
    command: ["turnserver", "-c", "/etc/coturn/turnserver.conf", "--no-cli"]
    ports:
      - "3478:3478"
      - "3478:3478/udp"
      - "5349:5349"
      - "5349:5349/udp"
      - "50100-50200:50100-50200/udp"
    volumes:
      - tuRuta/turnserver.conf:/etc/coturn/turnserver.conf:ro
      - tuRuta/cert.pem:/var/tmp/cert.pem:ro
      - tuRuta/privkey.pem:/var/tmp/privkey.pem:ro
    environment:
      - TURN_SERVER_NAME=${OVERWRITEHOST}
      - TURN_SECRET=${TURN_SECRET}

networks:
  nginx-proxy-manager_default:
    external: true