palmier 0.9.6 → 0.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -13
- package/dist/agents/agent.d.ts +0 -1
- package/dist/agents/agent.js +0 -1
- package/dist/agents/aider.d.ts +0 -1
- package/dist/agents/aider.js +0 -1
- package/dist/agents/claude.d.ts +0 -1
- package/dist/agents/claude.js +0 -1
- package/dist/agents/cline.d.ts +0 -1
- package/dist/agents/cline.js +0 -1
- package/dist/agents/codex.d.ts +0 -1
- package/dist/agents/codex.js +0 -1
- package/dist/agents/copilot.d.ts +0 -1
- package/dist/agents/copilot.js +0 -1
- package/dist/agents/cursor.d.ts +0 -1
- package/dist/agents/cursor.js +0 -1
- package/dist/agents/deepagents.d.ts +0 -1
- package/dist/agents/deepagents.js +0 -1
- package/dist/agents/droid.d.ts +0 -1
- package/dist/agents/droid.js +0 -1
- package/dist/agents/gemini.d.ts +0 -1
- package/dist/agents/gemini.js +0 -1
- package/dist/agents/goose.d.ts +0 -1
- package/dist/agents/goose.js +0 -1
- package/dist/agents/hermes.d.ts +0 -1
- package/dist/agents/hermes.js +0 -1
- package/dist/agents/kimi.d.ts +0 -1
- package/dist/agents/kimi.js +0 -1
- package/dist/agents/kiro.d.ts +0 -1
- package/dist/agents/kiro.js +0 -1
- package/dist/agents/openclaw.d.ts +0 -1
- package/dist/agents/openclaw.js +0 -1
- package/dist/agents/opencode.d.ts +0 -1
- package/dist/agents/opencode.js +0 -1
- package/dist/agents/qoder.d.ts +0 -1
- package/dist/agents/qoder.js +0 -1
- package/dist/agents/qwen.d.ts +0 -1
- package/dist/agents/qwen.js +0 -1
- package/dist/agents/shared-prompt.d.ts +0 -1
- package/dist/agents/shared-prompt.js +0 -1
- package/dist/client-store.d.ts +0 -1
- package/dist/client-store.js +0 -1
- package/dist/commands/clients.d.ts +0 -1
- package/dist/commands/clients.js +0 -1
- package/dist/commands/info.d.ts +0 -1
- package/dist/commands/info.js +0 -1
- package/dist/commands/init.d.ts +0 -1
- package/dist/commands/init.js +1 -2
- package/dist/commands/pair.d.ts +0 -1
- package/dist/commands/pair.js +0 -1
- package/dist/commands/restart.d.ts +0 -1
- package/dist/commands/restart.js +0 -1
- package/dist/commands/run.d.ts +0 -1
- package/dist/commands/run.js +0 -1
- package/dist/commands/serve.d.ts +0 -1
- package/dist/commands/serve.js +0 -1
- package/dist/commands/uninstall.d.ts +0 -1
- package/dist/commands/uninstall.js +0 -1
- package/dist/config.d.ts +0 -1
- package/dist/config.js +0 -1
- package/dist/event-queues.d.ts +0 -1
- package/dist/event-queues.js +0 -1
- package/dist/events.d.ts +0 -1
- package/dist/events.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/linked-device.d.ts +0 -1
- package/dist/linked-device.js +0 -1
- package/dist/mcp-handler.d.ts +0 -1
- package/dist/mcp-handler.js +0 -1
- package/dist/mcp-tools.d.ts +0 -1
- package/dist/mcp-tools.js +0 -1
- package/dist/nats-client.d.ts +0 -1
- package/dist/nats-client.js +0 -1
- package/dist/network.d.ts +0 -1
- package/dist/network.js +0 -1
- package/dist/notification-store.d.ts +0 -1
- package/dist/notification-store.js +0 -1
- package/dist/pending-requests.d.ts +0 -1
- package/dist/pending-requests.js +0 -1
- package/dist/platform/index.d.ts +0 -1
- package/dist/platform/index.js +0 -1
- package/dist/platform/linux.d.ts +0 -1
- package/dist/platform/linux.js +0 -1
- package/dist/platform/macos.d.ts +0 -1
- package/dist/platform/macos.js +0 -1
- package/dist/platform/platform.d.ts +0 -1
- package/dist/platform/platform.js +0 -1
- package/dist/platform/windows.d.ts +0 -1
- package/dist/platform/windows.js +0 -1
- package/dist/pwa/assets/{index-MLEFUP3r.js → index-DWvRAUiy.js} +31 -31
- package/dist/pwa/assets/{web-B1sKCc7e.js → web-C4iZbqTC.js} +1 -1
- package/dist/pwa/assets/{web-ETD-8ZHd.js → web-CBFqJGX6.js} +1 -1
- package/dist/pwa/assets/{web-B4xEa6WO.js → web-DL4uXOpS.js} +1 -1
- package/dist/pwa/index.html +2 -2
- package/dist/pwa/service-worker.js +1 -1
- package/dist/rpc-handler.d.ts +0 -1
- package/dist/rpc-handler.js +0 -1
- package/dist/sms-store.d.ts +0 -1
- package/dist/sms-store.js +0 -1
- package/dist/spawn-command.d.ts +0 -1
- package/dist/spawn-command.js +0 -1
- package/dist/task.d.ts +0 -1
- package/dist/task.js +0 -1
- package/dist/transports/http-transport.d.ts +0 -1
- package/dist/transports/http-transport.js +0 -1
- package/dist/transports/nats-transport.d.ts +0 -1
- package/dist/transports/nats-transport.js +0 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.js +0 -1
- package/dist/update-checker.d.ts +0 -1
- package/dist/update-checker.js +0 -1
- package/package.json +5 -1
- package/.github/workflows/ci.yml +0 -16
- package/.github/workflows/publish.yml +0 -37
- package/CLAUDE.md +0 -22
- package/palmier-server/.github/workflows/ci.yml +0 -21
- package/palmier-server/.github/workflows/deploy.yml +0 -38
- package/palmier-server/CLAUDE.md +0 -17
- package/palmier-server/PRODUCTION.md +0 -358
- package/palmier-server/README.md +0 -231
- package/palmier-server/nats.conf +0 -19
- package/palmier-server/package.json +0 -15
- package/palmier-server/pnpm-lock.yaml +0 -7639
- package/palmier-server/pnpm-workspace.yaml +0 -3
- package/palmier-server/pwa/index.html +0 -16
- package/palmier-server/pwa/logo/logo_20260421.png +0 -0
- package/palmier-server/pwa/package.json +0 -34
- package/palmier-server/pwa/public/apple-touch-icon.png +0 -0
- package/palmier-server/pwa/public/favicon.ico +0 -0
- package/palmier-server/pwa/public/pwa-192x192.png +0 -0
- package/palmier-server/pwa/public/pwa-512x512.png +0 -0
- package/palmier-server/pwa/src/App.css +0 -3012
- package/palmier-server/pwa/src/App.tsx +0 -59
- package/palmier-server/pwa/src/agentLabels.ts +0 -11
- package/palmier-server/pwa/src/api.ts +0 -67
- package/palmier-server/pwa/src/components/CapabilityToggles.tsx +0 -170
- package/palmier-server/pwa/src/components/ConnectionStatusIcon.tsx +0 -113
- package/palmier-server/pwa/src/components/HostMenu.tsx +0 -429
- package/palmier-server/pwa/src/components/PermissionsDialog.tsx +0 -34
- package/palmier-server/pwa/src/components/PullToRefreshIndicator.tsx +0 -46
- package/palmier-server/pwa/src/components/RunDetailView.tsx +0 -343
- package/palmier-server/pwa/src/components/SessionComposer.tsx +0 -157
- package/palmier-server/pwa/src/components/SessionsView.tsx +0 -326
- package/palmier-server/pwa/src/components/SwipeToDeleteRow.tsx +0 -170
- package/palmier-server/pwa/src/components/TabBar.tsx +0 -40
- package/palmier-server/pwa/src/components/TaskCard.tsx +0 -255
- package/palmier-server/pwa/src/components/TaskForm.tsx +0 -766
- package/palmier-server/pwa/src/components/TasksView.tsx +0 -179
- package/palmier-server/pwa/src/constants.ts +0 -2
- package/palmier-server/pwa/src/contexts/HostConnectionContext.tsx +0 -432
- package/palmier-server/pwa/src/contexts/HostStoreContext.tsx +0 -124
- package/palmier-server/pwa/src/draftGuard.ts +0 -24
- package/palmier-server/pwa/src/formatTime.ts +0 -44
- package/palmier-server/pwa/src/hooks/useBackClose.ts +0 -75
- package/palmier-server/pwa/src/hooks/useMediaQuery.ts +0 -17
- package/palmier-server/pwa/src/hooks/usePullToRefresh.ts +0 -102
- package/palmier-server/pwa/src/hooks/usePushSubscription.ts +0 -77
- package/palmier-server/pwa/src/main.tsx +0 -14
- package/palmier-server/pwa/src/native/Device.ts +0 -49
- package/palmier-server/pwa/src/pages/Dashboard.tsx +0 -542
- package/palmier-server/pwa/src/pages/PairHost.tsx +0 -232
- package/palmier-server/pwa/src/pages/PairSetup.tsx +0 -134
- package/palmier-server/pwa/src/service-worker.ts +0 -142
- package/palmier-server/pwa/src/types.ts +0 -75
- package/palmier-server/pwa/src/vite-env.d.ts +0 -11
- package/palmier-server/pwa/tsconfig.json +0 -21
- package/palmier-server/pwa/tsconfig.node.json +0 -19
- package/palmier-server/pwa/vite.config.ts +0 -47
- package/palmier-server/server/.env.example +0 -20
- package/palmier-server/server/package.json +0 -36
- package/palmier-server/server/src/db.ts +0 -44
- package/palmier-server/server/src/fcm.ts +0 -74
- package/palmier-server/server/src/index.ts +0 -688
- package/palmier-server/server/src/nats-jwt.ts +0 -299
- package/palmier-server/server/src/nats-setup.ts +0 -48
- package/palmier-server/server/src/nats.ts +0 -33
- package/palmier-server/server/src/notify.ts +0 -34
- package/palmier-server/server/src/push.ts +0 -68
- package/palmier-server/server/src/routes/device.ts +0 -224
- package/palmier-server/server/src/routes/fcm.ts +0 -64
- package/palmier-server/server/src/routes/hosts.ts +0 -56
- package/palmier-server/server/src/routes/push.ts +0 -101
- package/palmier-server/server/tsconfig.json +0 -20
- package/palmier-server/spec.md +0 -533
- package/src/agents/agent-instructions.md +0 -28
- package/src/agents/agent.ts +0 -114
- package/src/agents/aider.ts +0 -35
- package/src/agents/claude.ts +0 -39
- package/src/agents/cline.ts +0 -35
- package/src/agents/codex.ts +0 -40
- package/src/agents/copilot.ts +0 -37
- package/src/agents/cursor.ts +0 -36
- package/src/agents/deepagents.ts +0 -36
- package/src/agents/droid.ts +0 -35
- package/src/agents/gemini.ts +0 -43
- package/src/agents/goose.ts +0 -33
- package/src/agents/hermes.ts +0 -36
- package/src/agents/kimi.ts +0 -35
- package/src/agents/kiro.ts +0 -36
- package/src/agents/openclaw.ts +0 -29
- package/src/agents/opencode.ts +0 -36
- package/src/agents/qoder.ts +0 -36
- package/src/agents/qwen.ts +0 -32
- package/src/agents/shared-prompt.ts +0 -30
- package/src/client-store.ts +0 -68
- package/src/commands/clients.ts +0 -29
- package/src/commands/info.ts +0 -29
- package/src/commands/init.ts +0 -165
- package/src/commands/pair.ts +0 -137
- package/src/commands/restart.ts +0 -6
- package/src/commands/run.ts +0 -608
- package/src/commands/serve.ts +0 -211
- package/src/commands/uninstall.ts +0 -9
- package/src/config.ts +0 -36
- package/src/cross-spawn.d.ts +0 -5
- package/src/event-queues.ts +0 -41
- package/src/events.ts +0 -29
- package/src/index.ts +0 -111
- package/src/linked-device.ts +0 -52
- package/src/mcp-handler.ts +0 -200
- package/src/mcp-tools.ts +0 -839
- package/src/nats-client.ts +0 -19
- package/src/network.ts +0 -96
- package/src/notification-store.ts +0 -30
- package/src/pending-requests.ts +0 -73
- package/src/platform/index.ts +0 -20
- package/src/platform/linux.ts +0 -296
- package/src/platform/macos.ts +0 -329
- package/src/platform/platform.ts +0 -31
- package/src/platform/windows.ts +0 -299
- package/src/rpc-handler.ts +0 -691
- package/src/sms-store.ts +0 -28
- package/src/spawn-command.ts +0 -123
- package/src/task.ts +0 -343
- package/src/transports/http-transport.ts +0 -478
- package/src/transports/nats-transport.ts +0 -76
- package/src/types.ts +0 -89
- package/src/update-checker.ts +0 -40
- package/test/agent-instructions.test.ts +0 -209
- package/test/agent-output-parsing.test.ts +0 -74
- package/test/linux-cron.test.ts +0 -41
- package/test/macos-plist.test.ts +0 -112
- package/test/notification-store.test.ts +0 -57
- package/test/pairing.test.ts +0 -35
- package/test/result-state.test.ts +0 -110
- package/test/task-parsing.test.ts +0 -82
- package/test/taskrun-messages.test.ts +0 -224
- package/test/tsconfig.json +0 -9
- package/test/windows-xml.test.ts +0 -89
- package/tsconfig.json +0 -19
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
# Production Deployment Guide
|
|
2
|
-
|
|
3
|
-
Single-instance deployment on Ubuntu 24 with TLS support. NATS and PostgreSQL run in Docker; the Palmier web server runs directly on the host via systemd. Caddy handles TLS termination with automatic Let's Encrypt certificates. Deployments are automated via GitHub Actions — pushing to `main` triggers a CI build, then deploys to the VPS over SSH.
|
|
4
|
-
|
|
5
|
-
## Architecture
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
Internet
|
|
9
|
-
│
|
|
10
|
-
├── palmier.me → Cloudflare → Caddy → redirect to www
|
|
11
|
-
├── www.palmier.me → Cloudflare Pages (landing site, static)
|
|
12
|
-
├── app.palmier.me → Cloudflare → Caddy → localhost:3000 (Palmier server, HTTPS)
|
|
13
|
-
└── nats.palmier.me → Caddy (direct) → localhost:9222 (NATS WebSocket)
|
|
14
|
-
→ port 4222 direct (NATS TCP for hosts)
|
|
15
|
-
|
|
16
|
-
Caddy (ports 80/443, auto TLS)
|
|
17
|
-
|
|
18
|
-
Docker
|
|
19
|
-
├── NATS (ports 4222 TCP public, 9222 WS localhost)
|
|
20
|
-
└── PostgreSQL (port 5432 localhost)
|
|
21
|
-
|
|
22
|
-
systemd
|
|
23
|
-
└── Palmier Server (port 3000 localhost)
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Prerequisites
|
|
27
|
-
|
|
28
|
-
Three DNS records pointing to your server's public IP:
|
|
29
|
-
|
|
30
|
-
- `palmier.me` — root domain (Cloudflare proxied, redirects to `www`)
|
|
31
|
-
- `www.palmier.me` — Landing site (Cloudflare Pages, static)
|
|
32
|
-
- `app.palmier.me` — PWA + API over HTTPS (Cloudflare proxied)
|
|
33
|
-
- `nats.palmier.me` — NATS WebSocket + TCP (DNS only, no Cloudflare proxy)
|
|
34
|
-
|
|
35
|
-
### Install Node.js 24+
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo bash -
|
|
39
|
-
sudo apt install -y nodejs
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Install pnpm
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
sudo npm install -g pnpm
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Install Docker
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
sudo apt install -y docker.io docker-compose-v2
|
|
52
|
-
sudo usermod -aG docker $USER
|
|
53
|
-
# Log out and back in for group to take effect
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Install Caddy
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
sudo apt install -y caddy
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## 1. TLS with Caddy
|
|
63
|
-
|
|
64
|
-
Caddy auto-provisions Let's Encrypt certificates with zero configuration.
|
|
65
|
-
|
|
66
|
-
Create `/etc/caddy/Caddyfile`:
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
palmier.me {
|
|
70
|
-
redir https://www.palmier.me{uri} permanent
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
app.palmier.me {
|
|
74
|
-
reverse_proxy localhost:3000
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
nats.palmier.me {
|
|
78
|
-
@websocket {
|
|
79
|
-
header Connection *Upgrade*
|
|
80
|
-
header Upgrade websocket
|
|
81
|
-
}
|
|
82
|
-
reverse_proxy @websocket localhost:9222
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
This gives you:
|
|
87
|
-
|
|
88
|
-
- `https://app.palmier.me` — PWA + API (auto TLS, Cloudflare CDN for static assets)
|
|
89
|
-
- `wss://nats.palmier.me` — NATS WebSocket (auto TLS, direct to VPS)
|
|
90
|
-
- `https://www.palmier.me` — Landing site (Cloudflare Pages, no VPS involvement)
|
|
91
|
-
|
|
92
|
-
Local mode (loopback) serves the bundled PWA from the palmier host binary on `http://localhost:<port>`, so no separate domain is needed.
|
|
93
|
-
|
|
94
|
-
Caddy auto-provisions Let's Encrypt certs for both domains. Set Cloudflare SSL/TLS mode to **Full (strict)** so Cloudflare verifies the origin cert when connecting to your VPS.
|
|
95
|
-
|
|
96
|
-
No need to configure TLS in NATS itself.
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
sudo systemctl enable --now caddy
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## 2. NATS + PostgreSQL
|
|
103
|
-
|
|
104
|
-
Create a directory for production Docker config:
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
mkdir -p ~/palmier-prod
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### 2a. Generate NATS auth keys and config
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
cd server && pnpm nats-setup
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Follow the on-screen instructions — it outputs the `NATS_ACCOUNT_SEED` env var (for step 6) and the NATS config snippet (for `nats.conf` below). Store the operator seed securely as a backup.
|
|
117
|
-
|
|
118
|
-
### 2b. nats.conf
|
|
119
|
-
|
|
120
|
-
Create `~/palmier-prod/nats.conf`. Paste the auth snippet from step 2a after the websocket block:
|
|
121
|
-
|
|
122
|
-
```
|
|
123
|
-
listen: 0.0.0.0:4222
|
|
124
|
-
|
|
125
|
-
websocket {
|
|
126
|
-
listen: "0.0.0.0:9222"
|
|
127
|
-
no_tls: true
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
# Paste the operator/resolver/resolver_preload output from nats-setup here
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### 2c. docker-compose.yml
|
|
134
|
-
|
|
135
|
-
Create `~/palmier-prod/docker-compose.yml`:
|
|
136
|
-
|
|
137
|
-
```yaml
|
|
138
|
-
services:
|
|
139
|
-
nats:
|
|
140
|
-
image: nats:2-alpine
|
|
141
|
-
restart: unless-stopped
|
|
142
|
-
ports:
|
|
143
|
-
- "4222:4222"
|
|
144
|
-
- "127.0.0.1:9222:9222"
|
|
145
|
-
volumes:
|
|
146
|
-
- ./nats.conf:/etc/nats/nats.conf:ro
|
|
147
|
-
- nats-data:/data
|
|
148
|
-
command: ["-c", "/etc/nats/nats.conf"]
|
|
149
|
-
|
|
150
|
-
postgres:
|
|
151
|
-
image: postgres:17-alpine
|
|
152
|
-
restart: unless-stopped
|
|
153
|
-
ports:
|
|
154
|
-
- "127.0.0.1:5432:5432"
|
|
155
|
-
environment:
|
|
156
|
-
POSTGRES_DB: palmier
|
|
157
|
-
POSTGRES_USER: palmier
|
|
158
|
-
POSTGRES_PASSWORD: <generate-a-strong-password>
|
|
159
|
-
volumes:
|
|
160
|
-
- pgdata:/var/lib/postgresql/data
|
|
161
|
-
|
|
162
|
-
volumes:
|
|
163
|
-
nats-data:
|
|
164
|
-
pgdata:
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Generate a Postgres password:
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
openssl rand -hex 16
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### 2d. Start containers
|
|
174
|
-
|
|
175
|
-
```bash
|
|
176
|
-
cd ~/palmier-prod
|
|
177
|
-
docker compose up -d
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## 3. NATS TCP for Remote Hosts
|
|
181
|
-
|
|
182
|
-
Hosts connect to NATS over TCP (port 4222). Since Caddy only handles HTTP/WebSocket, port 4222 must be open on the firewall for hosts to connect. Each host authenticates with its own JWT (issued during `palmier init`), scoped to only its own NATS subjects.
|
|
183
|
-
|
|
184
|
-
For encrypted host connections, you can add a TLS-terminating TCP proxy (e.g., nginx stream block) in front of port 4222.
|
|
185
|
-
|
|
186
|
-
## 4. Firewall
|
|
187
|
-
|
|
188
|
-
```bash
|
|
189
|
-
sudo ufw allow 22/tcp # SSH (must allow before enabling!)
|
|
190
|
-
sudo ufw allow 80/tcp # Caddy HTTP -> HTTPS redirect
|
|
191
|
-
sudo ufw allow 443/tcp # Caddy HTTPS
|
|
192
|
-
sudo ufw allow 4222/tcp # NATS TCP for hosts
|
|
193
|
-
sudo ufw enable
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
## 5. Clone the Repository
|
|
197
|
-
|
|
198
|
-
Set up VPS git access first (see [VPS Git Access](#vps-git-access)), then clone:
|
|
199
|
-
|
|
200
|
-
```bash
|
|
201
|
-
mkdir -p ~/source
|
|
202
|
-
cd ~/source
|
|
203
|
-
git clone git@github.com:caihongxu/palmier-server.git
|
|
204
|
-
cd palmier-server
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
The first push to `main` will build and start the server automatically via GitHub Actions.
|
|
208
|
-
|
|
209
|
-
## 6. Configure Environment
|
|
210
|
-
|
|
211
|
-
Create `server/.env`:
|
|
212
|
-
|
|
213
|
-
```bash
|
|
214
|
-
PORT=3000
|
|
215
|
-
DATABASE_URL=postgresql://palmier:<your-pg-password>@localhost:5432/palmier
|
|
216
|
-
|
|
217
|
-
NATS_URL=nats://localhost:4222
|
|
218
|
-
NATS_HOST_URL=nats://nats.palmier.me:4222
|
|
219
|
-
NATS_WS_URL=wss://nats.palmier.me
|
|
220
|
-
NATS_ACCOUNT_SEED=<from-nats-setup>
|
|
221
|
-
|
|
222
|
-
VAPID_PUBLIC_KEY=<generated>
|
|
223
|
-
VAPID_PRIVATE_KEY=<generated>
|
|
224
|
-
VAPID_MAILTO=mailto:you@palmier.me
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
Key differences from development:
|
|
228
|
-
|
|
229
|
-
- `NATS_WS_URL` uses `wss://` through Caddy (not direct `ws://`)
|
|
230
|
-
- `NATS_HOST_URL` uses your public domain so remote hosts can reach NATS
|
|
231
|
-
- `NATS_ACCOUNT_SEED` from step 2a (`pnpm nats-setup`)
|
|
232
|
-
|
|
233
|
-
Generate VAPID keys:
|
|
234
|
-
|
|
235
|
-
```bash
|
|
236
|
-
npx web-push generate-vapid-keys
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
## 7. Palmier systemd Service
|
|
240
|
-
|
|
241
|
-
Create `/etc/systemd/system/palmier-server.service`:
|
|
242
|
-
|
|
243
|
-
```ini
|
|
244
|
-
[Unit]
|
|
245
|
-
Description=Palmier Server
|
|
246
|
-
After=network.target docker.service
|
|
247
|
-
|
|
248
|
-
[Service]
|
|
249
|
-
Type=simple
|
|
250
|
-
User=hongxu
|
|
251
|
-
WorkingDirectory=/home/hongxu/source/palmier-server/server
|
|
252
|
-
ExecStart=/usr/bin/node dist/index.js
|
|
253
|
-
Restart=on-failure
|
|
254
|
-
RestartSec=5
|
|
255
|
-
EnvironmentFile=/home/hongxu/source/palmier-server/server/.env
|
|
256
|
-
|
|
257
|
-
[Install]
|
|
258
|
-
WantedBy=multi-user.target
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
Enable and start:
|
|
262
|
-
|
|
263
|
-
```bash
|
|
264
|
-
sudo systemctl daemon-reload
|
|
265
|
-
sudo systemctl enable --now palmier-server
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
## 8. Verify
|
|
269
|
-
|
|
270
|
-
At this point, all services should be running (Docker from step 2, Caddy from step 1, Palmier from step 7). Verify:
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
sudo systemctl status caddy
|
|
274
|
-
sudo systemctl status palmier-server
|
|
275
|
-
cd ~/palmier-prod && docker compose ps
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
- `https://app.palmier.me` — should load the PWA (server mode)
|
|
279
|
-
- `https://app.palmier.me/health` — should return OK
|
|
280
|
-
- Logs: `journalctl -u palmier-server -f`
|
|
281
|
-
- Docker logs: `cd ~/palmier-prod && docker compose logs -f`
|
|
282
|
-
|
|
283
|
-
## CI/CD with GitHub Actions
|
|
284
|
-
|
|
285
|
-
Deployments are automated via two GitHub Actions workflows in `.github/workflows/`:
|
|
286
|
-
|
|
287
|
-
- **`ci.yml`** — runs on every push (except `main`) and pull requests. Builds server + PWA to catch errors early.
|
|
288
|
-
- **`deploy.yml`** — runs on push to `main`. Builds in CI first, then SSHs into the VPS to pull, build, and restart the service.
|
|
289
|
-
|
|
290
|
-
### GitHub Secrets
|
|
291
|
-
|
|
292
|
-
Add these in the repo settings (Settings → Secrets and variables → Actions):
|
|
293
|
-
|
|
294
|
-
| Secret | Description |
|
|
295
|
-
|---|---|
|
|
296
|
-
| `VPS_HOST` | Droplet IP address |
|
|
297
|
-
| `VPS_USER` | SSH username (e.g., `hongxu`) |
|
|
298
|
-
| `SSH_PRIVATE_KEY` | Ed25519 private key for SSH access |
|
|
299
|
-
|
|
300
|
-
### VPS SSH Setup
|
|
301
|
-
|
|
302
|
-
Generate a deploy key pair and add the public key to the VPS:
|
|
303
|
-
|
|
304
|
-
```bash
|
|
305
|
-
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/palmier-deploy -N ""
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
Append the public key to the VPS `~/.ssh/authorized_keys`. Add the private key as the `SSH_PRIVATE_KEY` GitHub secret.
|
|
309
|
-
|
|
310
|
-
### VPS Git Access
|
|
311
|
-
|
|
312
|
-
The VPS needs to pull from the private repo. Add a read-only deploy key:
|
|
313
|
-
|
|
314
|
-
1. Generate a key on the VPS: `ssh-keygen -t ed25519 -C "palmier-server-deploy" -f ~/.ssh/deploy-key -N ""`
|
|
315
|
-
2. Add the public key to the repo (Settings → Deploy keys, read-only)
|
|
316
|
-
3. Configure SSH on the VPS to use the key for GitHub:
|
|
317
|
-
```
|
|
318
|
-
# ~/.ssh/config
|
|
319
|
-
Host github.com
|
|
320
|
-
IdentityFile ~/.ssh/deploy-key
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
### Passwordless sudo for deploy
|
|
324
|
-
|
|
325
|
-
The deploy workflow needs to restart the systemd service. Allow the deploy user to do this without a password:
|
|
326
|
-
|
|
327
|
-
```bash
|
|
328
|
-
sudo visudo -f /etc/sudoers.d/palmier-deploy
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
Add:
|
|
332
|
-
|
|
333
|
-
```
|
|
334
|
-
hongxu ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart palmier-server
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
### Deploying
|
|
338
|
-
|
|
339
|
-
Push to `main` and the deploy workflow handles everything automatically. To deploy manually:
|
|
340
|
-
|
|
341
|
-
```bash
|
|
342
|
-
ssh hongxu@<vps-ip>
|
|
343
|
-
cd ~/source/palmier-server
|
|
344
|
-
git pull
|
|
345
|
-
pnpm install --frozen-lockfile
|
|
346
|
-
cd pwa && pnpm build && cd ..
|
|
347
|
-
cd server && pnpm build && cd ..
|
|
348
|
-
sudo systemctl restart palmier-server
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
## Component Summary
|
|
352
|
-
|
|
353
|
-
| Component | Runtime | Ports |
|
|
354
|
-
|---|---|---|
|
|
355
|
-
| PostgreSQL | Docker | 5432 (localhost only) |
|
|
356
|
-
| NATS | Docker | 4222 (public, for hosts), 9222 (localhost, proxied by Caddy) |
|
|
357
|
-
| Palmier Server | systemd + Node.js | 3000 (localhost only) |
|
|
358
|
-
| Caddy | systemd | 80, 443 (public) |
|
package/palmier-server/README.md
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
# Palmier Server
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-
|
|
5
|
-
Palmier is a platform for remotely scheduling, managing, and executing autonomous AI tasks on host machines via a progressive web app. Uses NATS for real-time communication (pub/sub and request-reply) and push notifications for task progress.
|
|
6
|
-
|
|
7
|
-
## Architecture
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
+-----------+ +----------------+ +------------------+
|
|
11
|
-
| | HTTP | | NATS | |
|
|
12
|
-
| PWA |------>| Web Server |<----->| NATS Server |
|
|
13
|
-
| (React) | | (Express) | | |
|
|
14
|
-
| | | | | |
|
|
15
|
-
+-----------+ +----------------+ +------------------+
|
|
16
|
-
| | ^
|
|
17
|
-
| NATS WebSocket | PostgreSQL | NATS
|
|
18
|
-
+-------------------------------------------> |
|
|
19
|
-
| |
|
|
20
|
-
+----v----+ +-------+-------+
|
|
21
|
-
| | | |
|
|
22
|
-
| DB | | Host(s) |
|
|
23
|
-
| (PG) | | (separate |
|
|
24
|
-
| | | repo) |
|
|
25
|
-
+---------+ +---------------+
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
- **PWA** -- React 19 + Vite progressive web app. Connects to NATS over WebSocket for real-time task updates and to the web server for host registration and push notifications. No user accounts — paired hosts are stored in localStorage.
|
|
29
|
-
- **Web Server** -- Express + TypeScript API server. Handles host registration, push notifications (subscribes to `host-event.>` pub/sub for confirmation and completion events), and push notification relay (for host CLI requests via NATS). In production, also serves the built PWA static files.
|
|
30
|
-
- **NATS Server** -- Message broker. Provides pub/sub messaging and request-reply for real-time communication between all components.
|
|
31
|
-
- **Host** -- Runs on remote Linux/Windows machines to execute tasks via pluggable agent tools (e.g., Claude Code, Codex, Gemini). Each agent implements an `AgentTool` interface that handles command construction. Communicates with the platform over NATS and exposes a local MCP server (`/mcp`, streamable HTTP) with auto-generated REST endpoints for tools and resources. See the [palmier](https://github.com/caihongxu/palmier) repo.
|
|
32
|
-
- **Android App** -- Native Android wrapper (Capacitor) for the PWA. Provides FCM push messaging and native device capabilities — GPS, notifications, SMS, contacts, calendar, alarms, battery, and ringer control. All capabilities work in the background via FCM data messages. See the [palmier-android](https://github.com/caihongxu/palmier-android) repo.
|
|
33
|
-
|
|
34
|
-
## Prerequisites
|
|
35
|
-
|
|
36
|
-
- Node.js 24+
|
|
37
|
-
- pnpm (`npm install -g pnpm`)
|
|
38
|
-
- PostgreSQL 17
|
|
39
|
-
- NATS server with WebSocket enabled
|
|
40
|
-
|
|
41
|
-
## Getting Started
|
|
42
|
-
|
|
43
|
-
1. **Clone the repository**
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
git clone https://github.com/caihongxu/palmier-server.git
|
|
47
|
-
cd palmier-server
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
2. **Install dependencies** (uses pnpm workspaces)
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
pnpm install
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
3. **Configure environment variables**
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
cp server/.env.example server/.env
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Edit `server/.env` and fill in the values (see table below).
|
|
63
|
-
|
|
64
|
-
4. **Generate VAPID keys** for web push notifications
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
npx web-push generate-vapid-keys
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Copy the public and private keys into `server/.env`.
|
|
71
|
-
|
|
72
|
-
5. **Create the PostgreSQL database**
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
createdb palmier
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Update `DATABASE_URL` in `server/.env` with your connection string. Tables are created automatically on server startup.
|
|
79
|
-
|
|
80
|
-
6. **Start the NATS server** with the included config
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
nats-server -c nats.conf
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
The config enables WebSocket on port 9222. See **NATS JWT Auth Setup** below.
|
|
87
|
-
|
|
88
|
-
## Development
|
|
89
|
-
|
|
90
|
-
Development uses two servers: Vite for the PWA (with hot module replacement) and Express for the API. Vite proxies `/api/*` requests to Express so everything appears same-origin.
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
# Terminal 1 -- API server (port 3000)
|
|
94
|
-
cd server
|
|
95
|
-
pnpm dev
|
|
96
|
-
|
|
97
|
-
# Terminal 2 -- PWA dev server (port 5173, proxies /api to :3000)
|
|
98
|
-
cd pwa
|
|
99
|
-
pnpm dev
|
|
100
|
-
|
|
101
|
-
# To proxy to a remote API server instead of localhost:
|
|
102
|
-
# Linux / macOS:
|
|
103
|
-
API_URL=https://app.palmier.me pnpm dev
|
|
104
|
-
# Windows (PowerShell):
|
|
105
|
-
$env:API_URL="https://app.palmier.me"; pnpm dev
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
Open `http://localhost:5173` in your browser.
|
|
109
|
-
|
|
110
|
-
### Production
|
|
111
|
-
|
|
112
|
-
In production, Express serves the built PWA static files directly — one server, one port.
|
|
113
|
-
|
|
114
|
-
```bash
|
|
115
|
-
# Build the PWA
|
|
116
|
-
cd pwa && pnpm build
|
|
117
|
-
|
|
118
|
-
# Start the server (serves API + PWA on port 3000)
|
|
119
|
-
cd server && pnpm start
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Open `http://localhost:3000`.
|
|
123
|
-
|
|
124
|
-
### Host Setup
|
|
125
|
-
|
|
126
|
-
The host runs on a separate Linux machine. See the [palmier README](https://github.com/caihongxu/palmier) for full details.
|
|
127
|
-
|
|
128
|
-
1. On the host machine, in your project directory, run:
|
|
129
|
-
```bash
|
|
130
|
-
palmier init
|
|
131
|
-
```
|
|
132
|
-
The interactive wizard detects agents, asks for the HTTP port, detects the default network interface, shows a summary for confirmation, registers with the server, saves config to `~/.config/palmier/host.json`, installs a background daemon, and generates a pairing code.
|
|
133
|
-
|
|
134
|
-
2. Enter the pairing code in the PWA to connect your device to the host.
|
|
135
|
-
|
|
136
|
-
## Environment Variables
|
|
137
|
-
|
|
138
|
-
| Variable | Description | Example |
|
|
139
|
-
|---|---|---|
|
|
140
|
-
| `PORT` | HTTP server port | `3000` |
|
|
141
|
-
| `DATABASE_URL` | PostgreSQL connection string | `postgresql://user:password@localhost:5432/palmier` |
|
|
142
|
-
| `NATS_URL` | NATS server URL (TCP, for server's own connection) | `nats://localhost:4222` |
|
|
143
|
-
| `NATS_HOST_URL` | NATS URL sent to hosts during registration (use LAN IP) | `nats://192.168.1.100:4222` |
|
|
144
|
-
| `NATS_WS_URL` | NATS WebSocket URL sent to PWA clients | `wss://nats.palmier.me` (prod) or `ws://192.168.1.100:9222` (LAN) |
|
|
145
|
-
| `NATS_ACCOUNT_SEED` | NATS account NKey seed for signing JWTs | *(from nats-setup)* |
|
|
146
|
-
| `VAPID_PUBLIC_KEY` | VAPID public key for web push | *(generated via web-push)* |
|
|
147
|
-
| `VAPID_PRIVATE_KEY` | VAPID private key for web push | *(generated via web-push)* |
|
|
148
|
-
| `VAPID_MAILTO` | Contact email for VAPID | `mailto:admin@example.com` |
|
|
149
|
-
| `GOOGLE_APPLICATION_CREDENTIALS` | Path to Firebase service account JSON (for FCM) | `/path/to/service-account.json` |
|
|
150
|
-
|
|
151
|
-
> **LAN setup note:** `NATS_URL` uses `localhost` because the server connects to NATS locally. `NATS_HOST_URL`, `NATS_WS_URL` must use the LAN IP so remote hosts and browsers can reach them. Firewall must allow inbound on ports 3000 (HTTP), 4222 (NATS TCP), 5173 (Vite dev), and 9222 (NATS WebSocket).
|
|
152
|
-
|
|
153
|
-
## API Endpoints
|
|
154
|
-
|
|
155
|
-
All endpoints are prefixed with `/api`. No user authentication is required.
|
|
156
|
-
|
|
157
|
-
| Method | Path | Description |
|
|
158
|
-
|---|---|---|
|
|
159
|
-
| `POST` | `/api/hosts/register` | Register a new host (returns hostId + NATS JWT credentials) |
|
|
160
|
-
| `GET` | `/api/config` | Get pairing-only NATS credentials (can only publish to `pair.*`) |
|
|
161
|
-
| `GET` | `/api/nats-credentials/:hostId` | Get host-scoped NATS credentials for PWA (RPC + events for one host) |
|
|
162
|
-
| `POST` | `/api/push/subscribe` | Register a push notification subscription |
|
|
163
|
-
| `DELETE` | `/api/push/subscribe` | Remove a push notification subscription |
|
|
164
|
-
| `GET` | `/api/push/vapid-key` | Get the VAPID public key |
|
|
165
|
-
| `POST` | `/api/push/respond` | Respond to a pending task confirmation via push notification |
|
|
166
|
-
| `POST` | `/api/fcm/register` | Register an FCM token for a host (Android device) |
|
|
167
|
-
| `POST` | `/api/fcm/geolocation-response` | Receive device location from Android, forward via NATS |
|
|
168
|
-
| `POST` | `/api/device/notifications` | Relay device notification from Android to host via NATS |
|
|
169
|
-
| `POST` | `/api/device/sms` | Relay incoming SMS from Android to host via NATS |
|
|
170
|
-
| `POST` | `/api/device/contacts-response` | Relay contacts response from Android to host via NATS |
|
|
171
|
-
| `POST` | `/api/device/calendar-response` | Relay calendar response from Android to host via NATS |
|
|
172
|
-
| `POST` | `/api/device/sms-response` | Relay SMS send response from Android to host via NATS |
|
|
173
|
-
| `POST` | `/api/device/alarm-response` | Relay alarm response from Android to host via NATS |
|
|
174
|
-
| `POST` | `/api/device/battery-response` | Relay battery response from Android to host via NATS |
|
|
175
|
-
| `POST` | `/api/device/ringer-response` | Relay ringer mode response from Android to host via NATS |
|
|
176
|
-
| `GET` | `/health` | Health check |
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
## Key Implementation Notes
|
|
180
|
-
|
|
181
|
-
- **No user accounts** — the PWA stores paired hosts in localStorage. Each device pairs with a host via a pairing code and receives a client token.
|
|
182
|
-
- **Client tokens** are generated and validated on the host, not the server. They are included in every NATS RPC payload and as Bearer tokens for HTTP requests.
|
|
183
|
-
- **NATS RPC** — the RPC method is derived from the NATS subject (e.g., `...rpc.task.list` → `task.list`), not the message body. The body contains request parameters plus `clientToken`. All NATS requests go through a centralized `request()` helper in `HostConnectionContext` that handles encoding/decoding and logging.
|
|
184
|
-
- **Pairing** — `palmier pair` (or auto-pair after `palmier init`) generates a 6-char pairing code. The PWA enters the code, which routes to the host via NATS (`pair.<CODE>`) or HTTP (`POST /pair`). The host validates the code and returns a client token.
|
|
185
|
-
- **Task IDs** are generated by the host as UUIDs.
|
|
186
|
-
- **Schedule can be enabled/disabled** — the `schedule_enabled` frontmatter field (default `true`) controls whether the schedule is active. When disabled, timers are removed and device events are ignored for that task, but it can still be run manually. The schedule lives in two flat fields: `schedule_type` (`"crons"`, `"specific_times"`, `"on_new_notification"`, or `"on_new_sms"`) and `schedule_values` (array of cron expressions or local datetime strings — only used by `"crons"` and `"specific_times"`). The two `on_new_*` types have no `schedule_values`; they fire in response to device notifications/SMS relayed over NATS, with the daemon owning a per-task FIFO queue that `palmier run` drains via `POST /task-event/pop`.
|
|
187
|
-
- **Host responses** return flat task objects (frontmatter fields at the top level, not nested) for `task.list`, `task.create`, and `task.update`.
|
|
188
|
-
- **NATS "503"** means "no responders" — the dashboard silently handles this when no host is connected, showing an empty task list instead of an error.
|
|
189
|
-
- **Helmet CSP** is disabled (`contentSecurityPolicy: false`) to allow NATS WebSocket connections and inline Vite scripts during dev.
|
|
190
|
-
- **Static file serving** is conditional — Express only serves `pwa/dist/` if the directory exists, so it doesn't interfere during dev when using Vite.
|
|
191
|
-
- **No CORS** needed — Vite proxy handles same-origin in dev, Express static serving handles it in production.
|
|
192
|
-
- **Push notifications** — the PWA registers a service worker (`injectManifest` strategy via vite-plugin-pwa) and subscribes the browser for Web Push. The Web Server subscribes to `host-event.>` and sends push notifications for confirmation requests, task completions, and task failures.
|
|
193
|
-
- **Markdown rendering** — Task results are rendered as rich formatted text using `react-markdown` with `remark-gfm` (GitHub Flavored Markdown), supporting tables, strikethrough, task lists, and autolinks.
|
|
194
|
-
- **Pending prompts** — Dashboard fetches `host.info` once per connection and seeds any already-open confirmation/permission/input prompts from the response's `pending_prompts` array. Each entry carries a `meta` field with a unified `session_name` label (agent name for confirm/input, task name for permission) so modals render without needing the task list. After connect, live prompts arrive via NATS events (`confirm-request`, `permission-request`, `input-request`). The Dashboard owns the subscription and renders modals via React portal so they surface regardless of which tab is active. Push notification action buttons trigger `POST /api/push/respond`, which forwards to the `task.user_input` NATS RPC.
|
|
195
|
-
- **Host-scoped routes** — all authenticated views live under `/hosts/:hostId/...` so the URL is the source of truth for the active host. Sessions tab is `/hosts/:hostId`, Tasks tab is `/hosts/:hostId/tasks`, run detail is `/hosts/:hostId/runs/:taskId/:runId`. `/` redirects to the first paired host (or `/pair` when no hosts are paired). Notification deep links include the host in the path so tapping a notification switches the active host even if another host was selected at the time.
|
|
196
|
-
- **Lazy tab loads** — Sessions tab (default) fetches `taskrun.list` on mount; Tasks tab fetches `task.list` on mount. Neither is called at startup — only `host.info` is. Task lifecycle events are persisted to `status.json` on the host (for crash detection) and broadcast via `host-event.<host_id>.<task_id>` pub/sub and HTTP SSE.
|
|
197
|
-
- **NATS auth** uses decentralized JWT/NKey authentication. Each host receives scoped credentials (can only access its own subjects). PWA clients get two-phase credentials: pairing-only JWT for the pairing flow, then host-scoped JWT after pairing. The server signs all user JWTs with the account key. Run `pnpm --filter palmier-server nats-setup` to generate keys and NATS config. See **NATS JWT Auth Setup** below.
|
|
198
|
-
|
|
199
|
-
## NATS JWT Auth Setup
|
|
200
|
-
|
|
201
|
-
NATS uses decentralized JWT/NKey authentication. Each host gets scoped credentials that restrict it to its own subjects — one host cannot read or impersonate another.
|
|
202
|
-
|
|
203
|
-
**One-time setup:**
|
|
204
|
-
|
|
205
|
-
```bash
|
|
206
|
-
# Generate operator/account NKey pairs and NATS config
|
|
207
|
-
cd server && pnpm nats-setup
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
This outputs:
|
|
211
|
-
1. An `NATS_ACCOUNT_SEED` value — add it to `server/.env`
|
|
212
|
-
2. A NATS config snippet — replace the `authorization` block in `nats.conf`
|
|
213
|
-
|
|
214
|
-
**How it works:**
|
|
215
|
-
|
|
216
|
-
| Role | Publish | Subscribe |
|
|
217
|
-
|------|---------|-----------|
|
|
218
|
-
| **Host** (id=X) | `host-event.X.>`, `host.X.>` | `host.X.>`, `pair.*` |
|
|
219
|
-
| **PWA** (pairing) | `pair.*` | *(none)* |
|
|
220
|
-
| **PWA** (connected to X) | `host.X.rpc.>` | `host-event.X.>` |
|
|
221
|
-
| **Server** | `>` | `>` |
|
|
222
|
-
|
|
223
|
-
- The **operator** key signs the **account** JWT (embedded in NATS server config, one-time)
|
|
224
|
-
- The **account** key signs **user** JWTs at runtime (per host registration, per PWA session)
|
|
225
|
-
- Host credentials are generated during `POST /api/hosts/register` and stored in `~/.config/palmier/host.json`
|
|
226
|
-
- PWA uses two-phase credentials: `GET /api/config` returns pairing-only JWT, then `GET /api/nats-credentials/:hostId` returns host-scoped JWT after pairing. A PWA client can only access the specific host it paired with.
|
|
227
|
-
|
|
228
|
-
## Related Repositories
|
|
229
|
-
|
|
230
|
-
- [palmier](https://github.com/caihongxu/palmier) -- The host binary, published as `palmier` on npm. Install with `npm install -g palmier`. Uses npm (not pnpm).
|
|
231
|
-
- [palmier-android](https://github.com/caihongxu/palmier-android) -- Native Android wrapper (Capacitor) for the PWA. Provides FCM and native device capabilities (GPS, notifications, SMS, contacts, calendar, alarms, battery, ringer).
|
package/palmier-server/nats.conf
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# NATS Server Configuration for Palmier
|
|
2
|
-
|
|
3
|
-
# TCP listener (for server + host)
|
|
4
|
-
listen: 0.0.0.0:4222
|
|
5
|
-
|
|
6
|
-
# WebSocket listener (for PWA browser clients)
|
|
7
|
-
websocket {
|
|
8
|
-
listen: "0.0.0.0:9222"
|
|
9
|
-
no_tls: true
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
# JWT/NKey authentication
|
|
13
|
-
# Generate these values by running: cd server && pnpm nats-setup
|
|
14
|
-
# Paste the auth snippet from the output below.
|
|
15
|
-
# operator: <OPERATOR_JWT>
|
|
16
|
-
# resolver: MEMORY
|
|
17
|
-
# resolver_preload: {
|
|
18
|
-
# <ACCOUNT_PUBLIC_KEY>: <ACCOUNT_JWT>
|
|
19
|
-
# }
|