Migrating this website to IONOS

After excessive price rises from my previous web hosting supplier, I was looking for a new supplier. After some hunting around, I settled on IONOS. Their online documentation has some holes in it. I really wanted a step-by-step here's how you deploy a static site over SFTP/SSH/Git but I couldn't find it. A live chat assured me this was possible. So, this page is my notes on my migration, in case they’re helpful for anyone else

When I made the notes I’ve based this page on, I tried to record choices and menu positions, but there are bound to be minor errors, especially when I was getting confused.

The summary is, I was able to do the migration I wanted and I now have single-command deployment over Git set up. I do recommend IONOS (at least, it’s been fine for the month or so I’ve been here), even if their online documentation could be better.

These notes were written in September 2024, things may have changed since then.

This site’s scale and setup

This website is extremely simple and low bandwidth. I hand-write all the pages in HTML and use limited CSS and Javascript with no frameworks. I highly compress video and images. At time of migration, the deployed website was less than 6 MB and the entire Git repository was under 50 MB. My decision might not be applicable to other people.

My previous web hosting supplier used an Apache virtual host. Deployment was via Git over SSH. Documents were placed in an htdocs subdirectory of the Git repository. It was a basic Linux/Apache/MySQL/PHP implementation, but I wasn’t using the database or PHP.

Some ground rules

My goal was for zero downtime. OK, this site doesn’t need five-nines uptime, so being offline for seconds or minutes (or even hours, if I’m honest with myself about this site’s level of traffic) wouldn’t be a problem . However, I didn’t want to commit to a step unless I knew it was going to work, and part of the point of having a personal hobby website is to play at being something more sophisticated.

Since I don’t have a database, I didn’t have to worry about synchronising the updates to that. I could do overlapping migration where the old and new web hosting served the same pages and people would switch over as DNS changes propagated.

In these notes I’ll use domain as a place holder for the domain for this website (pertinentdetail.org). Sometimes I’ll expand it explicitly so you get the idea.

Selecting a plan

At the time of migration, online, IONOS UK appeared to offer packages with the following prices excluding VAT:

However, a link just before the table also mentioned a starter package. This also appeared when I press the “See all features” button. The extra option was:

Given the scale of my website, I selected the starter package. This would be more expensive initially (£24 for the first six months instead of £6 for the Plus package) but would close by nine months (£36 for both of these and also for Standard). I wanted the minimum package to ensure I wasn’t replying on features only available in the more expensive package.

Checking back now (November 2024), the starter package is no longer available. The IONOS US website has slightly different names and prices.

Initial steps

Having created the account the documentation didn't get any better. Logging on to my new account. there's was nice banner, that said something like:

Your next step

Read our quick start guide

Create your own wesbite in a flash. Want to know how to get started? Then it is worth checking out our Quick Start in the Help Centre. Here we have put together useful tips and tutorials to get you started.

The quick start guide looked useful. However, when I tried to read it, the server gave a 404 error. Ho hum.

Creating the SFTP/SSH access

The IONOS Linux web hosting comes with SFTP/SSH access. I wanted Git push deployment as that’s what I used to have and it makes things simple. I came across Deploy a website remotely using Git which was very helpful and needed very little tailoring.

I logged into my new web hosting instance using SSH. Then, I did the following (commands are in brackets because this isn’t an exact record of what I did):

On my development machine:

This replicated the Git repository from my machine onto the IONOS server and deployed it into a suitable directory. While getting the right setup, I got these errors which you might see.

fatal: not a git repository: '~/domain.git'
You used ~ instead of $HOME in hooks/post-receive
fatal: not a git repository: '/some/path/domain.git'
You mistyped the path: read the error carefully, there’ll be some mistake.

Testing in staging

IONOS does provide the ability to deploy your website onto a random test domain so you can check it’s responding before you make it live. They call these staging domains “system domains”. So, my next step was to use this to make sure the files had made it over intact and the website was correctly configured.

On the IONOS control panel:

This returned a name like s1234567890.websitehome.co.uk. Note that this is accessible only over HTTP, not HTTPS.

I checked the deployment was working, including the .htaccess rewrite rules I use to provide URLs without file extensions.

Tell IONOS about the real domain

The next step was to get the IONOS servers to server the website for the correct URLs. Note that I did not change live DNS settings yet. So, anyone coming in externally will still go to the old web server. To check the IONOS servers are happy with the domain names, I need to bypass DNS. I used Curl for this.

Before IONOS will let you configure their servers to respond to a non-staging URL, you need to confirm you have ownership of that domain by making DNS changes. They provide a TXT record that you need to add to your DNS entries on your current DNS provider. Having done that, you need to wait for the DNS records to propagate, IONOS to detect it, at which point it allows the external domain to be served from its servers.

Note that, by default, if you ask IONOS to serve pages for a domain, it will serve them both at that bare domain (for this site, pertinentdetail.org and at the www subdomain (www.pertinentdetail.org). We’ll fix that later.

During this process, IONOS is maintaining its own DNS record for your domain. It’s not live as the domain is till using the nameserver at my old supplier. However, this is very convenient as it allows the DNS to be set up correctly before any transfer, and allows you to see what settings IONOS wants so you set them on your existing nameserver.

With that done, back on the IONOS control panel:

I needed to test the domain was being server correctly from IONOS’s servers whilst also confirming that anyone externally would still be talking to the old servers. For this I used curl with the -v option so I could see the IP addresses Curl was using.

Also, my old server was set up for HTTPS, whereas IONOS was still on plain HTTP (no SSL certificate yet). This allowed

curl -v http://www.domain
The result was a redirect by the old name server to https://www.domain, and the IP address (shown by the -v option) confirms this came from the old server.
curl -v --resolve www.domain:80:aa.bb.cc.dd http://www.domain
This returned the page without a redirect, and checking the IP address showed this came from IONOS’s servers.

I want requests to domain to be redirected to www.domain.

Note that the control of the website (for example, which part of the webspace is used for its files), is now in the Subdomains tab.

On Domains & SSL, DNS tab, the A records for the @ and www are now different. www should be what it was before, @ is something else (let's say, ee.ff.gg.hh).

Back to Curl for testing:

curl -v --resolve www.domain:80:aa.bb.cc.dd --resolve domain:80:ee.ff.gg.hh http://www.domain
Returns full web page.
curl -v --resolve www.domain:80:aa.bb.cc.dd --resolve domain:80:ee.ff.gg.hh http://domain
Returns 302 response redirect with Location http://www.domain.

Prepare for SSL: shadow configure DNS at IONOS

Note: To use SSL with a website on IONOS you have to use their DNS servers.

Well, at least this is true for their automated SSL that comes with their web hosting. Maybe if you’re doing something more complex, you don’t need to do this, but if so, I couldn’t work it out. In any event, I want this to be hassle free which means getting IONOS to renew certificates automatically.

We can take advantage of IONOS’s ability to edit DNS records even though their not live to get everything set up.

For reference, at this point, the error when enabling SSL says:

The SSL certificate can only be used for domains that are using IONOS name servers. To set IONOS name servers for domain, select 'Use IONOS Name Servers' in the 'DNS Settings' section.

Except those instructions aren't clear. In the Domains & SSL section, there's a DNS tab. At the bottom of that there's a recommended help topic of DNS Settings, but doesn't quite have anything matching. However, there is a Nameserver tab which gives you some name servers to use at your external domain provider.

Time for a break

At this point, I’d gone as far as I could without affecting the running domain. So, at this point I took a break.

This was useful. During the break, I thought of a way to get a bit further without risking downtime on the website if, for example, I couldn’t transfer and enable SSL all in one go.

Enabling SSL before switching hosting for the live site

There’s a chicken-and-egg problem here. I can’t activate SSL without transferring name servers. However, if I transfer name servers with the live URLs pointing at the IONOS web hosting servers, SSL won’t work and all HTTPS URLs will break.

The plan I came up with was to alter the shadow DNS records so the live URLs pointed at my old web hosting supplier. This will allow me to transfer the name server without breaking HTTPS. Then, I could take advantage of IONOS’s use of wildcard SSL certificates to create a domain certificate and test it on a subdomain before switching the live URLs.

I could reverse the order of some of this to get some more steps done before committing to the nameserver transfer.

Switching nameservers

On the old supplier, change the nameserver to the values supplied by IONOS. Old supplier says NSset async started.

Now we have to wait for the transfer. IONOS says up to 72 hours.

Some time later:

nslookup
set type=ns
domain

This shows IONOS name servers.

Note that, unlike IONOS, my old supplier does not let me view DNS entries any more, so I couldn't set up a shadow record for transfer back if anything went wrong.

Enable SSL

Remember at this point, domain and www.domain URLs are still pointing at my old web hosting supplier. Only www2.domain is pointing at IONOS. However, this is enough to get SSL activated.

Time to test SSL with Curl:

curl -v http://www2.domain
OK, using IONOS web hosting
curl -v https://www2.domain
OK, using IONOS web hosting
curl -v http://domain
redirect using old web hosting
curl -v http://www.domain
OK using old web hosting

Being too cautious leads to a mistake

The next step is to transfer DNS for the main URLs. Since I always redirect domain to www.domain all external URLs should be using the latter. So I thought I’d try to move them one at a time starting with the bare domain as no one should be using that so an error would be less severe.

Wait for DNS to propagate (not too long as I set five minute TTLs earlier).

Test with Curl:

curl -v http://domain
Redirect using new web hosting.
curl -v https://domain
error:0A000438:SSL routines::tlsv1 alert internal error.

Firefox also reports SSL_ERROR_INTERNAL_ERROR_ALERT. SSL Labs also shows an error. This error is coming back from the server.

And now I have downtime, at least it's not on the main www.domain URL.

Transferring to new hosting a bit earlier than expected

My problem now is I can’t tell if the problem is affecting just the bare domain URLs, perhaps just because it’s an artefact of forwarding, or would also affect the important www.domain URLs when serving pages.

My plan was to distinguish whether it was the bare domain URLs or forwarding by serving both myself rather than using IONOS’s forwarding option. I used an Apache forwarding rule to detect the request was to the bare URL and forward to the www subdomain:

RewriteCond %{HTTP_HOST} ^domain$ [NC]
RewriteRule ^/?(.*)$ https://www.domain/$1 [R,L]

I used the IONOS control panel to point the domain at the web space. However, I forgot to untick the “Also set up for www subdomain” option. This meant both domain and www.domain URLs were pointing to IONOS’s servers before I could check that SSL was working.

Fortunately, it all worked successfully.

The last thing to do was to delete the test www2 and www.www2 subdomains and confirm everything remained working, which it did. I still had the ability to switch back to my old web hosting supplier as I had time left on that contract.

With everything up and running successfully, I haven’t gone back and worked out a correct sequence for the final stage of the transfer and I don’t want to risk a return of the SSL errors by experimenting.

Lessons learnt

The most important lesson I learnt was to be glad I’d set a reminder three weeks before my web hosting contract was due to renew for a year. I then looked at renewing manually early (just in case something went wrong with the automatic payment). At that point, I noticed the price.

Although I had to move web hosting suppliers in a hurry, that was much better than finding out some time after the renewal had gone through.

Having a simple website that doesn’t rely on any features specific to my old web hosting supplier made moving simple.


[Up] Up to the welcome page.
Comments should be addressed to webmaster@pertinentdetail.org.
Copyright © 2024 Steven Singer.