Docker Quick Start
Prerequisites
- Docker installed
Quick start
docker run -d -p 1453:1453 -v openbin_data:/data ghcr.io/akifbayram/openbin:latestOpen http://localhost:1453 in your browser, register an account, and start adding bins. The database and JWT secret are created automatically on first startup.
Using Docker Compose
If you prefer Docker Compose, clone the repo and run:
git clone https://github.com/akifbayram/openbin.git
cd openbin
docker compose up -dData Persistence
All data is stored in the api_data Docker volume, mounted at /data inside the container:
| Path inside container | Contents |
|---|---|
/data/openbin.db | SQLite database (all bins, locations, users) |
/data/photos/ | Uploaded bin and avatar photos |
/data/backups/ | Automatic backups (if enabled) |
/data/.jwt_secret | Auto-generated JWT signing secret |
The volume is named api_data and is managed by Docker. Data persists across container restarts and updates.
Backing up your data
To back up manually, copy the contents of the Docker volume or enable the built-in backup feature (see Configuration). At minimum, preserve the openbin.db file — it contains everything except photos.
Changing the port
With docker run, swap the first port number: -p 8080:1453.
With Docker Compose, set HOST_PORT in your .env file (e.g. HOST_PORT=8080) and restart the container. See Configuration for all options.
Updating
Pull the latest image and restart:
# docker run
docker pull ghcr.io/akifbayram/openbin:latest
docker stop openbin && docker rm openbin
docker run -d -p 1453:1453 -v openbin_data:/data --name openbin ghcr.io/akifbayram/openbin:latest
# Docker Compose
docker compose pull
docker compose up -dThe database and all data on the volume are preserved.
Backup
Manual backup
Copy the Docker volume data to a safe location. The database file is the critical piece:
docker cp openbin:/data/openbin.db ./openbin-backup.dbAutomatic backups
Enable the built-in backup feature by setting environment variables in your .env file:
BACKUP_ENABLED=true
BACKUP_INTERVAL=daily
BACKUP_RETENTION=7Backup files are written to /data/backups/ inside the container (the api_data volume). See Configuration for the full backup reference.
What's in a backup archive
Each automatic backup is a ZIP file named backup-YYYY-MM-DDTHHMMSS.zip containing:
| Path in ZIP | Description |
|---|---|
openbin.db | Full SQLite database snapshot (SQLite installs only) |
openbin.sql | PostgreSQL dump produced by pg_dump (PostgreSQL installs only) |
photos/ | All uploaded photos and generated thumbnails, organized by bin ID |
The archive contains either openbin.db or openbin.sql depending on the database engine in use. Cross-engine restore is not supported — a SQLite backup cannot be restored into a PostgreSQL instance and vice versa.
JWT secret not included
The JWT signing secret (.jwt_secret) is not included in backup archives. See Restoring the JWT secret below.
Restore
Quick restore (Docker)
Stop the container to prevent writes during restore:
bashdocker compose downFind the backup on the Docker volume. If you kept backups on the default volume:
bash# List available backups docker run --rm -v openbin_api_data:/data alpine ls /data/backups/If you copied backups off-host, use your local copy.
Extract the database and photos into the data volume, replacing existing files:
bash# Extract from backup into a temp directory mkdir -p /tmp/openbin-restore unzip backup-2026-03-15T020000.zip -d /tmp/openbin-restore # Copy into the Docker volume docker run --rm \ -v openbin_api_data:/data \ -v /tmp/openbin-restore:/restore \ alpine sh -c "cp /restore/openbin.db /data/openbin.db && \ rm -rf /data/photos && \ cp -r /restore/photos /data/photos && \ chown -R 1000:1000 /data"Volume name
The volume name is typically
openbin_api_dataorqrcode_api_datadepending on your project directory name. Rundocker volume lsto find the correct name.Start the container:
bashdocker compose up -dVerify by logging in and checking your bins, photos, and user accounts.
Restoring the JWT secret
The .jwt_secret file lives at /data/.jwt_secret and is not included in backup archives. This secret signs all JWT tokens — if it changes, every user session is invalidated and users must log in again.
If you still have the original volume (e.g. you're restoring just the database), the .jwt_secret file is already in place. No action needed.
If the volume was lost, you have two options:
| Scenario | What to do |
|---|---|
You set JWT_SECRET in .env | Nothing — the env var takes precedence over the file. Sessions survive as long as the env var stays the same. |
| You relied on the auto-generated secret | The secret is gone. OpenBin will generate a new one on next startup. All existing sessions become invalid — users will need to log in again. No data is lost. |
Recommendation
For production deployments, set JWT_SECRET explicitly in your .env file and include your .env file in your off-host backup strategy. This ensures sessions survive even a full volume loss.
Restoring without Docker
If you run OpenBin directly (no container), extract the backup and place the files where your environment variables point:
# Stop the server process first
unzip backup-2026-03-15T020000.zip -d /tmp/openbin-restore
# Copy database (default: ./data/openbin.db)
cp /tmp/openbin-restore/openbin.db ./data/openbin.db
# Copy photos (default: ./uploads)
rm -rf ./uploads
cp -r /tmp/openbin-restore/photos ./uploadsThen start the server. Check DATABASE_PATH and PHOTO_STORAGE_PATH in your .env if you use non-default paths.
Verifying a restore
After starting OpenBin on restored data:
- Log in — if login fails, the JWT secret changed (see above). Users can log in again with their existing passwords.
- Check bins — open a bin and confirm items, tags, and notes are present.
- Check photos — open a bin with photos and verify they load. Thumbnails are regenerated automatically if missing.
- Check user accounts — all registered users and their roles should be intact (stored in the database).
Running Behind a Reverse Proxy
If you place OpenBin behind Nginx, Caddy, or another reverse proxy, set TRUST_PROXY=true in your .env file so that rate limiting and secure cookie handling work correctly:
TRUST_PROXY=trueSee your reverse proxy's documentation for configuration with OpenBin.