summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--files/etc/nginx/sites-available/webmap2
-rw-r--r--files/etc/systemd/system/webmap-download@.service7
-rw-r--r--files/etc/systemd/system/webmap-import@.service39
-rw-r--r--files/etc/systemd/system/webmap-publish@.service40
-rw-r--r--files/etc/tmpfiles.d/webmap.conf11
-rw-r--r--group_vars/all.yml5
-rw-r--r--handlers/main.yml9
-rw-r--r--tasks/apt.yml9
-rw-r--r--tasks/httpd.yml6
-rw-r--r--tasks/webmap.yml263
m---------webmap-tools0
11 files changed, 380 insertions, 11 deletions
diff --git a/files/etc/nginx/sites-available/webmap b/files/etc/nginx/sites-available/webmap
index d16ab60..92809e2 100644
--- a/files/etc/nginx/sites-available/webmap
+++ b/files/etc/nginx/sites-available/webmap
@@ -62,7 +62,7 @@ server {
}
location ^~ /tiles/ {
expires 1d;
- gzip_static on;
+ brotli_static on;
try_files $uri =404;
error_page 404 /_.txt;
}
diff --git a/files/etc/systemd/system/webmap-download@.service b/files/etc/systemd/system/webmap-download@.service
index a928a13..2c5a3e4 100644
--- a/files/etc/systemd/system/webmap-download@.service
+++ b/files/etc/systemd/system/webmap-download@.service
@@ -8,7 +8,7 @@ Upholds=webmap-update@%i.target
[Service]
User=_webmap-download
-Group=nogroup
+Group=_webmap
Nice=15
IOSchedulingClass=idle
@@ -16,7 +16,7 @@ IOSchedulingClass=idle
Type=oneshot
ExecStart=/usr/local/bin/webmap-download \
--cachedir=/var/cache/webmap \
- --lockdir=%t/webmap-download \
+ --lockdir=%t/lock/webmap/download \
--no-exit-code \
--quiet \
-- %I
@@ -31,8 +31,7 @@ ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
ReadWritePaths=/var/cache/webmap
-RuntimeDirectory=webmap-download
-RuntimeDirectoryPreserve=yes
+ReadWritePaths=%t/lock/webmap/download
[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..06d204c
--- /dev/null
+++ b/files/etc/systemd/system/webmap-import@.service
@@ -0,0 +1,39 @@
+[Unit]
+Description=Webmap updater service (import %I to PostgreSQL)
+After=postgresql.service webmap-update@%i.target
+After=webmap-download@%i.service
+Upholds=webmap-update@%i.target
+
+# XXX webmap-download write cached files atomatically but there is no
+# guarantee that GDAL/OGR opens them atomically. It'd therefore make
+# sense to use the following Conflict= directive, however systemd skips
+# webmap-download@%i.service in that case.
+#Conflicts=webmap-download@%i.service
+
+[Service]
+User=_webmap-import
+Group=_webmap
+
+Nice=15
+IOSchedulingClass=idle
+
+Type=oneshot
+ExecStart=/usr/local/bin/webmap-import \
+ --cachedir=/var/cache/webmap \
+ --lockfile=%t/lock/webmap/lock \
+ -- %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
+PrivateTmp=yes
+
+[Install]
+WantedBy=webmap-update@%i.target
diff --git a/files/etc/systemd/system/webmap-publish@.service b/files/etc/systemd/system/webmap-publish@.service
new file mode 100644
index 0000000..e2f8e6b
--- /dev/null
+++ b/files/etc/systemd/system/webmap-publish@.service
@@ -0,0 +1,40 @@
+[Unit]
+Description=Webmap updater service (publish %I as MVT)
+#After=postgresql.service webmap-update@%i.target
+#After=webmap-download@%i.service
+#After=webmap-import@%i.service
+#Upholds=webmap-update@%i.target
+
+[Service]
+User=_webmap-publish
+Group=_webmap
+
+Nice=15
+IOSchedulingClass=idle
+
+Type=oneshot
+ExecStart=/usr/local/bin/webmap-publish \
+ --lockfile=%t/lock/webmap/lock \
+ --destdir=/var/www/webmap/tiles/%i \
+ --name=%I \
+ --webroot=/var/www/webmap \
+ --metadata=/var/www/webmap/tiles/metadata.json \
+ --metadata-lockfile=%t/lock/webmap/tiles.lock \
+ --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=/var/www/webmap/tiles
+ReadWritePaths=%t/lock/webmap
+PrivateTmp=yes
+
+#[Install]
+#WantedBy=webmap-update@%i.target
diff --git a/files/etc/tmpfiles.d/webmap.conf b/files/etc/tmpfiles.d/webmap.conf
new file mode 100644
index 0000000..620cd24
--- /dev/null
+++ b/files/etc/tmpfiles.d/webmap.conf
@@ -0,0 +1,11 @@
+d %t/lock/webmap 0755 root root
+
+# for webmap-download's --lockdir
+d %t/lock/webmap/download 0755 _webmap-download _webmap
+
+# for webmap-import's *and* webmap-publish's --lockfile (hence the
+# ownership and g+w)
+f %t/lock/webmap/lock 0664 root _webmap
+
+# for webmap-publish's --metadata-lockfile
+f %t/lock/webmap/tiles.lock 0644 _webmap-publish _webmap
diff --git a/group_vars/all.yml b/group_vars/all.yml
index a0d35c6..5d4474a 100644
--- a/group_vars/all.yml
+++ b/group_vars/all.yml
@@ -7,3 +7,8 @@ webmap_layer_groups:
- sks
- st
- vbk
+
+# PostgreSQL's version number and cluster name
+postgresql:
+ version: 15
+ cluster: main
diff --git a/handlers/main.yml b/handlers/main.yml
index c241ecc..281951b 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,9 @@
- 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
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/httpd.yml b/tasks/httpd.yml
index 22757d5..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
diff --git a/tasks/webmap.yml b/tasks/webmap.yml
index 9b60359..9e2c2f6 100644
--- a/tasks/webmap.yml
+++ b/tasks/webmap.yml
@@ -1,17 +1,23 @@
- name: Install gdal-bin
apt: pkg=gdal-bin install-recommends=true
-- name: Install unzip
- apt: pkg=unzip
+- 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-lxml
- python3-requests
+ - python3-systemd
- python3-tqdm
- python3-urllib3
- python3-xdg
@@ -64,9 +70,13 @@
- 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=nogroup
+ group=_webmap
createhome=false
home=/nonexistent
shell=/usr/sbin/nologin
@@ -95,7 +105,7 @@
- name: Create directory /var/cache/webmap
file: path=/var/cache/webmap
state=directory
- owner=_webmap-download group=nogroup
+ owner=_webmap-download group=root
mode=0755
- name: Copy webmap-download@.service
@@ -111,3 +121,248 @@
with_items: "{{ webmap_layer_groups }}"
- meta: flush_handlers
+
+
+- name: Create system user '_webmap-import'
+ user: name=_webmap-import 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: 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:
+ 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-import 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
+ 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
+ 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:
+ database: 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:
+ database: 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:
+ database: 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:
+ database: 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:
+ database: 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
+
+- meta: flush_handlers
+
+
+- name: Create system user '_webmap-publish'
+ user: name=_webmap-publish system=true
+ group=_webmap
+ createhome=false
+ home=/nonexistent
+ shell=/usr/sbin/nologin
+ comment="Webmap update (publication as MVT)"
+ password="!"
+ state=present
+
+- name: Copy /usr/local/share/webmap/publish.py
+ copy: src=webmap-tools/webmap-publish
+ dest=/usr/local/share/webmap/publish.py
+ owner=root group=root
+ mode=0755
+
+- name: Create /usr/local/bin/webmap-publish
+ file: src=../share/webmap/publish.py
+ dest=/usr/local/bin/webmap-publish
+ owner=root group=root
+ state=link force=yes
+
+- name: Create directory /var/www/webmap/tiles
+ file: path=/var/www/webmap/tiles
+ state=directory
+ owner=_webmap-publish group=root
+ mode=0755
+
+- name: Copy webmap-publish@.service
+ copy: src=etc/systemd/system/webmap-publish@.service
+ dest=/etc/systemd/system/webmap-publish@.service
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+
+#- name: Enable webmap-publish@.service
+# service: name=webmap-publish@{{ item }}.service enabled=true
+# with_items: "{{ webmap_layer_groups }}"
+
+
+- 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
diff --git a/webmap-tools b/webmap-tools
-Subproject 729a5df4ba9889aebcd51787ec11a4d0d1ea547
+Subproject 7cda119879cf48ba72ba34522fa9cdf9ef6d9b4