Self-hosting
Run Tributary on your own machine with Docker. Your files stay in your Google accounts.
What you need
- A machine with Docker and Docker Compose. The images are built for 64-bit Intel and AMD (amd64).
- A Google account to create a free Google Cloud project, which is what lets Tributary reach Drive.
- If you want to use it from other devices, a domain name and HTTPS.
Start it
Make a folder, then save this as docker-compose.yml inside it, or download the file.
# Tributary. Put this beside your .env file, then run: docker compose up -d
name: tributary
services:
# The address browsers use. It serves the app and passes API calls to the api service.
web:
image: swayam5342/tributary-web:0.1.0
environment:
DEXTRO_API_URL: http://api:8080
ports:
# Only this machine can reach it. Put your HTTPS proxy in front of this port.
- 127.0.0.1:${PORT:-3000}:3000
networks:
default:
# Fixed so the api service can trust the visitor's address from this one alone.
ipv4_address: 172.28.77.250
depends_on:
- api
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
restart: unless-stopped
api:
image: swayam5342/tributary-api:0.1.0
environment:
DEXTRO_DATABASE_URL: postgres://tributary:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}@postgres:5432/tributary?sslmode=disable
DEXTRO_PUBLIC_URL: ${PUBLIC_URL:?set PUBLIC_URL in .env}
DEXTRO_TRUSTED_PROXIES: 172.28.77.250
DEXTRO_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
DEXTRO_GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
DEXTRO_GOOGLE_PICKER_API_KEY: ${GOOGLE_PICKER_API_KEY:-}
DEXTRO_ENCRYPTION_KEYS: ${ENCRYPTION_KEYS:?set ENCRYPTION_KEYS in .env}
DEXTRO_ENCRYPTION_KEY_ID: ${ENCRYPTION_KEY_ID:-}
depends_on:
postgres:
condition: service_healthy
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
restart: unless-stopped
postgres:
image: postgres:18-alpine
environment:
POSTGRES_USER: tributary
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
POSTGRES_DB: tributary
volumes:
- postgres-data:/var/lib/postgresql
healthcheck:
test: [CMD-SHELL, pg_isready -U tributary -d tributary]
interval: 3s
timeout: 3s
retries: 20
restart: unless-stopped
networks:
default:
ipam:
config:
- subnet: 172.28.77.0/24
volumes:
postgres-data:Create a .env file beside it, with its own random secrets:
cat > .env <<EOF
PUBLIC_URL=http://127.0.0.1:3000
POSTGRES_PASSWORD=$(openssl rand -hex 24)
ENCRYPTION_KEYS=k1:$(openssl rand -base64 32)
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
EOFKeep a copy of ENCRYPTION_KEYS somewhere safe. Without it, every linked account has to be set up again.
Start it:
docker compose up -dOpen http://127.0.0.1:3000. The first account you create becomes the admin, and after that only the admin can add people.
Connect Google
Tributary uses your own Google project, so nothing passes through anyone else's. In the Google Cloud console:
- Create a project and enable the Google Drive API.
- On the consent screen, add the
drive.filescope. - Create an OAuth client of type Web application.
- Add these redirect addresses, using your
PUBLIC_URL:
http://127.0.0.1:3000/api/v1/auth/google/callback
http://127.0.0.1:3000/api/v1/storage/google/callbackPut the client ID and secret in .env, then run docker compose up -d again. You can now link accounts on the Storage page.
While the consent screen is in Testing, every account you link has to be listed as a test user, and its sign-in expires after 7 days.
Use it from other devices
Sign-in cookies only work over HTTPS, apart from on 127.0.0.1, so a plain address on your network won't keep you signed in. Put a reverse proxy such as Caddy or nginx in front of port 3000, then set PUBLIC_URL to the address people use, such as https://files.example.com, and update Google's redirect addresses to match.
Admin commands
Run these on the server, from the folder with your compose file:
docker compose exec api /tributary-cli help
docker compose exec api /tributary-cli statusstatus | Accounts, usage and when each background job last ran |
users | List the accounts on this server |
create-user | Add someone |
reset-password | Set a new password, which they'll have to replace |
delete-user | Remove an account. Their files stay in their Drive |
transfer-admin | Hand the admin role to someone else |
sync | Check every linked account against Drive now |
links | List the public Google links on this server |
upload-limit | Show or change the largest upload allowed |
Update and back up
To update, change the version in docker-compose.yml, then run:
docker compose pull
docker compose up -dDatabase changes apply by themselves when the server starts.
Your files are safe in Drive, but the trash, links, users and keys live in the database, so back that up too:
docker compose exec -T postgres pg_dump -U tributary tributary > tributary.sqlIf the database is ever lost, a sync brings your files and folders back from Drive. The trash, users and keys don't come back.
Ready to build on it? Read the API guide, or see the code on GitHub.