{"id":2003,"date":"2026-01-28T10:21:08","date_gmt":"2026-01-28T10:21:08","guid":{"rendered":"https:\/\/veerhost.com\/docs\/vps\/how-to-secure-and-harden-moltbot-on-a-veerhost-vps-formerly-clawdbot\/"},"modified":"2026-03-31T17:54:49","modified_gmt":"2026-03-31T17:54:49","slug":"how-to-secure-and-harden-openclaw-on-a-veerhost-vps","status":"publish","type":"docs","link":"https:\/\/veerhost.com\/de\/docs\/vps\/how-to-secure-and-harden-openclaw-on-a-veerhost-vps\/","title":{"rendered":"How to Secure and Harden OpenClaw on a VeerHost VPS"},"content":{"rendered":"<p class=\"wp-block-paragraph\">Running OpenClaw on a VPS gives you full control, but it also makes you responsible for server security. This guide shows you how to harden your VeerHost VPS so your OpenClaw deployment is harder to scan, exploit, or abuse.<\/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\">Note: Some older guides may still refer to OpenClaw as Moltbot or Clawdbot. This document uses the current name: OpenClaw.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Security principles<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before changing anything, follow these rules:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Expose as few ports as possible<\/li>\n\n\n\n<li>Run services with least privilege<\/li>\n\n\n\n<li>Keep secrets out of public repos<\/li>\n\n\n\n<li>Use HTTPS for public-facing endpoints<\/li>\n\n\n\n<li>Keep the OS and packages updated<\/li>\n\n\n\n<li>Monitor logs and restart failures quickly<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1) Keep the system updated<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run updates regularly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update &amp;&amp; sudo apt -y upgrade<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enable automatic security updates if appropriate for your workflow:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y unattended-upgrades\nsudo dpkg-reconfigure --priority=low unattended-upgrades<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2) Create a sudo user and avoid daily root login<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you are still working as root, create a dedicated admin user:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>adduser openclawadmin\nusermod -aG sudo openclawadmin<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Test sudo access:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>su - openclawadmin\nsudo whoami<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3) Use SSH keys<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Generate a key on your local machine if you do not already have one:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-keygen -t ed25519<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Copy it to the server:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-copy-id openclawadmin@YOUR_VPS_IP<\/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 openclawadmin@YOUR_VPS_IP<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4) Harden SSH<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Edit the SSH config:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/ssh\/sshd_config<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Recommended settings:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PermitRootLogin no\nPasswordAuthentication no\nPubkeyAuthentication yes\nChallengeResponseAuthentication no\nUsePAM yes\nX11Forwarding no<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Reload SSH:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl reload ssh<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Important: make sure your SSH key works before disabling password login.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5) Configure the firewall<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Allow only required traffic:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw default deny incoming\nsudo ufw default allow outgoing\nsudo ufw allow OpenSSH\nsudo ufw allow 80\nsudo ufw allow 443\nsudo ufw enable\nsudo ufw status verbose<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If OpenClaw runs behind Nginx, do not expose its internal app port publicly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6) Bind OpenClaw to localhost only<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If OpenClaw listens on port 3000, bind it to <code>127.0.0.1<\/code> instead of <code>0.0.0.0<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example Docker port binding:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ports:\n  - \"127.0.0.1:3000:3000\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This prevents direct public access while still allowing Nginx to proxy requests locally.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7) Put Nginx in front of OpenClaw<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A reverse proxy helps with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>HTTPS termination<\/li>\n\n\n\n<li>Cleaner domain routing<\/li>\n\n\n\n<li>Optional basic auth<\/li>\n\n\n\n<li>Rate limiting<\/li>\n\n\n\n<li>Hiding internal ports<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Basic example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    listen 80;\n    server_name bot.yourdomain.com;\n\n    location \/ {\n        proxy_pass http:\/\/127.0.0.1:3000;\n        proxy_http_version 1.1;\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}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">8) Enable HTTPS<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Install Certbot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y certbot python3-certbot-nginx\nsudo certbot --nginx -d bot.yourdomain.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is especially important if OpenClaw uses webhooks, dashboards, or admin endpoints over the web.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">9) Protect environment files and secrets<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Your <code>.env<\/code> file should never be world-readable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check permissions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls -l .env<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set secure permissions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod 600 .env<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Best practices:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Never commit <code>.env<\/code> to Git<\/li>\n\n\n\n<li>Rotate tokens after leaks<\/li>\n\n\n\n<li>Use strong database passwords<\/li>\n\n\n\n<li>Keep API keys out of screenshots, logs, and tutorials<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">10) Secure the database<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If PostgreSQL or MySQL is used only by OpenClaw, keep it private.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Good practice:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bind database services to localhost or Docker internal networking<\/li>\n\n\n\n<li>Do not expose database ports publicly<\/li>\n\n\n\n<li>Use a dedicated database user with limited privileges<\/li>\n\n\n\n<li>Back up the database regularly<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Check open listening ports:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ss -tulpn<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">11) Add Fail2ban<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Install Fail2ban to reduce brute-force attacks:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y fail2ban\nsudo systemctl enable fail2ban\nsudo systemctl start fail2ban<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check status:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo fail2ban-client status<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">12) Limit dashboard and webhook exposure<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If OpenClaw includes an admin panel, dashboard, or webhook endpoint:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Protect it with HTTPS<\/li>\n\n\n\n<li>Add authentication where possible<\/li>\n\n\n\n<li>Restrict by IP if only you need access<\/li>\n\n\n\n<li>Use strong random secrets<\/li>\n\n\n\n<li>Disable unused endpoints<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">13) Watch logs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check logs often for failed logins, repeated crashes, or suspicious requests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Docker logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker compose logs -f openclaw<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">System auth logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo journalctl -u ssh -n 100 --no-pager<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nginx logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tail -f \/var\/log\/nginx\/access.log \/var\/log\/nginx\/error.log<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">14) Back up critical files<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">At minimum, back up:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>.env<\/code><\/li>\n\n\n\n<li><code>docker-compose.yml<\/code><\/li>\n\n\n\n<li>Nginx config<\/li>\n\n\n\n<li>Database dumps<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Example PostgreSQL backup:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker exec -t openclaw_postgres pg_dump -U openclaw_user openclaw &gt; openclaw_backup.sql<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">15) Restart safely after changes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Whenever you change environment variables, proxy settings, or Docker config, restart the stack cleanly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker compose down\ndocker compose up -d<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then verify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker compose ps\ndocker compose logs --tail=50<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Common mistakes to avoid<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Leaving port 3000 open to the public internet<\/li>\n\n\n\n<li>Keeping root SSH login enabled<\/li>\n\n\n\n<li>Using weak passwords for the database or bot tokens<\/li>\n\n\n\n<li>Storing secrets in GitHub repositories<\/li>\n\n\n\n<li>Running outdated Docker images for months<\/li>\n\n\n\n<li>Exposing database ports like 5432 or 3306 publicly<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Quick hardening checklist<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>System updated<\/li>\n\n\n\n<li>SSH keys enabled<\/li>\n\n\n\n<li>Root SSH disabled<\/li>\n\n\n\n<li>Firewall enabled<\/li>\n\n\n\n<li>OpenClaw bound to localhost<\/li>\n\n\n\n<li>Nginx reverse proxy configured<\/li>\n\n\n\n<li>HTTPS enabled<\/li>\n\n\n\n<li><code>.env<\/code> locked down<\/li>\n\n\n\n<li>Database not publicly exposed<\/li>\n\n\n\n<li>Fail2ban installed<\/li>\n\n\n\n<li>Backups tested<\/li>\n\n\n\n<li>Logs monitored<\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Running OpenClaw on a VPS gives you full control, but it also makes you responsible for server security. This guide shows you [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1967,"menu_order":8,"comment_status":"open","ping_status":"closed","template":"","doc_tag":[],"class_list":["post-2003","docs","type-docs","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/docs\/2003","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/docs"}],"about":[{"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/types\/docs"}],"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=2003"}],"version-history":[{"count":4,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/docs\/2003\/revisions"}],"predecessor-version":[{"id":2293,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/docs\/2003\/revisions\/2293"}],"up":[{"embeddable":true,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/docs\/1967"}],"wp:attachment":[{"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/media?parent=2003"}],"wp:term":[{"taxonomy":"doc_tag","embeddable":true,"href":"https:\/\/veerhost.com\/de\/wp-json\/wp\/v2\/doc_tag?post=2003"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}