From ac7e8bb6f22e73e591abec4b2000f11291fa2e59 Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Sat, 15 Feb 2025 06:05:44 +0100
Subject: [PATCH 01/11] grafana: set dur. for Prom. hyperv. disk rw rate and
 hdd io aler. to 90m

Set duration for Prometheus hypervisor disk rw rate and hard disk io
alerts to 90m to account for the very long running (over an hour) backup
job.
---
 .../grafana/docker_compose/prometheus_alerts.rules.yaml     | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/resources/chaosknoten/grafana/docker_compose/prometheus_alerts.rules.yaml b/resources/chaosknoten/grafana/docker_compose/prometheus_alerts.rules.yaml
index 5cc54e9..f684385 100644
--- a/resources/chaosknoten/grafana/docker_compose/prometheus_alerts.rules.yaml
+++ b/resources/chaosknoten/grafana/docker_compose/prometheus_alerts.rules.yaml
@@ -166,7 +166,7 @@ groups:
       # Longer intervals to account for disk intensive hypervisor tasks (backups, moving VMs, etc.).
       - alert: HypervisorHostUnusualDiskReadRate
         expr: (sum by (instance) (rate(node_disk_read_bytes_total[2m])) / 1024 / 1024 > 50) * on(instance) group_left (nodename) node_uname_info{nodename="chaosknoten"}
-        for: 60m
+        for: 90m
         labels:
           severity: warning
         annotations:
@@ -174,7 +174,7 @@ groups:
           description: "Disk is probably reading too much data (> 50 MB/s)\n  VALUE = {{ $value }}"
       - alert: HypervisorHostUnusualDiskWriteRate
         expr: (sum by (instance) (rate(node_disk_written_bytes_total[2m])) / 1024 / 1024 > 50) * on(instance) group_left (nodename) node_uname_info{nodename="chaosknoten"}
-        for: 60m
+        for: 90m
         labels:
           severity: warning
         annotations:
@@ -256,7 +256,7 @@ groups:
       # Since hard disks on the hypervisor can easily have their IO saturated by hypervisor tasks (backups, moving VMs, etc.), alert when the IO is above the regular threshold for a very long time.
       - alert: HypervisorHostUnusualHardDiskIo
         expr: (rate(node_disk_io_time_seconds_total{device=~"s.+"}[1m]) > 0.5) * on(instance) group_left (nodename) node_uname_info{nodename="chaosknoten"}
-        for: 50m
+        for: 90m
         labels:
           severity: warning
         annotations:

From 537ef55b6f0e8086e62d3fb8dde08d3bac17ee44 Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Sat, 15 Feb 2025 06:21:14 +0100
Subject: [PATCH 02/11] eh22-wiki: add missing redirect for /design

Apparently this is still needed.
---
 .../chaosknoten/eh22-wiki/nginx/eh22.easterhegg.eu.conf     | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/resources/chaosknoten/eh22-wiki/nginx/eh22.easterhegg.eu.conf b/resources/chaosknoten/eh22-wiki/nginx/eh22.easterhegg.eu.conf
index 5b7f07f..d3ed959 100644
--- a/resources/chaosknoten/eh22-wiki/nginx/eh22.easterhegg.eu.conf
+++ b/resources/chaosknoten/eh22-wiki/nginx/eh22.easterhegg.eu.conf
@@ -64,6 +64,12 @@ server {
         fastcgi_pass unix:/var/run/php/php-fpm-dokuwiki.sock;
     }
 
+    location = /design {
+        # Disable port in redirect as NGINX would redirect to the PROXY Protocol port 8443 for locations like https://eh22.easterhegg.eu/design
+        port_in_redirect off;
+        return 302 /design/;
+    }
+
     location /design/ {
         # Disable port in redirect as NGINX would redirect to the PROXY Protocol port 8443 for locations like https://eh22.easterhegg.eu/design
         port_in_redirect off;

From fc24bfff5ddb2acc32f92d59fb144381cd471155 Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Thu, 13 Feb 2025 02:00:32 +0100
Subject: [PATCH 03/11] add redis role for ensuring redis is installed from
 distro packages

This is a requirement for a new netbox role.
---
 roles/redis/README.md       | 15 +++++++++++++++
 roles/redis/tasks/main.yaml |  5 +++++
 2 files changed, 20 insertions(+)
 create mode 100644 roles/redis/README.md
 create mode 100644 roles/redis/tasks/main.yaml

diff --git a/roles/redis/README.md b/roles/redis/README.md
new file mode 100644
index 0000000..dd30500
--- /dev/null
+++ b/roles/redis/README.md
@@ -0,0 +1,15 @@
+# Role `redis`
+
+Ensures `redis` is installed by installing the distributions package.
+
+## Supported Distributions
+
+Should work on Debian-based distributions.
+
+## Required Arguments
+
+None.
+
+## Optional Arguments
+
+None.
diff --git a/roles/redis/tasks/main.yaml b/roles/redis/tasks/main.yaml
new file mode 100644
index 0000000..ad70e44
--- /dev/null
+++ b/roles/redis/tasks/main.yaml
@@ -0,0 +1,5 @@
+- name: Ensure redis is installed
+  ansible.builtin.apt:
+    name:
+      - redis
+  become: true

From 96629953773060c5c60720f55bd3f096b0df7b29 Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Thu, 13 Feb 2025 03:24:15 +0100
Subject: [PATCH 04/11] add postgresql role for ens. psql and opt. some dbs and
 users are set up

Add postgresql role for ensuring postgresql is installed.
Furthermore the role optionally takes some basic configuration to ensure
databases with their owners and users are set up as specified.

This is a requirement for a new netbox role.
---
 roles/postgresql/README.md                | 37 +++++++++++++++++++++++
 roles/postgresql/defaults/main.yaml       |  2 ++
 roles/postgresql/meta/argument_specs.yaml | 28 +++++++++++++++++
 roles/postgresql/tasks/main.yaml          | 28 +++++++++++++++++
 4 files changed, 95 insertions(+)
 create mode 100644 roles/postgresql/README.md
 create mode 100644 roles/postgresql/defaults/main.yaml
 create mode 100644 roles/postgresql/meta/argument_specs.yaml
 create mode 100644 roles/postgresql/tasks/main.yaml

diff --git a/roles/postgresql/README.md b/roles/postgresql/README.md
new file mode 100644
index 0000000..6457931
--- /dev/null
+++ b/roles/postgresql/README.md
@@ -0,0 +1,37 @@
+# Role `postgresql`
+
+Ensures `postgresql` is installed by installing the distributions package.  
+Also ensures the optionally given databases and users are set up as specified.
+
+## Supported Distributions
+
+Should work on Debian-based distributions.
+
+## Required Arguments
+
+None.
+
+## Optional Arguments
+
+- `postgresql__dbs`: List of databases with their owner to ensure are set up.  
+- `postgresql__dbs.*.name`: Name of the database.
+- `postgresql__dbs.*.owner`: Owner of the database.
+- `postgresql__users`: List of users to ensure are set up.
+- `postgresql__users.*.name`: Name of the user.
+- `postgresql__users.*.password`: Optional password for the user.
+   If left unset, the user will have no password set, but can still connect using [peer authentication](https://www.postgresql.org/docs/current/auth-peer.html) on the local system.
+   (Peer authentication works when a password is set as well.)
+
+## Example Arguments
+
+```yaml
+postgresql__dbs:
+  - name: netbox
+    owner: netbox
+  - name: foo
+    owner: bar
+postgresql__users:
+  - name: netbox
+    password: super_secret
+  - name: bar
+```
diff --git a/roles/postgresql/defaults/main.yaml b/roles/postgresql/defaults/main.yaml
new file mode 100644
index 0000000..21fcd46
--- /dev/null
+++ b/roles/postgresql/defaults/main.yaml
@@ -0,0 +1,2 @@
+postgresql__dbs: [ ]
+postgresql__users: [ ]
diff --git a/roles/postgresql/meta/argument_specs.yaml b/roles/postgresql/meta/argument_specs.yaml
new file mode 100644
index 0000000..28e5813
--- /dev/null
+++ b/roles/postgresql/meta/argument_specs.yaml
@@ -0,0 +1,28 @@
+argument_specs:
+  main:
+    options:
+      postgresql__dbs:
+        type: list
+        elements: dict
+        required: false
+        default: [ ]
+        options:
+          name:
+            type: str
+            required: true
+          owner:
+            type: str
+            required: true
+      postgresql__users:
+        type: list
+        elements: dict
+        required: false
+        default: [ ]
+        options:
+          name:
+            type: str
+            required: true
+          password:
+            type: str
+            required: false
+            default: ""
diff --git a/roles/postgresql/tasks/main.yaml b/roles/postgresql/tasks/main.yaml
new file mode 100644
index 0000000..fc61857
--- /dev/null
+++ b/roles/postgresql/tasks/main.yaml
@@ -0,0 +1,28 @@
+- name: Ensure postgresql is installed
+  ansible.builtin.apt:
+    name:
+      - postgresql
+  become: true
+
+- name: Ensure Python library for community.postgresql is installed if needed
+  ansible.builtin.apt:
+    name:
+      - python3-psycopg
+  become: true
+  when: postgresql__dbs != [ ] or postgresql__users != [ ]
+
+- name: Ensure users
+  community.postgresql.postgresql_user:
+    name: "{{ item.name }}"
+    password: "{{ item.password | default('') }}"
+  become: true
+  become_user: postgres
+  loop: "{{ postgresql__users }}"
+
+- name: Ensure dbs with owners
+  community.postgresql.postgresql_db:
+    name: "{{ item.name }}"
+    owner: "{{ item.owner }}"
+  become: true
+  become_user: postgres
+  loop: "{{ postgresql__dbs }}"

From 783c36bcc1730505fbc9eadc22c822a4d23689f3 Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Fri, 14 Feb 2025 21:43:44 +0100
Subject: [PATCH 05/11] add netbox role for ensuring netbox is deployed as
 specified

The role takes over the deployment of netbox and its dependencies, while
still requiring the user to provide the netbox version, db password and
config as well as to set up a web server and handle stuff like creating
users, etc.
---
 roles/netbox/README.md                |  77 +++++++++++++++++++
 roles/netbox/handlers/main.yaml       |  24 ++++++
 roles/netbox/meta/argument_specs.yaml |  12 +++
 roles/netbox/meta/main.yaml           |  11 +++
 roles/netbox/tasks/main.yaml          | 103 ++++++++++++++++++++++++++
 5 files changed, 227 insertions(+)
 create mode 100644 roles/netbox/README.md
 create mode 100644 roles/netbox/handlers/main.yaml
 create mode 100644 roles/netbox/meta/argument_specs.yaml
 create mode 100644 roles/netbox/meta/main.yaml
 create mode 100644 roles/netbox/tasks/main.yaml

diff --git a/roles/netbox/README.md b/roles/netbox/README.md
new file mode 100644
index 0000000..38b7968
--- /dev/null
+++ b/roles/netbox/README.md
@@ -0,0 +1,77 @@
+# `netbox` role
+
+A role for setting up NetBox.  
+It automatically pulls in all required dependencies like Redis and PostgreSQL, deploys the provided systemd services and gunicorn config and sets up a PostgreSQL database named `netbox` with an owner named `netbox` and the specified password.
+However providing the [NetBox configuration](#netbox-configuration), [setting up a web server like nginx to proxy to gunicorn](#web-server-setup) and tasks like creating users, etc. you have to do yourself.
+
+## Supported Distributions
+
+Should work on Debian-based distributions.
+
+## Required Arguments
+
+- `netbox__version`: The NetBox version to deploy.
+- `netbox__db_password`: The password to use for connection to the database.
+  This is required since the upgrade script runs as root and therefore peer authentication doesn't work.
+- `netbox__config`: The NetBox config to deploy.
+  See [NetBox Configuration](#netbox-configuration) for more infos.
+
+## Optional Arguments
+
+None.
+
+## NetBox Configuration
+
+The NetBox configuration should include a connection to Redis as well as a connection to PostgreSQL.  
+Configuration for the Redis connection:
+
+```python
+REDIS = {
+    "tasks": {
+      "HOST": "localhost",
+      "PORT": 6379,
+      "USERNAME": "",
+      "PASSWORD": "",
+      "DATABASE": 0,
+      "SSL": False,
+    },
+    "caching": {
+      "HOST": "localhost",
+      "PORT": 6379,
+      "USERNAME": "",
+      "PASSWORD": "",
+      "DATABASE": 1,
+      "SSL": False,
+    },
+}
+```
+
+Configuration for the PostgreSQL connection:
+
+```python
+DATABASE = {
+  "HOST": "localhost",
+  "NAME": "netbox",
+  "USER": "netbox",
+  "PASSWORD": "<same as netbox__db_password>",
+}
+```
+
+Further configuration should take place. Some relevant resources can be found here:
+
+- Installation guide configuration docs: <https://netboxlabs.com/docs/netbox/en/stable/installation/3-netbox/#configuration>
+- Configuration docs: <https://netboxlabs.com/docs/netbox/en/stable/configuration/>
+- Example configuration: <https://github.com/netbox-community/netbox/blob/main/netbox/netbox/configuration_example.py>
+
+## Web Server Setup
+
+As this role just sets up gunicorn, but doesn't set up a web server, you need to do that yourself.  
+The relevant documentation on how to do that can be found here:
+
+- Web server setup docs: <https://netboxlabs.com/docs/netbox/en/stable/installation/5-http-server/>
+- Example base nginx config: <https://github.com/netbox-community/netbox/blob/main/contrib/nginx.conf>
+
+## Links & Resources
+
+- The NetBox Git Repo: <https://github.com/netbox-community/netbox>
+- The NetBox installation docs: <https://netboxlabs.com/docs/netbox/en/stable/installation/>
diff --git a/roles/netbox/handlers/main.yaml b/roles/netbox/handlers/main.yaml
new file mode 100644
index 0000000..fd7eb62
--- /dev/null
+++ b/roles/netbox/handlers/main.yaml
@@ -0,0 +1,24 @@
+- name: Run upgrade script
+  ansible.builtin.command: /opt/netbox/upgrade.sh
+  become: true
+  # When it runs, this should always report changed.
+  changed_when: true
+
+- name: Ensure netbox systemd services are set up and up-to-date
+  ansible.builtin.systemd_service:
+    daemon_reload: true
+    name: "{{ item }}"
+    enabled: true
+    state: restarted
+  become: true
+  loop:
+    - "netbox.service"
+    - "netbox-rq.service"
+
+- name: Ensure netbox housekeeping timer is set up and up-to-date
+  ansible.builtin.systemd_service:
+    daemon_reload: true
+    name: "netbox-housekeeping.timer"
+    enabled: true
+    state: restarted
+  become: true
diff --git a/roles/netbox/meta/argument_specs.yaml b/roles/netbox/meta/argument_specs.yaml
new file mode 100644
index 0000000..f836b43
--- /dev/null
+++ b/roles/netbox/meta/argument_specs.yaml
@@ -0,0 +1,12 @@
+argument_specs:
+  main:
+    options:
+      netbox__version:
+        type: str
+        required: true
+      netbox__db_password:
+        type: str
+        required: true
+      netbox__config:
+        type: str
+        required: true
diff --git a/roles/netbox/meta/main.yaml b/roles/netbox/meta/main.yaml
new file mode 100644
index 0000000..79c845d
--- /dev/null
+++ b/roles/netbox/meta/main.yaml
@@ -0,0 +1,11 @@
+---
+dependencies:
+  - role: redis
+  - role: postgresql
+    vars:
+      postgresql__dbs:
+        - name: netbox
+          owner: netbox
+      postgresql__users:
+        - name: netbox
+          password: "{{ netbox__db_password }}"
diff --git a/roles/netbox/tasks/main.yaml b/roles/netbox/tasks/main.yaml
new file mode 100644
index 0000000..89bf4a6
--- /dev/null
+++ b/roles/netbox/tasks/main.yaml
@@ -0,0 +1,103 @@
+- name: Ensure all dependencies are installed
+  ansible.builtin.apt:
+    name:
+      - python3
+      - python3-pip
+      - python3-venv
+      - python3-dev
+      - build-essential
+      - libxml2-dev
+      - libxslt1-dev
+      - libffi-dev
+      - libpq-dev
+      - libssl-dev
+      - zlib1g-dev
+      - git
+  become: true
+
+- name: Ensure NetBox source is present
+  ansible.builtin.git:
+    repo: https://github.com/netbox-community/netbox.git
+    dest: /opt/netbox/
+    version: "{{ netbox__version }}"
+  become: true
+  notify:
+    - Run upgrade script
+    - Ensure netbox systemd services are set up and up-to-date
+
+- name: Ensure netbox user
+  block:
+    - name: Ensure netbox group exists
+      ansible.builtin.group:
+        name: netbox
+        system: true
+      become: true
+
+    - name: Ensure netbox user exists
+      ansible.builtin.user:
+        name: netbox
+        group: netbox
+        password: '!'
+        system: true
+      become: true
+
+- name: Ensure relevant directories are owned by netbox user
+  ansible.builtin.file:
+    path: "{{ item }}"
+    state: directory
+    owner: netbox
+    recurse: true
+  become: true
+  loop:
+    - "/opt/netbox/netbox/media/"
+    - "/opt/netbox/netbox/reports/"
+    - "/opt/netbox/netbox/scripts/"
+
+- name: Deploy configuration.py
+  ansible.builtin.copy:
+    content: "{{ netbox__config }}"
+    dest: "/opt/netbox/netbox/netbox/configuration.py"
+    mode: "0644"
+    owner: root
+    group: root
+  become: true
+  notify: Ensure netbox systemd services are set up and up-to-date
+
+- name: Ensure provided gunicorn config is copied
+  ansible.builtin.copy:
+    remote_src: true
+    src: "/opt/netbox/contrib/gunicorn.py"
+    dest: "/opt/netbox/gunicorn.py"
+    mode: "0644"
+    owner: root
+    group: root
+  become: true
+  notify: Ensure netbox systemd services are set up and up-to-date
+
+- name: Ensure provided netbox systemd service files are copied
+  ansible.builtin.copy:
+    remote_src: true
+    src: "/opt/netbox/contrib/{{ item }}"
+    dest: "/etc/systemd/system/{{ item }}"
+    mode: "0644"
+    owner: root
+    group: root
+  become: true
+  loop:
+    - "netbox.service"
+    - "netbox-rq.service"
+  notify: Ensure netbox systemd services are set up and up-to-date
+
+- name: Ensure provided housekeeping systemd service and timer are copied
+  ansible.builtin.copy:
+    remote_src: true
+    src: "/opt/netbox/contrib/{{ item }}"
+    dest: "/etc/systemd/system/{{ item }}"
+    mode: "0644"
+    owner: root
+    group: root
+  become: true
+  loop:
+    - "netbox-housekeeping.service"
+    - "netbox-housekeeping.timer"
+  notify: Ensure netbox housekeeping timer is set up and up-to-date

From dbb784e2bbafdd4983c00fffd379c2e46a66b8f6 Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Sat, 15 Feb 2025 03:52:02 +0100
Subject: [PATCH 06/11] add license notice to README

This is in preparation for extending that notice to point out code that
is licensed differently.
---
 README.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/README.md b/README.md
index 68c92b4..ab14d1d 100644
--- a/README.md
+++ b/README.md
@@ -45,3 +45,7 @@ Im Ansible-Repo müssen diese Sachen hinzugefügt werden:
     * Individuelle Config für den Service. Wenn Docker Compose, hier weiterleiten auf den eigentlichen Dienst in Compose.
     * Cert-Dateinamen anpassen
 * `resources/chaosknoten/`*host*`/docker_compose/compose.yaml.j2`: Config für Docker Compose (wenn verwendet)
+
+## License
+
+This CCCHH ansible-ccchh repository is licensed under the [MIT License](./LICENSE).

From 09a8551c8ae56a10b12752f1a2cacd0309fc5383 Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Sat, 15 Feb 2025 05:22:21 +0100
Subject: [PATCH 07/11] add option to netbox role for custom pipeline code for
 OIDC mapping

Add option to netbox role for ensuring custom pipeline code for OIDC
group and role mapping is either present or not.

The custom pipeline code is licensed under the Creative Commons: CC
BY-SA 4.0 license.

See:
https://github.com/goauthentik/authentik/blob/main/LICENSE
https://github.com/goauthentik/authentik/blob/main/website/integrations/services/netbox/index.md
https://docs.goauthentik.io/integrations/services/netbox/
https://git.hamburg.ccc.de/CCCHH/nix-infra/commit/5676b1a4680dbe706686f38902f5607ec33330ff
---
 README.md                                     |  3 +-
 roles/netbox/README.md                        | 13 ++++-
 roles/netbox/defaults/main.yaml               |  1 +
 ...om_pipeline_oidc_group_and_role_mapping.py | 55 +++++++++++++++++++
 roles/netbox/meta/argument_specs.yaml         |  4 ++
 roles/netbox/tasks/main.yaml                  | 21 +++++++
 6 files changed, 95 insertions(+), 2 deletions(-)
 create mode 100644 roles/netbox/defaults/main.yaml
 create mode 100644 roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py

diff --git a/README.md b/README.md
index ab14d1d..6906a7f 100644
--- a/README.md
+++ b/README.md
@@ -48,4 +48,5 @@ Im Ansible-Repo müssen diese Sachen hinzugefügt werden:
 
 ## License
 
-This CCCHH ansible-ccchh repository is licensed under the [MIT License](./LICENSE).
+This CCCHH ansible-ccchh repository is licensed under the [MIT License](./LICENSE).  
+[`custom_pipeline_oidc_group_and_role_mapping.py`](./roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py) is licensed under the Creative Commons: CC BY-SA 4.0 license.
diff --git a/roles/netbox/README.md b/roles/netbox/README.md
index 38b7968..594e8f8 100644
--- a/roles/netbox/README.md
+++ b/roles/netbox/README.md
@@ -18,7 +18,9 @@ Should work on Debian-based distributions.
 
 ## Optional Arguments
 
-None.
+- `netbox__custom_pipeline_oidc_group_and_role_mapping`: Whether or not to have custom pipeline code for OIDC group and role mapping present.
+  See [Custom Pipeline Code for OIDC Group and Role Mapping](#custom-pipeline-code-for-oidc-group-and-role-mapping) for more infos.  
+  Defaults to `false`.
 
 ## NetBox Configuration
 
@@ -71,6 +73,15 @@ The relevant documentation on how to do that can be found here:
 - Web server setup docs: <https://netboxlabs.com/docs/netbox/en/stable/installation/5-http-server/>
 - Example base nginx config: <https://github.com/netbox-community/netbox/blob/main/contrib/nginx.conf>
 
+## Custom Pipeline Code for OIDC Group and Role Mapping
+
+Setting the option `netbox__custom_pipeline_oidc_group_and_role_mapping` to `true` makes this role ensure custom pipeline code for OIDC group and role mapping is present.
+Note that this role uses code for NetBox >= 4.0.0.  
+The code is available in `files/custom_pipeline_oidc_group_and_role_mapping.py`, licensed under the CC BY-SA 4.0 license and taken from [this authentik NetBox documentation](https://docs.goauthentik.io/integrations/services/netbox/).
+The documentation also shows how to use the pipeline code by defining a custom `SOCIAL_AUTH_PIPELINE`, which you also need to do, as the configuration isn't provided by this role.
+However instead of under `netbox.custom_pipeline.` the functions are available under `netbox.custom_pipeline_oidc_mapping.` with this role.
+See also [the default settings.py](https://github.com/netbox-community/netbox/blob/main/netbox/netbox/settings.py) for the default `SOCIAL_AUTH_PIPELINE`.
+
 ## Links & Resources
 
 - The NetBox Git Repo: <https://github.com/netbox-community/netbox>
diff --git a/roles/netbox/defaults/main.yaml b/roles/netbox/defaults/main.yaml
new file mode 100644
index 0000000..49b518e
--- /dev/null
+++ b/roles/netbox/defaults/main.yaml
@@ -0,0 +1 @@
+netbox__custom_pipeline_oidc_group_and_role_mapping: false
diff --git a/roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py b/roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py
new file mode 100644
index 0000000..470f388
--- /dev/null
+++ b/roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py
@@ -0,0 +1,55 @@
+# Licensed under Creative Commons: CC BY-SA 4.0 license.
+# https://github.com/goauthentik/authentik/blob/main/LICENSE
+# https://github.com/goauthentik/authentik/blob/main/website/integrations/services/netbox/index.md
+# https://docs.goauthentik.io/integrations/services/netbox/
+from netbox.authentication import Group
+
+class AuthFailed(Exception):
+    pass
+
+def add_groups(response, user, backend, *args, **kwargs):
+    try:
+        groups = response['groups']
+    except KeyError:
+        pass
+
+    # Add all groups from oAuth token
+    for group in groups:
+        group, created = Group.objects.get_or_create(name=group)
+        user.groups.add(group)
+
+def remove_groups(response, user, backend, *args, **kwargs):
+    try:
+        groups = response['groups']
+    except KeyError:
+        # Remove all groups if no groups in oAuth token
+        user.groups.clear()
+        pass
+
+    # Get all groups of user
+    user_groups = [item.name for item in user.groups.all()]
+    # Get groups of user which are not part of oAuth token
+    delete_groups = list(set(user_groups) - set(groups))
+
+    # Delete non oAuth token groups
+    for delete_group in delete_groups:
+        group = Group.objects.get(name=delete_group)
+        user.groups.remove(group)
+
+
+def set_roles(response, user, backend, *args, **kwargs):
+    # Remove Roles temporary
+    user.is_superuser = False
+    user.is_staff = False
+    try:
+        groups = response['groups']
+    except KeyError:
+        # When no groups are set
+        # save the user without Roles
+        user.save()
+        pass
+
+    # Set roles is role (superuser or staff) is in groups
+    user.is_superuser = True if 'superusers' in groups else False
+    user.is_staff = True if 'staff' in groups else False
+    user.save()
diff --git a/roles/netbox/meta/argument_specs.yaml b/roles/netbox/meta/argument_specs.yaml
index f836b43..0506389 100644
--- a/roles/netbox/meta/argument_specs.yaml
+++ b/roles/netbox/meta/argument_specs.yaml
@@ -10,3 +10,7 @@ argument_specs:
       netbox__config:
         type: str
         required: true
+      netbox__custom_pipeline_oidc_group_and_role_mapping:
+        type: bool
+        required: false
+        default: false
diff --git a/roles/netbox/tasks/main.yaml b/roles/netbox/tasks/main.yaml
index 89bf4a6..dffa746 100644
--- a/roles/netbox/tasks/main.yaml
+++ b/roles/netbox/tasks/main.yaml
@@ -25,6 +25,27 @@
     - Run upgrade script
     - Ensure netbox systemd services are set up and up-to-date
 
+- name: Ensures custom pipeline code for OIDC group and role mapping is present
+  ansible.builtin.copy:
+    src: custom_pipeline_oidc_group_and_role_mapping.py
+    dest: /opt/netbox/netbox/netbox/custom_pipeline_oidc_mapping.py
+    mode: "0644"
+    owner: root
+    group: root
+  when: netbox__custom_pipeline_oidc_group_and_role_mapping
+  become: true
+  notify:
+    - Ensure netbox systemd services are set up and up-to-date
+
+- name: Ensures custom pipeline code for OIDC group and role mapping is not present
+  ansible.builtin.file:
+    path: /opt/netbox/netbox/netbox/custom_pipeline_oidc_mapping.py
+    state: absent
+  when: not netbox__custom_pipeline_oidc_group_and_role_mapping
+  become: true
+  notify:
+    - Ensure netbox systemd services are set up and up-to-date
+
 - name: Ensure netbox user
   block:
     - name: Ensure netbox group exists

From 2ec1471d7fb1483bf1753e93b3971ce5a2df583c Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Sat, 15 Feb 2025 19:57:15 +0100
Subject: [PATCH 08/11] netbox: move NetBox from NixOS to Ansible

Also introduce netbox_hosts group for applying netbox role to multiple
hosts.
---
 inventories/chaosknoten/host_vars/netbox.yaml | 16 +++++
 inventories/chaosknoten/hosts.yaml            | 12 ++++
 playbooks/deploy.yaml                         |  5 ++
 .../netbox/netbox/configuration.py.j2         | 60 +++++++++++++++++++
 .../netbox/nginx/netbox.hamburg.ccc.de.conf   | 48 +++++++++++++++
 .../nginx/acme_challenge.conf                 |  2 +-
 .../public-reverse-proxy/nginx/nginx.conf     |  2 +-
 7 files changed, 143 insertions(+), 2 deletions(-)
 create mode 100644 inventories/chaosknoten/host_vars/netbox.yaml
 create mode 100644 resources/chaosknoten/netbox/netbox/configuration.py.j2
 create mode 100644 resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf

diff --git a/inventories/chaosknoten/host_vars/netbox.yaml b/inventories/chaosknoten/host_vars/netbox.yaml
new file mode 100644
index 0000000..2304112
--- /dev/null
+++ b/inventories/chaosknoten/host_vars/netbox.yaml
@@ -0,0 +1,16 @@
+netbox__version: "v4.1.7"
+netbox__db_password: "{{ lookup('community.general.passwordstore', 'noc/vm-secrets/chaosknoten/netbox/DATABASE_PASSWORD', create=false, missing='error') }}"
+netbox__config: "{{ lookup('ansible.builtin.template', 'resources/chaosknoten/netbox/netbox/configuration.py.j2') }}"
+netbox__custom_pipeline_oidc_group_and_role_mapping: true
+
+nginx__version_spec: ""
+nginx__configurations:
+  - name: netbox.hamburg.ccc.de
+    content: "{{ lookup('ansible.builtin.file', 'resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf') }}"
+
+certbot__version_spec: ""
+certbot__acme_account_email_address: j+letsencrypt-ccchh@jsts.xyz
+certbot__certificate_domains:
+  - "netbox.hamburg.ccc.de"
+certbot__new_cert_commands:
+  - "systemctl reload nginx.service"
diff --git a/inventories/chaosknoten/hosts.yaml b/inventories/chaosknoten/hosts.yaml
index 911a87d..0f10bea 100644
--- a/inventories/chaosknoten/hosts.yaml
+++ b/inventories/chaosknoten/hosts.yaml
@@ -32,6 +32,10 @@ all:
         mumble:
           ansible_host: mumble.hamburg.ccc.de
           ansible_user: chaos
+        netbox:
+          ansible_host: netbox-intern.hamburg.ccc.de
+          ansible_user: chaos
+          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
         onlyoffice:
           ansible_host: onlyoffice-intern.hamburg.ccc.de
           ansible_user: chaos
@@ -64,6 +68,7 @@ all:
         keycloak:
         lists:
         mumble:
+        netbox:
         onlyoffice:
         pad:
         pretalx:
@@ -94,6 +99,7 @@ all:
         keycloak:
         lists:
         mumble:
+        netbox:
         onlyoffice:
         pad:
         pretalx:
@@ -112,6 +118,7 @@ all:
         keycloak:
         lists:
         mumble:
+        netbox:
         onlyoffice:
         pad:
         pretalx:
@@ -123,6 +130,7 @@ all:
         eh22-wiki:
         tickets:
         keycloak:
+        netbox:
         onlyoffice:
         pad:
         pretalx:
@@ -136,6 +144,7 @@ all:
         tickets:
         cloud:
         keycloak:
+        netbox:
         onlyoffice:
         pad:
         pretalx:
@@ -146,3 +155,6 @@ all:
       hosts:
         eh22-wiki:
         wiki:
+    netbox_hosts:
+      hosts:
+        netbox:
diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml
index da2937f..66f03de 100644
--- a/playbooks/deploy.yaml
+++ b/playbooks/deploy.yaml
@@ -29,6 +29,11 @@
   roles:
     - dokuwiki
 
+- name: Ensure NetBox deployment on netbox_hosts
+  hosts: netbox_hosts
+  roles:
+    - netbox
+
 - name: Ensure NGINX deployment on nginx_hosts, which are also public_reverse_proxy_hosts, before certbot role runs
   hosts: nginx_hosts:&public_reverse_proxy_hosts
   roles:
diff --git a/resources/chaosknoten/netbox/netbox/configuration.py.j2 b/resources/chaosknoten/netbox/netbox/configuration.py.j2
new file mode 100644
index 0000000..789a539
--- /dev/null
+++ b/resources/chaosknoten/netbox/netbox/configuration.py.j2
@@ -0,0 +1,60 @@
+ALLOWED_HOSTS = [ "netbox.hamburg.ccc.de" ]
+DATABASE = {
+  "HOST": "localhost",
+  "NAME": "netbox",
+  "USER": "netbox",
+  "PASSWORD": "{{ lookup('community.general.passwordstore', 'noc/vm-secrets/chaosknoten/netbox/DATABASE_PASSWORD', create=false, missing='error') }}",
+}
+REDIS = {
+    "tasks": {
+      "HOST": "localhost",
+      "PORT": 6379,
+      "USERNAME": "",
+      "PASSWORD": "",
+      "DATABASE": 0,
+      "SSL": False,
+    },
+    "caching": {
+      "HOST": "localhost",
+      "PORT": 6379,
+      "USERNAME": "",
+      "PASSWORD": "",
+      "DATABASE": 1,
+      "SSL": False,
+    },
+}
+SECRET_KEY = "{{ lookup('community.general.passwordstore', 'noc/vm-secrets/chaosknoten/netbox/SECRET_KEY', create=false, missing='error') }}"
+SESSION_COOKIE_SECURE = True
+
+# CCCHH ID (Keycloak) integration.
+# https://github.com/python-social-auth/social-core/blob/0925304a9e437f8b729862687d3a808c7fb88a95/social_core/backends/keycloak.py#L7
+# https://python-social-auth.readthedocs.io/en/latest/backends/keycloak.html
+REMOTE_AUTH_BACKEND = "social_core.backends.keycloak.KeycloakOAuth2"
+SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = (
+    "https://id.hamburg.ccc.de/realms/ccchh/protocol/openid-connect/token"
+)
+SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = (
+    "https://id.hamburg.ccc.de/realms/ccchh/protocol/openid-connect/auth"
+)
+SOCIAL_AUTH_KEYCLOAK_KEY = "netbox"
+SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi/Shi+b2OyYNGVFPsa6qf9SesEpRl5U5rpwgmt8H7NawMvwpPUYVW9o46QW0ulYcDmysT3BzpP3tagO/SFNoOjZdYe0D9nJ7vEp8KHbzR09KCfkyQIi0wLssKnDotVHL5JeUY+iKk+gjiwF9FSFSHPBqsST7hXVAut9LkOvs2aDod9AzbTH/uYbt4wfUm5l/1Ii8D+K7YcsFGUIqxv4XS/ylKqObqN4M2dac69iIwapoh6reaBQEm66vrOzJ+3yi4DZuPrkShJqi2hddtoyZihyCkF+eJJKEI5LrBf1KZB3Ec2YUrqk93ZGUGs/XY6R87QSfR3hJ82B1wnF+c2pw+QIDAQAB"
+SOCIAL_AUTH_KEYCLOAK_SECRET = "{{ lookup('community.general.passwordstore', 'noc/vm-secrets/chaosknoten/netbox/SOCIAL_AUTH_KEYCLOAK_SECRET', create=false, missing='error') }}"
+# Use custom OIDC group and role mapping pipeline functions added in via
+# netbox__custom_pipeline_oidc_group_and_role_mapping.
+# The default pipeline this is based on can be found here:
+# https://github.com/netbox-community/netbox/blob/main/netbox/netbox/settings.py
+SOCIAL_AUTH_PIPELINE = [
+    "social_core.pipeline.social_auth.social_details",
+    "social_core.pipeline.social_auth.social_uid",
+    "social_core.pipeline.social_auth.social_user",
+    "social_core.pipeline.user.get_username",
+    "social_core.pipeline.user.create_user",
+    "social_core.pipeline.social_auth.associate_user",
+    "netbox.authentication.user_default_groups_handler",
+    "social_core.pipeline.social_auth.load_extra_data",
+    "social_core.pipeline.user.user_details",
+    # Custom OIDC group and role mapping functions.
+    "netbox.custom_pipeline_oidc_mapping.add_groups",
+    "netbox.custom_pipeline_oidc_mapping.remove_groups",
+    "netbox.custom_pipeline_oidc_mapping.set_roles",
+]
diff --git a/resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf b/resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf
new file mode 100644
index 0000000..5550686
--- /dev/null
+++ b/resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf
@@ -0,0 +1,48 @@
+# partly generated 2022-01-08, Mozilla Guideline v5.6, nginx 1.17.7, OpenSSL 1.1.1k, intermediate configuration
+# https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1k&guideline=5.6
+server {
+    # Listen on a custom port for the proxy protocol.
+    listen 8443 ssl http2 proxy_protocol;
+    # Make use of the ngx_http_realip_module to set the $remote_addr and
+    # $remote_port to the client address and client port, when using proxy
+    # protocol.
+    # First set our proxy protocol proxy as trusted.
+    set_real_ip_from 172.31.17.140;
+    # Then tell the realip_module to get the addreses from the proxy protocol
+    # header.
+    real_ip_header proxy_protocol;
+
+    server_name netbox.hamburg.ccc.de;
+
+    ssl_certificate /etc/letsencrypt/live/netbox.hamburg.ccc.de/fullchain.pem;
+    ssl_certificate_key /etc/letsencrypt/live/netbox.hamburg.ccc.de/privkey.pem;
+    # verify chain of trust of OCSP response using Root CA and Intermediate certs
+    ssl_trusted_certificate /etc/letsencrypt/live/netbox.hamburg.ccc.de/chain.pem;
+
+    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
+    add_header Strict-Transport-Security "max-age=63072000" always;
+
+    proxy_set_header Host $host;
+    proxy_set_header X-Forwarded-Host $host;
+    proxy_set_header X-Real-IP $remote_addr;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header X-Forwarded-Port 443;
+    # This is https in any case.
+    proxy_set_header X-Forwarded-Proto https;
+    # Hide the X-Forwarded header.
+    proxy_hide_header X-Forwarded;
+    # Assume we are the only Reverse Proxy (well using Proxy Protocol, but that
+    # is transparent).
+    # Also provide "_hidden" for by, since it's not relevant.
+    proxy_set_header Forwarded "for=$remote_addr;proto=https;host=$host;by=_hidden";
+
+    client_max_body_size 25m;
+
+    location /static/ {
+        alias /opt/netbox/netbox/static/;
+    }
+
+    location / {
+        proxy_pass http://127.0.0.1:8001;
+    }
+}
diff --git a/resources/chaosknoten/public-reverse-proxy/nginx/acme_challenge.conf b/resources/chaosknoten/public-reverse-proxy/nginx/acme_challenge.conf
index d5ae146..c3f9fed 100644
--- a/resources/chaosknoten/public-reverse-proxy/nginx/acme_challenge.conf
+++ b/resources/chaosknoten/public-reverse-proxy/nginx/acme_challenge.conf
@@ -17,7 +17,7 @@ map $host $upstream_acme_challenge_host {
     invite.hamburg.ccc.de 172.31.17.144:31820;
     keycloak-admin.hamburg.ccc.de 172.31.17.144:31820;
     matrix.hamburg.ccc.de 172.31.17.150:31820;
-    netbox.hamburg.ccc.de 172.31.17.149:31820;
+    netbox.hamburg.ccc.de 172.31.17.167:31820;
     onlyoffice.hamburg.ccc.de 172.31.17.147:31820;
     pad.hamburg.ccc.de 172.31.17.141:31820;
     pretalx.hamburg.ccc.de 172.31.17.157:31820;
diff --git a/resources/chaosknoten/public-reverse-proxy/nginx/nginx.conf b/resources/chaosknoten/public-reverse-proxy/nginx/nginx.conf
index 0529f4c..dfcf8d2 100644
--- a/resources/chaosknoten/public-reverse-proxy/nginx/nginx.conf
+++ b/resources/chaosknoten/public-reverse-proxy/nginx/nginx.conf
@@ -32,7 +32,7 @@ stream {
         onlyoffice.hamburg.ccc.de 172.31.17.147:8443;
         hackertours.hamburg.ccc.de 172.31.17.151:8443;
         staging.hackertours.hamburg.ccc.de 172.31.17.151:8443;
-        netbox.hamburg.ccc.de 172.31.17.149:8443;
+        netbox.hamburg.ccc.de 172.31.17.167:8443;
         matrix.hamburg.ccc.de 172.31.17.150:8443;
         element.hamburg.ccc.de 172.31.17.151:8443;
         branding-resources.hamburg.ccc.de 172.31.17.151:8443;

From 4def1334d8b5c42338c022605d0ccad80396f19a Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Sat, 15 Feb 2025 20:06:55 +0100
Subject: [PATCH 09/11] for non-verbose output hide user passwords in
 postgresql role

---
 roles/postgresql/tasks/main.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/roles/postgresql/tasks/main.yaml b/roles/postgresql/tasks/main.yaml
index fc61857..8f89018 100644
--- a/roles/postgresql/tasks/main.yaml
+++ b/roles/postgresql/tasks/main.yaml
@@ -18,6 +18,8 @@
   become: true
   become_user: postgres
   loop: "{{ postgresql__users }}"
+  loop_control:
+    label: "user {{ item.name }} with {{ 'a password' if item.password is defined else 'no password' }}"
 
 - name: Ensure dbs with owners
   community.postgresql.postgresql_db:

From 61cd5053d097b2b729a575d12279496d56d70da2 Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Sun, 16 Feb 2025 00:36:10 +0100
Subject: [PATCH 10/11] flatten inventories making them simpler

Remove the child groups as we weren't using their functionality anyway.
Also remove the debian_11/12 host groups as they're not in use.
---
 inventories/chaosknoten/hosts.yaml | 316 ++++++++++++++---------------
 inventories/z9/hosts.yaml          |  44 ++--
 2 files changed, 177 insertions(+), 183 deletions(-)

diff --git a/inventories/chaosknoten/hosts.yaml b/inventories/chaosknoten/hosts.yaml
index 0f10bea..97ef4bb 100644
--- a/inventories/chaosknoten/hosts.yaml
+++ b/inventories/chaosknoten/hosts.yaml
@@ -1,160 +1,158 @@
 all:
-  children:
-    debian_12:
-      hosts:
-        ccchoir:
-          ansible_host: ccchoir-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        cloud:
-          ansible_host: cloud-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        eh22-wiki:
-          ansible_host: eh22-wiki-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        grafana:
-          ansible_host: grafana-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        tickets:
-          ansible_host: tickets-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        keycloak:
-          ansible_host: keycloak-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        lists:
-          ansible_host: lists.hamburg.ccc.de
-          ansible_user: chaos
-        mumble:
-          ansible_host: mumble.hamburg.ccc.de
-          ansible_user: chaos
-        netbox:
-          ansible_host: netbox-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        onlyoffice:
-          ansible_host: onlyoffice-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        pad:
-          ansible_host: pad-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        pretalx:
-          ansible_host: pretalx-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        public-reverse-proxy:
-          ansible_host: public-reverse-proxy.hamburg.ccc.de
-          ansible_user: chaos
-        wiki:
-          ansible_host: wiki-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-        zammad:
-          ansible_host: zammad-intern.hamburg.ccc.de
-          ansible_user: chaos
-          ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
-    base_config_hosts:
-      hosts:
-        ccchoir:
-        cloud:
-        eh22-wiki:
-        grafana:
-        keycloak:
-        lists:
-        mumble:
-        netbox:
-        onlyoffice:
-        pad:
-        pretalx:
-        public-reverse-proxy:
-        tickets:
-        wiki:
-        zammad:
-    docker_compose_hosts:
-      hosts:
-        ccchoir:
-        grafana:
-        tickets:
-        keycloak:
-        lists:
-        onlyoffice:
-        pad:
-        pretalx:
-        zammad:
-    nextcloud_hosts:
-      hosts:
-        cloud:
-    nginx_hosts:
-      hosts:
-        ccchoir:
-        eh22-wiki:
-        grafana:
-        tickets:
-        keycloak:
-        lists:
-        mumble:
-        netbox:
-        onlyoffice:
-        pad:
-        pretalx:
-        public-reverse-proxy:
-        wiki:
-        zammad:
-    public_reverse_proxy_hosts:
-      hosts:
-        public-reverse-proxy:
-    certbot_hosts:
-      hosts:
-        ccchoir:
-        eh22-wiki:
-        grafana:
-        tickets:
-        keycloak:
-        lists:
-        mumble:
-        netbox:
-        onlyoffice:
-        pad:
-        pretalx:
-        wiki:
-        zammad:
-    prometheus_node_exporter_hosts:
-      hosts:
-        ccchoir:
-        eh22-wiki:
-        tickets:
-        keycloak:
-        netbox:
-        onlyoffice:
-        pad:
-        pretalx:
-        wiki:
-        zammad:
-    infrastructure_authorized_keys_hosts:
-      hosts:
-        ccchoir:
-        eh22-wiki:
-        grafana:
-        tickets:
-        cloud:
-        keycloak:
-        netbox:
-        onlyoffice:
-        pad:
-        pretalx:
-        public-reverse-proxy:
-        wiki:
-        zammad:
-    wiki_hosts:
-      hosts:
-        eh22-wiki:
-        wiki:
-    netbox_hosts:
-      hosts:
-        netbox:
+  hosts:
+    ccchoir:
+      ansible_host: ccchoir-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    cloud:
+      ansible_host: cloud-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    eh22-wiki:
+      ansible_host: eh22-wiki-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    grafana:
+      ansible_host: grafana-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    tickets:
+      ansible_host: tickets-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    keycloak:
+      ansible_host: keycloak-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    lists:
+      ansible_host: lists.hamburg.ccc.de
+      ansible_user: chaos
+    mumble:
+      ansible_host: mumble.hamburg.ccc.de
+      ansible_user: chaos
+    netbox:
+      ansible_host: netbox-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    onlyoffice:
+      ansible_host: onlyoffice-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    pad:
+      ansible_host: pad-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    pretalx:
+      ansible_host: pretalx-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    public-reverse-proxy:
+      ansible_host: public-reverse-proxy.hamburg.ccc.de
+      ansible_user: chaos
+    wiki:
+      ansible_host: wiki-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    zammad:
+      ansible_host: zammad-intern.hamburg.ccc.de
+      ansible_user: chaos
+      ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+base_config_hosts:
+  hosts:
+    ccchoir:
+    cloud:
+    eh22-wiki:
+    grafana:
+    keycloak:
+    lists:
+    mumble:
+    netbox:
+    onlyoffice:
+    pad:
+    pretalx:
+    public-reverse-proxy:
+    tickets:
+    wiki:
+    zammad:
+docker_compose_hosts:
+  hosts:
+    ccchoir:
+    grafana:
+    tickets:
+    keycloak:
+    lists:
+    onlyoffice:
+    pad:
+    pretalx:
+    zammad:
+nextcloud_hosts:
+  hosts:
+    cloud:
+nginx_hosts:
+  hosts:
+    ccchoir:
+    eh22-wiki:
+    grafana:
+    tickets:
+    keycloak:
+    lists:
+    mumble:
+    netbox:
+    onlyoffice:
+    pad:
+    pretalx:
+    public-reverse-proxy:
+    wiki:
+    zammad:
+public_reverse_proxy_hosts:
+  hosts:
+    public-reverse-proxy:
+certbot_hosts:
+  hosts:
+    ccchoir:
+    eh22-wiki:
+    grafana:
+    tickets:
+    keycloak:
+    lists:
+    mumble:
+    netbox:
+    onlyoffice:
+    pad:
+    pretalx:
+    wiki:
+    zammad:
+prometheus_node_exporter_hosts:
+  hosts:
+    ccchoir:
+    eh22-wiki:
+    tickets:
+    keycloak:
+    netbox:
+    onlyoffice:
+    pad:
+    pretalx:
+    wiki:
+    zammad:
+infrastructure_authorized_keys_hosts:
+  hosts:
+    ccchoir:
+    eh22-wiki:
+    grafana:
+    tickets:
+    cloud:
+    keycloak:
+    netbox:
+    onlyoffice:
+    pad:
+    pretalx:
+    public-reverse-proxy:
+    wiki:
+    zammad:
+wiki_hosts:
+  hosts:
+    eh22-wiki:
+    wiki:
+netbox_hosts:
+  hosts:
+    netbox:
diff --git a/inventories/z9/hosts.yaml b/inventories/z9/hosts.yaml
index f8a452d..0dde922 100644
--- a/inventories/z9/hosts.yaml
+++ b/inventories/z9/hosts.yaml
@@ -1,25 +1,21 @@
 all:
-  children:
-    debian_11:
-      hosts:
-        light:
-          ansible_host: light.z9.ccchh.net
-          ansible_user: chaos
-        authoritative-dns:
-          ansible_host: authoritative-dns.z9.ccchh.net
-          ansible_user: chaos
-    debian_12:
-      hosts:
-    nginx_hosts:
-      hosts:
-        light:
-    ola_hosts:
-      hosts:
-        light:
-    foobazdmx_hosts:
-      hosts:
-        light:
-    infrastructure_authorized_keys_hosts:
-      hosts:
-        light:
-        authoritative-dns:
+  hosts:
+    light:
+      ansible_host: light.z9.ccchh.net
+      ansible_user: chaos
+    authoritative-dns:
+      ansible_host: authoritative-dns.z9.ccchh.net
+      ansible_user: chaos
+nginx_hosts:
+  hosts:
+    light:
+ola_hosts:
+  hosts:
+    light:
+foobazdmx_hosts:
+  hosts:
+    light:
+infrastructure_authorized_keys_hosts:
+  hosts:
+    light:
+    authoritative-dns:

From ff540126a161fbc0cdff8f71bbb4938a7e459e7b Mon Sep 17 00:00:00 2001
From: June <june@jsts.xyz>
Date: Sun, 16 Feb 2025 02:34:14 +0100
Subject: [PATCH 11/11] add chaosknoten to hosts and new hypervisors group

Also exclude that group from the tasks otherwise targeting all hosts.
---
 inventories/chaosknoten/hosts.yaml | 5 +++++
 playbooks/deploy.yaml              | 4 ++--
 playbooks/maintenance.yaml         | 4 ++--
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/inventories/chaosknoten/hosts.yaml b/inventories/chaosknoten/hosts.yaml
index 97ef4bb..4949dc5 100644
--- a/inventories/chaosknoten/hosts.yaml
+++ b/inventories/chaosknoten/hosts.yaml
@@ -4,6 +4,8 @@ all:
       ansible_host: ccchoir-intern.hamburg.ccc.de
       ansible_user: chaos
       ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+    chaosknoten:
+      ansible_host: chaosknoten.hamburg.ccc.de
     cloud:
       ansible_host: cloud-intern.hamburg.ccc.de
       ansible_user: chaos
@@ -57,6 +59,9 @@ all:
       ansible_host: zammad-intern.hamburg.ccc.de
       ansible_user: chaos
       ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de
+hypervisors:
+  hosts:
+    chaosknoten:
 base_config_hosts:
   hosts:
     ccchoir:
diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml
index 66f03de..d7dcdac 100644
--- a/playbooks/deploy.yaml
+++ b/playbooks/deploy.yaml
@@ -59,8 +59,8 @@
   roles:
     - prometheus_node_exporter
 
-- name: Configure unattended upgrades
-  hosts: all
+- name: Configure unattended upgrades for all non-hypervisors
+  hosts: all:!hypervisors
   become: true
   roles:
     - role: debops.debops.unattended_upgrades
diff --git a/playbooks/maintenance.yaml b/playbooks/maintenance.yaml
index 8ce7caa..31c817b 100644
--- a/playbooks/maintenance.yaml
+++ b/playbooks/maintenance.yaml
@@ -26,8 +26,8 @@
       vars:
         nginx__version_spec: "{{ nextcloud__nginx_version_spec | default('') }}"
 
-- name: Make Sure System Package Are Up-To-Date
-  hosts: all
+- name: Make Sure System Package Are Up-To-Date for all non-hypervisors
+  hosts: all:!hypervisors
   roles:
     - apt_update_and_upgrade