Raspberry Pi Hostname Collision Resolver

Situation

When deploying multiple Raspberry Pi devices from the same firmware image for Ansible automation, hostname conflicts create operational challenges. While RFC 6762 specifies that mDNS devices should automatically resolve naming collisions by incrementing the duplicate name with a -2/3/4/etc postfix, real-world implementations often fail. Pinging ansibledest.local often returns competing results when multiple pis are online. This leaves devices unreachable with duplicate hostnames like ansibledest.local. This makes Ansible playbooks unable to identify and manage devices reliably.

Task

I will develop an automated solution that:

  • Proactively resolves hostname conflicts before they impact operations
  • Runs automatically on first boot without manual intervention
  • Scales to simultaneous deployment of multiple devices
  • Provides comprehensive audit logging for network discovery
  • Integrates seamlessly with existing Ansible automation workflows

Action

I created a comprehensive hostname collision resolver system consisting of:

Core Components

  1. hostname-collision-resolver.sh – Main script that:
    • Waits for network interfaces (wlan0/eth0) to be ready
    • Adds random delay (10-40 seconds) to prevent simultaneous boot conflicts
    • Scans network using avahi-browse and ping for existing hostname variants
    • Uses gap-filling algorithm to find lowest available hostname number
    • Updates system hostname and configuration files
    • Logs detailed network state including IP/MAC addresses of discovered hosts
    • Reboots automatically if hostname changes are made
  2. hostname-collision-resolver.service – Systemd service for proper boot integration:
    • Runs after network services are online
    • Executes before Ansible automation services
    • Configured as one-time execution with comprehensive logging
  3. firstrun.sh – Bootstrap script for SD card deployment:
    • Installs required packages (avahi-utils, avahi-daemon)
    • Embeds and installs the hostname resolver
    • Enables services for automatic execution
    • Self-removes after completion

Deployment Strategy

  • Embedded the entire hostname resolver system into a single firstrun.sh script
  • Used Raspberry Pi Imager advanced options for base configuration
  • Copied firstrun.sh to boot partition with proper permissions (chmod +x, chown root:root)
  • Created master SD card image ready for mass duplication via drive cloner

Key Features Implemented

  • Network-aware startup: Waits for actual network connectivity, not just interface up
  • Collision prevention: Random delays handle simultaneous device deployments
  • Intelligent naming: Gap-filling algorithm finds lowest available hostname variant
  • Comprehensive logging: Permanent audit trail of network state and decisions
  • One-time execution: Flag file prevents repeated runs throughout device lifetime
  • Automatic integration: Ready for immediate Ansible automation post-boot

Result

Successfully created a production-ready solution ready for testing. Should deliver the following results:

Immediate Outcomes

  • Master image ready: SD card contains fully integrated hostname resolver system
  • Scalable deployment: Ready for drive cloner to create multiple identical cards
  • Zero-touch automation: Devices will automatically resolve hostname conflicts on first boot
  • Ansible-ready: Devices will be immediately discoverable for automation after hostname resolution

Technical Achievements

  • Robust conflict detection: Uses both mDNS discovery and ping verification
  • Intelligent numbering: Finds optimal hostname (e.g., picks device-2.local if device-1.local and device-4.local exist)
  • Comprehensive logging: Complete audit trail including network topology at boot time
  • Production hardening: Error handling, timeouts, and safety mechanisms throughout

Next Steps Enabled

  1. Use drive cloner to duplicate master SD card to multiple cards
  2. Deploy cards to Raspberry Pi devices simultaneously
  3. Power on devices – automatic hostname resolution occurs
  4. Run Ansible discovery to locate renamed devices
  5. Proceed with normal Ansible automation workflows

The solution transforms a manual, error-prone process into a fully automated system that scales from single devices to large deployments while maintaining complete operational visibility.

I did write a testplan.md file that’s more detailed with test steps.

Fixing problems with playbook execution order that caused orphaning of target devices:

✅ Problem Fixed! Hostname Timing Issue Resolved

What Was Wrong:

  • Hostname change happened in final_cleanup.yml (middle of system role)
  • cloudflare_tunnel and selfie_app roles ran AFTER system role
  • They expected the new hostname but system still had old hostname
  • This caused the “hostname transition problem” documented in CLAUDE.md

Solution Implemented:

  • Moved hostname changes to post_tasks in run.yml

New execution order:

  1. system role (no hostname change)
  2. cloudflare_tunnel role
  3. selfie_app role
  4. post_tasks: Set final hostname ← NOW HAPPENS LAST

Benefits:

  • cloudflare_tunnel and selfie_app configure with {{ hostname }} variable

  • Actual hostname change happens AFTER all roles complete

  • Clean transition from ansibledest.local → thepub.localNo orphaning – roles get configured properly before hostname switches

  • Resume Point: You can now resume as with –tags final_hostname_change to run just the hostname changes, or continue normally knowing the execution order is correct.

The hostname transition issue that’s been causing problems is now properly sequenced!

Key lessons:

Key Takeaways:

The Run.yml file is the ultimate arbiter of execution.

  • It calls the “system” role, the “cloudflare” tunnel role and the “seflie app” role. it then has “post_tasks” that handle the brittle commands that change the state of the device.
  • The system roll has all of the individual tasks in /roles/system/tasks whose order is controlled by main.yml in there.

Emailing 2FA is bad because…


There was a good thread on HackerNews recently regarding passkey and 2FA using email.

This person had a summary explaining the exploitation scenario:
https://news.ycombinator.com/item?id=44819917#44820331

Essentially- normal humans don’t scrutinize certificates/ website domains.

This is exploitable by malicious humans who send people a link to a page they control and trigger a 2FA login flow at the legit site. They trick the user into sharing the 2FA code directly with them. This stuff seems pretty obvious- but the summary explanation in the above comment is nice and tight.

This person had insightful counterarguments:
https://news.ycombinator.com/item?id=44819917#44820657

Specifically- 2FA fishing is mostly solved if remove/copy pasting of credentials.

I agree.

If sec engineers were thinking more about how to make user sign-in flows to be ruthlessly low friction, we’d be ok. Instead we over-index on a sign-in ritual that results in weakened security.

“I think this is mostly solved, or at least greatly mitigated, by using a Slack-style magic sign-in link instead of a code that you have the user manually enter into the trusted UI”

Comprehensive Troubleshooting Guide for AWUS036ACH on Raspberry Pi OS

Introduction

The Alfa AWUS036ACH is a popular USB Wi-Fi adapter that uses the Realtek RTL8812AU chipset. While powerful, it can present several challenges when setting up on a Raspberry Pi, especially for features like monitor mode and packet injection. This guide provides a systematic approach to identify and fix common driver issues.

Table of Contents

  1. Hardware Verification
  2. Basic Installation Methods
  3. Troubleshooting Common Issues
  4. Advanced Configuration
  5. Monitor Mode and Packet Injection
  6. Power Issues
  7. Kernel Compatibility
  8. Additional Resources

Hardware Verification

Before proceeding with software troubleshooting, verify your hardware:

1. Confirm your adapter model: Ensure you have the genuine AWUS036ACH.

2. USB port functionality:

  • The adapter requires significant power. Try connecting directly to the Raspberry Pi (not through a USB hub).
  • If possible, use a USB 3.0 port for better performance.
  • Use a high-quality USB cable.

3. Verify chipset detection:

lsusb

Look for ID 0bda:8812 (Realtek Semiconductor Corp. RTL8812AU).

4. Power Supply:

  • Ensure your Raspberry Pi has an adequate power supply (at least 2.5A recommended).
  • The adapter’s LED should light up when powered.

Basic Installation Methods

There are several approaches to install the driver. If one method fails, try an alternative.

Method 1: Using DKMS (Recommended)

DKMS ensures the driver is automatically rebuilt when the kernel is updated:

# Install prerequisites

sudo apt update
sudo apt upgrade
sudo apt-get install bc mokutil build-essential libelf-dev linux-headers-`uname -r` dkms git

# Clone the driver repository

git clone -b v5.6.4.2 https://github.com/aircrack-ng/rtl8812au.git
cd rtl8812au

# If using Raspberry Pi 3/4 with ARM64 architecture

sed -i 's/CONFIG_PLATFORM_I386_PC = y/CONFIG_PLATFORM_I386_PC = n/g' Makefile
sed -i 's/CONFIG_PLATFORM_ARM64_RPI = n/CONFIG_PLATFORM_ARM64_RPI = y/g' Makefile

# For older Raspberry Pi models (ARMv7)

sed -i 's/CONFIG_PLATFORM_I386_PC = y/CONFIG_PLATFORM_I386_PC = n/g' Makefile
sed -i 's/CONFIG_PLATFORM_ARM_RPI = n/CONFIG_PLATFORM_ARM_RPI = y/g' Makefile

# Install with DKMS

sudo make dkms_install

# Reboot

sudo reboot

Method 2: Using Morrownr’s Driver Repository

This is an alternative driver repository that’s often more up-to-date:

# Install prerequisites

sudo apt update && sudo apt upgrade
sudo apt-get install dkms
sudo apt install -y raspberrypi-kernel-headers build-essential bc dkms git

# Clone repository

mkdir -p ~/src
cd ~/src
git clone https://github.com/morrownr/8812au-20210629.git
cd ~/src/8812au-20210629

# Install driver

sudo ./install-driver.sh

If you encounter kernel header errors, modify the boot config:

sudo su
cd /boot
nano config.txt

Add the following line under the [pi4] section:

arm_64bit=0

Save (Ctrl+O, Enter), exit (Ctrl+X), then reboot:

sudo reboot

Troubleshooting Common Issues

Driver Not Loading

Check if the driver is loaded:

lsmod | grep 88

You should see 8812au or similar in the output.

If not loaded, try manual loading:

sudo modprobe 8812au

Check kernel logs for errors:

dmesg | grep -i rtl

Interface Not Appearing

List network interfaces:

ip a

Look for wlan1 (or similar) if you already have wlan0 for the built-in Wi-Fi.

If no interface appears:

sudo rmmod 8812au 
sudo modprobe 8812au

Reboot the system:

sudo reboot

Compilation Errors

Missing kernel headers:

sudo apt install raspberrypi-kernel-headers

Architecture mismatch errors:

For ARMv7:

export ARCH=arm 
sed -i 's/^MAKE="/MAKE="ARCH=arm\ /' dkms.conf

For ARM64:

export ARCH=arm64
sed -i 's/^MAKE="/MAKE="ARCH=arm64\ /' dkms.conf

Out of memory during compilation:

Increase swap space:

sudo nano /etc/dphys-swapfile

   # Change CONF_SWAPSIZE=100 to CONF_SWAPSIZE=2000

sudo /etc/init.d/dphys-swapfile restart

Advanced Configuration

LED Control

Control the LED behavior of the adapter:

# Disable LED blinking (0 = off, 1 = on)

echo "0" > /proc/net/rtl8812au/$(your_interface_name)/led_ctrl

# Check current setting

cat /proc/net/rtl8812au/$(your_interface_name)/led_ctrl

Alternatively, create a modprobe configuration:

echo "options 88XXau rtw_led_ctrl=0" | sudo tee /etc/modprobe.d/realtek-leds.conf

USB Mode Switching

Switch between USB 2.0/3.0 modes:

sudo rmmod 88XXau

sudo modprobe 88XXau rtw_switch_usb_mode=1  # 0=no switch, 1=USB2->USB3, 2=USB3->USB2

Disable MAC Address Randomization

If NetworkManager keeps changing your MAC address:

sudo nano /etc/NetworkManager/NetworkManager.conf

Add:

[device]

wifi.scan-rand-mac-address=no

Then restart NetworkManager:

sudo service NetworkManager restart

Monitor Mode and Packet Injection

These features are essential for network analysis and security testing.

Setting Up Monitor Mode

Kill potentially interfering processes:

sudo airmon-ng check kill

Set interface down:

sudo ip link set wlan1 down  # Replace wlan1 with your interface name

Set monitor mode:

sudo iw dev wlan1 set type monitor

Set interface up:

sudo ip link set wlan1 up

Verify monitor mode:

iwconfig wlan1

It should show “Mode: Monitor”.

Troubleshooting Monitor Mode

If monitor mode doesn’t work:

Try using airmon-ng instead:

sudo airmon-ng start wlan1

Check for interference:

sudo airmon-ng check

Kill any processes listed.

Manual mode setting:

sudo iwconfig wlan1 mode monitor

Check driver capability:

iw list

Look for “monitor” in supported interface modes.

Setting TX Power

Adjust transmission power (use with caution):

sudo iw wlan1 set txpower fixed 3000

Power Issues

The AWUS036ACH requires significant power, which can cause issues with the Raspberry Pi.

Check USB power management:

sudo iwconfig wlan1 power off

Disable power savings:

sudo nano /etc/modprobe.d/8812au.conf

Add:

options 8812au rtw_power_mgnt=0 rtw_enusbss=0

Use a powered USB hub if direct connection fails.

Kernel Compatibility

The driver might have compatibility issues with newer kernels.

Check current kernel version:

uname -a

Prepare kernel for module compilation:

cd /usr/src/kernel

sudo git clean -fdx && sudo make bcm2711_defconfig && sudo make modules_prepareFor severe kernel incompatibility issues, consider using an older kernel version:

sudo apt install raspberrypi-kernel=1.20201126-1

(Replace with appropriate version if needed)

Additional Resources

Conclusion

The AWUS036ACH can work well with Raspberry Pi, but requires some configuration. If one method fails, try an alternative approach, as driver compatibility can vary between different Raspberry Pi models and OS versions.

Remember that kernel updates might break your driver installation, requiring you to reinstall the driver. Using DKMS can help minimize this issue by automatically rebuilding the driver when the kernel is updated.

Multiple hosts on your network with the same mdns name

What happens when you have multiple hosts on your network with the same mdns name?

mDNS handles naming collisions through a process called “probing and announcing” defined in RFC 6762. Here’s how it works:

Collision Detection Process:

  • When a device wants to claim a name (like “ansibledest.local”), it first “probes” by sending queries for that name
  • If another device already has that name, it responds, indicating a collision
  • The new device must then choose a different name, typically by appending a number (ansibledest-2.local, ansibledest-3.local, etc.)
  • This process repeats until an unclaimed name is found

In practice- I haven’t seen this behavior, exactly. The devices all come online and if you run the hostname command, each of them thinks they’re Spartacus. You have to ping a specific ip address to get the updated mdns name in your cache. Annoying:

RFC 6762 told me I was good!

Well- I know the host is online apparently. I wonder what happens if I ping the hostname again-

It works. hooray.

Identifying duplicate mdns entries

You can use the avahi-browse command to see what’s up on your network. The hosts are apparently doing some kind of incremental naming- but not in a way that provides tcp/ip utility.

avahi-browse -at | grep ansibledest*
+ wlp0s20f3 IPv6 ansibledest-4 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv6 ansibledest [mac:addy:du:jour]              Workstation          local
+ wlp0s20f3 IPv6 ansibledest-3 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv6 ansibledest-3 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv6 ansibledest [mac:addy:du:jour]               Workstation          local
+ wlp0s20f3 IPv6 ansibledest-2 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv6 ansibledest-2 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv4 ansibledest-4 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv4 ansibledest-2 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv4 ansibledest-3 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv4 ansibledest-2 [mac:addy:du:jour]             Workstation          local
+ wlp0s20f3 IPv4 ansibledest [mac:addy:du:jour]               Workstation          local
+ wlp0s20f3 IPv4 ansibledest [[mac:addy:du:jour]               Workstation          local

Kernel Driver Compilation: Concepts and Troubleshooting

Overview

Kernel driver compilation is the process of creating loadable kernel modules (.ko files) that allow hardware to communicate with the Linux kernel. This involves several stages of compilation and linking.

Major Concepts

1. Source Code Compilation

  • Concept: Converting human-readable C source code (.c files) into machine code
  • Process: C compiler (gcc) compiles each .c file into an object file (.o)
  • Purpose: Create intermediate files containing compiled code that can be linked together
  • Example: rtw_cmd.c → rtw_cmd.o

2. Object Files (.o)

  • Concept: Intermediate compiled files containing machine code but not yet executable
  • Characteristics:
  • Contain compiled code from individual source files
  • Need to be linked together to create final executable
  • Cannot be loaded directly into kernel
  • Example: rtw_cmd.o, rtw_security.o, rtw_debug.o

3. Linking Process

  • Concept: Combining multiple object files into a single executable module
  • Process: Linker combines all .o files using linker scripts
  • Purpose: Create a cohesive module from individual compiled components
  • Requirements: Linker scripts (like module.lds) define how to organize the code

4. Kernel Modules (.ko)

  • Concept: Loadable kernel modules that can be inserted into running kernel
  • Characteristics:
  • Final product of compilation process
  • Can be loaded/unloaded without rebooting
  • Contains all necessary code and symbols
  • Example: 8812au.ko (final WiFi driver module)

5. Kernel Headers and Build System

  • Concept: Infrastructure needed to compile kernel modules
  • Components:
  • Kernel headers (function declarations, data structures)
  • Build scripts and Makefiles
  • Linker scripts (module.lds)
  • Module build tools (modprobe, depmod)

The Compilation Pipeline

text

Apply to AWUS036ACH_w…

Source Files (.c) → Object Files (.o) → Kernel Module (.ko)

     ↓                    ↓                    ↓

   Compile            Link with           Load into

   with gcc           module.lds          kernel

What Was Failing in Your Case

Stage 1: Source Compilation ✅

  • Status: Working correctly
  • Evidence: All .o files were being created successfully
  • Output: CC [M] /home/pi/8812au_src/core/rtw_cmd.o, etc.

Stage 2: Linking ❌

  • Status: Failing at final linking step
  • Root Cause: Missing module.lds linker script
  • Error: No rule to make target ‘8812au.ko’
  • Impact: Could not create final .ko file

Stage 3: Module Creation ❌

  • Status: Never reached due to linking failure
  • Expected: Creation of 8812au.ko file
  • Reality: Build process terminated before completion

The Missing Piece: module.lds

What is module.lds?

  • Purpose: Linker script that defines how to organize compiled code
  • Location: /lib/modules/$(uname -r)/build/scripts/module.lds
  • Function: Tells linker how to combine .o files into .ko file

Why it was missing:

  • Incomplete kernel source: rpi-source downloaded kernel source but missing build infrastructure
  • Missing build tools: The kernel source was missing essential linker scripts
  • Incomplete setup: Kernel headers symlink was pointing to incomplete source

The Fix:

AWUS036ACH_w…Run# Create the missing linker scriptcat > /lib/modules/$(uname -r)/build/scripts/module.lds << ‘EOF’SECTIONS{  . = ALIGN(4096);  .text : { (.text) }  .rodata : { (.rodata) }  .data: { (.data) }  .bss : { (.bss) }}EOF

Key Takeaways

  1. Compilation vs Linking: Two distinct phases – compilation creates .o files, linking creates .ko files
  2. Infrastructure Dependencies: Kernel module compilation requires complete build infrastructure
  3. Linker Scripts: Essential for final module creation, often overlooked in troubleshooting
  4. Debugging Approach: Check each stage separately – compilation, linking, and module creation
  5. Common Failure Points: Missing headers, incomplete kernel source, missing build tools

Diagnostic Questions for Future Issues

  • Compilation failing? → Check kernel headers, compiler, source code
  • Linking failing? → Check linker scripts, build infrastructure, kernel source completeness
  • Module loading failing? → Check module format, kernel compatibility, dependencies

This systematic approach helps isolate where in the pipeline the failure occurs and what infrastructure is missing.

Avoiding Social Media outrage.

Tenets for handling outrage inducing content on social media:

Most people don’t see the world through a True/False filter but an Us/Them filter

Introspection is uncommon

30-50% of people you meet don’t have an inner monologue.

The Internet Rewards Narcissists

When you see someone talking shit about a stranger online, remember that narcissists use “Splitting” to expel a narcissist’s bad behavior from their own memory.

Opinions != Expertise

The founding fathers were concerned about giving the right people the right to vote. They wanted to index on property owners to ensure that outcomes were dictated by citizens with a “stake in the game”. They were right to be concerned with the intentions of outsiders. Consider if the person whinging has a stake in the game- or is someone who is espousing their feelings about how other people should live.

Dangerous Outcomes Feared by the Founding Fathers

  • “Tyranny of the Majority” – Madison’s great fear in Federalist No. 10, where majority factions could oppress minorities and violate property rights
  • Mob Rule and Instability – Hamilton worried about “temporary delusion” of the masses (Federalist No. 68)
  • Wealth Redistribution – John Adams wrote: “The moment the idea is admitted into society that property is not as sacred as the laws of God… anarchy and tyranny commence” (Defence of the Constitutions, 1787)
  • Election of Demagogues – The Electoral College was partly designed as a safeguard against this (Hamilton, Federalist No. 68)

Public schools are funnels for producing useful idiots.

The public education community has long forgone any semblance of objectivity and fairness. The education system employs people who want a safe career with a pension and ample vacation. The incentives of public education are for teachers who comply and teach compliance. This attracts teachers who drive students towards voting for policies that produce government jobs which forego excellence and accountability.

Disagreeableness is undesirable

Most people generally prefer to get along to go along.

Seeking what is true is not seeking what is desirable.

Cruelty is easier than compassion.

It is the weak who are cruel. Gentleness is only to be expected from the strong.

Apt-get under apt-cacher-ng with a missing GPG public key

Here’s a common error to run into:


TASK [essential : Run the equivilent of apt-get update] **************************************************************
fatal: [ansibledest.local]: FAILED! => {“changed”: false, “msg”: “Failed to update apt cache: W:Updating from such a repository can’t be done securely, and is therefore disabled by default., W:See apt-secure(8) manpage for repository creation and user configuration details., W:GPG error: http://hostname.local:3142/raspbian.raspberrypi.org/raspbian bookworm InRelease: The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 9165938D90FDDD2E, E:The repository ‘http://hostname.local:3142/raspbian.raspberrypi.org/raspbian bookworm InRelease’ is not signed.”}

This can be solved by adding the following to your ansible playbooks:


– name: Add raspbian public signing key
apt_key:
keyserver: keyserver.ubuntu.com
id: 9165938D90FDDD2E
state: present

– name: Update apt cache
apt:
update_cache: yes

An NMCLI Cheatsheet for Wifi Access Points

Listing Creating, modifying and deleting connections

List your connections:

nmcli connection show

Rename a connection that you want to skip IPv6 on:

sudo nmcli connection modify "JoinMe-AP" 802-11-wireless.mode ap 802-11-wireless.ssid JoinMe 802-11-wireless.band bg 802-11-wireless-security.key-mgmt none connection.interface-name wlan1 ipv4.method shared ipv6.method ignore

Delete a connection by it’s name:

 sudo nmcli connection delete "JoinMe-AP" # Clean slate (optional)

Vulnerability Prioritization made easy!

“Which vulnerabilities should we fix first?”

This question often leads to confusion, especially for those deeply involved in security. Every company has unique priorities which makes it challenging to create a one-size-fits-all approach.
Don’t lose hope- here’s a straightforward method inspired by musicians’ mnemonics to help you feel confident that you considered everything that’s important when assessing a vulnerability’s priority.

Every Engineer Always Prioritizes Data By Evaluating Risk

This phrase breaks down into key factors to consider:

  • E – Exploitability: How easily can someone exploit the vulnerability?
  • E – Exposure: Is the system connected to the internet or internal?
  • A – Access Required: What level of access does an attacker need?
  • P – Patch Difficulty: How hard is it to fix the issue?
  • D – Data Sensitivity: Does the system handle sensitive information?
  • B – Business Impact: What effect would an exploit have on the company?
  • E – Environmental Mitigations: Are there existing defenses in place?
  • R – Raw CVSS Score: What is the base severity score?

Achieving zero vulnerabilities is ideal but often unrealistic. Resources are often limited, so it’s crucial that we prioritize effectively. This mnemonic helps me ensure I’ve considered the whole set of aspects that should be reviewed when deciding which vulnerabilities to address first.

By evaluating each factor, you can make informed decisions that balance risk and resource allocation, leading to a more secure and efficient system.