URL Navigation with the React front end

Continuing the discussion from Links to invoices:

I can’t seem to get this working with the selfhosted version, been at it for a while now but no dice.

Spun up a invoiceninja VPS from the marketplace at digitalocean to try it out but it didn’t work there. Tried a manual install from scratch on a LEMP stack on Ubuntu (followed the guide linked in the docs) but also couldn’t get it working.

Here’s the nginx server block:

server {
   listen       443 ssl http2 default_server;
   listen       [::]:443 ssl http2 default_server;
   server_name  mydomain.com;
   client_max_body_size 20M;

   root         /var/www/ninja/public;

   gzip on;
   gzip_types application/javascript application/x-javascript text/javascript text/plain application/xml application/json;
   gzip_proxied    no-cache no-store private expired auth;
   gzip_min_length 1000;

   index index.php index.html index.htm;

   ssl_certificate "/etc/letsencrypt/live/mydomain.com/fullchain.pem";
   ssl_certificate_key "/etc/letsencrypt/live/mydomain.com/privkey.pem";
         ssl_session_timeout  10m;

   charset utf-8;

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

   if (!-e $request_filename) {
           rewrite ^(.+)$ /index.php?q= last;
   }

   location ~ \.php$ {
           fastcgi_split_path_info ^(.+\.php)(/.+)$;
           fastcgi_pass unix:/run/php/php8.1-fpm.sock;
           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;
   }

   location ~ /\.ht {
       deny all;
   }

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

   access_log /var/log/nginx/ininja.access.log;
   error_log /var/log/nginx/ininja.error.log;

   sendfile off;

  }

  server {
      listen      80;
      server_name mydomain.com;
      add_header Strict-Transport-Security max-age=2592000;
      rewrite ^ https://$server_name$request_uri? permanent;
  }

Looking at the demo online at react.invoicing.co it works great, just want to confirm URL navigation is also possible with the selfhosted install as well?

Coming from a v4 install I have had for many years and URLs are a massive part of my workflow, hope I can get it working.

I appreciate any help!

Hi,

@david do you have any suggestions?

@hars76

Are you using the release invoiceninja.zip file to install?

This contains the react app built. I think the other methods you have mentioned, do not come bundled with the React app.

Yep, installed with the release zip. The react front end is up and running, I just can’t refresh the page or navigate directly to any url other than the root url.

What makes it a bit tricky to troubleshoot is the lack of any log entries in the error logs. Even with EXPANDED_LOGGING=true in the .env, storage/laravel.log doesn’t have any entries when hitting the 404.

Nothing of note in /var/log/php8.1-fpm.log or /var/log/nginx/ininja.error.log

The only thing I can see of note is the 404 in /var/log/nginx/ininja.access.log

If I navigate to an invoice and hit refresh (or copy URL and paste into new tab):

my.ip.add.ress - - [03/Apr/2023:15:13:44 +0800] "GET /invoices/wMvbmOeYAl/edit HTTP/2.0" 404 2035 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:15:13:45 +0800] "GET /js/app.js?id=5524b72f53decd8646cccb755463a439 HTTP/2.0" 200 11866 "https://mydomain.com/invoices/wMvbmOeYAl/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:15:13:45 +0800] "GET /vendor/alpinejs@2.8.2/alpine.js HTTP/2.0" 200 23136 "https://mydomain.com/invoices/wMvbmOeYAl/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:15:13:45 +0800] "GET /css/app.css?id=11b2fe68fd0b620e451e1b2a3296bdf1 HTTP/2.0" 200 45634 "https://mydomain.com/invoices/wMvbmOeYAl/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:15:13:45 +0800] "GET /vendor/cookieconsent@3/cookieconsent.min.css HTTP/2.0" 200 4958 "https://mydomain.com/invoices/wMvbmOeYAl/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:15:13:45 +0800] "GET /vendor/livewire/livewire.js?id=90730a3b0e7144480175 HTTP/2.0" 200 54356 "https://mydomain.com/invoices/wMvbmOeYAl/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:15:13:45 +0800] "GET /vendor/cookieconsent@3/cookieconsent.min.js HTTP/2.0" 200 7590 "https://mydomain.com/invoices/wMvbmOeYAl/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:15:13:45 +0800] "GET /css/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0B4gaVI.woff2 HTTP/2.0" 200 16740 "https://mydomain.com/invoices/wMvbmOeYAl/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:15:13:45 +0800] "GET /images/client-portal-new-image.jpg HTTP/2.0" 200 637229 "https://mydomain.com/invoices/wMvbmOeYAl/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"

Tried:

  1. Different browsers (Brave, Orion, Safari) and clearing caches/history.

  2. Different DNS servers (1.1.1.1, 9.9.9.9)

  3. Disabling/Enabling cloudflare proxying

  4. php artisan optimize

  5. php artisan ninja:check-data → SUCCESS

  6. php artisan cache:clear && php artisan config:cache

  7. try_files $uri $uri/ /index.php?$query_string /index.php;

  8. sudo chown -R www-data:www-data /var/www/ninja

  9. sudo find /var/www/ninja -type d -exec chmod 755 {} \;

  10. Just to test and rule out permissions: sudo chmod 777 *


I don’t know if this is a lead or not but I have a home server and installed invoiceninja with docker-compose as an additional test.

Refreshing the page and going to a URL works with a docker install. 2 differences:

  1. It’s on my local network so no SSL

  2. There is a # in the URL eg: http://homeserver.lan/#/invoices/Opnel5aKBz/edit

When viewing an invoice and refreshing the page, I see a get request to / in the nginx container logs:

"GET / HTTP/1.1" 200 17177 "-"

If I try adding a # to the url on the VPS install (eg:

https://vpsinstall.com/#/invoices/KGRb41dBLZ/edit

I get redirected to the dashboard, I don’t get a 404.

The /#/ is not present on your react demo so I’m not sure it’s relevent.


As per this issue: URLs are broken in production environments · Issue #199 · invoiceninja/ui · GitHub

Does your react demo build include the index.html file with nginx pointing to that instead of the .php?

Noticed you have 2 separate demo installs with no button to switch so I’m guessing there’s some differences in setup.

Sorry for the novel length post, just trying to remember everything I’ve tried so far, it’s been quite a few hours of troubleshooting. :slight_smile:

@hars76

Can you try using this nginx configuration and see if it helps:

server {

   listen 8000;
   server_name inrelease.test;
   root /path/to/your/public/folder/inrelease/public;
   index index.php index.html index.htm;
   
   client_max_body_size 100M;

   location / {
       try_files $uri $uri/ =404;

   }
   if (!-e $request_filename) {
       rewrite ^(.+)$ /index.php?q=$1 last;

   }
   location ~* /logo/.*\.php$ {
       return 503;

   }

   location ~ \.php$ {
   include snippets/fastcgi-php.conf;
   fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }

   location ~ /\.ht {
       deny all;

   }
}

I use this config in my dev environment to test the react build and it is behaving correctly for me, this will at least exclude the configuration from being the issue.

The prebuilt LEMP droplet I spun up at DO was using Ubuntu 22.04 so just in case, I destroyed it and spun up a base Ubuntu 20.04 one with no software and installed php8.1, nginx, mariadb from scratch. Same problem unfortunately.

I used your nginx config as-is only editing these 2 lines:

   server_name mydomain.com;
   root /var/www/ninja/public;

Setup DB:

create database ninja;
create user 'ninja'@'localhost' identified by 'ninja';
grant all privileges on ninja.* to 'ninja'@'localhost';
flush privileges;
exit

Downloaded the release:

sudo mkdir -p /var/www/ninja && cd /var/www/ninja
wget https://github.com/invoiceninja/invoiceninja/releases/download/v5.5.102/invoiceninja.zip
unzip invoiceninja.zip
sudo chown -R www-data:www-data /var/www/ninja
sudo find ./ -type d -exec chmod 755 {} \;
sudo mv .env.example .env

Changed these two lines in the .env:

APP_URL="http://mydomain.com:8000"
REQUIRE_HTTPS="false"

Restarted nginx & php, went to http://mydomain.com:8000/setup

Set domain to http://, unchecked require https and got into the flutter front end.

Changed to the react front-end, created a client & invoice. Hit refresh and got the same 404 in the nginx access log:

my.ip.add.ress - - [03/Apr/2023:12:01:52 +0000] "GET /invoices/k8mep2bMyJ/edit HTTP/1.1" 404 2041 "http://mydomain.com:8000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:12:01:52 +0000] "GET /js/app.js?id=5524b72f53decd8646cccb755463a439 HTTP/1.1" 200 30771 "http://mydomain.com:8000/invoices/k8mep2bMyJ/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:12:01:52 +0000] "GET /css/app.css?id=11b2fe68fd0b620e451e1b2a3296bdf1 HTTP/1.1" 200 45634 "http://mydomain.com:8000/invoices/k8mep2bMyJ/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:12:01:52 +0000] "GET /vendor/livewire/livewire.js?id=90730a3b0e7144480175 HTTP/1.1" 200 174819 "http://mydomain.com:8000/invoices/k8mep2bMyJ/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"
my.ip.add.ress - - [03/Apr/2023:12:01:53 +0000] "GET /images/client-portal-new-image.jpg HTTP/1.1" 200 637229 "http://mydomain.com:8000/invoices/k8mep2bMyJ/edit" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15"

Tried the various artisan commands as well but same deal unfortunately.

From looking around this is an issue a few people have had but is a tricky one to nail down. Please let me know if you think of anything else I can try. I appreciate your help!

I’m puzzled on this. Especially if you are using the exact some nginx configuration.

Are you able to DM me the URL to this installation?

You have mail. Thanks again!

Hi,

I do experiment the same issue, but a different server config (selfhost on shared hosting on Siteground)
Everytime I do refresh a page, I get a 404 error on React UI.

I have also noticed that the /# is not following from page to page in the URL, but can’t find on my end where this change is coming from
And not sure if it’s related, but everytime I update IN, PHP version is crashing and downgraded automatically to 7.4 on server. I do have to manually set PHP version back to 8 to continue the update process.

Thanks for your support

@alexgauvin

I have a solution for this checked in, available in the next release :slight_smile:

1 Like

Nice one cheers David!

Thanks @david,

Most recent update seems to have address the trailing /#/. Thanks for that. The React UI is now usable.

My issue with automatic downgrading to PHP 7.4 after every update is not resolved. Any clue of the cause of that ?

Thanks for your support

@alexgauvin

What action do you need to take after the PHP version is downgraded? I’m not sure how the PHP version could downgrade if you are using NGINX as the php path is defined in there?

@david, thanks for your reply.

My Invoice Ninja is installed on a Siteground shared hosting.
IN v5 is set on a subdomain of my main domain and I also have v4 installed and running on another subdomain of the same main domain.
v5 is set to run on PHP 8.1.17
v4 is set on PHP 7.4.33, because it cannot run under PHP 8
Main domain is set to run on PHP 8

Everytime I do a Force update on v5 (running on PHP8), it generates a fatal error (see below) and it then downgrades automatically to PHP 7.4 on the server.
In order to continue with the update process, I need to go in Siteground’s PHP manager and change the PHP version back to 8.1 and refresh the page.
I did try to set PHP version to 8.2.4, same error.
I did reach Siteground’s support about that and they think the problem is on the app’s side.

I must admit I am not a server specialist

Here is the Fatal error generated each time I try to update IN v5

Fatal error : Composer detected issues in your platform: Your Composer dependencies require a PHP version “>= 8.1.2”. You are running 7.4.33. in /home/customer/www/sub.domain.com/vendor/composer/platform_check.php on line 24

Thanks for your support

@alexgauvin

It sounds like this is a “feature” implemented by Siteground in their platform. I don’t think there is a way to fix this from our side. I would enquire with Siteground if they can disable this, as it shouldn’t be necessary for them to do this in your scenario.

Hi @david, thanks for your reply.

Here is a workaround that Siteground gave me in order to fix this issue :
Add this line to the .htaccess at the root of Invoice Ninja

AddHandler application/x-httpd-php81 .php .php5 .php4 .php3

this resolves my issue.
One question though : Will .htaccess file overwritten in future update ?

Thanks for your support

@alexgauvin

We exclude the .htaccess from being overwritten, so your custom one should survive upgrades.