{"id":1995,"date":"2026-01-28T05:34:20","date_gmt":"2026-01-28T05:34:20","guid":{"rendered":"https:\/\/veerhost.com\/?p=1995"},"modified":"2026-02-19T12:02:57","modified_gmt":"2026-02-19T12:02:57","slug":"openclaw-security-guide","status":"publish","type":"post","link":"https:\/\/veerhost.com\/de\/openclaw-security-guide\/","title":{"rendered":"OpenClaw Security Guide: How to Protect Your VPS From Hackers, Scanners, and Vulnerabilities"},"content":{"rendered":"<p class=\"wp-block-paragraph\">Running <strong>OpenClaw<\/strong> (or any always-online bot service) on a <strong>VPS<\/strong> is powerful\u2014but it also makes your server a target. The reality is that most attacks aren\u2019t personal. The internet is full of automated scanners that continuously probe VPS IPs for <strong>open ports<\/strong>, <strong>weak SSH<\/strong>, <strong>exposed dashboards<\/strong>, <strong>public databases<\/strong>, and <strong>misconfigured webhooks<\/strong>. If OpenClaw is new (or quickly evolving), it\u2019s even more important to lock things down before you go live.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide is a complete, practical playbook to secure your VPS when running OpenClaw. It covers the most common ways VPS machines get compromised and shows you exactly how to protect yourself with hardening, firewall rules, safe networking, proper secrets management, monitoring, and incident response.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Security Disclaimer:<\/strong> This article is general security guidance. Security is a process, not a one-time setup. Apply the steps that fit your environment, keep your system updated, and treat your bot token, database credentials, and SSH access like the keys to your home.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Table of Contents<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Threat Model: How Hackers Actually Target VPS Bots<\/li>\n\n\n\n<li>The \u201cGolden Rules\u201d for Securing OpenClaw<\/li>\n\n\n\n<li>VPS Hardening: Secure SSH, Users, and Updates<\/li>\n\n\n\n<li>Firewall &amp; Port Exposure: Close Everything You Don\u2019t Need<\/li>\n\n\n\n<li>Run OpenClaw Safely: Localhost Binding, Reverse Proxies, and Least Privilege<\/li>\n\n\n\n<li>Webhooks &amp; Dashboards: HTTPS, Auth, and Rate Limiting<\/li>\n\n\n\n<li>Database Security: Local-Only, Permissions, and Backups<\/li>\n\n\n\n<li>Secrets: <code>.env<\/code> Safety, Rotation, and Leak Prevention<\/li>\n\n\n\n<li>Monitoring &amp; Alerts: Logs, Audit Trails, and Suspicious Activity<\/li>\n\n\n\n<li>Malware &amp; Persistence Checks: What to Look For<\/li>\n\n\n\n<li>Incident Response: What to Do If You Think You\u2019re Compromised<\/li>\n\n\n\n<li>Security Maintenance Checklist (Weekly\/Monthly)<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">1) Threat Model: How Hackers Target OpenClaw VPS Deployments<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Before you secure anything, understand the common attack paths. Most compromises happen through a handful of repeating patterns:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A) Open Ports<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Attackers scan public IP ranges for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Open SSH (22)<\/li>\n\n\n\n<li>Open bot ports (3000\/5000\/8080\/etc.)<\/li>\n\n\n\n<li>Exposed databases (3306 MySQL, 5432 PostgreSQL, 6379 Redis)<\/li>\n\n\n\n<li>Exposed admin dashboards and panels<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">B) Weak SSH Security<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Common failures:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Password login enabled (brute-forced)<\/li>\n\n\n\n<li>Root login allowed<\/li>\n\n\n\n<li>Reused credentials<\/li>\n\n\n\n<li>No rate limiting (thousands of guesses per minute)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">C) Exposed Webhooks \/ Admin Endpoints<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If your bot exposes <code>\/webhook<\/code>, <code>\/admin<\/code>, <code>\/panel<\/code>, <code>\/debug<\/code>, or a health endpoint returning too much info, scanners will find it and try:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Credential stuffing<\/li>\n\n\n\n<li>Default passwords<\/li>\n\n\n\n<li>Exploit attempts against known framework vulnerabilities<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">D) Dependency Vulnerabilities<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Node\/Python projects often pull many dependencies. If you run outdated packages, attackers may exploit:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Known RCE vulnerabilities<\/li>\n\n\n\n<li>Prototype pollution (Node)<\/li>\n\n\n\n<li>Unsafe deserialization (Python)<\/li>\n\n\n\n<li>Misconfigured debug modes<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">E) Leaked Secrets<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is extremely common:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>.env<\/code> pushed to Git<\/li>\n\n\n\n<li>Tokens pasted into public chats\/screenshots<\/li>\n\n\n\n<li>Server logs containing secrets<\/li>\n\n\n\n<li>World-readable <code>.env<\/code> (<code>chmod 644<\/code>)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">2) The Golden Rules for Securing OpenClaw<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If you do nothing else, do these:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Expose the fewest ports possible<\/strong> (ideally only 22 + 80\/443 if using HTTPS).<\/li>\n\n\n\n<li><strong>SSH keys only<\/strong> + <strong>disable password login<\/strong> + <strong>disable root login<\/strong>.<\/li>\n\n\n\n<li><strong rtrvr-ls=\"0~hs,5~hs,6~hs,8~hs,9~hs,12~ow,13~lc,15~ow,16~hs,47~lc\">Bind OpenClaw<\/strong> <strong rtrvr-ls=\"0~hs,5~hs,6~hs,8~hs,9~hs,12~ow,13~lc,15~ow,16~hs,47~lc\">to localhost (127.0.0.1)<\/strong> if using a reverse proxy.<\/li>\n\n\n\n<li><strong>Never expose your database to the public internet<\/strong>.<\/li>\n\n\n\n<li><strong>Keep OS + dependencies updated<\/strong> and remove unused services.<\/li>\n\n\n\n<li><strong>Use least privilege<\/strong>: run OpenClaw as a non-root user with minimal permissions.<\/li>\n\n\n\n<li><strong>Monitor logs<\/strong> and use brute-force protections like Fail2ban.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">3) VPS Hardening: Secure SSH, Users, and Updates<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">3.1 Create a non-root user (if you\u2019re using root now)<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>adduser molt\nusermod -aG sudo molt\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Switch to that user:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>su - molt\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3.2 Update the system<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update &amp;&amp; sudo apt -y upgrade\nsudo apt -y install curl git ufw unzip\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3.3 Use SSH keys (recommended)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On your local machine:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-keygen -t ed25519\nssh-copy-id molt@YOUR_VPS_IP\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Test login:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh molt@YOUR_VPS_IP\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3.4 Lock down SSH (critical)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Edit SSH configuration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/ssh\/sshd_config\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set (or ensure) these values:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PermitRootLogin no\nPasswordAuthentication no\nPubkeyAuthentication yes\nChallengeResponseAuthentication no\nUsePAM yes\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restart SSH:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart ssh\n<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Important: Make sure you can still log in with keys before disabling password auth.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">4) Firewall &amp; Port Exposure: Close Everything You Don\u2019t Need<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">4.1 Set strict firewall defaults<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw default deny incoming\nsudo ufw default allow outgoing\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Allow SSH:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow OpenSSH\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you use webhooks or a dashboard behind HTTPS, allow web traffic:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow 80\nsudo ufw allow 443\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enable firewall:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw enable\nsudo ufw status\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4.2 Make sure OpenClaw\u2019s internal port is NOT public<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If your bot runs on port <code>3000<\/code>, <strong>do not<\/strong> open it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw delete allow 3000 2&gt;\/dev\/null || true\nsudo ufw status\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4.3 Check what\u2019s listening publicly<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ss -tulpn\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You want sensitive services to bind to <code>127.0.0.1<\/code> (localhost), not <code>0.0.0.0<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">5) Run OpenClaw Safely: Localhost Binding, Reverse Proxies, Least Privilege<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">5.1 Run OpenClaw as a non-root user<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Never run your bot with <code>sudo node ...<\/code> or as root.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you use PM2 (Node):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pm2 start \"npm start\" --name openclaw\npm2 save\npm2 startup\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you use systemd (Python or Node), run it under your non-root user.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5.2 Bind to localhost only (very important)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Bad<\/strong> (publicly reachable):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>0.0.0.0:3000<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Good<\/strong> (local only):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>127.0.0.1:3000<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Example: Node (Express) bind to localhost<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>const host = \"127.0.0.1\";\nconst port = process.env.PORT || 3000;\n\napp.listen(port, host, () =&gt; {\n  console.log(`Listening on http:\/\/${host}:${port}`);\n});\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Example: FastAPI \/ Uvicorn bind to localhost<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>uvicorn app:app --host 127.0.0.1 --port 3000\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">5.3 Use least-privilege file permissions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you store configs in <code>.env<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod 600 .env\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ensure your project directory isn\u2019t world-writable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod -R o-w ~\/openclaw\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">6) Webhooks &amp; Dashboards: HTTPS, Auth, and Rate Limiting<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If OpenClaw uses webhooks, you should terminate TLS with a reverse proxy like <strong>Nginx<\/strong> and only forward traffic internally.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6.1 Install Nginx<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt -y install nginx\nsudo systemctl enable --now nginx\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">6.2 Reverse proxy to localhost app port<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Example Nginx server block:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    listen 80;\n    server_name YOUR_DOMAIN;\n\n    location \/ {\n        proxy_pass http:\/\/127.0.0.1:3000;\n        proxy_http_version 1.1;\n\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">6.3 Add SSL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use Let\u2019s Encrypt with Certbot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt -y install certbot python3-certbot-nginx\nsudo certbot --nginx -d YOUR_DOMAIN\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">6.4 Add Basic Auth to admin routes (recommended)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Install utility:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt -y install apache2-utils\nsudo htpasswd -c \/etc\/nginx\/.htpasswd admin\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nginx config:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>location \/admin {\n    auth_basic \"Restricted\";\n    auth_basic_user_file \/etc\/nginx\/.htpasswd;\n    proxy_pass http:\/\/127.0.0.1:3000;\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Reload Nginx:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nginx -t &amp;&amp; sudo systemctl reload nginx\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">6.5 Add rate limiting for webhooks<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This reduces bot abuse and brute attempts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In Nginx <code>http {}<\/code> block:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>limit_req_zone $binary_remote_addr zone=webhook_limit:10m rate=10r\/s;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In your server block:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>location \/webhook {\n    limit_req zone=webhook_limit burst=20 nodelay;\n    proxy_pass http:\/\/127.0.0.1:3000\/webhook;\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">7) Database Security: Local-Only, Permissions, and Backups<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">7.1 Never expose DB ports publicly<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not allow:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>3306 (MySQL)<\/li>\n\n\n\n<li>5432 (Postgres)<\/li>\n\n\n\n<li>6379 (Redis)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Check firewall rules:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw status numbered\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">7.2 Bind DB to localhost<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">MySQL<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Edit:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/mysql\/mysql.conf.d\/mysqld.cnf\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>bind-address = 127.0.0.1\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restart:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart mysql\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">PostgreSQL<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Edit:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/postgresql\/*\/main\/postgresql.conf\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>listen_addresses = 'localhost'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restart:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart postgresql\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">7.3 Use a dedicated DB user with minimal permissions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Don\u2019t use root DB users in OpenClaw.<br>Create a separate user limited to OpenClaw\u2019s database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7.4 Backups (simple examples)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Postgres:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pg_dump -U openclaw_user -d openclaw > openclaw_backup.sql\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">MySQL:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysqldump -u openclaw_user -p openclaw > openclaw_backup.sql\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Store backups securely (preferably off-server).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">8) Secrets: <code>.env<\/code> Safety, Rotation, and Leak Prevention<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">8.1 Store secrets in <code>.env<\/code> (not in code)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>BOT_TOKEN=YOUR_TOKEN\nDB_PASSWORD=STRONG_PASSWORD\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">8.2 Make <code>.env<\/code> private<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod 600 .env\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">8.3 Prevent accidental commits<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create <code>.gitignore<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nano .gitignore\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Add:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.env\n*.log\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">8.4 Rotate secrets regularly<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If your token or DB password leaks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Rotate bot token immediately<\/li>\n\n\n\n<li>Rotate DB password<\/li>\n\n\n\n<li>Revoke old keys<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">9) Monitoring &amp; Alerts: Catch Problems Early<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">9.1 Install Fail2ban (blocks brute force)<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt -y install fail2ban\nsudo systemctl enable --now fail2ban\nsudo fail2ban-client status\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">9.2 Watch auth logs<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tail -n 200 \/var\/log\/auth.log\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">9.3 Watch your bot logs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">PM2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pm2 logs openclaw\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">systemd:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -u openclaw@YOURUSER -f\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">9.4 Check for unexpected network activity<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ss -tulpn\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">10) Malware &amp; Persistence Checks (What Attackers Leave Behind)<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If a VPS is compromised, attackers often install:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Crypto miners<\/li>\n\n\n\n<li>Backdoor SSH keys<\/li>\n\n\n\n<li>Cron jobs that re-download malware<\/li>\n\n\n\n<li>Hidden processes<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">10.1 Check CPU spikes<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>top\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">10.2 Check suspicious cron jobs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">System-wide:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ls -la \/etc\/cron.*\nsudo cat \/etc\/crontab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">User crons:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>crontab -l\nsudo crontab -l\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">10.3 Check authorized SSH keys<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cat ~\/.ssh\/authorized_keys\nsudo cat \/root\/.ssh\/authorized_keys 2&gt;\/dev\/null\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">10.4 Check new users<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cut -d: -f1 \/etc\/passwd\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">10.5 Check recently modified binaries in common dirs<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo find \/usr\/bin \/usr\/local\/bin -type f -mtime -7 2&gt;\/dev\/null | head -n 50\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">11) Incident Response: If You Think You\u2019ve Been Hacked<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If you suspect compromise, don\u2019t \u201cwait and see.\u201d<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Immediate steps (fast and effective)<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Disconnect exposure<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tighten firewall immediately:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw default deny incoming\nsudo ufw allow OpenSSH\nsudo ufw allow 80\nsudo ufw allow 443\nsudo ufw enable\n<\/code><\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Rotate secrets<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bot token<\/li>\n\n\n\n<li>Database passwords<\/li>\n\n\n\n<li>Any API keys<\/li>\n<\/ul>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>Check logins<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>last -a | head -n 50\nsudo tail -n 200 \/var\/log\/auth.log\n<\/code><\/pre>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>Find suspicious processes<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>ps aux --sort=-%cpu | head\nps aux --sort=-%mem | head\n<\/code><\/pre>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li><strong>If you confirm compromise<\/strong><br>The most reliable remediation is:<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Back up only essential data (DB dumps, config templates\u2014not binaries)<\/li>\n\n\n\n<li><strong>Rebuild the VPS from a clean image<\/strong><\/li>\n\n\n\n<li>Re-deploy OpenClaw securely<\/li>\n\n\n\n<li>Restore data from trusted backups<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">In real incidents, \u201ccleaning\u201d a compromised server is often less reliable than rebuilding.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">12) Security Maintenance Checklist (Use This Forever)<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">Daily \/ Weekly<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Check bot logs for unusual errors or spikes<\/li>\n\n\n\n<li>Check auth logs for brute-force attempts<\/li>\n\n\n\n<li>Confirm only expected ports are open: <code>sudo ss -tulpn sudo ufw status<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Monthly<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Update OS: <code>sudo apt update &amp;&amp; sudo apt -y upgrade<\/code><\/li>\n\n\n\n<li>Update dependencies:\n<ul class=\"wp-block-list\">\n<li>Node: <code>npm audit<\/code> + update packages<\/li>\n\n\n\n<li>Python: update pinned versions where possible<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Rotate secrets if your risk is high (public bot, high traffic)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Every change<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If you changed ports, Nginx, or webhook routes: re-check firewall rules<\/li>\n\n\n\n<li>If you added an admin route: add auth + rate limiting<\/li>\n\n\n\n<li>If you enabled remote DB access: reconsider (and lock it down by IP)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Extra Hardening (Optional but Strong)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to go beyond basics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>SSH allowlisting<\/strong> (only your home\/office IP can SSH)<\/li>\n\n\n\n<li>Use <strong>2FA via a bastion<\/strong> (advanced setups)<\/li>\n\n\n\n<li>Put OpenClaw behind <strong>Cloud WAF\/CDN<\/strong> (for public endpoints)<\/li>\n\n\n\n<li>Run OpenClaw in a container with limited permissions<\/li>\n\n\n\n<li>Use AppArmor\/SELinux profiles (advanced)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Summary (What \u201cSecure OpenClaw on a VPS\u201d Really Means)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A secure OpenClaw deployment usually looks like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Only ports <strong>22 + 80\/443<\/strong> open<\/li>\n\n\n\n<li>Bot app listens on <strong>127.0.0.1<\/strong> only<\/li>\n\n\n\n<li>Nginx reverse proxy handles <strong>HTTPS<\/strong><\/li>\n\n\n\n<li>Admin\/dashboard routes require <strong>authentication<\/strong><\/li>\n\n\n\n<li>SSH uses <strong>keys only<\/strong>, <strong>root disabled<\/strong>, <strong>fail2ban enabled<\/strong><\/li>\n\n\n\n<li>Databases bind to <strong>localhost<\/strong>, not public internet<\/li>\n\n\n\n<li>Secrets stored safely, not committed, and rotated when needed<\/li>\n\n\n\n<li>Logs monitored regularly<\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Running OpenClaw (or any always-online bot service) on a VPS is powerful\u2014but it also makes your server a target. The reality is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1996,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[],"class_list":["post-1995","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials"],"_links":{"self":[{"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/posts\/1995","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/comments?post=1995"}],"version-history":[{"count":2,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/posts\/1995\/revisions"}],"predecessor-version":[{"id":2056,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/posts\/1995\/revisions\/2056"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/media\/1996"}],"wp:attachment":[{"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/media?parent=1995"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/categories?post=1995"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/tags?post=1995"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}