EU sovereignty is a hot topic, we’ve already written about the OCI EU sovereign cloud, but we also wanted to investigate a cloud that’s purely based in Europe and with a strong backing company. We choose to investigate StackIT.de.
About StackIT
StackIT is part of Schwartz Group, parent of the large LIDL supermarket chain. StackIT wants to provide digital sovereignty based on Open Source software. It’s cloud solution seems to be based on OpenStack. While we were exploring StackIT we found almost weekly there were new services being added or improved. StackIT is mostly focussed on the DACH (Germany, Austria and Switzerland) region, however with some manual labour by the StackIT sales team, non-DACH companies can also become customer. StackIT is (currently?) not available for private persons.
Your identity within StackIT
Within StackIT a customer gets a Customer Account, this is the basis for the billing and administration. Below the Customer Account one or more Projects can be created. Identities for administrators are created at the Customer account level or Project level. Accounts at the higher level can be granted access to projects. Cloud resources are located inside a project. There are some basic rights an Administrator can grant to other people, like owner, editor or reader, but more specific rights or roles can also granted to people. Having access to a project makes it possible for a person to create a service-account for themselves. This service account can be used to authenticate Terraform or a cli tool.
Available services within StackIT
With the risk that the information written here is outdated before even publishing it we like to give an overview of available services at StackIT:
- IaaS VM (called compute engine)
- Networking
- Storage: Object storage (S3 compatible), NFS, Block storage
- Databases (and search): PostgreSQL, Mariadb, MSSQL server, OpenSearch, Redis, MongoDB
- App platforms: Kubernetes, Cloud Foundry, managed git, container registry
- Logging + Monitoring: Observability + Logme: both based on open source solutions
- AI model services
- Workflows (based on Apache Airflow)
Getting started
After a customer account was created for us (It involved some administrative work), we could create a Project within our account. As owner of the customer account you’re also the owner of the created project. This gives you the right to add more administrators, and of course to create resources. First step after logging on to the cloud portal at https://portal.stackit.cloud/ is to create a service account so we can use terraform to make the resources. A service account can be then granted a role within the project. To be able to authenticate using a service account, a service account key needs to be created. Save this key in a safe place and note that this key is shown only once.
Creating a resource can be done using the StackIT portal, Terraform or the StackIT cli. Doing it via the StackIT portal gives you immediate feedback about the incurred cost. (You can use of course a cost calculator too.) As one of our requirements was to be able to use Terraform to deploy infrastructure, we’ll further explore that part.
Creating some infrastructure
Lets start with creating an object storage bucket at StackIT to save the terraform state: The StackIT terraform provider supports having your state file on StackIT object storage. For this PoC we created the storage bucket manually.
terraform {
backend "s3" {
bucket = "amis-terraform-state"
key = "AMISProject2Public"
endpoints = {
s3 = "https://object.storage.eu01.onstackit.cloud"
}
region = "eu01"
skip_credentials_validation = true
skip_region_validation = true
skip_s3_checksum = true
skip_requesting_account_id = true
secret_key = "xxx"
access_key = "yyy”
}
}
provider "stackit" {
default_region = "eu01"
service_account_key_path = "/path/to/StackIT/stackit-service-account.json"
enable_beta_resources = true
}
With the above terraform configuration, terraform will save the state in a s3 compatible object storage on Stackit.cloud. Additionally, we’ve enabled beta-resources in the provider. Certain items we like to use are in beta stage.
Creating a network and IaaS vm
A network can be created within a Project. Whenever a network is created some cost is incurred as each network automatically gets an external (Public) IP address.
resource "stackit_network" "netwerk-app" {
project_id = var.stackit_project_id
name = "Netwerk-App"
ipv4_nameservers = ["1.1.1.1", "8.8.8.8"]
ipv4_prefix = "10.94.1.0/24"
routed = true
labels = {
"status" = "POC"
}
}
A project_id is a required argument on most resources. We can add nameservers, an IPv4 prefix and some labels to the network.
Create a network security group to set some base access rules so we can access our VM:
resource "stackit_security_group" "app_sg" {
project_id = var.stackit_project_id
name = "Application_security_group"
}
resource "stackit_security_group_rule" "inbound_from_amis_office" {
project_id = var.stackit_project_id
security_group_id = stackit_security_group.app_sg.security_group_id
direction = "ingress"
# protocol = {
# name = "tcp"
# }
# port_range = {
# min = 22
# max = 22
# }
ip_range = "192.168.32.6/32"
}
resource "stackit_security_group_rule" "inbound_from_martijns_home" {
project_id = var.stackit_project_id
security_group_id = stackit_security_group.app_sg.security_group_id
direction = "ingress"
ip_range = "127.0.0.1/32"
}
resource "stackit_security_group_rule" "inbound_from_internal" {
project_id = var.stackit_project_id
security_group_id = stackit_security_group.app_sg.security_group_id
direction = "ingress"
ip_range = "10.94.0.0/16"
}
To create a vm, some requirements need to be met, a network interface needs to be created in the network created earlier, a ssh key needs to be available (so one can access the vm) and a boot image needs to be choosen. We can use a datasource for that, but watch out for updates.
data "stackit_image_v2" "Rocky" {
project_id = var.project_id
name = "Rocky Linux 10"
}
# create a network interface:
resource "stackit_network_interface" "interface" {
project_id = var.project_id
network_id = var.network_id
security_group_ids = var.security_groups_ids
}
# a ssh public key object:
resource "stackit_key_pair" "mykey" {
name = "martijns_key"
public_key = chomp(file("path/to/my/pubkey.pub"))
}
Combining this all into a server resource
resource "stackit_server" "server" {
project_id = var.project_id
name = var.server_name
boot_volume = {
size = var.boot_disk_size
source_type = "image"
source_id = data.stackit_image_v2.Rocky.image_id
performance_class = var.boot_disk_perf_class
}
availability_zone = var.availability_zone
machine_type = var.machine_type
keypair_name = stackit_key_pair.mykey.name
network_interfaces = [stackit_network_interface.interface.network_interface_id]
lifecycle {
ignore_changes = [
boot_volume.source_id
]
}
}
Finally, if we need a public ip address added for a server (to be able to reach it):
resource "stackit_public_ip" "publicip" {
network_interface_id = stackit_network_interface.interface.network_interface_id
}
output "public_ip_address" { value = stackit_public_ip.publicip[0].ip }
With these resources a complete VM with a public ip address is made available. StackIT provides documentation about the provided VM images, so read there how you can login to your VM.
Create a DBaaS database
StackIT supports the creation of a database using Terraform. In the next example we create a PostgreSQL database instance, a database and a database user. Lets go straight to the Terraform code:
resource "stackit_postgresflex_instance" "postgres1" {
project_id = var.stackit_project_id
name = "postgres1"
acl = [ "${module.my-compute-01.public_ip_address}/32" ]
replicas = 1
version = 17
backup_schedule = "0 10 * * *"
flavor = {
cpu = 2
ram = 4
}
storage = {
class = "premium-perf2-stackit"
size = 5
}
}
resource "stackit_postgresflex_user" "mydb_user" {
project_id = var.stackit_project_id
instance_id = stackit_postgresflex_instance.postgres1.instance_id
username = "myuser"
roles = [ "login" ]
}
resource "stackit_postgresflex_database" "mydb" {
project_id = var.stackit_project_id
instance_id = stackit_postgresflex_instance.postgres1.instance_id
owner = "myuser"
name = "mydb"
depends_on = [ stackit_postgresflex_user.mydb_user ]
}
output "db_user_pass" {
value = stackit_postgresflex_user.mydb_user.password
sensitive = true
}
output "database_hostname" {
value = stackit_postgresflex_user.mydb_user.host
}
With the code above we get a minimal database system. Its outputs are the hostname and the password is also saved but not displayed by default as it’s a sensitive value. Make sure to include any (external) ip addresses in the acl to be able to access the database instance.
Unfortunately, unlike other clouds, there is no (as far as we could see) easy way to stop a PostgreSQL database and start it again when needed.
Conclusion
Having a cloud based completely in Europe with European ownership is nice and in the current climate probably essential. With StackIT we can see there are European options that support basic cloud abilities like being able to deploy using Terraform. When there is a requirement to be EU sovereign, and we don’t actually need any of the Hyperscaler’s more advanced PaaS services, this is certainly an option.
