sslnginxssl-certificateserver-name

Nginx Setup for Multiple domains with individual ssl certificates to same upstream


so I have multiple domains with multiple let's encrypt ssl certificates (one per domain) which all point to the same app (upstream). Currently I am using the code below. However it is quite a lot of code, especially if I have to replicated it for every domain. So I am wondering if there is a way to combine it so that I have much of the code only once, which would make it much easier to maintain.

The redirect for https://www.any-domain-here is problematic, as well as the last, main, server block, as both require the ssl certificate and I will need to include those for all different domains. So is there a way to do this without duplicating those code blocks?

############################
#
# Upstream
#
upstream upstream {
    least_conn;
    server app:8080;
}
upstream blog.upstream {
    least_conn;
    server app_nginx;
}
############################
#
# redirect all 80 to 443
# and allow Let's Encrypt
#
server {
    server_name ~.;
    listen 80;
    listen [::]:80;
    # config for .well-known
    include /etc/nginx/includes/letsencrypt.conf;

    location / {
        return         301 https://$host$uri;
    }
}
############################
#
# Redirect all www to non-www
#
server {
    server_name "~^www\.(.*)$" ;
    return 301 https://$1$request_uri ;
    ssl_certificate /etc/letsencrypt/live/www.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.domain.com/privkey.pem;
}
##########################
# HTTPS
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name domain.com;

    location /blog/ {
        proxy_set_header Host $host;
        proxy_pass  http://blog.upstream;
    }

    ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
    # access_log
    access_log            /var/log/nginx/access.log;
    # proxy_pass config
    location / {
        # include proxy presets
        include /etc/nginx/includes/proxy.conf;
        proxy_pass              http://domain.com$uri;
    }
    # general ssl parameters
    include /etc/nginx/includes/ssl-params-with-preload.conf;

    root         /var/www/html;
}

Solution

  • I solved this by creating quite a couple of include files.

    I have the following default.conf now:

    # don't redirect proxy
    proxy_redirect  off;
    # turn off global logging
    access_log off;
    # DON'T enable gzip as it opens up vulnerabilities
    # logging format
    log_format compression '$remote_addr - $remote_user [$time_local] '
                           '"$request" $status $bytes_sent '
                           '"$http_referer" "$http_user_agent" "$gzip_ratio"';
    ############################
    #
    # redirect all 80 to 443
    # and allow Let's Encrypt
    #
    server {
      listen 80;
      listen [::]:80;
      server_name ~. ;
    
      location /.well-known/acme-challenge {
        root /var/www/html;
        default_type text/plain;
        # allow all;
      }
    
      location / {
        return 301 https://$host$uri;
      }
    }
    # include website configs
    include /etc/nginx/includes/nginx-server.conf;
    

    My nginx-server.conf has the following content:

    ############################
    #
    # Upstream
    #
    upstream veare_upstream {
        server veare:8080;
    }
    ############################
    #
    # redirect all 80 to 443
    # and allow Let's Encrypt
    #
    server {
        server_name www.veare.de;
        listen 80;
        listen [::]:80;
    
        root /var/www/html;
    
        location /.well-known/acme-challenge {
            default_type text/plain;
        }
    
        location / {
            return         301 https://$host$uri;
        }
    }
    ############################
    #
    # Redirect all www to non-www
    #
    server {
        listen 80;
        listen [::]:80;
        server_name "~^www\.(.*)$" ;
        return 301 https://$1$request_uri;
    }
    ##########################
    # HTTPS
    include /etc/nginx/includes/domains/*.conf;
    

    The last line includes all my domain files, one e.g. is veare.de.conf they are all named exactly like the domain:

    ############################
    #
    # Redirect all www to non-www
    #
    #
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name www.veare.de;
        ssl_certificate /etc/letsencrypt/live/www.veare.de/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.veare.de/privkey.pem;
        return 301 https://veare.de$request_uri;
    }
    ##########################
    # HTTPS
    server {
        server_name veare.de;
        ssl_certificate /etc/letsencrypt/live/veare.de/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/veare.de/privkey.pem;
    
        location ^~ /.well-known/acme-challenge {
          allow all;
          # Set correct content type. According to this:
          # https://community.letsencrypt.org/t/using-the-webroot-domain-verification-method/1445/29
          # Current specification requires "text/plain" or no content header at all.
          # It seems that "text/plain" is a safe option.
          default_type "text/plain";
          root /var/www/html;
        }
    
        include /etc/nginx/includes/main-server.conf;
    }
    

    This works perfectly for me.