This document provides essential instructions for deploying, maintaining, and recovering a ferry instance in production.
Ferry is optimized for containerized environments. Use the provided docker-compose.yaml as a starting point.
Initial Configuration:
Generate a local config.yaml with strong random secrets before the first start:
cp config.example.yaml config.yaml
docker compose run --rm ferry ./ferry init-configThe command creates config.yaml when it is missing and replaces known placeholder secrets in an existing file. Production starts reject default secrets unless dev_mode: true or FERRY_DEV_MODE=true is set explicitly.
Configuration via Environment Variables:
Any value in the config.yaml can be overridden by an environment variable with the prefix FERRY_. Nested structures use underscores as separators.
Common Overrides:
FERRY_SERVER_PUBLIC_URL: The external URL (e.g.,https://share.example.com). Required for link generation.FERRY_SECURITY_BEHIND_REVERSE_PROXY: Set totrue(default) orfalse.FERRY_AUTH_BOOTSTRAP_PASSWORD: A strong secret for initial setup and recovery.FERRY_SERVER_TRUSTED_PROXIES: Comma-separated list of trusted proxy IPs.FERRY_AUTH_RATE_LIMIT_ENABLED: Enable or disable the rate limiter (true/false).FERRY_DATABASE_PATH: Path to the SQLite database.FERRY_DEV_MODE: Allows development defaults when set totrue. Do not use for production.
Ensure the following paths are mounted as persistent volumes:
/app/data: Contains the SQLite database (ferry.db)./app/storage: Contains the Content-Addressable Storage (CAS) files.
Ferry is designed to run behind a reverse proxy (Nginx, Caddy, HAProxy, or UTM).
To support large uploads via the TUS protocol, you must disable request buffering and allow large bodies:
server {
listen 443 ssl;
server_name share.example.com;
# 1. Allow large files (0 = unlimited)
client_max_body_size 0;
# 2. Disable buffering for TUS resumable uploads
proxy_request_buffering off;
proxy_buffering off;
location / {
proxy_pass http://ferry:8080;
# 3. Essential headers for auth and rate limiting
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;
}
}To ensure the Rate Limiter sees the correct client IP, you must add your proxy's internal IP to the server.trusted_proxies list in config.yaml or via the FERRY_SERVER_TRUSTED_PROXIES environment variable.
A consistent backup must include both the database and the physical storage.
- Database: Since Ferry uses SQLite in WAL mode, simply copying
ferry.dbmight result in an inconsistent state.- Recommended: Use the SQLite
.backupcommand or a filesystem snapshot that includesferry.db,ferry.db-shm, andferry.db-wal.
- Recommended: Use the SQLite
- CAS Storage: Back up the entire
/app/storagedirectory. Files in the CAS are immutable once written.
If you use modern backup software (like restic, borg, tar with --exclude-caches, or Bacula), you can exclude the large CAS storage directory to save space and time. Since the physical files are transient (shares expire) and can be re-uploaded if necessary, backing up only the database might be sufficient for some use cases.
To signal backup programs to skip the storage directory, place a standard CACHEDIR.TAG file in the root of the storage directory:
# Inside the container or storage volume root
printf "Signature: 8a477f597d28d172789f06886806bc55\n" > data/storage/CACHEDIR.TAGFerry's internal cleanup process will explicitly ignore this file.
- Stop the ferry service.
- Restore the physical files to
/app/storage. - Restore the database file(s) to
/app/data. - Restart ferry. The background worker will automatically verify storage integrity during its next run.
If you lose administrative access or misconfigure the system, use the built-in recovery mode.
- Stop the container/service.
- Run the break-glass command:
# Inside the container or via CLI ./ferry break-glass - Access: The service will listen on
127.0.0.1:8081(loopback only) and bypass normal user authentication. - Login: Use the
bootstrap_passwordconfigured in yourconfig.yamlor env. - Repair: Use the dashboard to reset admin passwords, enable accounts, or fix settings.
If you cannot use break-glass mode, you can manually trigger the bootstrap flow by stopping the service and temporarily moving/renaming the ferry.db file (Note: this resets the entire system state).
Monitor the System Status page regularly.
- Deduplication Ratio: High ratios indicate storage efficiency.
- Disk Free: Ensure the host has sufficient space. CAS does not currently enforce hard quotas.
- Cleanup Worker: Verify the "Last Run" timestamp to ensure background maintenance is active.
Maintenance Note: The current "One-Page" dashboard is a deliberate design choice for the initial release to gather UX feedback. A split into separate "Shares" and "Users" pages may occur in future versions.