These roles are intended for a single-purpose host that acts as an internet-facing proxy/router service, which protects internal apps.
- Routing multiple domains to (internal) ips
- SSL termination with up2date cipherlist and HTTP/2, optional force-ssl redirect
- automatic issuing of missing ssl certificates if requested
requires Ubuntu 16.04+
- Ubuntu 16.04 ships a nginx version with http2 but without Brotli, which we will compile
This module consists of 2 independent submodules:
- Installs nginx from (Ubuntu)-Source with enabled ngx_brotli support
- hosts: router
roles:
- role: pludoni.nginx_app_proxy/nginx_brotli
nginx_conf_extra:
# create extra files under /etc/nginx/conf.d/brotli
brotli:
# there are already gzip and proxy headers enabled, just e.g.
- brotli on
- brotli_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript
Note Brotli on-the-fly encoding is disabled by default. It will only be active if you enable the option in a conf.d/*.conf like shown above.
All Brotli-options here: https://github.com/google/ngx_brotli
- Creates an unpriviliged user that will run the certificate request and have hold of the ssl certificates/keys
- hosts: router
roles:
- role: pludoni.nginx_app_proxy/letsencrypt
# for Letsencrypt registration, Letsencrypt will write you emails if your certificates are about to expire
letsencrypt_email: [email protected]
# create http basic htpasswd files
nginx_basic_auth_users:
- { name: "admin", password: "password123", file: "/etc/nginx/backend.passwd" }
routings:
# a list of http/https hosts which are bundled together
- name: myservice1
# target ip
target: '10.10.10.3'
# issue letsencrypt certificate and add to cronjob
letsencrypt: true
# redirect all http -> https traffic and enable HSTS
force_ssl: true
domains:
- mydomain.de
- www.mydomain.de
# variant 2: NO Letsencrypt but manually uploaded ssl certs (must to by yourself before)
# also overwrite some configs
- name: myservice2
target: '10.10.10.2'
ssl_key: '/etc/ssl/main.key'
ssl_crt: '/etc/ssl/combined.crt'
proxy_read_timeout: 120s
proxy_send_timeout: 120s
client_max_body_size: 50M
# chunked transfer encoding allowing (docker registry, upload etc.)
chunked_transfer: yes
# allow long upload
proxy_read_timeout: 900
# allow http upgrade
websocket: yes
# enable http basic auth with predefined password files
http_basic_auth_section: |
auth_basic "closed site";
auth_basic_user_file /etc/nginx/backend.passwd;
domains:
- myservice1.de
- www.myservice1.de
- en.myservice1.de
-
Each routing will receive its own logfiles under /var/log/nginx/NAME/[access|error].log with logrotate.
-
There are several cronjobs:
- Every month or so, letsencrypt will update the certificates that are running out in the current month
- Every day, all certificates and private keys are packaged as a .tar.gz and put to /backup
-
You can download that seed file every so often and use it, if you are making a new host use that seedfile:
letsencrypt_seed_file: "{{playbook_dir}}/files/letsencrypt-data.tar.gz"
- It will uploaded/unzipped once.
- Uses SSL local session cache, so if you have more than 40.000 clients / 10minute window, that cache will be empty. Then switching to session tickets would help, or reducing that timeout in
letsencrypt/templates/nginx-ssl.conf
- This router doesnt add security headers X-Frame-Options or Content-Type Options by default. For our uses, we need some apps that need to be embeddable and our app server add that header anyways.
- No real "Load Balancer" at the moment. Target can only be one IP.
- Uses the "Legacy config" from https://cipherli.st/, which still supports IE < 9 and Android 2.3.
- There is a locally tested Fail2Ban jail config which can be run as another role:
- role: pludoni.nginx_app_proxy/fail2ban
letsencrypt_email: [email protected]
fail2ban_ignoreip: 127.0.0.1/8 10.0.0.0/8
fail2ban_destmail: admin@localhost
fail2ban_sender: "{{fail2ban_destmail}}"
fail2ban_mta: "sendmail"
As the letsencrypt role modifies the nginx default access logs to include the hostname and more information, the fail2ban also needed some adjustments. Most important is the nginx-noscript Fail2Ban Jail, which will block out spider that are looking for missing scripts, like wp-admin, wp-login, phpmyadmin etc.
There are another 2 jails, nginx-home (for blocking crawler that querying /~) and badbots, but those are less valuable.
You can read more about this here: https://www.digitalocean.com/community/tutorials/how-to-protect-an-nginx-server-with-fail2ban-on-ubuntu-14-04