# How to setup Let's Encrypt for Nginx on Ubuntu 16.04 (including IPv6, HTTP/2 and A+ SLL rating) There are two main modes to run the Let's Encrypt client (called `Certbot`): - [Standalone](https://certbot.eff.org/docs/using.html#standalone): replaces the webserver to respond to ACME challenges - [Webroot](https://certbot.eff.org/docs/using.html#webroot): needs your webserver to serve challenges from a known folder. **Webroot is better** because it doesn't need to replace Nginx (to bind to port 80). In the following, we're setting up `mydomain.com`. HTML is served from `/var/www/mydomain`, and challenges are served from `/var/www/letsencrypt`. ------------------------------------------------------------------------------- ## Nginx snippets First we create two snippets (to avoid duplicating code in every virtual host configuration). Create a file `/etc/nginx/snippets/letsencrypt.conf` containing: location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/letsencrypt; } Create a file `/etc/nginx/snippets/ssl.conf` containing: ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_protocols TLSv1.2; ssl_ciphers EECDH+AESGCM:EECDH+AES; ssl_ecdh_curve secp384r1; ssl_prefer_server_ciphers on; ssl_stapling on; ssl_stapling_verify on; add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; Create the folder for the challenges: sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge ------------------------------------------------------------------------------- ## Nginx virtual hosts (HTTP-only) We don't have a certificate yet at this point, so the domain will be served only as HTTP. Create a file `/etc/nginx/sites-available/mydomain.conf` containing: server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; server_name mydomain.com www.mydomain.com; include /etc/nginx/snippets/letsencrypt.conf; root /var/www/mydomain; index index.html; location / { try_files $uri $uri/ =404; } } Enable the site: rm /etc/nginx/sites-enabled/default ln -s /etc/nginx/sites-available/mydomain.conf /etc/nginx/sites-enabled/mydomain.conf And reload Nginx: sudo systemctl reload nginx ------------------------------------------------------------------------------- ## Certbot Install the package: sudo apt-get install software-properties-common sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install certbot Note: there is also a `letsencrypt` package in APT, but it's a much older version of the client. ------------------------------------------------------------------------------- ## Get the certificate Request the certificate (don't forget to replace with your own email address): certbot certonly --webroot --agree-tos --no-eff-email --email YOUR@EMAIL.COM -w /var/www/letsencrypt -d www.domain.com -d domain.com It will save the files in `/etc/letsencrypt/live/www.mydomain.com/`. Note: The flag `--no-eff-email` opts out of signing up for the [EFF mailing list](https://lists.eff.org/cgi-bin/mailman/listinfo), remove the flag if you'd like to signup. ---- ## Nginx virtual hosts (HTTPS-only) Now that you have a certificate for the domain, switch to HTTPS by editing the file `/etc/nginx/sites-available/mydomain.conf` and replacing contents with: ## http://mydomain.com redirects to https://mydomain.com server { listen 80; listen [::]:80; server_name mydomain.com; include /etc/nginx/snippets/letsencrypt.conf; location / { return 301 https://mydomain.com$request_uri; } } ## http://www.mydomain.com redirects to https://www.mydomain.com server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; server_name www.mydomain.com; include /etc/nginx/snippets/letsencrypt.conf; location / { return 301 https://www.mydomain.com$request_uri; } } ## https://mydomain.com redirects to https://www.mydomain.com server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name mydomain.com; ssl_certificate /etc/letsencrypt/live/www.mydomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.mydomain.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/www.mydomain.com/fullchain.pem; include /etc/nginx/snippets/ssl.conf; location / { return 301 https://www.mydomain.com$request_uri; } } ## Serves https://www.mydomain.com server { server_name www.mydomain.com; listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server ipv6only=on; ssl_certificate /etc/letsencrypt/live/www.mydomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.mydomain.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/www.mydomain.com/fullchain.pem; include /etc/nginx/snippets/ssl.conf; root /var/www/mydomain; index index.html; location / { try_files $uri $uri/ =404; } } Then reload Nginx: sudo systemctl reload nginx Note that `http://mydomain.com` redirects to `https://mydomain.com` (which redirects to `https://www.mydomain.com`) because redirecting to `https://www.mydomain.com` directly would be incompatible with HSTS. --- ## Automatic renewal using Cron Certbot can renew all certificates that expire within 30 days, so let's make a cron for it. You can test it has the right config by launching a dry run: certbot renew --dry-run Create a file `/root/letsencrypt.sh`: #!/bin/bash systemctl reload nginx # If you have other services that use the certificates: # systemctl restart mosquitto Make it executable: chmod +x /root/letsencrypt.sh Edit cron: sudo crontab -e And add the line: 20 3 * * * certbot renew --noninteractive --renew-hook /root/letsencrypt.sh ---- ## Conclusion Congratulations, you should now be able to see your website at `https://www.mydomain.com` 🙂 You can now also test that your domain has A+ SLL rating: - https://www.ssllabs.com/ssltest/analyze.html?d=mydomain.com - https://www.ssllabs.com/ssltest/analyze.html?d=www.mydomain.com I would also recommend setting up content-specific features like `Content Security Policy` and `Subresource Integrity`: - [Mozilla Observatory](https://observatory.mozilla.org): submit a domain to get content-specific advices - [Mozilla Security Guidelines](https://wiki.mozilla.org/Security/Guidelines/Web_Security) If Let's Encrypt is useful to you, consider [donating to Let's Encrypt](https://letsencrypt.org/donate/) or [donating to the EFF](https://supporters.eff.org/donate/).