Skip to content

Instantly share code, notes, and snippets.

@elnygren
Created November 16, 2016 19:30
Show Gist options
  • Save elnygren/e9888a86478c9d25ffbd9ffc5c3aaa4a to your computer and use it in GitHub Desktop.
Save elnygren/e9888a86478c9d25ffbd9ffc5c3aaa4a to your computer and use it in GitHub Desktop.
Certbot autorenew + Nginx (with Django specific conf)
- hosts: server
become: yes
become_method: sudo
user: root
vars:
- APP_NAME: app
- CERTBOT_EMAIL: [email protected]
- DOMAIN_NAME: www.emblica.fi
- OTHER_DOMAINS: ['emblica.fi'] # fed to certbot
tasks:
# just the LE cert related tasks for brevity
- name: Ensure /srv/scripts exists
file: path=/srv/scripts state=directory
tags:
- setup
- name: Copy certbot-create script
template: src=templates/certbot-create.sh.j2 dest=/srv/scripts/certbot-create.sh mode=755
tags:
- setup
- name: Create Let's Encrypt certs
command: /srv/scripts/certbot-create.sh
tags:
- setup
- name: Move certbot-renew
template: src=templates/certbot-renew.sh.j2 dest=/srv/scripts/certbot-renew.sh mode=755
tags:
- setup
- name: Set certbot autorenew cron job
cron: name="certbot" special_time=monthly job="/srv/scripts/certbot-renew.sh"
tags:
- setup
#!/bin/bash
# Create cert(s)
# Use 80 and 443 - nginx should not yet be running
docker run --rm --name letsencrypt \
-v "/etc/letsencrypt:/etc/letsencrypt" \
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
-p "443:443" \
-p "80:80" \
quay.io/letsencrypt/letsencrypt \
--standalone \
--agree-tos \
--renew-by-default \
-d {{ DOMAIN_NAME }} \
{% for domain in OTHER_DOMAINS %}
-d {{ domain }} \
{% endfor %}
-m {{ CERTBOT_EMAIL }} \
certonly
#!/bin/bash
# Renew cert
# nginx should have the correct /.well-known/ set
docker run --rm --name letsencrypt \
-v "/etc/letsencrypt:/etc/letsencrypt" \
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
--volumes-from {{ APP_NAME }}-nginx \
quay.io/letsencrypt/letsencrypt \
certonly \
--noninteractive \
--webroot \
--webroot-path /var/www/{{ APP_NAME }} \
--agree-tos \
--renew-by-default \
-d {{ DOMAIN_NAME }} \
{% for domain in OTHER_DOMAINS %}
-d {{ domain }} \
{% endfor %}
-m {{ CERTBOT_EMAIL }} \
# Reload nginx
docker kill --signal=HUP {{ APP_NAME }}-nginx
worker_processes 2;
events {
worker_connections 2000;
multi_accept on;
use epoll;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 50M;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging
##
# stdout
access_log /dev/fd/1;
error_log /dev/fd/1;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 9;
gzip_buffers 16 8k;
# gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/png image/gif image/jpeg;
upstream django {
server app:8000;
}
#
# Redirect all http traffic to (possibly naked) https domain
#
server {
listen 80 default_server;
server_name _;
return 301 https://{{ DOMAIN_NAME }}$request_uri;
}
#
# Redirect www https traffic to naked https domain.
#
server {
listen 443 ssl;
server_name www.{{ DOMAIN_NAME }};
return 301 https://{{ DOMAIN_NAME }}$request_uri;
}
#
# Main server block - all traffic redirected here
#
server {
listen 443 ssl default_server;
server_name {{ DOMAIN_NAME }}{% for domain in OTHER_DOMAINS %} {{ domain }}{% endfor %};
charset utf-8;
client_max_body_size 75M; # max upload size
#
# Django media and static
#
location /media {
alias /srv/media;
}
location /static {
alias /srv/static;
}
#
# Let's Encrypt
#
# Statically serve all files in .well-known, which is the location where letsencrypt stores the proof file
location /.well-known/ {
root /var/www/{{ APP_NAME }};
}
#
# Finally, send all non-media requests to the Django server.
#
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
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_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
ssl_certificate /etc/letsencrypt/live/{{ DOMAIN_NAME }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ DOMAIN_NAME }}/privkey.pem;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment