Landing on NGINX page behind several NGINX proxies

Version invoiceninja/invoiceninja:5

Environment Docker/Portainer Stack

Checklist

  • Can you replicate the issue on our v5 demo site or Invoice Ninja?
    Not really applicable, I’m struggling to get the invoice application working at all, my best attempt to so far seems functional, but unreachable.
  • Have you searched existing issues? I’ve looked through the forum and github issues, there are too many stacks / configurations to make sense of.
  • Have you inspected the logs in storage/logs/laravel.log for any errors? I struggled for a bit with the debian dockerfiles. I found a forum post ( IP and Host for a VPS Server with Domain and Reverse Proxy -- 8003 -- Logo not showing - #5 by nico.zaglmayr ) which with a bit of editing got me to at least the point where the containers launched from the stack are no longer in a boot-loop and the application appears to have connected with the database. The app appears functional from the logs. All that remains is reaching the app?

Describe the bug

The stack appears to be running on portainer, but when visiting the desired APP_URL we’re confronted with the “Welcome to nginx!” screen. Which seems to indicate that the nginx server may not be configured. The main issue here is my home server configuration is already a confusing nginx mess. I have an nginx reverse to even reach portainer, an nginx proxy manager instance in portainer which is how I’ve been adding servers to the home subdomain, and now seemingly from what I’ve read from the forum/instructions online, nginx or caddy typically gets included in order to work with this app. There are too many reverse proxies.

Steps To Reproduce

services:
  server:
    image: nginx
    container_name: invoiceninja_server
    restart: always
    volumes:
      - app-public:/var/www/app/public:ro
    depends_on:
      - app
    ports:
      - '9030:80'
    networks:
      - invoiceninja
      - portainer_network
    extra_hosts:
      - 'in5.localhost:192.168.1.230'
      - 'in.localhost:192.168.1.230'
      - 'invoice.home:192.168.1.230'
      - 'invoicedb.home:192.168.1.230'

  app:
    image: invoiceninja/invoiceninja:5
    container_name: invoiceninja_app
    restart: always
    volumes:
      - app-public:/var/www/app/public:rw,delegated
      - app-storage:/var/www/app/storage:rw,delegated
    environment:
      - APP_URL=http://invoice.home
      - APP_KEY=base64:<your-key-here>
      - APP_DEBUG=false
      - REQUIRE_HTTPS=false
      - PHANTOMJS_PDF_GENERATION=false
      - PDF_GENERATOR=snappdf
      - TRUSTED_PROXIES='*'
      - DB_HOST=db
      - DB_PORT=3306
      - DB_DATABASE=ninja
      - DB_USERNAME=ninja
      - DB_PASSWORD=ninja
    depends_on:
      - db
    networks:
      - invoiceninja
      - portainer_network
    extra_hosts:
      - 'in5.localhost:192.168.1.230'
      - 'in.localhost:192.168.1.230'
      - 'invoice.home:192.168.1.230'
      - 'invoicedb.home:192.168.1.230'
    ports:
      - '9028:3000'

  db:
    image: mysql:8
    container_name: invoiceninja_db
    ports:
      - '3310:3306'
    restart: always
    volumes:
      - mysql-data:/var/lib/mysql:rw,delegated
    environment:
      - MYSQL_ROOT_PASSWORD=ninjaAdm1nPassword
      - MYSQL_USER=ninja
      - MYSQL_PASSWORD=ninja
      - MYSQL_DATABASE=ninja
    networks:
      - invoiceninja
      - portainer_network
    extra_hosts:
      - 'in5.localhost:192.168.1.230'
      - 'in.localhost:192.168.1.230'
      - 'invoice.home:192.168.1.230'
      - 'invoicedb.home:192.168.1.230'

networks:
  invoiceninja:
    driver: bridge
  portainer_network:
    external: true

volumes:
  mysql-data:
  app-public:
  app-storage:

Expected Behavior

I should land on the invoice ninja app.

Additional context

Note: The original example had a bug where it tried reaching the database on 3310, fixed it by using 3306, I’m editing the post due to weird formatting, thought the forum might use markdown, it did not. portainer_network is the network which reaches the external nginx proxy manager which lets me add domains like invoice.home.

Screenshots

Logs

Hi,

Maybe this AI answer will help:

The reason you are seeing the “Welcome to nginx!” screen is that the server service is running the default nginx Docker image, which serves a generic welcome page unless you override its configuration.

To serve Invoice Ninja, NGINX needs a specific configuration file instructing it to look in /var/www/app/public and route PHP requests to your app container (which runs PHP-FPM on port 9000).

Here is how to fix your Portainer stack.

1. Create the NGINX Configuration File

You need to provide NGINX with the Invoice Ninja virtual host config. In the directory where your Portainer stack/volumes reside (or via Portainer’s config feature), create a file named in-vhost.conf with the following contents:

Nginx

server {
    listen 80 default_server;
    server_name _;

    server_tokens off;
    root /var/www/app/public;
    index index.php;

    client_max_body_size 100M;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
    }
}

2. Update Your Docker Compose File

Update your server service to mount the new configuration file into NGINX. You can also clean up a lot of the unnecessary networking and port mapping that is confusing the deployment.

Here is the corrected setup for your use case:

YAML

services:
  server:
    image: nginx
    container_name: invoiceninja_server
    restart: always
    volumes:
      # Mount the nginx config you created above
      - /path/to/your/in-vhost.conf:/etc/nginx/conf.d/default.conf:ro
      - app-public:/var/www/app/public:ro
    depends_on:
      - app
    ports:
      - '9030:80' # Point your NGINX Proxy Manager to port 9030
    networks:
      - invoiceninja
      - portainer_network

  app:
    image: invoiceninja/invoiceninja:5
    container_name: invoiceninja_app
    restart: always
    volumes:
      - app-public:/var/www/app/public:rw,delegated
      - app-storage:/var/www/app/storage:rw,delegated
    environment:
      - APP_URL=http://invoice.home
      - APP_KEY=base64: # Make sure to generate a real base64 key here
      - APP_DEBUG=false
      - REQUIRE_HTTPS=false
      - PHANTOMJS_PDF_GENERATION=false
      - PDF_GENERATOR=snappdf
      - TRUSTED_PROXIES=*
      - DB_HOST=db
      - DB_PORT=3306 
      - DB_DATABASE=ninja
      - DB_USERNAME=ninja
      - DB_PASSWORD=ninja
    depends_on:
      - db
    networks:
      - invoiceninja

  db:
    image: mysql:8
    container_name: invoiceninja_db
    restart: always
    ports:
      - '3310:3306'
    volumes:
      - mysql-data:/var/lib/mysql:rw,delegated
    environment:
      - MYSQL_ROOT_PASSWORD=ninjaAdm1nPassword
      - MYSQL_USER=ninja
      - MYSQL_PASSWORD=ninja
      - MYSQL_DATABASE=ninja
    networks:
      - invoiceninja

networks:
  invoiceninja:
    driver: bridge
  portainer_network:
    external: true

volumes:
  mysql-data:
  app-public:
  app-storage:

Key Corrections Explained

  • The App Port: You do not need to expose port 3000 or any external port on the app container. The app container is just a PHP processor (PHP-FPM) listening internally on port 9000. Your new nginx configuration (fastcgi_pass app:9000;) tells the web server how to talk to it internally over the invoiceninja bridge network.

  • Extra Hosts: I removed the extra_hosts mappings. They are completely unnecessary for your configuration. Docker’s internal DNS handles the server talking to app and app talking to db. Your external NGINX Proxy Manager handles routing invoice.home to your host machine’s IP on port 9030.

  • Portainer Integration: Ensure NGINX Proxy Manager is routing traffic for invoice.home to [YOUR_HOST_IP]:9030.