VPS Don Get Hacked? Wetin You Go Do Next
VPS don get compromised? No try clean am. Isolate am for provider firewall, snapshot the disk as evidence, rotate every key, then rebuild from clean image.
No clean a hacked VPS
If person hack your VPS, the decision wey matter pass suppose happen before you run any command. No try clean the machine. Isolate am for the provider side, take snapshot of the disk as evidence, rotate every credential wey e hold, then rebuild am for fresh server from sources wey you trust.
You no fit prove say rootkit don comot, because the tools wey suppose prove am na the same tools wey attacker dey control.
Na the whole argument be that. Make we look the mechanism behind am. Attacker wey reach root fit replace ps so one process ID no go ever show for the output. One line for /etc/ld.so.preload fit load attacker code into every dynamically linked program for the box, so ls, ss and find all go lie for the same consistent way. Loadable kernel module fit hide files below the system call, so even freshly downloaded binary go see clean disk. You delete the miner, CPU graph go drop, and server go quiet. Quiet na also how working backdoor dey look.
Rebuild cost less than how e dey feel. Typical VPS na just some packages, one config directory, and one data set, so rebuild na finite job wey get end. To search for every change wey attacker make na open-ended work, and e no ever reach proof.
Confirm say na real breach
Plenty servers wey dem report as hacked no really get breach. Thousands of failed SSH logins every day na internet background noise, because dem dey scan every public IPv4 address continuously. A lastb output wey full of root and admin attempts mean say scanners don find your port. E no mean say anybody enter.
These signals really mean something:
- Successful login wey you no fit account for, like
Accepted password for root from 203.0.113.7. - A key inside
authorized_keyswey you no add. - Abuse notice from your host about traffic wey dey leave your server.
- Process wey dey use 100% CPU and carry name wey dem copy from kernel thread. Miners wey enter through exposed Redis and Docker sockets commonly dey show under names like
kdevtmpfsiandkinsing. - Outbound connections to addresses wey none of your services dey use.
The kernel thread disguise get quick test. Real kernel threads dey print inside square brackets and dem no get executable behind them, so sudo ls -l /proc/<pid>/exe dey fail for them with No such file or directory. If process wey print as [kworker/0:2] get an exe link wey dey point to something under /tmp, na ordinary user program wey dey wear kernel name.
Run these checks knowing say the box fit dey lie to you. Dem enough to decide say something dey wrong. Dem no enough to decide say nothing dey wrong.
Cut network for provider side, no be from inside the box
Isolation come first, because every step wey follow am na waste while another person still hold shell. Reading logs, rotating keys, and restoring data no get use while live attacker still dey watch.
Do am for your provider control panel, inside network firewall wey dey run outside your operating system. Deny inbound and outbound traffic, and keep web console as your way to enter. Rules wey dem enforce there go survive anything wey happen for disk.
Get two reasons why you no suppose do this from inside the server. Firewall wey you configure inside compromised kernel dey enforced by that kernel, and root fit flush nftables as easily as you fit write am. And sudo ip link set enp1s0 down over SSH go cut your own session first, so e go lock you out of machine wey you still dey examine.
Block outbound traffic together with inbound traffic. Reverse shell dey dial out from your box go attacker, so inbound-only block go leave established connection working normally. If your provider only offer inbound rules, the remaining options na to detach network interface or power off the instance.
No reboot yet. First check whether /var/log/journal dey exist. If that directory no dey, journald dey write to /run/log/journal, wey dey memory, so reboot go delete the intrusion record. Running processes go disappear when system reboot too, and their command lines often na the clearest evidence wey you go ever get.
Disk touch anything before snapshot am
Snapshot and backup get different work for here. The snapshot wey you take now na copy of compromised disk: e be your evidence, and na the only thing wey fit let you go back if you overwrite something by mistake. Your older backups na the recovery path. If your provider panel dey use the two words loosely, read how VPS snapshots different from real backups first, because retention rules and restore behaviour no be the same.
Take the snapshot from provider panel before you log in again. Live snapshot dey crash consistent: e capture the disk as e be for that moment, just like say you pull power. That one dey okay for evidence. Give am name wey go make sure say nobody restore am by mistake. Something as direct as COMPROMISED-do-not-restore-2026-08-12 na the correct level of subtlety. Keep am until your investigation finish and any abuse ticket with your host don close.
SSH no dey again: how to enter
Two ways dey, and both dey inside provider panel. Web console (VNC or serial) go connect to the machine like say you plug keyboard directly. E go work when sshd don die, when firewall configuration wrong, and when attacker don change SSH port. E dey authenticate with local password, so server wey dey use key-only authentication fit need root password reset before console go useful.
Rescue mode na better option. E go boot small live system, with your disk attached but e no dey run, so commands wey you run dey trustworthy: compromised kernel and compromised binaries no dey execute. Mount the disk as read only.
lsblk -f
sudo mkdir -p /mnt/victim
sudo mount -o ro /dev/vda1 /mnt/victimIf lsblk show LVM (logical volume manager) volumes instead of plain partition, activate dem with sudo vgchange -ay first. Then mount the device wey appear under /dev/mapper/.
No chroot into the mounted disk just to look around. chroot go execute the attacker's binaries with your permissions, and this go destroy the main reason why you boot rescue mode.
Collect evidence wey you fit still trust
Run these commands from rescue mode, with the disk mounted read only at /mnt/victim. Start with logins, because dem show when the intrusion happen. Everything else go easier once you get the time window.
sudo grep -aE 'Accepted (password|publickey)' /mnt/victim/var/log/auth.log
sudo last -f /mnt/victim/var/log/wtmp
sudo lastb -f /mnt/victim/var/log/btmp
sudo journalctl -D /mnt/victim/var/log/journal -u ssh --since "2026-07-01"If /var/log/auth.log no dey, that one alone no mean say anything suspicious happen. Some current Ubuntu images ship without rsyslog, so sshd dey log only to the journal. Na wetin the journalctl -D line dey read. Wetin you need note na gap for logs wey otherwise dey continuous, or log file wey dem truncate reach zero bytes. Log wiping common, and attackers usually do am roughly.
Next, check the accounts and keys.
sudo find /mnt/victim/root /mnt/victim/home -name 'authorized_keys*' -exec ls -l {} +
sudo awk -F: '$3 == 0 {print $1}' /mnt/victim/etc/passwd
sudo lsattr /mnt/victim/root/.ssh/authorized_keysThe awk line prints every account wey get user ID 0. Anything apart from root for that output na second root account. The find pattern deliberately match authorized_keys2 too, because OpenSSH dey read both file names by default, and people fit easily overlook the second one. If lsattr prints an i for the attribute list, the file immutable: attacker fit set that flag so your attempt to delete the key fail with Operation not permitted, and tired admin go think say the edit work.
Persistence dey hide for small number of places, so check all of dem.
sudo ls -lt /mnt/victim/etc/systemd/system
sudo ls -l /mnt/victim/etc/cron.d /mnt/victim/var/spool/cron/crontabs
sudo cat /mnt/victim/etc/ld.so.preload
sudo grep -rnE 'curl|wget|base64|/dev/tcp' /mnt/victim/etc/update-motd.d /mnt/victim/etc/rc.local /mnt/victim/root/.bashrc /mnt/victim/root/.profile/etc/ld.so.preload no dey exist for normal Ubuntu or Debian system, so No such file or directory na the healthy result. Any content at all deserve your attention. Login file wey pipe base64 -d output enter shell na the same matter: legitimate config no need hide its own text.
Build the timeline from change time instead of modification time.
sudo find /mnt/victim -xdev -newerct '2026-08-01' -type f -printf '%TF %TT %p\n' | sorttouch fit set modification time to any value wey attacker want, so mtime fit lie cheaply. Change time (ctime) dey update whenever anything change for the inode, and touch no fit move am backwards. So -newerct give more honest list of wetin dem write recently. E still no be proof, because root fit change the system clock or write directly to the block device.
Package integrity worth one command and one warning. For live system, sudo dpkg --verify prints one line for every packaged file wey checksum no longer match. E puts 5 for the checksum column. sudo debsums -ac do the same work and include config files when dem install the debsums package. Read the result in one direction only. Changed /usr/sbin/sshd na real evidence. Clean report prove nothing, because the same root account wey replace the binary fit rewrite the checksum lists under /var/lib/dpkg/info/. Rootkit scanners like rkhunter and chkrootkit follow the same rule: hit na information, but clean run no mean say system clear.
Copy everything you collect comot from the machine before you do anything destructive.
sudo tar --ignore-failed-read -C /mnt/victim -czf /root/evidence-2026-08-12.tgz \
var/log etc root/.ssh root/.bash_history home
sha256sum /root/evidence-2026-08-12.tgzWrite that hash down somewhere wey no dey for the server. If this matter later become insurance claim or police report, showing say the archive no change since collection na wetin separate evidence from ordinary folder of files. Accidentally deleting things during investigation normal, and the snapshot plus this archive na wetin make recovery possible. To undo bad rm afterwards harder pass wetin people expect, as recover files wey rm -rf delete explain.
Find the door wey dem use enter
If rebuild no close the entry route, dem go breach you again, often within days, because the scan wey find you the first time never stop. Four doors cover most single-server breaches.
SSH password login. One Accepted password for root line from address wey you no recognise dey enough as answer. Check PasswordAuthentication inside /etc/ssh/sshd_config and every file under /etc/ssh/sshd_config.d/. sshd dey use the first value e collect for a keyword, and the Include line dey for top of the main file on Ubuntu. So, config file wey dem drop inside fit quietly override the setting wey you edit further down.
A service wey publish without authentication. Redis for 6379, Docker API for 2375, or database wey bind to 0.0.0.0 instead of 127.0.0.1. Docker na the common surprise. When you publish container port, e insert DNAT (destination network address translation) rules wey dem evaluate before ufw chains. So ufw status fit report say port block, while the container behind am dey answer the whole internet. Understand this before rebuild: why Docker published ports bypass ufw explain the rule ordering and the fix.
An unpatched web application. Search web server access log around the earliest suspicious timestamp for POST to upload path or admin path. Then look for files under web root wey get matching change time. One PHP file wey stray inside uploads directory na the classic result.
A leaked credential. Key wey dem commit to repository, token wey person paste for chat, or an .env file wey misconfigured web server dey serve as static file. Automation make am easy to do by mistake. Na why e make sense to keep secrets out of AI agents and their config files.
If you still no fit name the door after all this, assume say credential leak happen and treat every secret wey the machine hold as public.
Rotate every credential wey the machine fit see
Rotate dem only after you cut the network connection, never before. If you rotate dem while attacker still get connection, you just hand the new secrets over.
- Every SSH private key wey dey stored for the server, plus every account for another place wey trust the matching public key.
- Any key wey you forward enter the box with
ssh -A. Agent forwarding dey leave socket under/tmp, and root for that machine fit use am authenticate as you anywhere wey accept your key, for as long as your session remain open. - API tokens inside
.envfiles, for systemdEnvironment=lines, inside CI configuration, and for provider credentials. - Database passwords, plus the application accounts wey dey use dem.
- TLS (transport layer security) private keys wey the server hold. Issue the certificate again and revoke the old one.
- Your hosting account password, with two-factor authentication turned on. That panel fit rebuild, create snapshot, and open console for every server wey you own, so na the real perimeter.
- Any password wey you type inside shell session for that host while e dey compromised, because root fit record terminal session as e dey happen.
If you use any password for that machine anywhere else, change am there too. Reusing password na how one compromised VPS fit turn into compromised email account.
Checklist for rebuild
- Create a new server from a fresh distribution image. No use snapshot from the breached box, and no use whole-root-filesystem restore.
- Install packages from the distribution repositories. Never copy binary from the old disk come over.
- Restore only data, from backup wey date before the earliest evidence for your timeline. Database dumps, uploads, application state. Leave
/etc,/usrand the old unit files behind. - Enter the rotated secrets by hand. No copy the old
.envcome over. - Inspect restored web content for files wey dem add inside the intrusion window before you serve any of dem again.
- Harden am before you expose am: key-only SSH, one non-root working account, default-deny inbound firewall, and no service wey you publish wider than e need. Work through the first ten minutes for new VPS, then harden SSH properly, then add fail2ban for Ubuntu 24.04 to reduce the login noise. Give each service its own least-privilege account so the next foothold no go be root foothold.
- Power off the old server, and keep its snapshot until the investigation and any abuse ticket don close.
- Fix the backups. If step 3 na guesswork, the real lesson be say your backup history too short to reach behind the intrusion. Versioned off-server backups with long retention na wetin go give you clean restore point next time: restic backups for VPS gives you both.
If you no fit date the intrusion, you no fit choose safe backup. For that case, restore only data wey you fit inspect by eye: SQL dump wey you fit read, directory of images wey you fit list. Treat everything executable as suspect and install am again from the repositories.
Wetin the abuse notice from your host mean
Most people dey find out say their server don get breached from their provider, no be from their own monitoring. Hosts dey see the outbound traffic: SSH brute force against other networks, spam for port 25, or one share for reflection attack. The ticket normally get timestamps, ports, and sample of the flows, together with deadline wey dem measure in hours.
Reply am, even if na only to say say you don isolate the server and dey rebuild am. Providers fit null-route or suspend server when person no answer ticket, and this go turn your incident to outage. Then ask for the raw log lines wey the report come from. Those timestamps dey recorded outside your machine, so na dem be the one part of the timeline wey attacker no fit edit. Dem often show when the intrusion happen better pass anything wey dey for disk.
A customer server wey get breached na normal work for host, and dem no dey hold am against you if you handle am well. The wider question of whether VPS hosting safe mostly depend on wetin customer configure. Na exactly that part you now get chance to do again from scratch.
Wen to call professional
- The server hold personal data wey belong to other people. Under GDPR (General Data Protection Regulation), dem must report personal data breach to supervisory authority without undue delay, and within 72 hours after dem become aware of am where that one dey feasible. To judge whether that clock don start na legal work, e no be sysadmin work.
- Payment card data dey within scope. The card schemes require approved forensic investigator, and your own investigation fit damage the case.
- Extortion demand dey, or dem don encrypt your data.
- The machine fit reach other machines: internal network, hypervisor, or CI runner wey hold production credentials. One compromised host for a group na incident for the whole group until dem prove otherwise.
- You go need the evidence to stand for insurance or law enforcement. Stop after the snapshot, take full disk image, and record who handle am and when.
For one VPS wey dey run your own services, and nobody else data dey inside am, the playbook above na the complete work. Isolate am for the provider. Take snapshot for evidence. Collect anything wey still trustworthy. Rotate everything. Rebuild am clean.
FAQ
I fit clean compromised VPS instead rebuild am?
No be with confidence, because you go dey ask the breached system to report about itself. A replaced ps fit hide process, a line for /etc/ld.so.preload fit inject code into every dynamically linked tool wey you run, and a kernel module fit hide files from every program at once. You fit find things, so any hit get meaning. You no fit prove say nothing dey hidden, so clean result no prove say system clean. Cleaning only make sense when the server no hold anything wey matter to you and you accept say e fit get breached again.
I suppose power off compromised server or leave am running?
First cut the server network for the provider side, then leave am running long enough to take snapshot and check the processes wey dey run. Powering off go destroy the process list, and e go delete the journal completely when /var/log/journal no dey exist, because journald go then write to memory under /run. Power am off anyway if e dey actively attack other networks and you no get way to block the outbound traffic. Stopping the harm pass preserving the evidence.
How I go know when attacker enter?
Find the earliest Accepted password or Accepted publickey line wey you no fit explain, for /var/log/auth.log or inside the journal. Cross-check am with change-time listing, find / -xdev -newerct 'YYYY-MM-DD' -type f, because ctime harder to forge than mtime. Then compare both with the timestamps for your provider abuse ticket. Dem record those timestamps outside the machine, so nobody fit edit dem from the server. Choose backup wey older than the earliest of those three dates. If nothing match, assume say the breach older than your backup history and restore only data wey you fit inspect.
My backups safe to restore after breach?
The data usually safe, if you inspect am first. The system files no safe. Backup wey you take after the intrusion go contain the backdoor, so if you restore the whole root filesystem, you go restore the attacker too. Check the backup repository itself too. If the credentials for am dey stored on the breached server, person fit don delete or change the backup history. Na why append-only or pull-based backup targets matter. Restore application data, then install the software again from the distribution repositories.
I must tell anybody say my VPS get breached?
Always reply to your host abuse notice. Apart from that, e depend on whose data dey for the machine. Personal data wey belong to other people fit create legal reporting duty, like the GDPR 72-hour notification to supervisory authority. If user credentials dey stored for the server, tell those users so dem fit change passwords for other places. If keys for the machine authorised access to third-party systems, like code host or cloud account, tell those providers so dem fit check whether person misuse the access. If na purely personal server and e no hold anybody else's data, you no get obligation beyond the abuse ticket.