SafeBucket
On-prem file sharing made simple, fast and safe
Alternative to: WeTransfer, ShareFile, Dropbox Transfer
SafeBucket is an open source file sharing platform with pluggable infrastructure where files bypass the server via presigned uploads and downloads. It supports public share links with expiration and password protection, OIDC SSO with role-based access control, audit logging, and swappable storage, database, and cache backends.
SafeBucket Docker Compose example
Self-host SafeBucket on your own server, homelab, or VPS starting from this Docker Compose example.
It runs SafeBucket in Docker containers using the official ghcr.io/safebucket/safebucket:latest, rustfs/rustfs:latest, amazon/aws-cli:latest images, with persistent volumes and automatic restarts preconfigured.
Review the environment variables and adjust them to your setup, save the file as compose.yml (or docker-compose.yml), and start the stack with docker compose up -d.
services:
safebucket:
image: ghcr.io/safebucket/safebucket:latest
restart: unless-stopped
environment:
# Log verbosity (debug, info, warn, error).
APP__LOG_LEVEL: "info"
# Configuration profile.
APP__PROFILE: "default"
# Public URL of the API (usually the same host as the web UI).
APP__API_URL: "https://safebucket.example.com"
# Public URL where the web UI is reached (e.g. https://files.example.com).
APP__WEB_URL: "https://safebucket.example.com"
# Port the app listens on inside the container.
APP__PORT: "8080"
# CIDR ranges of trusted reverse proxies (X-Forwarded-* handling).
APP__TRUSTED_PROXIES: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128"
# Serve the bundled web UI from the app (keep true).
APP__STATIC_FILES__ENABLED: "true"
# Secret used to sign auth tokens. Use a long random string.
APP__TOKEN_SECRET: "5ugUl8bMKAnm/I1ZpbJF3klvD/Q7d2g6vi8slufTMs0="
# Email address of the initial admin account created on first boot.
APP__ADMIN_EMAIL: "admin@safebucket.io"
# Password of the initial admin account created on first boot.
APP__ADMIN_PASSWORD: "changeme"
# Comma-separated origins allowed for browser (CORS) requests; include your public URL.
APP__ALLOWED_ORIGINS: "https://safebucket.example.com"
# Days deleted files are kept in trash before permanent removal.
APP__TRASH_RETENTION_DAYS: "7"
# AES-256 key for MFA secrets — must be exactly 32 characters.
APP__MFA_ENCRYPTION_KEY: "ChangeMe32CharacterKeyForAES256!"
# Require multi-factor authentication for all users (true/false).
APP__MFA_REQUIRED: "false"
# Maximum upload size in bytes (default 50 GB).
APP__MAX_UPLOAD_SIZE: "53687091200"
# Storage backend type.
STORAGE__TYPE: "rustfs"
# Name of the S3 bucket used for object storage.
STORAGE__RUSTFS__BUCKET_NAME: "safebucket"
# Internal endpoint the app uses to reach the object store.
STORAGE__RUSTFS__ENDPOINT: "bucket:9000"
# Public URL of the object store that browsers use for presigned up/downloads.
STORAGE__RUSTFS__EXTERNAL_ENDPOINT: "https://s3.example.com"
# Object-store access key.
STORAGE__RUSTFS__ACCESS_KEY: "rustfsadmin"
# Object-store secret key.
STORAGE__RUSTFS__SECRET_KEY: "changeme"
# Metadata database type (self-contained SQLite by default).
DATABASE__TYPE: "sqlite"
# Path to the SQLite database file.
DATABASE__SQLITE__PATH: "/app/data/safebucket.db"
# Cache backend (in-memory by default).
CACHE__TYPE: "memory"
# Event bus backend (in-memory by default).
EVENTS__TYPE: "memory"
EVENTS__QUEUES__NOTIFICATIONS__NAME: "safebucket-notifications"
EVENTS__QUEUES__BUCKET_EVENTS__NAME: "safebucket-bucket-events"
EVENTS__QUEUES__OBJECT_DELETION__NAME: "safebucket-object-deletion"
# Notifier backend and where it stores queued notifications.
NOTIFIER__TYPE: "filesystem"
NOTIFIER__FILESYSTEM__DIRECTORY: "/app/data/notifications"
# Activity log backend and where it stores entries.
ACTIVITY__TYPE: "filesystem"
ACTIVITY__FILESYSTEM__DIRECTORY: "/app/data/activity"
# Enabled authentication providers.
AUTH__PROVIDERS__KEYS: "local"
AUTH__PROVIDERS__LOCAL__NAME: "local"
AUTH__PROVIDERS__LOCAL__TYPE: "local"
# Allow local users to share files (true/false).
AUTH__PROVIDERS__LOCAL__SHARING__ALLOWED: "true"
# Go garbage-collector aggressiveness.
GOGC: "50"
volumes:
- safebucket_data:/app/data
depends_on:
bucket-init:
condition: service_completed_successfully
bucket:
image: rustfs/rustfs:latest
restart: unless-stopped
environment:
# Object-store access key.
RUSTFS_ACCESS_KEY: "rustfsadmin"
# Object-store secret key.
RUSTFS_SECRET_KEY: "changeme"
volumes:
- rustfs_data:/data
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:9000/health && curl -f http://localhost:9001/rustfs/console/health"]
interval: 3s
timeout: 2s
retries: 10
start_period: 2s
bucket-init:
image: amazon/aws-cli:latest
environment:
# Credentials and target used to create the bucket and apply its CORS policy.
AWS_ACCESS_KEY_ID: "rustfsadmin"
AWS_SECRET_ACCESS_KEY: "changeme"
AWS_RETRY_MODE: "standard"
AWS_MAX_ATTEMPTS: "5"
AWS_REGION: "us-east-1"
BUCKET_NAME: "safebucket"
ENDPOINT_URL: "http://bucket:9000"
entrypoint: ["/bin/sh", "-c"]
command:
- |
echo "Configuring RustFS buckets via aws-cli..."
echo "Waiting for RustFS to be ready..."
while ! aws s3api head-bucket --bucket $${BUCKET_NAME} --endpoint-url $${ENDPOINT_URL} 2>/dev/null; do
echo "Checking if bucket exists... if not creating it."
aws s3api create-bucket --bucket $${BUCKET_NAME} --endpoint-url $${ENDPOINT_URL} 2>/dev/null || true
sleep 2
done
echo "RustFS is ready and bucket $${BUCKET_NAME} exists."
echo "Applying CORS policy..."
aws s3api put-bucket-cors --bucket $${BUCKET_NAME} --endpoint-url $${ENDPOINT_URL} --cors-configuration '{"CORSRules":[{"AllowedHeaders":["*"],"AllowedMethods":["GET","PUT","POST","DELETE","HEAD"],"AllowedOrigins":["*"],"ExposeHeaders":["ETag"]}]}'
echo "Buckets configured successfully."
depends_on:
bucket:
condition: service_healthy
restart: "no"
volumes:
safebucket_data:
rustfs_data:
Values set to changeme are required — replace them with your own
values before starting SafeBucket.
Prefer a managed setup? WinterFlow installs, configures, and updates SafeBucket for you using this same Docker Compose configuration.