Files
zoeissleeping 30a425744d feat: add startup migration script and improve Docker setup
- Add scripts/start.ts to run drizzle migrations before server start
- Update Dockerfile to copy migration files and install prod deps
- Change entrypoint to use migration-aware startup script
- Add deployment documentation
2026-05-11 17:43:13 -05:00

187 lines
4.3 KiB
Markdown

# Deploying Veridian
Self-hosted deployment guide using Docker Compose on a VPS.
## Prerequisites
- A VPS with Docker and Docker Compose installed
- A domain name pointed at your VPS IP address
- An external reverse proxy (Caddy, Nginx, etc.) for HTTPS termination
## First Deploy
### 1. Clone the repository
```bash
git clone https://gitea.wildcardproject.com/zoeissleeping/veridian.git
cd veridian
```
### 2. Configure environment variables
```bash
cp .env.example .env
```
Edit `.env` and set the required values:
```bash
# Generate a secure auth secret
openssl rand -base64 32
# Set these in .env
POSTGRES_PASSWORD=<your-secure-db-password>
BETTER_AUTH_SECRET=<output from openssl>
NUXT_PUBLIC_URL=https://your-domain.com
```
### 3. Build and start
```bash
docker compose up --build -d
```
This will:
1. Build the Nuxt application
2. Start PostgreSQL and wait for it to be healthy
3. Run all pending database migrations automatically
4. Start the application server
### 4. Verify
```bash
# Check container status
docker compose ps
# Check app logs (should show migration + server start)
docker compose logs app
# Check for errors
docker compose logs app | grep -i error
```
### 5. Set up your reverse proxy
Point your reverse proxy at `127.0.0.1:3000`. Example Caddy config:
```
your-domain.com {
reverse_proxy 127.0.0.1:3000
}
```
## Updating
When you pull new changes:
```bash
git pull
# Rebuild and restart (migrations run automatically on startup)
docker compose up --build -d
```
The app container will:
1. Rebuild with the latest code
2. Run any new migrations that were added
3. Restart the server
## Database Migrations
Migrations run automatically every time the app container starts, via [`scripts/start.ts`](scripts/start.ts). This uses Drizzle ORM's programmatic migration API (`drizzle-orm/node-postgres/migrator`).
- **First deploy**: All migrations run, creating all tables
- **Updates**: Only new/pending migrations run
- **No changes**: Migrations are a no-op
If a migration fails, the app will not start and the container will exit with an error. Check logs with:
```bash
docker compose logs app
```
### Creating new migrations
After modifying [`drizzle/schema.ts`](drizzle/schema.ts):
```bash
bunx drizzle-kit generate
```
This creates a new SQL file in `drizzle/migrations/`. Commit it to git. It will be applied automatically on next deploy.
## Database Backups
### Manual backup
```bash
docker compose exec db pg_dump -U postgres veridian > backup_$(date +%Y%m%d).sql
```
### Restore from backup
```bash
cat backup_20250101.sql | docker compose exec -T db psql -U postgres veridian
```
### Automated backups (optional)
Add a cron job on the host:
```bash
# Daily backup at 3 AM
0 3 * * * cd /path/to/veridian && docker compose exec -T db pg_dump -U postgres veridian | gzip > /var/backups/veridian/veridian_$(date +\%Y\%m\%d).sql.gz
```
## Troubleshooting
### App won't start
```bash
# Check logs
docker compose logs app
# Common issues:
# - Missing .env file or required variables not set
# - Database not reachable (check db container is healthy)
# - Migration errors (schema conflicts)
```
### Database connection refused
```bash
# Check DB is healthy
docker compose ps db
# Check DB logs
docker compose logs db
# Test connection
docker compose exec db psql -U postgres veridian -c "SELECT 1"
```
### Reset database (destructive)
```bash
docker compose down -v # Removes volumes!
docker compose up --build -d
```
## Environment Variables Reference
| Variable | Required | Description |
|----------|----------|-------------|
| `POSTGRES_DB` | No | Database name (default: `veridian`) |
| `POSTGRES_USER` | No | Database user (default: `postgres`) |
| `POSTGRES_PASSWORD` | **Yes** | Database password |
| `DATABASE_URL` | Auto | Built from the above vars by docker-compose |
| `BETTER_AUTH_SECRET` | **Yes** | Auth encryption secret (`openssl rand -base64 32`) |
| `NUXT_PUBLIC_URL` | **Yes** | Public URL (e.g., `https://veridian.example.com`) |
| `S3_ACCESS_KEY_ID` | No | S3-compatible storage access key |
| `S3_SECRET_ACCESS_KEY` | No | S3-compatible storage secret key |
| `S3_BUCKET_NAME` | No | S3 bucket name |
| `S3_REGION` | No | S3 region |
| `S3_ENDPOINT` | No | S3 endpoint URL |
| `DISABLE_SIGNUP` | No | Set to `true` to disable new user signups |
| `DISABLE_LOCAL_AUTH` | No | Set to `true` to disable email/password auth |