Skip to content

Native and Kubernetes Deployment

Svwergio_mel edited this page Nov 12, 2026 · 1 revision

Native, Docker, and Kubernetes Deployment

This guide covers persistent background deployment of chat-export-server across macOS, Linux, Windows, Docker / Colima, and Kubernetes (deploy/k8s), while keeping the local-first loopback security model (127.0.0.1:8765).

Browser automation is performed by the Chat Export Chrome extension (WebSocket ceb_ bridge into your logged-in tabs). You do not need Chrome DevTools MCP, Playwright, or an IDE-attached debugger for normal operation.


1. macOS Native Deployment (launchd)

Prerequisites and Build

Install Node.js 22+ via Homebrew and build the server:

brew install node@22
git clone https://github.com/svergio/chat-export-server.git
cd chat-export-server
npm install && npm run build

Configuration (~/.chat-export/.env)

Create the server home directory and .env file:

mkdir -p ~/.chat-export
chmod 700 ~/.chat-export
cat > ~/.chat-export/.env <<'EOF'
CHAT_EXPORT_HOME=/Users/YOUR_USER/.chat-export
CHAT_EXPORT_HOST=127.0.0.1
CHAT_EXPORT_PORT=8765
CHAT_EXPORT_DASHBOARD_ENABLED=true
CHAT_EXPORT_ADMIN_USER=admin
CHAT_EXPORT_ADMIN_PASS=change_this_password
CHAT_EXPORT_MCP_TOKEN=cem_YOUR_GENERATED_TOKEN
CHAT_EXPORT_ALLOW_DESTRUCTIVE=false
EOF
chmod 600 ~/.chat-export/.env

Generate a fresh MCP key with node dist/cli.js key new if you prefer hash-only storage in ~/.chat-export/keys.json.

Persistent LaunchAgent (~/Library/LaunchAgents/io.github.svergio.chat-export-server.plist)

Create the LaunchAgent plist so chat-export-server starts automatically at login and restarts on failure:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>io.github.svergio.chat-export-server</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/homebrew/bin/node</string>
    <string>/ABS/PATH/TO/chat-export-server/dist/cli.js</string>
    <string>start</string>
  </array>
  <key>WorkingDirectory</key>
  <string>/ABS/PATH/TO/chat-export-server</string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>CHAT_EXPORT_HOME</key>
    <string>/Users/YOUR_USER/.chat-export</string>
    <key>CHAT_EXPORT_ENV_FILE</key>
    <string>/Users/YOUR_USER/.chat-export/.env</string>
    <key>PATH</key>
    <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
  </dict>
  <key>RunAtLoad</key>
  <true/>
  <key>KeepAlive</key>
  <true/>
  <key>StandardOutPath</key>
  <string>/Users/YOUR_USER/.chat-export/server.log</string>
  <key>StandardErrorPath</key>
  <string>/Users/YOUR_USER/.chat-export/server.log</string>
</dict>
</plist>

Load and manage the service:

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/io.github.svergio.chat-export-server.plist
launchctl kickstart -k gui/$(id -u)/io.github.svergio.chat-export-server
tail -f ~/.chat-export/server.log
curl -sS http://127.0.0.1:8765/health

2. Linux Native Deployment (systemd --user)

Prerequisites and Build

Install Node.js 22+ (via NodeSource, fnm, or nvm) and build chat-export-server:

git clone https://github.com/svergio/chat-export-server.git ~/chat-export-server
cd ~/chat-export-server
npm install && npm run build
mkdir -p ~/.chat-export ~/.config/systemd/user
cp .env.example ~/.chat-export/.env
chmod 600 ~/.chat-export/.env

User Systemd Unit (~/.config/systemd/user/chat-export-server.service)

[Unit]
Description=Chat Export MCP and Browser Bridge Server
After=network.target

[Service]
Type=simple
WorkingDirectory=%h/chat-export-server
Environment=CHAT_EXPORT_HOME=%h/.chat-export
EnvironmentFile=%h/.chat-export/.env
ExecStart=/usr/bin/env node %h/chat-export-server/dist/cli.js start
Restart=on-failure
RestartSec=3

[Install]
WantedBy=default.target

Enable lingering (so the user service runs even before GUI login) and start the unit:

systemctl --user daemon-reload
systemctl --user enable --now chat-export-server
loginctl enable-linger "$USER"
journalctl --user -u chat-export-server -f

3. Windows Native Deployment

Prerequisites and PowerShell Setup

Install Node.js 22+ via winget or nvm-windows:

winget install OpenJS.NodeJS.LTS
git clone https://github.com/svergio/chat-export-server.git "$env:USERPROFILE\chat-export-server"
Set-Location "$env:USERPROFILE\chat-export-server"
npm install
npm run build

New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.chat-export" | Out-Null
Copy-Item .env.example "$env:USERPROFILE\.chat-export\.env"

Edit $env:USERPROFILE\.chat-export\.env and set CHAT_EXPORT_HOST=127.0.0.1, CHAT_EXPORT_PORT=8765, and CHAT_EXPORT_ADMIN_PASS.

Option A: Windows Task Scheduler (Register-ScheduledTask / schtasks)

Register a background logon task bound to 127.0.0.1:8765:

$NodePath = (Get-Command node).Source
$ServerDir = "$env:USERPROFILE\chat-export-server"
$EnvFile = "$env:USERPROFILE\.chat-export\.env"

$Action = New-ScheduledTaskAction `
  -Execute $NodePath `
  -Argument "`"$ServerDir\dist\cli.js`" start" `
  -WorkingDirectory $ServerDir

$Trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)

[System.Environment]::SetEnvironmentVariable("CHAT_EXPORT_HOME", "$env:USERPROFILE\.chat-export", "User")
[System.Environment]::SetEnvironmentVariable("CHAT_EXPORT_ENV_FILE", $EnvFile, "User")

Register-ScheduledTask -TaskName "ChatExportServer" -Action $Action -Trigger $Trigger -Settings $Settings -Force
Start-ScheduledTask -TaskName "ChatExportServer"

Equivalent schtasks CLI registration:

schtasks /Create /TN "ChatExportServer" /TR "`"C:\Program Files\nodejs\node.exe`" `"$env:USERPROFILE\chat-export-server\dist\cli.js`" start" /SC ONLOGON /RL LIMITED /F
schtasks /Run /TN "ChatExportServer"

Option B: NSSM or PM2

With NSSM (Non-Sucking Service Manager):

nssm install ChatExportServer "C:\Program Files\nodejs\node.exe" "`"$env:USERPROFILE\chat-export-server\dist\cli.js`" start"
nssm set ChatExportServer AppDirectory "$env:USERPROFILE\chat-export-server"
nssm set ChatExportServer AppEnvironmentExtra "CHAT_EXPORT_HOME=$env:USERPROFILE\.chat-export" "CHAT_EXPORT_ENV_FILE=$env:USERPROFILE\.chat-export\.env"
nssm start ChatExportServer

With PM2:

npm install -g pm2
$env:CHAT_EXPORT_HOME="$env:USERPROFILE\.chat-export"
$env:CHAT_EXPORT_ENV_FILE="$env:USERPROFILE\.chat-export\.env"
pm2 start "$env:USERPROFILE\chat-export-server\dist\cli.js" --name chat-export-server -- start
pm2 save

4. Docker and Colima Deployment

Single-Container Stack (chat-export-server/docker-compose.yml)

On macOS, Colima provides a lightweight runtime without Docker Desktop:

colima start
docker context use colima
cd chat-export-server
cp .env.example .env    # set CHAT_EXPORT_ADMIN_PASS and tokens
docker compose build
docker compose up -d
curl -sS http://127.0.0.1:8765/health

The container binds 127.0.0.1:8765:8765 on the host and persists state in the chat-export-data named volume mounted at /data.

Split Nginx + Server Stack

When running the workspace root docker-compose.yml alongside chat-export-dashboard:

  • server runs chat-export-server:local internally on port 8765 with /data mounted on chat-export-data.
  • web runs chat-export-dashboard:local (nginx) published at 127.0.0.1:8765:80, serving dashboard static assets and reverse-proxying /mcp, /ws, /api, and /health to SERVER_UPSTREAM=server:8765.
docker compose build
docker compose up -d
curl -sS http://127.0.0.1:8765/health

5. Kubernetes Deployment (deploy/k8s)

For self-hosted clusters (k3s, kind, Colima Kubernetes, MicroK8s, or cloud clusters), deploy/k8s packages a Kustomize overlay with a StatefulSet/Deployment, PersistentVolumeClaim, Secret, and ClusterIP service.

1. Configure chat-export-secrets

Populate your secrets before applying (never commit plaintext tokens to git):

kubectl create namespace chat-export --dry-run=client -o yaml | kubectl apply -f -

kubectl -n chat-export create secret generic chat-export-secrets \
  --from-literal=CHAT_EXPORT_ADMIN_USER=admin \
  --from-literal=CHAT_EXPORT_ADMIN_PASS='YOUR_STRONG_ADMIN_PASSWORD' \
  --from-literal=CHAT_EXPORT_MCP_TOKEN='cem_YOUR_MCP_TOKEN' \
  --from-literal=CHAT_EXPORT_BROWSER_TOKENS='b-main:ceb_YOUR_BROWSER_TOKEN:Chrome Main' \
  --dry-run=client -o yaml | kubectl apply -f -

2. Apply Kustomize Manifests and PVC Storage

kubectl apply -k deploy/k8s
kubectl -n chat-export rollout status deploy/chat-export-server
kubectl -n chat-export get pvc,pods,svc

The PVC mounts at /data (CHAT_EXPORT_HOME=/data), preserving config.json, keys.json, SQLite cache (chat-export.db), exports/, and audit.log across pod restarts.

3. Loopback Port-Forward (127.0.0.1:8765)

Do not expose chat-export-server on a public unauthenticated Ingress. Instead, forward the service to local loopback on the workstation running Chrome and your MCP client:

kubectl -n chat-export port-forward --address 127.0.0.1 svc/chat-export-server 8765:8765

4. Connect the Local Chrome Extension and MCP Client

With kubectl port-forward active on 127.0.0.1:8765:

  1. Open the Chrome extension popup → Advanced → set host 127.0.0.1, port 8765, and paste the ceb_… token from chat-export-secrets (or enroll via http://127.0.0.1:8765/dashboard/).
  2. Enable Server bridge (ws://127.0.0.1:8765/ws tunnels over the K8s port-forward directly into the pod).
  3. Point any MCP client (Cursor, Claude Desktop, local LLM agent, etc.) to http://127.0.0.1:8765/mcp with Authorization: Bearer cem_….

Related Guides

Clone this wiki locally