Nextcloud + Docker Compose + Nginx

Nextcloud using Nginx & Docker Compose

This sample config set includes:

  • Nextcloud setup using Docker-Compose
  • Nginx serves the Docker using reverse-proxy
  • Systemd service file (optional)

There are examples of the nginx config that include:

  1. Top-level dir mode (serving directly on https://example.com or https://subdomain.example.com)
  2. Sub directory mode (serving on https://example.com/nextcloud or https://subdomain.example.com/nextcloud - or other directory name)

[docker-compose.yml]

version: "3"

services:
  nginx:
    image: nginx:stable
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      # put HTTPS certificates here
      - /etc/letsencrypt/live/example.com/fullchain.pem:/root/ssl/cert.pem:ro
      - /etc/letsencrypt/live/example.com/privkey.pem:/root/ssl/key.pem:ro
    ports:
      - 443:443
    links:
      - nextcloud

  nextcloud:
    image: nextcloud:latest
    restart: unless-stopped
    links:
      - mysql
    ports:
      - 8080:80
    environment:
      # replace example.com with your domain/subdomain
      - VIRTUAL_HOST=example.com
      - VIRTUAL_PORT=8080
      # update credentials here
      - MYSQL_HOST=mysql
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_PASSWORD=nextcloud
      - APACHE_DISABLE_REWRITE_IP=1
      - TRUSTED_PROXIES=172.21.0.0 172.21.0.1 172.21.0.2 172.21.0.3
    volumes:
      - nextcloud:/var/www/html
      # update the path of your config here (or comment out)
      - ./nextcloud/config.php:/var/www/html/config/config.php

  mysql:
    image: mysql:8.0
    restart: unless-stopped
    environment:
      # update credentials here
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_PASSWORD=nextcloud
      - MYSQL_ROOT_PASSWORD=nextcloud
    volumes:
      - mysql:/var/lib/mysql

volumes:
  mysql:
  nextcloud:
  nginx:

[nextcloud.config.php]

<?php
// You might need to add the following config parts to your existing config if you have one

$CONFIG = array (
  // replace with your subdir name if necessary
  'overwritewebroot' => 'nextcloud',
  # docker hosts
  'trusted_proxies' =>
  array (
    0 => '172.21.0.0',
    1 => '172.21.0.1',
    2 => '172.21.0.2',
    3 => '172.21.0.3',
  ),
  // add your domain here
  'trusted_domains' =>
  array (
    0 => 'example.com',
  ),
  'dbtype' => 'mysql',
  // update this if necessary
  'overwrite.cli.url' => 'http://example.com/nextcloud',
);

[nextcloud.service]

# /etc/systemd/system/nextcloud.service

[Unit]
Description=Nextcloud
Requires=docker.service
After=docker.service
StartLimitIntervalSec=0
[Service]
Type=oneshot
RemainAfterExit=yes
#Restart=always
RestartSec=10
User=root
# change to your directory with docker-compose.yml
WorkingDirectory=/root/apps
ExecStart=/usr/bin/docker-compose up -d
ExecStop=/usr/bin/docker-compose down

[Install]
WantedBy=multi-user.target

[nginx.rootdir.conf]

# This config file is for when setting nextcloud on the root of the domain/subdomain (https://example.com/)

events {
    worker_connections 1024;
}

http {
  server {
    listen 443 ssl;
    ssl_certificate /root/ssl/cert.pem;
    ssl_certificate_key /root/ssl/key.pem;

    # replace example.com with your domain or subdomain
    server_name example.com;

    access_log /dev/stdout;
    error_log /dev/stderr;
    
    add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;

    # Server configuration

    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }

    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }

    location ^~ /.well-known {
      return 301 $scheme://$host/index.php$uri;
    }
    
    location / {
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      
      # "nextcloud" can be replaced with your docker image name (also through docker-compose.yml)
      proxy_pass http://nextcloud/;
    }
  }
}

[nginx.subdir.conf]

# This config file is for when setting nextcloud on the a subdirectory in the domain/subdomain (https://example.com/nextcloud/)

events {
    worker_connections 1024;
}

http {
  server {
    listen 443 ssl;
    ssl_certificate /root/ssl/cert.pem;
    ssl_certificate_key /root/ssl/key.pem;

    # replace example.com with your domain or subdomain
    server_name example.com;

    access_log /dev/stdout;
    error_log /dev/stderr;
    
    add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;

    # Server configuration

    location /nextcloud/ {
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      
      # "nextcloud" can be replaced with your docker image name (also through docker-compose.yml)
      proxy_pass http://nextcloud/;
    }

    location = /.well-known/carddav {
      # replace nextcloud with your subdir name if needed
      return 301 $scheme://$host/nextcloud/remote.php/dav;
    }

    location = /.well-known/caldav {
      # replace nextcloud with your subdir name if needed
      return 301 $scheme://$host/nextcloud/remote.php/dav;
    }

    location ^~ /.well-known {
      # replace nextcloud with your subdir name if needed
      return 301 $scheme://$host/nextcloud/index.php$uri;
    }
  }
}