Skip to content

lehvitus/fs

 
 

Repository files navigation

fs

An experimental Object Storage written in Go that should be partially compatible with S3

Running

Single binary, two modes:

  • fs (no subcommand) starts the server (backward compatible)
  • fs server starts the server explicitly
  • fs admin ... runs admin CLI commands

Features

Bucket operations:

  • PUT /{bucket}
  • HEAD /{bucket}
  • DELETE /{bucket}
  • GET / (list buckets)

Object operations:

  • PUT /{bucket}/{key}
  • GET /{bucket}/{key}
  • HEAD /{bucket}/{key}
  • DELETE /{bucket}/{key}
  • GET /{bucket}?list-type=2&prefix=... (ListObjectsV2-style)

Multipart upload:

  • POST /{bucket}/{key}?uploads (initiate)
  • PUT /{bucket}/{key}?uploadId=...&partNumber=N (upload part)
  • GET /{bucket}/{key}?uploadId=... (list parts)
  • POST /{bucket}/{key}?uploadId=... (complete)
  • DELETE /{bucket}/{key}?uploadId=... (abort)

Multi-object delete:

  • POST /{bucket}?delete with S3-style XML body

AWS SigV4 streaming payload decoding for uploads (aws-chunked request bodies)

Authentication:

  • AWS SigV4 request verification (header and presigned URL forms)
  • Local credential/policy store in bbolt
  • Bootstrap access key/secret via environment variables

Admin API (JSON):

  • POST /_admin/v1/users
  • GET /_admin/v1/users
  • GET /_admin/v1/users/{accessKeyId}
  • PUT /_admin/v1/users/{accessKeyId}/policy
  • PUT /_admin/v1/users/{accessKeyId}/status
  • DELETE /_admin/v1/users/{accessKeyId}

Admin API policy examples (SigV4):

ENDPOINT="http://localhost:2600"
REGION="us-east-1"
ADMIN_ACCESS_KEY="${FS_ROOT_USER}"
ADMIN_SECRET_KEY="${FS_ROOT_PASSWORD}"
SIGV4="aws:amz:${REGION}:s3"

Replace user policy with one scoped statement:

curl --aws-sigv4 "$SIGV4" \
  --user "${ADMIN_ACCESS_KEY}:${ADMIN_SECRET_KEY}" \
  -H "Content-Type: application/json" \
  -X PUT "${ENDPOINT}/_admin/v1/users/test-user/policy" \
  -d '{
    "policy": {
      "statements": [
        {
          "effect": "allow",
          "actions": ["s3:ListBucket", "s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
          "bucket": "backup",
          "prefix": "restic/*"
        }
      ]
    }
  }'

Set multiple statements (for multiple buckets):

curl --aws-sigv4 "$SIGV4" \
  --user "${ADMIN_ACCESS_KEY}:${ADMIN_SECRET_KEY}" \
  -H "Content-Type: application/json" \
  -X PUT "${ENDPOINT}/_admin/v1/users/test-user/policy" \
  -d '{
    "policy": {
      "statements": [
        {
          "effect": "allow",
          "actions": ["s3:ListBucket", "s3:GetObject"],
          "bucket": "test-bucket",
          "prefix": "*"
        },
        {
          "effect": "allow",
          "actions": ["s3:ListBucket", "s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
          "bucket": "test-bucket-2",
          "prefix": "*"
        }
      ]
    }
  }'

Admin CLI:

  • fs admin user create --access-key backup-user --role readwrite
  • fs admin user list
  • fs admin user get backup-user
  • fs admin user set-status backup-user --status disabled
  • fs admin user set-role backup-user --role readonly --bucket backup-bucket --prefix restic/
  • fs admin user set-role backup-user --role readwrite --bucket backups-2 (appends another statement)
  • fs admin user remove-role backup-user --role readonly --bucket backup-bucket --prefix restic/
  • fs admin user set-role backup-user --role admin --replace (replaces all statements)
  • fs admin user delete backup-user
  • fs admin snapshot create --data-path /var/lib/fs --out /backup/fs-20260311.tar.gz
  • fs admin snapshot inspect --file /backup/fs-20260311.tar.gz
  • fs admin snapshot restore --file /backup/fs-20260311.tar.gz --data-path /var/lib/fs --force
  • fs admin diag health
  • fs admin diag version

Auth Setup

Required when FS_AUTH_ENABLED=true:

  • FS_MASTER_KEY must be base64 for 32 decoded bytes (AES-256 key), e.g. openssl rand -base64 32
  • FS_ROOT_USER and FS_ROOT_PASSWORD define initial credentials
  • ADMIN_API_ENABLED=true enables /_admin/v1/* routes (bootstrap key only)

Reference: auth/README.md

Additional docs:

  • Admin OpenAPI spec: docs/admin-api-openapi.yaml
  • S3 compatibility matrix: docs/s3-compatibility.md

CLI credential/env resolution for fs admin:

  • Flags: --access-key, --secret-key, --endpoint, --region
  • Env fallback:
    • FS_ROOT_USER / FS_ROOT_PASSWORD (same defaults as server bootstrap)
    • FSCLI_ACCESS_KEY / FSCLI_SECRET_KEY
    • AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
    • FSCLI_ENDPOINT (fallback to ADDRESS + PORT, then http://localhost:2600)
    • FSCLI_REGION (fallback FS_AUTH_REGION, default us-east-1)

Note:

  • fs admin snapshot ... commands operate locally on filesystem paths and do not require endpoint or auth credentials.

Health:

  • GET /healthz
  • HEAD /healthz
  • GET /metrics (Prometheus exposition format)
  • HEAD /metrics

Limitations

  • Not full S3 API coverage.
  • No versioning or lifecycle policies.
  • Error and edge-case behavior is still being refined for client compatibility.

License

MIT License

About

S3 Compatible Object Storage in Go

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Go 99.8%
  • Dockerfile 0.2%