name: VPS Infrastructure Setup
description: HOSTiQ kVPS70 in Rotterdam. 2026-04-17 incident recovered + hardened. Bot/n8n/caddy active. Root/VNC password rotation pending.
type: project
originSessionId: 923c00c5-a78e-457b-ab0c-851d2987f1af
2026-04-17 Incident — root cause and recovery
- Real root cause: fail2ban banned 193.93.78.10 (Serhii's home IP, which is ALSO the Cowork sandbox egress IP because sandbox runs locally on his machine). Trigger: 4×
Failed password for root in PowerShell SSH attempts at 08:32 and 08:34 UTC (maxretry=3, bantime=24h). fail2ban has persistent.bdb, so the ban survived the 09:31 UTC kernel-upgrade reboot via Restore Ban.
- Confusing detour: VNC
nft flush ruleset looked like it "fixed firewall" — actually it just temporarily wiped fail2ban's addr-set-sshd. fail2ban re-populated it soon after.
- Secondary issue: Telegram bot silent 15-17 Apr (~37 h before reboot) — Claude CLI polling apparently got stuck in the running tmux session, but systemd thought service was fine.
- Third issue (after reboot): Claude Code v2.1.112 shows interactive "Enable auto mode?" prompt at startup → new bot session blocked until user presses 1. Fixed by watchdog (see below).
Hardening done 2026-04-17
/etc/fail2ban/jail.local → ignoreip = 127.0.0.1/8 ::1 193.93.78.10 (permanent whitelist for our shared egress IP). Reload with systemctl reload fail2ban.
- UFW re-enabled with existing allow rules (22/tcp, 80/tcp, 443/tcp, 6080/tcp all IPv4+IPv6; 5001/tcp from 172.18.0.0/16 for BioGaia Docker Caddy).
ufw status verbose to confirm.
/etc/apt/apt.conf.d/50unattended-upgrades: Automatic-Reboot "false" and Automatic-Reboot-WithUsers "false" — kernel updates no longer auto-reboot. Backup at same filename with .bak-YYYYMMDD-HHMMSS suffix.
/srv/services/claude-watchdog/watchdog.py extended (v2): tmux-session liveness check + auto-mode prompt unlock (tmux send-keys "1" Enter) + restart cooldown 10 min. Backup at .bak-YYYYMMDD-HHMMSS. State file /tmp/claude-watchdog-state.json has new keys last_bot_restart and last_automode_unlock.
- Telegram bot token rotated via @BotFather /revoke (old token returns 401 Unauthorized now). Sandbox ed25519 key added to
/root/.ssh/authorized_keys (fingerprint SHA256:tA5mTCBfdOkF+cCVO2h97Y6EMdxx76VqfyE+28+Cudg) — REPLACED 2026-04-23: orphan (private part lost with sandbox reset). New key claude-desktop-2026-04-23 (fp SHA256:h2WYv5Xf1L8vzm4Ixa9Gh6+DGAmIPOdBv+/WavO7E+8), private part now in Windows Credential Manager. Registry at /srv/passepartout/ssh/. See reference_vps_ssh.md.
Still pending (require user action)
- [ ] Rotate root password (old
SVz5i9061t2sHdWvZC passed through chat). User should set via SolusVM console or passwd in SSH.
- [ ] Rotate VNC password in SolusVM panel (
QeTydYCb was in chat). Done in vpspanel.twinservers.net:5656.
- [ ] Optional: second bot token rotation without passing token through chat (current
AAEzlp1... was sent via chat — low risk for a personal-use bot but not zero).
VNC keyboard layout gotcha (for future reference)
- QEMU VNC for this VPS mis-translates
_, >>, | (underscore→dash, >>→.., |→).
- In
asyncvnc, hold Shift + press minus to produce proper _. Avoid complex shell via VNC — get SSH back ASAP.
Server Details
- Provider: HOSTiQ (hostiq.ua)
- Plan: kVPS70 (3 vCPU, 6 GB RAM, 70 GB SSD)
- OS: Ubuntu 24.04.4 LTS
- IP: 31.131.26.203
- Hostname: hqnl0398037.online-vm.com
- Datacenter: Rotterdam, Netherlands
- Payment: Quarterly (3869.80 грн), next payment 13/07/2026
- SolusVM Panel: vpspanel.twinservers.net:5656 (login: hq237287)
Installed Software (as of 2026-04-13)
- Node.js v22.22.2, npm 10.9.7
- Bun 1.3.12
- Docker 29.4.0 + Docker Compose
- Claude Code 2.1.104 (Sonnet 4.6, Max subscription, OAuth auth)
- Gemini CLI 0.37.1 (Google AI Ultra for Business, OAuth auth)
- UFW firewall (ports 22, 80, 443)
- Caddy 2 (Docker, reverse proxy)
- n8n latest (Docker, port 5678 localhost only)
Telegram Channels — FULLY WORKING + PERSISTENT
- Bot: @my27claudeclawbot (ClaudeClaw bot)
- Plugin: telegram@claude-plugins-official
- Serhii's Telegram ID 312194208, dmPolicy: allowlist
- Systemd service: claude-bot.service (enabled, auto-starts on reboot)
- Service file: /etc/systemd/system/claude-bot.service
- Start script: /usr/local/bin/claude-bot-start.sh
- TELEGRAM_BOT_TOKEN set in systemd service Environment directive
- Token format: 8718732237:XXX (bot_id stays the same across rotations)
- Token rotated 2026-04-17 after SSH recovery incident (old token revoked via @BotFather /revoke)
- Token stored in 6 files on VPS: /etc/systemd/system/claude-bot.service, /usr/local/bin/{claude-bot-start,security-alert,weekly-review,morning-checkin,ssh-login-alert}.sh — use
grep -rIEl TELEGRAM_BOT_TOKEN /etc/systemd /usr/local/bin to find them all
- PATH includes /root/.bun/bin (required for bun/Telegram plugin)
- Working directory: / (systemd default)
- tmux session name: claude-bot
Directory Structure
- /srv/ — main services directory
- /srv/docker-compose.yml — Caddy + n8n
- /srv/caddy/Caddyfile — reverse proxy config (currently serves "AG Dev Hub Server is running" on :80)
- /srv/wiki/ — LLM Wiki git repo (master branch, 4 project stubs)
- /srv/services/ — web services (empty, ready for future apps)
- /srv/CLAUDE.md — instructions for server-side Claude Code agent
Claude Code Desktop SSH Connection
- Name: "База хостік"
- SSH Host: root@31.131.26.203
- Working directory: /srv
- Model set to Sonnet 4.6 in ~/.claude/settings.json
- Desktop Claude Code via SSH was connecting but had issues with responsiveness — may need troubleshooting
Shared Memory (LLM Wiki)
- /srv/wiki/ → GitHub private repo: github.com/serhiivereschak/ag-wiki
- Desktop clone: D:\Users\Sergey.Vereschak.DELTAMEDICAL\Documents\ag-wiki
- 4 project folders: lunar-hubble, ad-analytics, pediatric-news, zest-content
- GitHub PAT stored in /root/.git-credentials
- New PAT (2026-04-14):
claude-server-vps — repo+workflow, No expiration. Saved in ag-wiki/infrastructure/index.md
- Old compromised token ghp_JKP6MA5AC1Ajzv... — відкликано
Remaining Setup Steps (priority order)
- n8n domain — point domain to n8n, configure Caddy reverse proxy
- VPS git setup — server Claude should pull ag-wiki and run git credential setup from infrastructure/index.md
- Voice layer (later) — faster-whisper + ukrainian-tts, requires upgrade to kVPS90
Why: Central server for Serhii's multi-agent infrastructure — Claude Code orchestrates via Telegram, Gemini CLI handles heavy dev tasks, n8n automates workflows.
How to apply: SSH to 31.131.26.203. Services in /srv/. Telegram bot runs as systemd service claude-bot.service — starts automatically on reboot. To manage: systemctl start/stop/status claude-bot.