Anton Shestakov <engored@ya.ru>, Thu, 21 Jan 2016 01:50:21 +0800
roles: common, interactive, memcached, nginx, email
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/roles/nginx/defaults/main.yml Thu Jan 21 01:50:21 2016 +0800
+munin_nginx_vhosts: munin.{{ hostname }}
+munin_pkcs12_pass: big dumb passphrase
+ value: '{{ hostname }}'
+ value: hostmaster@{{ hostname }}
+ value: Munin for {{ hostname }}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/roles/nginx/files/etc/munin/plugins/nginx_requests_by_vhost Thu Jan 21 01:50:21 2016 +0800
+. $MUNIN_LIBDIR/plugins/plugin.sh
+ echo "no (quick hacky plugin)"
+ echo "graph_title Nginx requests by vhost"
+ echo 'graph_args --base 1000'
+ echo 'graph_vlabel requests / ${graph_period}'
+ echo 'graph_category nginx'
+ for vhost in $vhosts; do
+ name="$(clean_fieldname "$vhost")"
+ echo "${name}.label ${vhost}"
+ echo "${name}.type DERIVE"
+ echo "${name}.draw LINE1"
+for vhost in $vhosts; do
+ name="$(clean_fieldname "$vhost")"
+ echo "${name}.value $(wc -l /var/log/nginx/${vhost}.access.log | cut -d' ' -f1)"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/roles/nginx/files/etc/nginx/sites-available/nginx_status Thu Jan 21 01:50:21 2016 +0800
+ location /nginx_status {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/roles/nginx/handlers/main.yml Thu Jan 21 01:50:21 2016 +0800
+ service: name=nginx state=restarted
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/roles/nginx/tasks/easy-rsa.yml Thu Jan 21 01:50:21 2016 +0800
+- name: Set up a local easy-rsa certificates directory
+ command: make-cadir /etc/nginx/easy-rsa/
+ creates: /etc/nginx/easy-rsa/
+- name: Editing vars in-place
+ lineinfile: dest=/etc/nginx/easy-rsa/vars
+ regexp: '^export KEY_{{ item.key }}="'
+ line: 'export KEY_{{ item.key }}="{{ item.value }}"'
+ with_items: munin_ca_vars
+- name: Running clean-all
+ shell: . ./vars && ./clean-all
+ chdir: /etc/nginx/easy-rsa/
+ creates: /etc/nginx/easy-rsa/keys/index.txt
+- name: Running build-ca
+ shell: . ./vars && ./build-ca --batch
+ chdir: /etc/nginx/easy-rsa/
+ creates: /etc/nginx/easy-rsa/keys/ca.key
+- name: Running build-key-server
+ shell: . ./vars && ./build-key-server --batch munin.{{ hostname }}
+ chdir: /etc/nginx/easy-rsa/
+ creates: /etc/nginx/easy-rsa/keys/munin.{{ hostname }}.key
+- name: Running build-key
+ shell: . ./vars && ./build-key --batch munin.{{ hostname }}.{{ item }}
+ chdir: /etc/nginx/easy-rsa/
+ creates: /etc/nginx/easy-rsa/keys/munin.{{ hostname }}.{{ item }}.key
+ with_items: munin_clients
+- name: Export client certificate as a PKCS#12 file
+ -out /etc/nginx/easy-rsa/keys/munin.{{ hostname }}.{{ item }}.p12
+ -inkey /etc/nginx/easy-rsa/keys/munin.{{ hostname }}.{{ item }}.key
+ -in /etc/nginx/easy-rsa/keys/munin.{{ hostname }}.{{ item }}.crt
+ -certfile /etc/nginx/easy-rsa/keys/ca.crt
+ -passout 'pass:{{ munin_pkcs12_pass }}'
+ creates: /etc/nginx/easy-rsa/keys/munin.{{ hostname }}.{{ item }}.p12
+ with_items: munin_clients
+- name: Fetch the resulting PKCS#12 file
+ fetch: src=/etc/nginx/easy-rsa/keys/munin.{{ hostname }}.{{ item }}.p12 dest=./pkcs12/ flat=yes fail_on_missing=yes
+ with_items: munin_clients
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/roles/nginx/tasks/main.yml Thu Jan 21 01:50:21 2016 +0800
+- name: Install packages
+ apt: pkg={{ item }} state=present
+ - easy-rsa # for munin certificate auth
+ - libwww-perl # for munin plugins
+ tags: [packages, inert]
+- name: Disable default site
+ file: path=/etc/nginx/sites-enabled/default state=absent
+- name: Add nginx status server
+ copy: src=etc/nginx/sites-available/nginx_status dest=/etc/nginx/sites-available/nginx_status
+ file: src=/etc/nginx/sites-available/nginx_status dest=/etc/nginx/sites-enabled/nginx_status state=link
+- name: Enable Nginx status server
+- name: Create a Diffie-Hellman key exchange parameters file
+ {% if ansible_virtualization_type == "virtualbox" %}-dsaparam{% endif %}
+ -out /etc/nginx/dh-2048.pem
+ creates: /etc/nginx/dh-2048.pem
+- name: Extract information for HPKP header
+ shell: openssl rsa -in /etc/nginx/easy-rsa/keys/{{ item }} -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64
+ - munin.{{ hostname }}.key
+ failed_when: "'unable' in hpkpinfo.stderr"
+- name: Add munin.{{ hostname }}
+ template: src=etc/nginx/sites-available/munin dest=/etc/nginx/sites-available/munin.{{ hostname }}
+- name: Enable munin.{{ hostname }}
+ file: src=/etc/nginx/sites-available/munin.{{ hostname }} dest=/etc/nginx/sites-enabled/99munin.{{ hostname }} state=link
+- name: Enable extra Munin plugins
+ file: src=/usr/share/munin/plugins/{{ item }} dest=/etc/munin/plugins/{{ item }} state=link
+- name: Copy custom Nginx-related Munin plugins
+ copy: src=etc/munin/plugins/{{ item }} dest=/etc/munin/plugins/{{ item }} mode=0755
+ - nginx_requests_by_vhost
+- name: Configure custom Munin plugins
+ template: src=etc/munin/plugin-conf.d/{{ item }} dest=/etc/munin/plugin-conf.d/{{ item }}
+ - nginx_requests_by_vhost
+- name: Monitor Nginx with Monit
+ file: src=/etc/monit/monitrc.d/nginx dest=/etc/monit/conf.d/nginx state=link
+- name: Allow HTTP and HTTPS
+ ufw: rule=allow name='{{ item }}'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/roles/nginx/templates/etc/munin/plugin-conf.d/nginx_requests_by_vhost Thu Jan 21 01:50:21 2016 +0800
+[nginx_requests_by_vhost]
+env.vhosts {{ munin_nginx_vhosts }}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/roles/nginx/templates/etc/nginx/sites-available/munin Thu Jan 21 01:50:21 2016 +0800
+ server_name munin.{{ hostname }};
+ access_log /var/log/nginx/munin.{{ hostname }}.access.log;
+ error_log /var/log/nginx/munin.{{ hostname }}.error.log;
+ return 301 https://munin.{{ hostname }}$request_uri;
+ server_name munin.{{ hostname }};
+ listen [::]:443 ssl spdy;
+ ssl_certificate /etc/nginx/easy-rsa/keys/munin.{{ hostname }}.crt;
+ ssl_certificate_key /etc/nginx/easy-rsa/keys/munin.{{ hostname }}.key;
+ ssl_trusted_certificate /etc/nginx/easy-rsa/keys/ca.crt;
+ ssl_client_certificate /etc/nginx/easy-rsa/keys/ca.crt; # XXX: should work without this?
+ ssl_dhparam /etc/nginx/dh-2048.pem;
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ # access from <frame | iframe | object>: DENY | SAMEORIGIN | ALLOW-FROM uri
+ add_header X-Frame-Options 'SAMEORIGIN';
+ # HPKP: 5184000 = 60 days
+ add_header Public-Key-Pins '{% for r in hpkpinfo.results %}pin-sha256="{{ r.stdout }}"; {% endfor %}max-age=5184000';
+ # HSTS: 31536000 = 365 days (set to 0 to expire and allow plain HTTP)
+ add_header Strict-Transport-Security 'max-age=31536000';
+ # Content-Security-Policy-Report-Only: default-src https:; script-src https: 'unsafe-eval' 'unsafe-inline'; style-src https: 'unsafe-inline'; img-src https: data:; font-src https: data:; report-uri /csp-report
+ add_header Cache-Control private;
+ access_log /var/log/nginx/munin.{{ hostname }}.access.log;
+ error_log /var/log/nginx/munin.{{ hostname }}.error.log;
+ root /var/cache/munin/www;