# LinkVault KI-gestützte Sammlung für **Links** und **Prompts**: eingeben → automatisch **kategorisieren**, in **Kategorien / Hersteller / Tags** einsortieren und schnell **wiederfinden**. Beide Sammlungen laufen in derselben App und Datenbank, per Menü umschaltbar. ## Funktionen - 🔗 **Link hinzufügen** – Seite wird geladen und der Textinhalt extrahiert. - ✨ **Prompt hinzufügen** – eigener Bereich für KI-Prompts, per Kopf-Menü zwischen „Links" und „Prompts" umschaltbar. Prompts werden ebenfalls automatisch kategorisiert und getaggt, lassen sich per Kategorie/Volltext durchsuchen und mit einem Klick in die Zwischenablage kopieren. Der Prompt-Text unterstützt **Markdown** (Überschriften, Listen, Fett/Kursiv, Codeblöcke, Zitate) – in der Karten-Vorschau wird das gerendert, beim Kopieren landet der rohe Markdown-Text (für Struktur in der Ziel-KI) in der Zwischenablage. - 🤖 **Automatische KI-Analyse** (OpenAI) – Titel, Zusammenfassung/Kategorie und Tags werden erzeugt. Bestehende Kategorien werden wiederverwendet, damit die Sammlung konsistent bleibt. - ✎ **Bearbeiten** – alle Felder lassen sich jederzeit manuell anpassen. Alternativ kann die KI Links/Prompts **neu beschreiben bzw. neu kategorisieren** lassen. - 🗂️ **Filtern** nach Kategorie (Links zusätzlich nach Hersteller) über die Seitenleiste. - 🔍 **Suche** – klassische Textsuche, bei Links zusätzlich optionale **semantische KI-Suche** (findet auch sinnverwandte Treffer via Embeddings). - ↕️ **Sortieren** nach Datum (neueste/älteste zuerst) oder Name (A–Z / Z–A). - 🔖 **Merkliste** – Links lassen sich zur späteren Durchsicht markieren. - 🕓 **Hinzufügedatum** wird pro Eintrag angezeigt. - 📤 **Export/Import** (Einstellungen) – Links als CSV oder SQL-Dump exportieren, SQL-Dump auch wieder importieren. - 🌗 **Dark/Light-Modus** über den Umschalter im Kopfbereich. - 👥 **Mehrbenutzer** – Registrierung/Login, jeder Nutzer sieht nur seine eigenen Links und Prompts. Die Fußzeile zeigt Autor, Version und den Hostnamen des Servers. Die Version lässt sich über `APP_VERSION` in der `.env` setzen. ## Technik - **Backend:** FastAPI (Python) - **Frontend:** HTML + HTMX (kein Node.js nötig) - **Datenbank:** SQLite (Standard, konfigurierbar über `DATABASE_URL`) - **KI:** OpenAI (`gpt-4o-mini` + `text-embedding-3-small`, konfigurierbar) ## Schnellstart ```bash ./run.sh ``` Das Skript legt eine virtuelle Umgebung an, installiert die Abhängigkeiten, erstellt bei Bedarf eine `.env` und startet den Server auf http://127.0.0.1:8000. Danach in `.env` den `OPENAI_API_KEY` eintragen und den Server neu starten. > Ohne API-Key läuft die App trotzdem – Links werden dann nur ohne KI-Analyse > gespeichert (Kategorie „Sonstiges", keine Zusammenfassung/semantische Suche). ### Manuell ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt cp .env.example .env # OPENAI_API_KEY eintragen uvicorn app.main:app --reload --port 8000 ``` ## Projektstruktur ``` app/ main.py FastAPI-App, Routen (Links & Prompts), Auth-Sessions config.py Konfiguration aus .env database.py SQLAlchemy Engine/Session models.py User-, Link- und Prompt-Modelle security.py Passwort-Hashing (bcrypt) scraper.py Seiteninhalt laden & extrahieren (nur Links) ai.py OpenAI: Kategorisierung (Links & Prompts), Embeddings search.py Semantische Suche (Kosinus-Ähnlichkeit, nur Links) backup.py CSV-/SQL-Export und sicherer SQL-Import (nur Links) mdrender.py Sicheres Markdown-Rendering für Prompt-Inhalte templates/ Jinja2 + HTMX Oberfläche ``` ## Proxmox Für den Betrieb in einem Proxmox-VE-LXC-Container gibt es ein Helper-Script (`scripts/proxmox/install-linkvault.sh`). Es legt automatisch einen Debian-12-Container an und richtet LinkVault darin als systemd-Service ein. ### Installation Auf dem **Proxmox-Host** (als root) ausführen: ```bash bash <(curl -fsSL https://gitea.teamthiele.de/ethiele/linkvault/raw/branch/main/scripts/proxmox/install-linkvault.sh) ``` > Falls das Repo (wieder) auf privat gestellt wird, zusätzlich ein Gitea > Access Token verwenden (**Einstellungen → Anwendungen → Neuen Token > erzeugen**, Scope `read:repository` genügt): > ```bash > export GIT_TOKEN= > bash <(curl -fsSL -H "Authorization: token ${GIT_TOKEN}" \ > https://gitea.teamthiele.de/ethiele/linkvault/raw/branch/main/scripts/proxmox/install-linkvault.sh) > ``` > `GIT_TOKEN` wird automatisch an das Script weitergereicht und auch beim > `git clone` innerhalb des LXC-Containers verwendet. Alternativ, falls das Repo bereits lokal ausgecheckt ist: ```bash bash scripts/proxmox/install-linkvault.sh ``` Das Script: 1. lädt bei Bedarf das Debian-12-LXC-Template herunter, 2. erstellt einen unprivilegierten LXC-Container, 3. installiert darin Python, klont das Repo nach `/opt/linkvault`, 4. legt ein venv an und installiert die Abhängigkeiten, 5. erzeugt eine `.env` mit zufälligem `SECRET_KEY`, 6. richtet LinkVault als systemd-Service (`linkvault.service`) ein und startet ihn. Am Ende gibt das Script die URL des Containers sowie das generierte root-Passwort aus. ### Konfiguration Alle Einstellungen lassen sich per Umgebungsvariable vor dem Aufruf setzen (Defaults siehe Kopf des Scripts): | Variable | Bedeutung | Default | |-------------------|-----------------------------------------|---------------------------------| | `CTID` | Container-ID | nächste freie ID | | `CT_HOSTNAME` | Hostname des Containers | `linkvault` | | `CT_DISK_GB` | Größe der Root-Disk in GB | `8` | | `CT_MEMORY_MB` | RAM in MB | `1024` | | `CT_SWAP_MB` | Swap in MB | `512` | | `CT_CORES` | CPU-Kerne | `2` | | `CT_BRIDGE` | Netzwerk-Bridge | `vmbr0` | | `CT_IP` | Statische IP (`192.168.1.50/24`) oder `dhcp` | `dhcp` | | `CT_GW` | Gateway (nur bei statischer IP nötig) | – | | `CT_STORAGE` | Storage für die Root-Disk | `local-lvm` | | `TEMPLATE_STORAGE`| Storage für das LXC-Template | `local` | | `CT_PASSWORD` | root-Passwort des Containers | zufällig generiert | | `REPO_URL` | Git-Repo, das geklont wird | `.../ethiele/linkvault.git` | | `APP_PORT` | Port, auf dem uvicorn lauscht | `8000` | | `GIT_TOKEN` | Gitea Access Token (nur bei privatem Repo) | – | | `TIMEZONE` | Zeitzone des Containers (`timedatectl`) | `Europe/Berlin` | Beispiel mit statischer IP und fester Container-ID: ```bash CTID=150 CT_HOSTNAME=linkvault CT_IP=192.168.1.50/24 CT_GW=192.168.1.1 \ bash <(curl -fsSL https://gitea.teamthiele.de/ethiele/linkvault/raw/branch/main/scripts/proxmox/install-linkvault.sh) ``` ### Nach der Installation In `/opt/linkvault/.env` **innerhalb des Containers** den `OPENAI_API_KEY` eintragen (siehe [Schnellstart](#schnellstart) für weitere `.env`-Optionen), danach den Dienst neu starten: ```bash pct exec -- systemctl restart linkvault ``` Nützliche Befehle: ```bash pct exec -- systemctl status linkvault # Status prüfen pct exec -- journalctl -u linkvault -f # Logs verfolgen ``` ### Updaten Wenn sich im Git-Repo etwas geändert hat, den Container mit `scripts/proxmox/update-linkvault.sh` auf den neuesten Stand bringen. Das Script zieht per `git pull`, aktualisiert die Python-Abhängigkeiten und startet den systemd-Service neu. Auf dem **Proxmox-Host** ausführen: ```bash CTID=113 bash <(curl -fsSL https://gitea.teamthiele.de/ethiele/linkvault/raw/branch/main/scripts/proxmox/update-linkvault.sh) ``` (`GIT_TOKEN` nur nötig, falls das Repo privat ist – siehe oben.) Alternativ, falls das Repo bereits **auf dem Proxmox-Host selbst** per `git clone` ausgecheckt wurde (z.B. unter `~/linkvault`) und du dich in diesem Verzeichnis befindest: ```bash CTID=113 bash scripts/proxmox/update-linkvault.sh ``` ## Hinweise für den Produktivbetrieb - Einen zufälligen `SECRET_KEY` in `.env` setzen. - Hinter einem HTTPS-Reverse-Proxy betreiben (Session-Cookies). - Für mehr Last statt SQLite z.B. PostgreSQL via `DATABASE_URL` verwenden.