Compare commits

34 Commits
Design ... main

Author SHA1 Message Date
20bc5db523 docs: update Profice-services/feedgine 2026-03-26 13:33:32 +00:00
3a833aa8e8 docs: update Profice-services/feedgine 2026-03-26 13:14:26 +00:00
bf48d5781a docs: create Profice-services/feedgine 2026-03-26 13:12:33 +00:00
b877e2a859 docs: update IT_Abteilung/Automatisierung/Channable_stack 2026-03-06 11:13:15 +00:00
0e3b3b0203 docs: create IT_Abteilung/Automatisierung/Channable_stack 2026-03-06 11:09:11 +00:00
a3d4ee5ac7 docs: update IT_Abteilung/Security/UFW 2026-02-24 08:56:46 +00:00
2747f218e9 docs: create IT_Abteilung/Security/UFW 2026-02-24 08:54:59 +00:00
9a720c74da docs: rename IT_Abteilung/wiki to IT_Abteilung/DatenBank/wiki 2026-02-24 08:32:48 +00:00
18a20881b0 docs: update IT_Abteilung/Security/SSH 2026-02-24 08:32:28 +00:00
c35f09dcea docs: create IT_Abteilung/Security/SSH 2026-02-24 08:29:19 +00:00
04c668eb7b docs: create IT_Abteilung/DatenBank/Gitea 2026-02-24 08:17:57 +00:00
112aa978c7 docs: update IT_Abteilung/Security/PasswortManager 2026-02-23 10:45:43 +00:00
7fcdd36f60 docs: create IT_Abteilung/Security/PasswortManager 2026-02-23 10:43:43 +00:00
b5bd8e00fb docs: update IT_Abteilung/DatenBank/PostgreSQL 2026-02-23 10:32:44 +00:00
de9dee3313 docs: update IT_Abteilung/DatenBank/PostgreSQL 2026-02-23 10:28:32 +00:00
086c7bd43d docs: update IT_Abteilung/DatenBank/PostgreSQL 2026-02-23 10:21:10 +00:00
3ac688e4b1 docs: create IT_Abteilung/DatenBank/PostgreSQL 2026-02-23 10:09:11 +00:00
e84ecd637d docs: update home 2026-02-23 09:51:02 +00:00
7c799d30c5 docs: update home 2026-02-23 09:32:16 +00:00
cc0dccdd7f docs: rename IT_Abteilung/n8n to IT_Abteilung/Automatisierung/n8n 2026-02-23 09:22:41 +00:00
9d9cfe598c docs: rename IT_Abteilung/Wireguard to IT_Abteilung/Security/Wireguard 2026-02-23 09:21:55 +00:00
66d712c05b docs: update IT_Abteilung/n8n 2026-02-23 09:19:33 +00:00
755de7c164 docs: update IT_Abteilung/Wireguard 2026-02-23 09:19:09 +00:00
feaa5069c4 docs: create IT_Abteilung/Wireguard 2026-02-23 09:18:38 +00:00
ab58cde4d6 docs: delete README 2026-02-23 09:05:43 +00:00
b5d526f18b docs: delete IT_Abteilung/Willkomen 2026-02-23 09:05:23 +00:00
5922dafa17 docs: create IT_Abteilung/wiki 2026-02-23 09:04:59 +00:00
c4e78bc400 docs: update IT_Abteilung/n8n 2026-02-23 08:50:39 +00:00
ca3bad7f62 docs: create IT_Abteilung/n8n 2026-02-23 08:44:22 +00:00
Jane Doe
f49fb7715e docs: add all untracked content 2026-02-19 08:13:19 +00:00
590f1323c7 docs: create home 2026-02-17 12:49:52 +00:00
8772fab75c docs: create IT_Abteilung/Willkomen 2026-02-17 12:41:54 +00:00
b4363897fe Update home.md 2026-02-17 12:33:47 +00:00
484f494fc9 docs: upload appicon_1024x1024-01.png 2026-02-17 12:32:53 +00:00
13 changed files with 11975 additions and 703 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,146 @@
---
title: N8N Profice Dokumentation
description:
published: true
date: 2026-02-23T09:19:32.266Z
tags:
editor: markdown
dateCreated: 2026-02-23T08:44:20.329Z
---
# 🛠️ n8n Instanz-Dokumentation: n8n.profice.de
Diese Dokumentation beschreibt die Konfiguration, den Betrieb und die Nutzung der n8n-Automatisierungsinstanz unter der Domain **n8n.profice.de**.
---
## 1. Architektur-Übersicht
Die n8n-Instanz ist in einer hochsicheren Umgebung isoliert. Sie ist **nicht** über das öffentliche Internet erreichbar.
* **Host:** `n8n.profice.de`
* **Bereitstellung:** Docker & Docker Compose
* **Reverse Proxy:** Traefik (mit automatischer TLS-Verschlüsselung)
* **Netzwerksicherheit:** Zugriff ausschließlich über **WireGuard VPN**
---
## 2. Sicherheitskonzept (Zero-Exposure)
Um maximale Sicherheit für unsere Workflows zu gewährleisten, folgt das System dem Prinzip des "Least Privilege Access":
1. **VPN-Tunnel:** Der Server akzeptiert Pakete für den Traefik-Proxy nur, wenn diese über das virtuelle WireGuard-Interface eingehen.
2. **IP-Whitelisting:** In der Firewall (UFW/Iptables) sind die Ports 80 und 443 für das öffentliche Interface gesperrt und nur für das VPN-Subnetz (z.B. `10.8.0.0/24`) freigegeben.
3. **End-to-End Verschlüsselung:** Trotz VPN wird der Verkehr innerhalb des Tunnels zusätzlich via HTTPS (Let's Encrypt) verschlüsselt.
---
## 3. Installation & Konfiguration
### 3.1 Docker Compose Setup
Die Instanz wird über eine `docker-compose.yml` Datei verwaltet. Hier ist die Konfiguration, die mit Traefik kommuniziert:
```yaml
version: '3.8'
services:
n8n:
image: n8nio/n8n:latest
container_name: n8n_app
restart: always
environment:
- N8N_HOST=n8n.profice.de
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=[https://n8n.profice.de/](https://n8n.profice.de/)
- GENERIC_TIMEZONE=Europe/Berlin
volumes:
- /opt/n8n/data:/home/node/.n8n
networks:
- traefik_network
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`n8n.profice.de`)"
- "traefik.http.routers.n8n.entrypoints=websecure"
- "traefik.http.routers.n8n.tls.certresolver=myresolver"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
networks:
traefik_network:
external: true
```
### 3.2 Traefik Integration
Traefik fungiert als zentraler Edge-Router und übernimmt die SSL-Terminierung. Da die Instanz hinter einem VPN liegt und nicht über das öffentliche Internet für eine HTTP-01-Challenge erreichbar ist, wird die **DNS-01-Challenge** empfohlen, um gültige Let's Encrypt Zertifikate zu erhalten.
* **Automatische Erkennung:** Durch Docker-Labels erkennt Traefik den n8n-Container automatisch.
* **Sicherheit:** Traefik leitet Anfragen nur weiter, wenn der Host-Header exakt `n8n.profice.de` entspricht.
---
## 4. Nutzung und Zugriff
Um die n8n-Plattform zu nutzen, müssen die folgenden Schritte auf dem Endgerät des Benutzers durchgeführt werden:
### 4.1 VPN-Verbindung (WireGuard)
Ein Zugriff ohne aktiven VPN-Tunnel ist technisch ausgeschlossen.
1. Öffnen Sie den **WireGuard Client**.
2. Aktivieren Sie den Tunnel für das Profil `profice-intern`.
3. Vergewissern Sie sich, dass der Status auf "Aktiv" steht.
### 4.2 Web-Interface
1. Öffnen Sie einen Browser Ihrer Wahl.
2. Rufen Sie die Adresse [https://n8n.profice.de](https://n8n.profice.de) auf.
3. Melden Sie sich mit Ihren Benutzerdaten an.
> [!IMPORTANT]
> Sollten Sie eine Fehlermeldung wie "DNS_PROBE_FINISHED_NXDOMAIN" erhalten, prüfen Sie bitte, ob Ihr WireGuard-Tunnel die DNS-Anfragen korrekt an den internen DNS-Server weiterleitet.
---
## 5. Wartung und Updates
### 5.1 n8n aktualisieren
Da n8n in einem Docker-Container läuft, ist der Update-Prozess standardisiert:
```bash
# Zum Installationsverzeichnis navigieren
cd /opt/n8n-docker
# Neueste Version vom Docker Hub beziehen
docker-compose pull
# Container mit der neuen Version neu starten
docker-compose up -d
```
### 5.2 Backup-Strategie
Der Schutz Ihrer Automatisierungsdaten ist essenziell. Da n8n alle Konfigurationen, Anmeldedaten und Workflows lokal speichert, muss das Datenverzeichnis regelmäßig gesichert werden.
* **Datenverzeichnis:** `/opt/n8n/data` (enthält die SQLite-Datenbank `database.sqlite`, Verschlüsselungs-Keys und binäre Anhänge).
* **Häufigkeit:** Es wird ein tägliches Backup dieses Verzeichnisses empfohlen.
* **Vorgehensweise:** Sichern Sie das Verzeichnis idealerweise im gestoppten Zustand der Container oder nutzen Sie Dateisystem-Snapshots.
* **Manueller Export:** Einzelne Workflows können jederzeit über die n8n-Benutzeroberfläche als `.json` Dateien exportiert und in einem Git-Repository (z.B. GitLab/GitHub) versioniert werden.
---
## 6. Fehlerbehebung (Troubleshooting)
Sollten Probleme beim Zugriff auf **n8n.profice.de** auftreten, nutzen Sie bitte die folgende Tabelle zur ersten Diagnose:
| Symptom | Mögliche Ursache | Lösung |
| :--- | :--- | :--- |
| **Seite lädt unendlich / Timeout** | WireGuard-Tunnel ist inaktiv. | Prüfen Sie Ihren WireGuard-Client und die Verbindung zum VPN-Server. |
| **504 Gateway Timeout** | Der n8n-Dienst reagiert nicht oder der Container ist abgestürzt. | Prüfen Sie den Status mit `docker ps`. Starten Sie ggf. mit `docker-compose restart n8n` neu. |
| **403 Forbidden** | Zugriff erfolgt von einer nicht autorisierten IP-Adresse. | Stellen Sie sicher, dass Ihr Traffic korrekt durch den VPN-Tunnel geroutet wird (IP-Check). |
| **DNS_PROBE_FINISHED_NXDOMAIN** | Die Domain kann intern nicht aufgelöst werden. | Prüfen Sie, ob der im WireGuard-Profil hinterlegte DNS-Server erreichbar ist. |
| **Workflows werden nicht ausgeführt** | Datenbank-Lock oder fehlende Ressourcen. | Prüfen Sie die Logs mittels `docker logs --tail 50 n8n_app`. |
---
**Dokumentationsstatus:** Aktiv ✅
**Verantwortlich:** IT-Abteilung / DevOps
**Letzte Aktualisierung:** 23.02.2026

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
---
title: Wiki.js Profice Dokumentation
description:
published: true
date: 2026-02-23T09:04:58.250Z
tags:
editor: markdown
dateCreated: 2026-02-23T09:04:58.250Z
---
# 📚 Wiki.js Instanz-Dokumentation: wiki.profice.de
Diese Dokumentation beschreibt die Einrichtung, den Betrieb und die Synchronisations-Logik der zentralen Wissensdatenbank **wiki.profice.de**.
---
## 1. Architektur-Überblick
Wiki.js dient als zentrales Dokumentations-Tool und ist tief in unsere Infrastruktur integriert. Die Datenhaltung erfolgt redundant durch eine Kopplung mit unserem internen Git-System.
* **Domain:** `wiki.profice.de`
* **Plattform:** Wiki.js (Node.js Applikation)
* **Datenbank:** PostgreSQL (Docker)
* **Reverse Proxy:** Traefik
* **Versionskontrolle:** Gitea (`git.profice.de`)
* **Netzwerk:** Zugriff nur via **WireGuard VPN**
---
## 2. Sicherheits- und Netzwerkzugriff
### 2.1 VPN-Beschränkung (WireGuard)
Die Instanz `wiki.profice.de` ist **nicht** öffentlich erreichbar. Der Zugriff wird durch den Traefik-Proxy streng auf Anfragen aus dem WireGuard-Tunnel beschränkt.
* **Voraussetzung:** Ein aktiver WireGuard-Tunnel mit Zugriff auf das Netzsegment von `profice.de`.
* **DNS:** Die interne Auflösung der Domain erfolgt nur bei bestehender VPN-Verbindung.
### 2.2 TLS-Verschlüsselung
Obwohl die Verbindung über einen verschlüsselten VPN-Tunnel erfolgt, wird der Traffic zusätzlich durch **TLS-Zertifikate** (via Let's Encrypt / Traefik) gesichert, um "Man-in-the-Middle"-Angriffe innerhalb des Netzwerks zu verhindern.
---
## 3. Technische Konfiguration (Docker)
Die Bereitstellung erfolgt über Docker Compose. Wiki.js benötigt eine PostgreSQL-Datenbank für den Betrieb.
### 3.1 Docker Compose Beispiel
```yaml
version: "3.8"
services:
db:
image: postgres:15-alpine
container_name: wikijs_db
environment:
- POSTGRES_DB=wiki
- POSTGRES_USER=wikijs
- POSTGRES_PASSWORD=dein_sicheres_passwort
volumes:
- /opt/wiki/db-data:/var/lib/postgresql/data
networks:
- internal_network
wiki:
image: requarks/wiki:2
container_name: wikijs_app
depends_on:
- db
environment:
- DB_TYPE=postgres
- DB_HOST=db
- DB_PORT=5432
- DB_USER=wikijs
- DB_PASS=dein_sicheres_passwort
- DB_NAME=wiki
volumes:
- /opt/wiki/config:/wiki/config
networks:
- internal_network
- traefik_network
labels:
- "traefik.enable=true"
- "traefik.http.routers.wiki.rule=Host(`wiki.profice.de`)"
- "traefik.http.routers.wiki.entrypoints=websecure"
- "traefik.http.routers.wiki.tls.certresolver=myresolver"
networks:
traefik_network:
external: true
internal_network:
external: false
```
## 4. Gitea-Integration (Git Storage)
Ein wesentliches Merkmal dieser Instanz ist die bidirektionale Synchronisation mit unserem internen Gitea-Server. Dies stellt sicher, dass alle Dokumente als reine Markdown-Dateien versioniert und auch bei einem Datenbankausfall gesichert sind.
* **Repository-URL:** `https://git.profice.de/it-docs/wiki-storage.git`
* **Synchronisations-Modus:** Bidirektional (Push bei Änderungen im Wiki / Pull bei Änderungen im Repository).
* **Authentifizierung:** Die Kopplung erfolgt über einen **Personal Access Token**, der in Gitea für den Dokumentations-Account generiert wurde.
### Konfigurationsschritte im Wiki:
1. Navigieren Sie zu **Administration > Storage**.
2. Wählen Sie **Git** aus der Liste der verfügbaren Storage-Module.
3. Tragen Sie die URL von `git.profice.de` und die entsprechenden Anmeldedaten ein.
4. Stellen Sie das Synchronisations-Intervall ein (Standard: 5 Minuten).
---
## 5. Verwendung und Best Practices
### 5.1 Editor-Wahl
Für technische Dokumentationen ist zwingend der **Markdown-Editor** zu verwenden. Dies gewährleistet die volle Kompatibilität mit dem Gitea-Storage und ermöglicht eine saubere Versionskontrolle.
### 5.2 Medien und Anhänge
Bilder sollten direkt per Drag-and-Drop in den Editor gezogen werden. Wiki.js speichert diese im lokalen `/assets` Verzeichnis, welches automatisch mit in das Git-Repository übertragen wird.
### 5.3 Zugriffsschutz
Da das Wiki sensible Infrastruktur-Details enthält (wie z.B. n8n-Konfigurationen), ist der Zugriff strikt auf Benutzer innerhalb des **WireGuard-VPN-Tunnels** beschränkt. Traefik blockiert alle Anfragen, die von externen (öffentlichen) IP-Adressen kommen.
---
## 6. Wartung und Fehlerbehebung
### 6.1 System-Updates
Die Wartung erfolgt über Docker. Vor jedem Update wird ein Snapshot der PostgreSQL-Datenbank empfohlen.
```bash
# Verzeichnis der Docker-Installation aufrufen
cd /opt/wiki-js
# Neue Images ziehen und Container neu starten
docker-compose pull
docker-compose up -d
```
### 6.2 Troubleshooting-Guide
Falls Probleme mit der Instanz **wiki.profice.de** auftreten, nutzen Sie bitte die folgende Übersicht zur Fehlerbehebung:
| Symptom | Mögliche Ursache | Lösung |
| :--- | :--- | :--- |
| **Gitea-Sync schlägt fehl** | Der Personal Access Token ist abgelaufen oder die Repository-Berechtigungen wurden geändert. | Erzeugen Sie einen neuen Token auf `git.profice.de` und aktualisieren Sie diesen in den Wiki.js Storage-Einstellungen. |
| **Seite nicht erreichbar** | Die WireGuard-Verbindung ist inaktiv oder der Client befindet sich im falschen IP-Bereich. | Prüfen Sie Ihren VPN-Status. Stellen Sie sicher, dass der DNS-Server die IP korrekt auflöst. |
| **Bilder laden nicht** | Die Git-Synchronisation hat einen Konflikt in den `/assets` erzeugt. | Überprüfen Sie das Repository auf `git.profice.de` auf Merge-Konflikte und führen Sie diese ggf. manuell zusammen. |
| **"Bad Gateway" (502)** | Der Wiki.js-Container oder der Postgres-Container ist abgestürzt. | Prüfen Sie den Status mit `docker ps`. Starten Sie die Container mit `docker-compose restart` neu. |
| **Änderungen fehlen** | Die bidirektionale Synchronisation ist verzögert. | Erzwingen Sie einen manuellen "Import" über das Administrations-Panel unter "Storage". |
---
**Dokumentationsstatus:** Aktiv ✅
**Verantwortlich:** IT-Administration / DevOps
**Letzte Aktualisierung:** 23.02.2026

File diff suppressed because it is too large Load Diff

1638
IT_Abteilung/Security/SSH.md Normal file

File diff suppressed because it is too large Load Diff

1395
IT_Abteilung/Security/UFW.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,186 @@
---
title: Wireguard VPN Profice Dokumentation
description:
published: true
date: 2026-02-23T09:19:08.176Z
tags:
editor: markdown
dateCreated: 2026-02-23T09:18:36.441Z
---
# 🛡️ WireGuard VPN Dokumentation: Zentraler Sicherheits-Gateway
Diese Dokumentation beschreibt die Installation und Verwaltung des WireGuard VPN-Servers, der als exklusiver Zugangspunkt für unsere internen Dienste fungiert. Aktuell sichert dieser den Zugriff auf **wiki.profice.de** und **n8n.profice.de**.
---
## 1. Funktionsprinzip und Architektur
WireGuard agiert als "Türsteher" für unser Netzwerk. Anstatt Dienste direkt dem öffentlichen Internet auszusetzen, lauscht der WireGuard-Container auf einem einzelnen UDP-Port. Nur Geräte mit einem gültigen kryptografischen Schlüssel können einen Tunnel aufbauen.
* **Modus:** Docker-basiertes Deployment.
* **Zweck:** Verschlüsselter Zugriff auf das interne Docker-Netzwerk und IP-Whitelisting für Traefik.
* **Abgedeckte Domains:** * `wiki.profice.de`
* `n8n.profice.de`
---
## 2. Installation (Docker Compose)
Wir nutzen das bewährte Image von **linuxserver/wireguard**, da es eine einfache Verwaltung von Peers (Clients) über Umgebungsvariablen ermöglicht.
### 2.1 Docker Compose Konfiguration
Die Datei befindet sich auf dem Server unter `/opt/wireguard/docker-compose.yml`.
```yaml
version: "3.8"
services:
wireguard:
image: lscr.io/linuxserver/wireguard:latest
container_name: wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Berlin
- SERVERURL=vpn.profice.de # Deine öffentliche IP oder DynDNS
- SERVERPORT=51820
- PEERS=AdminHandy,AdminLaptop,Mitarbeiter1 # Namen der Endgeräte
- PEERDNS=1.1.1.1 # Optionaler DNS
- INTERNAL_SUBNET=10.13.13.0
- ALLOWEDIPS=0.0.0.0/0 # Oder spezifische interne IPs
volumes:
- /opt/wireguard/config:/config
- /lib/modules:/lib/modules
ports:
- 51820:51820/udp
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
restart: always
```
## 3. Geräte-Verbindung (Client Setup)
Sobald der Container gestartet ist, erstellt WireGuard automatisch die notwendigen Konfigurationsprofile für alle in der `PEERS`-Variable definierten Endgeräte.
### 3.1 Smartphone (iOS / Android)
Die einfachste Methode für mobile Geräte ist die Verwendung des QR-Codes.
1. Installieren Sie die **WireGuard App** aus dem offiziellen App Store oder Google Play Store.
2. Öffnen Sie ein Terminal auf dem Server und lassen Sie sich den QR-Code anzeigen:
```bash
docker logs -f wireguard
### 3.1 Mobile Verbindung (Smartphone/Tablet)
Die einfachste Methode für mobile Geräte ist die Verwendung des QR-Codes.
1. **App installieren:** Installieren Sie die offizielle **WireGuard App** aus dem Google Play Store oder Apple App Store.
2. **QR-Code anzeigen:** Öffnen Sie ein Terminal auf dem Server und lassen Sie sich den Code in den Logs anzeigen:
```bash
docker logs wireguard
```
3. **Hinzufügen:** Wählen Sie in der App das **"+" Icon** -> **Scan from QR code**.
4. **Verbindung:** Scannen Sie den Code für Ihren Peer (z. B. `peer_AdminHandy`) und aktivieren Sie den Tunnel.
---
### 3.2 Desktop-Verbindung (Windows / macOS / Linux)
Für Desktop-Rechner verwenden wir die Konfigurationsdateien (`.conf`).
1. **Konfiguration finden:** Navigieren Sie auf dem Server in den Ordner des jeweiligen Peers:
```bash
cd /opt/wireguard/config/peer_<NAME>/
```
2. **Download:** Kopieren Sie die Datei `peer_<NAME>.conf` sicher auf Ihren Computer (z. B. via SCP oder SFTP).
3. **Import:** * Installieren Sie den Client von [wireguard.com](https://www.wireguard.com).
* Wählen Sie **Tunnel aus Datei importieren** und wählen Sie die `.conf`-Datei aus.
4. **Aktivieren:** Klicken Sie auf **Aktivieren**, um die gesicherte Verbindung herzustellen.
---
## 4. Integration mit Traefik & Domain-Schutz
Der Schutz der Domains `wiki.profice.de` und `n8n.profice.de` erfolgt durch eine Kombination aus verschlüsseltem Tunnel und **IP-Whitelisting** auf Proxy-Ebene.
### 4.1 IP-Whitelisting in Traefik
Damit nur VPN-Nutzer auf die Weboberflächen zugreifen können, wird eine Middleware definiert. Diese lässt ausschließlich Traffic aus dem WireGuard-Subnetz zu.
**Beispiel für die Traefik-Konfiguration (Dynamic File Config):**
```yaml
http:
middlewares:
vpn-only-access:
ipWhiteList:
sourceRange:
- "10.13.13.0/24" # Das interne WireGuard-Subnetz
- "172.18.0.0/16" # Optional: Das interne Docker-Netzwerk
```
### 4.2 Zuweisung zu den Diensten
Damit die Sicherheits-Middleware aktiv wird, muss sie in den Docker-Labels der jeweiligen Dienste (**n8n** und **Wiki.js**) hinterlegt werden. Dies teilt Traefik mit, dass jede Anfrage an diese Domains zuerst die IP-Whitelist-Prüfung bestehen muss.
Fügen Sie folgende Zeilen zu den entsprechenden Containern in Ihrer `docker-compose.yml` hinzu:
**Für n8n:**
```yaml
labels:
- "traefik.http.routers.n8n.middlewares=vpn-only-access@file"
```
**Für Wiki.js:**
```yaml
labels:
- "traefik.http.routers.wiki.middlewares=vpn-only-access@file"
```
## 5. Verwaltung neuer Benutzer (Peers)
Die Verwaltung von Benutzern und Geräten erfolgt zentral über die Konfiguration des WireGuard-Docker-Containers. Der Prozess ist hochgradig automatisiert:
### 5.1 Einen neuen Peer hinzufügen
Um einen neuen Mitarbeiter oder ein weiteres Gerät (z. B. ein Tablet) hinzuzufügen, gehen Sie wie folgt vor:
1. **Konfigurationsdatei öffnen:** Öffnen Sie die `docker-compose.yml` im WireGuard-Installationsverzeichnis (meist `/opt/wireguard/`).
2. **Peer-Liste erweitern:** Suchen Sie unter `environment:` die Variable `PEERS=`. Fügen Sie den neuen Namen durch ein Komma getrennt hinzu.
* *Wichtig:* Keine Leerzeichen verwenden und nur alphanumerische Zeichen nutzen.
* *Beispiel:* `PEERS=AdminPC,ChefHandy,Mitarbeiter_A`
3. **Änderungen anwenden:** Starten Sie den Stack neu. WireGuard erkennt die Änderung und generiert im Hintergrund automatisch neue Schlüsselpaare und Konfigurationsdateien:
```bash
docker-compose up -d
```
### 5.2 Zugriff auf die Zugangsdaten
Nach dem Neustart erstellt der Container für jeden Peer einen eigenen Unterordner. Diese finden Sie auf dem Host-Server unter:
` /opt/wireguard/config/peer_<Name>/`
In diesem Ordner befinden sich:
* **peer_<Name>.conf:** Die Konfigurationsdatei für Desktop-Clients.
* **peer_<Name>.png:** Der QR-Code für die schnelle Einrichtung auf mobilen Endgeräten.
---
## 6. Fehlerbehebung (Troubleshooting)
Falls Probleme bei der Verbindung oder beim Zugriff auf die geschützten Domains auftreten, nutzen Sie bitte die folgende Tabelle zur Diagnose:
| Problem | Mögliche Ursache | Lösung |
| :--- | :--- | :--- |
| **Kein Handshake möglich** | Der UDP-Port 51820 ist durch eine Firewall blockiert. | Stellen Sie sicher, dass Port **51820/UDP** am Router und in der Server-Firewall (z.B. UFW) für externe Anfragen geöffnet ist. |
| **VPN steht, aber kein Internet** | Das IP-Forwarding am Host-System ist deaktiviert. | Prüfen Sie dies mit `sysctl net.ipv4.ip_forward`. Der Wert muss auf `1` stehen. Aktivieren Sie es ggf. in der `/etc/sysctl.conf`. |
| **Domains nicht auflösbar** | Die DNS-Konfiguration im VPN-Profil ist inkorrekt. | Prüfen Sie die `PEERDNS`-Einstellung in der Docker-Konfiguration. Empfohlen ist ein stabiler DNS wie `1.1.1.1` oder der interne DNS des Netzwerks. |
| **Traefik meldet "403 Forbidden"** | Die IP-Adresse des VPN-Clients ist nicht in der Whitelist der Traefik-Middleware. | Kontrollieren Sie die Traefik-Konfiguration. Das Subnetz des VPNs (z. B. `10.13.13.0/24`) muss explizit in der `ipWhiteList`-Middleware erlaubt sein. |
| **Verbindung bricht häufig ab** | Instabile Internetverbindung oder MTU-Probleme. | Testen Sie eine geringere MTU-Größe in der Client-Konfiguration (z. B. `MTU = 1280`). |
---
## 7. Sicherheitsrevisions-Log
Sämtliche Änderungen an der Peer-Liste oder den Firewall-Regeln müssen im Git-Repository des Infrastruktur-Teams dokumentiert werden, um die Nachvollziehbarkeit des Zugriffsmanagements zu gewährleisten.
---
**Dokumentationsstatus:** Aktiv ✅
**Abteilung:** IT-Security / DevOps
**Verantwortlich:** Systemadministrator
**Letzte Aktualisierung:** 23.02.2026

1181
Profice-services/feedgine.md Normal file

File diff suppressed because it is too large Load Diff

BIN
appicon_1024x1024-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

56
home.md Normal file
View File

@@ -0,0 +1,56 @@
---
title: Start Seite
description:
published: true
date: 2026-02-23T09:51:00.752Z
tags:
editor: markdown
dateCreated: 2026-02-17T12:49:50.713Z
---
# Willkommen im Knowledge Hub der Profice GmbH 🚀
Herzlich willkommen auf der zentralen Wissensdatenbank der **Profice GmbH**. Wir sind die Experten für **Automatisierung**, **KI-Integration** und performance-orientiertes **Google Ads Management**.
Dieses Wiki dient als unser primäres Werkzeug für das Erstellen, Speichern und Teilen von Unternehmenswissen. Hier fließen unsere Erfahrungen aus Projekten, technischen Dokumentationen und strategischen Prozessen zusammen.
---
## 📂 Abteilungen
Wählen Sie einen Bereich aus, um zu den entsprechenden Dokumentationen zu gelangen:
### [💻 IT-Abteilung](https://wiki.profice.de/de/IT_Abteilung)
Unsere technische Zentrale. Hier finden Sie alles zur Systemadministration und Softwareentwicklung.
* **[🔒 Sicherheit & VPN](/IT_Abteilung/Security)** Dokumentation zu WireGuard, Traefik und Zugriffsschutz.
* **[🤖 Automatisierung](/IT_Abteilung/Automatisierung)** Alles über n8n Workflows und Prozess-Logik.
### [📈 Marketing (Platzhalter)](/Marketing)
Strategien für Google Ads, Content-Erstellung und Kampagnenmanagement für unsere Kunden.
### [🤝 Sales / Vertrieb (Platzhalter)](/Sales)
Onboarding-Unterlagen, Pitch-Decks und Prozesse für die Neukundenakquise.
---
## 💡 Warum wir dieses Wiki nutzen
In einer Welt von KI und Automatisierung ist **strukturiertes Wissen** unser wertvollstes Gut. Wiki.js hilft uns dabei:
* **Wissen zu sichern:** Keine Informationen gehen verloren, wenn Teammitglieder wechseln oder Projekte abgeschlossen werden.
* **Einfaches Onboarding:** Neue Mitarbeiter finden sich schneller in unsere spezialisierten Workflows (wie Google Ads Skripte oder n8n-Nodes) ein.
* **Versionierung:** Dank der Anbindung an unser **Gitea-Repository** bleibt jede Änderung nachvollziehbar.
---
## 🛠️ Schnellzugriffe für Mitarbeiter
* [Interne Tools & Logins](#)
* [Urlaubsanträge & Prozesse](#)
* [CI/CD Richtlinien](#)
---
> **Hinweis:** Dies ist ein geschlossenes System. Der Zugriff ist nur über den **Profice WireGuard Tunnel** gestattet. Sollten Sie Probleme beim Zugriff haben, wenden Sie sich bitte an die [IT-Abteilung](/IT_Abteilung/Security).
---
**Profice GmbH** *Innovation durch Automatisierung & KI.* *Letzte Aktualisierung der Startseite: 23.02.2026*

View File

@@ -1,703 +0,0 @@
/* ==========================================================================
Wiki.js Custom Theme - Profice Corporate Design
Optimized CSS Injection with Light/Dark Mode Support
========================================================================== */
/* ===== CSS VARIABLES - LIGHT MODE (Default) ===== */
:root {
/* Core Colors */
--pf-bg-body: #F7F7F0;
--pf-bg-content: #FFFFFF;
--pf-bg-sidebar: #4F4747;
--pf-bg-header: #4F4747;
/* Text Colors */
--pf-text-primary: #4F4747;
--pf-text-secondary: #6B6363;
--pf-text-muted: #8A8A7A;
--pf-text-inverse: #F7F7F0;
/* Accent Colors */
--pf-accent-teal: #5A9E96;
--pf-accent-teal-hover: #4A8E86;
--pf-accent-orange: #D4864A;
--pf-accent-green: #7FB882;
/* UI Elements */
--pf-border-light: rgba(79, 71, 71, 0.1);
--pf-border-medium: rgba(79, 71, 71, 0.2);
--pf-shadow-soft: 0 2px 12px rgba(79, 71, 71, 0.08);
--pf-shadow-medium: 0 4px 20px rgba(79, 71, 71, 0.12);
--pf-shadow-card: 0 1px 3px rgba(79, 71, 71, 0.06), 0 4px 16px rgba(79, 71, 71, 0.06);
/* Transitions */
--pf-transition: 0.2s ease;
--pf-transition-slow: 0.3s ease;
/* Spacing */
--pf-radius-sm: 6px;
--pf-radius-md: 10px;
--pf-radius-lg: 16px;
--pf-radius-pill: 50px;
}
/* ===== CSS VARIABLES - DARK MODE ===== */
.theme--dark,
[data-theme="dark"],
.dark-mode {
--pf-bg-body: #1E1E1E;
--pf-bg-content: #2D2D2D;
--pf-bg-sidebar: #252525;
--pf-bg-header: #252525;
--pf-text-primary: #E8E8E8;
--pf-text-secondary: #B0B0B0;
--pf-text-muted: #888888;
--pf-text-inverse: #1E1E1E;
--pf-border-light: rgba(255, 255, 255, 0.08);
--pf-border-medium: rgba(255, 255, 255, 0.15);
--pf-shadow-soft: 0 2px 12px rgba(0, 0, 0, 0.3);
--pf-shadow-medium: 0 4px 20px rgba(0, 0, 0, 0.4);
--pf-shadow-card: 0 1px 3px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.2);
}
/* ===== GLOBAL RESET & BASE ===== */
body {
background-color: var(--pf-bg-body) !important;
color: var(--pf-text-primary) !important;
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif !important;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* ===== HEADER / APP BAR ===== */
header,
.v-app-bar,
.v-toolbar,
.application--wrap > header {
background-color: var(--pf-bg-header) !important;
border-bottom: none !important;
box-shadow: var(--pf-shadow-soft) !important;
}
.v-toolbar__content {
background: transparent !important;
border: none !important;
}
/* Header elements */
.v-app-bar .v-toolbar__title,
.v-toolbar__title,
header .v-btn,
header .v-icon,
.v-app-bar .v-icon {
color: var(--pf-text-inverse) !important;
}
/* Header buttons - clean circular style */
header .v-btn,
.v-app-bar .v-btn {
background: rgba(255, 255, 255, 0.1) !important;
border-radius: 50% !important;
box-shadow: none !important;
min-width: 40px !important;
width: 40px !important;
height: 40px !important;
padding: 0 !important;
transition: var(--pf-transition) !important;
}
header .v-btn:hover,
.v-app-bar .v-btn:hover {
background: rgba(255, 255, 255, 0.2) !important;
transform: none !important;
}
/* ===== SEARCH BAR - Clean Pill Style ===== */
.v-app-bar .v-text-field,
header .search-box,
.v-toolbar .v-input,
.v-app-bar .v-input {
background: rgba(255, 255, 255, 0.12) !important;
border: none !important;
border-radius: var(--pf-radius-pill) !important;
box-shadow: none !important;
max-width: 400px !important;
}
.v-app-bar .v-text-field input,
.v-app-bar .v-input input {
color: var(--pf-text-inverse) !important;
padding: 8px 16px !important;
}
.v-app-bar .v-text-field input::placeholder,
.v-app-bar .v-input input::placeholder {
color: rgba(255, 255, 255, 0.5) !important;
}
/* Remove search field underlines and outlines */
.v-app-bar .v-text-field .v-input__slot::before,
.v-app-bar .v-text-field .v-input__slot::after,
.v-app-bar .v-input .v-input__slot::before,
.v-app-bar .v-input .v-input__slot::after {
display: none !important;
border: none !important;
}
.v-app-bar .v-text-field .v-input__slot,
.v-app-bar .v-input .v-input__slot {
background: transparent !important;
box-shadow: none !important;
border: none !important;
}
.v-app-bar .v-text-field.v-input--is-focused .v-input__slot,
.v-app-bar .v-input.v-input--is-focused .v-input__slot {
background: rgba(255, 255, 255, 0.18) !important;
}
/* ===== SIDEBAR / NAVIGATION DRAWER ===== */
.v-navigation-drawer,
.v-navigation-drawer__content {
background-color: var(--pf-bg-sidebar) !important;
border-right: none !important;
}
/* Sidebar text */
.v-navigation-drawer .v-list-item__title,
.v-navigation-drawer .v-list-item__subtitle,
.v-navigation-drawer .v-icon {
color: var(--pf-text-inverse) !important;
}
/* Sidebar navigation items */
.v-navigation-drawer .v-list-item {
margin: 4px 8px !important;
border-radius: var(--pf-radius-sm) !important;
transition: var(--pf-transition) !important;
border: none !important;
min-height: 40px !important;
}
.v-navigation-drawer .v-list-item:hover {
background: rgba(255, 255, 255, 0.08) !important;
}
/* Active sidebar item - subtle highlight, no thick border */
.v-navigation-drawer .v-list-item--active,
.v-navigation-drawer .v-list-item.v-list-item--active {
background: rgba(90, 158, 150, 0.25) !important;
border: none !important;
}
.v-navigation-drawer .v-list-item--active .v-list-item__title,
.v-navigation-drawer .v-list-item--active .v-icon {
color: #FFFFFF !important;
font-weight: 600 !important;
}
/* Sidebar section headers */
.v-navigation-drawer .v-subheader {
color: var(--pf-accent-orange) !important;
font-size: 11px !important;
font-weight: 700 !important;
text-transform: uppercase !important;
letter-spacing: 0.5px !important;
}
/* ===== MAIN CONTENT AREA ===== */
main,
.v-main,
.v-main__wrap {
background-color: var(--pf-bg-body) !important;
}
/* Content container - Clean white card */
.container,
.v-container,
.page-col-content,
.contents {
background: var(--pf-bg-content) !important;
border-radius: var(--pf-radius-lg) !important;
box-shadow: var(--pf-shadow-card) !important;
padding: 32px !important;
margin: 24px !important;
border: 1px solid var(--pf-border-light) !important;
}
/* Remove any glass morphism / backdrop filter */
.container,
.v-container,
.page-col-content,
.contents {
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
/* ===== BREADCRUMBS ===== */
.v-breadcrumbs {
background: transparent !important;
padding: 8px 0 16px 0 !important;
display: flex !important;
align-items: center !important;
}
.v-breadcrumbs__item,
.v-breadcrumbs a {
color: var(--pf-text-muted) !important;
font-size: 13px !important;
text-decoration: none !important;
transition: var(--pf-transition) !important;
}
.v-breadcrumbs a:hover {
color: var(--pf-accent-teal) !important;
}
.v-breadcrumbs__divider {
color: var(--pf-text-muted) !important;
padding: 0 8px !important;
}
/* ===== TYPOGRAPHY ===== */
h1, h2, h3, h4, h5, h6 {
color: var(--pf-text-primary) !important;
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif !important;
font-weight: 600 !important;
line-height: 1.3 !important;
}
h1 {
font-size: 2rem !important;
margin-bottom: 20px !important;
padding-bottom: 12px !important;
border-bottom: 2px solid var(--pf-accent-teal) !important;
}
h2 {
font-size: 1.5rem !important;
margin-top: 32px !important;
margin-bottom: 16px !important;
color: var(--pf-text-primary) !important;
}
h3 {
font-size: 1.25rem !important;
color: var(--pf-accent-teal) !important;
margin-top: 24px !important;
margin-bottom: 12px !important;
}
p {
color: var(--pf-text-secondary) !important;
line-height: 1.7 !important;
margin-bottom: 16px !important;
}
a {
color: var(--pf-accent-teal) !important;
text-decoration: none !important;
transition: var(--pf-transition) !important;
}
a:hover {
color: var(--pf-accent-teal-hover) !important;
text-decoration: underline !important;
}
/* ===== BUTTONS - Standardized Teal Gradient ===== */
.v-btn,
button:not(.v-app-bar .v-btn),
input[type="submit"],
input[type="button"] {
background: linear-gradient(135deg, var(--pf-accent-teal), var(--pf-accent-green)) !important;
color: #FFFFFF !important;
border: none !important;
border-radius: var(--pf-radius-md) !important;
padding: 10px 20px !important;
font-weight: 600 !important;
font-size: 14px !important;
text-transform: none !important;
letter-spacing: 0 !important;
box-shadow: 0 2px 8px rgba(90, 158, 150, 0.3) !important;
transition: var(--pf-transition) !important;
}
.v-btn:hover,
button:not(.v-app-bar .v-btn):hover,
input[type="submit"]:hover,
input[type="button"]:hover {
box-shadow: 0 4px 16px rgba(90, 158, 150, 0.4) !important;
transform: translateY(-1px) !important;
}
/* Secondary / Outlined buttons */
.v-btn--outlined {
background: transparent !important;
color: var(--pf-text-primary) !important;
border: 2px solid var(--pf-border-medium) !important;
box-shadow: none !important;
}
.v-btn--outlined:hover {
background: var(--pf-bg-body) !important;
border-color: var(--pf-accent-teal) !important;
color: var(--pf-accent-teal) !important;
transform: none !important;
}
/* Icon buttons in content area */
.v-btn--icon {
background: transparent !important;
box-shadow: none !important;
}
.v-btn--icon:hover {
background: var(--pf-border-light) !important;
}
/* ===== CARDS ===== */
.v-card {
background: var(--pf-bg-content) !important;
border-radius: var(--pf-radius-md) !important;
box-shadow: var(--pf-shadow-card) !important;
border: 1px solid var(--pf-border-light) !important;
transition: var(--pf-transition-slow) !important;
overflow: hidden !important;
position: relative !important;
}
.v-card:hover {
box-shadow: var(--pf-shadow-medium) !important;
transform: none !important;
border-color: var(--pf-border-medium) !important;
}
/* Remove the top gradient bar from cards */
.v-card::before {
display: none !important;
}
/* ===== FORMS & INPUTS ===== */
.v-text-field .v-input__slot,
.v-input .v-input__slot,
input:not([type="submit"]):not([type="button"]),
textarea,
select {
background: var(--pf-bg-body) !important;
border: 1px solid var(--pf-border-medium) !important;
border-radius: var(--pf-radius-sm) !important;
transition: var(--pf-transition) !important;
}
.v-text-field.v-input--is-focused .v-input__slot,
.v-input.v-input--is-focused .v-input__slot,
input:focus,
textarea:focus,
select:focus {
border-color: var(--pf-accent-teal) !important;
box-shadow: 0 0 0 3px rgba(90, 158, 150, 0.15) !important;
outline: none !important;
}
/* ===== CODE BLOCKS ===== */
pre,
code {
font-family: 'Consolas', 'Monaco', 'Fira Code', monospace !important;
}
pre {
background: #2D2D2D !important;
color: #E8E8E8 !important;
border-radius: var(--pf-radius-md) !important;
padding: 20px !important;
margin: 16px 0 !important;
border-left: 4px solid var(--pf-accent-teal) !important;
overflow-x: auto !important;
}
code:not(pre code) {
background: rgba(90, 158, 150, 0.1) !important;
color: var(--pf-accent-teal) !important;
padding: 2px 6px !important;
border-radius: 4px !important;
font-size: 0.9em !important;
}
/* ===== BLOCKQUOTES ===== */
blockquote {
background: rgba(90, 158, 150, 0.08) !important;
border-left: 4px solid var(--pf-accent-teal) !important;
border-radius: 0 var(--pf-radius-sm) var(--pf-radius-sm) 0 !important;
padding: 16px 20px !important;
margin: 16px 0 !important;
color: var(--pf-text-secondary) !important;
}
/* ===== ALERTS ===== */
.v-alert {
border-radius: var(--pf-radius-md) !important;
padding: 16px 20px !important;
border: none !important;
margin: 16px 0 !important;
}
.v-alert.success,
.v-alert--success {
background: rgba(127, 184, 130, 0.15) !important;
border-left: 4px solid var(--pf-accent-green) !important;
}
.v-alert.info,
.v-alert--info {
background: rgba(90, 158, 150, 0.15) !important;
border-left: 4px solid var(--pf-accent-teal) !important;
}
.v-alert.warning,
.v-alert--warning {
background: rgba(212, 134, 74, 0.15) !important;
border-left: 4px solid var(--pf-accent-orange) !important;
}
.v-alert.error,
.v-alert--error {
background: rgba(220, 80, 80, 0.15) !important;
border-left: 4px solid #DC5050 !important;
}
/* ===== TABLES ===== */
table {
width: 100% !important;
border-collapse: collapse !important;
border-radius: var(--pf-radius-md) !important;
overflow: hidden !important;
box-shadow: var(--pf-shadow-soft) !important;
margin: 16px 0 !important;
}
table th {
background: var(--pf-bg-sidebar) !important;
color: var(--pf-text-inverse) !important;
font-weight: 600 !important;
padding: 14px 16px !important;
text-align: left !important;
}
table td {
padding: 12px 16px !important;
border-bottom: 1px solid var(--pf-border-light) !important;
color: var(--pf-text-secondary) !important;
}
table tr:hover td {
background: rgba(90, 158, 150, 0.04) !important;
}
/* ===== TAGS / CHIPS ===== */
.v-chip {
background: linear-gradient(135deg, var(--pf-accent-teal), var(--pf-accent-green)) !important;
color: #FFFFFF !important;
border-radius: var(--pf-radius-pill) !important;
font-size: 12px !important;
font-weight: 500 !important;
padding: 4px 12px !important;
}
/* ===== DIALOGS / MODALS ===== */
.v-dialog {
border-radius: var(--pf-radius-lg) !important;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2) !important;
overflow: hidden !important;
}
.v-dialog .v-card {
border-radius: var(--pf-radius-lg) !important;
box-shadow: none !important;
}
/* ===== TOOLTIPS ===== */
.v-tooltip__content {
background: var(--pf-bg-sidebar) !important;
color: var(--pf-text-inverse) !important;
border-radius: var(--pf-radius-sm) !important;
padding: 8px 12px !important;
font-size: 13px !important;
box-shadow: var(--pf-shadow-medium) !important;
}
/* ===== SCROLLBAR ===== */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: var(--pf-bg-body);
}
::-webkit-scrollbar-thumb {
background: var(--pf-text-muted);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--pf-text-secondary);
}
/* ===== SELECTION ===== */
::selection {
background: var(--pf-accent-teal);
color: #FFFFFF;
}
/* ===== WIKI.JS SPECIFIC FIXES ===== */
/* Page title styling */
.page-header h1,
.contents > h1:first-child {
font-size: 2rem !important;
color: var(--pf-text-primary) !important;
border-bottom: 2px solid var(--pf-accent-teal) !important;
padding-bottom: 12px !important;
margin-bottom: 24px !important;
}
/* Sidebar tree view */
.v-treeview {
background: transparent !important;
}
.v-treeview-node__root {
border-radius: var(--pf-radius-sm) !important;
margin: 2px 0 !important;
}
.v-treeview-node__root:hover {
background: rgba(255, 255, 255, 0.06) !important;
}
/* Comments section */
.comments-container {
background: var(--pf-bg-content) !important;
border-radius: var(--pf-radius-md) !important;
padding: 20px !important;
border: 1px solid var(--pf-border-light) !important;
}
/* Editor */
.editor,
.ProseMirror,
.CodeMirror {
background: var(--pf-bg-content) !important;
border-radius: var(--pf-radius-md) !important;
border: 1px solid var(--pf-border-medium) !important;
}
.editor:focus-within,
.ProseMirror:focus,
.CodeMirror-focused {
border-color: var(--pf-accent-teal) !important;
box-shadow: 0 0 0 3px rgba(90, 158, 150, 0.15) !important;
}
/* Page info sidebar cards */
.page-col-sd .v-card {
background: var(--pf-bg-content) !important;
border: 1px solid var(--pf-border-light) !important;
margin-bottom: 16px !important;
}
/* Dividers */
hr,
.v-divider {
border-color: var(--pf-border-light) !important;
margin: 24px 0 !important;
}
/* Lists */
ul, ol {
padding-left: 24px !important;
margin: 12px 0 !important;
}
li {
margin-bottom: 8px !important;
color: var(--pf-text-secondary) !important;
}
li::marker {
color: var(--pf-accent-teal) !important;
}
/* Images */
.contents img {
border-radius: var(--pf-radius-md) !important;
box-shadow: var(--pf-shadow-soft) !important;
max-width: 100% !important;
height: auto !important;
}
/* Loading states */
.v-progress-circular {
color: var(--pf-accent-teal) !important;
}
/* ===== RESPONSIVE ===== */
@media (max-width: 960px) {
.container,
.v-container,
.page-col-content,
.contents {
padding: 20px !important;
margin: 12px !important;
border-radius: var(--pf-radius-md) !important;
}
h1 {
font-size: 1.75rem !important;
}
h2 {
font-size: 1.35rem !important;
}
}
@media (max-width: 600px) {
.container,
.v-container,
.page-col-content,
.contents {
padding: 16px !important;
margin: 8px !important;
}
.v-btn {
padding: 8px 16px !important;
font-size: 13px !important;
}
}
/* ===== PRINT ===== */
@media print {
header,
.v-app-bar,
.v-navigation-drawer,
footer {
display: none !important;
}
body {
background: #FFFFFF !important;
}
.container,
.v-container {
box-shadow: none !important;
border: none !important;
margin: 0 !important;
padding: 0 !important;
}
}