Refine AgentFeed UI and local workflow

This commit is contained in:
peter 2026-06-11 14:01:16 +01:00
parent 3179f832fc
commit ba9f5eb168
29 changed files with 2986 additions and 69 deletions

View file

@ -0,0 +1,348 @@
# Proxmox Container Deployment Runbook For LLM Operators
This document is written for an LLM or automation agent that is deploying Daybook into a Linux container on a Proxmox host.
The recommended deployment target is a Proxmox LXC or VM running Debian/Ubuntu with Docker and Docker Compose. Daybook itself runs as a Docker container inside that guest.
## Deployment Model
```text
Proxmox host
Debian/Ubuntu LXC or VM
Docker Engine
daybook container
/app application code baked into image
/data persistent mounted volume
```
Persistent runtime data lives outside the image in `deploy/data` on the guest:
```text
deploy/data/
db.sqlite3
artifacts_store/
```
Do not store runtime data inside the image.
## Files In This Directory
| File | Purpose |
|---|---|
| `Dockerfile` | Builds the Daybook image. |
| `docker-compose.yml` | Runs Daybook with a persistent `./data:/data` bind mount. |
| `entrypoint.sh` | Runs migrations, collects static files, then starts Gunicorn. |
| `env.example` | Template for deployment environment variables. |
| `proxmox_llm_deploy.md` | This runbook. |
## Prerequisites On The Proxmox Guest
The guest OS should have:
- Docker Engine
- Docker Compose plugin
- Git
- Network access to pull Python base images and Python packages
For Debian/Ubuntu guests, install basics:
```bash
sudo apt-get update
sudo apt-get install -y ca-certificates curl git
```
Install Docker using Docker's current official instructions for the guest OS. Then verify:
```bash
docker --version
docker compose version
```
## Clone Or Copy The Project
Choose a stable application path on the guest:
```bash
sudo mkdir -p /opt/daybook
sudo chown "$USER:$USER" /opt/daybook
```
If using Git:
```bash
git clone <REPO_URL> /opt/daybook
cd /opt/daybook
```
If files were copied by another mechanism, ensure the project root contains:
```text
manage.py
requirements.txt
deploy/docker-compose.yml
deploy/Dockerfile
```
## Create The Environment File
From the project root:
```bash
cd /opt/daybook
cp deploy/env.example deploy/.env
```
Generate secrets:
```bash
python3 - <<'PY'
import secrets
print('DJANGO_SECRET_KEY=' + secrets.token_urlsafe(50))
print('DAYBOOK_API_TOKEN=' + secrets.token_urlsafe(32))
PY
```
Edit `deploy/.env`:
```bash
nano deploy/.env
```
Set at minimum:
```text
DJANGO_DEBUG=0
DJANGO_SECRET_KEY=<generated-secret>
DJANGO_ALLOWED_HOSTS=<container-ip>,<dns-name-if-any>,localhost,127.0.0.1
DAYBOOK_API_TOKEN=<generated-token>
DAYBOOK_DATA_DIR=/data
DATABASE_PATH=/data/db.sqlite3
ARTIFACTS_ROOT=/data/artifacts_store
```
Important:
- Do not commit `deploy/.env`.
- Do not use the development token `dev-token` for a real deployment.
- Include the actual IP or DNS name users will use in `DJANGO_ALLOWED_HOSTS`.
## Create Persistent Data Directory
From the project root:
```bash
mkdir -p deploy/data
```
The compose file mounts this path into the container as `/data`.
## Build And Start
From the project root:
```bash
docker compose -f deploy/docker-compose.yml up -d --build
```
Watch logs:
```bash
docker compose -f deploy/docker-compose.yml logs -f daybook
```
Expected startup behavior:
- Django migrations run.
- Static files are collected.
- Gunicorn starts on port `8000` inside the container.
- Host port `8000` maps to container port `8000`.
## Verify Deployment
Check container state:
```bash
docker compose -f deploy/docker-compose.yml ps
```
Check capabilities endpoint from the guest:
```bash
curl -fsS http://127.0.0.1:8000/api/capabilities
```
Expected JSON includes:
```json
{
"artifact_kinds": ["html_fragment", "html_full", "markdown", "deck", "image", "pdf", "binary"],
"auth": "bearer_token"
}
```
Open the app from another machine:
```text
http://<guest-ip>:8000/
```
If this fails:
- Confirm the Proxmox guest firewall allows TCP `8000`.
- Confirm any Proxmox firewall rules allow TCP `8000`.
- Confirm `DJANGO_ALLOWED_HOSTS` includes the hostname/IP being used.
## Publish A Smoke-Test Artifact
Replace `<TOKEN>` with `DAYBOOK_API_TOKEN` from `deploy/.env`.
```bash
curl -fsS -X POST http://127.0.0.1:8000/api/artifacts \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"persona": "deploy-smoke",
"source_type": "agent",
"source_name": "Deployment Smoke Agent",
"kind": "markdown",
"title": "Deployment Smoke Test",
"content": "# Deployment Smoke Test\n\nDaybook accepted an artifact.",
"tags": ["deploy", "smoke"],
"metadata": {"run_id": "deploy-smoke-001"}
}'
```
Then refresh:
```text
http://<guest-ip>:8000/
```
## Operational Commands
Stop:
```bash
docker compose -f deploy/docker-compose.yml down
```
Start:
```bash
docker compose -f deploy/docker-compose.yml up -d
```
Rebuild after code changes:
```bash
docker compose -f deploy/docker-compose.yml up -d --build
```
View logs:
```bash
docker compose -f deploy/docker-compose.yml logs -f daybook
```
Run Django management command:
```bash
docker compose -f deploy/docker-compose.yml exec daybook python manage.py check
```
Open shell:
```bash
docker compose -f deploy/docker-compose.yml exec daybook sh
```
## Backup
Back up the guest directory:
```text
/opt/daybook/deploy/data
```
It contains:
- SQLite database
- Artifact files
Simple backup command:
```bash
tar -czf daybook-data-$(date +%Y%m%d-%H%M%S).tar.gz -C /opt/daybook/deploy data
```
For consistent backups during heavy writes, stop the container first:
```bash
docker compose -f /opt/daybook/deploy/docker-compose.yml down
tar -czf daybook-data-$(date +%Y%m%d-%H%M%S).tar.gz -C /opt/daybook/deploy data
docker compose -f /opt/daybook/deploy/docker-compose.yml up -d
```
## Restore
Stop Daybook:
```bash
docker compose -f /opt/daybook/deploy/docker-compose.yml down
```
Replace `/opt/daybook/deploy/data` with the restored data directory, then start:
```bash
docker compose -f /opt/daybook/deploy/docker-compose.yml up -d
```
## Updating The App
If deployed from Git:
```bash
cd /opt/daybook
git pull
docker compose -f deploy/docker-compose.yml up -d --build
```
The container entrypoint runs migrations on startup.
## Reverse Proxy Notes
If putting Daybook behind Nginx, Caddy, Traefik, or a Proxmox-level reverse proxy:
- Proxy to `http://<guest-ip>:8000`.
- Add the public hostname to `DJANGO_ALLOWED_HOSTS`.
- Terminate TLS at the proxy.
- Keep `DJANGO_DEBUG=0`.
Example `DJANGO_ALLOWED_HOSTS`:
```text
DJANGO_ALLOWED_HOSTS=daybook.example.com,localhost,127.0.0.1
```
## LLM Deployment Checklist
Before declaring deployment complete, verify all items:
- `deploy/.env` exists and does not use placeholder secrets.
- `DJANGO_DEBUG=0`.
- `DJANGO_ALLOWED_HOSTS` includes the access hostname/IP.
- `deploy/data/` exists.
- `docker compose -f deploy/docker-compose.yml ps` shows `daybook` running or healthy.
- `curl -fsS http://127.0.0.1:8000/api/capabilities` succeeds on the guest.
- Browser opens `http://<guest-ip>:8000/`.
- Smoke-test artifact POST succeeds with the configured bearer token.
- `deploy/data/db.sqlite3` exists after startup.
- `deploy/data/artifacts_store/` exists after posting an artifact.
## Known MVP Constraints
- SQLite is used by default. This is acceptable for local/self-hosted MVP usage.
- The API uses a single shared bearer token.
- No reader authentication is implemented yet.
- Manual drag/drop upload is deferred.
- Content revisions are deferred.