[INTRODUCTION]
Hello Nextcloud community and developers. I have setup my Nextcloud server locally on my server at home using proxmox VM and LXCs by following this guide (Nextcloud Installationsanleitung Hub 9 - Carsten Rieger IT-Services). Most of the time I search and learnt that it is dangerous to expose a home-server to public internet. With that I found a solution using Tailscale network (https://tailscale.com) to access remotely in a secure way along caddy as reverse proxy with cloudflare-dns-module (https://caddyserver.com) and cloudflare (https://cloudflare.com) as DNS. This solution does not need any port forwarding and SSL cert generation manually as caddy resolve itself. (however I generate SSL) This idea is currently taken from Tailscale YouTube channel presented by Alex Kretzschmar (Alex Kretzschmar (@ironicbadger@techhub.social) - TechHub) & (https://www.youtube.com/@Tailscale)
[/details]
- Nextcloud version [Nextcloud Hub 9 (30.0.1)]
- Operating system and version Proxmox VM (Ubuntu 24.04) Local home-server
- nginx version (1.27.2)
- PHP version (8.3)
- Caddy with dns-cloudflare-module (on proxmox LXC-1001)
- Tailscale (on proxmox LXC-1001) & (Ubuntu 24.04) Local home-server)
- Cloudflare DNS for managing DNS records and API
Note Tailscale is also installed in Proxmox VM ((Ubuntu 24.04) Local home-server) in which Nextcloud, nginx, PHP are running. This mean, I have 1x VM and 1x LXC both with Tailscale installed. Moreover, Caddy LXC is the name of my proxmox LXC in which caddy and tailscale are installed. Avoid confusion, please
[The issue I am facing]
During Nextcloud installation, I request and create Let’s Encrypt certificates (RSA 4096) without opening TCP ports 80 and 443 (Let's Encrypt Zertifikate (RSA 4096 oder EC 384) ohne offene TCP-Ports 80 und 443 beantragen und erstellen - Carsten Rieger IT-Services) because my ISP has blocked almost all my ports. I am using a domestic internet service which doesn’t allow any port forwarding and static public ip. After setting up my Nextcloud server, nextcloud.conf, config.php, nginx.conf and allowed trusted domains and IP addresses. Now I can only access to my newly created Nextcloud server through IP address but not via domain.
I am also sure that my caddy reverse proxy which is in LXC doesn’t communicate. This may be due to miss configuration. I am putting all the .conf, .config and Caddyfile commands in order to analyze by the community to rectify the error I made.
[The output of /etc/nginx/nginx.conf
] file
user www-data;
worker_processes auto;
pid /var/run/nginx.pid;
events {
worker_connections 2048;
multi_accept on;
use epoll;
}
http {
log_format criegerde escape=json # *criegerde not know to me why I put this. Assist if need amendment, please
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"remote_user":"$remote_user",'
'"request":"$request",'
'"status": "$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"request_time":"$request_time",'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
server_names_hash_bucket_size 64;
access_log /var/log/nginx/access.log criegerde; # *criegerde
error_log /var/log/nginx/error.log warn;
set_real_ip_from 100.110.210.310 192.168.10.20; #1st IP is of caddy lxc tailscale which run inside the caddy lxc and 2nd IP is actual IP address of caddy LXC container.
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
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 1.1.1.1 1.0.0.1 valid=30s; # as of cloudflare DNS, assist if need amendment, please
resolver_timeout 5s;
include /etc/nginx/conf.d/*.conf;
[The output of /var/www/nextcloud/config/config.php
] file
<?php
$CONFIG = array (
'instanceid' => 'XXXXXX,
'passwordsalt' => 'XXXXXXXXXXXXXXXXXXX',
'secret' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
'trusted_domains' =>
array (
0 => 'nc.example.com',
1 => '192.168.10.123', # Local IP address of my local Ubuntu home-server installed in Proxmox as VM
2 => 'nc.shee-foo.ts.net', # Tailscale domain address/name of the installed on local Ubuntu home-server in Proxmox as VM
3 => '100.80.170.11', # tailscale IP address of the above domain
),
'datadirectory' => '/var/nc_data',
'dbtype' => 'xxxx',
'version' => 'xx.xx.x',
'overwrite.cli.url' => 'http://localhost', # when I put 'https://nc.example.com', I cannot even access my Nextcloud server via IP address
'dbname' => 'nextclouddb',
'dbhost' => 'localhost',
'dbport' => '',
'dbtableprefix' => 'oc_',
'mysql.utf8mb4' => true,
'dbuser' => 'nc',
'dbpassword' => 'XXXXX',
'installed' => true,
// 'overwritehost' => 'nc.example.com', # when // I can access my Nextcloud server with IP address otherwise not
'activity_expire_days' => 14,
'allow_local_remote_servers' => true,
'auth.bruteforce.protection.enabled' => true,
'forbidden_filenames' =>
array (
0 => '.htaccess',
1 => 'Thumbs.db',
2 => 'thumbs.db',
),
'cron_log' => true,
'default_phone_region' => 'OF',
'enable_previews' => true,
'enabledPreviewProviders' =>
array (
0 => 'OC\\Preview\\PNG',
1 => 'OC\\Preview\\JPEG',
2 => 'OC\\Preview\\GIF',
3 => 'OC\\Preview\\BMP',
4 => 'OC\\Preview\\XBitmap',
5 => 'OC\\Preview\\Movie',
6 => 'OC\\Preview\\PDF',
7 => 'OC\\Preview\\MP3',
8 => 'OC\\Preview\\TXT',
9 => 'OC\\Preview\\MarkDown',
10 => 'OC\\Preview\\HEIC',
11 => 'OC\\Preview\\Movie',
12 => 'OC\\Preview\\MKV',
13 => 'OC\\Preview\\MP4',
14 => 'OC\\Preview\\AVI',
),
'filesystem_check_changes' => 0,
'filelocking.enabled' => 'true',
'htaccess.RewriteBase' => '/',
'integrity.check.disabled' => false,
'knowledgebaseenabled' => false,
'log_rotate_size' => '104857600',
'logfile' => '/var/log/nextcloud/nextcloud.log',
'loglevel' => 2,
'logtimezone' => 'Europe/Paris',
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'overwriteprotocol' => 'https',
'preview_max_x' => 1024,
'preview_max_y' => 768,
'preview_max_scale_factor' => 1,
'profile.enabled' => false,
'redis' =>
array (
'host' => '/var/run/redis/redis-server.sock',
'port' => 0,
'password' => 'XXXXXXX',
'timeout' => 0.5,
'dbindex' => 1,
),
'quota_include_external_storage' => false,
'share_folder' => '/Freigaben',
'skeletondirectory' => '',
'trashbin_retention_obligation' => 'auto, 7',
'maintenance_window_start' => 1,
'maintenance' => false,
);
[The output of /etc/nginx/conf.d/nextcloud.conf
] file
limit_req_zone $binary_remote_addr zone=NextcloudRateLimit:10m rate=2r/s;
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
http2 on;
server_name nc.example.com;
ssl_certificate /etc/letsencrypt/live/nc.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nc.example.com/privkey.pem;
#ssl_certificate /etc/letsencrypt/ecc-certs/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/ecc-certs/privkey.pem;
#ssl_trusted_certificate /etc/letsencrypt/ecc-certs/chain.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA38>
ssl_ecdh_curve X448:secp521r1:secp384r1;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
client_max_body_size 10G;
client_body_timeout 3600s;
client_body_buffer_size 512k;
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 text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.g>
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
add_header Permissions-Policy "interest-cohort=()";
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 "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always;
fastcgi_hide_header X-Powered-By;
include mime.types;
types {
text/javascript mjs;
}
root /var/www/nextcloud;
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\/.+|ocs-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 $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
fastcgi_connect_timeout 3600;
fastcgi_max_temp_file_size 0;
}
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463, $asset_immutable";
expires 6M;
access_log off;
location ~ \.wasm$ {
default_type application/wasm;
}
}
location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d;
access_log off;
}
location /remote {
return 301 /remote.php$request_uri;
}
location /login {
limit_req zone=NextcloudRateLimit burst=5 nodelay;
limit_req_status 429;
try_files $uri $uri/ /index.php$request_uri;
}
location / {
try_files $uri $uri/ /index.php$request_uri;
}
}
[The output of /etc/nginx/conf.d/http.conf
] file
server unix:/run/php/php8.3-fpm.sock;
}
map $arg_v $asset_immutable {
"" "";
default "immutable";
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name nc.example.com 192.168.10.123; # IP address of my local Ubuntu home-server on which Nextcloud is installed
root /var/www;
location / {
return 301 https://$host$request_uri;
}
}
[The output of /etc/hosts
] file
127.0.0.1 localhost
127.0.1.1 nc.example.com nc
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
[The output of /etc/hostname
] file
nc.example.com
[The output of Caddyfile
]
(cloudflare) {
tls {
dns cloudflare <api_token>
}
}
# nextcloud
https://nc.shee-foo.ts.net { #Tailscale domain of Ubuntu home-server which is already made trusted
reverse_proxy 192.168.10.123:80 # IP of ubuntu home-server on Proxmox VM on which nextcloud, PHP and nginx webserver is running
import cloudflare
}
[Closing remarks]
Having the detailed output of my Nextcloud server, it is requested to the community and developers to please have your analysis and guide me, PLEASE
Regards