HA behind nginx reverse proxy with certificate-bases auth?

Wow, that actually almost made sense. I said almost. I’ve been fighting with Nginx. I’m trying to get things working without ssl right now, thinking it would be easier, and plan on putting ssl in later. I can get to my octoprint server remotely. When I try to get to my HA server, I get the HA connecting screen with the HA logo, so I know nginx is getting to the server. But it’s asking for a password. and says unable to connect. HA works fine from inside and if I forward the HA port out through my firewall I can connect find. So I think it’s something in the way I have nginx configured, but I have no idea what. Here is my non ssl nginx configuration below. HA and NGINX are not on the same server.

server {
    listen 80;
    server_name <full.external.hostname.com>;
    access_log /home/nginx/ha_nginx.log;
    proxy_buffering off;

    location / {
      proxy_pass http://<www.xxx.yyy.zzz>:8123;   #internal ip address of HA server
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Scheme $scheme;
      proxy_set_header X-Real-IP $remote_addr;
    }
}

You may need to add 2 lines to the nginx config.

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;

Without it, never seems to load correctly.

Thanks,
I’ve tried with those two lines in and out. The problem I’m running into at least some of the time, is that bogus hostnames on my domain end up re-directing to valid servers. So for example
my domain is dog.com.
on the internet domain server, dog.com re-directs to my external ISP provided IP address.
HA.dog.com works fine and re-directs to my internal ha server.
octo.dog.com works fine and re-directs to my internal octoprint server.
cat.dog.com which shouldn’t work, sends me to my internal ha server.
dog.com by itself usually fails, but in some configurations, it will send me to one of the two servers I have (ha or octo).

Another question.
All of my applications (HA, AD, Octoprint, nginx) are on separate servers. Do I need a SSL certificate for each name I am using coming in from outside (one for ha.dog.com, another for ad.dog.com, etc)?

You will need SSL certs for each domain including subdomains unless you have a wildcard SSL. Here is a some of my config using certificate based auth with password failover…

server {
    server_name cat.dog.com;
    listen 80;
    rewrite ^ https://$host$request_uri permanent;
          }

server {
    listen 443 ssl http2;
    server_name cat.dog.com;

    ssl_certificate /etc/letsencrypt/live/cat.dog.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cat.dog.com/privkey.pem;
    ssl_client_certificate /etc/nginx/ssl/auth/client.pem;
    ssl_verify_client optional; # or `on` if you require client key
    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_session_timeout 10m;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets on;
    ssl_session_ticket_key file.key;

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_buffer_size 4k;     #for quick first byte delivery

    client_body_buffer_size 8K;
    client_max_body_size 20m;
    client_body_timeout 10s;
    client_header_buffer_size 1k;
    large_client_header_buffers 2 16k;
    client_header_timeout 5s;

    proxy_buffering off;
    proxy_connect_timeout 90;
    proxy_send_timeout 90;
    proxy_read_timeout 90;
    proxy_buffers 32 4k;
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
    server_tokens off;
    keepalive_timeout 120;

    # Create this with: htpasswd -c /etc/nginx/.htpasswd some-username
    # If you add more users, omit the -c
    auth_basic_user_file /etc/nginx/.htpasswd;

location /manifest.json {
         proxy_pass http://127.0.0.1:8123/manifest.json;
                                     }
location /api/notify.html5/callback {
         proxy_pass http://127.0.0.1:8123/api/notify.html5notify/callback;
                                      }
location /api {
         proxy_pass http://127.0.0.1:8123/api;
         # WebSocket support (nginx 1.4)
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection $connection_upgrade;
                   }
location / {
      if ($ssl_client_verify = SUCCESS) {
         set $auth_basic off;
      }
         auth_basic $auth_basic;
         proxy_pass http://127.0.0.1:8123;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header Host $host;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         # WebSocket support (nginx 1.4)
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection $connection_upgrade;
         aio threads;
         }

)

I believe manifest.json and html5/callback cannot be authenticated so the locations are specified first. I also put out my api without authentication.Basically proof it all works and down the road it might get secured.

I also have mosquitto MQTT broker running SSL in another server block. It took some time to get working but been very reliable. I believe the WebSocket support lines are crucial, without them the page would render but not load any data.

1 Like

WOW, thanks,
Now if I just understood any of it. LOL

Looks like some research to do tomorrow…

Thanks again.

Here is some reading material:

https://deviantengineer.com/2015/05/nginx-reverseproxy-centos7/

I started off with this and once it started working, kept adding while making sure not to break it. :smiley:
Most of my SSL stuff is hardening ssl and weeding out old ciphers, enforcing latest TLS and not allowing downgrade attacks. Performance settings so http2 is utilized as well as caching.

Have you tried Guacamole with Traefik.

Do you mind sharing how you got the DUO extension to work in your compose file.

This is what I have.

If I run this command I am able to use DUO.

docker run
-p 8080:8080
-v /home/user/guacamole/config:/config
-e “EXTENSIONS=auth-duo”
oznu/guacamole

This is my compose file.

guacamole:
image: oznu/guacamole
container_name: Guacamole
restart: unless-stopped
volumes:

  • /home/user/guacamole/config/:/config
    ports:
  • “8074:8080”
    environment:
  • PUID=1000
  • PGID=1000
  • TZ=Africa/Harare
    labels:
  • “traefik.backend=Guacamole”
  • “traefik.docker.network=proxy”
  • “traefik.frontend.rule=Host:guac.mydomain.xx”
  • “traefik.enable=false”
  • “traefik.port=8080”
  • “traefik.default.protocol=http”
    network_mode: bridge

Curious, have you implemented Guacamole with docker and got Fail2ban to work?