summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--ansible.cfg1
-rw-r--r--files/etc/nginx/sites-available/webmap124
-rw-r--r--files/etc/nginx/sites-enabled/webmap80
-rw-r--r--files/etc/postfix/master.cf44
-rw-r--r--files/etc/postfix/tls_policy2
-rw-r--r--files/etc/postgresql/postgresql.conf4
-rw-r--r--files/etc/systemd/system/webmap-cgi.service36
-rw-r--r--files/etc/systemd/system/webmap-cgi.socket11
-rw-r--r--files/etc/systemd/system/webmap-download@.service37
-rw-r--r--files/etc/systemd/system/webmap-import@.service37
-rw-r--r--files/etc/systemd/system/webmap-update@.target3
-rw-r--r--files/etc/systemd/system/webmap-update@.timer11
-rw-r--r--files/etc/tmpfiles.d/webmap.conf8
-rw-r--r--group_vars/all.yml25
-rw-r--r--handlers/main.yml12
-rw-r--r--setup.yml15
-rw-r--r--tasks/apt.yml9
-rw-r--r--tasks/base.yml4
-rw-r--r--tasks/httpd.yml19
-rw-r--r--tasks/mail.yml10
-rw-r--r--tasks/network.yml1
-rw-r--r--tasks/webmap.yml433
-rw-r--r--templates/etc/postfix/main.cf.j25
-rw-r--r--templates/etc/systemd/system/webmap-update@.timer.d/override.conf.j23
m---------webmap-tools0
26 files changed, 846 insertions, 91 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..a9b9b64
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "webmap-tools"]
+ path = webmap-tools
+ url = https://git.guilhem.org/KlimatanalysNorr/tools.git
diff --git a/ansible.cfg b/ansible.cfg
index a35402e..cf64db8 100644
--- a/ansible.cfg
+++ b/ansible.cfg
@@ -1,5 +1,6 @@
[defaults]
inventory = ./hosts.ini
+max_diff_size = 524288
[privilege_escalation]
become = True
diff --git a/files/etc/nginx/sites-available/webmap b/files/etc/nginx/sites-available/webmap
new file mode 100644
index 0000000..24ccdb9
--- /dev/null
+++ b/files/etc/nginx/sites-available/webmap
@@ -0,0 +1,124 @@
+server {
+ listen 80;
+ listen [::]:80;
+
+ server_name karta.klimatanalysnorr.se hel01.guilhem.se;
+
+ include /etc/lacme/nginx.conf;
+
+ access_log /var/log/nginx/access.log;
+ error_log /var/log/nginx/error.log warn;
+
+ location / {
+ return 301 https://$host$request_uri;
+ }
+}
+
+server {
+ listen 443;
+ listen [::]:443;
+
+ server_name hel01.guilhem.se;
+
+ access_log /var/log/nginx/access.log;
+ error_log /var/log/nginx/error.log warn;
+
+ ssl_certificate /etc/nginx/ssl/webmap.rsa.pem;
+ ssl_certificate_key /etc/nginx/ssl/webmap.rsa.key;
+ include snippets/ssl.conf;
+
+ location / {
+ return 303 https://karta.klimatanalysnorr.se$request_uri;
+ }
+}
+
+server {
+ listen 443 ssl http2 default_server;
+ listen [::]:443 ssl http2 default_server;
+
+ server_name karta.klimatanalysnorr.se;
+
+ access_log /var/log/nginx/access.log;
+ error_log /var/log/nginx/error.log warn;
+
+ ssl_certificate /etc/nginx/ssl/webmap.rsa.pem;
+ ssl_certificate_key /etc/nginx/ssl/webmap.rsa.key;
+ include snippets/ssl.conf;
+
+ root /var/www/webmap;
+ index index.html;
+
+ add_header Referrer-Policy "no-referrer";
+ add_header X-Frame-Options "DENY";
+ add_header X-Content-Type-Options "nosniff";
+ add_header X-XSS-Protection "1; mode=block";
+ add_header Strict-Transport-Security "max-age=31557600; includeSubDomains" always;
+ add_header Content-Security-Policy "default-src 'none'; frame-ancestors 'none'; form-action 'none'; base-uri 'self'";
+ #add_header Access-Control-Allow-Origin $http_origin always;
+
+ include mime.types;
+ types {
+ # application/protobuf and application/vnd.google.protobuf might be valid types too, cf.
+ # https://stackoverflow.com/questions/30505408/what-is-the-correct-protobuf-content-type
+ application/x-protobuf pbf;
+ }
+
+ location ^~ /assets/ {
+ expires 7d;
+ try_files $uri =404;
+ location ~ "\.(?:css|js|svg)$" {
+ brotli_static on;
+ }
+ }
+ location ^~ /tiles/ {
+ expires 30m;
+ brotli_static on;
+ try_files $uri =404;
+ # service an empty payload to save bandwidth
+ error_page 404 /_.txt;
+ }
+ location ^~ /raster/ {
+ expires 30m;
+ try_files $uri =404;
+ # service an empty payload to save bandwidth
+ error_page 404 /_.txt;
+ }
+ location = /q {
+ expires epoch;
+ limit_except POST { deny all; }
+ #if ($request_method = OPTIONS) {
+ # add_header Strict-Transport-Security "max-age=31557600; includeSubDomains";
+ # add_header Access-Control-Allow-Origin $http_origin;
+ # add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
+ # add_header Access-Control-Allow-Headers "Accept, Content-Type";
+ # add_header Access-Control-Max-Age 28800;
+ # return 204;
+ #}
+ client_max_body_size 64k;
+ gzip on;
+ gzip_types application/json text/plain;
+ include uwsgi_params;
+ uwsgi_pass unix:/run/webmap-cgi.socket;
+ }
+
+ location = /_.txt {
+ # cache 404 responses for 30m like for valid tiles
+ add_header Strict-Transport-Security "max-age=31557600; includeSubDomains" always;
+ add_header Cache-Control "public; max-age=1800" always;
+ #add_header Access-Control-Allow-Origin $http_origin always;
+ internal;
+ }
+
+ location / {
+ add_header Referrer-Policy "no-referrer";
+ add_header X-Frame-Options "SAMEORIGIN";
+ add_header X-Content-Type-Options "nosniff";
+ add_header X-XSS-Protection "1; mode=block";
+ add_header Strict-Transport-Security "max-age=31557600; includeSubDomains" always;
+ add_header Content-Security-Policy "default-src 'none'; connect-src 'self'; font-src 'self'; frame-src 'self'; img-src 'self' data: https://minkarta.lantmateriet.se/map/; script-src 'self'; style-src 'self'; frame-ancestors 'self'; form-action 'none'; worker-src blob:; base-uri 'self'";
+
+ expires 1h;
+ brotli_static on;
+ try_files $uri $uri/ =404;
+ }
+}
diff --git a/files/etc/nginx/sites-enabled/webmap b/files/etc/nginx/sites-enabled/webmap
deleted file mode 100644
index d16ab60..0000000
--- a/files/etc/nginx/sites-enabled/webmap
+++ /dev/null
@@ -1,80 +0,0 @@
-server {
- listen 80;
- listen [::]:80;
-
- server_name karta.klimatanalysnorr.se hel01.guilhem.se;
-
- include /etc/lacme/nginx.conf;
-
- access_log /var/log/nginx/access.log;
- error_log /var/log/nginx/error.log warn;
-
- location / {
- return 301 https://$host$request_uri;
- }
-}
-
-server {
- listen 443;
- listen [::]:443;
-
- server_name hel01.guilhem.se;
-
- access_log /var/log/nginx/access.log;
- error_log /var/log/nginx/error.log warn;
-
- ssl_certificate /etc/nginx/ssl/webmap.rsa.pem;
- ssl_certificate_key /etc/nginx/ssl/webmap.rsa.key;
- include snippets/ssl.conf;
-
- location / {
- return 303 https://karta.klimatanalysnorr.se$request_uri;
- }
-}
-
-server {
- listen 443 ssl http2 default_server;
- listen [::]:443 ssl http2 default_server;
-
- server_name karta.klimatanalysnorr.se;
-
- access_log /var/log/nginx/access.log;
- error_log /var/log/nginx/error.log warn;
-
- ssl_certificate /etc/nginx/ssl/webmap.rsa.pem;
- ssl_certificate_key /etc/nginx/ssl/webmap.rsa.key;
- include snippets/ssl.conf;
-
- add_header Referrer-Policy "no-referrer";
- add_header X-Frame-Options "SAMEORIGIN";
- add_header X-Content-Type-Options "nosniff";
- add_header X-XSS-Protection "1; mode=block";
- add_header Strict-Transport-Security "max-age=31557600; includeSubDomains" always;
- add_header Content-Security-Policy "default-src 'none'; connect-src 'self'; font-src 'self'; frame-src 'self'; img-src 'self' data: https://minkarta.lantmateriet.se/map/; script-src 'self'; style-src 'self'; frame-ancestors 'self'; form-action 'none'; base-uri 'self'";
-
- root /var/www/webmap;
- index index.html;
-
- location ^~ /assets/ {
- expires 7d;
- gzip_static on;
- try_files $uri =404;
- }
- location ^~ /tiles/ {
- expires 1d;
- gzip_static on;
- try_files $uri =404;
- error_page 404 /_.txt;
- }
-
- location = /_.txt {
- # cache 404 responses
- add_header Strict-Transport-Security "max-age=31557600; includeSubDomains" always;
- add_header Cache-Control "public; max-age=86400" always;
- internal;
- }
-
- location / {
- try_files $uri $uri/ =404;
- }
-}
diff --git a/files/etc/postfix/master.cf b/files/etc/postfix/master.cf
new file mode 100644
index 0000000..3c60f31
--- /dev/null
+++ b/files/etc/postfix/master.cf
@@ -0,0 +1,44 @@
+#
+# Postfix master process configuration file. For details on the format
+# of the file, see the master(5) manual page (command: "man 5 master" or
+# on-line: http://www.postfix.org/master.5.html).
+#
+# Do not forget to execute "postfix reload" after editing this file.
+#
+# ==========================================================================
+# service type private unpriv chroot wakeup maxproc command + args
+# (yes) (yes) (no) (never) (100)
+# ==========================================================================
+smtp inet n - y - - smtpd
+pickup unix n - y 60 1 pickup
+cleanup unix n - y - 0 cleanup
+qmgr unix n - n 300 1 qmgr
+tlsmgr unix - - y 1000? 1 tlsmgr
+rewrite unix - - y - - trivial-rewrite
+bounce unix - - y - 0 bounce
+defer unix - - y - 0 bounce
+trace unix - - y - 0 bounce
+verify unix - - y - 1 verify
+flush unix n - y 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - y - - smtp
+relay unix - - y - - smtp
+ -o syslog_name=postfix/$service_name
+# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
+ -o smtp_tls_security_level=fingerprint
+relay-smtps unix - - y - - smtp
+ -o syslog_name=postfix/$service_name
+# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
+ -o smtp_tls_wrappermode=yes
+ -o smtp_tls_security_level=fingerprint
+showq unix n - y - - showq
+error unix - - y - - error
+retry unix - - y - - error
+discard unix - - y - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - y - - lmtp
+anvil unix - - y - 1 anvil
+scache unix - - y - 1 scache
+postlog unix-dgram n - n - 1 postlogd
diff --git a/files/etc/postfix/tls_policy b/files/etc/postfix/tls_policy
index 2af19c5..c5641d3 100644
--- a/files/etc/postfix/tls_policy
+++ b/files/etc/postfix/tls_policy
@@ -1,3 +1,3 @@
# WARN: smtp_tls_fingerprint_digest MUST be sha256!
-[smtp.guilhem.org]:587 fingerprint ciphers=high protocols=!SSLv2:!SSLv3:!TLSv1:!TLSv1.1:!TLSv1.2
+[smtp.guilhem.org]:465 fingerprint ciphers=high protocols=!SSLv2:!SSLv3:!TLSv1:!TLSv1.1:!TLSv1.2
match=B2:37:09:EC:B9:54:DC:51:FA:77:A1:31:0D:30:06:84:7E:10:81:5B:9B:30:B0:31:6E:9A:7B:53:13:C8:37:62
diff --git a/files/etc/postgresql/postgresql.conf b/files/etc/postgresql/postgresql.conf
new file mode 100644
index 0000000..038438a
--- /dev/null
+++ b/files/etc/postgresql/postgresql.conf
@@ -0,0 +1,4 @@
+shared_buffers = 768MB
+temp_buffers = 128MB
+work_mem = 16MB
+effective_cache_size = 1536MB
diff --git a/files/etc/systemd/system/webmap-cgi.service b/files/etc/systemd/system/webmap-cgi.service
new file mode 100644
index 0000000..88f22e5
--- /dev/null
+++ b/files/etc/systemd/system/webmap-cgi.service
@@ -0,0 +1,36 @@
+[Unit]
+Description=Webmap CGI (Common Gateway Interface)
+After=syslog.target network.target postgresql.service
+
+[Service]
+DynamicUser=yes
+User=_webmap-cgi
+# Note: the "WARNING: you have enabled harakiri without post buffering" can
+# be ignored because body requests are in fact buffered on the nginx side
+ExecStart=/usr/bin/uwsgi -M -p2 \
+ --single-interpreter --die-on-term \
+ --close-on-exec --close-on-exec2 \
+ --max-requests 1000 \
+ --max-worker-lifetime 86400 \
+ --max-worker-lifetime-delta 11 \
+ --harakiri 60 \
+ --lazy-apps \
+ --plugins python3 \
+ --pythonpath /usr/local/share/webmap \
+ --wsgi-file /usr/libexec/webmap-cgi
+Nice=10
+RestartSec=15s
+Restart=always
+
+# Hardening
+NoNewPrivileges=yes
+ProtectHome=yes
+ProtectSystem=strict
+PrivateDevices=yes
+ProtectControlGroups=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+RestrictAddressFamilies=AF_UNIX
+
+[Install]
+WantedBy=multi-user.target
diff --git a/files/etc/systemd/system/webmap-cgi.socket b/files/etc/systemd/system/webmap-cgi.socket
new file mode 100644
index 0000000..2828985
--- /dev/null
+++ b/files/etc/systemd/system/webmap-cgi.socket
@@ -0,0 +1,11 @@
+[Unit]
+Description=Webmap CGI (Common Gateway Interface) activation socket
+After=syslog.target network.target
+
+[Socket]
+ListenStream=%t/webmap-cgi.socket
+SocketUser=www-data
+SocketMode=0666
+
+[Install]
+WantedBy=sockets.target
diff --git a/files/etc/systemd/system/webmap-download@.service b/files/etc/systemd/system/webmap-download@.service
new file mode 100644
index 0000000..d7a49dc
--- /dev/null
+++ b/files/etc/systemd/system/webmap-download@.service
@@ -0,0 +1,37 @@
+[Unit]
+Description=Webmap updater service (download ‘%I’)
+# Chaining logic from https://serverfault.com/questions/1079993/why-does-my-systemd-timer-only-trigger-once-when-the-unit-is-a-target#answer-1128671
+# XXX Looks like Upholds= prevents running a single unit, as it causes
+# webmap-update@%i.target to start upon `systemctl start webmap-download@foo.service`
+After=network-online.target webmap-update@%i.target
+Upholds=webmap-update@%i.target
+
+[Service]
+User=_webmap-download
+Group=_webmap
+
+Nice=15
+IOSchedulingClass=idle
+
+Type=oneshot
+ExecStart=/usr/local/bin/webmap-download \
+ --cachedir=%C/webmap \
+ --lockdir=%t/lock/webmap/cache \
+ --no-exit-code \
+ --quiet \
+ -- %I
+
+# Hardening
+NoNewPrivileges=yes
+ProtectHome=yes
+ProtectSystem=strict
+PrivateDevices=yes
+ProtectControlGroups=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+ReadWritePaths=%C/webmap
+ReadWritePaths=%t/lock/webmap/cache
+
+[Install]
+WantedBy=webmap-update@%i.target
diff --git a/files/etc/systemd/system/webmap-import@.service b/files/etc/systemd/system/webmap-import@.service
new file mode 100644
index 0000000..964c37d
--- /dev/null
+++ b/files/etc/systemd/system/webmap-import@.service
@@ -0,0 +1,37 @@
+[Unit]
+Description=Webmap updater service (import ‘%I’ to PostGIS)
+After=postgresql.service webmap-update@%i.target
+After=webmap-download@%i.service
+Upholds=webmap-update@%i.target
+
+[Service]
+User=_webmap
+Group=_webmap
+
+Nice=15
+IOSchedulingClass=idle
+
+Type=oneshot
+ExecStart=/usr/local/bin/webmap-import \
+ --cachedir=%C/webmap \
+ --lockfile=%t/lock/webmap/lock \
+ --lockdir-sources=%t/lock/webmap/cache \
+ --mvtdir=/var/www/webmap/tiles/%I \
+ --mvt-compress \
+ -- %I
+
+# Hardening
+NoNewPrivileges=yes
+ProtectHome=yes
+ProtectSystem=strict
+PrivateDevices=yes
+ProtectControlGroups=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+ReadWritePaths=%t/lock/webmap
+ReadWritePaths=/var/www/webmap/tiles
+PrivateTmp=yes
+
+[Install]
+WantedBy=webmap-update@%i.target
diff --git a/files/etc/systemd/system/webmap-update@.target b/files/etc/systemd/system/webmap-update@.target
new file mode 100644
index 0000000..840de96
--- /dev/null
+++ b/files/etc/systemd/system/webmap-update@.target
@@ -0,0 +1,3 @@
+[Unit]
+Description=Webmap updater (target unit ‘%I’)
+StopWhenUnneeded=true
diff --git a/files/etc/systemd/system/webmap-update@.timer b/files/etc/systemd/system/webmap-update@.timer
new file mode 100644
index 0000000..74fb848
--- /dev/null
+++ b/files/etc/systemd/system/webmap-update@.timer
@@ -0,0 +1,11 @@
+[Unit]
+Description=Webmap updater (timer unit)
+
+[Timer]
+OnCalendar=*-*-* 01:00:00
+AccuracySec=1s
+RandomizedDelaySec=3599
+Unit=webmap-update@%i.target
+
+[Install]
+WantedBy=timers.target
diff --git a/files/etc/tmpfiles.d/webmap.conf b/files/etc/tmpfiles.d/webmap.conf
new file mode 100644
index 0000000..786e6dd
--- /dev/null
+++ b/files/etc/tmpfiles.d/webmap.conf
@@ -0,0 +1,8 @@
+d %t/lock/webmap 00755 root root
+
+# for `webmap-download --lockdir` *and* `webmap-import --lockdir-sources`
+# (hence the set-group-ID bit and g+w)
+d %t/lock/webmap/cache 02775 _webmap-download _webmap
+
+# for `webmap-import --lockfile`
+f %t/lock/webmap/lock 00644 _webmap _webmap
diff --git a/group_vars/all.yml b/group_vars/all.yml
new file mode 100644
index 0000000..29ad0b9
--- /dev/null
+++ b/group_vars/all.yml
@@ -0,0 +1,25 @@
+---
+# The list of layer groups to process, see
+# webmap-tools/config.yml:layer-groups.
+webmap_layer_groups:
+ - mrr
+ - skydd
+ - avverk
+ - ren
+ - vbk
+ - ri
+ - svk
+ - misc
+ - nv
+
+webmap_layer_groups_nodownload:
+ - misc
+
+# adjust calendar events for individual units
+webmap_layer_groups_update_calendar:
+ mrr: "*-*-* 05:00:00" # updated daily at 04:33 CEST
+
+# PostgreSQL's version number and cluster name
+postgresql:
+ version: 15
+ cluster: main
diff --git a/handlers/main.yml b/handlers/main.yml
index c241ecc..b6ee548 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -5,6 +5,9 @@
- name: systemctl daemon-reload
command: /usr/bin/systemctl daemon-reload
+- name: systemd-tmpfiles --create
+ command: /usr/bin/systemd-tmpfiles --create
+
- name: Refresh hostname
command: /usr/bin/hostnamectl hostname {{ inventory_hostname_short }}
@@ -46,3 +49,12 @@
- name: Reload nginx
service: name=nginx.service state=reloaded
+
+- name: Restart PostgreSQL
+ service: name=postgresql.service state=restarted
+
+- name: Reload PostgreSQL
+ service: name=postgresql.service state=reloaded
+
+- name: Stop webmap-cgi.service
+ service: name=webmap-cgi.service state=stopped
diff --git a/setup.yml b/setup.yml
index fd85241..33780a8 100644
--- a/setup.yml
+++ b/setup.yml
@@ -5,13 +5,28 @@
- name: Install etckeeper
apt: pkg=etckeeper
- import_tasks: ./tasks/firewall.yml
+ tags: firewall
- import_tasks: ./tasks/network.yml
+ tags: network
- import_tasks: ./tasks/sysctl.yml
+ tags: sysctl
- import_tasks: ./tasks/hosts.yml
+ tags: hosts
- import_tasks: ./tasks/apt.yml
+ tags: apt
- import_tasks: ./tasks/ssh.yml
+ tags: ssh
- import_tasks: ./tasks/base.yml
+ tags: base
- import_tasks: ./tasks/mail.yml
+ tags:
+ - mail
+ - postfix
+ - import_tasks: ./tasks/webmap.yml
+ tags: webmap
- import_tasks: ./tasks/httpd.yml
+ tags:
+ - httpd
+ - nginx
handlers:
- import_tasks: ./handlers/main.yml
diff --git a/tasks/apt.yml b/tasks/apt.yml
index 1023908..f17a2e4 100644
--- a/tasks/apt.yml
+++ b/tasks/apt.yml
@@ -5,8 +5,13 @@
- apt
- lsb-release
-- name: Remove /etc/apt/sources.list
- file: path=/etc/apt/sources.list state=absent
+# something keeps recreating (without content) it if we delete it, so we
+# leave it instead but ensure it's empty instead
+- name: Create empty /etc/apt/sources.list
+ copy: content=""
+ dest=/etc/apt/sources.list
+ owner=root group=root
+ mode=0644
notify:
- apt-get update
diff --git a/tasks/base.yml b/tasks/base.yml
index 623d209..ad8b1f0 100644
--- a/tasks/base.yml
+++ b/tasks/base.yml
@@ -18,7 +18,6 @@
- dosfstools
- eatmydata
- acpid
- - acl
- fdisk
- gdisk
- genisoimage
@@ -106,6 +105,7 @@
apt: pkg={{ packages }}
vars:
packages:
+ - acl
- bind9-dnsutils
- bzip2
- htop
@@ -114,10 +114,12 @@
- python3
- less
- iproute2
+ - jq
- git
- curl
- screen
- sudo
+ - tig
- vim-nox
- qemu-guest-agent
# Useful for `getent passwd dynamic_user`
diff --git a/tasks/httpd.yml b/tasks/httpd.yml
index 2138d35..2e1fa98 100644
--- a/tasks/httpd.yml
+++ b/tasks/httpd.yml
@@ -2,6 +2,12 @@
- name: Install nginx
apt: pkg=nginx-light
+- name: Install nginx modules
+ apt: pkg={{ packages }}
+ vars:
+ packages:
+ - libnginx-mod-http-brotli-static
+
- name: Start nginx
service: name=nginx enabled=true state=started
@@ -29,13 +35,20 @@
mode=0644
notify: Reload nginx
-- name: Copy /etc/nginx/sites-enabled/webmap
- copy: src=etc/nginx/sites-enabled/webmap
- dest=/etc/nginx/sites-enabled/webmap
+- name: Copy /etc/nginx/sites-available/webmap
+ copy: src=etc/nginx/sites-available/webmap
+ dest=/etc/nginx/sites-available/webmap
owner=root group=root
mode=0644
notify: Reload nginx
+- name: Create /etc/nginx/sites-enabled/webmap
+ file: src=../sites-available/webmap
+ dest=/etc/nginx/sites-enabled/webmap
+ owner=root group=root
+ state=link force=yes
+ notify: Reload nginx
+
- name: Create directory /var/www/webmap
file: path=/var/www/webmap
state=directory
diff --git a/tasks/mail.yml b/tasks/mail.yml
index 89d8530..8f58c8a 100644
--- a/tasks/mail.yml
+++ b/tasks/mail.yml
@@ -13,7 +13,7 @@
notify:
- Run newaliases
-- name: Configure Postfix
+- name: Configure Postfix (main.cf)
template: src=etc/postfix/main.cf.j2
dest=/etc/postfix/main.cf
owner=root group=root
@@ -21,6 +21,14 @@
notify:
- Reload Postfix
+- name: Configure Postfix (master.cf)
+ copy: src=etc/postfix/master.cf
+ dest=/etc/postfix/master.cf
+ owner=root group=root
+ mode=0644
+ notify:
+ - Restart Postfix
+
- name: Start Postfix
service: name=postfix.service enabled=true state=started
diff --git a/tasks/network.yml b/tasks/network.yml
index 1551f82..a02b07c 100644
--- a/tasks/network.yml
+++ b/tasks/network.yml
@@ -32,6 +32,7 @@
packages:
- systemd-resolved
- libnss-resolve
+ - libnss-myhostname
- name: Create directory /etc/systemd/resolved.conf.d
file: path=/etc/systemd/resolved.conf.d
diff --git a/tasks/webmap.yml b/tasks/webmap.yml
new file mode 100644
index 0000000..de320d4
--- /dev/null
+++ b/tasks/webmap.yml
@@ -0,0 +1,433 @@
+- name: Install gdal-bin
+ apt: pkg=gdal-bin install-recommends=true
+
+- name: Install unzip and brotli
+ apt: pkg={{ packages }}
+ vars:
+ packages:
+ - unzip
+ - brotli
+
+- name: Install python dependencies
+ apt: pkg={{ packages }}
+ vars:
+ packages:
+ - python3
+ - python3-brotli
+ - python3-gdal
+ - python3-requests
+ - python3-systemd
+ - python3-tqdm
+ - python3-urllib3
+ - python3-xdg
+ - python3-yaml
+
+- name: Create directory /etc/webmap
+ file: path=/etc/webmap
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Copy /etc/webmap/config.yml
+ copy: src=webmap-tools/config.yml
+ dest=/etc/webmap/config.yml
+ owner=root group=root
+ mode=0644
+
+- name: Create directory /usr/local/share/webmap
+ file: path=/usr/local/share/webmap
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Copy /usr/local/share/webmap/*.py modules
+ copy: src=webmap-tools/{{ item }}
+ dest=/usr/local/share/webmap/{{ item }}
+ owner=root group=root
+ mode=0644
+ with_items:
+ # TODO these should be compiled
+ - common.py
+ - common_gdal.py
+ - import_source.py
+ - export_mvt.py
+ - rename_exchange.py
+
+- name: Copy webmap-update@.target
+ copy: src=etc/systemd/system/webmap-update@.target
+ dest=/etc/systemd/system/webmap-update@.target
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+
+- name: Copy webmap-update@.timer
+ copy: src=etc/systemd/system/webmap-update@.timer
+ dest=/etc/systemd/system/webmap-update@.timer
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+
+- name: Create directory /etc/systemd/system/webmap-update@*.timer.d
+ file: path=/etc/systemd/system/webmap-update@{{ item }}.timer.d
+ state=directory
+ owner=root group=root
+ mode=0755
+ with_items: "{{ webmap_layer_groups_update_calendar.keys() | list }}"
+
+- name: Copy /etc/systemd/system/webmap-update@*.timer.d/override.conf
+ template: src=etc/systemd/system/webmap-update@.timer.d/override.conf.j2
+ dest=/etc/systemd/system/webmap-update@{{ item }}.timer.d/override.conf
+ owner=root group=root
+ mode=0644
+ with_items: "{{ webmap_layer_groups_update_calendar.keys() | list }}"
+ notify:
+ - systemctl daemon-reload
+
+- name: Enable webmap-update.timer
+ service: name=webmap-update@{{ item }}.timer state=started enabled=true
+ with_items: "{{ webmap_layer_groups }}"
+
+- meta: flush_handlers
+
+
+- name: Create system group '_webmap'
+ group: name=_webmap system=true
+ state=present
+
+- name: Create system user '_webmap-download'
+ user: name=_webmap-download system=true
+ group=_webmap
+ createhome=false
+ home=/nonexistent
+ shell=/usr/sbin/nologin
+ comment="Webmap update (download)"
+ password="!"
+ state=present
+
+- name: Copy /usr/local/share/webmap/download.py
+ copy: src=webmap-tools/webmap-download
+ dest=/usr/local/share/webmap/download.py
+ owner=root group=root
+ mode=0755
+
+- name: Create /usr/local/bin/webmap-download
+ file: src=../share/webmap/download.py
+ dest=/usr/local/bin/webmap-download
+ owner=root group=root
+ state=link force=yes
+
+- name: Create directory /var/cache/webmap
+ file: path=/var/cache/webmap
+ state=directory
+ owner=_webmap-download group=root
+ mode=0755
+
+- name: Create directory /var/cache/webmap/custom
+ file: path=/var/cache/webmap/custom
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Copy custom layers into /var/cache/webmap/custom
+ copy: src=webmap-tools/layers/custom/
+ dest=/var/cache/webmap/custom/
+ owner=root group=root
+ mode=0644
+ directory_mode=0755
+
+- name: Copy webmap-download@.service
+ copy: src=etc/systemd/system/webmap-download@.service
+ dest=/etc/systemd/system/webmap-download@.service
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+
+- name: Enable webmap-download@.service
+ service: name=webmap-download@{{ item }}.service enabled=true
+ with_items: "{{ webmap_layer_groups | difference(webmap_layer_groups_nodownload) }}"
+
+- name: Disable some webmap-download@.service
+ service: name=webmap-download@{{ item }}.service enabled=false
+ with_items: "{{ webmap_layer_groups_nodownload }}"
+
+- meta: flush_handlers
+
+
+- name: Create system user '_webmap'
+ user: name=_webmap system=true
+ group=_webmap
+ createhome=false
+ home=/nonexistent
+ shell=/usr/sbin/nologin
+ comment="Webmap update (extract/import)"
+ password="!"
+ state=present
+
+- name: Install PostgreSQL and PostGIS
+ apt: pkg={{ packages }}
+ vars:
+ packages:
+ - postgresql
+ - postgresql-postgis
+ - postgis
+ # for ansible
+ - python3-psycopg
+
+- name: Generate sv_SE.UTF-8 locales
+ locale_gen: name=sv_SE.UTF-8 state=present
+ # PostgreSQL needs to be restarted to see the new locale
+ notify: Restart PostgreSQL
+
+- name: Configure PostgreSQL
+ copy: src=etc/postgresql/postgresql.conf
+ dest=/etc/postgresql/{{ postgresql.version }}/{{ postgresql.cluster }}/conf.d/local.conf
+ owner=postgres group=postgres
+ mode=0644
+ notify: Restart PostgreSQL
+
+- name: Start PostgreSQL
+ service: name=postgresql@{{ postgresql.version }}-{{ postgresql.cluster }}.service state=started
+
+- meta: flush_handlers
+
+# Usage: \sudo -u postgres psql </usr/local/share/webmap/schema.sql
+- name: Copy /usr/local/share/webmap/schema.sql
+ copy: src=webmap-tools/schema.sql
+ dest=/usr/local/share/webmap/schema.sql
+ owner=root group=root
+ mode=0644
+
+- name: Create PostgreSQL database
+ become: true
+ # XXX: this creates /var/lib/postgresql/.ansible/tmp
+ become_user: postgres
+ community.postgresql.postgresql_db:
+ name: webmap
+ comment: Backend PostGIS database for KlimatanalysNorr tooling
+ encoding: UTF-8
+ lc_collate: sv_SE.UTF-8
+ lc_ctype: sv_SE.UTF-8
+ locale_provider: icu
+ icu_locale: sv-SE-x-icu
+ template: template0
+ owner: postgres
+
+- name: Create 'webmap_import' and 'webmap_guest' PostgreSQL users (roles)
+ become: true
+ become_user: postgres
+ community.postgresql.postgresql_user:
+ login_db: webmap
+ name: "{{ item }}"
+ with_items:
+ - webmap_import
+ - webmap_guest
+
+- name: Add a rule for 'webmap_import' user in pg_hba.conf
+ ansible.builtin.lineinfile:
+ path: /etc/postgresql/{{ postgresql.version }}/{{ postgresql.cluster }}/pg_hba.conf
+ regexp: '^local\s+webmap\s'
+ line: 'local webmap all peer map=pgmap_webmap'
+ # must come before 'local all all peer', cf.
+ # https://dba.stackexchange.com/questions/177142/postgresql-cannot-peer-authenticate-using-usermap-provided-user-name-dbuser
+ insertbefore: '^local\s+all\s+all\s'
+ create: false
+ notify: Reload PostgreSQL
+
+- name: Add a mapping rule for 'webmap_import' user in pg_ident.conf
+ ansible.builtin.lineinfile:
+ path: /etc/postgresql/{{ postgresql.version }}/{{ postgresql.cluster }}/pg_ident.conf
+ regexp: '^pgmap_webmap\s.*\swebmap_import\s*$'
+ line: 'pgmap_webmap _webmap webmap_import'
+ create: false
+ notify: Reload PostgreSQL
+
+- name: Add a mapping rule for 'webmap_guest' user in pg_ident.conf
+ ansible.builtin.lineinfile:
+ path: /etc/postgresql/{{ postgresql.version }}/{{ postgresql.cluster }}/pg_ident.conf
+ regexp: '^pgmap_webmap\s.*\swebmap_guest\s*$'
+ line: 'pgmap_webmap /^_?[a-zA-Z][a-zA-Z0-9_\-]*[a-zA-Z0-9]$ webmap_guest'
+ create: false
+ notify: Reload PostgreSQL
+
+- name: Create 'postgis' PostgreSQL schema
+ become: true
+ become_user: postgres
+ community.postgresql.postgresql_schema:
+ name: postgis
+ login_db: webmap
+ owner: postgres
+
+- name: Install 'postgis' PostgreSQL extension to the webmap database in the postgis schema
+ become: true
+ become_user: postgres
+ community.postgresql.postgresql_ext:
+ name: postgis
+ login_db: webmap
+ schema: postgis
+ comment: Geographic objects support for PostgreSQL
+
+- name: GRANT CONNECT ON DATABASE webmap TO webmap_import, webmap_guest
+ become: true
+ become_user: postgres
+ community.postgresql.postgresql_privs:
+ login_db: webmap
+ privs: CONNECT
+ type: database
+ role: webmap_import,webmap_guest
+
+- name: GRANT USAGE ON SCHEMA postgis TO webmap_import, webmap_guest
+ become: true
+ become_user: postgres
+ community.postgresql.postgresql_privs:
+ login_db: webmap
+ privs: USAGE
+ type: schema
+ obj: postgis
+ role: webmap_import,webmap_guest
+
+# webmap-import should TRUNCATE existing output layers
+- name: REVOKE CREATE ON SCHEMA postgis FROM webmap_import
+ become: true
+ become_user: postgres
+ community.postgresql.postgresql_privs:
+ login_db: webmap
+ privs: CREATE
+ type: schema
+ obj: postgis
+ role: webmap_import
+ state: absent
+
+- name: GRANT SELECT ON TABLES IN SCHEMA postgis TO webmap_guest
+ become: true
+ become_user: postgres
+ community.postgresql.postgresql_privs:
+ login_db: webmap
+ privs: SELECT
+ type: table
+ obj: ALL_IN_SCHEMA
+ schema: postgis
+ role: webmap_guest
+
+- name: GRANT USAGE, SELECT ON SEQUENCES IN SCHEMA postgis TO webmap_guest
+ become: true
+ become_user: postgres
+ community.postgresql.postgresql_privs:
+ login_db: webmap
+ privs: USAGE,SELECT
+ type: sequence
+ obj: ALL_IN_SCHEMA
+ schema: postgis
+ role: webmap_guest
+
+- name: Copy /usr/local/share/webmap/import.py
+ copy: src=webmap-tools/webmap-import
+ dest=/usr/local/share/webmap/import.py
+ owner=root group=root
+ mode=0755
+
+- name: Create /usr/local/bin/webmap-import
+ file: src=../share/webmap/import.py
+ dest=/usr/local/bin/webmap-import
+ owner=root group=root
+ state=link force=yes
+
+- name: Copy webmap-import@.service
+ copy: src=etc/systemd/system/webmap-import@.service
+ dest=/etc/systemd/system/webmap-import@.service
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+
+- name: Enable webmap-import@.service
+ service: name=webmap-import@{{ item }}.service enabled=true
+ with_items: "{{ webmap_layer_groups }}"
+
+
+- name: Build administrative-codes.json*
+ become: false
+ local_action:
+ module: community.general.make
+ chdir: ./webmap-tools/administrative-codes
+ target: all
+
+- name: Create directory /var/www/webmap/data
+ file: path=/var/www/webmap/data
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Copy /var/www/webmap/data/administrative-codes.json*
+ copy: src=./webmap-tools/administrative-codes/{{ item }}
+ dest=/var/www/webmap/data/{{ item }}
+ owner=root group=root
+ mode=0644
+ with_items:
+ - administrative-codes.json
+ - administrative-codes.json.br
+
+- meta: flush_handlers
+
+
+- name: Create directory /var/www/webmap/tiles
+ file: path=/var/www/webmap/tiles
+ state=directory
+ owner=_webmap group=root
+ mode=0755
+
+
+- name: Copy /etc/tmpfiles.d/webmap.conf
+ copy: src=etc/tmpfiles.d/webmap.conf
+ dest=/etc/tmpfiles.d/webmap.conf
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemd-tmpfiles --create
+
+- meta: flush_handlers
+
+
+- name: Install Python/WSGI dependencies
+ apt: pkg={{ packages }}
+ vars:
+ packages:
+ - uwsgi-core
+ - uwsgi-plugin-python3
+ # TODO[trixie]: install python3-psycopg-c instead
+ - python3-psycopg
+
+- name: Copy webmap-cgi.socket
+ copy: src=etc/systemd/system/webmap-cgi.socket
+ dest=/etc/systemd/system/webmap-cgi.socket
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+
+- name: Copy webmap-cgi.service
+ copy: src=etc/systemd/system/webmap-cgi.service
+ dest=/etc/systemd/system/webmap-cgi.service
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+ - Stop webmap-cgi.service
+
+- name: Copy /usr/libexec/webmap-cgi
+ copy: src=./webmap-tools/webmap-cgi
+ dest=/usr/libexec/webmap-cgi
+ owner=root group=root
+ mode=0755
+ notify:
+ - Stop webmap-cgi.service
+
+- meta: flush_handlers
+
+- name: Enable webmap-cgi.socket
+ service: name=webmap-cgi.socket state=started enabled=true
+
+- name: Disable webmap-cgi.service
+ service: name=webmap-cgi.service enabled=false
diff --git a/templates/etc/postfix/main.cf.j2 b/templates/etc/postfix/main.cf.j2
index 9557cc4..35a6790 100644
--- a/templates/etc/postfix/main.cf.j2
+++ b/templates/etc/postfix/main.cf.j2
@@ -29,10 +29,9 @@ alias_database = $virtual_alias_maps
mailbox_size_limit = 0
# Forward everything to our internal outgoing proxy
-# TODO: User relay-smtps on 465/tcp once Hetzner opens it
relay_domains =
-relayhost = [smtp.guilhem.org]:587
-default_transport = relay
+relayhost = [smtp.guilhem.org]:465
+default_transport = relay-smtps
smtpd_tls_security_level = none
smtp_tls_exclude_ciphers = EXPORT, LOW, MEDIUM, aNULL, eNULL, DES, RC4, MD5
diff --git a/templates/etc/systemd/system/webmap-update@.timer.d/override.conf.j2 b/templates/etc/systemd/system/webmap-update@.timer.d/override.conf.j2
new file mode 100644
index 0000000..795ee20
--- /dev/null
+++ b/templates/etc/systemd/system/webmap-update@.timer.d/override.conf.j2
@@ -0,0 +1,3 @@
+[Timer]
+OnCalendar=
+OnCalendar={{ webmap_layer_groups_update_calendar[item] }}
diff --git a/webmap-tools b/webmap-tools
new file mode 160000
+Subproject 4263125c9bc8f23cf5ef6f3257b575537e3cad7