feat(stack): add Paperless-ngx document management system

- Add paperless.yml stack (port 8091, documents.schweitz.net)
- Uses shared postgres (DB: paperless) and redis (DB 8)
- ClamAV installed on host for virus scanning (port 3310)
- Add Paperless integration to library-desk stack
- Update CONTAINERS.md with Paperless and ClamAV profiles
- Add Portainer and NPM API documentation to setup-new-host.md
- Update redis-shared.yml and postgres-shared.yml with Paperless refs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-25 00:36:15 +01:00
co-authored by Claude Opus 4.5
parent 7e06c915ad
commit 765818b4e9
7 changed files with 655 additions and 12 deletions
+67 -5
View File
@@ -1,7 +1,7 @@
# Container Reference - tower-of-joy Infrastructure
> **Last Updated:** 2025-12-14
> **Total Services:** 24 containers across 19 stacks
> **Last Updated:** 2025-12-24
> **Total Services:** 26 containers across 20 stacks
> **System:** Intel i7-6700, RTX 2080 Ti (11GB VRAM), 16GB RAM, Zorin OS 16.3
---
@@ -34,6 +34,8 @@
| **Library Desk** | 8089 | http://192.168.86.149:8089 | LAN | No | 4 | ✅ Running (external) |
| **AMP (Game Server)** | Varies | http://192.168.86.149:8081 | LAN | No | - | ✅ Running |
| **Home Assistant** | 8123 | https://housekeeping.schweitz.net | Internet | No | - | ✅ Running |
| **Paperless-ngx** | 8091 | https://documents.schweitz.net | Internet | No | 8 | ✅ Running |
| **ClamAV** | 3310 | N/A (host service) | No | No | - | ✅ Running |
### External Domains (SSL via Let's Encrypt)
- **home.schweitz.net** → Organizr (Protected by Authentik SSO)
@@ -45,6 +47,7 @@
- **code.schweitz.net** → Code-Server (host service)
- **amp.schweitz.net** → AMP Game Server
- **housekeeping.schweitz.net** → Home Assistant
- **documents.schweitz.net** → Paperless-ngx
- **tatlock.schweitz.net** → (Reserved)
### External Repositories
@@ -122,8 +125,8 @@ PostgreSQL Shared is a centralized PostgreSQL 17 database server providing isola
| **Resource Limits** | None |
| **GPU Required** | No |
| **Dependencies** | docker-dataplane network |
| **Databases** | `authentik` (Authentik SSO), `gitea` (Git hosting), `organizr` (Organizr dashboard), `postgres` (default/admin) |
| **Database Users** | `authentik_user`, `gitea_user`, `organizr_user`, `postgres` (superuser) |
| **Databases** | `authentik` (Authentik SSO), `gitea` (Git hosting), `organizr` (Organizr dashboard), `paperless` (Document management), `postgres` (default/admin) |
| **Database Users** | `authentik_user`, `gitea_user`, `organizr_user`, `paperless_user`, `postgres` (superuser) |
| **Health Check** | `pg_isready -U postgres` (30s interval) |
| **Backup Strategy** | `/backups` volume for pg_dump exports |
@@ -158,7 +161,7 @@ Redis Shared is a centralized Redis 7 key-value store providing cache, session s
| **Resource Limits** | None |
| **GPU Required** | No |
| **Dependencies** | docker-dataplane network |
| **Database Allocation** | DB 0: Authentik, DB 1: Tatlock (memory), DB 2: Wiki.js, DB 3: Scheduler, DB 4: Library Desk, DB 5: SearXNG, DB 6: Tatlock (benchmarks), DB 7: Nextcloud, DB 8-15: Available |
| **Database Allocation** | DB 0: Authentik, DB 1: Tatlock (memory), DB 2: Wiki.js, DB 3: Scheduler, DB 4: Library Desk, DB 5: SearXNG, DB 6: Tatlock (benchmarks), DB 7: Nextcloud, DB 8: Paperless, DB 9-15: Available |
| **Persistence** | AOF (Append-Only File) enabled for durability |
| **Health Check** | `redis-cli ping` returns PONG (30s interval) |
| **Connection String** | `redis://redis-shared:6379/0` (DB 0), `redis://redis-shared:6379/1` (DB 1), etc. |
@@ -471,6 +474,65 @@ Home Assistant is an open-source smart home automation platform that integrates
---
### Paperless-ngx
Paperless-ngx is a document management system that transforms physical documents into a searchable online archive with automatic OCR text recognition, tagging, and full-text search. It provides a web interface for uploading, organizing, and retrieving documents with support for correspondents, document types, and custom fields. The service integrates with Library Desk for document indexing and uses ClamAV for virus scanning of uploaded files. Configs and database are stored on SSD (backed up), while documents are stored on HDD for capacity. Uses shared PostgreSQL for metadata and shared Redis (DB 8) for task queuing.
| Property | Value |
|----------|-------|
| **Image** | `ghcr.io/paperless-ngx/paperless-ngx:latest` |
| **Container Name** | `paperless` |
| **Access URL (LAN)** | http://192.168.86.149:8091 |
| **Access URL (Public)** | https://documents.schweitz.net |
| **External Access** | Yes (via NPM reverse proxy with SSL) |
| **Port Mapping** | 8091:8000 (HTTP) |
| **Network Mode** | Bridge (docker-dataplane) |
| **Restart Policy** | `unless-stopped` |
| **Volume Mounts** | SSD (backed up): `~/docker-data/paperless/data:/usr/src/paperless/data`; HDD: `/mnt/media/paperless/media:/usr/src/paperless/media`, `/mnt/media/paperless/consume:/usr/src/paperless/consume`, `/mnt/media/paperless/export:/usr/src/paperless/export` |
| **Environment** | `PAPERLESS_DBHOST=postgres-shared`, `PAPERLESS_REDIS=redis://redis-shared:6379/8`, `PAPERLESS_URL=https://documents.schweitz.net`, `TZ=Europe/Amsterdam` |
| **Resource Limits** | Memory: 4GB limit, 512MB reservation |
| **GPU Required** | No |
| **Dependencies** | PostgreSQL Shared, Redis Shared (DB 8), NPM (reverse proxy), ClamAV (host) |
| **Database** | PostgreSQL `paperless` on postgres-shared |
| **Health Check** | `curl -f http://localhost:8000` (30s interval) |
| **Features** | OCR (eng+nld), document tagging, full-text search, correspondents, custom fields, webhooks |
| **Integration** | Library Desk (webhook on document added), ClamAV (virus scanning) |
---
### ClamAV
ClamAV is an open-source antivirus engine running on the host OS, providing virus scanning capabilities for the entire server and accessible via TCP socket for container-based services like Paperless-ngx. It includes automatic virus definition updates via freshclam and can perform both on-demand and real-time scanning. Running on the host provides better security isolation than containerized scanning and allows scanning of the host filesystem directly.
| Property | Value |
|----------|-------|
| **Deployment Type** | Host-based systemd service (NOT containerized) |
| **Binary Location** | `/usr/bin/clamd`, `/usr/bin/clamdscan` |
| **Service Names** | `clamav-daemon.service`, `clamav-freshclam.service` |
| **Access URL** | N/A (TCP socket only) |
| **External Access** | No (internal service) |
| **Port Binding** | 0.0.0.0:3310 (TCP socket for remote scanning) |
| **Restart Policy** | `always` (systemd) |
| **Config Location** | `/etc/clamav/clamd.conf`, `/etc/clamav/freshclam.conf` |
| **Database Location** | `/var/lib/clamav/` (virus definitions) |
| **Resource Usage** | ~2-4GB RAM (virus definitions loaded in memory) |
| **GPU Required** | No |
| **Dependencies** | None (host service) |
| **Update Schedule** | Automatic via freshclam (checks multiple times daily) |
| **Connection String** | `clamav://192.168.86.149:3310` |
| **Features** | On-demand scanning, TCP socket API, automatic updates, host filesystem access |
**Usage from containers:**
```bash
# Test connectivity
nc -zv 192.168.86.149 3310
# Scan a file (from host)
clamdscan /path/to/file
```
---
### Samba
Samba provides SMB/CIFS network file sharing for seamless access to homelab storage from Windows, macOS, Linux, and mobile devices, exposing curated shares for media libraries, downloads, and backups with configurable read-only and read-write permissions. It runs as a single container on the samba_default network, serving three shares: Media (read-write access to Jellyfin content), Downloads (read-write for torrent clients), and Backups (read-only for safe data recovery). The service uses password authentication for the user jpmschweitzer and stores its minimal configuration on the SSD while directly mounting HDD paths for zero-copy file access with native performance.
+267
View File
@@ -0,0 +1,267 @@
# Plan: Add Paperless-ngx and ClamAV
## Overview
Add document management (Paperless-ngx) and host-level virus scanning (ClamAV) to the tower-of-joy infrastructure.
## Decisions Made
| Decision | Choice |
|----------|--------|
| Database | Use `postgres-shared` (new DB: `paperless`) |
| Redis | Use `redis-shared` DB 8 |
| ClamAV | Host OS installation (full server protection) |
| External Access | Yes, at `documents.schweitz.net` via NPM |
| Network | `docker-dataplane` |
| Stack | Separate `paperless.yml` stack |
## Services
| Service | Port | Location | Purpose |
|---------|------|----------|---------|
| Paperless-ngx | 8091 | Container | Document management, OCR |
| ClamAV | 3310 | Host OS | Virus scanning + server protection |
---
## Implementation Steps
### Phase 1: ClamAV Host Installation (requires sudo)
**User must run these commands manually:**
```bash
# Install ClamAV
sudo apt update
sudo apt install clamav clamav-daemon -y
# Stop freshclam to update definitions
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam
# Configure clamd to listen on network
sudo sed -i 's/^#TCPSocket.*/TCPSocket 3310/' /etc/clamav/clamd.conf
sudo sed -i 's/^#TCPAddr.*/TCPAddr 0.0.0.0/' /etc/clamav/clamd.conf
# If TCPSocket/TCPAddr not present, add them
grep -q "^TCPSocket" /etc/clamav/clamd.conf || echo "TCPSocket 3310" | sudo tee -a /etc/clamav/clamd.conf
grep -q "^TCPAddr" /etc/clamav/clamd.conf || echo "TCPAddr 0.0.0.0" | sudo tee -a /etc/clamav/clamd.conf
# Restart daemon
sudo systemctl restart clamav-daemon
# Enable at boot
sudo systemctl enable clamav-daemon clamav-freshclam
# Verify
clamdscan --ping 3
```
### Phase 2: Create Storage Directories
```bash
# SSD - configs and working data
mkdir -p ~/docker-data/paperless/{data,consume,export}
# HDD - document storage
mkdir -p /mnt/media/paperless/media
```
### Phase 3: Create PostgreSQL Database
```bash
docker exec -i postgres-shared psql -U postgres <<'EOF'
-- Paperless database
CREATE DATABASE paperless;
CREATE USER paperless_user WITH PASSWORD '<generate-secure-password>';
GRANT ALL PRIVILEGES ON DATABASE paperless TO paperless_user;
\c paperless
GRANT ALL ON SCHEMA public TO paperless_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO paperless_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO paperless_user;
EOF
```
### Phase 4: Create Stack File
**Create:** `stacks/paperless.yml`
```yaml
version: '3.8'
# Paperless-ngx - Document Management System
# Port: 8091 (HTTP)
# GPU: No
# External: documents.schweitz.net
services:
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
container_name: paperless
restart: unless-stopped
ports:
- "8091:8000"
volumes:
# SSD - config and working data
- /home/jpmschweitzer/docker-data/paperless/data:/usr/src/paperless/data
- /home/jpmschweitzer/docker-data/paperless/consume:/usr/src/paperless/consume
- /home/jpmschweitzer/docker-data/paperless/export:/usr/src/paperless/export
# HDD - document storage
- /mnt/media/paperless/media:/usr/src/paperless/media
environment:
# Database (shared PostgreSQL)
PAPERLESS_DBENGINE: postgresql
PAPERLESS_DBHOST: postgres-shared
PAPERLESS_DBPORT: 5432
PAPERLESS_DBNAME: paperless
PAPERLESS_DBUSER: paperless_user
PAPERLESS_DBPASS: ${PAPERLESS_DB_PASSWORD}
# Redis (shared, DB 8)
PAPERLESS_REDIS: redis://redis-shared:6379/8
# Security
PAPERLESS_SECRET_KEY: ${PAPERLESS_SECRET_KEY}
# URLs
PAPERLESS_URL: https://documents.schweitz.net
PAPERLESS_ALLOWED_HOSTS: "*"
PAPERLESS_CORS_ALLOWED_HOSTS: "http://localhost:8091,https://documents.schweitz.net"
# OCR Settings
PAPERLESS_OCR_LANGUAGE: eng+nld
PAPERLESS_OCR_MODE: skip
PAPERLESS_OCR_OUTPUT_TYPE: pdfa
# Webhooks (for Library Desk integration)
PAPERLESS_WEBHOOKS_ALLOW_INTERNAL_REQUESTS: "true"
# Admin user (created on first run)
PAPERLESS_ADMIN_USER: admin
PAPERLESS_ADMIN_PASSWORD: ${PAPERLESS_ADMIN_PASSWORD}
# Timezone
TZ: Europe/Amsterdam
labels:
- "com.centurylinklabs.watchtower.enable=true"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 512M
networks:
- docker-dataplane
networks:
docker-dataplane:
external: true
name: docker-dataplane
```
### Phase 5: Environment Variables
Add to Portainer stack environment or `.env`:
```bash
# Generate these:
PAPERLESS_DB_PASSWORD=<openssl rand -hex 32>
PAPERLESS_SECRET_KEY=<openssl rand -base64 32>
PAPERLESS_ADMIN_PASSWORD=<your-admin-password>
```
### Phase 6: Deploy Stack
Via Portainer or:
```bash
cd /mnt/media/Projects/portainer-core/stacks
docker-compose -f paperless.yml up -d
```
### Phase 7: Configure NPM Proxy
Create proxy host in NPM:
- Domain: `documents.schweitz.net`
- Forward: `paperless:8000` (or `192.168.86.149:8091`)
- SSL: Request Let's Encrypt certificate
- Websockets: Enable
- Access List: As needed (Authentik SSO optional)
### Phase 8: Post-Deployment Configuration
1. **Access Paperless UI:** https://documents.schweitz.net
2. **Login** with admin credentials
3. **Create API Token:** My Profile → API Token → Create
4. **Create Custom Fields:**
- `source_url` (URL)
- `library_indexed` (Boolean)
- `library_doc_id` (Text)
- `collection` (Text)
5. **Configure Webhook Workflow:**
- Trigger: Document Added
- Action: Webhook to `http://library-desk:8089/documents/webhook`
### Phase 9: Update Library Desk Configuration
Add to Library Desk environment:
```bash
PAPERLESS_URL=http://paperless:8000
PAPERLESS_TOKEN=<api-token>
CLAMAV_HOST=192.168.86.149 # Host IP (ClamAV on host)
CLAMAV_PORT=3310
CLAMAV_ENABLED=true
```
---
## Files to Create/Modify
| Action | File | Description |
|--------|------|-------------|
| Create | `stacks/paperless.yml` | Paperless-ngx stack |
| Update | `CONTAINERS.md` | Add Paperless profile, update tables |
| Update | `stacks/postgres-shared.yml` | Add paperless DB setup in comments |
| Update | `stacks/redis-shared.yml` | Update DB allocation (DB 8: Paperless) |
## CONTAINERS.md Updates
Add to Quick Reference table:
```
| **Paperless-ngx** | 8091 | https://documents.schweitz.net | Internet | No | 8 | ✅ Running |
| **ClamAV** | 3310 | N/A (host service) | No | No | - | ✅ Running |
```
Add to External Domains:
```
- **documents.schweitz.net** → Paperless-ngx
```
Update Redis DB allocation:
```
DB 8: Paperless (task queue, cache)
```
Add to PostgreSQL databases:
```
paperless (document storage)
```
---
## Verification Checklist
- [ ] ClamAV responds: `clamdscan --ping 3`
- [ ] PostgreSQL database exists: `docker exec postgres-shared psql -U postgres -c '\l' | grep paperless`
- [ ] Paperless container running: `docker ps | grep paperless`
- [ ] Paperless health check passes
- [ ] External access works: https://documents.schweitz.net
- [ ] Library Desk can reach Paperless webhook endpoint
- [ ] ClamAV accessible from containers: `nc -zv 192.168.86.149 3310`
+196 -2
View File
@@ -259,5 +259,199 @@ If already logged into another `.schweitz.net` service:
---
**Last Updated**: 2025-12-13
**Based on**: library.schweitz.net setup session
## Appendix: Portainer API for Remote Stack Deployment
When you cannot access the Portainer web UI (e.g., outside home network), you can deploy stacks via the API.
### Authentication
```bash
# Get JWT token (valid for 8 hours)
http --ignore-stdin POST http://192.168.86.149:8001/api/auth \
username=admin password=<password>
# Response: {"jwt":"eyJ..."}
```
### List Stacks
```bash
http --ignore-stdin GET http://192.168.86.149:8001/api/stacks \
"Authorization:Bearer <token>"
```
### Read Stack File
```bash
http --ignore-stdin GET "http://192.168.86.149:8001/api/stacks/<stack_id>/file" \
"Authorization:Bearer <token>"
```
### Create Stack
**Endpoint**: `POST /api/stacks/create/standalone/string?endpointId=3`
**Payload format**:
```json
{
"name": "stack-name",
"stackFileContent": "version: '3.8'\nservices:\n ...",
"env": [
{"name": "VAR_NAME", "value": "var_value"},
{"name": "SECRET_KEY", "value": "secret_value"}
]
}
```
**Example deployment script**:
```bash
#!/bin/bash
# Get token
TOKEN=$(http --ignore-stdin POST http://192.168.86.149:8001/api/auth \
username=admin password=<password> | jq -r '.jwt')
# Read stack file and create JSON payload
STACK_CONTENT=$(cat /path/to/stack.yml)
jq -n \
--arg name "my-stack" \
--arg content "$STACK_CONTENT" \
'{
name: $name,
stackFileContent: $content,
env: [
{name: "DB_PASSWORD", value: "secret123"},
{name: "API_KEY", value: "key456"}
]
}' > /tmp/payload.json
# Deploy
curl -s -X POST "http://192.168.86.149:8001/api/stacks/create/standalone/string?endpointId=3" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @/tmp/payload.json
```
### Update Stack
```bash
curl -s -X PUT "http://192.168.86.149:8001/api/stacks/<stack_id>?endpointId=3" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @/tmp/payload.json
```
### Delete Stack
```bash
http --ignore-stdin DELETE "http://192.168.86.149:8001/api/stacks/<stack_id>?endpointId=3" \
"Authorization:Bearer <token>"
```
### Key Notes
- **Endpoint ID**: Use `3` for the local Docker environment (verify with `GET /api/endpoints`)
- **Stack Type**: Use `standalone/string` for Docker Compose stacks (not Swarm)
- **Environment Variables**: Passed as array of `{name, value}` objects, referenced in compose as `${VAR_NAME}`
- **Token Expiry**: JWT tokens expire after 8 hours; re-authenticate if needed
---
## Appendix: NPM API for Remote Proxy Configuration
When you cannot access the NPM web UI, you can configure proxy hosts via the API (port 81).
### Authentication
```bash
http --ignore-stdin POST http://192.168.86.149:81/api/tokens \
identity=<email> secret=<password>
# Response: {"token":"eyJ...", "expires":"..."}
```
### List Proxy Hosts
```bash
http --ignore-stdin GET http://192.168.86.149:81/api/nginx/proxy-hosts \
"Authorization:Bearer <token>"
```
### Create Proxy Host (without SSL)
```bash
curl -s -X POST http://192.168.86.149:81/api/nginx/proxy-hosts \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"domain_names": ["subdomain.schweitz.net"],
"forward_scheme": "http",
"forward_host": "192.168.86.149",
"forward_port": 8091,
"access_list_id": 0,
"certificate_id": 0,
"ssl_forced": false,
"caching_enabled": false,
"block_exploits": true,
"advanced_config": "",
"allow_websocket_upgrade": true,
"http2_support": false,
"hsts_enabled": false,
"hsts_subdomains": false,
"enabled": true,
"locations": []
}'
```
### Request Let's Encrypt Certificate
```bash
curl -s -X POST http://192.168.86.149:81/api/nginx/certificates \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"domain_names": ["subdomain.schweitz.net"],
"meta": {"dns_challenge": false},
"provider": "letsencrypt"
}'
# Response includes certificate ID
```
### Update Proxy Host with SSL
```bash
curl -s -X PUT http://192.168.86.149:81/api/nginx/proxy-hosts/<proxy_id> \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"domain_names": ["subdomain.schweitz.net"],
"forward_scheme": "http",
"forward_host": "192.168.86.149",
"forward_port": 8091,
"access_list_id": 0,
"certificate_id": <cert_id>,
"ssl_forced": true,
"caching_enabled": false,
"block_exploits": true,
"advanced_config": "",
"allow_websocket_upgrade": true,
"http2_support": true,
"hsts_enabled": true,
"hsts_subdomains": false,
"enabled": true,
"locations": []
}'
```
### Key Notes
- **API Port**: NPM API is on port 81, not 80/443
- **Token Expiry**: Tokens expire after 1 day
- **SSL Flow**: Create proxy host → Request certificate → Update proxy host with certificate_id
- **forward_host**: Use container name (if on same network) or host IP
- **Verify**: Check `meta.nginx_online: true` in response
---
**Last Updated**: 2025-12-24
**Based on**: library.schweitz.net setup session, Paperless-ngx API deployment
+4
View File
@@ -35,6 +35,10 @@ services:
# SearXNG Configuration
- SEARXNG_URL=http://searxng:8080
# Paperless Configuration
- PAPERLESS_URL=http://paperless:8000
- PAPERLESS_TOKEN=${PAPERLESS_TOKEN}
# Ollama Configuration (for embeddings)
- OLLAMA_URL=http://ollama:11434
- OLLAMA_MODEL=nomic-embed-text
+110
View File
@@ -0,0 +1,110 @@
version: '3.8'
# Paperless-ngx - Document Management System
# Port: 8091 (HTTP)
# GPU: No
# External: documents.schweitz.net
# Storage: Configs on SSD (backed up), documents on HDD
services:
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
container_name: paperless
restart: unless-stopped
ports:
- "8091:8000"
volumes:
# SSD - configs and database (backed up)
- /home/jpmschweitzer/docker-data/paperless/data:/usr/src/paperless/data
# HDD - document storage
- /mnt/media/paperless/media:/usr/src/paperless/media
- /mnt/media/paperless/consume:/usr/src/paperless/consume
- /mnt/media/paperless/export:/usr/src/paperless/export
environment:
# Database (shared PostgreSQL)
PAPERLESS_DBENGINE: postgresql
PAPERLESS_DBHOST: postgres-shared
PAPERLESS_DBPORT: 5432
PAPERLESS_DBNAME: paperless
PAPERLESS_DBUSER: paperless_user
PAPERLESS_DBPASS: ${PAPERLESS_DB_PASSWORD}
# Redis (shared, DB 8)
PAPERLESS_REDIS: redis://redis-shared:6379/8
# Security
PAPERLESS_SECRET_KEY: ${PAPERLESS_SECRET_KEY}
# URLs
PAPERLESS_URL: https://documents.schweitz.net
PAPERLESS_ALLOWED_HOSTS: "*"
PAPERLESS_CORS_ALLOWED_HOSTS: "http://localhost:8091,https://documents.schweitz.net"
# OCR Settings
PAPERLESS_OCR_LANGUAGE: eng
PAPERLESS_OCR_LANGUAGES: nld # Install Dutch on first startup
PAPERLESS_OCR_MODE: skip
PAPERLESS_OCR_OUTPUT_TYPE: pdfa
# Webhooks (for Library Desk integration)
PAPERLESS_WEBHOOKS_ALLOW_INTERNAL_REQUESTS: "true"
# Admin user (created on first run)
PAPERLESS_ADMIN_USER: admin
PAPERLESS_ADMIN_PASSWORD: ${PAPERLESS_ADMIN_PASSWORD}
# Timezone
TZ: Europe/Amsterdam
labels:
- "com.centurylinklabs.watchtower.enable=true"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
deploy:
resources:
limits:
memory: 4G
reservations:
memory: 512M
networks:
- docker-dataplane
networks:
docker-dataplane:
external: true
name: docker-dataplane
# =============================================================================
# DEPLOYMENT INSTRUCTIONS
# =============================================================================
#
# 1. Environment variables required in Portainer:
# PAPERLESS_DB_PASSWORD=<openssl rand -hex 32>
# PAPERLESS_SECRET_KEY=<openssl rand -base64 32>
# PAPERLESS_ADMIN_PASSWORD=<your-admin-password>
#
# 2. Database already created in postgres-shared:
# Database: paperless
# User: paperless_user
#
# 3. Redis using shared instance DB 8
#
# 4. After deployment, configure NPM:
# Domain: documents.schweitz.net
# Forward: paperless:8000 or 192.168.86.149:8091
# SSL: Let's Encrypt
# Websockets: Enable
#
# 5. Post-deployment in Paperless UI:
# - Create API token (My Profile → API Token)
# - Create custom fields: source_url, library_indexed, library_doc_id, collection
# - Create webhook workflow to http://library-desk:8089/documents/webhook
#
# 6. ClamAV is running on host at 192.168.86.149:3310
# Configure Library Desk with:
# CLAMAV_HOST=192.168.86.149
# CLAMAV_PORT=3310
# CLAMAV_ENABLED=true
+1
View File
@@ -133,4 +133,5 @@ networks:
# - Authentik (identity provider)
# - Gitea (git hosting) - migrated from dedicated instance
# - Nextcloud (personal cloud storage) - migrated from MariaDB
# - Paperless-ngx (document management) - DB: paperless, User: paperless_user
# - Future applications as needed
+10 -5
View File
@@ -63,11 +63,16 @@ networks:
#
# Redis supports 16 databases (0-15). Assign one per application:
#
# DB 0: General cache (default, shared lightweight caching)
# DB 1: Authentik (sessions, cache, message queue)
# DB 2: Gitea (cache, sessions)
# DB 3: Nextcloud (file locking, distributed cache, sessions)
# DB 4-15: Reserved for future applications
# DB 0: Authentik (sessions, cache, message queue)
# DB 1: Tatlock (memory)
# DB 2: Wiki.js
# DB 3: Scheduler
# DB 4: Library Desk
# DB 5: SearXNG
# DB 6: Tatlock (benchmarks)
# DB 7: Nextcloud (file locking, distributed cache, sessions)
# DB 8: Paperless (task queue, cache)
# DB 9-15: Reserved for future applications
#
# Connection Examples:
#