summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Lusk <luskjh@gmail.com>2026-05-26 09:14:41 -0400
committerJoshua Lusk <luskjh@gmail.com>2026-05-26 09:14:41 -0400
commit94b0799bc018132084cab540efb521454c918375 (patch)
treef31e4937d71295981338e3bd36cee858a87a81f2
parent62c00bba0f4fdaeca96a9055b34d36b89cc8e34a (diff)
add https playbook
-rw-r--r--Makefile4
-rw-r--r--README.md1
-rw-r--r--playbooks/https.yaml73
-rw-r--r--playbooks/templates/nginx/https.conf.j260
4 files changed, 138 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 88a2f75..a139adc 100644
--- a/Makefile
+++ b/Makefile
@@ -37,3 +37,7 @@ security:
.PHONY: http
http:
$(BIN)/ansible-playbook -e @vault.yaml playbooks/http.yaml
+
+.PHONY: https
+https:
+ $(BIN)/ansible-playbook -e @vault.yaml playbooks/https.yaml
diff --git a/README.md b/README.md
index 9ad0779..e385b86 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,7 @@ _Listed in applicable order._
| `bootstrap`<sup>*</sup> | Bootstrap access |
| `security` | Security hardening |
| `http` | Web server |
+| `https` | SSL certificates |
### <sup>*</sup>Pre-bootstraped targets
diff --git a/playbooks/https.yaml b/playbooks/https.yaml
new file mode 100644
index 0000000..84146db
--- /dev/null
+++ b/playbooks/https.yaml
@@ -0,0 +1,73 @@
+- name: SSL certificates
+ hosts: hollyhock
+ become: true
+ tasks:
+ - name: Install certbot
+ community.general.snap:
+ name: certbot
+ classic: true
+ state: present
+
+ - name: Create symlink for certbot
+ ansible.builtin.file:
+ src: /snap/bin/certbot
+ dest: /usr/bin/certbot
+ state: link
+
+ - name: Allow https traffic through firewall
+ community.general.ufw:
+ rule: allow
+ port: 443
+ proto: tcp
+
+ - name: Generate certificates
+ ansible.builtin.command: |
+ certbot certonly --nginx --non-interactive --agree-tos --email {{ admin_email }}
+ {% for domain in item.domains %}-d {{ domain }} {% endfor %}
+ loop: "{{ sites }}"
+ register: ssl_certs
+ failed_when:
+ - ssl_certs.rc != 0
+ - "'Certificate not yet due for renewal' not in ssl_certs.stdout"
+ - "'Keeping the existing certificate' not in ssl_certs.stdout"
+ changed_when:
+ - "'Successfully received certificate' in ssl_certs.stdout"
+ - "'Deploying Certificate' in ssl_certs.stdout"
+
+ - name: Copy initial https sites
+ ansible.builtin.template:
+ src: nginx/https.conf.j2
+ dest: "/etc/nginx/sites-available/{{ item.name }}-https"
+ mode: "0644"
+ loop: "{{ sites }}"
+
+ - name: Disable http nginx sites
+ ansible.builtin.file:
+ path: "/etc/nginx/sites-enabled/{{ item.name }}-http"
+ state: absent
+ loop: "{{ sites }}"
+
+ - name: Check if final sites have been enabled
+ ansible.builtin.stat:
+ path: "/etc/nginx/sites-enabled/{{ item.name }}"
+ register: final_sites
+ loop: "{{ sites }}"
+
+ - name: Enable https sites
+ ansible.builtin.file:
+ src: "/etc/nginx/sites-available/{{ item.item.name }}-https"
+ dest: "/etc/nginx/sites-enabled/{{ item.item.name }}-https"
+ state: link
+ loop: "{{ final_sites.results }}"
+ when: not item.stat.exists
+ notify: Test and restart nginx
+
+ - name: Enable certbot timer
+ ansible.builtin.systemd:
+ name: snap.certbot.renew.timer
+ enabled: true
+ state: started
+
+ handlers:
+ - name: Test and restart nginx
+ ansible.builtin.include_tasks: tasks/test_and_restart_nginx.yaml
diff --git a/playbooks/templates/nginx/https.conf.j2 b/playbooks/templates/nginx/https.conf.j2
new file mode 100644
index 0000000..4962040
--- /dev/null
+++ b/playbooks/templates/nginx/https.conf.j2
@@ -0,0 +1,60 @@
+server {
+ server_name {{ item.domains | join(' ') }};
+
+ listen 80;
+ listen [::]:80;
+
+ return 301 https://$host$request_uri;
+}
+
+server {
+ server_name {{ item.domains | join(' ') }};
+
+ listen 443 ssl;
+ listen [::]:443 ssl;
+
+ root /var/www/html;
+ index index.nginx-debian.html;
+
+ location / {
+ try_files $uri $uri/ =404;
+ }
+
+ ssl_certificate /etc/letsencrypt/live/{{ item.domains[0] }}/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/{{ item.domains[0] }}/privkey.pem;
+ include /etc/letsencrypt/options-ssl-nginx.conf;
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
+
+ access_log /var/log/nginx/{{ item.name }}/access.log;
+ error_log /var/log/nginx/{{ item.name }}/error.log;
+}
+server {
+ server_name {{ item.domains | join(' ') }};
+
+ listen 80;
+ listen [::]:80;
+
+ return 301 https://$host$request_uri;
+}
+
+server {
+ server_name {{ item.domains | join(' ') }};
+
+ listen 443 ssl;
+ listen [::]:443 ssl;
+
+ root /var/www/html;
+ index index.nginx-debian.html;
+
+ location / {
+ try_files $uri $uri/ =404;
+ }
+
+ ssl_certificate /etc/letsencrypt/live/{{ item.domains[0] }}/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/{{ item.domains[0] }}/privkey.pem;
+ include /etc/letsencrypt/options-ssl-nginx.conf;
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
+
+ access_log /var/log/nginx/{{ item.name }}/access.log;
+ error_log /var/log/nginx/{{ item.name }}/error.log;
+}