Skip to content

Instantly share code, notes, and snippets.

@robertoschwald
Last active June 17, 2024 21:33
Show Gist options
  • Save robertoschwald/f852803908edda5d9360bbeabb647cbb to your computer and use it in GitHub Desktop.
Save robertoschwald/f852803908edda5d9360bbeabb647cbb to your computer and use it in GitHub Desktop.
Configure NextCloud Docker with nginx-proxy, MariaDB, Redis, LetsEncrypt and Cron Support
#!/usr/bin/env bash
# Create Nextcloud host directory structure, .env and docker-compose.yml files
# 2020 robertoschwald
# Consists of the following containers:
# nginx-proxy (frontend proxy)
# nginx-proxy-letsencrypt (LetsEncrypt issuing)
# nextcloud-app (Nextcloud application server)
# nextcloud-cron (Nextcloud cron server. Executes cron.php every few minutes)
# nextcloud-redis (Redis Server for Nextcloud file locking)
# nextcloud-mariadb (DB Server)
# All transaction data is stored on the Docker host, so you can take down / upgrade servers any time.
# Prerequisite
# For this script to work, you must at least have port 80 open to the internet,
# so LetsEncrypt certificates can be created successfully.
# Arm based Docker servers (like Pi):
# If you use an ARM based system like the Raspberry Pi,
# use the "andrewmacheret/docker-letsencrypt-nginx-proxy-companion" image instead in letsencrypt-companion
##############
# KNOWN ISSUES
##############
# CentOS8 / RHEL8 /Fedora 29 Container DNS fails:
# Prepare firewalld, otherwise containers cannot access the internet for DNS
# firewall-cmd --zone=public --add-masquerade --permanent
# firewall-cmd --reload
#
# cron.php not executed:
# Currently, the nextcloud-cron container executes cron.php, but this is not reflected in the nextcloud-app container
# See https://github.com/nextcloud/docker/issues/914
# Workaround:
# add file /etc/cron.d/nextcloud on the Docker host:
# */5 * * * * root docker exec --user www-data nextcloud-app php -f cron.php
##############
# Installation:
##############
# 1. Save this script
# 2. Modify the config section. The DATA_DIR is the toplevel host directory to store persisted files in.
# 3. Execute the script. This creates all directories and files needed
# 4. Create the docker networks manually. In this case, you can up / down the composables independently:
# docker network create --driver bridge nginx-proxy
# docker network create --driver bridge nextcloud
# 5. Execute 'docker-compose up -d' in the nginx-proxy/docker-build dir to startup the proxy with LE support
# 6. Execute 'docker-compose up -d' in the nextcloud/nextcloud-docker-build dir to startup all nextcloud containers.
# 7. After some minutes, you are able to access your installation with SSL cert installed.
# 8. Add missing indices and int values in db by executing the given occ commands.
# If you already have nginx-proxy running, you can skip step 4. Ensure to modify the nginx-proxy network name
# in this case to the existing one.
# DO NOT FORGET TO SECURE THIS FILE (e.g. chmod 700 prepare_nextcloud_docker.sh)
# Config. Modify as needed!
###############################################
DATA_DIR="/data/applications"
DOMAIN_NAME="cloud.example.com"
EMAIL="me@example.com"
DB_ROOT_PW="MySuperSecurePasswordForDbRoot"
DB_PW="MySuperSecureNexcloudDbPw"
REDIS_PW="MySuperSecureRedisPw"
###############################################
# macOS Catalina problem, so get from the symlink. Works on most OSs.
TIME_ZONE=`ls -al /etc/localtime | sed 's/.*\/zoneinfo\///g'`
mkdir -p ${DATA_DIR}/../ssl_certs
mkdir -p ${DATA_DIR}/nginx-proxy/etc/nginx/conf.d
mkdir -p ${DATA_DIR}/nginx-proxy/etc/nginx/vhost.d
mkdir -p ${DATA_DIR}/nginx-proxy/etc/nginx/htpasswd
mkdir -p ${DATA_DIR}/nginx-proxy/html
mkdir -p ${DATA_DIR}/nginx-proxy/docker-build
mkdir -p ${DATA_DIR}/nextcloud-mariadb/var/lib
mkdir -p ${DATA_DIR}/nextcloud-mariadb/etc/mysql/conf.d
mkdir -p ${DATA_DIR}/nextcloud-redis/etc
mkdir -p ${DATA_DIR}/nextcloud/etc/apache2/conf-enabled
mkdir -p ${DATA_DIR}/nextcloud/etc/php/conf.d
mkdir -p ${DATA_DIR}/nextcloud/html
mkdir -p ${DATA_DIR}/nextcloud/data
mkdir -p ${DATA_DIR}/nextcloud/var/log
mkdir -p ${DATA_DIR}/nextcloud/nextcloud-docker-build
echo " "
echo " "
if [ ! -f ${DATA_DIR}/nextcloud/nextcloud-docker-build/db.env ]; then
echo "Create ${DATA_DIR}/nextcloud/nextcloud-docker-build/db.env"
cat <<EOF > ${DATA_DIR}/nextcloud/nextcloud-docker-build/db.env
MYSQL_ROOT_PASSWORD="${DB_ROOT_PW}"
MYSQL_PASSWORD="${DB_PW}"
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
EOF
fi
if [ ! -f ${DATA_DIR}/nextcloud/nextcloud-docker-build/nextcloud.env ]; then
echo "Create ${DATA_DIR}/nextcloud/nextcloud-docker-build/nextcloud.env"
cat <<EOF > ${DATA_DIR}/nextcloud/nextcloud-docker-build/nextcloud.env
# NextCloud does not know it runs behind a SSL Proxy
# See https://github.com/nextcloud/docker/issues/742
OVERWRITEPROTOCOL=https
EOF
fi
if [ ! -f ${DATA_DIR}/nextcloud/nextcloud-docker-build/redis.env ]; then
echo "Create ${DATA_DIR}/nextcloud/nextcloud-docker-build/redis.env"
cat <<EOF > ${DATA_DIR}/nextcloud/nextcloud-docker-build/redis.env
REDIS_HOST_PASSWORD="${REDIS_PW}"
EOF
fi
if [ ! -f ${DATA_DIR}/nextcloud-mariadb/etc/mysql/conf.d/override.conf ]; then
echo "Create ${DATA_DIR}/nextcloud-mariadb/etc/mysql/conf.d/override.conf"
cat <<EOF > ${DATA_DIR}/nextcloud-mariadb/etc/mysql/conf.d/override.conf
# Add override settings to this file as needed and restart the container.
[mysqld]
max_allowed_packet=32M
EOF
fi
if [ ! -f ${DATA_DIR}/nextcloud/etc/php/conf.d/override.ini ]; then
echo "Create ${DATA_DIR}/nextcloud/etc/php/conf.d/override.ini"
cat <<EOF > ${DATA_DIR}/nextcloud/etc/php/conf.d/override.ini
# PHP config overrides.
upload_max_filesize = 2048M
post_max_size = 2048M
max_execution_time = 900
EOF
fi
if [ ! -f ${DATA_DIR}/nextcloud/etc/apache2/conf-enabled/override.conf ]; then
echo "Create ${DATA_DIR}/nextcloud/etc/apache2/conf-enabled/override.conf"
cat <<EOF > ${DATA_DIR}/nextcloud/etc/apache2/conf-enabled/override.conf
# Add Nextcloud Apache2 config overrides in this file
EOF
fi
if [ ! -f ${DATA_DIR}/nextcloud/etc/php/conf.d/override-cron.ini ]; then
echo "Create ${DATA_DIR}/nextcloud/etc/php/conf.d/override-cron.ini"
cat <<EOF > ${DATA_DIR}/nextcloud/etc/php/conf.d/override-cron.ini
# PHP config overrides for nextcloud-cron Container.
# max_execution_time = 900
EOF
fi
if [ ! -f ${DATA_DIR}/nginx-proxy/etc/nginx/conf.d/override.conf ]; then
echo "Create ${DATA_DIR}/nginx-proxy/etc/nginx/conf.d/override.conf"
cat <<EOF > ${DATA_DIR}/nginx-proxy/etc/nginx/conf.d/override.conf
server_tokens off;
client_max_body_size 2000m;
EOF
fi
chmod 400 ${DATA_DIR}/nextcloud/nextcloud-docker-build/*.env
echo "Create ${DATA_DIR}/nginx-proxy/docker-build/docker-compose.yml"
cat <<EOF > ${DATA_DIR}/nginx-proxy/docker-build/docker-compose.yml
version: '3.5'
services:
# The NGINX proxy. This is the only container exposed to the world.
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
restart: unless-stopped
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
ports:
- 80:80
- 443:443
volumes:
- ${DATA_DIR}/nginx-proxy/etc/nginx/conf.d/override.conf:/etc/nginx/conf.d/override.conf
- ${DATA_DIR}/nginx-proxy/etc/nginx/htpasswd:/etc/nginx/htpasswd
- ${DATA_DIR}/nginx-proxy/etc/nginx/vhost.d:/etc/nginx/vhost.d
- ${DATA_DIR}/nginx-proxy/html:/usr/share/nginx/html
- ${DATA_DIR}/../ssl_certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- TZ=${TIME_ZONE}
networks:
- nginx-proxy
# The Companion to update Letsencrypt certificates.
letsencrypt-companion:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nginx-proxy-letsencrypt
restart: unless-stopped
volumes:
- ${DATA_DIR}/nginx-proxy/etc/nginx/conf.d:/etc/nginx/conf.d
- ${DATA_DIR}/nginx-proxy/etc/nginx/vhost.d:/etc/nginx/vhost.d
- ${DATA_DIR}/nginx-proxy/html:/usr/share/nginx/html
- ${DATA_DIR}/../ssl_certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- nginx-proxy
environment:
- TZ=${TIME_ZONE}
networks:
- nginx-proxy
networks:
nginx-proxy:
name: nginx-proxy
external: true
EOF
echo "Create ${DATA_DIR}/nextcloud/nextcloud-docker-build/docker-compose.yml"
cat <<EOF > ${DATA_DIR}/nextcloud/nextcloud-docker-build/docker-compose.yml
version: '3.5'
services:
# The MariaDB Database
db:
image: mariadb
container_name: nextcloud-mariadb
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
restart: unless-stopped
volumes:
- ${DATA_DIR}/nextcloud-mariadb/etc/mysql/conf.d/override.conf:/etc/mysql/conf.d/override.conf
- ${DATA_DIR}/nextcloud-mariadb/var/lib:/var/lib/mysql
- ${DATA_DIR}/nextcloud-mariadb/var/log:/var/log
environment:
- TZ=${TIME_ZONE}
env_file:
- db.env
networks:
- nextcloud
# Redis In-Memory store
redis:
image: redis
container_name: nextcloud-redis
restart: always
environment:
- TZ=${TIME_ZONE}
env_file:
- redis.env
networks:
- nextcloud
# Main NextCloud Container
app:
image: nextcloud
container_name: nextcloud-app
restart: unless-stopped
volumes:
- ${DATA_DIR}/nextcloud/html:/var/www/html
- ${DATA_DIR}/nextcloud/data:/var/www/html/data
- ${DATA_DIR}/nextcloud/etc/php/conf.d/override.ini:/usr/local/etc/php/conf.d/override.ini
environment:
- MYSQL_HOST=nextcloud-mariadb
- VIRTUAL_HOST=${DOMAIN_NAME}
- LETSENCRYPT_HOST=${DOMAIN_NAME}
- LETSENCRYPT_EMAIL=${EMAIL}
- REDIS_HOST=nextcloud-redis
- TZ=${TIME_ZONE}
env_file:
- db.env
- nextcloud.env
- redis.env
depends_on:
- db
- redis
links:
- db:clouddatabase
networks:
- nginx-proxy
- nextcloud
# NextCloud instance which runs crond on the same shared volume as the app
cron:
image: nextcloud
container_name: nextcloud-cron
restart: unless-stopped
volumes:
- ${DATA_DIR}/nextcloud/html:/var/www/html
- ${DATA_DIR}/nextcloud/data:/var/www/html/data
- ${DATA_DIR}/nextcloud/etc/php/conf.d/override-cron.ini:/usr/local/etc/php/conf.d/override-cron.ini
environment:
- TZ=${TIME_ZONE}
entrypoint: /cron.sh
env_file:
- db.env
depends_on:
- app
networks:
nginx-proxy:
external: true
nextcloud:
name: nextcloud
external: true
EOF
echo " "
echo " "
echo "FILES CREATED"
echo " "
echo "1. Power up your nginx-proxy containers (only if not already running)"
echo "cd ${DATA_DIR}/nginx-proxy/docker-build"
echo "docker-compose up -d"
echo " "
echo "2. Power up your nextcloud containers:"
echo "cd ${DATA_DIR}/nextcloud/nextcloud-docker-build"
echo "docker-compose up -d"
echo " "
echo "3. Access https://${DOMAIN_NAME} and create an admin user"
echo " "
echo "4. Create optional Nextcloud db indexes"
echo "docker exec --user www-data nextcloud-app php occ db:add-missing-indices"
echo "docker exec --user www-data nextcloud-app php occ db:convert-filecache-bigint"
echo " "
# end
@Erik-Smie
Copy link

Erik-Smie commented Jan 30, 2022

Thanks you very much for providing this setup. Very useful to me and I learned a lot. For other users:

  • The script pulls the latest Mariadb (10.6), which is not compatible with the Nextcloud 23. I googled a lot, but stay with Mariadb 10.5.13 seems best to me
  • (I think to have found out that) Redis leads to an internal server error at first log in at nextcloud server -- "internal server error, server can not Internal Server Error".
    The return:
    "The server was unable to complete your request. If this happens again, please send the technical details below to the server administrator.
    More details can be found in the server log. Technical Information
    Remote Address: external ip adres
    and a code like "xeTisVxTOQWzudx0rw8T "

I could not find an other solution than remove Redis and depencies (from the docker-compose file) than the nextcloud server works, but without Redis. Other solutions?

Thanks a lot!

@QuentinFonteneau
Copy link

Hi !
I solved the Redis problem by adding this in docker-compose.yml (redis service) :
command: redis-server --requirepass myPasswordRedis

@dirtyharrywk
Copy link

Keep getting "Access through untrusted domain

Please contact your administrator. If you are an administrator, edit the "trusted_domains" setting in config/config.php like the example in config.sample.php."
When I enter the URL into my browser. The config.php file was empty. This is what baffles me about containers, I do not know which container to edit the config.php file. I have six containers running, nextcloud-cron, next cloud-app, nextcloud-mariadb, nextcloud-redis, nginx-proxy-letsencrypt and nginx-proxy. Any help would be greatly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment