🔁 Part 2 – Bluehost to Hetzner VPS — The Complete Migration Journey

(Moving WordPress, SSL Setup, DNS, and Fixing Every Real-World Error)

By the time your fresh WordPress install is running on Hetzner, the real adventure hasn’t even begun.
Installing WordPress on a VPS is easy — migrating your live site without breaking it is where the story gets interesting.

Part 1 – Shared Hosting to VPS — My Real Journey of Moving dtptips.com from Bluehost to Hetzner

In this post, I’ll walk you through exactly how I moved dtptips.com from Bluehost shared hosting to a Hetzner VPS, using Migrate Guru, fixing the classic “Error establishing database connection,” repairing broken layouts, enabling SSL via Certbot, and finally updating DNS — all the way until the site loaded perfectly from its new home.

🔁 Part 2 - Bluehost to Hetzner VPS — The Complete Migration Journey

📬 Step 1 — Preparing for Migration: Emails, Passwords & Safety Notes

Once you’ve set up your VPS (see Part 1), you’ll already have received that crucial Hetzner email containing:

  • Your server IP
  • The root username
  • A temporary root password

Keep that email safe — it’s your lifeline.
Save these details in a password manager or encrypted notes app.
Never post them online or in screenshots.

Before starting migration, you’ll also need:

  • The SFTP/SSH credentials of your new server
  • Access to your old site’s WordPress dashboard on Bluehost

💡 Tip: It’s wise to temporarily pause any auto-backup or caching plugins before migration. It prevents half-migrated caches from corrupting the transfer.


🧰 Step 2 — Why I Chose Migrate Guru (and What It Actually Does)

When I first thought of migrating manually, I imagined a simple ZIP file and a database export.
Reality? Broken serialization, missing uploads, PHP timeouts, and file-size limits.

That’s when I discovered Migrate Guru by BlogVault.
It automates everything — compresses your site, transfers it to the destination via SFTP, unpacks, and reconfigures URLs — all within one interface.

What it does behind the scenes:

  1. Creates a temporary clone of your old site.
  2. Transfers it to your new server using SFTP.
  3. Updates database URLs automatically.
  4. Sends you an email once done.

No downtime. No manual import/export.


🚀 Step 3 — Running the Migration

On your old WordPress site (Bluehost):

  1. Install Migrate Guru from Plugins → Add New → Search “Migrate Guru” → Install → Activate.
  2. Open Migrate Guru → Migrate Site → Other Host.
  3. Fill in the details: Field What to Enter Why Destination URL http://your_server_ip/ The temporary IP where new WordPress runs SFTP Host your_server_ip Allows file transfer via SSH SFTP User root Your server login SFTP Password (your root password) Used once for file copy Port 22 Standard SSH port Destination Path /var/www/your_site_folder/ Where WordPress is installed
  4. Click Migrate and keep the tab open.
    You’ll see live progress: “Creating Archive → Transferring Files → Restoring Database → Updating URLs.”

Depending on your site size, it may take 10–30 minutes.
Once complete, you’ll get an email confirmation saying:

Migration completed successfully.


⚠️ Step 4 — The First Login and the First 500 Error

When I opened my IP address after migration, instead of my familiar dtptips layout, I got:

This page isn’t working.
HTTP ERROR 500

That’s usually a PHP or plugin conflict — common right after migration.

🧩 Cause

Caching or optimization plugins (like Autoptimize, LiteSpeed Cache, WP Rocket, SG Optimizer) were still referencing the old environment.

🛠️ Fix

  1. Go to http://your_server_ip/wp-admin
  2. Log in with your old site’s credentials (they migrate with the site).
  3. Deactivate all optimization or SSL plugins.
  4. Go to Settings → Permalinks → Save Changes twice.

Saving permalinks forces WordPress to rebuild its rewrite rules for the new Nginx environment.

After doing that, the homepage loaded — though the layout still looked strange.


🎨 Step 5 — Why the Layout and Images Broke

The site opened, but everything was plain text — no styling, no images, just bare HTML.

When I inspected the page (right-click → Inspect → Network tab), I saw that CSS and image files were still loading from:

https://dtptips.com/wp-content/...

But the site was currently served from:

http://your_server_ip/

Browsers block mixed (HTTPS ↔ HTTP) resources, so CSS never loads.


💡 Fix 1 — Replace Old URLs in the Database

You can do this directly via MySQL:

mysql -u root -p your_database_name

Then run:

UPDATE wp_options SET option_value = REPLACE(option_value,'https://dtptips.com','http://your_server_ip');
UPDATE wp_posts SET post_content = REPLACE(post_content,'https://dtptips.com','http://your_server_ip');
UPDATE wp_postmeta SET meta_value = REPLACE(meta_value,'https://dtptips.com','http://your_server_ip');
EXIT;

What this does:
Every reference to your old domain is replaced with your temporary IP so images, CSS, and JS files load correctly during testing.

After running these queries, refresh your homepage and press Ctrl + F5 — your site should now show proper styling and images.


💡 Fix 2 — The “Parent Theme Not Found” Problem

If you’re using a child theme (like Trending News based on WalkerPress), WordPress may lose the link between them.

To check, open your themes folder:

ls /var/www/your_site_folder/wp-content/themes/

If you see something like walkerpress-1 instead of walkerpress, rename it:

mv /var/www/your_site_folder/wp-content/themes/walkerpress-1 /var/www/your_site_folder/wp-content/themes/walkerpress

Then, in your dashboard, go to Appearance → Themes, temporarily activate a default theme (Twenty Twenty-Three), then switch back to your child theme.

That refreshes theme inheritance and restores your layout.


🔒 Step 6 — Installing SSL with Certbot (the Easy, Free Way)

Once your site works over HTTP, it’s time to enable HTTPS.
Hetzner doesn’t provide SSL by default, but Certbot from Let’s Encrypt makes it painless.

Install Certbot and the Nginx plugin:

apt install certbot python3-certbot-nginx -y

Then run:

certbot --nginx -d yourdomain.com -d www.yourdomain.com

What happens next:

  1. Certbot automatically contacts Let’s Encrypt servers.
  2. It verifies domain ownership via your Nginx configuration.
  3. It downloads and installs the SSL certificates.
  4. It updates your Nginx config to redirect HTTP → HTTPS.

You’ll see:

Congratulations! Your certificate and chain have been saved.

⚠️ Common SSL Mistake: Enabling HTTPS Too Early

Before I had a certificate, I enabled “Force SSL” inside WordPress.
The result? A loop of ERR_TOO_MANY_REDIRECTS.

If that happens:

  • Edit wp-config.php and make sure these lines are set to HTTP until SSL works:
define('WP_HOME', 'http://your_server_ip');
define('WP_SITEURL', 'http://your_server_ip');
  • Disable “Really Simple SSL” until after Certbot installation succeeds.

Once SSL works, change both to https://yourdomain.com.


🌍 Step 7 — Updating DNS Records to Point the Domain

Now the final step: connecting your domain name to the new VPS.

At your domain registrar (Bluehost → Domains → Manage DNS, or any other provider), edit or add the following:

TypeHostValueTTL
A@your_server_ip3600
Awwwyour_server_ip3600

This tells the internet that dtptips.com now lives at your Hetzner VPS.

Propagation usually takes 15–60 minutes.
During that time, some visitors may still reach the old site — that’s normal.


🧩 Step 8 — Final URL Cleanup After DNS Propagation

Once your domain points to the VPS, update URLs back from IP → domain:

mysql -u root -p your_database_name

Then:

UPDATE wp_options SET option_value = REPLACE(option_value,'http://your_server_ip','https://yourdomain.com');
UPDATE wp_posts SET post_content = REPLACE(post_content,'http://your_server_ip','https://yourdomain.com');
UPDATE wp_postmeta SET meta_value = REPLACE(meta_value,'http://your_server_ip','https://yourdomain.com');
EXIT;

Now every image, CSS, and internal link uses HTTPS again.


🧱 Step 9 — Permission Fix for Missing Images or 403 Errors

If uploads still fail or thumbnails appear broken:

chown -R www-data:www-data /var/www/your_site_folder
find /var/www/your_site_folder -type d -exec chmod 755 {} \;
find /var/www/your_site_folder -type f -exec chmod 644 {} \;
systemctl reload nginx

Why: This ensures your web server (user www-data) owns and can read all files.
If the wrong user owns them (for example root), WordPress can’t access uploads or theme assets.


🧩 Step 10 — Verifying SSL Renewal Automation

Let’s Encrypt certificates expire every 90 days.
Certbot automatically sets up a cron job to renew them.
You can test it manually:

certbot renew --dry-run

You’ll see “Congratulations, all renewals succeeded.”
That means SSL will stay active forever without manual renewal.


⚠️ Step 11 — Real-World Mistakes and What They Taught Me

MistakeWhat HappenedHow I Fixed It
Editing configs with nano on WindowsConsole frozeSwitched to WinSCP + Notepad++
Forgot to deactivate cache pluginsGot 500 error after migrationLogged in via IP, deactivated all optimization plugins
Enabled SSL too earlyERR_TOO_MANY_REDIRECTSDisabled “Force SSL” until Certbot finished
Parent theme folder renamedLayout & CSS disappearedRenamed back to walkerpress and reactivated theme
Wrong file permissions403 errors on imagesReset with chown + chmod
DNS cached locallyOld site kept openingFlushed DNS (Windows → ipconfig /flushdns)

Every one of these cost me an hour the first time — and five seconds the next time.


🧠 Step 12 — Optional: Speed & Security Tweaks

Once everything works, consider these optimizations:

  • Install UFW firewall to allow only SSH (22), HTTP (80), HTTPS (443): ufw allow 22; ufw allow 80; ufw allow 443; ufw enable
  • Enable Redis Cache for database acceleration.
  • Use Fail2Ban to block repeated failed logins.
  • Set up automatic backups using a cron job or plugin like UpdraftPlus.

🏁 Final Checklist — Your Migration at a Glance

✅ VPS deployed and secured
✅ WordPress installed and tested
✅ Site migrated using Migrate Guru
✅ 500 error fixed by disabling cache plugins
✅ Database connection verified
✅ Images & CSS restored by URL replacement
✅ SSL installed via Certbot
✅ DNS updated to point to new VPS
✅ Automatic SSL renewal verified

Your site now runs on a fast NVMe VPS with full control and a clear upgrade path — all at roughly half the cost of shared hosting.


💬 Final Thoughts

Migrating dtptips.com from Bluehost to Hetzner taught me that VPS hosting isn’t about complexity — it’s about control.
At first, every command feels intimidating. But once you understand what each line does, you realise it’s just logic: fetch, configure, reload, verify.

The site now loads faster, handles more traffic, and feels future-proof.
And the best part? Every issue you fix manually once becomes permanent knowledge.


⚠️ Disclaimer

All examples and commands are provided for educational purposes.
Replace placeholders such as your_server_ip, yourdomain.com, your_database_name, and your_password with your own secure values.
Never share actual credentials publicly.
dtptips.com and the author accept no responsibility for misuse or data loss from incorrect configurations.


#WordPress #Migration #Hetzner #Bluehost #SSL #VPS #DNS #dtptips #Tutorial

Visited 16 times, 1 visit(s) today

Arjun Nair

Arjun Nair

Arjun is a seasoned Linux enthusiast and open-source contributor. He has worked with multiple distributions including Debian, Fedora, and Arch-based systems, and regularly tests new desktop environments and community projects. With over a decade in IT system administration, Arjun brings practical, hands-on insights to Linux tutorials and reviews.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.