Scaleway provides an object storage service compatible with the S3 API.
Here’s how to configure your bucket via Terraform, though you can also do it directly through the console.
Table of contents:
Note: the var.scw_project
variable contains your project UUID, which you can find in the console.
IAM Permissions Management
First, we’ll create an application
to which we’ll assign permissions and from which we’ll retrieve the key pair for authentication.
Here, I’m granting full permissions (ObjectStorageFullAccess
) for the Object Storage API, but you can be more restrictive if you prefer.
# iam.tf
resource "scaleway_iam_application" "my_app" {
name = "MyApp"
description = "MyApp application"
}
resource "scaleway_iam_api_key" "my_app" {
application_id = scaleway_iam_application.my_app.id
description = "MyApp API Key"
default_project_id = var.scw_project
}
resource "scaleway_iam_policy" "my_app_object_storage" {
name = "MyApp Object Storage"
description = "Gives MyApp full access to object storage"
application_id = scaleway_iam_application.my_app.id
rule {
project_ids = [var.scw_project]
permission_set_names = ["ObjectStorageFullAccess"]
}
}
Add the outputs below to retrieve the authentication key pair:
# outputs.tf
output "my_app_access_key" {
value = scaleway_iam_api_key.my_app.access_key
sensitive = true
}
output "my_app_secret_key" {
value = scaleway_iam_api_key.my_app.secret_key
sensitive = true
}
Bucket creation
Let’s move on to creating the bucket. I’ve added rules to migrate objects between storage classes, but you’re not required to use them. CORS rules are important if you want to use direct uploads.
# object_storage.tf
resource "scaleway_object_bucket" "my_app" {
name = "my_app"
region = "fr-par"
project_id = var.scw_project
tags = {
"Application" = "MyApp"
}
lifecycle_rule {
id = "abort_incomplete_multipart_upload"
enabled = true
abort_incomplete_multipart_upload_days = 7
}
lifecycle_rule {
id = "onezone_ia"
enabled = true
transition {
days = 30
storage_class = "ONEZONE_IA"
}
}
lifecycle_rule {
id = "glacier"
enabled = true
transition {
days = 120
storage_class = "GLACIER"
}
}
cors_rule {
allowed_methods = ["GET", "HEAD", "POST", "PUT", "DELETE"]
allowed_headers = ["*"]
allowed_origins = [
"*"
]
expose_headers = ["ETag"]
max_age_seconds = 3600
}
}
The last thing we need to configure here is the bucket policy to ensure that the application
can access it.
Note that I’ve also added a rule for my own user so I can still access the bucket from the console.
# object_storage.tf
resource "scaleway_object_bucket_policy" "my_app" {
bucket = scaleway_object_bucket.my_app.name
policy = jsonencode({
Id = "my_app",
Version = "2023-04-17",
Statement = [
{
Effect = "Allow"
Action = ["*"]
Principal = { SCW = "application_id:${scaleway_iam_application.my_app.id}" }
Resource = [
scaleway_object_bucket.my_app.name,
"${scaleway_object_bucket.my_app.name}/*",
]
},
{
Effect = "Allow"
Action = ["*"]
Principal = { SCW = "user_id:${var.scw_my_user}" }
Resource = [
scaleway_object_bucket.my_app.name,
"${scaleway_object_bucket.my_app.name}/*",
]
}
]
})
}
Ruby on Rails Configuration
We can now configure Active Storage with our setup.
# config/storage.yml
scaleway:
service: S3
access_key_id: <%= Rails.application.credentials.dig(:scaleway, :access_key) %>
secret_access_key: <%= Rails.application.credentials.dig(:scaleway, :secret_key) %>
region: fr-par
bucket: my_app
endpoint: https://s3.fr-par.scw.cloud
Retrieve the key pair using the commands below:
tf output my_app_access_key
tf output my_app_secret_key
And that’s it!