summaryrefslogtreecommitdiff
path: root/roles/nginx/vhost
diff options
context:
space:
mode:
Diffstat (limited to 'roles/nginx/vhost')
-rw-r--r--roles/nginx/vhost/defaults/main.yml13
-rw-r--r--roles/nginx/vhost/handlers/main.yml5
-rw-r--r--roles/nginx/vhost/tasks/acme.yml44
-rw-r--r--roles/nginx/vhost/tasks/main.yml25
-rw-r--r--roles/nginx/vhost/templates/generic-proxy-no-buffering-with-acme.conf.j243
5 files changed, 130 insertions, 0 deletions
diff --git a/roles/nginx/vhost/defaults/main.yml b/roles/nginx/vhost/defaults/main.yml
new file mode 100644
index 00000000..dfedb50b
--- /dev/null
+++ b/roles/nginx/vhost/defaults/main.yml
@@ -0,0 +1,13 @@
+---
+# nginx_vhost:
+# name: example
+# template: generic-proxy-no-buffering-with-acme
+# acme: yes
+# hostnames:
+# - example.com
+# - www.example.com
+# proxy_pass: http://127.0.0.1:8080
+
+# nginx_vhost:
+# name: other-example
+# content: "<<< content of vhost >>>"
diff --git a/roles/nginx/vhost/handlers/main.yml b/roles/nginx/vhost/handlers/main.yml
new file mode 100644
index 00000000..d4e42ca0
--- /dev/null
+++ b/roles/nginx/vhost/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: reload nginx
+ service:
+ name: nginx
+ state: reloaded
diff --git a/roles/nginx/vhost/tasks/acme.yml b/roles/nginx/vhost/tasks/acme.yml
new file mode 100644
index 00000000..99ad7856
--- /dev/null
+++ b/roles/nginx/vhost/tasks/acme.yml
@@ -0,0 +1,44 @@
+---
+- name: check if acme certs already exist
+ loop: "{{ nginx_vhost.hostnames }}"
+ loop_control:
+ loop_var: acme_hostname
+ stat:
+ path: "/var/lib/acme/live/{{ acme_hostname }}"
+ register: acme_cert_stat
+
+- name: set acmecert_missing_hostnames variable
+ set_fact:
+ acmecert_missing_hostnames: "{{ acme_cert_stat.results | acme_cert_nonexistent(nginx_vhost.hostnames) }}"
+
+- name: link nonexistent hostnames to self-signed interim cert
+ when: acmecert_missing_hostnames | length > 0
+ block:
+ - name: get id of existing selfsigned interim certificate
+ command: cat /var/lib/acme/.selfsigned-interim-cert
+ changed_when: false
+ check_mode: false
+ register: selfsigned_interim_cert_id
+
+ - name: set selfsigned_interim_cert_id variable
+ set_fact:
+ selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"
+
+ - name: link to snakeoil cert for nonexistent hostnames
+ loop: "{{ acmecert_missing_hostnames }}"
+ loop_control:
+ loop_var: acme_missing_hostname
+ file:
+ src: "../certs/{{ selfsigned_interim_cert_id }}"
+ dest: "/var/lib/acme/live/{{ acme_missing_hostname }}"
+ state: link
+
+- name: make sure nginx config has been (re)loaded
+ meta: flush_handlers
+
+- name: get certificate using acmetool
+ import_role:
+ name: acmetool/cert
+ vars:
+ acmetool_cert_name: "{{ nginx_vhost.hostnames[0] }}"
+ acmetool_cert_hostnames: "{{ nginx_vhost.hostnames }}"
diff --git a/roles/nginx/vhost/tasks/main.yml b/roles/nginx/vhost/tasks/main.yml
new file mode 100644
index 00000000..4de3393d
--- /dev/null
+++ b/roles/nginx/vhost/tasks/main.yml
@@ -0,0 +1,25 @@
+---
+- name: install nginx configs from template
+ when: "'template' in nginx_vhost"
+ template:
+ src: "{{ nginx_vhost.template }}.conf.j2"
+ dest: "/etc/nginx/sites-available/{{ nginx_vhost.name }}"
+ notify: reload nginx
+
+- name: install nginx configs from config data
+ when: "'content' in nginx_vhost"
+ copy:
+ content: "{{ nginx_vhost.content }}"
+ dest: "/etc/nginx/sites-available/{{ nginx_vhost.name }}"
+ notify: reload nginx
+
+- name: enable vhost config
+ file:
+ src: "../sites-available/{{ nginx_vhost.name }}"
+ dest: "/etc/nginx/sites-enabled/{{ nginx_vhost.name }}"
+ state: link
+ notify: reload nginx
+
+- name: generate acme certificate
+ when: "'acme' in nginx_vhost and nginx_vhost.acme"
+ include_tasks: acme.yml
diff --git a/roles/nginx/vhost/templates/generic-proxy-no-buffering-with-acme.conf.j2 b/roles/nginx/vhost/templates/generic-proxy-no-buffering-with-acme.conf.j2
new file mode 100644
index 00000000..55bd5ac6
--- /dev/null
+++ b/roles/nginx/vhost/templates/generic-proxy-no-buffering-with-acme.conf.j2
@@ -0,0 +1,43 @@
+server {
+ listen 80;
+ listen [::]:80;
+ server_name {{ nginx_vhost.hostnames | join(' ') }};
+
+ include snippets/acmetool.conf;
+
+ location / {
+ return 301 https://$host$request_uri;
+ }
+}
+
+server {
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ server_name {{ nginx_vhost.hostnames | join(' ') }};
+
+ include snippets/acmetool.conf;
+ include snippets/ssl.conf;
+ ssl_certificate /var/lib/acme/live/{{ nginx_vhost.hostnames[0] }}/fullchain;
+ ssl_certificate_key /var/lib/acme/live/{{ nginx_vhost.hostnames[0] }}/privkey;
+ include snippets/hsts.conf;
+
+ location / {
+ include snippets/proxy-nobuff.conf;
+{% if 'client_max_body_size' in nginx_vhost %}
+ client_max_body_size {{ nginx_vhost.client_max_body_size }};
+{% endif %}
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Forwarded-Ssl on;
+ proxy_set_header X-Forwarded-Port $server_port;
+
+ # for websockets
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+
+ proxy_pass {{ nginx_vhost.proxy_pass }};
+ }
+}