Search code examples
nginxnginx-reverse-proxymultiple-domains

nginx as reverse proxy for multiple domains and multiple containers


I have nginx, certbot and spring boot applications all running as docker containers, configured in one docker-compose.yml.

I use the following nginx.conf:

server {
    listen 80;
    listen [::]:80;
    server_name sub1.domain.de;

    location ~ /.well-known/acme-challenge {
        allow all;
        root /var/www/html;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name sub1.domain.de;

    server_tokens off;

    ssl_certificate /etc/letsencrypt/live/sub1.domain.de/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub1.domain.de/privkey.pem;

    ssl_buffer_size 8k;

    ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;

    ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

    ssl_ecdh_curve secp384r1;
    ssl_session_tickets off;

    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;

    location / {
        proxy_pass http://container1:8080;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
  add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
        #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        # enable strict transport security only if you understand the implications
    }

    root /var/www/html;
       index index.html index.htm index.nginx-debian.html;
   }




server {
    listen 80;
    listen [::]:80;
    server_name sub2.domain.de;

    location ~ /.well-known/acme-challenge {
        allow all;
        root /var/www/html;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}


server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name sub2.domain.de;

    server_tokens off;

    ssl_certificate /etc/letsencrypt/live/sub1.domain.de/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub1.domain.de/privkey.pem;

    ssl_buffer_size 8k;

    ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;

    ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

    ssl_ecdh_curve secp384r1;
    ssl_session_tickets off;

    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;

    location / {
        proxy_pass http://bcontainer2:8081;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
        #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        # enable strict transport security only if you understand the implications
    }

    root /var/www/html;
       index index.html index.htm index.nginx-debian.html;
   }

SSL certificates are for both domains but are named like the first domain.
When trying to reach sub1.domain.de I get a 502, bad gateway. What am I missing here?
I can reach my container2 via the ip-adress:8081 though.

Thanks in advance for your help!


Solution

  • If someone is having the same troubles, here is my solution, which worked fine for me:

    in the docker-compose.yml you have to map your containers to different ports. That's what I already did, you can check the file in my first post. So this file stays the same.

    In the nginx.conf though you have to address the container with it corresponding intern port. Meaning in my case (two containers, both are listening to port 8080 internally) the proxy_pass has to direct to "container_name:8080" in both cases. I first thought it has to be the host port, which is not the case.

    nginx.conf:

    server {
        listen 80;
        listen [::]:80;
        server_name sub1.domain.de;
    
        location ~ /.well-known/acme-challenge {
            allow all;
            root /var/www/html;
        }
    
        location / {
            return 301 https://$host$request_uri;
        }
    }
    
    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        http2 on;
        server_name sub1.domain.de;
    
        server_tokens off;
    
        ssl_certificate /etc/letsencrypt/live/sub1.domain.de/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/sub1.domain.de/privkey.pem;
    
        ssl_buffer_size 8k;
    
        ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
    
        ssl_protocols TLSv1.2;
        ssl_prefer_server_ciphers on;
    
        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
    
        ssl_ecdh_curve secp384r1;
        ssl_session_tickets off;
    
        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.8.8;
    
        location / {
            proxy_pass http://container1:8080;
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-XSS-Protection "1; mode=block" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header Referrer-Policy "no-referrer-when-downgrade" always;
      add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
            #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
            # enable strict transport security only if you understand the implications
        }
    
        root /var/www/html;
           index index.html index.htm index.nginx-debian.html;
       }
    
    
    
    
    server {
        listen 80;
        listen [::]:80;
        server_name sub2.domain.de;
    
        location ~ /.well-known/acme-challenge {
            allow all;
            root /var/www/html;
        }
    
        location / {
            return 301 https://$host$request_uri;
        }
    }
    
    
    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        http2 on;
        server_name sub2.domain.de;
    
        server_tokens off;
    
        ssl_certificate /etc/letsencrypt/live/sub1.domain.de/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/sub1.domain.de/privkey.pem;
    
        ssl_buffer_size 8k;
    
        ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
    
        ssl_protocols TLSv1.2;
        ssl_prefer_server_ciphers on;
    
        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
    
        ssl_ecdh_curve secp384r1;
        ssl_session_tickets off;
    
        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.8.8;
    
        location / {
            proxy_pass http://bcontainer2:8080;
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-XSS-Protection "1; mode=block" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header Referrer-Policy "no-referrer-when-downgrade" always;
            add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
            #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
            # enable strict transport security only if you understand the implications
        }
    
        root /var/www/html;
           index index.html index.htm index.nginx-debian.html;
       }