Add Koillection deployment guide (CT 114)
This commit is contained in:
parent
73f9c0be41
commit
89442b3d10
433
114_koillection_deployment.md
Normal file
433
114_koillection_deployment.md
Normal file
@ -0,0 +1,433 @@
|
||||
# 114 — Koillection Deployment Guide
|
||||
|
||||
> Status: **PLANNED** — not yet deployed
|
||||
> CT ID: 114 · IP: 192.168.1.114
|
||||
> Domain: `collections.spendlik.sk`
|
||||
> Last updated: 2026-07-03
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Koillection is a self-hosted collection manager for tracking physical collections of any kind. No pre-built metadata scrapers — metadata is added freely per item, with custom fields via templates. MIT licensed.
|
||||
|
||||
**Collections planned for this instance:**
|
||||
- 🚗 Hot Wheels (series, year, colour, condition, variants)
|
||||
- 🧱 LEGO (set number, theme, piece count, minifigures, completion status)
|
||||
- 🦇 Batmobiles (source media, scale, manufacturer, condition)
|
||||
- 📚 Comics (title, issue, publisher, language, condition)
|
||||
- 📄 Paper Models (designer, scale, subject, format — physical printed copies)
|
||||
|
||||
Stack: `koillection/koillection` (PHP/Symfony + Vue.js) + PostgreSQL 16. Uploads (item photos) bind-mounted to NAS for data safety.
|
||||
|
||||
---
|
||||
|
||||
## Resource Allocation
|
||||
|
||||
| Resource | Allocation |
|
||||
|---|---|
|
||||
| **CT ID** | 114 |
|
||||
| **IP** | 192.168.1.114 |
|
||||
| **CPUs** | 1 |
|
||||
| **RAM** | 512 MB |
|
||||
| **Disk** | 8 GB (app + DB only; photos on NAS) |
|
||||
| **Template** | Debian 13 (trixie) |
|
||||
| **Privileged** | Yes (Docker requires it) |
|
||||
| **Nesting** | Enabled (`features: nesting=1`) |
|
||||
|
||||
---
|
||||
|
||||
## NAS Mount Planning
|
||||
|
||||
Photos uploaded to Koillection land in `/uploads` inside the container. This will be bind-mounted from the NAS at:
|
||||
|
||||
```
|
||||
/volume1/proxmox/data/koillection/uploads
|
||||
```
|
||||
|
||||
Create this directory on the NAS before deployment:
|
||||
|
||||
```bash
|
||||
# On the Synology NAS (SSH or File Station)
|
||||
mkdir -p /volume1/proxmox/data/koillection/uploads
|
||||
```
|
||||
|
||||
> ⚠️ The NAS path follows the same convention as Paperless (`/volume1/proxmox/data/<service>`). Be consistent.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Create LXC Container
|
||||
|
||||
In the Proxmox web UI terminal on the host:
|
||||
|
||||
```bash
|
||||
pct create 114 local:vztmpl/debian-13-standard_13.0-1_amd64.tar.zst \
|
||||
--hostname koillection \
|
||||
--cores 1 \
|
||||
--memory 512 \
|
||||
--swap 512 \
|
||||
--rootfs local-lvm:8 \
|
||||
--net0 name=eth0,bridge=vmbr0,ip=192.168.1.114/24,gw=192.168.1.1 \
|
||||
--unprivileged 0 \
|
||||
--features nesting=1 \
|
||||
--ostype debian \
|
||||
--start 1
|
||||
```
|
||||
|
||||
Enter the container:
|
||||
|
||||
```bash
|
||||
pct enter 114
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Base Setup
|
||||
|
||||
```bash
|
||||
apt update && apt upgrade -y
|
||||
apt install -y nano curl ca-certificates gnupg lsb-release
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Install Docker
|
||||
|
||||
```bash
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
|
||||
https://download.docker.com/linux/debian \
|
||||
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
apt update
|
||||
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
```bash
|
||||
docker run --rm hello-world
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — NAS Bind Mount
|
||||
|
||||
Add the NAS uploads path as a Proxmox bind mount. Exit the container first:
|
||||
|
||||
```bash
|
||||
exit
|
||||
```
|
||||
|
||||
On the Proxmox host:
|
||||
|
||||
```bash
|
||||
pct set 114 --mp0 /mnt/pve/nas/proxmox/data/koillection/uploads,mp=/uploads
|
||||
```
|
||||
|
||||
> ⚠️ Adjust the host-side NAS path to match how the NAS is mounted on the Proxmox host. Verify the mount point with `ls /mnt/pve/` or check `pvesm status` first. If the NAS is not yet mounted at the host level, add it following the same pattern used for CT 111 (Paperless).
|
||||
|
||||
Re-enter the container and verify the mount is visible:
|
||||
|
||||
```bash
|
||||
pct enter 114
|
||||
ls /uploads
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Deploy Koillection
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/koillection
|
||||
cd /opt/koillection
|
||||
nano .env
|
||||
```
|
||||
|
||||
Paste (fill in a strong password for `DB_PASSWORD`):
|
||||
|
||||
```env
|
||||
DB_DRIVER=pdo_pgsql
|
||||
DB_NAME=koillection
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
DB_USER=koillection
|
||||
DB_PASSWORD=CHANGE_ME
|
||||
DB_VERSION=16
|
||||
APP_ENV=prod
|
||||
APP_DEBUG=0
|
||||
APP_SECRET=CHANGE_ME_32CHAR_RANDOM_STRING
|
||||
PHP_TZ=Europe/Bratislava
|
||||
HTTPS_ENABLED=0
|
||||
```
|
||||
|
||||
> Generate `APP_SECRET` with: `openssl rand -hex 16`
|
||||
|
||||
```bash
|
||||
nano docker-compose.yml
|
||||
```
|
||||
|
||||
Paste:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
koillection:
|
||||
image: koillection/koillection:latest
|
||||
container_name: koillection
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8080:80"
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- /uploads:/uploads
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
db:
|
||||
image: postgres:16
|
||||
container_name: koillection-db
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- POSTGRES_DB=${DB_NAME}
|
||||
- POSTGRES_USER=${DB_USER}
|
||||
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||
volumes:
|
||||
- ./volumes/postgresql:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-q", "-d", "koillection", "-U", "koillection"]
|
||||
timeout: 45s
|
||||
interval: 10s
|
||||
retries: 10
|
||||
```
|
||||
|
||||
Start:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
Wait until the koillection container logs settle (Symfony app startup). Then verify locally:
|
||||
|
||||
```bash
|
||||
curl -s http://localhost:8080 | grep -i koillection
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — nginx Reverse Proxy (CT 101)
|
||||
|
||||
Enter CT 101:
|
||||
|
||||
```bash
|
||||
pct enter 101
|
||||
nano /etc/nginx/sites-available/koillection
|
||||
```
|
||||
|
||||
Paste:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name collections.spendlik.sk;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.1.114:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
client_max_body_size 20M;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> `client_max_body_size 20M` — item photos can be large. Adjust upward if needed.
|
||||
|
||||
Enable and reload:
|
||||
|
||||
```bash
|
||||
ln -s /etc/nginx/sites-available/koillection /etc/nginx/sites-enabled/
|
||||
nginx -t && systemctl reload nginx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 7 — SSL Certificate
|
||||
|
||||
Still in CT 101:
|
||||
|
||||
```bash
|
||||
certbot --nginx -d collections.spendlik.sk
|
||||
```
|
||||
|
||||
> ⚠️ Always inspect the config after certbot:
|
||||
|
||||
```bash
|
||||
cat /etc/nginx/sites-available/koillection
|
||||
```
|
||||
|
||||
Check for duplicate `server_name` directives and missing closing braces. Fix manually if needed.
|
||||
|
||||
Also set `HTTPS_ENABLED=1` in `/opt/koillection/.env` in CT 114, then restart:
|
||||
|
||||
```bash
|
||||
# In CT 114
|
||||
cd /opt/koillection
|
||||
nano .env # set HTTPS_ENABLED=1
|
||||
docker compose restart koillection
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 8 — DNS Record
|
||||
|
||||
In WebSupport admin panel:
|
||||
|
||||
1. Add A record: `collections` → current public IP
|
||||
2. **Check both DNS management pages**
|
||||
3. Note the numeric record ID
|
||||
4. Add to `00_index.md` DNS table
|
||||
|
||||
---
|
||||
|
||||
## Phase 9 — DDNS Updater (CT 108)
|
||||
|
||||
Enter CT 108, add `collections.spendlik.sk` to `/usr/local/bin/ddns-update.sh` using the record ID from Phase 8, following the existing script pattern.
|
||||
|
||||
---
|
||||
|
||||
## Phase 10 — Authelia Protection (CT 102)
|
||||
|
||||
Enter CT 102, edit `/etc/authelia/configuration.yml`. Add to `access_control.rules`:
|
||||
|
||||
```yaml
|
||||
- domain: collections.spendlik.sk
|
||||
policy: two_factor
|
||||
```
|
||||
|
||||
> Koillection has its own internal login system. Authelia adds a second layer before users even reach the login page. Since this is a personal single-user instance, you may prefer Authelia bypass and rely on Koillection's own login instead — your call.
|
||||
|
||||
Restart Authelia after editing:
|
||||
|
||||
```bash
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
Add the Authelia middleware to the nginx vhost in CT 101 (follow the pattern from other protected services).
|
||||
|
||||
---
|
||||
|
||||
## Phase 11 — First Login & Initial Setup
|
||||
|
||||
Open `https://collections.spendlik.sk` from mobile data (hairpin NAT — never test from LAN).
|
||||
|
||||
On first load, Koillection will prompt you to create an admin account. Do so, then:
|
||||
|
||||
1. Set your timezone to `Europe/Bratislava` in profile settings
|
||||
2. Set the display currency if tracking purchase values
|
||||
3. Set visibility defaults (private by default is fine for a personal instance)
|
||||
|
||||
---
|
||||
|
||||
## Phase 12 — Collection Setup
|
||||
|
||||
Recommended collection structure. Create each as a top-level Collection:
|
||||
|
||||
### 🚗 Hot Wheels
|
||||
Suggested item fields (via Template):
|
||||
- Series / Line
|
||||
- Year of release
|
||||
- Colour
|
||||
- Casting name
|
||||
- Country of manufacture
|
||||
- Condition (Mint / Good / Played)
|
||||
- Treasure Hunt (yes/no)
|
||||
|
||||
### 🧱 LEGO
|
||||
Suggested item fields:
|
||||
- Set number
|
||||
- Theme
|
||||
- Sub-theme
|
||||
- Piece count
|
||||
- Minifigure count
|
||||
- Year
|
||||
- Completion status (Sealed / Built / Parts only)
|
||||
- Instruction booklet present (yes/no)
|
||||
|
||||
> 💡 The set number field makes cross-referencing with kocka-novinky.sk and Brickset API straightforward.
|
||||
|
||||
### 🦇 Batmobiles
|
||||
Suggested item fields:
|
||||
- Source (Film / TV / Comics / Game)
|
||||
- Year of appearance
|
||||
- Manufacturer (Hot Wheels / Corgi / LEGO / custom)
|
||||
- Scale
|
||||
- Condition
|
||||
|
||||
### 📚 Comics
|
||||
Suggested item fields:
|
||||
- Title / Series
|
||||
- Issue number
|
||||
- Publisher
|
||||
- Language
|
||||
- Year
|
||||
- Condition (Mint / Very Good / Good / Fair)
|
||||
- Story arc
|
||||
|
||||
### 📄 Paper Models (physical hardcopy)
|
||||
Suggested item fields:
|
||||
- Designer / Publisher
|
||||
- Subject (aircraft, ship, building…)
|
||||
- Scale
|
||||
- Format (magazine supplement / standalone / kit)
|
||||
- Build status (Unbuilt / Built / Display)
|
||||
|
||||
> 💡 Tags are cross-collection in Koillection — tag items with `#display`, `#wishlist`, `#for-sale` etc. to group across all five collections at once.
|
||||
|
||||
---
|
||||
|
||||
## Backup
|
||||
|
||||
The only things that need backing up:
|
||||
|
||||
1. **PostgreSQL database** — contains all collection metadata
|
||||
2. **NAS uploads directory** — contains all item photos (already on NAS, covered by NAS backup)
|
||||
|
||||
Add a daily DB dump to cron in CT 114:
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```cron
|
||||
0 3 * * * docker exec koillection-db pg_dump -U koillection koillection > /opt/koillection/backups/koillection-$(date +\%Y\%m\%d).sql 2>/dev/null
|
||||
```
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/koillection/backups
|
||||
```
|
||||
|
||||
> ⚠️ Always back up the database before upgrading Koillection — the developer notes that data migrations can occasionally have edge cases.
|
||||
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
| Issue | Fix |
|
||||
|---|---|
|
||||
| Photos not saving | Verify `/uploads` bind mount is writable inside the container |
|
||||
| App not starting | Check `docker compose logs koillection` — usually a DB connection issue on first boot |
|
||||
| certbot corrupts nginx config | Always inspect after issuance |
|
||||
| Large photo uploads rejected | Increase `client_max_body_size` in nginx vhost |
|
||||
| HTTPS redirect loop | Set `HTTPS_ENABLED=1` in `.env` and restart the koillection container after SSL is in place |
|
||||
Loading…
Reference in New Issue
Block a user