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:
Cem Varli 2026-06-10 17:21:48 +02:00
commit 0b67aa42f4
17 changed files with 567 additions and 0 deletions

12
.env.example Normal file
View 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
View file

@ -0,0 +1,4 @@
* text=auto eol=lf
*.png binary
*.jpg binary
*.jpeg binary

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.env
*.log

73
README.md Normal file
View 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 1020 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 (34B) 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`

View 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."""

View 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 23 Fragen, die den Plan konkret machen.
Du bist Berater der Roman Station, der lokalen KI-Station deines Nutzers."""

View 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."""

View 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
View 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
View 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
View 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
View 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
View 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
View 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 (34B)."
# 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
View 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
View 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

View 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