How to Deploy SeaweedFS - An open-source S3 Storage Alternative to MinIO

Updated on 08 May, 2026
Deploy SeaweedFS with Docker Compose, HTTPS, Traefik, and S3-compatible distributed object storage access.
How to Deploy SeaweedFS - An open-source S3 Storage Alternative to MinIO header image

SeaweedFS is an Open-Source, high-performance distributed storage system for blobs, objects, files, and S3-compatible access. It includes a master, a volume server, a filer, an S3 gateway, and an admin interface.

This article shows you how to deploy a single-node SeaweedFS with Traefik using Docker Compose on Ubuntu 24.04. It also shows you how to secure it with Let's Encrypt certificates, how to access it, and perform basic operations.

Prerequisites

Before you begin, ensure you:

Set Up the Directory Structure, Configuration, and Environment Variables

Set up a project directory to store your configuration files and generate authentication credentials.

Set up Directories and Configuration Files

  1. Create and navigate to the project's folder.

    console
    $ mkdir seaweedfs && cd seaweedfs
    
  2. Run the following command twice to generate access and secret keys for your S3 configuration.

    console
    $ openssl rand -hex 16
    

    Note the values to use in the later steps.

  3. Create a .env file to store the deployment variables used by Docker Compose.

    console
    $ nano .env
    
  4. Add the following content. Replace storage.example.com with your admin subdomain, your-email@example.com with your email address for Let's Encrypt notifications, and yourpassword with a strong password for the admin dashboard.

    ini
    STORAGE_DOMAIN=storage.example.com
    LETSENCRYPT_EMAIL=your-email@example.com
    ADMIN_PASSWORD=yourpassword
    

    Save and close the file.

  5. Create ./s3-config.json to configure S3 authentication.

    console
    $ nano s3-config.json
    
  6. Add the following content. Replace YOUR_ACCESS_KEY and YOUR_SECRET_KEY with the values generated above.

    json
    {
      "identities": [
        {
          "name": "admin",
          "credentials": [
            {
              "accessKey": "YOUR_ACCESS_KEY",
              "secretKey": "YOUR_SECRET_KEY"
            }
          ],
          "actions": [
            "Admin",
            "Read",
            "Write",
            "List",
            "Tagging"
          ]
        }
      ]
    }
    

    Save and close the file.

Deploy with Docker Compose

Define your Docker Compose services with Traefik labels for automatic discovery and TLS.

  1. Create the Docker Compose file.

    console
    $ nano docker-compose.yml
    
  2. Copy and paste the following configuration into the file.

    yaml
    services:
      traefik:
        image: traefik:v3.7.0
        container_name: traefik
        restart: unless-stopped
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
          - ./letsencrypt:/letsencrypt
        command:
          - --providers.docker=true
          - --providers.docker.exposedByDefault=false
          - --entrypoints.web.address=:80
          - --entrypoints.websecure.address=:443
          - --entrypoints.web.http.redirections.entrypoint.to=websecure
          - --entrypoints.web.http.redirections.entrypoint.scheme=https
          - --entrypoints.web.http.redirections.entrypoint.permanent=true
          - --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}
          - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
          - --certificatesresolvers.letsencrypt.acme.httpchallenge=true
          - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
    
      master:
        image: chrislusf/seaweedfs:latest
        container_name: seaweed-master
        command: master -ip.bind=0.0.0.0 -port=9333
        volumes:
          - ./master-data:/data
        restart: unless-stopped
    
      volume:
        image: chrislusf/seaweedfs:latest
        container_name: seaweed-volume
        command: volume -mserver=master:9333 -port=8080 -ip.bind=0.0.0.0
        volumes:
          - ./volume-data:/data
        depends_on:
          - master
        restart: unless-stopped
    
      filer:
        image: chrislusf/seaweedfs:latest
        container_name: seaweed-filer
        command: filer -master=master:9333 -port=8888 -ip.bind=0.0.0.0
        volumes:
          - ./filer-data:/data
        depends_on:
          - master
          - volume
        restart: unless-stopped
    
      s3:
        image: chrislusf/seaweedfs:latest
        container_name: seaweed-s3
        command: s3 -filer=filer:8888 -port=8333 -ip.bind=0.0.0.0 -config=/etc/seaweedfs/s3.json
        volumes:
          - ./s3-config.json:/etc/seaweedfs/s3.json
        depends_on:
          - filer
        restart: unless-stopped
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.s3.rule=Host(`s3.${STORAGE_DOMAIN}`)"
          - "traefik.http.routers.s3.entrypoints=websecure"
          - "traefik.http.routers.s3.tls.certresolver=letsencrypt"
          - "traefik.http.services.s3.loadbalancer.server.port=8333"
    
      admin:
        image: chrislusf/seaweedfs:latest
        container_name: seaweed-admin
        command: 'admin -masters="master:9333" -port=23646 -adminUser=admin -adminPassword=${ADMIN_PASSWORD} -dataDir=/data'
        volumes:
          - ./admin-data:/data
        depends_on:
          - master
        restart: unless-stopped
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.admin.rule=Host(`${STORAGE_DOMAIN}`)"
          - "traefik.http.routers.admin.entrypoints=websecure"
          - "traefik.http.routers.admin.tls.certresolver=letsencrypt"
          - "traefik.http.services.admin.loadbalancer.server.port=23646"
    

    Save and close the file.

    Docker Compose reads the .env file automatically. The ${STORAGE_DOMAIN}, ${LETSENCRYPT_EMAIL}, and ${ADMIN_PASSWORD} placeholders are substituted with the values you set earlier. Traefik uses the labels to route:

    • storage.example.com to the SeaweedFS Admin UI.
    • s3.storage.example.com to the S3 API endpoint.

    The configuration defines the following services:

    • Traefik — reverse proxy that discovers services through Docker labels, obtains and renews Let's Encrypt certificates, and redirects HTTP traffic to HTTPS.
    • Master — centralized metadata coordinator. It manages cluster topology and volume locations. Data persists in ./master-data.
    • Volume — stores file chunks under instruction from the master. Data persists in ./volume-data.
    • Filer — provides a filesystem interface and integrates with the master and volume server.
    • S3 — S3-compatible API gateway for programmatic object uploads and downloads.
    • Admin — web dashboard for browsing and managing uploaded files, protected by the password set in ADMIN_PASSWORD.
  3. Add the current user to the docker group so that you can run Docker commands without sudo.

    console
    $ sudo usermod -aG docker $USER
    
  4. Apply the group change to the current shell session.

    console
    $ newgrp docker
    
  5. Start the Docker Compose services in detached mode.

    console
    $ docker compose up -d
    
  6. Verify that all services are running.

    console
    $ docker compose ps
    

Test SeaweedFS

Test SeaweedFS functionality by uploading and downloading a file from your local terminal through the S3 API.

  1. Configure the AWS CLI with your SeaweedFS S3 credentials. Run the following command and enter each value when prompted.

    console
    $ aws configure --profile seaweedfs
    
    • AWS Access Key ID — enter the accessKey value from s3-config.json.
    • AWS Secret Access Key — enter the secretKey value from s3-config.json.
    • Default region name — press Enter to leave it empty. SeaweedFS does not use the region value.
    • Default output format — enter json.
  2. Create a bucket.

    console
    $ aws --endpoint-url https://s3.storage.example.com --profile seaweedfs s3 mb s3://test-bucket
    
  3. Upload a test file called test.txt.

    console
    $ echo "This is test content." | aws --endpoint-url https://s3.storage.example.com --profile seaweedfs s3 cp - s3://test-bucket/test.txt
    
  4. Download the test file.

    console
    $ aws --endpoint-url https://s3.storage.example.com --profile seaweedfs s3 cp s3://test-bucket/test.txt downloaded.txt
    
  5. Verify the file contents.

    console
    $ cat downloaded.txt
    

    The output displays the contents of the file.

    This is test content.

Application Use Cases

  1. Open https://storage.example.com in a web browser and log in with the username admin and the ADMIN_PASSWORD value that you set in the .env file.

    SeaweedFS dashboard homepage

  2. Navigate the bucket in the Buckets tab.

    SeaweedFS bucket management tab

    In this tab, you can create a new bucket, delete a bucket, view a bucket's details, change bucket ownership, and set a bucket's storage quota.

  3. Navigate into your test-bucket sample to view the contents inside.

    SeaweedFS bucket browser tab

    In this tab, you can browse the contents of a bucket, download them, view them, delete them, check their properties, or create new folders.

Conclusion

You have successfully deployed SeaweedFS with Docker Compose and secured its public endpoints using Traefik and Let's Encrypt. The admin dashboard is accessible at https://storage.example.com and the S3-compatible API is available at https://s3.storage.example.com. For more information, refer to the official SeaweedFS documentation.

Comments