Skip to content

Instantly share code, notes, and snippets.

@nicgirault
Forked from mattiaslundberg/Ansible Let's Encrypt Nginx setup
Last active November 6, 2020 07:33
Show Gist options
  • Save nicgirault/67913430bc52727e6fbc70d230028a37 to your computer and use it in GitHub Desktop.
Save nicgirault/67913430bc52727e6fbc70d230028a37 to your computer and use it in GitHub Desktop.
Let's Encrypt Nginx setup with Ansible

Ansible playbook to setup a redirection server from your root domain name to wwww subdomain using Let's encrypt on nginx.

The Ansible playbook installs nginx and let's encrypt to redirect https://example.com to https://www.example.com. The server pass A rating on SSL Labs.

To use:

  1. Install Ansible
  2. Setup an Ubuntu 16.04 server accessible over ssh
  3. Create /etc/ansible/hosts according to template below and change example.com to your domain
  4. Copy the rest of the files to an empty directory (playbook.yml in the root of that folder and the rest in the templates subfolder)
  5. Run ansible-playbook playbook.yml
  6. Restart nginx (systemctl restart nginx)
[production]
example.com ansible_user=root letsencrypt_email=me@example.com domain_name=example.com ansible_ssh_private_key_file=key.pem
---
- hosts: letsencrypt
become: true
gather_facts: no
pre_tasks:
- raw: apt-get install -y python-simplejson
tasks:
- name: Upgrade system
apt: upgrade=dist update_cache=yes
- name: Install nginx
apt: name=nginx state=latest
- name: install letsencrypt
apt: name=letsencrypt state=latest
- name: create letsencrypt directory
file: name=/var/www/letsencrypt state=directory
- name: Remove default nginx config
file: name=/etc/nginx/sites-enabled/default state=absent
- name: Install system nginx config
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
- name: Install nginx site for letsencrypt requests
template:
src: templates/nginx-http.j2
dest: /etc/nginx/sites-enabled/http
- name: Reload nginx to activate letsencrypt site
service: name=nginx state=restarted
- name: Create letsencrypt certificate
shell: letsencrypt certonly -n --webroot -w /var/www/letsencrypt -m {{ letsencrypt_email }} --agree-tos -d {{ domain_name }}
args:
creates: /etc/letsencrypt/live/{{ domain_name }}
- name: Generate dhparams
shell: openssl dhparam -out /etc/nginx/dhparams.pem 2048
args:
creates: /etc/nginx/dhparams.pem
- name: Install nginx site for specified site
template:
src: templates/nginx-le.j2
dest: /etc/nginx/sites-enabled/le
- name: Reload nginx to activate specified site
service: name=nginx state=restarted
- name: Add letsencrypt cronjob for cert renewal
cron:
name: letsencrypt_renewal
special_time: weekly
job: letsencrypt --renew certonly -n --webroot -w /var/www/letsencrypt -m {{ letsencrypt_email }} --agree-tos -d {{ domain_name }} && service nginx reload
server_tokens off;
server {
listen 80 default_server;
server_name {{ domain_name }};
location /.well-known/acme-challenge {
root /var/www/letsencrypt;
try_files $uri $uri/ =404;
}
location / {
rewrite ^ https://www.{{ domain_name }}$request_uri? permanent;
}
}
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com; img-src 'self' data: https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; font-src 'self'; frame-src 'none'; object-src 'none'";
# HTTPS server
#
server {
listen 443 ssl default deferred;
server_name {{ domain_name }};
ssl on;
ssl_certificate /etc/letsencrypt/live/{{ domain_name }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ domain_name }}/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/{{ domain_name }}/fullchain.pem;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_dhparam /etc/nginx/dhparams.pem;
ssl_prefer_server_ciphers on;
location / {
rewrite ^ https://www.{{ domain_name }}$request_uri? permanent;
}
}
user www-data;
worker_processes 4;
pid /run/nginx.pid;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
@pete-proton
Copy link

pete-proton commented Nov 6, 2020

thanks for the scripts. IMO rewrite like

    location / {
        rewrite ^ https://www.{{ domain_name }}$request_uri? permanent;
    }

cripples the outcome a bit, since certificate is for {{ domain_name }}, but redirect forces to do www.{{ domain_name }}, in which case the certificate does not match the site address. to me www prefix looks redundant anyway these days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment