{"id":32663,"date":"2026-08-03T00:44:05","date_gmt":"2026-08-02T22:44:05","guid":{"rendered":"https:\/\/contabo.com\/blog\/?p=32663"},"modified":"2026-08-03T00:44:08","modified_gmt":"2026-08-02T22:44:08","slug":"vps-hacked-recovery","status":"publish","type":"post","link":"https:\/\/contabo.com\/blog\/vps-hacked-recovery\/","title":{"rendered":"VPS Got Hacked: Recovery Steps and How to Secure"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">This happens more than you&#8217;d think \u2014 and it is recoverable. The most important thing to understand upfront: a compromised VPS cannot be fully trusted again, even after removing obvious malware. Attackers install backdoors in places that are very hard to find without forensic expertise. The correct path is to provision a clean server, restore only verified data, and harden before going live. If you are on Contabo, you can spin up a fresh VPS in minutes from the <a href=\"https:\/\/contabo.com\/blog\/ready-for-a-fresh-look-our-new-customer-control-panel-is-live\/\">Customer Control Panel<\/a>. This guide covers both phases: what to do right now, and how to prevent it happening again.<\/p>\n\n\n\n<h2 id=\"h-the-two-phase-recovery-plan-at-a-glance\" class=\"wp-block-heading\">The Two-Phase Recovery Plan at a Glance<\/h2>\n\n\n\n<div class=\"vpsr-table-wrap\" role=\"region\" aria-label=\"Two-phase VPS hack recovery plan\" tabindex=\"0\">\n  <style>\n    .vpsr-table-wrap{overflow-x:auto;margin:24px 0;font-family:Calibri,\"Segoe UI\",Arial,sans-serif;}\n    .vpsr-table{width:100%;border-collapse:collapse;font-size:15px;line-height:1.5;color:#2b2b2b;min-width:560px;}\n    .vpsr-table caption{text-align:left;font-weight:700;font-size:16px;color:#365F91;margin-bottom:10px;caption-side:top;}\n    .vpsr-table thead th{background:#365F91;color:#ffffff;font-weight:700;text-align:left;padding:12px 14px;border:1px solid #365F91;}\n    .vpsr-table tbody td{padding:12px 14px;border:1px solid #d9e2ef;vertical-align:top;}\n    .vpsr-table tbody tr:nth-child(even){background:#f4f7fb;}\n    .vpsr-table tbody tr td:first-child{font-weight:700;color:#4F81BD;white-space:nowrap;}\n    .vpsr-table tbody tr td:last-child{font-weight:600;color:#365F91;white-space:nowrap;}\n  <\/style>\n  <table class=\"vpsr-table\">\n    <caption>Two-phase VPS hack recovery plan: rebuild, then harden<\/caption>\n    <thead>\n      <tr>\n        <th scope=\"col\">Phase<\/th>\n        <th scope=\"col\">Steps<\/th>\n        <th scope=\"col\">Time estimate<\/th>\n      <\/tr>\n    <\/thead>\n    <tbody>\n      <tr>\n        <td>Phase 1: Rebuild (now)<\/td>\n        <td>1. Snapshot if evidence needed \u2192 2. Provision clean VPS \u2192 3. Restore verified data only \u2192 4. Rotate all credentials<\/td>\n        <td>~30\u201360 min<\/td>\n      <\/tr>\n      <tr>\n        <td>Phase 2: Harden (before going live)<\/td>\n        <td>5. Non-root sudo user \u2192 6. SSH keys + disable passwords \u2192 7. UFW firewall \u2192 8. Fail2ban \u2192 9. Auto-updates \u2192 10. network-level Firewall<\/td>\n        <td>~30 min<\/td>\n      <\/tr>\n    <\/tbody>\n  <\/table>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Phase 1: Immediate Recovery \u2014 What to Do Right Now<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A determined attacker installs backdoors in modified system binaries, hidden cron jobs, and kernel-level rootkits that are extremely difficult to detect. Trying to clean a compromised server is risky \u2014 you may miss something. The approach recommended across the security community: wipe and rebuild from a clean OS image. It is faster, safer, and more reliable than forensic cleanup for solo developers and small teams.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Take a Snapshot First (If You Need Evidence)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before touching anything: if you need a record of what happened \u2014 for a client report, insurance, or legal reasons \u2014 take a snapshot of the compromised server from the Contabo CCP before wiping. Navigate to new.contabo.com, select your server, and take a snapshot. This preserves the compromised state for later inspection. If you have no need to preserve evidence, skip straight to Step 2.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Provision a Fresh VPS<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Do not attempt to clean the compromised server. Log in to the Contabo Customer Control Panel, provision a new <a href=\"https:\/\/contabo.com\/en\/vps\/\">VPS<\/a>, and choose a current supported OS image \u2014 Ubuntu LTS or Debian stable are both solid choices. Start completely fresh: do not restore any system configuration or installed packages from the old server.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Restore Only Verified Data<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Not everything from the old server is safe to restore. Use this as your guide:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Safe to restore: database dumps (inspect for injected content first \u2014 see command below), user-uploaded files (scan for malicious scripts), application code from a known-clean Git repository or local backup.<\/li>\n\n\n\n<li>Do NOT restore: system configuration files, SSH config, cron jobs, installed packages or binaries from the old server. Any of these could carry a backdoor across.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code># Before restoring a database dump, grep for suspicious injected strings:<br>grep -i '&lt;script\\|exec(\\|eval(\\|base64' backup.sql<br><br># Check application files for common webshell patterns:<br>grep -rn 'eval(base64_decode\\|system($_\\|passthru(' .\/app\/<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Rotate Every Credential That Touched the Old Server<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Assume all of the following were exposed. Rotate them before the new server goes live:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SSH keys \u2014 generate entirely new ones. Never copy old private keys to the new server.<\/li>\n\n\n\n<li>Database passwords \u2014 all users, not just root.<\/li>\n\n\n\n<li>API keys and tokens your application used (payment providers, email services, third-party APIs).<\/li>\n\n\n\n<li>Any credentials stored in .env files or application config on the old server.<\/li>\n\n\n\n<li>Your Contabo CCP password and 2FA codes if you have any reason to suspect account-level access.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Phase 2: Harden the New Server Before Going Live<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The new server is clean. Before restoring your application or pointing your domain, run through this sequence. These steps address the entry vectors that most commonly enable VPS compromises: root login left enabled, password-based SSH, and unnecessary open ports. Each step below closes one of them.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Create a Non-Root Sudo User<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>adduser &#91;username]<br>usermod -aG sudo &#91;username]<br>su - &#91;username]<br># Do all further setup as this user. Never log in as root again.<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: SSH Keys Only \u2014 Disable Password Authentication<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Generate new keys locally, copy to the new server, verify they work \u2014 then lock down SSH.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># On your LOCAL machine \u2014 generate fresh keys:<br>ssh-keygen -t ed25519 -C \"your@email.com\"<br><br># Copy to the new VPS:<br>ssh-copy-id &#91;username]@&#91;new-server-ip]<br><br># Test key login in a NEW terminal before changing SSH config.<br># Then edit \/etc\/ssh\/sshd_config:<br><br>PermitRootLogin no<br>PasswordAuthentication no<br>PubkeyAuthentication yes<br><br>sudo systemctl restart sshd<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 7: Enable UFW Firewall (Default-Deny)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Allow SSH first \u2014 or you will lock yourself out:<br>sudo ufw allow &#91;ssh-port]\/tcp<br>sudo ufw allow 80\/tcp<br>sudo ufw allow 443\/tcp<br><br>sudo ufw default deny incoming<br>sudo ufw default allow outgoing<br>sudo ufw enable<br>sudo ufw status verbose<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 8: Install Fail2ban<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install fail2ban -y<br>sudo cp \/etc\/fail2ban\/jail.conf \/etc\/fail2ban\/jail.local<br><br># In jail.local, find &#91;sshd] and set:<br># bantime = 1h<br># maxretry = 5<br># findtime = 10m<br><br>sudo systemctl enable --now fail2ban<br>sudo fail2ban-client status sshd<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 9: Enable Automatic Security Updates<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install unattended-upgrades -y<br>sudo dpkg-reconfigure --priority=low unattended-upgrades<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 10: Activate Contabo Firewall in the Customer Control Panel<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/contabo.com\/en\/firewall\/\">Contabo Firewall<\/a> is included free with every <a href=\"https:\/\/contabo.com\/en\/vps\/\">VPS<\/a> and <a href=\"https:\/\/contabo.com\/en\/vps-dedicated\/\">Max Performance VPS<\/a>. It runs at the network level, filtering traffic before it reaches the OS, and stays active even during server reboots. Navigate to new.contabo.com \u2192 Network Services \u2192 Firewall, create a firewall, and add inbound rules for the ports you allowed in Step 7. Set everything else to deny. This pairs with UFW to give you two independent filtering layers: one at the network edge, one at the OS level.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Likely Went Wrong: The Three Most Common Entry Points<\/h2>\n\n\n\n<style>\n.cb-table-wrap{margin:24px 0;overflow-x:auto;font-family:Calibri,\"Segoe UI\",Arial,sans-serif;}\n.cb-table{width:100%;border-collapse:collapse;font-size:15px;line-height:1.5;color:#333;}\n.cb-table caption{caption-side:top;text-align:left;font-weight:600;font-size:16px;color:#365F91;margin-bottom:8px;}\n.cb-table thead th{background:#4F81BD;color:#fff;text-align:left;padding:12px 14px;font-weight:600;border:1px solid #4F81BD;}\n.cb-table tbody td{padding:12px 14px;border:1px solid #dbe5f1;vertical-align:top;}\n.cb-table tbody tr:nth-child(even){background:#f4f8fc;}\n.cb-table tbody tr:hover{background:#eaf1fa;}\n.cb-table code{background:#eef2f7;padding:1px 5px;border-radius:3px;font-size:13px;}\n@media (max-width:600px){\n  .cb-table thead{display:none;}\n  .cb-table, .cb-table tbody, .cb-table tr, .cb-table td{display:block;width:100%;}\n  .cb-table tbody tr{margin-bottom:12px;border:1px solid #dbe5f1;border-radius:6px;overflow:hidden;}\n  .cb-table td{border:none;border-bottom:1px solid #eef2f7;padding:10px 14px;}\n  .cb-table td::before{content:attr(data-label);display:block;font-weight:600;color:#4F81BD;font-size:12px;text-transform:uppercase;letter-spacing:.03em;margin-bottom:4px;}\n}\n<\/style>\n<div class=\"cb-table-wrap\">\n<table class=\"cb-table\">\n\n<thead>\n<tr>\n<th scope=\"col\">Entry Vector<\/th>\n<th scope=\"col\">The Fix<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-label=\"Entry Vector\">Root login left enabled \u2014 the primary target of automated SSH attacks<\/td>\n<td data-label=\"The Fix\">Steps 5 + 6 \u2014 create non-root sudo user, set <code>PermitRootLogin no<\/code><\/td>\n<\/tr>\n<tr>\n<td data-label=\"Entry Vector\">Password-based SSH \u2014 brute-forced by bots within hours of provisioning<\/td>\n<td data-label=\"The Fix\">Step 6 \u2014 SSH keys only, set <code>PasswordAuthentication no<\/code><\/td>\n<\/tr>\n<tr>\n<td data-label=\"Entry Vector\">Unnecessary open ports \u2014 exposes services that should not be public<\/td>\n<td data-label=\"The Fix\">Steps 7 + 10 \u2014 UFW default-deny + Contabo network Firewall<\/td>\n<\/tr>\n<tr>\n<td data-label=\"Entry Vector\">Crypto miner running (common sign of compromise, not entry vector)<\/td>\n<td data-label=\"The Fix\">Detect with <code>top<\/code> or <code>ps aux | grep -i xmrig<\/code> \u2014 then proceed with Phase 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n\n\n\n<div class=\"wp-block-uagb-advanced-heading uagb-block-f1c522bb\"><h2 class=\"uagb-heading-text\">FAQ: VPS Hacked \u2014 What To Do<\/h2><\/div>\n\n\n\n<div class=\"schema-faq wp-block-yoast-faq-block\"><div class=\"schema-faq-section\" id=\"faq-question-1785709337927\"><strong class=\"schema-faq-question\">Can I clean a hacked VPS without reinstalling?<\/strong> <p class=\"schema-faq-answer\">Technically yes, but it is not recommended for most cases. A skilled attacker can install rootkits hidden in system binaries or kernel modules that are extremely difficult to detect without forensic tools. For the majority of solo developers and small teams, wiping and rebuilding from a clean OS image is faster, safer, and more reliable. Reserve the forensic investigation path for situations where evidence preservation is legally required.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1785709351407\"><strong class=\"schema-faq-question\">How do I know if my VPS is running a crypto miner?<\/strong> <p class=\"schema-faq-answer\"># Check for processes consuming 90-100% CPU:<br>top<br># or:<br>htop<br><br># Search for common miner process names:<br>ps aux | grep -i &#8216;xmrig\\|miner\\|monero&#8217;<br><br># Check for suspicious cron jobs:<br>crontab -l<br>cat \/etc\/cron.d\/*<br>cat \/etc\/cron.daily\/*<br>A process running at near-100% CPU with an unfamiliar name is a strong signal. Crypto miners were cited in roughly 43% of AI responses as the most common visible sign of a compromised VPS \u2014 often installed within hours of the initial breach.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1785709366419\"><strong class=\"schema-faq-question\">Should I contact Contabo if my VPS is hacked?<\/strong> <p class=\"schema-faq-answer\">Yes \u2014 contact Contabo support if the compromise may have affected network infrastructure, if your server is being used to send spam or attack other hosts (which can lead to suspension), or if you need help with the rescue mode or snapshot process. Contabo&#8217;s support team is available 24\/7 via the Customer Control Panel. Acting quickly limits potential collateral damage and keeps your account in good standing.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1785709378213\"><strong class=\"schema-faq-question\">What is the fastest way to recover a hacked Contabo VPS?<\/strong> <p class=\"schema-faq-answer\">Snapshot the old server if you need evidence \u2192 provision a new Contabo VPS from the CCP (takes a few minutes) \u2192 restore only application data from a clean backup \u2192 run the ten hardening steps in Phase 2 before going live. For a typical small deployment, total recovery time is one to two hours.<\/p> <\/div> <\/div>\n","protected":false},"excerpt":{"rendered":"<p>This happens more than you&#8217;d think \u2014 and it is recoverable. The most important thing to understand upfront: a compromised VPS cannot be fully trusted again, even after removing obvious malware. Attackers install backdoors in places that are very hard to find without forensic expertise. The correct path is to provision a clean server, restore [&hellip;]<\/p>\n","protected":false},"author":78,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":"","_members_access_role":[],"_members_access_error":""},"categories":[18],"tags":[],"ppma_author":[4285],"class_list":["post-32663","post","type-post","status-publish","format-standard","hentry","category-tutorials"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Jie Guo","author_link":"https:\/\/contabo.com\/blog\/author\/jieguo\/"},"uagb_comment_info":0,"uagb_excerpt":"This happens more than you&#8217;d think \u2014 and it is recoverable. The most important thing to understand upfront: a compromised VPS cannot be fully trusted again, even after removing obvious malware. Attackers install backdoors in places that are very hard to find without forensic expertise. The correct path is to provision a clean server, restore&hellip;","authors":[{"term_id":4285,"user_id":78,"is_guest":0,"slug":"jieguo","display_name":"Jie Guo","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/4e0d981b06988d6d456834e9d55bc9e713e918fa8444325543d14f448154106b?s=96&d=mm&r=g","author_category":"","user_url":"","last_name":"Guo","first_name":"Jie","job_title":"","description":""}],"_links":{"self":[{"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/posts\/32663","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/users\/78"}],"replies":[{"embeddable":true,"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/comments?post=32663"}],"version-history":[{"count":1,"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/posts\/32663\/revisions"}],"predecessor-version":[{"id":32664,"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/posts\/32663\/revisions\/32664"}],"wp:attachment":[{"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/media?parent=32663"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/categories?post=32663"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/tags?post=32663"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/contabo.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=32663"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}