Self-hosted · Free · Secure
Self-hosted — your data stays yours
Free, self-hosted file synchronization and sharing for teams. Deploy on your own infrastructure, keep full control of your data. One binary, zero external dependencies.
Your data, your infrastructure, your rules. Deploy on your own server with full control.
Instant delta sync across all your devices via WebSocket. Always up to date.
Owner / Editor / Viewer + Group hierarchy. Precise access control for every file and folder.
Full version history with content-addressable storage. Restore any previous version instantly.
Go + SQLite. One binary, zero external dependencies. Deploy in seconds.
Native macOS app, Linux server, and CLI for both platforms. Sync everywhere.
Create shared spaces, invite team members, and collaborate with granular access control.
Deleted files go to trash first. Recover accidentally deleted files with one click.
Download the right binary for your platform
Everything you need to go from a fresh VPS to a running SyncBox instance. Pick your deployment method.
Get SyncBox running in under 5 minutes. Good for testing and evaluation — for production, use the Production (VPS) tab.
curl -L -o syncbox-server /downloads/syncbox-server-linux-amd64 chmod +x syncbox-server
openssl rand -hex 32
Save this output — you'll paste it into your config file below.
cat <<'EOF' > config.yaml server: addr: "0.0.0.0:8080" storage: type: "local" path: "./data/storage" database: path: "./data/syncbox.db" auth: jwt_secret: "PASTE_YOUR_64_CHAR_HEX_HERE" admin: email: "[email protected]" EOF
mkdir -p ./data/storage ./syncbox-server --config config.yaml
curl http://localhost:8080/health
# → {"status":"ok","version":"3.0"}
Open http://YOUR_IP:8080 in a browser. Register with your admin email to become the first admin user.
Complete production setup on Ubuntu/Debian with systemd, Nginx, and HTTPS. Tested on Ubuntu 22.04/24.04.
# Install dependencies sudo apt update && sudo apt install -y ca-certificates curl ufw nginx certbot python3-certbot-nginx # Create a dedicated user (no login shell) sudo useradd -r -s /usr/sbin/nologin -m -d /opt/syncbox syncbox # Create directories sudo mkdir -p /opt/syncbox/data/storage /opt/syncbox/web sudo chown -R syncbox:syncbox /opt/syncbox
# Download server binary sudo curl -L -o /opt/syncbox/syncbox-server /downloads/syncbox-server-linux-amd64 sudo chmod +x /opt/syncbox/syncbox-server # Download and extract web frontend sudo curl -L -o /tmp/syncbox-web.tar.gz /downloads/syncbox-web.tar.gz sudo tar -xzf /tmp/syncbox-web.tar.gz -C /opt/syncbox/web sudo chown -R syncbox:syncbox /opt/syncbox
Generate a JWT secret first, then create the full config:
# Generate JWT secret openssl rand -hex 32 # → copy the output for jwt_secret below
sudo tee /opt/syncbox/config.yaml > /dev/null <<'EOF'
# ==================================================
# SyncBox Server Configuration — Production
# ==================================================
server:
# Listen on localhost only — Nginx handles public traffic
addr: "127.0.0.1:8081"
# CORS origins: add your actual domain
allowed_origins:
- "https://sync.example.com"
storage:
type: "local" # "local" or "s3"
path: "/opt/syncbox/data/storage" # Writable path for file storage
database:
path: "/opt/syncbox/data/syncbox.db" # SQLite database file
auth:
jwt_secret: "PASTE_YOUR_64_CHAR_HEX_HERE" # REQUIRED — from openssl rand -hex 32
# --- Email: choose ONE of smtp or resend ---
smtp:
host: "smtp.example.com"
port: 465
username: "[email protected]"
password: "your-smtp-password"
from: "SyncBox <[email protected]>"
# resend:
# api_key: "re_xxxxx"
# from: "SyncBox <[email protected]>"
admin:
email: "[email protected]" # First user with this email becomes admin
rate_limit:
auth:
rate: 10
interval: "1s"
burst: 100
api:
rate: 100
interval: "1s"
burst: 1000
EOF
sudo chown syncbox:syncbox /opt/syncbox/config.yaml
sudo chmod 600 /opt/syncbox/config.yaml
sudo tee /etc/systemd/system/syncbox.service > /dev/null <<'EOF' [Unit] Description=SyncBox File Sync Server After=network.target [Service] Type=simple User=syncbox WorkingDirectory=/opt/syncbox ExecStart=/opt/syncbox/syncbox-server --config /opt/syncbox/config.yaml Restart=on-failure RestartSec=5 LimitNOFILE=65535 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable syncbox
sudo ufw allow OpenSSH sudo ufw allow 80 sudo ufw allow 443 sudo ufw --force enable
Replace sync.example.com with your actual domain. Point your DNS A record to the server IP first.
sudo tee /etc/nginx/sites-available/syncbox > /dev/null <<'EOF'
server {
listen 80;
server_name sync.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name sync.example.com;
ssl_certificate /etc/letsencrypt/live/sync.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sync.example.com/privkey.pem;
add_header X-Robots-Tag "noindex, nofollow, noarchive" always;
root /opt/syncbox/web;
index index.html;
# API + WebSocket proxy
location /api/ {
client_max_body_size 50m;
proxy_pass http://127.0.0.1:8081;
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 https;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
location /health {
proxy_pass http://127.0.0.1:8081;
}
# Prevent SPA fallback for missing static assets
location = /favicon.ico {
try_files $uri =204;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot|map)$ {
try_files $uri =404;
}
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
}
EOF
sudo ln -sf /etc/nginx/sites-available/syncbox /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
# Get SSL certificate from Let's Encrypt sudo certbot --nginx -d sync.example.com
# Start the service
sudo systemctl start syncbox
# Check status
sudo systemctl status syncbox
# Test health endpoint
curl https://sync.example.com/health
# → {"status":"ok","version":"3.0"}
Open https://sync.example.com in your browser. Register with the email address you set in admin.email — that account automatically becomes the admin. You'll receive an email verification code to complete registration.
Deploy with Docker Compose. The official image uses a multi-stage build (golang:1.24 + node:20 + alpine:3.20 runtime).
mkdir -p /opt/syncbox && cd /opt/syncbox
Inside the container, the config lives at /etc/syncbox/config.yaml and data is stored at /data.
cat <<'EOF' > config.yaml
server:
addr: "0.0.0.0:8080"
allowed_origins:
- "https://sync.example.com"
storage:
type: "local"
path: "/data/storage"
database:
path: "/data/syncbox.db"
auth:
jwt_secret: "PASTE_YOUR_64_CHAR_HEX_HERE"
smtp:
host: "smtp.example.com"
port: 465
username: "[email protected]"
password: "your-smtp-password"
from: "SyncBox <[email protected]>"
admin:
email: "[email protected]"
rate_limit:
auth:
rate: 10
interval: "1s"
burst: 100
api:
rate: 100
interval: "1s"
burst: 1000
EOF
cat <<'EOF' > docker-compose.yml
version: "3.8"
services:
syncbox:
image: syncbox/syncbox:latest
container_name: syncbox
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./config.yaml:/etc/syncbox/config.yaml:ro
- syncbox-data:/data
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
deploy:
resources:
limits:
memory: 512M
cpus: "1.0"
volumes:
syncbox-data:
EOF
docker compose up -d
# Verify
docker compose ps
curl http://localhost:8080/health
# → {"status":"ok","version":"3.0"}
For HTTPS, put Nginx or Caddy in front. See the Production (VPS) tab for the Nginx config — just change proxy_pass to http://127.0.0.1:8080.
Switch from local disk to S3-compatible storage (AWS S3, MinIO, Cloudflare R2, etc.). Change the storage block in config.yaml:
storage:
type: "s3"
s3:
endpoint: "https://s3.amazonaws.com"
region: "us-east-1"
bucket: "my-syncbox-files"
access_key: "AKIAIOSFODNN7EXAMPLE"
secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
storage:
type: "s3"
s3:
endpoint: "https://minio.internal:9000"
region: "us-east-1"
bucket: "syncbox"
access_key: "minioadmin"
secret_key: "minioadmin"
storage:
type: "s3"
s3:
endpoint: "https://<ACCOUNT_ID>.r2.cloudflarestorage.com"
region: "auto"
bucket: "syncbox"
access_key: "your-r2-access-key"
secret_key: "your-r2-secret-key"
database.path) always stays on local disk. Only file content is stored in S3. Make sure your S3 bucket exists before starting the server.
SyncBox needs email for user registration (verification codes) and team invitations. Choose ONE of SMTP or Resend.
Enable 2FA on your Google account, then generate an App Password at myaccount.google.com → Security → App Passwords.
smtp: host: "smtp.gmail.com" port: 465 username: "[email protected]" password: "xxxx xxxx xxxx xxxx" # 16-char app password from: "SyncBox <[email protected]>"
smtp: host: "email-smtp.us-east-1.amazonaws.com" port: 465 username: "AKIAIOSFODNN7EXAMPLE" # SES SMTP credentials (not IAM keys) password: "your-ses-smtp-password" from: "SyncBox <[email protected]>"
No SMTP config needed. Get an API key from resend.com/api-keys and verify your sending domain.
# Remove the smtp: block and use this instead: resend: api_key: "re_123456789" from: "SyncBox <[email protected]>"
Once your server is running, set up the desktop app or CLI on each device.
# Download and install curl -L -O /downloads/SyncBox-macOS-arm64.zip unzip SyncBox-macOS-arm64.zip mv SyncBox.app /Applications/ # Open the app open /Applications/SyncBox.app
On first launch, enter your server URL (e.g. https://sync.example.com), then log in with your email. Files sync to ~/SyncBox/ by default.
# macOS (Apple Silicon) curl -L -o syncbox /downloads/syncbox-cli-darwin-arm64 # — OR — Linux (amd64) curl -L -o syncbox /downloads/syncbox-cli-linux-amd64 chmod +x syncbox sudo mv syncbox /usr/local/bin/
# Log in — you'll receive a verification code via email syncbox login https://sync.example.com # Start the background sync daemon syncbox start # Check sync status syncbox status # Stop syncing syncbox stop
Regular maintenance ensures data safety and smooth upgrades.
Use SQLite's built-in .backup command for a consistent snapshot — never copy the .db file while the server is running.
# One-time backup sqlite3 /opt/syncbox/data/syncbox.db ".backup /opt/syncbox/backups/syncbox-$(date +%Y%m%d).db" # Cron job: daily at 2 AM echo '0 2 * * * syncbox sqlite3 /opt/syncbox/data/syncbox.db ".backup /opt/syncbox/backups/syncbox-$(date +\%Y\%m\%d).db"' | sudo tee /etc/cron.d/syncbox-backup
# rsync to a backup location (local or remote) rsync -a /opt/syncbox/data/storage/ /mnt/backup/syncbox-storage/ # Or tar archive tar -czf /mnt/backup/syncbox-storage-$(date +%Y%m%d).tar.gz -C /opt/syncbox/data storage/
SyncBox logs via systemd journal. Configure rotation:
# View logs sudo journalctl -u syncbox -f # Limit journal size (in /etc/systemd/journald.conf) # SystemMaxUse=500M
# 1. Download new binary sudo curl -L -o /opt/syncbox/syncbox-server-new /downloads/syncbox-server-linux-amd64 sudo chmod +x /opt/syncbox/syncbox-server-new # 2. Swap binary (keep the old one for rollback) sudo mv /opt/syncbox/syncbox-server /opt/syncbox/syncbox-server-old sudo mv /opt/syncbox/syncbox-server-new /opt/syncbox/syncbox-server # 3. Restart sudo systemctl restart syncbox # 4. Verify curl https://sync.example.com/health # Rollback if needed: # sudo mv /opt/syncbox/syncbox-server-old /opt/syncbox/syncbox-server # sudo systemctl restart syncbox
From zero to syncing in 6 steps
Download the Linux binary, create config.yaml, and start the server.
Open the web UI and register with your admin email to become the first admin.
Create a shared space for your team's files. Set permissions as needed.
Invite team members via email. They'll receive a link to register and join.
Download the macOS app or CLI, enter your server URL, and log in.
Your files sync automatically. Changes propagate instantly across all devices.