Nginx reverse proxy (on another machine on which my domain name points) gives 401 http errors after some time (hours, days) on /api/

I have a Debian server on which my domain points, with a Nginx reverse proxy to redirect hass.mydomain.tld to the port 8123 of my raspberry pi.

I have 401 errors on :

  • /api/history
  • /api/hassio/addons
  • /api/hassio/ingress
  • Maybe others ?

after some time. Logging out and in again does not help. But ! Restarting Nginx works. Weird.

The websocket works fine because the latest sensor values display correctly in Lovelace. Only the histories (and graphes) don’t work.

I saw some people with 401 errors on this forum but trying their solution did not work for me.
There’s nothing interesting in the home assistant logs even in debug.

Here’s the Nginx config:

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

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

	##
	# Gzip Settings
	##

	gzip on;

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}


# configuration file /etc/nginx/conf.d/global.conf:
server_tokens off;

# configuration file /etc/nginx/conf.d/hass.<domain>.conf:
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream homeassistant {
    server 192.168.1.43:8123;
    keepalive 64;
}

server {
    listen 80;
    listen [::]:80;
    server_name hass.<domain> xmpp-upload.hass.<domain>;

    access_by_lua_file /usr/share/ssowat/access.lua;

    include /etc/nginx/conf.d/acme-challenge.conf.inc;

    include /etc/nginx/conf.d/hass.<domain>.d/*.conf;

    location /yunohost {
        return 301 https://$http_host$request_uri;
    }

    location ^~ '/.well-known/ynh-diagnosis/' {
        alias /tmp/.well-known/ynh-diagnosis/;
    }

    location ^~ '/.well-known/autoconfig/mail/' {
        alias /var/www/.well-known/hass.<domain>/autoconfig/mail/;
    }

    access_log /var/log/nginx/hass.<domain>-access.log;
    error_log /var/log/nginx/hass.<domain>-error.log;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name hass.<domain>;

    include /etc/nginx/conf.d/security.conf.inc;

    ssl_certificate /etc/yunohost/certs/hass.<domain>/crt.pem;
    ssl_certificate_key /etc/yunohost/certs/hass.<domain>/key.pem;

    
    more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
    
    
    # OCSP settings
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/yunohost/certs/hass.<domain>/crt.pem;
    resolver 127.0.0.1 127.0.1.1 valid=300s;
    resolver_timeout 5s;
    

    location ^~ '/.well-known/autoconfig/mail/' {
        alias /var/www/.well-known/hass.<domain>/autoconfig/mail/;
    }

    access_by_lua_file /usr/share/ssowat/access.lua;

    include /etc/nginx/conf.d/hass.<domain>.d/*.conf;

    include /etc/nginx/conf.d/yunohost_sso.conf.inc;
    include /etc/nginx/conf.d/yunohost_admin.conf.inc;
    include /etc/nginx/conf.d/yunohost_api.conf.inc;

    access_log /var/log/nginx/hass.<domain>-access.log;
    error_log /var/log/nginx/hass.<domain>-error.log;
}

# vhost dedicated to XMPP http_upload
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name xmpp-upload.hass.<domain>;
    root /dev/null;

    location /upload/ {
        alias /var/xmpp-upload/hass.<domain>/upload/;
        # Pass all requests to metronome, except for GET and HEAD requests.
        limit_except GET HEAD {
          proxy_pass http://localhost:5290;
        }

        include proxy_params;
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'HEAD, GET, PUT, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Authorization';
        add_header 'Access-Control-Allow-Credentials' 'true';
        client_max_body_size 105M; # Choose a value a bit higher than the max upload configured in XMPP server
    }

    include /etc/nginx/conf.d/security.conf.inc;

    ssl_certificate /etc/yunohost/certs/hass.<domain>/crt.pem;
    ssl_certificate_key /etc/yunohost/certs/hass.<domain>/key.pem;

    
    more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
    
    
    # OCSP settings
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/yunohost/certs/hass.<domain>/crt.pem;
    resolver 127.0.0.1 127.0.1.1 valid=300s;
    resolver_timeout 5s;
    

    access_log /var/log/nginx/xmpp-upload.hass.<domain>-access.log;
    error_log /var/log/nginx/xmpp-upload.hass.<domain>-error.log;
}

# configuration file /etc/nginx/conf.d/acme-challenge.conf.inc:
location ^~ '/.well-known/acme-challenge/'
{
        default_type "text/plain";
        alias /tmp/acme-challenge-public/;
        gzip off;
}

# configuration file /etc/nginx/conf.d/hass.<domain>.d/redirect.conf:

location / {
    proxy_pass http://homeassistant;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}

location /api/websocket {
    proxy_pass http://homeassistant/api/websocket;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

}

EDIT: After some debugging I found out that when i don’t get the 401 error (after a nginx restart i.e), I get that in the homeassistant log :

2021-01-12 15:25:48 DEBUG (MainThread) [homeassistant.components.http.auth] Authenticated 2001:861:<windows_ip_address> for /api/history/period/2021-01-11T14:25:48.076Z using bearer token
2021-01-12 15:25:48 DEBUG (MainThread) [homeassistant.components.http.view] Serving /api/history/period/2021-01-11T14:25:48.076Z to 2001:861:<windows_ip_address> (auth: True)

I don’t get the “Authenticated … using bearer token” when I get the 401 error.