Skip to main content

Run SeaweedFS for S3-compatible object storage

Inspect 1.36

SeaweedFS runs an S3-compatible object store inside your own cluster. You get buckets and an S3 endpoint on storage you operate, so your uploads, your Velero backups, and the data behind JuiceFS all sit on disks you control rather than on someone else's service. On Syself Autopilot that matters twice over: the data stays on your Hetzner hardware, and backing it with block volumes keeps it off the nodes, where node replacement never touches it.

SeaweedFS has a few moving parts, and how you set replication decides how much failure the data survives. For the full breakdown and the replication values before you deploy, expand the reference below.

When self-hosted S3 is the right call#

Run your own object store for sovereignty, cost, or egress. The data stays on hardware you own, which answers data-residency questions directly. There are no per-request or per-gigabyte charges from an outside provider, only the cost of the disks. And traffic between your workloads and your buckets stays inside the cluster network, so you do not pay to move data out and back.

SeaweedFS is yours to run: it is not part of the cluster stack, so its health, upgrades, and data are your responsibility rather than part of the managed platform. If you only need a bucket and do not want to operate the store, point your workloads at any S3-compatible endpoint instead. See . If you would rather not operate SeaweedFS, the Syself Consulting team can deploy and maintain it for you, or advise on sizing and replication.

Deploy SeaweedFS #

Install the master, volume servers, filer, and S3 gateway from the SeaweedFS Helm chart:

Note

The chart name and values here follow the SeaweedFS Helm chart. Confirm the current chart repository, release name, and value keys against the SeaweedFS chart before you install, since these change between chart versions.

		$ helm repo add seaweedfs https://seaweedfs.github.io/seaweedfs/helm
$ helm repo update
$ helm install seaweedfs seaweedfs/seaweedfs \
    --namespace seaweedfs --create-namespace \
    --set master.replicas=1 \
    --set volume.replicas=1 \
    --set filer.replicas=1 \
    --set s3.enabled=true
	

Back it with volumes #

The volume servers need real disks. Give them a StorageClass through the chart's persistence values. Two choices fit Syself Autopilot:

  • Hetzner Cloud block volumes through the standard class. The data detaches and reattaches with the volume server, so it survives node replacement.
  • Local disks through on a bare metal server. Faster, but the data is tied to that server.
		$ helm upgrade seaweedfs seaweedfs/seaweedfs \
    --namespace seaweedfs \
    --set 'volume.dataDirs[0].name=data' \
    --set 'volume.dataDirs[0].type=persistentVolumeClaim' \
    --set 'volume.dataDirs[0].storageClass=standard' \
    --set 'volume.dataDirs[0].size=100Gi'
	

Expose the S3 endpoint #

The S3 gateway speaks the S3 API with path-style addressing, so the bucket name goes in the path (http://<endpoint>/<bucket>), not in the hostname. Clients set forcePathStyle (or s3ForcePathStyle) to true.

Create buckets and keys #

Create a bucket and an access key with the s3 admin interface or the gateway's configured identities:

		$ echo "s3.bucket.create -name backups" | kubectl exec -i -n seaweedfs sts/seaweedfs-master -- weed shell
	

The same administration is available in a browser: port-forward the master and open its admin interface, which shows cluster status, volumes, and topology.

		$ kubectl -n seaweedfs port-forward svc/seaweedfs-master 9333:9333
	

Then open http://localhost:9333.

Generate a separate access key ID and secret for each use, and grant each key only the buckets and actions it needs. A key that only writes backups should not be able to read your uploads bucket. Least-privilege keys limit the blast radius if one leaks.

Important

The exact command to create buckets and keys depends on your SeaweedFS version and how you configure S3 identities. Check the SeaweedFS S3 documentation for the syntax your version uses.

Keep the access key ID and secret in a Kubernetes Secret, never in a container image or a plain manifest. Workloads read them from the Secret at runtime:

s3-credentials.yamlyaml
		apiVersion: v1
kind: Secret
metadata:
  name: s3-credentials
  namespace: default
type: Opaque
stringData:
  AWS_ACCESS_KEY_ID: <access-key-id>
  AWS_SECRET_ACCESS_KEY: <secret-access-key>
  S3_ENDPOINT: http://seaweedfs-s3.seaweedfs.svc.cluster.local:8333
	

Related: to wire an application to the store · to put a shared filesystem on top · to send cluster backups here.