From 496885341d35ba52236d407c7cee6c3ecd3bdbc8 Mon Sep 17 00:00:00 2001 From: Jeremy Lecour Date: Fri, 30 Sep 2016 10:59:00 +0200 Subject: [PATCH] add an nginx role --- nginx/README.md | 18 +++ nginx/defaults/main.yml | 8 ++ nginx/files/init.d/spawn-fcgi-munin-graph | 130 ++++++++++++++++++ .../files/munin/plugin-conf.d/evolinux.nginx | 2 + nginx/files/nginx/snippets/private_htpasswd | 1 + .../nginx/snippets/private_ipaddr_whitelist | 1 + nginx/handlers/main.yml | 16 +++ nginx/tasks/configure_munin.yml | 52 +++++++ nginx/tasks/create_default_cert.yml | 18 +++ nginx/tasks/main.yml | 108 +++++++++++++++ nginx/templates/default_site.j2 | 56 ++++++++ nginx/templates/nginx.conf.j2 | 88 ++++++++++++ 12 files changed, 498 insertions(+) create mode 100644 nginx/README.md create mode 100644 nginx/defaults/main.yml create mode 100644 nginx/files/init.d/spawn-fcgi-munin-graph create mode 100644 nginx/files/munin/plugin-conf.d/evolinux.nginx create mode 100644 nginx/files/nginx/snippets/private_htpasswd create mode 100644 nginx/files/nginx/snippets/private_ipaddr_whitelist create mode 100644 nginx/handlers/main.yml create mode 100644 nginx/tasks/configure_munin.yml create mode 100644 nginx/tasks/create_default_cert.yml create mode 100644 nginx/tasks/main.yml create mode 100644 nginx/templates/default_site.j2 create mode 100644 nginx/templates/nginx.conf.j2 diff --git a/nginx/README.md b/nginx/README.md new file mode 100644 index 00000000..cd837265 --- /dev/null +++ b/nginx/README.md @@ -0,0 +1,18 @@ +# nginx + +Install Nginx. + +## Tasks + +Everything is in the `tasks/main.yml` file. + +## Available variables + +Main variables are : + +* `nginx_worker_processes` : number of worker processes ; +* `nginx_default_redirect_url` : URL to redirect to in case of error ; +* `nginx_ipaddr_whitelist_present` : list of IP addresses to have in the whitelist. +* `nginx_ipaddr_whitelist_absent` : list of IP addresses **not** to have in the whitelist. + +The full list of variables (with default values) can be found in `defaults/main.yml`. diff --git a/nginx/defaults/main.yml b/nginx/defaults/main.yml new file mode 100644 index 00000000..590ff298 --- /dev/null +++ b/nginx/defaults/main.yml @@ -0,0 +1,8 @@ +nginx_worker_processes: '{{ ansible_processor_vcpus }}' +nginx_default_redirect_url: "http://evolix.fr" + +nginx_private_ipaddr_whitelist_present: [] +nginx_private_ipaddr_whitelist_absent: [] + +nginx_private_htpasswd_present: [] +nginx_private_htpasswd_absent: [] diff --git a/nginx/files/init.d/spawn-fcgi-munin-graph b/nginx/files/init.d/spawn-fcgi-munin-graph new file mode 100644 index 00000000..7d5d6055 --- /dev/null +++ b/nginx/files/init.d/spawn-fcgi-munin-graph @@ -0,0 +1,130 @@ +#! /bin/sh + +### BEGIN INIT INFO +# Provides: spawn-fcgi-munin-graph +# Required-Start: $all +# Required-Stop: $all +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Description: starts FastCGI for Munin-Graph +### END INIT INFO +# -------------------------------------------------------------- +# Munin-CGI-Graph Spawn-FCGI Startscript by Julien Schmidt +# eMail: munin-trac at julienschmidt.com +# www: http://www.julienschmidt.com +# -------------------------------------------------------------- +# Install: +# 1. Copy this file to /etc/init.d +# 2. Edit the variables below +# 3. run "update-rc.d spawn-fcgi-munin-graph defaults" +# -------------------------------------------------------------- +# Special thanks for their help to: +# Frantisek Princ +# J�r�me Warnier +# -------------------------------------------------------------- +# Last Update: 14. February 2013 +# +# Please change the following variables: + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +NAME=spawn-fcgi-munin-graph +PID_FILE=/var/run/munin/$NAME.pid +SOCK_FILE=/var/run/munin/$NAME.sock +SOCK_USER=www-data +FCGI_USER=munin +FCGI_GROUP=munin +FCGI_WORKERS=2 +DAEMON=/usr/bin/spawn-fcgi +DAEMON_OPTS="-s $SOCK_FILE -F $FCGI_WORKERS -U $SOCK_USER -u $FCGI_USER -g $FCGI_GROUP -P $PID_FILE -- /usr/lib/munin/cgi/munin-cgi-graph" + +# -------------------------------------------------------------- +# No edits necessary beyond this line +# -------------------------------------------------------------- + +if [ ! -x $DAEMON ]; then + echo "File not found or is not executable: $DAEMON!" + exit 0 +fi + +status() { + if [ ! -r $PID_FILE ]; then + return 1 + fi + + for FCGI_PID in `cat $PID_FILE`; do + if [ -z "${FCGI_PID}" ]; then + return 1 + fi + + FCGI_RUNNING=`ps -p ${FCGI_PID} | grep ${FCGI_PID}` + if [ -z "${FCGI_RUNNING}" ]; then + return 1 + fi + done; + + return 0 +} + +start() { + if status; then + echo "FCGI is already running!" + exit 1 + else + $DAEMON $DAEMON_OPTS + fi +} + +stop () { + if ! status; then + echo "No PID-file at $PID_FILE found or PID not valid. Maybe not running" + exit 1 + fi + + # Kill processes + for PID_RUNNING in `cat $PID_FILE`; do + kill -9 $PID_RUNNING + done + + # Remove PID-file + rm -f $PID_FILE + + # Remove Sock-File + rm -f $SOCK_FILE +} + +case "$1" in + start) + echo "Starting $NAME: " + start + echo "... DONE" + ;; + + stop) + echo "Stopping $NAME: " + stop + echo "... DONE" + ;; + + force-reload|restart) + echo "Stopping $NAME: " + stop + echo "Starting $NAME: " + start + echo "... DONE" + ;; + + status) + if status; then + echo "FCGI is RUNNING" + else + echo "FCGI is NOT RUNNING" + fi + ;; + + *) + echo "Usage: $0 {start|stop|force-reload|restart|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/nginx/files/munin/plugin-conf.d/evolinux.nginx b/nginx/files/munin/plugin-conf.d/evolinux.nginx new file mode 100644 index 00000000..c505f929 --- /dev/null +++ b/nginx/files/munin/plugin-conf.d/evolinux.nginx @@ -0,0 +1,2 @@ +[nginx_*] +env.url http://munin/nginx_status diff --git a/nginx/files/nginx/snippets/private_htpasswd b/nginx/files/nginx/snippets/private_htpasswd new file mode 100644 index 00000000..0c16dd41 --- /dev/null +++ b/nginx/files/nginx/snippets/private_htpasswd @@ -0,0 +1 @@ +# user:password for HTTP Basic authentication diff --git a/nginx/files/nginx/snippets/private_ipaddr_whitelist b/nginx/files/nginx/snippets/private_ipaddr_whitelist new file mode 100644 index 00000000..0d7aeab9 --- /dev/null +++ b/nginx/files/nginx/snippets/private_ipaddr_whitelist @@ -0,0 +1 @@ +# Whitelisted IP addresses, used in default site… diff --git a/nginx/handlers/main.yml b/nginx/handlers/main.yml new file mode 100644 index 00000000..a0ed6523 --- /dev/null +++ b/nginx/handlers/main.yml @@ -0,0 +1,16 @@ + +--- +- name: restart nginx + service: + name: nginx + state: restarted + +- name: reload nginx + service: + name: nginx + state: reloaded + +- name: restart munin + service: + name: munin-node + state: restarted diff --git a/nginx/tasks/configure_munin.yml b/nginx/tasks/configure_munin.yml new file mode 100644 index 00000000..0b75af18 --- /dev/null +++ b/nginx/tasks/configure_munin.yml @@ -0,0 +1,52 @@ +--- +- name: Add munin to hosts + lineinfile: + dest: /etc/hosts + regexp: 'munin$' + line: '127.0.0.1 munin' + +- name: Copy Munin config for Nginx + copy: + src: munin/plugin-conf.d/evolinux.nginx + dest: /etc/munin/plugin-conf.d/ + mode: 0644 + notify: restart munin + +- name: Enable Munin plugins for Nginx + file: + src: '/usr/share/munin/plugins/{{ item }}' + dest: '/etc/munin/plugins/{{ item }}' + state: link + with_items: + - nginx_request + - nginx_status + notify: restart munin + +- name: Ensure packages for Munin CGI are installed + apt: + name: '{{ item }}' + state: installed + with_items: + - liblwp-useragent-determined-perl + - spawn-fcgi + +- name: Adjust rights for munin-cgi + file: + path: '{{ item }}' + owner: munin + group: adm + with_fileglob: + - /var/log/munin/munin-cgi-* + +- name: Install Init script for Munin-fcgi + copy: + src: init.d/spawn-fcgi-munin-graph + dest: /etc/init.d/ + mode: 0755 + +- name: Ensure that Munin-fcgi is started/stopped correctly + service: + name: spawn-fcgi-munin-graph + enabled: yes + state: started + notify: restart spawn-fcgi-munin-graph diff --git a/nginx/tasks/create_default_cert.yml b/nginx/tasks/create_default_cert.yml new file mode 100644 index 00000000..be019b9f --- /dev/null +++ b/nginx/tasks/create_default_cert.yml @@ -0,0 +1,18 @@ +--- +- name: Verify that ssl-cert is installed + apt: + name: ssl-cert + state: installed + +- name: Create private key for default site ({{ ansible_fqdn }}) + shell: openssl req -newkey rsa:2048 -sha256 -nodes -keyout /etc/ssl/private/{{ ansible_fqdn }}.key -out /etc/ssl/{{ ansible_fqdn }}.csr -batch -subj "/C=FR/ST=PACA/L=Marseille/O=Evolix/CN={{ ansible_fqdn }}/emailAddress=security@evolix.net" 2>/dev/null + +- name: Adjust rights on private key + file: + path: /etc/ssl/private/{{ ansible_fqdn }}.key + owner: root + group: ssl-cert + mode: 0640 + +- name: Create certificate for default site + shell: openssl x509 -req -days 3650 -sha256 -in /etc/ssl/{{ ansible_fqdn }}.csr -signkey /etc/ssl/private/{{ ansible_fqdn }}.key -out /etc/ssl/certs/{{ ansible_fqdn }}.crt 2>/dev/null diff --git a/nginx/tasks/main.yml b/nginx/tasks/main.yml new file mode 100644 index 00000000..c11711f0 --- /dev/null +++ b/nginx/tasks/main.yml @@ -0,0 +1,108 @@ +--- +- name: Ensure Nginx is installed + apt: + name: nginx-full + state: installed + notify: restart nginx + tags: + - nginx + +- name: Install Nginx configuration + template: + src: nginx.conf.j2 + dest: /etc/nginx/nginx.conf + mode: 0640 + # force: yes + notify: reload nginx + tags: + - nginx + +- name: Copy snippets + copy: + src: nginx/snippets/ + dest: /etc/nginx/snippets/ + directory_mode: 0640 + mode: 0640 + # force: yes + notify: reload nginx + tags: + - nginx + +- name: add IP addresses to private IP whitelist + lineinfile: + dest: /etc/nginx/snippets/private_ipaddr_whitelist + line: "allow {{ item }};" + state: present + with_items: "{{ nginx_private_ipaddr_whitelist_present }}" + +- name: remove IP addresses from private IP whitelist + lineinfile: + dest: /etc/nginx/snippets/private_ipaddr_whitelist + line: "allow {{ item }};" + state: absent + with_items: "{{ nginx_private_ipaddr_whitelist_absent }}" + +- name: add user:pwd to private htpasswd + lineinfile: + dest: /etc/nginx/snippets/private_htpasswd + line: "{{ item }}" + state: present + with_items: "{{ nginx_private_htpasswd_present }}" + +- name: remove user:pwd from private htpasswd + lineinfile: + dest: /etc/nginx/snippets/private_htpasswd + line: "{{ item }}" + state: absent + with_items: "{{ nginx_private_htpasswd_absent }}" + +- name: Check if a certificate is present for default site + stat: + path: /etc/ssl/certs/{{ ansible_fqdn }}.crt + register: stat_crt + tags: + - nginx + +- include: create_default_cert.yml + when: not stat_crt.stat.exists + tags: + - nginx + +- name: Install Nginx default site + template: + src: default_site.j2 + dest: /etc/nginx/sites-available/default + mode: 0640 + # force: yes + notify: reload nginx + tags: + - nginx + +- name: Enable Nginx default site + file: + src: /etc/nginx/sites-available/default + dest: /etc/nginx/sites-enabled/default + state: link + notify: reload nginx + tags: + - nginx + +- name: Verify that the service is enabled and started + service: + name: nginx + enabled: yes + state: started + tags: + - nginx + +- name: Check if Munin is installed + stat: + path: /etc/munin/plugin-conf.d/munin-node + register: stat_munin_node + tags: + - munin + +- include: configure_munin.yml + when: stat_munin_node.stat.exists + tags: + - munin diff --git a/nginx/templates/default_site.j2 b/nginx/templates/default_site.j2 new file mode 100644 index 00000000..1e1ceab5 --- /dev/null +++ b/nginx/templates/default_site.j2 @@ -0,0 +1,56 @@ +server { + + listen [::]:80; + listen 80; + server_name {{ ansible_fqdn }}; + return 301 https://{{ ansible_fqdn }}$request_uri; +} +server { + + listen 443 ssl spdy; + # listen [::]:80 default_server ipv6only=on; ## listen for ipv6 + + ssl_certificate /etc/ssl/certs/{{ ansible_fqdn }}.crt; + ssl_certificate_key /etc/ssl/private/{{ ansible_fqdn }}.key; + + server_name {{ ansible_fqdn }}; + index index.htm index.html index.php; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + error_page 403 {{ nginx_default_redirect_url }}; + + root /var/www; + + # Auth. + include /etc/nginx/snippets/private_ipaddr_whitelist; + deny all; + auth_basic "Reserved {{ ansible_fqdn }}"; + auth_basic_user_file /etc/nginx/snippets/private_htpasswd; + satisfy any; + + location / { + index index.html index.htm; + } + + location /munin/ { + alias /var/cache/munin/www/; + } + + location ^~ /munin-cgi/munin-cgi-graph/ { + fastcgi_split_path_info ^(/munin-cgi/munin-cgi-graph)(.*); + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_pass unix:/var/run/munin/spawn-fcgi-munin-graph.sock; + include fastcgi_params; + } +} + +server { + listen 80; + server_name munin; + + location /nginx_status { + stub_status on; + access_log off; + } +} diff --git a/nginx/templates/nginx.conf.j2 b/nginx/templates/nginx.conf.j2 new file mode 100644 index 00000000..d58a230a --- /dev/null +++ b/nginx/templates/nginx.conf.j2 @@ -0,0 +1,88 @@ +user www-data; +worker_processes {{ nginx_worker_processes }}; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + #multi_accept on; + use epoll; +} + +http { + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + + ## + # Tuning Evolix + ## + #connection_pool_size 256; + #client_header_buffer_size 64k; + #client_body_buffer_size 128k; + #large_client_header_buffers 8 16k; + #request_pool_size 4k; + #client_header_timeout 10m; + #client_body_timeout 10m; + #send_timeout 10m; + #client_max_body_size 50m; + server_tokens off; + server_names_hash_max_size 512; + server_names_hash_bucket_size 128; + server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # Gzip Settings + ## + + gzip on; + gzip_disable "msie6"; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; + + index index.html; + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access_log; + error_log /var/log/nginx/error_log; + + ## + # nginx-naxsi config + ## + # Uncomment it if you installed nginx-naxsi + ## + + #include /etc/nginx/naxsi_core.rules; + + ## + # nginx-passenger config + ## + # Uncomment it if you installed nginx-passenger + ## + + #passenger_root /usr; + #passenger_ruby /usr/bin/ruby; + + ## + # Virtual Host Configs + ## + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +}