Deploy BookOrbit on media-core

This commit is contained in:
Codex
2026-09-25 19:15:03 -07:00
parent 9845d5efec
commit 32063c3b3d
2 changed files with 159 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
# BookOrbit on media-core
- Web: `http://192.168.50.46:3000`
- Book library: `/mnt/truenas/multimedia/books` -> `/books`
- Book Dock: `/mnt/truenas/multimedia/curator/staging/bookorbit` -> `/book-dock`
- App data: `/opt/media-core/appdata/bookorbit/app`
- PostgreSQL: `/opt/media-core/appdata/bookorbit/postgres`
- Secrets: `/opt/media-core/appdata/bookorbit/secrets` (`0600`, not in Git)
Create the first library with container path `/books`. Do not later widen or replace that root without a database backup and a tested migration: BookOrbit currently has an open issue where root-folder changes can duplicate books or lose metadata and reading progress.
The existing Curator and BookOrbit share the final book files, but they do not share databases. During the initial evaluation, keep BookOrbit automatic file rename and metadata write-back disabled. Use Book Dock for reviewed imports and retain Curator as the control ledger until BookOrbit integration is explicitly designed.
Before upgrades, create a PostgreSQL dump and back up `/opt/media-core/appdata/bookorbit/app`. Image tags are descriptive and digests are authoritative.
+145
View File
@@ -0,0 +1,145 @@
x-arcane:
icon: bookorbit
urls:
- https://bookorbit.app/
services:
app:
image: ghcr.io/bookorbit/bookorbit:3.1.0@sha256:78b6eac18306eb7eba0dbf6592ecdee01b15f24de9a941cb853db4a0232d7999
container_name: bookorbit-app
restart: unless-stopped
init: true
depends_on:
postgres:
condition: service_healthy
ports:
- "3000:3000"
environment:
NODE_ENV: production
PORT: "3000"
APP_URL: http://192.168.50.46:3000
CLIENT_URL: http://192.168.50.46:3000
POSTGRES_HOST: postgres
POSTGRES_PORT: "5432"
POSTGRES_USER: bookorbit
POSTGRES_DB: bookorbit
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
JWT_SECRET_FILE: /run/secrets/jwt_secret
PODCAST_ENCRYPTION_KEY_FILE: /run/secrets/podcast_encryption_key
SETUP_BOOTSTRAP_TOKEN_FILE: /run/secrets/setup_bootstrap_token
EMAIL_ENCRYPTION_KEY_FILE: /run/secrets/email_encryption_key
MIGRATION_ENCRYPTION_KEY_FILE: /run/secrets/migration_encryption_key
BOOK_REQUEST_ENCRYPTION_KEY_FILE: /run/secrets/book_request_encryption_key
TZ: Asia/Shanghai
PUID: "1000"
PGID: "1000"
NODE_MAX_OLD_SPACE_SIZE: "2048"
BOOK_DOCK_PATH: /book-dock
LIBRARY_BROWSE_ROOT: /books
DISABLE_LOCAL_AUTH: "false"
volumes:
- type: bind
source: /mnt/truenas/multimedia/books
target: /books
bind:
create_host_path: false
- type: bind
source: /mnt/truenas/multimedia/curator/staging/bookorbit
target: /book-dock
bind:
create_host_path: false
- type: bind
source: /opt/media-core/appdata/bookorbit/app
target: /data
bind:
create_host_path: false
secrets:
- postgres_password
- jwt_secret
- podcast_encryption_key
- setup_bootstrap_token
- email_encryption_key
- migration_encryption_key
- book_request_encryption_key
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETGID
- SETUID
security_opt:
- no-new-privileges:true
healthcheck:
test:
- CMD
- node
- -e
- const p=process.env.PORT||3000;fetch('http://127.0.0.1:'+p+'/api/v1/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))
interval: 30s
timeout: 5s
retries: 5
start_period: 60s
stop_grace_period: 30s
labels:
com.getarcaneapp.arcane.icon: bookorbit
logging:
driver: json-file
options:
max-size: 10m
max-file: "3"
postgres:
image: pgvector/pgvector:pg18@sha256:2ba9ca5f2e7daa0f0e7723cba1ee9167bab54efd3640516a44ac1a928dd67e7a
container_name: bookorbit-db
restart: unless-stopped
environment:
POSTGRES_USER: bookorbit
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
POSTGRES_DB: bookorbit
PGDATA: /var/lib/postgresql/data/pgdata
TZ: Asia/Shanghai
volumes:
- type: bind
source: /opt/media-core/appdata/bookorbit/postgres
target: /var/lib/postgresql/data
bind:
create_host_path: false
secrets:
- postgres_password
healthcheck:
test: ["CMD-SHELL", "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
security_opt:
- no-new-privileges:true
stop_grace_period: 60s
labels:
com.getarcaneapp.arcane.icon: postgres
logging:
driver: json-file
options:
max-size: 10m
max-file: "3"
secrets:
postgres_password:
file: /opt/media-core/appdata/bookorbit/secrets/postgres_password
jwt_secret:
file: /opt/media-core/appdata/bookorbit/secrets/jwt_secret
podcast_encryption_key:
file: /opt/media-core/appdata/bookorbit/secrets/podcast_encryption_key
setup_bootstrap_token:
file: /opt/media-core/appdata/bookorbit/secrets/setup_bootstrap_token
email_encryption_key:
file: /opt/media-core/appdata/bookorbit/secrets/email_encryption_key
migration_encryption_key:
file: /opt/media-core/appdata/bookorbit/secrets/migration_encryption_key
book_request_encryption_key:
file: /opt/media-core/appdata/bookorbit/secrets/book_request_encryption_key