VPS Snaps

How to use Scaleway Object Storage for server backups

Scaleway Object Storage is S3-compatible storage in Paris, Amsterdam, Warsaw and Milan, at https://s3.<region>.scw.cloud, such as https://s3.fr-par.scw.cloud. As of October 2026, Scaleway's price catalog lists Standard One Zone at €0.000011 per GB-hour, about €8 per 1,000 GB a month, and Standard Multi-AZ at twice that. Keep backups in a Project of their own, give each server an IAM key that can upload and read but not delete, and let lifecycle rules, versioning and Object Lock prune and protect them.

12 min readUpdated Checked against official documentation

Regions, endpoints and storage classes

RegionCodeEndpointStorage classes
Paris, Francefr-parhttps://s3.fr-par.scw.cloudMulti-AZ, One Zone, Glacier
Amsterdam, Netherlandsnl-amshttps://s3.nl-ams.scw.cloudMulti-AZ, One Zone, Glacier
Warsaw, Polandpl-wawhttps://s3.pl-waw.scw.cloudMulti-AZ, One Zone
Milan, Italyit-milhttps://s3.it-mil.scw.cloudOne Zone

A bucket is reached as https://<bucket>.s3.fr-par.scw.cloud or, path-style, https://s3.fr-par.scw.cloud/<bucket>. Names are unique across all of Scaleway, in every region, and use lowercase letters, digits and hyphens. Avoid dots: they break the HTTPS certificate in the first form.

ClassS3 nameHow it's storedFor backups
Standard Multi-AZSTANDARDAcross three availability zones, one data center eachThe only copy, or backups you restore often
Standard One ZoneONEZONE_IAAcross three racks in one availability zoneA second copy; Scaleway suggests it for secondary backups
GlacierGLACIERAn archive cluster in Paris (DC4), used by Paris and Amsterdam bucketsMonthly or yearly archives, restored before download

Scaleway's console says Standard One Zone; S3 tools use ONEZONE_IA, AWS's name for One Zone-IA. A Glacier object is listed but can't be downloaded until restored, which Scaleway says can take from a few minutes to 24 hours to start for objects over 1 MB.

What it costs

Storage is billed per GB-hour. As of October 2026, Scaleway's public price catalog lists the figures below; Scaleway has changed some of them during the year, so check its pricing page before you rely on them:

ItemPricePer 1,000 GB a month (730 hours)
Standard Multi-AZ€0.000022 per GB-hour€16.06
Standard One Zone€0.000011 per GB-hour€8.03
Glacier€0.00000348 per GB-hour€2.54
Glacier restore€0.009 per GB€9.00
Traffic to the internet€0.01 per GB€10.00
Uploads, and traffic within one regionFree€0

Traffic from a bucket to another Scaleway region is €0.01 per GB. Old versions and unfinished multipart uploads are billed like any object. New customers can start a one-time 90-day trial covering 750 GB of Multi-AZ and One Zone storage.

UsageWorkingPer month
30 nightly 20 GB archives in One Zone600 GB × €0.000011 × 730€4.82
The same in Multi-AZ600 GB × €0.000022 × 730€9.64
12 monthly 50 GB archives in Glacier600 GB × €0.00000348 × 730€1.52
Restoring one monthly archive to a server elsewhere50 GB × €0.009 + 50 GB × €0.01€0.95

Keep backups in their own Project

IAM grants Object Storage permissions per Project, so a key that can delete can delete in every bucket of its Project. Put the backup buckets in a Project of their own, such as backups, then:

  1. In IAM, open Applications, click Create application, and name it after the server, such as web-01-backup.
  2. In Policies, click Create policy, choose the application as principal, and add a rule with the permission sets ObjectStorageObjectsRead and ObjectStorageObjectsWrite, scoped to Specific projects: backups.
  3. In API keys, click Generate API key, choose the application as bearer and an expiration, and set backups as the preferred Project for Object Storage.
  4. Save the secret key; it is shown once.
  • ObjectStorageObjectsRead lists and downloads; ObjectStorageObjectsWrite uploads. Without ObjectStorageObjectsDelete, the key can't delete objects or abort a failed multipart upload, so lifecycle rules clean up.
  • Write still lets the key overwrite an object of the same name, which destroys the old one unless versioning is on. Name backups by date and turn versioning on.
  • S3 tools can't name a Project, so every call goes to the key's preferred Project. New permissions can take up to 5 minutes to apply.

Generate a second key for your own user, with backups preferred, for the bucket settings below. It stays on your workstation as profile scw-admin.

Create the bucket

  1. In the backups Project, open Object Storage and click + Create bucket.
  2. Pick the region: one your servers aren't in.
  3. Enter a name, such as acme-web-01-backups, and keep it Private.
  4. Tick Enable bucket versioning, and Enable object lock if you may want locked backups. Object Lock can also be turned on later, but never off.
  5. Click Create bucket.

Configure the AWS CLI

~/.aws/config
[profile scaleway]
region = fr-par
endpoint_url = https://s3.fr-par.scw.cloud
retry_mode = standard
max_attempts = 5
s3 =
  multipart_chunksize = 100MB
  max_concurrent_requests = 4
~/.aws/credentials
[scaleway]
aws_access_key_id = <access_key>
aws_secret_access_key = <secret_key>
  • region and endpoint_url must match the bucket's region.
  • multipart_chunksize matters here: a Scaleway multipart upload has at most 1,000 parts of 5 MB to 5 GB, against 10,000 on AWS. The CLI's default 8 MB parts stop at about 8 GB per file; 100 MB parts reach about 100 GB.
  • max_concurrent_requests = 4, down from 10, sends fewer uploads at once, since Scaleway rate-limits PUT requests. retry_mode = standard retries throttling errors and 500, 502, 503 and 504 responses with backoff.

Run chmod 600 on both files. On your workstation, add scw-admin the same way with your own key.

Narrow the key to one bucket

A bucket policy narrows IAM to one bucket and exact actions. Once a bucket has one, only the principals it names can use the bucket, so name yourself too. This gives your user everything, and web-01's application listing, upload and download from its own IP address:

web-01-policy.json
{
  "Version": "2023-04-17",
  "Id": "acme-web-01-backups",
  "Statement": [
    {
      "Sid": "Admin",
      "Effect": "Allow",
      "Principal": { "SCW": "user_id:<your_user_id>" },
      "Action": "*",
      "Resource": ["acme-web-01-backups", "acme-web-01-backups/*"]
    },
    {
      "Sid": "Web01UploadAndRead",
      "Effect": "Allow",
      "Principal": { "SCW": "application_id:<application_id>" },
      "Action": ["s3:ListBucket", "s3:PutObject", "s3:GetObject"],
      "Resource": ["acme-web-01-backups", "acme-web-01-backups/*"],
      "Condition": { "IpAddress": { "aws:SourceIp": "203.0.113.10/32" } }
    }
  ]
}
  • 2023-04-17 is the current policy version: only what is allowed is permitted, so Deny statements do nothing.
  • aws:SourceIp holds the server's public address; list every address it may connect from, IPv6 included.
  • The bucket name covers bucket actions such as s3:ListBucket; the name with /* covers objects.
  • An action needs both IAM and the policy. Leaving out s3:PutObjectRetention and s3:PutBucketObjectLockConfiguration, which ObjectStorageObjectsWrite includes, keeps the server away from locks.
Terminal
aws s3api put-bucket-policy --bucket acme-web-01-backups --policy file://web-01-policy.json --profile scw-admin

A bucket has one policy, and a new one replaces it. If you lock yourself out, the Organization Owner can always delete it with aws s3api delete-bucket-policy. On the server, aws s3 ls s3://acme-web-01-backups/ --profile scaleway prints nothing for an empty bucket, and aws s3 rm on a test file should be refused, since the key has no delete permission.

Upload backups on a schedule

Name each backup by date, under a prefix the lifecycle rules match, with a checksum beside it. This archives two directories with tar:

/usr/local/bin/scaleway-backup.sh
#!/bin/sh
set -eu
NAME="web-01-$(date +%F).tar.gz"
cd /var/backups
tar -czf "$NAME" /etc /var/www
sha256sum "$NAME" > "$NAME.sha256"
for f in "$NAME" "$NAME.sha256"; do
  aws s3 cp "$f" "s3://acme-web-01-backups/daily/$f" --storage-class ONEZONE_IA --profile scaleway --only-show-errors
done
rm "$NAME" "$NAME.sha256"

--storage-class ONEZONE_IA stores it in Standard One Zone; leave it out for Multi-AZ. set -eu stops at the first error, so a failed upload never reaches the rm. Make it executable with chmod 700 and schedule it (see scheduling backups with cron):

/etc/cron.d/scaleway-backup
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
30 3 * * * root /usr/local/bin/scaleway-backup.sh

In rclone, the Scaleway provider knows the 1,000-part limit and sizes parts to fit files of known size:

/root/.config/rclone/rclone.conf
[scaleway]
type = s3
provider = Scaleway
access_key_id = <access_key>
secret_access_key = <secret_key>
region = fr-par
endpoint = s3.fr-par.scw.cloud
storage_class = ONEZONE_IA
no_check_bucket = true

no_check_bucket stops rclone trying to create the bucket, which this key can't. With no acl line, rclone sends no ACL header and objects stay private. rclone's menu lists Paris, Amsterdam and Warsaw; for Milan, type it-mil and s3.it-mil.scw.cloud. Use rclone copy, not rclone sync, which deletes and fails with this key.

Expire old backups with lifecycle rules

Lifecycle rules delete and move objects on Scaleway's side, so the server's key never needs to delete. This keeps nightly backups 30 days and moves monthly ones to Glacier after 90 days, deleting them after a year:

lifecycle.json
{
  "Rules": [
    {
      "ID": "expire-daily",
      "Status": "Enabled",
      "Filter": { "Prefix": "daily/" },
      "Expiration": { "Days": 30 },
      "NoncurrentVersionExpiration": { "NoncurrentDays": 7 }
    },
    {
      "ID": "archive-monthly",
      "Status": "Enabled",
      "Filter": { "Prefix": "monthly/" },
      "Transitions": [{ "Days": 90, "StorageClass": "GLACIER" }],
      "Expiration": { "Days": 365 },
      "NoncurrentVersionExpiration": { "NoncurrentDays": 7 }
    },
    {
      "ID": "abort-uploads",
      "Status": "Enabled",
      "Filter": { "Prefix": "" },
      "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 1 }
    },
    {
      "ID": "remove-delete-markers",
      "Status": "Enabled",
      "Filter": { "Prefix": "" },
      "Expiration": { "ExpiredObjectDeleteMarker": true }
    }
  ]
}
  • In a versioned bucket, Expiration acts only on the current version; NoncurrentVersionExpiration deletes the old version 7 days later, so a nightly backup lives about 37 days.
  • Transition rules created or changed since April 1, 2026 need at least 90 days before Glacier and 30 before One Zone, and Glacier exists only in Paris and Amsterdam. Upload monthly backups under monthly/.
  • AbortIncompleteMultipartUpload removes unfinished uploads, which are billed but not listed. The last rule removes delete markers with nothing behind them.
  • Rules run daily at midnight UTC and can take up to 24 hours to act. Prefixes and tags must not contain spaces.
Terminal
aws s3api put-bucket-lifecycle-configuration --bucket acme-web-01-backups --lifecycle-configuration file://lifecycle.json --profile scw-admin

As on AWS, a new configuration replaces the old one; aws s3api get-bucket-lifecycle-configuration reads it back.

Versioning and Object Lock

Versioning keeps an overwritten or deleted object as an older version, retrievable by version ID. Once on, it can be suspended but never removed. If you didn't tick it at creation:

Terminal
aws s3api put-bucket-versioning --bucket acme-web-01-backups --versioning-configuration Status=Enabled --profile scw-admin

Versioning doesn't stop a key with delete rights, such as yours, from deleting old versions; Object Lock does, for a set time. It needs versioning, can't be turned off, and keeps versioning from being suspended. Default retention is set only with S3 tools:

Terminal
aws s3api put-object-lock-configuration --bucket acme-web-01-backups --object-lock-configuration '{"ObjectLockEnabled": "Enabled", "Rule": {"DefaultRetention": {"Mode": "GOVERNANCE", "Days": 14}}}' --profile scw-admin
  • GOVERNANCE: users with the right permissions can change the lock or delete the version. The server's key, held to three actions by the bucket policy, can't.
  • COMPLIANCE: nobody, the Organization Owner included, can delete or overwrite a version or shorten its retention until the date passes.

Upload a test file; aws s3api get-object-retention --bucket acme-web-01-backups --key daily/test.txt --profile scw-admin should show the mode and a RetainUntilDate 14 days out. Keep the lock shorter than the lifecycle window, as here, and move to COMPLIANCE only once the numbers are right: a compliance-locked version stays, and is billed, until its date.

Verify and restore

Terminal
aws s3 ls s3://acme-web-01-backups/daily/ --human-readable --summarize --profile scaleway

To prove a backup restores, download it with its checksum file and check both:

Terminal
mkdir -p /tmp/restore-test && cd /tmp/restore-test && aws s3 cp s3://acme-web-01-backups/daily/ . --recursive --exclude "*" --include "web-01-2026-10-04.tar.gz*" --profile scaleway
Terminal
sha256sum -c web-01-2026-10-04.tar.gz.sha256 && tar -tzf web-01-2026-10-04.tar.gz > /dev/null && echo OK

A Glacier object must first come back to Standard Multi-AZ, the only class it restores to. This keeps the restored copy for 2 days:

Terminal
aws s3api restore-object --bucket acme-web-01-backups --key monthly/web-01-2026-07-01.tar.gz --restore-request Days=2 --profile scw-admin

While it runs, aws s3api head-object on the key shows ongoing-request="true" in its Restore field. Each multipart part restores like a separate object, so fewer, larger parts restore sooner. Then extract and check the files, as in testing a restore.

Limits and common errors

  • Objects up to 5 TB, in 1 to 1,000 parts of 5 MB to 5 GB.
  • 100 buckets per Organization, one bucket policy per bucket, 1,000 lifecycle rules per bucket, and up to 1,000 versions of one object.
  • Lifecycle rules run up to 500,000 jobs a day.
  • Server-side encryption with AES256 isn't supported; Scaleway offers SSE-C, SSE-ONE and SSE-KMS.
  • An error occurred (AccessDenied) when calling the ListBuckets operation: Permission denied.: the application has no Object Storage policy, or it was added under 5 minutes ago. The server's key can't list buckets by design, so test with a bucket path.
  • An error occurred (Forbidden) when calling the ListObjectsV2 operation: Forbidden, or an empty bucket list: the key's preferred Project isn't the bucket's.
  • An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied: a bucket policy doesn't name you.
  • HTTP 400 Bad Request: InvalidArgument.: the request asked for AES256 encryption, as --sse AES256 does.
  • Too Many Requests (HTTP 429): the PUT rate limit. Send fewer requests at once, or ask support to raise it.
  • Bucket already exists: the name is taken somewhere on Scaleway. A name freed by deleting a bucket in the console comes back after 24 hours.

A Scaleway bucket for a Scaleway server

For a Scaleway Instance, a bucket in another region costs €0.01 per GB to read back but survives losing the first region. Server and bucket still share one account and one bill, so keep another copy with a different provider, per the 3-2-1 rule, and encrypt backups before upload, as Scaleway itself advises for Glacier.

Frequently asked questions

What is the S3 endpoint for Scaleway Object Storage?
https://s3.<region>.scw.cloud: s3.fr-par.scw.cloud for Paris, s3.nl-ams.scw.cloud for Amsterdam, s3.pl-waw.scw.cloud for Warsaw and s3.it-mil.scw.cloud for Milan. Set the region to the matching code, such as fr-par.
Can I limit a Scaleway API key to one bucket?
Not with IAM alone, which grants Object Storage permissions per Project. Add a bucket policy naming the key's application and the actions it may use, or give each server's buckets their own Project.
What is the difference between Standard Multi-AZ and Standard One Zone?
Multi-AZ spreads data over three availability zones and survives losing a data center; One Zone keeps it on three racks in one zone, at half the price as of October 2026. Scaleway suggests One Zone for secondary backups.
How long does a Glacier restore take on Scaleway?
From a few minutes to 24 hours to start for objects over 1 MB, Scaleway says, and longer for objects with many parts. The object comes back as Standard Multi-AZ for the days you request.
Why does the AWS CLI fail to upload large files to Scaleway?
Scaleway allows 1,000 parts per multipart upload, and the CLI's default 8 MB parts top out near 8 GB. Raise multipart_chunksize in the profile, for example to 100MB.

How this was checked

Commands, limits and prices were checked against these official pages, on October 4, 2026: