Lukas Oppermann
Lukas Oppermann

Reputation: 2928

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;
}

Upvotes: 5

Views: 8566

Answers (1)

Lukas Oppermann
Lukas Oppermann

Reputation: 2928

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.

Upvotes: 4

Related Questions