Skip to main content
This guide covers deploying Primo to production. Choose the deployment method that matches your needs and technical expertise.
Persistent Storage Required: Primo stores all data in a SQLite database and needs persistent disk storage to function. Traditional serverless platforms (Vercel, Netlify, Cloudflare Pages) have ephemeral file systems and won’t work.

Quick Deploy: Railway

The fastest way to deploy Primo to production.

Prerequisites

  • Railway account (free to start)
  • Domain name (optional, Railway provides a free subdomain)

Deployment Steps

1

Click deploy button

Deploy on Railway
2

Configure environment (optional)

Set environment variables if you want automated setup:
  • PRIMO_SUPERUSER_EMAIL
  • PRIMO_SUPERUSER_PASSWORD
  • PRIMO_APP_URL (optional, auto-detected)
3

Wait for deployment

Railway will:
  • Pull the Docker image
  • Create a persistent volume
  • Deploy the container
  • Generate a URL
4

Access your instance

Click the generated URL to access Primo. If you didn’t set environment variables, you’ll see the setup screen.
5

Configure custom domain (optional)

Railway Settings → Domains → Add custom domain
Cost: From $5/month (includes persistent volume)
Railway automatically handles SSL certificates, deployments, and scaling. Perfect for production use.

VPS Deployment

Deploy to any VPS for full control over your infrastructure.

Prerequisites

  • VPS with Docker installed (Hetzner, DigitalOcean, etc.)
  • SSH access to your server
  • Domain name pointed to your server IP
  • Basic command line knowledge
1

SSH into your server

2

Create project directory

3

Create docker-compose.yml

4

Start the container

5

Verify it's running

You should see logs indicating the server started on port 8080.

Option 2: Docker Run

For simpler setups without compose:

Configure Reverse Proxy

Primo runs on port 8080. Use a reverse proxy for SSL and domain routing:
Get SSL certificates with Certbot:

Platform-Specific Guides

Hetzner Cloud

Hetzner offers affordable VPS hosting in Europe and the US.
  1. Create a VPS (CX22 recommended: €4/month)
  2. Install Docker:
  3. Follow VPS deployment steps above
  4. Configure firewall to allow ports 80, 443, and 22

DigitalOcean

DigitalOcean provides simple VPS hosting with excellent documentation.
  1. Create a Droplet ($6/month minimum)
  2. Choose “Docker” from one-click apps (or install manually)
  3. Follow VPS deployment steps above
  4. Use DigitalOcean’s cloud firewalls for security

Fly.io

Fly.io offers a free tier with persistent volumes:
1

Install Fly CLI

2

Login to Fly

3

Create fly.toml

4

Create volume

5

Deploy

Database Backups

Primo uses SQLite, stored in /app/pb_data. Back up this directory regularly.
Cloud users: Backups are handled automatically. Backup frequency depends on your plan.
PocketBase has built-in automated backups that you can configure through the admin UI.
1

Access PocketBase Admin

Navigate to https://your-domain.com/_/ and log in with your admin credentials.
2

Go to Settings → Backups

Click on Settings in the sidebar, then select the Backups tab.
3

Configure backup schedule

Set a cron expression for your backup schedule:
  • Daily at 2 AM: 0 2 * * *
  • Every 6 hours: 0 */6 * * *
  • Hourly: 0 * * * *
  • Every minute (not recommended): * * * * *
4

Choose backup location

  • Local storage: Backups saved to /app/pb_data/backups
  • S3-compatible storage: Configure AWS S3, Backblaze B2, or similar for off-site backups
5

Set retention policy

Configure how many backups to keep (e.g., keep last 7 days of backups).
For production sites, configure S3-compatible storage for off-site backups. This protects against server failures.

Manual Backups with Docker

Add to crontab:

Restore from Backup

Test your backups regularly. A backup you haven’t tested is not a backup.

Updating Primo

Docker Compose

Docker Run

Always backup before updating, especially for major version changes.

Performance Optimization

Enable Gzip Compression

In your reverse proxy: Nginx:
Caddy:

Add Caching Headers

Use a CDN

Point your domain through Cloudflare (free tier) for:
  • Global CDN
  • DDoS protection
  • SSL certificates
  • Caching

Security Checklist

Generate random passwords for all accounts. Never use default or simple passwords.
Only allow ports 80, 443, and 22 (SSH). Block all other inbound traffic.
Regularly update Docker and the Primo image for security patches.
Never serve Primo over HTTP in production. Use Let’s Encrypt for free SSL certificates.
  • Disable password authentication
  • Use SSH keys only
  • Change default SSH port
  • Use fail2ban to block brute force attempts
Automate daily backups and store them off-server (S3, Backblaze, etc.).
Check Docker logs regularly for suspicious activity:

Troubleshooting

See the Troubleshooting Guide for common deployment issues and solutions.

Next Steps

Environment Variables

Configure Primo with environment variables

Troubleshooting

Solve common deployment issues