# Planka Runbook

> Last Verified: 2026-02-17 | Owner: John

# Runbook: Planka

**Service Type:** Kanban Board / Project Management
**Container:** planka (ghcr.io/plankanban/planka:2.0.0-rc.4)
**Ports:** 3100 (external) → 1337 (internal)
**External URL:** https://boards.basicconsulting.no
**Database:** PostgreSQL 15 (planka-db)
**Compose File:** ~/system/services/planka/docker-compose.yml

---

## Service Info

Planka is the visual project management tool for BasicAS Group. Kanban-style boards for task tracking.

**Stack:**
- **planka** - Main app (RC4)
- **planka-db** - PostgreSQL 15 (alpine)

**External Access:**
- Exposed via Cloudflare Tunnel: boards.basicconsulting.no
- Trust proxy enabled for correct client IPs

**Admin Access:**
- **Web UI:** http://localhost:3100 (local) or https://boards.basicconsulting.no
- **Username:** john
- **Password:** BasicAS2026!
- **Email:** john@basicconsulting.no
- **Database:** postgresql://postgres@planka-db/planka (internal only, no auth)

---

## Status Check

### Container Health
```bash
docker ps | grep planka
```

Expected output:
```
planka        Up X hours (healthy)
planka-db     Up X hours (healthy)
```

### HTTP Check
```bash
curl -I http://localhost:3100
```

Expected: `200 OK` or `302 Found`

### External Access Check
```bash
curl -I https://boards.basicconsulting.no
```

Expected: `200 OK` or `302 Found`

### Database Check
```bash
docker exec planka-db psql -U postgres -d planka -c "SELECT count(*) FROM \"user\";"
```

---

## Restart Procedure

### Quick Restart (Container Only)
```bash
docker restart planka
```

### Full Stack Restart (Container + Database)
```bash
cd ~/system/services/planka
docker compose down
docker compose up -d
```

Wait 30 seconds for healthcheck to pass, then verify:
```bash
docker ps | grep planka
curl -I http://localhost:3100
```

---

## Troubleshooting

### Problem: Container won't start
**Check logs:**
```bash
docker logs planka --tail 100
```

**Common causes:**
1. Database not ready - wait 30s and retry
2. Port 3100 already bound - check `lsof -i :3100`
3. Volume permission issues - check docker volumes

**Fix:**
```bash
cd ~/system/services/planka
docker compose down
docker compose up -d planka-db
sleep 30
docker compose up -d planka
```

### Problem: Login issues (can't sign in with admin credentials)
**Check environment variables:**
```bash
docker exec planka env | grep DEFAULT_ADMIN
```

Expected:
```
DEFAULT_ADMIN_EMAIL=john@basicconsulting.no
DEFAULT_ADMIN_PASSWORD=BasicAS2026!
DEFAULT_ADMIN_NAME=John AI
DEFAULT_ADMIN_USERNAME=john
```

**If admin was changed in UI, default credentials won't work. Reset via database:**
```bash
docker exec planka-db psql -U postgres -d planka -c "SELECT email, username FROM \"user\" WHERE \"isAdmin\" = true;"
```

### Problem: 502 Bad Gateway (external access)
**Check container is running:**
```bash
docker ps | grep planka
```

**Check Cloudflare tunnel:**
```bash
cloudflared tunnel info boards
```

**Check BASE_URL:**
```bash
docker exec planka env | grep BASE_URL
```

Expected: `BASE_URL=https://boards.basicconsulting.no`

### Problem: Database connection issues
**Check database health:**
```bash
docker exec planka-db pg_isready -U postgres -d planka
```

**Check connection string:**
```bash
docker exec planka env | grep DATABASE_URL
```

Expected: `DATABASE_URL=postgresql://postgres@planka-db/planka`

---

## API Access

Planka has a REST API. Example:

### Get Boards (requires auth token)
```bash
curl -H "Authorization: Bearer <TOKEN>" http://localhost:3100/api/boards
```

**Get Token:**
1. Login via UI
2. Inspect browser Network tab → find `accessToken` in response
3. Or use user credentials to authenticate programmatically

---

## Dependencies

- **Docker** - Service runtime
- **Cloudflare Tunnel** - External access (boards.basicconsulting.no)

**No dependencies on other local services.**

---

## Backup

### Database Dump
```bash
docker exec planka-db pg_dump -U postgres planka | gzip > ~/backups/planka-$(date +%Y%m%d-%H%M%S).sql.gz
```

### Docker Volumes (includes file uploads)
```bash
docker run --rm -v planka-data:/data -v ~/backups:/backup alpine tar -czf /backup/planka-data-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
docker run --rm -v planka-db-data:/data -v ~/backups:/backup alpine tar -czf /backup/planka-db-data-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
```

### Restore from Backup
```bash
# Stop service
cd ~/system/services/planka
docker compose down

# Restore database
gunzip -c ~/backups/planka-YYYYMMDD-HHMMSS.sql.gz | docker exec -i planka-db psql -U postgres -d planka

# Restore volumes (if needed)
docker run --rm -v planka-data:/data -v ~/backups:/backup alpine tar -xzf /backup/planka-data-YYYYMMDD-HHMMSS.tar.gz -C /data
docker run --rm -v planka-db-data:/data -v ~/backups:/backup alpine tar -xzf /backup/planka-db-data-YYYYMMDD-HHMMSS.tar.gz -C /data

# Start service
docker compose up -d
```

---

## Configuration

### Key Environment Variables
- `BASE_URL` - External URL (https://boards.basicconsulting.no)
- `DATABASE_URL` - PostgreSQL connection string
- `SECRET_KEY` - Encryption key for sessions/tokens
- `TOKEN_EXPIRES_IN` - JWT token expiry (365 days)
- `DEFAULT_LANGUAGE` - UI language (en-US)
- `DEFAULT_ADMIN_*` - Initial admin user credentials
- `TRUST_PROXY` - Enable for correct IPs behind Cloudflare

Full config: ~/system/services/planka/docker-compose.yml

---

## Notes

- **Version:** 2.0.0-rc.4 (release candidate, not stable)
- **Auth method:** Password-based (no SSO/LDAP yet)
- **Database:** Uses PostgreSQL with `trust` auth (no password) - secure as internal-only
- **Token expiry:** 365 days (1 year) - very long, consider shorter for security
- **Admin password:** Stored in docker-compose.yml (plaintext) - consider secrets management

---

**Last updated:** 2026-02-10
**Maintained by:** John (AI Director)