Deploy Serverless Containers to Scaleway with OpenTofu

December 5th, 2025 721 Words

After building multiarch Docker containers for Rust applications, you want to deploy them somewhere. Scaleway’s serverless container platform offers a straightforward way to run containers without managing infrastructure, and OpenTofu provides the infrastructure-as-code tooling. This guide walks through deploying Docker containers to Scaleway using the OpenTofu provider, from setting up the registry to running your container.

Prerequisites

Before we start, you’ll need:

Installing OpenTofu

OpenTofu is an open-source fork of Terraform that provides infrastructure-as-code capabilities.

# Install OpenTofu on macOS with Homebrew
$ > brew install opentofu

Let’s verify the installation worked:

$ > tofu version

OpenTofu v1.9.0
on darwin_arm64

Setting Up Scaleway Credentials

First things first, you’ll need to create API credentials in the Scaleway console. Once you’ve got them, we can store them as environment variables.

$ > export SCW_ACCESS_KEY="your-access-key"
$ > export SCW_SECRET_KEY="your-secret-key"
$ > export SCW_DEFAULT_REGION="fr-par"
$ > export SCW_DEFAULT_PROJECT_ID="your-project-id"
$ > export SCW_DEFAULT_ORGANIZATION_ID="your-organization-id"

This will use the Paris location in France for the running container.

Creating the Container Registry

Next, create an OpenTofu configuration file main.tf for a container registry to store the Docker image

terraform {
  required_providers {
    scaleway = {
      source = "scaleway/scaleway"
      version = "~> 2.64"

    }
  }
  required_version = ">= 0.13"
}

provider "scaleway" { }

resource "scaleway_container_namespace" "main" {
  name        = "rocket-example"
  description = "test container"
}

output "container_registry" {
  value       = "${scaleway_container_namespace.main.registry_endpoint}"
  description = "Registry endpoint for the container"
}

Now let’s initialise OpenTofu and plan the registry:

$ > tofu init
[]

OpenTofu has been successfully initialised!

$ > tofu plan
[]

Have a quick look at the plan to see what’ll be created, then apply it:

$ > tofu apply tfplan
scaleway_registry_namespace.main: Creating...
scaleway_registry_namespace.main: Creation complete after 2s

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

container_registry = "rg.fr-par.scw.cloud/funcscwrocketexampler5etvjil"

The container registry is needed in the next step for tagging and pushing the Docker container.

Building and Pushing Docker Images

With the registry created, we can now build and push the Docker image. For Scaleway, you’ll need to push a architecture-specific image for amd64 platform. Here’s how to do it:

# Build for ARM64 (Scaleway only supports amd64)
$ > docker build \
    --platform linux/amd64 \
    -f Dockerfile . \
    -t rg.fr-par.scw.cloud/funcscwrocketexampler5etvjil/application:latest-amd64

# Authenticate with Scaleway registry using the CLI
$ > scw registry login

The CLI generates a temporary token and configures Docker authentication automatically. Once that’s done, you can push the image:

$ > docker push rg.fr-par.scw.cloud/funcscwrocketexampler5etvjil/application:latest-amd64

Deploying the Container

Now comes deploying the container; add the container resource to the OpenTofu configuration. Here’s the updated main.tf with the container:

terraform {
  required_providers {
    scaleway = {
      source = "scaleway/scaleway"
      version = "~> 2.64"

    }
  }
  required_version = ">= 0.13"
}

provider "scaleway" { }

resource "scaleway_container_namespace" "main" {
  name        = "rocket-example"
  description = "test container"
}

output "container_registry" {
  value       = "${scaleway_container_namespace.main.registry_endpoint}"
  description = "Registry endpoint for the container"
}

resource "scaleway_container" "main" {
  name         = "application"
  namespace_id = scaleway_container_namespace.main.id
  registry_image  = "${scaleway_container_namespace.main.registry_endpoint}/application:latest-amd64"
  port         = 8080
  cpu_limit    = 256
  memory_limit = 512
  min_scale    = 1
  max_scale    = 1

  environment_variables = {
    ROCKET_LOG_LEVEL = "debug"
    ROCKET_ADDRESS   = "0.0.0.0"
    ROCKET_PORT      = "8080"
  }

  privacy = "public"
  deploy  = true
}

output "container_url" {
  value       = scaleway_container.main.domain_name
  description = "Public URL for the container"
}

Apply the configuration and watch it deploy:

$ > tofu apply
scaleway_container_namespace.main: Creating...
scaleway_container_namespace.main: Creation complete after 2s
scaleway_container.main: Creating...
scaleway_container.main: Creation complete after 15s

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

container_registry = "rg.fr-par.scw.cloud/funcscwrocketexampler5etvjil"
container_url = "rocketexampler5etvjil-application.functions.fnc.fr-par.scw.cloud"

Verifying the Deployment

Time to see if everything’s working! Let’s test the deployed container:

$ > curl https://rocketexampler5etvjil-application.functions.fnc.fr-par.scw.cloud/
Hello, World! API is running.

You can also check the container status using the Scaleway CLI:

$ > scw container container list

ID                                    NAME         NAMESPACE ID                          STATUS  MIN SCALE
0e118806-70a4-43c9-9794-7cf35fdd943d  application  e10e600c-b00c-452c-923a-1d6e1552cff5  ready   1

Cleanup

When you’re done experimenting or need to clean up, removing all resources is straightforward:

$ > tofu destroy

This removes the container and registry namespace.

That’s It! 🎉

Working with Scaleway and OpenTofu for container deployments was a nice journey; still prefer a programmatic approach like the AWS Cloud Development Kit over OpenTofu and Terraform. But it works …


  • Multiarch Docker Containers with Rust

    December 5 th, 2025 395 Words

    This guide shows how to build multiarch Docker containers for Rust applications using cargo zigbuild for cross-compilation and Docker build commands for architecture-specific or multiarch container images. Based on the example for Building a Rust API with Rocket and JWT Authentication, this guide provides the next steps.

  • Building a Rust API with Rocket and JWT Authentication

    December 5 th, 2025 1868 Words

    When building backend APIs, JWT authentication is a common requirement. In Rust, you’ve got several web frameworks to choose from, and Rocket is one that makes request handling feel natural with its request guard system. Combining Rocket with JWTiny for JWT validation and JWKServe as a local identity provider gives you a complete setup for development and testing without external dependencies.

  • JWTiny: Minimal JWT Validation for Rust

    December 4 th, 2025 1340 Words

    I was learning Rust with an example project that needed JWT validation. The popular jsonwebtoken crate depends on serde, but I wanted miniserde instead. That constraint led me to build my own validator — handling signature verification, claims validation, and remote key fetching, designed for reuse across requests. JWTiny is the result.

  • JWKServe: A Fake JWT Authentication Service for Local Development

    December 4 th, 2025 990 Words

    When writing backend services that validate JWT access tokens, you run into a frustrating problem: you need a real identity provider just to test your authentication logic. With Cognito, Auth0, or other OpenID Connect providers, spinning up an authentication service for local development or CI pipelines adds unnecessary complexity. You need valid signatures and correct claims, not the provider itself. That’s where JWKServe comes in.

  • Static Website Hosting in Europe with Free Services

    June 10 th, 2025 303 Words

    The AWS European Sovereign Cloud is maybe the most interesting developments of the current cloud computing era; having AWS create a dedicated branch for european workloads is the next big move. But, how do you run a static website without using US vendors at all?

  • AWS CDK: Serverless WebService Blueprints

    January 19 th, 2025 113 Words

    The past days have been full of content about serverless workloads with AWS AppSync, Amazon Cognito, and AWS Fargate. This guide wraps up all scenarios and is your starting point if you want to build modern serverless applications with AWS using the Cloud Development Kit (CDK).

  • AWS CDK: AppSync Events API with Cognito for WebSockets and React

    January 19 th, 2025 944 Words

    The Amazon AppSync Events API was recently announced and is a new feature to use a WebSocket API for real-time communication. Based on the Amazon Cognito User Pool with Managed Login and guide for GraphQL Data API in Amazon AppSync, this guide shows you how to add real-time communication to your React application using WebSockets and the Amazon AppSync Events API with Amazon Cognito.