Runbook: Add a New Application
When to Use
- Deploying a new application to the server
- Setting up a new repo from the app template
Prerequisites
- Server already bootstrapped (Self-Hosting Guide)
- DNS A record pointing your app domain to the server IP
- SSH access as the
deployuser
Steps
1. Create the repository
Use GitHub's "Use this template" button on towlion/app-template to create a new repo under the towlion organization (or your own account).
2. Provision per-app credentials on the server
ssh deploy@YOUR_SERVER_IP
sudo bash /opt/platform/infrastructure/create-app-credentials.sh <app-name>
This creates an isolated PostgreSQL user, MinIO bucket, and writes credentials to /opt/platform/credentials/<app-name>.env.
3. Clone the repo on the server
4. Create deploy/.env
Edit deploy/.env with your values. If you ran create-app-credentials.sh, the deploy workflow will automatically fill in the database and S3 credentials on first deploy.
5. Configure GitHub secrets
Set these repository secrets (Settings > Secrets and variables > Actions):
| Secret | Value |
|---|---|
SERVER_HOST |
Your server IP |
SERVER_USER |
deploy |
SERVER_SSH_KEY |
SSH private key for the deploy user |
APP_DOMAIN |
Your app's domain (e.g., app.example.com) |
Optional:
| Secret | Value |
|---|---|
PREVIEW_DOMAIN |
Base domain for PR previews (e.g., example.com). Also add a *.preview.<app-name>.<domain> DNS A record. |
6. Push to main
Push code to the main branch. The deploy workflow will:
- SSH into the server
- Pull the latest code
- Create the app database (if it doesn't exist)
- Build and start containers
- Run Alembic migrations
- Write a Caddyfile and reload Caddy
7. Verify
Expected: {"status": "healthy"} with HTTP 200.
References
- Deployment Tutorial — full step-by-step walkthrough
- Deploy Prompt — reusable Claude Code session prompt for deployments
- Server Contract — directory layout and lifecycle details