Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
5925b22bf5 |
|||
|
4bdd36b8f7 |
|||
|
1290063204 |
|||
| f2a6ae5de9 | |||
|
e3635939f4 |
|||
|
f7c3e2146d |
|||
| ddce7783db | |||
| 8f07ad8ca4 | |||
| 6a1caed856 | |||
| d20120d708 | |||
| bf04f2d163 | |||
| 39d95a7b9f | |||
| 247cb031f2 |
24 changed files with 502 additions and 120 deletions
|
|
@ -37,7 +37,7 @@ keys:
|
||||||
- &host_ntfy_ansible_pull_age_key age1dkecypmfuj0tcm2cz8vnvq5drpu2ddhgnfkzxvscs7m4e79gpseqyhr9pg
|
- &host_ntfy_ansible_pull_age_key age1dkecypmfuj0tcm2cz8vnvq5drpu2ddhgnfkzxvscs7m4e79gpseqyhr9pg
|
||||||
- &host_spaceapiccc_ansible_pull_age_key age1mdtnk78aeqnwqadjqje5pfha04wu92d3ecchyqajjmy434kwq98qksq2wa
|
- &host_spaceapiccc_ansible_pull_age_key age1mdtnk78aeqnwqadjqje5pfha04wu92d3ecchyqajjmy434kwq98qksq2wa
|
||||||
- &host_acmedns_ansible_pull_age_key age16pxqxdj25xz6w200sf8duc62vyk0xkhzc7y63nyhg29sm077vp8qy4sywv
|
- &host_acmedns_ansible_pull_age_key age16pxqxdj25xz6w200sf8duc62vyk0xkhzc7y63nyhg29sm077vp8qy4sywv
|
||||||
- &host_mjolnir_ansible_pull_age_key age1hv7m3xypesdfm0dfzwgctde8v307g9xaunnfu2687y0lagcs5q7s3eg0kj
|
- &host_draupnir_ansible_pull_age_key age1hv7m3xypesdfm0dfzwgctde8v307g9xaunnfu2687y0lagcs5q7s3eg0kj
|
||||||
- &host_diday_staging_runner_ansible_pull_age_key age1522f3qzddm82w63j7ajdkr0khvced6ht7tzp3grvp0j3hewtvesssr5kpf
|
- &host_diday_staging_runner_ansible_pull_age_key age1522f3qzddm82w63j7ajdkr0khvced6ht7tzp3grvp0j3hewtvesssr5kpf
|
||||||
- &host_auth_dns_ansible_pull_age_key age18zgt4y2sd75hxnpe333zz39048ctxpr0q8a3uqh3jajjkyawsdrq8yg5ve
|
- &host_auth_dns_ansible_pull_age_key age18zgt4y2sd75hxnpe333zz39048ctxpr0q8a3uqh3jajjkyawsdrq8yg5ve
|
||||||
- &host_forgejo_runner_ansible_pull_age_key age1az0k6cadssk6r8qcqxfr8cyu5mndy59pwt8yqq6w065ew6au4ezsmg2vkf
|
- &host_forgejo_runner_ansible_pull_age_key age1az0k6cadssk6r8qcqxfr8cyu5mndy59pwt8yqq6w065ew6au4ezsmg2vkf
|
||||||
|
|
@ -201,12 +201,12 @@ creation_rules:
|
||||||
*admin_gpg_keys
|
*admin_gpg_keys
|
||||||
age:
|
age:
|
||||||
- *host_spaceapiccc_ansible_pull_age_key
|
- *host_spaceapiccc_ansible_pull_age_key
|
||||||
- path_regex: "inventories/chaosknoten/host_vars/mjolnir\\.sops\\..+"
|
- path_regex: "inventories/chaosknoten/host_vars/draupnir\\.sops\\..+"
|
||||||
key_groups:
|
key_groups:
|
||||||
- pgp:
|
- pgp:
|
||||||
*admin_gpg_keys
|
*admin_gpg_keys
|
||||||
age:
|
age:
|
||||||
- *host_mjolnir_ansible_pull_age_key
|
- *host_draupnir_ansible_pull_age_key
|
||||||
- path_regex: "inventories/chaosknoten/host_vars/diday-staging-runner\\.sops\\..+"
|
- path_regex: "inventories/chaosknoten/host_vars/diday-staging-runner\\.sops\\..+"
|
||||||
key_groups:
|
key_groups:
|
||||||
- pgp:
|
- pgp:
|
||||||
|
|
|
||||||
35
docs/concepts-and-configurations/matrix-moderation.md
Normal file
35
docs/concepts-and-configurations/matrix-moderation.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
title: Matrix Moderation
|
||||||
|
---
|
||||||
|
|
||||||
|
# Matrix Moderation
|
||||||
|
|
||||||
|
All Matrix rooms created around CCCHH and which are considered *official* are subject to centralized moderation.
|
||||||
|
This moderation is enforced by a [Mjolnir](https://github.com/matrix-org/mjolnir) bot on a techincal level and operated by a dedicated sub-team of the Infra Group.
|
||||||
|
|
||||||
|
The moderation team can be reached at [matrix-moderation@hamburg.ccc.de](mailto:matrix-moderation@hamburg.ccc.de).
|
||||||
|
|
||||||
|
## Principles and Guidelines
|
||||||
|
|
||||||
|
During moderation, we adhere to the following principles:
|
||||||
|
|
||||||
|
- No *predictive policing*. We strive for fast and accurate moderation and, while we do incorporate reports from trustworthy sources close to the chaos community, we do not moderate based on gut feelings.
|
||||||
|
|
||||||
|
- Prohibited content includes spam, pornography, harassment, and fascist-like behavior. We remove such content and subsequently ban the user responsible (see [Matrix: Taking Moderation Action](../guides/matrix-taking-moderation-action.md)).
|
||||||
|
|
||||||
|
- The CCCHH admin account may be used under special circumstances to issue warnings and explain the moderation team’s decisions in general terms. It does not respond to DMs and does not engage in discussions. If moderation action is to be discussed, people are referred to the moderation team at [matrix-moderation@hamburg.ccc.de](mailto:matrix-moderation@hamburg.ccc.de) instead.
|
||||||
|
|
||||||
|
- New Matrix rooms related to CCCHH are **always** created by the CCCHH admin and protected by the moderation bot. See [Matrix: Create a New Room](../guides/matrix-create-room.md) for details on creating rooms.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
The bot account `@moderation:hamburg.ccc.de` (Draupnir) maintains various internal lists of rules that are applied in so-called "Protected Rooms".
|
||||||
|
These can include, for example, user bans or entire server bans.
|
||||||
|
Additionally, certain automatic monitoring measures (so-called "protections") apply in these rooms, which trigger a configured action if violated.
|
||||||
|
For example, a user is not allowed to tag too many other users in a single message, as this is considered spam and results in a kick.
|
||||||
|
The bot is controlled and configured via a privileged *CCCHH Moderation Management* room using `!mjolnir` commands.
|
||||||
|
There, individual actions can also be triggered through the bot as needed, such as redacting messages, kicking users from all or some channels, etc.
|
||||||
|
|
||||||
|
It is also possible to make our moderation bot's local lists available to other entities and subscribe our bot to other entities' lists.
|
||||||
|
Our list is published in `#general-moderation:hamburg.ccc.de` where other moderation bots can freely watch it.
|
||||||
|
|
||||||
53
docs/guides/matrix-create-room.md
Normal file
53
docs/guides/matrix-create-room.md
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
title: "Matrix: Create a New Room"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Matrix: Create a New Room
|
||||||
|
|
||||||
|
!!! success "Goal"
|
||||||
|
|
||||||
|
Create a new matrix room for a CCCHH group or function with correct protections and permissions
|
||||||
|
|
||||||
|
## 1. Create the Room
|
||||||
|
|
||||||
|
Rooms are always created by the *CCCHH-Admin* Account whose credentials can be found in *infra-secrets*.
|
||||||
|
To create a room, log in to https://element.hamburg.ccc.de and click on *New Conversation* -> *New Room*.
|
||||||
|
Enter a Room Name and optionally give it an address on the *hamburg.ccc.de* server.
|
||||||
|
|
||||||
|
## 2. Configure Room Metadata
|
||||||
|
|
||||||
|
Once the room is created, please give it a topic and if possible a room icon.
|
||||||
|
This makes it easier to distinguish the many rooms we have.
|
||||||
|
|
||||||
|
## 3. Invite the Moderation-Bot
|
||||||
|
|
||||||
|
Either perform the following steps via the GUI or enter the displayed commands into the chat window of the new room:
|
||||||
|
|
||||||
|
|
||||||
|
1. Invite the User `@moderation:hamburg.ccc.de` to the new room
|
||||||
|
```
|
||||||
|
/invite @moderation:hamburg.ccc.de
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Give the moderation bot *Admin* Power-Level so that it can properly enforce all protections
|
||||||
|
```
|
||||||
|
/op @moderation:hamburg.ccc.de 100
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Set Up Room Protection
|
||||||
|
|
||||||
|
We have now added the moderation bot to the room but this is not enough.
|
||||||
|
The bot needs to be told explicitly which rooms it should protect and the newly created one therefore needs to be added to that list.
|
||||||
|
|
||||||
|
First, note down the *Internal Room ID* which can be found in the new Rooms settings under the *Advanced* tab.
|
||||||
|
Then enter the *CCCHH Moderation Management* room and write the following draupnir command while substituting the copied room id:
|
||||||
|
|
||||||
|
```
|
||||||
|
!draupnir rooms add <room-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Closing Up
|
||||||
|
|
||||||
|
You should now have a new Matrix Room under moderation protection.
|
||||||
|
To verify that everything was done correctly, you can enter `!draupnir verify` in the *CCCHH Moderation Management* room and observe that the moderation bot does not give you an error.
|
||||||
|
|
||||||
52
docs/guides/matrix-taking-moderation-action.md
Normal file
52
docs/guides/matrix-taking-moderation-action.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
title: "Matrix: Taking Moderation Action"
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! success "Goal"
|
||||||
|
|
||||||
|
Perform common moderation actions in Matrix using our moderation bot
|
||||||
|
|
||||||
|
See the [Matrix-Moderation](../concepts-and-configurations/matrix-moderation.md) Concept for an overview on how the moderation system functions.
|
||||||
|
|
||||||
|
All bot actions are triggered through the *CCCHH Moderation Management* room.
|
||||||
|
|
||||||
|
!!! warning "Warning"
|
||||||
|
|
||||||
|
Moderation actions should be triggered through the bot to avoid exposing members of the moderation team to harassment.
|
||||||
|
Even if the bot is unwieldy, think before taking action with your personal account and do so on your own scrutiny.
|
||||||
|
|
||||||
|
## Banning a User
|
||||||
|
|
||||||
|
```
|
||||||
|
!draupnir ban user general <glob> <reason>
|
||||||
|
```
|
||||||
|
|
||||||
|
- `<glob>` can be a user ID (e.g. `@example:matrix.org`) but also more sophisticated. Be careful when using actual glob syntax as whole servers can be banned even if just a single user is the intended target.
|
||||||
|
- `<reason>` is technically optional but should always be supplied so that we know why a certain user was banned in retrospect. The bot supports parsing quotations so `"<reason>"` is usually what you want if more than one word is used.
|
||||||
|
|
||||||
|
## Banning a Server
|
||||||
|
|
||||||
|
```
|
||||||
|
!draupnir ban server general <glob> <reason>
|
||||||
|
```
|
||||||
|
|
||||||
|
- `<glob>` can be used to ban subdomains of a domain too, e.g. `*.example.com`. If used, an additional `--force` is required after the whole command.
|
||||||
|
- `<reason>` should be supplied and supports quotation (`"<reason>") if more than one word is used
|
||||||
|
- When a domain is banned, we usually also ban all subdomains too. This needs to be done in two separate commands.
|
||||||
|
|
||||||
|
## Redacting a single Message
|
||||||
|
|
||||||
|
```
|
||||||
|
!draupnir redact <permalink>
|
||||||
|
```
|
||||||
|
|
||||||
|
- `<permalink>` is **not** the message ID but the actual *https://matrix.to/#blablabla* link that can be retrieved with most clients through a *Share* or *Copy link to Message* button on an individual message.
|
||||||
|
|
||||||
|
## Redacting all Messages of a User
|
||||||
|
|
||||||
|
```
|
||||||
|
!draupnir redact <user-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
- `user-id` the Matrix-ID of the user of whom all messages in all rooms should be redacted (e.g. `@bla:example.com`).
|
||||||
|
|
||||||
27
docs/guides/update-dokuwiki.md
Normal file
27
docs/guides/update-dokuwiki.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
title: Updating Dokuwiki
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! success "Goal"
|
||||||
|
|
||||||
|
How to update our wiki (<https://wiki.hamburg.ccc.de>) to the latest version
|
||||||
|
|
||||||
|
## 1. Create a Snaphot
|
||||||
|
|
||||||
|
Go to the Chaosknoten Proxmox UI and create a snapshot of the `wiki` VM: <https://chaosknoten.hamburg.ccc.de:8006/#v1:0:=qemu%2F127:4:::::29::>
|
||||||
|
|
||||||
|
## 2. Update Plugins
|
||||||
|
|
||||||
|
- Go to the wiki's extension manager: <https://wiki.hamburg.ccc.de/start?do=admin&page=extension> or go to Admin > Extension Manager
|
||||||
|
- Update the "DokuWiki Upgrade Plugin" (if it has updates)
|
||||||
|
- Update other plugins while we're here already
|
||||||
|
|
||||||
|
## 3. Update Dokuwiki
|
||||||
|
|
||||||
|
- Go to the Wiki Upgrade: <https://wiki.hamburg.ccc.de/start?do=admin&page=upgrade> or go to Admin > Wiki Upgrade
|
||||||
|
- Click through the steps. Note: Disabling any plugins before the upgrade was not necessary in the past.
|
||||||
|
|
||||||
|
## Closing Up
|
||||||
|
|
||||||
|
Log out and back in again to verify that the Keycloak connection still works.
|
||||||
|
Maybe browse some pages as check if anything is obviously broken.
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
ansible_pull__age_private_key: ENC[AES256_GCM,data:2kBG8j8JHa/dlXgWMdbSobulFdVunf052T1QQfm1X2vpEZx2HPCL87fWea+O0WOg7+eoMYbiShu0Vw1eTjb+687LjU8l4cj2JWIajnYfDGH+ipWXojxj613C3RZV3JfDOclVTwP8fCHu7z7P3fKrsKWb5d3t2ohTT+sGdVdimakAOf192CkufcVIthq2imiWbntiMTOdMGJxyIjqT2Io2H89nSbJXkONsuHCF/PbxhryB2LZbl8aZV32knk=,iv:hpscVc7iO4r/h31vS6Zno2pkEsgA2uR7wD/1PjH1znM=,tag:ypiwFtgeXuj4gOsgTCRTBw==,type:str]
|
ansible_pull__age_private_key: ENC[AES256_GCM,data:2kBG8j8JHa/dlXgWMdbSobulFdVunf052T1QQfm1X2vpEZx2HPCL87fWea+O0WOg7+eoMYbiShu0Vw1eTjb+687LjU8l4cj2JWIajnYfDGH+ipWXojxj613C3RZV3JfDOclVTwP8fCHu7z7P3fKrsKWb5d3t2ohTT+sGdVdimakAOf192CkufcVIthq2imiWbntiMTOdMGJxyIjqT2Io2H89nSbJXkONsuHCF/PbxhryB2LZbl8aZV32knk=,iv:hpscVc7iO4r/h31vS6Zno2pkEsgA2uR7wD/1PjH1znM=,tag:ypiwFtgeXuj4gOsgTCRTBw==,type:str]
|
||||||
knot__dnssec_key_secret: ENC[AES256_GCM,data:WPFTLyJIttFtqqTZV2fGN0Tt1vRS318TGmd2YqNzYisE3TBi6Z2aClxuYh56Q+j7TUQwCvga3jd5w017sEz3kA==,iv:umaFHBCy9AZgNFv7uXLCtO0o/NZDAZ1QNg5DcGHWEW8=,tag:oR92C1Uj5iXU9L02MqzGSQ==,type:str]
|
knot__keys:
|
||||||
|
- id: ENC[AES256_GCM,data:ff7Z1SHmKVseX4hguwcfrqLKyDKu3Imw1Q==,iv:Ds5T3cvi2XYAa3C8mbgYjN8AHM4FsKR2RTPvykWgy2E=,tag:7Gveno0zsLf3bDOYgkQkbw==,type:str]
|
||||||
|
secret: ENC[AES256_GCM,data:dJcVnqQ6hlA/xp4NQ5s9by+z9cm5oWD7KAlPX+kDsvSJn33YiZ/A/wf0jfT+FeVLaBerQ6WipxZs90rp8rD+dg==,iv:JVby6vORdqChps6cRx1EJPNBC7+M0Vgp1ji1nQtv3K4=,tag:X0KggJahlTOAowTNnpPs2g==,type:str]
|
||||||
|
algorithm: ENC[AES256_GCM,data:r7uojDN+o1yYgaY=,iv:KBWKZbd+5qZstuMh6gseq/vC86UB/l9m4wVZpA4usPk=,tag:gfU3asmwOIgxJQsqPG712g==,type:str]
|
||||||
|
- id: ENC[AES256_GCM,data:Dulyfbyd0yrEX2gUm/YA,iv:VmSUtH5aryl7Vhq8TDj7anRASqNZaN77usVI+Rd8SVc=,tag:1ZJmSHHufQr1+DcnKYyY9w==,type:str]
|
||||||
|
secret: ENC[AES256_GCM,data:zlEdYedWmlW8mTLu+cUejyjlqLcx14Bz4D20pPa21UagtCH7GYeCldmC5sM=,iv:+TvHyfRgCscza04CtLGuRIkt30KLVRx01GKEq0Dqkvw=,tag:mX/MrOePWjJ9JwiGP6TQQw==,type:str]
|
||||||
|
algorithm: ENC[AES256_GCM,data:r7uojDN+o1yYgaY=,iv:KBWKZbd+5qZstuMh6gseq/vC86UB/l9m4wVZpA4usPk=,tag:gfU3asmwOIgxJQsqPG712g==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age18zgt4y2sd75hxnpe333zz39048ctxpr0q8a3uqh3jajjkyawsdrq8yg5ve
|
- enc: |
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArVUxoOFhZdi9PSkZlU3pw
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArVUxoOFhZdi9PSkZlU3pw
|
||||||
VW0vNVRTSG9EamUvVGR0dnN6ajcwTXdlQkdZCkFGVWxPcTNSOGtJdlpSMXJxOFBX
|
VW0vNVRTSG9EamUvVGR0dnN6ajcwTXdlQkdZCkFGVWxPcTNSOGtJdlpSMXJxOFBX
|
||||||
|
|
@ -11,8 +16,9 @@ sops:
|
||||||
SHhROG5nMGp2d3dwWVJsZk55TW93dU0KnW2ZhU6OhwwPBIxcO1xP+W8DV5Obj6ov
|
SHhROG5nMGp2d3dwWVJsZk55TW93dU0KnW2ZhU6OhwwPBIxcO1xP+W8DV5Obj6ov
|
||||||
Hgb8MQ6i9FlhAN/P8onBsqvbh0ttBEFQ6aRJj5njKs/MMfKUk9Q25g==
|
Hgb8MQ6i9FlhAN/P8onBsqvbh0ttBEFQ6aRJj5njKs/MMfKUk9Q25g==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2026-05-01T17:08:09Z"
|
recipient: age18zgt4y2sd75hxnpe333zz39048ctxpr0q8a3uqh3jajjkyawsdrq8yg5ve
|
||||||
mac: ENC[AES256_GCM,data:TaMWf1ESs8nYzxkElMYtsz+/Be0PtI7FA0q6IFK+ob4dl/EN+AeTD7Pp0MZF8zcRvZ4hF0Ybimet5bwVR+d7UIXlXz3qP//pX68JDCvcLMQuhNtm6Ws+mwVxkpxEvBr1PtxlSvcQ76vH3ryEsXkP84gmlCDEdX1GAZYZ9ZS3Cfk=,iv:g3tzUfTPNUQyOAxWJEFPHg0IAPAzQgwYABHm4mFOOrI=,tag:C6KE/bg/3jS7Wc56y6YOJQ==,type:str]
|
lastmodified: "2026-09-11T08:41:08Z"
|
||||||
|
mac: ENC[AES256_GCM,data:Kp+FNfKFSD1SGgHS7xc51CGqugyAQlTHqI1bxQxuGLht7dTdbltu8llyyGSwYuToAeUAgBKi+Nv4OQ7qM3nQ/1I3IjUJ6t3G3LNbOfOe6h4cF5wb2pV8NnpzjpwEgOMVI6dzCbW/hRqND8JrgSgnkPjM4WyOtiz8+N7evY8qAOs=,iv:kOkxsVfuVO5/XJBmnQKZm8mFVoQlUZKT51TUUAGij/8=,tag:8i59H3tvwUvSBU0LWLsdbg==,type:str]
|
||||||
pgp:
|
pgp:
|
||||||
- created_at: "2026-05-20T02:08:47Z"
|
- created_at: "2026-05-20T02:08:47Z"
|
||||||
enc: |-
|
enc: |-
|
||||||
|
|
@ -185,4 +191,4 @@ sops:
|
||||||
-----END PGP MESSAGE-----
|
-----END PGP MESSAGE-----
|
||||||
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
|
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.12.1
|
version: 3.13.3
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,23 @@ deploy_systemd_resolved_config__enable: false
|
||||||
|
|
||||||
alloy_config_additional: "{{ lookup('ansible.builtin.template', 'resources/chaosknoten/auth-dns/alloy/knot-exporter.alloy') }}"
|
alloy_config_additional: "{{ lookup('ansible.builtin.template', 'resources/chaosknoten/auth-dns/alloy/knot-exporter.alloy') }}"
|
||||||
|
|
||||||
knot__dnssec_key_id: "auth-dns.hamburg.ccc.de-1"
|
|
||||||
knot__remotes:
|
knot__remotes:
|
||||||
- id: erfadns.ber.ccc.de
|
- id: erfadns.ber.ccc.de
|
||||||
address: [ "2a02:8000:1000:101::196", "185.106.84.196" ]
|
address: [ "2a02:8000:1000:101::196", "185.106.84.196" ]
|
||||||
|
via: [ "2a00:14b0:4200:3000:124::1", "212.12.48.124" ]
|
||||||
- id: ns.vie.ccc.de
|
- id: ns.vie.ccc.de
|
||||||
address: [ "2a02:1b8:10:31::228", "146.255.57.228" ]
|
address: [ "2a02:1b8:10:31::228", "146.255.57.228" ]
|
||||||
|
via: [ "2a00:14b0:4200:3000:124::1", "212.12.48.124" ]
|
||||||
|
- id: cccfr-de-hidden-primary
|
||||||
|
address: [ "89.163.204.252" ]
|
||||||
|
via: [ "2a00:14b0:4200:3000:124::1", "212.12.48.124" ]
|
||||||
|
key: "xfr-ccchh-cccfr"
|
||||||
|
|
||||||
knot__catalog_zones:
|
knot__catalog_zones:
|
||||||
- domain: "hamburg.ccc.de.catalog."
|
- domain: "hamburg.ccc.de.catalog."
|
||||||
notify_targets: [ "erfadns.ber.ccc.de" ]
|
notify_targets: [ "erfadns.ber.ccc.de" ]
|
||||||
|
|
||||||
knot__zones:
|
knot__primary_zones:
|
||||||
- domain: "hh.ccc.de."
|
- domain: "hh.ccc.de."
|
||||||
catalog_member: "hamburg.ccc.de.catalog."
|
catalog_member: "hamburg.ccc.de.catalog."
|
||||||
notify_targets: [ "erfadns.ber.ccc.de" ]
|
notify_targets: [ "erfadns.ber.ccc.de" ]
|
||||||
|
|
@ -48,3 +53,7 @@ knot__zones:
|
||||||
- domain: "3.2.0.0.0.0.0.f.0.b.4.1.0.0.a.2.ip6.arpa."
|
- domain: "3.2.0.0.0.0.0.f.0.b.4.1.0.0.a.2.ip6.arpa."
|
||||||
notify_targets: [ "erfadns.ber.ccc.de" ]
|
notify_targets: [ "erfadns.ber.ccc.de" ]
|
||||||
content: "{{ lookup('ansible.builtin.file', 'resources/chaosknoten/auth-dns/zones/3.2.0.0.0.0.0.f.0.b.4.1.0.0.a.2.ip6.arpa.zone') }}"
|
content: "{{ lookup('ansible.builtin.file', 'resources/chaosknoten/auth-dns/zones/3.2.0.0.0.0.0.f.0.b.4.1.0.0.a.2.ip6.arpa.zone') }}"
|
||||||
|
|
||||||
|
knot__catalog_secondary_zones:
|
||||||
|
- domain: "cccfr.catalog.invalid"
|
||||||
|
primary: "cccfr-de-hidden-primary"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
ansible_pull__age_private_key: ENC[AES256_GCM,data:mUKh1aFJ8hn0GqfWQw5pWSAj9qaj5wH/NrHhEp9sdOYfNCBPp1dfYIDTqFAnPNz2SLzoQ+HIuPYxSCaWNq0zS8TStBelUoEGDuE=,iv:rbVLKpUzHr2ZZsHlRZtBp9E8IX9TVAa/nJAXfnh4fJQ=,tag:wT/0Ku9yrwD9snnzMigU3g==,type:str]
|
ansible_pull__age_private_key: ENC[AES256_GCM,data:mUKh1aFJ8hn0GqfWQw5pWSAj9qaj5wH/NrHhEp9sdOYfNCBPp1dfYIDTqFAnPNz2SLzoQ+HIuPYxSCaWNq0zS8TStBelUoEGDuE=,iv:rbVLKpUzHr2ZZsHlRZtBp9E8IX9TVAa/nJAXfnh4fJQ=,tag:wT/0Ku9yrwD9snnzMigU3g==,type:str]
|
||||||
secret__mjolnir_matrix_user_password: ENC[AES256_GCM,data:FDCZW5dt1HHxLDSqLi3rH5eX1Go7qKQDK9+w0q8IjpTSNFNZg91B19V4voDx+2UNv2l1OUwAngAgckEZ0mSndA==,iv:c+zW3LhoqAhuu3PWlXiyZ8r8TGgF/RnswnI+fo08EBE=,tag:lPrXolXFD+5gpoGkm4GMog==,type:str]
|
secret__draupnir_matrix_user_token: ENC[AES256_GCM,data:WtWZQh8Khwv4bq0U0vg2203P4PnLHNRVBTN59NqGX9PggVi2rRy3PZc=,iv:L3d+xI85IXB0DfynjQxhAjAmZ3rKLTFVWCcBcdqxzF8=,tag:qAiv4M1EbKVd+ysWhV/JIA==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age1hv7m3xypesdfm0dfzwgctde8v307g9xaunnfu2687y0lagcs5q7s3eg0kj
|
- enc: |
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3b2MzYzFWaHJ4M3NkaDkw
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3b2MzYzFWaHJ4M3NkaDkw
|
||||||
cEYzVDhQSGQ4SGpJQllmZGNTUUhGSy9KZkZjCi9CY0pRVTh3SUQyK0dlckMvVGI1
|
cEYzVDhQSGQ4SGpJQllmZGNTUUhGSy9KZkZjCi9CY0pRVTh3SUQyK0dlckMvVGI1
|
||||||
|
|
@ -11,8 +10,9 @@ sops:
|
||||||
V09XOXY4bHBpbWxpdTNycHVwVUptdE0KsksBHnhpGmag6KZmeUjI6GzYPVvG06bw
|
V09XOXY4bHBpbWxpdTNycHVwVUptdE0KsksBHnhpGmag6KZmeUjI6GzYPVvG06bw
|
||||||
mGhQf8hwa4m7tTtD806kVuKJ/nXhOZXFr1Gp65iWGBfT5lJk2VIayQ==
|
mGhQf8hwa4m7tTtD806kVuKJ/nXhOZXFr1Gp65iWGBfT5lJk2VIayQ==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2026-02-11T01:05:26Z"
|
recipient: age1hv7m3xypesdfm0dfzwgctde8v307g9xaunnfu2687y0lagcs5q7s3eg0kj
|
||||||
mac: ENC[AES256_GCM,data:7DdCLStFif0EhqsgthwZD50v+FPa1drUmBKUhmWw9FKtCBKmNM5LbCI5TvKGJqq8gtKiMUKpOf/pA/8qGNavfl8MdRrhm9inlkHgkwgLQwAx7/ds8uHexVBjG2gV+hMPtoNCnGRkQRHwrepz/7L6Y5L5UUhWHEUEhMuxrejzNBY=,iv:SpziMsqQ34/hAH1HkbGjqG4ZyZybcWE9Xp5xWkPADGA=,tag:eYWlsKj+OPMcpU1u1Caavg==,type:str]
|
lastmodified: "2026-09-06T11:30:21Z"
|
||||||
|
mac: ENC[AES256_GCM,data:tTOVUVlU2BOD7Xxxmn6I6b8V+zouNgyNfet18JZKuIrAqRgag/oKadoa+lBjiH/JiCUunNueACf14wsrw5eOdpJiL1zBg8sK6kyPDrI1IRGMJWXX0x01DJSL1INNz6fKdHTA+hqI0w6lTWPiLwgTbsfyMwF+lutaJv79cANC3UU=,iv:i34JCNJHLgQwZAKGrF1dX1TZSvOnB3HqQe/BvA9HTtY=,tag:8LY0AdEtVFTVY2d0dbiuDA==,type:str]
|
||||||
pgp:
|
pgp:
|
||||||
- created_at: "2026-05-20T02:08:45Z"
|
- created_at: "2026-05-20T02:08:45Z"
|
||||||
enc: |-
|
enc: |-
|
||||||
|
|
@ -185,4 +185,4 @@ sops:
|
||||||
-----END PGP MESSAGE-----
|
-----END PGP MESSAGE-----
|
||||||
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
|
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.11.0
|
version: 3.13.3
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
docker_compose__compose_file_content: "{{ lookup('ansible.builtin.file', 'resources/chaosknoten/mjolnir/docker_compose/compose.yaml') }}"
|
docker_compose__compose_file_content: "{{ lookup('ansible.builtin.file', 'resources/chaosknoten/draupnir/docker_compose/compose.yaml') }}"
|
||||||
docker_compose__configuration_files:
|
docker_compose__configuration_files:
|
||||||
- name: config.yaml
|
- name: config.yaml
|
||||||
content: "{{ lookup('ansible.builtin.template', 'resources/chaosknoten/mjolnir/docker_compose/config.yaml.j2') }}"
|
content: "{{ lookup('ansible.builtin.template', 'resources/chaosknoten/draupnir/docker_compose/config.yaml.j2') }}"
|
||||||
|
|
@ -36,8 +36,8 @@ all:
|
||||||
lists:
|
lists:
|
||||||
ansible_host: lists.hamburg.ccc.de
|
ansible_host: lists.hamburg.ccc.de
|
||||||
ansible_user: chaos
|
ansible_user: chaos
|
||||||
mjolnir:
|
draupnir:
|
||||||
ansible_host: mjolnir.hosts.hamburg.ccc.de
|
ansible_host: draupnir.hosts.hamburg.ccc.de
|
||||||
ansible_user: chaos
|
ansible_user: chaos
|
||||||
ansible_ssh_common_args: -J ssh://chaos@router.hamburg.ccc.de
|
ansible_ssh_common_args: -J ssh://chaos@router.hamburg.ccc.de
|
||||||
mumble:
|
mumble:
|
||||||
|
|
@ -132,7 +132,7 @@ base_config_hosts:
|
||||||
sunders:
|
sunders:
|
||||||
renovate:
|
renovate:
|
||||||
spaceapiccc:
|
spaceapiccc:
|
||||||
mjolnir:
|
draupnir:
|
||||||
auth-dns:
|
auth-dns:
|
||||||
forgejo-runner:
|
forgejo-runner:
|
||||||
forgejo-runner-external:
|
forgejo-runner-external:
|
||||||
|
|
@ -158,7 +158,7 @@ docker_compose_hosts:
|
||||||
ntfy:
|
ntfy:
|
||||||
sunders:
|
sunders:
|
||||||
spaceapiccc:
|
spaceapiccc:
|
||||||
mjolnir:
|
draupnir:
|
||||||
nextcloud_hosts:
|
nextcloud_hosts:
|
||||||
hosts:
|
hosts:
|
||||||
cloud:
|
cloud:
|
||||||
|
|
@ -246,7 +246,7 @@ infrastructure_authorized_keys_hosts:
|
||||||
sunders:
|
sunders:
|
||||||
renovate:
|
renovate:
|
||||||
spaceapiccc:
|
spaceapiccc:
|
||||||
mjolnir:
|
draupnir:
|
||||||
auth-dns:
|
auth-dns:
|
||||||
lists:
|
lists:
|
||||||
forgejo-runner:
|
forgejo-runner:
|
||||||
|
|
@ -284,7 +284,7 @@ ansible_pull_hosts:
|
||||||
zammad:
|
zammad:
|
||||||
ntfy:
|
ntfy:
|
||||||
spaceapiccc:
|
spaceapiccc:
|
||||||
mjolnir:
|
draupnir:
|
||||||
auth-dns:
|
auth-dns:
|
||||||
forgejo-runner:
|
forgejo-runner:
|
||||||
forgejo-runner-external:
|
forgejo-runner-external:
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,20 @@
|
||||||
// https://docs.renovatebot.com/presets-default/#automergestablenonmajor
|
// https://docs.renovatebot.com/presets-default/#automergestablenonmajor
|
||||||
{
|
{
|
||||||
"groupName": "all stable non-major dependencies",
|
"groupName": "all stable non-major dependencies",
|
||||||
"groupSlug": "all-stable-minor-patch",
|
"groupSlug": "all-stable-minor",
|
||||||
"matchCurrentVersion": "!/^0/",
|
"matchCurrentVersion": "!/^0/",
|
||||||
"matchUpdateTypes": [
|
"matchUpdateTypes": [
|
||||||
"minor",
|
"minor"
|
||||||
"patch"
|
],
|
||||||
|
"matchPackageNames": [
|
||||||
|
"!git.hamburg.ccc.de/ccchh/oci-images/keycloak"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"matchUpdateTypes": ["patch"],
|
||||||
|
"matchCurrentVersion": "!/^0/",
|
||||||
|
"automerge": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"matchDatasources": ["docker"],
|
"matchDatasources": ["docker"],
|
||||||
"matchPackageNames": ["docker.io/pretix/standalone"],
|
"matchPackageNames": ["docker.io/pretix/standalone"],
|
||||||
|
|
|
||||||
|
|
@ -499,7 +499,8 @@ keycloak.hosts IN AAAA 2a00:14b0:42:102::6
|
||||||
onlyoffice.hosts IN AAAA 2a00:14b0:42:102::7
|
onlyoffice.hosts IN AAAA 2a00:14b0:42:102::7
|
||||||
renovate.hosts IN AAAA 2a00:14b0:42:102::8
|
renovate.hosts IN AAAA 2a00:14b0:42:102::8
|
||||||
sunders.hosts IN AAAA 2a00:14b0:42:102::9
|
sunders.hosts IN AAAA 2a00:14b0:42:102::9
|
||||||
mjolnir.hosts IN AAAA 2a00:14b0:42:102::a
|
draupnir.hosts IN AAAA 2a00:14b0:42:102::a
|
||||||
|
mjolnir.hosts IN CNAME draupnir.hosts
|
||||||
netbox.hosts IN AAAA 2a00:14b0:42:102::b
|
netbox.hosts IN AAAA 2a00:14b0:42:102::b
|
||||||
tickets.hosts IN AAAA 2a00:14b0:42:102::c
|
tickets.hosts IN AAAA 2a00:14b0:42:102::c
|
||||||
zammad.hosts IN AAAA 2a00:14b0:42:102::d
|
zammad.hosts IN AAAA 2a00:14b0:42:102::d
|
||||||
|
|
|
||||||
11
resources/chaosknoten/draupnir/docker_compose/compose.yaml
Normal file
11
resources/chaosknoten/draupnir/docker_compose/compose.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Links & Resources
|
||||||
|
# https://github.com/matrix-org/mjolnir/blob/main/docs/setup_docker.md
|
||||||
|
|
||||||
|
services:
|
||||||
|
draupnir:
|
||||||
|
image: ghcr.io/the-draupnir-project/draupnir:v3.1.0
|
||||||
|
command: [ "bot", "--draupnir-config", "/etc/draupnir/production.yaml" ]
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./draupnir_data:/data
|
||||||
|
- ./configs/config.yaml:/etc/draupnir/production.yaml:ro
|
||||||
22
resources/chaosknoten/draupnir/docker_compose/config.yaml.j2
Normal file
22
resources/chaosknoten/draupnir/docker_compose/config.yaml.j2
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# https://github.com/the-draupnir-project/Draupnir/blob/main/config/default.yaml
|
||||||
|
|
||||||
|
homeserverUrl: "https://matrix.hamburg.ccc.de"
|
||||||
|
rawHomeserverUrl: "https://matrix.hamburg.ccc.de"
|
||||||
|
accessToken: "{{ secret__draupnir_matrix_user_token }}"
|
||||||
|
|
||||||
|
dataPath: "/data/storage"
|
||||||
|
logLevel: "INFO"
|
||||||
|
recordIgnoredInvites: true
|
||||||
|
managementRoom: "#moderation-management:hamburg.ccc.de"
|
||||||
|
experimentalRustCrypto: true
|
||||||
|
automaticallyRedactForReasons:
|
||||||
|
- "spam"
|
||||||
|
- "advertising"
|
||||||
|
- "porn"
|
||||||
|
- "harassmet"
|
||||||
|
|
||||||
|
# currently not working because /_synapse is not routed via reverse proxy
|
||||||
|
pollReports: false
|
||||||
|
|
||||||
|
# this knob can turn of moderation action temporarily
|
||||||
|
noop: false
|
||||||
|
|
@ -70,7 +70,7 @@ services:
|
||||||
- loki_data:/var/loki
|
- loki_data:/var/loki
|
||||||
|
|
||||||
ntfy-alertmanager-ccchh-critical:
|
ntfy-alertmanager-ccchh-critical:
|
||||||
image: docker.io/xenrox/ntfy-alertmanager:1.0.0
|
image: docker.io/xenrox/ntfy-alertmanager:1.0.1
|
||||||
container_name: ntfy-alertmanager-ccchh-critical
|
container_name: ntfy-alertmanager-ccchh-critical
|
||||||
volumes:
|
volumes:
|
||||||
- ./configs/ntfy-alertmanager-ccchh-critical:/etc/ntfy-alertmanager/config
|
- ./configs/ntfy-alertmanager-ccchh-critical:/etc/ntfy-alertmanager/config
|
||||||
|
|
@ -79,7 +79,7 @@ services:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
ntfy-alertmanager-fux-critical:
|
ntfy-alertmanager-fux-critical:
|
||||||
image: docker.io/xenrox/ntfy-alertmanager:1.0.0
|
image: docker.io/xenrox/ntfy-alertmanager:1.0.1
|
||||||
container_name: ntfy-alertmanager-fux-critical
|
container_name: ntfy-alertmanager-fux-critical
|
||||||
volumes:
|
volumes:
|
||||||
- ./configs/ntfy-alertmanager-fux-critical:/etc/ntfy-alertmanager/config
|
- ./configs/ntfy-alertmanager-fux-critical:/etc/ntfy-alertmanager/config
|
||||||
|
|
@ -88,7 +88,7 @@ services:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
ntfy-alertmanager-ccchh:
|
ntfy-alertmanager-ccchh:
|
||||||
image: docker.io/xenrox/ntfy-alertmanager:1.0.0
|
image: docker.io/xenrox/ntfy-alertmanager:1.0.1
|
||||||
container_name: ntfy-alertmanager-ccchh
|
container_name: ntfy-alertmanager-ccchh
|
||||||
volumes:
|
volumes:
|
||||||
- ./configs/ntfy-alertmanager-ccchh:/etc/ntfy-alertmanager/config
|
- ./configs/ntfy-alertmanager-ccchh:/etc/ntfy-alertmanager/config
|
||||||
|
|
@ -97,7 +97,7 @@ services:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
ntfy-alertmanager-fux:
|
ntfy-alertmanager-fux:
|
||||||
image: docker.io/xenrox/ntfy-alertmanager:1.0.0
|
image: docker.io/xenrox/ntfy-alertmanager:1.0.1
|
||||||
container_name: ntfy-alertmanager-fux
|
container_name: ntfy-alertmanager-fux
|
||||||
volumes:
|
volumes:
|
||||||
- ./configs/ntfy-alertmanager-fux:/etc/ntfy-alertmanager/config
|
- ./configs/ntfy-alertmanager-fux:/etc/ntfy-alertmanager/config
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# Links & Resources
|
|
||||||
# https://github.com/matrix-org/mjolnir/blob/main/docs/setup_docker.md
|
|
||||||
|
|
||||||
services:
|
|
||||||
mjolnir:
|
|
||||||
image: docker.io/matrixdotorg/mjolnir:v1.12.1
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- ./mjolnir_data:/data
|
|
||||||
- ./configs/config.yaml:/data/config/production.yaml:ro
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
# https://github.com/matrix-org/mjolnir/blob/main/config/default.yaml
|
|
||||||
|
|
||||||
homeserverUrl: "https://matrix.hamburg.ccc.de"
|
|
||||||
rawHomeserverUrl: "https://matrix.hamburg.ccc.de"
|
|
||||||
# Mjolnir should be able to retrieve an access token itself
|
|
||||||
encryption:
|
|
||||||
use: true
|
|
||||||
username: "moderation"
|
|
||||||
password: {{ secret__mjolnir_matrix_user_password }}
|
|
||||||
dataPath: "/data/storage"
|
|
||||||
autojoinOnlyIfManager: true
|
|
||||||
recordIgnoredInvites: true
|
|
||||||
# The native encryption backend doesn't seem to support v12 rooms yet.
|
|
||||||
# https://github.com/matrix-org/mjolnir/issues/641
|
|
||||||
managementRoom: "#moderation-management-v11:hamburg.ccc.de"
|
|
||||||
forwardMentionsToManagementRoom: false
|
|
||||||
verboseLogging: false
|
|
||||||
logLevel: "INFO"
|
|
||||||
syncOnStartup: true
|
|
||||||
verifyPermissionsOnStartup: true
|
|
||||||
noop: false
|
|
||||||
fasterMembershipChecks: false
|
|
||||||
protectAllJoinedRooms: true
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
user nginx;
|
user nginx;
|
||||||
worker_processes auto;
|
worker_processes auto;
|
||||||
worker_rlimit_nofile 2050; # should be worker_connections*2 at least
|
|
||||||
|
|
||||||
error_log /var/log/nginx/error.log notice;
|
error_log /var/log/nginx/error.log notice;
|
||||||
pid /var/run/nginx.pid;
|
pid /var/run/nginx.pid;
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,11 @@
|
||||||
---
|
---
|
||||||
|
knot__deploy_prometheus_exporter: true
|
||||||
|
knot__log_level: info
|
||||||
knot__remotes: [ ]
|
knot__remotes: [ ]
|
||||||
|
knot__keys: [ ]
|
||||||
|
knot__catalog_zones: [ ]
|
||||||
|
knot__primary_zones: [ ]
|
||||||
|
knot__catalog_secondary_zones: [ ]
|
||||||
|
knot__secondary_zones: [ ]
|
||||||
|
knot__dynamic_zones: [ ]
|
||||||
|
knot__acls: [ ]
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,15 @@
|
||||||
argument_specs:
|
argument_specs:
|
||||||
main:
|
main:
|
||||||
options:
|
options:
|
||||||
knot__dnssec_key_id:
|
knot__log_level:
|
||||||
description: The id of the TSIG key which knot will use for zone transfer signing
|
|
||||||
type: str
|
type: str
|
||||||
required: true
|
required: false
|
||||||
knot__dnssec_key_secret:
|
|
||||||
description: The secret value of the TSIG key which knot will use for zone transfer signing
|
knot__deploy_prometheus_exporter:
|
||||||
type: str
|
type: bool
|
||||||
required: true
|
required: false
|
||||||
|
description: Whether a prometheus exporter for knot should also be installed
|
||||||
|
|
||||||
knot__remotes:
|
knot__remotes:
|
||||||
description:
|
description:
|
||||||
- A list of definitions for remote nameservers that are used for different purposes
|
- A list of definitions for remote nameservers that are used for different purposes
|
||||||
|
|
@ -25,11 +26,19 @@ argument_specs:
|
||||||
type: list
|
type: list
|
||||||
required: true
|
required: true
|
||||||
elements: str
|
elements: str
|
||||||
|
key:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
via:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: false
|
||||||
|
|
||||||
knot__catalog_zones:
|
knot__catalog_zones:
|
||||||
description: A list of catalog zones that will be served by knot
|
description: A list of catalog zones that will be served by knot
|
||||||
type: list
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
required: true
|
required: false
|
||||||
options:
|
options:
|
||||||
domain:
|
domain:
|
||||||
type: str
|
type: str
|
||||||
|
|
@ -38,11 +47,12 @@ argument_specs:
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
required: false
|
required: false
|
||||||
knot__zones:
|
|
||||||
|
knot__primary_zones:
|
||||||
description: A list of user zones that will be served by knot
|
description: A list of user zones that will be served by knot
|
||||||
type: list
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
required: true
|
required: false
|
||||||
options:
|
options:
|
||||||
domain:
|
domain:
|
||||||
type: str
|
type: str
|
||||||
|
|
@ -57,3 +67,105 @@ argument_specs:
|
||||||
content:
|
content:
|
||||||
type: str
|
type: str
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
knot__dynamic_zones:
|
||||||
|
description: A list of user zones operated via DDNS that will be served by knot
|
||||||
|
type: list
|
||||||
|
elements: dict
|
||||||
|
required: false
|
||||||
|
options:
|
||||||
|
domain:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
notify_targets:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: false
|
||||||
|
catalog_member:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
acl:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: true
|
||||||
|
|
||||||
|
knot__secondary_zones:
|
||||||
|
description: A list of secondary zones that will be served by knot
|
||||||
|
required: false
|
||||||
|
type: list
|
||||||
|
elements: dict
|
||||||
|
options:
|
||||||
|
domain:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
notify_targets:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: false
|
||||||
|
catalog_member:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
primary:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
|
||||||
|
knot__catalog_secondary_zones:
|
||||||
|
description: A list of zones which are catalog secondaries and which will generate new zones based on the catalog content
|
||||||
|
type: list
|
||||||
|
elements: dict
|
||||||
|
required: false
|
||||||
|
options:
|
||||||
|
domain:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
notify_targets:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: false
|
||||||
|
primary:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
|
||||||
|
knot__keys:
|
||||||
|
description: TSIG Key stanzas used by knot
|
||||||
|
required: false
|
||||||
|
type: list
|
||||||
|
elements: dict
|
||||||
|
options:
|
||||||
|
id:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
algorithm:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
secret:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
|
||||||
|
knot__acls:
|
||||||
|
description: ACL stanzas
|
||||||
|
required: false
|
||||||
|
type: list
|
||||||
|
elements: dict
|
||||||
|
options:
|
||||||
|
id:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
address:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: false
|
||||||
|
key:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
remote:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: false
|
||||||
|
action:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
update_type:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: false
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
- name: Deploy configured zones
|
- name: Deploy configured zones
|
||||||
become: true
|
become: true
|
||||||
notify: reload knot
|
notify: reload knot
|
||||||
loop: "{{ knot__zones }}"
|
loop: "{{ knot__primary_zones }}"
|
||||||
loop_control:
|
loop_control:
|
||||||
label: "{{ item.domain }}"
|
label: "{{ item.domain }}"
|
||||||
vars:
|
vars:
|
||||||
|
|
@ -34,17 +34,3 @@
|
||||||
group: knot
|
group: knot
|
||||||
mode: u=rw,g=r
|
mode: u=rw,g=r
|
||||||
validate: "kzonecheck -v -o '{{ item.domain }}' %s"
|
validate: "kzonecheck -v -o '{{ item.domain }}' %s"
|
||||||
|
|
||||||
# this seems weird but hear me out:
|
|
||||||
# if we don't disable SLAAC, the node automatically gets an address based on IPv6 Router-Advertisements
|
|
||||||
# this results in outgoing zone transfers failing because knot will prefer to use the dynamic address over the statically configured one.
|
|
||||||
# so because we are configuring a DNS Nameserver where known IP-Addresses are actually important for ACL reasons, SLAAC is disabled
|
|
||||||
- name: Disable IPv6 SLAAC
|
|
||||||
become: true
|
|
||||||
notify: netplan apply
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: "netplan-disable-ra.yaml"
|
|
||||||
dest: "/etc/netplan/10-disable-ra.yaml"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: u=rw,g=,o=
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
---
|
---
|
||||||
- ansible.builtin.import_tasks: 01-install.yaml # noqa: name[missing]
|
- tags: [ knot ]
|
||||||
- ansible.builtin.import_tasks: 02-configure.yaml # noqa: name[missing]
|
block:
|
||||||
- ansible.builtin.import_tasks: 03-configure-exporter.yaml # noqa: name[missing]
|
- ansible.builtin.import_tasks: 01-install.yaml # noqa: name[missing]
|
||||||
|
- ansible.builtin.import_tasks: 02-configure.yaml # noqa: name[missing]
|
||||||
|
- ansible.builtin.include_tasks: 03-configure-exporter.yaml # noqa: name[missing]
|
||||||
|
when: knot__deploy_prometheus_exporter
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,17 @@ server:
|
||||||
|
|
||||||
log:
|
log:
|
||||||
- target: syslog
|
- target: syslog
|
||||||
any: info
|
any: {{ knot__log_level }}
|
||||||
|
|
||||||
database:
|
database:
|
||||||
storage: "/var/lib/knot"
|
storage: "/var/lib/knot"
|
||||||
|
|
||||||
key:
|
key:
|
||||||
- id: {{ knot__dnssec_key_id }}
|
{% for i_key in knot__keys -%}
|
||||||
algorithm: hmac-sha512
|
- id: "{{ i_key.id }}"
|
||||||
secret: "{{ knot__dnssec_key_secret }}"
|
algorithm: "{{ i_key.algorithm | default("hmac-sha256") }}"
|
||||||
|
secret: "{{ i_key.secret }}"
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
remote:
|
remote:
|
||||||
# static, external and public remote used for DNSSEC KSK checking
|
# static, external and public remote used for DNSSEC KSK checking
|
||||||
|
|
@ -28,6 +30,13 @@ remote:
|
||||||
{% for i_remote in knot__remotes -%}
|
{% for i_remote in knot__remotes -%}
|
||||||
- id: "{{ i_remote.id }}"
|
- id: "{{ i_remote.id }}"
|
||||||
address: [ {% for i_addr in i_remote.address %}"{{ i_addr}}"{% if not loop.last %},{% endif %} {% endfor %} ]
|
address: [ {% for i_addr in i_remote.address %}"{{ i_addr}}"{% if not loop.last %},{% endif %} {% endfor %} ]
|
||||||
|
{% if i_remote.via | default(None) -%}
|
||||||
|
via: [ {% for i_via in i_remote.via %}"{{ i_via }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
|
{% endif -%}
|
||||||
|
{% if i_remote.key | default(None) -%}
|
||||||
|
key: "{{ i_remote.key }}"
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
@ -46,10 +55,33 @@ policy:
|
||||||
nsec3: true
|
nsec3: true
|
||||||
nsec3-salt-length: 0
|
nsec3-salt-length: 0
|
||||||
|
|
||||||
|
# explicit acl configurations
|
||||||
|
# we mostly rely on automatic ACLs but for some dynamic zones, explicit allow stanzas are required
|
||||||
|
acl:
|
||||||
|
{% for i_acl in knot__acls -%}
|
||||||
|
- id: "{{ i_acl.id }}"
|
||||||
|
{% if i_acl.address | default(None) -%}
|
||||||
|
address: [ {% for i_addr in i_acl.address %}"{{ i_addr}}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
|
{% endif -%}
|
||||||
|
{% if i_acl.key | default(None) -%}
|
||||||
|
key: "{{ i_acl.key }}"
|
||||||
|
{% endif -%}
|
||||||
|
{% if i_acl.remote | default(None) -%}
|
||||||
|
remote: "{{ i_acl.remote }}"
|
||||||
|
{% endif -%}
|
||||||
|
{% if i_acl.action | default(None) -%}
|
||||||
|
action: "{{ i_acl.action }}"
|
||||||
|
{% endif -%}
|
||||||
|
{% if i_acl.update_type | default(None) -%}
|
||||||
|
update-type: [ {% for i_addr in i_acl.update_type %}"{{ i_addr}}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
# define default settings that apply to all zones
|
# define default settings that apply to all zones
|
||||||
template:
|
template:
|
||||||
# template for general-purpose user zones
|
# template for general-purpose primary zones
|
||||||
- id: default
|
- id: primary
|
||||||
storage: "/etc/knot/zones"
|
storage: "/etc/knot/zones"
|
||||||
file: "%s.zone"
|
file: "%s.zone"
|
||||||
semantic-checks: on
|
semantic-checks: on
|
||||||
|
|
@ -57,17 +89,45 @@ template:
|
||||||
zonefile-load: difference-no-serial
|
zonefile-load: difference-no-serial
|
||||||
serial-policy: dateserial
|
serial-policy: dateserial
|
||||||
journal-content: all
|
journal-content: all
|
||||||
default-ttl: 7200
|
|
||||||
dnssec-signing: on
|
dnssec-signing: on
|
||||||
dnssec-policy: default
|
dnssec-policy: default
|
||||||
|
|
||||||
{# catalog-role: member #}
|
# template for generic secondary zones
|
||||||
{# catalog-zone: hamburg.ccc.de.catalog. #}
|
- id: secondary
|
||||||
|
storage: "/var/lib/knot/secondary_zones/"
|
||||||
|
dnssec-signing: off
|
||||||
|
|
||||||
|
# template for zones that support dynamic updates
|
||||||
|
- id: dynamic-primary
|
||||||
|
storage: "/var/lib/knot/dynamic_zones/"
|
||||||
|
zonefile-load: whole
|
||||||
|
journal-content: changes
|
||||||
|
dnssec-signing: on
|
||||||
|
dnssec-policy: default
|
||||||
|
|
||||||
# template for automatically created special zones
|
# template for automatically created special zones
|
||||||
- id: catalog
|
- id: catalog
|
||||||
catalog-role: generate
|
catalog-role: generate
|
||||||
dnssec-signing: off
|
dnssec-signing: off
|
||||||
|
storage: "/var/lib/knot/catalog_zones/"
|
||||||
|
|
||||||
|
# template for secondary catalog zones (they are interpreted and generate secondary zones based on their content)
|
||||||
|
- id: catalog-secondary
|
||||||
|
catalog-role: interpret
|
||||||
|
dnssec-signing: off
|
||||||
|
storage: "/var/lib/knot/secondary_zones/"
|
||||||
|
|
||||||
|
# templates for secondary catalog member zones
|
||||||
|
# these templates are for zones which get spawned by catalog zones
|
||||||
|
# unfortunately we need one template per interpreted catalog zone because it must include all information required for that zone to work as secondary
|
||||||
|
# it reuses master and notify values from the catalog zones
|
||||||
|
{% for i_zone in knot__catalog_secondary_zones -%}
|
||||||
|
- id: catalog-secondary-member-{{ i_zone.domain }}
|
||||||
|
storage: "/var/lib/knot/secondary_zones/"
|
||||||
|
dnssec-signing: off
|
||||||
|
master: {{ i_zone.primary }}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
# define zones on this server
|
# define zones on this server
|
||||||
|
|
@ -80,10 +140,10 @@ zone:
|
||||||
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
# normal zones
|
# primary zones
|
||||||
{% for i_zone in knot__zones -%}
|
{% for i_zone in knot__primary_zones -%}
|
||||||
- domain: "{{ i_zone.domain }}"
|
- domain: "{{ i_zone.domain }}"
|
||||||
template: default
|
template: primary
|
||||||
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
{% if i_zone.catalog_member | default(False) -%}
|
{% if i_zone.catalog_member | default(False) -%}
|
||||||
catalog-role: member
|
catalog-role: member
|
||||||
|
|
@ -92,3 +152,39 @@ zone:
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
# dynamic primary zones
|
||||||
|
{% for i_zone in knot__dynamic_zones -%}
|
||||||
|
- domain: "{{ i_zone.domain }}"
|
||||||
|
template: "dynamic-primary"
|
||||||
|
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
|
acl: [ {% for i_acl in i_zone.acl %}"{{ i_acl }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
|
{% if i_zone.catalog_member | default(False) -%}
|
||||||
|
catalog-role: member
|
||||||
|
catalog-zone: "{{ i_zone.catalog_member }}"
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
# secondary zones
|
||||||
|
{% for i_zone in knot__secondary_zones -%}
|
||||||
|
- domain: "{{ i_zone.domain }}"
|
||||||
|
template: secondary
|
||||||
|
master: {{ i_zone.primary }}
|
||||||
|
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
|
{% if i_zone.catalog_member | default(False) -%}
|
||||||
|
catalog-role: member
|
||||||
|
catalog-zone: "{{ i_zone.catalog_member }}"
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
# secondary catalog zones
|
||||||
|
{% for i_zone in knot__catalog_secondary_zones -%}
|
||||||
|
- domain: "{{ i_zone.domain }}"
|
||||||
|
template: catalog-secondary
|
||||||
|
catalog-template: catalog-secondary-member-{{ i_zone.domain }}
|
||||||
|
master: {{ i_zone.primary }}
|
||||||
|
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# {{ ansible_managed }}
|
|
||||||
network:
|
|
||||||
ethernets:
|
|
||||||
{%- for i_iface_name in ansible_facts["interfaces"] -%}
|
|
||||||
{%- if i_iface_name != "lo" -%}
|
|
||||||
{%- set i_iface = ansible_facts[i_iface_name] %}
|
|
||||||
|
|
||||||
{{ i_iface_name }}:
|
|
||||||
match:
|
|
||||||
macaddress: "{{ i_iface.macaddress }}"
|
|
||||||
accept-ra: false
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
Loading…
Reference in a new issue