vex2: some redirects and stuff
authorBernhard Tittelbach <bernhard@tittelbach.org>
Sun, 2 Nov 2025 01:07:51 +0000 (02:07 +0100)
committerBernhard Tittelbach <bernhard@tittelbach.org>
Sun, 2 Nov 2025 01:07:51 +0000 (02:07 +0100)
23 files changed:
ansible/host_playbooks/vex2.yml
ansible/host_vars/vex2/realraumat.yaml [new file with mode: 0644]
ansible/roles/acmetool/base/defaults/main.yml
ansible/roles/web/r3redirects/defaults/main.yml [new file with mode: 0644]
ansible/roles/web/r3redirects/handlers/main.yml [new file with mode: 0644]
ansible/roles/web/r3redirects/tasks/main.yml [new file with mode: 0644]
ansible/roles/web/r3redirects/tasks/nginx.yml [new file with mode: 0644]
ansible/roles/web/r3redirects/templates/r3.at.j2 [new file with mode: 0644]
ansible/roles/web/r3redirects/templates/sensors.realraum.at.j2 [new file with mode: 0644]
ansible/roles/web/r3redirects/templates/w.r3.at.j2 [new file with mode: 0644]
ansible/roles/web/r3status/defaults/main.yml
ansible/roles/web/r3status/tasks/main.yml
ansible/roles/web/r3status/tasks/nginx.yml
ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.service.j2 [new file with mode: 0644]
ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.sh.j2 [new file with mode: 0755]
ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.timer.j2 [new file with mode: 0644]
ansible/roles/web/r3status/templates/nginx.j2
ansible/roles/web/realraumat/defaults/main.yml [new file with mode: 0644]
ansible/roles/web/realraumat/files/404.html [new file with mode: 0644]
ansible/roles/web/realraumat/handlers/main.yml [new file with mode: 0644]
ansible/roles/web/realraumat/tasks/main.yml [new file with mode: 0644]
ansible/roles/web/realraumat/tasks/nginx.yml [new file with mode: 0644]
ansible/roles/web/realraumat/templates/www.realraum.at.j2 [new file with mode: 0644]

index 91649f6..a053a2d 100644 (file)
@@ -6,5 +6,7 @@
   - role: dirty-hacks/vex2-base
   - role: acmetool/base
   - role: nginx
+  - role: web/realraumat
+  - role: web/r3redirects
   - role: web/dokuwiki
   - role: web/r3status
diff --git a/ansible/host_vars/vex2/realraumat.yaml b/ansible/host_vars/vex2/realraumat.yaml
new file mode 100644 (file)
index 0000000..cfc1835
--- /dev/null
@@ -0,0 +1,9 @@
+---
+r3at_urls:
+  - r3.at
+
+  
+wwwrealraum_urls:
+  - www.realraum.at
+  - realraum.at
+
index c9a7107..b8c9ca0 100644 (file)
@@ -1,11 +1,12 @@
 ---
-acmetool_directory_server_le_live: "https://acme-v01.api.letsencrypt.org/directory"
-acmetool_directory_server_le_staging: "https://acme-staging.api.letsencrypt.org/directory"
+acmetool_directory_server_le_live: "https://acme-v02.api.letsencrypt.org/directory"
+acmetool_directory_server_le_staging: "https://acme-staging-v02.api.letsencrypt.org/directory"
 
 ## this can't be changed after the account as been created (aka after the first run)
 ## and it's not recommended to keep this empty so we don't define it here which will lead to an error
 # acmetool_account_email:
 acmetool_directory_server: "{{ acmetool_directory_server_le_staging }}"
+# acmetool_directory_server: "{{ acmetool_directory_server_le_live }}"
 
 #### optionally set http(s)_proxy
 # acmetool_http_proxy:
diff --git a/ansible/roles/web/r3redirects/defaults/main.yml b/ansible/roles/web/r3redirects/defaults/main.yml
new file mode 100644 (file)
index 0000000..677b963
--- /dev/null
@@ -0,0 +1,10 @@
+---
+r3at_urls:
+  - r3.at
+
+wikirealraum.at_urls:
+  - wiki.realraum.at
+  - w.r3.at
+
+sensors_urls:
+  - sensors.realraum.at
diff --git a/ansible/roles/web/r3redirects/handlers/main.yml b/ansible/roles/web/r3redirects/handlers/main.yml
new file mode 100644 (file)
index 0000000..d4e42ca
--- /dev/null
@@ -0,0 +1,5 @@
+---
+- name: reload nginx
+  service:
+    name: nginx
+    state: reloaded
diff --git a/ansible/roles/web/r3redirects/tasks/main.yml b/ansible/roles/web/r3redirects/tasks/main.yml
new file mode 100644 (file)
index 0000000..d8e14c3
--- /dev/null
@@ -0,0 +1,3 @@
+---
+
+- import_tasks: nginx.yml
diff --git a/ansible/roles/web/r3redirects/tasks/nginx.yml b/ansible/roles/web/r3redirects/tasks/nginx.yml
new file mode 100644 (file)
index 0000000..b1c0605
--- /dev/null
@@ -0,0 +1,106 @@
+---
+
+- name: install nginx vhost config files
+  loop:
+    - r3.at
+    - w.r3.at
+    - sensors.realraum.at
+  template:
+    src: "{{ item }}.j2"
+    dest: /etc/nginx/sites-available/{{ item }}
+  notify: reload nginx
+
+- name: check if acme certs already exists
+  stat:
+    path: /var/lib/acme/live/w.r3.at
+  register: wr3_acme_cert
+
+- name: check if acme certs already exists
+  stat:
+    path: /var/lib/acme/live/r3.at
+  register: r3_acme_cert
+
+- name: check if acme certs already exists
+  stat:
+    path: /var/lib/acme/live/sensors.realraum.at
+  register: sensors_acme_cert
+
+- name: link nonexistent hostname to self-signed interim cert
+  when: not wr3_acme_cert.stat.exists
+  block:
+    - name: get id of existing selfsigned interim certificate
+      command: cat /var/lib/acme/.selfsigned-interim-cert
+      changed_when: false
+      check_mode: false
+      register: selfsigned_interim_cert_id
+
+    - name: set selfsigned_interim_cert_id variable
+      set_fact:
+        selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"
+
+    - name: link to snakeoil cert for nonexistent hostnames
+      file:
+        src: "../certs/{{ selfsigned_interim_cert_id }}"
+        dest: /var/lib/acme/live/w.r3.at
+        state: link
+
+- name: link nonexistent hostname to self-signed interim cert
+  when: not r3_acme_cert.stat.exists
+  block:
+    - name: get id of existing selfsigned interim certificate
+      command: cat /var/lib/acme/.selfsigned-interim-cert
+      changed_when: false
+      check_mode: false
+      register: selfsigned_interim_cert_id
+
+    - name: set selfsigned_interim_cert_id variable
+      set_fact:
+        selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"
+
+    - name: link to snakeoil cert for nonexistent hostnames
+      file:
+        src: "../certs/{{ selfsigned_interim_cert_id }}"
+        dest: /var/lib/acme/live/r3.at
+        state: link
+
+- name: link nonexistent hostname to self-signed interim cert
+  when: not sensors_acme_cert.stat.exists
+  block:
+    - name: get id of existing selfsigned interim certificate
+      command: cat /var/lib/acme/.selfsigned-interim-cert
+      changed_when: false
+      check_mode: false
+      register: selfsigned_interim_cert_id
+
+    - name: set selfsigned_interim_cert_id variable
+      set_fact:
+        selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"
+
+    - name: link to snakeoil cert for nonexistent hostnames
+      file:
+        src: "../certs/{{ selfsigned_interim_cert_id }}"
+        dest: /var/lib/acme/live/sensors.realraum.at
+        state: link
+
+- name: enable nginx vhost config
+  loop:
+    - r3.at
+    - w.r3.at
+    - sensors.realraum.at
+  file:
+    src: ../sites-available/{{ item }}
+    dest: /etc/nginx/sites-enabled/{{ item }}
+    state: link
+  notify: reload nginx
+
+- name: make sure nginx config has been loaded
+  meta: flush_handlers
+
+# - name: get certificate using acmetool
+#   import_role:
+#     name: acmetool/cert
+#   vars:
+#     acmetool_cert_name: {{ item }}
+#   loop:
+#     - r3.at
+#     - w.r3.at
diff --git a/ansible/roles/web/r3redirects/templates/r3.at.j2 b/ansible/roles/web/r3redirects/templates/r3.at.j2
new file mode 100644 (file)
index 0000000..147aeda
--- /dev/null
@@ -0,0 +1,27 @@
+server {
+    listen [::]:443 ssl;
+    listen 443 ssl;
+
+    server_name {{ r3at_urls | join(' ') }};
+
+    include snippets/acmetool.conf;
+    include snippets/ssl.conf;
+    ssl_certificate /var/lib/acme/live/{{ r3at_urls[0] }}/fullchain;
+    ssl_certificate_key /var/lib/acme/live/{{ r3at_urls[0] }}/privkey;
+    include snippets/hsts.conf;
+
+    include snippets/security-headers.conf;
+
+
+    location = /events.ics {
+        return 302 https://status.realraum.at/shmcache/grical_realraum.ical; # planned: 301
+    }
+
+    location = /events.ical {
+        return 302 https://status.realraum.at/shmcache/grical_realraum.ical; # planned: 301
+    }
+
+    location = / {
+        return 302 https://realraum.at/;
+    }
+}
diff --git a/ansible/roles/web/r3redirects/templates/sensors.realraum.at.j2 b/ansible/roles/web/r3redirects/templates/sensors.realraum.at.j2
new file mode 100644 (file)
index 0000000..5afbc99
--- /dev/null
@@ -0,0 +1,20 @@
+server {
+    listen [::]:443 ssl;
+    listen 443 ssl;
+
+    server_name {{ sensors_urls | join(' ') }};
+
+    include snippets/acmetool.conf;
+    include snippets/ssl.conf;
+    ssl_certificate /var/lib/acme/live/{{ sensors_urls[0] }}/fullchain;
+    ssl_certificate_key /var/lib/acme/live/{{ sensors_urls[0] }}/privkey;
+    include snippets/hsts.conf;
+
+    include snippets/security-headers.conf;
+
+    access_log off;
+
+    location / {
+        return 307 https://status.realraum.at/;
+    }
+}
diff --git a/ansible/roles/web/r3redirects/templates/w.r3.at.j2 b/ansible/roles/web/r3redirects/templates/w.r3.at.j2
new file mode 100644 (file)
index 0000000..9eb2696
--- /dev/null
@@ -0,0 +1,20 @@
+server {
+    listen [::]:443 ssl;
+    listen 443 ssl;
+
+    server_name {{ wikirealraum | join(' ') }};
+
+    include snippets/acmetool.conf;
+    include snippets/ssl.conf;
+    ssl_certificate /var/lib/acme/live/{{ wikirealraum[0] }}/fullchain;
+    ssl_certificate_key /var/lib/acme/live/{{ wikirealraum[0] }}/privkey;
+    include snippets/hsts.conf;
+
+    include snippets/security-headers.conf;
+
+    access_log off;
+
+    location / {
+        return 302 https://doku.realraum.at$request_uri;
+    }
+}
index ed8bd03..29ac966 100644 (file)
@@ -1,2 +1,3 @@
 ---
 r3status_spaceapi_path: /dev/shm/spaceapi
+r3status_ics_path: /dev/shm/ics
index af225ed..b4a5a39 100644 (file)
     dest: /usr/local/bin/ssh-spaceapi-update.py
     mode: 0755
 
+- name: install grical caching script
+  template:
+    src: cache_realraum_imported_calendar.sh.j2
+    dest: /usr/local/bin/cache_realraum_imported_calendar.sh
+    mode: 0755
+
+- name: copy grical caching services
+  loop:
+    - cache_realraum_imported_calendar.timer
+    - cache_realraum_imported_calendar.service
+  template:
+    src: "{{ item }}.j2"
+    dest: /etc/systemd/system/{{ item }}
+    mode: 0644
+
+- name: install copy grical caching services
+  loop:
+    - cache_realraum_imported_calendar.timer
+    - cache_realraum_imported_calendar.service
+  ansible.builtin.systemd:
+    name: "{{ item }}"
+    state: started
+    enabled: yes
+    daemon_reload: yes
+
 - name: create spaceapi user ssh config directory
   file:
     path: /srv/r3status/spaceapi/.ssh
@@ -29,6 +54,7 @@
     content: |
       no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding,no-user-rc,command="/usr/local/bin/ssh-spaceapi-update.py" {{ r3status_spaceapi_update_user_ssh_key }}
 
+### TODO: grical downloader script
 
 - name: create status web-root directory
   file:
index 1c0f7d8..f2302c7 100644 (file)
@@ -39,8 +39,8 @@
 - name: make sure nginx config has been loaded
   meta: flush_handlers
 
-- name: get certificate using acmetool
-  import_role:
-    name: acmetool/cert
-  vars:
-    acmetool_cert_name: status.realraum.at
+# - name: get certificate using acmetool
+#   import_role:
+#     name: acmetool/cert
+#   vars:
+#     acmetool_cert_name: status.realraum.at
diff --git a/ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.service.j2 b/ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.service.j2
new file mode 100644 (file)
index 0000000..9712e84
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=grical ics caching service
+
+[Service]
+Type=oneshot
+WorkingDirectory={{ r3status_ics_path }}
+ExecStart=/usr/local/bin/cache_realraum_imported_calendar.sh
+User=spaceapi
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.sh.j2 b/ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.sh.j2
new file mode 100755 (executable)
index 0000000..5e4d34a
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/zsh
+DL_PATH=/dev/shm/wget
+APACHE_PATH={{ r3status_ics_path }}
+ALL_JSON_SRC="https://grical.realraum.at/s/?query=!realraum+|+!r3extern&limit=9&view=json"
+ALL_JSON_FILE="grical_realraum.json"
+LOCALONLY_JSON_SRC="https://grical.realraum.at/s/?query=!realraum&limit=9&view=json"
+LOCALONLY_JSON_FILE="grical_realraum_only.json"
+ICAL_DATE_FROM=$(date -d "last month" +"%Y-%m-%d")
+ICAL_DATE_TILL=$(date -d "today + 3 months" +"%Y-%m-%d")
+ALL_ICAL_SRC="https://grical.realraum.at/s/?query=!realraum+|+!r3extern%20${ICAL_DATE_FROM}%20${ICAL_DATE_TILL}&view=ical"
+ALL_ICAL_FILE="grical_realraum.ical"
+LOCALONLY_ICAL_SRC="https://grical.realraum.at/s/?query=!realraum%20${ICAL_DATE_FROM}%20${ICAL_DATE_TILL}&view=ical"
+LOCALONLY_ICAL_FILE="grical_realraum_only.ical"
+mkdir $APACHE_PATH 2>/dev/null
+mkdir $DL_PATH 2>/dev/null
+### sed makes ical validate according to http://severinghaus.org/projects/icv/?url=https%3A%2F%2Fr3.at%2Fevents.ical
+for s d in $ALL_JSON_SRC $ALL_JSON_FILE $ALL_ICAL_SRC $ALL_ICAL_FILE $LOCALONLY_JSON_SRC $LOCALONLY_JSON_FILE $LOCALONLY_ICAL_SRC $LOCALONLY_ICAL_FILE; do
+       wget --no-check-certificate -o /dev/null --tries=1 "$s" -O "${DL_PATH}/${d}" \
+       && sed -i '/^GEO:/d;/^METHOD:PUBLISH/d;s/^\(DTSTAMP:[0-9A-Z]\+\)/\1Z/' "${DL_PATH}/${d}" \
+       && [[ -s "${DL_PATH}/${d}" ]] \
+       && mv "${DL_PATH}/${d}" "${APACHE_PATH}/${d}"    
+done
+
diff --git a/ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.timer.j2 b/ansible/roles/web/r3status/templates/cache_realraum_imported_calendar.timer.j2
new file mode 100644 (file)
index 0000000..0e94ff1
--- /dev/null
@@ -0,0 +1,9 @@
+[Unit]
+Description=grical ics caching time
+
+[Timer]
+OnActiveSec=60
+OnUnitActiveSec=60
+
+[Install]
+WantedBy=multi-user.target
index 698b5b1..76fe826 100644 (file)
@@ -16,6 +16,16 @@ server {
 
     location = /spaceapi.json {
         alias {{ r3status_spaceapi_path }}/spaceapi.json;
+        add_header Access-Control-Allow-Origin "*";
+        add_header Pragma "no-cache";
+        add_header Cache-Control "no-cache";
+    }
+
+    location ^/ics/(.*)$ {
+        alias {{ r3status_ics_path }}/$1;
+        add_header Access-Control-Allow-Origin "*";
+        add_header Pragma "no-cache";
+        add_header Cache-Control "no-cache";
     }
 
     location /js/ {
diff --git a/ansible/roles/web/realraumat/defaults/main.yml b/ansible/roles/web/realraumat/defaults/main.yml
new file mode 100644 (file)
index 0000000..67c12fe
--- /dev/null
@@ -0,0 +1,3 @@
+---
+wwwrealraum_urls:
+  - www.realraum.at
\ No newline at end of file
diff --git a/ansible/roles/web/realraumat/files/404.html b/ansible/roles/web/realraumat/files/404.html
new file mode 100644 (file)
index 0000000..c225713
--- /dev/null
@@ -0,0 +1,26 @@
+<html>
+<head>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+    <!--meta http-equiv="Content-Security-Policy" content="default-src 'none'; base-uri 'self'; connect-src 'self'; form-action 'self'; img-src data:; script-src 'self'; style-src 'unsafe-inline'"-->
+    <meta content="origin" name="referrer">    
+       <title>404 - Error ressource not found</title>
+       <style>
+       h1 {
+               font-size:400%;
+               text-align: center;
+       }
+       h2 {
+               font-size:200%;
+               text-align: center;
+       }
+       </style>
+</head>
+<body>
+<h1><img src="https://www.realraum.at/logo-red_250x250.png"><br/>4 ohhh 4</h1>
+<h2>In four dimensions we can have a brane.</h2>
+<h2>But call it a dimension, then you need to get a brain!<h2>
+</body>
+</html>
+
+
+
diff --git a/ansible/roles/web/realraumat/handlers/main.yml b/ansible/roles/web/realraumat/handlers/main.yml
new file mode 100644 (file)
index 0000000..d4e42ca
--- /dev/null
@@ -0,0 +1,5 @@
+---
+- name: reload nginx
+  service:
+    name: nginx
+    state: reloaded
diff --git a/ansible/roles/web/realraumat/tasks/main.yml b/ansible/roles/web/realraumat/tasks/main.yml
new file mode 100644 (file)
index 0000000..5b05a88
--- /dev/null
@@ -0,0 +1,17 @@
+---
+- name: create webroot path
+  file:
+    name: /srv/realraumat/www/
+    state: directory
+    owner: www-data
+
+- name: Copy files to remote locations
+  ansible.builtin.copy:
+    dest: /srv/realraumat/www/404.html
+    group: www-data
+    owner: www-data
+    src: files/404.html
+
+- import_tasks: nginx.yml
+
+
diff --git a/ansible/roles/web/realraumat/tasks/nginx.yml b/ansible/roles/web/realraumat/tasks/nginx.yml
new file mode 100644 (file)
index 0000000..db6571d
--- /dev/null
@@ -0,0 +1,53 @@
+---
+
+- name: install nginx vhost config files
+  loop:
+    - www.realraum.at
+  template:
+    src: "{{ item }}.j2"
+    dest: /etc/nginx/sites-available/{{ item }}
+  notify: reload nginx
+
+- name: check if acme certs already exists
+  stat:
+    path: /var/lib/acme/live/www.realraum.at
+  register: wwwrealraum_acme_cert
+
+- name: link nonexistent hostname to self-signed interim cert
+  when: not wwwrealraum_acme_cert.stat.exists
+  block:
+    - name: get id of existing selfsigned interim certificate
+      command: cat /var/lib/acme/.selfsigned-interim-cert
+      changed_when: false
+      check_mode: false
+      register: selfsigned_interim_cert_id
+
+    - name: set selfsigned_interim_cert_id variable
+      set_fact:
+        selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"
+
+    - name: link to snakeoil cert for nonexistent hostnames
+      file:
+        src: "../certs/{{ selfsigned_interim_cert_id }}"
+        dest: /var/lib/acme/live/www.realraum.at
+        state: link
+
+- name: enable nginx vhost config
+  loop:
+    - www.realraum.at
+  file:
+    src: ../sites-available/{{ item }}
+    dest: /etc/nginx/sites-enabled/{{ item }}
+    state: link
+  notify: reload nginx
+
+- name: make sure nginx config has been loaded
+  meta: flush_handlers
+
+# - name: get certificate using acmetool
+#   import_role:
+#     name: acmetool/cert
+#   vars:
+#     acmetool_cert_name: {{ item }}
+#   loop:
+#     - www.realraum.at
diff --git a/ansible/roles/web/realraumat/templates/www.realraum.at.j2 b/ansible/roles/web/realraumat/templates/www.realraum.at.j2
new file mode 100644 (file)
index 0000000..fdbf2cf
--- /dev/null
@@ -0,0 +1,116 @@
+server {
+    listen [::]:443 ssl;
+    listen 443 ssl;
+
+    server_name {{ wwwrealraum_urls | join(' ') }};
+
+    include snippets/acmetool.conf;
+    include snippets/ssl.conf;
+    ssl_certificate /var/lib/acme/live/{{ wwwrealraum_urls[0] }}/fullchain;
+    ssl_certificate_key /var/lib/acme/live/{{ wwwrealraum_urls[0] }}/privkey;
+    include snippets/hsts.conf;
+
+    include snippets/security-headers.conf;
+    add_header Content-Security-Policy "upgrade-insecure-requests";
+    # Can be used rather than HSTS when it shouldn't be cached
+
+
+    root /srv/realraumat/www/;
+    access_log off;
+    error_log  /var/log/nginx/realraum.at/error.log notice;
+#    rewrite_log on;
+
+
+    # Default redirect to WordPress site
+    location / {
+        return 302 https://wp.realraum.at$request_uri;
+    }
+
+    location ~ ^/wiki/(.*)$ {
+        return 302 https://doku.realraum.at/$1;
+    }
+
+    # Specific file redirects to status subdomain
+    location = /sensors.html {
+        return 302 https://status.realraum.at/; # planned: 301
+    }
+
+    location = /status.json {
+        return 302 https://status.realraum.at/spaceapi.json; # planned: 301
+    }
+
+    location = /shmcache/status.json {
+        return 302 https://status.realraum.at/spaceapi.json; # planned: 301
+    }
+
+    location ~ ^/shmcache/(.*)$ {
+        return 302 https://status.realraum.at/ics/$1; # planned: 301
+    }
+
+    location = /gc_button1.gif {
+        return 302 https://status.realraum.at/gc_button1.gif; # planned: 301
+    }
+    location = /kiosk1024x768.html {
+        return 302 https://status.realraum.at/kiosk1024x768.html; # planned: 301
+    }
+    location = /kiosk1050x1680_2.html {
+        return 302 https://status.realraum.at/kiosk1050x1680_2.html; # planned: 301
+    }
+    location = /kiosk1366x768.html {
+        return 302 https://status.realraum.at/kiosk1366x768.html; # planned: 301
+    }
+    location = /kiosk1440x900.html {
+        return 302 https://status.realraum.at/kiosk1440x900.html; # planned: 301
+    }
+    location = /kiosk1680x1050_1.html {
+        return 302 https://status.realraum.at/kiosk1680x1050_1.html; # planned: 301
+    }
+    location = /kiosk768x1366.html {
+        return 302 https://status.realraum.at/kiosk768x1366.html; # planned: 301
+    }
+    location = /kiosk768x1366sensors.html {
+        return 302 https://status.realraum.at/kiosk768x1366sensors.html; # planned: 301
+    }
+    location = /kiosk900x1440.html {
+        return 302 https://status.realraum.at/kiosk900x1440.html; # planned: 301
+    }
+    location = /kiosk.css {
+        return 302 https://status.realraum.at/kiosk.css; # planned: 301
+    }
+    location = /kiosk.js {
+        return 302 https://status.realraum.at/kiosk.js; # planned: 301
+    }
+    location = /logo-red_250x250.png {
+        return 302 https://status.realraum.at/logo-red_250x250.png; # planned: 301
+    }
+    location = /logo-re_empty_100x100.png {
+        return 302 https://status.realraum.at/logo-re_empty_100x100.png; # planned: 301
+    }
+    location = /logo-re_open_100x100.png {
+        return 302 https://status.realraum.at/logo-re_open_100x100.png; # planned: 301
+    }
+    location = /purl.js {
+        return 302 https://status.realraum.at/purl.js; # planned: 301
+    }
+    location = /vis.css {
+        return 302 https://status.realraum.at/vis.css; # planned: 301
+    }
+    location = /vis.js {
+        return 302 https://status.realraum.at/vis.js; # planned: 301
+    }
+
+    location = /logo-re_open_100x100.png {
+        return 302 https://status.realraum.at/logo-re_open_100x100.png; # planned: 301
+    }
+
+    location = /logo-re_empty_100x100.png {
+        return 302 https://status.realraum.at/logo-re_empty_100x100.png; # planned: 301
+    }
+
+    location = /logo-red_250x250.png {
+        return 302 https://status.realraum.at/logo-red_250x250.png; # planned: 301
+    }
+
+    error_page 404 /404.html;
+
+}