SeaweedFSยถ

Descriptionยถ

SeaweedFS is a fast distributed storage system for blobs, objects, and files. It exposes an S3-compatible API, so applications store and retrieve objects with standard S3 SDKs and CLIs.

Overviewยถ

This role deploys SeaweedFS as the central provider of the project-wide object-store service (engine seaweedfs). Web-app roles consume it like a database: they enable a seaweedfs service in their meta/services.yml and resolve host, port, bucket, and credentials through the objstore lookup. A single server container runs master, volume, filer, and the S3 gateway in one process. The role serves one canonical domain:

  • api.seaweedfs.s3.* is the public S3 endpoint and is reachable without SSO gating.

The browser interfaces for the filer and master are served by web-app-seaweedfs, which reaches this role over the shared object-store network. A node running this role without the console keeps its object store and its S3 endpoint; it simply has no browser console.

Per-consumer S3 identities are rendered into s3.json: each consuming role receives an access key and bucket-scoped Read, Write, WriteAcp, List, and Tagging actions, and consumers marked public additionally receive anonymous read on their bucket. Consumer buckets are created through weed shell when a consumer role requests provisioning. The bucket of every consumer not marked public carries a bucket policy statement DenyAnonymousRead that denies all unsigned reads, so a public-read ACL set by an app never exposes an object; signed and presigned requests are unaffected. Every deploy of this role converges that statement on all existing consumer buckets, adding it to private buckets and removing it from public ones, and a consumerโ€™s provisioning applies it right after creating the bucket. Other statements an operator adds to a consumerโ€™s bucket policy are kept.

Every vhost of a shared consumer marked public also serves its bucket under /_infinito/objstore/<bucket>/, and lookup('objstore', application_id, 'relative_url') returns that host-relative base for URLs a browser loads. The route passes GET and HEAD for object keys only: it answers 404 for a path ending in /, drops the query string and the Authorization and Cookie headers, and sends the request over the loopback to the api.seaweedfs.s3.* vhost. Responses carry X-Content-Type-Options: nosniff and a sandbox Content Security Policy. A consumer without public: true or in embedded mode gets an empty relative_url and no route.

In embedded mode (shared: false) a consumerโ€™s compose stack receives a storage-only SeaweedFS container without UI or published ports. The embedded S3 listener starts without identities and accepts unauthenticated requests until the background s3.configure grant at startup registers the consumer identity; from then on it authenticates against that identity. Embedded buckets carry no DenyAnonymousRead statement because the listener publishes no port, so the container MUST stay confined to the consumerโ€™s isolated compose network.

Architectureยถ

ARCHITECTURE.md draws SeaweedFS from its own metadata: the containers it runs under compose, what changes under swarm, how each volume is backed, and every role it depends on or is depended upon by.

Section

Drawn from

Compose

meta/services.yml

Swarm

meta/services.yml replicas and placement

Volumes

meta/volumes.yml against the NFS decision chain

Dependencies

meta/services.yml and meta/main.yml of every role

Featuresยถ

  • S3-compatible API: Standard S3 SDKs and CLIs work against the gateway for uploads, media, attachments, and exports.

  • Central object-store service: One shared instance serves all consuming web-app roles, mirroring the shared database pattern.

  • Per-consumer isolation: Every consumer receives its own identity and bucket with bucket-scoped actions only.

  • Separable console: The browser interfaces deploy and scale independently of the storage engine.

  • Embedded mode: Roles that opt out of the shared instance run a private storage-only container inside their own compose network.

Quick Setupยถ

Developmentยถ

Clone, set up the workstation, and deploy SeaweedFS onto the local stack:

git clone https://github.com/infinito-nexus/core.git
cd core
make onboard
make compose-deploy mode=reinstall apps=web-svc-seaweedfs full_cycle=false

Productionยถ

Run the published image to provision the inventory and deploy SeaweedFS to a managed server over SSH. The image logs in as root, so the server must accept root over a public key, and the two key variables are the two halves of one key pair: the private half authenticates the deploy, and the public half is what the deploy keeps authorized for root and installs for the administrator account. Naming a public half that does not belong to the private one locks the running deploy out at its next reconnect.

APP=web-svc-seaweedfs
HOST="<your-server>"
DOMAIN="<your-domain>"
TLS_MODE=self_signed
SSH_PUBLIC_KEY="<your-ssh-public-key>"
SSH_PRIVATE_KEY="<your-ssh-private-key-file>"
WORKDIR="$HOME/.infinito.nexus"

mkdir -p "$WORKDIR/inventories"
docker run --rm \
  -v "$WORKDIR/inventories:/etc/infinito.nexus/inventories" \
  -v "$SSH_PRIVATE_KEY:/run/secrets/deploy_key:ro" \
  -e APP="$APP" -e HOST="$HOST" -e DOMAIN="$DOMAIN" -e TLS_MODE="$TLS_MODE" -e SSH_PUBLIC_KEY="$SSH_PUBLIC_KEY" \
  ghcr.io/infinito-nexus/core/debian:latest bash -c '
    INVENTORY=/etc/infinito.nexus/inventories/production
    infinito administration inventory provision "$INVENTORY" \
      --inventory-file "$INVENTORY/devices.yml" \
      --host "$HOST" \
      --include "$APP" \
      --vars "{\"TLS_MODE\": \"$TLS_MODE\", \"DOMAIN_PRIMARY\": \"$DOMAIN\", \"SYS_SVC_SSHD_PERMIT_ROOT_LOGIN\": \"prohibit-password\", \"users\": {\"root\": {\"authorized_keys\": [\"$SSH_PUBLIC_KEY\"]}, \"administrator\": {\"authorized_keys\": [\"$SSH_PUBLIC_KEY\"]}}}" &&
    infinito administration deploy dedicated "$INVENTORY/devices.yml" \
      --password-file "$INVENTORY/.password" \
      -u root --private-key /run/secrets/deploy_key \
      --diff -vv'

The inventory under $WORKDIR is written by the container as root, including the vault password at inventories/production/.password. Run sudo chown -R "$USER" "$WORKDIR" afterwards to read it.

Further Resourcesยถ

Creditsยถ

Kevin Veen-Birkenbach

Part of the Infinito.Nexus Project and maintained by Kevin Veen-Birkenbach. Licensed under the Infinito.Nexus Community License (Non-Commercial).

That licence covers this role. The software it deploys is a separate grant: Apache-2.0, under which commercial use is allowed. You owe its authors this much: keep the copyright notice and the licence text. Permission for one of the two is not permission for the other.