Infrastructure & DevOps

Complete production reference for VitoCoin's hosting, deployment, monitoring, backup, and security architecture. All configurations documented here are live on production nodes as of 2026-04-09.

00

Live Infrastructure Status

Real-time — auto-refreshes every 20s
● Node 1 — Frankfurt
Vitocoin
Nginx
Fail2ban
Height
Peers
Hashrate
● Node 2 — Moscow
Height
Peers
Hashrate
● Node 3 — Moscow
Height
Peers
Hashrate
Frontend CDN
LIVE
Vercel Edge — vitocoin.com
SSL / HTTPS
ENFORCED
Vercel auto-renew TLS
Nginx Proxy
ACTIVE
Port 80 → 6333, rate-limited
Backups
CRON
Every 6h, 28-file rotation
Fail2ban
ACTIVE
API abuse → 1h ban
Watchdog
5 MIN
systemd timer restarts on failure
Monitor Cron
1 MIN
CPU/RAM/height logged
CI/CD
GITHUB
Push main → Vercel auto-deploy
01

Architecture Diagram

┌─────────────────────────────────────────────────────────────────────────┐ │ USER / BROWSER │ │ https://vitocoin.com │ └────────────────────────────┬────────────────────────────────────────────┘ │ HTTPS (TLS 1.3) ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ VERCEL EDGE NETWORK (CDN) │ │ • Static files: app.html, whitepaper.html, sw.js, manifest.json, … │ │ • Global CDN — <50ms TTFB worldwide │ │ • Auto HTTPS / TLS certificate renewal │ │ • Rewrites: /api/node/* → Node 1 (195.114.193.73:6333) │ │ /api/node2/* → Node 2 (213.139.77.18:6333) │ │ /api/node3/* → Node 3 (84.201.20.90:6333) │ └──────────────┬──────────────────────┬─────────────────┬────────────────┘ │ proxied API calls │ │ ▼ ▼ ▼ ┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐ │ NODE 1 — Frankfurt │ │ NODE 2 — Moscow │ │ NODE 3 — Moscow │ │ 195.114.193.73 │ │ 213.139.77.18 │ │ 84.201.20.90 │ │ Hetzner VPS │ │ Yandex Cloud │ │ Yandex Cloud │ │ ─────────────────── │ │ ─────────────────── │ │ ─────────────────── │ │ Nginx :80 ←→ RL │ │ Nginx :80 ←→ RL │ │ Nginx :80 ←→ RL │ │ ↕ proxy │ │ ↕ proxy │ │ ↕ proxy │ │ vitocoin :6333 API │ │ vitocoin :6333 API │ │ vitocoin :6333 API │ │ vitocoin :6334 P2P │ │ vitocoin :6334 P2P │ │ vitocoin :6334 P2P │ │ Miner: 8 threads │ │ Miner: 4 threads │ │ Miner: 4 threads │ │ SQLite chainstore │ │ SQLite chainstore │ │ SQLite chainstore │ │ ─────────────────── │ │ ─────────────────── │ │ ─────────────────── │ │ Fail2ban (API abuse)│ │ Fail2ban │ │ Fail2ban │ │ UFW (deny default) │ │ UFW │ │ UFW │ │ Watchdog (5min) │ │ Watchdog (5min) │ │ Watchdog (5min) │ │ Monitor cron (1min) │ │ Monitor cron (1min) │ │ Monitor cron (1min) │ │ Backup cron (6h) │ │ Backup cron (6h) │ │ Backup cron (6h) │ └─────────┬────────────┘ └─────────┬────────────┘ └─────────┬────────────┘ │ P2P TCP │ │ └──────────────────────────┴──────────────────────────┘ Full mesh P2P — port 6334 Headers-first sync + block relay ┌─────────────────────────────────────────────────────────────────────────┐ │ SUPABASE (Auth / Wallet metadata) │ │ pjhhurgivuptqeulsqty.supabase.co │ │ • auth.users — email/password JWT auth │ │ • wallets — user_id → VITO address mapping │ │ Direct from frontend (no proxy) — anon key + RLS │ └─────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────┐ │ CI/CD — GitHub + Vercel │ │ Developer pushes to main branch │ │ → GitHub webhook triggers Vercel deployment │ │ → Vercel builds (echo 'static'), deploys static files │ │ → vitocoin.com updated in ~30 seconds │ │ Node updates: SSH push + systemctl restart │ └─────────────────────────────────────────────────────────────────────────┘
02

Hosting & SSL

Frontend — Vercel Edge

PropertyValue
PlatformVercel (Pro)
Projectvito-coin-v2
Domainvitocoin.com (custom, DNS → Vercel)
TLSAuto-provisioned via Let's Encrypt, TLS 1.2/1.3, HSTS enabled
CDNVercel Edge Network — 100+ PoPs globally, <50ms TTFB
Buildecho 'static' — zero build time, pure static delivery
CacheHTML/JS: no-cache; icons: max-age=604800

Backend Nodes — VPS

NodeProviderRegionSpecsOS
Node 1 195.114.193.73HetznerFrankfurt, DE2 vCPU, 4 GB RAMUbuntu 22.04
Node 2 213.139.77.18Yandex CloudMoscow, RU4 vCPU, 8 GB RAMUbuntu 22.04
Node 3 84.201.20.90Yandex CloudMoscow, RU4 vCPU, 8 GB RAMUbuntu 22.04
Geographic diversity note: Nodes 2 and 3 share the same datacenter region (Moscow/Yandex). A single regional outage would take 2 of 3 nodes offline simultaneously. Phase 2 expansion targets Frankfurt + New York + Singapore for full geographic redundancy.
03

CI/CD Pipeline

Frontend Deployment (Vercel — automatic)

# Deploy frontend changes:
git add -A
git commit -m "feat: describe change"
git push vercel-deploy HEAD:main --force
# → Vercel webhook triggers automatically
# → Build runs (echo 'static') in ~5s
# → Edge deployment propagates in ~25s
# → vitocoin.com updated

Manual Vercel Deploy via API

COMMIT=$(git rev-parse HEAD)
TOKEN="<vercel-token>"
curl -X POST "https://api.vercel.com/v13/deployments?teamId=<team-id>" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "vito-coin-v2",
    "gitSource": {
      "type": "github",
      "ref": "main",
      "repoId": "1199887899",
      "sha": "'"$COMMIT"'"
    },
    "target": "production"
  }'

Node Deployment (SSH push)

# Update all 3 nodes with a new api.py patch:
for IP in 195.114.193.73 213.139.77.18 84.201.20.90; do
  sshpass -p "$PASS" scp patch.py root@$IP:/tmp/patch.py
  sshpass -p "$PASS" ssh root@$IP "python3 /tmp/patch.py && systemctl restart vitocoin"
done

# Or via git pull (if node has git access):
ssh root@195.114.193.73 "cd /opt/vitocoin && git pull origin main && systemctl restart vitocoin"
Rollback: Each api.py patch creates a .bak file before modifying. To rollback: cp /opt/vitocoin/vitocoin/api.py.phase2.bak /opt/vitocoin/vitocoin/api.py && systemctl restart vitocoin
04

Monitoring

Per-Minute Monitoring Cron

Every minute, /opt/vitocoin/monitor.sh collects and logs:

# Collected fields (JSON per line in /var/log/vitocoin/monitor.log):
{
  "ts":       "2026-04-09T10:40:00Z",   # UTC timestamp
  "cpu_pct":  12,                        # CPU usage %
  "ram_pct":  34,                        # RAM usage %
  "disk_pct": 8,                         # Disk usage %
  "height":   11,                        # Current chain height
  "peers":    4,                         # P2P peer count
  "hashrate": "184.81 KH/s",             # Miner hashrate
  "mining":   true                       # Is miner running?
}

# Read last 60 minutes:
tail -60 /var/log/vitocoin/monitor.log | python3 -c "
import json,sys
for line in sys.stdin:
    d=json.loads(line)
    print(f'{d[\"ts\"]} cpu={d[\"cpu_pct\"]}% ram={d[\"ram_pct\"]}% h={d[\"height\"]} peers={d[\"peers\"]}')
"

Automated Alerts

  • Node unresponsive: If /status returns no valid JSON → systemctl restart vitocoin automatically
  • No peers for 2+ minutes: Logged as ALERT in monitor.log (manual investigation required)
  • 5-minute watchdog: vitocoin-watchdog.timer → calls healthcheck.sh → restarts node if unhealthy

Prometheus Metrics Endpoint

# Scrape endpoint (Prometheus-compatible text format):
curl http://195.114.193.73:6333/metrics

# Output sample:
# HELP vitocoin_height Current chain height
# TYPE vitocoin_height gauge
vitocoin_height 11
# HELP vitocoin_peers Connected peer count
# TYPE vitocoin_peers gauge
vitocoin_peers 4
# HELP vitocoin_chain_work Accumulated chain PoW
# TYPE vitocoin_chain_work counter
vitocoin_chain_work 47245361163

Log Locations

LogPathRotation
Node stdout/stderrjournalctl -u vitocoinsystemd journal, 7 days
System monitor/var/log/vitocoin/monitor.logCapped at 10,080 lines (7 days)
Backup log/var/log/vitocoin/backup.loglogrotate daily, 14 days
Nginx access/var/log/nginx/access.loglogrotate daily, 14 days
Nginx error/var/log/nginx/error.loglogrotate daily, 14 days
Fail2ban/var/log/fail2ban.loglogrotate weekly
05

Automated Backups

Blockchain Database Backup

Runs every 6 hours via cron on all 3 nodes. Script: /opt/vitocoin/backup.sh

# Backup process:
1. sqlite3 chainstore.db "PRAGMA wal_checkpoint(TRUNCATE);"  # flush WAL first
2. cp chainstore.db /tmp/backup_TIMESTAMP.db
3. gzip /tmp/backup_TIMESTAMP.db
4. mv → /opt/vitocoin/backups/chainstore_YYYYMMDD_HHMMSS.db.gz
5. Prune: keep last 28 backups (7 days × 4/day)

# Backup location:
/opt/vitocoin/backups/chainstore_20260409_103904.db.gz   (4.0K compressed)

# To restore from backup:
systemctl stop vitocoin
gunzip -c /opt/vitocoin/backups/chainstore_TIMESTAMP.db.gz > \
  /opt/vitocoin/chaindata/chainstore.db
systemctl start vitocoin

Backup Retention Policy

FrequencyRetentionCountStorage est.
Every 6 hours7 days28 files~112 KB (at current chain size)
Weekly rotationManual via cron: find … -mtime +30 -deleteGrows with chain
Recovery SLA: In the event of data loss on one node, the chain can be fully restored from any other running node via P2P sync (automatic on restart) or from a backup file. Current backup RPO: 6 hours maximum.

Cron Schedule (all nodes)

# crontab -l
* * * * *  /opt/vitocoin/monitor.sh >> /var/log/vitocoin/monitor.log 2>&1
0 */6 * * * /opt/vitocoin/backup.sh >> /var/log/vitocoin/backup.log 2>&1
0 2 * * 0   find /opt/vitocoin/backups -name '*.db.gz' -mtime +30 -delete
06

Performance

Frontend — Target: <2s First Contentful Paint

AssetStrategyCacheSize
app.htmlStatic, served by Vercel Edge CDNno-cache (always fresh)~350 KB
features-p1/p2.jsLazy-loaded on demandno-cache~80 KB each
Icons (PNG)Static CDNmax-age=604800 (1 week)<50 KB
Service WorkerPWA offline cacheno-cache on sw.js itself~5 KB
API callsProxied via Vercel to Node 1API headers: no-cache~1–5 KB/response

API Performance (Node-side)

  • Response time: <10ms for most endpoints at current chain size (11 blocks, 12 UTXOs)
  • SSE: 1-second push interval, persistent TCP connection — no polling overhead
  • Bottleneck: Python GIL + ThreadingHTTPServer — not suitable for >100 concurrent connections. Nginx worker process limit set to auto (matches CPU cores).

CDN Headers (vercel.json)

# HTML and JS files — never cached (always fresh):
Cache-Control: no-cache, no-store, must-revalidate

# Icons — cached aggressively:
Cache-Control: public, max-age=604800, immutable

# SSE endpoint — disable buffering:
Cache-Control: no-cache
X-Accel-Buffering: no
07

Security Hardening

Layer 1: Vercel Edge (Frontend)

  • HTTPS enforced — no HTTP access to vitocoin.com
  • Vercel's global DDoS mitigation active on all edge nodes
  • No server-side secrets in frontend code (Supabase anon key is public by design)
  • CSP headers: not yet configured (Phase 2 security hardening)

Layer 2: Nginx Rate Limiting (per-node)

# Rate limit zones (nginx.conf):
limit_req_zone  $binary_remote_addr zone=api_get:10m  rate=60r/m;   # 1 req/sec avg
limit_req_zone  $binary_remote_addr zone=api_post:10m rate=10r/m;   # 1 req/6sec avg
limit_req_zone  $binary_remote_addr zone=sse:10m      rate=5r/m;    # 5 SSE connections/min
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;            # max concurrent

# Burst allowances (nodelay = immediate 429 on burst exceeded):
GET  endpoints: burst=30 nodelay → 429 Too Many Requests
POST endpoints: burst=5  nodelay → 429
SSE  endpoint:  burst=3  nodelay + max 3 concurrent connections/IP

Layer 3: Fail2ban (API Abuse)

# /etc/fail2ban/jail.d/vitocoin.conf
[vitocoin-api]
enabled  = true
maxretry = 20          # 20 rate-limit hits in 60s → ban
findtime = 60
bantime  = 3600        # 1 hour ban
action   = iptables-multiport[ports="80,6333"]

# View current bans:
fail2ban-client status vitocoin-api

Layer 4: UFW Firewall (per-node)

# Current UFW rules (identical on all 3 nodes):
Default: deny incoming, allow outgoing

ufw allow 22/tcp      # SSH (management access)
ufw allow 80/tcp      # Nginx HTTP (rate-limited API proxy)
ufw allow 6334/tcp    # P2P port (MUST be open for blockchain sync)
# Port 6333 (direct API) is accessible but proxied; can be closed for hardening

Layer 5: Application-Level Miner Protection

# Miner auto-ban in api.py:
if hashrate > 85% of network AND hashrate > 5 MH/s:
    _MINER_BAN_LIST.add(ip)   # block further requests

# Rate limit in api.py (independent of nginx):
GET:  300 req/min/IP
POST: 60  req/min/IP

# Template requests log miner identity (wallet + hashrate) for audit
08

Firewall Rules

PortProtocolDirectionActionPurpose
22TCPInboundALLOWSSH management access
80TCPInboundALLOWNginx HTTP proxy (rate-limited) → port 6333
6333TCPInboundALLOW*Direct Python API (bypass Nginx) — consider blocking for hardening
6334TCPInboundALLOWP2P blockchain sync — MUST be open
443TCPInboundCLOSEDHTTPS on VPS not configured (SSL handled by Vercel edge only)
All othersTCP/UDPInboundDENYUFW default deny
*Port 6333 is accessible directly from the internet, bypassing Nginx rate-limiting. To enforce Nginx-only access: ufw deny 6333/tcp on each node. Vercel proxies all web traffic through port 6333 via the Nginx :80 proxy chain — direct 6333 access is only used for debugging.
09

Security Checklist

  • HTTPS enforced on vitocoin.com — Vercel auto-renew Let's Encrypt TLS. HTTP redirected to HTTPS at edge.
  • Nginx rate limiting active on all 3 nodes — 60 GET/min, 10 POST/min per IP. SSE limited to 5 connections/min.
  • Fail2ban active — 20 rate-limit hits in 60s → 1-hour IP ban on ports 80 and 6333.
  • UFW firewall configured — deny all inbound except SSH (22), Nginx proxy (80), P2P (6334).
  • Malicious path blocking in Nginxwp-admin, phpmyadmin, .env, .git return 444 (no response).
  • Application-level rate limiter in api.py — 300 GET/60 POST per IP per minute. Miner registry with 85% hashrate auto-ban.
  • No secrets in frontend code — Supabase anon key is public by design. Private keys never stored on server.
  • Nginx security headers — X-Frame-Options: DENY, X-Content-Type-Options: nosniff, X-XSS-Protection, Referrer-Policy on all responses.
  • Port 6333 accessible directly (bypasses Nginx) — Low risk currently. Recommended: ufw deny 6333/tcp to enforce all API traffic through Nginx rate-limiter. Not yet applied to avoid breaking Vercel proxy.
  • 51% attack risk is high at current hashrate — Network ~900 KH/s; any GPU can exceed this. Disclosed. Risk reduces as external miners join.
  • No CSP (Content Security Policy) headers — Frontend XSS protection not yet configured. Priority Phase 2 item.
  • TODO: SSH key-only auth — Nodes currently use password auth. Recommend: disable PasswordAuthentication in sshd_config, use SSH keys only.
  • TODO: HTTPS on node APIs — Node APIs serve HTTP only. For direct API consumers: consider adding a self-signed cert or Let's Encrypt via certbot + Nginx HTTPS listener on port 443.
  • TODO: Off-site backup replication — Current backups stored on-node only. Recommend: rsync backups to a separate S3 bucket or remote server nightly.
  • TODO: Alert notifications — Monitor alerts currently write to log only. Recommend: integrate with Telegram bot or email for critical alerts (node down, peers=0).