Setup with docker: nexctloud:fpm, nginx results in php-fpm returning 404

Hi,

I have a fresh nextcloud installation. My setup is using the nextcloud:fpm docker image with a nginx in front and a mariadb as a backend.

When I try to open https://my-domain.com I get a 404 Not Found.

When I look into the logs of the nextcloud container, I see:

172.16.238.10 -  16/Nov/2020:14:20:29 +0000 "GET /index.php" 404

What could be wrong? Or, how can I get a better debug output from php-fpm?

My setup:

docker-compose.yml:

version: '3.3'
services:
  nginx:
    image: nginx:stable
    ports:
      - "80:80"
      - "443:443"
      - "7443:7443"
    volumes:
      - /etc/nginx/conf.d:/etc/nginx/conf.d
      - /etc/nginx/sites-enabled:/etc/nginx/sites-enabled
      - /etc/nginx/sites-available:/etc/nginx/sites-available
      - nextcloud:/var/www/html/nextcloud
    networks:
      nginx:
        ipv4_address: "172.16.238.10"
  mariadb:
    container_name: mariadb
    image: mariadb
    restart: always
    environment:
        MYSQL_RANDOM_ROOT_PASSWORD: "yes"
    volumes:
    - mariadb:/var/lib/mysql
    networks:
    - nginx
  nextcloud:
    container_name: nextcloud
    image: nextcloud
    volumes:
    - nextcloud:/var/www/html
    networks:
      nginx:
        ipv4_address: "172.16.238.12"
    environment:
      MYSQL_DATABASE: hgbutze_nextcloud
      MYSQL_USER: "hgbutze"
      MYSQL_PASSWORD: "<I will not tell you>"
      MYSQL_HOST: mariadb
    depends_on:
    - mariadb
networks:
  nginx:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: "172.16.238.0/24"
volumes:
  mariadb:
      external: true
  nextcloud:
      external: true

My nextcloud-site config for nginx:

upstream php-handler {
    server nextcloud:9000;
}

server {
    listen 443 ssl http2;
    #listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80 default_server ipv6only=on; ## listen for ipv6

    # Make site accessible from http://localhost/
    server_name <my-nextcloud-domain>;

    # Certificates used
    ssl_certificate /etc/letsencrypt/live/<my-nextcloud-domain>/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/<my-nextcloud-domain>/privkey.pem; # managed by Certbot

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    # set_real_ip_from  10.0.0.0/8;
    # set_real_ip_from  172.16.0.0/12;
    # set_real_ip_from  192.168.0.0/16;
    # real_ip_header    X-Real-IP;

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
    #
    # 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 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;

    root /var/www/html/nextcloud;

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

    # The following 2 rules are only needed for the user_webfinger app.
    # Uncomment it if you're planning to use this app.
    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;

    # The following rule is only needed for the Social app.
    # Uncomment it if you're planning to use this app.
    #rewrite ^/.well-known/webfinger /public.php?service=webfinger last;

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

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

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

    # Uncomment if your server is build with the ngx_pagespeed module
    # This module is currently not supported.
    #pagespeed off;

    location / {
        rewrite ^ /index.php;
    }

    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\/.+|oc[ms]-provider\/.+)\.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;

        # Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;

        # Enable pretty urls
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
        try_files $uri/ =404;
        index index.php;
    }

    # Adding the cache control header for js, css and map files
    # Make sure it is BELOW the PHP block
    location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
        try_files $uri /index.php$request_uri;
        add_header Cache-Control "public, max-age=15778463";
        # Add headers to serve security related headers (It is intended to
        # have those duplicated to the ones above)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
        #
        # 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 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;

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

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

    location /.well-known {
	    alias /var/www/certbot/.well-known;
   }
}

So what could be wrong or how can I debug further?

I’m having this exact same issue currently… Did you ever resolve it?

I’m getting the same scenario but my setup is a bit different, I have an NGinX Container running as web server on the Docker Host Server, and a NextCloud FPM container, they both share a volume named www that is linked to /usr/share/nginx/html for the NGinX container and /var/www/html for the NextCloud FPM Container.

Almost same exact nginx.conf file you have (from the github repo of the official nextcloud docker page), except for the root I’m pointing to the location on the NGinX container (/usr/share/ngxin/html) and I get a 404 error on the logs of both containers:

NextCloud

172.19.0.5 -  07/Mar/2023:16:03:47 +0000 "GET /index.php" 404

NGinX

72.69.67.104 - - [07/Mar/2023:16:03:47 +0000] "GET /index.php HTTP/1.1" 404 47 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" "2603:3020:1818:ac00:b851:91bc:e330:27b4"

Hi, same issue here but with apache as a proxy. I get 404 for all queries (even the non static ones) in the fpm log
I don’t understand what can be wrong…

This can happen if you are using two different roots, eg. /var/www/html for the webserver and /var/www/nextcloud in the FPM container.

I adjusted the fastcgi parameter SCRIPT_FILENAME in my nginx config from

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

to

fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;

and it worked.
Thx to Caddy reverse proxy index.php 404 · Issue #737 · nextcloud/docker · GitHub

1 Like