WordPress in front (root) of Nextcloud

NGINX reverse proxy

This guide will exemplary describe how to configure WordPress (/) in front of Nextcloud (/nextcloud). It is based on the initial WordPress how to and requires all the implementations before changing the following files.


sudo -s

Comment the proxy.conf and header.conf in the web server configuration

nano /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
server_names_hash_bucket_size 64;
upstream php-handler {
server unix:/run/php/php7.3-fpm.sock;
}
set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
include /etc/nginx/optimization.conf;
include /etc/nginx/ssl.conf;
#include /etc/nginx/proxy.conf;
#include /etc/nginx/header.conf;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
sendfile on;
send_timeout 3600;
tcp_nopush on;
tcp_nodelay on;
open_file_cache max=500 inactive=10m;
open_file_cache_errors on;
keepalive_timeout 65;
reset_timedout_connection on;
server_tokens off;
resolver 192.168.2.1 valid=30s;
#resolver 127.0.0.53 valid=30s; is recommended but reuqires a valid resolver configuration
resolver_timeout 5s;
include /etc/nginx/conf.d/*.conf;
}

Create the nginx reverse proxy gateway.conf file to handle the incoming requests depending on the expected applications/urls

touch /etc/nginx/conf.d/gateway.conf && nano /etc/nginx/conf.d/gateway.conf 
server {
server_name your.dedyn.io;
listen 80 default_server;
listen [::]:80 default_server;
location ^~ /.well-known/acme-challenge {
proxy_pass http://127.0.0.1:81;
proxy_set_header Host $host;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name your.dedyn.io;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
root /var/www/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
include /etc/nginx/proxy.conf;
include /etc/nginx/header.conf;
client_max_body_size 10240M;
### NEXTCLOUD ###
location ^~ /nextcloud/ {
client_max_body_size 10240M;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
send_timeout 3600;
proxy_buffering off;
proxy_request_buffering off;
proxy_max_temp_file_size 10240m;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:82;
proxy_redirect off;
}
location = /.well-known/carddav {
return 301 $scheme://$host/nextcloud/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/nextcloud/remote.php/dav;
}
location = /.well-known/webfinger {
return 301 $scheme://$host/nextcloud/public.php?service=webfinger;
}
location ~ /(ocm-provider|ocs-provider)/ {
return 301 $scheme://$host/nextcloud/$1/;
}
### WORDPRESS ###
location ^~ / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-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;
proxy_pass http://127.0.0.1:84;
proxy_redirect off;
}
}

Modify the existing nextcloud.conf to listen to the reverse proxy

cp /etc/nginx/conf.d/nextcloud.conf /etc/nginx/conf.d/nextcloud.conf.bak
nano /etc/nginx/conf.d/nextcloud.conf
server {
listen 127.0.0.1:82;
server_name 127.0.0.1;
root /var/www/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $scheme://$host/nextcloud/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/nextcloud/remote.php/dav;
}
#SOCIAL app enabled? Please uncomment the following row
#rewrite ^/.well-known/webfinger /nextcloud/public.php?service=webfinger last;
#WEBFINGER app enabled? Please uncomment the following two rows.
#rewrite ^/.well-known/host-meta /nextcloud/public.php?service=host-meta last;
#rewrite ^/.well-known/host-meta.json /nextcloud/public.php?service=host-meta-json last;
client_max_body_size 10240M;
location /nextcloud {
rewrite ^ /nextcloud/index.php$request_uri;
}
location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)/ {
deny all;
}
location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ \.(?:flv|mp4|mov|m4a)$ {
mp4;
mp4_buffer_size 100M;
mp4_max_buffer_size 1024M;
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
include fastcgi_params;
include php_optimization.conf;
fastcgi_pass php-handler;
fastcgi_param HTTPS on;
fastcgi_param REMOTE_ADDR $http_x_real_ip;
}
location ~ ^\/nextcloud/(?:index|ipcheck|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+).php(?:$|\/) {
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
include fastcgi_params;
include php_optimization.conf;
fastcgi_pass php-handler;
fastcgi_param HTTPS on;
fastcgi_param REMOTE_ADDR $http_x_real_ip;
}
location ~ ^\/nextcloud/(?:updater|oc[ms]-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
location ~ ^\/nextcloud\/.+[^\/]\.(?:css|js|woff2?|svg|gif|png|html|ttf|ico|jpg|jpeg)$ {
try_files $uri /nextcloud/index.php$request_uri;
proxy_set_header Cache-Control "public, max-age=15778463";
proxy_set_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload;";
proxy_set_header X-Content-Type-Options nosniff;
proxy_set_header X-XSS-Protection "1; mode=block";
proxy_set_header X-Robots-Tag none;
proxy_set_header X-Download-Options noopen;
proxy_set_header X-Permitted-Cross-Domain-Policies none;
proxy_set_header Referrer-Policy no-referrer;
access_log off;
}
}

Modify the wordpress configuration file

cp /etc/nginx/conf.d/wordpress.conf /etc/nginx/conf.d/wordpress.conf.bak
nano /etc/nginx/conf.d/wordpress.conf
server {
server_name 127.0.0.1;
listen 127.0.0.1:84;
root /var/www/wordpress/;
location ^~ /{ 
index index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params; 
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php-handler;
fastcgi_connect_timeout 60;
fastcgi_index index.php;
fastcgi_param REMOTE_ADDR $http_x_real_ip;
}
location ~* /\.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
location /wp-admin {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/wordpress-access;
}
location ~* /(?:uploads|files)/.*.(html|htm|shtml|php|js|swf)$ {
deny all;
}
}
}

Amend the wp-config.php to point WordPress to the webroot instead of its subfolder

nano /etc/nginx/wp-config.php
<?php
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)
    $_SERVER['HTTPS']='on';
if(isset($_SERVER['HTTP_X_FORWARDED_HOST']))
    $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
define('WP_HOME', 'https://your.dedyn.io');
define('WP_SITEURL', 'https://your.dedyn.io');
define('DB_NAME', 'wordpress');
define('DB_USER', 'wordpress');
define('DB_PASSWORD', 'wordpressDBpassword');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', '');
define('AUTH_KEY',         'from the url below');
define('SECURE_AUTH_KEY',  'from the url below');
define('LOGGED_IN_KEY',    'from the url below');
define('NONCE_KEY',        'from the url below');
define('AUTH_SALT',        'from the url below');
define('SECURE_AUTH_SALT', 'from the url below');
define('LOGGED_IN_SALT',   'from the url below');
define('NONCE_SALT',       'from the url below');
$table_prefix = 'ncblog_';
define('WP_DEBUG', false);
if ( !defined('ABSPATH') )
 define('ABSPATH', dirname(__FILE__) . '/');
require_once(ABSPATH . 'wp-settings.php');

To generate your define-values open: https://api.wordpress.org/secret-key/1.1/salt/


Don’t forget to backup your Nextcloud

Enjoy your harden WordPress, but don’t forget to backup your WordPress. Find instructions here: Nextcloud backup and restore

Carsten Rieger

Carsten Rieger is a senior system engineer in full-time and also working as an IT freelancer. He is working with linux environments for more than 15 years, an Open Source enthusiast and highly motivated on linux installation and troubleshooting. Mostly working with Debian/Ubuntu Linux, Nginx and Apache web server, MariaDB/MySQL/PostgreSQL, PHP, Cloud infrastructure (e.g. Nextcloud) and other open source projects (e.g. Roundcube) and in voluntary work for the Dr. Michael & Angela Jacobi Stiftung for more than 7 years.