Wednesday, February 21, 2024

How to Set Up a Tunneled Wi-Fi Hotspot on Raspberry Pi OS Bookworm with WireGuard and NetworkManager

This guide updates our earlier tutorial for Debian 12 Bookworm on Raspberry Pi. In this architecture, the Raspberry Pi connects to upstream internet via Ethernet (eth0), establishes an encrypted WireGuard VPN tunnel (wg0), and broadcasts a secure Wi-Fi access point on wlan0. All client traffic connected to the hotspot is policy-routed strictly through the WireGuard tunnel.

Modern Bookworm Architecture: NetworkManager replaces dhcpcd and leverages the built-in dnsmasq-base plugin for DHCP and DNS caching, eliminating the need for standalone services like isc-dhcp-server.

1. Create the Wi-Fi Hotspot Profile in NetworkManager

Create a hotspot connection in the Raspberry Pi desktop Network GUI or via nmcli. Set the hotspot subnet to 10.0.1.1/24, enable auto-connect, and set MTU to 1420.

To enforce robust WPA2-only (RSN/AES) authentication and disable legacy WPA1:

nmcli con modify "Wi-Fi Hot" 802-11-wireless-security.proto rsn

2. Configure Policy Routing Table

Create a dedicated routing table for hotspot clients (subnet 10.0.1.0/24):

echo "200 INET2" | sudo tee -a /etc/iproute2/rt_tables

3. WireGuard Configuration (/etc/wireguard/wg0.conf)

Configure WireGuard with policy rules and MSS clamping to ensure seamless MTU handling through the tunnel:

[Interface]
PrivateKey = YOUR_PRIVATE_KEY
Address = 10.10.0.6/24
PostUp = iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE; ip rule add from 10.0.1.0/24 table INET2 priority 100; ip route add default dev wg0 table INET2; ip route add 8.8.8.8/32 dev wg0; ip route add 8.8.4.4/32 dev wg0; iptables -t mangle -A FORWARD -o wg0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu; iptables -t mangle -A FORWARD -i wg0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu; ip route flush cache
PreDown = iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE; ip rule del from 10.0.1.0/24 table INET2 priority 100; ip route del default dev wg0 table INET2; ip route del 8.8.8.8/32 dev wg0; ip route del 8.8.4.4/32 dev wg0; iptables -t mangle -D FORWARD -o wg0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu; iptables -t mangle -D FORWARD -i wg0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu; ip route flush cache
Table = off
MTU = 1280

[Peer]
PublicKey = SERVER_PUBLIC_KEY
AllowedIPs = 0.0.0.0/0
Endpoint = YOUR_VPN_SERVER_IP:PORT
PersistentKeepalive = 25

4. Enable Kernel IPv4 Forwarding

Enable packet forwarding in /etc/sysctl.conf:

sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf

5. DNS Configuration for DHCP Clients

Configure NetworkManager's shared dnsmasq instance to supply public DNS servers to hotspot clients:

sudo mkdir -p /etc/NetworkManager/dnsmasq-shared.d/
echo "dhcp-option=option:dns-server,8.8.8.8,8.8.4.4" | sudo tee /etc/NetworkManager/dnsmasq-shared.d/dns.conf

6. Monitoring and Verification

Check active DHCP leases granted to Wi-Fi clients:

cat /var/lib/NetworkManager/dnsmasq-wlan0.leases

Verify dnsmasq runtime process parameters:

ps aux | grep dnsmasq

How to Fix Repeating Keys and Keystroke Lag on WayVNC (Debian 12 Bookworm)

When connecting remotely to a WayVNC server on Debian 12 Bookworm (or Raspberry Pi OS) over high-latency or cross-border connections, you may encounter severe repeating keys (for instance, pressing a key once produces a long string like aaaaaaaaaa).

Root Cause

In remote desktop protocols, pressing and releasing a key sends distinct key-down and key-up network packets. If packet loss or network jitter causes the key-release packet to be delayed or dropped, the compositor's auto-repeat timer assumes the key is still physically held down and floods the active application with repeats.

Solution: Disable Compositor Key-Repeat

As documented in the Wayfire Core Options, disabling key repeat entirely on the host side prevents phantom keystrokes over latent links.

Edit the Wayfire configuration file (/etc/wayfire/defaults.ini or user-level ~/.config/wayfire.ini):

sudo nano /etc/wayfire/defaults.ini

Add or set kb_repeat_rate = 0 under the [input] section:

[input]
kb_repeat_rate = 0

Save the file and restart the WayVNC service or reboot the Raspberry Pi to apply the change:

sudo systemctl restart wayvnc
# or:
sudo reboot

Once rebooted, keystrokes will register accurately without runaway repetitions, even across lossy WAN connections.

Saturday, February 10, 2024

How to Capture Screenshots over SSH on Debian 12 Wayland Desktops

On legacy Debian 11 (Bullseye) and older X11 desktops, taking a screenshot of an active desktop session remotely over SSH was straightforward using scrot:

DISPLAY=:0.0 scrot -o screenshot.jpg

In Python:

import os
os.environ["DISPLAY"] = ":0.0"
os.system("scrot -o screenshot.jpg")

Wayland on Debian 12 (Bookworm)

On Debian 12 (and Raspberry Pi OS Bookworm with Wayfire or labwc), Wayland is the default compositor. Because Wayland enforces strict security isolation between graphical clients and display sockets, scrot will fail with the error:

failed to create display

To take screenshots under Wayland, use the native grim utility (pre-installed on Raspberry Pi OS). When calling grim over SSH from a non-interactive TTY, you must explicitly export both WAYLAND_DISPLAY and XDG_RUNTIME_DIR:

WAYLAND_DISPLAY=wayland-1 XDG_RUNTIME_DIR=/run/user/1000 grim screenshot.png

Python Automation Script

To capture screenshots programmatically in Python over SSH:

import os

pngfile = "/tmp/screenshot.png"
os.environ["WAYLAND_DISPLAY"] = "wayland-1"
os.environ["XDG_RUNTIME_DIR"] = "/run/user/1000"

os.system(f"grim {pngfile}")
Tip: If you are unsure of your socket names, run echo $WAYLAND_DISPLAY and echo $XDG_RUNTIME_DIR from a terminal inside the active desktop session, or check the socket files in /run/user/$(id -u)/.

Thursday, February 8, 2024

How to Set Default Route and Network Metrics on Debian 12 (Bookworm) Using NetworkManager

On Debian 12 (Bookworm) and Raspberry Pi OS Bookworm, dhcpcd has been deprecated and replaced by NetworkManager as the default network management stack. Consequently, /etc/dhcpcd.conf is no longer present.

When multiple network interfaces (such as Ethernet eth0 and Wi-Fi wlan0) are connected simultaneously, the Linux kernel determines the default gateway based on routing metrics. Lower metric values take precedence over higher values.

Rule: Lower route metric = higher routing priority. To prioritize an interface for default internet access, assign it a lower metric than competing interfaces.

1. Inspect Current Routing Metrics

Check the existing routing table and metric values:

ip route show
# or:
route -n

2. List NetworkManager Connection Profiles

Identify the exact connection name you wish to adjust:

nmcli connection show

3. Adjust the Route Metric

You can set the route metric directly using a single nmcli command:

# Set metric to 100 for higher priority (e.g. Ethernet)
nmcli connection modify "Wired connection 1" ipv4.route-metric 100

# Reactivate the connection to apply changes
nmcli connection up "Wired connection 1"

Alternatively, you can edit the connection interactively:

nmcli connection edit "Wired connection 1"
nmcli> set ipv4.route-metric 100
nmcli> save
nmcli> quit

Run ip route show again to verify that your preferred connection now holds the lowest metric on the default route.

Wednesday, July 5, 2023

How to Configure Eturnal TURN Server with TLS 1.3 and Static Credentials on Debian 12

Eturnal is a modern, lightweight STUN/TURN server written in Erlang that serves as an efficient alternative to Coturn with built-in TLS 1.3 support. While Eturnal natively uses time-limited ephemeral credentials (REST API authentication), many WebRTC clients require static usernames and passwords. Here is how to configure Eturnal on Debian 12 and generate static credentials using an HMAC-SHA1 Python helper.

Stack: Eturnal 1.12+ • Debian 12 Bookworm • TLS 1.3 • HMAC-SHA1 Password Generator

1. Installing Eturnal on Debian 12

# Add Eturnal package repository and install
curl -fsSL https://eturnal.net/gpg.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/eturnal.gpg
echo "deb https://eturnal.net/debian bookworm main" | sudo tee /etc/apt/sources.list.d/eturnal.list
sudo apt-get update && sudo apt-get install eturnal -y

2. Generating Static TURN Credentials via Python

To produce valid credentials matching your configured shared secret (secret: "YOUR_SHARED_SECRET" in /etc/eturnal.yml):

import time
import hmac
import hashlib
import base64

SHARED_SECRET = "YOUR_SHARED_SECRET"
# Set expiration timestamp (e.g. 1 year in the future)
expiry = int(time.time()) + (365 * 24 * 3600)
username = f"{expiry}:user1"

# Compute HMAC-SHA1 hash
key = SHARED_SECRET.encode('utf-8')
msg = username.encode('utf-8')
password = base64.b64encode(hmac.new(key, msg, hashlib.sha1).digest()).decode('utf-8')

print(f"TURN Username: {username}")
print(f"TURN Password: {password}")

Monday, July 3, 2023

How to Compile and Install Coturn 4.6.2 with TLS 1.3 Support on Debian 12 (Bookworm)

Coturn is the standard open-source STUN/TURN server enabling WebRTC audio/video connections across symmetric NATs and firewalls. Full support for modern TLS 1.3 encrypted TURN connections (TURNS) was added in Coturn 4.6.2. Because Debian 12 (Bookworm) originally packaged Coturn 4.6.1, compiling version 4.6.2 from source with OpenSSL 3.x is necessary for enterprise TLS 1.3 compliance.

Features: TURNS over TLS 1.3 • WebRTC relay performance • Debian 12 Bookworm

Compilation & Installation Commands

# 1. Install build tools and OpenSSL 3 development libraries
sudo apt-get update
sudo apt-get install -y pkg-config build-essential libssl-dev libevent-dev git

# 2. Download Coturn 4.6.2 release
cd /usr/src
git clone https://github.com/coturn/coturn.git
cd coturn
git checkout 4.6.2

# 3. Configure and compile with OpenSSL
./configure --prefix=/usr/local
make -j$(nproc)
sudo make install

# Verify binary and TLS support
turnserver -v

Sunday, April 23, 2023

How to Suppress OpenCV and GStreamer nvarguscamerasrc (GST_ARGUS) Debug Logs on NVIDIA Jetson

When capturing MIPI CSI camera video on NVIDIA Jetson Nano, Xavier, or Orin platforms using OpenCV with GStreamer's nvarguscamerasrc plugin, the driver constantly spams stdout and stderr with verbose hardcoded debug strings (such as GST_ARGUS: Creating output stream and CONSUMER: Waiting until producer is connected...).

Why Log Levels Don't Work: These prints are hardcoded inside NVIDIA's gstnvarguscamerasrc.cpp C++ source code via printf(), bypassing standard GStreamer debug level filters (GST_DEBUG=0).

1. Rebuilding nvarguscamerasrc Without Hardcoded Prints

Download your matching JetPack BSP public sources and remove the hardcoded print macros:

# Check active L4T release
cat /etc/nv_tegra_release

# Extract gst-nvarguscamera source
cd ~/src/Linux_for_Tegra/source/public
tar -jxvf gst-nvarguscamera_src.tbz2
cd gst-nvarguscamera/

# Edit gstnvarguscamerasrc.cpp and empty out the print macros:
sed -i 's/#define GST_ARGUS_PRINT(...) printf(__VA_ARGS__)/#define GST_ARGUS_PRINT(...)/g' gstnvarguscamerasrc.cpp
sed -i 's/#define CONSUMER_PRINT(...) printf(__VA_ARGS__)/#define CONSUMER_PRINT(...)/g' gstnvarguscamerasrc.cpp

# Compile and install plugin
make
sudo make install

2. Suppressing OpenCV Warnings in Python

In your Python application, silence OpenCV library logs and restart the camera daemon prior to acquisition:

import os
import warnings

# Suppress Python warnings & OpenCV internal logging
warnings.filterwarnings('ignore')
os.environ["OPENCV_LOG_LEVEL"] = "OFF"

# Restart camera daemon to ensure clean hardware state
os.system("sudo systemctl restart nvargus-daemon")

Your camera capture scripts will now run silently without terminal clutter.

How Google Antigravity Solved the Mysterious NVIDIA Sleep Reboot on My Dell Inspiron 7567 (Ubuntu Linux)

If you run modern Ubuntu or Linux on a Dell Inspiron 15 Gaming (7567) or a similar 7th-gen Intel laptop paired with an NVIDIA GeForce GTX ...