Ιδιωτική απομακρυσμένη εγκατάσταση
Το μοτίβο εκτελεί Libre WebUI, Ollama και Cloudflare Tunnel σε έναν Docker host χωρίς δημοσίευση ports. Το Cloudflare Access είναι εξωτερικό identity boundary και το auth Libre εσωτερικό. Work και Watchtower είναι ξεχωριστά root-equivalent opt-ins.
Είναι solo μίας replica: SQLite, τοπικά encrypted blobs, embedded vectors, local
coordination και embedded worker μοιράζονται data volume. Μην το μετατρέψετε σε team
αλλάζοντας selectors στο .env. Team απαιτεί docker-compose.team.yml και
docker-compose.team.work.yml, που παρέχουν PostgreSQL/PGVector, versioned S3, Redis,
external worker και gateway ως μία τοπολογία.
Ξεκινήστε από deploy/private/docker-compose.yml,
με default image main:
LIBRE_WEBUI_IMAGE=ghcr.io/libre-webui/libre-webui:main
Το dev είναι για ρητό development opt-in, όχι client default.
Μοντέλο ασφάλειας
- Cloudflare Access προστατεύει όλο το hostname,
/api/*και WebSocket upgrades. Χωρίς public bypass. - Τα API απαιτούν current account, model lifecycle και Work απαιτούν admin database role.
- App, Ollama, SearXNG, cloudflared χρησιμοποιούν private Compose network χωρίς published ports.
- Το SearXNG παρέχει προαιρετικό web search, internal και ανενεργό μέχρι
ενεργοποίηση admin. Ορίστε
SEARXNG_SECRETστο.env. - Η app τρέχει non-root, read-only rootfs, χωρίς capabilities, no-new-privileges και limits.
- Work είναι off χωρίς override. Όταν on, containers έχουν δικό τους read-only root, dropped capabilities, limits, volume και default-deny network.
Η base stack δεν mountάρει Docker socket. Με docker-compose.work-proxy.yml, filtered
proxy σε internal network κρατά socket και επιτρέπει μόνο containers, images, volumes,
networks, exec, info. Swarm, secrets, build, system απαγορεύονται και app δεν χρειάζεται
socket/group. Η proxy μειώνει API surface, όχι blast radius: δημιουργός container μπορεί
να bind-mount host paths. Είναι hardening, όχι multi-tenant isolation.
Τα raw-socket docker-compose.work.yml και Watchtower δίνουν arbitrary Docker API και
έλεγχο host. Read-only mount δεν κάνει το API read-only. Ο backup helper αρνείται raw
socket· μεταφέρετε Work στη filtered proxy πριν scheduled integrated backups.
Bootstrap
- Δημιουργήστε non-root sudo operator και επιβεβαιώστε SSH key login πριν απενεργοποιήσετε root SSH.
- Αντιγράψτε
deploy/private/.env.exampleσε/opt/libre-webui/.env, mode0600, δημιουργήστε secrets και ορίστεBLOB_QUOTA_BYTES_PER_USER. ΤοBLOB_QUOTA_RESERVATION_TTL_MSλήγει εγκαταλειμμένες reservations, default μία ώρα. - Για Work, ορίστε
DOCKER_GIDστην αριθμητική ομάδα/var/run/docker.sock. - Αποθηκεύστε tunnel token σε
/opt/libre-webui/secrets/tunnel-tokenmode0640ή αυστηρότερο. - Δημιουργήστε Cloudflare Access app για πλήρες hostname, session 24 ώρες και μόνο
επιθυμητές identities. Enable Protect with Access. Για public health, ξεχωριστή
path policy μόνο
/health/live. Ποτέ blanket Bypass στην κύρια app. - Κρατήστε
ENABLE_SIGNUP=false. Με προστατευμένο hostname δημιουργήστε πρώτο local admin· κενή βάση επιτρέπει αυτό το bootstrap account. Registration μόνο σε σκόπιμο παράθυρο. - Ρυθμίστε Turnstile hostname και
TURNSTILE_EXPECTED_HOSTNAMEακριβώς.
Έναρξη:
cd /opt/libre-webui
docker compose config --quiet
docker compose up -d
docker compose ps
Work με proxy:
docker compose -f docker-compose.yml -f docker-compose.work-proxy.yml up -d
Το raw docker-compose.work.yml παραμένει με τις συνέπειες εμπιστοσύνης.
Με Access, CLI tests χρειάζονται service token εκτός shell history και δύο headers:
curl --fail --silent --show-error \
-H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
-H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET" \
https://your-hostname.example/api/auth/system-info
Μη πιστοποιημένο protected API πρέπει 401:
curl --output /dev/null --write-out '%{http_code}\n' \
-H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \
-H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET" \
https://your-hostname.example/api/work/tasks
Σκλήρυνση host
Υπάρχουν sshd drop-in και fail2ban jail. Πριν εφαρμογή, επιβεβαιώστε άλλη sudo συνεδρία
και sshd -t πριν reload. Με UFW default deny inbound και rate-limited SSH:
ufw default deny incoming
ufw default allow outgoing
ufw limit OpenSSH
ufw enable
Κρατήστε unattended security upgrades. Απενεργοποιήστε X11, agent και TCP forwarding εκτός τεκμηριωμένης ανάγκης.
Backup και επαναφορά
Πριν backup, εκτελέστε read-only recovery inventory μέσα στο running deployment container, ώστε να χρησιμοποιεί ακριβή έκδοση, env και volume. Host checkout μπορεί να δει λάθος βάση ή διαφορετικό source.
docker exec libre-webui \
libre-webui recovery-check --json --data-dir /app/backend/data
Exit 0 χωρίς blockers, 1 blockers στο JSON, 2 αδυναμία εκτέλεσης. Η αναφορά έχει
μόνο fingerprint key και secret-presence flags, ποτέ values. Κρατήστε την με backup
για version, schema, Work resources και exclusions.
Δημιουργήστε dedicated encryption/signing keys με το ακριβές image, εκτός application volume, και αντιγράψτε τα σε ξεχωριστή protected recovery θέση:
install -d -m 0700 /etc/libre-webui/backup-keys
image_ref=$(docker inspect libre-webui --format '{{.Image}}')
docker run --rm --user 0:0 --read-only --network none --cap-drop ALL \
--security-opt no-new-privileges \
--mount type=bind,src=/etc/libre-webui/backup-keys,dst=/backup-keys \
--entrypoint /usr/local/bin/libre-webui "$image_ref" \
backup keygen \
--directory /backup-keys
Η δημιουργία αρνείται υπάρχοντα outputs. Μην αντικαταστήσετε keys: απώλεια encryption ή signing identity ακυρώνει recovery proof.
Εγκαταστήστε scripts/systemd και timer:
install -d -m 0700 /var/backups/libre-webui
install -m 0750 deploy/private/libre-webui-backup \
/usr/local/sbin/libre-webui-backup
install -m 0750 deploy/private/libre-webui-restore \
/usr/local/sbin/libre-webui-restore
install -m 0644 deploy/private/libre-webui-backup.{service,timer} \
/etc/systemd/system/
systemctl daemon-reload
systemctl enable --now libre-webui-backup.timer
Η unit προαιρετικά διαβάζει /etc/libre-webui/backup.env, όχι application .env:
install -d -m 0750 /etc/libre-webui
install -m 0600 /dev/null /etc/libre-webui/backup.env
Εκεί ορίζονται LIBRE_WEBUI_STACK_DIR, LIBRE_WEBUI_BACKUP_RETENTION_DAYS,
LIBRE_WEBUI_CONTAINER_NAME, LIBRE_WEBUI_BACKUP_KEY_DIR. Owner root, mode 0600.
Αλλαγή LIBRE_WEBUI_BACKUP_DIR αλλάζει systemd write boundary. Ο κατάλογος πρέπει να
υπάρχει και χρειάζεται matching drop-in. Αφού ορίσετε
LIBRE_WEBUI_BACKUP_DIR=/srv/backups/libre-webui στο backup.env:
install -d -m 0700 /srv/backups/libre-webui
systemctl edit libre-webui-backup.service
Προσθέστε:
[Service]
ReadWritePaths=/srv/backups/libre-webui
systemctl daemon-reload
systemctl start libre-webui-backup.service
Χωρίς ReadWritePaths=, το ProtectSystem=strict σωστά εμποδίζει custom write.
Η υπηρεσία επιτρέπει έξι ώρες. Ο helper αποκτά host lock, σταματά app μόνο αν έτρεχε
και δημιουργεί archive από quiesced volume με exact image. Περιέχει signed manifest και
operator-encrypted payload με data, runtime και secrets. Επαληθεύει ανεξάρτητα πριν
atomic metadata. Read-only maintenance containers έχουν private writable /tmp tmpfs
χωρίς persisted plaintext. Αντιγράψτε αρχεία και keys off-host.
Με docker-compose.work-proxy.yml, recovery πρέπει να αποδείξει όλα τα referenced
Work volumes. Διαβάζει DOCKER_HOST, βρίσκει proxy στο ίδιο live Compose project και
το μοναδικό κοινό internal network από actual attachments. Επειδή Compose βάζει prefix,
μη hardcodeάρετε όνομα. Μόνο archive container συνδέεται στη filtered proxy χωρίς raw
socket· verification μένει --network none. Missing proxy, unexpected endpoint,
external/ambiguous network ή raw socket αποτυγχάνει πριν stop/publish.
Δοκιμή σε νέο volume:
LIBRE_WEBUI_RESTORE_IMAGE="$image_ref" \
libre-webui-restore \
/var/backups/libre-webui/libre-webui-integrated-YYYYMMDDTHHMMSSZ.lwb \
libre-webui-restore-drill
Ο restore helper αρνείται existing volume/config target, επαληθεύει archive/inventory
σε disposable storage, αντιγράφει data και γράφει runtime.json/secrets.json με
private permissions. Δεν επανασυνδέει ούτε εκκινεί live stack. Ελέγξτε config και
δοκιμάστε isolated stack.
Ollama models κατεβαίνουν ξανά. Docker Work volumes, Kubernetes PVCs και host folders είναι εκτός data directory και χρειάζονται δικά τους coordinated snapshots/retention.
Ενημερώσεις
Το Libre είναι stateful ακόμη με mutable tag. Η base Compose το εξαιρεί από Watchtower. Upgrade μόνο συντονισμένα:
- Καταγράψτε running image ID και επιλύστε reviewed replacement σε immutable digest.
- Εκτελέστε
libre-webui recovery-check, backup service και απαιτήστε νέο verified archive/report. - Ορίστε
LIBRE_WEBUI_IMAGEστο digest, pull και recreate μόνοlibre-webui, ποτέ data volume. - Απαιτήστε
/health/ready, sign-in, session/history, document retrieval και Work smoke tests. Αλλιώς rollback στο digest και διατηρήστε failed state και backup.
Η host sequence είναι σκόπιμα manual. Ελέγξτε νεότερο .lwb/.json πριν pull:
docker inspect libre-webui --format '{{.Config.Image}} {{.Image}}'
docker exec libre-webui \
libre-webui recovery-check --json --data-dir /app/backend/data
systemctl start libre-webui-backup.service
systemctl --no-pager --full status libre-webui-backup.service
ls -lt /var/backups/libre-webui/libre-webui-integrated-* | head
# Set LIBRE_WEBUI_IMAGE=ghcr.io/libre-webui/libre-webui@sha256:REVIEWED_DIGEST
# in the root-owned .env, then recreate only the application.
docker compose pull libre-webui
docker compose up -d --no-deps libre-webui
docker inspect libre-webui --format '{{.State.Health.Status}} {{.Image}}'
Watchtower override μόνο για labeled sidecars:
docker compose \
-f docker-compose.yml \
-f docker-compose.watchtower.yml \
up -d
Ελέγχει Ollama/SearXNG κάθε 30 λεπτά. Data/config μένουν στα volumes/mounts. Δεν
ενημερώνει Libre, cloudflared, proxy ή sandboxes. Client ακολουθεί main, experimental
μπορεί :dev, αλλά ίδια manual backup-gated αναβάθμιση. Μην συνδέετε solo stack σε team
persistence· αναπτύξτε πλήρη team topology.