feat: self-hosted remote support over VNC
Browser-based remote control (noVNC) with invite links, per-user access control, garagedoor SSO and a persisted client list. The hub proxies RFB rather than pointing the browser at a VNC server. That is what lets it authenticate upstream with a stored password the browser never sees, and enforce view-only by dropping input messages on the client->server stream instead of hiding buttons. Machines are reachable two ways: direct TCP for LAN hosts, or an outbound agent tunnel for anything behind NAT. Node 22's global WebSocket keeps the agent dependency-free, and node:sqlite keeps the image free of native builds. Ships with an end-to-end suite that boots the real server against a fake VNC server and a fake auth service (72 assertions), plus Gitea Actions CI/CD to Portainer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
# Deployed to Portainer (Swarm endpoint) by .gitea/workflows/deploy.yml.
|
||||
# ${IMAGE} and the secrets below are injected as env_data at deploy time.
|
||||
#
|
||||
# Two constraints this stack cannot break:
|
||||
# 1. exactly one replica — agent control sockets and live sessions are held in
|
||||
# process memory, so a second replica would not see the first one's agents;
|
||||
# 2. pinned placement — the SQLite volume is node-local, so the task has to
|
||||
# come back to the same node or it wakes up with an empty database.
|
||||
services:
|
||||
remote-control-support:
|
||||
image: ${IMAGE:-git.mancinas.io/rmancinas/remote-control-support-webapp:latest}
|
||||
ports:
|
||||
- "8091:8080"
|
||||
environment:
|
||||
DB_PATH: /data/rcs.db
|
||||
TRUST_PROXY: "true"
|
||||
AUTH_URL: ${AUTH_URL:-http://192.168.4.208:8000}
|
||||
ADMIN_USERS: ${ADMIN_USERS:-}
|
||||
ADMIN_LEVEL: ${ADMIN_LEVEL:-}
|
||||
ENCRYPTION_KEY: ${ENCRYPTION_KEY:-}
|
||||
PUBLIC_URL: ${PUBLIC_URL:-}
|
||||
ALLOW_SESSION_INVITES: ${ALLOW_SESSION_INVITES:-true}
|
||||
volumes:
|
||||
- rcs_data:/data
|
||||
deploy:
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
update_config:
|
||||
# start-first would briefly run two containers against one SQLite file.
|
||||
order: stop-first
|
||||
failure_action: rollback
|
||||
restart_policy:
|
||||
condition: any
|
||||
delay: 10s
|
||||
|
||||
volumes:
|
||||
rcs_data:
|
||||
Reference in New Issue
Block a user