rmnr
DocsLayoutsModulesDirectoryBest PracticeAgentsInstall

Command Palette

Search for a command to run...

New
  • Introduction
  • Installation
  • Architecture
  • Stack
  • Directory
  • Install with Agent
    new
  • Bundle Builder
    new
  • MCP server
    new
  • VPS Control Room
    new
  • Changelog
    new
  • All website templates
    new
  • Personal Brand OS
  • Agency Studio OS
  • Notion Page Clone OS — localStorage demo (pointer to open-silong for production)
  • SaaS Marketing OS
  • Kreator Studio OS
  • Konsultan OS
  • Wirausaha OS
  • Riset Kit
  • All layouts
  • 19
  • 3
  • 6
  • All slices
    new
  • 2
  • 2
  • 6
  • 3
  • 3
  • 1
  • 1
  • 7
  • 25
  • 6
  • All recipes

Install guide

VPS Control Room

A mobile-first PWA dashboard for driving a single VPS through a web browser. Multi-pane terminals (up to 24 concurrent ptys), AI-agent launchers, host telemetry, and shell-allowlist actions — all behind one shared secret on a Tailscale-only domain.

GitHubnpm: rahman-crFull roadmap🇮🇩 Bahasa Indonesia

Three install paths

🤖

AI-assisted

~20 min

npx rahman-cr ai claude

Walk through every step with Claude / Codex / Gemini

⚡

One-line

~10 min

npx rahman-cr install --vps … --domain …

All values ready, want minimum prompts

🛠️

Manual

~30 min

See Phase 5 → C below

Want to read each step before running it

Phase 0

Local prereqs (your laptop)

Run on your laptop, not the VPS.

terminalbash
npx rahman-cr doctor

Confirms Node 18+, ssh, git, and openssl are all in PATH.

Also have ready: an SSH key (~/.ssh/id_ed25519.pub) and a password manager — you'll need to store two 32-char secrets at the end.

terminalbash
# generate an SSH key if you don't have one yet
ssh-keygen -t ed25519 -C "your-email"

Phase 1

VPS provisioning

Bring your own VPS. Tested providers: Hostinger, DigitalOcean, Vultr, Hetzner. Minimum Ubuntu 22.04, 1 GB RAM, 5 GB disk, 1 vCPU. Recommended Ubuntu 24.04 LTS, 2 GB+ RAM.

After provisioning, confirm you have the public IPv4 and can SSH in.

Hostinger VPSDigitalOceanVultrHetzner

Phase 2

Push SSH key, kill password auth

Get rid of password auth before doing anything else.

terminal (laptop)bash
# from your laptop
ssh-copy-id user@<vps-ip>
ssh user@<vps-ip> 'echo ok'   # should print: ok (no password prompt)

Recommended: disable password auth on the VPS afterward.

terminal (VPS)bash
# on the VPS
sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sudo systemctl restart sshd

Phase 3

Tailscale on the VPS

The dashboard is designed for Tailscale-only access. The reverse proxy binds to the Tailscale interface; the public IP never sees the dashboard.

3.1 Generate a Tailscale auth key

Open the keys admin page and click Generate auth key:

Tailscale → Settings → Keys
  • Reusable: No
  • Ephemeral: No
  • Pre-authorized: Yes
  • Tags: tag:server

Copy the tskey-auth-…string — you'll paste it in the next step.

3.2 Install Tailscale on the VPS

terminal (VPS)bash
ssh user@<vps-ip>
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --authkey=tskey-auth-XXXX --hostname=control-room
tailscale ip -4    # → 100.x.y.z
exit

3.3 Note your tailnet hostname

Your dashboard URL will be control-room.<tailnet>.ts.net. Find your tailnet name at:

Tailscale → DNS

Phase 4 (optional)

Custom DNS

Skip this phase if you're happy using .ts.net. Otherwise, create an A record pointing your custom subdomain at the Tailscale 100.x IP.

4.1 Manual via your DNS provider

TypeNameValueTTL
Acontrol100.x.y.z300

4.2 Hostinger API (one curl)

Generate a token at developers.hostinger.com first.

terminalbash
# replace YOUR_TOKEN, yourdomain.com, and 100.x.y.z
curl -X POST https://developers.hostinger.com/api/dns/v1/zones/yourdomain.com/records \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"A","name":"control","content":"100.x.y.z","ttl":300}'

4.3 Verify

terminalbash
dig +short control.yourdomain.com    # → 100.x.y.z

⚠️ Do NOT set the A record to your public IP. That defeats the threat model — Traefik binds to Tailscale only, so a public record just leaks the VPS IP.

Phase 5

Pick an install path

Three paths, same end state. Run from your laptop.

A. AI-assisted

The CLI prints a structured prompt + copies it to your clipboard. Paste into Claude / Codex / Gemini. The AI triggers the /sc-all skill if available and walks the remaining phases.

terminalbash
npx rahman-cr ai claude     # or: codex | gemini

B. One-line (non-interactive)

SSHs in, installs Node 22 + Tailscale (optional), clones the repo, generates two 32-char secrets, writes .env.local (chmod 600), runs install-systemd.sh and deploy.sh main, then verifies. Login secret prints once at the end — save it.

terminalbash
# already on tailnet
npx rahman-cr install \
  --vps user@<ip> \
  --domain control-room.<tailnet>.ts.net

# fresh VPS not on tailnet yet
npx rahman-cr install \
  --vps user@<ip> \
  --domain control-room.<tailnet>.ts.net \
  --tailscale-key tskey-auth-XXXX

C. Manual

Walk every step yourself. Good for learning the architecture.

terminal (VPS)bash
ssh user@<vps-ip>
mkdir -p ~/projects && cd ~/projects
git clone https://github.com/rahmanef63/control-room.git vps-control-room
cd vps-control-room

cp .env.example .env.local
$EDITOR .env.local    # set CONTROL_ROOM_SECRET, _SESSION_SECRET, NEXT_PUBLIC_APP_HOST, _APP_URL
chmod 600 .env.local

npm --prefix frontend install
npm --prefix agent    install
npm --prefix cli      install

sudo bash scripts/install-systemd.sh
bash scripts/deploy.sh main

Generate the two secrets locally with openssl rand -hex 32 (twice — they must be different).

Phase 6

Verify

6.1 systemd services

terminalbash
ssh user@<vps-ip> 'systemctl is-active vps-control-room-agent vps-control-room-frontend'
# expect:
#   active
#   active

6.2 Health endpoint

terminalbash
ssh user@<vps-ip> 'curl -s http://127.0.0.1:4001/health'
# expect: {"ok":true,...}

6.3 Browser login

Open https://control-room.<tailnet>.ts.net (or your custom domain). Paste CONTROL_ROOM_SECRET from your password manager. Spawn a terminal, type whoami, expect your VPS user.

6.4 Install as a PWA

  • iOS Safari: Share → Add to Home Screen
  • Android Chrome: ⋮ → Install app

Reference

API endpoints (AI / automation)

The AI prompt embeds this catalog. Listed here for direct reference.

Tailscale

  • Docs: tailscale.com/api
  • Auth: Bearer ${TAILSCALE_API_KEY}
  • POST /api/v2/tailnet/-/keys — create auth key
  • GET /api/v2/tailnet/-/devices — list devices

Hostinger

  • Docs: developers.hostinger.com
  • Auth: Bearer ${HOSTINGER_API_TOKEN}
  • GET /api/vps/v1/virtual-machines — list VPS
  • POST /api/dns/v1/zones/{domain}/records — create DNS record

Dokploy (optional)

  • Auth header: x-api-key: ${DOKPLOY_API_KEY}
  • POST ${DOKPLOY_API_URL}/api/application.create
  • POST ${DOKPLOY_API_URL}/api/application.deploy
  • POST ${DOKPLOY_API_URL}/api/domain.create

GitHub

  • Docs: docs.github.com/rest
  • Generate a PAT: github.com/settings/tokens
  • POST https://api.github.com/user/repos — create repo
  • POST /repos/{owner}/{repo}/keys — create deploy key

Operations

Day-2: update, rollback, rotate

Deploy an update

terminal (VPS)bash
ssh user@<vps-ip>
cd ~/projects/vps-control-room
git pull origin main
bash scripts/deploy.sh main

Rollback (one-shot)

terminal (VPS)bash
cd ~/projects/vps-control-room/frontend
mv .next .next-broken
mv .next-previous .next
sudo systemctl restart vps-control-room-frontend

Rotate secrets

terminal (VPS)bash
# on the VPS
NEW=$(openssl rand -hex 32)
NEW_SESSION=$(openssl rand -hex 32)
sed -i "s/^CONTROL_ROOM_SECRET=.*/CONTROL_ROOM_SECRET=$NEW/" .env.local
sed -i "s/^CONTROL_ROOM_SESSION_SECRET=.*/CONTROL_ROOM_SESSION_SECRET=$NEW_SESSION/" .env.local
sudo systemctl restart vps-control-room-agent vps-control-room-frontend
echo "new login: $NEW"
echo "(save in password manager, then clear scrollback)"

Skill

/sc-all anchor

The AI prompt auto-loads the sc-all skill if you have it installed at ~/.claude/skills/sc-all/ (or the equivalent for Codex / Gemini). /sc-all orchestrates:

  • GitHub repo ensure (private fork) + push
  • Dokploy project + application creation
  • Self-hosted Convex deploy (skipped — Control Room is terminal-only)
  • DNS record creation
  • Deploy poll until done

For Control Room, /sc-all skips Convex but reuses the GitHub + Dokploy + DNS phases. The rahman-cr install one-liner also reuses this sequencing.

Troubleshoot

Common symptoms

SymptomLikely causeFix
ssh: connection refusedVPS firewall blocking port 22Open port 22 in provider firewall
tailscale up hangsAuth key expired or wrong tagsRegenerate at admin.tailscale.com/settings/keys
dig returns nothingDNS not propagatedWait 5 min, try dig +trace
Login page says invalidSecret mismatchRe-check .env.local on the VPS
White dashboard after deployBuild failed silentlyjournalctl -u vps-control-room-frontend
systemctl shows failedWrong WorkingDirectoryRe-run scripts/install-systemd.sh from repo root

Need more depth? Read the full INSTALL roadmap, ONBOARDING walkthrough, SECURITY threat model, or CONTRIBUTING guide.