When and How to Upgrade from Shared Hosting to VPS

HomeShared HostingWhen and How to Upgrade from Shared Hosting to VPS
When and How to Upgrade from Shared Hosting to VPS

Shared hosting is the perfect launchpad for any business, beginner‑friendly and maintenance‑free. But growth hits resource ceilings, slowdowns, and lack of control. 

Upgrading to a VPS (Virtual Private Server) gives you dedicated resources, full root access, and isolation. However, the migration itself can be risky, one misstep can cause data loss, downtime, or broken functionality.

 

When Must You Upgrade?

  1. Persistent slow loading despite optimization - images compressed, caching on, yet Time to First Byte stays above 600 ms and full load above 3 s. Shared CPU/RAM contention is the culprit.

  2. Frequent “Resource Limit Hit” errors (508/503) - your host suspends processes or throttles your site because you’ve hit inode, entry process, or CPU minute caps.

  3. Traffic spikes crash the site - a viral post or sale takes you offline. Shared plans can’t burst; VPS resources are dedicated and scalable.

  4. Custom software or PHP extensions are needed - shared hosts lock down the environment. With a VPS you get root, so you can install Redis, Node.js, specific PHP modules, or even a different database version.

  5. Security and compliance requirements have risen - taking payments, storing personal data, or needing PCI‑DSS/GDPR mandates isolation. A VPS gives you a private OS instance and a dedicated IP.

  6. Email deliverability is tanking - shared IPs are often blacklisted. A VPS with a clean dedicated IP and proper DNS (SPF, DKIM, DMARC, rDNS) fixes your sender reputation.

  7. You plan to host multiple high‑traffic sites or resell - you need to partition resources per site, not share a single pool.

 

How to Migrate from Shared Hosting to VPS

This guide assumes you’re moving from a cPanel‑based shared host to a Linux VPS. Every step includes detailed commands, checks, and rollback options.

Pre‑Migration Preparation

Inventory Everything

Make a complete list of what needs moving:

  • Domains/Subdomains - including parked and add‑on domains.

  • Website files - size, location (public_html, subdirectory).

  • Databases - names, users, prefixes.

  • Email accounts - addresses, passwords, forwarders, autoresponders, and stored mail (IMAP folders).

  • Cron jobs - list all (crontab -l if you have SSH access; otherwise in cPanel).

  • SSL certificates - issuing authority, expiry dates.

  • Third‑party integrations - payment gateways, CDN, external APIs that might have IP whitelisting.

  • PHP version and extensions - note the exact PHP version (e.g., 8.1.27) and active modules. Create a phpinfo() page on your shared host and save the output.

Choose Your VPS and Environment

  • Managed vs. Unmanaged: If you’re not comfortable with command‑line, choose a managed VPS where the provider handles security and stack.

  • Alternatively, install a free control panel: CloudPanel (very lightweight, Nginx‑focused), HestiaCP (feature‑rich), or aaPanel. Paid cPanel/WHM is also an option but expensive.

  • OS: Ubuntu 24.04 LTS or Rocky Linux 9.

  • Resources: Start with at least 2 vCPU, 4 GB RAM, 50 GB NVMe SSD - you can always resize later.

  • Backup services: Ensure the VPS provider offers automatic off‑site backups or plan to set up your own (we’ll cover it).

Set Up a Testing Domain/Staging Environment

A local hosts file trick tests basic rendering, but a temporary staging subdomain lets you test everything - SSL, emails, redirects, payment gateways - under a real domain before switching live.

  • Create a subdomain like staging.yourdomain.com and point its A record to the new VPS IP (or use a totally different test domain you own).

  • This allows full, secure testing without affecting production.

Lower DNS TTL in Advance

At least 24 hours before the final switch, set the TTL (Time‑to‑Live) of your domain’s A and www records to 300 seconds (5 minutes).This speeds up propagation.

If you’re also changing nameservers, TTL change alone won’t help; you’ll need to plan a longer propagation window. In this guide we stick to A‑record change, which is quicker.

 

Create a Perfect, Redundant Backup of Your Shared Host

Backup everything - not just files and databases - and verify each backup is restorable.

Full cPanel Backup (if available)

  • Use cPanel’s Backup Wizard → “Full Backup”. Choose to store it in your home directory or download via FTP.

  • This single *.tar.gz file contains: all files, databases, email forwarders, filters, and DNS zone files. Download it and store securely off‑server.

Manual, Granular Backups

Even with a full backup, take separate manual copies for extra safety:

Files:

  • Via FTP/SFTP (e.g., FileZilla in binary mode), download the entire public_html (or the document root of each add‑on domain).

  • Compress into a .zip or .tar.gz locally for easy upload.

Databases:

  • Export each database via phpMyAdmin. Select the database → Export → Custom → check “Add DROP TABLE / VIEW…” and “Add CREATE DATABASE…”, format SQL, compression gzipped.

  • Alternatively, use cPanel’s “Backup” → download each database.

  • Important: Note the database name, username, and password (they will be re‑created on the VPS). If your CMS config file references a specific MySQL hostname (often localhost), note that too.

Email (if you plan to move it):

  • Full cPanel backup includes email, but you can also:

    • Use an email client (Thunderbird/Outlook) to connect to each account via IMAP, synchronize all folders, then export locally.

    • For manual server‑level copying, if you have SSH access on shared hosting, copy /home/username/mail/. Most shared hosts don’t give that, so the cPanel full backup is your best bet.

Cron Jobs:

  • In cPanel, go to “Cron Jobs”, take a screenshot or copy each line.

SSL Certificates:

  • Private keys and certificates can be exported from cPanel’s “SSL/TLS” area, but we’ll generate new ones on the VPS. Keep them as reference.

Email Filtering and Forwarders:

  • Document all forwarders (cPanel → Forwarders) and global email filters (cPanel → Global Email Filters). You’ll recreate them.

Verify Backups

  • Unzip a database backup and check that the SQL file looks complete (tables present).

  • Spot‑check file backup - open a few images, ensure they aren’t corrupted.

  • Golden rule: A backup that hasn’t been tested is not a backup.

 

Harden and Prepare Your VPS

Before restoring anything, make the server secure.

Initial SSH and Basic Security

Log in as root.

bash

ssh root@your_vps_ip

 

Update the system:

bash

apt update && apt upgrade -y

 

Create a new sudo user (replace deploy with your name):

bash

adduser deploy

usermod -aG sudo deploy

 

Configure SSH key authentication for the new user:
On your local machine, generate a key if you haven’t (ssh-keygen), then copy it:

bash

ssh-copy-id deploy@your_vps_ip

 

Disable root SSH login and password authentication (only after you’ve tested your key works in a separate terminal window). Edit /etc/ssh/sshd_config:

text

PermitRootLogin no

PasswordAuthentication no

PubkeyAuthentication yes


Then sudo systemctl restart sshd. Keep the current root session open until you confirm the new user can log in.

Firewall (UFW)

bash

sudo ufw allow OpenSSH

sudo ufw allow 80/tcp

sudo ufw allow 443/tcp

# If you use a custom SSH port, replace OpenSSH with that port

sudo ufw enable

sudo ufw status verbose

 

Install Fail2ban

bash

sudo apt install fail2ban -y

sudo systemctl enable fail2ban --now

This protects SSH and eventually web services from brute‑force.

 

Set Timezone and Hostname

bash

sudo timedatectl set-timezone Asia/Kolkata   # or your timezone

sudo hostnamectl set-hostname yourdomain.com

 

Enable Automatic Security Updates

bash

sudo apt install unattended-upgrades -y

sudo dpkg-reconfigure --priority=low unattended-upgrades

 

Install the Web Stack and Control Panel (Recommended)

For a safe migration that keeps you in control without deep server admin, install a lightweight control panel. We’ll use HestiaCP as an example - it’s free, open‑source, and includes a web interface, mail server, DNS, and firewall.

Install HestiaCP

Ensure you’re logged in as root (temporarily) or use sudo.

Download the installer and run:

bash

wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh

bash hst-install.sh --interactive no --email your@email.com --password YourStrongPass --hostname panel.yourdomain.com --apache no --nginx yes --multiphp yes --mysql-classic yes --named yes --sieve yes --port 2023

(Adjust flags: --apache no --nginx yes gives a fast Nginx + PHP-FPM stack without Apache.)

  • The installer outputs the admin URL (https://panel.yourdomain.com:8083) and credentials. Save them securely.

  • After installation, log into the panel and go through the quick setup wizard.

  • Important: Change the default admin password immediately from the panel.

If you prefer no panel, you can manually install LEMP/LAMP, but a panel dramatically reduces mistakes.

 

Pre‑Restore Site Setup

Create the hosting environment for your domain(s) before moving data.

Add Your Domain in the Panel

  • In HestiaCP (or whatever panel), add a Web Domain: yourdomain.com.

  • Ensure the “Create DNS zone” option is unchecked (you will manage DNS externally or point it later).

  • The PHP version should match what you noted from the old host (e.g., PHP 8.1). Install extra PHP extensions if needed (via panel or apt).

 

Create a Staging Subdomain

  • Add a new web domain: staging.yourdomain.com. This will be your full‑fidelity test environment. We’ll restore the site here first.

 

Set Up Database and User

  • In the panel's database section, create a new database and user with exactly the same names, username, and password as the old site. This avoids having to update config files. (If you can’t, create any and we’ll update config later.)

  • Note the MySQL host: it will be localhost unless your panel uses a separate database server.

 

Configure PHP Settings

  • Copy exact upload_max_filesize, post_max_size, memory_limit, and max_execution_time from the old host’s phpinfo(). Adjust in panel or via php.ini overrides.

 

Restore the Full Site to the Staging Environment

We’ll first restore everything to staging.yourdomain.com, making it a carbon copy of the production site.

 

Upload Website Files

Using SFTP (FileZilla, key‑based auth), upload the compressed backup of public_html to the staging.yourdomain.com document root (e.g.,/home/deploy/web/staging.yourdomain.com/public_html/).

 

Extract it using the panel’s file manager or via SSH:

bash

cd /home/deploy/web/staging.yourdomain.com/public_html/

unzip backup.zip  # or tar -xzf backup.tar.gz

 

Ownership and permissions: Run

bash

sudo chown -R deploy:deploy /home/deploy/web/staging.yourdomain.com/public_html/

find /home/deploy/web/staging.yourdomain.com/public_html/ -type d -exec chmod 755 {} \;

find /home/deploy/web/staging.yourdomain.com/public_html/ -type f -exec chmod 644 {} \;

# If you have a special writable directories (uploads, cache), set them to 775/664 if needed.

 

If the site uses a CMS like WordPress, ensure wp-content/uploads and wp-content/cache are writable:

bash

sudo chown -R www-data:www-data /home/deploy/web/staging.yourdomain.com/public_html/wp-content/uploads

sudo chmod -R 755 /home/deploy/web/staging.yourdomain.com/public_html/wp-content/uploads

 

Import Databases

Via panel’s phpMyAdmin or command line:

bash

mysql -u database_user -p database_name < /path/to/backup.sql

 

After import, check if the site configuration file (e.g., wp-config.php) references the correct database credentials. If you used different credentials, update them now.

  • Change site URLs in the database (for WordPress):
    Since the site is currently on staging.yourdomain.com, run these SQL queries to replace all old domain references:

sql

UPDATE wp_options SET option_value = 'https://staging.yourdomain.com' WHERE option_name = 'siteurl' OR option_name = 'home';

UPDATE wp_posts SET post_content = REPLACE(post_content, 'https://yourdomain.com', 'https://staging.yourdomain.com');

UPDATE wp_postmeta SET meta_value = REPLACE(meta_value, 'https://yourdomain.com', 'https://staging.yourdomain.com');

(If the site uses a different prefix, adjust accordingly. For other CMS, similarly update base URLs.)

 

Restore Cron Jobs

  • Add back all cron jobs through the panel or by editing the user’s crontab (crontab -e).

  • Disable them initially - comment them out (#) - so they don’t run during testing and interfere with live sites or send test emails. We’ll enable later.

 

Test the Staging Site in Full Isolation

This is the most critical safety step. Verify everything works perfectly on the staging subdomain before ever touching live DNS.

Basic HTTP Test

  • Open http://staging.yourdomain.com (and https later) in a browser. You must see the site exactly as live.

  • Click through menus, posts, pages. Check for broken links (might still point to the main domain - we’ll replace them; they should be relative or use the staging URL now).

 

Test HTTPS with a Trusted SSL Certificate

  • Install a Let’s Encrypt SSL for staging.yourdomain.com. In HestiaCP, go to Web → Edit → SSL → “Generate Let’s Encrypt”.

  • Force HTTPS (enable HSTS if appropriate). Check the padlock, no mixed content errors.

 

Functionality Checks

  • Forms: Submit a test contact form. Ensure it sends email (we haven’t configured email yet; it may fail - skip for now).

  • E‑commerce (if applicable): Add a product to cart, go to checkout, use sandbox/test payment gateway.

  • Admin panel: Log into WordPress admin (or CMS backend). Verify you can edit posts, upload media, update plugins.

  • Caching: If you use a caching plugin, clear and rebuild cache.

  • Redirects: Check any custom redirects (e.g., old URLs). Test with curl:

bash

curl -I http://staging.yourdomain.com/old-page

 

Database and File Sync Test

  • Make a small change on the staging site (e.g., a new post, a test comment). Then check if it persists after reload. This confirms database writability.

 

Check Error Logs

In the panel or via SSH, tail the site’s error log:

bash

tail -f /home/deploy/web/staging.yourdomain.com/logs/error.log

Visit pages and see if any PHP errors pop up. Fix them now - often due to missing PHP extensions or different PHP version.

 

Perform a Full Backup of the Staging Site (as Restore Point)

Once staging is flawless, take a snapshot: backup the staging files and database again. This will be your “golden” backup. If anything goes wrong during the final switch, you can quickly roll back.

 

Migrate Email (If Moving Email to VPS)

Email is notoriously tricky. Handle it with extreme care to prevent loss.

Choose Email Strategy

  • Option A (Recommended): Use an external email service (Google Workspace, Zoho, MXRoute) and only update MX records. This keeps email independent from hosting and avoids any migration pain. If you go this route, skip to step 8.

  • Option B: Host email on the VPS using the control panel’s mail server (Exim + Dovecot).

 

If Hosting on VPS, Restore Email Data

  • Full cPanel backup restoration: If you have the full backup, HestiaCP offers a script to restore it; otherwise you need manual work.

  • Manual method:

    1. Recreate every email account in your panel with exactly the same address and password.

    2. The old mail data (in mail/ directory of your backup) needs to be placed in the new mail directory. Usually the structure is /home/username/mail/yourdomain.com/account/. Preserve folder structure (cur, new, tmp).

    3. Use an IMAP sync tool like imapsync to transfer emails directly from the old server to the new one while both are online. This is the safest method:

bash

imapsync --host1 old.mail.server --user1 info@yourdomain.com --password1 XXXX --host2 localhost --user2 info@yourdomain.com --password2 YYYY

Run this for each account. This copies all folders and messages without any loss. You can do it before switching DNS - just ensure the new server accepts mail for the domain even without proper DNS (you can add a temporary hosts entry on the VPS).

Recreate email forwarders and filters manually in the panel.

 

Test Email Sending and Receiving on the VPS

  • Temporarily modify your local machine’s hosts file to point the mail server hostname to the VPS IP, configure an email client, and test sending.

  • Or use webmail (Roundcube/HestiaCP’s webmail) once accounts are created.

 

Final DNS Configuration and Production Switch

Now you switch production traffic with zero downtime.

Prepare Live DNS Records

  • A record for @ (yourdomain.com) points to VPS IP.

  • A record for www (or CNAME) points to VPS IP.

  • MX record - if you moved email to VPS, update MX to mail.yourdomain.com with priority 10, and create an A record mail pointing to VPS IP. If using external email, set MX records as per that provider.

  • SPF, DKIM, DMARC - ensure they are added. The VPS mail server will generate DKIM keys; add the public key as a TXT record.

  • rDNS (PTR record) - contact your VPS provider to set reverse DNS for your IP to mail.yourdomain.com (important for email deliverability).

 

Point Production Domain to the Staging Environment? No - Convert Staging to Production.

Actually, you don’t want to keep the staging subdomain. Instead, now you change the site’s configuration back to yourdomain.com on the VPS.

Method:

  1. On the VPS, rename the domain: remove staging.yourdomain.com web domain (or just change its document root to your main domain’s).

    • In HestiaCP, you can add the main domain yourdomain.com and set its document root to the same directory that the staging site used.

    • Or simply create a new web domain yourdomain.com and copy everything from staging’s directory to its directory, then remove the staging domain.

  2. Update URLs back in the database:
    Replace staging.yourdomain.com with yourdomain.com using the same SQL replace queries as before, but reversed.

  3. Verify SSL: Generate a new Let’s Encrypt certificate for yourdomain.com and www.yourdomain.com.

Now your VPS has the exact production site ready.

 

The Cutover - Switch DNS

  • In your domain registrar’s DNS zone, update the A record for @ and www to the VPS IP. TTL should already be 300.

  • Do NOT delete the old A record yet - just change it. Save.

  • Immediately after, on the VPS, tail the access log:

bash

tail -f /var/log/nginx/domains/yourdomain.com.log  # adjust path

Within a few minutes, you should see hits from remote IPs (not just your tests). This indicates propagation has begun.

 

Minimize Downtime with a Final Sync

If you have a constantly changing site (e‑commerce, forums), you might lose data between your final backup and DNS switch. To prevent this:

  • Option: Put the old site in maintenance mode, quickly rsync files and dump the database, import to VPS, then switch DNS. This gives a few minutes of planned downtime.

  • Better Option (zero downtime): Use a tool like rsync to sync only changed files, and use database replication (or manually re‑dump/import) without maintenance mode. With low TTL and quick propagation, the window is tiny.

  • For most small to medium sites, the chance of lost transactions during the 5‑15 minute propagation is negligible. The risk is acceptable.

 

Keep Old Hosting Active

Do not cancel your shared hosting for at least 72 hours. Keep it running as a fallback. If the new server has issues, you can repoint the A record back to the old IP and instantly recover.

 

Post‑Migration Validation and Hardening

Once traffic is flowing to the VPS, perform final checks and lock things down.

SSL and Mixed Content

  • Force HTTPS. Check with https://www.whynopadlock.com to find any insecure resources.

  • Ensure HSTS header is sent.

Check Email Flow

  • Send test emails from the site (contact form, password resets). Check if they arrive in the inbox (not spam).

  • Use mail‑tester.com to validate SPF, DKIM, DMARC, and rDNS.

Monitor Logs

  • Watch Apache/Nginx and PHP error logs for a few hours to catch any silent errors.

  • Check MySQL slow query log.

Set Up Automated Backups

  • Configure daily off‑site backups - most panels have backup modules that can upload to S3, Google Drive, or SFTP.

  • Schedule: daily database, weekly files, retention of at least 7 days.

Configure a Server Monitoring and Uptime Service

  • Install a lightweight monitoring agent (e.g., Netdata) or use external uptime robot (UptimeRobot, HetrixTools) to alert you if the server goes down.

Enable Caching for Performance

  • Implement full‑page caching with Nginx FastCGI cache or a Redis object cache.

  • If using WordPress, install a caching plugin and pair it with Redis.

Set Up a Staging Workflow for Future Changes

  • Re‑create a permanent staging.yourdomain.com subdomain for testing updates before pushing them to production. Now you have the perfect foundation.

 

Complete Safety‑Migration Checklist

Pre‑Flight

  • Full cPanel backup downloaded & verified

  • Granular backup of files, databases, emails, cron, filters

  • Inventory of PHP version, extensions, and settings

  • Staging subdomain created and A record pointed to VPS

  • VPS hardened (SSH key, UFW, Fail2ban, unattended upgrades)

  • Control panel installed and configured

  • TTL lowered to 300 seconds (24 h before switch)

Staging Build

  • Files uploaded, permissions set

  • Database imported, credentials matched

  • Site URLs updated to staging domain

  • SSL certificate for staging installed

  • Full functionality test (forms, checkout, admin, redirects)

  • All errors resolved, logs clean

  • Golden backup of staging created

Email Setup (if migrating email too)

  • Email accounts recreated with identical credentials

  • Mail data synced using imapsync (no loss)

  • Forwarders/filters manually recreated

  • DKIM, SPF, DMARC records prepared

  • rDNS requested from VPS provider

Cutover

  • Production domain added on VPS, URLs changed back

  • Live SSL certificate generated for production domain

  • DNS A records updated to VPS IP

  • Old hosting left running as fallback

  • Access logs monitored for live traffic

  • No cancel of old plan for 72 hours

Post‑Migration

  • Mixed content scan and HSTS

  • Email deliverability test (mail‑tester.com ≥ 9/10)

  • Automated off‑site backups configured

  • Monitoring alerts set up

  • Caching layer enabled

  • Original shared hosting cancelled only after full confirmation

Previous post
-
Next Post
-