From ef3b04d49da7bdee4551abbc99fc6632357ccbe7 Mon Sep 17 00:00:00 2001
From: lilly
Date: Sun, 19 Jul 2026 16:59:38 +0200
Subject: [PATCH] add dooris role for setup of dooris interaction on the node
itself
---
inventories/z9/host_vars/dooris.sops.yaml | 20 ++++----
inventories/z9/host_vars/dooris.yaml | 22 ++-------
inventories/z9/hosts.yaml | 3 --
playbooks/deploy.yaml | 7 +++
.../z9/dooris/docker_compose/compose.yaml.j2 | 17 -------
roles/dooris/README.md | 16 +++++++
roles/dooris/handlers/main.yml | 5 ++
roles/dooris/meta/argument_specs.yml | 48 +++++++++++++++++++
roles/dooris/meta/main.yml | 27 +++++++++++
roles/dooris/tasks/main.yml | 34 +++++++++++++
roles/dooris/templates/compose.yaml.j2 | 17 +++++++
.../dooris/templates}/nginx/http_handler.conf | 0
.../dooris/templates/nginx/site.conf | 8 ++--
roles/dooris/templates/sshd_config | 6 +++
14 files changed, 179 insertions(+), 51 deletions(-)
delete mode 100644 resources/z9/dooris/docker_compose/compose.yaml.j2
create mode 100644 roles/dooris/README.md
create mode 100644 roles/dooris/handlers/main.yml
create mode 100644 roles/dooris/meta/argument_specs.yml
create mode 100644 roles/dooris/meta/main.yml
create mode 100644 roles/dooris/tasks/main.yml
create mode 100644 roles/dooris/templates/compose.yaml.j2
rename {resources/z9/dooris => roles/dooris/templates}/nginx/http_handler.conf (100%)
rename resources/z9/dooris/nginx/dooris.ccchh.net.conf => roles/dooris/templates/nginx/site.conf (84%)
create mode 100644 roles/dooris/templates/sshd_config
diff --git a/inventories/z9/host_vars/dooris.sops.yaml b/inventories/z9/host_vars/dooris.sops.yaml
index 73c87269..9620b051 100644
--- a/inventories/z9/host_vars/dooris.sops.yaml
+++ b/inventories/z9/host_vars/dooris.sops.yaml
@@ -1,11 +1,14 @@
-secret__dooris_client_secret: ENC[AES256_GCM,data:v85gIBNH4s4j36crJ+Pb2lu2cdZpwz0xndHzBKZNGKg=,iv:Rlt6R7JMcHTAAVPiTtFaxqsWD8G5B9Ab3yqItYdFR+E=,tag:dlMHaxTMx3LgOzCsTLUdzw==,type:str]
-secret__dooris_ccujack_password: ENC[AES256_GCM,data:bHeftSA7eC1cSydBRumksRgw2v0=,iv:X/pfsvQPZREifGjHDGx8mVk2TDrlrRVb6MiAr01wI9o=,tag:ti//x7eDbheMG6Hsn2KBlg==,type:str]
+dooris__static_api_token: ENC[AES256_GCM,data:pXmjn36FnOwA7fWAd3Go4W1CiMeRbbAiquj9KI/pQEDy1qDuobBbBft25m3uSAo6VI02PW2oZ4koY8uoPDUwNA==,iv:TNaZjwGBHvIbmF7VPIOo5mYzH1NEIyKIgjzkrobNCoI=,tag:4dHZepMxUGcvBYEp0kNwYQ==,type:str]
+dooris__openid_client_secret: ENC[AES256_GCM,data:PqmtHR6LCGXcK5dyqKihUqU6+lydW0mJf7kMMf41qh4=,iv:ZjIl8jwB2lfJHjwcDEFFCbafMBnpzkccxBvvsjg+ia8=,tag:+eCnr9ojv9uUoO9k5khY6w==,type:str]
+dooris__ccujack_password: ENC[AES256_GCM,data:FBbrdoQRdVZ+1n8WZg42jZz/xvQ=,iv:GLuen+LiB4MrvU71gEdVYWbdHKaDcEKify3vPePuoO0=,tag:nuqkP0cJLsvNAieWDNY3HA==,type:str]
+dooris__acmedns:
+ subdomain: ENC[AES256_GCM,data:XncJZ7qT51dLSkvfIc0Nc3SFxK1y/ip1cO4HA9CJMFtQy+mP,iv:mgwfx0QMzHadvUDZDYCzsiP1Oh+P/5DekbZ4M6y08t4=,tag:4oyXvAJEOFlw7wrrrhwspQ==,type:str]
+ apiUser: ENC[AES256_GCM,data:YLhXPrrts+JtwRMLrU2oM8hLTiFvZuqrlLrNKtgoL8IUdTxe,iv:L2R0YNRNoMuWGMYvgwRLP0RZwxqmMfQL4REyMX6VIuo=,tag:LegIPuVqMcxpIL1ZksIgbg==,type:str]
+ apiKey: ENC[AES256_GCM,data:NbyLJeFhUOac3pWkMTjdRPd9IKSwLYZR6ahiFljLJo5So5nnsL/tAw==,iv:DerEdaPnUWr3pCPzq8A8y5qIH3RKwHZ+EqKh8sHAVaU=,tag:PrxKMdRwxGPCP7Z9XDuI0A==,type:str]
ansible_pull__age_private_key: ENC[AES256_GCM,data:Yi4ST1zDVN4dLDs9i6aajUvEzTSYvwfYIRZUC278rgdO0bGk4y6saevmqK4mUnpIpz8M+ze//1OTDTgU6K4AE1TsX8vWB7fboGE=,iv:srZYtxDXXkCu5h7HwYbMtPr7PYhhgJ8rZQ3H4TOJmTk=,tag:iq6YEEyzYd6rNoAIgdk5Sw==,type:str]
-secret__acme_dns_api_key_dooris_ccchh_net: ENC[AES256_GCM,data:1qDNE8CeXo6SA5vaZYQ/2yNUE9Y1nUkL976Qsq6D9QYCc3fIrkKMXg==,iv:clOa/vwup2QS0Yvq8JTFGhCkuviWWBPNzp0tht8WZXY=,tag:WwN035cE5AxVSpJqRqkGqw==,type:str]
sops:
age:
- - recipient: age1j0876shgsn7f2thxh9kx9x5uwnh45z6sy2jlk2qz5jhgedm26g5srn9kax
- enc: |
+ - enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrYW9aYzMxeFYxemp5MUlR
NGJOaDRCc2E5bGdjSnFkcm5YMTdaSldKSFVVCmJmNERQbDF0Y2NDZGNnWVE5UlIy
@@ -13,8 +16,9 @@ sops:
YVc5c281N0Fod2hib29wOEJXZkZKOXMKx2g337TvrUk5hXZNbxlPlrWOydYbSBoW
aHvFML6xynRtBrMsp9IebicBxZKSWLi7uHi+LuAzkIcqpAlJUUBAbg==
-----END AGE ENCRYPTED FILE-----
- lastmodified: "2026-04-19T21:46:01Z"
- mac: ENC[AES256_GCM,data:5VlEYqo7ez4EgdMqGGnelc02EoT/bCLYVbPGHth4kd+DhOaJ1EXhmVB5eiX3AwyRl2nr79z/idCDJ6R1QdfQ5v8rYnnWcqehtiIIz0RBXhbED/hN2oz48yRhIX9vCB0gjsK6cacDzTCHP0tPEsQF+Ax4uWdXNHKnZVYS70qxbEI=,iv:noc3LJdiZ10w9O6JfwTxzLUNKT74rfdTX/Gb94fP3JI=,tag:WgFpYsFO3WjrjCs/7R634w==,type:str]
+ recipient: age1j0876shgsn7f2thxh9kx9x5uwnh45z6sy2jlk2qz5jhgedm26g5srn9kax
+ lastmodified: "2026-07-29T12:14:25Z"
+ mac: ENC[AES256_GCM,data:rBtCeee53GXl+upHXGP4TTpUvszMzV0r1eQqzE7jG3WP/ywqfWqsM+sp3124wQzHTZoMxJc0m95YAseSdA+7EFSAQPRRdpfzMxTpoKQBFHS0BfgM/14ppB+kDER1ucNKT521+PyOjbmB86ovTc8MfR2vsHDZ+FrIopUGzPpcBPs=,iv:JiSoJxPt9JW/kWy0aVz6jGNOoQPkZKG/vTkdis/fKSo=,tag:0V6hicsuT6/qLjGb/+fJPw==,type:str]
pgp:
- created_at: "2026-05-20T02:08:48Z"
enc: |-
@@ -187,4 +191,4 @@ sops:
-----END PGP MESSAGE-----
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
unencrypted_suffix: _unencrypted
- version: 3.12.2
+ version: 3.13.2
diff --git a/inventories/z9/host_vars/dooris.yaml b/inventories/z9/host_vars/dooris.yaml
index 3792153d..14231924 100644
--- a/inventories/z9/host_vars/dooris.yaml
+++ b/inventories/z9/host_vars/dooris.yaml
@@ -1,21 +1,5 @@
-docker_compose__compose_file_content: "{{ lookup('ansible.builtin.template', 'resources/z9/dooris/docker_compose/compose.yaml.j2') }}"
-docker_compose__configuration_files: [ ]
+dooris__hostname: "dooris.ccchh.net"
+dooris__openid_client_id: "dooris"
+dooris__ccujack_user: "dooris"
certbot__acme_account_email_address: le-admin@hamburg.ccc.de
-certbot__certs:
- - commonName: "dooris.ccchh.net"
- challengeType: "dns-01-acme-dns"
- dns_01_acme_dns:
- subdomain: "37caae1f-b77f-4eb1-aa71-dc3f7ed24360"
- apiUser: "fd42b696-a394-4e2a-8fcc-d44c9fac5d4e"
- apiKey: "{{ secret__acme_dns_api_key_dooris_ccchh_net }}"
-certbot__new_cert_commands:
- - "systemctl restart nginx.service"
-
-nginx__version_spec: ""
-nginx__deploy_redirect_conf: false
-nginx__configurations:
- - name: dooris.ccchh.net
- content: "{{ lookup('ansible.builtin.file', 'resources/z9/dooris/nginx/dooris.ccchh.net.conf') }}"
- - name: http_handler
- content: "{{ lookup('ansible.builtin.file', 'resources/z9/dooris/nginx/http_handler.conf') }}"
diff --git a/inventories/z9/hosts.yaml b/inventories/z9/hosts.yaml
index 38e29fd6..b4373d6c 100644
--- a/inventories/z9/hosts.yaml
+++ b/inventories/z9/hosts.yaml
@@ -17,11 +17,9 @@ all:
ansible_user: chaos
certbot_hosts:
hosts:
- dooris:
light:
docker_compose_hosts:
hosts:
- dooris:
waybackproxy:
yate:
foobazdmx_hosts:
@@ -38,7 +36,6 @@ infrastructure_authorized_keys_hosts:
yate:
nginx_hosts:
hosts:
- dooris:
light:
waybackproxy:
ola_hosts:
diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml
index 7a144409..59fe15a4 100644
--- a/playbooks/deploy.yaml
+++ b/playbooks/deploy.yaml
@@ -170,3 +170,10 @@
- transmission
tags:
- transmission
+
+- name: Setup dooris
+ hosts: dooris
+ roles:
+ - dooris
+ tags:
+ - dooris
diff --git a/resources/z9/dooris/docker_compose/compose.yaml.j2 b/resources/z9/dooris/docker_compose/compose.yaml.j2
deleted file mode 100644
index e81b2335..00000000
--- a/resources/z9/dooris/docker_compose/compose.yaml.j2
+++ /dev/null
@@ -1,17 +0,0 @@
----
-
-services:
- dooris:
- image: git.hamburg.ccc.de/ccchh/dooris:latest
- environment:
- DOORIS_OPENID_ISSUER: https://id.hamburg.ccc.de/realms/ccchh/
- DOORIS_OPENID_CLIENT_ID: dooris
- DOORIS_OPENID_CLIENT_SECRET: "{{ secret__dooris_client_secret }}"
- DOORIS_BASE_URL: https://dooris.ccchh.net
- DOORIS_CCUJACK_USER: "dooris"
- DOORIS_CCUJACK_PASSWORD: "{{ secret__dooris_ccujack_password }}"
- DOORIS_AUTHORIZED_KEYS_FILE: "/srv/state/dooris_authorized_keys"
- network_mode: host
- restart: unless-stopped
- volumes:
- - "./state:/srv/state/:rw"
diff --git a/roles/dooris/README.md b/roles/dooris/README.md
new file mode 100644
index 00000000..f868b1d5
--- /dev/null
+++ b/roles/dooris/README.md
@@ -0,0 +1,16 @@
+# dooris
+
+Deployment configuration of [dooris](https://git.hamburg.ccc.de/CCCHH/dooris) on our host.
+For an exact description of host requirements, see the README of dooris itself.
+
+## Required Arguments
+
+- `dooris__hostname`: The hostname on which the dooris server is reachable
+- `dooris__ccujack_user`: Username for authentication against homematic ccujack
+- `dooris__ccujack_password` Password for authentication against homematic ccujack
+- `dooris__openid_client_id`: Client-ID in CCCHH ID for dooris
+- `dooris__openid_client_secret`: Client-Secret in CCCHH ID for dooris
+- `dooris__static_api_token`: A static token that is valid on the servers API and can operate locks
+- `dooris__acmedns`: Configuration of ACMEDNS domain + credentials for dooris.
+ Must be a dict with keys `subdomain`, `apiUser`, `apiKey` which are shown when creating a domain in ACMEDNS.
+
diff --git a/roles/dooris/handlers/main.yml b/roles/dooris/handlers/main.yml
new file mode 100644
index 00000000..0e3528f6
--- /dev/null
+++ b/roles/dooris/handlers/main.yml
@@ -0,0 +1,5 @@
+- name: "reload sshd"
+ become: true
+ ansible.builtin.systemd_service:
+ name: "ssh.service"
+ state: "reloaded"
diff --git a/roles/dooris/meta/argument_specs.yml b/roles/dooris/meta/argument_specs.yml
new file mode 100644
index 00000000..2d2726ac
--- /dev/null
+++ b/roles/dooris/meta/argument_specs.yml
@@ -0,0 +1,48 @@
+argument_specs:
+ main:
+ options:
+ dooris__static_api_token:
+ description: "A static token that is valid on the servers API and can operate locks"
+ required: true
+ type: str
+
+ dooris__hostname:
+ description: "The hostname on which the dooris server is reachable"
+ required: true
+ type: str
+
+ dooris__openid_client_id:
+ description: "Client-ID in CCCHH ID for dooris"
+ required: true
+ type: str
+
+ dooris__openid_client_secret:
+ description: "Client-Secret in CCCHH ID for dooris"
+ required: true
+ type: str
+
+ dooris__ccujack_user:
+ description: "Username for authentication against homematic ccujack"
+ required: true
+ type: str
+
+ dooris__ccujack_password:
+ description: "Password for authentication against homematic ccujack"
+ required: true
+ type: str
+
+ dooris__acmedns:
+ description: "Configuration of ACMEDNS domain + credentials for dooris"
+ required: true
+ type: dict
+ options:
+ subdomain:
+ required: true
+ type: str
+ apiUser:
+ required: true
+ type: str
+ apiKey:
+ required: true
+ type: str
+
diff --git a/roles/dooris/meta/main.yml b/roles/dooris/meta/main.yml
new file mode 100644
index 00000000..77baaf55
--- /dev/null
+++ b/roles/dooris/meta/main.yml
@@ -0,0 +1,27 @@
+dependencies:
+ - role: docker_compose
+ vars:
+ docker_compose__compose_file_content: "{{ lookup('ansible.builtin.template', 'compose.yaml.j2') }}"
+ docker_compose__configuration_files: []
+
+ - role: certbot
+ vars:
+ certbot__new_cert_commands:
+ - "systemctl restart nginx.service"
+ certbot__certs:
+ - commonName: "{{ dooris__hostname }}"
+ challengeType: "dns-01-acme-dns"
+ dns_01_acme_dns:
+ subdomain: "{{ dooris__acmedns.subdomain }}"
+ apiUser: "{{ dooris__acmedns.apiUser }}"
+ apiKey: "{{ dooris__acmedns.apiKey }}"
+
+ - role: nginx
+ vars:
+ nginx__version_spec: ""
+ nginx__deploy_redirect_conf: false
+ nginx__configurations:
+ - name: "{{ dooris__hostname }}"
+ content: "{{ lookup('ansible.builtin.template', 'nginx/site.conf') }}"
+ - name: http_handler
+ content: "{{ lookup('ansible.builtin.template', 'nginx/http_handler.conf') }}"
diff --git a/roles/dooris/tasks/main.yml b/roles/dooris/tasks/main.yml
new file mode 100644
index 00000000..659dccd6
--- /dev/null
+++ b/roles/dooris/tasks/main.yml
@@ -0,0 +1,34 @@
+- name: Create local dooris group
+ become: true
+ ansible.builtin.group:
+ name: "dooris"
+ gid: 10000
+
+- name: Create local dooris user
+ become: true
+ ansible.builtin.user:
+ name: "dooris"
+ uid: 10000
+ group: "dooris"
+ system: true
+ password: "!"
+ home: "/ansible_docker_compose/state/"
+ shell: "/ansible_docker_compose/state/ssh-cli"
+
+- name: Ensure dooris state directory exists and has correct permissions
+ become: true
+ ansible.builtin.file:
+ path: "/ansible_docker_compose/state/"
+ owner: "dooris"
+ group: "dooris"
+ mode: "u=rwx,g=rx,o="
+
+- name: Create ssh server config for dooris user
+ become: true
+ notify: "reload sshd"
+ ansible.builtin.template:
+ src: sshd_config
+ dest: /etc/ssh/sshd_config.d/dooris.conf
+ owner: root
+ group: root
+ mode: u=rw,g=r,o=r
diff --git a/roles/dooris/templates/compose.yaml.j2 b/roles/dooris/templates/compose.yaml.j2
new file mode 100644
index 00000000..2bb5e825
--- /dev/null
+++ b/roles/dooris/templates/compose.yaml.j2
@@ -0,0 +1,17 @@
+---
+services:
+ dooris:
+ image: git.hamburg.ccc.de/ccchh/dooris:latest
+ environment:
+ DOORIS_OPENID_ISSUER: https://id.hamburg.ccc.de/realms/ccchh/
+ DOORIS_OPENID_CLIENT_ID: "{{ dooris__openid_client_id }}"
+ DOORIS_OPENID_CLIENT_SECRET: "{{ dooris__openid_client_secret }}"
+ DOORIS_BASE_URL: "https://{{ dooris__hostname }}"
+ DOORIS_CCUJACK_USER: "{{ dooris__ccujack_user }}"
+ DOORIS_CCUJACK_PASSWORD: "{{ dooris__ccujack_password }}"
+ DOORIS_AUTHORIZED_KEYS_FILE: "/srv/state/dooris_authorized_keys"
+ DOORIS_STATIC_API_TOKENS: "{{ dooris__static_api_token }}"
+ network_mode: host
+ restart: unless-stopped
+ volumes:
+ - "./state:/srv/state/:rw"
diff --git a/resources/z9/dooris/nginx/http_handler.conf b/roles/dooris/templates/nginx/http_handler.conf
similarity index 100%
rename from resources/z9/dooris/nginx/http_handler.conf
rename to roles/dooris/templates/nginx/http_handler.conf
diff --git a/resources/z9/dooris/nginx/dooris.ccchh.net.conf b/roles/dooris/templates/nginx/site.conf
similarity index 84%
rename from resources/z9/dooris/nginx/dooris.ccchh.net.conf
rename to roles/dooris/templates/nginx/site.conf
index efb5b1f1..a5c2b1c1 100644
--- a/resources/z9/dooris/nginx/dooris.ccchh.net.conf
+++ b/roles/dooris/templates/nginx/site.conf
@@ -4,12 +4,12 @@ server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
- server_name dooris.ccchh.net;
+ server_name {{ dooris__hostname }};
- ssl_certificate /etc/letsencrypt/live/dooris.ccchh.net/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/dooris.ccchh.net/privkey.pem;
+ ssl_certificate /etc/letsencrypt/live/{{ dooris__hostname }}/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/{{ dooris__hostname }}/privkey.pem;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
- ssl_trusted_certificate /etc/letsencrypt/live/dooris.ccchh.net/chain.pem;
+ ssl_trusted_certificate /etc/letsencrypt/live/{{ dooris__hostname }}/chain.pem;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
diff --git a/roles/dooris/templates/sshd_config b/roles/dooris/templates/sshd_config
new file mode 100644
index 00000000..ea246f33
--- /dev/null
+++ b/roles/dooris/templates/sshd_config
@@ -0,0 +1,6 @@
+# {{ ansible_managed }}
+
+Match User dooris
+ AuthorizedKeysFile /ansible_docker_compose/state/dooris_authorized_keys
+ ForceCommand /ansible_docker_compose/state/ssh-cli
+ SetEnv DOORIS_SERVER_URL=https://{{ dooris__hostname }} DOORIS_API_TOKEN={{ dooris__static_api_token}}