21st Century C: C Tips from the New School; Ben Klemens; O'Reilly
-
Perl New Features; Joshua McAdams, brian d foy; Perl School
-
DevOps And Site Reliability Engineering Handbook; Stephen Fleming; Audible
-
Distributed Systems: Principles and Paradigms; Andrew S. Tanenbaum; Pearson
-
Terraform Cookbook; Mikael Krief; Packt Publishing
-
Systemprogrammierung in Go; Frank Müller; dpunkt
-
Amazon Web Services in Action; Michael Wittig and Andreas Wittig; Manning Publications
-
Ultimate Go Notebook; Bill Kennedy
+
Go Brain Teasers - Exercise Your Mind; Miki Tebeka; The Pragmatic Programmers
Learn You Some Erlang for Great Good; Fred Herbert; No Starch Press
-
Systems Performance Tuning; Gian-Paolo D. Musumeci and others...; O'Reilly
-
Hands-on Infrastructure Monitoring with Prometheus; Joel Bastos, Pedro Araujo; Packt
-
Kubernetes Cookbook; Sameer Naik, Sébastien Goasguen, Jonathan Michaux; O'Reilly
+
Tmux 2: Productive Mouse-free Development; Brain P. Hogan; The Pragmatic Programmers
+
The Go Programming Language; Alan A. A. Donovan; Addison-Wesley Professional
+
The Docker Book; James Turnbull; Kindle
Site Reliability Engineering; How Google runs production systems; O'Reilly
-
Go Brain Teasers - Exercise Your Mind; Miki Tebeka; The Pragmatic Programmers
-
Programming Perl aka "The Camel Book"; Tom Christiansen, brian d foy, Larry Wall & Jon Orwant; O'Reilly
-
Data Science at the Command Line; Jeroen Janssens; O'Reilly
-
Clusterbau mit Linux-HA; Michael Schwartzkopff; O'Reilly
-
Leanring eBPF; Liz Rice; O'Reilly
-
Pro Puppet; James Turnbull, Jeffrey McCune; Apress
-
Programming Ruby 3.3 (5th Edition); Noel Rappin, with Dave Thomas; The Pragmatic Bookshelf
-
Developing Games in Java; David Brackeen and others...; New Riders
-
Raku Fundamentals; Moritz Lenz; Apress
-
The KCNA (Kubernetes and Cloud Native Associate) Book; Nigel Poulton
-
Concurrency in Go; Katherine Cox-Buday; O'Reilly
-
The Kubernetes Book; Nigel Poulton; Unabridged Audiobook
-
The Pragmatic Programmer; David Thomas; Addison-Wesley
-
97 things every SRE should know; Emil Stolarsky, Jaime Woo; O'Reilly
-
Polished Ruby Programming; Jeremy Evans; Packt Publishing
-
Chaos Engineering - System Resiliency in Practice; Casey Rosenthal and Nora Jones; eBook
-
Learn You a Haskell for Great Good!; Miran Lipovaca; No Starch Press
-
C++ Programming Language; Bjarne Stroustrup;
The Practise of System and Network Administration; Thomas A. Limoncelli, Christina J. Hogan, Strata R. Chalup; Addison-Wesley Professional Pro Git; Scott Chacon, Ben Straub; Apress
-
The Go Programming Language; Alan A. A. Donovan; Addison-Wesley Professional
-
Java ist auch eine Insel; Christian Ullenboom;
-
Tmux 2: Productive Mouse-free Development; Brain P. Hogan; The Pragmatic Programmers
DNS and BIND; Cricket Liu; O'Reilly
-
Effective awk programming; Arnold Robbins; O'Reilly
-
Modern Perl; Chromatic ; Onyx Neon Press
-
Raku Recipes; J.J. Merelo; Apress
-
Effective Java; Joshua Bloch; Addison-Wesley Professional
+
Systemprogrammierung in Go; Frank Müller; dpunkt
+
Java ist auch eine Insel; Christian Ullenboom;
100 Go Mistakes and How to Avoid Them; Teiva Harsanyi; Manning Publications
-
Higher Order Perl; Mark Dominus; Morgan Kaufmann
+
The Kubernetes Book; Nigel Poulton; Unabridged Audiobook
+
Leanring eBPF; Liz Rice; O'Reilly
+
Chaos Engineering - System Resiliency in Practice; Casey Rosenthal and Nora Jones; eBook
+
Modern Perl; Chromatic ; Onyx Neon Press
+
The KCNA (Kubernetes and Cloud Native Associate) Book; Nigel Poulton
Object-Oriented Programming with ANSI-C; Axel-Tobias Schreiner
-
Funktionale Programmierung; Peter Pepper; Springer
+
Systems Performance Tuning; Gian-Paolo D. Musumeci and others...; O'Reilly
+
Effective awk programming; Arnold Robbins; O'Reilly
+
Effective Java; Joshua Bloch; Addison-Wesley Professional
Seeking SRE: Conversations About Running Production Systems at Scale; David N. Blank-Edelman; eBook
+
Higher Order Perl; Mark Dominus; Morgan Kaufmann
+
Learn You a Haskell for Great Good!; Miran Lipovaca; No Starch Press
+
Perl New Features; Joshua McAdams, brian d foy; Perl School
+
Concurrency in Go; Katherine Cox-Buday; O'Reilly
+
Raku Fundamentals; Moritz Lenz; Apress
The DevOps Handbook; Gene Kim, Jez Humble, Patrick Debois, John Willis; Audible
+
Pro Puppet; James Turnbull, Jeffrey McCune; Apress
+
Funktionale Programmierung; Peter Pepper; Springer
+
Kubernetes Cookbook; Sameer Naik, Sébastien Goasguen, Jonathan Michaux; O'Reilly
+
Data Science at the Command Line; Jeroen Janssens; O'Reilly
+
Distributed Systems: Principles and Paradigms; Andrew S. Tanenbaum; Pearson
+
Terraform Cookbook; Mikael Krief; Packt Publishing
+
Amazon Web Services in Action; Michael Wittig and Andreas Wittig; Manning Publications
+
C++ Programming Language; Bjarne Stroustrup;
+
Programming Ruby 3.3 (5th Edition); Noel Rappin, with Dave Thomas; The Pragmatic Bookshelf
+
21st Century C: C Tips from the New School; Ben Klemens; O'Reilly
+
DevOps And Site Reliability Engineering Handbook; Stephen Fleming; Audible
Think Raku (aka Think Perl 6); Laurent Rosenfeld, Allen B. Downey; O'Reilly
-
The Docker Book; James Turnbull; Kindle
+
The Pragmatic Programmer; David Thomas; Addison-Wesley
+
Raku Recipes; J.J. Merelo; Apress
+
Ultimate Go Notebook; Bill Kennedy
+
Clusterbau mit Linux-HA; Michael Schwartzkopff; O'Reilly
+
Hands-on Infrastructure Monitoring with Prometheus; Joel Bastos, Pedro Araujo; Packt
+
97 things every SRE should know; Emil Stolarsky, Jaime Woo; O'Reilly
+
Developing Games in Java; David Brackeen and others...; New Riders
+
Polished Ruby Programming; Jeremy Evans; Packt Publishing
+
Programming Perl aka "The Camel Book"; Tom Christiansen, brian d foy, Larry Wall & Jon Orwant; O'Reilly
Technical references
I didn't read them from the beginning to the end, but I am using them to look up things. The books are in random order:
-
BPF Performance Tools - Linux System and Application Observability, Brendan Gregg; Addison Wesley
-
Algorithms; Robert Sedgewick, Kevin Wayne; Addison Wesley
Go: Design Patterns for Real-World Projects; Mat Ryer; Packt
-
Implementing Service Level Objectives; Alex Hidalgo; O'Reilly
-
Relayd and Httpd Mastery; Michael W Lucas
The Linux Programming Interface; Michael Kerrisk; No Starch Press
Understanding the Linux Kernel; Daniel P. Bovet, Marco Cesati; O'Reilly
+
Implementing Service Level Objectives; Alex Hidalgo; O'Reilly
+
Relayd and Httpd Mastery; Michael W Lucas
+
BPF Performance Tools - Linux System and Application Observability, Brendan Gregg; Addison Wesley
+
Algorithms; Robert Sedgewick, Kevin Wayne; Addison Wesley
Groovy Kurz & Gut; Joerg Staudemeier; O'Reilly
Self-development and soft-skills books
@@ -118,44 +118,44 @@
In random order:
-
Eat That Frog!; Brian Tracy; Hodder Paperbacks
+
Consciousness: A Very Short Introduction; Susan Blackmore; Oxford Uiversity Press
The Obstacle Is The Way; Ryan Holiday; Profile Books Ltd
+
The Joy of Missing Out; Christina Crook; New Society Publishers
+
Who Moved My Cheese?; Dr. Spencer Johnson; Vermilion
Search Inside Yourself - The Unexpected path to Achieving Success, Happiness (and World Peace); Chade-Meng Tan, Daniel Goleman, Jon Kabat-Zinn; HarperOne
-
101 Essays that change the way you think; Brianna Wiest; Audiobook
-
Eat That Frog; Brian Tracy
-
The Software Engineer's Guidebook: Navigating senior, tech lead, and staff engineer positions at tech companies and startups; Gergely Orosz; Audiobook
-
Deep Work; Cal Newport; Piatkus
-
Psycho-Cybernetics; Maxwell Maltz; Perigee Books
-
The Bullet Journal Method; Ryder Carroll; Fourth Estate
-
The 7 Habits Of Highly Effective People; Stephen R. Covey; Simon & Schuster UK
The Power of Now; Eckhard Tolle; Yellow Kite
-
So Good They Can't Ignore You; Cal Newport; Business Plus
-
Digital Minimalism; Cal Newport; Portofolio Penguin
-
The Complete Software Developer's Career Guide; John Sonmez; Unabridged Audiobook
-
Slow Productivity; Cal Newport; Penguin Random House
+
Eat That Frog!; Brian Tracy; Hodder Paperbacks
+
Soft Skills; John Sommez; Manning Publications
Getting Things Done; David Allen
+
Eat That Frog; Brian Tracy
+
Influence without Authority; A. Cohen, D. Bradford; Wiley
+
Solve for Happy; Mo Gawdat (RE-READ 1ST TIME)
The Phoenix Project - A Novel About IT, DevOps, and Helping your Business Win; Gene Kim and Kevin Behr; Trade Select
-
Buddah and Einstein walk into a Bar; Guy Joseph Ale, Claire Bloom; Blackstone Publishing
-
Time Management for System Administrators; Thomas A. Limoncelli; O'Reilly
+
The Complete Software Developer's Career Guide; John Sonmez; Unabridged Audiobook
+
Staff Engineer: Leadership beyond the management track; Will Larson; Audiobook
+
Ultralearning; Scott Young; Thorsons
+
Deep Work; Cal Newport; Piatkus
+
101 Essays that change the way you think; Brianna Wiest; Audiobook
+
The Software Engineer's Guidebook: Navigating senior, tech lead, and staff engineer positions at tech companies and startups; Gergely Orosz; Audiobook
The Good Enough Job; Simone Stolzoff; Ebury Edge
-
Atomic Habits; James Clear; Random House Business
+
So Good They Can't Ignore You; Cal Newport; Business Plus
+
Digital Minimalism; Cal Newport; Portofolio Penguin
The Daily Stoic; Ryan Holiday, Stephen Hanselman; Profile Books
+
The Off Switch; Mark Cropley; Virgin Books (RE-READ 1ST TIME)
+
Buddah and Einstein walk into a Bar; Guy Joseph Ale, Claire Bloom; Blackstone Publishing
97 Things Every Engineering Manager Should Know; Camille Fournier; Audiobook
-
Never Split the Difference; Chris Voss, Tahl Raz; Random House Business
-
Influence without Authority; A. Cohen, D. Bradford; Wiley
-
Staff Engineer: Leadership beyond the management track; Will Larson; Audiobook
-
Who Moved My Cheese?; Dr. Spencer Johnson; Vermilion
-
Meditation for Mortals, Oliver Burkeman, Audiobook
-
Consciousness: A Very Short Introduction; Susan Blackmore; Oxford Uiversity Press
-
Ultralearning; Anna Laurent; Self-published via Amazon
+
Time Management for System Administrators; Thomas A. Limoncelli; O'Reilly
The Courage to Be Disliked; Ichiro Kishimi and Fumitake Koga; Audiobook
+
Meditation for Mortals, Oliver Burkeman, Audiobook
+
The Bullet Journal Method; Ryder Carroll; Fourth Estate
+
Psycho-Cybernetics; Maxwell Maltz; Perigee Books
Coders at Work - Reflections on the craft of programming, Peter Seibel and Mitchell Dorian et al., Audiobook
-
Soft Skills; John Sommez; Manning Publications
-
The Off Switch; Mark Cropley; Virgin Books (RE-READ 1ST TIME)
-
Ultralearning; Scott Young; Thorsons
+
Atomic Habits; James Clear; Random House Business
Stop starting, start finishing; Arne Roock; Lean-Kanban University
-
The Joy of Missing Out; Christina Crook; New Society Publishers
-
Solve for Happy; Mo Gawdat (RE-READ 1ST TIME)
+
Never Split the Difference; Chris Voss, Tahl Raz; Random House Business
+
Slow Productivity; Cal Newport; Penguin Random House
+
The 7 Habits Of Highly Effective People; Stephen R. Covey; Simon & Schuster UK
+
Ultralearning; Anna Laurent; Self-published via Amazon
@@ -164,30 +164,30 @@
Some of these were in-person with exams; others were online learning lectures only. In random order:
-
Developing IaC with Terraform (with Live Lessons); O'Reilly Online
Scripting Vim; Damian Conway; O'Reilly Online
-
Red Hat Certified System Administrator; Course + certification (Although I had the option, I decided not to take the next course as it is more effective to self learn what I need)
-
Functional programming lecture; Remote University of Hagen
-
Cloud Operations on AWS - Learn how to configure, deploy, maintain, and troubleshoot your AWS environments; 3-day online live training with labs; Amazon
-
The Well-Grounded Rubyist Video Edition; David. A. Black; O'Reilly Online
-
MySQL Deep Dive Workshop; 2-day on-site training
Ultimate Go Programming; Bill Kennedy; O'Reilly Online
-
Algorithms Video Lectures; Robert Sedgewick; O'Reilly Online
-
Protocol buffers; O'Reilly Online
-
Structure and Interpretation of Computer Programs; Harold Abelson and more...;
+
MySQL Deep Dive Workshop; 2-day on-site training
F5 Loadbalancers Training; 2-day on-site training; F5, Inc.
-
Apache Tomcat Best Practises; 3-day on-site training
-
AWS Immersion Day; Amazon; 1-day interactive online training
The Ultimate Kubernetes Bootcamp; School of Devops; O'Reilly Online
+
Developing IaC with Terraform (with Live Lessons); O'Reilly Online
+
Apache Tomcat Best Practises; 3-day on-site training
+
Algorithms Video Lectures; Robert Sedgewick; O'Reilly Online
+
Protocol buffers; O'Reilly Online
Linux Security and Isolation APIs Training; Michael Kerrisk; 3-day on-site training
+
AWS Immersion Day; Amazon; 1-day interactive online training
+
Structure and Interpretation of Computer Programs; Harold Abelson and more...;
+
Red Hat Certified System Administrator; Course + certification (Although I had the option, I decided not to take the next course as it is more effective to self learn what I need)
+
Functional programming lecture; Remote University of Hagen
+
The Well-Grounded Rubyist Video Edition; David. A. Black; O'Reilly Online
+
Cloud Operations on AWS - Learn how to configure, deploy, maintain, and troubleshoot your AWS environments; 3-day online live training with labs; Amazon
Technical guides
These are not whole books, but guides (smaller or larger) which I found very useful. in random order:
-
Raku Guide at https://raku.guide
Advanced Bash-Scripting Guide
+
Raku Guide at https://raku.guide
How CPUs work at https://cpu.land
Podcasts
@@ -198,60 +198,60 @@
Backend Banter
-
BSD Now [BSD]
-
Fork Around And Find Out
-
Cup o' Go [Golang]
-
Pratical AI
-
The ProdCast (Google SRE Podcast)
The Pragmatic Engineer Podcast
-
Modern Mentor
+
Fallthrough [Golang]
Deep Questions with Cal Newport
-
Hidden Brain
Maintainable
+
Fork Around And Find Out
+
The ProdCast (Google SRE Podcast)
+
Modern Mentor
The Changelog Podcast(s)
-
Fallthrough [Golang]
-
Dev Interrupted
+
Pratical AI
+
Hidden Brain
+
BSD Now [BSD]
Wednesday Wisdom
+
Cup o' Go [Golang]
+
Dev Interrupted
Podcasts I liked
I liked them but am not listening to them anymore. The podcasts have either "finished" (no more episodes) or I stopped listening to them due to time constraints or a shift in my interests.
-
Ship It (predecessor of Fork Around And Find Out)
Modern Mentor
-
FLOSS weekly
Go Time (predecessor of fallthrough)
-
CRE: Chaosradio Express [german]
+
FLOSS weekly
Java Pub House
+
Ship It (predecessor of Fork Around And Find Out)
+
CRE: Chaosradio Express [german]
Newsletters I like
This is a mix of tech and non-tech newsletters I am subscribed to. In random order:
-
Ruby Weekly
Andreas Brandhorst Newsletter (Sci-Fi author)
-
Golang Weekly
+
VK Newsletter
+
The Imperfectionist
Applied Go Weekly Newsletter
The Valuable Dev
Changelog News
-
Register Spill
-
The Imperfectionist
-
Monospace Mentor
+
Golang Weekly
byteSizeGo
+
Monospace Mentor
The Pragmatic Engineer
-
VK Newsletter
+
Ruby Weekly
+
Register Spill
Magazines I like(d)
This is a mix of tech I like(d). I may not be a current subscriber, but now and then, I buy an issue. In random order:
f3s: Kubernetes with FreeBSD - Part 5: WireGuard mesh network
-Published at 2025-05-11T11:35:57+03:00
+Published at 2025-05-11T11:35:57+03:00, last updated Sun 11 Jan 21:33:40 EET 2026
This is the fifth blog post about my f3s series for my self-hosting demands in my home lab. f3s? The "f" stands for FreeBSD, and the "3s" stands for k3s, the Kubernetes distribution I will use on FreeBSD-based physical machines.
I will post a new entry every month or so (there are too many other side projects for more frequent updates — I bet you can understand).
+This post has been updated to include two roaming clients (earth - Fedora laptop, pixel7pro - Android phone) that connect to the mesh via the internet gateways. The updated content is integrated throughout the post.
+ These are all the posts so far:
-By default, traffic within my home LAN, including traffic inside a k3s cluster, is not encrypted. While it resides in the "secure" home LAN, adopting a zero-trust policy means encryption is still preferable to ensure confidentiality and security. So we decide to secure all the traffic of all f3s participating hosts by building a mesh network of all participating hosts:
+By default, traffic within my home LAN, including traffic inside a k3s cluster, is not encrypted. While it resides in the "secure" home LAN, adopting a zero-trust policy means encryption is still preferable to ensure confidentiality and security. So we decide to secure all the traffic of all f3s participating hosts by building a mesh network:
+
+
+
+The mesh network consists of eight infrastructure hosts and two roaming clients:
-
+Infrastructure hosts (full mesh):
-Whereas f0, f1, and f2 are the FreeBSD base hosts, r0, r1, and r2 are the Rocky Linux Bhyve VMs, and blowfish and fishfinger are two OpenBSD systems running on the internet (as mentioned in the first blog of this series—these systems are already built; in fact, this very blog is served by those OpenBSD systems).
+
+
f0, f1, and f2 are the FreeBSD base hosts in my home LAN
+
r0, r1, and r2 are the Rocky Linux Bhyve VMs running on the FreeBSD hosts
+
blowfish and fishfinger are two OpenBSD systems running on the internet (as mentioned in the first blog of this series—these systems are already built; in fact, this very blog is served by those OpenBSD systems)
+
+oaming clients (gateway-only connections):
-As we can see from the graph, it is a true full-mesh network, where every host has a VPN tunnel to every other host. The benefit is that we do not need to route traffic through intermediate hosts (significantly simplifying the routing configuration). However, the downside is that there is some overhead in configuring and managing all the tunnels.
+
+
earth is my Fedora laptop (192.168.2.200) which connects only to the internet gateways for remote access
+
pixel7pro is my Android phone (192.168.2.201) which routes all traffic through the VPN when activated
+
+As we can see from the diagram, the eight infrastructure hosts form a true full-mesh network, where every host has a VPN tunnel to every other host. The benefit is that we do not need to route traffic through intermediate hosts (significantly simplifying the routing configuration). However, the downside is that there is some overhead in configuring and managing all the tunnels. The roaming clients take a simpler approach—they only connect to the two internet-facing gateways (blowfish and fishfinger), which is sufficient for remote access and internet connectivity.
For simplicity, we also establish VPN tunnels between f0 <-> r0, f1 <-> r1, and f2 <-> r2. Technically, this wouldn't be strictly required since the VMs rN are running on the hosts fN, and no network traffic is leaving the box. However, it simplifies the configuration as we don't have to account for exceptions, and we are going to automate the mesh network configuration anyway (read on).
Expected traffic flow
-The traffic is expected to flow between the host groups through the mesh network as follows:
+The traffic is expected to flow between the host groups through the mesh network as follows:
+
+nfrastructure mesh traffic:
-
fN <-> rN: The traffic between the FreeBSD hosts and the Rocky Linux VMs will be routed through the VPN tunnels for persistent storage. In a later post in this series, we will set up an NFS server on the fN hosts.
+
fN <-> rN: The traffic between the FreeBSD hosts and the Rocky Linux VMs will be routed through the VPN tunnels for persistent storage. In a later post in this series, we will set up an NFS server on the fN hosts.
fN <-> blowfish,fishfinger: The traffic between the FreeBSD hosts and the OpenBSD host blowfish,fishfinger will be routed through the VPN tunnels for management. We may want to log in via the internet to set it up remotely. The VPN tunnel will also be used for monitoring purposes.
rN <-> blowfish,fishfinger: The traffic between the Rocky Linux VMs and the OpenBSD host blowfish,fishfinger will be routed through the VPN tunnels for usage traffic. Since k3s will be running on the rN hosts, the OpenBSD servers will route the traffic through relayd to the services running in Kubernetes.
fN <-> fM: The traffic between the FreeBSD hosts may be later used for data replication for the NFS storage.
rN <-> rM: The traffic between the Rocky Linux VMs will later be used by the k3s cluster itself, as every rN will be a Kubernetes worker node.
blowfish <-> fishfinger: The traffic between the OpenBSD hosts isn't strictly required for this setup, but I set it up anyway for future use cases.
+oaming client traffic:
+
+
+
earth,pixel7pro <-> blowfish,fishfinger: The roaming clients connect exclusively to the two internet gateways. All traffic from these clients (0.0.0.0/0) is routed through the VPN, providing secure internet access and the ability to reach services running in the mesh (via the gateways). The gateways use NAT to allow roaming clients to access the internet using the gateway's public IP address. The roaming clients cannot be reached by the LAN hosts—they are client-only and initiate all connections.
+
We won't cover all the details in this blog post, as we only focus on setting up the Mesh network in this blog post. Subsequent posts in this series will cover the other details.
Deciding on WireGuard
@@ -283,9 +310,36 @@ http://www.gnu.org/software/src-highlite -->
192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
+192.168.2.200 earth.wg0 earth.wg0.wan.buetow.org
+192.168.2.201 pixel7pro.wg0 pixel7pro.wg0.wan.buetow.org
END
+To enable roaming clients (like earth and pixel7pro) to access the internet through the VPN, we need to configure NAT on the OpenBSD gateways. This allows the roaming clients to use the gateway's public IP address for outbound traffic. We add the following to /etc/pf.conf on both blowfish and fishfinger:
+
+
+
# NAT for WireGuard clients to access internet
+match out on vio0 from 192.168.2.0/24 to any nat-to (vio0)
+
+# Allow inbound traffic on WireGuard interface
+pass in on wg0
+
+# Allow all UDP traffic on WireGuard port
+pass in inet proto udp from any to any port 56709
+
+
+The NAT rule translates outgoing traffic from the WireGuard network (192.168.2.0/24) to the gateway's public IP. The firewall rules permit WireGuard traffic on the wg0 interface and UDP port 56709. After updating /etc/pf.conf, reload the firewall:
+
+
+
blowfish$ doas pfctl -f /etc/pf.conf
+
+
WireGuard configuration
So far, we have only started WireGuard on all participating hosts without any useful configuration. This means that no VPN tunnel has been established yet between any of the hosts.
@@ -358,7 +412,41 @@ Endpoint = 46.23.94.99:56709
PersistentKeepalive = 25
-Whereas there are two main sections. One is [Interface], which configures the current host (here: f0):
+For roaming clients like pixel7pro (Android phone) or earth (Fedora laptop), the configuration looks different because they route all traffic through the VPN and only connect to the internet gateways:
+
+
+
+Note the key differences for roaming clients:
+
+
DNS is configured to use external DNS servers (Cloudflare and Google)
+
AllowedIPs = 0.0.0.0/0, ::/0 routes all traffic (IPv4 and IPv6) through the VPN
+
Only two peers are configured (the internet gateways), not the full mesh
+
PersistentKeepalive = 25 is used for both peers to maintain NAT traversal
+
+Whereas there are two main sections. One is [Interface], which configures the current host (here: f0 or pixel7pro):
Address: Local virtual IP address on the WireGuard interface.
@@ -436,32 +524,12 @@ hosts:
wg0:
domain: 'wg0.wan.buetow.org'
ip: '192.168.2.130'
- f1:
- os: FreeBSD
- ssh:
- user: paul
- conf_dir: /usr/local/etc/wireguard
- sudo_cmd: doas
- reload_cmd: service wireguard reload
- lan:
- domain: 'lan.buetow.org'
- ip: '192.168.1.131'
- wg0:
- domain: 'wg0.wan.buetow.org'
- ip: '192.168.2.131'
- f2:
- os: FreeBSD
- ssh:
- user: paul
- conf_dir: /usr/local/etc/wireguard
- sudo_cmd: doas
- reload_cmd: service wireguard reload
- lan:
- domain: 'lan.buetow.org'
- ip: '192.168.1.132'
- wg0:
- domain: 'wg0.wan.buetow.org'
- ip: '192.168.2.132'
+ exclude_peers:
+ - earth
+ - pixel7pro
+ # f1 and f2 similarly configured with exclude_peers for roaming clients
+ # (full config omitted for brevity)
+ ...
r0:
os: Linux
ssh:
@@ -475,36 +543,16 @@ hosts:
wg0:
domain: 'wg0.wan.buetow.org'
ip: '192.168.2.120'
- r1:
- os: Linux
- ssh:
- user: root
- conf_dir: /etc/wireguard
- sudo_cmd:
- reload_cmd: systemctl reload wg-quick@wg0.service
- lan:
- domain: 'lan.buetow.org'
- ip: '192.168.1.121'
- wg0:
- domain: 'wg0.wan.buetow.org'
- ip: '192.168.2.121'
- r2:
- os: Linux
- ssh:
- user: root
- conf_dir: /etc/wireguard
- sudo_cmd:
- reload_cmd: systemctl reload wg-quick@wg0.service
- lan:
- domain: 'lan.buetow.org'
- ip: '192.168.1.122'
- wg0:
- domain: 'wg0.wan.buetow.org'
- ip: '192.168.2.122'
+ exclude_peers:
+ - earth
+ - pixel7pro
+ # r1 and r2 similarly configured
+ ...
blowfish:
os: OpenBSD
ssh:
user: rex
+ port: 2
conf_dir: /etc/wireguard
sudo_cmd: doas
reload_cmd: sh /etc/netstart wg0
@@ -514,10 +562,14 @@ hosts:
wg0:
domain: 'wg0.wan.buetow.org'
ip: '192.168.2.110'
+ exclude_peers:
+ - earth
+ - pixel7pro
fishfinger:
os: OpenBSD
ssh:
user: rex
+ port: 2
conf_dir: /etc/wireguard
sudo_cmd: doas
reload_cmd: sh /etc/netstart wg0
@@ -527,10 +579,41 @@ hosts:
wg0:
domain: 'wg0.wan.buetow.org'
ip: '192.168.2.111'
+ exclude_peers:
+ - earth
+ - pixel7pro
+ earth:
+ os: Linux
+ wg0:
+ domain: 'wg0.wan.buetow.org'
+ ip: '192.168.2.200'
+ exclude_peers:
+ - f0
+ - f1
+ - f2
+ - r0
+ - r1
+ - r2
+ - pixel7pro
+ pixel7pro:
+ os: Android
+ wg0:
+ domain: 'wg0.wan.buetow.org'
+ ip: '192.168.2.201'
+ exclude_peers:
+ - f0
+ - f1
+ - f2
+ - r0
+ - r1
+ - r2
+ - earth
The file specifies details such as SSH user settings, configuration directories, sudo or reload commands, and IP/domain assignments for both internal LAN-facing interfaces and WireGuard (wg0) interfaces. Each host is assigned specific roles, including internal participants and publicly accessible nodes with internet-facing IPs, enabling the creation of a fully connected mesh VPN.
+Roaming clients: Note the earth and pixel7pro entries—these are configured differently from the infrastructure hosts. They have no lan or internet sections, which signals to the generator that they are roaming clients. The exclude_peers configuration ensures they only connect to the internet gateways (blowfish and fishfinger) and are not reachable by LAN hosts. The generator automatically configures these clients with AllowedIPs = 0.0.0.0/0, ::/0 to route all traffic through the VPN, includes DNS configuration (1.1.1.1, 8.8.8.8), and enables PersistentKeepalive for NAT traversal.
+
wireguardmeshgenerator.rb overview
The wireguardmeshgenerator.rb script consists of the following base classes:
@@ -624,6 +707,8 @@ Generating dist/r1/etc/wireguard/wg2/etc/wireguard/wg0.conf
Generating dist/blowfish/etc/wireguard/wg0.conf
Generating dist/fishfinger/etc/wireguard/wg0.conf
+Generating dist/earth/etc/wireguard/wg0.conf
+Generating dist/pixel7pro/etc/wireguard/wg0.conf
It generated all the wg0.conf files listed in the output, plus those keys:
@@ -663,6 +748,10 @@ keys/psk/fishfinger_r1.key
keys/psk/blowfish_r2.key
keys/psk/fishfinger_r2.key
keys/psk/blowfish_fishfinger.key
+keys/psk/blowfish_earth.key
+keys/psk/earth_fishfinger.key
+keys/psk/blowfish_pixel7pro.key
+keys/psk/fishfinger_pixel7pro.key
keys/f1/priv.key
keys/f1/pub.key
keys/f2/priv.key
@@ -677,6 +766,10 @@ keys/blowfish/priv.key
keys/blowfish/pub.key
keys/fishfinger/priv.key
keys/fishfinger/pub.key
+keys/earth/priv.key
+keys/earth/pub.key
+keys/pixel7pro/priv.key
+keys/pixel7pro/pub.key
Those keys are embedded in the resulting wg0.conf, so later, we only need to install the wg0.conf files and not all the keys individually.
@@ -812,6 +905,40 @@ http://www.gnu.org/software/src-highlite -->
That would also delete and re-generate all the keys involved.
+
Setting up roaming clients
+
+For roaming clients like earth (Fedora laptop) and pixel7pro (Android phone), the setup process differs slightly since these devices are not always accessible via SSH:
+
+Android phone (pixel7pro):
+
+The configuration is transferred to the phone using a QR code. The official WireGuard Android app (from Google Play Store) can scan and import the configuration:
+
+
+
+
+Scan the QR code with the WireGuard app to import the configuration. The phone will then route all traffic through the VPN when the tunnel is activated. Note that WireGuard does not support automatic failover between the two gateways (blowfish and fishfinger)—if one fails, manual disconnection and reconnection is required to switch to the other.
+
+Fedora laptop (earth):
+
+For the laptop, manually copy the generated configuration:
+
+
+
+
+The service is disabled from auto-start so the VPN is only active when manually started. This allows selective VPN usage based on need.
+
Happy WireGuard-ing
All is set up now. E.g. on f0:
@@ -999,6 +1126,121 @@ peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
allowed ips: 192.168.2.131/32
+
Managing Roaming Client Tunnels
+
+Since roaming clients like earth and pixel7pro connect on-demand rather than being always-on like the infrastructure hosts, it's useful to know how to start and stop the WireGuard tunnels.
+
+
Starting and stopping on earth (Fedora laptop)
+
+On the Fedora laptop, WireGuard is managed via systemd. Starting the tunnel:
+
+
+
earth$ sudo systemctl start wg-quick@wg0.service
+earth$ sudo wg show
+interface: wg0
+ public key: Mc1CpSS3rbLN9A2w9c75XugQyXUkGPHKI2iCGbh8DRo=
+ private key: (hidden)
+ listening port: 56709
+ fwmark: 0xca6c
+
+peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
+ preshared key: (hidden)
+ endpoint: 46.23.94.99:56709
+ allowed ips: 0.0.0.0/0, ::/0
+ latest handshake: 5 seconds ago
+ transfer: 15.89 KiB received, 32.15 KiB sent
+ persistent keepalive: every 25 seconds
+
+peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
+ preshared key: (hidden)
+ endpoint: 23.88.35.144:56709
+ allowed ips: (none)
+ latest handshake: 5 seconds ago
+ transfer: 124 B received, 180 B sent
+ persistent keepalive: every 25 seconds
+
+
+Stoppint the tunnel:
+
+
+
earth$ sudo systemctl stop wg-quick@wg0.service
+earth$ sudo wg show
+# No output - WireGuard interface is down
+
+
+Checking the tunnel status:
+
+
+
earth$ sudo systemctl status wg-quick@wg0.service
+● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
+ Loaded: loaded (/usr/lib/systemd/system/wg-quick@.service; disabled)
+ Active: active (exited) since Sun 2026-01-11 22:45:00 EET
+
+
+The service remains disabled to prevent auto-start on boot, allowing manual control of when the VPN is active.
+
+
Starting and stopping on pixel7pro (Android phone)
+
+On Android using the official WireGuard app, tunnel management is like this:
+
+Starting the tunnel:
+
+
+
1. Open the WireGuard app
+
2. Tap the toggle switch next to the pixel7pro tunnel configuration
+
3. The switch turns blue/green and shows "Active"
+
4. A key icon appears in the notification bar indicating VPN is active
+
5. All traffic now routes through the VPN
+
+Stopping the tunnel:
+
+
+
1. Open the WireGuard app
+
2. Tap the toggle switch again to disable it
+
3. The switch turns gray and shows "Inactive"
+
4. The notification bar key icon disappears
+
5. Normal internet routing resumes
+
+Quick toggling from notification:
+
+
+
Pull down the notification shade
+
Tap the WireGuard notification to quickly enable/disable the tunnel without opening the app
+
+The WireGuard Android app supports automatically activating tunnels based on:
+
+
+
Mobile data connection (e.g., enable VPN when on cellular)
+
WiFi SSID (e.g., disable VPN when on trusted home network)
+
Ethernet connection status
+
+These settings can be configured by tapping the pencil icon next to the tunnel name, then scrolling to "Toggle on/off based on" options.
+
+
Verifying connectivity
+
+Once the tunnel is active on either device, verify connectivity:
+
+
+
# From earth laptop:
+earth$ ping -c2 blowfish.wg0
+earth$ ping -c2 fishfinger.wg0
+earth$ curl https://ifconfig.me # Should show gateway's public IP
+
+
+Check which gateway is active: The device will typically prefer one gateway (usually the first one with a successful handshake). To see which gateway is actively routing traffic, check the transfer statistics with sudo wg show on earth, or observe which gateway shows recent handshakes and increasing transfer bytes.
+
Conclusion
Having a mesh network on our hosts is great for securing all the traffic between them for our future k3s setup. A self-managed WireGuard mesh network is better than Tailscale as it eliminates reliance on a third party and provides full control over the configuration. It reduces unnecessary abstraction and "magic," enabling easier debugging and ensuring full ownership of our network.
diff --git a/gemfeed/atom.xml b/gemfeed/atom.xml
index d9eda66d..d24610e7 100644
--- a/gemfeed/atom.xml
+++ b/gemfeed/atom.xml
@@ -1,6 +1,6 @@
- 2026-01-11T10:46:34+02:00
+ 2026-01-11T22:40:26+02:00foo.zone feedTo be in the .zone!
@@ -9566,7 +9566,7 @@ Jul 06 10:f3s: Kubernetes with FreeBSD - Part 5: WireGuard mesh network
https://foo.zone/gemfeed/2025-05-11-f3s-kubernetes-with-freebsd-part-5.html
- 2025-05-11T11:35:57+03:00
+ 2025-05-11T11:35:57+03:00, last updated Sun 11 Jan 21:33:40 EET 2026Paul Buetow aka snonuxpaul@dev.buetow.org
@@ -9576,12 +9576,14 @@ Jul 06 10:
f3s: Kubernetes with FreeBSD - Part 5: WireGuard mesh network
-Published at 2025-05-11T11:35:57+03:00
+Published at 2025-05-11T11:35:57+03:00, last updated Sun 11 Jan 21:33:40 EET 2026
This is the fifth blog post about my f3s series for my self-hosting demands in my home lab. f3s? The "f" stands for FreeBSD, and the "3s" stands for k3s, the Kubernetes distribution I will use on FreeBSD-based physical machines.
I will post a new entry every month or so (there are too many other side projects for more frequent updates — I bet you can understand).
+This post has been updated to include two roaming clients (earth - Fedora laptop, pixel7pro - Android phone) that connect to the mesh via the internet gateways. The updated content is integrated throughout the post.
+ These are all the posts so far:
-By default, traffic within my home LAN, including traffic inside a k3s cluster, is not encrypted. While it resides in the "secure" home LAN, adopting a zero-trust policy means encryption is still preferable to ensure confidentiality and security. So we decide to secure all the traffic of all f3s participating hosts by building a mesh network of all participating hosts:
+By default, traffic within my home LAN, including traffic inside a k3s cluster, is not encrypted. While it resides in the "secure" home LAN, adopting a zero-trust policy means encryption is still preferable to ensure confidentiality and security. So we decide to secure all the traffic of all f3s participating hosts by building a mesh network:
+
+
+
+The mesh network consists of eight infrastructure hosts and two roaming clients:
-
+Infrastructure hosts (full mesh):
-Whereas f0, f1, and f2 are the FreeBSD base hosts, r0, r1, and r2 are the Rocky Linux Bhyve VMs, and blowfish and fishfinger are two OpenBSD systems running on the internet (as mentioned in the first blog of this series—these systems are already built; in fact, this very blog is served by those OpenBSD systems).
+
+
f0, f1, and f2 are the FreeBSD base hosts in my home LAN
+
r0, r1, and r2 are the Rocky Linux Bhyve VMs running on the FreeBSD hosts
+
blowfish and fishfinger are two OpenBSD systems running on the internet (as mentioned in the first blog of this series—these systems are already built; in fact, this very blog is served by those OpenBSD systems)
+
+oaming clients (gateway-only connections):
-As we can see from the graph, it is a true full-mesh network, where every host has a VPN tunnel to every other host. The benefit is that we do not need to route traffic through intermediate hosts (significantly simplifying the routing configuration). However, the downside is that there is some overhead in configuring and managing all the tunnels.
+
+
earth is my Fedora laptop (192.168.2.200) which connects only to the internet gateways for remote access
+
pixel7pro is my Android phone (192.168.2.201) which routes all traffic through the VPN when activated
+
+As we can see from the diagram, the eight infrastructure hosts form a true full-mesh network, where every host has a VPN tunnel to every other host. The benefit is that we do not need to route traffic through intermediate hosts (significantly simplifying the routing configuration). However, the downside is that there is some overhead in configuring and managing all the tunnels. The roaming clients take a simpler approach—they only connect to the two internet-facing gateways (blowfish and fishfinger), which is sufficient for remote access and internet connectivity.
For simplicity, we also establish VPN tunnels between f0 <-> r0, f1 <-> r1, and f2 <-> r2. Technically, this wouldn't be strictly required since the VMs rN are running on the hosts fN, and no network traffic is leaving the box. However, it simplifies the configuration as we don't have to account for exceptions, and we are going to automate the mesh network configuration anyway (read on).
Expected traffic flow
-The traffic is expected to flow between the host groups through the mesh network as follows:
+The traffic is expected to flow between the host groups through the mesh network as follows:
+
+nfrastructure mesh traffic:
-
fN <-> rN: The traffic between the FreeBSD hosts and the Rocky Linux VMs will be routed through the VPN tunnels for persistent storage. In a later post in this series, we will set up an NFS server on the fN hosts.
+
fN <-> rN: The traffic between the FreeBSD hosts and the Rocky Linux VMs will be routed through the VPN tunnels for persistent storage. In a later post in this series, we will set up an NFS server on the fN hosts.
fN <-> blowfish,fishfinger: The traffic between the FreeBSD hosts and the OpenBSD host blowfish,fishfinger will be routed through the VPN tunnels for management. We may want to log in via the internet to set it up remotely. The VPN tunnel will also be used for monitoring purposes.
rN <-> blowfish,fishfinger: The traffic between the Rocky Linux VMs and the OpenBSD host blowfish,fishfinger will be routed through the VPN tunnels for usage traffic. Since k3s will be running on the rN hosts, the OpenBSD servers will route the traffic through relayd to the services running in Kubernetes.
fN <-> fM: The traffic between the FreeBSD hosts may be later used for data replication for the NFS storage.
rN <-> rM: The traffic between the Rocky Linux VMs will later be used by the k3s cluster itself, as every rN will be a Kubernetes worker node.
blowfish <-> fishfinger: The traffic between the OpenBSD hosts isn't strictly required for this setup, but I set it up anyway for future use cases.
+oaming client traffic:
+
+
+
earth,pixel7pro <-> blowfish,fishfinger: The roaming clients connect exclusively to the two internet gateways. All traffic from these clients (0.0.0.0/0) is routed through the VPN, providing secure internet access and the ability to reach services running in the mesh (via the gateways). The gateways use NAT to allow roaming clients to access the internet using the gateway's public IP address. The roaming clients cannot be reached by the LAN hosts—they are client-only and initiate all connections.
+
We won't cover all the details in this blog post, as we only focus on setting up the Mesh network in this blog post. Subsequent posts in this series will cover the other details.
Deciding on WireGuard
@@ -9846,9 +9873,36 @@ http://www.gnu.org/software/src-highlite -->
192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
+192.168.2.200 earth.wg0 earth.wg0.wan.buetow.org
+192.168.2.201 pixel7pro.wg0 pixel7pro.wg0.wan.buetow.org
END
+To enable roaming clients (like earth and pixel7pro) to access the internet through the VPN, we need to configure NAT on the OpenBSD gateways. This allows the roaming clients to use the gateway's public IP address for outbound traffic. We add the following to /etc/pf.conf on both blowfish and fishfinger:
+
+
+
# NAT for WireGuard clients to access internet
+match out on vio0 from 192.168.2.0/24 to any nat-to (vio0)
+
+# Allow inbound traffic on WireGuard interface
+pass in on wg0
+
+# Allow all UDP traffic on WireGuard port
+pass in inet proto udp from any to any port 56709
+
+
+The NAT rule translates outgoing traffic from the WireGuard network (192.168.2.0/24) to the gateway's public IP. The firewall rules permit WireGuard traffic on the wg0 interface and UDP port 56709. After updating /etc/pf.conf, reload the firewall:
+
+
+
blowfish$ doas pfctl -f /etc/pf.conf
+
+
WireGuard configuration
So far, we have only started WireGuard on all participating hosts without any useful configuration. This means that no VPN tunnel has been established yet between any of the hosts.
@@ -9921,7 +9975,41 @@ Endpoint = 46.23.94.99:56709
PersistentKeepalive = 25
-Whereas there are two main sections. One is [Interface], which configures the current host (here: f0):
+For roaming clients like pixel7pro (Android phone) or earth (Fedora laptop), the configuration looks different because they route all traffic through the VPN and only connect to the internet gateways:
+
+
+
+Note the key differences for roaming clients:
+
+
DNS is configured to use external DNS servers (Cloudflare and Google)
+
AllowedIPs = 0.0.0.0/0, ::/0 routes all traffic (IPv4 and IPv6) through the VPN
+
Only two peers are configured (the internet gateways), not the full mesh
+
PersistentKeepalive = 25 is used for both peers to maintain NAT traversal
+
+Whereas there are two main sections. One is [Interface], which configures the current host (here: f0 or pixel7pro):
Address: Local virtual IP address on the WireGuard interface.
@@ -9999,32 +10087,12 @@ hosts:
wg0:
domain: 'wg0.wan.buetow.org'
ip: '192.168.2.130'
- f1:
- os: FreeBSD
- ssh:
- user: paul
- conf_dir: /usr/local/etc/wireguard
- sudo_cmd: doas
- reload_cmd: service wireguard reload
- lan:
- domain: 'lan.buetow.org'
- ip: '192.168.1.131'
- wg0:
- domain: 'wg0.wan.buetow.org'
- ip: '192.168.2.131'
- f2:
- os: FreeBSD
- ssh:
- user: paul
- conf_dir: /usr/local/etc/wireguard
- sudo_cmd: doas
- reload_cmd: service wireguard reload
- lan:
- domain: 'lan.buetow.org'
- ip: '192.168.1.132'
- wg0:
- domain: 'wg0.wan.buetow.org'
- ip: '192.168.2.132'
+ exclude_peers:
+ - earth
+ - pixel7pro
+ # f1 and f2 similarly configured with exclude_peers for roaming clients
+ # (full config omitted for brevity)
+ ...
r0:
os: Linux
ssh:
@@ -10038,36 +10106,16 @@ hosts:
wg0:
domain: 'wg0.wan.buetow.org'
ip: '192.168.2.120'
- r1:
- os: Linux
- ssh:
- user: root
- conf_dir: /etc/wireguard
- sudo_cmd:
- reload_cmd: systemctl reload wg-quick@wg0.service
- lan:
- domain: 'lan.buetow.org'
- ip: '192.168.1.121'
- wg0:
- domain: 'wg0.wan.buetow.org'
- ip: '192.168.2.121'
- r2:
- os: Linux
- ssh:
- user: root
- conf_dir: /etc/wireguard
- sudo_cmd:
- reload_cmd: systemctl reload wg-quick@wg0.service
- lan:
- domain: 'lan.buetow.org'
- ip: '192.168.1.122'
- wg0:
- domain: 'wg0.wan.buetow.org'
- ip: '192.168.2.122'
+ exclude_peers:
+ - earth
+ - pixel7pro
+ # r1 and r2 similarly configured
+ ...
blowfish:
os: OpenBSD
ssh:
user: rex
+ port: 2
conf_dir: /etc/wireguard
sudo_cmd: doas
reload_cmd: sh /etc/netstart wg0
@@ -10077,10 +10125,14 @@ hosts:
wg0:
domain: 'wg0.wan.buetow.org'
ip: '192.168.2.110'
+ exclude_peers:
+ - earth
+ - pixel7pro
fishfinger:
os: OpenBSD
ssh:
user: rex
+ port: 2
conf_dir: /etc/wireguard
sudo_cmd: doas
reload_cmd: sh /etc/netstart wg0
@@ -10090,10 +10142,41 @@ hosts:
wg0:
domain: 'wg0.wan.buetow.org'
ip: '192.168.2.111'
+ exclude_peers:
+ - earth
+ - pixel7pro
+ earth:
+ os: Linux
+ wg0:
+ domain: 'wg0.wan.buetow.org'
+ ip: '192.168.2.200'
+ exclude_peers:
+ - f0
+ - f1
+ - f2
+ - r0
+ - r1
+ - r2
+ - pixel7pro
+ pixel7pro:
+ os: Android
+ wg0:
+ domain: 'wg0.wan.buetow.org'
+ ip: '192.168.2.201'
+ exclude_peers:
+ - f0
+ - f1
+ - f2
+ - r0
+ - r1
+ - r2
+ - earth
The file specifies details such as SSH user settings, configuration directories, sudo or reload commands, and IP/domain assignments for both internal LAN-facing interfaces and WireGuard (wg0) interfaces. Each host is assigned specific roles, including internal participants and publicly accessible nodes with internet-facing IPs, enabling the creation of a fully connected mesh VPN.
+Roaming clients: Note the earth and pixel7pro entries—these are configured differently from the infrastructure hosts. They have no lan or internet sections, which signals to the generator that they are roaming clients. The exclude_peers configuration ensures they only connect to the internet gateways (blowfish and fishfinger) and are not reachable by LAN hosts. The generator automatically configures these clients with AllowedIPs = 0.0.0.0/0, ::/0 to route all traffic through the VPN, includes DNS configuration (1.1.1.1, 8.8.8.8), and enables PersistentKeepalive for NAT traversal.
+
wireguardmeshgenerator.rb overview
The wireguardmeshgenerator.rb script consists of the following base classes:
@@ -10187,6 +10270,8 @@ Generating dist/r1/etc/wireguard/wg2/etc/wireguard/wg0.conf
Generating dist/blowfish/etc/wireguard/wg0.conf
Generating dist/fishfinger/etc/wireguard/wg0.conf
+Generating dist/earth/etc/wireguard/wg0.conf
+Generating dist/pixel7pro/etc/wireguard/wg0.conf
It generated all the wg0.conf files listed in the output, plus those keys:
@@ -10226,6 +10311,10 @@ keys/psk/fishfinger_r1.key
keys/psk/blowfish_r2.key
keys/psk/fishfinger_r2.key
keys/psk/blowfish_fishfinger.key
+keys/psk/blowfish_earth.key
+keys/psk/earth_fishfinger.key
+keys/psk/blowfish_pixel7pro.key
+keys/psk/fishfinger_pixel7pro.key
keys/f1/priv.key
keys/f1/pub.key
keys/f2/priv.key
@@ -10240,6 +10329,10 @@ keys/blowfish/priv.key
keys/blowfish/pub.key
keys/fishfinger/priv.key
keys/fishfinger/pub.key
+keys/earth/priv.key
+keys/earth/pub.key
+keys/pixel7pro/priv.key
+keys/pixel7pro/pub.key
Those keys are embedded in the resulting wg0.conf, so later, we only need to install the wg0.conf files and not all the keys individually.
@@ -10375,6 +10468,40 @@ http://www.gnu.org/software/src-highlite -->
That would also delete and re-generate all the keys involved.
+
Setting up roaming clients
+
+For roaming clients like earth (Fedora laptop) and pixel7pro (Android phone), the setup process differs slightly since these devices are not always accessible via SSH:
+
+Android phone (pixel7pro):
+
+The configuration is transferred to the phone using a QR code. The official WireGuard Android app (from Google Play Store) can scan and import the configuration:
+
+
+
+
+Scan the QR code with the WireGuard app to import the configuration. The phone will then route all traffic through the VPN when the tunnel is activated. Note that WireGuard does not support automatic failover between the two gateways (blowfish and fishfinger)—if one fails, manual disconnection and reconnection is required to switch to the other.
+
+Fedora laptop (earth):
+
+For the laptop, manually copy the generated configuration:
+
+
+
+
+The service is disabled from auto-start so the VPN is only active when manually started. This allows selective VPN usage based on need.
+
Happy WireGuard-ing
All is set up now. E.g. on f0:
@@ -10562,6 +10689,121 @@ peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
allowed ips: 192.168.2.131/32
+
Managing Roaming Client Tunnels
+
+Since roaming clients like earth and pixel7pro connect on-demand rather than being always-on like the infrastructure hosts, it's useful to know how to start and stop the WireGuard tunnels.
+
+
Starting and stopping on earth (Fedora laptop)
+
+On the Fedora laptop, WireGuard is managed via systemd. Starting the tunnel:
+
+
+
earth$ sudo systemctl start wg-quick@wg0.service
+earth$ sudo wg show
+interface: wg0
+ public key: Mc1CpSS3rbLN9A2w9c75XugQyXUkGPHKI2iCGbh8DRo=
+ private key: (hidden)
+ listening port: 56709
+ fwmark: 0xca6c
+
+peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
+ preshared key: (hidden)
+ endpoint: 46.23.94.99:56709
+ allowed ips: 0.0.0.0/0, ::/0
+ latest handshake: 5 seconds ago
+ transfer: 15.89 KiB received, 32.15 KiB sent
+ persistent keepalive: every 25 seconds
+
+peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
+ preshared key: (hidden)
+ endpoint: 23.88.35.144:56709
+ allowed ips: (none)
+ latest handshake: 5 seconds ago
+ transfer: 124 B received, 180 B sent
+ persistent keepalive: every 25 seconds
+
+
+Stoppint the tunnel:
+
+
+
earth$ sudo systemctl stop wg-quick@wg0.service
+earth$ sudo wg show
+# No output - WireGuard interface is down
+
+
+Checking the tunnel status:
+
+
+
earth$ sudo systemctl status wg-quick@wg0.service
+● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
+ Loaded: loaded (/usr/lib/systemd/system/wg-quick@.service; disabled)
+ Active: active (exited) since Sun 2026-01-11 22:45:00 EET
+
+
+The service remains disabled to prevent auto-start on boot, allowing manual control of when the VPN is active.
+
+
Starting and stopping on pixel7pro (Android phone)
+
+On Android using the official WireGuard app, tunnel management is like this:
+
+Starting the tunnel:
+
+
+
1. Open the WireGuard app
+
2. Tap the toggle switch next to the pixel7pro tunnel configuration
+
3. The switch turns blue/green and shows "Active"
+
4. A key icon appears in the notification bar indicating VPN is active
+
5. All traffic now routes through the VPN
+
+Stopping the tunnel:
+
+
+
1. Open the WireGuard app
+
2. Tap the toggle switch again to disable it
+
3. The switch turns gray and shows "Inactive"
+
4. The notification bar key icon disappears
+
5. Normal internet routing resumes
+
+Quick toggling from notification:
+
+
+
Pull down the notification shade
+
Tap the WireGuard notification to quickly enable/disable the tunnel without opening the app
+
+The WireGuard Android app supports automatically activating tunnels based on:
+
+
+
Mobile data connection (e.g., enable VPN when on cellular)
+
WiFi SSID (e.g., disable VPN when on trusted home network)
+
Ethernet connection status
+
+These settings can be configured by tapping the pencil icon next to the tunnel name, then scrolling to "Toggle on/off based on" options.
+
+
Verifying connectivity
+
+Once the tunnel is active on either device, verify connectivity:
+
+
+
# From earth laptop:
+earth$ ping -c2 blowfish.wg0
+earth$ ping -c2 fishfinger.wg0
+earth$ curl https://ifconfig.me # Should show gateway's public IP
+
+
+Check which gateway is active: The device will typically prefer one gateway (usually the first one with a successful handshake). To see which gateway is actively routing traffic, check the transfer statistics with sudo wg show on earth, or observe which gateway shows recent handshakes and increasing transfer bytes.
+
Conclusion
Having a mesh network on our hosts is great for securing all the traffic between them for our future k3s setup. A self-managed WireGuard mesh network is better than Tailscale as it eliminates reliance on a third party and provides full control over the configuration. It reduces unnecessary abstraction and "magic," enabling easier debugging and ensuring full ownership of our network.
diff --git a/gemfeed/f3s-kubernetes-with-freebsd-part-5/wireguard-full-mesh-with-roaming.svg b/gemfeed/f3s-kubernetes-with-freebsd-part-5/wireguard-full-mesh-with-roaming.svg
new file mode 100644
index 00000000..24c8ec9a
--- /dev/null
+++ b/gemfeed/f3s-kubernetes-with-freebsd-part-5/wireguard-full-mesh-with-roaming.svg
@@ -0,0 +1,2183 @@
+
+
+
diff --git a/gemfeed/f3s-kubernetes-with-freebsd-part-5/wireguard-full-mesh.svg b/gemfeed/f3s-kubernetes-with-freebsd-part-5/wireguard-full-mesh.svg
deleted file mode 100644
index f2f4f359..00000000
--- a/gemfeed/f3s-kubernetes-with-freebsd-part-5/wireguard-full-mesh.svg
+++ /dev/null
@@ -1,772 +0,0 @@
-
-
-
diff --git a/index.html b/index.html
index 1b0f84ef..d8a84f24 100644
--- a/index.html
+++ b/index.html
@@ -13,7 +13,7 @@
Hello!
-This site was generated at 2026-01-11T10:46:34+02:00 by Gemtexter
+This site was generated at 2026-01-11T22:40:26+02:00 by Gemtexter
-This site was last updated at 2026-01-11T10:46:34+02:00
+This site was last updated at 2026-01-11T22:40:26+02:00
The following stats were collected via uptimed on all of my personal computers over many years and the output was generated by guprecords, the global uptime records stats analyser of mine.