Zum Inhalt springen
Ein Server-Turm aus glühenden Low-Poly-Ebenen, aus dem Lichtpfade zu zwei hervorgehobenen Container-Knoten laufen — als leuchtende Low-Poly-Illustration.
Alle Beiträge
Serie: NextSearchTeil 2 von 4
·Self-HostingUnraidNextcloud

NextSearch auf Unraid

Zwei Container für NextSearch, alles Übrige kommt aus dem, was auf dem Unraid-Server ohnehin schon läuft. Ein Compose-Stack, und die Suche steht.

NextSearch braucht auf Unraid zwei eigene Container. Der Rest steht bei den meisten schon.

Im ersten Teil ging es darum, was NextSearch macht: den Inhalt bestehender Nextcloud-Ordner durchsuchbar, strikt lesend, ohne Cluster daneben. Hier geht es um die andere Hälfte — wie das Ding auf einem Unraid-Server landet, ohne dass daraus ein Nachmittag wird.

Unraid ist dafür ein dankbarer Untergrund. Postgres und Redis laufen auf vielen Boxen längst für andere Anwendungen mit. Meilisearch, Tika und Gotenberg sind dieselben Dienste, die Paperless-ngx nutzt — auf Unraid also gut ausgetreten. Der Plan ist entsprechend: benutzen, was da ist, und den eigenen Fußabdruck klein halten.

Die vollständige Anleitung im Repository

docs/unraid.md enthält den kompletten Stack zum Kopieren, samt der Varianten für externes S3 und für den Weg ohne Compose Manager.


Warum es bei zwei Containern bleibt

Das App-Image bringt eine All-in-one-Rolle mit: FrankenPHP, Queue-Worker und Scheduler laufen unter einem Supervisor im selben Container. Damit besteht NextSearch selbst nur noch aus:

  • app — das Backend mit serve, worker und scheduler in einem
  • web — die Nuxt-Oberfläche, der einzige Container mit veröffentlichtem Port

Alles Weitere sind Dienste, auf die man über das Netz zeigt. Die gibt es auf Unraid durchgängig für linux/amd64:

DienstImageAuf Unraid
Postgrespostgres:18-alpineCommunity-Applications-Template, oft schon in Betrieb
Redisredis:8-alpineCommunity-Applications-Template, oft schon in Betrieb
Meilisearchgetmeili/meilisearchCommunity-Applications-Template
Tikaapache/tika:3.3.1.0-fullaus der offiziellen Unraid-Anleitung zu Paperless-ngx bekannt
Gotenberggotenberg/gotenberg:8dito
S3minio/minioCommunity-Applications-Template — oder externes S3

Das -full-Tag von Tika bringt Tesseract samt Sprachpaketen mit, OCR braucht also keinen eigenen Container. Gotenberg wird ausschließlich für Vorschaubilder von Office-Dateien verwendet; wer die per PREVIEW_OFFICE_ENABLED=false abschaltet, braucht es gar nicht.

Eine Ausnahme von der Wiederverwenden-Regel ist der Objektspeicher. Der Stack unten fährt ein kleines MinIO mit, das auf Unraid-Storage schreibt — Vorschaubilder und extrahierter Text bleiben damit auf dem Array, und externes S3 wird nirgends gebraucht.


Der Stack

Am wenigsten fummelig ist das Compose-Manager-Plugin (Apps → nach „Compose Manager" suchen). Es fährt einen Compose-Stack direkt auf Unraid, und die ganze Verdrahtung steht in einer Datei statt verteilt über ein Dutzend Container-Templates.

Neuen Stack anlegen, das Folgende hineinkopieren, Hosts eintragen:

name: nextsearch

services:
  app:
    image: mirkohaaser/nextsearch-app:0.2.4
    # All-in-one: FrankenPHP + Queue-Worker + Scheduler in einem Container.
    command: ["app-entrypoint", "all"]
    environment:
      APP_KEY: base64:PASTE_A_GENERATED_KEY_HERE
      APP_URL: http://YOUR_UNRAID_IP:3000
      ADMIN_EMAIL: admin@example.com
      ADMIN_PASSWORD: change-me-please

      # Vorhandene Unraid-Postgres und -Redis mitbenutzen.
      DB_HOST: 192.168.1.10
      DB_PORT: "5432"
      DB_DATABASE: nextsearch
      DB_USERNAME: nextsearch
      DB_PASSWORD: your-postgres-password

      REDIS_HOST: 192.168.1.10
      REDIS_PORT: "6379"
      REDIS_PASSWORD: your-redis-password-or-remove-this-line

      # Suche und Extraktion.
      MEILISEARCH_HOST: http://192.168.1.10:7700
      MEILI_MASTER_KEY: your-meili-master-key
      TIKA_URL: http://192.168.1.10:9998
      GOTENBERG_URL: http://192.168.1.10:3000

      # Objektspeicher: das mitgelieferte MinIO auf Unraid-Storage.
      FILESYSTEM_DISK: s3
      AWS_ENDPOINT: http://minio:9000
      AWS_ACCESS_KEY_ID: nextsearch
      AWS_SECRET_ACCESS_KEY: nextsearch-secret
      AWS_BUCKET: nextsearch
      AWS_USE_PATH_STYLE_ENDPOINT: "true"
    volumes:
      - /mnt/user/appdata/nextsearch/storage:/app/storage
    depends_on:
      minio:
        condition: service_healthy
    restart: unless-stopped

  minio:
    image: minio/minio:RELEASE.2025-09-07T16-13-09Z
    command: ["server", "/data", "--console-address", ":9001"]
    environment:
      MINIO_ROOT_USER: nextsearch
      MINIO_ROOT_PASSWORD: nextsearch-secret
    volumes:
      - /mnt/user/appdata/nextsearch/minio:/data
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 10s
      timeout: 5s
      retries: 20
    restart: unless-stopped

  web:
    image: mirkohaaser/nextsearch-web:0.2.4
    environment:
      NUXT_BACKEND_URL: http://app:8080
      NITRO_PORT: "3000"
      NITRO_HOST: 0.0.0.0
    ports:
      - "3000:3000"
    depends_on:
      - app
    restart: unless-stopped

Vier Werte lohnen einen zweiten Blick:

APP_KEY verschlüsselt die hinterlegten Nextcloud-Zugangsdaten und muss ein echter Schlüssel sein. Auf einer beliebigen Maschine mit Docker erzeugen:

docker run --rm mirkohaaser/nextsearch-app:0.2.4 php artisan key:generate --show

Die komplette base64:…-Zeichenkette einsetzen — und stehen lassen. Wird sie später getauscht, lassen sich die gespeicherten Nextcloud-Passwörter nicht mehr entschlüsseln.

MEILI_MASTER_KEY muss derselbe Wert sein, der am Meilisearch-Container gesetzt ist.

Die Hosts. 192.168.1.10 durch die Adresse ersetzen, unter der der jeweilige Dienst tatsächlich läuft. Liegt ein Dienst als Container im selben Unraid-Docker-Netz, tut es auch sein Containername.

Das Image-Tag auf eine veröffentlichte Version festnageln — hier 0.2.4 statt latest. Sonst schiebt ein „force update" in Unraid den Stack auf einen Build, den niemand bestellt hat.

Nur web veröffentlicht einen Port. Hinter einem Reverse-Proxy (Nginx Proxy Manager, SWAG, Traefik) zeigt man auf den web-Container auf 3000 und setzt APP_URL auf die externe Adresse.


Suche, Extraktion, Objektspeicher

Meilisearch, Tika und Gotenberg sind die drei Dienste, die für die meisten neu dazukommen. Zwei Wege stehen offen.

Als eigene Unraid-Container über die Community Applications: Meilisearch mit gesetztem MEILI_MASTER_KEY und MEILI_ENV=production auf Port 7700, Tika aus apache/tika:3.3.1.0-full auf 9998, Gotenberg aus gotenberg/gotenberg:8 auf 3000. Dann zeigen MEILISEARCH_HOST, TIKA_URL und GOTENBERG_URL jeweils dorthin. Wer Paperless-ngx betreibt, kann dessen Tika und Gotenberg direkt mitbenutzen — zwei URLs, fertig.

Ein Stolperstein am Rande: Gotenberg lauscht selbst auf 3000, und dieser Host-Port ist durch den web-Container schon belegt. Beim eigenen Gotenberg-Container also einen anderen Host-Port wählen.

Oder mit in denselben Stack, wenn man sie nicht getrennt pflegen will. Dann kommen die drei Dienste unten dazu und die URLs oben zeigen auf die Servicenamen (http://meilisearch:7700, http://tika:9998, http://gotenberg:3000):

  meilisearch:
    image: getmeili/meilisearch:v1.50.0
    environment:
      MEILI_MASTER_KEY: your-meili-master-key
      MEILI_ENV: production
      MEILI_NO_ANALYTICS: "true"
    volumes:
      - /mnt/user/appdata/nextsearch/meili:/meili_data
    restart: unless-stopped

  tika:
    image: apache/tika:3.3.1.0-full
    restart: unless-stopped

  gotenberg:
    image: gotenberg/gotenberg:8.34
    command:
      - gotenberg
      - --api-timeout=120s
      - --chromium-disable-javascript=true
      - --chromium-allow-list=file:///tmp/.*
    restart: unless-stopped

Postgres und Redis bleiben auch dann außerhalb — das sind die beiden, bei denen sich Wiederverwenden am ehesten lohnt.

Beim Objektspeicher ist nichts einzurichten: NextSearch legt den Bucket beim ersten Start selbst an. Das MinIO-Volume steht auf …/appdata/nextsearch/minio. Bei einem großen Archiv gehört es auf eine eigene Freigabe statt in appdata — die Blobs wachsen mit dem Index, und appdata liegt üblicherweise auf dem Cache-Pool. Es ändert sich nur der Pfad.

Wer schon ein MinIO betreibt, wirft den minio-Dienst samt depends_on heraus und zeigt mit AWS_ENDPOINT auf die vorhandene Instanz. Für echtes S3 (AWS, Backblaze B2, Wasabi) fällt zusätzlich AWS_ENDPOINT weg und AWS_USE_PATH_STYLE_ENDPOINT auf false; der Bucket muss dort vorher existieren, weil ein eingeschränkter Schlüssel meist keinen anlegen darf.


Erster Start, spätere Updates

Beim ersten Hochfahren erledigt app die Migrationen, legt den Administrator aus ADMIN_EMAIL und ADMIN_PASSWORD an und richtet den Meilisearch-Index ein. Im Container-Log steht dann starting all-in-one. Danach http://YOUR_UNRAID_IP:3000 öffnen, anmelden, eine Nextcloud-Instanz hinterlegen, Verbindungstest laufen lassen, einen Ordner auswählen. Der Fortschritt steht unter Admin → Status.

Für ein Update genügt es, die Image-Tags im Stack hochzuziehen und neu zu deployen (Compose Manager → Update). Der app-Container fährt die Migrationen beim Start erneut. Postgres und Objektspeicher rührt ein Image-Tausch nicht an, und der Suchindex baut sich ohnehin selbst wieder auf, falls man ihn einmal leert.

Ein Hinweis zur All-in-one-Rolle: Sie ist für einen einzelnen Knoten gedacht und bootstrappt beim Start. Gegen eine Datenbank darf deshalb genau ein app-Container laufen. Wer verteilt fahren will, nimmt die getrennten Rollen serve, worker und scheduler aus der regulären docker-compose.yml. Für eine Unraid-Kiste zu Hause ist All-in-one der kürzere Weg.


Fazit

Der Aufwand liegt bei diesem Setup nicht im Aufsetzen von NextSearch, sondern im Eintragen der Hosts, die schon laufen. Zwei Container, ein Compose-Stack, ein Schlüssel, der stehen bleiben muss — danach indexiert der Scheduler von allein.


Call to Action

Der Stack zum Kopieren steht in docs/unraid.md, NextSearch selbst unter https://github.com/McGo/NextSearch.

Wer das für ein Team oder eine ganze Organisation aufsetzen will — mit eigenem S3, hinter einem Reverse-Proxy, angebunden an mehrere Instanzen — kann sich gerne melden.