Hop til hovedindhold

Privat fjerndeployment

Dette mønster kører Libre WebUI, Ollama og Cloudflare Tunnel på én Docker-vært uden at offentliggøre programmets eller Ollamas porte. Cloudflare Access er den ydre identitetsgrænse, mens Libre WebUI-godkendelse er den indre. Work og Watchtower er separate, valgfrie funktioner med root-lignende rettigheder.

Skabelonen bruger solo-topologien med én replika: SQLite, lokale krypterede blobs, indlejrede vektorer, lokal koordinering og en indlejret jobworker deler programmets datavolumen. Gør den ikke til en teaminstallation ved at ændre backendvælgere i .env. Teaminstallationer skal bruge repositoriets docker-compose.team.yml (og docker-compose.team.work.yml, når Work er aktiveret), som etablerer PostgreSQL/PGVector, versioneret S3-lagring, Redis, en ekstern worker og gatewayen som én koordineret topologi.

Brug deploy/private/docker-compose.yml som udgangspunkt. Den bruger som standard imaget main:

LIBRE_WEBUI_IMAGE=ghcr.io/libre-webui/libre-webui:main

Tagget dev er egnet til en udviklingsinstans, der udtrykkeligt er valgt, ikke som standard for klienten.

Sikkerhedsmodel

  • Cloudflare Access beskytter hele værtsnavnet, herunder /api/* og WebSocket-opgraderinger. Tilføj ikke offentlige bypass-stier.
  • Libre WebUI kræver en aktuel konto til programmets API'er. Modellivscyklus og Work-handlinger kræver, at den aktuelle databaserolle er administrator.
  • Programmet, Ollama, SearXNG og cloudflared bruger kun et privat Compose-netværk. Værten offentliggør ingen programporte.
  • Den medfølgende SearXNG-tjeneste driver valgfri websøgning. Den er kun intern og inaktiv, indtil en administrator aktiverer søgning i Settings > Search. Angiv SEARXNG_SECRET i .env, før stacken startes.
  • Appen kører uden root med skrivebeskyttet rodfilsystem, uden Linux-capabilities, med no-new-privileges og grænser for CPU, hukommelse og PID.
  • Work er deaktiveret, medmindre en af dens overrides medtages. Når Work aktiveres, får containerne deres eget skrivebeskyttede rodfilsystem, fjernede capabilities, ressourcegrænser, arbejdsområdevolumen og en netværkspolitik, der nægter som standard.

Basisstacken monterer ingen Docker-socket. Aktivering af Work med docker-compose.work-proxy.yml bevarer dette: En socketproxy på et internt netværk holder socketen og videresender kun de API-sektioner, Work bruger (containere, images, volumener, netværk, exec og info). Swarm-, secrets-, build- og systemslutpunkter nægtes i proxyen, og programmet behøver hverken socketmontering eller medlemskab af socketgruppen. Proxyen indsnævrer Docker API-overfladen, ikke konsekvensområdet for det, den videresender — den, der kan oprette containere, kan stadig bind-mounte værtsstier. Behandl den som et reelt hærdningslag, ikke som flerbrugerisolering.

Alternativerne med rå socket er fortsat den største tillidsgrænse: docker-compose.work.yml og Watchtower-overrides giver en container en proces, der kan foretage vilkårlige Docker API-kald og kontrollere værten. En skrivebeskyttet socketmontering gør ikke Docker API-adgang skrivebeskyttet. Den integrerede sikkerhedskopieringshjælper nægter at arve en rå Docker-socket. Flyt Work til den filtrerede proxy, før du stoler på planlagte integrerede sikkerhedskopier.

Grundopsætning

  1. Opret en sudo-operatør uden root, og bekræft nøglebaseret SSH-login, før root-SSH deaktiveres.
  2. Kopiér deploy/private/.env.example til /opt/libre-webui/.env, angiv tilstanden 0600, generér unikke hemmeligheder, og dimensionér BLOB_QUOTA_BYTES_PER_USER til værten. BLOB_QUOTA_RESERVATION_TTL_MS lader forladte uploadreservationer udløbe; standarden er én time.
  3. Hvis Work skal aktiveres, skal DOCKER_GID sættes til den numeriske gruppe, der ejer /var/run/docker.sock.
  4. Gem Cloudflare-tunneltokenen i /opt/libre-webui/secrets/tunnel-token med tilstanden 0640 eller strengere.
  5. Opret et selvhostet Cloudflare Access-program for hele værtsnavnet, brug en 24-timers session, og tillad kun de tilsigtede identiteter. Aktivér Protect with Access på tunnelruten. Hvis overvågning kræver et offentligt sundhedstjek, skal du oprette et separat, stiafgrænset program eller en politik kun til /health/live. Tilføj aldrig en generel Bypass-politik til hovedprogrammet: Matchende Bypass-politikker ophæver dets Allow-politik.
  6. Behold ENABLE_SIGNUP=false. Når Access-tilladelseslisten beskytter værtsnavnet, skal du oprette den første lokale administrator. En tom database tillader automatisk denne ene bootstrap-konto. Aktivér kun registrering i et bevidst senere tidsrum.
  7. Konfigurer Turnstile-begrænsninger for værtsnavnet, og sæt TURNSTILE_EXPECTED_HOSTNAME til præcis det offentlige værtsnavn.

Start og verificer:

cd /opt/libre-webui
docker compose config --quiet
docker compose up -d
docker compose ps

For at aktivere Work skal override-filen til socketproxyen medtages bevidst:

docker compose -f docker-compose.yml -f docker-compose.work-proxy.yml up -d

Varianten med rå socket (docker-compose.work.yml) er stadig tilgængelig til installationer, der kræver den, med de tillidsmæssige konsekvenser beskrevet ovenfor.

Når Access er aktivt, kræver kommandolinjetest en Cloudflare Access-tjenestetoken, medmindre den præcise sti har en snæver bypass. Gem legitimationsoplysningerne uden for shell-historikken, og send begge headere:

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

En ikke-godkendt anmodning til et beskyttet program-API skal returnere 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

Hærd værten

Mappen indeholder en sshd-drop-in og et fail2ban-jail. Før sshd-drop-in-filen anvendes, skal du bekræfte en separat sudo-session uden root i en anden terminal. Test konfigurationen med sshd -t, før SSH genindlæses.

Brug UFW (eller en tilsvarende firewall) til at nægte indgående trafik som standard og kun tillade hastighedsbegrænset SSH. Docker offentliggør ingen tjenesteporte i skabelonen:

ufw default deny incoming
ufw default allow outgoing
ufw limit OpenSSH
ufw enable

Behold automatiske sikkerhedsopdateringer aktiveret. Deaktivér videresendelse af X11, agent og TCP, medmindre installationen har et dokumenteret behov for dem.

Sikkerhedskopiering og gendannelse

Kør den skrivebeskyttede gendannelsesoversigt inde i den aktive deploymentscontainer, før en sikkerhedskopi tages. Dermed bruges præcis den udrullede programversion, miljøet og den monterede datavolumen. En kommando fra en checkout på værten kan undersøge den forkerte database eller køre kildekode, der afviger fra det udrullede image.

docker exec libre-webui \
libre-webui recovery-check --json --data-dir /app/backend/data

Exit-status 0 betyder, at der ikke blev fundet blokeringer for gendannelsesberedskab, 1 betyder, at JSON-rapporten indeholder blokeringer, og 2 betyder, at kommandoen ikke kunne køre. Rapporten indeholder kun et fingeraftryk af krypteringsnøglen og flag for tilstedeværelsen af hemmeligheder. Den udskriver aldrig en nøgle eller anden hemmelig værdi. Behold oversigten sammen med den tilhørende sikkerhedskopi, så operatører kan sammenligne programversion, skemafingeraftryk, forventede Work-ressourcer og undtagelser før en gendannelse.

Opret dedikerede krypterings- og signeringsnøgler til sikkerhedskopiering med præcis det udrullede image. Hold mappen uden for programvolumenet, og kopiér krypteringsnøglen og den private signeringsnøgle til en separat beskyttet gendannelsesplacering:

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

Nøglegenereringen nægter at overskrive eksisterende outputfiler. Generér aldrig nye nøgler oven på et eksisterende sikkerhedskopisæt. Hvis arkivets krypteringsnøgle eller signeringsidentitet går tabt, bliver det tilhørende gendannelsesbevis ubrugeligt.

Installér de medfølgende scripts og systemd-enheder til sikkerhedskopiering og gendannelse, og aktivér derefter timeren:

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

Enheden kan valgfrit læse vedligeholdelsesspecifikke overrides fra /etc/libre-webui/backup.env. Den indlæser ikke programmets .env. Opret kun filen som root, når en override er nødvendig:

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 og LIBRE_WEBUI_BACKUP_KEY_DIR kan sættes direkte dér. Behold root som ejer og tilstanden 0600. En tilpasset nøglemappe skal forblive læsbar for root inde i systemd-sandkassen.

Ændring af LIBRE_WEBUI_BACKUP_DIR ændrer også systemd's skrivegrænse. Mappen skal findes, før tjenesten starter, og enheden kræver en tilsvarende drop-in. Efter at LIBRE_WEBUI_BACKUP_DIR=/srv/backups/libre-webui er angivet i backup.env:

install -d -m 0700 /srv/backups/libre-webui
systemctl edit libre-webui-backup.service

Tilføj præcis denne sti i editoren, og genindlæs derefter enheden:

[Service]
ReadWritePaths=/srv/backups/libre-webui
systemctl daemon-reload
systemctl start libre-webui-backup.service

Uden en tilsvarende ReadWritePaths=-post forhindrer ProtectSystem=strict korrekt, at timeren skriver til en tilpasset placering.

Sikkerhedskopieringstjenesten tillader op til seks timer til store arkiver. Hjælperen skaffer en lås på værten, stopper kun programmet, hvis det allerede kørte, og opretter arkivet mod den hvilende volumen med præcis det udrullede image. Arkivet har et signeret manifest og en operatørkrypteret payload. Det indeholder datamappen samt den kørsels- og hemmelighedskonfiguration, der kræves for at åbne tilstanden. Hjælperen verificerer derefter hele arkivet uafhængigt, før metadatarapporten publiceres atomisk. Dens skrivebeskyttede vedligeholdelsescontainere får en privat, skrivbar /tmp tmpfs til SQLite-inspektion og godkendt arkivverificering. Ingen midlertidig klartekst lagres i containerlaget. Kopiér begge filer og de separat beskyttede gendannelsesnøgler væk fra værten.

Når Work bruger docker-compose.work-proxy.yml, skal gendannelse også bevise, at alle Work-volumener, som databasen henviser til, stadig findes. Hjælperen læser det udrullede programs DOCKER_HOST, finder socketproxytjenesten i det samme aktive Compose-projekt og registrerer deres ene fælles interne netværk fra Dockers faktiske netværkstilknytninger. Compose sætter projektnavnet foran netværksnavnet, så et gættet navn må ikke konfigureres eller hardcodes. Kun containeren, der opretter arkivet, tilsluttes det interne netværk og kan nå den filtrerede proxy; den får ingen rå socket. Uafhængig arkivverificering fortsætter med --network none. En manglende proxy, et uventet slutpunkt, et eksternt eller tvetydigt fælles netværk eller en rå socketmontering giver fejl, før programmet stoppes, og før et arkiv publiceres.

Test gendannelse til en ny volumen uden at erstatte den aktive volumen:

LIBRE_WEBUI_RESTORE_IMAGE="$image_ref" \
libre-webui-restore \
/var/backups/libre-webui/libre-webui-integrated-YYYYMMDDTHHMMSSZ.lwb \
libre-webui-restore-drill

Gendannelseshjælperen nægter en eksisterende volumen eller et konfigurationsmål, verificerer arkivet og dets interne gendannelsesoversigt i midlertidigt lager og kopierer derefter data til den nye volumen samt skriver gendannede runtime.json og secrets.json med private tilladelser. Den omkobler eller starter aldrig den aktive stack. Gennemgå den gendannede konfiguration, opdater deploymentspecifikke værdier bevidst, og test den gendannede volumen med en isoleret stack.

Ollama-modeller kan hentes igen. Docker Work-volumener, Kubernetes Work-PVC'er og værtsbundne Work-mapper ligger uden for programmets datamappe og kræver deres egne koordinerede snapshots og opbevaringspolitikker.

Opdateringer

Libre WebUI er tilstandsbevarende, selv når imagetagget kan ændres. Basisfilen til Compose markerer permanent programmet som udelukket fra Watchtower. Opgradér kun som en koordineret operatørhandling:

  1. Registrer ID'et for det aktive image, og opløs den gennemgåede erstatning til en uforanderlig digest.
  2. Kør libre-webui recovery-check, start sikkerhedskopieringstjenesten, og kræv et nyoprettet arkiv og en verificeringsrapport, før du fortsætter.
  3. Sæt LIBRE_WEBUI_IMAGE til den gennemgåede digest, hent den, og genskab kun libre-webui med Docker Compose. Fjern eller genskab ikke dens datavolumen.
  4. Kræv, at /health/ready, login, session/historik, dokumenthentning og Work-smoketest består. Rul tilbage til den registrerede image-digest, hvis de ikke gør, og bevar både den fejlede tilstand og den verificerede sikkerhedskopi til diagnosticering.

Sekvensen på værtssiden er bevidst manuel. Erstat kun digesten efter gennemgang, og kontrollér det nyeste par af .lwb og .json før download:

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}}'

Den valgfrie socketbærende Watchtower-override er fortsat kun tilgængelig for de sidecars, der udtrykkeligt er mærket i basisfilen:

docker compose \
-f docker-compose.yml \
-f docker-compose.watchtower.yml \
up -d

Watchtower kontrollerer Ollama og SearXNG hvert 30. minut. Ollama-modeldata forbliver i den navngivne volumen, og SearXNG-konfigurationen i dens bind-mount. Den opdaterer ikke Libre WebUI, cloudflared, Work-socketproxyen eller Work-sandkasser. En klientinstallation følger main; en eksperimentel instans kan vælge :dev, men programmet kræver stadig samme manuelle opgradering med krav om sikkerhedskopi. Forbind aldrig denne private solo-stack med teamets persistensstjenester. Udrul hele teamtopologien i stedet.