InvoiceNinja Running Behind HAProxy - Mixed Content Errors


I am attempting to get invoice ninja working through HAProxy, I have run into an issue where HAProxy displays mixed content, so far I have done the following:

on invoiceninja:

  • added TRUSTED_PROXIES='111.222.333.444/24 to my .env file
  • running with require_https set to false

on HAProxy:

  • tried adding http-request header set to name: X-Forwarded-Proto, fmt https to my HAProxy frontend actions

the backend is configured to not use SSL, and is just accessing via http on port 80.

at this point I’m getting some mixed content, running with require https true results in a redirect error from the client browser, telling HAProxy to connect using SSL on port 80 or 443 results in HAProxy giving a 503 error, I suspect I could solve this by just using a self-signed cert on invoiceninja, running it truly as an SSL encrypted web server, instead of this forcing https traffic over an http connection to the load balancer, then just using that self-signed cert for communication between HAProxy and invoiceninja, but thats an extra layer of work that I don’t know if i really wanna take on if theres a way I can do this without involving additional certs and configuration.

Suggestions on fixing the mixed content issue before I go about running the whole server with a self signed?


Maybe the info here will help:

I use HAProxy and have personally tested this nginx config.

In my case HAProxy handles SSL termination, so the traffic is over port 80, but the URL is still https. This is how I resolved the mixed content issues.

If on the Invoice Ninja container you use nginx, then just force https:

server {
    listen   80;
    listen   [::]:80;
    fastcgi_hide_header X-Powered-By;

    root /var/www/invoiceninja/public/;
    index index.php index.html index.htm;
    charset utf-8;
    client_max_body_size 99M;

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

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

    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/invoiceninja.access.log;
    error_log   /var/log/nginx/invoiceninja.error.log;

    location ~ \.php$ {
        proxy_set_header X-Forwarded-Proto https;
        fastcgi_param  HTTPS 'on';
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php;
        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;

    sendfile off;

The lines that make this happen are:

        proxy_set_header X-Forwarded-Proto https;
        fastcgi_param  HTTPS 'on';

If you use Apache, something similar to this should work, I did not test the apache variant, but have used something similar to this in the past with other projects:

<VirtualHost *:80>

        RemoteIPHeader X-Forwarded-For

        SetEnv HTTPS "on"
        RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
        RequestHeader set "X-Forwarded-SSL" expr=%{HTTPS}

        DocumentRoot "/var/www/invoiceninja/"

        LogLevel warn
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined