Getting started
Architecture
Control plane
master / worker · mTLS
Clients
Master VPS
Worker nodes
Node VPS #1
Node VPS #2
┌───────────────────────── MASTER VPS ─────────────────────────┐
browser ──HTTPS──▶ │ nginx ──▶ web console (autoscript-web) │
│ └▶ FastAPI agent API (autoscript-agent) ──▶ SQLite │
Telegram ────────▶│ telegram bot (autoscript-bot) │
│ local node "local-01" (always online while panel runs) │
└──────────────┬──────────────────────────────┬─────────────────┘
│ mTLS RPC (panel → node) │ signed heartbeat (node → panel)
┌──────────────▼──────────────┐ ┌────────────▼────────────────┐
│ NODE VPS (agent) │ │ NODE VPS (agent) │
│ xray · ssh/dropbear · │ │ ssh-ws · zivpn · nginx │
│ stunnel · nginx │ │ │
└──────────────┬──────────────┘ └────────────┬────────────────┘
│ VPN traffic │
end user client ─────────────────▶┴───────────────────────────────┘- The master never runs the standalone node code from node/ — it auto-registers itself as local-01 and is considered online while the panel process is up.
- Only remote worker boxes run the node agent, installed with the node one-liner.
- End-user VPN traffic goes straight to the node it was provisioned on. The panel is a control plane, not a data path.
The installer deploys everything as systemd units. Knowing the unit names is most of troubleshooting.
On the master
| Unit | Role |
|---|---|
| autoscript-agent | FastAPI API the web console talks to |
| autoscript-web | Web console server on a random internal port behind nginx |
| autoscript-bot | Telegram bot process |
| autoscript-ssh-ws | SSH-over-WebSocket bridge |
| autoscript-stunnel | TLS wrapper for SSH/stunnel port sets |
| autoscript-ip-limit.service / .timer | Periodic device (concurrent IP) enforcement |
| nginx | TLS termination, panel vhost, / upgrade for SSH-WS |
On each node
| Unit | Role |
|---|---|
| autoscript-node | Node agent: handshake, heartbeat, mTLS RPC server |
| autoscript-node-ssh-ws | SSH-over-WebSocket bridge on the node |
| autoscript-node-stunnel | TLS wrapper for the node's SSH/stunnel port set |
| autoscript-node-logclean.service / .timer | Periodic log rotation and cleanup on the node |
systemctl status autoscript-agent autoscript-web autoscript-bot nginx
journalctl -u autoscript-agent -n 200 --no-pager
# on a node
systemctl status autoscript-node
journalctl -u autoscript-node -f- /opt/autoscript
- Checked-out release: backend, node payload, built web bundle
- /etc/autoscript/agent.env
- Master environment: panel port, path slug, secrets (root-only)
- /etc/autoscript/db.sqlite
- Default database path (chosen at install)
- /etc/autoscript/panel-credentials.txt
- Generated panel URL + admin credentials, mode 600
- /etc/default/autoscript-node
- Node environment: NODE_ID, MASTER, AGENT_PORT
- /usr/local/bin/autoscript
- Admin CLI
- /root/autoscript-backup-<timestamp>.tar.gz
- Default location for panel backup archives
- /var/log/autoscript-repair.log
- Output of the automatic service-repair routine
Credentials are root-only
agent.env and panel-credentials.txt hold admin credentials and signing secrets. Never move them into a web-served directory or a git repo.The installer resets ufw to deny-inbound and then opens exactly what the stack needs. Panel and local-node API ports are randomised so they never collide with the CDN-friendly VPN port sets.
| Port set | Value | Purpose |
|---|---|---|
| TLS ports (default) | 443, 2053, 2083, 2087, 2096, 8443 | Cloudflare-proxyable TLS entrypoints for VMess/VLESS/Trojan |
| Plain ports (default) | 80, 8080, 8880, 2052, 2082, 2086, 2095 | Cloudflare-proxyable plaintext/WS entrypoints |
| Panel port | randomised at install | HTTPS web console + API (autoscript set-port) |
| Local node API port | randomised at install | mTLS RPC for the master’s own local-01 node |
| 22/tcp | 22 | System SSH, always allowed |
Node agent port is IP-locked
$MASTER and inserts a GRVPN_AGENT iptables/ip6tables chain that only accepts the panel’s IPv4/IPv6 addresses on the agent port. Changing the panel IP requires re-running the node’s firewall step.Browser → panel
Nginx terminates TLS on the panel port and proxies to the internal web server and the FastAPI agent. The console lives under a secret path slug (autoscript set-path) so the panel is not discoverable at the domain root, and fail2ban is configured by default.
Node → panel (handshake + heartbeat)
A node bootstraps by POSTing to /api/public/node-handshake on the master with its node id, client-certificate fingerprint and agent port. After that it sends a signed keepalive every ~15 seconds carrying CPU, RAM and NIC snapshots. The panel marks a node offline when heartbeats stop arriving.
Panel → node (RPC)
For anything that changes node state — provisioning an account, reloading Xray, applying certs, syncing ZIVPN users, running a benchmark — the panel calls the node agent’s mTLS HTTPS server on the agent port. The certificate pinned at handshake time is the identity; a node whose fingerprint changes must be re-approved.
Updates
The panel cannot update itself from the web UI. Updates are performed on the VPS with autoscript update, which installs the latest published release of the official repository, runs migrations and restarts the stack.
- SQLite on the master is the single source of truth for accounts, nodes, plans, invoices, wallets, settings and audit logs.
- Nodes hold derived state only: Xray config, SSH system users, ZIVPN
users.json, certs. Anything on a node can be rebuilt from the panel by re-syncing. - Counters are deltas. Node agents scrape cumulative traffic counters and report deltas, so a service restart or counter reset does not double-count or go negative.
Every master/node interaction goes through a small, fixed contract. Node → master calls land on public routes; master → node calls hit the agent's mTLS RPC server.
Node → master (public, signed)
| Endpoint | Purpose |
|---|---|
| POST /api/public/node-handshake | First-boot enrolment; pins the node client certificate |
| POST /api/public/node-heartbeat | 15s keepalive with CPU, RAM and NIC telemetry |
| POST /api/public/node-webhook | Async events: strikes, cert renewal, job results |
| POST /api/public/node-ssh-usage | SSH/dropbear session and traffic usage batches |
| GET /api/public/node-install/<token> | One-time install script fetched by the node one-liner |
| GET /api/public/node-agent.tar.gz | Node agent payload served to workers |
| GET /api/public/node-agent-version | Version probe used by autoscript-node-update |
| POST /api/public/node-uninstall | Node self-deregistration when uninstalled |
| GET /api/public/master-baseline | Baseline config the node applies after enrolment |
| POST /api/public/master-user-usage | Aggregated per-user usage deltas |
Master → node (mTLS + bearer)
| Endpoint | Purpose |
|---|---|
| POST /rpc/users.apply | Full or partial user set for Xray, SSH and ZIVPN |
| POST /rpc/config.apply | Push hosts matrix, port sets and SNI overrides |
| POST /rpc/service.restart | Restart xray / nginx / zivpn / the agent itself |
| GET /rpc/status · /rpc/ping · /rpc/node.health | Reachability, status snapshot and health checks |
| POST /rpc/node.config · node.restart · node.rebuild | Re-apply node config, restart or rebuild the node |
| POST /rpc/xray.install · xray.version | Install or report the Xray core version |
| POST /rpc/cert.issue | Issue or renew TLS certificates on the node |
| POST /rpc/firewall.apply · system.tune | Firewall chains and kernel/network tuning |
| POST /rpc/net.probe · net.speedtest | Latency probes and bandwidth benchmarks |
| GET /rpc/logs · POST /rpc/logs.purge | Fetch or trim node logs |
| POST /rpc/traffic.reset · vpn.halt | Reset counters, halt VPN services |
| POST /rpc/agent.update · agent.update_safe · agent.stop · GET /rpc/agent.version | Node agent lifecycle |
| GET /rpc/ws | WebSocket channel for live streams (logs, stats) |
Both factors are required
Authorization: Bearer secret shown on the panel's Nodes page. Missing either one is rejected before the handler runs.Besides the request path, the master runs scheduled work. Most “it fixed itself” behaviour comes from these.
| Worker | Where | What it does |
|---|---|---|
| Scheduler loop | inside autoscript-agent | Expiry sweeps, renewals, plan/quota enforcement and queued jobs |
| Heartbeat cache refresher | inside autoscript-agent | Keeps the last-known node telemetry hot for the dashboard and map |
| autoscript-ip-limit.timer | master | Enforces concurrent-device (IP) limits on a schedule |
| repair-services | master CLI | Restarts unhealthy units, logging to /var/log/autoscript-repair.log |
| autoscript-node-logclean.timer | node | Trims node logs so small worker disks do not fill |
| autoscript-node-update | node (via RPC) | Pulls the matching node release when the panel triggers an update |
