This guide uses Docker Compose to run Shelf. Note that Shelf requires a Supabase backend for authentication and database functionality, which adds complexity to the self-hosted deployment.
For Docker installation, see Docker.
[!WARNING]
Shelf requires Supabase for authentication and database functionality. Unlike many self-hosted applications, Shelf does not include its own database layer. You must either:
- Use the Supabase cloud service (recommended for ease of setup)
- Self-host your own Supabase instance (more complex but fully self-contained)
Create a directory for your Shelf deployment:
mkdir -p /opt/shelf
cd /opt/shelf
Create a .env file with your Supabase credentials:
cat > .env << EOF
# Supabase Configuration
DATABASE_URL=postgres://postgres:[YOUR-PASSWORD]@[YOUR-PROJECT-ID].supabase.co:6543/postgres
DIRECT_URL=postgres://postgres:[YOUR-PASSWORD]@[YOUR-PROJECT-ID].supabase.co:5432/postgres
SUPABASE_ANON_PUBLIC=[YOUR-ANON-PUBLIC-KEY]
SUPABASE_SERVICE_ROLE=[YOUR-SERVICE-ROLE-KEY]
SUPABASE_URL=https://[YOUR-PROJECT-ID].supabase.co
# Application Configuration
SERVER_URL=https://shelf.yourdomain.com
SESSION_SECRET=[GENERATE-A-STRONG-SECRET]
INVITE_TOKEN_SECRET=[GENERATE-ANOTHER-STRONG-SECRET]
# Optional Features
MAPTILER_TOKEN=[YOUR-MAPTILER-TOKEN-FOR-GPS-FEATURES]
SMTP_HOST=smtp.yourdomain.com
SMTP_PORT=587
SMTP_USER=noreply@yourdomain.com
SMTP_FROM="Shelf Notifications"
SMTP_PWD=[YOUR-SMTP-PASSWORD]
SMTP_SECURE=false
# Production Settings
NODE_ENV=production
LOG_LEVEL=info
MAX_REQUEST_SIZE=10mb
ENABLE_TELEMETRY=false
TRUST_PROXY_HEADERS=true
EOF
Create a docker-compose.yml file:
version: '3.8'
services:
shelf:
image: ghcr.io/shelf-nu/shelf.nu:latest
restart: unless-stopped
ports:
- "3000:8080"
env_file:
- .env
volumes:
- ./media:/app/public/media
environment:
- NODE_ENV=production
Create a directory for media files:
mkdir -p media
chown -R 1000:1000 media
Use Docker Compose to start services in the background:
docker compose up -d
For production deployments, use a specific version instead of latest:
version: '3.8'
services:
shelf:
# Use specific version for production stability
image: ghcr.io/shelf-nu/shelf.nu:v1.18.6
restart: unless-stopped
ports:
- "3000:8080"
env_file:
- .env
volumes:
- ./media:/app/public/media
environment:
- NODE_ENV=production
For production use, set up a reverse proxy with TLS:
server {
listen 443 ssl;
server_name shelf.yourdomain.com;
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
location / {
proxy_pass http://127.0.0.1:3000;
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;
# Increase buffer sizes for file uploads
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
docker compose logs -f
# Pull the latest image
docker compose pull
# Restart the services
docker compose down
docker compose up -d
# Create a backup of media files
tar -czf shelf-media-backup-$(date +%Y%m%d).tar.gz media/
Check if the container is running:
docker compose ps
Check application logs:
docker compose logs shelf
latest for stabilityAny questions?
Feel free to contact us. Find all contact information on our contact page.