Zum Inhalt springen
Q
QuoteNode

Installation

QuoteNode aktualisieren

Neue Versionen prüfen, auf das Paket eines neuen Release aktualisieren und sicher zurückrollen.

QuoteNode aktualisieren

QuoteNode prüft automatisch, ob neue Releases verfügbar sind. Ist eine neuere Version verfügbar, zeigt der Admin-Bereich eine Benachrichtigung mit der Release-Bezeichnung und einem Link zu den Release Notes.

Jedes Release wird als Bereitstellungspaket veröffentlicht: docker-compose.yml (und docker-compose.coolify.yml) mit den per Digest festgelegten Release-Images, env.example, release.json und die Werkzeuge in operator/. Aktualisieren heißt, die Compose-Datei durch die des nächsten Pakets zu ersetzen. Aktuelles Release ist v0.9.8-alpha (Paket).

Wie Sie aktualisieren, hängt von der Installationsart ab. Die Checkliste und die Befehle unten gelten für ein Installationsverzeichnis (Server, LAN, Laptop oder ein NAS-Ordner mit docker-compose.yml und .env). Ein Portainer-Stack hat kein solches Verzeichnis: weiter mit Portainer-Stack. Coolify: weiter mit Coolify.

Bekanntes Problem in v0.9.5-alpha: Beispiel-Backup-Ziel

Die env.example von v0.9.5-alpha enthält eine aktive Beispielzeile, BACKUP_RCLONE_REMOTE=s3:mybucket/backups. Dieses Ziel ist nicht konfiguriert: Gelangt die Zeile in Ihre Einstellungen, schlägt jedes Backup fehl, und ein fehlgeschlagener Upload hinterlässt keine lokale Kopie dieses Backups. Die Einstellungen dieser Anleitungen enthalten sie nie; prüfen Sie Ihre Installation, wenn Sie .env aus env.example erstellt oder bei einem Upgrade Einstellungen daraus übernommen haben.

Kommentieren Sie im Installationsverzeichnis genau diese Beispielzeile aus (ein echtes Ziel bleibt unverändert) und erstellen Sie die Container neu:

# Run in Bash (for example Linux, Git Bash or WSL); other shells can edit the exact placeholder manually.
(
  set -eu
  umask 077
  temporary_env="$(mktemp .env.backup-remote.XXXXXX)"
  trap 'rm -f "$temporary_env"' EXIT
  carriage_return="$(printf '\r')"
  # Match only the published placeholder, with either LF or Windows CRLF line endings.
  sample_pattern="^BACKUP_RCLONE_REMOTE=s3:mybucket/backups${carriage_return}\{0,1\}$"
  sed "s|${sample_pattern}|# &|" .env > "$temporary_env"
  if LC_ALL=C grep -Eq "^BACKUP_RCLONE_REMOTE=s3:mybucket/backups${carriage_return}?$" "$temporary_env"; then
    echo "Sample backup remote is still active; settings were not replaced." >&2
    exit 1
  else
    match_status=$?
    [ "$match_status" -eq 1 ] || exit "$match_status"
  fi
  # Keep real remote settings unchanged; publish a changed file atomically with private permissions.
  if ! cmp -s .env "$temporary_env"; then
    mv "$temporary_env" .env
  fi
  docker compose up -d
)

Löschen Sie in Portainer die Stack-Variable BACKUP_RCLONE_REMOTE, wenn sie diesen Beispielwert hat, und aktualisieren Sie dann den Stack. Die Coolify-Definition von v0.9.5-alpha übergibt diese Variable nicht an die Anwendung; löschen Sie den Beispielwert aus der Ressource, bevor Sie auf ein späteres Release aktualisieren.

Backups bleiben dann im Backup-Volume. Starten Sie ein Backup im Admin-Bereich (Admin → Security → Backup), prüfen Sie, dass es erfolgreich abgeschlossen wird, und sorgen Sie für eine Kopie außerhalb des Servers: ein konfiguriertes rclone-Ziel oder regelmäßige Kopien der Archive auf einen anderen Rechner (Sicherung und Wiederherstellung).

Umstieg auf PostgreSQL 18

Die Compose-Dateien verwenden bereits postgres:18-alpine, neue Installationen benötigen daher nichts. Lief eine frühere Alpha auf PostgreSQL 16, migrieren Sie die Daten einmalig — ein PostgreSQL-18-Server startet nicht auf einem älteren Datenverzeichnis, und die Anwendung schreibt es nie automatisch um. Folgen Sie dem eigenen, datensicheren Verfahren: Daten auf PostgreSQL 18 migrieren (Wege über die Kommandozeile und nur über die Oberfläche, je Plattform).

So funktioniert die Versionsprüfung

Die Admin-Oberfläche ruft beim Admin-Login https://quotenode.dev/releases/latest.json ab. Das ist eine nur lesende, nicht authentifizierte GET-Anfrage; es werden keine Daten Ihrer Instanz gesendet. Ist das Manifest nicht erreichbar, schlägt die Prüfung still fehl und der Admin-Bereich funktioniert normal.

Die Prüfung und die Manifest-URL sind Teil der fertig gebauten Weboberfläche. VITE_RELEASE_CHECK_ENABLED oder VITE_RELEASE_MANIFEST_URL in .env oder in Coolify zu setzen, hat bei einem Release keine Wirkung; diese Werte gelten nur, wenn Sie das Frontend-Image selbst aus dem Quellcode bauen. Soll eine Installation quotenode.dev nicht kontaktieren, sperren Sie diese Adresse in Ihrem Netz.

Checkliste vor dem Upgrade

Für ein Installationsverzeichnis; Portainer und Coolify haben unten eigene Abschnitte.

  1. Notieren Sie das aktuelle Release: release.json im Installationsverzeichnis oder Admin > Lizenz.
  2. Kopieren Sie .env außerhalb des Servers — sie enthält Secrets, die sich nicht neu erzeugen lassen (insbesondere DB_ENCRYPTION_KEY).
  3. Laden Sie das neue Paket neben die Installation. Am laufenden Betrieb ändert das nichts:
mkdir -p ../next && cd ../next
curl -fsSLO https://quotenode.dev/releases/v0.9.8-alpha/quotenode-deploy-v0.9.8-alpha.tar.gz
tar -xzf quotenode-deploy-v0.9.8-alpha.tar.gz --strip-components=1
cd -
# Hat das neue Release Einstellungen hinzugefügt oder entfernt? Vergleichen Sie Ihre .env mit der neuen Vorlage.
diff <(grep -o '^[A-Z_]*=' .env | sort) <(grep -o '^[A-Z_]*=' ../next/env.example | sort)
  1. Ergänzen Sie in .env die Einstellungen, die das neue Release braucht (der Vergleich oben listet sie auf; Installationen aus der Zeit vor Release-Paketen: siehe Installationen aus der Zeit vor Release-Paketen). Die laufende Installation verwendet sie noch nicht.
  2. Erstellen Sie mit dem Werkzeug des neuen Pakets den Upgrade-Checkpoint und eine verifizierte Sicherung. Am laufenden Betrieb ändert das nichts, und beim ersten Fehler bricht es ab:
BACKUP_ARCHIVE_ENCRYPTION_MODE=AGE_RECIPIENT BACKUP_AGE_RECIPIENT=age1... \
  ../next/operator/upgrade.sh prepare --export-to ../quotenode-backups

Der Checkpoint (in .quotenode-upgrade/, nur von dieser Installation verwendet) hält die installierte docker-compose.yml, .env und release.json, die Identität der laufenden Images und den Zustand des Datenbankschemas fest. Die Sicherung entsteht mit den Werkzeugen des neuen Releases auf dem Compose-Projekt und den Volumes dieser Installation, bleibt in diesem Lauf lokal, auch wenn entfernte Sicherungen konfiguriert sind, und wird in ../quotenode-backups erst behalten, wenn ihr SHA-256 übereinstimmt. Kopieren Sie dieses Verzeichnis außerhalb des Servers, bevor Sie fortfahren. Den age-Empfänger finden Sie in Ihrem Recovery Kit (Sicherung und Wiederherstellung).

  1. Sind geplante Sicherungen aktiv, prüfen Sie zusätzlich, ob die letzte erfolgreich war (Admin-Bereich).

Ablauf des Upgrades

Docker Compose (Server, LAN, Laptop, NAS-Ordner)

Führen Sie nach der Checkliste im Installationsverzeichnis aus, damit Compose-Projekt und Volumes gleich bleiben:

../next/operator/upgrade.sh apply

upgrade.sh apply lädt zuerst alle Images des neuen Releases und bricht beim ersten Fehler ab: Scheitert ein Download, läuft die Installation unverändert weiter. Erst danach installiert es docker-compose.yml, release.json, env.example und operator/ aus dem Paket, startet die neue Version und wartet, bis sie gesund ist. Datenbankmigrationen laufen automatisch beim Start des neuen Backends. Docker Compose 2.17 oder neuer ist erforderlich.

Portainer-Stack

upgrade.sh benötigt ein Installationsverzeichnis, daher wird ein Portainer-Stack in Portainer aktualisiert:

  1. Prüfen Sie, dass das letzte geplante Backup erfolgreich war (Admin-Bereich), sichern Sie die Volumes des Stacks mit dem Snapshot- oder Backup-Werkzeug Ihrer Plattform und speichern Sie eine Kopie der aktuellen Stack-Definition und ihrer Umgebungsvariablen.
  2. Öffnen Sie den Editor des Stacks und ersetzen Sie die Definition durch den folgenden Block: die Portainer-Anpassung der docker-compose.yml des Release, derselbe Block wie in Installation mit Portainer. Fügen Sie nicht die Originaldatei des Pakets ein: Sie liest .env, die Portainer nicht hat.
  3. Behalten Sie den Stack-Namen und seine Umgebungsvariablen (stack.env); ergänzen Sie die Einstellungen, die das neue Release braucht (Vergleich mit seiner env.example).
  4. Klicken Sie mit aktiviertem Image-Abruf auf Update the stack. Datenbankmigrationen laufen beim Start des neuen Backends.
# Portainer Web editor adaptation of the release docker-compose.yml: env_file reads stack.env (the stack's
# environment variables) instead of .env in postgres, backend and backup-worker. Images, services, ports and
# volumes are unchanged. For a folder-based installation use the unchanged file of the release package.
x-json-file-logging: &json-file-logging
  driver: json-file
  options:
    max-size: "${DOCKER_LOG_MAX_SIZE:-10m}"
    max-file: "${DOCKER_LOG_MAX_FILE:-5}"

# ==========================================================================
# QuoteNode — standalone deployment (docker compose)
# GENERATED by scripts/render-deployment.mjs — do not edit by hand.
# Release v0.9.8-alpha (commit ff74453ca68f3c40bd86a32f0b0b813aaffc7aea, build 28); platforms: linux/amd64.
# API image:      ghcr.io/lesisty7/quotenode/quotenode-api@sha256:0ed701f952c27ea0e1db168a00de75facb231f7c6d5f6b4f0f3b77ef98d4f140
# Frontend image: ghcr.io/lesisty7/quotenode/quotenode-frontend@sha256:40a1cdc4fca5cebd9f43d34daef4ba059a88000ff08af821e199566f07260606
#
# Settings: the .env file in this directory (start from env.example, the commented catalogue of every
# setting; postgres, backend and backup-worker read it). Start: docker compose up -d
# DOMAIN: public host name for automatic HTTPS, or :80 / http://<address> for plain HTTP on a trusted LAN.
# Only the caddy entry point publishes ports (HTTP_PORT/HTTPS_PORT, default 80/443).
# Upgrades: replace this file with the next release package version; volumes keep the data.
# ==========================================================================

services:
  postgres:
    # Database (PostgreSQL 18); internal network only, data in the database volume.
    image: postgres:18-alpine@sha256:77f585114c32fbca283dc835b0596f4e52b51b4c6662d7810b2f4084f60a1873
    # JIT is off by default: for this OLTP workload most queries fall below jit_above_cost,
    # so JIT compilation rarely helps and can add latency. Set PG_JIT=on to re-enable.
    command: ["postgres", "-c", "jit=${PG_JIT:-off}"]
    env_file: stack.env
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_INITDB_ARGS: "--data-checksums"
      # postgres:18 refuses to start on a bare /var/lib/postgresql/data mount (new default layout).
      # Pin PGDATA to the legacy path so the existing volume mount keeps working; major upgrades go
      # through a logical dump/restore, never an in-place upgrade of the data directory.
      PGDATA: /var/lib/postgresql/data
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 10
    # CPU ceilings are opt-in (*_CPUS): 0 = no ceiling, all host cores. Docker refuses a ceiling above the
    # host's core count, so a fixed default would stop the stack on smaller hosts (minimum: 2 cores).
    cpus: ${POSTGRES_CPUS:-0}
    # Ceiling, not a reservation: PG sits at tens of MB until working set/connections grow.
    # Default 512m fits the 4 GB-VM profile; raise POSTGRES_MEM_LIMIT for larger tiers.
    mem_limit: ${POSTGRES_MEM_LIMIT:-512m}
    restart: unless-stopped
    logging: *json-file-logging
    # No published host port: the database is reachable only on the internal network.

  gotenberg:
    # PDF rendering (Chromium) for the backend; internal network only, keeps no data.
    image: gotenberg/gotenberg:8@sha256:aa552cc115db488e0f0bcb07446aac13071ad51505b642c84bb894500907b42b
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:3000/health"]
      interval: 10s
      timeout: 5s
      retries: 5
    cpus: ${GOTENBERG_CPUS:-0}
    # Chromium PDF rendering: measured ~188 MiB peak rendering a real offer template, so
    # 448m keeps ~2.4x headroom. Freed budget goes to backup-worker (closer to its limit).
    mem_limit: ${GOTENBERG_MEM_LIMIT:-448m}
    restart: unless-stopped
    logging: *json-file-logging

  backend:
    # API server (Java): business logic and web jobs; uploads, PDFs and the GeoIP database live in volumes.
    image: ghcr.io/lesisty7/quotenode/quotenode-api@sha256:0ed701f952c27ea0e1db168a00de75facb231f7c6d5f6b4f0f3b77ef98d4f140
    # Time Docker gives the backend between SIGTERM and SIGKILL. 60 s = the SMTP handoff hard limit
    # (mail.handoff.deadline-ms + end-of-data-allowance-ms = 25 s) + 5 s to record its outcome + the HTTP
    # graceful drain phase (30 s). A ceiling, not a delay: an idle backend exits in seconds.
    stop_grace_period: 60s
    depends_on:
      postgres:
        condition: service_healthy
      gotenberg:
        condition: service_healthy
    env_file: stack.env
    environment:
      SPRING_PROFILES_ACTIVE: prod
      JOBS_MODE: web
      # The caddy edge below is the backend's only HTTP peer, so it is the trusted proxy by default (security
      # finding #80); without it every request would appear to come from the edge container. Override only
      # for a custom proxy chain.
      SECURITY_TRUSTED_PROXIES: ${SECURITY_TRUSTED_PROXIES:-caddy}
      BACKUP_LOCAL_DIR: /app/data/backups
    volumes:
      - backend_uploads:/app/data/uploads
      - backend_pdfs:/app/data/pdfs
      - backend_backups:/app/data/backups
      - backend_geoip:/app/data/geoip
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
      interval: 15s
      timeout: 10s
      retries: 5
      start_period: 45s
    cpus: ${BACKEND_CPUS:-0}
    # Heap auto-scales to 70% of this limit (MaxRAMPercentage); default 1536m → ~1 GB heap,
    # fits the 4 GB-VM profile. Raise BACKEND_MEM_LIMIT for heavier load (see resource docs).
    mem_limit: ${BACKEND_MEM_LIMIT:-1536m}
    restart: unless-stopped
    logging: *json-file-logging

  backup-worker:
    # Scheduled backups: same image as the backend, JOBS_MODE=backup-only; archives go to the backups volume.
    image: ghcr.io/lesisty7/quotenode/quotenode-api@sha256:0ed701f952c27ea0e1db168a00de75facb231f7c6d5f6b4f0f3b77ef98d4f140
    depends_on:
      postgres:
        condition: service_healthy
      backend:
        condition: service_healthy
    env_file: stack.env
    environment:
      SPRING_PROFILES_ACTIVE: prod
      JOBS_MODE: backup-only
      BACKUP_LOCAL_DIR: /app/data/backups
      # Worker runs pg_dump in a shell (out-of-JVM) and never does web/import heap work,
      # so it needs little heap. On this small 768m container the ~350 MB fixed non-heap
      # cost makes the global MaxRAMPercentage=70 (538 MB heap → 888 MB total) unsafe.
      # Cap heap lower so heap_max + non-heap stays well under the limit.
      JAVA_OPTS: "-XX:MaxRAMPercentage=45.0 -XX:+UseG1GC -XX:G1PeriodicGCInterval=300000"
    volumes:
      - backend_uploads:/app/data/uploads
      - backend_pdfs:/app/data/pdfs
      - backend_backups:/app/data/backups
      - backend_geoip:/app/data/geoip
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
      interval: 15s
      timeout: 10s
      retries: 5
      # JVM boots a large Spring context (CPU-bound); the grace window must outlast
      # cold start to avoid a false-unhealthy restart loop under load.
      start_period: 300s
    # CPU is a ceiling (idle cost ~0); give the worker enough to boot fast and to run
    # pg_dump + age-encryption/compression bursts without throttling. Idles near zero CPU.
    cpus: ${WORKER_CPUS:-0}
    # Default 832m: measured backup peak (JVM idle + pg_dump + tar + gzip) is ~607 MiB, so
    # this keeps a ~27% margin. Do NOT set WORKER_MEM_LIMIT below ~768m or backups risk OOM.
    mem_limit: ${WORKER_MEM_LIMIT:-832m}
    restart: unless-stopped
    logging: *json-file-logging

  frontend:
    # Web UI: the static build served by Caddy, reached through the caddy entry point.
    image: ghcr.io/lesisty7/quotenode/quotenode-frontend@sha256:40a1cdc4fca5cebd9f43d34daef4ba059a88000ff08af821e199566f07260606
    depends_on:
      backend:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:80/"]
      interval: 15s
      timeout: 5s
      retries: 3
    cpus: ${FRONTEND_CPUS:-0}
    # Prod frontend is Caddy serving the static build (measured ~46 MiB peak under load); 96m is ample.
    # CPU is a free ceiling, so headroom for concurrent connections costs nothing at idle.
    mem_limit: ${FRONTEND_MEM_LIMIT:-96m}
    restart: unless-stopped
    logging: *json-file-logging

  caddy:
    # Entry point: the only published ports (HTTP_PORT/HTTPS_PORT, default 80/443), TLS for DOMAIN, routing, security headers.
    image: ghcr.io/lesisty7/quotenode/quotenode-frontend@sha256:40a1cdc4fca5cebd9f43d34daef4ba059a88000ff08af821e199566f07260606
    # The released frontend image carries the edge config (frontend/caddy/Caddyfile.edge) and the Cloudflare
    # ranges, so the edge needs no host files. Same image digest as the frontend service.
    command: ["caddy", "run", "--config", "/etc/caddy/Caddyfile.edge", "--adapter", "caddyfile"]
    depends_on:
      backend:
        condition: service_healthy
      frontend:
        condition: service_healthy
    environment:
      # Site address for frontend/caddy/Caddyfile.edge: a public host name enables automatic HTTPS; ":80" or
      # "http://host" serves plain HTTP on a trusted LAN. Required: an empty site address is not a valid config.
      DOMAIN: ${DOMAIN:?set DOMAIN to the public host name, or :80 for plain HTTP on a LAN}
      # Optional: address(es) of an operator reverse proxy in front of this edge (default: trust none).
      EDGE_TRUSTED_PROXIES: ${EDGE_TRUSTED_PROXIES:-}
    ports:
      - "${HTTP_PORT:-80}:80"
      - "${HTTPS_PORT:-443}:443"
      - "${HTTPS_PORT:-443}:443/udp"      # HTTP/3 (QUIC)
    volumes:
      - caddy_data:/data
      - caddy_config:/config
    # caddy is the single ingress (TLS, HTTP/3/QUIC, proxying all traffic); give it
    # cores for handshake/encryption bursts under load. CPU idle cost ~0.
    cpus: ${CADDY_CPUS:-0}
    # 96m fits the 4 GB / light-traffic profile. Under heavy TLS load (many concurrent
    # handshakes, large QUIC buffers) raise CADDY_MEM_LIMIT — this ingress is untested at scale.
    mem_limit: ${CADDY_MEM_LIMIT:-96m}
    restart: unless-stopped
    logging: *json-file-logging

# Persistent data: database, uploads, generated PDFs, local backup archives, GeoIP database and the entry
# point's certificates/config. Docker prefixes each name with the Compose project name (by default the
# directory name), so keep the project name across upgrades.
volumes:
  postgres_data:
  backend_uploads:
  backend_pdfs:
  backend_backups:
  backend_geoip:
  caddy_data:
  caddy_config:

Zum Zurückrollen stellen Sie die Volume-Sicherung zusammen mit der gespeicherten Stack-Definition wieder her. Starten Sie die vorherige Definition nie auf einer Datenbank, die das neue Release bereits migriert hat.

Coolify

Ersetzen Sie die Compose-Definition der Ressource durch die docker-compose.coolify.yml des neuen Pakets (Edit Compose File) und stellen Sie bereit. Coolify lädt die neuen Images, bevor es die laufenden Container stoppt. Siehe Installation mit Coolify.

Installationen aus der Zeit vor Release-Paketen

Haben Sie QuoteNode nach diesen Anleitungen installiert, bevor es Release-Pakete gab (eine handgeschriebene docker-compose.yml mit :latest-Images), aktualisieren Sie im selben Verzeichnis mit denselben Befehlen: upgrade.sh erstellt die Sicherung mit den Werkzeugen des neuen Releases auf dem Compose-Projekt und den Volumes Ihrer Installation, sodass vorher weder ein operator/-Verzeichnis noch ein Backup-Dienst nötig ist. Ergänzen Sie vor prepare diese Einstellungen in .env; die laufende Installation verwendet sie noch nicht:

  • DOMAIN konfiguriert jetzt den neuen Einstiegspunkt (caddy): Ein öffentlicher Hostname erhält automatisch HTTPS; für einfaches HTTP im LAN oder auf dem Laptop verwenden Sie DOMAIN=http://<Adresse> (zum Beispiel http://192.168.1.20 oder http://localhost).
  • Sind die Ports 80/443 belegt, setzen Sie HTTP_PORT / HTTPS_PORT, statt die Compose-Datei zu bearbeiten.

Das Paket behält die Volume-Namen der früheren Anleitungen (postgres_data, backend_uploads, backend_pdfs), Ihre Daten werden also weiterverwendet. Starten Sie upgrade.sh aus demselben Verzeichnis (bzw. behalten Sie denselben Stack-Namen in Portainer): Ein anderer Projektname würde mit leeren Volumes starten.

Wenn eine Migration das Upgrade stoppt

Eine Migration kann die Ausführung verweigern, wenn sie Daten findet, die sie nicht selbstständig ändern darf. Das Backend startet dann nicht, und diese Migration ändert nichts — sie wird vollständig zurückgerollt und hinterlässt nichts zu reparieren in der Migrationshistorie. Frühere Migrationen desselben Upgrades können bereits angewendet sein; Ihre Datenbank steht also direkt vor dem verweigerten Schritt und nicht auf der Ausgangsversion. Es gibt keine Eile und keinen Datenverlust.

Den Grund lesen Sie im Log:

docker compose logs backend | grep -i "cannot enforce"

Für Zuordnungen von Angebotsabschnitten enthält das Image eine geführte Reparatur, die ohne laufendes Backend funktioniert — sie zeigt die betroffenen Angebote und lässt Sie entscheiden, was mit ihnen geschieht. Siehe Fehlerbehebung bei der Installation.

Verwenden Sie nicht flyway repair oder baseline, um eine verweigerte Migration zu umgehen. Sie reparieren die Daten nicht, und eine blockierte Migration hinterlässt nichts zu reparieren.

Da frühere Migrationen bereits angewendet sein können, erlaubt ein fehlgeschlagener Start allein nie die Rückkehr zu den vorherigen Images — siehe Zurückrollen.

Prüfung nach dem Upgrade

  1. Öffnen Sie /health — die Antwort ist UP.
  2. Öffnen Sie /actuator/info: Dessen commitSha entspricht commitSha in der neuen release.json.
  3. Melden Sie sich an und prüfen Sie die neue Version unter Admin > Lizenz.
  4. Erstellen Sie ein Testangebot und erzeugen Sie ein PDF.
  5. Öffnen Sie einen öffentlichen Link, um das Routing zu prüfen.
  6. Ist SMTP eingerichtet, senden Sie eine Testbenachrichtigung per E-Mail.

Zurückrollen

Führen Sie niemals docker compose down -v aus — das löscht alle Daten, einschließlich der Datenbank.

upgrade.sh rollback kehrt nur dann zur von prepare gesicherten Definition zurück, wenn das sicher ist: Der Checkpoint muss zu dieser Installation gehören, das Datenbankschema muss genau dem festgehaltenen entsprechen — ein fehlgeschlagener Start beweist das nicht, frühere Migrationen können bereits festgeschrieben sein — und jedes vorherige Image muss noch dasjenige sein, das lief. Andernfalls lehnt es ab und ändert nichts:

../next/operator/upgrade.sh rollback
  • Erlaubt: Die gesicherte docker-compose.yml, .env und release.json kommen zurück, und die vorherigen Images starten ohne Download; vom neuen Release hinzugefügte Dienste werden entfernt, Volumes bleiben erhalten.
  • Abgelehnt: Starten Sie die vorherigen Images nicht von Hand. Hat eine Migration abgelehnt, beheben Sie das in der neuen Version (siehe Wenn eine Migration das Upgrade stoppt) oder stellen Sie die Sicherung vor dem Upgrade wieder her — Datenbank und Dateien als eine Einheit — wie unter Sicherung und Wiederherstellung beschrieben. Die Wiederherstellung prüft Archiv und Kompatibilität, bevor sie etwas ändert, und behält eine Sicherheitskopie, bis das Ergebnis verifiziert ist.
  • Installationen aus der Zeit vor Release-Paketen rollen genauso zurück. Stellen Sie nach einer Ablehnung die Sicherung aus ../quotenode-backups mit operator/restore.sh dieses Releases wieder her; das Release aktualisiert die wiederhergestellten Daten beim Start.

Versionsformat

QuoteNode verwendet semantische Versionierung mit Kanal-Suffix:

  • v0.9.0-alpha — frühe Entwicklung
  • v0.9.0-beta — öffentliche Beta
  • v0.9.0-rc — Release Candidate
  • v0.9.0 — stabiles Release

Eine Release-Bezeichnung wird nie für andere Images wiederverwendet. release.json und https://quotenode.dev/releases/latest.json enthalten Version, Kanal, Bezeichnung, Commit und die Image-Digests des Release.

Last reviewed: Recently