How can I have multiple web servers and a Nextcloud server hosted on a nginx instance without domains?

What I’m trying to do: I am attempting to host a web server, with more in the future, and Nextcloud on my Ubuntu Server. I do not own a domain, these services will only be available within the LAN for now, and I am currently utilizing self-signed certificates.

I have the charlie site functional, but I can’t access Nextcloud via web client following installation.

The following is a representation of my goal.

                                Web client
                                    |
           -----------------------------------------------------
           |                                                   |
           v                                                   v
           https://192.168.1.189/charlie (web site)            https://192.168.1.189/nc (Nextcloud)

Where I’m stuck: I’ve seen tutorials utilize different IPs or domains for each respective web server or Nextcloud on nginx, but I have no domains and only 1 local IPv4 address for my Ubuntu Server.

The following are my web site and Nextlcoud config files.

  1. nginx.conf
user  www-data;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /run/nginx.pid;

events {
    worker_connections  1024;
}


http {
    include /etc/nginx/snippets/ssl-params.conf;
    include /etc/nginx/snippets/self-signed.conf;
    include /etc/nginx/sites-enabled/*.conf;

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;
}
  1. charlie.conf (web site)
# HTTP
#server {
	#listen		80;
	#server_name	192.168.1.189;

	#location /charlie {
		#root 	/usr/share/nginx/html;
		#index	index.html; 
	#}

	#error_page   500 502 503 504  /50x.html;
	#location = /50x.html {
		#root   /usr/share/nginx/html;
	#}
#}

#------------------------------------------------------------------

# HTTPS
server {
	
	listen 		443 ssl default_server;
	server_name 	192.168.1.189;

	location /charlie {
		root 	/usr/share/nginx/html;
		index	index.html;
	}  

	error_page   500 502 503 504  /50x.html;
	location = /50x.html {
		root   /usr/share/nginx/html;
	}
}

# Redirect
server {
	listen		80;
	server_name	192.168.1.189;
	return		301 https://$host$request_uri;
}
  1. nc.conf (Nextcloud)
upstream php-handler {
    #server 127.0.0.1:9000;
    server unix:/var/run/php/php8.3-fpm.sock;
}

# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
    "" "";
    default ", immutable";
}

server {
    listen 80;
    listen [::]:80;
    server_name 192.168.1.189;

    # Prevent nginx HTTP Server Detection
    server_tokens off;

    # Enforce HTTPS just for `/nextcloud`
    location /nextcloud {
        return 301 https://$server_name$request_uri;
    }
}

server {
    #listen 443      ssl http2;
    #listen [::]:443 ssl http2;
    # With NGinx >= 1.25.1 you should use this instead:
    listen 443      ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name 192.168.1.189;

    # Path to the root of the domain
    root /var/www;

    # Use Mozilla's guidelines for SSL/TLS settings
    # https://mozilla.github.io/server-side-tls/ssl-config-generator/
    
    # PROVIDED VIA CODE SNIPPET
    #ssl_certificate     /etc/ssl/nginx/cloud.example.com.crt;
    #ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;

    # Prevent nginx HTTP Server Detection
    server_tokens off;

    # Set .mjs and .wasm MIME types
    # Either include it in the default mime.types list
    # and include that list explicitly or add the file extension
    # only for Nextcloud like below:
    include mime.types;
    types {
        text/javascript mjs;
	application/wasm wasm;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location ^~ /.well-known {
        # The rules in this block are an adaptation of the rules
        # in the Nextcloud `.htaccess` that concern `/.well-known`.

        # ENSURE PROPER CONFIG VIA SOURCE LINK 
        location = /.well-known/carddav { return 301 /nextcloud/remote.php/dav/; }
        location = /.well-known/caldav  { return 301 /nextcloud/remote.php/dav/; }

        location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
        location /.well-known/pki-validation    { try_files $uri $uri/ =404; }

        # Let Nextcloud's API for `/.well-known` URIs handle all other
        # requests by passing them to the front-end controller.
        return 301 /nextcloud/index.php$request_uri;
    }

    location ^~ /nextcloud {
        # set max upload size and increase upload timeout:
        client_max_body_size 512M;
        client_body_timeout 300s;
        fastcgi_buffers 64 4K;

        # Enable gzip but do not remove ETag headers
        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.geo+json application/vnd.ms-fontobject application/wasm 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;

        # Pagespeed is not supported by Nextcloud, so if your server is built
        # with the `ngx_pagespeed` module, uncomment this line to disable it.
        #pagespeed off;

        # The settings allows you to optimize the HTTP2 bandwidth.
        # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
        # for tuning hints
        client_body_buffer_size 512k;

        # HSTS settings
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

        # HTTP response headers borrowed from Nextcloud `.htaccess`
        add_header Referrer-Policy                   "no-referrer"       always;
        add_header X-Content-Type-Options            "nosniff"           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;

        # Remove X-Powered-By, which is an information leak
        fastcgi_hide_header X-Powered-By;

        # Specify how to handle directories -- specifying `/nextcloud/index.php$request_uri`
        # here as the fallback means that Nginx always exhibits the desired behaviour
        # when a client requests a path that corresponds to a directory that exists
        # on the server. In particular, if that directory contains an index.php file,
        # that file is correctly served; if it doesn't, then the request is passed to
        # the front-end controller. This consistent behaviour means that we don't need
        # to specify custom rules for certain paths (e.g. images and other assets,
        # `/updater`, `/ocs-provider`), and thus
        # `try_files $uri $uri/ /nextcloud/index.php$request_uri`
        # always provides the desired behaviour.
        index index.php index.html /nextcloud/index.php$request_uri;

        # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
        location = /nextcloud {
            if ( $http_user_agent ~ ^DavClnt ) {
                return 302 /nextcloud/remote.php/webdav/$is_args$args;
            }
        }

        # Rules borrowed from `.htaccess` to hide certain paths from clients
        location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)    { return 404; }
        location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console)                  { return 404; }

        # Ensure this block, which passes PHP files to the PHP process, is above the blocks
        # which handle static assets (as seen below). If this block is not declared first,
        # then Nginx will encounter an infinite rewriting loop when it prepends
        # `/nextcloud/index.php` to the URI, resulting in a HTTP 500 error response.
        location ~ \.php(?:$|/) {
            # Required for legacy support
            rewrite ^/nextcloud/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /nextcloud/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;         # Avoid sending the security headers twice
            fastcgi_param front_controller_active true;     # Enable pretty urls
            fastcgi_pass php-handler;

            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;

            fastcgi_max_temp_file_size 0;
        }

        # Serve static files
        location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
            try_files $uri /nextcloud/index.php$request_uri;
            # HTTP response headers borrowed from Nextcloud `.htaccess`
            add_header Cache-Control                     "public, max-age=15778463$asset_immutable";
            add_header Referrer-Policy                   "no-referrer"       always;
            add_header X-Content-Type-Options            "nosniff"           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;
            access_log off;     # Optional: Don't log access to assets
        }

        location ~ \.(otf|woff2?)$ {
            try_files $uri /nextcloud/index.php$request_uri;
            expires 7d;         # Cache-Control policy borrowed from `.htaccess`
            access_log off;     # Optional: Don't log access to assets
        }

        # Rule borrowed from `.htaccess`
        location /nextcloud/remote {
            return 301 /nextcloud/remote.php$request_uri;
        }

        location /nextcloud {
            try_files $uri $uri/ /nextcloud/index.php$request_uri;
        }
    }

    # SUPPRESS LOG MESSAGES (nginx section 3)
    location = /data/htaccesstest.txt {
    allow all;
    log_not_found off;
    access_log off;
    }
}

What I’ve already tried: I’ve spent some time in the Nextcloud community forum and as of now the issue seems to be my lack of understanding for configuring nginx with multiple servers. I’ve been watching tutorial videos regarding nginx configurations, but nothing seems to be obviously wrong from my perspective as of yet.

Hey @Swimmer2-Unboxed7! You have two different server blocks defined listening on the same IP and the same ports. My first suggestion would be to merge your second (charlie.conf) and third (nc.conf) configs together. Since both your web server and NextCloud are listening on the same IP and same port, you should be able to simply define multiple location blocks inside the same server block.

Thank you, I will try this! Could you also explain the reasoning for me?

Here is my updated config. Upon trying to restart nginx, I receive the following errors. I didn’t notice anything wrong with lines 15 and 20 besides their similarity? As for line 35, how to address multiple locations listening on the same port (80/443)?

Starting nginx.service - nginx - high performance web server...
Jun 25 16:06:20 optiplex nginx[4324]: nginx: [warn] server name "192.168.1.189/charlie" has suspicious symbols in /etc/nginx/sites-enabled/charlie_nc.conf:15
Jun 25 16:06:20 optiplex nginx[4324]: nginx: [warn] server name "192.168.1.189/charlie" has suspicious symbols in /etc/nginx/sites-enabled/charlie_nc.conf:20
Jun 25 16:06:20 optiplex nginx[4324]: nginx: [emerg] a duplicate listen 0.0.0.0:80 in /etc/nginx/sites-enabled/charlie_nc.conf:35
Jun 25 16:06:20 optiplex systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Jun 25 16:06:20 optiplex systemd[1]: nginx.service: Failed with result 'exit-code'.
Jun 25 16:06:20 optiplex systemd[1]: Failed to start nginx.service - nginx - high performance web server.

charlie_nc.conf

upstream php-handler {
    #server 127.0.0.1:9000;
    server unix:/var/run/php/php8.3-fpm.sock;
}

# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
    "" "";
    default ", immutable";
}

server {
        # Web server redirect
        listen          80;
        server_name     192.168.1.189/charlie;
        return          301 https://$host$request_uri;

        # Web server 
        listen          443 ssl default_server;
        server_name     192.168.1.189/charlie;

        location /charlie {
                root    /var/www/html;
                index   index.html;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   /var/www/html;
        }

        #-------------------------

        # NC redirect
        # listen 80; # COMMENT COMMENT COMMENT
        # listen [::]:80; # COMMENT COMMENT COMMENT
        server_name 192.168.1.189/nc;

        # Prevent nginx HTTP Server Detection
        server_tokens off;

        # Enforce HTTPS just for `/nextcloud`
        location /nextcloud {
                return 301 https://$server_name$request_uri;
        }

        # NC
        #listen 443      ssl http2;
        #listen [::]:443 ssl http2;
        # With NGinx >= 1.25.1 you should use this instead:
        # listen 443      ssl; # COMMENT COMMENT COMMENT
        # listen [::]:443 ssl; # COMMENT COMMENT COMMENT
        http2 on;
        server_name 192.168.1.189/nc;

        # Path to the root of the domain
        root /var/www;

        # Use Mozilla's guidelines for SSL/TLS settings
        # https://mozilla.github.io/server-side-tls/ssl-config-generator/
    
        # PROVIDED VIA CODE SNIPPET
        #ssl_certificate     /etc/ssl/nginx/cloud.example.com.crt;
        #ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;

        # Prevent nginx HTTP Server Detection
        server_tokens off;

        # Set .mjs and .wasm MIME types
        # Either include it in the default mime.types list
        # and include that list explicitly or add the file extension
        # only for Nextcloud like below:
        include mime.types;
        types {
                text/javascript mjs;
                application/wasm wasm;
         }

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

        location ^~ /.well-known {
                # The rules in this block are an adaptation of the rules
                # in the Nextcloud `.htaccess` that concern `/.well-known`.

                # ENSURE PROPER CONFIG VIA SOURCE LINK 
                location = /.well-known/carddav { return 301 /nextcloud/remote.php/dav/; }
                location = /.well-known/caldav  { return 301 /nextcloud/remote.php/dav/; }

                location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
                location /.well-known/pki-validation    { try_files $uri $uri/ =404; }

                # Let Nextcloud's API for `/.well-known` URIs handle all other
                # requests by passing them to the front-end controller.
                return 301 /nextcloud/index.php$request_uri;
        }

        location ^~ /nextcloud {
                # set max upload size and increase upload timeout:
                client_max_body_size 512M;
                client_body_timeout 300s;
                fastcgi_buffers 64 4K;

                # Enable gzip but do not remove ETag headers
                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.geo+json application/vnd.ms-fontobject application/wasm 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;

                # Pagespeed is not supported by Nextcloud, so if your server is built
                # with the `ngx_pagespeed` module, uncomment this line to disable it.
                #pagespeed off;

                # The settings allows you to optimize the HTTP2 bandwidth.
                # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
                # for tuning hints
                client_body_buffer_size 512k;

                # HSTS settings
                # WARNING: Only add the preload option once you read about
                # the consequences in https://hstspreload.org/. This option
                # will add the domain to a hardcoded list that is shipped
                # in all major browsers and getting removed from this list
                # could take several months.
                #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

                # HTTP response headers borrowed from Nextcloud `.htaccess`
                add_header Referrer-Policy                   "no-referrer"       always;
                add_header X-Content-Type-Options            "nosniff"           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;

                # Remove X-Powered-By, which is an information leak
                fastcgi_hide_header X-Powered-By;

                # Specify how to handle directories -- specifying `/nextcloud/index.php$request_uri`
                # here as the fallback means that Nginx always exhibits the desired behaviour
                # when a client requests a path that corresponds to a directory that exists
                # on the server. In particular, if that directory contains an index.php file,
                # that file is correctly served; if it doesn't, then the request is passed to
                # the front-end controller. This consistent behaviour means that we don't need
                # to specify custom rules for certain paths (e.g. images and other assets,
                # `/updater`, `/ocs-provider`), and thus
                # `try_files $uri $uri/ /nextcloud/index.php$request_uri`
                # always provides the desired behaviour.
                index index.php index.html /nextcloud/index.php$request_uri;

                # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
                location = /nextcloud {
                        if ( $http_user_agent ~ ^DavClnt ) {
   return 302 /nextcloud/remote.php/webdav/$is_args$args;
                        }
                }

                # Rules borrowed from `.htaccess` to hide certain paths from clients
                location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)    { return 404; }
                location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console)                  { return 404; }

                # Ensure this block, which passes PHP files to the PHP process, is above the blocks
                # which handle static assets (as seen below). If this block is not declared first,
                # then Nginx will encounter an infinite rewriting loop when it prepends
                # `/nextcloud/index.php` to the URI, resulting in a HTTP 500 error response.
                location ~ \.php(?:$|/) {
                        # Required for legacy support
                        rewrite ^/nextcloud/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /nextcloud/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;         # Avoid sending the security headers twice
                        fastcgi_param front_controller_active true;     # Enable pretty urls
                        fastcgi_pass php-handler;

                        fastcgi_intercept_errors on;
                        fastcgi_request_buffering off;

                        fastcgi_max_temp_file_size 0;
                }

                # Serve static files
                location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
                        try_files $uri /nextcloud/index.php$request_uri;
                        # HTTP response headers borrowed from Nextcloud `.htaccess`
                        add_header Cache-Control                     "public, max-age=15778463$asset_immutable";
                        add_header Referrer-Policy                   "no-referrer"       always;
                        add_header X-Content-Type-Options            "nosniff"           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;
                        access_log off;     # Optional: Don't log access to assets
                }

                location ~ \.(otf|woff2?)$ {
                        try_files $uri /nextcloud/index.php$request_uri;
                        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
                        access_log off;     # Optional: Don't log access to assets
                }

                # Rule borrowed from `.htaccess`
                        location /nextcloud/remote {
                                return 301 /nextcloud/remote.php$request_uri;
                        }

                location /nextcloud {
                        try_files $uri $uri/ /nextcloud/index.php$request_uri;
                }
        }

        # SUPPRESS LOG MESSAGES (nginx section 3)
        location = /data/htaccesstest.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

}

I can sure try! The short of it is that your config shouldn’t even work as is, although I suspect the fact that the NextCloud server is listening on IPv6 might be the reason why it still works.

As to why – You are defining two server blocks with an identical address. You listen on the same range of addresses and ports (the listen directives are identical between blocks) and you use the same server_name (you have used your IP as the name here). By all accounts NGINX here would not know to which server block to direct your request towards, and thus should fail on reload. By merging both configs together you should get rid of that potential issue.

All that being said, since you didn’t mention your NGINX deployment crashing and you can access your charlie web server, can you try to access NextCloud via your IPv6 address instead of your IPv4 address? I am curious to see if that might work. (I would still merge both server blocks anyways as that is the actual recommended way to do a deployment like yours.)

I believe I have merged them in the charlie_nc.conf file above, no? I have only one server block from what I can tell.

Sorry! I missed your updates before I posted my reply! You only need one listen directive per address/port combo, so you can get rid of any duplicate directives. For server_name, you might actually not need one for your use case – check Server names for more details.

1 Like

I have updated charlie_nc.conf above with “# COMMENT COMMENT COMMENT” throughout for you to see the duplicates I wish to comment out.

I have looked at the documentation you showed me and I believe my server_name variables are not necessary do to me having only one server block, correct?

That is quite likely indeed, especially if this is going to be a local server for now.

I have implemented the changes and have noticed a new error.

Jun 25 23:02:13 optiplex systemd[1]: Starting nginx.service - nginx - high performance web server...
Jun 25 23:02:13 optiplex nginx[6734]: nginx: [warn] duplicate extension "wasm", content type: "application/wasm", previous content type: "application/wasm" in /etc/ngi>
Jun 25 23:02:13 optiplex nginx[6734]: nginx: [warn] "ssl_stapling" ignored, issuer certificate not found for certificate "/etc/ssl/certs/oller-net-selfsigned.crt"
Jun 25 23:02:13 optiplex nginx[6734]: nginx: [emerg] duplicate location "/nextcloud" in /etc/nginx/sites-enabled/charlie_nc.conf:103
Jun 25 23:02:13 optiplex systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Jun 25 23:02:13 optiplex systemd[1]: nginx.service: Failed with result 'exit-code'.
Jun 25 23:02:13 optiplex systemd[1]: Failed to start nginx.service - nginx - high performance web server.

The Nextcloud documentation provided the config and I don’t know if I should change it trying to fix this error. I’ll likely ask the NC community about this one too.

That new error is probably due to this code block

location /nextcloud {
        return 301 https://$server_name$request_uri;
}

combined with this code block:

location ^~ /nextcloud {
        # set max upload size and increase upload timeout:
...

You fundamentally have two location blocks with the same location.

Try something along the lines of the following config (note: I have not tested this so you might still run into errors):

upstream php-handler {
    #server 127.0.0.1:9000;
    server unix:/var/run/php/php8.3-fpm.sock;
}

# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
    "" "";
    default ", immutable";
}

# If you want to redirect http to https
server {
        listen          80;
        return          301 https://$host$request_uri;
}

server {
        # Web server 
        # listen          80; # If you want to have everything on http instead of https
        listen          443 ssl default_server;
        http2 on; # Only if you want to enable http2

        location /charlie {
                root    /var/www/html;
                index   index.html;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   /var/www/html;
        }

        #-------------------------

        # NC redirect

        # Prevent nginx HTTP Server Detection
        server_tokens off;

        # Path to the root of the domain
        root /var/www;

        # Use Mozilla's guidelines for SSL/TLS settings
        # https://mozilla.github.io/server-side-tls/ssl-config-generator/
    
        # PROVIDED VIA CODE SNIPPET
        #ssl_certificate     /etc/ssl/nginx/cloud.example.com.crt;
        #ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;

        # Prevent nginx HTTP Server Detection
        server_tokens off;

        # Set .mjs and .wasm MIME types
        # Either include it in the default mime.types list
        # and include that list explicitly or add the file extension
        # only for Nextcloud like below:
        include mime.types;
        types {
                text/javascript mjs;
                application/wasm wasm;
         }

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

        location ^~ /.well-known {
                # The rules in this block are an adaptation of the rules
                # in the Nextcloud `.htaccess` that concern `/.well-known`.

                # ENSURE PROPER CONFIG VIA SOURCE LINK 
                location = /.well-known/carddav { return 301 /nextcloud/remote.php/dav/; }
                location = /.well-known/caldav  { return 301 /nextcloud/remote.php/dav/; }

                location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
                location /.well-known/pki-validation    { try_files $uri $uri/ =404; }

                # Let Nextcloud's API for `/.well-known` URIs handle all other
                # requests by passing them to the front-end controller.
                return 301 /nextcloud/index.php$request_uri;
        }

        location ^~ /nextcloud {
                # set max upload size and increase upload timeout:
                client_max_body_size 512M;
                client_body_timeout 300s;
                fastcgi_buffers 64 4K;

                # Enable gzip but do not remove ETag headers
                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.geo+json application/vnd.ms-fontobject application/wasm 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;

                # Pagespeed is not supported by Nextcloud, so if your server is built
                # with the `ngx_pagespeed` module, uncomment this line to disable it.
                #pagespeed off;

                # The settings allows you to optimize the HTTP2 bandwidth.
                # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
                # for tuning hints
                client_body_buffer_size 512k;

                # HSTS settings
                # WARNING: Only add the preload option once you read about
                # the consequences in https://hstspreload.org/. This option
                # will add the domain to a hardcoded list that is shipped
                # in all major browsers and getting removed from this list
                # could take several months.
                #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

                # HTTP response headers borrowed from Nextcloud `.htaccess`
                add_header Referrer-Policy                   "no-referrer"       always;
                add_header X-Content-Type-Options            "nosniff"           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;

                # Remove X-Powered-By, which is an information leak
                fastcgi_hide_header X-Powered-By;

                # Specify how to handle directories -- specifying `/nextcloud/index.php$request_uri`
                # here as the fallback means that Nginx always exhibits the desired behaviour
                # when a client requests a path that corresponds to a directory that exists
                # on the server. In particular, if that directory contains an index.php file,
                # that file is correctly served; if it doesn't, then the request is passed to
                # the front-end controller. This consistent behaviour means that we don't need
                # to specify custom rules for certain paths (e.g. images and other assets,
                # `/updater`, `/ocs-provider`), and thus
                # `try_files $uri $uri/ /nextcloud/index.php$request_uri`
                # always provides the desired behaviour.
                index index.php index.html /nextcloud/index.php$request_uri;

                # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
                location = /nextcloud {
                        if ( $http_user_agent ~ ^DavClnt ) {
   return 302 /nextcloud/remote.php/webdav/$is_args$args;
                        }
                }

                # Rules borrowed from `.htaccess` to hide certain paths from clients
                location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)    { return 404; }
                location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console)                  { return 404; }

                # Ensure this block, which passes PHP files to the PHP process, is above the blocks
                # which handle static assets (as seen below). If this block is not declared first,
                # then Nginx will encounter an infinite rewriting loop when it prepends
                # `/nextcloud/index.php` to the URI, resulting in a HTTP 500 error response.
                location ~ \.php(?:$|/) {
                        # Required for legacy support
                        rewrite ^/nextcloud/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /nextcloud/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;         # Avoid sending the security headers twice
                        fastcgi_param front_controller_active true;     # Enable pretty urls
                        fastcgi_pass php-handler;

                        fastcgi_intercept_errors on;
                        fastcgi_request_buffering off;

                        fastcgi_max_temp_file_size 0;
                }

                # Serve static files
                location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
                        try_files $uri /nextcloud/index.php$request_uri;
                        # HTTP response headers borrowed from Nextcloud `.htaccess`
                        add_header Cache-Control                     "public, max-age=15778463$asset_immutable";
                        add_header Referrer-Policy                   "no-referrer"       always;
                        add_header X-Content-Type-Options            "nosniff"           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;
                        access_log off;     # Optional: Don't log access to assets
                }

                location ~ \.(otf|woff2?)$ {
                        try_files $uri /nextcloud/index.php$request_uri;
                        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
                        access_log off;     # Optional: Don't log access to assets
                }

                # Rule borrowed from `.htaccess`
                        location /nextcloud/remote {
                                return 301 /nextcloud/remote.php$request_uri;
                        }

                location /nextcloud {
                        try_files $uri $uri/ /nextcloud/index.php$request_uri;
                }
        }

        # SUPPRESS LOG MESSAGES (nginx section 3)
        location = /data/htaccesstest.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

}
1 Like

I have updated the config as follows and made a major breakthrough! I am able to visit the NC web UI, and am instructed to update “trusted domains” in config.php.

upstream php-handler {
    #server 127.0.0.1:9000;
    server unix:/var/run/php/php8.3-fpm.sock;
}

# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
    "" "";
    default ", immutable";
}

# HTTPS redirect
server {
        listen 80;
        return 301 https://$host$request_uri;

}

server {
        listen 443 ssl default_server;
        http2 on;

        # ------------
        # Web server |
        # ------------

        location /charlie {
                root    /var/www/html;
                index   index.html;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   /var/www/html;
        }

        # -----------
        # Nextcloud |
        # -----------

        # Prevent nginx HTTP Server Detection
        server_tokens off;

        # Path to the root of the domain
        root /var/www;

        # Use Mozilla's guidelines for SSL/TLS settings
        # https://mozilla.github.io/server-side-tls/ssl-config-generator/

        # PROVIDED VIA CODE SNIPPET
        #ssl_certificate     /etc/ssl/nginx/cloud.example.com.crt;
        #ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;

        # Prevent nginx HTTP Server Detection

        # Duplicate? Line 40
        # server_tokens off;

        # Set .mjs and .wasm MIME types
        # Either include it in the default mime.types list
        # and include that list explicitly or add the file extension
        # only for Nextcloud like below:
        include mime.types;
        types {
                text/javascript mjs;
                application/wasm wasm;
         }

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

        location ^~ /.well-known {
                # The rules in this block are an adaptation of the rules
                # in the Nextcloud `.htaccess` that concern `/.well-known`.

                # ENSURE PROPER CONFIG VIA SOURCE LINK 
                location = /.well-known/carddav { return 301 /nextcloud/remote.php/dav/; }
                location = /.well-known/caldav  { return 301 /nextcloud/remote.php/dav/; }

                location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
                location /.well-known/pki-validation    { try_files $uri $uri/ =404; }

                # Let Nextcloud's API for `/.well-known` URIs handle all other
                # requests by passing them to the front-end controller.
                return 301 /nextcloud/index.php$request_uri;
        }

        location ^~ /nextcloud {
                # set max upload size and increase upload timeout:
                client_max_body_size 512M;
                client_body_timeout 300s;
                fastcgi_buffers 64 4K;

                # Enable gzip but do not remove ETag headers
                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.geo+json application/vnd.ms-fontobject application/wasm 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;

                # Pagespeed is not supported by Nextcloud, so if your server is built
                # with the `ngx_pagespeed` module, uncomment this line to disable it.
                #pagespeed off;

                # The settings allows you to optimize the HTTP2 bandwidth.
 # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
                # for tuning hints
                client_body_buffer_size 512k;

                # HSTS settings
                # WARNING: Only add the preload option once you read about
                # the consequences in https://hstspreload.org/. This option
                # will add the domain to a hardcoded list that is shipped
                # in all major browsers and getting removed from this list
                # could take several months.
                #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

                # HTTP response headers borrowed from Nextcloud `.htaccess`
                add_header Referrer-Policy                   "no-referrer"       always;
                add_header X-Content-Type-Options            "nosniff"           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;

                # Remove X-Powered-By, which is an information leak
                fastcgi_hide_header X-Powered-By;

                # Specify how to handle directories -- specifying `/nextcloud/index.php$request_uri`
                # here as the fallback means that Nginx always exhibits the desired behaviour
                # when a client requests a path that corresponds to a directory that exists
                # on the server. In particular, if that directory contains an index.php file,
                # that file is correctly served; if it doesn't, then the request is passed to
                # the front-end controller. This consistent behaviour means that we don't need
                # to specify custom rules for certain paths (e.g. images and other assets,
                # `/updater`, `/ocs-provider`), and thus
                # `try_files $uri $uri/ /nextcloud/index.php$request_uri`
                # always provides the desired behaviour.
                index index.php index.html /nextcloud/index.php$request_uri;
                # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
                location = /nextcloud {
                        if ( $http_user_agent ~ ^DavClnt ) {
                                return 302 /nextcloud/remote.php/webdav/$is_args$args;
                        }
                }

                # Rules borrowed from `.htaccess` to hide certain paths from clients
                location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)    { return 404; }
                location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console)                  { return 404; }

                # Ensure this block, which passes PHP files to the PHP process, is above the blocks
                # which handle static assets (as seen below). If this block is not declared first,
                # then Nginx will encounter an infinite rewriting loop when it prepends
                # `/nextcloud/index.php` to the URI, resulting in a HTTP 500 error response.
                location ~ \.php(?:$|/) {
                        # Required for legacy support
                        rewrite ^/nextcloud/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /nextcloud/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;         # Avoid sending the security headers twice
                        fastcgi_param front_controller_active true;     # Enable pretty urls
                        fastcgi_pass php-handler;

                        fastcgi_intercept_errors on;
                        fastcgi_request_buffering off;

                        fastcgi_max_temp_file_size 0;
                }
                # Serve static files
                location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
                        try_files $uri /nextcloud/index.php$request_uri;
                        # HTTP response headers borrowed from Nextcloud `.htaccess`
                        add_header Cache-Control                     "public, max-age=15778463$asset_immutable";
                        add_header Referrer-Policy                   "no-referrer"       always;
                        add_header X-Content-Type-Options            "nosniff"           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;
                        access_log off;     # Optional: Don't log access to assets
                }

                location ~ \.(otf|woff2?)$ {
                        try_files $uri /nextcloud/index.php$request_uri;
                        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
                        access_log off;     # Optional: Don't log access to assets
                }

                # Rule borrowed from `.htaccess`
                        location /nextcloud/remote {
                                return 301 /nextcloud/remote.php$request_uri;
                        }

                location /nextcloud {
                        try_files $uri $uri/ /nextcloud/index.php$request_uri;
                }
        }

        # SUPPRESS LOG MESSAGES (nginx section 3)
        location = /data/htaccesstest.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

}

1 Like