Skip to main content

Deployment Options

PrivyCode server can be deployed using multiple methods:

Railway

One-click deployment with Railway (Recommended)

Docker

Deploy anywhere using Docker containers

VPS

Deploy on any VPS (DigitalOcean, AWS, etc.)

Fly.io

Deploy on Fly.io with automatic scaling
Railway provides the easiest deployment experience with automatic builds and PostgreSQL provisioning.
1

Create a Railway account

Visit Railway and sign up with your GitHub account.
2

Create a new project

Click New ProjectDeploy from GitHub repo → Select your PrivyCode repository
3

Add PostgreSQL database

In your Railway project:
  • Click NewDatabaseAdd PostgreSQL
  • Railway will automatically provision a PostgreSQL instance
  • The DATABASE_URL will be automatically injected as an environment variable
4

Configure environment variables

Go to your service → Variables tab and add:
GO_ENV=production
PORT=8080
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
GITHUB_CALLBACK_URL=https://your-app.railway.app/github/callback
FRONTEND_URL=https://your-frontend-url.com
MOBILE_URL=https://your-frontend-url.com
DATABASE_URL is automatically provided by Railway when you add PostgreSQL. Do not override it unless necessary.
5

Update GitHub OAuth callback URL

Go to your GitHub OAuth App settings and update:
  • Homepage URL: Your frontend production URL
  • Authorization callback URL: https://your-app.railway.app/github/callback
6

Deploy

Railway will automatically deploy your app. You can monitor the build logs in the Deployments tab.
Your app will be available at https://your-app.railway.app
7

Run migrations

You need to run migrations once after the first deployment:
  1. Temporarily uncomment the migration line in cmd/server/main.go:
    config.RunMigrations()
    
  2. Push the change to trigger a redeployment
  3. After successful deployment, comment it out again and push

Railway Configuration File

The repository includes a railway.json configuration file:
railway.json
{
  "$schema": "https://railway.com/railway.schema.json",
  "project": "a4937608-3ed2-4de0-95a9-27e1f0972b99",
  "service": "privycode-server",
  "environment": "production"
}
This file helps Railway identify the service and environment settings.

Deploy with Docker

PrivyCode includes a production-ready Dockerfile using multi-stage builds for optimal image size.

Dockerfile Overview

Dockerfile
# Build stage
FROM golang:1.23-alpine AS builder

WORKDIR /app

# Install git (for some Go dependencies)
RUN apk add --no-cache git

# Copy go mod files first for better caching
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY . .

# Build the binary
RUN CGO_ENABLED=0 GOOS=linux go build -o main ./cmd/server

# Production stage
FROM alpine:latest

WORKDIR /app

# Install ca-certificates for HTTPS requests
RUN apk --no-cache add ca-certificates

# Copy binary from builder
COPY --from=builder /app/main .

# Expose port
EXPOSE 8080

# Run the binary
CMD ["./main"]
This multi-stage build:
  • Uses golang:1.23-alpine for building (small base image)
  • Compiles a static binary with CGO_ENABLED=0
  • Uses alpine:latest for the final image (only ~5MB base)
  • Results in a final image size of ~20MB

Build and Run with Docker

1

Build the Docker image

docker build -t privycode-server .
2

Run with environment variables

docker run -d \
  --name privycode-server \
  -p 8080:8080 \
  --env-file .env \
  privycode-server
3

Verify the container is running

docker ps
docker logs privycode-server
You should see:
Connected to PostgreSQL successfully!!!
Server starting on :8080...

Docker Compose (Full Stack)

For a complete setup with PostgreSQL:
docker-compose.yml
version: '3.8'

services:
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: privycode
      POSTGRES_USER: privycode
      POSTGRES_PASSWORD: your_secure_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U privycode"]
      interval: 10s
      timeout: 5s
      retries: 5

  server:
    build: .
    ports:
      - "8080:8080"
    environment:
      - GO_ENV=production
      - PORT=8080
      - DATABASE_URL=postgresql://privycode:your_secure_password@db:5432/privycode?sslmode=disable
      - GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID}
      - GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET}
      - GITHUB_CALLBACK_URL=${GITHUB_CALLBACK_URL}
      - FRONTEND_URL=${FRONTEND_URL}
      - MOBILE_URL=${MOBILE_URL}
    depends_on:
      db:
        condition: service_healthy

volumes:
  postgres_data:
Run with:
docker-compose up -d

Deploy on VPS (DigitalOcean, AWS, etc.)

1

Set up your VPS

  • Create a VPS instance (Ubuntu 22.04 recommended)
  • SSH into your server
  • Install Docker:
    curl -fsSL https://get.docker.com -o get-docker.sh
    sh get-docker.sh
    
2

Set up PostgreSQL

Option 1: Use a managed database (recommended)
  • DigitalOcean Managed Databases
  • AWS RDS
  • Supabase PostgreSQL
Option 2: Run PostgreSQL in Docker
docker run -d \
  --name privycode-db \
  -e POSTGRES_DB=privycode \
  -e POSTGRES_PASSWORD=your_secure_password \
  -v pgdata:/var/lib/postgresql/data \
  -p 5432:5432 \
  postgres:15-alpine
3

Clone and build

git clone https://github.com/greatdaveo/privycode-server
cd privycode-server
docker build -t privycode-server .
4

Create .env file

nano .env
Add your production environment variables (see Environment Variables).
5

Run the container

docker run -d \
  --name privycode-server \
  --restart unless-stopped \
  -p 8080:8080 \
  --env-file .env \
  privycode-server
6

Set up Nginx reverse proxy (optional)

server {
    listen 80;
    server_name api.yourdomain.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        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;
    }
}
Then get SSL certificate:
sudo certbot --nginx -d api.yourdomain.com

Post-Deployment Checklist

1

Run database migrations

Ensure migrations have been run on your production database.
2

Update GitHub OAuth settings

Update callback URL to your production domain.
3

Update CORS allowed origins

If your frontend is on a different domain, verify it’s in the CORS middleware:
internal/middleware/cors.go
allowedOrigins := map[string]bool{
    "https://privycode.com":     true,
    "https://www.privycode.com": true,
    // Add your domain here
}
4

Test critical endpoints

# Health check
curl https://your-api.com/

# GitHub OAuth
curl https://your-api.com/github/login
5

Monitor logs

# View in Railway dashboard → Deployments → Logs
6

Set up monitoring (optional)

Consider using:
  • Railway built-in metrics
  • Sentry for error tracking
  • UptimeRobot for uptime monitoring

Troubleshooting

  • Verify DATABASE_URL format is correct
  • Check if database is accessible from your server
  • For Railway: ensure PostgreSQL service is linked
  • Check SSL mode settings (sslmode=require for production)
  • Verify callback URL matches exactly (including https://)
  • Check if GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET are correct
  • Ensure your domain is not blocked by GitHub
  • Add your frontend domain to internal/middleware/cors.go
  • Rebuild and redeploy after changing CORS settings
  • Verify FRONTEND_URL environment variable is correct
Check logs for errors:
docker logs privycode-server
Common issues:
  • Missing required environment variables
  • Database connection failure
  • Port already in use

Next Steps

Environment Variables

Complete reference for all configuration options

API Reference

Explore available endpoints

Setup Guide

Local development setup

Security

Production security best practices

Build docs developers (and LLMs) love