release-tracker/docs/DEPLOYMENT.md

9.6 KiB

Deployment Guide

This document describes how to deploy the Release Tracker application using two different approaches:

  1. Docker Compose (Self-Hosted) - Uses SQLite database
  2. 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

# 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

  1. Install Turso CLI:

    curl -sSfL https://get.tur.so/install.sh | bash
    
  2. Login to Turso:

    turso auth login
    
  3. Create a database:

    turso db create release-tracker
    
  4. Get the database URL:

    turso db show release-tracker
    

    Copy the "LibSQL URL" (looks like: libsql://release-tracker-username.turso.io)

  5. Create an authentication token:

    turso db tokens create release-tracker
    

    Save this token securely.

Step 2: Deploy to Vercel

  1. Connect Repository:

    • Go to vercel.com
    • Click "Add New Project"
    • Import your Git repository
  2. Configure Build Settings:

    • Framework Preset: Next.js
    • Build Command: npm run build
    • Output Directory: .next
  3. Set Environment Variables: In the Vercel dashboard, go to Project Settings → Environment Variables, add:

    Variable Value Required
    DB_TYPE turso Yes
    TURSO_URL Your Turso database URL Yes
    TURSO_TOKEN Your Turso auth token Yes
    ENABLE_PASSCODE true (recommended for public sites) No (default: false)
    PASSCODE Your secret passcode If ENABLE_PASSCODE=true

    Note: The build process will automatically run database migrations using the prebuild script. Make sure the environment variables are set before the first build.

    Security: For public deployments, set ENABLE_PASSCODE=true and PASSCODE to protect the application with a simple passcode. The cookie lasts 7 days.

  4. Deploy:

    • Click "Deploy"
    • Vercel will build and deploy automatically
    • The build process will:
      1. Run prebuild script to create database tables
      2. Build the Next.js application
      3. Deploy to Vercel's edge network

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_URL and TURSO_TOKEN are set in Vercel Environment Variables
  • Check that the Turso database exists and is accessible
  • Try running npx drizzle-kit push locally 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=true and PASSCODE are 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_NAME hasn'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: Uses better-sqlite3 driver with local file
  • DB_TYPE=turso: Uses @libsql/client driver 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:

  1. Export from SQLite:

    sqlite3 data/app.db .dump > backup.sql
    
  2. 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

  1. When ENABLE_PASSCODE=true, all routes require authentication
  2. Users are redirected to /login page
  3. After entering the correct passcode, a 7-day cookie is set
  4. Cookie is httpOnly, secure (in production), and SameSite=strict
  5. 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