S3 Gateway

Configuration

Configuring the Shelby S3 Gateway

The S3 Gateway supports two configuration formats:

  • YAML — Simple, supports reads and writes (add aptosPrivateKey to enable writes)
  • TypeScript — For advanced or dynamic configuration (custom providers, programmatic setup)

YAML Configuration

Create a shelby.config.yaml file and run with --config:

npx @shelby-protocol/s3-gateway --config shelby.config.yaml

Full Example

shelby.config.yaml
# Network configuration (required)
network:
  name: shelbynet              # "shelbynet" or "local"
  rpcEndpoint: https://api.shelbynet.shelby.xyz/shelby
  aptosFullnode: https://api.shelbynet.shelby.xyz/v1
  aptosIndexer: https://api.shelbynet.shelby.xyz/v1/graphql
  apiKey: <YOUR_API_KEY>         # Optional

# Server settings
server:
  host: localhost      # Bind address (default: localhost)
  port: 9000           # Listen port (default: 9000)
  region: shelbyland   # S3 region for signing (default: shelbyland)
  verbose: false       # Enable request logging (default: false)

# S3 credentials for request signing (optional — defaults to dev credentials)
credentials:
  - accessKeyId: AKIAIOSFODNN7EXAMPLE
    secretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    aptosPrivateKey: <YOUR_APTOS_PRIVATE_KEY>  # Enables uploads & deletes

# Shelby account addresses to expose as S3 buckets (required)
# Use your own account address from `shelby account info`
buckets:
  - <YOUR_SHELBY_ACCOUNT_ADDRESS>

To enable write operations (uploads, deletes), add aptosPrivateKey to a credential entry. Without it, the credential only permits read operations.

Minimal Example

shelby.config.yaml
network:
  name: shelbynet
  rpcEndpoint: https://api.shelbynet.shelby.xyz/shelby
  aptosFullnode: https://api.shelbynet.shelby.xyz/v1
  aptosIndexer: https://api.shelbynet.shelby.xyz/v1/graphql
  apiKey: <YOUR_API_KEY>

buckets:
  - <YOUR_SHELBY_ACCOUNT_ADDRESS>

With the minimal config, the gateway uses default development credentials and supports read-only access. Add a credentials section with aptosPrivateKey to enable writes.

Configuration Reference

Network Options (Required)

OptionTypeDefaultDescription
name"shelbynet" | "local""shelbynet"Network name
rpcEndpointstringNetwork defaultShelby RPC endpoint URL
aptosFullnodestring-Aptos fullnode URL
aptosIndexerstring-Aptos indexer URL
apiKeystring-API key for authentication

Server Options

OptionTypeDefaultDescription
hoststring"localhost"Bind address for the server
portnumber9000Port to listen on
regionstring"shelbyland"S3 region for SigV4 signing
verbosebooleanfalseEnable detailed request logging

The region setting must match what your S3 clients use for signing requests. Some tools require a standard AWS region like "us-east-1".

Credentials

Array of S3 credential objects. If not specified, default dev credentials are used.

These are not AWS credentials. They are shared secrets used for S3 SigV4 request signing between your S3 client and the gateway. The same values must be configured in both the gateway config and your S3 client (rclone, boto3, etc.). You can use any values you want — the defaults work for local development.

FieldTypeDescription
accessKeyIdstringPublic identifier for the credential (used in the Authorization header)
secretAccessKeystringShared secret used for HMAC request signing (never sent over the network)
aptosPrivateKeystring (optional)Your Aptos Ed25519 private key. If you've set up the Shelby CLI, copy your private_key from ~/.shelby/config.yaml. Accepts the ed25519-priv-0x... format or raw hex (0x...). Enables write operations (uploads, deletes) for this credential

Buckets (Required)

Array of Shelby account addresses (strings) to expose as S3 buckets.

Environment Variables

VariableDefaultDescription
PORT9000Server port (overrides config file)
HTTPS-Set to true to enable HTTPS

CLI Options

OptionDescription
-c, --config <path>Path to config file
-p, --port <port>Port to listen on (overrides config)
-h, --helpShow help message

Advanced: TypeScript Configuration

For dynamic configuration or custom credential/bucket providers, use a TypeScript config.

A ready-to-use example that reads your existing ~/.shelby/config.yaml is included in the package at example.shelby.config.ts. To use it:

npx @shelby-protocol/s3-gateway --config example.shelby.config.ts

Or create your own:

shelby.config.ts
import { Account, Ed25519PrivateKey, Network } from "@aptos-labs/ts-sdk";
import {
  defineConfig,
  StaticCredentialProvider,
  StaticBucketProvider,
} from "@shelby-protocol/s3-gateway";

const privateKey = new Ed25519PrivateKey(process.env.APTOS_PRIVATE_KEY!);
const aptosSigner = Account.fromPrivateKey({ privateKey });
const signerAddress = aptosSigner.accountAddress.toString();

export default defineConfig({
  shelby: {
    network: Network.SHELBYNET,
    rpc: {
      baseUrl: "https://api.shelbynet.shelby.xyz/shelby",
    },
  },
  server: {
    port: 9000,
    region: "shelbyland",
  },
  credentialProvider: new StaticCredentialProvider({
    credentials: {
      AKIAIOSFODNN7EXAMPLE: {
        secretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        aptosSigner, // Enables write operations (uploads, deletes)
      },
    },
  }),
  bucketProvider: new StaticBucketProvider({
    buckets: [signerAddress],
  }),
});

The aptosSigner field is what enables write operations. Without it, the credential only permits reads. In YAML configs, set aptosPrivateKey to achieve the same result.

Custom Providers

Implement custom providers for dynamic credential or bucket lookup:

shelby.config.ts
import { defineConfig } from "@shelby-protocol/s3-gateway";
import type { CredentialProvider } from "@shelby-protocol/s3-gateway";

// Custom credential provider (e.g., from database)
class DatabaseCredentialProvider implements CredentialProvider {
  async getCredential(accessKeyId: string) {
    const result = await db.query(
      "SELECT secret_key FROM credentials WHERE access_key_id = ?",
      [accessKeyId]
    );
    return result ? { accessKeyId, secretAccessKey: result.secret_key } : undefined;
  }

  async listAccessKeyIds() {
    const results = await db.query("SELECT access_key_id FROM credentials");
    return results.map((r) => r.access_key_id);
  }

  async refresh() {
    // Refresh cache if needed
  }
}

export default defineConfig({
  shelby: { /* ... */ },
  credentialProvider: new DatabaseCredentialProvider(),
  bucketProvider: new StaticBucketProvider({ buckets: ["0x..."] }),
});