luna 25f3612561 fix(v2): critical bug fixes — root SSH, bootstrap wait, SG deletion order, PAT masking
- EC2 bootstrap now enables root SSH (copies authorized_keys to root, sets
  PermitRootLogin without-password, reloads sshd) so all commands run as
  root and NVM at /root/.nvm is accessible
- Added /var/lib/pp-bootstrap-done sentinel; deploy waits for it before
  running any user commands — prevents race between SSH availability and
  user-data completion (docker/nvm install can take 3-5+ min)
- Fixed stopPreview: terminate instance first, delete key pair next, then
  delete security group with 30s delay — SG deletion was previously
  attempted before termination causing it to fail
- Fixed redeploy to always fetch fresh instanceIp/sshPrivateKey from DB
  rather than using potentially-stale preview parameter
- Fixed .env writing to use base64 encoding via echo|base64-d to safely
  handle values with special characters, single quotes, and newlines
- PAT and git clone URL now masked in preview logs (shows **** for password)
- Fixed inactivity cron: removed dead inactivityMs variable, use join on
  repoConfig to avoid N+1, deduplicate pending INACTIVITY_STOP jobs
- Fixed IAM policy UI: ec2:CreateKeyPair (backend uses CreateKeyPair, not
  ImportKeyPair which is a different AWS operation)
- Admin panel: added Edit button with username/password form for users
- Privacy page: fetch and display admin contactEmail from settings
- pnpm-workspace.yaml: fix allowBuilds→onlyBuiltDependencies for pnpm 9

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-25 08:34:50 +00:00

PR Previews (PP)

Self-hosted service that connects to a Gitea instance via webhook. When a PR is opened or updated, PP automatically provisions an AWS EC2 instance, builds and runs the project, and comments a live preview URL back on the PR.

Quick Start

Prerequisites

  • Docker & Docker Compose
  • Gitea instance with admin access
  • AWS account with EC2 permissions

Setup

  1. Clone and configure:

    cp example.env .env
    # Edit .env — at minimum set SESSION_SECRET, PP_BASE_URL, and ENCRYPTION_KEY
    # Generate ENCRYPTION_KEY: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
    
  2. Start services:

    docker compose up -d
    
  3. Open the web UI at http://localhost:5000 (or your configured PP_BASE_URL)

  4. Create your admin account on first login — you'll be prompted for a username and password.

  5. Complete the setup wizard to configure Gitea and AWS credentials.

Architecture

./backend/             # Node.js backend (rjweb-server + Prisma)
./frontend/            # React + Vite + Tailwind CSS
./prisma/schema.prisma # PostgreSQL schema
./docker-compose.yml   # PP itself (backend + db)
./Dockerfile           # Multi-stage build

Environment Variables

Variable Description
DATABASE_URL PostgreSQL connection string
SESSION_SECRET Cookie signing secret (32+ random chars)
PP_BASE_URL Public URL of this PP instance (no trailing slash)
ENCRYPTION_KEY AES-256 key — 64 hex chars (32 bytes). Generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
PORT Backend port (default: 5000)
LOG_LEVEL Logging level: trace/debug/info/warn/error (default: info)

PP Commands (in PR comments)

Command Action
/pp rebuild Re-run build on existing EC2 instance
/pp stop Stop and terminate the preview
/pp start Start or restart a stopped/ignored preview
/pp logs Post last 50 lines of logs as a comment
/pp ignore Ignore all future events for this PR

Required AWS IAM Permissions

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": [
      "ec2:RunInstances", "ec2:TerminateInstances", "ec2:DescribeInstances",
      "ec2:CreateSecurityGroup", "ec2:DeleteSecurityGroup",
      "ec2:AuthorizeSecurityGroupIngress", "ec2:DescribeSecurityGroups",
      "ec2:CreateKeyPair", "ec2:DeleteKeyPair", "ec2:CreateTags",
      "sts:GetCallerIdentity"
    ],
    "Resource": "*"
  }]
}

Development

# Database (via Docker)
docker compose up -d pp-db

# Run migrations
cd backend && npx prisma migrate dev --schema=../prisma/schema.prisma

# Backend (port 5000)
cd backend && pnpm install && pnpm dev

# Frontend dev server (port 3000, proxies API to backend)
cd frontend && pnpm install && pnpm dev
S
Description
No description provided
Readme Apache-2.0 129 MiB
Languages
TypeScript 97.8%
HTML 1.1%
Dockerfile 0.7%
CSS 0.3%
JavaScript 0.1%