p2d2 Multi-Repo Deployment – Komplette Dokumentation
Gültig ab: November 2025
1. System-Architektur
1.1 Übersicht
┌────────── Push ──────────┐ ┌────── Push ───────┐
│ GitLab (opencode.de) │ │ GitHub (3x Team) │
│ ├─ main │ │ ├─ team-de1 │
│ └─ develop │ │ ├─ team-de2 │
└────────────┬─────────────┘ │ └─ team-fv │
│ └───────────────────┘
│ │
│ Webhook │
↓ ↓
┌────────────────────────────────┐
│ Frontend VM (Port 9321) │
│ Webhook-Server │
│ ├─ Secret-Validierung │
│ ├─ Repo-Router │
│ ├─ git clone → staging-Server │
│ └─ Deploy-Trigger │
└───────────────┬────────────────┘
│
↓
┌──────── staging server ──────────┐
│ systemd Services │
│ ├─ astro-main (Port 3000) │
│ ├─ astro-develop (Port 3001) │
│ ├─ astro-feature-team-de1 (3002)│
│ ├─ astro-feature-team-de2 (3003)│
│ └─ astro-feature-team-fv (3004) │
└───────────────┬──────────────────┘
│
↓
┌────────── Präsentation ──────────┐
│ Caddy Reverse Proxy (OPNSense) │
│ ├─ www.data-dna.eu → :3000 │
│ ├─ dev.data-dna.eu → :3001 │
│ ├─ f-de1.data-dna.eu → :3002 │
│ ├─ f-de2.data-dna.eu → :3003 │
│ └─ f-fv.data-dna.eu → :3004 │
└──────────────────────────────────┘1.2 Deployment-Flows
Flow 1: Main/Develop (dein Repo, GitLab)
Du: git push origin develop
↓
GitLab Webhook → POST http://www.data-dna.eu:9321/webhook
↓
Webhook-Server:
├─ Liest x-gitlab-token Header
├─ Validiert gegen SECRET_DEVELOP
├─ Findet: https://gitlab.opencode.de/.../p2d2.git
├─ Branch: develop
└─ Ruft auf: deploy-branch.sh develop ... https://gitlab...
↓
Deploy-Script:
├─ git clone --branch develop
├─ npm ci + npm run build
├─ sudo systemctl restart astro-develop
└─ Live unter dev.data-dna.euFlow 2: Feature Branches (Team-Repos, GitHub)
Team: git push origin feature/team-de1/meine-funktion
↓
GitHub Webhook → POST http://www.data-dna.eu:9321/webhook
↓
Webhook-Server:
├─ Liest x-hub-signature-256 Header
├─ Kalkuliert HMAC-SHA256 mit SECRET_TEAM_DE1
├─ Validiert Signature
├─ Branch-Pattern Match: /^feature\/team-de1\/.+/ ✓
├─ Findet: https://github.com/team-de1/p2d2-feature.git
└─ Ruft auf: deploy-branch.sh feature/team-de1/meine-funktion ... https://github.com/team-de1/...
↓
Deploy-Script:
├─ git clone --branch feature/team-de1/meine-funktion
├─ npm ci + npm run build
├─ sudo systemctl restart astro-feature-team-de1
└─ Live unter f-de1.data-dna.eu2. Webhook-Server Konfiguration
2.1 Secrets Management
# /home/astro/webhook-server/.env
# GitLab Secrets (dein Repo)
SECRET_MAIN=dein_secret_main_hier
SECRET_DEVELOP=dein_secret_develop_hier
# GitHub Shared Secrets (Team-Repos)
SECRET_TEAM_DE1=team_de1_secret_hier
SECRET_TEAM_DE2=team_de2_secret_hier
SECRET_TEAM_FV=team_fv_secret_hier2.2 Branch-Konfiguration
// /home/astro/webhook-server/index.js (Auszug)
const branchConfig = {
'main': {
domain: 'www.data-dna.eu',
deployPath: '/var/www/astro/deployments/main',
port: 3000,
repo: 'https://gitlab.opencode.de/OC000028072444/p2d2.git',
secret: process.env.SECRET_MAIN,
provider: 'gitlab'
},
'develop': {
domain: 'dev.data-dna.eu',
deployPath: '/var/www/astro/deployments/develop',
port: 3001,
repo: 'https://gitlab.opencode.de/OC000028072444/p2d2.git',
secret: process.env.SECRET_DEVELOP,
provider: 'gitlab'
},
'feature/team-de1': {
domain: 'f-de1.data-dna.eu',
deployPath: '/var/www/astro/deployments/feature-de1',
port: 3002,
repo: 'https://github.com/team-de1/p2d2-feature.git',
secret: process.env.SECRET_TEAM_DE1,
provider: 'github',
matchPattern: /^feature\/team-de1\/.+/
},
'feature/team-de2': {
domain: 'f-de2.data-dna.eu',
deployPath: '/var/www/astro/deployments/feature-de2',
port: 3003,
repo: 'https://github.com/team-de2/p2d2-feature.git',
secret: process.env.SECRET_TEAM_DE2,
provider: 'github',
matchPattern: /^feature\/team-de2\/.+/
},
'feature/team-fv': {
domain: 'f-fv.data-dna.eu',
deployPath: '/var/www/astro/deployments/feature-fv',
port: 3004,
repo: 'https://github.com/team-fv/p2d2-feature.git',
secret: process.env.SECRET_TEAM_FV,
provider: 'github',
matchPattern: /^feature\/team-fv\/.+/
}
};3. Team Onboarding
3.1 Schritt 1: Team-Repo erstellen
Team macht das:
# Option A: Neues Repo
# GitHub.com → New Repository → p2d2-feature
# Clone & Feature-Branch erstellen
git clone https://github.com/team-de1/p2d2-feature.git
cd p2d2-feature
git checkout -b feature/team-de1/setup
# Option B: Fork des Main-Repos
# GitHub.com → fork Peter-Koenig/p2d2-hub
# Clone & Feature-Branch erstellen
git clone https://github.com/team-de1/p2d2-feature.git
cd p2d2-feature
git checkout -b feature/team-de1/meine-funktion3.2 Schritt 2: Secret generieren & verteilen
Du machst das:
# Secret generieren
openssl rand -hex 32
# Ausgabe: a1b2c3d4e5f6g7h8...
# Mit Team teilen (verschlüsselt!)
# Signal, PGP, oder sicherer Kanal
# In .env eintragen
echo "SECRET_TEAM_DE1=a1b2c3d4e5f6g7h8..." >> /home/astro/webhook-server/.env
# Webhook-Server neu starten
sudo systemctl restart webhook-server3.3 Schritt 3: GitHub Webhook konfigurieren
Team macht das:
- GitHub → Repository → Settings → Webhooks → Add webhook
- Payload URL:
http://<deine-ip>:9321/webhook - Content type:
application/json - Secret: Den Secret von dir
- Which events:
Just the push event - Active: ✅
- Add webhook
Test:
- Recent Deliveries → Klick auf Eintrag → "Redeliver"
- Oder: Team macht Test-Push zu
feature/team-de1/test
4. Development Workflow
4.1 Feature entwickeln (Team)
# Team entwickelt lokal
git checkout feature/team-de1/neue-funktion
# ... Code ändern ...
git add .
git commit -m "Feature: Neue Funktion"
git push origin feature/team-de1/neue-funktionWas passiert automatisch:
Push → GitHub Webhook
→ Server validiert Secret
→ Deploy-Script triggert
→ f-de1.data-dna.eu updated
→ LIVE in ~2 Minuten4.2 Feature testen
Team kann ihre Änderungen live anschauen:
# Team testet unter
https://f-de1.data-dna.eu/
# Bei Änderungen: Einfach neuen Push
git add .
git commit -m "Bugfix: xyz"
git push origin feature/team-de1/neue-funktion
# → Automatisch deployed5. Integration in Main/Develop
5.1 Feature Ready → Pull Request
Team erstellt Pull Request (in ihrem Repo oder zu deinem):
# GitHub: team-de1/p2d2-feature
# PR: feature/team-de1/neue-funktion → develop
# Oder: Zu deinem Main-Repo
# PR: OC000028072444/p2d2
# feature/team-de1/neue-funktion → develop5.2 Du reviewst & merged
# Du auf deinem Repo
git checkout develop
git pull origin develop
# Feature-Branch mergen
git merge feature/team-de1/neue-funktion
git push origin developWas passiert:
Git Push zu develop
↓
GitLab Webhook
↓
Server deployed zu dev.data-dna.eu
↓
Team + du können testen auf Staging5.3 Release → Main
# Nach Test/Approval
git checkout main
git pull origin main
git merge develop
git push origin mainWas passiert:
Git Push zu main
↓
GitLab Webhook
↓
Server deployed zu www.data-dna.eu
↓
LIVE in Produktion!6. Deployment-Verzeichnisstruktur
/var/www/astro/
├── deployments/
│ ├── main/
│ │ ├── deploys/
│ │ │ ├── 20251104003111/ ← Latest
│ │ │ ├── 20251104002000/
│ │ │ └── ...
│ │ ├── live → deploys/20251104003111/ ← Active
│ │ └── logs/
│ ├── develop/
│ │ ├── deploys/
│ │ ├── live → ...
│ │ └── logs/
│ ├── feature-de1/
│ │ ├── deploys/
│ │ ├── live → ...
│ │ └── logs/
│ ├── feature-de2/
│ ├── feature-fv/
│ └── scripts/
│ └── deploy-branch.sh
└── shared/
└── src/
└── content/
└── kommunen/ ← Externe Collection7. Monitoring & Troubleshooting
7.1 Logs prüfen
# Webhook-Server
sudo journalctl -u webhook-server -f
# Deployment-Service
sudo journalctl -u astro-develop -f
# Build-Logs
tail -f /var/www/astro/deployments/develop/logs/npm-build-*.log7.2 Häufige Probleme
Problem: Webhook triggert nicht
# 1. Webhook-Server läuft?
sudo systemctl status webhook-server
# 2. Secret korrekt?
grep SECRET_TEAM_DE1 /home/astro/webhook-server/.env
# 3. Logs anschauen
sudo journalctl -u webhook-server -n 50Problem: Build schlägt fehl
# Deploy-Logs
tail -100 /var/www/astro/deployments/feature-de1/logs/npm-build-*.log
# Service-Logs
sudo journalctl -u astro-feature-team-de1 -n 30Problem: Service startet nicht
# Verzeichnis existiert?
ls -la /var/www/astro/deployments/feature-de1/live/
# Port gebunden?
sudo lsof -i :3002
# Service neu starten
sudo systemctl restart astro-feature-team-de18. Sicherheit
8.1 Secret-Verwaltung
- ✅ Jedem Team eigener Secret
- ✅ Secrets in
.env(nicht im Code) - ✅ Datei-Berechtigungen:
600(nur astro) - ✅ GitHub HMAC-SHA256 Validierung
- ✅ GitLab Token Validierung
- ⚠️ Secrets regelmäßig rotieren
8.2 Branch-Schutz
Server-seitig: Branch-Pattern-Matching
// Team DE1 kann NICHT zu feature/team-de2 deployen
// Server validiert Pattern: /^feature\/team-de1\/.+/
// Unbekannte Branches: 404 (ignoriert)GitHub: Branch-Protection-Rules (optional)
Settings → Branches → Add rule
├─ Pattern: main
├─ Require pull request reviews
└─ Require status checks to pass9. Quick Reference
Secrets generieren
openssl rand -hex 32Webhook-Server Logs
sudo journalctl -u webhook-server -fService neu starten
sudo systemctl restart astro-developDeployment manuell
sudo -u astro /var/www/astro/scripts/deploy-branch.sh \
feature/team-de1/setup \
/var/www/astro/deployments/feature-de1 \
3002 \
https://github.com/team-de1/p2d2-feature.gitStatus aller Services
sudo systemctl status astro-*10. Zusammenfassung
┌─────────────────────────────────────────────┐
│ Workflow Summary │
├─────────────────────────────────────────────┤
│ │
│ Team entwickelt in ihrem GitHub-Repo │
│ └─ feature/team-de1/* │
│ │
│ Push triggert Webhook │
│ └─ Server validiert Secret + Branch │
│ │
│ Deploy-Script wird aufgerufen │
│ └─ Git clone + npm build │
│ │
│ Service wird neu gestartet │
│ └─ f-de1.data-dna.eu LIVE │
│ │
│ Team testet auf Feature-Domain │
│ └─ Nach Approval: PR zu develop │
│ │
│ Du mergst develop → main │
│ └─ Automatisches Deployment zu www │
│ │
│ LIVE in Produktion ✅ │
│ │
└─────────────────────────────────────────────┘English Version
Valid as of November 2025
1. System Architecture
1.1 Overview
Push Push
↓ ↓
GitLab GitHub
(opencode.de) (3x Team)
↓ ↓
main team-de1
develop team-de2
team-fv
↓ ↓
Webhook (Frontend VM)
Port 9321
Webhook Server
├─ Secret Validation
└─ Repo Router
↓
git clone
staging Server
↓
Deploy Trigger
↓
staging server
systemd Services
├─ astro-main (Port 3000)
├─ astro-develop (Port 3001)
├─ astro-feature-team-de1 (3002)
├─ astro-feature-team-de2 (3003)
└─ astro-feature-team-fv (3004)
↓
Presentation
Caddy Reverse Proxy (OPNSense)
├─ www.data-dna.eu → :3000
├─ dev.data-dna.eu → :3001
├─ f-de1.data-dna.eu → :3002
├─ f-de2.data-dna.eu → :3003
└─ f-fv.data-dna.eu → :30041.2 Deployment Flows
Flow 1: Main/Develop (your repo, GitLab)
git push origin develop
↓
Webhook → POST http://www.data-dna.eu:9321/webhook
↓
Webhook Server
├─ Reads x-gitlab-token Header
├─ Validates against SECRET_DEVELOP
└─ Finds: https://gitlab.opencode.de/.../p2d2.git
Branch: develop
↓
Calls: deploy-branch.sh develop ... https://gitlab...
↓
Deploy Script
├─ git clone --branch develop
├─ npm ci
├─ npm run build
└─ sudo systemctl restart astro-develop
↓
Live at: dev.data-dna.euFlow 2: Feature Branches (Team Repos, GitHub)
git push origin feature/team-de1/my-function
↓
Webhook → POST http://www.data-dna.eu:9321/webhook
↓
Webhook Server
├─ Reads x-hub-signature-256 Header
├─ Calculates HMAC-SHA256 with SECRET_TEAM_DE1
├─ Validates Signature
├─ Branch Pattern Match: feature/team-de1/*
└─ Finds: https://github.com/team-de1/p2d2-feature.git
↓
Calls: deploy-branch.sh feature/team-de1/my-function ... https://github.com/team-de1/...
↓
Deploy Script
├─ git clone --branch feature/team-de1/my-function
├─ npm ci
├─ npm run build
└─ sudo systemctl restart astro-feature-team-de1
↓
Live at: f-de1.data-dna.eu2. Webhook Server Configuration
2.1 Secrets Management
/home/astro/webhook-server/.env
# GitLab Secrets (your repo)
SECRET_MAIN=<your-secret-main-here>
SECRET_DEVELOP=<your-secret-develop-here>
# GitHub Shared Secrets (Team Repos)
SECRET_TEAM_DE1=<team-de1-secret-here>
SECRET_TEAM_DE2=<team-de2-secret-here>
SECRET_TEAM_FV=<team-fv-secret-here>2.2 Branch Configuration
/home/astro/webhook-server/index.js (excerpt)
branchConfig: {
main: {
domain: "www.data-dna.eu",
deployPath: "/var/www/astro/deployments/main",
port: 3000,
repo: "https://gitlab.opencode.de/OC000028072444/p2d2.git",
secret: process.env.SECRET_MAIN,
provider: "gitlab",
},
develop: {
domain: "dev.data-dna.eu",
deployPath: "/var/www/astro/deployments/develop",
port: 3001,
repo: "https://gitlab.opencode.de/OC000028072444/p2d2.git",
secret: process.env.SECRET_DEVELOP,
provider: "gitlab",
},
"feature/team-de1": {
domain: "f-de1.data-dna.eu",
deployPath: "/var/www/astro/deployments/feature-de1",
port: 3002,
repo: "https://github.com/team-de1/p2d2-feature.git",
secret: process.env.SECRET_TEAM_DE1,
provider: "github",
matchPattern: "feature/team-de1/*",
},
"feature/team-de2": {
domain: "f-de2.data-dna.eu",
deployPath: "/var/www/astro/deployments/feature-de2",
port: 3003,
repo: "https://github.com/team-de2/p2d2-feature.git",
secret: process.env.SECRET_TEAM_DE2,
provider: "github",
matchPattern: "feature/team-de2/*",
},
"feature/team-fv": {
domain: "f-fv.data-dna.eu",
deployPath: "/var/www/astro/deployments/feature-fv",
port: 3004,
repo: "https://github.com/team-fv/p2d2-feature.git",
secret: process.env.SECRET_TEAM_FV,
provider: "github",
matchPattern: "feature/team-fv/*",
}
}3. Team Onboarding
3.1 Step 1: Team creates repo
Option A: New repo
# GitHub.com
New Repository → p2d2-feature
# Clone
git clone https://github.com/team-de1/p2d2-feature.git
cd p2d2-feature
# Create feature branch
git checkout -b feature/team-de1/setupOption B: Fork main repo
# GitHub.com
fork Peter-Koenig/p2d2-hub
# Clone
git clone https://github.com/team-de1/p2d2-feature.git
cd p2d2-feature
# Create feature branch
git checkout -b feature/team-de1/my-function3.2 Step 2: Generate & distribute secret (you do this)
# Generate secret
openssl rand -hex 32
# Output:
a1b2c3d4e5f6g7h8...
# Share with team (encrypted! Signal, PGP, or secure channel)
# Add to .env
SECRET_TEAM_DE1=a1b2c3d4e5f6g7h8...
# /home/astro/webhook-server/.env
# Restart webhook server
systemctl restart webhook-server3.3 Step 3: Configure GitHub webhook (team does this)
- GitHub Repository → Settings → Webhooks → Add webhook
- Payload URL:
http://<your-ip>:9321/webhook - Content type:
application/json - Secret: The secret from you
- Which events: Just the push event
- Active: ✓
- Add webhook
Test:
- Recent Deliveries → Click on entry → Redeliver
- Or team makes test push to
feature/team-de1/test
4. Development Workflow
4.1 Develop feature (team)
Team develops locally:
git checkout feature/team-de1/new-function
# ... change code ...
git add .
git commit -m "Feature: New function"
git push origin feature/team-de1/new-functionWhat happens automatically:
- GitHub → Webhook → Server validates secret
- Deploy script triggers
- f-de1.data-dna.eu updates → LIVE in ~2 minutes
4.2 Test feature
Team can view their changes live:
- Team tests at f-de1.data-dna.eu
For changes:
# Simply new push
git add .
git commit -m "Bugfix: xyz"
git push origin feature/team-de1/new-function
# → Automatically deployed5. Integration into Main/Develop
5.1 Feature Ready → Pull Request
Team creates pull request:
# Pull request in their repo
GitHub: team-de1/p2d2-feature
PR: feature/team-de1/new-function → develop
# Or: To your main repo
PR: OC000028072444/p2d2
feature/team-de1/new-function → develop5.2 You review & merge
You on your repo:
git checkout develop
git pull origin develop
# Merge feature branch
git merge feature/team-de1/new-function
git push origin developWhat happens:
- Push to
develop→ Webhook deploys to dev.data-dna.eu - You can test on staging
5.3 Release → Main
After test/approval:
git checkout main
git pull origin main
git merge develop
git push origin mainWhat happens:
- Push to
main→ Webhook deploys to www.data-dna.eu - LIVE in production!
6. Deployment Directory Structure
/var/www/astro
├── deployments
│ ├── main
│ │ ├── deploys
│ │ │ ├── 20251104003111 ← Latest
│ │ │ ├── 20251104002000
│ │ │ └── ...
│ │ └── live → deploys/20251104003111 ← Active
│ ├── develop
│ │ ├── deploys
│ │ └── live → ...
│ │ └── logs
│ ├── feature-de1
│ │ ├── deploys
│ │ └── live → ...
│ │ └── logs
│ ├── feature-de2
│ └── feature-fv
├── scripts
│ └── deploy-branch.sh
└── shared
└── src
└── content
└── kommunen ← External Collection7. Monitoring & Troubleshooting
7.1 Check logs
# Webhook server
journalctl -u webhook-server -f
# Deployment service
journalctl -u astro-develop -f
# Build logs
tail -f /var/www/astro/deployments/develop/logs/npm-build-*.log7.2 Common problems
Webhook not triggering:
- Webhook server running?
systemctl status webhook-server
``` ```- Secret correct?
# SECRET_TEAM_DE1
/home/astro/webhook-server/.env- Check logs:
journalctl -u webhook-server -n 50
``` ```Build fails:
# Deploy logs
tail -100 /var/www/astro/deployments/feature-de1/logs/npm-build-*.log
# Service logs
journalctl -u astro-feature-team-de1 -n 30Service doesn't start:
# Directory exists?
ls -la /var/www/astro/deployments/feature-de1/live
# Port bound?
lsof -i :3002
# Restart service
systemctl restart astro-feature-team-de18. Security
8.1 Secret Management
- Each team has own secret
- Secrets in
.env, not in code - File permissions:
600(only astro) - GitHub: HMAC-SHA256 validation
- GitLab: Token validation
- Rotate secrets regularly
8.2 Branch Protection
Server-side: Branch Pattern Matching
- Team DE1 CANNOT deploy to
feature/team-de2 - Server validates pattern
feature/team-de1/* - Unknown branches → 404 (ignored)
Branch Protection Rules (optional):
# Branches → Add rule
Pattern: main
✓ Require pull request reviews
✓ Require status checks to pass9. Quick Reference
# Generate secrets
openssl rand -hex 32
# Webhook server logs
journalctl -u webhook-server -f
# Restart service
systemctl restart astro-develop
# Manual deployment
sudo -u astro /var/www/astro/scripts/deploy-branch.sh feature/team-de1/setup /var/www/astro/deployments/feature-de1 3002 https://github.com/team-de1/p2d2-feature.git
# Status of all services
systemctl status astro-*10. Summary: Workflow Overview
- Team develops in their GitHub repo (
feature/team-de1) - Push triggers webhook
- Server validates secret + branch
- Deploy script is called:
- Git clone
- npm build
- Service is restarted
- f-de1.data-dna.eu → LIVE
- Team tests on feature domain
- After approval → PR to develop
- You merge →
develop→main - Automatic deployment to www → LIVE in production