This guide walks through a self-hosted installation of Shelf. Due to Shelf’s architecture relying on Supabase for authentication and database services, there are specific requirements for self-hosting.
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)
Install Git to clone the project repository.
sudo apt-get update && sudo apt-get install -y git
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
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
SESSION_SECRET=[GENERATE-A-STRONG-SECRET]
SERVER_URL=https://shelf.yourdomain.com
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]
INVITE_TOKEN_SECRET=[GENERATE-ANOTHER-STRONG-SECRET]
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
Use Docker Compose to start services in the background:
docker compose up -d
For a completely self-hosted solution, you’ll need to run your own Supabase stack. This is significantly more complex:
Follow the Supabase self-hosting guide to set up your own Supabase instance.
Update your environment variables to point to your self-hosted Supabase instance:
DATABASE_URL=postgres://postgres:[PASSWORD]@your-supabase-host:6543/postgres
DIRECT_URL=postgres://postgres:[PASSWORD]@your-supabase-host:5432/postgres
SUPABASE_URL=https://your-supabase-host
# ... other variables remain the same
Once deployed, access Shelf at http://your-server-ip:3000 or your configured domain.
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;
}
}
Prefer automation? See Shelf Ansible Setup for an example playbook.
Prefer containers? See Shelf Docker Setup.
Monitor application logs with:
docker compose logs -f
Any questions?
Feel free to contact us. Find all contact information on our contact page.