Provisioning
Cloud-Infrastruktur per Code: Server, Netzwerke, Firewalls, DNS, Load Balancer, TLS-Zertifikate und Volumes. Single-Server oder Multi-Node-Cluster. Provider-unabhängig, ENV-gesteuert, mit State-Tracking.
Überblick
jardisops/provisioning automatisiert die komplette Cloud-Infrastruktur: vom einzelnen Server bis zum Multi-Node-Cluster mit Private Network, Load Balancer und automatischem DNS. Alles wird über .env-Dateien konfiguriert, der aktuelle Zustand in .provision-state.json persistiert.
GitHub: jardisOps/provisioning
| Eigenschaft | Wert |
|---|---|
| PHP | ≥ 8.2 |
| Provider | Hetzner Cloud, INWX DNS |
| Modi | Single-Server, Multi-Node-Cluster |
| Verschlüsselung | AES-256-GCM, Sodium |
| State | .provision-state.json |
Installation
composer require jardisops/provisioningInitialisierung eines neuen Projekts:
vendor/bin/provision init --project-root=.Erzeugt .env-Template, Makefile und .gitignore.
Architektur
┌──────────────────────────────────────────────────────┐
│ CLI (vendor/bin/provision) │
└─────────────────────────┬────────────────────────────┘
│
┌─────────────────────────▼────────────────────────────┐
│ Provisioner (Orchestrator) │
│ Provider-unabhängige Workflow-Koordination │
└──┬────────┬─────────┬─────────┬─────────┬────────┬───┘
│ │ │ │ │ │
Server Network Firewall LoadBal. DNS Volume
│ │ │ │ │ │
└────────┴─────────┴─────────┴─────────┴────────┘
│
┌───────────▼───────────┐
│ Provider-Adapter │
│ Hetzner │ INWX │ ... │
└───────────────────────┘Der Provisioner kennt keine Provider-Details. Er arbeitet ausschließlich über Interfaces aus Support/Contract/.
Deployment-Modi
Single-Server
Ein Server mit externer Firewall, optionalem DNS und optionalem Volume.
PROVISION_MODE=single
INFRA_PROVIDER=hetzner
SERVER_NAME=my-app
SERVER_TYPE=cpx31Ablauf:
- SSH-Key registrieren
- Cloud-Init-Script generieren (Härtung)
- Server erstellen + warten bis Running
- Externe Firewall erstellen (22, 80, 443)
- DNS-Records erstellen (optional)
- Volume erstellen (optional)
- State speichern
Multi-Node-Cluster
Mehrere Server mit Private Network, interner Firewall, Load Balancer und TLS.
PROVISION_MODE=cluster
INFRA_PROVIDER=hetzner
CLUSTER_NAME=jardis-prod
CLUSTER_NODE_COUNT=3
CLUSTER_NODE_1_ROLE=server
CLUSTER_NODE_1_TYPE=cpx31
CLUSTER_NODE_1_NAME=jardis-prod-server-1
CLUSTER_NODE_2_ROLE=agent
CLUSTER_NODE_2_TYPE=cpx31
CLUSTER_NODE_2_NAME=jardis-prod-agent-1
CLUSTER_NODE_3_ROLE=agent
CLUSTER_NODE_3_TYPE=cpx31
CLUSTER_NODE_3_NAME=jardis-prod-agent-2
# Private Network
PRIVATE_NETWORK_NAME=jardis-prod-net
PRIVATE_NETWORK_SUBNET=10.0.1.0/24
PRIVATE_NETWORK_ZONE=eu-central
# Load Balancer
LOADBALANCER_ENABLED=true
LOADBALANCER_NAME=jardis-prod-lb
LOADBALANCER_TYPE=lb11
LOADBALANCER_ALGORITHM=round_robin
LOADBALANCER_HEALTH_CHECK_PATH=/healthAblauf:
- SSH-Key registrieren + Cloud-Init generieren
- Private Network erstellen
- Server-Node erstellen (10.0.1.2)
- Agent-Nodes erstellen (10.0.1.3, 10.0.1.4, ...)
- Externe Firewall (22, 80, 443) + interne Firewall (K3S-Ports)
- TLS-Zertifikat erstellen (Let's Encrypt)
- Load Balancer erstellen + Targets zuweisen
- DNS-Records auf LB-IP
- Volumes erstellen (optional)
- State speichern
Interne Firewall-Regeln (K3S):
| Port | Protokoll | Dienst |
|---|---|---|
| 6443 | TCP | Kubernetes API |
| 8472 | UDP | Flannel/WireGuard |
| 10250 | TCP | Kubelet |
| 2379 | TCP | etcd |
| 2380 | TCP | etcd Peer |
Konfiguration
Globale Variablen
| Variable | Beschreibung |
|---|---|
PROVISION_MODE | single oder cluster |
INFRA_PROVIDER | Infrastructure-Provider (hetzner) |
DNS_PROVIDER | DNS-Provider (hetzner, inwx) — optional |
SSH_KEY_PATH | Pfad zum SSH Public Key |
Hetzner Cloud
| Variable | Beschreibung |
|---|---|
HETZNER_API_TOKEN | API-Token (unterstützt Verschlüsselung) |
HETZNER_DNS_TOKEN | DNS-Token (optional, fällt auf API-Token zurück) |
HETZNER_REGION | Rechenzentrum (fsn1, nbg1, hel1, ash, sin) |
HETZNER_IMAGE | Server-Image (ubuntu-24.04) |
HETZNER_BACKUP_ENABLED | Automatische Backups (true/false) |
INWX DNS
| Variable | Beschreibung |
|---|---|
INWX_USER | INWX Benutzername |
INWX_PASSWORD | Passwort (unterstützt Verschlüsselung) |
DNS_ZONE | DNS-Zone (example.com) |
DNS_RECORDS | Records (api:A,portal:A,monitoring:A) |
DNS_TTL | Time-to-Live (Default: 300) |
Sicherheit / Cloud-Init
| Variable | Default | Beschreibung |
|---|---|---|
SECURITY_DEPLOY_USER | deploy | Nicht-Root Deploy-User |
SECURITY_SSH_PORT | 22 | SSH-Port |
SECURITY_DISABLE_ROOT | true | Root-Login deaktivieren |
SECURITY_DISABLE_PASSWORD_AUTH | true | Nur SSH-Key-Auth |
SECURITY_AUTO_UPDATES | true | Automatische Updates |
SECURITY_FAIL2BAN | true | Fail2Ban aktivieren |
Load Balancer
| Variable | Default | Beschreibung |
|---|---|---|
LOADBALANCER_ENABLED | — | Load Balancer aktivieren |
LOADBALANCER_NAME | — | Name |
LOADBALANCER_TYPE | lb11 | Typ (lb11, lb21) |
LOADBALANCER_ALGORITHM | round_robin | Algorithmus |
LOADBALANCER_HEALTH_CHECK_PROTOCOL | http | Protokoll |
LOADBALANCER_HEALTH_CHECK_PORT | 80 | Port |
LOADBALANCER_HEALTH_CHECK_PATH | /health | Pfad |
LOADBALANCER_HEALTH_CHECK_INTERVAL | 15 | Intervall (Sek.) |
LOADBALANCER_HEALTH_CHECK_TIMEOUT | 10 | Timeout (Sek.) |
LOADBALANCER_HEALTH_CHECK_RETRIES | 3 | Wiederholungen |
CLI-Commands
vendor/bin/provision <command> [optionen]| Command | Beschreibung |
|---|---|
init | Projekt bootstrappen (ENV-Template, Makefile) |
provision | Infrastruktur aufbauen |
provision --dry-run | Vorschau ohne Änderungen |
deprovision --force | Alles abbauen |
status | Aktuellen Zustand anzeigen |
status --json | Zustand als JSON |
node:add | Node zum Cluster hinzufügen |
node:remove | Node aus Cluster entfernen |
secret:generate-key | Verschlüsselungs-Key generieren |
secret:encrypt | Wert verschlüsseln (AES-256-GCM) |
secret:encrypt-sodium | Wert verschlüsseln (Sodium) |
Node-Management
Node hinzufügen
vendor/bin/provision node:add \
--name=jardis-prod-agent-3 \
--role=agent \
--type=cpx31 \
--volume=50Erstellt Server, hängt ihn ins Private Network, wendet Firewalls an, fügt ihn zum Load Balancer hinzu.
Node entfernen
vendor/bin/provision node:remove \
--name=jardis-prod-agent-3 \
--delete-volumeEntfernt Node aus LB, löst Volumes, entfernt Firewalls, löscht Server.
Secret-Management
API-Tokens und Passwörter können verschlüsselt in .env gespeichert werden:
# Key generieren
vendor/bin/provision secret:generate-key
# Wert verschlüsseln
vendor/bin/provision secret:encrypt --value="hcloud-Xyz..."
# → secret(aes:k9Xp2mV8nQ3wR6yT...)In .env eintragen:
HETZNER_API_TOKEN=secret(aes:k9Xp2mV8nQ3wR6yT...)
INWX_PASSWORD=secret(sodium:A7bQ9c...)Die Entschlüsselung erfolgt automatisch beim Laden der Konfiguration via jardissupport/dotenv + jardissupport/secret.
State-Tracking
Der aktuelle Infrastruktur-Zustand wird in .provision-state.json persistiert:
{
"version": 1,
"mode": "cluster",
"cluster_name": "jardis-prod",
"provider": "hetzner",
"region": "fsn1",
"created_at": "2024-01-15T10:30:00+00:00",
"resources": {
"ssh_key": { "id": 123, "name": "jardis-prod" },
"nodes": [
{ "name": "server-1", "role": "server", "public_ip": "49.12.xx.xx", "private_ip": "10.0.1.2" }
],
"firewalls": [...],
"network": { "name": "jardis-prod-net", "subnet": "10.0.1.0/24" },
"load_balancer": { "name": "jardis-prod-lb", "ip": "49.12.xx.xx" },
"dns_records": [...]
}
}Idempotent: Mehrfaches Ausführen von provision erstellt keine Duplikate: der State verhindert doppelte Ressourcen.
Provider erweitern
Neuen Provider hinzufügen:
- Verzeichnis
src/Provider/<Name>/erstellen - 6–7 Interfaces implementieren (
ServerProviderInterface,NetworkProviderInterface, etc.) - Handler-Klasse erstellen (
<Name>InfraHandler) - In
ProvisionerFactoryregistrieren .env.exampleim Provider-Verzeichnis anlegen
Der Provisioner, StateManager und die CLI funktionieren automatisch: keine Änderungen nötig.
Makefile
| Target | Beschreibung |
|---|---|
make provision | Infrastruktur aufbauen |
make provision-dry | Dry-Run |
make deprovision | Alles abbauen |
make cluster-status | Status anzeigen |
make cluster-status-json | Status als JSON |
make node-add | Node hinzufügen |
make node-remove | Node entfernen |
make generate-key-file | Verschlüsselungs-Key generieren |
make encrypt | Wert verschlüsseln (AES) |
make encrypt-sodium | Wert verschlüsseln (Sodium) |
Abhängigkeiten
| Package | Zweck |
|---|---|
jardissupport/dotenv | ENV-Laden mit Typ-Casting |
jardissupport/secret | Secret-Verschlüsselung/-Entschlüsselung |
ext-json | JSON-Verarbeitung |
ext-curl | HTTP-Requests |
ext-xmlrpc | INWX XML-RPC API |