Restore a hacked or broken server from backup
If an attacker had root, or you cannot be sure they did not, do not clean the old server. Build a fresh one from the vendor's installer, patch it, restore only your data from a backup made before the break-in, change every password and key, check it, and only then put it back online.
Do this first.
- Cut the hacked server off the network (provider firewall or console), but do not wipe it yet. Take a disk snapshot if your provider offers one: it is your evidence.
- From a clean computer, change the passwords for your hosting account, DNS registrar and backup storage.
- Work out roughly when the intrusion started, so you pick a backup from before it.
- Never restore onto the hacked system itself.
Restore or repair?
| Situation | What to do |
|---|---|
| Root or admin account compromised, unknown processes, rootkit suspected | Rebuild and restore data (this page) |
| Only a website or CMS account was abused | Often a site-level clean-up: see Website hacked |
| Update broke the system | Roll back an update first |
| Disk failed or system will not boot, no attack | Reinstall and restore; you may restore /etc more freely |
| A few files deleted | Recover deleted files |
CISA's ransomware guide recommends rebuilding systems from pre-configured standard images where possible, restoring data from offline, encrypted backups, and taking care "not to re-infect clean systems during recovery".
1. Isolate and keep evidence
Block all traffic except your own IP address at the provider's firewall, or disconnect the network from the console. Keep the old disk or a snapshot of it for at least a few weeks: you may need it to learn how the attacker got in, for insurance, or for a breach report (see Personal data breach). Incident response covers evidence in more detail.
2. Pick a clean backup
Look for the first sign of the attack in logs, file dates and alerts, then choose a backup from before it. List and compare snapshots:
# restic
restic snapshots
restic diff 4e5f9b1a 9c2d7e03 # what changed between two snapshots
restic check --read-data # read and verify all stored data
# Borg
borg list
borg check --verify-data
Backups can contain the attacker's files too, such as a web shell in an upload folder. You will scan the restored data in step 5. If the backup storage was writable from the hacked server and not append-only, treat it with extra suspicion and check it fully.
3. Install a fresh operating system
Create a new server, or reinstall from your provider's official image or the vendor's installer (check the image checksum if you download it). Use a current supported release, not the old one if it was near end of life (Is my OS supported?). Do not reuse the old disk. Keep the firewall closed to everyone except you until step 8.
4. Patch and harden before anything else
# Debian / Ubuntu
sudo apt update && sudo apt full-upgrade
# RHEL, Rocky, AlmaLinux, Fedora
sudo dnf upgrade --refresh
# Reboots the server: needed if a new kernel was installed
sudo reboot
Then set up SSH with new keys, disable password logins and add only the users you need: see SSH hardening, Server hardening and Automatic updates. Install your software (web server, PHP, database) from the distribution's repositories, using your saved package list as a guide, not a script to run blindly.
5. Restore data, not programs
Restore into a staging folder first, then copy across only what you need.
# As root. restic keeps full paths under --target
restic restore 4e5f9b1a --target /root/restore \
--include /var/www --include /var/backups/db --include /etc
# Borg: extract writes into the current folder; paths have no leading slash
mkdir -p /root/restore && cd /root/restore
borg extract ::web1-2026-10-28T02:15:01 var/www var/backups/db etc
| Restore | Reinstall fresh | Do not copy back |
|---|---|---|
| Site content, uploads, documents, database dumps | Packages, CMS core, plugins and themes from official sources | /etc/passwd, /etc/shadow, /etc/sudoers, authorized_keys |
| Individual config files you have read and compared | Programs in /usr, /bin, /opt | Crontabs, systemd units, /etc/ld.so.preload, shell startup files, unless reviewed line by line |
Look for planted files before copying. PHP files in upload folders, recently changed files and unknown scripts are the usual signs:
find /root/restore/var/www -path '*uploads*' -name '*.php'
find /root/restore/var/www -type f -newermt '2026-10-20' | head -50
diff -ru /root/restore/etc/nginx /etc/nginx | less
Copy with a dry run first. -a keeps permissions and times; rsync's manual notes it does not include ACLs (-A), extended attributes (-X) or hard links (-H), so add those if you use them. A trailing slash on the source copies the folder's contents rather than the folder itself.
rsync -aHAX --dry-run -v /root/restore/var/www/ /var/www/
rsync -aHAX /root/restore/var/www/ /var/www/
Restore databases from the dumps (as root):
# MariaDB / MySQL
mariadb < /root/restore/var/backups/db/mariadb-all.sql
# PostgreSQL: roles first, then the database (--create makes it)
runuser -u postgres -- psql -X -d postgres < /root/restore/var/backups/db/pg-globals.sql
runuser -u postgres -- pg_restore --create -d postgres < /root/restore/var/backups/db/mydb.dump
An --all-databases dump also restores the old database users and their passwords, which you change in step 6. If the new server runs a newer MariaDB version than the old one, run sudo mariadb-upgrade afterwards. More help: Database won't start.
6. Rotate every secret
Assume the attacker copied everything that was on the old server. CISA's guide says to issue password resets for all affected systems once the rebuild is done.
- Every user and admin password, including control panels and CMS admins.
- SSH keys: create new key pairs; the fresh install already has new host keys, so tell users the fingerprint changed.
- Database passwords, then update them in the application config.
- Application secrets: API tokens,
.envfiles, WordPress salts, session and encryption keys. - TLS private keys: issue new certificates and revoke the old ones.
- Backup repository credentials, cloud API keys, mail relay and DNS API tokens.
The full list is in Leaked credentials.
7. Verify
sudo ss -tulpn # only the ports you expect
awk -F: '$3 == 0' /etc/passwd # only root should have UID 0
sudo ls /etc/cron.* /var/spool/cron # no unknown jobs
systemctl list-units --type=service --state=running
Run a malware scan over web folders (Malware scan) and check for persistence tricks (Find backdoors). Test the site or application from your own browser using a hosts-file entry before changing DNS.
8. Bring it back online
- Take a first backup of the new server, so you have a known-good starting point.
- Open the firewall, then switch DNS or move the IP address.
- Watch logs closely for two weeks: failed logins, new admin users, outbound connections (Logging and monitoring).
- Fix the hole the attacker used. Without that, the new server can be hacked the same way.
How to confirm it is fixed
- The server runs a supported, fully patched release.
- No programs, crontabs or user accounts came from the old system unreviewed.
- Every password, key and token has been changed.
- You know how the attacker got in, and that path is closed.
When to call a professional
Bring in an incident response firm if personal or payment data may have been taken, if several servers or your cloud account were reached, or if you cannot find how the attacker got in. Your hosting provider can often provide snapshots, console access and a new server quickly.