Skip to main content

Create and manage an object or SFTP storage

CDB Object Storage offers three storage types, each suited to different workloads and access protocols:

  • S3 Standard — general-purpose S3-compatible storage for backups, content delivery, and most workloads
  • S3 Fast — high-performance S3-compatible storage optimized for AI/ML workloads, IoT telemetry, and latency-sensitive applications (available in Sines-2, Sines-3, and London-2)
  • SFTP — legacy file-based storage accessed via SFTP protocol, with the same pricing and billing terms as S3 Standard

Create a storage

  1. 1

    Open Object Storages

    In the CDB Technical Web Portal, navigate to Storage > Object Storages.

  2. 2

    Start creation

    Click Add new object storage in the top-right corner.

  3. 3

    Enter storage details

    In the dialog, enter the storage name and select a location. The location name shows the storage type and data center — S3 Standard Luxembourg-2 or SFTP Amsterdam. SFTP locations appear and disappear based on available capacity.

    Add new object storage dialog with Name and Location fields

    A maximum of 3600 storages can be created per account.

S3 Standard and S3 Fast

S3 Standard and S3 Fast use the same creation flow — the only difference is the location selected in the dropdown. Each S3 storage supports up to 1000 buckets and 10 million objects per bucket. For optimal performance, keep under 100K objects per bucket and distribute data across multiple buckets.

In the Location dropdown, select an S3 Standard or S3 Fast location, then click Create at the bottom of the dialog.

Location dropdown in the Add new object storage dialog showing S3 and SFTP location options

A Details dialog opens immediately, showing the storage credentials: access key, secret key, hostname, and location. Click Copy object storage data to copy all credentials at once.

Store the secret key, because it is returned only when a key is created. The initial key has read-write access. Additional access keys — read-write or read-only — can be created after the storage exists. Read-only keys are supported on S3 Standard only.

Details dialog showing S3 storage credentials including access key, secret key, and hostname

S3 management options

The created storage appears in the storage list. To manage it, click ... (three dots) next to the storage name and select an option:

OptionDescription
DetailsView Object Storage User name, Location, and Hostname.
Access keysCreate and delete read-write or read-only S3 access keys. S3 Standard supports up to 10 access keys; S3 Fast supports up to 2. Read-only keys are supported on S3 Standard only. The secret is returned only when a key is created.
BucketsManage the storage's buckets.
Delete object storagePermanently delete the storage and all its contents. This action cannot be undone.

SFTP storage

SFTP storage requires choosing an authentication method during creation — password or SSH key. Both can be managed after creation.

In the Location dropdown, select an SFTP location and enter a name as described in the general steps above. Then select the authentication method:

  1. 1

    Select authentication method

    Select Password or SSH Key. Leave the password field empty to generate one automatically.

  2. 2

    Create

    Click Create at the bottom of the dialog.

    Add new object storage dialog with SFTP Amsterdam location and password authentication fields

SFTP management options

After creation, manage the SFTP storage by clicking ... (three dots) next to the storage name and selecting an option:

OptionDescription
DetailsView the hostname and connection path. Use port 2200 to connect via SFTP.
EditConfigure the server alias and the HTTP Expires response header for files served over HTTP. Configuration details are in the Edit dialog section.
Set/Update passwordSet or replace the password used to authenticate SFTP connections.
Remove passwordRemove password authentication from the storage. After removal, only SSH key authentication is accepted.
SSH keys managerAdd or remove SSH keys for SFTP authentication. Up to five keys are allowed per storage.
Delete object storagePermanently delete the storage and all its contents. This action cannot be undone.
SFTP storage actions dropdown showing Details, Edit, password management, SSH keys manager, and Delete options

Edit dialog

The Edit dialog for SFTP storage has two fields. Open it by clicking ... > Edit next to the storage name.

Edit dialog for SFTP storage with Server alias and Expires fields

In the Server alias field, enter a domain name (subdomains are supported), then add a CNAME record in DNS settings: <server_name>.<host>. For a storage named 12345-test in Amsterdam, the record would be CNAME 12345-test.ams.origin.gcdn.co.

In the Expires field, set the value of the HTTP Expires response header for files served over HTTP. Use the format N years|months|weeks|days|hours|minutes|seconds. The default is one year.

Storage status indicator

Each storage row shows a colored circle to the left of the ID.

After creation or a settings update — adding keys or changing a password — the storage enters a processing state shown by an orange circle. A green circle indicates the storage is ready.

Storage list showing orange and green status circles next to storage entries

Each S3-compatible or SFTP storage is provisioned with a single API call. S3 and SFTP use different endpoints. For S3 storage, the secret key is returned only at creation time and cannot be retrieved later.

An API token is required.

export GCORE_API_KEY="{YOUR_API_KEY}"

Quickstart

The scripts below list available locations, create an S3 storage, and print the credentials.

from gcore import CDB

client = CDB()

# Step 1. List available locations and select an S3-compatible one
locations = client.storage.locations.list()
s3_location = next(loc for loc in locations if loc.type == "s3_compatible")

# Step 2. Create S3 storage — access key and secret key are returned only here
storage = client.storage.object_storages.create(
    location_name=s3_location.name,
    name="my-storage",
)
print(f"Storage ID: {storage.id}")
print(f"Endpoint:   {storage.address}")
print(f"Full name:  {storage.full_name}")
print(f"Access key: {storage.access_keys[0].access_key}")
print(f"Secret key: {storage.access_keys[0].secret_key}")
package main

import (
    "context"
    "fmt"
    "log"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/storage"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    // Step 1. List available locations and select an S3-compatible one
    locations, err := client.Storage.Locations.List(ctx, storage.LocationListParams{})
    if err != nil {
        log.Fatalf("list locations: %v", err)
    }
    var locationName string
    for _, loc := range locations.Results {
        if loc.Type == "s3_compatible" {
            locationName = loc.Name
            break
        }
    }

    // Step 2. Create S3 storage — access key and secret key are returned only here
    s3, err := client.Storage.ObjectStorages.New(ctx, storage.ObjectStorageNewParams{
        Name:         "my-storage",
        LocationName: locationName,
    })
    if err != nil {
        log.Fatalf("create storage: %v", err)
    }
    fmt.Printf("Storage ID: %d\n", s3.ID)
    fmt.Printf("Endpoint:   %s\n", s3.Address)
    fmt.Printf("Full name:  %s\n", s3.FullName)
    fmt.Printf("Access key: %s\n", s3.AccessKeys[0].AccessKey)
    fmt.Printf("Secret key: %s\n", s3.AccessKeys[0].SecretKey)
}

The sections below cover the individual API operations: S3 creation with step-by-step detail, SFTP creation, SFTP password updates, and deletion for both storage types.

Step-by-step

Each step below explains what the call does, which parameters matter, and what the response looks like.

The initial key in the response has read-write access. Additional keys — read-write or read-only — can be created using the access keys endpoint. S3 Standard supports up to 10 access keys per storage; S3 Fast supports up to 2. Read-only keys are supported on S3 Standard only.

The access key request body uses the field name read_only. The response returns the same concept as is_read_only — note this naming difference when building API clients.

List S3 storages

Use GET /docs/storage/v4/object_storages to retrieve all S3 storages in the account. Each item includes a type field reporting the performance tier: standard for CEPH-backed storages and fast for VAST-backed storages. Pass ?type=standard or ?type=fast to filter the list to a specific tier.

from gcore import CDB

client = CDB()

storages = client.storage.object_storages.list()
for s in storages.results:
    print(f"{s.id}  {s.name}  {s.location_name}  type={s.type}")
package main

import (
    "context"
    "fmt"
    "log"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/storage"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    result, err := client.Storage.ObjectStorages.List(ctx, storage.ObjectStorageListParams{})
    if err != nil {
        log.Fatalf("list storages: %v", err)
    }
    for _, s := range result.Results {
        fmt.Printf("%d  %s  %s\n", s.ID, s.Name, s.LocationName)
    }
}
# List all storages
curl https://api.cdb-staging.cdn.orange.com/storage/v4/object_storages \
  -H "Authorization: APIKey $GCORE_API_KEY"

# List only S3 Standard (CEPH-backed) storages
curl "https://api.cdb-staging.cdn.orange.com/storage/v4/object_storages?type=standard" \
  -H "Authorization: APIKey $GCORE_API_KEY"

# List only S3 Fast (VAST-backed) storages
curl "https://api.cdb-staging.cdn.orange.com/storage/v4/object_storages?type=fast" \
  -H "Authorization: APIKey $GCORE_API_KEY"

The API returns:

{
  "count": 1,
  "results": [
    &#123;
      "id": 12345,
      "name": "my-storage",
      "full_name": "123456-my-storage",
      "location_name": "luxembourg-2",
      "type": "standard",
      "address": "luxembourg-2.portal.cdb-staging.cdn.orange.com/storage",
      "provisioning_status": "active",
      "created_at": "2024-01-15T10:30:00Z"
    &#125;
  ]
}

Backblaze- and Wasabi-backed storages report type=standard in the response but are not returned by the ?type=standard filter. The filter selects CEPH-backed storages only. Omitting type returns all storages regardless of backend.

Create SFTP storage

SFTP storage uses a different endpoint and requires a password_mode field. Setting it to auto generates a random password returned in the creation response — the only time it is visible. Use set to provide a custom password, or none to disable password authentication and use SSH keys instead.

from gcore import CDB

client = CDB()

sftp = client.storage.sftp_storages.create(
    location_name="ams",
    name="my-sftp-storage",
    password_mode="auto",
)
print(f"Storage ID: {sftp.id}")
print(f"Hostname:   {sftp.address}")
print(f"Password:   {sftp.password}")
package main

import (
    "context"
    "fmt"
    "log"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/storage"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    sftp, err := client.Storage.SftpStorages.New(ctx, storage.SftpStorageNewParams{
        Name:         "my-sftp-storage",
        LocationName: "ams",
        PasswordMode: storage.SftpStorageNewParamsPasswordModeAuto,
    })
    if err != nil {
        log.Fatalf("create SFTP storage: %v", err)
    }
    fmt.Printf("Storage ID: %d\n", sftp.ID)
    fmt.Printf("Hostname:   %s\n", sftp.Address)
    fmt.Printf("Password:   %s\n", sftp.Password)
}
curl -X POST https://api.cdb-staging.cdn.orange.com/storage/v4/sftp_storages \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '&#123;"location_name": "ams", "name": "my-sftp-storage", "password_mode": "auto"&#125;'

Response:

&#123;
  "id": 13865,
  "name": "my-sftp-storage",
  "full_name": "1000503-my-sftp-storage",
  "location_name": "ams",
  "address": "ams.origin.gcdn.co",
  "provisioning_status": "creating",
  "has_password": true,
  "password": "SVaUEHefakmx",
  "created_at": "2026-07-13T13:08:43Z"
&#125;

Connect to the storage using SFTP on port 2200:

sftp -P 2200 1000503-my-sftp-storage@ams.origin.gcdn.co

Update SFTP password

Use PATCH /v4/sftp_storages/{storage_id} to replace an SFTP storage's password. Set password_mode to set and provide the new value in password. The password field is only accepted when password_mode is set.

from gcore import CDB

client = CDB()

sftp_id = 13865
client.storage.sftp_storages.update(
    sftp_id,
    password_mode="set",
    password="MyNewPassword123",
)
print("Password updated")
package main

import (
    "context"
    "fmt"
    "log"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/storage"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    var sftpID int64 = 13865

    _, err := client.Storage.SftpStorages.Update(ctx, sftpID, storage.SftpStorageUpdateParams{
        PasswordMode: storage.SftpStorageUpdateParamsPasswordModeSet,
        Password:     gcore.String("MyNewPassword123"),
    })
    if err != nil {
        log.Fatalf("update SFTP password: %v", err)
    }
    fmt.Println("Password updated")
}
curl -X PATCH "https://api.cdb-staging.cdn.orange.com/storage/v4/sftp_storages/$SFTP_ID" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '&#123;"password_mode": "set", "password": "MyNewPassword123"&#125;'

Returns HTTP 200 with the updated storage object.

Delete storage

Deleting a storage permanently removes all data it contains. S3 and SFTP storages use different endpoints.

Delete S3 storage:

from gcore import CDB

client = CDB()

storage_id = 13864
client.storage.object_storages.delete(storage_id)
print("Storage deleted")
package main

import (
    "context"
    "fmt"
    "log"

    gcore "github.com/G-Core/gcore-go"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    var storageID int64 = 13864

    err := client.Storage.ObjectStorages.Delete(ctx, storageID)
    if err != nil {
        log.Fatalf("delete storage: %v", err)
    }
    fmt.Println("Storage deleted")
}
curl -X DELETE "https://api.cdb-staging.cdn.orange.com/storage/v4/object_storages/$STORAGE_ID" \
  -H "Authorization: APIKey $GCORE_API_KEY"

Returns HTTP 204 with no response body.

Delete SFTP storage uses the SFTP endpoint:

from gcore import CDB

client = CDB()

sftp_id = 13865
client.storage.sftp_storages.delete(sftp_id)
print("SFTP storage deleted")
package main

import (
    "context"
    "fmt"
    "log"

    gcore "github.com/G-Core/gcore-go"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    var sftpID int64 = 13865

    err := client.Storage.SftpStorages.Delete(ctx, sftpID)
    if err != nil {
        log.Fatalf("delete SFTP storage: %v", err)
    }
    fmt.Println("SFTP storage deleted")
}
curl -X DELETE "https://api.cdb-staging.cdn.orange.com/storage/v4/sftp_storages/$SFTP_ID" \
  -H "Authorization: APIKey $GCORE_API_KEY"

Returns HTTP 204 with no response body.

Provision S3-compatible and SFTP storages declaratively using the CDB Terraform provider v2.

Create S3 storage

Declares an S3 storage. The storage is provisioned with one access key automatically. To create an S3 Fast storage instead of S3 Standard, set location_name to an S3 Fast location name (e.g. sines-2) — the resource type is the same.

resource "gcore_storage_object_storage" "example" {
  location_name = "luxembourg-2"
  name          = "my-storage"
}

output "s3_endpoint" {
  value = gcore_storage_object_storage.example.address
}

output "s3_access_key" {
  value = gcore_storage_object_storage.example.access_keys[0].access_key
}

output "s3_secret_key" {
  value     = gcore_storage_object_storage.example.access_keys[0].secret_key
  sensitive = true
}

# terraform import gcore_storage_object_storage.example '<storage_id>'
terraform apply

Delete S3 storage

Remove the resource block. Terraform deletes the storage on the next apply.

Deleting the storage permanently removes all buckets and objects it contains. This action cannot be undone.

# Remove or comment out this block:
# resource "gcore_storage_object_storage" "example" { ... }
terraform apply

Create SFTP storage

Declares an SFTP storage and sets a password with the write-only arguments password_wo and password_wo_version. Terraform sends password_wo to the API and does not keep it in state, so the password cannot be read back from an output. After apply, use full_name as the login username on port 2200. Omit both password arguments to create a storage that accepts SSH keys only.

resource "gcore_storage_sftp" "example" {
  location_name       = "ams"
  name                = "my-sftp-storage"
  password_wo         = var.sftp_password
  password_wo_version = 1
}

output "sftp_address" {
  value = gcore_storage_sftp.example.address
}

output "sftp_full_name" {
  value = gcore_storage_sftp.example.full_name
}

# terraform import gcore_storage_sftp.example '<storage_id>'
terraform apply

Update SFTP password

Replace the password by setting password_wo to the new value and incrementing password_wo_version, then apply. A change to password_wo alone produces no plan. Remove both arguments to clear password authentication without replacing the storage.

resource "gcore_storage_sftp" "example" {
  location_name       = "ams"
  name                = "my-sftp-storage"
  password_wo         = var.sftp_password
  password_wo_version = 2
}
terraform apply

Delete SFTP storage

Remove the resource block — Terraform deletes the storage on the next apply.

Deleting the storage permanently removes all its contents. This action cannot be undone.

# Remove or comment out this block:
# resource "gcore_storage_sftp" "example" {
#   location_name       = "ams"
#   name                = "my-sftp-storage"
#   password_wo         = var.sftp_password
#   password_wo_version = 1
# }
terraform apply