Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
a61d1e8
removed cloudflare, restructured and created files (see changes in To…
Aug 10, 2025
44f1235
chore: docker-compose -> docker compose
felbinger Aug 22, 2025
ea44122
begin monitoring refactoring
Aug 22, 2025
a7a39c4
added backup section
Aug 22, 2025
479ff1f
checked backup in ToDo List
Aug 22, 2025
6afc835
added borg passphrase automation
Aug 22, 2025
5377cef
Theorie v0.1 (grober Inhalt verfasst)
Aug 22, 2025
37f43dc
fixed typo
Aug 22, 2025
e94e03d
moved To Do list to PR Description
Aug 22, 2025
144f95e
fixed inconsistend docker compose usage in grafana
Aug 22, 2025
61ac1c4
Added Title to Backup page
Oct 8, 2025
1f62dc4
fixed typo
Oct 8, 2025
bed5a12
commented cloudflare proxy - transparent proxy diagram
Oct 13, 2025
b9c2369
small refactor
Oct 14, 2025
6b440e8
removed Cloudflare & format text
Oct 14, 2025
16b1ca4
theorie: rewrite
felbinger Oct 15, 2025
9cf305b
backup: start rewrite
felbinger Oct 15, 2025
3647ce2
nginx: begin rewrite
felbinger Oct 15, 2025
513cc87
nginx: finish
felbinger Oct 15, 2025
ddf2114
nginx: adjust default
felbinger Oct 15, 2025
85d2cf3
traefik: fix typo
felbinger Oct 15, 2025
9db3b21
traefik: restructure
felbinger Oct 15, 2025
303f0d0
img/proxy-diagram: remove
felbinger Oct 15, 2025
6cd69c5
img/services: cleanup
felbinger Oct 15, 2025
a1e8e3f
img/internal-networks: migrate into png with drawio content
felbinger Oct 15, 2025
b8978e6
requirements: remove include plugin
felbinger Oct 15, 2025
7620eb8
ipv4-to-v6-proxy: reword
felbinger Oct 15, 2025
c2ce25b
Update docs/installation/30_backup.md
felbinger Oct 15, 2025
e8de6a1
Update docs/installation/30_backup.md
felbinger Oct 15, 2025
f1d94d2
Update docs/installation/30_backup.md
felbinger Oct 15, 2025
cea4a13
Update docs/installation/10_nginx.md
felbinger Oct 15, 2025
7d9e590
Update docs/installation/20_traefik.md
felbinger Oct 15, 2025
165238a
adopt suggestions of copilot
felbinger Oct 15, 2025
5bb672a
contribution: init
felbinger Oct 15, 2025
9c3e9c8
README/contribution: remove
felbinger Oct 15, 2025
f153f78
add Cloudflare API Token Chapter
Oct 15, 2025
61763b6
add blank line
felbinger Oct 15, 2025
ffc7380
fixup enum
felbinger Oct 15, 2025
6a7fb55
reword and add links
Oct 15, 2025
ccf2e44
Merge branch 'reform_adminguide' of https://github.com/felbinger/Admi…
Oct 15, 2025
8cbec9e
removed cloudflare, restructured and created files (see changes in To…
Aug 10, 2025
34f2b56
refactoring
Aug 22, 2025
4b737f3
services/aram3: extend by exile mod
felbinger Oct 17, 2025
6489a4c
mkdocs: add tags for services
felbinger Oct 17, 2025
5d0e272
services/dayz: init with blog post
felbinger Oct 17, 2025
d3a7f26
fix typo
felbinger Oct 17, 2025
4f1b50a
resolve merge conflicts
Oct 20, 2025
e25e77a
checked grammar and wording
Oct 20, 2025
7693f4f
rewrite TL;DR-IPv6 only Server
Oct 20, 2025
84d46d5
added IPv6 Adress generate script
Oct 20, 2025
fec7b9b
added port script
Oct 20, 2025
6961d2d
added searchport command/function
Oct 21, 2025
4f32221
removed duplicate contribution file
Oct 21, 2025
d491bc9
grammar and spelling
Oct 21, 2025
3a984a1
removed duplicate 'installation' folder
Oct 21, 2025
d5cd20f
cleanup
felbinger Oct 21, 2025
28c6ddf
remove empty page
felbinger Oct 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 1 addition & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,2 @@
# Admin Guide
You can find this repository here: [https://adminguide.pages.dev](https://adminguide.pages.dev).

## Contribute
Feel free to open issues / pull requests. Please validate that your changes work as intented!
You can start the mkdocs development server by running `mkdocs serve`.

Contribution Guidelines:
* Web Services are exposed to `[::1]:8000`
* Secret Environment Variables are in an env_file (and not in the `docker-compose.yml` itself, to prevent leaks) with the following format:
```shell
# .servicename.env
KEY=value
```
* environment variables should be in form of a YAML array, not an object:
```yaml
environment:
- "KEY=value"
```
instead of
```yaml
# WRONG - please don't do this
environemnt:
KEY: value
# WRONG
```
* If possible the service should use either mariadb or postgresql.
If it makes sense, other databases (e.g. sqlite) are also quiet fine.
* YAML arrays should be quoted, regardless which data is stored:
```yaml
volumes:
- "/srv/service_name/data:/data"
ports:
- "[::1]:8000:1234"
networks:
- "default"
- "database"
```
* All domain examples should end in `domain.de`
You can find the rendered guide on [adminguide.pages.dev](https://adminguide.pages.dev).
63 changes: 0 additions & 63 deletions docs/10_overview.md

This file was deleted.

20 changes: 0 additions & 20 deletions docs/30_backup.md

This file was deleted.

11 changes: 11 additions & 0 deletions docs/A._Theorie/10_reverse-proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 1. Wahl des Reverse Proxies
Im Rahmen dieses Guides werden [nginx](https://www.nginx.com/) auf dem Host sowie
[Traefik](https://traefik.io/) als Container vorgestellt.

Nginx ist ein leistungsstarker und weit verbreiteter Webserver und Reverse Proxy, welcher sich
durch hohe Stabilität, Effizienz und Flexibilität in klassischen Serverumgebungen auszeichnet.

Traefik hingegen ist speziell auf containerisierte Umgebungen ausgelegt und integriert sich
nahtlos mit Plattformen wie Docker oder Kubernetes. Es erkennt neue Services automatisch und
konfiguriert Routing-Regeln dynamisch, was es besonders für moderne, dynamische Deployments
attraktiv macht.
71 changes: 71 additions & 0 deletions docs/A._Theorie/20_tls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# 2. TLS
Für die verschlüsselte Kommunikation zwischen Nutzer und Webserver sind TLS-Zertifikate
erforderlich.

In den Standard-Einstellungen von Betriebssystemen und Browsern ist bereits eine Auswahl
vertrauenswürdiger Zertifizierungsstellen (CAs) hinterlegt. Nur Zertifikate, die von einer
dieser anerkannten Stellen ausgestellt oder signiert wurden, werden vom Browser automatisch
als sicher bzw. vertrauenswürdig eingestuft. Diese sogenannte "Trusted Root Certificate Authority
List" wird von den jeweiligen Herstellern (z. B. Microsoft, Apple, Mozilla, Google) gepflegt und
regelmäßig aktualisiert.

Es gibt grundsätzlich drei Möglichkeiten, TLS-Zertifikate zu beziehen bzw. auszustellen:

1. **Kommerzielle Anbieter**

Zertifikate können kostenpflichtig von anerkannten Zertifizierungsstellen wie DigiCert,
GlobalSign oder GoDaddy erworben werden. Sie werden häufig von Unternehmen genutzt, um
zusätzliche Garantieleistungen, erweiterte Validierungen (OV/EV) oder Supportleistungen
zu erhalten.

2. **Kostenlose Zertifikate**

Let’s Encrypt wurde 2015 von der gemeinnützigen Organisation Internet Security Research Group (ISRG)
gegründet. Ziel war es, das Web durch die Bereitstellung kostenloser, automatisierter und durch offene
Zertifikate sicherer zu gestalten und so verschlüsselte Verbindungen (HTTPS) zum Standard im Internet
zu etablieren.

Neben Let’s Encrypt existieren weitere Anbieter, die ähnliche kostenlose Zertifizierungsdienste anbieten,
wie beispielsweise ZeroSSL und [Actalis](https://www.actalis.com/). Alle Anbieter unterstützen das
ACME-Protokoll (Automatic Certificate Management Environment), über das die Ausstellung und Verlängerung
von Zertifikaten automatisiert erfolgen kann.

Diese kostenlosen Zertifikate sind von den gängigen Browsern als vertrauenswürdig anerkannt und eignen sich
hervorragend für öffentliche Websites, Webanwendungen und APIs. Im Vergleich zu kommerziellen Angeboten bieten
sie zwar keine zusätzlichen Garantieleistungen oder erweiterte Validierung (z. B. EV-Zertifikate), erfüllen
aber auf technischer Ebene die selben Sicherheitsstandards.

3. **Eigene Zertifizierungsstelle (CA)**

Neben öffentlichen und kommerziellen Anbietern besteht auch die Möglichkeit, eine eigene Zertifizierungsstelle
(Certificate Authority, CA) zu betreiben. Damit können eigene Zertifikate ausgestellt werden – beispielsweise
für interne Server, Entwicklungsumgebungen oder Testsysteme.

Diese Variante ist kostenlos, erfordert jedoch mehr administrativen Aufwand. Damit Browser und Betriebssysteme
den ausgestellten Zertifikaten vertrauen, muss das Root-Zertifikat der eigenen CA manuell auf allen beteiligten
Geräten installiert werden. In kontrollierten Umgebungen (z. B. Firmennetzwerke oder geschlossene Systeme) kann
dies automatisiert über zentrale Verwaltungswerkzeuge erfolgen.

Für den produktiven Einsatz im öffentlichen Internet ist diese Lösung jedoch nicht geeignet, da externe Nutzer
das Root-Zertifikat nicht installiert haben und der Browser die Verbindung daher als nicht vertrauenswürdig
einstufen würde.

!!! warning
Von der Verwendung selbstsignierter Zertifikate und dem Ignorieren von Browserwarnungen ist dringend abzuraten.

Wer sich daran gewöhnt, Sicherheitsmeldungen einfach „wegzuklicken“, entwickelt schnell ein riskantes Verhalten.

Im Rahmen dieses Guides wird auf kostenlose TLS-Zertifikate des Anbieters Let’s Encrypt gesetzt.

Für die Verwaltung dieser stehen verschiedene Tools und Clients zur Verfügung. Wird nginx als Reverse Proxy
eingesetzt, bietet sich die Verwendung von [acme.sh](https://github.com/acmesh-official/acme.sh), ein schlanker,
in Shell geschriebener ACME-Client, der sich einfach in bestehende Umgebungen integrieren lässt, an.
Traefik hingegen verwendet für diesen Zweck standardmäßig den in Go entwickelten ACME-Client [Lego](https://go-acme.github.io/lego/).

Unabhängig von der gewählten Implementierung stehen bei Let’s Encrypt verschiedene [ACME-Challenge-Typen](https://letsencrypt.org/docs/challenge-types/)
zur Verfügung, über die die Domainvalidierung erfolgt.

Während die Challenge-Typen HTTP-01 und TLS-ALPN-01 voraussetzen, dass der Reverse Proxy aus dem Internet
erreichbar ist, bietet die DNS-01-Challenge die Möglichkeit, die Domainvalidierung über einen TXT-Eintrag
im DNS durchzuführen. Dadurch muss der Webserver nicht öffentlich zugänglich sein, und die ausgestellten
Zertifikate können somit auch in internen Umgebungen verwendet werden.
63 changes: 63 additions & 0 deletions docs/A._Theorie/30_ipv6-per-serivce.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# 3. Eine IPv6 Adresse pro Service

!!! note
Die meisten Hosting-Provider weisen jedem Server ein /64-IPv6-Präfix zu,
was einem Adressraum von $2^{64}$ Adressen entspricht – eine Zahl, die in
der Praxis quasi unerschöpflich ist.

Ausnahmen gibt es beispielsweise bei Strato: Dort wird nicht ein ganzes /64-IPv6-Präfix,
sondern lediglich eine einzelne IPv6-Adresse pro Server zugewiesen. Dadurch ist es nicht
möglich, jedem Dienst eine eigene IPv6-Adresse zu geben
([siehe YouTube Short](https://www.youtube.com/shorts/oSvU4HXZ_Wc)).

Wird jedem nginx Reverse Proxy eine eigene IPv6-Adresse zugewiesen, kann bereits auf OSI-Layer 3
nachvollzogen werden, an welchen Webservice eine Anfrage gerichtet war. Würde hingegen für alle
Dienste nur eine gemeinsame Adresse verwendet, wäre eine eindeutige Zuordnung frühestens auf
Layer 5 (durch Auswertung des TLS SNI Headers) möglich; ohne ein spezielles Analysewerkzeug sogar
erst auf Layer 7, etwa über die Logdaten des Webservers.

Der Webserver nginx bietet mit der Direktive `listen` die Möglichkeit, virtuelle Hosts an spezifische
IPv4- oder IPv6-Adressen zu binden. Diese Technik erlaubt eine frühzeitige Trennung und Zuordnung des
eingehenden Traffics zu den einzelnen Anwendungen. Soll ein Dienst abgeschaltet oder vorübergehend
blockiert werden, kann dessen zugewiesene Adresse zudem sehr einfach über die Firewall – oder sogar
direkt beim Provider – gesperrt werden, ohne dass Änderungen an der Servicekonfiguration selbst
erforderlich sind.


## Useful Scripts

### IPv6 Adresse generieren
!!! note
Dieses Skript erzeugt jediglich eine neue IPv6-Adresse! Diese wird nicht automatisch dem
Netzwerkinterface hinzugefügt. Dies muss separat erfolgen!

Das erstellen einer neuen IPv6 Adresse aus dem /64 Präfix des Servers kann mit folgendem simplen
Skript automatisiert werden:

```bash
#!/bin/bash

v=$(cat /dev/urandom | tr -dc a-f0-9 | fold -w16 | head -n1)
echo your:first:four:blocks:${v:0:4}:${v:4:4}:${v:8:4}:${v:12}
```

Die ersten vier Blöcke der IPv6-Adresse (`your:first:four:blocks`) müssen dabei durch das
jeweilige /64-Präfix des Servers ersetzt werden (Bsp.: `2001:0db8:85a3:0053`).


### Verwendete Ports auflisten
Wenn man jedem Dienst eine eigene IPv6-Adresse zuweist, kann jeder Dienst nach Außen den gleichen
Port verwenden (z. B. 443 für HTTPS). Auf dem Host müssen die Ports jedoch unterschiedlich sein.
Um sich die verwendet Ports aller Dienste anzeigen zu lassen, kann folgender Befehl verwendet werden:
`grep -oP "(?<=proxy_pass)[^;]*" /etc/nginx/sites-enabled/* | sed "s/ /\t/" | expand -t 30 | grep ${1:-.}`


Wenn man diesen Befehl in eine Funktion schreibt und diese in die `.bashrc` einfügt, kann man nach
der Verwendung eines genauen Ports suchen:
```bash
function searchport {
grep -oP "(?<=proxy_pass)[^;]*" /etc/nginx/sites-enabled/* | sed "s/ /\t/" | expand -t 30 | grep ${1:-.}
}
```

Verwendung: `searchport 8080` -> Listet alle Dienste auf, die den Port 8080 verwenden.
91 changes: 91 additions & 0 deletions docs/A._Theorie/40_ipv4-to-ipv6-proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# 4. IPv4 to IPv6 Proxy

## Sonderfälle
### Virtualisierungsserver
Zwar richtet sich dieser Guide in erster Linie an Administratoren einfacher vServer, doch kann es
schnell vorkommen, dass aufgrund steigender Leistungsanforderungen auf einen dedizierten Server
gewechselt wird.

Nehmen wir an, ein solcher Server verfügt über eine IPv4-Adresse und ein /64-IPv6-Präfix, auf dem
mehrere virtuelle Maschinen betrieben werden sollen. Das Hostsystem, das direkt auf der physischen
Hardware installiert ist, kann in diesem Szenario als Router fungieren. Über NAT und Port Address
Translation (PAT) lassen sich dabei gezielt einzelne Ports an die virtualisierten Systeme weiterleiten.

Dank des zugewiesenen IPv6-Präfixes kann jedoch jeder virtuellen Maschine eine eigene öffentliche
IPv6-Adresse zugeordnet werden, wodurch sie direkt aus dem Internet erreichbar ist – ganz ohne NAT.

In diesem Zusammenhang kann der Einsatz eines IPv4-zu-IPv6-Proxys sinnvoll sein. Ein solcher Proxy
nimmt Anfragen über IPv4 entgegen und leitet sie intern per IPv6 an den Zielserver weiter. Auf diese
Weise bleibt die Erreichbarkeit auch für IPv4-Clients gewährleistet, selbst wenn die eigentliche
Infrastruktur ausschließlich auf IPv6 basiert.

### IPv6-only Server
Angenommen, es steht eine größere Anzahl von Servern zur Verfügung. Um Kosten und Verwaltungsaufwand
zu reduzieren, wird dabei bewusst auf individuelle IPv4-Adressen verzichtet und jedem System ausschließlich
ein IPv6-Netz zugewiesen.

!!! warning
Dieses Setup impliziert, dass die Systeme selbst keine ausgehende IPv4-Verbindung aufbauen können.
Das kann die Administration erschweren – beispielsweise, wenn Repositories von GitHub, Docker Hub oder
anderen ausschließlich über IPv4 erreichbaren Diensten bezogen werden sollen. In solchen Fällen ist
entweder ein IPv6-fähiger Mirror oder ein NAT64-Gateway erforderlich, um den Zugriff zu ermöglichen.

Die wenigsten Anbieter stellen derzeit NAT64 Gateways zur Verfügung, weshalb zum derzeitigen Zeitpunkt
von dieser Systemarchitektur abzuraten ist.

Die Erreichbarkeit dieser Server aus dem IPv4-Internet kann in einem solchen Szenario über einen zentralen
IPv4-zu-IPv6-Proxy sichergestellt werden. Dieser Proxy fungiert als gemeinsame Eingangsstelle für alle
IPv4-Anfragen und leitet sie intern über IPv6 an die jeweiligen Zielsysteme weiter – effizient, kostensparend
und ohne die Notwendigkeit zusätzlicher IPv4-Ressourcen.

## IPv4-to-IPv6 Proxy
Zur Vereinfachung der vorgestellten Sonderfälle kann folgende einfache nginx Konfiguration verwendet werden.
Diese implementiert einen IPv4-to-IPv6 Proxy, der zwar in dieser Version lediglich HTTP- und HTTPs-Verbindungen
unterstützt, jedoch mit geringfügigen Anpassungen auch für andere TLS-gesicherte Protokolle wie SMTPs, IMAPs
oder POP3s verwendet werden kann.

```nginx
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;

sendfile on;
keepalive_timeout 65;

server {
listen 80 default_server;
location / {
return 301 https://$host$request_uri;
}
}
}

stream {
server {
listen 443;

proxy_connect_timeout 1s;
proxy_timeout 3s;

resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] ipv6=on ipv4=off;

proxy_pass $ssl_preread_server_name:443;
ssl_preread on;
}
}
```
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
# Internal Networks
# 5. Internal Networks

Die im AdminGuide aufgeführten Services erhalten grundsätzlich alle ihre eigene Datenbank. Dies erfordert zum einen mehr
Die in diesem Guide aufgeführten Services erhalten grundsätzlich alle ihre eigene Datenbank. Dies erfordert zum einen mehr
Ressourcen, als eine zentrale Datenbank, zum anderen erfordert es beim Exportieren der Datenbanken für ein Backup die
Behandlung mehrerer Datenbankserver.

Wenn man eine Datenbank für alle Dienste nutzen möchte so sollte dieser als eigener Service definiert werden und über ein
docker-internes Netzwerk mit den anderen Diensten kommunizieren.

![Schematic with internal networks](img/internal_networks.png){: loading=lazy }
```mermaid
flowchart LR
Internet@{ shape: cloud, label: Internet }
Web@{ shape: diamond, label: "Reverse Proxy" }
A[HedgeDoc]
B[Nextcloud]
DB@{ shape: cyl, label: MariaDB }

Internet <-- "[::]:443" --> Web
Web <-- "[::1]:8000" --> A
Web <-- "[::1]:8001" --> B
A & B <--> DB
```

Das interne Netzwerk kann mit dem folgenden Befehl erstellt werden:
```shell
Expand Down
Loading
Loading