This nginx ansible role aims to provide both, configuration for reverseproxies as well as the terminating server.
It enables advanced configuration scenarios, such as complex location to upstream configs, uwsgi and unix socket support as well as TLS client authentication (optionally enforcing a specific CN presented by the client). A server may listen on multiple domains, optionally redirecting to the primary domain. HTTP basic authentication may be configured on a per-server basis.
This role is currently based on debian stable.
Note: A server is one server block in the nginx config.
Note: I found this role not to work with ansible 2.7.7 (current debian buster) as the default handling in jinja is different. Use ansible from buster-backports (> 2.9.16).
This role expects to be the only entity configuring nginx on the respective host. It will disable all other sites_available (those that are not configured through this role), although it will not delete any configuration or files associated.
The role can retrieve, configure and maintain letsencrypt certificates. One certificate per server is retrieved, containing all additional_domains of that server.
If a server does not need its letsencrypt certificate anymore, this role will delete the certificate from certbot so it is not renewed. Only certificates created by this role will ever be possibly deleted.
If the domains associated with a server change, the role will acquire new certificates for the respective server.
nginx_workers: auto
nginx_user: www-data
nginx_revproxy_sites:
- fqdn_: site.example.com: # FQDN of primary domain (the domain this server responds on primarily)
location_to_upstream:
- {protocol: 'http', location: /, addrs: ['192.168.1.1:3000']}
- {protocol: 'https', location: /mult, addrs: ['192.168.1.1:3000', '192.168.1.2:3000'], upstream_location: '/prox', additional_options: ['proxy_set_header X-Graylog-Server-URL https://$server_name/;']}
- {protocol: 'http', location: /asd, socket_path: '/lol/test'}
- {protocol: 'uwsgi', location: /asd2, socket_path: '/lol/uwsgi'}
- {protocol: 'uwsgi', location: /asd3, addrs: ['192.168.1.10:3000'], uwsgi_param_location: '/etc/nginx/specialparams'}
- {location: /static, webroot: '/var/www/static', client_max_body_size: '100M'}
additional_domains:
- site2.example.com
- site3.example.com
redirect_to_primary: true
port: {http: 80, https: 443}
ssl: {enabled: false, pem_path: "", key_path: ""}
ssl_client_auth: {enabled: true, ca_cert: '/etc/ssl/certs/ca.crt', force_cn: 'server.example.com'}
letsencrypt: {enabled: false, email: 'admin@example.com'}
hsts: {max_age: 63072000, includeSubDomains: true}
basic_auth: {user: 'user', password: 'pass', message: 'AUTHENTICATE'}
log: {syslog: false, access_fmt: 'combined', error_fmt: 'error'}
error_pages:
- { codes: ['502', '503'], location: "/usr/share/error", site: "/unavailable.html" }
nginx_revproxy_sites:
- fqdn_: site.example.com:
location_to_upstream:
- {protocol: 'http', location: /grafana, addrs: ['127.0.0.1:3000'], additional_options: ['proxy_set_header Authorization ""'], pass_normalized_uri: true}
- {protocol: 'http', location: /prometheus, addrs: ['127.0.0.1:9090'], upstream_location: /prometheus, pass_normalized_uri: true}
letsencrypt: {enabled: true, email: 'admin@site.com'}
nginx_revproxy_sites:
- fqdn_: server3.example.com
serves_static_default: true
letsencrypt: {enabled: true, email: 'admin@site.com'}
- fqdn_: site.example.com:
location_to_upstream:
- {protocol: 'http', location: /grafana, addrs: ['127.0.0.1:3000'], additional_options: ['proxy_set_header Authorization ""']}
- {protocol: 'http', location: /prometheus, addrs: ['127.0.0.1:9090'], upstream_location: /prometheus}
letsencrypt: {enabled: true, email: 'admin@site.com'}
This example enforces authentication for external connections while allowing connections without authentication on localhost.
nginx_revproxy_sites:
- fqdn_: site.example.com:
listen: {ipv4: 192.168.10.1} # not specifying ipv6 will listen globally ([::])
location_to_upstream:
- {protocol: 'http', location: /grafana, addrs: ['127.0.0.1:3000'], additional_options: ['proxy_set_header Authorization ""']}
- {protocol: 'http', location: /prometheus, addrs: ['127.0.0.1:9090'], upstream_location: /prometheus}
letsencrypt: {enabled: true, email: 'admin@site.com'}
basic_auth: {user: 'user', password: 'pass, message: 'AUTHENTICATE'}
log: {syslog: true, access_fmt: 'graylog2_json' , error_fmt: 'error'}
- fqdn_: site.example.com_: # trailing r'_+' will be stripped. This allows multiple servers with the same server name
listen: {ipv4: 127.0.0.1, ipv6: false} # ipv6 disabled
location_to_upstream:
- {protocol: 'http', location: /grafana, addrs: ['127.0.0.1:3000'], additional_options: ['proxy_set_header Authorization ""']}
- {protocol: 'http', location: /prometheus, addrs: ['127.0.0.1:9090'], upstream_location: /prometheus}
log: {syslog: true, access_fmt: 'graylog2_json' , error_fmt: 'error'}
You can configure upstream TLS, optionally with mutual authentication. The role does not take care of copying certificates to the servers.
nginx_revproxy_sites:
- fqdn_: site1.example.com
location_to_upstream:
- {protocol: 'https', location: /, addrs: ['backend.example.com:443']}
# Presents a client certificate to the upstream, accepts upstream server certs of the specified CA
tls_to_upstream: {client_auth: true, cert: '/etc/ssl/web/site1.example.com.crt', key: '/etc/ssl/web/site1.example.com.key', cacert: '/etc/ssl/web/examplecom_webca.crt'}
letsencrypt: {enabled: true, email: 'admin@example.com'}
hsts: {max_age: 63072000, includeSubDomains: true}
log: {syslog: true, access_fmt: 'splunk_kv' , error_fmt: 'error'}
- fqdn_: site2.example.com
location_to_upstream:
- {protocol: 'https', location: /, addrs: ['10.0.0.3:8000']}
# Does not present a client certificate to the upstream, accepts upstream server certs of the specified CA
tls_to_upstream: {client_auth: false, cacert: '/etc/ssl/web/examplecom_webca.crt'}
letsencrypt: {enabled: true, email: 'admin@example.com'}
hsts: {max_age: 63072000, includeSubDomains: true}
log: {syslog: true, access_fmt: 'splunk_kv' , error_fmt: 'error'}
You can configure some resources to be served locally by either using the above webroot statements, or alias statements.
nginx_revproxy_sites:
- fqdn_: site1.example.com
location_to_upstream:
- {location: "/mailman3/static/favicon.ico", alias: "/var/lib/mailman3/web/static/postorius/img/favicon.ico", no_trail_slash: true}
- {location: "/mailman3/static", alias: "/var/lib/mailman3/web/static"}
- {protocol: 'https', location: /, addrs: ['backend.example.com:443']}
# Presents a client certificate to the upstream, accepts upstream server certs of the specified CA
tls_to_upstream: {client_auth: true, cert: '/etc/ssl/web/site1.example.com.crt', key: '/etc/ssl/web/site1.example.com.key', cacert: '/etc/ssl/web/examplecom_webca.crt'}
letsencrypt: {enabled: true, email: 'admin@example.com'}
hsts: {max_age: 63072000, includeSubDomains: true}
log: {syslog: true, access_fmt: 'splunk_kv' , error_fmt: 'error'}