diff --git a/CHANGELOG.md b/CHANGELOG.md
index 84a8db92..5b266afc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* **scheduled-ops:** prune label filter — scheduled system prune operations can be scoped to resources matching a specific Docker label (e.g. `com.docker.compose.project=mystack`)
* **scheduled-ops:** CSV export for execution history — one-click download of the full run history from the execution history panel
+### Changed
+
+* **multi-node:** show inline warning when configuring a remote node with an HTTP URL — recommends HTTPS or VPN for public internet connections; HTTP remains fully supported for private networks
+
### Fixed
* **fleet:** "Open in Editor" button in Fleet View's stack drill-down now correctly navigates to the stack editor instead of the dashboard. Also passes the stack name through the callback chain so the correct file is loaded.
diff --git a/backend/src/index.ts b/backend/src/index.ts
index 1da03b98..e3133144 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -4493,7 +4493,14 @@ app.post('/api/nodes', async (req: Request, res: Response) => {
api_token: api_token || '',
});
- res.json({ success: true, id });
+ const isPlainHttp = type === 'remote' && api_url && api_url.startsWith('http://');
+ res.json({
+ success: true,
+ id,
+ ...(isPlainHttp && {
+ warning: 'This node uses plain HTTP. Use HTTPS or a VPN for connections over the public internet.'
+ })
+ });
} catch (error: any) {
if (error.message?.includes('UNIQUE constraint')) {
return res.status(409).json({ error: 'A node with that name already exists' });
@@ -4527,7 +4534,13 @@ app.put('/api/nodes/:id', async (req: Request, res: Response) => {
// Evict cached Docker connection so it reconnects with new config
NodeRegistry.getInstance().evictConnection(id);
- res.json({ success: true });
+ const isPlainHttp = updates.api_url && updates.api_url.startsWith('http://');
+ res.json({
+ success: true,
+ ...(isPlainHttp && {
+ warning: 'This node uses plain HTTP. Use HTTPS or a VPN for connections over the public internet.'
+ })
+ });
} catch (error: any) {
console.error('Failed to update node:', error);
res.status(500).json({ error: error.message || 'Failed to update node' });
diff --git a/docs/features/multi-node.mdx b/docs/features/multi-node.mdx
index e8dc9441..b8f68b4e 100644
--- a/docs/features/multi-node.mdx
+++ b/docs/features/multi-node.mdx
@@ -77,8 +77,94 @@ Node status indicators:
Click the **pencil icon** on any remote node row to edit its name, URL, or token. Click the **trash icon** to remove it. The local node cannot be edited or deleted.
-## Security considerations
+## Security
-- Node tokens grant full control over the remote Sencho instance. Rotate them if compromised via Settings → Nodes → Generate Token (the old token is invalidated).
-- Use HTTPS between instances in production to prevent token interception.
-- The host console and container exec terminals are blocked for node-proxy tokens - interactive shell access always requires a real browser session on that instance.
+### Token security
+
+Node tokens are long-lived JWTs that grant full control over the remote Sencho instance. Treat them like passwords:
+
+- **Rotate immediately** if a token is compromised: Settings → Nodes → Generate Token on the remote instance. The old token is invalidated instantly.
+- Tokens are **encrypted at rest** using AES-256-GCM in Sencho's SQLite database. Even if the database file is extracted, the tokens cannot be read without the instance's encryption key.
+- Tokens are scoped to `node_proxy` — they cannot access the host console or container exec terminals. Interactive shell access always requires a real browser session on that specific instance.
+
+### Transport encryption
+
+Sencho delegates transport encryption to your infrastructure rather than implementing TLS at the application layer. This is the same approach used by [Dockge](https://github.com/louislam/dockge) and other self-hosted tools — it avoids certificate management burden while letting you use the encryption layer that best fits your environment.
+
+
+
+
+There are three recommended approaches depending on your deployment:
+
+#### Private network (LAN or VPC)
+
+If all your Sencho instances are on the same local network, VPC, or subnet — HTTP is perfectly fine. The token never leaves the private network, so there is no interception risk.
+
+```
+http://192.168.1.50:3000 ← safe on a private LAN
+http://10.0.1.20:3000 ← safe inside a VPC
+```
+
+#### VPN tunnel (WireGuard, Tailscale)
+
+
The base URL of the Sencho instance running on the remote machine.
+ {formData.api_url.startsWith('http://') && ( ++ This URL uses plain HTTP. If this node is reachable over the public internet, use HTTPS + or a VPN to prevent token interception. HTTP is fine for private networks (LAN, VPN, VPC). +
+