Restrict access to invoiceninja backend

Hi,

We’re hardening our self hosted invoice ninja instance. By exposing on internet only the relevant services :

  • From internet : payement link , client portal
  • From our office : backend

It seems like all the backend api endpoints are under : /api

So basically its just adding a new location directive to protect /api ;
One issue we found, is that because “rewrite” takes precedence on “location” that doesn’t work.
So we moved the rewrite from the block’s root to the “location /” directive.

Do you see any reasons to keep the rewrite in the root ?

[...]

   # Restrict access to /api for private network only
   location /api {
    allow OFFICE_IP_RANGE;
    deny all;  # Deny all other access
   }

# Force redirect  / to client portal
   location = / {
   	return 301 /client/login;
   }

   location / {
   	# This condition moved from root to here ("rewrite" precedence on "location" directives)
	if (!-e $request_filename) {
		rewrite ^(.+)$ /index.php?q= last;
	}

[...]

Hi,

@david can you please advise?

:eyes: watching this thread

This worked for me (using docker)

server {
    listen 80 default_server;
    server_name _;   
    root /var/www/html/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;
 
    charset utf-8;

    set_real_ip_from 172.22.0.0/16;     # Your Docker bridge network
    real_ip_header X-Real-IP;     # Trust this header
    real_ip_recursive on;               # Use last non-trusted IP

    # Restrict access to /api for private network only
    location ^~ /api {
        allow 172.22.0.0/16; # Allow bridge-network access
        allow 192.168.1.0/22;  # Allow local network access
        deny all;  # Deny all other access

        try_files $uri $uri/ /index.php?$query_string;
    }
 
    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; }
 
    error_page 404 /index.php;

    # Public access to index.php (used by Laravel) e.g. /client/.../...
    location = /index.php {
        fastcgi_pass invoice-ninja-api-1:9000;
        include fastcgi.conf;
    }

    location ~ \.php$ {
        allow 172.22.0.0/16;  # Allow Docker bridge access
        allow 192.168.1.0/22;  # Allow local network access
        deny all;

        fastcgi_pass invoice-ninja-api-1:9000;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
1 Like