WordPress media upload in wrong folder

This one is a little weird. I had inherited a web site; I do some volunteer service, and the original web site was done in FrontPage 98. People who used the web site knew the URL to a particular file on that web site: the meetings directory.

Later, a member showed me an app that was super useful; but the best way to implement it was as a WordPress plugin. I guess I’m learning WordPress now (not that I was a fan of FrontPage 98: good riddance).

After the conversion, the members that knew the URL to the meeting directory complained that their bookmarks were broken. Fair enough, I had broken them. I got a redirector plugin, and created a 301 redirect from the known URL to the new location.

But there was a problem with the new location: my default WordPress URL scheme for the uploads folder includes putting year and month in the URL. So an upload today would be in ./uploads/2023/04/

What’s going to happen next month, when there is a new meetings directory file? It isn’t going in the April folder, I can assure you. Am I going to have to update the redirect every single month?

I’ve been doing computers for 40 years. Having to update the redirect every single month is stupid. Why can’t I just move the file to the root of the uploads directory?

Well … turns out WordPress needs to have a database entry for every file. I can move the file, but that orphans that entry in the database.

Even if I do move it, how does the old office manager update it? A regular old Media Library upload will upload the new file to a dated folder, and now we’ve got two files with the same name but different locations and URLs.

I had to find a plugin that does media file replace (in-place), but that wasn’t too hard. I use Enable Media Replace by ShortPixel. It was pretty easy to train the old office manager to follow the steps: click on the file in the Media Library, find the Replace button, and follow the directions on screen.

That was six years ago. This morning, the new office manager deleted the file. She had the presence of mind to recognize that something was wrong; but not enough to halt before doing damage. The new meeting directory file now has the wrong name and the wrong URL.

I kind of hate WordPress for the permissions trouble. What looked to be simple with the WordPress CLI (command line interface), wp media import did not work. ./wordpress/bin/wp would only ever get Permission denied. I should probably mention that the “user” I’m logged in as is not the same user as who runs the web site and has access to all the files.

Here are the steps I had to take to repair the damage. I got to figure them out; hopefully you will find them useful. And if the file gets damaged again, I’ll have these instructions for a quick repair.

  1. ssh into the server and find the uploaded file. In this case it will be in ./uploads/2023/04/
  2. rename the file to the old file name.
  3. move the file from ./wordpress/htdocs/wp-content/uploads/2023/04/ to ./wordpress/htdocs/wp-content/uploads/
  4. Delete the file in the WordPress Media Library (web page). WordPress will still show you the file, because it isn’t looking at the file, it’s looking at it’s database entries about the file. It looks like the file is there, but it’s a phantom. Delete it.
  5. Back to the server command line prompt: change the file system permisssions to be way too permisive.
  6. ./wordpress/bin/wp media import ./wordpress/htdocs/wp-content/uploads/file.pdf --path=./wordpress/htdocs/ --skip-copy
  7. change the file system permisssions back. ASAP.
  8. When you look at the WordPress Media Library (web page), you will see your file again – but this time it has a non-time-stamped URL. Huzzah! Paste that link into whatever page needs to serve it up. In my case, since I moved the new file to where the old file was, the links were still good.

How to give way too many permissions (this is terrible):

sudo chmod -R 777 /path/to/folder/wordpress

How to fix the permissions:

find ./wordpress -type d -print0 | sudo xargs -0 chmod 755

find ./wordpress -type f -print0 | sudo xargs -0 chmod 644

The Helm migration is complete

As I mentioned before, The Helm email appliance company is calling it quits, which I understand. If the business isn’t going to make it, it is better to pull the plug than just keep letting things linger. Best of luck to them on their next adventure.

So, what did I do?

  • (there was a detour while Amazon pissed on their customers wanting to run Mail-In-A-Box) (me)
  • I provisioned the smallest Ubuntu 22.04 LTS machine that Linode has.
    • Mildly annoyed that it doesn’t really support LVM (Logical Volume Manager); they have a backup service that runs an agent inside their machines, and that agent doesn’t do LVM. Still, I know that I’m going to need to grow disks, so I had to learn how to re-partition the Linode so I could do LVM. LVM done.
  • I made a mail server on the Linode machine at a domain name I have that I don’t really use. I followed the excellent guide from Christoph Haas at workaround.org: ISPmail guide for Debian 11 “Bullseye”
  • I got RoundCube webmail working for the domain name; complete with SPF and DKIM.
  • I got Thunderbird to send and receive from the domain name.
  • Then I added Nextcloud to the same box. I wanted CalDav for contacts and calendar, when I eventually hook my iPhone to it.
    • The Nextcloud documentation really needs a lot of work here. If I were retired, I would like to help them with their documentation.
    • Finally, I have the files.example.tld function of The Helm replaced, although at a different domain name.
    • Rspamd uses Redis, but so does Nextcloud. But one uses the network stack, and the other, Unix sockets. Get them both set same.
  • Then I added Duplicati backup. This wasn’t great, as it added a ton of overhead in the form of Mono, just for a graphical user interface.
  • I realize that I’m going to want to host my WordPress here too. I don’t want to have to wrangle four Let’s Encrypt SSL certificates, one for each domain. What about a single wildcard SSL certificate?
    • Yes, that can be done, but: my domain names registrar doesn’t support it. Linode does, though. I install the Linode DNS agent on my machine, and spin up Linode DNS servers to do the DNS work. I have to configure my domain names registrar to tell the rest of the world that Linode is where my name servers are.
    • Somewhere in there I installed the Unbounded DNS resolver. Looks like I need this on my home machine, too, for Home Assistant.io1
  • I got to the point where I could request the domain name transfer. Turns out the people at The Helm were going through Ghandi.net. Ghandi.net tooks as long as they legally could, before actually doing the DNS transfer.
    • Ghandi –> registrar, then registrar to point to Linode. Linode DNS needs to be reconfigured for SPF and DKIM. I had gotten some DNS records wrong, too.
  • Thunderbird to connect to the mail.domain.tld, and though the name hasn’t changed, everything underneath has. Thunderbird is not happy; I lose all my old mail.
    • Well, I didn’t, but it is in a new folder now, so that I’ve got an old version of my mailbox and a new version of my mailbox, and they are separate. Not ideal. Perhaps I could have done an IMAP to IMAP transfer, if I hadn’t already moved the domain name.
  • Hey, looky there: one of the volumes filled up (but everything else was unaffected). Time to grow a disk using LVM.
  • iPhone to connect to CalDAV; phew that was not well documented and had tons of conflicting information.
  • Not really happy with Duplicati, so I remove it and Mono, and install Restic backup instead.
  • Okay, so the last thing left to do is to migrate this blog from Amazon to this new Linode machine. The transfer using NS Cloner goes well, as it usually does. But domain names need to be updated via Let’s Encrypt certbot.
    • Crud. I’m on holiday out of town with family, and have only a Windows laptop with me. Per best practice security protocols, I can only ssh in from home. Logging in via root@ is blocked, and I don’t think I can even do a ssh-copy-id without getting in first and lowering the root login barrier. The certbot to add gerisch.org to the domains list is going to have to wait.
  • Here I am, at home, and I’m done. Dovecot, Postfix, RoundCube, Nextcloud, and WordPress all on one box.
  • While I was on holiday, I took the .mp3 files on the Nextcloud, and made Nextcloud Music Player playlists for the different types of files. Then on the 16 hour drive home, my iPhone logged in to the Nextcloud web interface and played playlists.
    • It’s a bit of nirvana to me, to have a large list of songs (randomized of course) playing absolutely advertising-free because I paid for the songs in the first place.
  1. I ended up not connecting Home Assistant to their cloud ↩︎

WordPress initial install error: “Cannot select database”

The full error is

Cannot select database

The database server could be connected to (which means your username and password is okay) but the database could not be selected.

What is actually wrong is that you don’t have a file wp-config.php

From what I gather, it used to be that wget http://wordpress.org/latest.tar.gz would bring in a .tar.gz file which contained wp-config.php. That file isn’t there any more in the source.

In the old scheme, the installer would modify it with the user name, password, database table name and then proceed with the rest of the installation.

If I had to guess, I’d guess the new scheme is supposed to do cp wp-config-sample.php wp-config.php and then the installation picks up as it did before (modifying it with the user name, password, database table name); then proceeding with the rest of the installation.

Someone got the idea that instead of maintaining two wp-config files, they could maintain and ship one, and then copy it during install. This is a good idea: makes the source a tiny bit smaller, saving storage and transfer bytes. Just one thing though: do the copy, stupid, and check your results. Err out in a rather ugly mess if you didn’t get the copy right – then at least you’d hear about it mightily if you got it wrong.

The solution is to manually copy the file, edit it with the user name, password, and database table name, and then try to install again, twice.

If you simply copy wp-config-sample.php to wp-config.php and then run the install, it’s going to bark at you that wp-config.php already exists. Also, it is not going to ask you for the user name, password, and database table name. Since you already had to fuck around with the wp-config.php file, surely you already took care of the user name, password, and database table name.

So,

  1. start the install from scratch
  2. copy the file wp-config-sample.php to wp-config.php
  3. edit the new file, supplying database table name, user name, and password
  4. start the install from scratch again and let it bark at you that the new file already exists
  5. click the try again link.

Finally the “famous five minute install” is done after you spent thirty minutes in frustration finding this post and not doing what the documentation says.

Personally, I think it is low quality programming to leave this bug in the basic install process. It’s been there for months. So, what? No-one at Automattic tests the installer any more?

PHP Upgrade for Bitnami Lightsail WordPress

Turns out the way to upgrade is to spin up a new box (or two) and migrate.

Step 1) Spin up a new instance. At the moment I’m using Amazon Lightsail.

Step 2) assign a DNS entry to it. At the moment I’m using Hover. I do have the DNS entries set to a 15 minute time-to-live. Whatever IP address that Lightsail assigned is what I put into Hover.

Step 3) Set the new machine to know it’s new host name.

  1. Of course, the what-used-to-work is different now. The command is now sudo /opt/bitnami/bncert-tool

Step 4) Get logged in to the new instance of WordPress. BTW, the login user name has changed. It used to be bitnami now it is user

Step 5) Update WordPress to the current version, if it’s out of date.

Step 6) Delete the plugins in the base image that won’t be migrating over. BTW, one of the plugins, TaxoPress, apparently had a different name prior to updated and would err out instead of deleting. Do upgrade the ones I’m keeping.

Step 7) I use NS Cloner and NS Cloner Pro to migrate between servers. I like the people there; they did actually help me when I was having an error getting it to run. I was migrating a site with All-in-One Event Calendar by Time.ly and apparently that plugin just does not play nice with database records or something. I am lucky that I bought a licence a long time ago; since then they have had to raise their prices. As a tool, it has been working great, but the price increase was really steep. If I did this for a living, I’d have no qualms about paying the annual license fee.

And then ….

The problem is that I just migrated gerisch.org to davidgerisch.xyz, but I really want the web site on gerisch.org

Okay, so there are two ways out of the problem here.

Alternative 1 is to go to the old gerisch.org and run sudo /opt/bitnami/bncert-tool and change it to something else and then go to davidgerisch.xyz and run sudo /opt/bitnami/bncert-tool and change it to gerisch.org AND THEN do database search and replace to swap out davidgerisch.xyz to be gerisch.org instead – all on the new machine. My experience with these sort of database search and replaces hasn’t been wonderful. There’s also the problem of being logged in to the web site I’m changing the name of; at some point I cut off my own feet while I’m trying to stand on them (DNS -wise).

I went with alternative 2:

  1. In Lightsail, detach the static IP that gerisch.org is pointing to.
  2. In Lightsail, delete machine (old) gerisch.org
  3. In Lightsail, spin up (new) gerisch.org
  4. In Lightsail, attach the static IP for gerisch.org to this new machine.
  5. Run sudo /opt/bitnami/bncert-tool to assign the machine it’s new name gerisch.org
    1. Note that with alternative 2, the Hover domain name registration hasn’t changed. The public IP is on a different box (running an out-of-the-box WordPress install), but from the DNS point of view, this is simpler – nothing has changed. DNS name gerisch.org is still pointing the same IP address it always has.
    2. With alternative 1, I had the problem that the old box “knew” it was gerisch.org, so I had to run bncert-tool to change it to something else. If I didn’t, and I just ran bncert-tool on the new box, trying to claim gerisch.org, the Let’s Encrypt people would complain, correctly, that this domain name is currently in use on a box it can talk to right now, and that box has a different IP address. Am I trying to steal it’s identity?
  6. Do the top steps 4, 5, 6, and 7 again: Update WordPress, plugins, and migrate with NS Cloner Pro.
  7. Delete the running machine davidgerisch.xyz – it was only every going to be a temporary container anyway.
  8. Change all the Hover entries to point to the same IP as gerisch.org

My site is pretty small, so the migration with NS Cloner Pro takes under five minutes. If I had more data and it was going to take longer, I’d probably figure out how to enable FTP so that NS Cloner Pro could use that.

Advertising sucks (again)

I don’t know how much money there is in tracking people and selling their online profiles / behavior patterns. My guess is that a huge amount of folly has people convinced that their folly is worth it. I hope that they are severely disappointed.

I first noticed with WordPress, that Automattic (the company behind WordPress), really wants to track your every move. They created the Gravatar system, and it is something that you cannot opt out of. You as a WordPress admin were not allowed local profile pictures – you had to use Automattic’s avatars or use nothing. And now it’s gotten worse. Your web site won’t run right without reporting in to the Automattic servers.

Every visit of yours to any WordPress site will generate a “hit” of you going to that web site. It’s worse than cookies, because at least you can delete your cookies.

What I’ve noticed is that if I have uBlock Origin turned on and “Block remote fonts” turned on, then WordPress does not render the admin panel correctly. Remote fonts are a way for the web site to get your machine to “phone home” to someone else’s servers. Apparently, Dahsicons have been a thing since WordPress 3.3.

Why should my web site make a call to Automattic’s servers just because you visited my web site? It does that with Gravatar (unless I try really hard to block that).

Other web sites appear broken when remote fonts are turned off.

I have a hard time believing that there is any good value to me for my web browser to retrieve on every page load an image file from a remote server just to show a button.

Bitnami phpmyadmin

Just a quick note for me to easily find and remember how to access PHP My Admin on a Bitnami WordPress instance

From the command line on my local machine:

ssh -4 -N -L 8888:www.gerisch.org:443 -i $insertpathtopemfilehere nottheadmin@gerisch.org

And then in a browser:

https://www.gerisch.org:8888/phpmyadmin

Lastly, remember that the login name to phpmyadmin is root (not the Bitnami application password, or any other user name).

Because public Internet access to PHP My Admin would be a Very Bad Idea, the Bitnami WordPress image is configured such that PHP My Admin refuses to run, if the requests don’t come through www.gerisch.org

This is a good idea.

But what that also means is that I need something listening on my www.gerisch.org address, that can forward the network traffic to the remote web server.

ssh -4 says use IP v4 addresses only (suppresses IP v6 errors if your machine doesn’t have that).

ssh -N says do not execute remote commands (all we’re going to be doing here is port forwarding).

ssh -L says local to remote port forwarding will be done.

8888:www.gerisch.org:443 says the local port to listen on is port 8888, the local address to listen on is the home address of www.gerisch.org, and when listening on the “server” www.gerisch.org, know that it will be listening for port 443 traffic (https instead of http). Another way of thinking about this is that your web browser that is throwing HTTP GETs and PUTs will be throwing them at port 8888, since that is the port the service is listening on. But when the traffic is thrown across the Internet, ssh is going to throw the traffic to www.gerisch.org port 443. Yet, www.gerisch.org:443 is really just a front for gerisch.org:443

ssh -i says to use a public/private key pair for logging in (instead of a password). $insertpathtopemfilehere is the variable that holds the path to the .pem file.

ssh nottheadmin@gerisch.org is the actual remote login name and server name.

COVID-19, new water heater, WordPress annoyances, Zoom meetings, oh my

Wow a lot of stuff has happened since my last post. I’m still catching up; but, I didn’t want to go too long without pointing out I’m still alive.

COVID-19: John Hopkins University has some computer science students who are doing data gathering and mapping that on to ArcGIS. The web page works as a status report of where we are today. Thanks to Ars Technica for the original article.

Today, Italy went over the 10,000 dead mark.

New Water Heater: I went two weeks without hot water. I am grateful this was before COVID-19, because I used my gym membership for my daily hot shower. In fact, a friend of mine, way back when, pointed out that if you ever go homeless, a gym membership is a way to stay human for around $20 per month.

And now the gyms are closed due to COVID-19. Well that hurts the homeless even more.

The whole water heater debacle deserves a post of it’s own, so I will do that, later.

WordPress Annoyances: there are things that don’t work, and, the WordPress Support Forums are a mass of dead and empty posts of people asking for help. Other forms of help don’t seem to be, either.

I want to migrate between sites, and from single-site to multisite, but man this stuff just does not work.

Zoom Meetings: Man oh man, I wish I had listened to my stock picking guys when they said Zoom was the new hotness in video conferencing over the Internet. Zoom stock price has nearly doubled since then. And now, even I use Zoom, and I know of three people who signed up to pay a monthly subscription. By the way, Discord is pretty cool, too.

Microsoft should be ashamed of themselves that they couldn’t leverage their leadership with Skype and Teams into being the industry leader. Of course Google had a shot way back when with Hangouts, too. Google though is just kind of a big failure to get anything done since merging with Doubleclick and abandoning the whole “Don’t be evil” motto.

New site steps

Note this is for a new WordPress Multisite

  • Log into AWS Management Console
  • Lightsail Create a new instance (Linux, WordPress Multisite)
  • Create a new static IP address
  • Assign the static IP address to the new instance.
  • Buy a new domain name (if I don’t have one available) – in this case, gerisch.org
  • Update DNS with the new static IP address
  • ssh – i path-to-pem-file-for-AWS-instances bitnami@gerisch.org
  • Make Ubuntu like OpenSUSE
  • Log out, and log back in (get the benefits of pageup for history search, and .. as the cd .. alias)
  • cd /opt/bitnami/apps/wordpress
  • sudo ./bnconfig --machine_hostname gerisch.org
  • sudo mv bnconfig bnconfig.disabled
  • sudo apt upgrade
  • sudo init 6
  • wait for reboot to finish
  • ssh – i path-to-pem-file-for-AWS-instances bitnami@gerisch.org
  • sudo /opt/bitnami/bncert-tool

At this point, I get a warning:

Warning: Custom redirections are not supported in the Bitnami WordPress Multisite Stack. This tool will not be able to enable/disable redirections.
Press [Enter] to continue:

An updated version is available. Would you like to download it? You would need to run it manually later. [Y/n]:

sudo /opt/bitnami/bncert-tool

Welcome to the Bitnami HTTPS Configuration tool.

Domains

Please provide a valid space-separated list of domains for which you wish to configure your web server.

Domain list []:

gerisch.org

The following domains were not included: www.gerisch.org. Do you want to add them? [Y/n]:

The interesting thing here is that (if I’m interpreting things correctly) that WordPress Multisite really does not want one of the subdomains to be www.gerisch.org – yet here, Bitnami, through the Let’s Encrypt really does want one of the domains to be www

I hit <Enter> which signifies yes

Changes to perform

The following changes will be performed to your Bitnami installation:

  1. Stop web server
  2. Configure web server to use a free Let’s Encrypt certificate for the domains:
    gerisch.org www.gerisch.org
  3. Configure a cron job to automatically renew the certificate each month
  4. Configure web server name to: gerisch.org
  5. Start web server once all changes have been performed

Do you agree to these changes? [Y/n]:

I hit <Enter> which signifies yes

Create a free HTTPS certificate with Let’s Encrypt

Please provide a valid e-mail address for which to associate your Let’s Encrypt certificate.

Domain list: gerisch.org www.gerisch.org

Server name: gerisch.org

E-mail address []:

I put in my personal email address

The Let’s Encrypt Subscriber Agreement can be found at:

https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf

Do you agree to the Let’s Encrypt Subscriber Agreement? [Y/n]:

I hit <Enter> which signifies yes

And after a bit of work, the configuration of my new web site to be SSL protected is complete.

How to use Lightsail snapshots to revert to a previous version

I have the new Bitnami WordPress multisite web server up and running. I’d like to make a backup of it, prior to mucking with it, so that I can revert back if needed.

Schrodinger’s Backups: The condition of any backup is unknown until a restore is attempted.

Murphy’s take on Schrodinger’s Backups: You’re fucked. The backup is dead.

Well, that is often the case when you just lost the computer, and you now need to restore from your “backups”.

Let’s see what it takes to successfully take a Lightsail snapshot and restore to it.

Technically, you spin up a new instance, move the IP address, and delete the old instance. So you will be incurring a little bit more extra charges with Lightsail, because for a little while, you had two instances. Snapshots cost money, too.

Step the first: shut down your instance.

In theory, this step should not be necessary. The snapshot process should work on the running image. It probably will.

In theory, there is no difference between theory and practice. In practice, there is.

Although it is a remote chance, there is a problem of database coherency. What if, at the exact moment you take a snapshot, some database transaction is only half-posted? What if one half of the transaction is written to disk, then the snapshot happens, then the other half of the transaction gets written to disk? When you restore, the database is going to no longer be coherent.

For some databases, there are a whole subset of features and work done to ensure atomic transactions that prevent any piece of the transaction of being committed until all of it can be verified to be done. That’s all nice and everything, but what’s wrong with just shutting down the server? If your server is so mission critical that you cannot have a minute or two of downtime, you should be working on clusters of machines that can announce themselves into the cluster, and announce themselves out of the cluster and gracefully transition between states.

Power down the server, and the server is quiescent with the world.

Step the second: take the snapshot.

A picture being worth a thousand words, here’s thirteen thousand words:

Go to the snapshot manager tab a click the Create snapshot button
Lightsail picked a name for you; click the Create button to launch the snapshot process
This takes a minute or three
Once the snapshot is complete, you get the raindrops menu button

Step the third: the snapshot becomes the machine.

The raindrops menu has the option to create a new instance from the snapshot

See that big orange Create Instance button? Click it!

I may be a stockholder of Amazon.com stock, and will see revenue slightly rise as you invoke an additional charge on your account. Click it!
Now there are two instances; one pending, and the other stopped

Eventually, the new instance is running. But we still need to move off of the old instance.

The static IP address that DNS points to is connected to the server that crashed and is going away
The new instance, WordPress_Multisite-2, has a random IP address assigned during creation
After selecting the static IP from the list, click the green Checkmark button to assign it to the new instance
We now see the new instance in the wild, at the old IP address DNS points to
Delete the old instance, so as to not leave trash laying around

That’s pretty much it. The snapshot has been launched as a new instance, and is almost a verbatim copy of the old instance. Almost.

When the new instance was spun up, it got a new security certificate fingerprint.

Bitnami WordPress Multisite – DNS spoofing

In an earlier post, I said I hope you have pointed your domain name at your static IP address. Well, what if you don’t want to?

The point being that the DNS entry for the domain name currently points to the production WordPress site, and really, I would like to set up this multisite WordPress installation without having to change the public DNS entry.

Also, setting up this, my personal blog, I was using No-IP DNS services. I could update the DNS entry for gerisch.org, and the DNS replicated out almost instantly. It was great. But the other web site I’m working on (the one that got me into WordPress at all), is using Network Solutions for their DNS. They take their good sweet time replicating DNS entries out to the world. I don’t really want to post an update to DNS, wait, dink around with the new site while the production site is down, decide to revert to production, post an update to DNS, wait again while Network Solutions gets around to pointing everyone back to the production web site.

It would just be better if the new web server machine never got away from it’s own self when doing lookups for the domain name it will eventually be.

So I can start the WordPress install from the IP address of the server out on the public Internet. However, WordPress during it’s install, is going to do a DNS lookup, and try to invoke code on the server where the DNS really does resolve. Which isn’t where I am. So I’m going to try to install a fake DNS server on the new server, and have it redirect all calls to the old domain to the new server.

Step the first: install dnsmasq

sudo apt-get install dnsmasq

Next, set up listening on the local host address:

sudo vim /etc/dnsmasq.conf

Find your way to the line #listen-address= and edit it thus:

listen-address=www.gerisch.org

And save and exit

sudo vim /etc/dhcp/dhclient.conf

Find your way to #prepend domain-name-servers www.gerisch.org; and uncomment this line. Save and exit.

And now it gets weird.

The Bitnami / AWS Lightsail images use something called cloud-init : https://cloudinit.readthedocs.io/en/latest/topics/modules.html

So if you were going to try to edit /etc/hosts or /etc/resolv.conf you get warned to not edit them by hand, because they will be replaced on next boot. But they sure as heck don’t tell you where to implement edits. Just don’t do it here.

Turns out there are template files in /etc/cloud/templates that hold the magic.

cd /etc/cloud/templates
sudo cp hosts.debian.tmpl hosts.debian.tmpl.original
sudo vim hosts.debian.tmpl

Now I’m going add a line below www.gerisch.org localhost which will be the IP address I want this machine to go to whenever it tries to resolve the domain name of the production web site

And indeed, if I use dig from an ssh session in the machine, dig reports back the local machine’s address, not the one out on the public Internet