Archive
- A list of the letters that are known not to be in the solution word.
- A list of the letters that must be in the solution word.
- For each position, a list of the letters that must to be at that position.
- For each position, a list of the letters that must not be at that position.
Touristfahren
Last Touristfahren day at the 'ring. Lots of traffic but lots of fun. Driving a Renault Megane RS.
Two for One
Leading North American cryptic crossword setters Emily Cox and Henry Rathvon (collectively known as Hex) recently retired, just about the time that I became more interested in cryptics. Cryptics are popular in Britain, so many of the more challenging puzzles on line are made more challenging by the presence of British references.
I have been working my way through some of Hex's older puzzles published in Canada's National Post. The puzzles are not available through the Post website, but can be found here.
A New York Times cryptic from a year ago tripped me up with the clue Obscure quote spreading around on Democrat. I already had the following letters from cross-words:
R _ C _ _ _ _ _E
I assumed the word to be RECHERCHE and I assumed the clue was some how related
to HRC -- Hilary Rodham Clinton. Turns out that the answer was RECONDITE,
providing a lovely pair of nine-letter synonms sharing their first, third, and
final letters.
The official explanation from The Times offers:
This solution is also an unusual word, with a difficult container clue. “Obscure quote spreading around on Democrat” solves to RECONDITE, which means “dealing with abstruse or difficult subjects.” To solve, wrap a word for “quote” — RECITE — around OND, or “on Democrat.”
My first thought had been that the Democrat was Gary CONDIT.
Edge Case
Useless information: If you share a New York Times subscription with someone else, and you both play Wordle, you can maintain your individual streak data as long as you use different browsers to access the game. Using the WordleBot, however, requires a New York Times login, and Wordle will not maintain multiple users' streak data when the users login using the same account credentials.
One of the interesting bits of information that the WordleBot provides is the number of possible words that were available at each step in the game, letting you know the degree to which your solution was lucky or predestined.
After finishing the [Regular Expression Dictionary] MISSING LINK I decided to replicate this functionality. I created an app that would list possible Wordle words, given a series of guesses and the colors assigned by Wordle in response.
The service that I wrote for this application accepts two strings, one of the guesses and one with the corresponding colors. If one were wondering, for example, given these guesses, how many alternatives existed to QUOTA for this Wordle:

you would provide the strings SMARTTABLEATTIC and BBYBYYYBBBYYBBB,
This service (and an associated rudimentary front end) have been up and running for a few months, and they have allowed my Wordle companion to see what other possible solutions exist.
Until today, when it responded

The code records the following information from the supplied letters and colors:
@app.route("/red/wordle/",methods=['GET', 'OPTIONS'])
def wordle():
letters = request.args.get('letters').upper() # Concatenation of the guesses
colors = request.args.get('colors').upper() # and their colors (B,Y, or G)
# Input validation not shown
never = ""
always = [ "","","","","" ]
elsewhere = [ "","","","","" ]
required = ""
for i in range(0,nwords):
words.append(letters[i*5:i*5+5])
for j in range(0,5) :
if colors[i*5+j] == 'B' :
never += words[i][j]
elif colors[i*5+j] == 'G' :
always[j] = words[i][j]
required += words[i][j]
else: # yellow
elsewhere[j] += words[i][j]
required += words[i][j]
Lines 16-17 assume that if a letter is colored B (black), it does
not appear in the answer. In fact, as in the case of ATTIC, if
the guess contains multiple instances of a letter, all of which are
incorrectly placed, only the first instance is colored Y (yellow).
This represents a choice by the Wordle UI designer, since it would be
equally reasonable to color all the instances yellow.
The subtler error is in the way the parsing code represents the
information provided by the game. The always and elsewhere arrays
are meant to contain the characters at each position that must be
present (green) or are required elsewhere in the word (yellow). Given
the behavior of the game, it would make more sense to record for each
position which letters are required (green) and which are prohibited
(yellow or black) and separately maintain the global lists of
required and prohibited words.
The corrected code changes the order in which the colors
are processed, and only adds
letters to the never array if they are not already in the required
array.
never = ""
always = [ "","","","","" ]
prohibited = [ "","","","","" ]
required = ""
for i in range(0,nwords):
words.append(letters[i*5:i*5+5])
for j in range(0,5) :
if colors[i*5+j] == 'G' :
always[j] = words[i][j]
required += words[i][j]
elif colors[i*5+j] == 'Y' :
prohibited[j] += words[i][j]
required += words[i][j]
else :
prohibited[j] = words[i][j]
# It's only a never if it hasn't already shown up as yellow
if not (words[i][j] in required) :
never += words[i][j]
After deploying the modified code, the correct result is returned, revealing two common words to be
valid: QUOTA and JUNTA.

Cryptic Crossword 'Solving Aid'
Cryptic crossword puzzles (the 'normal' kind if you're in the UK or a former Commonwealth country such as Canada) are defined by the style of cluing, nicely summarized by the Emily Cox & Henry Rathvon in the Wall Street Journal:
The clues each have two parts. One part is a normal definition of the answer; the other is an additional hint using wordplay. Having two hints in each clue might seem a big giveaway to solvers. Why aren’t these clues twice as easy? The hitch: Either hint may come first. The definition may appear before or after the wordplay hint, often without any punctuation to mark the point of division. The challenge and fun of a cryptic puzzle is to see through the puzzle writer’s deceptions, to tease out the definition by rethinking the clue’s wording.
Some people might describe a cryptic crossword as a puzzle where every clue is its own dad joke.
My cryptic crossword skills are...developing, but I not infrequently find myself stuck. In this old puzzle from Cox and Rathvon

I was trying to solve 12A

knowing only that it was a nine-letter word, the third letter being 'O' and the last being 'U.
These constraints can be easily and compactly expressed as a simple regular expression
/^..O.....U$/
It had occurred to me in the past, that the ability to perform a regular expression search across a dictionary would be a useful tool to help solving this type of puzzle. While there are a number of sites available that offer this (Lou Helvy, dCode) and others, each suffers from shortcomings.
So I decided to create my own, tailored to my specific use case. The result provides an extremely simple user interface. The user enters a valid regular expression, and the tool continuously searches a large word list, displaying all matches, up to a preset limit:

This is implemented in Python as a Gunicorn/Flask web service running on an inexpensive, low-powered Linux PC, reachable through a custom domain.
And if you're wondering about that clue
Ceremonial dress is right in two ways for hearing
the words TRUE and SO are both synonyms for RIGHT, in the sense of
correct. The two words spoken together ("TRUE-SO") make a homophone of
TROUSSEAU, a type of ceremonial dress.
Targetrage
As obsessively noted [here] MISSING LINK , I have taken great care to reduce the materials cost for home-baked bagels. Getting the best price on a jar of Fleischmann's Yeast is tricky. At full-service grocers, the price is typically $7.00 to $9.00 for a 4-ounce jar. Ouch.
Wal-Mart's posted price is $5.48, but it is never in stock at the local "supercenter".
Target's online price depends on the store you've selected. At the store closest to me, it's $5.89:

But if you go to the store, the posted price is $7.48. You can evade this extra charge by ordering for curbside pickup (who pays extra for the privilege of venturing into a crowded big box store).
Weirdly, even the curbside price varies depending on which store you have selected when you first search for the product.
If you start your search at the Westwoood Target location, the price is $7.49:

And this is the price you'll get, even if you switch the pickup location to Framingham. On the other hand, if you have the Framingham store selected when you initially place the product in your cart, switching to the Westwood store preserves the lower price.
I suppose the general price differential between the two stores makes sense, based on the demographics of the two communities:

And Target's willingness to provide a 23% discount for pre-ordering the item for curbside pickup? I guess that's what that data point about my shopping behavior is worth to them.
Chuck and Michael
"Nerds of a certain age" are likely to have heard of, or perhaps even watched, the TV show Chuck. In addition to some amusing writing and strong performances by Adam Baldwin and Zachary Levi, the series featured a recurring leitmotif of notable books on software design and development.
The episode Chuck and the Broken Heart features the definitive work on XSLT: XSLT Programmer's Reference.
This book was my contstant companion for many years as I developed tooling to work with XML-based documentation content.

I always appreciated the clarity and completeness of the book, as well as Michael Kay's continuing support of the language.

Bagelnomics
Despite numerous comments from the chattering classes about how Americans are "just misinformed" about the impact of Bidenomics on their daily lives, Labor Departments inflation statistics when it comes to food don't lie:
| Category (Selected) | 2020-2024 Cumulative | Dec 2022 to Dec 2023 | Dec 2021 to Dec 2022 | Dec 2020 to Dec 2021 | Dec 2019 to Dec 2020 |
|---|---|---|---|---|---|
| Food away from home | 23.4 | 5.2 | 8.3 | 6.0 | 3.9 |
| Other food at home | 26.2 | 2.8 | 13.9 | 5.6 | 3.9 |
| Food | 23.3 | 2.7 | 10.4 | 6.3 | 3.9 |
| Cereals and bakery products | 26.7 | 2.6 | 16.1 | 4.8 | 3.2 |
| Nonalcoholic beverages and beverage materials | 24.8 | 2.6 | 12.6 | 5.2 | 4.4 |
| Meats, poultry, and fish | 24.4 | 2.3 | 4.5 | 12.6 | 5.0 |
| Food at home | 23.5 | 1.3 | 11.8 | 6.5 | 3.9 |
| Fruits and vegetables | 16.9 | 0.3 | 8.4 | 5.0 | 3.2 |
| Dairy and related products | 20.0 | -1.3 | 15.3 | 1.6 | 4.4 |
| Eggs | 45.7 | -23.8 | 59.9 | 11.1 | -1.5 |
Over the same time period (2019-2024) our awesome local bagel bakery increased their price for a baker's dozen bagels by 37%, from $13.95 to $19.05. So I started baking bagels myself. After several weeks of experimentation, I settled on a recipe that produces bagels that are the equal of those from the shop.
And what do they cost?
| Ingredient | Cost (/gm) | Amount | Cost | Notes |
|---|---|---|---|---|
| Diastatic Barley Malt Powder | $0.02 | 30g | $0.60 | Best price for 1.5 pounds from Amazon |
| Yeast | $0.05 | 10g | $0.50 | Fleischman's Active Dry 4oz bottle, retail from Target |
| Flour | $.0026 | 1100g | $1.05 | King Arthur Special Patent (50 pound bag from Restaurant Depot) |
| Baking Soda | $.044 | 10g | $0.04 | To adjust pH of pre-bake boiling bath |
| Salt | $0.022 | 10g | $0.02 | Morton salt, retail |
| Toppings | varies | varies | $0.50 | Retail poppy seeds, sesame seeds, jar garlic |
| Electricity | $0.30/kWh | 2 kWh | $0.60 | Electric stove, Eversource residential rate |
Total cost $3.31 per dozen (recipe makes 12 bagels), so $0.28 per bagel versus $1.47 from the bagel shop.
Google Domains, We Hardly Knew Ya
Three years ago I MISSING LINK deploying a pair of sites using HTTPS from a $100 fanless PC over my FIOS connection. The post details how Google Domains can be used to implement a roll-your-own DDNS system for domains registered there.
Not long after officially announcing that Google Domains was out of beta on March 15, 2022, Google sold Google Domains to Squarespace. I had been hoping that the API would continue to be supported by Squarespace, but sadly no.

Based on a quick Google search, it looked like Cloudfare was a viable replacement. Primarily known as a CDN-as-a-service provider, Cloudflare also offers domain registry services and an API that allows you to edit DNS records.
The domain migration process was trivially easy (my domains had not yet been migrated to Squarespace), the domain registration is cheaper, and the API straightforward to use. Some configuration details follow.
DNS Records: Disable Proxying
As part of their CDN, Cloudflare proxys DNS requests. For simplicity, disable this setting for all of your A and CNAME records (unless you want to update your NGINX configuration).
Scripted DDNS Updates
Based on this example, I created a script to update the IP address in the A records for both domians as needed.
(Since retiring, I haven't done much computer work, so please forgive the many flaws below.)
### !/bin/bash
#
# Use CloudFlare API to update A record with new IP address when needed.
#
SQUAWK_ZONE="xxx.com"
HA_ZONE="xxx.com"
AUTH_KEY="xxx"
AUTH_EMAIL="xxx.y.com"
SQUAWK_ZONE_ID=xxx
HA_ZONE_ID=xxx
UPDATE_TIME=$(date)
# Resolve current public IP
IP=$( dig +short myip.opendns.com @resolver1.opendns.com )
# For each virtual host, check to see if the DNS record matches our IP address
if host $SQUAWK_ZONE 1.1.1.1 | grep "has address" | grep "$IP"; then
echo "$SQUAWK_ZONE is currently set to $ip; no changes needed"
UPDATE_SQUAWK=false
fi
if host $HA_ZONE 1.1.1.1 | grep "has address" | grep "$IP"; then
echo "$HA_ZONE is currently set to $ip; no changes needed"
UPDATE_HA=false
fi
# If a host needs updating,first get the record ID for the A-record
# then use PATCH to udpate the value. For details see the excellent
# Cloudflare documntation: https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-patch-dns-record
if $UPDATE_SQUAWK ; then
dnsrecordid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$SQUAWK_ZONE_ID/dns_records?type=A&name=$SQUAWK_ZONE" \
-H "X-Auth-Email: $AUTH_EMAIL" \
-H "X-Auth-Key: $AUTH_KEY" \
-H "Content-Type: application/json" | jq -r '{"result"}[] | .[0] | .id')
# echo "DNSrecordid for $SQUAWK_ZONE is $dnsrecordid"
curl --request PATCH \
--url https://api.cloudflare.com/client/v4/zones/$SQUAWK_ZONE_ID/dns_records/$dnsrecordid \
--header "X-Auth-Email: $AUTH_EMAIL" \
--header "X-Auth-Key: $AUTH_KEY" \
--data '{
"content": "'$IP'",
"name": "'$SQUAWK_ZONE'",
"proxied": false,
"type": "A",
"comment": "'"DDNS Updated on $UPDATE_TIME"'",
"ttl": 1
}'
fi
if $UPDATE_HA ; then
dnsrecordid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$HA_ZONE_ID/dns_records?type=A&name=$HA_ZONE" \
-H "X-Auth-Email: $AUTH_EMAIL" \
-H "X-Auth-Key: $AUTH_KEY" \
-H "Content-Type: application/json" | jq -r '{"result"}[] | .[0] | .id')
# echo "DNSrecordid for $HA_ZONE is $dnsrecordid"
curl --request PATCH \
--url https://api.cloudflare.com/client/v4/zones/$HA_ZONE_ID/dns_records/$dnsrecordid \
--header "X-Auth-Email: $AUTH_EMAIL" \
--header "X-Auth-Key: $AUTH_KEY" \
--data '{
"content": "'$IP'",
"name": "'$HA_ZONE'",
"proxied": false,
"type": "A",
"comment": "'"DDNS Updated on $UPDATE_TIME"'",
"ttl": 1
}'
fi
For extra credit, the script updates the comment in the A record to indicate when it was updated:

Magic
If you're an AT&T cell customer, you can save a lot of money by switching to Consumer Cellular. For our 4-line plan, switching from AT&T saved more than $150 each month (four lines, unlimited data, throttled after 50GB) while still using the AT&T network infrastructure.
One initial problem was that conditional call forwarding (CCF) wasn't supported. CCF allows you to forward unanswered/unreachable/busy calls to a different number. If you have a Google Voice number (free VOIP calling, nice Android app), using CCF to forward missed cellular calls means that any voicemail messages can be transcribed and e-mailed to you.
This is a great feature, but using the standard AT&T Feature Access Code (FAC)
*004*15085551234*11#
to configure it resulted in errors like this:
Carrier Message
Call forwarding
GENERIC_FAILURE
Using the Android app UI (Settings->Calls->Call Forwarding) produced these errors:
Call settings error
Network or SIM card error.
For some reason, I tried doing this again recently, and this time it worked! Interestingly, updating the forwarding through the Android app didn't seem to work, but using the FAC did, and after setting forwarding through the FAC, the forwarding numbers appeared in the UI.
Handy. And magic.
Stolperstein
This morning's Boston Globe has a story about the Stolperstein Memorials that can be found across Europe.
Stolpersteine, or “stumbling stones,” identify European citizens taken from their homes in World War II. Each begins with the phrase “Here lived.” They then document the birth date, date of deportation or escape, and, if known, the date and place of death. Laid into the pavement in front of the last voluntarily chosen residence of these citizens, the plaques are the life’s work of German sculptor Gunter Demnig, whose inspiration comes from a passage in the Talmud: “A person is only forgotten when his name is forgotten.”
On one of my many business trips to Budapest, a colleague in the office mentioned these to me, and it happened that I had been walking past a Stolperstein each morning on the way to the office.

In front of an apartment door

embedded in the sidewalk cobblestones

is a memorial to Aczél Bertalan (in the Hungarian custom, the last name is given first).

Here lived Bertalan Aczél born 1877 Deported and Killed 1945.11.4 in Dachau
Saturday
They say it's good to have goals. Every Saturday, mine is to complete the Saturday New York Times crossword puzzle, in ink, without errors.
Today I came close, but unfortunately I spelled 'Lon Chaney' incorrectly on my very first entry.

If you want to play along, here were the clues:
ACROSS
1 It means "father of" in Arabic
4 Catty remark?
7 Rated PG-13 or R, say
12 Sylphlike
14 Fit out
15 "Amaaazing!"
16 Is a witness
17 Comedian John who is said to resemble a love child of
Harry Potter and Owl from "Winnie-the-Pooh"
18 Ottawa leader
19 Stun gun
20 Like part of a dress affected by static cling, say
22 Hootenanny
24 Word with gag and ground
25 Headwear for the big game?
27 Levy of "Schitt's Creek"
28 Isn't open about oneself
30 Drink cooler
33 Stereotypical Silicon Valley types
35 Act huffy?
37 Came out of the blue?
39 Launched weapons
41 Unwanted autocorrections
43 Bonny young lady
44 Influenza
45 Some Buddhist mandalas, e.g.
46 [More details below]
47 Acknowledgment of a poor performance
48 Schoolmaster for the classroom, e.g.
49 Italy's longest river
50 Spec for a script
51 Atlanta-based network
DOWN
1 Parcel
2 Place to study cultures
3 They're issued by the Bureau of Consular Affairs
4 Suit cut between "classic" and "slim"
5 House of Saud title
6 Like some blankets and bars
7 Along with the anteater, one of two animals
in the order Pilosa
8 Less hurried
9 "Pfft, this one doesn't work"
10 Count ___
11 Currency whose name means, literally, "round"
13 More than a couple
14 Skin-toned cosmetic
16 Silent film star known as the "Man of
a Thousand Faces"
18 Disciplinarians, at times
20 Something often seen with trunks
21 Fold
23 British pop star with more "Ed Sullivan Show"
appearances than the Beatles
26 It gets bald over time
29 Going down the drain, in a way
30 Inits. at a bar
31 Place to get a wax
32 Summit goal
34 Back
36 Occupied
38 Can opener
40 Cattle-grazing tract
42 Looks like
44 Good name for a biologist?
45 Collect dust
46 ___ Taylor-Johnson, director of "Fifty
Shades of Grey"
Illustration
Sometimes the most effective method for communicating technical information is a quick drawing on a whiteboard.
A number of years ago, I acquired a Craftsman tablesaw from the 1930s:

Although it was somewhat the worse for wear:

I installed a modern rip fence, table extensions, and an outfeed table:

I've been meaning to write up my experience adapting a new fence to this ancient saw, but I've been stymied by the problem of how to illustrate the story.
I wanted to avoid the time-consuming work of creating a parametric representation of my work (Sketchup or OnShape), and I was interested in a more informal look, so I tried creating sketches on my ReMarkable 2 tablet.

My modern fence (a Delta T3 Biesemeyer-style fence) is based on a heavy L-section bracket secured to the front face of the saw table. The main beam is then bolted to this bracket. Unfortunately, the table on my old saw wasn't thick enough to provide for a vertical face to which to secure the bracket:

The saw did have three threaded mounting holes on the underside of the front edge of the table. I used these holes to mount a 1x1 steel tube to the bottom:

With the tube mounted, now there was a surface tall enough to support the bracket...

...making it straightforward to mount the bracket:

User Error
Like many, I've spent much of the past year working from home. To improve my productivity, I created a wired and wireless infrastructure in my house. My internet service provider is Verizon FiOS, and their service is excellent, with good bandwidth and excellent reliability.
The following diagram summarizes the overall network configuration:

The "consumer" network is managed by a Google Mesh WiFi system. This mesh router is connected to the FiOS router through a wired connection. The mesh router is also connected to an Ethernet switch, and this switch provides wired connection for consumer devices including a game console, media streaming device, and a Chromecast-equipped smart TV.
The "professional" network is managed by the FiOS router. An Ethernet switch is connected to the router, and it provides wired connections for a Linux host (used to serve a hobby web site), a laser printer, the wired dock for my work computer, and a second media streaming device.
The laser printer and the Linux host are both configured with static IP addresses. The FiOS router is configured to forward ports 80 and 443, along with a nonstandard port for SSH traffic, to the Linux host. This allows me to use it as a web server and to manage it remotely. (The printer's static address makes it easier to connect to it from a Chromebook.)
The FiOS router is also configured to provide a second wireless network. This network is for "backup" in case of problems with the mesh network.
Earlier this year, the network stopped working, with the exception of the backup wireless network. The mesh router couldn't see the FiOS router, and noe of the wired devices could see the router either.
Looking at the status page for the FiOs router, it showed the two wired connections were active (the mesh router and the switch), but the overall interface was shown as "Disconnected":

I couldn't find any information about this specific error, so I finally concluded that there was a hardware problem with the FiOS router and obtained a replacement, which fixed the problem.
Then the problem happened again. Verizon support asked me to verify that the router's wired ports were not working by directly connecting a PC. I did so, and the PC could not connect ("no network detected").
What I didn't do, however, was disconnect the other devices from the router before performing the test. I decided to perform a hard reset of the FiOS router and reconstruct the network from scratch. When I connected the mesh router, everything was working fine. When I connected the switch, everything stopped working.
The underlying problem turned out to be that I had not configured the FiOS router's IPV4 address distribution settings. As soon as I excluded the static IP addresses from the IPV4 address distribution, the problem was solved.
I'm not sure exactly what led me to the solution, although as soon as I realized that the wired Ethernet switch was somehow poisoning the FiOS router, I had a good clue. I was somewhat surprised that the presence of a misconfigured device would take down the entire wired side of the router.
Quality of Life
I'm spending a lot of time in Visual Studio Code on a Linux-enabled Chromebook. (In fact, I'm using it right now.)
Unfortunately, the default appearance of the menu bar, well meh...

But it turns out that with a small preferences tweak

you can have a nice, compact menu bar:

Free hosting (multiple domains, SSL, subdomains)
In addition to this domain, I had a couple others languishing at the somewhat skeevy godaddy.com. I'd configured them to redirect to a pair of Medium publications, back when Medium was offering free SSL certificates for custom domains on their site.
I also had an obsolete Lenovo laptop running Linux, with Verizon Fios internet service, pointed to by a a DDNS name from noip.com I'd been using it for hobby-grade stuff, but the lack of HTTPS was going to be a problem.
But thanks to this article from Jeremy Gale I was able to redirect my two domains to my on-prem Ubuntu server, set up a number of subdomains, and obtain free SSL certificates for everything.
Here's a short recap of what I did.
Domain transfer from Godaddy to Google Domains
At https://domains.google.com you can easily initiate a domain transfer. The site walks you through the process, transfers any custom DNS settings, and credits you for remaining time from godaddy.com. Cost is $12 per domain for the transfer, and $12 for renewals thereafter.
Configure DDNS
Within the DNS Settings, create a Synthetic Record of type DDNS. Don't bother setting the IP address -- that is set by this script, run from the host, that uses Google Domains API.
### Google Domains provides an API to update a DNS
### "Synthetic record". This script updates a record with
### the script-runner's public IP address, as resolved using a DNS
### lookup.
###
### Google Dynamic DNS: https://support.google.com/domains/answer/6147083
### Synthetic Records: https://support.google.com/domains/answer/6069273
SQUAWK_USERNAME="****"
SQUAWK_PASSWORD="****"
SQUAWK_HOSTNAME="@.mistersquawk.com"
# Resolve current public IP
IP=$( dig +short myip.opendns.com @resolver1.opendns.com )
# Update Google DNS Record
URL="https://${SQUAWK_USERNAME}:${SQUAWK_PASSWORD}@domains.google.com/nic/update?hostname=${SQUAWK_HOSTNAME}&myip=${IP}"
curl -s $URL
Set up subdomains
I'm interested in a few subdomains for various projects -- you can easily set those up by adding Custom resource records of type CNAME:

For example, after working through the Angular Tour of Heroes project, I decided to deploy it to https://heroes.mistersquawk.com.
Configure nginx server block for each domain
Because I had two domains, but only one host, I was pleased to find this post on configuring multiple domains with Nginx on Ubuntu.
The short story is you simply create a server directive block for each domain or subdomain, specifying the location of the files to serve.
server {
listen 80;
listen [::]:80;
server_name domain-one.com www.domain-one.com;
root /var/www/domain-one.com/public_html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
Use certbot and LetsEncrypt to generate and install certificates
Certificates? That turned out to be the easiest of all. Simply head to https://certbot.eff.org/ and follow the instructions.
sudo certbot --nginx
Automatically analyzes your Nginx configuration and requests, then installs the reqired certificate. Once you've verified that it works
$ certbot renew --dry-run
Add this to your crontab to auto-renew the certificates:
18 4 * * * /usr/local/bin/certbot renew
vi
If you're going to work with a Linux host, you need to know at least a little vi.

Available formats: PDF Editable PDF Press-Ready PDF PNG
License: ©2025 Mister Squawk CC-BY-NC-SA
Icy Morning
Rain+snow+freeze means an icy hike in the hills overlooking Boston.

Nürburgring Nordschleife
Also in the "life goals satisfied" section, I recently had a chance to drive the famous "grüne hölle" in Germany:

Top of the World, New England Edition
I was able to fulfill a key life goal last week by hiking to the top of New England's highest peak, Mt. Washington. The hike took me up the Ammonoosuc Ravine Trail to the summit, then across to the summit of Mt. Jefferson and down the Caps Ridge trail. About 10 miles of walking and about 4500 feet of vertical climb. Time on the trail was 9 hours.
