Skip to content

Running SwiftFS

A SwiftFS deployment is one stateless process, one data directory and one PostgreSQL database. Object bytes live on the data directory's filesystem; everything else (buckets, keys, metadata, usage) lives in PostgreSQL.

Availability

SwiftFS Core's source and container image are published together with its open-source license. This guide describes running it once you have them.

Requirements

  • PostgreSQL 15 or later, UTF-8 encoding.
  • A filesystem for the data directory with working fsync and atomic rename: ext4 or XFS on Linux. Avoid network filesystems.
  • A 32-byte encryption key, which protects access-key secrets at rest:
Terminal
openssl rand -base64 32

Back the key up somewhere safe and separate: without it, every existing access key stops working.

The container

Terminal
docker run -d --name swiftfs \
  -p 9000:9000 -p 127.0.0.1:9100:9100 \
  -v swiftfs-data:/data \
  -e SWIFTFS_DATABASE_URL='postgres://swiftfs:…@db:5432/swiftfs' \
  -e SWIFTFS_ENCRYPTION_KEY='…' \
  -e SWIFTFS_PUBLIC_ENDPOINT='https://s3.example.com' \
  swiftfs
  • Port 9000 is the S3 API. Port 9100 serves health checks and Prometheus metrics: keep it private.
  • The image is a small distroless image running as a non-root user.
  • Database migrations run at start-up. To run them as a separate step, set SWIFTFS_AUTO_MIGRATE=false and run swiftfs migrate. Concurrent migrations are serialized, so several instances can start together.
  • Invalid configuration is reported in full at start-up, before anything listens.

The first account and key

SwiftFS is multi-tenant: accounts own buckets and access keys. Create one for each application or customer:

Terminal
docker exec swiftfs swiftfs admin account create acme
docker exec swiftfs swiftfs admin key create --account acme --description "web app"
docker exec swiftfs swiftfs admin account limits acme --storage 50GiB --buckets 20

The key's secret is printed once. Then use any S3 client with https://s3.example.com as the endpoint (see SDKs and tools). More commands are in administration.

Behind a proxy or load balancer

Terminate TLS in front of SwiftFS. The proxy must:

  • pass the original Host header through: it is part of every signature;
  • leave the path exactly as sent (//, %2F, ..);
  • not buffer request bodies, and allow large ones;
  • pass OPTIONS requests through (browsers' CORS preflights);
  • set X-Forwarded-For, with the proxy listed in SWIFTFS_TRUSTED_PROXIES.
nginx
location / {
    proxy_pass http://swiftfs:9000;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_request_buffering off;
    proxy_buffering off;
    client_max_body_size 0;
    proxy_http_version 1.1;
}

Use /health/ready on the ops port for health checks. It fails as soon as shutdown starts, so traffic drains first; in-flight requests get SWIFTFS_SHUTDOWN_TIMEOUT to finish.

Backups

Back up PostgreSQL and the data directory as a pair, in this order:

  1. Back up PostgreSQL (pg_dump works from a consistent snapshot).
  2. Then snapshot the data directory, starting within SWIFTFS_GC_GRACE (5 minutes by default) of step 1. Raise SWIFTFS_GC_GRACE if your snapshots can't start that soon.

Every object in the database backup then has its data in the snapshot. Data written in between becomes unreferenced after a restore and is cleaned up automatically. Back up the encryption key separately.

Monitoring

  • Metrics: scrape /metrics on the ops port with Prometheus. Alert on 5xx rates, failing background jobs, and above all swiftfs_corrupt_blobs > 0: stored data no longer matches its checksum, and the named objects must be restored from backup.
  • Status at a glance: swiftfs admin status shows health, disk use, stored totals, and every background job's last run.
  • Logs are JSON by default. A DATA LOSS line means a stored object's data is missing.

Upgrading

Stop the old version (or let your orchestrator replace it), start the new one; migrations apply at start-up. The on-disk format is versioned, and SwiftFS refuses to use a data directory it doesn't recognize.