Compare commits

..

No commits in common. "main" and "example/l7-alb-example" have entirely different histories.

68 changed files with 81 additions and 3196 deletions

View file

@ -1,4 +1,4 @@
name: "Default CI"
name: "Professional Services CI"
on:
push:
@ -17,23 +17,6 @@ jobs:
- name: TruffleHog Scan
uses: edplato/trufflehog-actions-scan@master
todo-check:
name: "Check for Open TODOs"
runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'stackit-ubuntu-22' }}
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: Search codebase
run: |
# Searches recursively (-r), showing line numbers (-n), ignoring binary files (-I)
# Excludes the .git directory to prevent false positives
if grep -rnIE "# ?TODO" --exclude-dir=.git --exclude-dir=.github .; then
echo "Error: TODOs found in the codebase. Please resolve them before merging."
exit 1
fi
echo "No TODOs found. Proceeding."
pre-commit-checks:
name: "Pre-Commit Hooks"
runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'stackit-ubuntu-22' }}

View file

@ -28,11 +28,11 @@ jobs:
- name: Push to Public Repo
run: |
echo "Setting up remote..."
git config --global user.name "ps-sync-bot"
git config --global user.email "ps-sync-bot@digits.schwarz"
git config --global user.name "prof-service-sync-bot"
git config --global user.email "prof-service-sync-bot@digits.schwarz"
# Add the GitHub remote using the SSH protocol
git remote add public git@github.com:stackitcloud/professional-service.git
git remote add public git@github.com:stackitcloud/professional-services.git
echo "Pushing main branch to GitHub..."
git push public main --force

View file

@ -1,41 +0,0 @@
# Project Governance: STACKIT Professional Service
This document defines the management, ownership, and maintenance processes for the STACKIT Professional Service repository.
## 1. Strategy & "The Story"
This repository serves as a bridge between internal excellence and public visibility.
- **Internal Git (Source of Truth):** The primary repository is hosted on our internal STACKIT Git instance. All internal communication, documentation, and chat links MUST point to the internal instance to promote our own infrastructure and tools.
- **GitHub (Public Mirror):** The GitHub repository is a mirror intended for external visibility, SEO, and accessibility for AI models (LLMs). It helps customers find our solutions and establishes STACKIT as a thought leader in cloud automation.
## 2. Ownership
### 2.1 Organizational Ownership
The repository is owned by the **STACKIT Professional Services** organization. High-level decisions regarding repository structure, licensing, and global policies are managed by the Core Maintainers team.
### 2.2 Example & Module Ownership
Individual examples or modules within the repository have specific owners, documented in their respective `MAINTAINERS.md` files.
- **Responsibility:** Owners are responsible for the technical health, periodic updates (e.g., dependency bumps), and community feedback for their specific content.
- **Handover:** If an owner leaves the project or company, ownership reverts to the Core Maintainers until a new owner is assigned.
## 3. Review & Quality Assurance
To ensure high standards and security, we follow a strict contribution process:
- **4-Eyes Principle:** No code enters the `main` branch without at least one successful Peer Review.
- **Automated Validation:** Every Pull Request must pass the CI pipeline, which includes:
- Linting and formatting checks.
- License header verification (Apache 2.0).
- Secret scanning (Trufflehog).
- **Best Effort Policy:** While we strive for quality, the content is provided "as-is." Use in production environments requires independent validation by the user.
## 4. Mirroring Process
The synchronization between the internal Git and GitHub is fully automated:
1. Changes are merged into the internal `main` branch.
2. A GitHub Action triggers on every push to `main`.

View file

@ -1,12 +1,12 @@
# STACKIT Professional Service
# STACKIT Professional Services
Welcome to the central repository for STACKIT examples, scripts, and boilerplate code!
Welcome to the central repository for STACKIT Professional Services examples, scripts, and boilerplate code!
> **⚠️ REPOSITORY MIRROR NOTICE**
>
> This GitHub repository is a **mirror**.
> The primary, internal source of truth for this codebase lives at:
> `https://professional-service.git.onstackit.cloud/professional-service-best-practices/professional-service`
> `https://professional-service.git.onstackit.cloud/professional-service-best-practices/professional-services`
>
> We automatically sync changes from our STACKIT managed GIT instance to this public GitHub repository.
>
@ -20,7 +20,7 @@ Let's be upfront about how this repository is maintained:
- **Strictly Best Effort:** Everything you find in this repository is provided on a "best effort" basis.
- **No Guarantees on Freshness:** We try our best to keep the examples, Terraform modules, and scripts up to date with the latest provider releases and API changes. However, **we cannot guarantee it**. Things move fast in the cloud, and some examples might become outdated over time.
- **Review Before Deploying:** Do not blindly copy-paste code from here directly into a production environment.
- **Use Your Brain:** Do not blindly copy-paste code from here directly into a production environment.
## Contents

View file

@ -1,107 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/helm" {
version = "3.1.1"
hashes = [
"h1:47CqNwkxctJtL/N/JuEj+8QMg8mRNI/NWeKO5/ydfZU=",
"h1:5b2ojWKT0noujHiweCds37ZreRFRQLNaErdJLusJN88=",
"zh:1a6d5ce931708aec29d1f3d9e360c2a0c35ba5a54d03eeaff0ce3ca597cd0275",
"zh:3411919ba2a5941801e677f0fea08bdd0ae22ba3c9ce3309f55554699e06524a",
"zh:81b36138b8f2320dc7f877b50f9e38f4bc614affe68de885d322629dd0d16a29",
"zh:95a2a0a497a6082ee06f95b38bd0f0d6924a65722892a856cfd914c0d117f104",
"zh:9d3e78c2d1bb46508b972210ad706dd8c8b106f8b206ecf096cd211c54f46990",
"zh:a79139abf687387a6efdbbb04289a0a8e7eaca2bd91cdc0ce68ea4f3286c2c34",
"zh:aaa8784be125fbd50c48d84d6e171d3fb6ef84a221dbc5165c067ce05faab4c8",
"zh:afecd301f469975c9d8f350cc482fe656e082b6ab0f677d1a816c3c615837cc1",
"zh:c54c22b18d48ff9053d899d178d9ffef7d9d19785d9bf310a07d648b7aac075b",
"zh:db2eefd55aea48e73384a555c72bac3f7d428e24147bedb64e1a039398e5b903",
"zh:ee61666a233533fd2be971091cecc01650561f1585783c381b6f6e8a390198a4",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}
provider "registry.terraform.io/hashicorp/kubernetes" {
version = "3.1.0"
constraints = ">= 2.14.0"
hashes = [
"h1:G9QqKNpcztBRqrywtlNylFJSpGzDfRFtO8hcWLdkvRY=",
"h1:oodIAuFMikXNmEtil5MQgP4dfSctUBYQiGJfjbsF3NY=",
"zh:0215c5c60be62028c09a2f22458e89cda3ef5830a632299f1d401eb3538874b0",
"zh:09ebb9f442431e278a310a9423f32caf467cb4b3cad3fe59573ca71fa7b14e20",
"zh:0c4e5912f83bb35846ae0a9ae54fc320706ee61894cd21cc6b4181b1c5a2fa5c",
"zh:1678c982853ad461e65ccb5e79d585e13ed109dd47dab2a66d3a7a304faeef65",
"zh:1c050a5c15e330457a9c18caacf61a923c59d663e13f2962e4b32f04fef523a0",
"zh:2c55bcec83be58ec132c7cb0a1ac644758b800d794fdc636d53a0eada0358a3a",
"zh:a062bb0aa316c08d8460c66a5d68da71da40de5d3bc3b31abcf3a1a9a19650f1",
"zh:a26fdea0afaa9b247c73c0b42843ca51ba7db0ac2571f9d3d50dcabd20ca1b98",
"zh:c872c9385a78d502bf5823d61cd3bb0f9a0585030e025eb12585c83451beeaa1",
"zh:f180879af931182beee4c8c0d9dab62b81d86f17ddcbe3786ef4c7cec9163a4e",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:f70f5789264069e0eef06f9b5d5fde955ef7206f7d446d1ce51a4c37a3f3e02f",
]
}
provider "registry.terraform.io/hashicorp/random" {
version = "3.8.1"
constraints = ">= 3.6.3"
hashes = [
"h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=",
"h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=",
"zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4",
"zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae",
"zh:229665ddf060aa0ed315597908483eee5b818a17d09b6417a0f52fd9405c4f57",
"zh:2469d2e48f28076254a2a3fc327f184914566d9e40c5780b8d96ebf7205f8bc0",
"zh:37d7eb334d9561f335e748280f5535a384a88675af9a9eac439d4cfd663bcb66",
"zh:741101426a2f2c52dee37122f0f4a2f2d6af6d852cb1db634480a86398fa3511",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:a902473f08ef8df62cfe6116bd6c157070a93f66622384300de235a533e9d4a9",
"zh:b85c511a23e57a2147355932b3b6dce2a11e856b941165793a0c3d7578d94d05",
"zh:c5172226d18eaac95b1daac80172287b69d4ce32750c82ad77fa0768be4ea4b8",
"zh:dab4434dba34aad569b0bc243c2d3f3ff86dd7740def373f2a49816bd2ff819b",
"zh:f49fd62aa8c5525a5c17abd51e27ca5e213881d58882fd42fec4a545b53c9699",
]
}
provider "registry.terraform.io/hashicorp/time" {
version = "0.13.1"
hashes = [
"h1:+W+DMrVoVnoXo3f3M4W+OpZbkCrUn6PnqDF33D2Cuf0=",
"h1:ZT5ppCNIModqk3iOkVt5my8b8yBHmDpl663JtXAIRqM=",
"zh:02cb9aab1002f0f2a94a4f85acec8893297dc75915f7404c165983f720a54b74",
"zh:04429b2b31a492d19e5ecf999b116d396dac0b24bba0d0fb19ecaefe193fdb8f",
"zh:26f8e51bb7c275c404ba6028c1b530312066009194db721a8427a7bc5cdbc83a",
"zh:772ff8dbdbef968651ab3ae76d04afd355c32f8a868d03244db3f8496e462690",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:898db5d2b6bd6ca5457dccb52eedbc7c5b1a71e4a4658381bcbb38cedbbda328",
"zh:8de913bf09a3fa7bedc29fec18c47c571d0c7a3d0644322c46f3aa648cf30cd8",
"zh:9402102c86a87bdfe7e501ffbb9c685c32bbcefcfcf897fd7d53df414c36877b",
"zh:b18b9bb1726bb8cfbefc0a29cf3657c82578001f514bcf4c079839b6776c47f0",
"zh:b9d31fdc4faecb909d7c5ce41d2479dd0536862a963df434be4b16e8e4edc94d",
"zh:c951e9f39cca3446c060bd63933ebb89cedde9523904813973fbc3d11863ba75",
"zh:e5b773c0d07e962291be0e9b413c7a22c044b8c7b58c76e8aa91d1659990dfb5",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.92.0"
constraints = ">= 0.87.0"
hashes = [
"h1:dE5sdzUaHkzVL8AW3+GXD2EEWX2PlS+sHT7F25SXcZ0=",
"h1:j26ncxqlAp4q0/NHFoiATuVdIg7KH0zZhWoSAd+4Yj0=",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:5eaa713f68a004ec33697f510ca4c7722940e2bab8080c025822ca547325ef98",
"zh:60ed4496492b9781f7cc581e346222a6356538a527e4ac67dce6815a64fc5c66",
"zh:6834a7819429e3482a5fdd547c442cc032d7047c3fb0dee30e8babb2438598e1",
"zh:6de632db0cbb42b429a9e752078df37716b0f335e5c39e883be5c55f7f1da553",
"zh:ac8b1bc8212236aaab789cef1dce718e6b8394bcf4b5f6c6f8dabf8c8a213573",
"zh:af4b1e805d6082a3ec94d2f5b68e8a62f04205af3f75a4a7d1b167e0f027d9ec",
"zh:b709258a4cd3acd0a9426809c1d7c1ed25859010b566c1b29481b132a7e2af13",
"zh:c7e8c5e8f2ca8c14c1bf5c92716a761b67792b38046b99653bdbf9ca423fc675",
"zh:c7f47c6b7e33d1f28bdc8d1aa5fda2734d74d6b1b0c6ef8b258489d9405af231",
"zh:d57dc6ad6b3a2879aa47012faf82f597a2ca1c3de1561bb96c6191e65072ea95",
"zh:d5b18390104164477913ced864e7a1cd5a678490f9412be887e5d8e3961d242e",
"zh:ead616306ab18c30a4c1110ad7fa8aee7d8a99e4410ceecbe5875beac5724f8a",
"zh:f73ad70183a35e5d04e4b48c44654c76fec48a8f4c913dd31a5befc2a1c2e4dc",
]
}

View file

@ -1,55 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This file defines the required Terraform providers and their configurations.
# It sets up the STACKIT, Kubernetes, and Helm providers to manage resources in the project and the SKE cluster.
terraform {
required_version = ">= 0.14.0"
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">= 0.87.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.6.3"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = ">=2.14.0"
}
}
}
provider "stackit" {
default_region = var.stackit_region
service_account_key_path = var.stackit_service_account_key_path
experiments = ["iam"]
}
provider "kubernetes" {
host = yamldecode(stackit_ske_kubeconfig.this.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.this.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.this.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.this.kube_config).clusters.0.cluster.certificate-authority-data)
}
provider "helm" {
kubernetes = {
host = yamldecode(stackit_ske_kubeconfig.this.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.this.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.this.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.this.kube_config).clusters.0.cluster.certificate-authority-data)
}
}

View file

@ -1,33 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
variable "stackit_project_id" {
type = string
default = "d75e6aab-b616-4b42-ae3b-aaf161ad626d"
}
variable "stackit_region" {
type = string
default = "eu01"
}
variable "stackit_service_account_key_path" {
type = string
default = "../../keys/stackit-sa.json"
}
resource "stackit_key_pair" "admin_keypair" {
name = "admin-keypair-12345"
public_key = chomp(file("~/.ssh/id_rsa.pub"))
}

View file

@ -1,67 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
resource "stackit_ske_kubeconfig" "this" {
project_id = var.stackit_project_id
cluster_name = stackit_ske_cluster.this.name
refresh = true
depends_on = [stackit_ske_cluster.this]
}
data "stackit_ske_kubernetes_versions" "this" {
version_state = "SUPPORTED"
}
data "stackit_ske_machine_image_versions" "this" {
version_state = "SUPPORTED"
}
locals {
flatcar_supported_version = one(flatten([
for mi in data.stackit_ske_machine_image_versions.this.machine_images : [
for v in mi.versions :
v.version
if mi.name == "flatcar"
]
]))
}
resource "stackit_ske_cluster" "this" {
project_id = var.stackit_project_id
name = "dbaas-otel"
kubernetes_version_min = data.stackit_ske_kubernetes_versions.this.kubernetes_versions.0.version
maintenance = {
enable_kubernetes_version_updates = true
enable_machine_image_version_updates = true
start = "01:00:00Z"
end = "02:00:00Z"
}
node_pools = [
{
name = "standard"
machine_type = "g2i.4"
minimum = "3"
maximum = "9"
max_surge = "3"
availability_zones = ["eu01-1", "eu01-2", "eu01-3"]
os_version_min = local.flatcar_supported_version
os_name = "flatcar"
volume_size = 150
volume_type = "storage_premium_perf6"
},
]
}

View file

@ -1,20 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
resource "stackit_observability_instance" "example" {
project_id = var.stackit_project_id
name = "example-obs"
plan_name = "Observability-Large-EU01"
alert_config = null
}

View file

@ -1,44 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
resource "stackit_postgresflex_instance" "this" {
project_id = var.stackit_project_id
name = "example-instance"
backup_schedule = "00 00 * * *"
flavor = {
cpu = 2
ram = 4
}
replicas = 3
storage = {
class = "premium-perf2-stackit"
size = 15
}
version = 15
acl = ["0.0.0.0/0"]
}
resource "stackit_postgresflex_user" "this" {
project_id = var.stackit_project_id
instance_id = stackit_postgresflex_instance.this.instance_id
username = "test"
roles = ["createdb", "login"]
}
resource "stackit_postgresflex_database" "this" {
project_id = var.stackit_project_id
instance_id = stackit_postgresflex_instance.this.instance_id
name = "test"
owner = stackit_postgresflex_user.this.username
}

View file

@ -1,38 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
resource "stackit_service_account" "this" {
name = "prom-proxy"
project_id = var.stackit_project_id
}
resource "time_rotating" "rotate" {
rotation_days = 150
}
resource "stackit_service_account_key" "this" {
project_id = var.stackit_project_id
service_account_email = stackit_service_account.this.email
ttl_days = 180
rotate_when_changed = {
rotation = time_rotating.rotate.id
}
}
resource "stackit_authorization_project_role_assignment" "this" {
resource_id = var.stackit_project_id
role = "prometheus-proxy.reader"
subject = stackit_service_account.this.email
}

View file

@ -1,65 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
locals {
sa_json = jsondecode(stackit_service_account_key.this.json)
otel_helm_values = templatefile("${path.module}/helm-values/otel-collector-values.tftpl", {
stackit_project_id = var.stackit_project_id
stackit_region = var.stackit_region
stackit_postgres_instance_id = stackit_postgresflex_instance.this.instance_id
observability_metrics_endpoint = stackit_observability_instance.example.metrics_push_url
secret_name = kubernetes_secret.otel_secret.metadata[0].name
sa_client_id = local.sa_json.credentials.sub
sa_issuer = local.sa_json.credentials.iss
sa_key_id = local.sa_json.credentials.kid
})
}
resource "stackit_observability_credential" "otel" {
project_id = var.stackit_project_id
instance_id = stackit_observability_instance.example.instance_id
}
resource "kubernetes_namespace" "monitoring" {
metadata {
name = "monitoring"
}
}
resource "kubernetes_secret" "otel_secret" {
metadata {
name = "otel-secrets"
namespace = kubernetes_namespace.monitoring.metadata[0].name
}
data = {
OBSERVABILITY_AUTHORIZATION_HEADER = "Basic ${base64encode("${stackit_observability_credential.otel.username}:${stackit_observability_credential.otel.password}")}"
JSON = stackit_service_account_key.this.json
PRIVATE_KEY = jsondecode(stackit_service_account_key.this.json).credentials.privateKey
}
}
resource "helm_release" "opentelemetry_collector" {
name = "opentelemetry-collector"
repository = "https://open-telemetry.github.io/opentelemetry-helm-charts"
chart = "opentelemetry-collector"
version = "0.152.0"
namespace = kubernetes_namespace.monitoring.metadata[0].name
timeout = 30
values = [
local.otel_helm_values
]
}

View file

@ -1,9 +0,0 @@
# Maintainers
General maintainers:
- Mauritz Uphoff (Mauritz.Uphoff@digits.schwarz)
This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis.
For questions, issues, or feature requests, please email general maintainers.
Please include the BP name and version in your request. We will track your request as an issue.

View file

@ -1,39 +0,0 @@
# DBaaS OpenTelemetry Metrics Collection
Collect metrics from STACKIT PostgreSQL Flex and MongoDB instances using OpenTelemetry (OTel) and export them to STACKIT Observability.
## Prerequisites
- STACKIT Project ID and Service Account key.
- Terraform, `kubectl`, and `helm` installed.
## Usage
1. **Configure**: Update `stackit_project_id` and `stackit_service_account_key_path` in `01-variables.tf`.
2. **Deploy**:
```bash
terraform init
terraform apply
```
## Scrape Configuration
The OTel Collector scrapes metrics from:
- **PostgreSQL**: `https://postgres-prom-proxy.api.stackit.cloud/v2/...`
- **MongoDB**: `https://mongodb-prom-proxy.api.stackit.cloud/v2/...`
_Note: MSSQL is not supported._
## Debugging
View live scrape data in the collector logs:
```bash
kubectl logs -l app.kubernetes.io/name=otel-collector -n monitoring -f
```
## Documentation
- [PostgreSQL Flex Metrics](https://docs.stackit.cloud/products/databases/postgresql-flex/reference/observability-metrics-in-postgresql-flex/)
- [MongoDB Flex Metrics](https://docs.stackit.cloud/products/databases/mongodb-flex/reference/observability-metrics/)

View file

@ -1,79 +0,0 @@
fullnameOverride: otel-collector
mode: deployment
podAnnotations:
stackit-sa-key-id: "${sa_key_id}"
image:
repository: "otel/opentelemetry-collector-contrib"
config:
receivers:
prometheus:
config:
scrape_configs:
- job_name: stackit-postgres
metrics_path: /v2/projects/$${STACKIT_PROJECT_ID}/regions/$${STACKIT_REGION}/instances/$${STACKIT_POSTGRES_INSTANCE_ID}/metrics
oauth2:
audience: $${SA_TOKEN_REQUEST_AUDIENCE}
client_certificate_key_file: /mnt/secrets-store/private-key
client_certificate_key_id: $${SA_TOKEN_REQUEST_CLIENT_CERTIFICATE_KEY_ID}
client_id: $${SA_TOKEN_REQUEST_CLIENT_ID}
grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer
iss: $${SA_TOKEN_REQUEST_ISSUER}
signature_algorithm: RS512
token_url: https://service-account.api.stackit.cloud/token
scheme: https
scrape_interval: 1m
static_configs:
- targets:
- postgres-prom-proxy.api.stackit.cloud:443
exporters:
debug:
verbosity: normal
prometheusremotewrite:
endpoint: $${OBSERVABILITY_METRICS_ENDPOINT}
headers:
Authorization: $${OBSERVABILITY_AUTHORIZATION_HEADER}
service:
pipelines:
metrics:
receivers: [prometheus]
exporters: [prometheusremotewrite, debug]
extraEnvs:
- name: STACKIT_PROJECT_ID
value: "${stackit_project_id}"
- name: STACKIT_REGION
value: "${stackit_region}"
- name: STACKIT_POSTGRES_INSTANCE_ID
value: "${stackit_postgres_instance_id}"
- name: OBSERVABILITY_METRICS_ENDPOINT
value: "${observability_metrics_endpoint}"
- name: OBSERVABILITY_AUTHORIZATION_HEADER
valueFrom:
secretKeyRef:
name: ${secret_name}
key: OBSERVABILITY_AUTHORIZATION_HEADER
- name: SA_TOKEN_REQUEST_CLIENT_ID
value: "${sa_client_id}"
- name: SA_TOKEN_REQUEST_ISSUER
value: "${sa_issuer}"
- name: SA_TOKEN_REQUEST_CLIENT_CERTIFICATE_KEY_ID
value: "${sa_key_id}"
- name: SA_TOKEN_REQUEST_AUDIENCE
value: "https://service-account.api.stackit.cloud/token"
extraVolumes:
- name: otel-secrets
secret:
secretName: ${secret_name}
items:
- key: PRIVATE_KEY
path: private-key
extraVolumeMounts:
- name: otel-secrets
mountPath: /mnt/secrets-store
readOnly: true

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/random" {
version = "3.8.1"
constraints = ">= 3.6.3"
hashes = [
"h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=",
"h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=",
"zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4",
"zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae",
@ -27,7 +26,6 @@ provider "registry.terraform.io/stackitcloud/stackit" {
constraints = ">= 0.87.0"
hashes = [
"h1:8de9n+Roq6Z2Ltp9poBBBN9a4zSpx73VLpgFS5mTyoI=",
"h1:RStdHSDwbtonYfg7mR5Y92v6fxIVX9FEz0UN+tm9kHI=",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:0ed12db90276ccd2d6f87135b7dd078657823c3ca33121c6a157d0bdf08f801e",
"zh:160b32bcf1d01666784cf8469e10e0a38d4c3d24c80c0c5be470cc63ef27ea62",

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/random" {
version = "3.8.1"
constraints = ">= 3.6.3"
hashes = [
"h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=",
"h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=",
"zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4",
"zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae",
@ -25,7 +24,6 @@ provider "registry.terraform.io/hashicorp/random" {
provider "registry.terraform.io/hashicorp/tls" {
version = "4.2.1"
hashes = [
"h1:F5d6bQY8UlBo0D71Sv7CsV+3aZOFz0yeNF+vufog7h4=",
"h1:akFNuHwvrtnYMBofieoeXhPJDhYZzJVu/Q/BgZK2fgg=",
"zh:0d1e7d07ac973b97fa228f46596c800de830820506ee145626f079dd6bbf8d8a",
"zh:5c7e3d4348cb4861ab812973ef493814a4b224bdd3e9d534a7c8a7c992382b86",
@ -44,9 +42,8 @@ provider "registry.terraform.io/hashicorp/tls" {
provider "registry.terraform.io/mastercard/restapi" {
version = "3.0.0"
constraints = ">= 3.0.0"
constraints = "3.0.0"
hashes = [
"h1:Fqxoc6bsydl6iWGx6ZvyqUDdGt7Cb4sW/BSHhBeHGgw=",
"h1:y1I3azDHOqRySTyDHsb3Xh1waP/99KfykZRagbRx1qI=",
"zh:0b63bd3c25a31f090a41933f90b7dd6e984add1c4261d8f5caa73f4d5aa065a4",
"zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7",
@ -71,7 +68,6 @@ provider "registry.terraform.io/stackitcloud/stackit" {
constraints = ">= 0.87.0"
hashes = [
"h1:8de9n+Roq6Z2Ltp9poBBBN9a4zSpx73VLpgFS5mTyoI=",
"h1:RStdHSDwbtonYfg7mR5Y92v6fxIVX9FEz0UN+tm9kHI=",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:0ed12db90276ccd2d6f87135b7dd078657823c3ca33121c6a157d0bdf08f801e",
"zh:160b32bcf1d01666784cf8469e10e0a38d4c3d24c80c0c5be470cc63ef27ea62",

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/random" {
version = "3.8.1"
constraints = ">= 3.6.3"
hashes = [
"h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=",
"h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=",
"zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4",
"zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae",
@ -26,7 +25,6 @@ provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.90.0"
constraints = ">= 0.87.0"
hashes = [
"h1:QgP6TOtucJ3A6fA51rdUvxhYGjl9RrWvXQZpjHTOuiU=",
"h1:W29Kv6XUxYssF2Gy8KcmTx3EFstt6k8sKgPRIBbq+qs=",
"zh:003af58a84884558bbb2fc40fcbefa6774ec20aa9e4b97cf3f950190a600afd2",
"zh:026ee9cef4670cf33369f8654c6b9b1d8c0e116ceb0b353c882be222951ecdd4",

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.80.0"
constraints = "0.80.0"
hashes = [
"h1:VqmLlSV9sMOX7aq5Bnsj18KNKCUPFahZzf0SA5fTkVk=",
"h1:wz7uGwzVoo1NO18CDLcfjLraTSiWQ5EzJnDeCKcFi60=",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:3a0e6cb125ef76a24b2b5ff9c786c57058f385571d283bd68f633225fcca695a",

View file

@ -8,7 +8,7 @@
# default password in production.
#
# Generate a SHA-512 hash on Linux/macOS:
# openssl passwd -6 "YourPassword"
# python3 -c "import crypt; print(crypt.crypt('YourPassword', crypt.mksalt(crypt.METHOD_SHA512)))"
# ---------------------------------------------------------------------------
users:
- name: admin-user

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/random" {
version = "3.6.3"
constraints = "3.6.3"
hashes = [
"h1:Fnaec9vA8sZ8BXVlN3Xn9Jz3zghSETIKg7ch8oXhxno=",
"h1:zG9uFP8l9u+yGZZvi5Te7PV62j50azpgwPunq2vTm1E=",
"zh:04ceb65210251339f07cd4611885d242cd4d0c7306e86dda9785396807c00451",
"zh:448f56199f3e99ff75d5c0afacae867ee795e4dfda6cb5f8e3b2a72ec3583dd8",
@ -26,7 +25,6 @@ provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.90.0"
constraints = ">= 0.66.0"
hashes = [
"h1:QgP6TOtucJ3A6fA51rdUvxhYGjl9RrWvXQZpjHTOuiU=",
"h1:W29Kv6XUxYssF2Gy8KcmTx3EFstt6k8sKgPRIBbq+qs=",
"zh:003af58a84884558bbb2fc40fcbefa6774ec20aa9e4b97cf3f950190a600afd2",
"zh:026ee9cef4670cf33369f8654c6b9b1d8c0e116ceb0b353c882be222951ecdd4",

View file

@ -2,6 +2,4 @@
## Overview
> ⚠️ Two levels of folders must be enabled via a support ticket. By default, only one level is possible.
This repository demonstrates code to generate nested folders within a project.

View file

@ -1,47 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/aws" {
version = "5.100.0"
constraints = "~> 5.0"
hashes = [
"h1:edXOJWE4ORX8Fm+dpVpICzMZJat4AX0VRCAy/xkcOc0=",
"zh:054b8dd49f0549c9a7cc27d159e45327b7b65cf404da5e5a20da154b90b8a644",
"zh:0b97bf8d5e03d15d83cc40b0530a1f84b459354939ba6f135a0086c20ebbe6b2",
"zh:1589a2266af699cbd5d80737a0fe02e54ec9cf2ca54e7e00ac51c7359056f274",
"zh:6330766f1d85f01ae6ea90d1b214b8b74cc8c1badc4696b165b36ddd4cc15f7b",
"zh:7c8c2e30d8e55291b86fcb64bdf6c25489d538688545eb48fd74ad622e5d3862",
"zh:99b1003bd9bd32ee323544da897148f46a527f622dc3971af63ea3e251596342",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:9f8b909d3ec50ade83c8062290378b1ec553edef6a447c56dadc01a99f4eaa93",
"zh:aaef921ff9aabaf8b1869a86d692ebd24fbd4e12c21205034bb679b9caf883a2",
"zh:ac882313207aba00dd5a76dbd572a0ddc818bb9cbf5c9d61b28fe30efaec951e",
"zh:bb64e8aff37becab373a1a0cc1080990785304141af42ed6aa3dd4913b000421",
"zh:dfe495f6621df5540d9c92ad40b8067376350b005c637ea6efac5dc15028add4",
"zh:f0ddf0eaf052766cfe09dea8200a946519f653c384ab4336e2a4a64fdd6310e9",
"zh:f1b7e684f4c7ae1eed272b6de7d2049bb87a0275cb04dbb7cda6636f600699c9",
"zh:ff461571e3f233699bf690db319dfe46aec75e58726636a0d97dd9ac6e32fb70",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.94.0"
constraints = "> 0.90.0"
hashes = [
"h1:ikFzd4yeJ1LR8ojP2PsZwiK2ZLhxBjRXkEg2HJrI07U=",
"zh:06c8da7d8a048216e825fa7d1e45949c1bda2a5f53f9bb0556b83b6610703fe6",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:19e82636cfd52a65105e0cf030bc8a0c815082818ef953b84f9b1e349a87318c",
"zh:24af9b7d2f1bb38f480b1aa8cf5e4ecf483bd4403642a9e8a5accbe1ae212feb",
"zh:3b10850e9242bcd00c519ff4140130e8443002fd60b6dff90983e7cb1973b2c3",
"zh:54837a0fa4ddbcf0b8407718f8823b831322deba3bd7ec8492e4578928f50633",
"zh:5cfd6a6b1ca73826a03f8746ef84a5c4059648bc49abf8056c8e0f9b87800a23",
"zh:6ab3bcfef6ff65b4ce76d333b4ad99e5f91991fcf5bddbe1958aadde6ee05eab",
"zh:81b96dc29b055f15e475d8bc32482617a582785949b3c02f44ef15d19951f69c",
"zh:85f478c2fcf10219263462d0f06b5cc41603b1edad813c336e100b3e0a55bfe8",
"zh:9adbb7655fddfe4d4081746d0d7e39c3e8fbf8aa3d8b7d3b5164f30c16a6bd93",
"zh:9c24b39e788283ead8a8ce1f013a47562ff0dc1ccb642a8e18644cbdcda0f1c4",
"zh:a425f28d6a5f6f024cab56c848c55025e84a09db946f1b00a2655d9567251cea",
"zh:f28aa62d2f06e08fe6d18ef9103a8164aa9278540779bebd61120f810c603c6b",
]
}

View file

@ -1,44 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/vault" {
version = "5.9.0"
constraints = "5.9.0"
hashes = [
"h1:8wcXxEMo7XvCnrtZHSpAuWmRfYiZkWn2tssshB1BDzo=",
"zh:16e23a37c0965938544af282a7bc13dabca445f462ab27829f98e936ace4d263",
"zh:249fcf9da1a690fe9aa44a7421fad89a425afb0c2ce7eaf306d75daddd691af5",
"zh:3d92af386049a229a428f21b938a22df61703447c8ceed65c73f111a64e627d2",
"zh:4033fedf9d4f54f0aacf7c4a79e20978bcd67c0a8ab9411acd447db1469108a4",
"zh:51c78d0dc378037bbaf3cd26ff29fae7c40d7b134b40d059b982257987c15f9f",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:86e414b7327343de676ec506d30c557a514dbd992b27a2670466adaf9ed69718",
"zh:879c3a61ed8d183a68ddb590e63a7e0d6aab8d8044fd4a13658e7b1661395a9d",
"zh:8d548617543ee2ce0340972a5df93e7ac37b7895d4bf506bd587f8daac58e6d6",
"zh:8d75b3bbfd9a536c8c1d84504cb3d1c8e1a3fd30e377a51a6311476632363103",
"zh:922f625a36642c49daa432e07c12e72ff75025e0b9afda8d7240f38c6789fe46",
"zh:fbceae685b395acaff6c820ed7d7eaa6250ef4769e04481145dc50e09b89db2f",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.94.0"
constraints = ">= 0.94.0"
hashes = [
"h1:ikFzd4yeJ1LR8ojP2PsZwiK2ZLhxBjRXkEg2HJrI07U=",
"zh:06c8da7d8a048216e825fa7d1e45949c1bda2a5f53f9bb0556b83b6610703fe6",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:19e82636cfd52a65105e0cf030bc8a0c815082818ef953b84f9b1e349a87318c",
"zh:24af9b7d2f1bb38f480b1aa8cf5e4ecf483bd4403642a9e8a5accbe1ae212feb",
"zh:3b10850e9242bcd00c519ff4140130e8443002fd60b6dff90983e7cb1973b2c3",
"zh:54837a0fa4ddbcf0b8407718f8823b831322deba3bd7ec8492e4578928f50633",
"zh:5cfd6a6b1ca73826a03f8746ef84a5c4059648bc49abf8056c8e0f9b87800a23",
"zh:6ab3bcfef6ff65b4ce76d333b4ad99e5f91991fcf5bddbe1958aadde6ee05eab",
"zh:81b96dc29b055f15e475d8bc32482617a582785949b3c02f44ef15d19951f69c",
"zh:85f478c2fcf10219263462d0f06b5cc41603b1edad813c336e100b3e0a55bfe8",
"zh:9adbb7655fddfe4d4081746d0d7e39c3e8fbf8aa3d8b7d3b5164f30c16a6bd93",
"zh:9c24b39e788283ead8a8ce1f013a47562ff0dc1ccb642a8e18644cbdcda0f1c4",
"zh:a425f28d6a5f6f024cab56c848c55025e84a09db946f1b00a2655d9567251cea",
"zh:f28aa62d2f06e08fe6d18ef9103a8164aa9278540779bebd61120f810c603c6b",
]
}

View file

@ -12,6 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
provider "stackit" {
default_region = "eu01"
service_account_key_path = ""
}
resource "stackit_secretsmanager_instance" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example-instance"
@ -24,6 +29,16 @@ resource "stackit_secretsmanager_user" "example" {
write_enabled = true
}
provider "vault" {
address = "https://prod.sm.eu01.stackit.cloud"
skip_child_token = true
auth_login_userpass {
username = stackit_secretsmanager_user.example.username
password = stackit_secretsmanager_user.example.password
}
}
resource "stackit_observability_instance" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example-instance"

View file

@ -1,41 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">= 0.94.0"
}
vault = {
source = "hashicorp/vault"
version = "5.9.0"
}
}
}
provider "stackit" {
default_region = "eu01"
service_account_key_path = ""
}
provider "vault" {
address = "https://prod.sm.eu01.stackit.cloud"
skip_child_token = true
auth_login_userpass {
username = stackit_secretsmanager_user.example.username
password = stackit_secretsmanager_user.example.password
}
}

View file

@ -1,44 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/kubernetes" {
version = "3.1.0"
constraints = ">= 3.1.0"
hashes = [
"h1:oodIAuFMikXNmEtil5MQgP4dfSctUBYQiGJfjbsF3NY=",
"zh:0215c5c60be62028c09a2f22458e89cda3ef5830a632299f1d401eb3538874b0",
"zh:09ebb9f442431e278a310a9423f32caf467cb4b3cad3fe59573ca71fa7b14e20",
"zh:0c4e5912f83bb35846ae0a9ae54fc320706ee61894cd21cc6b4181b1c5a2fa5c",
"zh:1678c982853ad461e65ccb5e79d585e13ed109dd47dab2a66d3a7a304faeef65",
"zh:1c050a5c15e330457a9c18caacf61a923c59d663e13f2962e4b32f04fef523a0",
"zh:2c55bcec83be58ec132c7cb0a1ac644758b800d794fdc636d53a0eada0358a3a",
"zh:a062bb0aa316c08d8460c66a5d68da71da40de5d3bc3b31abcf3a1a9a19650f1",
"zh:a26fdea0afaa9b247c73c0b42843ca51ba7db0ac2571f9d3d50dcabd20ca1b98",
"zh:c872c9385a78d502bf5823d61cd3bb0f9a0585030e025eb12585c83451beeaa1",
"zh:f180879af931182beee4c8c0d9dab62b81d86f17ddcbe3786ef4c7cec9163a4e",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:f70f5789264069e0eef06f9b5d5fde955ef7206f7d446d1ce51a4c37a3f3e02f",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.94.0"
constraints = ">= 0.94.0"
hashes = [
"h1:ikFzd4yeJ1LR8ojP2PsZwiK2ZLhxBjRXkEg2HJrI07U=",
"zh:06c8da7d8a048216e825fa7d1e45949c1bda2a5f53f9bb0556b83b6610703fe6",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:19e82636cfd52a65105e0cf030bc8a0c815082818ef953b84f9b1e349a87318c",
"zh:24af9b7d2f1bb38f480b1aa8cf5e4ecf483bd4403642a9e8a5accbe1ae212feb",
"zh:3b10850e9242bcd00c519ff4140130e8443002fd60b6dff90983e7cb1973b2c3",
"zh:54837a0fa4ddbcf0b8407718f8823b831322deba3bd7ec8492e4578928f50633",
"zh:5cfd6a6b1ca73826a03f8746ef84a5c4059648bc49abf8056c8e0f9b87800a23",
"zh:6ab3bcfef6ff65b4ce76d333b4ad99e5f91991fcf5bddbe1958aadde6ee05eab",
"zh:81b96dc29b055f15e475d8bc32482617a582785949b3c02f44ef15d19951f69c",
"zh:85f478c2fcf10219263462d0f06b5cc41603b1edad813c336e100b3e0a55bfe8",
"zh:9adbb7655fddfe4d4081746d0d7e39c3e8fbf8aa3d8b7d3b5164f30c16a6bd93",
"zh:9c24b39e788283ead8a8ce1f013a47562ff0dc1ccb642a8e18644cbdcda0f1c4",
"zh:a425f28d6a5f6f024cab56c848c55025e84a09db946f1b00a2655d9567251cea",
"zh:f28aa62d2f06e08fe6d18ef9103a8164aa9278540779bebd61120f810c603c6b",
]
}

View file

@ -12,6 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
provider "stackit" {
default_region = "eu01"
service_account_key_path = ""
}
provider "kubernetes" {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
resource "stackit_ske_cluster" "default" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "ske-enc-vol"

View file

@ -1,38 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">= 0.94.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 3.1.0"
}
}
}
provider "stackit" {
default_region = "eu01"
service_account_key_path = ""
}
provider "kubernetes" {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/helm" {
version = "2.17.0"
constraints = "2.17.0"
hashes = [
"h1:K5FEjxvDnxb1JF1kG1xr8J3pNGxoaR3Z0IBG9Csm/Is=",
"h1:kQMkcPVvHOguOqnxoEU2sm1ND9vCHiT8TvZ2x6v/Rsw=",
"zh:06fb4e9932f0afc1904d2279e6e99353c2ddac0d765305ce90519af410706bd4",
"zh:104eccfc781fc868da3c7fec4385ad14ed183eb985c96331a1a937ac79c2d1a7",
@ -27,7 +26,6 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
constraints = ">= 2.25.2"
hashes = [
"h1:P0c8knzZnouTNFIRij8IS7+pqd0OKaFDYX0j4GRsiqo=",
"h1:vyHdH0p6bf9xp1NPePObAJkXTJb/I09FQQmmevTzZe0=",
"zh:02d55b0b2238fd17ffa12d5464593864e80f402b90b31f6e1bd02249b9727281",
"zh:20b93a51bfeed82682b3c12f09bac3031f5bdb4977c47c97a042e4df4fb2f9ba",
"zh:6e14486ecfaee38c09ccf33d4fdaf791409f90795c1b66e026c226fad8bc03c7",
@ -47,7 +45,6 @@ provider "registry.terraform.io/hashicorp/random" {
version = "3.7.2"
constraints = "3.7.2"
hashes = [
"h1:356j/3XnXEKr9nyicLUufzoF4Yr6hRy481KIxRVpK0c=",
"h1:KG4NuIBl1mRWU0KD/BGfCi1YN/j3F7H4YgeeM7iSdNs=",
"zh:14829603a32e4bc4d05062f059e545a91e27ff033756b48afbae6b3c835f508f",
"zh:1527fb07d9fea400d70e9e6eb4a2b918d5060d604749b6f1c361518e7da546dc",
@ -67,7 +64,6 @@ provider "registry.terraform.io/hashicorp/random" {
provider "registry.terraform.io/hashicorp/vault" {
version = "5.8.0"
hashes = [
"h1:eSJgYoJoVMce2xjJJCeAZnJELsC4RoqaotD0fgfn6dw=",
"h1:gk1cR+x1D+TEz05MKWmpp0p06+Trob5cN0eYU1vZGJs=",
"zh:18e79b42c8c155a5c541a45d54a6ccdeab23c404c239acdeed336a17cbfc2fd4",
"zh:241f50d1ea40030578034b4440e41676f1c9b5e8a2be5cd3afdb6e387914e0bf",
@ -88,7 +84,6 @@ provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.90.0"
constraints = ">= 0.66.0"
hashes = [
"h1:QgP6TOtucJ3A6fA51rdUvxhYGjl9RrWvXQZpjHTOuiU=",
"h1:W29Kv6XUxYssF2Gy8KcmTx3EFstt6k8sKgPRIBbq+qs=",
"zh:003af58a84884558bbb2fc40fcbefa6774ec20aa9e4b97cf3f950190a600afd2",
"zh:026ee9cef4670cf33369f8654c6b9b1d8c0e116ceb0b353c882be222951ecdd4",

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/helm" {
version = "3.1.1"
hashes = [
"h1:47CqNwkxctJtL/N/JuEj+8QMg8mRNI/NWeKO5/ydfZU=",
"h1:5b2ojWKT0noujHiweCds37ZreRFRQLNaErdJLusJN88=",
"zh:1a6d5ce931708aec29d1f3d9e360c2a0c35ba5a54d03eeaff0ce3ca597cd0275",
"zh:3411919ba2a5941801e677f0fea08bdd0ae22ba3c9ce3309f55554699e06524a",
"zh:81b36138b8f2320dc7f877b50f9e38f4bc614affe68de885d322629dd0d16a29",
@ -26,7 +25,6 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
constraints = ">= 2.14.0"
hashes = [
"h1:P0c8knzZnouTNFIRij8IS7+pqd0OKaFDYX0j4GRsiqo=",
"h1:vyHdH0p6bf9xp1NPePObAJkXTJb/I09FQQmmevTzZe0=",
"zh:02d55b0b2238fd17ffa12d5464593864e80f402b90b31f6e1bd02249b9727281",
"zh:20b93a51bfeed82682b3c12f09bac3031f5bdb4977c47c97a042e4df4fb2f9ba",
"zh:6e14486ecfaee38c09ccf33d4fdaf791409f90795c1b66e026c226fad8bc03c7",
@ -44,10 +42,9 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.91.0"
constraints = ">= 0.60.0"
constraints = "> 0.60.0"
hashes = [
"h1:8de9n+Roq6Z2Ltp9poBBBN9a4zSpx73VLpgFS5mTyoI=",
"h1:RStdHSDwbtonYfg7mR5Y92v6fxIVX9FEz0UN+tm9kHI=",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:0ed12db90276ccd2d6f87135b7dd078657823c3ca33121c6a157d0bdf08f801e",
"zh:160b32bcf1d01666784cf8469e10e0a38d4c3d24c80c0c5be470cc63ef27ea62",

View file

@ -1,44 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/kubernetes" {
version = "2.38.0"
constraints = "~> 2.24"
hashes = [
"h1:5CkveFo5ynsLdzKk+Kv+r7+U9rMrNjfZPT3a0N/fhgE=",
"zh:0af928d776eb269b192dc0ea0f8a3f0f5ec117224cd644bdacdc682300f84ba0",
"zh:1be998e67206f7cfc4ffe77c01a09ac91ce725de0abaec9030b22c0a832af44f",
"zh:326803fe5946023687d603f6f1bab24de7af3d426b01d20e51d4e6fbe4e7ec1b",
"zh:4a99ec8d91193af961de1abb1f824be73df07489301d62e6141a656b3ebfff12",
"zh:5136e51765d6a0b9e4dbcc3b38821e9736bd2136cf15e9aac11668f22db117d2",
"zh:63fab47349852d7802fb032e4f2b6a101ee1ce34b62557a9ad0f0f0f5b6ecfdc",
"zh:924fb0257e2d03e03e2bfe9c7b99aa73c195b1f19412ca09960001bee3c50d15",
"zh:b63a0be5e233f8f6727c56bed3b61eb9456ca7a8bb29539fba0837f1badf1396",
"zh:d39861aa21077f1bc899bc53e7233262e530ba8a3a2d737449b100daeb303e4d",
"zh:de0805e10ebe4c83ce3b728a67f6b0f9d18be32b25146aa89116634df5145ad4",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:faf23e45f0090eef8ba28a8aac7ec5d4fdf11a36c40a8d286304567d71c1e7db",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.94.0"
constraints = "~> 0.35"
hashes = [
"h1:ikFzd4yeJ1LR8ojP2PsZwiK2ZLhxBjRXkEg2HJrI07U=",
"zh:06c8da7d8a048216e825fa7d1e45949c1bda2a5f53f9bb0556b83b6610703fe6",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:19e82636cfd52a65105e0cf030bc8a0c815082818ef953b84f9b1e349a87318c",
"zh:24af9b7d2f1bb38f480b1aa8cf5e4ecf483bd4403642a9e8a5accbe1ae212feb",
"zh:3b10850e9242bcd00c519ff4140130e8443002fd60b6dff90983e7cb1973b2c3",
"zh:54837a0fa4ddbcf0b8407718f8823b831322deba3bd7ec8492e4578928f50633",
"zh:5cfd6a6b1ca73826a03f8746ef84a5c4059648bc49abf8056c8e0f9b87800a23",
"zh:6ab3bcfef6ff65b4ce76d333b4ad99e5f91991fcf5bddbe1958aadde6ee05eab",
"zh:81b96dc29b055f15e475d8bc32482617a582785949b3c02f44ef15d19951f69c",
"zh:85f478c2fcf10219263462d0f06b5cc41603b1edad813c336e100b3e0a55bfe8",
"zh:9adbb7655fddfe4d4081746d0d7e39c3e8fbf8aa3d8b7d3b5164f30c16a6bd93",
"zh:9c24b39e788283ead8a8ce1f013a47562ff0dc1ccb642a8e18644cbdcda0f1c4",
"zh:a425f28d6a5f6f024cab56c848c55025e84a09db946f1b00a2655d9567251cea",
"zh:f28aa62d2f06e08fe6d18ef9103a8164aa9278540779bebd61120f810c603c6b",
]
}

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/helm" {
version = "3.1.1"
hashes = [
"h1:47CqNwkxctJtL/N/JuEj+8QMg8mRNI/NWeKO5/ydfZU=",
"h1:5b2ojWKT0noujHiweCds37ZreRFRQLNaErdJLusJN88=",
"zh:1a6d5ce931708aec29d1f3d9e360c2a0c35ba5a54d03eeaff0ce3ca597cd0275",
"zh:3411919ba2a5941801e677f0fea08bdd0ae22ba3c9ce3309f55554699e06524a",
"zh:81b36138b8f2320dc7f877b50f9e38f4bc614affe68de885d322629dd0d16a29",
@ -26,7 +25,6 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
constraints = ">= 2.14.0"
hashes = [
"h1:P0c8knzZnouTNFIRij8IS7+pqd0OKaFDYX0j4GRsiqo=",
"h1:vyHdH0p6bf9xp1NPePObAJkXTJb/I09FQQmmevTzZe0=",
"zh:02d55b0b2238fd17ffa12d5464593864e80f402b90b31f6e1bd02249b9727281",
"zh:20b93a51bfeed82682b3c12f09bac3031f5bdb4977c47c97a042e4df4fb2f9ba",
"zh:6e14486ecfaee38c09ccf33d4fdaf791409f90795c1b66e026c226fad8bc03c7",
@ -45,7 +43,6 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
provider "registry.terraform.io/hashicorp/random" {
version = "3.8.1"
hashes = [
"h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=",
"h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=",
"zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4",
"zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae",
@ -66,7 +63,6 @@ provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.90.0"
constraints = ">= 0.66.0"
hashes = [
"h1:QgP6TOtucJ3A6fA51rdUvxhYGjl9RrWvXQZpjHTOuiU=",
"h1:W29Kv6XUxYssF2Gy8KcmTx3EFstt6k8sKgPRIBbq+qs=",
"zh:003af58a84884558bbb2fc40fcbefa6774ec20aa9e4b97cf3f950190a600afd2",
"zh:026ee9cef4670cf33369f8654c6b9b1d8c0e116ceb0b353c882be222951ecdd4",

View file

@ -1,64 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/helm" {
version = "3.1.1"
constraints = ">= 3.1.1"
hashes = [
"h1:5b2ojWKT0noujHiweCds37ZreRFRQLNaErdJLusJN88=",
"zh:1a6d5ce931708aec29d1f3d9e360c2a0c35ba5a54d03eeaff0ce3ca597cd0275",
"zh:3411919ba2a5941801e677f0fea08bdd0ae22ba3c9ce3309f55554699e06524a",
"zh:81b36138b8f2320dc7f877b50f9e38f4bc614affe68de885d322629dd0d16a29",
"zh:95a2a0a497a6082ee06f95b38bd0f0d6924a65722892a856cfd914c0d117f104",
"zh:9d3e78c2d1bb46508b972210ad706dd8c8b106f8b206ecf096cd211c54f46990",
"zh:a79139abf687387a6efdbbb04289a0a8e7eaca2bd91cdc0ce68ea4f3286c2c34",
"zh:aaa8784be125fbd50c48d84d6e171d3fb6ef84a221dbc5165c067ce05faab4c8",
"zh:afecd301f469975c9d8f350cc482fe656e082b6ab0f677d1a816c3c615837cc1",
"zh:c54c22b18d48ff9053d899d178d9ffef7d9d19785d9bf310a07d648b7aac075b",
"zh:db2eefd55aea48e73384a555c72bac3f7d428e24147bedb64e1a039398e5b903",
"zh:ee61666a233533fd2be971091cecc01650561f1585783c381b6f6e8a390198a4",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}
provider "registry.terraform.io/hashicorp/kubernetes" {
version = "3.1.0"
constraints = ">= 3.1.0"
hashes = [
"h1:oodIAuFMikXNmEtil5MQgP4dfSctUBYQiGJfjbsF3NY=",
"zh:0215c5c60be62028c09a2f22458e89cda3ef5830a632299f1d401eb3538874b0",
"zh:09ebb9f442431e278a310a9423f32caf467cb4b3cad3fe59573ca71fa7b14e20",
"zh:0c4e5912f83bb35846ae0a9ae54fc320706ee61894cd21cc6b4181b1c5a2fa5c",
"zh:1678c982853ad461e65ccb5e79d585e13ed109dd47dab2a66d3a7a304faeef65",
"zh:1c050a5c15e330457a9c18caacf61a923c59d663e13f2962e4b32f04fef523a0",
"zh:2c55bcec83be58ec132c7cb0a1ac644758b800d794fdc636d53a0eada0358a3a",
"zh:a062bb0aa316c08d8460c66a5d68da71da40de5d3bc3b31abcf3a1a9a19650f1",
"zh:a26fdea0afaa9b247c73c0b42843ca51ba7db0ac2571f9d3d50dcabd20ca1b98",
"zh:c872c9385a78d502bf5823d61cd3bb0f9a0585030e025eb12585c83451beeaa1",
"zh:f180879af931182beee4c8c0d9dab62b81d86f17ddcbe3786ef4c7cec9163a4e",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:f70f5789264069e0eef06f9b5d5fde955ef7206f7d446d1ce51a4c37a3f3e02f",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.94.0"
constraints = ">= 0.94.0"
hashes = [
"h1:ikFzd4yeJ1LR8ojP2PsZwiK2ZLhxBjRXkEg2HJrI07U=",
"zh:06c8da7d8a048216e825fa7d1e45949c1bda2a5f53f9bb0556b83b6610703fe6",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:19e82636cfd52a65105e0cf030bc8a0c815082818ef953b84f9b1e349a87318c",
"zh:24af9b7d2f1bb38f480b1aa8cf5e4ecf483bd4403642a9e8a5accbe1ae212feb",
"zh:3b10850e9242bcd00c519ff4140130e8443002fd60b6dff90983e7cb1973b2c3",
"zh:54837a0fa4ddbcf0b8407718f8823b831322deba3bd7ec8492e4578928f50633",
"zh:5cfd6a6b1ca73826a03f8746ef84a5c4059648bc49abf8056c8e0f9b87800a23",
"zh:6ab3bcfef6ff65b4ce76d333b4ad99e5f91991fcf5bddbe1958aadde6ee05eab",
"zh:81b96dc29b055f15e475d8bc32482617a582785949b3c02f44ef15d19951f69c",
"zh:85f478c2fcf10219263462d0f06b5cc41603b1edad813c336e100b3e0a55bfe8",
"zh:9adbb7655fddfe4d4081746d0d7e39c3e8fbf8aa3d8b7d3b5164f30c16a6bd93",
"zh:9c24b39e788283ead8a8ce1f013a47562ff0dc1ccb642a8e18644cbdcda0f1c4",
"zh:a425f28d6a5f6f024cab56c848c55025e84a09db946f1b00a2655d9567251cea",
"zh:f28aa62d2f06e08fe6d18ef9103a8164aa9278540779bebd61120f810c603c6b",
]
}

View file

@ -12,6 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
provider "stackit" {
default_region = "eu01"
service_account_key_path = ""
}
provider "kubernetes" {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
provider "helm" {
kubernetes {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
}
resource "stackit_ske_cluster" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example"

View file

@ -1,51 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">= 0.94.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 3.1.0"
}
helm = {
source = "hashicorp/helm"
version = ">= 3.1.1"
}
}
}
provider "stackit" {
default_region = "eu01"
service_account_key_path = ""
}
provider "kubernetes" {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
provider "helm" {
kubernetes = {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
}

View file

@ -1,64 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/helm" {
version = "3.1.1"
constraints = ">= 3.1.1"
hashes = [
"h1:5b2ojWKT0noujHiweCds37ZreRFRQLNaErdJLusJN88=",
"zh:1a6d5ce931708aec29d1f3d9e360c2a0c35ba5a54d03eeaff0ce3ca597cd0275",
"zh:3411919ba2a5941801e677f0fea08bdd0ae22ba3c9ce3309f55554699e06524a",
"zh:81b36138b8f2320dc7f877b50f9e38f4bc614affe68de885d322629dd0d16a29",
"zh:95a2a0a497a6082ee06f95b38bd0f0d6924a65722892a856cfd914c0d117f104",
"zh:9d3e78c2d1bb46508b972210ad706dd8c8b106f8b206ecf096cd211c54f46990",
"zh:a79139abf687387a6efdbbb04289a0a8e7eaca2bd91cdc0ce68ea4f3286c2c34",
"zh:aaa8784be125fbd50c48d84d6e171d3fb6ef84a221dbc5165c067ce05faab4c8",
"zh:afecd301f469975c9d8f350cc482fe656e082b6ab0f677d1a816c3c615837cc1",
"zh:c54c22b18d48ff9053d899d178d9ffef7d9d19785d9bf310a07d648b7aac075b",
"zh:db2eefd55aea48e73384a555c72bac3f7d428e24147bedb64e1a039398e5b903",
"zh:ee61666a233533fd2be971091cecc01650561f1585783c381b6f6e8a390198a4",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}
provider "registry.terraform.io/hashicorp/kubernetes" {
version = "3.1.0"
constraints = ">= 3.1.0"
hashes = [
"h1:oodIAuFMikXNmEtil5MQgP4dfSctUBYQiGJfjbsF3NY=",
"zh:0215c5c60be62028c09a2f22458e89cda3ef5830a632299f1d401eb3538874b0",
"zh:09ebb9f442431e278a310a9423f32caf467cb4b3cad3fe59573ca71fa7b14e20",
"zh:0c4e5912f83bb35846ae0a9ae54fc320706ee61894cd21cc6b4181b1c5a2fa5c",
"zh:1678c982853ad461e65ccb5e79d585e13ed109dd47dab2a66d3a7a304faeef65",
"zh:1c050a5c15e330457a9c18caacf61a923c59d663e13f2962e4b32f04fef523a0",
"zh:2c55bcec83be58ec132c7cb0a1ac644758b800d794fdc636d53a0eada0358a3a",
"zh:a062bb0aa316c08d8460c66a5d68da71da40de5d3bc3b31abcf3a1a9a19650f1",
"zh:a26fdea0afaa9b247c73c0b42843ca51ba7db0ac2571f9d3d50dcabd20ca1b98",
"zh:c872c9385a78d502bf5823d61cd3bb0f9a0585030e025eb12585c83451beeaa1",
"zh:f180879af931182beee4c8c0d9dab62b81d86f17ddcbe3786ef4c7cec9163a4e",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:f70f5789264069e0eef06f9b5d5fde955ef7206f7d446d1ce51a4c37a3f3e02f",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.94.0"
constraints = ">= 0.94.0"
hashes = [
"h1:ikFzd4yeJ1LR8ojP2PsZwiK2ZLhxBjRXkEg2HJrI07U=",
"zh:06c8da7d8a048216e825fa7d1e45949c1bda2a5f53f9bb0556b83b6610703fe6",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:19e82636cfd52a65105e0cf030bc8a0c815082818ef953b84f9b1e349a87318c",
"zh:24af9b7d2f1bb38f480b1aa8cf5e4ecf483bd4403642a9e8a5accbe1ae212feb",
"zh:3b10850e9242bcd00c519ff4140130e8443002fd60b6dff90983e7cb1973b2c3",
"zh:54837a0fa4ddbcf0b8407718f8823b831322deba3bd7ec8492e4578928f50633",
"zh:5cfd6a6b1ca73826a03f8746ef84a5c4059648bc49abf8056c8e0f9b87800a23",
"zh:6ab3bcfef6ff65b4ce76d333b4ad99e5f91991fcf5bddbe1958aadde6ee05eab",
"zh:81b96dc29b055f15e475d8bc32482617a582785949b3c02f44ef15d19951f69c",
"zh:85f478c2fcf10219263462d0f06b5cc41603b1edad813c336e100b3e0a55bfe8",
"zh:9adbb7655fddfe4d4081746d0d7e39c3e8fbf8aa3d8b7d3b5164f30c16a6bd93",
"zh:9c24b39e788283ead8a8ce1f013a47562ff0dc1ccb642a8e18644cbdcda0f1c4",
"zh:a425f28d6a5f6f024cab56c848c55025e84a09db946f1b00a2655d9567251cea",
"zh:f28aa62d2f06e08fe6d18ef9103a8164aa9278540779bebd61120f810c603c6b",
]
}

View file

@ -12,6 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
provider "stackit" {
default_region = "eu01"
service_account_key_path = ""
}
provider "kubernetes" {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
provider "helm" {
kubernetes {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
}
resource "stackit_ske_cluster" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example"

View file

@ -1,51 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">= 0.94.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 3.1.0"
}
helm = {
source = "hashicorp/helm"
version = ">= 3.1.1"
}
}
}
provider "stackit" {
default_region = "eu01"
service_account_key_path = ""
}
provider "kubernetes" {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
provider "helm" {
kubernetes = {
host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server
client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data)
client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data)
cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data)
}
}

View file

@ -5,7 +5,6 @@ provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.79.0"
constraints = "0.79.0"
hashes = [
"h1:AB51ok4llxeTmkVadjYpsafPbzSU5xEHLzcVBuVHxqc=",
"h1:l7AeT3WWi/u7QB7E1SaksYc5VjU9JS2LYc4OnavI3kw=",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:1eb8276c0d8a4b5b92534020df0cb270ed7c4d91dfed6db089ee775b50a8f5e3",

View file

@ -1,4 +0,0 @@
# STACKIT Landing Zone
For the full Terraform Landing Zone implementation, please visit:
[STACKIT Terraform Landing Zone Repository](https://github.com/stackitcloud/stackit-landing-zone)

View file

@ -1,7 +0,0 @@
# VPN Usecases
> ⚠️ Note: Currently, we are still leveraging the restful provider to roll out managed VPN resources. Native integration for the STACKIT Terraform provider is a work in progress. We will update these examples once it is released.
- [`STACKIT-STACKIT`](stackit-stackit)
- [`STACKIT-GCP`](stackit-gcp)
- [`STACKIT-AZURE`](stackit-azure)

View file

@ -1,70 +0,0 @@
# SNA with test-machine module
This module is used to quickly spin up a sna with a test virtual machine. We use this module to debug vpn connectivity.
> ⚠️ **SECURITY WARNING**
> Be careful: By default, **port security is disabled** on the network interface to allow unrestricted traffic for debugging purposes. **Do not use this module in a production environment**.
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
| ------------------------------------------------------------------ | -------- |
| <a name="requirement_stackit"></a> [stackit](#requirement_stackit) | >=0.95.0 |
## Providers
| Name | Version |
| ------------------------------------------------------------ | -------- |
| <a name="provider_stackit"></a> [stackit](#provider_stackit) | >=0.95.0 |
## Modules
No modules.
## Resources
| Name | Type |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| [stackit_network.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network) | resource |
| [stackit_network_area.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_area) | resource |
| [stackit_network_area_region.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_area_region) | resource |
| [stackit_network_interface.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_interface) | resource |
| [stackit_public_ip.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/public_ip) | resource |
| [stackit_resourcemanager_project.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource |
| [stackit_server.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/server) | resource |
| [stackit_volume.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/volume) | resource |
## Inputs
| Name | Description | Type | Default | Required |
| --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------- | ---------------------------------------- | :------: |
| <a name="input_machine_availability_zone"></a> [machine_availability_zone](#input_machine_availability_zone) | The availability zone (e.g. eu01-1) | `string` | n/a | yes |
| <a name="input_machine_disk_performance_class"></a> [machine_disk_performance_class](#input_machine_disk_performance_class) | Storage performance class | `string` | `"storage_premium_perf4"` | no |
| <a name="input_machine_disk_size"></a> [machine_disk_size](#input_machine_disk_size) | Boot volume size in GB | `number` | `20` | no |
| <a name="input_machine_image_id"></a> [machine_image_id](#input_machine_image_id) | Image UUID (Default: Debian 12) | `string` | `"c751cde7-e648-4f81-9722-ce9c7848bed0"` | no |
| <a name="input_machine_ipv4_prefix"></a> [machine_ipv4_prefix](#input_machine_ipv4_prefix) | The IPv4 prefix for the test machine's network (CIDR notation). This must be a subnet within the defined SNA network ranges. | `string` | n/a | yes |
| <a name="input_machine_name"></a> [machine_name](#input_machine_name) | name of the stackit test machine | `string` | n/a | yes |
| <a name="input_machine_network_name"></a> [machine_network_name](#input_machine_network_name) | The name of the network where the test machine will be connected. | `string` | n/a | yes |
| <a name="input_machine_type"></a> [machine_type](#input_machine_type) | Flavor of the machine | `string` | `"c2i.1"` | no |
| <a name="input_sna_default_nameserver"></a> [sna_default_nameserver](#input_sna_default_nameserver) | A list of STACKIT SNA default nameservers (IP addresses). | `list(string)` | <pre>[<br/> "1.1.1.1"<br/>]</pre> | no |
| <a name="input_sna_name"></a> [sna_name](#input_sna_name) | The name of the STACKIT Network Area (SNA). | `string` | n/a | yes |
| <a name="input_sna_network_range_prefix"></a> [sna_network_range_prefix](#input_sna_network_range_prefix) | A list of STACKIT SNA network range prefixes in CIDR notation. | `list(string)` | <pre>[<br/> "10.28.0.0/16"<br/>]</pre> | no |
| <a name="input_sna_transfer_range"></a> [sna_transfer_range](#input_sna_transfer_range) | The STACKIT SNA transfer range in CIDR notation. | `string` | `"172.16.0.0/16"` | no |
| <a name="input_stackit_admin_email"></a> [stackit_admin_email](#input_stackit_admin_email) | The email address of the project administrator. | `string` | n/a | yes |
| <a name="input_stackit_org_id"></a> [stackit_org_id](#input_stackit_org_id) | The STACKIT Organization ID (UUID). | `string` | n/a | yes |
| <a name="input_stackit_project_name"></a> [stackit_project_name](#input_stackit_project_name) | The name of the STACKIT project where the managed VPN and test machine will be deployed. | `string` | n/a | yes |
## Outputs
| Name | Description |
| ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| <a name="output_machine_network_ipv4"></a> [machine_network_ipv4](#output_machine_network_ipv4) | The IPv4 prefix of the machine's network. |
| <a name="output_machine_private_ipv4"></a> [machine_private_ipv4](#output_machine_private_ipv4) | The private IP address of the test machine. |
| <a name="output_machine_public_ip"></a> [machine_public_ip](#output_machine_public_ip) | The public IP address of the test machine. |
| <a name="output_project_id"></a> [project_id](#output_project_id) | The ID of the STACKIT project. |
| <a name="output_sna_id"></a> [sna_id](#output_sna_id) | The ID of the STACKIT Network Area. |
| <a name="output_sna_network_range"></a> [sna_network_range](#output_sna_network_range) | The network ranges (sna-ipv4) of the STACKIT Network Area. |
<!-- END_TF_DOCS -->

View file

@ -1,25 +0,0 @@
#cloud-config
# ---------------------------------------------------------------------------
# Example cloud-init for Linux instances (RHEL / Debian).
# Creates a local admin user for initial access.
#
# IMPORTANT: Replace the password hash below with a hash of your own
# secure password before deploying. Never use a shared or well-known
# default password in production.
#
# Generate a SHA-512 hash on Linux/macOS:
# openssl passwd -6 "YourPassword"
# ---------------------------------------------------------------------------
users:
- name: debug
groups: sudo
shell: /bin/bash
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
lock_passwd: false
# debug123
passwd: "$6$dIIA5b1oK7qi89.P$MH9SSMtnzCo8QvvUnVoCE5e1c7FY0NUgB4dpsv5JDq9zpRDiTpfiYtM5DitiJIuQWvZ7T1emTTgKaBufayaIW."
chpasswd:
expire: false
ssh_pwauth: true

View file

@ -1,96 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
resource "stackit_network_area" "this" {
name = var.sna_name
organization_id = var.stackit_org_id
labels = {
"preview/routingtables" = "true"
}
}
resource "stackit_network_area_region" "this" {
organization_id = var.stackit_org_id
network_area_id = stackit_network_area.this.network_area_id
ipv4 = {
transfer_network = var.sna_transfer_range
network_ranges = [
for prefix in var.sna_network_range_prefix : {
prefix = prefix
}
]
default_nameservers = var.sna_default_nameserver
}
}
resource "stackit_resourcemanager_project" "this" {
parent_container_id = var.stackit_org_id
name = var.stackit_project_name
owner_email = var.stackit_admin_email
labels = {
"networkArea" = stackit_network_area.this.network_area_id
}
}
resource "stackit_volume" "this" {
project_id = stackit_resourcemanager_project.this.project_id
name = "${var.machine_name}-volume"
availability_zone = var.machine_availability_zone
size = var.machine_disk_size
performance_class = var.machine_disk_performance_class
source = {
type = "image"
id = var.machine_image_id
}
}
resource "stackit_network" "this" {
name = var.machine_network_name
project_id = stackit_resourcemanager_project.this.project_id
ipv4_prefix = var.machine_ipv4_prefix
ipv4_nameservers = var.sna_default_nameserver
}
resource "stackit_network_interface" "this" {
project_id = stackit_resourcemanager_project.this.project_id
network_id = stackit_network.this.network_id
security = false
}
resource "stackit_server" "this" {
project_id = stackit_resourcemanager_project.this.project_id
name = var.machine_name
availability_zone = var.machine_availability_zone
machine_type = var.machine_type
boot_volume = {
source_type = "volume"
source_id = stackit_volume.this.volume_id
}
agent = {
provisioning_policy = "ALWAYS"
}
network_interfaces = [
stackit_network_interface.this.network_interface_id
]
user_data = file("${path.module}/debug-user.yml")
}
resource "stackit_public_ip" "this" {
project_id = stackit_resourcemanager_project.this.project_id
network_interface_id = stackit_network_interface.this.network_interface_id
}

View file

@ -1,43 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
output "sna_id" {
description = "The ID of the STACKIT Network Area."
value = stackit_network_area.this.network_area_id
}
output "project_id" {
description = "The ID of the STACKIT project."
value = stackit_resourcemanager_project.this.project_id
}
output "machine_public_ip" {
description = "The public IP address of the test machine."
value = stackit_public_ip.this.ip
}
output "machine_private_ipv4" {
description = "The private IP address of the test machine."
value = stackit_network_interface.this.ipv4
}
output "machine_network_ipv4" {
description = "The IPv4 prefix of the machine's network."
value = stackit_network.this.ipv4_prefix
}
output "sna_network_range" {
description = "The network ranges (sna-ipv4) of the STACKIT Network Area."
value = stackit_network_area_region.this.ipv4.network_ranges
}

View file

@ -1,22 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">=0.95.0"
}
}
}

View file

@ -1,138 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
variable "stackit_org_id" {
description = "The STACKIT Organization ID (UUID)."
type = string
validation {
condition = can(regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", var.stackit_org_id))
error_message = "The stackit_org_id must be a valid UUID."
}
}
variable "stackit_project_name" {
description = "The name of the STACKIT project where the managed VPN and test machine will be deployed."
type = string
validation {
condition = length(var.stackit_project_name) >= 1 && length(var.stackit_project_name) <= 63
error_message = "The project name must be between 1 and 63 characters long."
}
}
variable "stackit_admin_email" {
description = "The email address of the project administrator."
type = string
validation {
condition = can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", var.stackit_admin_email))
error_message = "The stackit_admin_email must be a valid email address."
}
}
variable "sna_name" {
description = "The name of the STACKIT Network Area (SNA)."
type = string
}
variable "sna_transfer_range" {
description = "The STACKIT SNA transfer range in CIDR notation."
type = string
default = "172.16.0.0/16"
validation {
condition = can(cidrnetmask(var.sna_transfer_range))
error_message = "The sna_transfer_range must be a valid CIDR notation."
}
}
variable "sna_network_range_prefix" {
description = "A list of STACKIT SNA network range prefixes in CIDR notation."
type = list(string)
default = ["10.28.0.0/16"]
validation {
condition = alltrue([for r in var.sna_network_range_prefix : can(cidrnetmask(r))])
error_message = "All elements in sna_network_range_prefix must be valid CIDR notations."
}
}
variable "sna_default_nameserver" {
description = "A list of STACKIT SNA default nameservers (IP addresses)."
type = list(string)
default = ["1.1.1.1"]
validation {
condition = alltrue([for ns in var.sna_default_nameserver : can(regex("^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$", ns))])
error_message = "All elements in sna_default_nameserver must be valid IP addresses."
}
}
variable "machine_network_name" {
description = "The name of the network where the test machine will be connected."
type = string
}
variable "machine_ipv4_prefix" {
description = "The IPv4 prefix for the test machine's network (CIDR notation). This must be a subnet within the defined SNA network ranges."
type = string
validation {
condition = can(cidrnetmask(var.machine_ipv4_prefix))
error_message = "The machine_ipv4_prefix must be a valid CIDR notation."
}
}
variable "machine_name" {
type = string
description = "name of the stackit test machine"
}
variable "machine_availability_zone" {
description = "The availability zone (e.g. eu01-1)"
type = string
validation {
condition = can(regex("^[a-z]{2}[0-9]{2}-[a-zA-Z0-9]+$", var.machine_availability_zone))
error_message = "The availability zone must follow the STACKIT pattern (e.g., eu01-1, eu01-m)."
}
}
variable "machine_type" {
description = "Flavor of the machine"
type = string
default = "c2i.1"
}
variable "machine_image_id" {
description = "Image UUID (Default: Debian 12)"
type = string
default = "c751cde7-e648-4f81-9722-ce9c7848bed0"
validation {
condition = can(regex("^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$", var.machine_image_id))
error_message = "The image_id must be a valid UUID."
}
}
variable "machine_disk_size" {
description = "Boot volume size in GB"
type = number
default = 20
validation {
condition = var.machine_disk_size >= 1
error_message = "The disk_size must be at least 1 GB."
}
}
variable "machine_disk_performance_class" {
description = "Storage performance class"
type = string
default = "storage_premium_perf4"
}

View file

@ -1,105 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/azurerm" {
version = "4.72.0"
constraints = "4.72.0"
hashes = [
"h1:QYnPAHT/PYheOOZz52ucHqw/ZO9PxWyPLtO7UD/jSMg=",
"zh:073472587c3752e89738522814d2b4eb2fd69eb2cb19c5a5ead3c7d2eabdc279",
"zh:1950effc0c315b6002c8cb6327b94fe59bda210e699367d9727bc66490d651d2",
"zh:47c990db75658525de57c8955a05b4752b88f3a900fffac0e7661d4a749e94f2",
"zh:610f2cbd6fab76750d8b093f03beabbb7162dc8c6affe0109f534ce240b3ff0f",
"zh:6739d645fe548c5a489d711f7748f32368cf68d723d2c59d3f2e21456304d692",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:a277ab095cc8aff3aede9e43eca2a699936472ef90abb272adf3daa609eb9141",
"zh:b1fdcdaf926c86de0d884beda90d78cb94a42ddede03a1f0b92c36b321d4f07e",
"zh:c003f1f15e52c54e189301ae2c7d8dd65acb2e5a7527d201355f2757b5465ba9",
"zh:c45f2d2206c0f8f71f207cd39eec73da9619d35932bbe1a5b8be7679c50a151e",
"zh:d7040d8ec295481bc1d30346ed7f3075c40ede87c0fedf1db34dd91c1c367a10",
"zh:e595f0b870cd5fd5debdc926fc1740201d2b66188b9b132dc598bdd6444e7348",
]
}
provider "registry.terraform.io/hashicorp/random" {
version = "3.9.0"
hashes = [
"h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=",
"zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1",
"zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea",
"zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f",
"zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0",
"zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61",
"zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc",
"zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e",
"zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef",
"zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b",
"zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257",
"zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04",
]
}
provider "registry.terraform.io/hashicorp/time" {
version = "0.14.0"
hashes = [
"h1:/hlxsUpuN/lvPTNL9+NyVGsOyRsK5NsxwFMsj5CdOp4=",
"zh:12abfd6b800e4d7fa6db7310dec8ffd440b31993861ef188c7ed5260b3073937",
"zh:23005521e800bb19e1597bf755c5f70d675d30b685d4255001ed5fa47d9df3f1",
"zh:2fea249b582ae97cd1cc10385187ea50993bb47c28cc5df0305e57ceaabf0a10",
"zh:322018d3b987b7aad08697178029a2bb667bed699e88328f0c89c52a2fd41341",
"zh:32a08e98fce2d273cb9b2c89d6c54727cc9f0a32e15bfd896be4e02cc6b48f95",
"zh:3db89aabd0e619616bd4b0f8b373a7586dfe60feffcea12a84a0bdbc445714b3",
"zh:7488f56c81d742dc020f29063626c8f07ca188aa97be61e7307e8d62397020a2",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:7cb4067f2e7559b13f7562ef722f948950901eb37834873e98360ab28f66e9d7",
"zh:9d552c8345f61e1b7db8e725144981345f18ac1014d58d6f5ddf0928a195fffb",
"zh:a8e69fb6b97fc9d86fb19a9f4d42abe33c4a68e700b15387ce2e17d2b9934bed",
"zh:aeeb900eb8dd0f790c60ea5c0e0c8d42bd6e4a54f391681d4decca15b544394b",
"zh:c239c619101a8c95e1f14061eb973c57a8d15fa0e68878ced5bbd76858ee5b79",
]
}
provider "registry.terraform.io/magodo/restful" {
version = "0.25.2"
hashes = [
"h1:gvoDTFfxp7n1B4Wsnx9IC7Ku8g8tdVR4mCC6TDX0Mws=",
"zh:0513ff62fce41a59462f39e1c4636f3c87e6f8d24ee579075900d3e0f57f6992",
"zh:1a3e39e6b8c7fd0f3983730944a029db8f00557922e337cff0567a07c5e74b45",
"zh:2527c96fcc45458efc9eca1c66cee98269d80693b571c57baee783402bfbaa28",
"zh:50cec9afe8b55629d1c94d477b26ff95de8cc8e3304f6c2bfc5dad3bccc6decc",
"zh:89e94c0f312d0ef4213b46ee776a27f6a5d114520c08a4716f4fee4c26c16f91",
"zh:9a9762ebaf9567a4aa34a1911f051527696241679e087137fcc7821e52b66483",
"zh:a065be3488e24928199904f4a496974c03fdcf2b06fccf016e405b3068d5ef76",
"zh:c62a1a6fb3c5135451f68ea4ed1f66d999ab654323d10526756e83f6f77d6bdf",
"zh:cf01364f89b713dc10eb87098839317e6f2de222bec2597923cddbb07bdd9c13",
"zh:dc0ac6a1e5e3199e1d35fb49f9de1d9325caa3c0d3e87ea8128295e19ac941c3",
"zh:e55cf6e8230f081b7c8ade592c14f1b8b45ee0aaa14c2bde2da9531d819a4392",
"zh:f333748916e68050c8935d760d6b9b469dd76eb94363af93562cbd076dba6ff5",
"zh:f809ab383cca0a5f83072981c64208cbd7fa67e986a86ee02dd2c82333221e32",
"zh:fdfdca8b7976c1a8b1b6a3589b4bfec277beb6dfb40c5568271d42f0b2f88a9d",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.95.0"
constraints = ">= 0.87.0, >= 0.95.0"
hashes = [
"h1:sKmc6SGKEFglXKLMtOluJkFm7tzQZKQV3/QxUbHug1E=",
"zh:023edbb8ca984233bb51605a9005d4f7cb3365f0b11ddd68d911a1e30ccf64be",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:1fc43ed3055c4912e5b3ae2eba49dd5407beaa9ba6617612f317543f7d26ccd7",
"zh:31e587a9f279661b74b139e2a964a7d1c54a4073d27d21c2f948e0e7ba4c0d04",
"zh:37427a23800dff84c1b89d4985cb935c0112c59acd716d8920c160221c459061",
"zh:3a575f5c7d1252d99aea9187923087e1d483b2b34e42c9f058f557ec28c45d84",
"zh:44c7ee340e1a09d6f9a9873959f8283f0d73aee4a8c884f7b36985f943874b65",
"zh:4fab8fe953a0d4c21589cd36d23afe072c6403e37620c82839f9f829139cbbbf",
"zh:69fc061b3c7ea82d9e9a31d3665a535f6bb9dc3d6ff5b466f940d3d04a105e19",
"zh:85ee00442eff70ea103a96276efb5e1485b661b0a1db08bcdbd28b11b1f966e6",
"zh:9761ef1321c93cb3e4bc2499995b3e7ae910e2ae68b3228164dea73e9687ddb5",
"zh:b158a4e4726a4d4c9f61c5dc71abb4ca3a621269e1d7af88ab36d34c3bcec66f",
"zh:da37df9a426d83da8f6c1340104a6b9a7eef4a7e2589d0b70a89c574a1b3cc78",
"zh:e6421b9a351b2c9b2ab2341f2c07d863eb2ed055b847ea839de96b0fd62baf97",
]
}

View file

@ -1,54 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">=0.95.0"
}
restful = {
source = "magodo/restful"
}
azurerm = {
source = "hashicorp/azurerm"
version = "4.72.0"
}
}
}
provider "stackit" {
default_region = var.stackit_region
service_account_key_path = var.stackit_service_account_key_path
enable_beta_resources = true
}
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
ephemeral "stackit_access_token" "this" {}
provider "restful" {
alias = "stackit"
base_url = "https://vpn.api.eu01.stackit.cloud"
security = {
http = {
token = {
token = ephemeral.stackit_access_token.this.access_token
}
}
}
}

View file

@ -1,34 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
variable "stackit_org_id" {
type = string
}
variable "stackit_region" {
type = string
default = "eu01"
}
variable "stackit_service_account_key_path" {
type = string
}
variable "azure_subscription_id" {
type = string
}
variable "stackit_admin_email" {
type = string
}

View file

@ -1,376 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# STACKIT Side (vpn-sna-01)
module "vpn_sna_01" {
source = "../module/stackit-sna-with-debug-machine"
machine_availability_zone = "eu01-1"
machine_ipv4_prefix = "10.10.10.0/24"
machine_network_name = "vpn-sna-01"
sna_name = "vpn-sna-01"
machine_name = "vpn-sna-01"
stackit_admin_email = var.stackit_admin_email
stackit_org_id = var.stackit_org_id
stackit_project_name = "vpn-sna-01"
sna_network_range_prefix = [
"10.10.0.0/16"
]
}
resource "restful_resource" "vpn_01_gateway" {
provider = restful.stackit
path = "/v1/projects/${module.vpn_sna_01.project_id}/regions/eu01/gateways"
body = {
availabilityZones = {
tunnel1 = "eu01-1"
tunnel2 = "eu01-2"
}
bgp = {
localAsn = 64512
overrideAdvertisedRoutes = ["10.10.0.0/16"]
}
displayName = "vpn01"
labels = null
planId = "p500"
routingType = "BGP_ROUTE_BASED"
}
read_path = "$(path)/$(body.id)"
update_path = "$(path)/$(body.id)"
update_method = "PUT"
delete_path = "$(path)/$(body.id)"
delete_method = "DELETE"
}
data "restful_resource" "vpn_01_gateway_status" {
provider = restful.stackit
id = "${restful_resource.vpn_01_gateway.id}/status"
}
resource "random_password" "vpn_psk" {
length = 32
special = false
}
# Azure Side
resource "azurerm_resource_group" "rg" {
name = "rg-vpn-test"
location = "West Europe"
}
# 1. Azure VNet and Subnets
resource "azurerm_virtual_network" "azure_vnet" {
name = "azure-vpn-network"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
address_space = ["10.11.0.0/16"]
}
resource "azurerm_subnet" "azure_gateway_subnet" {
name = "GatewaySubnet" # MUST be exactly named GatewaySubnet
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.azure_vnet.name
address_prefixes = ["10.11.0.0/24"]
}
resource "azurerm_subnet" "azure_vm_subnet" {
name = "vm-subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.azure_vnet.name
address_prefixes = ["10.11.1.0/24"]
}
# 2. Azure Public IPs (2 required for Active-Active HA VPN)
resource "azurerm_public_ip" "azure_gw_pip1" {
name = "azure-gw-pip1"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
allocation_method = "Static"
sku = "Standard"
zones = ["1", "2", "3"]
lifecycle {
ignore_changes = [domain_name_label]
}
}
resource "azurerm_public_ip" "azure_gw_pip2" {
name = "azure-gw-pip2"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
allocation_method = "Static"
sku = "Standard"
zones = ["1", "2", "3"]
lifecycle {
ignore_changes = [domain_name_label]
}
}
# 3. Azure HA VPN Gateway
resource "azurerm_virtual_network_gateway" "azure_gateway" {
name = "azure-ha-vpn"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
type = "Vpn"
vpn_type = "RouteBased"
active_active = true
bgp_enabled = true
sku = "VpnGw1AZ"
bgp_settings {
asn = 64513 # Azure's local ASN
peering_addresses {
ip_configuration_name = "vnetGatewayConfig1"
apipa_addresses = ["169.254.21.2"]
}
peering_addresses {
ip_configuration_name = "vnetGatewayConfig2"
apipa_addresses = ["169.254.21.6"]
}
}
ip_configuration {
name = "vnetGatewayConfig1"
public_ip_address_id = azurerm_public_ip.azure_gw_pip1.id
private_ip_address_allocation = "Dynamic"
subnet_id = azurerm_subnet.azure_gateway_subnet.id
}
ip_configuration {
name = "vnetGatewayConfig2"
public_ip_address_id = azurerm_public_ip.azure_gw_pip2.id
private_ip_address_allocation = "Dynamic"
subnet_id = azurerm_subnet.azure_gateway_subnet.id
}
}
# 4. Azure Local Network Gateways (Represents the 2 STACKIT Tunnels)
resource "azurerm_local_network_gateway" "stackit_tunnel1" {
name = "stackit-tunnel-1"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
gateway_address = data.restful_resource.vpn_01_gateway_status.output.tunnels[0].publicIP
bgp_settings {
asn = 64512
bgp_peering_address = "169.254.21.1"
}
}
resource "azurerm_local_network_gateway" "stackit_tunnel2" {
name = "stackit-tunnel-2"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
gateway_address = data.restful_resource.vpn_01_gateway_status.output.tunnels[1].publicIP
bgp_settings {
asn = 64512
bgp_peering_address = "169.254.21.5"
}
}
# 5. Azure VPN Connections
resource "azurerm_virtual_network_gateway_connection" "azure_tunnel1" {
name = "conn-to-stackit-tunnel1"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
type = "IPsec"
virtual_network_gateway_id = azurerm_virtual_network_gateway.azure_gateway.id
local_network_gateway_id = azurerm_local_network_gateway.stackit_tunnel1.id
shared_key = random_password.vpn_psk.result
enable_bgp = true
ipsec_policy {
ike_encryption = "GCMAES256"
ike_integrity = "SHA256"
ipsec_encryption = "GCMAES256"
ipsec_integrity = "GCMAES256"
dh_group = "DHGroup14"
pfs_group = "PFS14"
sa_lifetime = 3600
sa_datasize = 102400000
}
}
resource "azurerm_virtual_network_gateway_connection" "azure_tunnel2" {
name = "conn-to-stackit-tunnel2"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
type = "IPsec"
virtual_network_gateway_id = azurerm_virtual_network_gateway.azure_gateway.id
local_network_gateway_id = azurerm_local_network_gateway.stackit_tunnel2.id
shared_key = random_password.vpn_psk.result
enable_bgp = true
ipsec_policy {
ike_encryption = "GCMAES256"
ike_integrity = "SHA256"
ipsec_encryption = "GCMAES256"
ipsec_integrity = "GCMAES256"
dh_group = "DHGroup14"
pfs_group = "PFS14"
sa_lifetime = 3600
sa_datasize = 102400000
}
}
# Connection from STACKIT to Azure
resource "restful_resource" "vpn_01_connection" {
provider = restful.stackit
path = "${restful_resource.vpn_01_gateway.id}/connections"
body = {
displayName = "conn-to-azure"
tunnel1 = {
bgp = {
remoteAsn = 64513
}
peering = {
localAddress = "169.254.21.1"
remoteAddress = "169.254.21.2"
}
phase1 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
phase2 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
preSharedKey = random_password.vpn_psk.result
remoteAddress = azurerm_public_ip.azure_gw_pip1.ip_address
}
tunnel2 = {
bgp = {
remoteAsn = 64513
}
peering = {
localAddress = "169.254.21.5"
remoteAddress = "169.254.21.6"
}
phase1 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
phase2 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
preSharedKey = random_password.vpn_psk.result
remoteAddress = azurerm_public_ip.azure_gw_pip2.ip_address
}
}
lifecycle {
ignore_changes = [
body.tunnel1.preSharedKey,
body.tunnel2.preSharedKey
]
}
read_path = "$(path)/$(body.id)"
update_path = "$(path)/$(body.id)"
update_method = "PUT"
delete_path = "$(path)/$(body.id)"
delete_method = "DELETE"
}
# Azure Test VM & NSG
resource "azurerm_network_security_group" "vm_nsg" {
name = "test-vm-nsg"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
security_rule {
name = "Allow-STACKIT"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "10.10.0.0/16"
destination_address_prefix = "*"
}
}
resource "azurerm_network_interface" "vm_nic" {
name = "test-vm-nic"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.azure_vm_subnet.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_network_interface_security_group_association" "vm_nsg_assoc" {
network_interface_id = azurerm_network_interface.vm_nic.id
network_security_group_id = azurerm_network_security_group.vm_nsg.id
}
resource "azurerm_linux_virtual_machine" "azure_test_vm" {
name = "azure-vpn-test-vm"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_B1s"
admin_username = "azureuser"
admin_password = "VpnTestPassw0rd!"
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.vm_nic.id,
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}
}
# Outputs
output "vpn01_public_ip" {
value = module.vpn_sna_01.machine_public_ip
description = "Connect here via SSH to ping Azure"
}
output "vpn01_private_ip" {
value = module.vpn_sna_01.machine_private_ipv4
}
output "azure_test_vm_private_ip" {
value = azurerm_linux_virtual_machine.azure_test_vm.private_ip_address
}
# Command to run a ping test without SSHing
output "azure_run_command_ping_test" {
value = "az vm run-command invoke --resource-group ${azurerm_resource_group.rg.name} --name ${azurerm_linux_virtual_machine.azure_test_vm.name} --command-id RunShellScript --scripts 'ping -c 4 ${module.vpn_sna_01.machine_private_ipv4}'"
description = "Copy and paste this in your terminal to securely ping from the Azure VM to the STACKIT VM."
}

View file

@ -1,9 +0,0 @@
# Maintainers
General maintainers:
- Mauritz Uphoff (mauritz.uphoff@digits.schwarz)
This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis.
For questions, issues, or feature requests, please email general maintainers.
Please include the BP name and version in your request. We will track your request as an issue.

View file

@ -1,48 +0,0 @@
# STACKIT-to-Azure HA VPN Gateway
> ⚠️ azurerm_virtual_network_gateway.azure_gateway takes between 30-90mins
This example demonstrates how to establish a secure, Highly Available (HA) IPsec VPN connection between a STACKIT Network Area (SNA) and Microsoft Azure.
The connection uses **BGP (Border Gateway Protocol)** via an Azure Virtual Network Gateway (Active-Active mode) to automatically exchange and propagate routes dynamically between the two cloud environments.
## Architecture
This Terraform configuration provisions the following resources:
- **STACKIT:** An SNA, a debug machine, and an HA VPN Gateway (`ASN 64512`).
- **Azure:** A Resource Group, VNet, dedicated `GatewaySubnet`, an Active-Active Virtual Network Gateway (`ASN 64513`), two Local Network Gateways (representing STACKIT), and a private Ubuntu test VM.
- **VPN Connection:** Two redundant IPsec tunnels using dynamically generated PSKs and Link-Local BGP peering (`169.254.x.x/30`).
- **Security:** Azure Network Security Group (NSG) rules configured to allow inbound ICMP/SSH traffic specifically from the STACKIT network range.
## Prerequisites
- Configured STACKIT and Azure provider credentials.
- Azure CLI (`az`) installed and authenticated for testing from the Azure side.
## Outputs
Once the deployment is complete, Terraform will output the following information to help you verify connectivity:
- `vpn01_public_ip`: The public IP of the debug machine in STACKIT.
- `vpn01_private_ip`: The private IP of the debug machine in STACKIT.
- `azure_test_vm_private_ip`: The private IP of the test VM in Azure.
- `azure_run_command_ping_test`: A pre-formatted Azure CLI command to test the connection.
## How to Test the Connection
You can verify the bi-directional tunnel is fully operational by following these steps:
### 1. Test from Azure to STACKIT (Zero-Config)
We utilize the Azure "Run Command" feature to execute a ping test directly inside the private Azure VM without needing SSH access or a Bastion host.
Copy the command generated by the `azure_run_command_ping_test` output and run it in your terminal:
```bash
az vm run-command invoke \
--resource-group rg-vpn-test \
--name azure-vpn-test-vm \
--command-id RunShellScript \
--scripts 'ping -c 4 <vpn01_private_ip>'
```

View file

@ -1,83 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/google" {
version = "7.32.0"
hashes = [
"h1:hDMENgq6nxoM6ttxN1HNrqbYiyRV8avLmUuUe4QWvKY=",
"zh:091afeeeb58035f26ebaec34755a15d56e3229c4ce6db2745c52ba2593204a30",
"zh:15d6a375c49d023dd21e612610b12bf79fbc6459bc5ad64b989d2180e9931f7d",
"zh:2c70ee949b01c0c7925618e36417ac5b9c1de91c66bb0bd956b2b2bd1d38a2b6",
"zh:2e531cf6f3af847104df65675ebd9c9a7450ba91d8d21ff6ed04eeab6a5684e2",
"zh:42fece780ef909136213762731c945d59c58dbaf92f64a46989102da9ebfa998",
"zh:9008b13bec8c588ef41ec813c3d67d26acb22ada241d9dd9ed408687607726cc",
"zh:a62e09bd551de8ea74b68c1eb44f9d7d0dc56957811915d46ec0a28254a30e0b",
"zh:ad3d4419561d19e88b72ad4bedbbc73ee77f20acb594261be8f716bf1a89f947",
"zh:af0c23df89e5fb815751c64c9a438527d6e0609df52fa7e281dbd90aa238270b",
"zh:b4d1157559d04792441550ae79f13d16bd7cc3f80a9616cd9ef3f83466564ce4",
"zh:db32528838dc9641981769012bdabf21e658756f1581ccbcd239aab0eb4aed11",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}
provider "registry.terraform.io/hashicorp/random" {
version = "3.8.1"
hashes = [
"h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=",
"zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4",
"zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae",
"zh:229665ddf060aa0ed315597908483eee5b818a17d09b6417a0f52fd9405c4f57",
"zh:2469d2e48f28076254a2a3fc327f184914566d9e40c5780b8d96ebf7205f8bc0",
"zh:37d7eb334d9561f335e748280f5535a384a88675af9a9eac439d4cfd663bcb66",
"zh:741101426a2f2c52dee37122f0f4a2f2d6af6d852cb1db634480a86398fa3511",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:a902473f08ef8df62cfe6116bd6c157070a93f66622384300de235a533e9d4a9",
"zh:b85c511a23e57a2147355932b3b6dce2a11e856b941165793a0c3d7578d94d05",
"zh:c5172226d18eaac95b1daac80172287b69d4ce32750c82ad77fa0768be4ea4b8",
"zh:dab4434dba34aad569b0bc243c2d3f3ff86dd7740def373f2a49816bd2ff819b",
"zh:f49fd62aa8c5525a5c17abd51e27ca5e213881d58882fd42fec4a545b53c9699",
]
}
provider "registry.terraform.io/magodo/restful" {
version = "0.25.2"
hashes = [
"h1:gvoDTFfxp7n1B4Wsnx9IC7Ku8g8tdVR4mCC6TDX0Mws=",
"zh:0513ff62fce41a59462f39e1c4636f3c87e6f8d24ee579075900d3e0f57f6992",
"zh:1a3e39e6b8c7fd0f3983730944a029db8f00557922e337cff0567a07c5e74b45",
"zh:2527c96fcc45458efc9eca1c66cee98269d80693b571c57baee783402bfbaa28",
"zh:50cec9afe8b55629d1c94d477b26ff95de8cc8e3304f6c2bfc5dad3bccc6decc",
"zh:89e94c0f312d0ef4213b46ee776a27f6a5d114520c08a4716f4fee4c26c16f91",
"zh:9a9762ebaf9567a4aa34a1911f051527696241679e087137fcc7821e52b66483",
"zh:a065be3488e24928199904f4a496974c03fdcf2b06fccf016e405b3068d5ef76",
"zh:c62a1a6fb3c5135451f68ea4ed1f66d999ab654323d10526756e83f6f77d6bdf",
"zh:cf01364f89b713dc10eb87098839317e6f2de222bec2597923cddbb07bdd9c13",
"zh:dc0ac6a1e5e3199e1d35fb49f9de1d9325caa3c0d3e87ea8128295e19ac941c3",
"zh:e55cf6e8230f081b7c8ade592c14f1b8b45ee0aaa14c2bde2da9531d819a4392",
"zh:f333748916e68050c8935d760d6b9b469dd76eb94363af93562cbd076dba6ff5",
"zh:f809ab383cca0a5f83072981c64208cbd7fa67e986a86ee02dd2c82333221e32",
"zh:fdfdca8b7976c1a8b1b6a3589b4bfec277beb6dfb40c5568271d42f0b2f88a9d",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.95.0"
constraints = ">= 0.66.0, >= 0.87.0"
hashes = [
"h1:sKmc6SGKEFglXKLMtOluJkFm7tzQZKQV3/QxUbHug1E=",
"zh:023edbb8ca984233bb51605a9005d4f7cb3365f0b11ddd68d911a1e30ccf64be",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:1fc43ed3055c4912e5b3ae2eba49dd5407beaa9ba6617612f317543f7d26ccd7",
"zh:31e587a9f279661b74b139e2a964a7d1c54a4073d27d21c2f948e0e7ba4c0d04",
"zh:37427a23800dff84c1b89d4985cb935c0112c59acd716d8920c160221c459061",
"zh:3a575f5c7d1252d99aea9187923087e1d483b2b34e42c9f058f557ec28c45d84",
"zh:44c7ee340e1a09d6f9a9873959f8283f0d73aee4a8c884f7b36985f943874b65",
"zh:4fab8fe953a0d4c21589cd36d23afe072c6403e37620c82839f9f829139cbbbf",
"zh:69fc061b3c7ea82d9e9a31d3665a535f6bb9dc3d6ff5b466f940d3d04a105e19",
"zh:85ee00442eff70ea103a96276efb5e1485b661b0a1db08bcdbd28b11b1f966e6",
"zh:9761ef1321c93cb3e4bc2499995b3e7ae910e2ae68b3228164dea73e9687ddb5",
"zh:b158a4e4726a4d4c9f61c5dc71abb4ca3a621269e1d7af88ab36d34c3bcec66f",
"zh:da37df9a426d83da8f6c1340104a6b9a7eef4a7e2589d0b70a89c574a1b3cc78",
"zh:e6421b9a351b2c9b2ab2341f2c07d863eb2ed055b847ea839de96b0fd62baf97",
]
}

View file

@ -1,56 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">=0.95.0"
}
restful = {
source = "magodo/restful"
}
google = {
source = "hashicorp/google"
version = "7.32.0"
}
}
}
provider "stackit" {
default_region = var.stackit_region
service_account_key_path = var.stackit_service_account_key_path
enable_beta_resources = true
}
provider "google" {
project = var.gcp_project
region = "europe-west4"
zone = "europe-west4-a"
credentials = file(var.gcp_service_account_key_path)
}
ephemeral "stackit_access_token" "this" {}
provider "restful" {
alias = "stackit"
base_url = "https://vpn.api.eu01.stackit.cloud"
security = {
http = {
token = {
token = ephemeral.stackit_access_token.this.access_token
}
}
}
}

View file

@ -1,40 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# load via *.auto.tfvars
variable "stackit_org_id" {
type = string
}
variable "stackit_region" {
type = string
default = "eu01"
}
variable "stackit_service_account_key_path" {
type = string
}
variable "gcp_service_account_key_path" {
type = string
}
variable "gcp_project" {
type = string
}
variable "stackit_admin_email" {
type = string
}

View file

@ -1,305 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# STACKIT Side (vpn-sna-01)
module "vpn_sna_01" {
source = "../module/stackit-sna-with-debug-machine"
machine_availability_zone = "eu01-1"
machine_ipv4_prefix = "10.10.10.0/24"
machine_network_name = "vpn-sna-01"
sna_name = "vpn-sna-01"
machine_name = "vpn-sna-01"
stackit_admin_email = var.stackit_admin_email
stackit_org_id = var.stackit_org_id
stackit_project_name = "vpn-sna-01"
sna_network_range_prefix = [
"10.10.0.0/16"
]
}
resource "restful_resource" "vpn_01_gateway" {
provider = restful.stackit
path = "/v1/projects/${module.vpn_sna_01.project_id}/regions/eu01/gateways"
body = {
availabilityZones = {
tunnel1 = "eu01-1"
tunnel2 = "eu01-2"
}
bgp = {
localAsn = 64512
overrideAdvertisedRoutes = ["10.10.0.0/16"]
}
displayName = "vpn01"
labels = null
planId = "p500"
routingType = "BGP_ROUTE_BASED"
}
read_path = "$(path)/$(body.id)"
update_path = "$(path)/$(body.id)"
update_method = "PUT"
delete_path = "$(path)/$(body.id)"
delete_method = "DELETE"
}
data "restful_resource" "vpn_01_gateway_status" {
provider = restful.stackit
id = "${restful_resource.vpn_01_gateway.id}/status"
}
resource "random_password" "vpn_psk" {
length = 32
special = false
}
# GCP VPC and Subnet
resource "google_compute_network" "gcp_vpc" {
name = "gcp-vpn-network"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "gcp_subnet" {
name = "gcp-vpn-subnet"
ip_cidr_range = "10.11.0.0/16"
region = "europe-west4"
network = google_compute_network.gcp_vpc.id
}
# GCP HA VPN Gateway
resource "google_compute_ha_vpn_gateway" "gcp_gateway" {
name = "gcp-ha-vpn"
network = google_compute_network.gcp_vpc.id
region = "europe-west4"
}
# GCP Cloud Router (for BGP)
resource "google_compute_router" "gcp_router" {
name = "gcp-router"
network = google_compute_network.gcp_vpc.name
region = "europe-west4"
bgp {
asn = 64513 # GCP's local ASN
}
}
# GCP External VPN Gateway (Represents STACKIT in GCP)
resource "google_compute_external_vpn_gateway" "stackit_gateway" {
name = "stackit-external-gw"
redundancy_type = "TWO_IPS_REDUNDANCY"
description = "STACKIT VPN Gateway"
# Fetching the public IPs from STACKIT
interface {
id = 0
ip_address = data.restful_resource.vpn_01_gateway_status.output.tunnels[0].publicIP
}
interface {
id = 1
ip_address = data.restful_resource.vpn_01_gateway_status.output.tunnels[1].publicIP
}
}
# GCP VPN Tunnels
resource "google_compute_vpn_tunnel" "gcp_tunnel1" {
name = "gcp-tunnel-1"
region = "europe-west4"
vpn_gateway = google_compute_ha_vpn_gateway.gcp_gateway.id
peer_external_gateway = google_compute_external_vpn_gateway.stackit_gateway.id
peer_external_gateway_interface = 0
shared_secret = random_password.vpn_psk.result
router = google_compute_router.gcp_router.id
vpn_gateway_interface = 0
}
resource "google_compute_vpn_tunnel" "gcp_tunnel2" {
name = "gcp-tunnel-2"
region = "europe-west4"
vpn_gateway = google_compute_ha_vpn_gateway.gcp_gateway.id
peer_external_gateway = google_compute_external_vpn_gateway.stackit_gateway.id
peer_external_gateway_interface = 1
shared_secret = random_password.vpn_psk.result
router = google_compute_router.gcp_router.id
vpn_gateway_interface = 1
}
# GCP Cloud Router Interfaces & BGP Peers
resource "google_compute_router_interface" "gcp_router_interface1" {
name = "gcp-interface-1"
router = google_compute_router.gcp_router.name
region = "europe-west4"
ip_range = "169.254.0.2/30" # GCP's local BGP IP
vpn_tunnel = google_compute_vpn_tunnel.gcp_tunnel1.name
}
resource "google_compute_router_peer" "gcp_router_peer1" {
name = "gcp-peer-1"
router = google_compute_router.gcp_router.name
region = "europe-west4"
peer_ip_address = "169.254.0.1" # STACKIT's local BGP IP
peer_asn = 64512 # STACKIT's ASN
advertised_route_priority = 100
interface = google_compute_router_interface.gcp_router_interface1.name
}
resource "google_compute_router_interface" "gcp_router_interface2" {
name = "gcp-interface-2"
router = google_compute_router.gcp_router.name
region = "europe-west4"
ip_range = "169.254.1.2/30"
vpn_tunnel = google_compute_vpn_tunnel.gcp_tunnel2.name
}
resource "google_compute_router_peer" "gcp_router_peer2" {
name = "gcp-peer-2"
router = google_compute_router.gcp_router.name
region = "europe-west4"
peer_ip_address = "169.254.1.1"
peer_asn = 64512
advertised_route_priority = 100
interface = google_compute_router_interface.gcp_router_interface2.name
}
# Connection from STACKIT to GCP
resource "restful_resource" "vpn_01_connection" {
provider = restful.stackit
path = "${restful_resource.vpn_01_gateway.id}/connections"
body = {
displayName = "conn-to-gcp"
tunnel1 = {
bgp = {
remoteAsn = 64513
}
peering = {
localAddress = "169.254.0.1"
remoteAddress = "169.254.0.2"
}
phase1 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
phase2 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
preSharedKey = random_password.vpn_psk.result
remoteAddress = google_compute_ha_vpn_gateway.gcp_gateway.vpn_interfaces[0].ip_address
}
tunnel2 = {
bgp = {
remoteAsn = 64513
}
peering = {
localAddress = "169.254.1.1"
remoteAddress = "169.254.1.2"
}
phase1 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
phase2 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
preSharedKey = random_password.vpn_psk.result
remoteAddress = google_compute_ha_vpn_gateway.gcp_gateway.vpn_interfaces[1].ip_address
}
}
lifecycle {
ignore_changes = [
body.tunnel1.preSharedKey,
body.tunnel2.preSharedKey
]
}
read_path = "$(path)/$(body.id)"
update_path = "$(path)/$(body.id)"
update_method = "PUT"
delete_path = "$(path)/$(body.id)"
delete_method = "DELETE"
}
# GCP Test VM & Firewall Rules
# Firewall: Allow Identity-Aware Proxy (IAP) to SSH into the VM
resource "google_compute_firewall" "allow_iap_ssh" {
name = "allow-iap-ssh"
network = google_compute_network.gcp_vpc.name
allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = ["35.235.240.0/20"]
target_tags = ["test-vm"]
}
# Firewall: Allow STACKIT to ping/SSH into the GCP VM over the VPN
resource "google_compute_firewall" "allow_stackit_vpn_traffic" {
name = "allow-stackit-vpn-traffic"
network = google_compute_network.gcp_vpc.name
allow {
protocol = "icmp"
}
allow {
protocol = "tcp"
ports = ["22"]
}
# Your STACKIT SNA range
source_ranges = ["10.10.0.0/16"]
target_tags = ["test-vm"]
}
# GCP Virtual Machine
resource "google_compute_instance" "gcp_test_vm" {
name = "gcp-vpn-test-vm"
machine_type = "e2-micro"
zone = "europe-west4-a"
tags = ["test-vm"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-12"
}
}
network_interface {
subnetwork = google_compute_subnetwork.gcp_subnet.id
# Omitting the 'access_config' block ensures this VM gets NO public IP address.
}
}
# Outputs
output "vpn01_public_ip" {
value = module.vpn_sna_01.machine_public_ip
}
output "vpn01_private_ip" {
value = module.vpn_sna_01.machine_private_ipv4
}
output "gcp_test_vm_private_ip" {
value = google_compute_instance.gcp_test_vm.network_interface[0].network_ip
}
output "gcp_iap_command" {
value = "gcloud compute ssh ${google_compute_instance.gcp_test_vm.name} --tunnel-through-iap"
}

View file

@ -1,9 +0,0 @@
# Maintainers
General maintainers:
- Mauritz Uphoff (mauritz.uphoff@digits.schwarz)
This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis.
For questions, issues, or feature requests, please email general maintainers.
Please include the BP name and version in your request. We will track your request as an issue.

View file

@ -1,48 +0,0 @@
# STACKIT-to-GCP HA VPN Gateway
This example demonstrates how to establish a secure, Highly Available (HA) IPsec VPN connection between a STACKIT Network Area (SNA) and Google Cloud Platform (GCP).
The connection uses **BGP (Border Gateway Protocol)** via a GCP Cloud Router to automatically exchange and propagate routes dynamically between the two cloud environments.
## Architecture
This Terraform configuration provisions the following resources:
- **STACKIT:** An SNA, a debug machine, and an HA VPN Gateway (`ASN 64512`).
- **GCP:** A VPC, a Subnet (`europe-west4`), an HA VPN Gateway, a Cloud Router (`ASN 64513`), and a private Debian test VM.
- **VPN Connection:** Two redundant IPsec tunnels using dynamically generated PSKs and Link-Local BGP peering (`169.254.x.x/30`).
- **Security:** GCP Firewall rules configured to allow Identity-Aware Proxy (IAP) SSH access and inbound ICMP/SSH traffic from the STACKIT network.
## Prerequisites
- Configured STACKIT and GCP provider credentials.
- Google Cloud SDK (`gcloud` CLI) installed and authenticated for IAP testing.
## How to Test the Connection
Once `terraform apply` is complete, check the generated outputs. You can verify the bi-directional tunnel is fully operational by following these steps:
### 1. Test from GCP to STACKIT
Connect to the private GCP VM using Google's Identity-Aware Proxy (IAP) and ping the STACKIT debug machine.
```bash
# 1. SSH into the GCP test VM (copy this from the `gcp_iap_command` output)
gcloud compute ssh gcp-vpn-test-vm --zone=europe-west4-a --tunnel-through-iap
# 2. Ping the STACKIT private IP (copy from the `vpn01_private_ip` output)
ping <vpn01_private_ip>
```
### 2. Test from STACKIT to GCP
Connect to the STACKIT debug machine using its public IP, then ping the private GCP VM across the VPN tunnel.
```Bash
# 1. SSH into the STACKIT debug machine
ssh debug@<vpn01_public_ip>
# password debug123
# 2. Ping the GCP private IP (copy from the `gcp_test_vm_private_ip` output)
ping <gcp_test_vm_private_ip>
```

View file

@ -1,87 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/random" {
version = "3.8.1"
hashes = [
"h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=",
"zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4",
"zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae",
"zh:229665ddf060aa0ed315597908483eee5b818a17d09b6417a0f52fd9405c4f57",
"zh:2469d2e48f28076254a2a3fc327f184914566d9e40c5780b8d96ebf7205f8bc0",
"zh:37d7eb334d9561f335e748280f5535a384a88675af9a9eac439d4cfd663bcb66",
"zh:741101426a2f2c52dee37122f0f4a2f2d6af6d852cb1db634480a86398fa3511",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:a902473f08ef8df62cfe6116bd6c157070a93f66622384300de235a533e9d4a9",
"zh:b85c511a23e57a2147355932b3b6dce2a11e856b941165793a0c3d7578d94d05",
"zh:c5172226d18eaac95b1daac80172287b69d4ce32750c82ad77fa0768be4ea4b8",
"zh:dab4434dba34aad569b0bc243c2d3f3ff86dd7740def373f2a49816bd2ff819b",
"zh:f49fd62aa8c5525a5c17abd51e27ca5e213881d58882fd42fec4a545b53c9699",
]
}
provider "registry.terraform.io/magodo/restful" {
version = "0.25.2"
hashes = [
"h1:gvoDTFfxp7n1B4Wsnx9IC7Ku8g8tdVR4mCC6TDX0Mws=",
"zh:0513ff62fce41a59462f39e1c4636f3c87e6f8d24ee579075900d3e0f57f6992",
"zh:1a3e39e6b8c7fd0f3983730944a029db8f00557922e337cff0567a07c5e74b45",
"zh:2527c96fcc45458efc9eca1c66cee98269d80693b571c57baee783402bfbaa28",
"zh:50cec9afe8b55629d1c94d477b26ff95de8cc8e3304f6c2bfc5dad3bccc6decc",
"zh:89e94c0f312d0ef4213b46ee776a27f6a5d114520c08a4716f4fee4c26c16f91",
"zh:9a9762ebaf9567a4aa34a1911f051527696241679e087137fcc7821e52b66483",
"zh:a065be3488e24928199904f4a496974c03fdcf2b06fccf016e405b3068d5ef76",
"zh:c62a1a6fb3c5135451f68ea4ed1f66d999ab654323d10526756e83f6f77d6bdf",
"zh:cf01364f89b713dc10eb87098839317e6f2de222bec2597923cddbb07bdd9c13",
"zh:dc0ac6a1e5e3199e1d35fb49f9de1d9325caa3c0d3e87ea8128295e19ac941c3",
"zh:e55cf6e8230f081b7c8ade592c14f1b8b45ee0aaa14c2bde2da9531d819a4392",
"zh:f333748916e68050c8935d760d6b9b469dd76eb94363af93562cbd076dba6ff5",
"zh:f809ab383cca0a5f83072981c64208cbd7fa67e986a86ee02dd2c82333221e32",
"zh:fdfdca8b7976c1a8b1b6a3589b4bfec277beb6dfb40c5568271d42f0b2f88a9d",
]
}
provider "registry.terraform.io/mastercard/restapi" {
version = "3.0.0"
constraints = ">= 3.0.0"
hashes = [
"h1:y1I3azDHOqRySTyDHsb3Xh1waP/99KfykZRagbRx1qI=",
"zh:0b63bd3c25a31f090a41933f90b7dd6e984add1c4261d8f5caa73f4d5aa065a4",
"zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7",
"zh:2d31f322454d271eb328c2d3b3d41f426df98503982788be347799ddf68bf9bf",
"zh:47dd97e3f43bb89ae4254bba90ffbc6d521338554a1f94961e21214dd801b81b",
"zh:49636b072b9a30d15916468857bce91d39bc87bbba1c99fb3894fafa9409b8b4",
"zh:5566605a8e16478bc66c1fec8dea0890586c084221161dc82b73d162d44c08a7",
"zh:5859e0ad05aa6b3b108f0b718986e237a18d5176efea62d1ac1ef352561b4713",
"zh:76129b89e2b56d8d2af8f6e10cc748bea4ee6ec1105e916f1254cd124f4dcf9c",
"zh:bfc20b5fd03cb3243917e8cf360e5208284e757ab82f83c992da471ef16a0eab",
"zh:d1d2363009253cdfe5795a48b6412bff11104fe6a52fb0a57e5a95fc765a161e",
"zh:d1f0b981089ad709b73c4f989a9cd9118c4e3cb8fc0a2b303aa4d77cc5102a53",
"zh:dbfddb2f407481a4e88fdc17739c805d9d9fff2451efcb9226572d59ed2e9128",
"zh:df04a8c777d05896684171807b27c41befbf5f217f50b0e9b2b27164d4aacca5",
"zh:e68b450c66efe55d1132585477fa71207680806edafb3792ca44d9695d0a1d75",
"zh:f894e7e9913347e25e67d5d3bf91659c06877dd5fa11acf75820fa03fa34b8bd",
]
}
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.95.0"
constraints = ">= 0.66.0"
hashes = [
"h1:sKmc6SGKEFglXKLMtOluJkFm7tzQZKQV3/QxUbHug1E=",
"zh:023edbb8ca984233bb51605a9005d4f7cb3365f0b11ddd68d911a1e30ccf64be",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:1fc43ed3055c4912e5b3ae2eba49dd5407beaa9ba6617612f317543f7d26ccd7",
"zh:31e587a9f279661b74b139e2a964a7d1c54a4073d27d21c2f948e0e7ba4c0d04",
"zh:37427a23800dff84c1b89d4985cb935c0112c59acd716d8920c160221c459061",
"zh:3a575f5c7d1252d99aea9187923087e1d483b2b34e42c9f058f557ec28c45d84",
"zh:44c7ee340e1a09d6f9a9873959f8283f0d73aee4a8c884f7b36985f943874b65",
"zh:4fab8fe953a0d4c21589cd36d23afe072c6403e37620c82839f9f829139cbbbf",
"zh:69fc061b3c7ea82d9e9a31d3665a535f6bb9dc3d6ff5b466f940d3d04a105e19",
"zh:85ee00442eff70ea103a96276efb5e1485b661b0a1db08bcdbd28b11b1f966e6",
"zh:9761ef1321c93cb3e4bc2499995b3e7ae910e2ae68b3228164dea73e9687ddb5",
"zh:b158a4e4726a4d4c9f61c5dc71abb4ca3a621269e1d7af88ab36d34c3bcec66f",
"zh:da37df9a426d83da8f6c1340104a6b9a7eef4a7e2589d0b70a89c574a1b3cc78",
"zh:e6421b9a351b2c9b2ab2341f2c07d863eb2ed055b847ea839de96b0fd62baf97",
]
}

View file

@ -1,50 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">=0.95.0"
}
restapi = {
source = "Mastercard/restapi"
version = ">= 3.0.0"
}
restful = {
source = "magodo/restful"
}
}
}
provider "stackit" {
default_region = var.stackit_region
service_account_key_path = var.stackit_service_account_key_path
enable_beta_resources = true
experiments = ["iam"]
}
ephemeral "stackit_access_token" "this" {}
provider "restful" {
alias = "stackit"
base_url = "https://vpn.api.eu01.stackit.cloud"
security = {
http = {
token = {
token = ephemeral.stackit_access_token.this.access_token
}
}
}
}

View file

@ -1,32 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# load via *.auto.tfvars
variable "stackit_org_id" {
type = string
}
variable "stackit_region" {
type = string
default = "eu01"
}
variable "stackit_service_account_key_path" {
type = string
}
variable "stackit_admin_email" {
type = string
}

View file

@ -1,255 +0,0 @@
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module "vpn_sna_01" {
source = "../module/stackit-sna-with-debug-machine"
machine_availability_zone = "eu01-1"
machine_ipv4_prefix = "10.10.10.0/24"
machine_network_name = "vpn-sna-01"
sna_name = "vpn-sna-01"
machine_name = "vpn-sna-01"
stackit_admin_email = var.stackit_admin_email
stackit_org_id = var.stackit_org_id
stackit_project_name = "vpn-sna-01"
sna_network_range_prefix = [
"10.10.0.0/16"
]
}
module "vpn_sna_02" {
source = "../module/stackit-sna-with-debug-machine"
machine_availability_zone = "eu01-2"
machine_ipv4_prefix = "10.11.11.0/24"
machine_network_name = "vpn-sna-02"
machine_name = "vpn-sna-02"
sna_name = "vpn-sna-02"
stackit_admin_email = var.stackit_admin_email
stackit_org_id = var.stackit_org_id
stackit_project_name = "vpn-sna-02"
sna_network_range_prefix = [
"10.11.0.0/16"
]
}
# Gateway 1 (vpn-sna-01)
resource "restful_resource" "vpn_01_gateway" {
provider = restful.stackit
path = "/v1/projects/${module.vpn_sna_01.project_id}/regions/eu01/gateways"
body = {
availabilityZones = {
tunnel1 = "eu01-1"
tunnel2 = "eu01-2"
}
bgp = {
localAsn = 64512
overrideAdvertisedRoutes = ["10.10.0.0/16"]
}
displayName = "vpn01"
labels = null
planId = "p500"
routingType = "BGP_ROUTE_BASED"
}
read_path = "$(path)/$(body.id)"
update_path = "$(path)/$(body.id)"
update_method = "PUT"
delete_path = "$(path)/$(body.id)"
delete_method = "DELETE"
}
data "restful_resource" "vpn_01_gateway_status" {
provider = restful.stackit
id = "${restful_resource.vpn_01_gateway.id}/status"
}
# Gateway 2 (vpn-sna-02)
resource "restful_resource" "vpn_02_gateway" {
provider = restful.stackit
path = "/v1/projects/${module.vpn_sna_02.project_id}/regions/eu01/gateways"
body = {
availabilityZones = {
tunnel1 = "eu01-1"
tunnel2 = "eu01-2"
}
bgp = {
localAsn = 64513
overrideAdvertisedRoutes = ["10.11.0.0/16"]
}
displayName = "vpn02"
labels = null
planId = "p500"
routingType = "BGP_ROUTE_BASED"
}
read_path = "$(path)/$(body.id)"
update_path = "$(path)/$(body.id)"
update_method = "PUT"
delete_path = "$(path)/$(body.id)"
delete_method = "DELETE"
}
data "restful_resource" "vpn_02_gateway_status" {
provider = restful.stackit
id = "${restful_resource.vpn_02_gateway.id}/status"
}
# Shared VPN Credentials
resource "random_password" "vpn_psk" {
length = 32
special = false
}
# Connection from Gateway 1 to Gateway 2
resource "restful_resource" "vpn_01_connection" {
provider = restful.stackit
path = "${restful_resource.vpn_01_gateway.id}/connections"
body = {
displayName = "conn-to-vpn02"
tunnel1 = {
bgp = {
remoteAsn = 64513
}
peering = {
localAddress = "169.254.0.1"
remoteAddress = "169.254.0.2"
}
phase1 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
phase2 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
preSharedKey = random_password.vpn_psk.result
remoteAddress = data.restful_resource.vpn_02_gateway_status.output.tunnels[0].publicIP
}
tunnel2 = {
bgp = {
remoteAsn = 64513
}
peering = {
localAddress = "169.254.1.1"
remoteAddress = "169.254.1.2"
}
phase1 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
phase2 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
preSharedKey = random_password.vpn_psk.result
remoteAddress = data.restful_resource.vpn_02_gateway_status.output.tunnels[1].publicIP
}
}
lifecycle {
ignore_changes = [
body.tunnel1.preSharedKey,
body.tunnel2.preSharedKey
]
}
read_path = "$(path)/$(body.id)"
update_path = "$(path)/$(body.id)"
update_method = "PUT"
delete_path = "$(path)/$(body.id)"
delete_method = "DELETE"
}
# Connection from Gateway 2 to Gateway 1
resource "restful_resource" "vpn_02_connection" {
provider = restful.stackit
path = "${restful_resource.vpn_02_gateway.id}/connections"
body = {
displayName = "conn-to-vpn01"
tunnel1 = {
bgp = {
remoteAsn = 64512
}
peering = {
localAddress = "169.254.0.2"
remoteAddress = "169.254.0.1"
}
phase1 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
phase2 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
preSharedKey = random_password.vpn_psk.result
remoteAddress = data.restful_resource.vpn_01_gateway_status.output.tunnels[0].publicIP
}
tunnel2 = {
bgp = {
remoteAsn = 64512
}
peering = {
localAddress = "169.254.1.2"
remoteAddress = "169.254.1.1"
}
phase1 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
phase2 = {
dhGroups = ["modp2048"]
encryptionAlgorithms = ["aes256gcm16"]
integrityAlgorithms = ["sha2_256"]
}
preSharedKey = random_password.vpn_psk.result
remoteAddress = data.restful_resource.vpn_01_gateway_status.output.tunnels[1].publicIP
}
}
read_path = "$(path)/$(body.id)"
update_path = "$(path)/$(body.id)"
update_method = "PUT"
delete_path = "$(path)/$(body.id)"
delete_method = "DELETE"
lifecycle {
ignore_changes = [
body.tunnel1.preSharedKey,
body.tunnel2.preSharedKey
]
}
}
output "vpn01_public_ip" {
value = module.vpn_sna_01.machine_public_ip
}
output "vpn01_private_ip" {
value = module.vpn_sna_01.machine_private_ipv4
}
output "vpn02_public_ip" {
value = module.vpn_sna_02.machine_public_ip
}
output "vpn02_private_ip" {
value = module.vpn_sna_02.machine_private_ipv4
}

View file

@ -1,9 +0,0 @@
# Maintainers
General maintainers:
- Mauritz Uphoff (mauritz.uphoff@digits.schwarz)
This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis.
For questions, issues, or feature requests, please email general maintainers.
Please include the BP name and version in your request. We will track your request as an issue.

View file

@ -1,21 +0,0 @@
# STACKIT-to-STACKIT VPN Gateway
This example leverages the STACKIT VPN service to establish a secure, Highly Available (HA) connection between two separate STACKIT Network Areas (SNAs).
The connection utilizes **BGP (Border Gateway Protocol)** to automatically propagate and learn routing information between the two networks.
> **Note:** Currently, native SNA peering is not available in STACKIT. Therefore, provisioning a VPN connection is the required method to interconnect two SNAs. This will change in the future once native SNA peering is released.
![Architecture Diagram](docs/architecture.png)
## How to Test the Connection
Once the deployment is complete, you can verify the VPN tunnel using the provisioned debug machines:
1. **SSH** into the first debug machine using its public IP (`vpn01_public_ip`).
2. **Ping** the private IP of the second debug machine (`vpn02_private_ip`) across the tunnel.
```bash
# Example test command once connected to the vpn01 machine via SSH
ping <vpn02_private_ip>
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

View file

@ -15,70 +15,40 @@
variable "project_id" {
description = "The STACKIT Project ID"
type = string
validation {
condition = can(regex("^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$", var.project_id))
error_message = "The project_id must be a valid UUID."
}
}
variable "network_id" {
description = "The Network ID (UUID) where the machine should be spawned"
type = string
validation {
condition = can(regex("^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$", var.network_id))
error_message = "The network_id must be a valid UUID."
}
}
variable "name" {
description = "Hostname of the server"
type = string
default = "test-machine"
validation {
condition = can(regex("^[a-z0-9-]+$", var.name))
error_message = "The machine name must contain only lowercase letters, numbers, and hyphens."
}
}
variable "availability_zone" {
description = "The availability zone (e.g. eu01-1)"
type = string
validation {
condition = can(regex("^[a-z]{2}[0-9]{2}-[a-zA-Z0-9]+$", var.availability_zone))
error_message = "The availability zone must follow the STACKIT pattern (e.g., eu01-1, eu01-m)."
}
}
variable "machine_type" {
description = "Flavor of the machine"
type = string
default = "c2i.1"
default = "g1.1"
}
variable "image_id" {
description = "Image UUID (Default: Debian 12)"
type = string
default = "c751cde7-e648-4f81-9722-ce9c7848bed0"
validation {
condition = can(regex("^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$", var.image_id))
error_message = "The image_id must be a valid UUID."
}
}
variable "disk_size" {
description = "Boot volume size in GB"
type = number
default = 50
validation {
condition = var.disk_size >= 1
error_message = "The disk_size must be at least 1 GB."
}
}
variable "disk_performance_class" {