# Planka

> Self-hosted Kanban board with card cover images, inspired by Trello

## Overview

| Property | Value |
|----------|-------|
| **Category** | Productivity / Kanban Board |
| **Host** | guava (TrueNAS Scale) |
| **Status** | ✅ Active |
| **Image** | `ghcr.io/plankanban/planka:latest` |
| **Port** | 3090 |

## Access

| Type | URL |
|------|-----|
| **Primary** | **http://100.75.252.64:3090** (Tailscale) |
| **LAN** | http://192.168.0.100:3090 |

## Features

- Kanban boards with drag-and-drop cards
- Card cover images (auto-set from first image attachment)
- Multiple boards per project
- Card labels, due dates, checklists
- File attachments (up to 50MB)
- Multi-user with role-based access
- OIDC/SSO support (Authentik compatible)

## Architecture

```
┌─────────────────────────────────┐
│       planka (Node.js)          │
│         Port 3090:1337          │
│                                 │
│  ┌───────────┐  ┌────────────┐  │
│  │ Sails.js  │  │ Squid      │  │
│  │ API + UI  │  │ (outbound) │  │
│  └─────┬─────┘  └────────────┘  │
│        │                        │
│  ┌─────┴──────┐                 │
│  │ planka-db  │                 │
│  │ Postgres 16│                 │
│  └────────────┘                 │
└─────────────────────────────────┘
```

## Data Persistence

All data stored at `/mnt/data/planka-data/`:

| Directory | Purpose | Backup Priority |
|-----------|---------|-----------------|
| `db/` | PostgreSQL database | 🔴 Critical |
| `app/` | Attachments & cover images | 🔴 Critical |

### Backup

```bash
# Database backup
ssh guava "sudo docker exec planka-db pg_dump -U postgres planka > /tmp/planka_backup.sql"

# Full data backup
ssh guava "sudo tar -czf /tmp/planka_data_$(date +%Y%m%d).tar.gz /mnt/data/planka-data/"
```

## Configuration

Compose file: `/mnt/data/planka-data/docker-compose.yaml`

### Key Environment Variables

| Variable | Value | Description |
|----------|-------|-------------|
| `BASE_URL` | `http://100.75.252.64:3090` | Public-facing URL |
| `SECRET_KEY` | (64-byte hex) | Session encryption |
| `DATABASE_URL` | `postgresql://postgres@planka-db/planka` | DB connection |
| `DEFAULT_ADMIN_EMAIL` | `vish_loves_crista@pepe.com` | Admin account |
| `MAX_UPLOAD_FILE_SIZE` | `50mb` | Attachment size limit |
| `TOKEN_EXPIRES_IN` | `365` | Session lifetime (days) |
| `TRUST_PROXY` | `false` | Set `true` if behind reverse proxy |

## Operations

### Start/Stop

```bash
# Start
ssh guava "cd /mnt/data/planka-data && sudo docker compose up -d"

# Stop
ssh guava "cd /mnt/data/planka-data && sudo docker compose down"
```

### Update

```bash
ssh guava "cd /mnt/data/planka-data && sudo docker compose pull && sudo docker compose up -d"
```

### View Logs

```bash
ssh guava "sudo docker logs planka --tail 100"
ssh guava "sudo docker logs planka-db --tail 100"
```

## Troubleshooting

### Attachments/Cover Images Not Working

The app data directory must be owned by uid 1000 (node user inside container):
```bash
ssh guava "sudo chown -R 1000:1000 /mnt/data/planka-data/app"
ssh guava "sudo docker restart planka"
```

### 500 Errors on Upload

Check the data volume permissions (see above). Planka runs as `node` (uid 1000) inside the container.

### Upload Size Limit

Controlled by `MAX_UPLOAD_FILE_SIZE` env var in the compose file. Default is very low (~1MB) if not set.

## History

- **2026-03-29**: Deployed on guava, replacing Plane.so
- Chose Planka over Plane for simpler Kanban workflow and card cover image support

## External Links

- [Planka GitHub](https://github.com/plankanban/planka)
- [Planka Features](https://planka.app/features)
- [Planka Docs](https://docs.planka.cloud/)

---

*Deployed: 2026-03-29 | Standalone Docker Compose on guava*
