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:
- Standard: £6/month (£3/month for the first six months)
- Plus: £9/month (£1/month for the first six months)
- Premium: £16/month
- Ultimate: £24/month
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:
- Starter: £4/month
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):
- Create a top level directory with the name of the domain plus
.git
(mkdir pertinentdetail.org.git
). - Create a top level directory with the name of the domain (
mkdir pertinentdetail.org
). - Change into the .git directory (
cd pertinentdetail.org.git
). - Create an empty Git repository without a checkout (
git --bare init
). I can get away without any other options as the default branch name is still the same default as when I created my website years ago. I'll use branch in the examples. - Create and edit the file hooks/post-receive (
vi hooks/post-receive
). - Add the following contents (note the use of
$HOME
to indicate home-relative paths,~
doesn’t work here):#!/bin/sh git --work-tree=$HOME/domain --git-dir=$HOME/domain.git checkout -f branch
- Save the file and exit the editor (
:wq
). - Mark the file as executable (
chmod +x hooks/post-receive
).
On my development machine:
- Add a new Git remote branch for this server. username and servername are the details from my new IONOS account. Note the single quotes and the
~
:git remote add ionos 'ssh://username@servername/~/domain.git' git push ionos branch
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
inhooks/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:
- Add domain.
- Use system domain.
- Connect to webspace.
- Select path
domain/htdocs
.
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:
- Domains & SSL, details tab
- Add an external domain.
- Connect to webspace.
- Select path
domain/htdocs
. - Go to the Domains & SSL, DNS tab.
- Look up the A record for the www entry in the DNS records. Let’s call that address aa.bb.cc.dd.
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.
- IONOS control panel, Domains & SSL.
- Set up web forwarding.
- Untick the also set up for www subdomain.
- Select Type as Your domain.
- Select Redirect as destination as 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.
- IONOS control panel, Domains & SSL, DNS tab.
- Since I am not moving my email hosting, I need to deactivate the connection to IONOS’s mail provision. This can be done by deleting the mail service (the trashcan next to the MX record). This will remove IONOS’s MX, SPF and DKIM records.
- To keep my old mail service, I copy the following records:
- MX (multiple records).
- The TXT record for SPF.
- The CNAME record for DKIM.
- The CNANE records for imap, pop, smtp and webmail
- I copy other TXT records such as Google Site Verification.
- I then double check everything. I count the number of records I have, and pay close attention to which ones are registers on the domain (@) and which ones have names (such as _dmarc or xxx._domainkey).
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.
- IONOS control panel, Domains & SSL, subdomains tab.
- Create a new subdomain www2. This will also end up creating www.www2 but that's harmless. I'll delete it later.
- Once again, Set the destination to webspace /domain/htdocs
- Go to the DNS tab (which, if I recall correctly defaults to filtering for the subdomain).
- Disable the mail service for the new domain.
- Back at the top of Domains & SSL.
- Adjust the destination.
- Go to the DNS tab.
- Disable the webhosting service for www. This will also disable the forwarding servers for @.
- Add an A record for @ with the address of the existing webhosting servers on the old supplier. Use a TTL of 5 minutes (for fast reversion if something goes wrong).
- This also added an A record for www. Since that's not correct for me. Delete the A record, add a CNAME record to point to the old supplier (again, using a TTL of 5 minutes).
- Review the DNS records against the old supplier.
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.
- IONOS control panel, Domains & SSL, domain, details.
- Activate SSL encryption.
- SSL Starter wildcard.
- Activate Now.
- domain.
- Use with my IONOS website.
- Set Up SSL Certificate.
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.
- Wrong: IONOS, Domains & SSL, domain, details
- Wrong: Adjust destination.
- Wrong: Forward Domain.
- Wrong: Your domain.
- Wrong: www.domain.
- Wrong: Untick “Also set up for www subdomain”
- Wrong: HTTP redirect
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 to the welcome page.
Comments should be addressed to webmaster@pertinentdetail.org.
Copyright © 2024 Steven Singer.