Web-App für Asset-Import, Patchpanel-Audit, Port-Mapping und Export.
Die App besteht aus zwei Containern und einer SQLite-Datenbank:
frontend: React/Vite-Build, ausgeliefert über Nginxbackend: Express-API mit Auth, Import, Audit, Historie, Export und Admin-FunktionenSQLite: persistente Datenbankdatei für Benutzer, Panels, Mappings, Exporte und Historie
Der Browser spricht nur mit dem Frontend. Das Frontend proxyt /api intern zum Backend. Das Backend schreibt die fachlichen Daten in die SQLite-Datei.
Stand jetzt werden die fachlichen Daten nicht im Container-Dateisystem gehalten, sondern unter /app/data gespeichert. In Docker Compose ist dieses Verzeichnis als Volume eingebunden.
Wichtig dabei:
- Die eigentliche Datenbank liegt unter
/app/data/patchpanel.db - SQLite-WAL- und SHM-Dateien liegen ebenfalls im selben Volume
- Das Backend erzeugt keine zusätzliche Upload- oder Export-Ablage auf Platte
- Das Frontend ist statisch und hat keine fachlichen Persistenzdaten im Container
Das heißt: Die relevanten App-Daten liegen im Daten-Volume, nicht im Backend-Container selbst.
Neu ist jetzt zusätzlich:
- Der Volume-Name ist per ENV steuerbar
- Das Volume kann als externes Docker-Volume betrieben werden
- Das Proxy-Netzwerk ist per ENV steuerbar
- Standardmäßig wird ein eigenes Frontend-Netzwerk
patchmatrix-proxyautomatisch angelegt - Browser-Logins werden als HttpOnly-Session-Cookie gehalten statt als Token im Browser-Storage
Das Repository ist so vorbereitet, dass es direkt aus GitHub nutzbar ist:
- lokal mit
npm run dev - als Container-Deployment mit Docker
- als Container-Deployment mit Podman
- als Git-Stack in Portainer
Der Admin-Account ist fest mit dem Benutzernamen Admin im Backend verankert. Beim Start wird dieser User immer automatisch sichergestellt und mit der PIN aus ADMIN_BOOTSTRAP_PIN synchronisiert. Lokal ist ohne weitere Anpassung 2026 vorgesehen.
| Schicht | Technologie |
|---|---|
| Frontend | React 19, Vite, TypeScript |
| Backend | Node.js, Express, TypeScript |
| Datenbank | SQLite |
| Container | Docker / Podman / Nginx |
- Node.js 18 oder neuer
- npm 9 oder neuer
git clone <REPO_URL>
cd patchpanel-port-mapping
cp .env.example .env
# Optional JWT_SECRET setzen. Lokal ist die Admin-PIN standardmäßig 2026.
npm install
npm run devnpm run dev bleibt unverändert und startet weiterhin Backend und Frontend parallel.
Die Root-.env wird automatisch auch vom Backend eingelesen.
- Frontend:
http://localhost:5173 - Backend:
http://localhost:3001 - Health:
http://localhost:3001/api/health
Für lokale Tests reicht standardmäßig bereits:
ADMIN_BOOTSTRAP_PIN=2026Wenn du lokal eine andere PIN willst:
ADMIN_BOOTSTRAP_PIN=4826Empfohlen zusaetzlich:
JWT_SECRET=bitte-einen-langen-zufallswert-setzenWenn JWT_SECRET lokal leer bleibt, erzeugt das Backend fuer diese eine Laufzeit ein zufaelliges Development-Secret. In Produktion muss JWT_SECRET gesetzt sein.
- Benutzer:
Admin - PIN: Wert aus
ADMIN_BOOTSTRAP_PIN(genau 4 Ziffern) - Lokal ohne
.env-Anpassung:2026 - Der User
Adminwird bei jedem Backend-Start automatisch als aktiver Admin sichergestellt. - Eine Änderung von
ADMIN_BOOTSTRAP_PINwird beim nächsten Start direkt auf den UserAdminangewendet.
- Frontend veröffentlicht:
9100 - Backend veröffentlicht: kein Host-Port
- API läuft intern im Compose-Netzwerk und wird vom Frontend-Proxy unter
/apiangesprochen
Das ist absichtlich so, damit in Portainer nur der Frontend-Port sichtbar ist.
app-internal: internes Netzwerk für Frontend ↔ Backendproxy-network: zusätzliches Netzwerk für Reverse Proxy und containerübergreifende Erreichbarkeit; wird standardmäßig automatisch angelegt und kann optional auf ein bestehendes Reverse-Proxy-Netz umgestellt werden
Frontend und Backend hängen gemeinsam im internen Netzwerk. Zusätzlich treten beide Services auch dem konfigurierbaren Proxy-Netzwerk bei, damit Service-Namen in Portainer- und Nginx-Proxy-Manager-Deployments zuverlässig auflösbar bleiben. Nach außen veröffentlicht wird trotzdem weiterhin nur das Frontend; das Backend erhält keinen Host-Port.
Der Frontend-Nginx proxyt intern direkt auf den Service-Namen backend. In der vorgesehenen Stack-Struktur reicht das aus, solange Frontend und Backend gemeinsam im Compose-Netzwerk neu erstellt bzw. betrieben werden.
patchpanel-datawird nach/app/dataim Backend gemountet- Der tatsächliche Docker-Volume-Name kommt aus
APP_DATA_VOLUME_NAME - Mit
APP_DATA_VOLUME_EXTERNAL=truewird ein bereits existierendes externes Volume genutzt
cp .env.example .env
# ADMIN_BOOTSTRAP_PIN setzen und JWT_SECRET fuer Produktion vergeben
docker compose up --build -d
docker compose psMit den Standardwerten aus .env.example werden Daten-Volume und Frontend-Netzwerk automatisch angelegt. Es ist keine manuelle Vorbereitung von Volumes oder Netzwerken nötig.
Wenn du das Frontend stattdessen an ein bereits existierendes Reverse-Proxy-Netzwerk hängen willst, setze in .env:
PROXY_NETWORK_NAME=nginx-proxy-manager_default
PROXY_NETWORK_EXTERNAL=true- App:
http://localhost:9100
docker compose downcp .env.example .env
# ADMIN_BOOTSTRAP_PIN setzen und JWT_SECRET fuer Produktion vergeben
podman compose up --build -dAuch hier gilt: Mit den Defaultwerten werden Volume und Netzwerk automatisch erstellt.
- App:
http://localhost:9100
Portainer kann das Projekt direkt aus dem GitHub-Repository als Stack deployen.
StacksöffnenAdd stack- Git/Repository-Quelle auswählen
- Repository-URL eintragen
- Compose-Datei auf
docker-compose.ymlsetzen - Diese Environment-Variablen setzen:
JWT_SECRET=<starker-zufallswert>
ADMIN_BOOTSTRAP_PIN=<4-stellige-pin>
FRONTEND_PORT=9100
NODE_ENV=production
APP_DATA_VOLUME_NAME=patchmatrix-dataPortainer bzw. Compose legt das Volume patchmatrix-data und das Netzwerk patchmatrix-proxy dabei selbst an. Danach ist das Frontend über den konfigurierten Port erreichbar.
Wenn dein Nginx Proxy Manager bereits im Netzwerk nginx-proxy-manager_default läuft, dann nutze diese Werte:
JWT_SECRET=<starker-zufallswert>
ADMIN_BOOTSTRAP_PIN=<4-stellige-pin>
NODE_ENV=production
FRONTEND_PORT=9100
APP_DATA_VOLUME_NAME=patchmatrix-data
APP_DATA_VOLUME_EXTERNAL=true
PROXY_NETWORK_NAME=nginx-proxy-manager_default
PROXY_NETWORK_EXTERNAL=trueDann gilt:
- Fachliche Daten bleiben im Volume
patchmatrix-data - Das Frontend tritt dem Netzwerk
nginx-proxy-manager_defaultbei - Das Backend bleibt nur im internen App-Netz
- Bei einer Neuinstallation mit demselben Volume bleiben die Daten erhalten
- Wichtig: In diesem Modus müssen Volume und Netzwerk vor dem Deploy bereits existieren
- Unter
Volumesein Volumepatchmatrix-dataanlegen - Unter
Networksprüfen, dassnginx-proxy-manager_defaultexistiert - Stack mit
APP_DATA_VOLUME_EXTERNAL=trueundPROXY_NETWORK_EXTERNAL=truedeployen
APP_DATA_VOLUME_EXTERNAL=falsesetzen oder ganz weglassenPROXY_NETWORK_EXTERNAL=falsesetzen oder ganz weglassen- Optional
PROXY_NETWORK_NAME=patchmatrix-proxybelassen - Portainer lässt Volume und Netzwerk dann selbst anlegen
Für Option B liegen die Daten weiterhin nicht im Container, sondern in einem Docker-Volume. Es ist dann nur kein vorab separat angelegtes externes Volume.
Wichtig für Portainer:
Das Frontend startet bewusst nur mit einer einfachen Startreihenfolge auf das Backend, aber ohne harte depends_on-Health-Bedingung, damit es in Portainer/Compose nicht im Status created hängen bleibt. Das Backend bereitet sein Daten-Volume beim Start selbst vor, damit SQLite auf Docker-Named-Volumes zuverlässig schreiben kann.
| Variable | Standard | Beschreibung |
|---|---|---|
PORT |
3001 |
Backend-Port für lokalen Direktstart |
DATABASE_PATH |
./data/patchpanel.db |
SQLite-Datei |
JWT_SECRET |
leer in .env.example |
In Produktion Pflicht. Lokal wird ohne Wert ein einmaliges Development-Secret erzeugt |
CORS_ORIGIN |
http://localhost:5173 |
Für direkten Browserzugriff auf die API |
NODE_ENV |
development |
development oder production |
AUTH_COOKIE_NAME |
patchmatrix_auth |
Name des HttpOnly-Session-Cookies |
AUTH_COOKIE_TTL_HOURS |
8 |
Gültigkeit der Browser-Session in Stunden |
ADMIN_BOOTSTRAP_PIN |
2026 |
Lokale Default-PIN. In Produktion auf eine eigene 4-stellige PIN setzen |
FRONTEND_PORT |
9100 |
Veröffentlichter Frontend-Port für Container |
APP_DATA_VOLUME_NAME |
patchmatrix-data |
Docker-Volume-Name für /app/data |
APP_DATA_VOLUME_EXTERNAL |
false |
false legt das Volume automatisch an, true nutzt ein vorab angelegtes externes Volume |
PROXY_NETWORK_NAME |
patchmatrix-proxy |
Name des zusätzlichen Frontend-Netzwerks |
PROXY_NETWORK_EXTERNAL |
false |
false legt das Netzwerk automatisch an, true nutzt ein bereits existierendes Netzwerk |
npm run dev
npm run build
npm run verify
npm test
npm run test:frontendbackend/ Express + TypeScript + SQLite
frontend/ React + Vite + TypeScript
docker/ Dockerfiles + Nginx-Konfiguration
docker-compose.yml Docker/Podman/Portainer Stack
.env.example ENV-Vorlage
.dockerignore schlanker Build-Kontext