9.6 KiB
Deployment Guide
This document describes how to deploy the Release Tracker application using two different approaches:
- Docker Compose (Self-Hosted) - Uses SQLite database
- Vercel (Cloud) - Uses Turso (serverless SQLite)
Quick Comparison
| Feature | Docker Compose | Vercel |
|---|---|---|
| Database | SQLite (local file) | Turso (serverless SQLite) |
| Hosting | Your own server | Vercel cloud |
| Cost | Free (server cost only) | Free tier available |
| Setup complexity | Medium | Low |
| Data control | Full | Database hosted by Turso |
| Best for | Single-user, internal tools | Multi-user, public access |
Option 1: Docker Compose (Self-Hosted)
Prerequisites
- Linux server (or macOS/Windows with Docker Desktop)
- Docker and Docker Compose installed
- (Optional) Intel Mac users: Docker Desktop supports linux/amd64 builds
Deployment Steps
1. Build and Run on Linux Server (Recommended)
# Clone or copy the project to your Linux server
git clone <your-repo> release-tracker
cd release-tracker
# Build the Docker image
sudo docker compose build
# Run the container
sudo docker compose up -d
2. Build on Mac, Deploy to Linux
If you're on an Intel Mac and want to build locally then deploy to Linux:
# Build for linux/amd64 platform
docker build --platform linux/amd64 -t release-tracker:latest .
# Save the image
docker save release-tracker:latest | gzip > release-tracker.tar.gz
# Copy to Linux server
scp release-tracker.tar.gz user@linux-server:/tmp/
# On Linux server, load and run
ssh user@linux-server "cd /tmp && docker load < release-tracker.tar.gz"
# Create docker-compose.yml on Linux server and run
ssh user@linux-server "cd /opt/release-tracker && docker compose up -d"
3. Data Persistence
The SQLite database is stored in ./data/app.db and mounted as a volume. To backup:
# Backup
cp data/app.db backups/app.db.$(date +%Y%m%d)
# Restore
cp backups/app.db.20240101 data/app.db
sudo docker compose restart
Environment Variables
Create a .env file in the project root:
# Database (SQLite is the only option for Docker)
DB_TYPE=sqlite
DATABASE_URL=file:./data/app.db
# Next.js
NODE_ENV=production
NEXT_TELEMETRY_DISABLED=1
Updating the Application
# Pull latest code
git pull
# Rebuild and restart
sudo docker compose down
sudo docker compose build --no-cache
sudo docker compose up -d
Option 2: Vercel (Cloud)
Prerequisites
- Vercel account (sign up at vercel.com)
- Git repository (GitHub, GitLab, or Bitbucket)
- Turso account (sign up at turso.tech)
Step 1: Set Up Turso Database
-
Install Turso CLI:
curl -sSfL https://get.tur.so/install.sh | bash -
Login to Turso:
turso auth login -
Create a database:
turso db create release-tracker -
Get the database URL:
turso db show release-trackerCopy the "LibSQL URL" (looks like:
libsql://release-tracker-username.turso.io) -
Create an authentication token:
turso db tokens create release-trackerSave this token securely.
Step 2: Deploy to Vercel
-
Connect Repository:
- Go to vercel.com
- Click "Add New Project"
- Import your Git repository
-
Configure Build Settings:
- Framework Preset: Next.js
- Build Command:
npm run build - Output Directory:
.next
-
Set Environment Variables: In the Vercel dashboard, go to Project Settings → Environment Variables, add:
Variable Value Required DB_TYPEtursoYes TURSO_URLYour Turso database URL Yes TURSO_TOKENYour Turso auth token Yes ENABLE_PASSCODEtrue(recommended for public sites)No (default: false) PASSCODEYour secret passcode If ENABLE_PASSCODE=true Note: The build process will automatically run database migrations using the
prebuildscript. Make sure the environment variables are set before the first build.Security: For public deployments, set
ENABLE_PASSCODE=trueandPASSCODEto protect the application with a simple passcode. The cookie lasts 7 days. -
Deploy:
- Click "Deploy"
- Vercel will build and deploy automatically
- The build process will:
- Run
prebuildscript to create database tables - Build the Next.js application
- Deploy to Vercel's edge network
- Run
Updating on Vercel
Simply push to your Git repository:
git push origin main
Vercel will automatically rebuild and redeploy.
Local Development
Using SQLite (Default)
# Copy example env file
cp .env.local.example .env.local
# Install dependencies
npm install
# Run development server
npm run dev
Using Turso (Optional, for testing)
# Copy example env file and edit
cp .env.local.example .env.local
# Edit .env.local:
DB_TYPE=turso
TURSO_URL=libsql://your-database-url
TURSO_TOKEN=your-token
# Run development server
npm run dev
Troubleshooting
Docker Issues
Issue: Container fails to start with permission errors
Solution: The container runs as root (uid=0, gid=0) by default. If you have permission issues:
# Fix data directory permissions
sudo chown -R 0:0 ./data
sudo chmod -R 755 ./data
Issue: Database file is locked
Solution: Stop the container, remove the lock files, and restart:
sudo docker compose down
rm -f data/*.db-wal data/*.db-shm
sudo docker compose up -d
Vercel Issues
Issue: Build fails with "no such table" error
Solution: This happens when the database tables don't exist during build. The prebuild script should create them automatically. If it fails:
- Ensure
TURSO_URLandTURSO_TOKENare set in Vercel Environment Variables - Check that the Turso database exists and is accessible
- Try running
npx drizzle-kit pushlocally with the same credentials to verify
Issue: Build fails with database errors
Solution: Ensure environment variables are set in Vercel dashboard (not just in .env.local)
Issue: Data doesn't persist between deployments
Solution: This is expected with SQLite on Vercel. You must use Turso for persistence.
Issue: Passcode not working
Solution:
- Ensure both
ENABLE_PASSCODE=trueandPASSCODEare set - The passcode is case-sensitive
- Clear browser cookies and try again
- Check browser console for API errors
Authentication Issues
Issue: Cannot access site even with correct passcode
Solution:
- Check that cookies are enabled in your browser
- Try accessing in an incognito/private window
- Verify the
AUTH_COOKIE_NAMEhasn't changed between deployments - The cookie is set to expire after 7 days; if you cleared cookies, you'll need to re-enter the passcode
Turso Issues
Issue: Connection refused or timeout
Solution: Check your TURSO_URL and TURSO_TOKEN are correct. Turso databases may sleep after inactivity on free tier.
Architecture Notes
Database Abstraction
The application uses a database factory pattern (src/lib/db/index.ts) that automatically selects the appropriate database driver based on the DB_TYPE environment variable:
DB_TYPE=sqlite: Usesbetter-sqlite3driver with local fileDB_TYPE=turso: Uses@libsql/clientdriver with Turso
Both use the same Drizzle ORM schema, so no code changes are needed when switching between them.
Data Migration Between Environments
To migrate data from local SQLite to Turso:
-
Export from SQLite:
sqlite3 data/app.db .dump > backup.sql -
Import to Turso:
turso db shell release-tracker < backup.sql
Note: Some SQLite-specific syntax may need adjustment for Turso compatibility.
Authentication
The application supports optional passcode-based authentication, controlled by environment variables.
Configuration
| Variable | Description | Default |
|---|---|---|
ENABLE_PASSCODE |
Enable passcode protection | false |
PASSCODE |
The secret passcode | - |
AUTH_COOKIE_NAME |
Name of the auth cookie | release_tracker_auth |
Use Cases
Private Docker Deployment (no auth needed):
ENABLE_PASSCODE=false
Public Vercel Deployment (auth required):
ENABLE_PASSCODE=true
PASSCODE=your-secure-passcode-here
How It Works
- When
ENABLE_PASSCODE=true, all routes require authentication - Users are redirected to
/loginpage - After entering the correct passcode, a 7-day cookie is set
- Cookie is
httpOnly,secure(in production), andSameSite=strict - No logout functionality (users must clear cookies or wait 7 days)
Security Considerations
- Passcode is never sent to the client (verified server-side)
- Cookie cannot be accessed by JavaScript (
httpOnly) - Cookie is only sent over HTTPS in production (
secure) - Cookie expires after 7 days (
maxAge: 604800) - Single passcode for all users (simple but not suitable for multi-user scenarios)
Backup Strategy
Docker/SQLite
# Automated daily backup via cron
0 2 * * * cp /opt/release-tracker/data/app.db /backups/app.db.$(date +\%Y\%m\%d)
Vercel/Turso
Turso provides automatic backups. You can also export manually:
turso db dump release-tracker > backup.sql
Support
For issues specific to:
- Docker: Check Docker logs with
docker compose logs - Vercel: Check Vercel dashboard deployment logs
- Turso: Check Turso dashboard or run
turso db inspect release-tracker