Self-Hosting LightCMS
A complete guide to self-hosting LightCMS, covering environment variables, GitHub App credentials, PostgreSQL, AI endpoints, and a production deploy.
Want LightCMS fully under your control? Because LightCMS is built on SvelteKit, it can run on virtually any platform that supports Node.js or edge runtimes, including Vercel, Cloudflare Pages, Netlify, Docker containers, or your own Linux VPS.
This guide walks you step-by-step through setting up your environment, creating your GitHub App credentials, provisioning your PostgreSQL database, and launching LightCMS.
Prerequisites
Before you begin, ensure you have the following installed and configured:
- Runtime: Bun (v1.2+ recommended) or Node.js (v20+ or v24).
- Environment Manager (Optional): Mise is configured in the repository (
mise.toml) for managing tool versions. - Database: A PostgreSQL instance (v14+). You can use cloud providers like Neon, Supabase, Nile, or run PostgreSQL locally.
- GitHub Account: Required to register the GitHub App that manages repository access.
- Image Storage (Optional): Any Chevereto-compatible image upload endpoint (e.g., Freeimage.host, ImgBB, or a self-hosted Chevereto instance).
- SMTP Provider (Optional): Only needed if you want LightCMS itself to send email notifications (e.g., Resend, Zoho Mail, or Amazon SES). Newsletters never require it: Newsy uses GitHub as its backend.
- AI Services (Optional): An OpenAI-compatible API key for content generation and a Groq API key for speech-to-text audio transcription.
1. Clone the Repository & Install Dependencies
Clone the LightCMS repository to your local machine:
git clone https://github.com/pratyay360/lightcms.git
cd lightcms
Install the dependencies using Bun or Mise:
# Using Bun directly
bun install
# Or using Mise
mise run install
2. Run the GitHub Bot Setup
LightCMS integrates with GitHub using a GitHub App. You can automatically create and configure this app via the built-in Probot CLI:
# Using Bun
bun run bot:start
# Or using Mise
mise run bot
When started without existing credentials, Probot launches a local setup server (typically at http://localhost:3000). Open this URL in your browser:
- Click Register a GitHub App.
- Choose your personal GitHub account or organization.
- Probot automatically configures the required permissions and generates an RSA private key.
- Upon completion, Probot writes the generated credentials into your local
.envfile.
Required GitHub App Permissions
If you prefer to configure your GitHub App manually via GitHub Developer Settings:
- Repository Permissions:
Contents: Read and write (to read repository files and commit updates)Pull requests: Read and write (to create and review pull requests)Issues: Read and write (for issue comments and editorial discussions)Metadata: Read-only (mandatory for all GitHub Apps)
- Subscribe to Events:
PushPull requestInstallation
3. Configure Environment Variables
Open or create your .env file in the project root. Below is a complete reference of all supported variables:
# ---------------------------------------------------------------------------
# Core Authentication (Better Auth)
# ---------------------------------------------------------------------------
# Generate with: openssl rand -hex 32
BETTER_AUTH_SECRET="your-32-byte-hex-secret"
# Canonical URL of your running LightCMS instance (must match public URL)
BETTER_AUTH_URL="http://localhost:5173"
# ---------------------------------------------------------------------------
# Database Configuration (PostgreSQL)
# ---------------------------------------------------------------------------
DATABASE_URL="postgresql://user:password@localhost:5432/lightcms?sslmode=prefer"
# ---------------------------------------------------------------------------
# GitHub App Credentials (Generated by Setup Bot or GitHub Settings)
# ---------------------------------------------------------------------------
GITHUB_APP_ID="123456"
GITHUB_APP_NAME="lightcms-bot"
GITHUB_CLIENT_ID="Iv1.xxxxxxxxxxxx"
GITHUB_CLIENT_SECRET="your-github-client-secret"
# Private key with RSA formatting. In single-line env files, replace newlines with \n
GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
GITHUB_WEBHOOK="https://your-domain.example/github/setup"
GITHUB_WEBHOOK_SECRET="your-webhook-secret"
# Local Webhook Tunneling (Optional, for development)
WEBHOOK_PROXY_URL="https://smee.io/your-smee-channel"
# ---------------------------------------------------------------------------
# Image CDN Configuration (Chevereto-compatible)
# ---------------------------------------------------------------------------
CDN_URL="https://freeimage.host/api/1/upload"
CDN_KEY="your-cdn-api-key"
# ---------------------------------------------------------------------------
# Email / SMTP Configuration (Nodemailer)
# ---------------------------------------------------------------------------
MAIL_HOST="smtp.resend.com"
MAIL_PORT="465"
MAIL_SECURE="1"
MAIL_USER="resend"
MAIL_PASS="re_your_api_key"
MAIL_FROM="noreply@yourdomain.com"
# ---------------------------------------------------------------------------
# AI Copilot & Speech Transcription (Optional)
# ---------------------------------------------------------------------------
# OpenAI-compatible API endpoint for AI content generation
OPEN_AI_ENDPOINT="https://api.openai.com/v1"
OPEN_AI_APIKEY="sk-your-openai-key"
OPEN_AI_MODEL="gpt-4o-mini"
# Groq API Key for Whisper speech-to-text transcription
GROQ_API_KEY="gsk_your-groq-key"Secret Generation Helper
Generate secure random secrets locally without third-party websites:
openssl rand -hex 32
# or
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# or
python3 -c "import secrets; print(secrets.token_hex(32))"Recommended AI Providers
The AI Copilot uses standard OpenAI-compatible completions, which allows you to use any provider offering an OpenAI API format:
- Groq: Fast Llama models and Whisper voice transcription (
GROQ_API_KEY). - OpenRouter: Access Claude, GPT, Mistral, and open-source models with a single unified key (
OPEN_AI_ENDPOINT="https://openrouter.ai/api/v1"). - NVIDIA NIM: High-performance inference endpoints for open models.
- OpenAI: Official OpenAI endpoint and GPT models.
4. Set Up the Database & Run Migrations
LightCMS uses Drizzle ORM to manage its PostgreSQL schema. Once your DATABASE_URL is set in .env, apply the database migrations:
# Apply pending migrations to the database
bun run db:migrate
# Or push schema changes directly during local development
bun run db:pushHandy Database Utilities
- Drizzle Studio: Inspect and manipulate your database rows visually in your browser:
bun run db:studio - Generate Migrations: When updating schema definitions in
src/lib/server/db/:bun run db:generate
5. Configure Image Uploads (CDN)
LightCMS supports any Chevereto-compatible image upload API. When you paste or upload images in the editor, they are uploaded directly to your CDN.
Free and hosted options include:
Set the endpoint and API key in your .env:
CDN_URL="https://freeimage.host/api/1/upload"
CDN_KEY="your-api-key"
6. Local Development Workflow
Start the development server:
bun run dev
The application is now accessible at http://localhost:5173.
Testing Webhooks Locally
GitHub cannot send webhooks to localhost directly. To receive GitHub webhook events during local development:
- Create a free forwarding channel at smee.io.
- Set
WEBHOOK_PROXY_URLin your.envto your Smee channel URL. - Set the Webhook URL in your GitHub App settings to the same Smee URL.
- Run the GitHub bot in a separate terminal:
bun run bot:start
7. Production Deployment
When deploying to production, choose the SvelteKit adapter suitable for your target infrastructure:
- Vercel: Pre-configured with
@sveltejs/adapter-vercel. Connect your Git repository to Vercel, set your environment variables in the project settings, and deploy. - Cloudflare Pages: Use
@sveltejs/adapter-cloudflarefor global edge hosting. - Node.js / Docker: Use
@sveltejs/adapter-nodeto generate a standalone Node server that can be packaged into a Docker container or run directly behind Nginx/Caddy.
# Build the production bundle
bun run build
# Preview the built application
bun run previewProduction Checklist
- Ensure
BETTER_AUTH_URLmatches your live HTTPS domain (e.g.https://cms.yourdomain.com). - Keep
BETTER_AUTH_SECRETandGITHUB_WEBHOOK_SECRETprivate and rotated. - In your GitHub App settings, set the Webhook URL to your public endpoint:
https://your-domain.com/github/setup. - Ensure your PostgreSQL connection uses SSL (
sslmode=require) when communicating with cloud database providers.