Skip to content

How I moved away from standard hosting services

Dan Arel
Sep 13, 202612 min read1 read

After more than 20 years with DreamHost, I recently moved my websites and domain management to Cloudflare.

This decision had nothing to do with DreamHost quality or service, but because of ever rising costs and the fact that my needs no longer justify the cost. My website is a simple static site and my wife's is just a domain redirect to her Etsy store at this point.

This transition was actually pretty standard, and makes much of my life easier, but I decided to write about it anyway because you never know who is looking for some help or advice.

Moving DNS management

The first step was moving DNS management from DreamHost to Cloudflare.

I added each domain to Cloudflare, which prompted Cloudflare to scan the existing DNS records. That gave me a starting point, but I did not treat the scan as authoritative. I reviewed the records manually against the existing DreamHost configuration, checking for:

  • A records pointing to the current web servers.
  • CNAME records for subdomains and services.
  • MX records for email.
  • TXT records used for SPF, DKIM, domain verification, and other services.
  • Any redirects or special records associated with subdomains.

Once the records were in place, Cloudflare provided new nameservers. I updated the nameserver settings at the registrar and waited for the change to propagate.

The important thing here was not to make too many changes at once. I wanted DNS management to move first while the sites themselves continued operating as they had before. That created a useful buffer: Cloudflare could become authoritative for the domains without requiring the web hosting migration to happen simultaneously.

Transferring domain registration

I also transferred the domain registrations from DreamHost to Cloudflare Registrar.

The transfer process required unlocking each domain and obtaining an authorization code from DreamHost. Before starting the transfer, I checked the following:

  • The domain was unlocked.
  • The administrative contact information was current.
  • The email address associated with the domain was accessible.
  • WHOIS privacy or registration protection would not interfere with the transfer.
  • The domain was not subject to a recent transfer restriction.
  • The authorization code was available.

After initiating the transfer through Cloudflare, confirmation emails were sent to the administrative contact. Some transfers completed quickly; others required waiting for the normal registrar process.

One advantage of moving registration to Cloudflare is that domain registration and DNS management now live in the same place. Cloudflare Registrar also uses a cost-based pricing model rather than adding a large markup to the wholesale registration price. That was one of the factors that made the move financially worthwhile.

I still treated the registrar transfer as a separate process from the DNS change. A domain can use Cloudflare’s nameservers without being registered through Cloudflare, and separating those steps made it easier to troubleshoot anything that went wrong.

Moving the sites

The site itself were already well suited to a static publishing model. Rather than recreating a traditional hosted environment, I moved the deployment process toward Github and Cloudflare Workers.

The basic workflow is now:

  1. Make changes locally.
  2. Commit the changes to Git.
  3. Push the changes to GitHub.
  4. Cloudflare builds the site.
  5. Deploy the generated files.
  6. Let Cloudflare handle the domain, TLS, caching, and edge delivery.

This removes the need to manage a traditional web server for these sites. There is no control panel to maintain, no WordPress installation to patch, and no server filesystem to manage manually.

The most important part of the migration was making sure the build process was reproducible. The site source, configuration files, content, and deployment settings all needed to be accounted for. A static site is relatively simple once it is working, but the simplicity depends on knowing exactly how the site is generated and deployed.

Setting up Cloudflare Workers

I used Cloudflare Workers for URL handling that was more specific than a basic DNS or page rule.

Workers let me run a small piece of JavaScript at Cloudflare’s edge before a request reaches the site. For my purposes, that made it possible to handle redirects and other request logic without adding server-side code to the sites themselves.

The Worker checks the incoming request and applies rules based on the hostname and path. A simplified version looks like this:

export default {
  async fetch(request) {
    const url = new URL(request.url);

    if (
      url.hostname === "www.example.com" &&
      url.pathname === "/old-path"
    ) {
      return Response.redirect(
        "https://www.example.com/new-path",
        301
      );
    }

    return fetch(request);
  }
};

The actual Worker includes the rules specific to my domains and paths, but the basic idea is straightforward: inspect the request, match the URL, and return a redirect when necessary. Requests that do not match a special rule continue to the normal destination.

I also had to decide whether each redirect should be temporary or permanent. For URL changes that are intended to last, I used a 301 redirect. For testing or temporary routing, a 302 or 307 redirect would be more appropriate.

Handling the specific redirect

The most unusual part of the migration was handling this redirect:

[OLD URL]

which needed to point to:

[NEW URL]

This was not simply a matter of redirecting an entire domain. The old URL needed to preserve [the path / query string / a particular subdirectory / a legacy URL pattern], while the rest of the site continued to work normally.

I handled that with a Worker rule that matched the specific hostname and path:

if (
  url.hostname === "[old-hostname]" &&
  url.pathname === "[old-path]"
) {
  return Response.redirect(
    "[new-url]",
    301
  );
}

One detail that mattered was deciding what should happen to query parameters. In this case, I [preserved them / dropped them / mapped them to a new parameter structure]. That meant the redirect logic had to account for more than just the visible path.

I tested the redirect from the command line:

curl -I https://[old-url]

The response should include a 301 status and a Location header pointing to the new address:

HTTP/2 301
location: https://[new-url]

Testing with curl was useful because it showed the actual HTTP response without relying on browser caching or the browser’s interpretation of the redirect.

Yes — I’d replace the generic “Managing email during the change” section with something like this:

Email was a separate migration

Email was the part of the move I wanted to disturb the least.

My own email was already hosted with Proton Mail, so moving the domains away from DreamHost did not require migrating my mailbox, old messages, or daily mail workflow. The work was primarily DNS-related: making sure the records Proton Mail requires remained present and correct once Cloudflare became the authoritative DNS provider.

That meant carrying over and verifying:

  • Proton Mail’s MX records for incoming email.
  • The SPF TXT record authorizing Proton Mail to send mail for the domain.
  • The DKIM records Proton Mail uses to sign outgoing messages.
  • The DMARC policy for the domain.
  • Any verification TXT records connected to the Proton Mail setup.

The important part was that Cloudflare became the place where those records lived; it did not become the mail provider. Cloudflare’s DNS managed the instructions that tell other mail servers where to deliver mail and how to verify messages, while Proton Mail continued handling the actual mailbox.

I verified the records in Cloudflare before the nameserver switch, then tested incoming and outgoing mail after the change. I also checked message headers to make sure the SPF and DKIM authentication results were passing as expected.

Moving my wife’s email to Purelymail

My wife’s email was a different project. Rather than keeping it with DreamHost, we moved it to Purelymail.

That involved creating her mailbox and aliases at Purelymail, then changing the domain’s mail DNS records in Cloudflare. As with Proton Mail, the key records were the MX records, SPF policy, DKIM keys, and DMARC configuration.

The process was roughly:

  1. Create the address, mailbox, aliases, and any forwarding rules in Purelymail.
  2. Add Purelymail’s required DNS records in Cloudflare.
  3. Confirm that the MX records pointed to Purelymail rather than DreamHost.
  4. Update the domain’s SPF record so that Purelymail was authorized to send mail.
  5. Add the DKIM record supplied by Purelymail.
  6. Review the existing DMARC record so that it aligned with the new sending provider.
  7. Test sending and receiving from external accounts before shutting down the old DreamHost mail configuration.
  8. Confirm that any aliases, forwarders, or devices using the account had been updated.

The most important technical constraint was that each domain needs a coherent mail-authentication configuration. SPF records should not be duplicated, for example. A domain can have only one SPF TXT record, so if multiple services send mail for a domain—Proton Mail, Purelymail, a newsletter platform, a website form service, or something else—they need to be represented together in the same SPF policy.

A simplified example might look like this:

v=spf1 include:_spf.protonmail.ch include:example.purelymail.com ~all

The exact value depends on the providers and services involved, so I used the records supplied by Proton Mail and Purelymail rather than trying to write them from scratch.

Similarly, DKIM is usually easier to manage because each provider can use its own selector and publish a separate TXT or CNAME record. The main task is making sure those records are copied exactly and remain in DNS after moving nameservers.

Keeping the mail cutover low-risk

We tried to avoid a hard cutover where mail suddenly stopped arriving at the old provider before the new setup had been tested.

The safer sequence was:

  • Build and test the mailbox at the new provider first.
  • Add the new DNS records in Cloudflare.
  • Verify the records with the provider’s setup tools.
  • Test delivery from Gmail, Proton Mail, and another external account.
  • Test sending from the new address and inspect the message headers.
  • Update mail applications and devices.
  • Leave the old DreamHost email setup in place long enough to catch anything that had been missed.
  • Only then remove or cancel the old mail service.

Because DNS propagation and mail-server caching can take time, I did not assume that a successful test from one account meant the transition was complete. Testing from several services, over a day or two, provided more confidence that incoming mail was consistently reaching the right place.

A useful distinction

One thing that became clearer during this process is that domain registration, DNS, website hosting, and email hosting are related but separate services.

In the final configuration:

ServiceProviderRole
Domain registrationCloudflare RegistrarRenews and maintains ownership of the domains
DNSCloudflarePublishes web and mail routing records
Website hosting and deliveryCloudflare Pages and WorkersPublishes sites and handles custom routing
My emailProton MailHosts my mailbox and sends/receives my mail
My wife’s emailPurelymailHosts her mailbox and sends/receives her mail

That separation is useful. It means I can change the website infrastructure without moving email, change an email provider without transferring the domain, or move a registrar without rebuilding the sites. The services are connected by DNS, but they no longer all depend on one hosting account.

SSL and HTTPS behavior

Cloudflare automatically provided HTTPS for the public-facing sites, but I still paid attention to the SSL/TLS mode.

The important setting was choosing the correct relationship between Cloudflare and the origin server. If the origin supports HTTPS, “Full” or “Full (strict)” is preferable to using a flexible configuration. Using the wrong setting can create redirect loops or leave traffic between Cloudflare and the origin less protected than expected.

I also checked:

  • Whether HTTP requests redirected to HTTPS.
  • Whether the www and non-www versions behaved consistently.
  • Whether certificates covered all required hostnames.
  • Whether any embedded resources were still loading over HTTP.
  • Whether redirects worked correctly over both HTTP and HTTPS.

Testing the migration

I used a checklist rather than relying on a quick visual inspection.

For each site, I tested:

  • The main domain.
  • The www version of the domain.
  • Important internal pages.
  • Old URLs that needed redirects.
  • RSS feeds.
  • Sitemaps.
  • Robots.txt.
  • Contact forms or other interactive services.
  • Any subdomains.
  • Email addresses and aliases.
  • HTTP-to-HTTPS behavior.
  • Trailing-slash variations where relevant.

I also used command-line tools to inspect responses:

curl -I https://example.com
curl -IL https://example.com/old-page
dig example.com
dig MX example.com
dig TXT example.com

The -L option for curl follows redirects, which makes it useful for checking the entire redirect chain rather than only the first response.

I wanted to avoid redirect chains such as:

old URL → intermediate URL → final URL

A cleaner configuration is:

old URL → final URL

This is faster, easier to maintain, and less likely to create problems for search engines or visitors.

What I would do differently

The main lesson was to separate the migration into distinct stages:

  1. Inventory the existing DNS and hosting setup.
  2. Add the domains to Cloudflare.
  3. Recreate and verify DNS records.
  4. Change the nameservers.
  5. Transfer the domain registrations.
  6. Move or rebuild the site deployments.
  7. Configure Workers and redirects.
  8. Verify email independently.
  9. Test every important URL and service.

The temptation is to treat the migration as one large change. That makes it difficult to determine what caused a problem. By separating DNS, registration, hosting, redirects, and email, I could isolate each part and verify it before moving on.

I also learned not to assume that a successful page load means the migration is complete. A site can look fine while an old redirect is broken, an email alias has disappeared, an MX record is wrong, or a subdomain is still pointing to the old infrastructure.

The final setup

The result is a simpler arrangement:

  • Cloudflare manages DNS.
  • Cloudflare Registrar manages the domain registrations.
  • GitHub stores the site source.
  • [Cloudflare Pages / deployment platform] builds and publishes the sites.
  • Cloudflare Workers handle custom redirects and request logic.
  • [Email provider] handles mail.
  • Cloudflare provides HTTPS, caching, and edge delivery.

The move required some careful inventory and testing, but it also forced me to document how the sites actually worked. That may be the most valuable part of the process. After more than two decades with the same hosting provider, many details had become invisible simply because they had been working for so long.

Now the infrastructure is easier to understand, easier to change, and better aligned with the way I actually publish and manage these sites.

Did you enjoy this article?

Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.

Across the AtmosphereDiscussions