nextcloud / server

☁️ Nextcloud server, a safe home for all your data
https://nextcloud.com
GNU Affero General Public License v3.0
27.43k stars 4.08k forks source link

provide a Nginx V-Host File in the root Directory of a Nextcloud Installation like a .htaccess File #27083

Closed ghost closed 3 years ago

ghost commented 3 years ago

How to use GitHub

provide a Nginx V-Host File in the root Directory of a Nextcloud Installation like a .htaccess File

With each update, the V-Host configuration in the Nextcloud documentation changes. As you can see here when you compare the two docs. there have been minor changes that can be seen here. For example the .well-known location. https://docs.nextcloud.com/server/latest/admin_manual/installation/nginx.html https://docs.nextcloud.com/server/stable/admin_manual/installation/nginx.html

Unlike the Apache web server, where you have the .htaccess file, which is included as standard with every Nextcloud installation and can also be updated via a normal Nextcloud update, Nginx does not have this option. However, the problem can be solved by adding a .nginx-config file to every Nextcloud installation.

An implementation could look like this:

1: your regular V-Host File /etc/nginx/sites-enabled/nextcloud.conf could look like this:

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

server {
    listen 80;
    listen [::]:80;
    server_name cloud.example.com;

    # Enforce HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443      ssl http2;
    listen [::]:443 ssl http2;
    server_name cloud.example.com;

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

    # 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=15768000; includeSubDomains; preload;" always;

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # 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;

    # Path to the root of your installation
    root /var/www/nextcloud;

    # Path to the Nginx-Config File
    include /var/www/nextcloud/.nginx-config;

}

As you can see, the Nextcloud related configurations were removed from this config file. The Nextcloud-related configurations are located in the new .nginx-config file. A new include statement has been added at the end. This statement refers to the new .nginx-config file that would be added to the root directory of your Nextcloud installation.

2: the additional Nextcloud provided V-Host File /var/www/nextcloud/.nginx-config could look like this:

    # 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 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;

    # 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-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;

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

    # Specify how to handle directories -- specifying `/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`, `/ocm-provider`, `/ocs-provider`), and thus
    # `try_files $uri $uri/ /index.php$request_uri`
    # always provides the desired behaviour.
    index index.php index.html /index.php$request_uri;

    # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
    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;
    }

    # Make a regex exception for `/.well-known` so that clients can still
    # access it despite the existence of the regex rule
    # `location ~ /(\.|autotest|...)` which would otherwise handle requests
    # for `/.well-known`.
    location ^~ /.well-known {
        # The rules in this block are an adaptation of the rules
        # in `.htaccess` that concern `/.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; }

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

    # Rules borrowed from `.htaccess` to hide certain paths from clients
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|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 `/index.php`
    # to the URI, resulting in a HTTP 500 error response.
    location ~ \.php(?:$|/) {
        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;
    }

    location ~ \.(?:css|js|svg|gif)$ {
        try_files $uri /index.php$request_uri;
        expires 6M;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    location ~ \.woff2?$ {
        try_files $uri /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 /remote {
        return 301 /remote.php$request_uri;
    }

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

The advantage of this implementation is that the Nginx configuration is always up to date, similar to an Apache web server. Since the .nginx-config file can be updated like the .htaaccess file.

to load the new configuration after an update might have to reload/restart Nginx because the configuration is only read once when the webserver is started. Here you could use a daemon/watchdog to automatically reload/restart nginx after an update as mentioned here. https://github.com/nextcloud/notify_push/pull/48

so and why do you need it now? 1: to give beginners an easy way to use a secure web server configuration. Not every change in the dokumentation can be recognized as such at first glance and changes are nowhere mentioned clearly enough. 2: to fix security misconfigurations. https://nextcloud.com/blog/urgent-security-issue-in-nginx-php-fpm/ 3: Convenience for a significant proportion of Nextcloud users who usually get by with the standard configuration. 4: less or no manual web server configuration changes are necessary anymore because they are applied to a large extent after a Nextcloud update with the .nginx-config file.

go2sh commented 3 years ago

I think this would imply a great security risk as the include directive of ngnix is not bound to any particular commands like .htaccess is. You basically create a server config file, which can be changed by the user running the nextcloud php process. As an admin, I would not allow this.

solracsf commented 3 years ago

Please note; nginx is NOT officially supported by Nextcloud. Only Apache is officially supported, nginx is only community maintained.

tabp0le commented 3 years ago

I agree, this would be a potential security risk. If that were used on say shared hosting, a user could crash the entire server by entering something incorrectly. Nginx configs, unlike apache, must be modified ONLY by server administrators and should never be available to users.

ghost commented 3 years ago

if it really weakens security, of course, it should not be done in this way. Perhaps someone might have another Idea to make it easier.