I used to have a NextCloud Instance on my home server where I deployed nextcloud, redis and mariadb from docker, and used nginx from the host as the reverse proxy. I just recently discovered that I can put all these systems together in a single docker compose file, without me needing to install additional stuff on the host with apt. So, this was the docker-compose.yaml
I came up with.
services:
nginx:
image: nginx:alpine
container_name: nextcloud-nginx
restart: unless-stopped
volumes:
- /mnt/SysHDD/Docker-Compose/nextcloud/nginx/:/etc/nginx/:rw
- /home/server-inspiron/.acme.sh/:/mnt/certs/:ro
ports:
- 443:9000
- 8096:81
- 8920:82
networks:
nextcloud:
ipv4_address: 172.21.128.4
mariadb:
image: mariadb
container_name: nextcloud-mariadb
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1 --skip-innodb-read-only-compressed
volumes:
- /mnt/SysHDD/Databases/nextcloud-mariadb/:/var/lib/mysql/:rw
env_file:
- db.env
networks:
nextcloud:
ipv4_address: 172.21.128.1
redis:
image: redis
container_name: nextcloud-redis
restart: always
command: redis-server --requirepass SOMEPASSWORD
networks:
nextcloud:
ipv4_address: 172.21.128.2
app:
image: nextcloud:fpm
restart: unless-stopped
container_name: nextcloud-web
ports:
- 8080:9000
links:
- mariadb
- redis
volumes:
- web:/var/www/html
environment:
- MYSQL_HOST=172.21.128.1:3306
- REDIS_HOST_PASSWORD=SOMEPASSWORD
env_file:
- db.env
depends_on:
- mariadb
- redis
networks:
nextcloud:
ipv4_address: 172.21.128.3
volumes:
nextcloud-mariadb:
web:
networks:
nextcloud:
driver: bridge
ipam:
config:
- subnet: 172.21.0.0/16
gateway: 172.21.0.1
As you can see, The configuration is similar to the regular apache version of the nextcloud docker install, only difference being I included an alpine nginx image and the fpm version of nextcloud. Ignore the opened ports 8096 and 8920, as they are for redirect policies for an Emby media instance.
I knew that the fpm version requires a reverse proxy, so I forwarded port 9000, which is default for nextcloud:fpm to host port 443 for https.
I am ignoring discussion about certificates because I am not using a service like certbot. I am giving myself a better power control over it with acme.sh.
To forward the app, this was my nginx.conf
:
events {}
http {
server {
server_name mprakash.dynv6.net www.mprakash.dynv6.net;
listen 82 ssl;
listen 81;
# listen 9000 ssl;
return 301 https://mprakash.dynv6.net:2$request_uri;
ssl_certificate /mnt/certs/mprakash.dynv6.net_ecc/mprakash.dynv6.net.pem;
ssl_certificate_key /mnt/certs/mprakash.dynv6.net_ecc/mprakash.dynv6.net.key;
}
upstream nextcloud {
server 127.0.0.1:9000;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name serverinspiron-cloud.dynv6.net;
ssl_certificate /mnt/certs/serverinspiron-cloud.dynv6.net_ecc/serverinspiron-cloud.dynv6.net.pem;
ssl_certificate_key /mnt/certs/serverinspiron-cloud.dynv6.net_ecc/serverinspiron-cloud.dynv6.net.key;
client_max_body_size 512M;
fastcgi_buffers 64 4K;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
fastcgi_hide_header X-Powered-By;
root /var/www/html;
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
index index.php index.html /index.php$request_uri;
location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 /remote.php/webdav/$is_args$args;
}
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ^~ /.well-known {
location = /.well-known/carddav { return 301 /remote.php/dav/; }
location = /.well-known/caldav { return 301 /remote.php/dav/; }
location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
location /.well-known/pki-validation { try_files $uri $uri/ =404; }
return 301 /index.php$request_uri;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
location ~ \.php(?:$|/) {
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_pass localhost:9000;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ \.(?:css|js|svg|gif)$ {
try_files $uri /index.php$request_uri;
expires 6M;
access_log off;
}
location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d;
access_log off;
}
location /remote {
return 301 /remote.php$request_uri;
}
location / {
try_files $uri $uri/ /index.php$request_uri;
}
}
}
The configuration I am using is almost same as the nginx configuration in the nextcloud documentations.
I start the containers using docker compose up, and check the logs.
Logs for Nginx:
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf is not a file or does not exist
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
So far, so good.
Logs for Nextcloud:
=> Searching for scripts (*.sh) to run, located in the folder: /docker-entrypoint-hooks.d/before-starting
[31-Oct-2024 07:26:01] NOTICE: fpm is running, pid 1
[31-Oct-2024 07:26:01] NOTICE: ready to handle connections
Looks fine too.
But the problem arises when I try to open the app on my browser. When I try to do so, I get the following error:
The connection is forcefully closed, which means something exists on the other side, but I am unable to access it. What is the problem that I am facing? I think it has a pretty trivial solution but I am unable to figure it out. I request the community to please help me out. Thank you.