Making Home and End Buttons Work Correctly on a Mac

For the most part, using a Mac has been pretty easy after many years of using Windows. One of the really annoying changes though was the way the Home and End keyboard keys work. On a Mac they go to the start and end of the file rather than the line. If you’re like me, this seems really silly. To change it, do the following:

  1. Open Terminal (Cmd + Space, type “Terminal”).
  2. Create the KeyBindings directory by pasting this command:
mkdir -p ~/Library/KeyBindings
  1. Create and open the configuration file:
nano ~/Library/KeyBindings/DefaultKeyBinding.dict
  1. Paste the following code into the window:
{
    "\UF729"  = "moveToBeginningOfLine:";
    "\UF72B"  = "moveToEndOfLine:";
    "$\UF729" = "moveToBeginningOfLineAndModifySelection:";
    "$\UF72B" = "moveToEndOfLineAndModifySelection:";
}
  1. Press Ctrl + X, then Y, and Enter to exit.
  2. Restart your Mac (or log out and back in) for the changes to take effect.

Note: The lines starting with $ handle Shift + Home/End, allowing you to highlight the line just like on Windows.

[Read more]

Remote Desktop to Raspberry Pi

My Raspberry Pi is located away from my desktop setup. Normally this is OK since I can just SSH into the terminal. I ran across a scenario where I needed to access the GUI. In the past I would physically move it over and connect it to my monitor, keyboard, and mouse. Turns out there’s a much easier way to do this.

VNC to the Rescue

VNC is built into the Raspberry Pi operating system and allows for easy remote desktop connections. Here’s how:

[Read more]

Using Tailscale Services

Up until a few days ago, I used the Docker sidecar method to expose services with easy to remember addresses. For instance, using it with Immich so I could just enter something like https://immich.gallant-panda.ts.net in the browser to get to it. This works well but always seemed a bit clunky since it requires an additional docker container to work.

With the beta release of Tailscale services there is, in my opinion, a better, cleaner way to do this. Services allow you to essentially expose a specific service (not the whole machine) as a node on your Tailnet. You can even assign tags to it in order to apply access control via the normal Tailscale ACL’s and grants. The service can also act as a sort of load balancer since you can host the service on multiple machines and Tailscale will connect the user to the closest one automatically.

[Read more]

Tailscale Service from a Linux Client

If you cannot access a Tailscale service from a Linux machine, you likely need to run this command:

sudo tailscale set --accept-routes

Here’s why:

Unlike a standard device (a “node”), a Tailscale Service is a virtual entity. It doesn’t represent a single physical network interface.

  • Standard Node: Your Mac or Linux box has a direct “Peer” entry in the internal WireGuard table. Linux sees these 100.x.y.z addresses and knows they belong to the tailscale0 interface by default.
  • Service IP: A Service IP is essentially a Shared Anycast IP. It is “advertised” by one or more nodes in your network. Because it is being advertised rather than being a direct peer-to-peer connection, Linux treats the traffic to that IP as a route rather than a simple local interface destination.

Linux is often used as a router or server. To prevent Tailscale from accidentally hijacking existing routes or creating “routing loops”, Tailscale on Linux ignores all advertised routes until you explicitly opt-in.

[Read more]

Backup and Restore Docker Volume Data

Here are some scripts that can be used to manually backup and restore data from Docker volumes.

Manual Docker Volume Backup

This script uses a temporary Docker container to mount the target volume. It also mounts the current directory so it can write the archive file.

Usage: backup-docker-volume.sh <Volume Name> <Backup File Name>

#!/bin/bash

#!/bin/bash
# Usage: backup-docker-volume.sh <Volume Name> [Backup File Name]
# Example 1: ./backup-docker-volume.sh n8n_n8n_data n8n_data_backup
# Example 2: ./backup-docker-volume.sh n8n_n8n_data

# Use this command to find the name of the volume:
# docker inspect --format '{{ json .Mounts }}' <container_name_or_id>


# 1. Capture the volume name
VOLUME_NAME=$1

# 2. Check if the second argument ($2) is provided.
# If not, default to "n8n_backup_" + current timestamp.
TIMESTAMP=$(date +"%Y_%m_%d_%H_%M_%S")
BACKUP_NAME=${2:-"n8n_backup_$TIMESTAMP"}

# 3. Run the backup
docker run --rm \
  -v "$VOLUME_NAME":/source:ro \
  -v "$(pwd)":/backup \
  alpine tar czf /backup/"$BACKUP_NAME".tar.gz -C /source .

echo "Backup completed: ${BACKUP_NAME}.tar.gz"

Restore a Manual Backup

This script:

[Read more]