Initiale Version: Roman Station Installer
Lokale KI-Station fuer Zorin OS: Bash-Installer + Docker Compose (Ollama 0.30.7, Open WebUI 0.9.6, n8n 2.25.7), drei roemische Berater als Ollama-Modelfiles, Theme via gsettings, Desktop-Shortcuts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
0b67aa42f4
17 changed files with 567 additions and 0 deletions
12
.env.example
Normal file
12
.env.example
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Roman Station — Konfiguration
|
||||||
|
# install.sh kopiert diese Datei automatisch nach .env, falls keine existiert.
|
||||||
|
|
||||||
|
# Lokales Sprachmodell (CPU-tauglich, gut auf Deutsch).
|
||||||
|
# Alternativen ohne GPU: llama3.2:3b, phi4-mini, qwen3:4b
|
||||||
|
DEFAULT_MODEL=gemma3:4b
|
||||||
|
|
||||||
|
# Ports der Weboberflächen (nur bei Konflikten ändern)
|
||||||
|
WEBUI_PORT=3000
|
||||||
|
N8N_PORT=5678
|
||||||
|
|
||||||
|
TIMEZONE=Europe/Berlin
|
||||||
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
* text=auto eol=lf
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
*.jpeg binary
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
.env
|
||||||
|
*.log
|
||||||
73
README.md
Normal file
73
README.md
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
# Roman Station 🏛️
|
||||||
|
|
||||||
|
Deine eigene KI-Station — läuft komplett **lokal auf deinem Rechner**, ohne Cloud, ohne Abo, ohne dass deine Daten das Haus verlassen. Mit römischem Theme und drei vorinstallierten Beratern.
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- **Zorin OS** (frisch installiert reicht völlig)
|
||||||
|
- Mindestens **8 GB RAM** (16 GB empfohlen) und **25 GB freier Speicher**
|
||||||
|
- Internet für die Installation (danach läuft die KI offline)
|
||||||
|
|
||||||
|
## Installation — ein Befehl
|
||||||
|
|
||||||
|
Terminal öffnen (`Strg+Alt+T`), diese Zeile einfügen, Enter drücken:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -sL https://poised-mayfly.pikapod.net/cemsadmin/roman-station/raw/branch/main/install.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Das Script fragt einmal nach deinem Passwort (für die Installation) und erledigt dann alles selbst. Beim ersten Mal dauert es 10–20 Minuten, weil das Sprachmodell heruntergeladen wird. Danach liegen zwei Verknüpfungen auf dem Schreibtisch.
|
||||||
|
|
||||||
|
## Was du bekommst
|
||||||
|
|
||||||
|
| | Adresse | Was es ist |
|
||||||
|
|---|---|---|
|
||||||
|
| **Forum** | http://localhost:3000 | Chat mit deinen Beratern (Open WebUI) |
|
||||||
|
| **Werkstatt** | http://localhost:5678 | KI-Workflows bauen (n8n) |
|
||||||
|
|
||||||
|
### Deine Berater
|
||||||
|
|
||||||
|
Im Forum oben links das Modell wählen:
|
||||||
|
|
||||||
|
- **seneca** — stoischer Mentor für Lebensfragen, Entscheidungen und Fokus
|
||||||
|
- **cicero** — Schreiber und Rhetoriker für E-Mails, Texte und Argumente
|
||||||
|
- **marcus** — Stratege, der Vorhaben in klare Pläne zerlegt
|
||||||
|
|
||||||
|
Alle antworten auf Deutsch und laufen auf dem lokalen Modell `gemma3:4b` (in `.env` änderbar).
|
||||||
|
|
||||||
|
## Häufige Fragen
|
||||||
|
|
||||||
|
**Die Antworten kommen langsam.**
|
||||||
|
Normal ohne Grafikkarte — das Modell rechnet auf dem Prozessor. Kleine Modelle (3–4B) sind der richtige Kompromiss.
|
||||||
|
|
||||||
|
**Wie starte/stoppe ich die Station?**
|
||||||
|
Sie startet automatisch mit dem Rechner. Manuell:
|
||||||
|
```bash
|
||||||
|
cd ~/.roman-station
|
||||||
|
sudo docker compose stop # anhalten
|
||||||
|
sudo docker compose start # weiter
|
||||||
|
```
|
||||||
|
|
||||||
|
**Wie bekomme ich Updates?**
|
||||||
|
Einfach den Installations-Befehl von oben noch einmal ausführen — er aktualisiert alles, ohne deine Daten zu löschen.
|
||||||
|
|
||||||
|
**Etwas ist schiefgelaufen.**
|
||||||
|
Das Protokoll liegt in `~/roman-station-install.log`. Container-Details: `cd ~/.roman-station && sudo docker compose logs`.
|
||||||
|
|
||||||
|
**Komplett entfernen:**
|
||||||
|
```bash
|
||||||
|
cd ~/.roman-station
|
||||||
|
sudo docker compose down -v
|
||||||
|
cd ~ && rm -rf ~/.roman-station
|
||||||
|
rm -f ~/Desktop/roman-*.desktop ~/.local/share/applications/roman-*.desktop
|
||||||
|
```
|
||||||
|
|
||||||
|
## Für Bastler
|
||||||
|
|
||||||
|
- `docker-compose.yml` — der KI-Motor: [Ollama](https://ollama.com), [Open WebUI](https://github.com/open-webui/open-webui), [n8n](https://n8n.io), Versionen gepinnt
|
||||||
|
- `agents/modelfiles/` — die Berater als Ollama-Modelfiles (eigene hinzufügen: Datei kopieren, System-Prompt anpassen, Installer erneut laufen lassen)
|
||||||
|
- `agents/n8n/` — Beispiel-Workflows für die Werkstatt
|
||||||
|
- `theme/` — Wallpaper und Icon
|
||||||
|
- `.env` — Modell und Ports
|
||||||
|
|
||||||
|
Auf anderen Ubuntu-Systemen lässt sich die OS-Prüfung umgehen: `ROMAN_SKIP_OS_CHECK=1 bash install.sh`
|
||||||
13
agents/modelfiles/Cicero.Modelfile
Normal file
13
agents/modelfiles/Cicero.Modelfile
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
FROM {{MODEL}}
|
||||||
|
PARAMETER temperature 0.8
|
||||||
|
PARAMETER num_ctx 4096
|
||||||
|
SYSTEM """Du bist Cicero, Roms größter Redner — heute Schreiber und Rhetorik-Berater.
|
||||||
|
|
||||||
|
Deine Art:
|
||||||
|
- Du antwortest auf Deutsch und schreibst Texte, die sitzen: E-Mails, Bewerbungen, Posts, Reden, Argumentationen.
|
||||||
|
- Du fragst kurz nach Zielgruppe und Ton, wenn es unklar ist — sonst lieferst du direkt.
|
||||||
|
- Du beherrschst die klassische Rhetorik (Ethos, Pathos, Logos) und setzt sie unauffällig ein.
|
||||||
|
- Auf Wunsch korrigierst und verbesserst du fremde Texte und erklärst kurz, was du geändert hast.
|
||||||
|
- Du lieferst standardmäßig eine starke Fassung, keine drei halbgaren Varianten.
|
||||||
|
|
||||||
|
Du bist Berater der Roman Station, der lokalen KI-Station deines Nutzers."""
|
||||||
13
agents/modelfiles/Marcus.Modelfile
Normal file
13
agents/modelfiles/Marcus.Modelfile
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
FROM {{MODEL}}
|
||||||
|
PARAMETER temperature 0.3
|
||||||
|
PARAMETER num_ctx 4096
|
||||||
|
SYSTEM """Du bist Marcus Aurelius, Philosophenkaiser — heute Stratege und Planer.
|
||||||
|
|
||||||
|
Deine Art:
|
||||||
|
- Du antwortest auf Deutsch — nüchtern, strukturiert, ohne Pathos (wie in deinen Selbstbetrachtungen).
|
||||||
|
- Du zerlegst Vorhaben in klare Schritte: Ziel, nächste Aktionen, Prioritäten, Risiken.
|
||||||
|
- Du nutzt Listen und kurze Abschnitte, keine Textwände.
|
||||||
|
- Du benennst ehrlich, was wegfallen sollte — Fokus schlägt Vollständigkeit.
|
||||||
|
- Bei vagen Vorhaben stellst du genau die 2–3 Fragen, die den Plan konkret machen.
|
||||||
|
|
||||||
|
Du bist Berater der Roman Station, der lokalen KI-Station deines Nutzers."""
|
||||||
13
agents/modelfiles/Seneca.Modelfile
Normal file
13
agents/modelfiles/Seneca.Modelfile
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
FROM {{MODEL}}
|
||||||
|
PARAMETER temperature 0.7
|
||||||
|
PARAMETER num_ctx 4096
|
||||||
|
SYSTEM """Du bist Seneca, stoischer Philosoph und persönlicher Mentor.
|
||||||
|
|
||||||
|
Deine Art:
|
||||||
|
- Du antwortest auf Deutsch — ruhig, klar, ohne Geschwafel.
|
||||||
|
- Du hilfst bei Lebensfragen, Entscheidungen, Gewohnheiten und Fokus.
|
||||||
|
- Du nutzt stoische Prinzipien (Dichotomie der Kontrolle, memento mori, Tugend vor Komfort), ohne damit anzugeben.
|
||||||
|
- Du stellst höchstens eine Rückfrage, dann gibst du konkreten, umsetzbaren Rat.
|
||||||
|
- Gelegentlich ein kurzes passendes Zitat aus deinen Briefen — sparsam eingesetzt.
|
||||||
|
|
||||||
|
Du bist Berater der Roman Station, der lokalen KI-Station deines Nutzers."""
|
||||||
35
agents/n8n/taeglicher-rat-von-seneca.json
Normal file
35
agents/n8n/taeglicher-rat-von-seneca.json
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"name": "Täglicher Rat von Seneca (Beispiel)",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"id": "a1b2c3d4-0000-4000-8000-000000000001",
|
||||||
|
"name": "Manuell starten",
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"method": "POST",
|
||||||
|
"url": "http://ollama:11434/api/generate",
|
||||||
|
"sendBody": true,
|
||||||
|
"specifyBody": "json",
|
||||||
|
"jsonBody": "{ \"model\": \"seneca\", \"prompt\": \"Gib mir einen kurzen stoischen Rat für den heutigen Tag.\", \"stream\": false }",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "a1b2c3d4-0000-4000-8000-000000000002",
|
||||||
|
"name": "Seneca fragen",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 4.2,
|
||||||
|
"position": [220, 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"Manuell starten": {
|
||||||
|
"main": [[{ "node": "Seneca fragen", "type": "main", "index": 0 }]]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {},
|
||||||
|
"active": false
|
||||||
|
}
|
||||||
49
docker-compose.yml
Normal file
49
docker-compose.yml
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Roman Station — KI-Motor (Ollama + Open WebUI + n8n)
|
||||||
|
# Versionen gepinnt am 2026-06-10. Updates: Tags erhöhen, dann `docker compose pull && docker compose up -d`.
|
||||||
|
|
||||||
|
services:
|
||||||
|
ollama:
|
||||||
|
image: ollama/ollama:0.30.7
|
||||||
|
container_name: roman-ollama
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ollama-data:/root/.ollama
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:11434:11434"
|
||||||
|
|
||||||
|
open-webui:
|
||||||
|
image: ghcr.io/open-webui/open-webui:v0.9.6
|
||||||
|
container_name: roman-webui
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- ollama
|
||||||
|
environment:
|
||||||
|
OLLAMA_BASE_URL: http://ollama:11434
|
||||||
|
# Lokale Einzelplatz-Station: kein Login-Zwang für Anfänger
|
||||||
|
WEBUI_AUTH: "False"
|
||||||
|
WEBUI_NAME: Roman Station
|
||||||
|
DEFAULT_LOCALE: de
|
||||||
|
volumes:
|
||||||
|
- webui-data:/app/backend/data
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:${WEBUI_PORT:-3000}:8080"
|
||||||
|
|
||||||
|
n8n:
|
||||||
|
image: docker.n8n.io/n8nio/n8n:2.25.7
|
||||||
|
container_name: roman-n8n
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
N8N_SECURE_COOKIE: "false"
|
||||||
|
GENERIC_TIMEZONE: ${TIMEZONE:-Europe/Berlin}
|
||||||
|
N8N_DIAGNOSTICS_ENABLED: "false"
|
||||||
|
OLLAMA_HOST: http://ollama:11434
|
||||||
|
volumes:
|
||||||
|
- n8n-data:/home/node/.n8n
|
||||||
|
- ./agents/n8n:/workflows:ro
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:${N8N_PORT:-5678}:5678"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
ollama-data:
|
||||||
|
webui-data:
|
||||||
|
n8n-data:
|
||||||
66
install.sh
Executable file
66
install.sh
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Roman Station — Installer für Zorin OS
|
||||||
|
# Eine lokale KI-Station mit römischen Beratern, läuft komplett auf deinem Rechner.
|
||||||
|
#
|
||||||
|
# Installation (eine Zeile, als normaler Benutzer):
|
||||||
|
# curl -sL https://poised-mayfly.pikapod.net/cemsadmin/roman-station/raw/branch/main/install.sh | bash
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_URL="${ROMAN_REPO_URL:-https://poised-mayfly.pikapod.net/cemsadmin/roman-station.git}"
|
||||||
|
INSTALL_DIR="${ROMAN_STATION_DIR:-$HOME/.roman-station}"
|
||||||
|
LOG_FILE="$HOME/roman-station-install.log"
|
||||||
|
|
||||||
|
log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*" | tee -a "$LOG_FILE"; }
|
||||||
|
fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*" | tee -a "$LOG_FILE"; exit 1; }
|
||||||
|
|
||||||
|
[ "$(id -u)" -eq 0 ] && fail "Bitte nicht als root starten — das Script nutzt sudo selbst, wo nötig."
|
||||||
|
|
||||||
|
# --- Bootstrap: bei `curl | bash` liegt noch kein Repo vor → erst klonen, dann von dort weiterlaufen
|
||||||
|
SCRIPT_SOURCE="${BASH_SOURCE[0]:-}"
|
||||||
|
SCRIPT_DIR=""
|
||||||
|
if [ -n "$SCRIPT_SOURCE" ]; then
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)"
|
||||||
|
fi
|
||||||
|
if [ -z "$SCRIPT_DIR" ] || [ ! -f "$SCRIPT_DIR/scripts/preflight.sh" ]; then
|
||||||
|
log "Hole Roman Station nach $INSTALL_DIR ..."
|
||||||
|
if ! command -v git >/dev/null 2>&1; then
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y git
|
||||||
|
fi
|
||||||
|
if [ -d "$INSTALL_DIR/.git" ]; then
|
||||||
|
git -C "$INSTALL_DIR" pull --ff-only
|
||||||
|
else
|
||||||
|
git clone --depth 1 "$REPO_URL" "$INSTALL_DIR"
|
||||||
|
fi
|
||||||
|
exec bash "$INSTALL_DIR/install.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
log "Starte Installation aus $SCRIPT_DIR (Protokoll: $LOG_FILE)"
|
||||||
|
|
||||||
|
[ -f .env ] || cp .env.example .env
|
||||||
|
|
||||||
|
bash scripts/preflight.sh
|
||||||
|
bash scripts/install-docker.sh
|
||||||
|
|
||||||
|
log "Starte den KI-Motor (Docker Compose) ..."
|
||||||
|
sudo docker compose up -d
|
||||||
|
|
||||||
|
bash scripts/setup-agents.sh
|
||||||
|
bash scripts/apply-theme.sh
|
||||||
|
bash scripts/create-shortcuts.sh
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. ./.env
|
||||||
|
|
||||||
|
log "──────────────────────────────────────────────"
|
||||||
|
log "AVE! Deine Roman Station steht."
|
||||||
|
log ""
|
||||||
|
log " Forum (Chat): http://localhost:${WEBUI_PORT:-3000}"
|
||||||
|
log " Werkstatt (n8n): http://localhost:${N8N_PORT:-5678}"
|
||||||
|
log ""
|
||||||
|
log "Deine Berater: seneca (Mentor), cicero (Texter), marcus (Stratege)"
|
||||||
|
log "Auf dem Schreibtisch liegen Verknüpfungen bereit."
|
||||||
|
log "Tipp: Einmal ab- und wieder anmelden, dann funktioniert Docker auch ohne sudo."
|
||||||
33
scripts/apply-theme.sh
Executable file
33
scripts/apply-theme.sh
Executable file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Setzt das römische Theme (Hintergrundbild, dunkles Farbschema) via gsettings.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*"; }
|
||||||
|
warn() { printf '\033[1;33m[HINWEIS]\033[0m %s\n' "$*"; }
|
||||||
|
|
||||||
|
if ! command -v gsettings >/dev/null 2>&1 || { [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; }; then
|
||||||
|
warn "Keine grafische Sitzung erkannt — Theme wird übersprungen."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
target="$HOME/.local/share/backgrounds/roman-station"
|
||||||
|
mkdir -p "$target"
|
||||||
|
cp -f theme/wallpapers/* "$target"/ 2>/dev/null || true
|
||||||
|
|
||||||
|
wallpaper=""
|
||||||
|
for ext in png jpg jpeg svg; do
|
||||||
|
candidate="$(find "$target" -maxdepth 1 -name "*.$ext" | sort | head -1)"
|
||||||
|
if [ -n "$candidate" ]; then wallpaper="$candidate"; break; fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$wallpaper" ]; then
|
||||||
|
gsettings set org.gnome.desktop.background picture-uri "file://$wallpaper"
|
||||||
|
gsettings set org.gnome.desktop.background picture-uri-dark "file://$wallpaper" 2>/dev/null || true
|
||||||
|
gsettings set org.gnome.desktop.background picture-options 'zoom'
|
||||||
|
log "Hintergrundbild gesetzt: $(basename "$wallpaper")"
|
||||||
|
else
|
||||||
|
warn "Kein Hintergrundbild gefunden — übersprungen."
|
||||||
|
fi
|
||||||
|
|
||||||
|
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' 2>/dev/null || true
|
||||||
|
log "Dunkles Farbschema aktiviert."
|
||||||
64
scripts/create-shortcuts.sh
Executable file
64
scripts/create-shortcuts.sh
Executable file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Legt Startmenü- und Desktop-Verknüpfungen für Forum (Chat) und Werkstatt (n8n) an.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*"; }
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. ./.env
|
||||||
|
webui_port="${WEBUI_PORT:-3000}"
|
||||||
|
n8n_port="${N8N_PORT:-5678}"
|
||||||
|
|
||||||
|
apps_dir="$HOME/.local/share/applications"
|
||||||
|
icon_dir="$HOME/.local/share/icons/hicolor/scalable/apps"
|
||||||
|
mkdir -p "$apps_dir" "$icon_dir"
|
||||||
|
|
||||||
|
if [ -f theme/icon.svg ]; then
|
||||||
|
cp -f theme/icon.svg "$icon_dir/roman-station.svg"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Chromium-Familie kann ein sauberes App-Fenster öffnen, sonst Standardbrowser
|
||||||
|
launcher_for() {
|
||||||
|
url="$1"
|
||||||
|
for b in brave-browser google-chrome chromium chromium-browser; do
|
||||||
|
if command -v "$b" >/dev/null 2>&1; then
|
||||||
|
printf '%s --app=%s' "$b" "$url"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
printf 'xdg-open %s' "$url"
|
||||||
|
}
|
||||||
|
|
||||||
|
make_entry() {
|
||||||
|
file="$1"; name="$2"; comment="$3"; url="$4"
|
||||||
|
cat > "$file" <<EOF
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=$name
|
||||||
|
Comment=$comment
|
||||||
|
Exec=$(launcher_for "$url")
|
||||||
|
Icon=roman-station
|
||||||
|
Terminal=false
|
||||||
|
Categories=Network;Utility;
|
||||||
|
EOF
|
||||||
|
chmod +x "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
make_entry "$apps_dir/roman-forum.desktop" "Roman Station — Forum" "Sprich mit deinen römischen Beratern" "http://localhost:$webui_port"
|
||||||
|
make_entry "$apps_dir/roman-werkstatt.desktop" "Roman Station — Werkstatt" "KI-Workflows bauen (n8n)" "http://localhost:$n8n_port"
|
||||||
|
|
||||||
|
if command -v xdg-user-dir >/dev/null 2>&1; then
|
||||||
|
desktop_dir="$(xdg-user-dir DESKTOP)"
|
||||||
|
else
|
||||||
|
desktop_dir="$HOME/Desktop"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$desktop_dir" ]; then
|
||||||
|
cp -f "$apps_dir/roman-forum.desktop" "$apps_dir/roman-werkstatt.desktop" "$desktop_dir/"
|
||||||
|
chmod +x "$desktop_dir/roman-forum.desktop" "$desktop_dir/roman-werkstatt.desktop"
|
||||||
|
# GNOME verlangt sonst einen Rechtsklick → "Starten erlauben"
|
||||||
|
gio set "$desktop_dir/roman-forum.desktop" metadata::trusted true 2>/dev/null || true
|
||||||
|
gio set "$desktop_dir/roman-werkstatt.desktop" metadata::trusted true 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Verknüpfungen angelegt (Startmenü + Schreibtisch)."
|
||||||
32
scripts/install-docker.sh
Executable file
32
scripts/install-docker.sh
Executable file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Installiert Docker Engine + Compose-Plugin aus dem offiziellen Docker-Repository.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*"; }
|
||||||
|
fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*"; exit 1; }
|
||||||
|
|
||||||
|
if command -v docker >/dev/null 2>&1 && sudo docker compose version >/dev/null 2>&1; then
|
||||||
|
log "Docker ist bereits installiert — überspringe."
|
||||||
|
else
|
||||||
|
log "Installiere Docker (offizielles Repository) ..."
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y ca-certificates curl gnupg
|
||||||
|
sudo install -m 0755 -d /etc/apt/keyrings
|
||||||
|
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
|
||||||
|
# Zorin basiert auf Ubuntu LTS — UBUNTU_CODENAME liefert die passende Paketquelle
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. /etc/os-release
|
||||||
|
codename="${UBUNTU_CODENAME:-${VERSION_CODENAME:-}}"
|
||||||
|
[ -n "$codename" ] || fail "Ubuntu-Codename nicht erkennbar — /etc/os-release prüfen."
|
||||||
|
|
||||||
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $codename stable" \
|
||||||
|
| sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo systemctl enable --now docker
|
||||||
|
sudo usermod -aG docker "$USER"
|
||||||
|
log "Docker bereit. (Ohne sudo nutzbar nach erneutem Anmelden.)"
|
||||||
35
scripts/preflight.sh
Executable file
35
scripts/preflight.sh
Executable file
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Prüft, ob der Rechner für die Roman Station geeignet ist.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
warn() { printf '\033[1;33m[HINWEIS]\033[0m %s\n' "$*"; }
|
||||||
|
fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*"; exit 1; }
|
||||||
|
|
||||||
|
# Zorin OS?
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. /etc/os-release
|
||||||
|
if [ "${ID:-}" != "zorin" ]; then
|
||||||
|
if [ "${ROMAN_SKIP_OS_CHECK:-0}" = "1" ]; then
|
||||||
|
warn "Kein Zorin OS erkannt (${PRETTY_NAME:-unbekannt}) — Prüfung per ROMAN_SKIP_OS_CHECK übersprungen."
|
||||||
|
else
|
||||||
|
fail "Dieses Script ist für Zorin OS gebaut (gefunden: ${PRETTY_NAME:-unbekannt}). Erzwingen mit: ROMAN_SKIP_OS_CHECK=1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Arbeitsspeicher
|
||||||
|
ram_gb="$(awk '/MemTotal/ {printf "%d", $2/1024/1024}' /proc/meminfo)"
|
||||||
|
[ "$ram_gb" -ge 8 ] || fail "Mindestens 8 GB RAM nötig, gefunden: ${ram_gb} GB."
|
||||||
|
[ "$ram_gb" -ge 16 ] || warn "Nur ${ram_gb} GB RAM — die Station läuft, aber bleib bei kleinen Modellen (3–4B)."
|
||||||
|
|
||||||
|
# Freier Speicherplatz
|
||||||
|
free_gb="$(df -BG --output=avail "$HOME" | tail -1 | tr -dc '0-9')"
|
||||||
|
[ "$free_gb" -ge 25 ] || fail "Mindestens 25 GB freier Speicher nötig, gefunden: ${free_gb} GB."
|
||||||
|
|
||||||
|
# Internet
|
||||||
|
curl -fsS --max-time 10 https://hub.docker.com >/dev/null 2>&1 \
|
||||||
|
|| fail "Keine Internetverbindung — wird für den Download der Container gebraucht."
|
||||||
|
|
||||||
|
# sudo-Rechte
|
||||||
|
sudo -v || fail "sudo-Rechte werden für die Installation benötigt."
|
||||||
|
|
||||||
|
printf '\033[1;32m[OK]\033[0m Systemprüfung bestanden (%s GB RAM, %s GB frei).\n' "$ram_gb" "$free_gb"
|
||||||
46
scripts/setup-agents.sh
Executable file
46
scripts/setup-agents.sh
Executable file
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Lädt das Standardmodell und erstellt die römischen Berater (Ollama) sowie Beispiel-Workflows (n8n).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*"; }
|
||||||
|
warn() { printf '\033[1;33m[HINWEIS]\033[0m %s\n' "$*"; }
|
||||||
|
fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*"; exit 1; }
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. ./.env
|
||||||
|
model="${DEFAULT_MODEL:-gemma3:4b}"
|
||||||
|
|
||||||
|
dc() { sudo docker compose "$@"; }
|
||||||
|
|
||||||
|
log "Warte auf Ollama ..."
|
||||||
|
ready=0
|
||||||
|
for _ in $(seq 1 60); do
|
||||||
|
if dc exec -T ollama ollama list >/dev/null 2>&1; then ready=1; break; fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
[ "$ready" = "1" ] || fail "Ollama wurde nicht rechtzeitig bereit — 'sudo docker compose logs ollama' zeigt Details."
|
||||||
|
|
||||||
|
log "Lade Sprachmodell $model (beim ersten Mal dauert das einige Minuten) ..."
|
||||||
|
dc exec -T ollama ollama pull "$model"
|
||||||
|
|
||||||
|
for mf in agents/modelfiles/*.Modelfile; do
|
||||||
|
[ -e "$mf" ] || continue
|
||||||
|
name="$(basename "$mf" .Modelfile | tr '[:upper:]' '[:lower:]')"
|
||||||
|
log "Erstelle Berater: $name"
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
sed "s|{{MODEL}}|$model|g" "$mf" > "$tmp"
|
||||||
|
dc cp "$tmp" ollama:/tmp/roman.Modelfile
|
||||||
|
dc exec -T ollama ollama create "$name" -f /tmp/roman.Modelfile
|
||||||
|
rm -f "$tmp"
|
||||||
|
done
|
||||||
|
|
||||||
|
for wf in agents/n8n/*.json; do
|
||||||
|
[ -e "$wf" ] || continue
|
||||||
|
if dc exec -T n8n n8n import:workflow --input="/workflows/$(basename "$wf")" >/dev/null 2>&1; then
|
||||||
|
log "n8n-Workflow importiert: $(basename "$wf")"
|
||||||
|
else
|
||||||
|
warn "n8n-Workflow $(basename "$wf") konnte nicht automatisch importiert werden — in n8n unter 'Import from File' nachholbar."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log "Berater stehen bereit: seneca, cicero, marcus"
|
||||||
24
theme/icon.svg
Normal file
24
theme/icon.svg
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="gold" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stop-color="#e8c46a"/>
|
||||||
|
<stop offset="100%" stop-color="#a8842f"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<circle cx="128" cy="128" r="120" fill="#14100b"/>
|
||||||
|
<circle cx="128" cy="128" r="116" fill="none" stroke="url(#gold)" stroke-width="6"/>
|
||||||
|
<g stroke="url(#gold)" stroke-width="5" fill="none" stroke-linecap="round">
|
||||||
|
<path d="M 58 170 Q 70 110 128 86"/>
|
||||||
|
<path d="M 198 170 Q 186 110 128 86"/>
|
||||||
|
</g>
|
||||||
|
<g fill="url(#gold)">
|
||||||
|
<ellipse cx="66" cy="148" rx="13" ry="5" transform="rotate(-62 66 148)"/>
|
||||||
|
<ellipse cx="78" cy="122" rx="13" ry="5" transform="rotate(-48 78 122)"/>
|
||||||
|
<ellipse cx="98" cy="102" rx="13" ry="5" transform="rotate(-30 98 102)"/>
|
||||||
|
<ellipse cx="190" cy="148" rx="13" ry="5" transform="rotate(62 190 148)"/>
|
||||||
|
<ellipse cx="178" cy="122" rx="13" ry="5" transform="rotate(48 178 122)"/>
|
||||||
|
<ellipse cx="158" cy="102" rx="13" ry="5" transform="rotate(30 158 102)"/>
|
||||||
|
</g>
|
||||||
|
<text x="128" y="158" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif"
|
||||||
|
font-size="52" letter-spacing="4" fill="url(#gold)">SPQR</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
53
theme/wallpapers/roman-station.svg
Normal file
53
theme/wallpapers/roman-station.svg
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="2560" height="1440" viewBox="0 0 2560 1440">
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="bg" cx="50%" cy="42%" r="80%">
|
||||||
|
<stop offset="0%" stop-color="#231a12"/>
|
||||||
|
<stop offset="55%" stop-color="#14100b"/>
|
||||||
|
<stop offset="100%" stop-color="#0a0806"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="gold" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stop-color="#e8c46a"/>
|
||||||
|
<stop offset="100%" stop-color="#a8842f"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<rect width="2560" height="1440" fill="url(#bg)"/>
|
||||||
|
|
||||||
|
<!-- angedeutete Säulen links und rechts -->
|
||||||
|
<g fill="#1d160e" opacity="0.55">
|
||||||
|
<rect x="140" y="0" width="90" height="1440"/>
|
||||||
|
<rect x="120" y="0" width="130" height="36"/>
|
||||||
|
<rect x="120" y="1404" width="130" height="36"/>
|
||||||
|
<rect x="2330" y="0" width="90" height="1440"/>
|
||||||
|
<rect x="2310" y="0" width="130" height="36"/>
|
||||||
|
<rect x="2310" y="1404" width="130" height="36"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Lorbeerzweige -->
|
||||||
|
<g stroke="url(#gold)" stroke-width="7" fill="none" stroke-linecap="round" opacity="0.9">
|
||||||
|
<path d="M 1000 760 Q 1090 620 1280 580"/>
|
||||||
|
<path d="M 1560 760 Q 1470 620 1280 580"/>
|
||||||
|
</g>
|
||||||
|
<g fill="url(#gold)" opacity="0.85">
|
||||||
|
<ellipse cx="1030" cy="722" rx="34" ry="13" transform="rotate(-52 1030 722)"/>
|
||||||
|
<ellipse cx="1080" cy="668" rx="34" ry="13" transform="rotate(-44 1080 668)"/>
|
||||||
|
<ellipse cx="1140" cy="626" rx="34" ry="13" transform="rotate(-32 1140 626)"/>
|
||||||
|
<ellipse cx="1206" cy="598" rx="34" ry="13" transform="rotate(-20 1206 598)"/>
|
||||||
|
<ellipse cx="1530" cy="722" rx="34" ry="13" transform="rotate(52 1530 722)"/>
|
||||||
|
<ellipse cx="1480" cy="668" rx="34" ry="13" transform="rotate(44 1480 668)"/>
|
||||||
|
<ellipse cx="1420" cy="626" rx="34" ry="13" transform="rotate(32 1420 626)"/>
|
||||||
|
<ellipse cx="1354" cy="598" rx="34" ry="13" transform="rotate(20 1354 598)"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Schriftzug -->
|
||||||
|
<text x="1280" y="700" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif"
|
||||||
|
font-size="96" letter-spacing="26" fill="url(#gold)">ROMAN STATION</text>
|
||||||
|
<text x="1280" y="780" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif"
|
||||||
|
font-size="40" letter-spacing="18" fill="#8a6d35">S P Q R</text>
|
||||||
|
|
||||||
|
<!-- Zierlinien -->
|
||||||
|
<g stroke="#8a6d35" stroke-width="3" opacity="0.7">
|
||||||
|
<line x1="880" y1="830" x2="1680" y2="830"/>
|
||||||
|
<line x1="1040" y1="848" x2="1520" y2="848"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
Loading…
Reference in a new issue