How to Install SeaweedFS on Ubuntu 24.04 VPS — Distributed Object Storage with S3, Erasure Coding, and Cross-DC Sync
SeaweedFS is the quietly dominant choice when you need to store billions of small files cheaply on commodity hardware. Born from a re-implementation of the ideas in Facebook's Haystack paper, it fuses a Haystack-style object store with a filer layer, an S3 gateway, HDFS compatibility, WebDAV, and FUSE mounts into a single Go binary under 60 MB. Where MinIO gives you S3 and nothing else, and Ceph gives you everything but demands a small cluster of engineers to operate it, SeaweedFS sits in the sweet spot: one binary, three processes, and you have a production-grade distributed object store that handles erasure coding, replication, TTL, and cross-datacenter sync.
This guide walks you through a full production install on Ubuntu 24.04: the master/volume/filer architecture, systemd units for each process, the S3 gateway for drop-in compatibility with existing tooling, replication strategies (001/010/100), erasure coding for cold data, a WebDAV endpoint, and weed filer.sync for active-active cross-DC replication.
Need storage that scales past a single disk? Deploy SeaweedFS on our Professional VPS plan and get NVMe headroom, unmetered bandwidth, and a flat monthly bill — no per-GB surprises.
Table of Contents
What is SeaweedFS?
SeaweedFS is an open-source distributed object and file store written in Go. The design goal, from the project's first commit, was to make storing billions of small files cheap and fast on commodity hardware. The core trick — borrowed from Facebook's 2010 Haystack paper — is that instead of writing each uploaded file as its own inode on disk, SeaweedFS packs many objects into a large append-only "volume" file (32 GB by default). A volume has a single inode, a single file handle, and a small in-memory index that maps file IDs to offsets. Reading a 4 KB thumbnail becomes a single pread() on an already-open file descriptor — no directory traversal, no inode cache miss, no metadata server round-trip.
On top of that Haystack-style blob store, SeaweedFS adds several layers:
- Master server — a lightweight Raft-replicated process that tracks which volume servers hold which volumes, assigns new file IDs, and coordinates the topology (datacenter, rack, volume server tree).
- Volume server — the process that actually stores the bytes. One volume server can host hundreds of volumes and serves reads and writes directly to clients without going through the master.
- Filer — a process that maintains a directory tree and file metadata in an external store (LevelDB, PostgreSQL, MySQL, Redis, Cassandra, or the embedded store) and exposes it as a POSIX-like namespace. The filer is what makes S3 buckets, WebDAV, HDFS, and FUSE possible.
- S3 gateway — a subprocess of the filer that translates S3 API calls into filer operations.
- IAM, WebDAV, HDFS, FUSE gateways — additional front-ends, all talking to the same underlying volumes via the filer.
weed, that can run any combination of those roles. A single-node development install literally runs weed server -s3 and you have a fully functional S3-compatible store. Production installs split the master, volume, and filer into separate systemd services for isolation and independent scaling.SeaweedFS is under active development with monthly releases, has been in production at Shopify, Bytedance, and numerous smaller shops for years, and is one of the top-starred storage projects on GitHub. The official wiki is the canonical reference for advanced configuration.
SeaweedFS vs MinIO vs Ceph vs GlusterFS
Picking the right distributed store depends heavily on your workload. Here is how SeaweedFS lines up against the three most common alternatives.
| Dimension | SeaweedFS | MinIO | Ceph | GlusterFS |
|---|---|---|---|---|
| Primary interface | Object + File + S3 + HDFS + WebDAV | S3 only | Object (RGW) + Block (RBD) + File (CephFS) | POSIX file |
| Language | Go | Go | C++ | C |
| Binary size / install | ~60 MB single binary | ~120 MB single binary | 2+ GB, multi-daemon | ~50 MB per daemon |
| Small-file performance | Excellent (Haystack design) | Good | Poor (RADOS overhead per object) | Poor (one inode per file) |
| Large-file performance | Good | Excellent | Excellent | Excellent |
| Erasure coding | Yes (10+4 Reed-Solomon) | Yes (configurable) | Yes (configurable) | Yes (dispersed volumes) |
| Operational complexity | Low (3 processes) | Very low (1 process) | Very high (mon, mgr, osd, mds, rgw) | Medium |
| Cross-DC sync | Built-in via filer.sync | Site replication | RGW multisite | Geo-replication |
| Memory per TB | ~10-20 MB | ~100 MB | ~1 GB (OSD) | Moderate |
| License | Apache 2.0 | AGPLv3 | LGPL / multi | GPLv2 |
| Best for | Billions of small files, mixed access patterns, single-VPS to small cluster | Pure S3 workloads, enterprise backup targets | Large clusters needing unified block/file/object | NAS replacement, POSIX workloads |
Ceph is the heavyweight. It can do everything SeaweedFS does plus block storage (RBD) and a full POSIX file system (CephFS). The cost is operational: a production Ceph cluster needs at least three monitors, separate MDS daemons for CephFS, RGWs for S3, OSDs per disk, and careful CRUSH map planning. Ceph is the right answer for multi-petabyte clusters with dedicated storage engineers. SeaweedFS is the right answer for everyone else.
GlusterFS focuses on POSIX file semantics over the network. It has been the go-to for NAS-style deployments but has lost momentum since Red Hat wound down commercial support in 2023. For new projects, SeaweedFS or Garage (a geo-distributed S3-only store) are the more future-proof choices.
Garage deserves a mention: it is Rust-written, geo-distributed, S3-only, and extremely light. Pick Garage when you need multi-region active-active S3 and nothing else. Pick SeaweedFS when you need the extra protocols (WebDAV, HDFS, FUSE) or the small-file performance profile.
Architecture Overview: Master, Volume, Filer
Before installing anything, it helps to have a clear mental model of the three core processes.
+--------------------+
| Master server | (Raft, metadata, topology)
| port 9333 HTTP |
+---------+----------+
|
heartbeat/assignFid|lookup
|
+---------------------------+---------------------------+
| | |
+-----v------+ +------v-----+ +-------v-----+
| Volume | | Volume | | Volume |
| server 1 | | server 2 | | server 3 |
| port 8080 | | port 8080 | | port 8080 |
+-----+------+ +------+-----+ +-------+-----+
| | |
+-------- object data -------+---------------------------+
^
|
+---------+----------+
| Filer | (directory tree + metadata)
| port 8888 HTTP |
| port 8333 S3 |
| port 7333 WebDAV |
+--------------------+- The master is tiny. It handles
POST /dir/assignrequests ("give me a new file ID on a volume with replication 010") and tracks heartbeats from volume servers. It does not serve object bytes. - A volume server manages a set of volumes (large append-only files). Clients talk to it directly after the master tells them which volume to write to. One volume server typically maps to one physical host or one disk.
- The filer is optional for pure object workloads but mandatory for S3, WebDAV, HDFS, and FUSE. It keeps a directory tree in a metadata store (LevelDB by default; upgrade to PostgreSQL or Redis for higher write rates) and translates path-based calls into file-ID calls.
Prerequisites
- Ubuntu 24.04 LTS VPS with root or sudo access
- SSH access — port 22 open, or whatever port you have hardened it to
- At least 4 GB of RAM and 50 GB of disk for a small starter deployment (budget 2-3x your expected hot-data size)
curl,tar,fuse3(installed in Step 1)- A domain name pointing at your VPS (e.g.
s3.example.com) if you plan to expose the S3 gateway over TLS - Outbound internet access for package installs and Let's Encrypt
Recommended Plan: Professional>
SeaweedFS benefits from fast NVMe for its volume files and enough RAM to cache volume indices. For a single-node production deployment serving a mid-sized app we recommend Professional:>
- 6 vCPU
- 12 GB RAM
- 100 GB NVMe SSD
- Unmetered bandwidth
- EUR 19.99 / month>
For multi-node clusters, deploy one Professional VPS per volume server and a smaller Starter VPS for the master.
Connect via SSH:
ssh root@your-server-ipStep 1: Update the System
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl tar fuse3 ca-certificatesfuse3 is required only if you plan to use the weed mount command in Step 10. The rest is standard base tooling.
If the kernel was updated, reboot:
sudo rebootStep 2: Create the seaweedfs User and Data Layout
Run SeaweedFS as a dedicated unprivileged system user. Do not run it as root.
sudo useradd --system --home /var/lib/seaweedfs --shell /usr/sbin/nologin seaweedfsCreate the data directory tree:
sudo mkdir -p /var/lib/seaweedfs/{master,volume,filer}
sudo mkdir -p /etc/seaweedfs
sudo mkdir -p /var/log/seaweedfs
sudo chown -R seaweedfs:seaweedfs /var/lib/seaweedfs /var/log/seaweedfsThe three subdirectories under /var/lib/seaweedfs will hold, respectively:
master/— the master's Raft log and topology snapshotvolume/— the large.datand.idxvolume files (this is where your actual bytes live; point this at your largest disk in production)filer/— the embedded LevelDB metadata store for the filer (move to PostgreSQL for high write rates)
Step 3: Install the weed Binary from GitHub Releases
SeaweedFS does not publish official apt packages — the canonical install path is a single static binary from GitHub releases. This also means upgrades are a single binary swap.
Pick the latest linux_amd64_large_disk tarball (the "large disk" build supports volumes up to 256 GB; the regular build caps at 32 GB):
SEAWEED_VERSION="3.82"
cd /tmp
curl -fsSL "https://github.com/seaweedfs/seaweedfs/releases/download/${SEAWEED_VERSION}/linux_amd64_large_disk.tar.gz" -o weed.tar.gz
tar -xzf weed.tar.gz
sudo install -o root -g root -m 0755 weed /usr/local/bin/weedVerify:
weed versionExpected output:
version 30GB 3.82 linux amd64The 30GB/256GB prefix reflects the build variant. For write-heavy workloads with large objects (backup blobs, video), the large_disk build is strongly recommended because it avoids creating thousands of 32 GB volume files.
Step 4: systemd Unit for the Master Server
The master is stateless enough that a single instance is fine for a starter cluster. For HA, run three masters (covered in the FAQ).
Create /etc/systemd/system/seaweedfs-master.service:
sudo tee /etc/systemd/system/seaweedfs-master.service > /dev/null <<'EOF' [Unit] Description=SeaweedFS Master Server After=network-online.target Wants=network-online.target[Service] Type=simple User=seaweedfs Group=seaweedfs ExecStart=/usr/local/bin/weed master \ -mdir=/var/lib/seaweedfs/master \ -ip=127.0.0.1 \ -ip.bind=0.0.0.0 \ -port=9333 \ -defaultReplication=001 \ -volumeSizeLimitMB=30000 Restart=on-failure RestartSec=5s LimitNOFILE=65536
[Install] WantedBy=multi-user.target EOF
Key flags:
-defaultReplication=001sets the cluster-wide default replication to "one extra copy on another volume server on the same rack". Change to000for a single-node lab or010/100for higher durability (covered in Step 8).-volumeSizeLimitMB=30000caps each volume at ~30 GB. With thelarge_diskbuild you can safely push this to250000(250 GB).-ip=127.0.0.1is the address the master advertises to volume servers. On a single-host install this is loopback; on a multi-host cluster use the internal VLAN IP.
sudo systemctl daemon-reload
sudo systemctl enable --now seaweedfs-master
sudo systemctl status seaweedfs-master --no-pagerSmoke-test the master HTTP API:
curl http://127.0.0.1:9333/cluster/status | jqExpected output (abbreviated):
{
"IsLeader": true,
"Leader": "127.0.0.1:9333",
"Peers": []
}Step 5: systemd Unit for the Volume Server
Create /etc/systemd/system/seaweedfs-volume.service:
sudo tee /etc/systemd/system/seaweedfs-volume.service > /dev/null <<'EOF' [Unit] Description=SeaweedFS Volume Server After=network-online.target seaweedfs-master.service Wants=network-online.target Requires=seaweedfs-master.service[Service] Type=simple User=seaweedfs Group=seaweedfs ExecStart=/usr/local/bin/weed volume \ -dir=/var/lib/seaweedfs/volume \ -max=100 \ -mserver=127.0.0.1:9333 \ -ip=127.0.0.1 \ -port=8080 \ -dataCenter=dc1 \ -rack=rack1 \ -index=leveldb Restart=on-failure RestartSec=5s LimitNOFILE=1048576
[Install] WantedBy=multi-user.target EOF
Notable flags:
-max=100— maximum number of volumes this server will create. At 30 GB per volume with the default build, that is roughly 3 TB of raw capacity per volume server.-dataCenter=dc1 -rack=rack1— topology labels used by the replication placement engine. Even if you run on one box today, label it correctly — it makes future expansion trivial.-index=leveldb— keep the in-memory index on disk via LevelDB. Usememoryfor maximum speed if you have plenty of RAM, orbtreefor the middle ground.LimitNOFILE=1048576— SeaweedFS keeps many file descriptors open. The default Ubuntu limit of 1024 will cripple the volume server under load.
sudo systemctl daemon-reload
sudo systemctl enable --now seaweedfs-volume
sudo systemctl status seaweedfs-volume --no-pagerConfirm the volume server registered with the master:
curl -s http://127.0.0.1:9333/dir/status | jq '.Topology.DataCenters'You should see one volume server under dc1 → rack1.
Smoke Test: Upload and Download an Object
Ask the master for a new file ID:
curl -s http://127.0.0.1:9333/dir/assign | jqExpected:
{
"fid": "3,01637037d6",
"url": "127.0.0.1:8080",
"publicUrl": "127.0.0.1:8080",
"count": 1
}Upload a file against that fid:
echo "hello seaweed" > /tmp/hello.txt
curl -F file=@/tmp/hello.txt http://127.0.0.1:8080/3,01637037d6
curl http://127.0.0.1:8080/3,01637037d6The second curl prints hello seaweed. The volume store is working.
Step 6: systemd Unit for the Filer
The filer adds the directory namespace. Create /etc/seaweedfs/filer.toml:
sudo tee /etc/seaweedfs/filer.toml > /dev/null <<'EOF'
[leveldb2]
enabled = true
dir = "/var/lib/seaweedfs/filer"
EOF
sudo chown seaweedfs:seaweedfs /etc/seaweedfs/filer.tomlFor higher write rates, swap leveldb2 for a PostgreSQL or Redis backend — the filer.toml template at the wiki lists every option.
Create /etc/systemd/system/seaweedfs-filer.service:
sudo tee /etc/systemd/system/seaweedfs-filer.service > /dev/null <<'EOF' [Unit] Description=SeaweedFS Filer After=network-online.target seaweedfs-volume.service Wants=network-online.target Requires=seaweedfs-master.service[Service] Type=simple User=seaweedfs Group=seaweedfs Environment=WEED_LEVELDB2_DIR=/var/lib/seaweedfs/filer ExecStart=/usr/local/bin/weed filer \ -master=127.0.0.1:9333 \ -ip=127.0.0.1 \ -ip.bind=0.0.0.0 \ -port=8888 \ -defaultReplicaPlacement=001 Restart=on-failure RestartSec=5s LimitNOFILE=65536
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable --now seaweedfs-filer
Verify:
curl -s http://127.0.0.1:8888/ | headUpload a file to a path:
curl -F file=@/etc/hostname "http://127.0.0.1:8888/docs/hostname"
curl "http://127.0.0.1:8888/docs/hostname"List a directory:
curl -s "http://127.0.0.1:8888/docs/?pretty=y"The filer is now acting as a directory-aware front-end to the volume store.
Step 7: Enable the S3 API Gateway
The S3 gateway runs as a subprocess of the filer — you don't need another systemd service, just an additional weed s3 process pointed at the filer. For clean separation, run it as its own unit.
Generate an IAM-style credentials file at /etc/seaweedfs/s3.json:
ACCESS_KEY=$(openssl rand -hex 10)
SECRET_KEY=$(openssl rand -hex 20)
sudo tee /etc/seaweedfs/s3.json > /dev/null <<EOF
{
"identities": [
{
"name": "admin",
"credentials": [
{"accessKey": "${ACCESS_KEY}", "secretKey": "${SECRET_KEY}"}
],
"actions": ["Admin", "Read", "Write", "List", "Tagging"]
}
]
}
EOF
sudo chown seaweedfs:seaweedfs /etc/seaweedfs/s3.json
sudo chmod 600 /etc/seaweedfs/s3.json
echo "Access key: ${ACCESS_KEY}"
echo "Secret key: ${SECRET_KEY}"Save those keys somewhere safe.
Create /etc/systemd/system/seaweedfs-s3.service:
sudo tee /etc/systemd/system/seaweedfs-s3.service > /dev/null <<'EOF' [Unit] Description=SeaweedFS S3 API Gateway After=network-online.target seaweedfs-filer.service Wants=network-online.target Requires=seaweedfs-filer.service[Service] Type=simple User=seaweedfs Group=seaweedfs ExecStart=/usr/local/bin/weed s3 \ -filer=127.0.0.1:8888 \ -port=8333 \ -config=/etc/seaweedfs/s3.json Restart=on-failure RestartSec=5s LimitNOFILE=65536
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable --now seaweedfs-s3
Test with the AWS CLI:
sudo apt install -y awscli
aws configure set aws_access_key_id "${ACCESS_KEY}"
aws configure set aws_secret_access_key "${SECRET_KEY}"
aws --endpoint-url http://127.0.0.1:8333 s3 mb s3://backups
aws --endpoint-url http://127.0.0.1:8333 s3 cp /etc/hostname s3://backups/
aws --endpoint-url http://127.0.0.1:8333 s3 ls s3://backups/Every S3-aware tool — rclone, restic, aws-cli, boto3, velero, duplicati — works against http://127.0.0.1:8333 (or, after Step 12, https://s3.example.com) with no code changes.
Step 8: Replication Strategies (001, 010, 100)
SeaweedFS encodes replication as a three-digit string xyz:
| Position | Meaning | Example |
|---|---|---|
x | Extra copies on different data centers | 1xx = 1 copy in another DC |
y | Extra copies on different racks within the same DC | x1x = 1 copy on another rack |
z | Extra copies on different volume servers on the same rack | xx1 = 1 copy on another server |
000— no replication. Single-node labs only.001— one extra copy on another volume server, same rack. Minimum for production.010— one extra copy on another rack. Tolerates a rack-level failure.100— one extra copy in another datacenter. Tolerates a DC-level failure but writes incur WAN latency.011— one copy on another rack + one copy on another server same rack (3 total). Common for hot data.200— two extra copies in two different DCs (3 total). Maximum durability, maximum write latency.
-defaultReplication=010 (Step 4). Override per-file at upload time:curl -F [email protected] "http://127.0.0.1:8888/archive/bigfile.zip?replication=010"Or per-bucket on the S3 gateway:
aws --endpoint-url http://127.0.0.1:8333 s3api create-bucket \
--bucket critical-backups
then set replication on the filer directory that backs the bucket:
curl -X POST "http://127.0.0.1:8888/buckets/critical-backups/?op=configure&replication=010"To change replication on existing data, run:
weed shell
> volume.configure.replication -replication=010 -collection=backupsSeaweedFS will migrate volumes to the new placement in the background without downtime.
Step 9: Erasure Coding for Cold Data
Replication is fast but expensive — 010 costs 2x your raw storage. For cold data that rarely changes (backup snapshots, compliance archives, old logs) erasure coding (EC) drops overhead to roughly 1.4x while tolerating up to 4 lost shards out of 14.
SeaweedFS implements Reed-Solomon 10+4: each full volume is split into 10 data shards and 4 parity shards, distributed across at least 14 volume servers (or 14 disks if you run multiple volume servers on one box). Lose any 4 shards and the data is still recoverable.
EC is only applied to volumes that are read-only (no longer accepting writes). The typical workflow:
001 or 010 replication.Mark a volume read-only:
weed shell
> volume.mark -volumeId=3 -readonly=trueEncode all read-only volumes in a collection:
> ec.encode -collection=archive -fullPercent=95 -quietFor=3600-fullPercent=95— only EC volumes that are at least 95% full (skips half-empty volumes).-quietFor=3600— only EC volumes with no writes in the last hour.
> ec.balance -collection=archiveMonitor the transition:
> volume.listEach EC volume shows up as ecx.dat shards rather than full .dat files. For a deeper dive, the Erasure Coding wiki page walks through the math.
Rule of thumb: use replication for hot data (reads + writes within the last 30 days) and EC for everything older.
Step 10: WebDAV Endpoint and FUSE Mount
WebDAV
SeaweedFS ships a WebDAV gateway that any macOS Finder, Windows Explorer, or davfs2 client can mount. Create /etc/systemd/system/seaweedfs-webdav.service:
sudo tee /etc/systemd/system/seaweedfs-webdav.service > /dev/null <<'EOF' [Unit] Description=SeaweedFS WebDAV Gateway After=network-online.target seaweedfs-filer.service Requires=seaweedfs-filer.service[Service] Type=simple User=seaweedfs Group=seaweedfs ExecStart=/usr/local/bin/weed webdav \ -filer=127.0.0.1:8888 \ -port=7333 Restart=on-failure RestartSec=5s
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable --now seaweedfs-webdav
Mount from macOS: Finder → Go → Connect to Server → http://your-server:7333.
Mount from Linux:
sudo apt install -y davfs2
sudo mount -t davfs http://your-server:7333 /mnt/seaweedThis makes SeaweedFS a drop-in replacement for a network-attached disk — useful for cross-platform shared storage without running a full Nextcloud instance.
FUSE Mount via weed mount
For POSIX-style access on the same host:
sudo mkdir -p /mnt/seaweed
sudo weed mount \
-filer=127.0.0.1:8888 \
-dir=/mnt/seaweed \
-filer.path=/ \
-allowOthers=truels /mnt/seaweed now shows the filer tree. Writes, cp, rsync, tar — all standard POSIX tools work. To mount on boot, wrap it in a systemd service the same way we did for WebDAV.
Step 11: Cross-Datacenter Sync with weed filer.sync
For active-active replication between two SeaweedFS clusters in different regions, the canonical tool is weed filer.sync. It streams the filer's change log from cluster A to cluster B (and vice versa), typically with sub-second lag over a healthy WAN link.
On cluster A (with cluster B reachable at b.example.com):
sudo tee /etc/systemd/system/seaweedfs-filersync.service > /dev/null <<'EOF' [Unit] Description=SeaweedFS Filer Sync A -> B After=network-online.target seaweedfs-filer.service Requires=seaweedfs-filer.service[Service] Type=simple User=seaweedfs Group=seaweedfs ExecStart=/usr/local/bin/weed filer.sync \ -a=127.0.0.1:8888 \ -b=b.example.com:8888 \ -a.debug=false Restart=on-failure RestartSec=10s
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable --now seaweedfs-filersync
weed filer.sync is bidirectional by default — it syncs A → B and B → A simultaneously and resolves conflicts by timestamp (last-writer-wins). For write-heavy workloads where collisions are possible, partition your keyspace (e.g., each region only writes to its own bucket) and use sync purely for disaster recovery.
To verify sync health, watch the progress metric:
curl -s http://127.0.0.1:8888/metrics | grep filer_syncReal-time lag should stay under a second on a healthy link.
Step 12: Secure the APIs with Nginx and TLS
By default SeaweedFS speaks plain HTTP. For any internet-facing deployment, terminate TLS at Nginx.
sudo apt install -y nginx certbot python3-certbot-nginxCreate /etc/nginx/sites-available/seaweedfs:
# S3 gateway server { listen 443 ssl http2; server_name s3.example.com;ssl_certificate /etc/letsencrypt/live/s3.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/s3.example.com/privkey.pem;
client_max_body_size 5g;
location / { proxy_pass http://127.0.0.1:8333; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 600s; proxy_buffering off; } }
Filer HTTP API (optional - tighten access)
server { listen 443 ssl http2; server_name filer.example.com;ssl_certificate /etc/letsencrypt/live/filer.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/filer.example.com/privkey.pem;
location / { allow 203.0.113.0/24; # your office CIDR deny all; proxy_pass http://127.0.0.1:8888; proxy_set_header Host $host; } }
Enable and provision:
sudo ln -s /etc/nginx/sites-available/seaweedfs /etc/nginx/sites-enabled/
sudo certbot --nginx -d s3.example.com -d filer.example.com
sudo nginx -t && sudo systemctl reload nginxInstall CrowdSec or Fail2ban on the same host to throttle brute-force attempts against the S3 credentials.
Export metrics to Prometheus — SeaweedFS exposes /metrics on every process in Prometheus format. Scrape 127.0.0.1:9333/metrics, 127.0.0.1:8080/metrics, and 127.0.0.1:8888/metrics for master, volume, and filer telemetry respectively, then build dashboards in Grafana.
CloudCore Pricing Tiers
Picking the right CloudCore plan depends on your storage footprint, object count, and redundancy requirements.
| Plan | vCPU / RAM / Disk | Best Fit | Monthly |
|---|---|---|---|
| CloudCore Starter | 2 vCPU / 4 GB / 50 GB NVMe | Single-node lab, dev/staging filer, <10 GB hot data | EUR 7.99 |
| CloudCore Professional | 6 vCPU / 12 GB / 100 GB NVMe | Production single-node SeaweedFS, ~50 GB hot + warm data, S3 backend for a small app | EUR 19.99 |
| CloudCore Business | 8 vCPU / 24 GB / 400 GB NVMe | Dedicated volume server, ~300 GB with 001 replication, EC-backed cold tier, high-traffic filer workloads | EUR 29.99 |
010 setup is 2x Professional plus 1x Starter for the master; a 100 cross-DC setup is 2x Professional in different regions plus filer.sync.Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
No free volumes left on upload | All volumes at -max limit and full | Raise -max on the volume server, or add another volume server to the cluster |
rpc error: code = Unavailable from S3 gateway | Filer down or network path broken | systemctl status seaweedfs-filer; check that S3 gateway points at the correct filer host |
volume 3 is not found | Volume is EC-encoded or offline | volume.list in weed shell; if EC, reads work transparently via the master — ensure the master sees all shards |
| High memory on volume server | In-memory index with many volumes | Switch -index=leveldb in the volume unit and restart |
S3 SignatureDoesNotMatch | Clock skew or wrong region | Sync time with systemctl restart systemd-timesyncd; set AWS_REGION=us-east-1 (SeaweedFS default) |
Too many open files | systemd LimitNOFILE too low | Already set to 1,048,576 in the volume unit above; raise fs.file-max sysctl if needed |
| filer.sync lag growing | WAN saturated or one side behind | Check filer_sync_lag_ms metric; reduce write rate or provision more bandwidth |
| WebDAV refuses large files | Missing client_max_body_size | Raise the Nginx client_max_body_size to match your largest expected object |
| EC encoding slow | Single-threaded per volume | Run ec.encode during off-peak; CPU-bound, use a beefier plan during the migration |
Useful Commands
# Live logs for any component
sudo journalctl -u seaweedfs-master -f
sudo journalctl -u seaweedfs-volume -f
sudo journalctl -u seaweedfs-filer -fInteractive admin shell
weed shell -master=127.0.0.1:9333Inside the shell
> cluster.check
> volume.list
> fs.du /
> volume.balancecluster.check runs a full sanity pass — topology consistency, replica placement, volume health. Run it daily via cron and alert on non-empty output.
FAQ
What is SeaweedFS and how is it different from MinIO or Ceph?
SeaweedFS is a distributed object store inspired by Facebook's Haystack paper. Unlike MinIO — which focuses on S3 only — SeaweedFS exposes object, file (filer), HDFS, WebDAV, and S3 interfaces simultaneously on top of the same storage. It is much lighter than Ceph, runs as a single Go binary, scales to billions of small files efficiently, and supports per-collection replication and erasure coding. Ceph remains the right tool for multi-petabyte unified storage, but SeaweedFS covers 95% of self-hosted object-storage use cases at a fraction of the operational cost.
Do I need Kubernetes to run SeaweedFS?
No. SeaweedFS runs perfectly as plain systemd services on a single VPS or across a handful of VPS nodes, which is exactly the pattern this guide uses. Kubernetes Helm charts exist for larger clusters, but the binary itself has no orchestration requirement — each process is a simple weed <role> command.
What is the difference between the master, volume server, and filer?
The master tracks which volume servers hold which volumes and assigns new file IDs — it is the cluster coordinator. Volume servers hold the actual blobs in large append-only files. The filer adds a directory tree, metadata store, TTL, S3 buckets, and POSIX-like semantics on top of the volumes. Small clusters run all three on one VPS; large clusters split them across nodes and scale volume servers horizontally.
What do the replication codes 001, 010, and 100 mean?
Replication is encoded as xyz where x is extra copies on different data centers, y on different racks within the same DC, and z on different volume servers on the same rack. 001 = 1 extra copy on another server; 010 = 1 copy on another rack; 100 = 1 copy on another data center. Combine them for stronger durability — 022 keeps two rack-level copies plus two same-rack copies for 5 replicas total.
When should I enable erasure coding?
Enable EC once a volume stops receiving writes — typically on cold or archival data older than 30 days. EC converts a full volume into 14 shards (10 data + 4 parity) with roughly 1.4x overhead instead of 2x or 3x for replication, while still tolerating up to 4 shard losses. This is the recommended storage class for backup snapshots and write-once-read-rarely data. Keep hot data on replication for lower latency.
Can I run SeaweedFS behind a highly available setup?
Yes. Run 3 or 5 masters with the -peers flag for Raft quorum, distribute volume servers across racks/DCs to match your replication placement, and run multiple filers behind a load balancer. The filer metadata store (LevelDB → PostgreSQL/Redis/Cassandra) becomes the scaling bottleneck past a few million writes per day, so budget for a managed PostgreSQL or a Redis cluster in HA deployments.
Is SeaweedFS fully S3 compatible?
The S3 gateway supports the most commonly used operations — bucket lifecycle, multipart upload, pre-signed URLs, versioning, object tagging, ACLs, IAM policy subset, and server-side encryption. A few edge-case APIs (inventory, replication config, object lock Compliance mode) are partial. For 95% of S3 tooling — AWS CLI, rclone, restic, Velero, boto3, JS SDK — SeaweedFS is a drop-in replacement.
How does SeaweedFS compare to GlusterFS?
GlusterFS is a POSIX file system focused on network-attached storage semantics. SeaweedFS is object-first with a filer layer added on top. For workloads dominated by small files — thumbnails, avatars, chunked backups, ML training shards — SeaweedFS is typically an order of magnitude faster because it colocates many objects in one volume file and avoids GlusterFS's distributed hash table overhead. For pure POSIX NAS workloads where every file is large and clients expect traditional file semantics, GlusterFS is still a reasonable choice.
How do I back up SeaweedFS itself?
Three layers: (1) take filesystem snapshots of /var/lib/seaweedfs/volume on each volume server — because volumes are append-only, a snapshot is trivially consistent; (2) back up the filer metadata store (LevelDB directory or PostgreSQL dump) independently; (3) run weed filer.backup to stream filer state to another SeaweedFS cluster or to an S3 bucket at another provider for off-site redundancy.
Next Steps
With SeaweedFS running, the highest-leverage follow-ups are:
- Install MinIO on a second VPS and run both side by side during evaluation — MinIO's web console is polished and makes policy editing easier than hand-writing JSON, while SeaweedFS carries the small-file and multi-protocol advantages. Many teams use MinIO for tenant-facing buckets and SeaweedFS for internal backup/archive.
- Deploy Garage if you specifically need geo-distributed S3 with strong consistency across regions. Garage's CRDT-based design handles WAN partitions more gracefully than filer.sync for purely S3 workloads.
- Connect Nextcloud with SeaweedFS as primary object storage — Nextcloud supports S3 as its primary storage backend, which means all user files land directly in your SeaweedFS cluster. You get Nextcloud's collaboration UI plus SeaweedFS's storage economics.
- Scrape metrics with Prometheus — every
weedprocess exposes/metrics. A pre-built Grafana dashboard lives at grafana.com/dashboards/17216 — import it and you have latency, IOPS, and volume-health graphs in minutes.
- Back up databases with restic to the S3 gateway —
restic -r s3:https://s3.example.com/backups initfollowed byrestic backup /var/lib/postgresqlgives you versioned, deduplicated, encrypted backups with zero additional software.
- Read the official SeaweedFS wiki for advanced topics: multiple masters with Raft, Cassandra filer backend, S3 IAM policies, object lock, lifecycle rules, tiered storage to remote S3 (cloud tiering), and the Kubernetes operator.
- Explore tiered storage — SeaweedFS can tier cold EC volumes to cheaper external S3 (AWS S3 Glacier, Backblaze B2, Wasabi) while keeping hot volumes on local NVMe. You get the best of both worlds: fast local reads for recent data and archive economics for the long tail.
Skip the Manual Install — Deploy SeaweedFS on a Professional VPS>
Our Professional plan gives you the NVMe and RAM headroom SeaweedFS needs to stretch its legs — enough for a production single-node install with the S3 gateway, WebDAV, and filer.sync replication to a second region.>
- 6 vCPU, 12 GB RAM, 100 GB NVMe
- Unmetered bandwidth
- EUR 19.99 / month>
Deploy your storage VPS and have SeaweedFS serving S3 traffic within the hour.