Skip to content

Instantly share code, notes, and snippets.

Last active June 10, 2024 01:44
Show Gist options
  • Save mattiaslundberg/ba214a35060d3c8603e9b1ec8627d349 to your computer and use it in GitHub Desktop.
Save mattiaslundberg/ba214a35060d3c8603e9b1ec8627d349 to your computer and use it in GitHub Desktop.
Let's Encrypt Nginx setup with Ansible
Ansible playbook to setup HTTPS using Let's encrypt on nginx.
The Ansible playbook installs everything needed to serve static files from a nginx server over HTTPS.
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 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. Copy your (static HTML) code to `/var/www/` (`` replaced with your domain)
7. Restart nginx (`systemctl restart nginx`)
[letsencrypt] ansible_user=root
- hosts: letsencrypt
become: true
gather_facts: no
- raw: apt-get install -y python-simplejson
- 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
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
- name: Install nginx site for letsencrypt requests
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 }}
creates: /etc/letsencrypt/live/{{ domain_name }}
- name: Generate dhparams
shell: openssl dhparam -out /etc/nginx/dhparams.pem 2048
creates: /etc/nginx/dhparams.pem
- name: Install nginx site for specified site
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
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://{{ 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'; img-src 'self' data:; 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_dhparam /etc/nginx/dhparams.pem;
ssl_prefer_server_ciphers on;
root /var/www/{{ domain_name }};
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
user www-data;
worker_processes 4;
pid /run/;
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/*;
Copy link

nuxion commented Aug 13, 2022

thanks for this! nowadays python-simplejson is python3-simplejson (tested on debian 11)

Copy link


thanks for the tip

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