Using NGINX On Docker Containers Results In Missing Page Elements

Having a small issue with some page assets not showing up after trying to get Nextcloud working through NGINX.

Was previously testing on NC 14, but NC 15 is also showing the exact same issue:


Nextcloud2

docker-compose.yml:

version: '2'

services:
  nextcloud:
    image: nextcloud:fpm-alpine
    dns: # Using Cloudflare DNS
      - 1.1.1.1
      - 1.0.0.1
    environment:
      MYSQL_HOST: mysql
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud_user
      MYSQL_PASSWORD: ${DB_USER_PASS}
      NEXTCLOUD_ADMIN_USER: ${NC_ADMIN}
      NEXTCLOUD_ADMIN_PASSWORD: ${NC_ADMIN_PASS}
    expose:
      - "80"
      - "9000"
    labels:
      io.rancher.container.pull_image: always
      {{- if .Values.HOST_LABEL}}
      io.rancher.scheduler.affinity:host_label: ${HOST_LABEL}
      {{- end}}
    networks:
      - public-proxy
    restart: on-failure
    volumes_from:
      - nginx
  nginx:
    image: nginx:latest # Can't use ":alpine" until I have a way to get the "www-data" user added automatically. (Project for another time)
    dns: # Using Cloudflare DNS
      - 1.1.1.1
      - 1.0.0.1
    labels:
      io.rancher.container.pull_image: always
      {{- if .Values.HOST_LABEL}}
      io.rancher.scheduler.affinity:host_label: ${HOST_LABEL}
      {{- end}}
      io.rancher.sidekicks: nextcloud
      {{- if .Values.TRAEFIK_HOST}}
      traefik.enable: true
      ### Start Web Segment
      traefik.frontend.entryPoints: http,https
      traefik.frontend.headers.forceSTSHeader: true
      traefik.frontend.headers.referrerPolicy: no-referrer # Security enhancement (Prevents leaking of referer information)
      traefik.frontend.headers.SSLRedirect: true
      traefik.frontend.headers.STSPreload: true
      traefik.frontend.headers.STSSeconds: 15552000
      traefik.frontend.rule: Host:${TRAEFIK_HOST}
      traefik.port: "80"
      ### End Web Segment
      {{- else}}
      traefik.enable: false
      {{- end}}
    links:
      - mysql
      - nextcloud
      {{- if eq .Values.REDIS "true"}}
      - redis
      {{- end}}
    networks:
      - public-proxy
    {{- if .Values.WEB_PORT}}
    ports:
      - "${WEB_PORT}:80"
    {{- end}}
    restart: on-failure
    volumes:
      - /etc/localtime:/etc/localtime:ro # Syncronize time of container with the host system
      - /etc/timezone:/etc/timezone:ro # Syncronize timezone of container with the host system
      - /RancherCattle/${DATA_DIR}/Configuration/Nextcloud:/var/www/html/config # Nextcloud configuration files
      - /RancherCattle/${DATA_DIR}/Configuration/NGINX:/etc/nginx # NGINX configuration files
      - /RancherCattle/${DATA_DIR}/Apps:/var/www/html/custom_apps # Nextcloud apps
      - /RancherCattle/${DATA_DIR}/Nextcloud:/var/www/html # Nextcloud site
      - /RancherCattle/${DATA_DIR}/UserData:/var/www/html/data # Users' data file
  mysql:
    image: mysql:5
    dns: # Using Cloudflare DNS
      - 1.1.1.1
      - 1.0.0.1
    environment:
      MYSQL_DATABASE: nextcloud # Will rename this to "nextcloud_db" in the future.
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
      MYSQL_USER: nextcloud_user
      MYSQL_PASSWORD: ${DB_USER_PASS}
    labels:
      io.rancher.container.pull_image: always
      {{- if .Values.HOST_LABEL}}
      io.rancher.scheduler.affinity:host_label: ${HOST_LABEL}
      {{- end}}
    networks:
      db-admin:
        aliases:
          - nextcloud # This should allow access from "mysql.nextcloud.rancher.internal"
    restart: on-failure
    volumes:
      - /etc/localtime:/etc/localtime:ro # Syncronize time of container with the host system
      - /etc/timezone:/etc/timezone:ro # Syncronize timezone of container with the host system
      - /RancherCattle/${DATA_DIR}/Database:/var/lib/mysql
  {{- if eq .Values.REDIS "true"}}
  redis:
    image: redis:latest
    dns: # Using Cloudflare DNS
      - 1.1.1.1
      - 1.0.0.1
    labels:
      {{- if .Values.HOST_LABEL}}
      io.rancher.scheduler.affinity:host_label: ${HOST_LABEL}
      {{- end}}
    restart: on-failure
    volumes:
      - /etc/localtime:/etc/localtime:ro # Syncronize time of container with the host system
      - /etc/timezone:/etc/timezone:ro # Syncronize timezone of container with the host system
  {{- end}}

networks:
  db-admin: 
    external: true # Created by phpMyAdmin stack
  public-proxy:
    external: true # Created by Traefik stack

nginx.conf:

user       www-data;
worker_processes  4;  ## Default: 1
# worker_rlimit_nofile 8192;

#error_log  /var/log/nginx/error.log warn;
#pid        /var/run/nginx.pid;

events {
    worker_connections  1024;  ## Default: 1024
}

http {
    include    /etc/nginx/mime.types;
    default_type application/octet-stream;
    #access_log  /var/log/nginx/access.log  main;
    sendfile     on;
    tcp_nopush   on;
    #keepalive_timeout  65;
  
    upstream php-handler {
        server nextcloud:9000;
    }

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

        # Add headers to serve security related headers
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        add_header Referrer-Policy no-referrer;

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

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

        # Will test later
        #error_page 403 /core/templates/403.php;
        #error_page 404 /core/templates/404.php;

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

        location = /.well-known/carddav {
            return 301 $scheme://$host/remote.php/dav;
        }

        location = /.well-known/caldav {
            return 301 $scheme://$host/remote.php/dav;
        }

        # set max upload size
        client_max_body_size 1G;
        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 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;

        location / {
            rewrite ^ /index.php$request_uri;
        }

        location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
            deny all;
        }

        location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
            deny all;
        }

        location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;
            # Mitigate https://httpoxy.org/ vulnerabilities:
            fastcgi_param HTTP_PROXY "";
            #fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            #Avoid sending the security headers twice
            fastcgi_param modHeadersAvailable true;
            fastcgi_param front_controller_active true;
            fastcgi_pass php-handler;
            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;
        }

        location ~ ^/(?:updater|ocs-provider)(?:$|/) {
            try_files $uri/ =404;
            index index.php;
        }

        # Adding the cache control header for js and css files
        # Make sure it is BELOW the PHP block
        location ~ \.(?:css|js|woff2?|svg|gif)$ {
            try_files $uri /index.php$request_uri;
            add_header Cache-Control "public, max-age=15778463";
            add_header X-Content-Type-Options nosniff;
            add_header X-XSS-Protection "1; mode=block";
            add_header X-Robots-Tag none;
            add_header X-Download-Options noopen;
            add_header X-Permitted-Cross-Domain-Policies none;
            add_header Referrer-Policy no-referrer;

            # Optional: Don't log access to assets
            access_log off;
        }

        location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
            try_files $uri /index.php$request_uri;
            # Optional: Don't log access to other assets
            access_log off;
        }
    }
}

I assume it’s an issue with my NGINX configuration, but I’m not yet adept enough with it to figure it out.

Any help is greatly appreciated!
Thank you!

Hello !
I’ve got exactly the same problem with 2 nextcloud instances on 2 differents Nginx servers with php-fpm ; one on a Raspberry and the other virtualised on an ESX… I don’t think this issue is lied with docker container and I just can’t find any solution to fix it.
According to me, it could be a php configuration mistake or worst, a nginx configuration one…

Just to “up” your discussion… Because I would have been interresting in what the other could answer you…
Best regards

1 Like

My problem was related to a bad configuration of fail2ban which stopped php requests before their resolutions.
Nextcloud now just work well !