Node.js + Nginx + Letsencrypt + two Top-Level-Domains

November 2, 2016 189 views
Node.js Nginx Let's Encrypt DigitalOcean Ubuntu 16.04

Hey what is the best way to accomplish a good and secure setup with Node.js + Nginx + Letsencrypt and two Top-Level-Domains? I'm getting a little bit stuck in the moment.

First of all my domain setup: Now in the moment both DNS are managed over digitalocean and both have the A (and AAA) Records for my staging environments (live, dev, www -> cname)

But I configured both domains as the same (but I think that is bad practise for google)

My Nodejs application has two folders (for the dev and live system) in the /opt/… directory
I manage it with pm2 and ran every application on a different port.

In my Nginx sites-enabled folder, I have to files one for the dev and one for the live environment:

looks like that:

# Nginx config for /etc/nginx/sites-enabled/dev.altwiener-markt.com

limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
limit_req_status 444;
limit_conn_status 503;

proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args";
proxy_cache_valid 404 1m;

    upstream dev.altwiener-markt.com {
        server localhost:3325;
    }

    server {
        listen 80;
        server_name dev.altwiener-markt.com;
        limit_conn conn_limit_per_ip 10;
        limit_req zone=req_limit_per_ip burst=10 nodelay;
        return 301 https://$host$request_uri$is_args$args;
    }

    server {
        server_name dev.altwiener-markt.com;
        listen 443 ssl http2;
        keepalive_timeout 300;

        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;

        ssl on;
        ssl_stapling on;
        ssl_stapling_verify on;
        # Use certificate and key provided by Let's Encrypt:
        ssl_certificate /etc/letsencrypt/live/dev.altwiener-markt.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/dev.altwiener-markt.com/privkey.pem;
        ssl_session_timeout 5m;
        ssl_session_cache shared:SSL:10m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
        ssl_prefer_server_ciphers on;

        ##
        # `gzip` Settings
        #
        #
        gzip on;
        gzip_disable "MSIE [1-6]\.";

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 7;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_min_length 256;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;

        root /opt/dev.altwiener-markt.at/client/public;

        resolver 8.8.8.8 8.8.4.4 valid=300s;
        add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains';
        add_header X-Cache $upstream_cache_status;

        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;

        location / {
            proxy_cache_valid 200 30m;
            proxy_cache_valid 404 1m;
            proxy_pass http://dev.altwiener-markt.com;
            proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
            proxy_ignore_headers Set-Cookie;
            proxy_hide_header Set-Cookie;
            proxy_hide_header X-powered-by;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header Host $http_host;
            expires 10m;
        }

        location ~ \.(aspx|php|jsp|cgi)$ {
            return 404;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
            # root /opt/dev.altwiener-markt.at/client/public;
            # Per RFC2616 - 1 year maximum expiry
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
            expires 1y;
            add_header Cache-Control public;
            access_log  off;
            log_not_found off;

            # Some browsers still send conditional-GET requests if there's a
            # Last-Modified header or an ETag header even if they haven't
            # reached the expiry date sent in the Expires header.
            add_header Last-Modified "";
            add_header ETag "";
            break;
        }

        location ~ /.well-known {
            allow all;
        }
    }

The problem is when I want to add with certbot my domains it always has a 404 in the .well-known host directory...

certbot commmand

./certbot-auto certonly --webroot \
    -w /opt/altwiener-markt.at \
    -d altwiener-markt.at \
    -d www.altwiener-markt.at \
    -d live.altwiener-markt.at \
    -d altwiener-markt.com \
    -d www.altwiener-markt.com \
    -d live.altwiener-markt.com \
    -w /opt/dev.altwiener-markt.at \
    -d dev.altwiener-markt.at \
    -d dev.altwiener-markt.com \
    --non-interactive --agree-tos --email office@lukasholzer.com

I hope you can help me to make letsencrypt work for all domains.

Regards Lukas

Be the first one to answer this question.