Diese Anleitung führt Sie durch die Bereitstellung der STACKIT Landing Zone von Grund auf.
Note
Die Module in diesem Terraform-Repository sind nicht zur direkten Nutzung vorgesehen. Klonen Sie das Repository und passen Sie die Module an Ihre konkreten Anforderungen an. Es gibt keine Garantien für Migrationspfade oder dafür, dass die Module unverändert bleiben.
Bucket-Namen gelten STACKIT-weit. Der Standard bucket_naming = "project-id"
enthält jetzt die vollständige ID des jeweiligen Management- oder Anwendungsprojekts.
Nur der lesbare Präfix wird auf insgesamt höchstens 63 Zeichen gekürzt.
Die State-Adressen bleiben stabil, Bucket-Namen sind jedoch unveränderlich:
Vor dem Upgrade einer Installation mit vorhandenen bisherigen Bucket-Namen
bucket_naming = "legacy" setzen, sofern keine separate Ersetzung bzw.
Daten-/Backend-Migration geprüft wurde. Es gibt keine automatische Datenmigration
oder State-Neuanlage. Ein teilweise ausgeführtes Deployment ohne Buckets kann
Projekt und Checkpoint mit dem neuen Standard beibehalten. Vor Apply einen neuen
vollständigen Plan prüfen.
Siehe Issue #127.
Zentrale Observability-Aufbewahrungswerte sind optional/null und verwenden sonst die Servicestandards. Monitoring unterstützt keine Logs-/Trace-Aufbewahrung; Frontend und MetricsEndpoint keine Aufbewahrungsüberschreibungen. Explizite Werte müssen innerhalb der Servicegrenzen liegen (ganze Tage: Logs/Traces 1–30, Metriken/Downsampling 1–780). Das native Root weist diese unzulässigen Kombinationen vor der Ressourcenbereitstellung zurück.
- Eine STACKIT-Organisation, in der Ihr Benutzerkonto registriert ist
- Owner-Berechtigungen auf der STACKIT-Organisation
- Installierte STACKIT CLI (Installationsanleitung)
- Installiertes OpenTofu (>= 1.10) oder Terraform (>= 1.10)
bash,curlundjqauf dem Rechner, auf dem OpenTofu läuft, nur für die Variante Hub-Spoke + Firewall. API-Schlüssel-Bootstrap und HA-Konfiguration sind Shell-Provisioner; die HA-Skripte verwendenjq
Note
Diese Anleitung verwendet durchgehend tofu-Befehle. Wenn Sie Terraform verwenden, ersetzen Sie tofu durch terraform – alle Befehle funktionieren identisch.
Unter src/config/ stehen acht vollständige, einsatzbereite Konfigurationen bereit:
| Variante | Konfigurationsdatei | Beschreibung |
|---|---|---|
| Standalone | standalone.tfvars |
Nur Governance, Management, DevOps und öffentliche Landing Zones. Keine Network Area oder Firewall. |
| Hub-Spoke | hub-and-spoke.tfvars |
Ergänzt einen Connectivity-Hub mit Network Area und DNS-Zonen. Corporate Landing Zones verbinden sich über die Network Area. |
| Hub-Spoke + Firewall | hub-and-spoke-firewall.tfvars |
Vollständige Hub-Spoke-Topologie mit einer OPNsense-Firewall-Appliance an der WAN-/LAN-Grenze. |
| Regulated and Shared | hub-and-spoke-multi-area.tfvars |
Trennt regulierte Workloads von gemeinsam genutzten Workloads mit unterschiedlichen Sicherheitsanforderungen. |
| Finance and Research | hub-and-spoke-finance-research.tfvars |
Isoliert Geschäftsbereiche mit unterschiedlichen Eigentümern, Adressplänen und Konnektivitätsanforderungen. |
| Prod/Nonprod + Firewalls | hub-and-spoke-prod-nonprod-firewall.tfvars |
Dedizierte SNAs und OPNsense-Appliances für Produktion und Nichtproduktion. |
| Tenant Isolation | hub-and-spoke-tenant-isolation.tfvars |
Trennt drei Mandanten, die eine gemeinsame unternehmensweite STACKIT-Organisation nutzen. |
| Multi-Region | hub-and-spoke-multi-region.tfvars |
Stellt unabhängige Connectivity-Hubs, Landing Zones und Platform-Kubernetes-Cluster in eu01 und eu02 bereit. |
Wählen Sie die Variante, die Ihren Anforderungen entspricht, und passen Sie die entsprechende .tfvars-Datei vor der Bereitstellung an (Schritt 7). Aktualisieren Sie mindestens owner_email, organization_id, company_name und company_code.
Die Multi-SNA-Szenariodateien sind vollständige Konfigurationen. Ersetzen Sie vor dem Anwenden die Platzhalterwerte für owner_email, company_name, company_code und organization_id. Die Area-Schlüssel sind nur Beispiele; wählen Sie stabile Schlüssel passend zu Ihrer Grenze. Entscheidungshilfen und Einschränkungen stehen unter Mehrere Network Areas.
Das Szenario Prod/Nonprod + Firewalls erstellt eine Appliance pro SNA. Seine OPNsense-Richtlinien müssen derzeit nach dem Bootstrap für jede Appliance konfiguriert werden; der einzelne firewall_config-Block wird nicht automatisch verteilt.
Die Firewall-Variante benötigt einen zusätzlichen Schritt: Die Appliance startet unkonfiguriert, ihre Richtlinie wird in einem zweiten Apply aus dem anfangs auskommentierten firewall_config-Block derselben .tfvars-Datei übertragen. Bis dahin filtert sie nichts, und ihre Web-GUI ist aus dem Internet erreichbar – siehe OPNsense-Firewall konfigurieren. Standardmäßig wird eine einzelne Appliance bereitgestellt, die als Standardroute jeder Corporate Landing Zone ein Single Point of Failure ist. Der auskommentierte Block connectivity.firewall.ha macht daraus ein aktives/passives CARP-Paar – siehe Firewall hochverfügbar machen.
Beide Hub-Spoke-Varianten können zusätzlich ein Site-to-Site-IPsec-VPN im Hub terminieren. Es ist standardmäßig deaktiviert – siehe den auskommentierten Block connectivity.vpn in der .tfvars-Datei und Site-to-Site-VPN. Lesen Sie bei Verwendung der Firewall-Variante zuerst, welchen Verkehr die Firewall tatsächlich sieht, bevor Sie sich bei der VPN-Inspektion auf sie verlassen.
Note
Dieser Ansatz mit einem einzelnen Root-Modul eignet sich gut für kleinere Umgebungen. Bei größerem Umfang – typischerweise über 10 Landing Zones – können STACKIT-API-Ratenlimits bei Applies sowie langsamere Plan-/Refresh-Zyklen durch eine wachsende State-Datei auftreten. Werkzeuge wie Terragrunt, Terramate oder Spacelift können helfen, indem sie Landing Zones in isolierte State-Dateien aufteilen und Root-Modulaufrufe mit geeigneter Parallelitätssteuerung orchestrieren. Wenden Sie sich bei einer größeren Unternehmensbereitstellung an STACKIT oder einen Partner mit verifizierter Landing-Zone-Lösung im STACKIT Marketplace.
git clone https://github.com/stackitcloud/stackit-landing-zone.git
cd stackit-landing-zone/srcWenn Sie die Variante Hub-Spoke + Firewall bereitstellen, laden Sie das OPNsense-Image in das Verzeichnis src/ herunter:
curl -o firewall-image.qcow2 https://opnsense.object.storage.eu01.onstackit.cloud/opnsense-26.1-amd64-21-05-2026.qcow2Melden Sie sich interaktiv über den Browser an:
stackit auth loginEin kurzlebiges Projekt wird benötigt, um das erste Dienstkonto für die Terraform-/OpenTofu-Authentifizierung zu erstellen:
# get the organization id
stackit organization list
# create the project
stackit project create --name tmp-bootstrap --parent-id <ORGANIZATION_ID>Notieren Sie die project_id aus der Ausgabe.
stackit service-account create --name bootstrap-sa --project-id <PROJECT_ID>
# Grant the service account owner permissions at the organization level so it can provision all resources:
stackit organization member add <SERVICE_ACCOUNT_EMAIL> --role organization.owner --organization-id <ORGANIZATION_ID>Erstellen Sie einen Dienstkontoschlüssel und konfigurieren Sie ihn für den STACKIT-Terraform-Provider:
mkdir -p ~/.stackit
stackit service-account key create --email <SERVICE_ACCOUNT_EMAIL> --project-id <PROJECT_ID> -y --verbosity error > ~/.stackit/credentials.json
export STACKIT_SERVICE_ACCOUNT_KEY_PATH=/home/<USER>/.stackit/credentials.jsonImportant
STACKIT_SERVICE_ACCOUNT_KEY_PATH muss über Terminalsitzungen hinweg erhalten bleiben.
Note
~ funktioniert nicht als Referenz auf das Home-Verzeichnis. Bei Verwendung von mise können Sie den Export von STACKIT_SERVICE_ACCOUNT_KEY_PATH weglassen.
Alle unterstützten Authentifizierungsmethoden finden Sie in der Dokumentation des STACKIT-Terraform-Providers.
Kopieren und bearbeiten Sie die .tfvars-Datei passend zu Ihrem Bereitstellungsszenario:
cp config/standalone.tfvars terraform.auto.tfvarsPassen Sie die Werte an Ihre Organisation an. Erforderliche Variablen:
| Variable | Beschreibung |
|---|---|
owner_email |
In STACKIT registrierte E-Mail-Adresse des technischen Eigentümers |
company_name |
Unternehmensname für die Ordnerbenennung |
company_code |
Kurzes Präfix für Ressourcennamen (z. B. exc) |
organization_id |
ID des Root-Organisationscontainers |
tofu initWenn Sie den Block connectivity.vpn aktiviert haben, exportieren Sie zuerst die Pre-Shared Keys als Umgebungsvariable. Sie werden bewusst nicht in den tfvars gespeichert:
export TF_VAR_vpn_pre_shared_keys='{"onprem"={"tunnel1"="<20+ chars>","tunnel2"="<20+ chars>"}}'Note
Wenn Sie die mitgelieferte OPNsense-Firewall bereitstellen, folgen Sie anschließend unbedingt OPNsense-Firewall konfigurieren. Bis dahin filtert die Appliance nichts und ihre Web-GUI antwortet auf der öffentlichen IP.
Führen Sie in jedem Fall OpenTofu aus, um die Infrastruktur bereitzustellen:
tofu applyPrüfen Sie den Plan und bestätigen Sie mit yes.
Note
Falls Sie Ihre tfvars-Datei nicht mit dem Suffix .auto.tfvars kopiert haben, geben Sie sie ausdrücklich an: tofu apply -var-file ./config/<flavor>.tfvars
Nach dem ersten erfolgreichen Apply hat das Management-Modul einen S3-Bucket für Remote-State und ein Dienstkonto für die laufende Automatisierung erstellt. Migrieren Sie zu diesem Backend, um Zusammenarbeit im Team zu ermöglichen.
Entfernen Sie die Auskommentierung des Blocks backend "s3" in backend.tf und passen Sie den Namen bucket an die Terraform-Ausgabe management_bucket_name_tfstate an:
terraform {
backend "s3" {
bucket = "<MANAGEMENT_BUCKET_NAME_TFSTATE>"
endpoints = {
s3 = "https://object.storage.eu01.onstackit.cloud"
}
key = "terraform.tfstate"
region = "eu01"
skip_credentials_validation = true
skip_region_validation = true
skip_requesting_account_id = true
skip_s3_checksum = true
}
}Navigieren Sie im STACKIT Portal zum Management-Projekt → Secrets Manager → Secrets. Öffnen Sie das Secret mit dem Präfix object_storage_credentials_ und kopieren Sie die Werte ACCESS_KEY und SECRET_ACCESS_KEY.
Setzen Sie die S3-Backend-Zugangsdaten:
export AWS_ACCESS_KEY_ID=<ACCESS_KEY>
export AWS_SECRET_ACCESS_KEY=<SECRET_ACCESS_KEY>Important
Diese Werte müssen über Terminalsitzungen hinweg erhalten bleiben.
tofu init -migrate-stateBestätigen Sie die Migration, wenn Sie dazu aufgefordert werden.
Ersetzen Sie die Bootstrap-Zugangsdaten durch das vom Management-Modul erstellte Dienstkonto.
Navigieren Sie im STACKIT Portal zum Management-Projekt → Secrets Manager → Secrets. Öffnen Sie das Secret mit dem Präfix service_account_key_, kopieren Sie seinen Wert und speichern Sie ihn unter /home/<USER>/.stackit/credentials.json, wobei die Bootstrap-Zugangsdaten überschrieben werden.
Note
Verwenden Sie den absoluten Pfad – ~ funktioniert hier nicht.
Führen Sie einen Plan aus, um zu bestätigen, dass keine Änderungen erkannt werden:
tofu planDie Ausgabe sollte No changes. Your infrastructure matches the configuration. zeigen.
Note
Falls Sie Ihre tfvars-Datei nicht mit dem Suffix .auto.tfvars kopiert haben, geben Sie sie ausdrücklich an: tofu plan -var-file ./config/<flavor>.tfvars
Das vorübergehende Bootstrap-Projekt mit dem Dienstkonto wird nicht mehr benötigt:
stackit project delete --project-id <BOOTSTRAP_PROJECT_ID>Note
Resource-Manager-Ordner können erst 7 Tage nach dem Entfernen des letzten enthaltenen Projekts gelöscht werden. Ein tofu apply mit anschließendem tofu destroy schlägt daher fehl – Destroy meldet beim Löschen der Ordner einen Fehler, solange Projekte noch innerhalb ihrer Aufbewahrungsfrist liegen.
Schritt 9 startet die Appliance, lässt sie aber unkonfiguriert: Sie filtert nichts, und ihre Web-GUI antwortet auf der öffentlichen IP. Das Übertragen einer Richtlinie ist ein zweites Apply, da der API-Schlüssel aus der Appliance-Anmeldung abgeleitet wird und eine Provider-Konfiguration aufgelöst sein muss, bevor eine Ressource geplant wird. Ein während eines Apply erstellter Schlüssel kann den Provider daher nicht im selben Lauf konfigurieren.
Was die Richtlinie bewirkt und welche Verkehrsrichtungen sie tatsächlich sehen kann, steht unter Welcher Verkehr durch die Firewall fließt.
Note
Die Richtlinie wird mit dem Provider browningluke/opnsense übertragen. Er bildet das erweiterte Leseformat von OPNsense auf das Geschriebene zurück ab, sodass In-place-Updates und Drift-Erkennung funktionieren – der generische Provider Mastercard/restapi kann das nicht und macht Objekte faktisch nur einmal beschreibbar. Der Provider wird von der Community gepflegt und sein Autor rät vom Produktionseinsatz ab; berücksichtigen Sie dies, bevor Sie sich darauf verlassen.
1. Richtlinie aktivieren
Entfernen Sie die Auskommentierung des Blocks firewall_config in config/hub-and-spoke-firewall.tfvars. Er enthält Standardregeln: Internet-Egress mit NAT, Spoke-zu-Spoke auf HTTPS und ICMP beschränkt sowie die zwei Floating-Regeln, die die Web-GUI aus dem Internet nehmen.
Zwei Einträge benötigen Ihre Werte:
# Public: OpenTofu runs outside the Network Area* — a workstation, or a CI runner on the public internet. This is the normal case for a first deployment, because nothing is inside the area yet. Traffic goes over the appliance's public address:
endpoint = "https://<connectivity_firewall_public_ip>" # get it from running "tofu output connectivity_firewall_public_ip"
fw_management = {
content = ["10.0.0.0/16", "<your public address>/32"] # get it eg by running "curl -s https://ifconfig.me" or better use a fixed ip range
}
# Private: OpenTofu runs inside the Network Area* — a CI runner in a landing zone, a jumphost, or an established site-to-site VPN. Nothing to look up: the LAN address is the default, and your source address is already covered by `10.0.0.0/16`:
# omit endpoint
fw_management = {
content = ["10.0.0.0/16"]
}Warning
Das System, das OpenTofu ausführt, muss vor diesem Apply vom Alias fw_management abgedeckt sein. Andernfalls trennt derselbe Lauf, der die GUI schließt, seinen eigenen API-Zugriff; die Wiederherstellung erfolgt über die serielle Konsole (stackit server console <server-id> --project-id <connectivity-project-id>).
Eine dynamische Privat- oder Büroadresse ändert sich irgendwann und sperrt einen späteren Lauf aus.
2. API-Schlüssel bootstrappen, dann Richtlinie übertragen
tofu apply -var firewall_bootstrap=true && tofu apply -var firewall_bootstrap=trueDas erste tofu apply leitet den API-Schlüssel ab (und wartet dabei auf den Abschluss des mehrminütigen Appliance-Starts) und speichert ihn in src/.firewall-api-credentials.json, das von Git ignoriert wird. Das zweite tofu apply speichert ihn im Management-Secrets-Manager und überträgt Aliase, statische Routen, Regeln und NAT.
Zwei Läufe sind unvermeidbar: Der Provider benötigt den Schlüssel zur Plan-Zeit, und ein während eines Apply erstellter Wert kann keinen Provider im selben Lauf konfigurieren.
Die verwendete Appliance-Anmeldung stammt aus firewall_admin_password, standardmäßig dem im STACKIT-OPNsense-Image hinterlegten root-Passwort. Für eine neue Bereitstellung muss deshalb nichts exportiert werden.
Important
Ändern Sie das Passwort auf der Appliance (System → Access → Users). Das Passwort wird nur zur Ableitung des API-Schlüssels verwendet. Sobald der Schlüssel existiert, wird es überhaupt nicht mehr gelesen.
3. Bootstrap-Variable weglassen und Cache-Datei löschen
Ab jetzt ist jedes Apply ein einfaches tofu apply ohne Variablen:
rm src/.firewall-api-credentials.json
tofu applySchlüssel rotieren
Ein erneuter Bootstrap widerruft jeden vorhandenen API-Schlüssel auf der Appliance und erstellt einen neuen. Dadurch wird die Kopie im Secrets Manager sofort ungültig. Der Folgeschritt ist deshalb nicht optional: Erhöhen Sie firewall_api_secret_version um eins, damit der neue Schlüssel geschrieben wird. Ohne diese Erhöhung schlägt der Lauf mit 401 fehl, statt unbemerkt einen unbrauchbaren Schlüssel zu behalten.
rm -f src/.firewall-api-credentials.json
tofu apply -var firewall_bootstrap=true # mints the new key
# bump firewall_api_secret_version in your tfvars, then
tofu apply -var firewall_bootstrap=true # writes it to the Secrets Manager
rm src/.firewall-api-credentials.jsonEine einzelne Appliance ist die Standardroute jeder Corporate Landing Zone; ihr Ausfall nimmt daher die Plattform offline. Entfernen Sie die Auskommentierung des Blocks ha in connectivity.firewall, um eine zweite Appliance in einer anderen Availability Zone als aktives/passives CARP-Paar bereitzustellen:
ha = {
backup_zone = "eu01-1" # must differ from firewall.zone
}tofu apply erledigt anschließend den Rest. Es stellt das Backup bereit, meldet sich auf beiden Appliances an und schreibt deren knotenspezifische CARP-Einstellungen (Backup zuerst, Primary zuletzt, damit der Primary die Wahl gewinnt). Außerdem ergänzt es den Alias fw_cluster und die Regeln allow-fw-carp und allow-fw-pfsync in der Richtlinie – sie werden automatisch eingefügt, in den .tfvars ist nichts zu ergänzen.
Zwei Folgen sollten Sie vor der Aktivierung kennen:
- Die Landing-Zone-Routen ändern sich.
firewall_next_hop_ipwird zur virtuellen CARP-IP (.6vonlan_network_range) statt zur LAN-Adresse des Primary. Jede Corporate Landing Zone erhält deshalb im selben Apply eine umgeschriebene Standardroute. Rechnen Sie während der Routenaktualisierung mit einer kurzen Unterbrechung. - Die öffentliche IP führt kein Failover durch. STACKIT bindet eine öffentliche IP 1:1 an eine NIC. Egress vom Backup wird auf dessen eigene Adresse übersetzt. Eingehende Portweiterleitungen bleiben auf dem Primary, bis Sie DNS auf
tofu output connectivity_firewall_backup_public_ipumstellen. Langlebige ausgehende Verbindungen brechen für die Dauer eines Ausfalls ab; neue erholen sich innerhalb von Sekunden.
Was genau umschaltet und was gemessen wurde, steht unter Hochverfügbarkeit.
Important
Die Backup-Appliance startet mit demselben Image-Standardpasswort wie der Primary, und ihre Web-GUI antwortet auf ihrer eigenen öffentlichen IP, bis die Richtlinie übertragen ist. Die obige Aussperrwarnung gilt für beide Knoten.
Native Unterstützung für extensions.dns.gateway_api ist seit v0.109.0 im STACKIT-Terraform-Provider verfügbar und standardmäßig aktiviert, sobald die SKE-DNS-Erweiterung mindestens eine Zone hat. Deaktivieren Sie sie ausdrücklich, wenn der Cluster keine Gateway-API-Ressourcen verwendet:
platform_kubernetes = {
my-cluster = {
dns = {
enabled = true
gateway_api = false
}
# ...
}
}Mit dem Standard gateway_api = true konfiguriert die SKE-DNS-Erweiterung ExternalDNS automatisch für Gateway-API-Ressourcen (Gateway, HTTPRoute). Sie müssen DNS-Einträge oder LoadBalancer-Endpunkte nicht mehr manuell verwalten beziehungsweise ermitteln.
Note
Die SKE-DNS-Erweiterung installiert keine Gateway-API-CRDs. Die optionale Envoy-Gateway-Demo installiert sie automatisch. Installieren Sie für andere Gateway-API-Implementierungen kompatible CRDs separat. Sobald die CRDs verfügbar sind, wird ExternalDNS beim nächsten Cluster-Reconcile konfiguriert; ein zusätzliches OpenTofu-Apply ist nicht erforderlich.