CallMeTechie
EN Anmelden
Home Produkte Blog Über mich Kontakt

VPN Peers & Clients

v1.x · Updated vor 1 Monat

Überblick

Peers lassen sich auf zwei Arten organisieren: Tags (frei wählbare, many-to-many-Labels) und Peer-Gruppen (strukturierte one-to-many-Zuordnung). Beide Systeme teilen sich die Settings-Seite, haben aber unterschiedliche Datenmodelle und Lebenszyklen.

Tags waren historisch reine CSV-Strings in peers.tags — der Admin hat ein Komma-separiertes Feld bearbeitet, das war alles. Mit v1.48 kam die Registry-Tabelle tags dazu, damit Tag-Namen zentral verwaltbar sind: neu anlegen, umbenennen, löschen (inklusive Strip aus allen Peer-CSVs), Usage-Counts in der Admin-UI. Das Hybrid-Modell lebt weiter: Die CSV pro Peer ist weiterhin die Quelle für die Zuordnung, die Registry ist die zentrale Liste.

Peer-Gruppen sind das jüngere, einfachere System: Eine Tabelle, ein Foreign-Key in peers, Display-Farbe, Beschreibung. Gruppen sind für dauerhafte Rollen gedacht (z.B. "Admin", "Familie", "Mobil"), Tags für ad-hoc Labels (z.B. "Desktop", "nas-stack", "Test").

Tags

Datenmodell

-- Registry (ab Migration 39)
CREATE TABLE tags (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL UNIQUE,
  created_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX idx_tags_name ON tags(name);

-- Peer-seitig (ab Migration 10)
ALTER TABLE peers ADD COLUMN tags TEXT DEFAULT '';
-- CSV-Form: "nas, desktop, prod"

Die Registry speichert Tag-Namen im originalen Case, wie der Admin sie zuerst eingegeben hat. Uniqueness gegen bestehende Registry-Einträge läuft case-insensitive über COLLATE NOCASE. Sprich: "NAS" und "nas" landen in einer einzigen Registry-Zeile mit dem Original-Case "NAS".

Warum Hybrid statt reine M:N-Tabelle?

Eine klassische peer_tags(peer_id, tag_id)-Tabelle wäre sauberer, hätte aber bedeutet, die vorhandene UI, die Imports, die Backup-Exports und alle API-Clients neu zu schreiben. Statt Migration-Zwang hält die Registry einen eigenen Lebenszyklus und der Peer-CSV bleibt unangetastet:

Eigenschaft CSV Registry
Zuordnung Peer↔Tag Ja, pro-Peer Nein, nur zentrale Liste
Reine Orphans (Tag ohne Peer) Nein Ja
Umbenennen Würde viele Peers schreiben Einfach (eine Registry-Zeile) — aber nicht implementiert
Delete-Propagation Strip aus allen Peer-CSVs
Auto-Registration beim Peer-Save Ja (ensureRegistered)

Tag-Name-Validierung

src/services/tags.js:validateName:

  • Max 64 Zeichen.
  • Keine , (CSV-Parser würde tokenisieren), keine < > " (HTML-Safety), keine \n \r \t (Newline-Injection).

Das Feld wird vor Registry-INSERT und vor Peer-CSV-Write geprüft.

list() — Merge-View

Die Admin-UI zeigt eine zusammengeführte Liste: alle Registry-Einträge UND alle tatsächlich vergebenen Tags, mit einem registered-Flag und dem peer_count:

[
  {id: 7,    name: "NAS",     peer_count: 3, registered: true },
  {id: null, name: "legacy",  peer_count: 1, registered: false },
  {id: 12,   name: "pool",    peer_count: 0, registered: true }
]
  • id=null, registered:false — Tag taucht auf Peer-CSVs auf, ist aber nicht in der Registry. Die UI kann anbieten, ihn zu registrieren.
  • peer_count=0, registered:true — Orphan-Tag. Admin kann löschen ohne Peers zu betreffen.

Sortierung: localeCompare mit sensitivity:'base' — case-insensitive, aber Locale-aware.

Auto-Registration

Bei jedem peers.create und peers.update ruft der Peer-Service tags.ensureRegistered(data.tags) auf. Die Funktion:

  • Akzeptiert CSV-String oder Array.
  • Filtert jede Token gegen validateName-Regeln; invalide Tokens werden stumm übersprungen (ein kaputtes Token blockiert nicht das Peer-Save).
  • INSERT OR IGNORE — idempotent.
  • Läuft in einer Transaktion.

Ziel: Ein Admin, der "NAS, prod" in die Peer-Form tippt, sieht beide Tags sofort in der Registry-View; kein extra Setup-Schritt.

Startup-Backfill

tags.backfillFromPeers() wird einmalig beim Server-Boot (in server.js) aufgerufen:

  • Scannt peers.tags nach distinct Tokens.
  • Registriert alle, die noch nicht drin sind.

Zweck: Nach dem Upgrade auf die Registry-Version haben Bestandsinstallationen sofort einen gefüllten Registry-Katalog, ohne dass der Admin etwas tun muss.

remove(name) — die interessante Operation

Tag löschen bedeutet: Registry-Eintrag weg UND Token aus allen Peer-CSVs strippen.

DELETE FROM tags WHERE name = ? COLLATE NOCASE;
-- Dann in einer Transaktion:
for each peer with non-empty tags:
  tokens = splitCsv(peer.tags)
  filtered = tokens.filter(t => t.toLowerCase() !== name.toLowerCase())
  if filtered.length < tokens.length:
    UPDATE peers SET tags = filtered.join(', ') WHERE id = peer.id

Zwei Subtilitäten:

  1. Whole-Token-Match — Tag "prod" löschen darf nicht Token "production-backup" treffen. Der CSV wird token-weise verglichen, nicht per SQL LIKE '%prod%'.
  2. Case-insensitive Vergleich, Case-erhaltende Peers — der Peer hat "NAS, Prod", wir löschen "nas". Das Ergebnis ist "Prod" (Case bleibt), "NAS" ist weg.

Activity-Log: tag_deleted mit peers_affected und removed_from_registry.

splitCsv(csv) — der Parser

  • Splittet auf ,, trimmt jeden Token.
  • De-dupliziert case-insensitive, behält aber den ersten gesehenen Case.
  • Leere Tokens werden gedroppt.

So wird "NAS, nas, PROD, ," zu ["NAS", "PROD"].

UI

  • Settings → Tags-Admin-Karte (public/js/tags-admin.js) — neben der Peer-Gruppen-Karte.
  • Rendert die Merge-View aus GET /api/v1/tags.
  • Create-Input + Delete-Button pro Zeile.
  • Peers-Seite: Autocomplete aus Registry, beim Speichern kommt die CSV-Zeile in peers.tags.

Peer-Gruppen

Datenmodell

CREATE TABLE peer_groups (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL UNIQUE,
  color TEXT DEFAULT '#6b7280',
  description TEXT,
  created_at TEXT DEFAULT (datetime('now'))
);

-- FK auf peers (Migration 25)
ALTER TABLE peers ADD COLUMN group_id INTEGER
  REFERENCES peer_groups(id) ON DELETE SET NULL;
CREATE INDEX idx_peers_group_id ON peers(group_id);

Ein Peer hat genau eine Gruppe oder keine (NULL). ON DELETE SET NULL: Wird eine Gruppe gelöscht, bleiben die Peers bestehen, nur ihre group_id wird auf NULL gesetzt — Peers verschwinden nicht zusammen mit der Gruppe.

Farbe

color ist ein Hex-String (#rrggbb), wird in der UI als Farb-Chip neben dem Peer-Namen angezeigt. Default #6b7280 (Grau).

API und UI

  • GET/POST/PATCH/DELETE /api/v1/peer-groups — Standard-CRUD (src/routes/api/peerGroups.js).
  • Settings → Peer-Gruppen-Karte (public/js/peer-groups-admin.js).
  • Peers-Edit-Form hat ein Dropdown "Gruppe" mit allen Gruppen + "— keine —".

Tags vs Gruppen — wann was

Kriterium Tags Gruppen
Kardinalität many-to-many one-to-many
Lebenszyklus kurzlebig, ad-hoc dauerhaft, strukturell
Typische Use-Cases "Desktop", "Test", "backup-2026" "Admin", "Familie", "Mobil"
Delete-Verhalten Wird aus allen Peers entfernt Peers bleiben, group_id=NULL
Farbe Ja
Beschreibung Ja

Ein Peer ist z.B. in Gruppe "Familie", aber getaggt mit "Desktop, nas-backup". Die Gruppe bestimmt Default-Rollen (evtl. Route-Auth-Regeln in Zukunft), die Tags sind für Filter und Anzeige.

3. Peers / Clients verwalten

Die Seite Peers & Clients ist zweigeteilt:

  • Home Gateways — oben, als aufklappbare Karten mit Telemetrie.
  • Peers / Clients — unten, als Tabelle mit Suche, Gruppen-Filter und Tag-Filter. Gateway-Peers werden aus dieser Tabelle herausgefiltert, damit du sie nicht doppelt siehst.

3.1 Neuen Peer anlegen

Öffne den + Hinzufügen-Dialog. Die wichtigsten Felder:

  • Name — eindeutig, 1–63 Zeichen, a-z/0-9/Bindestrich. Wird auch als WireGuard-Peer-Bezeichnung benutzt.
  • Beschreibung — frei, max. 255 Zeichen. Hier landet z.B. das Client-Version-Label vom GateControl-Desktop-Client automatisch.
  • Interner Hostname (Pro) — siehe Domains & DNS. Nur wenn du Internal-DNS nutzt.
  • Gruppe — optional, siehe 3.4 Gruppen.
  • Tags — kommagetrennt; z.B. server, produktion, nas.
  • DNS-Server (Override) — überschreibt den globalen DNS-Eintrag nur für diesen Peer. Bleibt das Feld leer, gilt der globale Wert aus Settings.
  • Ablaufdatum — nach diesem Datum wird der Peer automatisch deaktiviert (Hintergrundjob alle 60 Sekunden).
  • Home Gateway (Checkbox) — macht aus dem Peer einen Gateway (siehe 4. Home-Gateway). Nicht nachträglich änderbar.

Nach Anlegen bekommst du Config, QR-Code und — bei Gateways — zusätzlich die gateway.env als einmalige Anzeige.

3.2 Hostname setzen (Internal DNS)

In der Peer-Tabelle taucht in der Zeile pro Peer eine kleine Badge auf: manuell (vom Admin gesetzt), auto (vom Agent gemeldet) oder veraltet (nach Master-Key-Rotation noch nicht neu gemeldet).

Sticky-Admin-Regel: Wenn du als Admin den Hostname gesetzt hast, überschreibt kein Agent-Heartbeat mehr diesen Wert. Möchtest du wieder automatische Übernahme, lösche den Hostname im Peer-Modal — dann darf der nächste Agent-Heartbeat ihn wieder setzen.

Agent-gesetzte Namen kannst du als Admin jederzeit überschreiben. Das Flag kippt dann auf manuell und bleibt dort.

3.3 Tags

Tags sind freie, nicht-hierarchische Labels. Verwalten kannst du sie unter Settings → Tags. Dort hast du eine Registry — angelegte Tags können so bereits autovervollständigt werden. Ein Tag, das an Peers hängt aber nicht in der Registry steht, zeigt das Badge nicht registriert.

Verwendung:

  • In der Peer-Tabelle kannst du nach Tag filtern (Chip-Leiste oberhalb der Tabelle).
  • Im Peer-Modal trägst du Tags kommagetrennt ein.
  • Beim Speichern werden unbekannte Tags automatisch in die Registry aufgenommen, damit sie künftig in Autocomplete erscheinen.

3.4 Gruppen

Peer-Gruppen sind sichtbare Kategorien mit Namen, Farbe und Beschreibung (z.B. "Büro", "Familie", "Server"). Jeder Peer gehört zu genau einer oder zu keiner Gruppe.

  • Gruppen anlegen und pflegen: Settings → Peer-Gruppen
  • Peer zuweisen: im Peer-Dialog Dropdown Gruppe
  • Filter: auf der Peers-Seite im Dropdown Alle / Nicht gruppiert / <Gruppe>

3.5 Deaktivieren vs. Löschen

  • Deaktivieren (Toggle in der Peer-Zeile, oder Batch-Aktion):
    • Peer bleibt in der DB, Keys bleiben erhalten.
    • WireGuard-Config wird ohne diesen Peer neu geschrieben, die aktive Verbindung wird sofort getrennt.
    • Kann jederzeit wieder aktiviert werden.
  • Löschen (Mülleimer-Icon, mit Bestätigung):
    • Peer wird endgültig entfernt, Keys sind weg.
    • Zu diesem Peer gehörende Routen zeigen einen peer offline-Badge — aktive Verbindungen werden getrennt.
    • Nicht rückgängig zu machen. Wenn du den Peer neu anlegst, bekommt er eine neue IP und neue Keys.

3.6 Ablaufdaten

Im Peer-Dialog unter Ablaufdatum kannst du 1d / 7d / 30d / 90d wählen oder ein eigenes Datum. Nach Ablauf wird der Peer automatisch deaktiviert. In der Tabelle siehst du:

  • Läuft bald ab (gelbes Badge, < 7 Tage)
  • Abgelaufen (rotes Badge, bereits deaktiviert)

3.7 Batch-Aktionen

Oben rechts auf Auswählen, dann Checkboxen in den Zeilen. Unten erscheint eine Aktionsleiste mit Aktivieren, Deaktivieren, Löschen.


Cookie Settings

Wir verwenden Cookies, um Ihre Erfahrung zu verbessern. Essentielle Cookies sind immer aktiv.

Datenschutzerklärung
ESC
↑↓ navigate open esc close