diff --git a/README.md b/README.md new file mode 100644 index 0000000..faf2ef1 --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# Nginx + +## Supported + +Nginx: 1.10.3 +Debian: Stretch + +Other versions might work but are not tested. + +## Parameters and defaults + +DNS resolver have to be defined in the `resolver` array. Defaults: + +``` +resolver: + - 8.8.8.8 + - 8.8.4.4 +``` + +All other configuration is to be placed inside the `nginx` dict. + +``` +# name: *upstreamconfig*, see below for definition +upstreams: {} + +# name: *vhostconfig*, see below for definition +vhosts: {} + +# force all traffic on ssl, except letsencrypt challenges +force_ssl: True + +``` + +** upstreamconfig **: +``` +# array of upstream servers +server: + - + # can be "unix:/path/to/socket" or "https://foo.bar" or "http://foo.bar" + address: *mandatory* + + # monitor dns for changes + resolve: true +``` + +** vhosts **: +``` +# Array of server names, example: foo.bar +servername: [] + +# set this server as default +default_server: False + +listen: + ssl: True + ssl_port: 443 + nossl: False + nossl_port: 80 + +# Example: https://upstream; If set to none no reverse proxy will be set up. +backend: None + +# Set ssl certs to letsencrypt paths and enable letsencrypt for this vhost +letsencrypt: True +``` + diff --git a/defaults/main.yml b/defaults/main.yml index b062a52..1471aa1 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,3 +1,8 @@ resolver: - 8.8.8.8 - 8.8.4.4 + +nginx: + force_ssl: True + upstreams: {} + vhosts: {} diff --git a/files/config/sites-available/https-redirect b/files/config/sites-available/https-redirect new file mode 100644 index 0000000..5e37684 --- /dev/null +++ b/files/config/sites-available/https-redirect @@ -0,0 +1,11 @@ +server { + listen 80; + listen [::]:80; + + location /.well-known/acme-challenge/ { + alias /var/www/letsencrypt/; + } + location / { + return 301 https://$host$request_uri; + } +} diff --git a/tasks/main.yml b/tasks/main.yml index a4ef3d2..ec0d3c5 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -30,6 +30,39 @@ notify: - restart nginx +- name: execute upstream template + template: + src: upstreams.conf.j2 + dest: /etc/nginx/conf.d/upstreams.conf + notify: + - restart nginx + +- name: create nginx vhosts + template: + dest: "/etc/nginx/sites-available/{{ item.key }}" + src: vhost.j2 + with_dict: "{{ nginx.vhosts }}" + notify: + - restart nginx + +- name: enable nginx vhosts + file: + src: "/etc/nginx/sites-available/{{ item.key }}" + path: "/etc/nginx/sites-enabled/{{ item.key }}" + state: link + with_dict: "{{ nginx.vhosts }}" + notify: + - restart nginx + +- name: enable https redirect + file: + src: "/etc/nginx/sites-available/https-redirect" + path: "/etc/nginx/sites-enabled/https-redirect" + state: link + when: nginx.force_ssl + notify: + - restart nginx + - name: delete nginx default config file: path=/etc/nginx/sites-enabled/default state=absent diff --git a/templates/upstreams.conf.j2 b/templates/upstreams.conf.j2 new file mode 100644 index 0000000..4b96fe9 --- /dev/null +++ b/templates/upstreams.conf.j2 @@ -0,0 +1,9 @@ +{% for upstreamname in nginx.upstreams %} +{% set upstream = nginx.upstreams[upstreamname] %} +upstream {{ upstreamname }} { +{% for s in upstream.server %} + server {{ s.address }} {%if s.resolve|d(False) %}resolve{% endif %}; +{% endfor %} +} + +{% endfor %} diff --git a/templates/vhost.j2 b/templates/vhost.j2 new file mode 100644 index 0000000..494988a --- /dev/null +++ b/templates/vhost.j2 @@ -0,0 +1,41 @@ +{% set vhost = item.value %} +{% set vhost_name = item.key %} +{% set vhost_listen = vhost.listen|default({}) %} + +server { + server_name {{ vhost.servername|join(' ') }}; + + {% if vhost_listen.ssl|default(True) %} + listen {{ vhost_listen.ssl_port|default(443) }} ssl {% if vhost.default_server|default(False) %}default_server{% endif %}; + listen [::]:{{ vhost_listen.ssl_port|default(443) }} ssl {% if vhost.default_server|default(False) %}default_server{% endif %}; + {% endif %} + {% if vhost_listen.nossl|default(False) %} + listen {{ vhost_listen.nossl_port|default(80) }} ssl {% if vhost.default_server|default(False) %}default_server{% endif %}; + listen [::]:{{ vhost_listen.nossl_port|default(80) }} ssl {% if vhost.default_server|default(False) %}default_server{% endif %}; + {% endif %} + + {% if vhost.backend|default(False) %} + location / { + proxy_pass {{ vhost.backend }}; + + # add proxy headers + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # hide downstream headers for security reasons + proxy_hide_header X-Powered-By; + proxy_hide_header Server; + proxy_hide_header X-AspNetMvc-Version; + proxy_hide_header X-AspNet-Version; + } + {% endif %} + + {% if vhost.letsencrypt|d(True) %} + ssl_certificate /etc/ssl/letsencrypt_{{ vhost_name }}_chained.crt; + ssl_certificate_key /etc/ssl/private/letsencrypt_{{ vhost_name }}.key; + ssl_trusted_certificate /etc/ssl/letsencrypt_full_chain.crt; + ssl_stapling_verify on; + ssl_stapling on; + {% endif %} +}