# 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:** ```bash 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:** ```bash 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 ```json { "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 ```bash # 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 ```