diff --git a/host_vars/srv02.yml b/host_vars/srv02.yml new file mode 100644 index 0000000000000000000000000000000000000000..56d017d2c82db5068b812f4be3e9594971f24ba4 --- /dev/null +++ b/host_vars/srv02.yml @@ -0,0 +1,10 @@ +nginx: + enabled_sites: + - default + - ffhl-status + - firmware + - git.luebeck.freifunk.net + - grafana + - hopglass-map + - luebeck.freifunk.net + - wiki diff --git a/roles/services/files/nginx/sites-available/default b/roles/services/files/nginx/sites-available/default new file mode 100644 index 0000000000000000000000000000000000000000..93c2bed2b028ce6180754ab1627f3ea011d4275c --- /dev/null +++ b/roles/services/files/nginx/sites-available/default @@ -0,0 +1,17 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + root /var/www/html; + + index index.html index.htm index.nginx-debian.html; + + server_name _; + include snippets/acme.conf; + + location / { + try_files $uri $uri/ =404; + } + +} + diff --git a/roles/services/files/nginx/sites-available/ffhl-status b/roles/services/files/nginx/sites-available/ffhl-status new file mode 100644 index 0000000000000000000000000000000000000000..0d72611c0a77a14708458437b7ab5dcffa827825 --- /dev/null +++ b/roles/services/files/nginx/sites-available/ffhl-status @@ -0,0 +1,17 @@ +server { + listen 80; + listen [::]:80; + listen localhost:443 ssl http2; + listen [::]:443 ssl http2; + + server_name status.luebeck.freifunk.net status.ffhl.de status.ffhl; + + include snippets/acme.conf; + include snippets/tls.conf; + include snippets/https-redirect.conf; + + ssl_certificate /var/lib/acme/live/luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/luebeck.freifunk.net/privkey; + + root /var/www/ffhl-status; +} diff --git a/roles/services/files/nginx/sites-available/firmware b/roles/services/files/nginx/sites-available/firmware new file mode 100644 index 0000000000000000000000000000000000000000..ecb690c72ddbd85eddbf29bc65dd3979803769ba --- /dev/null +++ b/roles/services/files/nginx/sites-available/firmware @@ -0,0 +1,31 @@ +server { + listen 80; + listen [::]:80; + listen localhost:443 ssl http2; + listen [::]:443 ssl http2; + server_name firmware.luebeck.freifunk.net firmware.ffhl.de firmware.ffhl 1.updates.services.ffhl 1.updates.services.ffhl.de 1.updates.services.luebeck.freifunk.net; + + include snippets/acme.conf; + include snippets/tls.conf; + ssl_certificate /var/lib/acme/live/luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/luebeck.freifunk.net/privkey; + + + client_max_body_size 5m; + client_body_timeout 60; + + root /var/www/firmware; + + location / { + fancyindex on; + fancyindex_css_href /.fancyindex/style.css; + # fancyindex_header /.fancyindex/header.html; + # fancyindex_footer /.fancyindex/footer.html; + fancyindex_exact_size off; + } + + location /wizard { + alias /var/www/firmware-selector; + } +} + diff --git a/roles/services/files/nginx/sites-available/git.luebeck.freifunk.net b/roles/services/files/nginx/sites-available/git.luebeck.freifunk.net new file mode 100644 index 0000000000000000000000000000000000000000..24d7ec1f26ef1a44340893362bc2fd42639617a7 --- /dev/null +++ b/roles/services/files/nginx/sites-available/git.luebeck.freifunk.net @@ -0,0 +1,39 @@ +include snippets/geoblock.conf; + +server { + listen 80; + listen [::]:80; + listen localhost:443 ssl http2; + listen [::]:443 ssl http2; + + server_name git.ffhl git.luebeck.freifunk.net git.ffhl.de; + + # TLS + include snippets/acme.conf; + include snippets/tls.conf; + ssl_certificate /var/lib/acme/live/www.luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/www.luebeck.freifunk.net/privkey; + + if ($ssl_protocol = "") { + # force TLS + return 301 https://$host$request_uri; + } + + + client_max_body_size 256M; + + # apply geoblocking + if ($allowed_country = no) { + return 302 https://luebeck.freifunk.net/; + } + + location / { + proxy_set_header Host $host; + proxy_pass http://localhost:3001/; + proxy_connect_timeout 300; + proxy_send_timeout 300; + proxy_read_timeout 300; + send_timeout 300; + } +} + diff --git a/roles/services/files/nginx/sites-available/grafana b/roles/services/files/nginx/sites-available/grafana new file mode 100644 index 0000000000000000000000000000000000000000..49dabc312231998390e242f31b9a94c6988ebe3d --- /dev/null +++ b/roles/services/files/nginx/sites-available/grafana @@ -0,0 +1,58 @@ +proxy_cache_path /var/cache/nginx levels=1:2 inactive=10m max_size=1g keys_zone=grafana:1m; + +upstream backend { + server 127.0.0.1:3000; +# server cranberry.luebeck.freifunk.net:3000 backup; +} + +server { + listen 80; + listen [::]:80; + + listen localhost:443 ssl http2; + listen [::]:443 ssl http2; + + server_name monitor.luebeck.freifunk.net monitor.ffhl.de monitor.ffhl; + + include snippets/acme.conf; + include snippets/tls.conf; + ssl_certificate /var/lib/acme/live/luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/luebeck.freifunk.net/privkey; + + if ($ssl_protocol = "") { + return 301 https://$host$request_uri; + } + + location /render/ { + more_clear_headers 'Pragma'; + more_clear_headers 'Cache-Control'; + more_clear_headers 'Expires'; + more_clear_headers 'last-modified'; + + add_header X-Cache-Status $upstream_cache_status; + expires 10m; + proxy_cache_key "$host$request_uri"; + + proxy_connect_timeout 300; + proxy_send_timeout 300; + proxy_read_timeout 300; + send_timeout 300; + proxy_cache grafana; + proxy_cache_min_uses 5; + + proxy_hide_header Cache-Control; + proxy_hide_header Expires; + proxy_hide_header X-Accel-Expires; + proxy_cache_methods GET POST; + proxy_pass http://127.0.0.1:3000; + } + + location / { + proxy_connect_timeout 5; + proxy_send_timeout 5; + proxy_read_timeout 5; + send_timeout 5; + proxy_pass http://backend; + } +} + diff --git a/roles/services/files/nginx/sites-available/hopglass-map b/roles/services/files/nginx/sites-available/hopglass-map new file mode 100644 index 0000000000000000000000000000000000000000..7533c721aa6aaf0cd4b4e1c889eb76c222c38c14 --- /dev/null +++ b/roles/services/files/nginx/sites-available/hopglass-map @@ -0,0 +1,32 @@ +server { + listen 80; + listen [::]:80 ; + listen localhost:443 ssl http2; + listen [::]:443 ssl http2; + server_name map2.luebeck.freifunk.net map.luebeck.freifunk.net map.ffhl.de map.ffhl; + + include snippets/acme.conf; + include snippets/tls.conf; + ssl_certificate /var/lib/acme/live/www.luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/www.luebeck.freifunk.net/privkey; + + root /var/www/hopglass; + index index.html; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } + + # the hopglass-server is listening on localhost:4000 + # but the expect it to be at a public url + # so we just map /data to localhost:4000 + location /data/ { + proxy_pass http://localhost:4000/; + } + + location /requestd/ { + proxy_pass http://localhost:21001/; + } +} diff --git a/roles/services/files/nginx/sites-available/luebeck.freifunk.net b/roles/services/files/nginx/sites-available/luebeck.freifunk.net new file mode 100644 index 0000000000000000000000000000000000000000..323e8bc03beb6c44595757e4f11ca104f3d65d56 --- /dev/null +++ b/roles/services/files/nginx/sites-available/luebeck.freifunk.net @@ -0,0 +1,52 @@ +server { + listen 80; + listen [::]:80; + + listen localhost:443 ssl http2; + listen [::]:443 ssl http2; + + server_name luebeck.freifunk.net ffhl.de ffhl; + + include snippets/acme.conf; + include snippets/tls.conf; + include snippets/https-redirect.conf; + + ssl_certificate /var/lib/acme/live/luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/luebeck.freifunk.net/privkey; + + root /var/www/luebeck.freifunk.net; + + location ~ /map(/?.*) { + return 301 $scheme://map.luebeck.freifunk.net$1; + } + + location ~ /wiki(/?.*) { + return 301 https://wiki.luebeck.freifunk.net$1; + } + + location /firmware/ { + return 301 $scheme://firmware.luebeck.freifunk.net/; + } + + location /opkg/ { + return 301 $scheme://firmware.luebeck.freifunk.net/; + } + + location = /Moelln { + return 302 https://wiki.luebeck.freifunk.net/wiki/Moelln; + } +} + +server { + listen [::]:80; + listen [::]:443 ssl; + server_name xn--lbeck-kva.freifunk.net www.luebeck.freifunk.net www.ffhl.de; + + include snippets/acme.conf; + include snippets/tls.conf; + + ssl_certificate /var/lib/acme/live/www.luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/www.luebeck.freifunk.net/privkey; + + return 301 $scheme://luebeck.freifunk.net$request_uri; +} diff --git a/roles/services/files/nginx/sites-available/services b/roles/services/files/nginx/sites-available/services new file mode 100644 index 0000000000000000000000000000000000000000..bad2efa3de5adc0e220b4f090f31c4723c3ad2a6 --- /dev/null +++ b/roles/services/files/nginx/sites-available/services @@ -0,0 +1,24 @@ +server { + listen 80; + listen [::]:80; + + listen localhost:443 ssl http2; + listen [::]:443 ssl http2; + + server_name services.ffhl.de services.luebeck.freifunk.net; + + include tls.conf; + ssl_certificate /var/lib/acme/live/luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/luebeck.freifunk.net/privkey; + + if ($ssl_protocol = "") { + return 301 https://$host$request_uri; + } + + location / { + proxy_set_header HOST $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_pass https://yunohost.luebeck.freifunk.net; + } +} diff --git a/roles/services/files/nginx/sites-available/wiki b/roles/services/files/nginx/sites-available/wiki new file mode 100644 index 0000000000000000000000000000000000000000..7590be7747173521fbad8240afb7a4d240d59521 --- /dev/null +++ b/roles/services/files/nginx/sites-available/wiki @@ -0,0 +1,16 @@ +server { + listen 80; + listen [::]:80; + listen localhost:443 ssl http2; + listen [::]:443 ssl http2; + + server_name wiki.luebeck.freifunk.net wiki.ffhl.de wiki.ffhl; + + include snippets/acme.conf; + include snippets/tls.conf; + + ssl_certificate /var/lib/acme/live/luebeck.freifunk.net/fullchain; + ssl_certificate_key /var/lib/acme/live/luebeck.freifunk.net/privkey; + + root /var/www/wiki; +} diff --git a/roles/services/files/nginx/snippets/acme.conf b/roles/services/files/nginx/snippets/acme.conf new file mode 100644 index 0000000000000000000000000000000000000000..b5e924981859a5e363298a06e6278539536b1c51 --- /dev/null +++ b/roles/services/files/nginx/snippets/acme.conf @@ -0,0 +1,5 @@ +location ^~ /.well-known/acme-challenge/ { + default_type "text/plain"; + alias /var/www/acme-challenge/; +} + diff --git a/roles/services/files/nginx/snippets/fastcgi-php.conf b/roles/services/files/nginx/snippets/fastcgi-php.conf new file mode 100644 index 0000000000000000000000000000000000000000..467a9e732b89af205fff56ad19bcdadcaccf352f --- /dev/null +++ b/roles/services/files/nginx/snippets/fastcgi-php.conf @@ -0,0 +1,13 @@ +# regex to split $uri to $fastcgi_script_name and $fastcgi_path +fastcgi_split_path_info ^(.+?\.php)(/.*)$; + +# Check that the PHP script exists before passing it +try_files $fastcgi_script_name =404; + +# Bypass the fact that try_files resets $fastcgi_path_info +# see: http://trac.nginx.org/nginx/ticket/321 +set $path_info $fastcgi_path_info; +fastcgi_param PATH_INFO $path_info; + +fastcgi_index index.php; +include fastcgi.conf; diff --git a/roles/services/files/nginx/snippets/geoblock.conf b/roles/services/files/nginx/snippets/geoblock.conf new file mode 100644 index 0000000000000000000000000000000000000000..e886b0b3f40a0734b87010918c9fc4839e9aaa6a --- /dev/null +++ b/roles/services/files/nginx/snippets/geoblock.conf @@ -0,0 +1,4 @@ +map $geoip_country_code $allowed_country { + default yes; + IN no; #India +} diff --git a/roles/services/files/nginx/snippets/https-redirect.conf b/roles/services/files/nginx/snippets/https-redirect.conf new file mode 100644 index 0000000000000000000000000000000000000000..abc0131749b6e837a2ad3a37e3e4d632204d82ad --- /dev/null +++ b/roles/services/files/nginx/snippets/https-redirect.conf @@ -0,0 +1,4 @@ +# set this in the domain specific config +if ($ssl_protocol = "") { + return 301 https://$server_name$request_uri; +} diff --git a/roles/services/files/nginx/snippets/snakeoil.conf b/roles/services/files/nginx/snippets/snakeoil.conf new file mode 100644 index 0000000000000000000000000000000000000000..ad26c3e211f0061abcbc41e3fa7996a1c7cb76fe --- /dev/null +++ b/roles/services/files/nginx/snippets/snakeoil.conf @@ -0,0 +1,5 @@ +# Self signed certificates generated by the ssl-cert package +# Don't use them in a production server! + +ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; +ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; diff --git a/roles/services/files/nginx/snippets/tls.conf b/roles/services/files/nginx/snippets/tls.conf new file mode 100644 index 0000000000000000000000000000000000000000..03aca3483ea977a1e193962882889646c029803c --- /dev/null +++ b/roles/services/files/nginx/snippets/tls.conf @@ -0,0 +1,18 @@ +# only the best ciphers +ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; +ssl_prefer_server_ciphers off; +ssl_dhparam /etc/nginx/dhparam.pem; +ssl_protocols TLSv1.2 TLSv1.3; +ssl_session_timeout 1d; +ssl_session_cache shared:MozSSL:10m; # about 40000 sessions +ssl_session_tickets off; + +add_header Strict-Transport-Security "max-age=63072000" always; + + +# set this in the domain specific config +#if ($ssl_protocol = "") { +# return 301 https://$server_name$request_uri; +#} + + diff --git a/roles/services/tasks/main.yml b/roles/services/tasks/main.yml index 399967cd51bd0524fd1e4f74d91004f72fe7e2ef..cd2ed302b8288fb84c8c721777b2d03ed2e1f0b1 100644 --- a/roles/services/tasks/main.yml +++ b/roles/services/tasks/main.yml @@ -11,6 +11,10 @@ include: software.yml tags: [base, apt, software] -- name: install packages +- name: setup monitoring include: monitoring.yml tags: [base, apt, software] + +- name: setup nginx + include: nginx.yml + tags: [nginx] diff --git a/roles/services/tasks/nginx.yml b/roles/services/tasks/nginx.yml new file mode 100644 index 0000000000000000000000000000000000000000..dc9d90c574520a4c9ae8531463e36a9345c0a2b6 --- /dev/null +++ b/roles/services/tasks/nginx.yml @@ -0,0 +1,40 @@ +--- + +- name: install nginx + apt: + state: present + install_recommends: no + update_cache: yes + name: nginx-full + +- name: copy snippets + copy: + src: nginx/snippets + dest: /etc/nginx/ + +- name: copy available sites + copy: + src: nginx/sites-available + dest: /etc/nginx + + +- name: remove previous enabled sites + block: + - file: state=absent path="/etc/nginx/sites-enabled/" + - file: state=directory path="/etc/nginx/sites-enabled" + + +- name: enable selected sites + file: + state: link + src: "../sites-available/{{item}}" + dest: "/etc/nginx/sites-enabled/{{item}}" + with_items: "{{ nginx.enabled_sites }}" + +- name: restart nginx + systemd: + enabled: true + state: restarted + name: "{{item}}" + with_items: + - nginx