From 449d7e67d5d4954c2e33ec66cee22ed64c8f85c7 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Thu, 5 Feb 2026 17:44:57 +0200 Subject: Update content for html --- about/resources.html | 204 +++++++-------- ...5-10-02-f3s-kubernetes-with-freebsd-part-7.html | 275 ++++++++++++++++++++ gemfeed/atom.xml | 277 ++++++++++++++++++++- index.html | 2 +- uptime-stats.html | 2 +- 5 files changed, 655 insertions(+), 105 deletions(-) diff --git a/about/resources.html b/about/resources.html index 5af79f2c..12650683 100644 --- a/about/resources.html +++ b/about/resources.html @@ -50,112 +50,112 @@ In random order:


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:


Self-development and soft-skills books



In random order:


Here are notes of mine for some of the books

@@ -164,22 +164,22 @@ Some of these were in-person with exams; others were online learning lectures only. In random order:


Technical guides



@@ -198,20 +198,20 @@

Podcasts I liked



@@ -219,39 +219,39 @@

Newsletters I like



This is a mix of tech and non-tech newsletters I am subscribed to. In random order:


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:


Formal education



diff --git a/gemfeed/2025-10-02-f3s-kubernetes-with-freebsd-part-7.html b/gemfeed/2025-10-02-f3s-kubernetes-with-freebsd-part-7.html index 32a02d14..96ec0ef2 100644 --- a/gemfeed/2025-10-02-f3s-kubernetes-with-freebsd-part-7.html +++ b/gemfeed/2025-10-02-f3s-kubernetes-with-freebsd-part-7.html @@ -46,6 +46,7 @@
  • ⇢ ⇢ OpenBSD relayd configuration
  • ⇢ ⇢ Automatic failover when f3s cluster is down
  • ⇢ ⇢ OpenBSD httpd fallback configuration
  • +
  • Exposing services via LAN ingress
  • Deploying the private Docker image registry
  • ⇢ ⇢ Prepare the NFS-backed storage
  • ⇢ ⇢ Install (or upgrade) the chart
  • @@ -894,6 +895,280 @@ http://www.gnu.org/software/src-highlite -->
    This fallback mechanism has proven invaluable during maintenance windows and unexpected outages, ensuring that users always get a response even when the home lab is offline.

    +

    Exposing services via LAN ingress


    +
    +In addition to external access through the OpenBSD relays, services can also be exposed on the local network using LAN-specific ingresses. This is useful for accessing services from within the home network without going through the internet, reducing latency and providing an alternative path if the external relays are unavailable.
    +
    +The LAN ingress architecture leverages the existing FreeBSD CARP (Common Address Redundancy Protocol) failover infrastructure that's already in place for NFS-over-TLS (see Part 5). Instead of deploying MetalLB or another LoadBalancer implementation, we reuse the CARP virtual IP (192.168.1.138) by adding HTTP/HTTPS forwarding alongside the existing stunnel service on port 2323.
    +
    +*Architecture overview*:
    +
    +The LAN access path differs from external access:
    +
    +**External access (*.f3s.foo.zone):**
    +
    +Internet → OpenBSD relayd (TLS termination, Let's Encrypt)
    +        → WireGuard tunnel
    +        → k3s Traefik :80 (HTTP)
    +        → Service
    +
    +
    +**LAN access (*.f3s.lan.foo.zone):**
    +
    +LAN → FreeBSD CARP VIP (192.168.1.138)
    +    → FreeBSD relayd (TCP forwarding)
    +    → k3s Traefik :443 (TLS termination, cert-manager)
    +    → Service
    +
    +
    +The key architectural decisions:
    +
    +
    +*Installing cert-manager*:
    +
    +First, install cert-manager to handle certificate lifecycle management for LAN services. The installation is automated with a Justfile:
    +
    +codeberg.org/snonux/conf/f3s/cert-manager
    +
    + +
    $ cd conf/f3s/cert-manager
    +$ just install
    +kubectl apply -f cert-manager.yaml
    +# ... cert-manager CRDs and resources created ...
    +kubectl apply -f self-signed-issuer.yaml
    +clusterissuer.cert-manager.io/selfsigned-issuer created
    +clusterissuer.cert-manager.io/selfsigned-ca-issuer created
    +kubectl apply -f ca-certificate.yaml
    +certificate.cert-manager.io/selfsigned-ca created
    +kubectl apply -f wildcard-certificate.yaml
    +certificate.cert-manager.io/f3s-lan-wildcard created
    +
    +
    +This creates:
    +
    +
    +Verify the certificates:
    +
    + +
    $ kubectl get certificate -n cert-manager
    +NAME               READY   SECRET                 AGE
    +f3s-lan-wildcard   True    f3s-lan-tls            5m
    +selfsigned-ca      True    selfsigned-ca-secret   5m
    +
    +
    +The wildcard certificate (f3s-lan-tls) needs to be copied to any namespace that uses it:
    +
    + +
    $ kubectl get secret f3s-lan-tls -n cert-manager -o yaml | \
    +    sed 's/namespace: cert-manager/namespace: services/' | \
    +    kubectl apply -f -
    +
    +
    +*Configuring FreeBSD relayd for LAN access*:
    +
    +On both FreeBSD hosts (f0, f1), install and configure relayd for TCP forwarding:
    +
    + +
    paul@f0:~ % doas pkg install -y relayd
    +
    +
    +Create /usr/local/etc/relayd.conf:
    +
    +
    +# k3s nodes backend table
    +table <k3s_nodes> { 192.168.1.120 192.168.1.121 192.168.1.122 }
    +
    +# TCP forwarding to Traefik (no TLS termination)
    +relay "lan_http" {
    +    listen on 192.168.1.138 port 80
    +    forward to <k3s_nodes> port 80 check tcp
    +}
    +
    +relay "lan_https" {
    +    listen on 192.168.1.138 port 443
    +    forward to <k3s_nodes> port 443 check tcp
    +}
    +
    +
    +Note: The IP addresses 192.168.1.120-122 are the LAN IPs of the k3s nodes (r0, r1, r2), not their WireGuard IPs. FreeBSD relayd requires PF (Packet Filter) to be enabled. Create a minimal /etc/pf.conf:
    +
    +
    +# Basic PF rules for relayd
    +set skip on lo0
    +pass in quick
    +pass out quick
    +
    +
    +Enable PF and relayd:
    +
    + +
    paul@f0:~ % doas sysrc pf_enable=YES pflog_enable=YES relayd_enable=YES
    +paul@f0:~ % doas service pf start
    +paul@f0:~ % doas service pflog start
    +paul@f0:~ % doas service relayd start
    +
    +
    +Verify relayd is listening on the CARP VIP:
    +
    + +
    paul@f0:~ % doas sockstat -4 -l | grep 192.168.1.138
    +_relayd  relayd   2903  11  tcp4   192.168.1.138:80      *:*
    +_relayd  relayd   2903  12  tcp4   192.168.1.138:443     *:*
    +
    +
    +Repeat the same configuration on f1. Both hosts will run relayd listening on the CARP VIP, but only the CARP MASTER will respond to traffic. When failover occurs, the new MASTER takes over seamlessly.
    +
    +*Adding LAN ingress to services*:
    +
    +To expose a service on the LAN, add a second Ingress resource to its Helm chart. Here's an example for Navidrome:
    +
    +
    +---
    +# LAN Ingress for navidrome.f3s.lan.foo.zone
    +apiVersion: networking.k8s.io/v1
    +kind: Ingress
    +metadata:
    +  name: navidrome-ingress-lan
    +  namespace: services
    +  annotations:
    +    spec.ingressClassName: traefik
    +    traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
    +spec:
    +  tls:
    +    - hosts:
    +        - navidrome.f3s.lan.foo.zone
    +      secretName: f3s-lan-tls
    +  rules:
    +    - host: navidrome.f3s.lan.foo.zone
    +      http:
    +        paths:
    +          - path: /
    +            pathType: Prefix
    +            backend:
    +              service:
    +                name: navidrome-service
    +                port:
    +                  number: 4533
    +
    +
    +Key points:
    +
    +
    +Apply the ingress and test:
    +
    + +
    $ kubectl apply -f navidrome-ingress-lan.yaml
    +ingress.networking.k8s.io/navidrome-ingress-lan created
    +
    +$ curl -k https://navidrome.f3s.lan.foo.zone
    +HTTP/2 302 
    +location: /app/
    +
    +
    +*Client-side DNS and CA setup*:
    +
    +To access LAN services, clients need DNS entries and must trust the self-signed CA.
    +
    +Add DNS entries to /etc/hosts on your laptop:
    +
    + +
    $ sudo tee -a /etc/hosts << 'EOF'
    +# f3s LAN services
    +192.168.1.138  navidrome.f3s.lan.foo.zone
    +EOF
    +
    +
    +The CARP VIP 192.168.1.138 provides high availability—traffic automatically fails over to the backup host if the master goes down.
    +
    +Export the self-signed CA certificate:
    +
    + +
    $ kubectl get secret selfsigned-ca-secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | \
    +    base64 -d > f3s-lan-ca.crt
    +
    +
    +Install the CA certificate on Linux (Fedora/Rocky):
    +
    + +
    $ sudo cp f3s-lan-ca.crt /etc/pki/ca-trust/source/anchors/
    +$ sudo update-ca-trust
    +
    +
    +After trusting the CA, browsers will accept the LAN certificates without warnings.
    +
    +*Scaling to other services*:
    +
    +The same pattern can be applied to any service. To add LAN access:
    +
    +1. Copy the f3s-lan-tls secret to the service's namespace (if not already there)
    +2. Add a LAN Ingress resource using the pattern above
    +3. Configure DNS: 192.168.1.138 service.f3s.lan.foo.zone
    +4. Commit and push (ArgoCD will deploy automatically)
    +
    +No changes needed to:
    +
    +
    +*TLS offloaders summary*:
    +
    +The f3s infrastructure now has three distinct TLS offloaders:
    +
    +
    +Each serves a different purpose with appropriate certificate management for its use case.
    +

    Deploying the private Docker image registry



    As not all Docker images I want to deploy are available on public Docker registries and as I also build some of them by myself, there is the need of a private registry.
    diff --git a/gemfeed/atom.xml b/gemfeed/atom.xml index 72abde8f..ef6b6975 100644 --- a/gemfeed/atom.xml +++ b/gemfeed/atom.xml @@ -1,6 +1,6 @@ - 2026-02-05T17:38:26+02:00 + 2026-02-05T17:44:05+02:00 foo.zone feed To be in the .zone! @@ -4675,6 +4675,7 @@ p hash.values_at(:a, :c)
  • ⇢ ⇢ OpenBSD relayd configuration
  • ⇢ ⇢ Automatic failover when f3s cluster is down
  • ⇢ ⇢ OpenBSD httpd fallback configuration
  • +
  • Exposing services via LAN ingress
  • Deploying the private Docker image registry
  • ⇢ ⇢ Prepare the NFS-backed storage
  • ⇢ ⇢ Install (or upgrade) the chart
  • @@ -5523,6 +5524,280 @@ http://www.gnu.org/software/src-highlite -->
    This fallback mechanism has proven invaluable during maintenance windows and unexpected outages, ensuring that users always get a response even when the home lab is offline.

    +

    Exposing services via LAN ingress


    +
    +In addition to external access through the OpenBSD relays, services can also be exposed on the local network using LAN-specific ingresses. This is useful for accessing services from within the home network without going through the internet, reducing latency and providing an alternative path if the external relays are unavailable.
    +
    +The LAN ingress architecture leverages the existing FreeBSD CARP (Common Address Redundancy Protocol) failover infrastructure that's already in place for NFS-over-TLS (see Part 5). Instead of deploying MetalLB or another LoadBalancer implementation, we reuse the CARP virtual IP (192.168.1.138) by adding HTTP/HTTPS forwarding alongside the existing stunnel service on port 2323.
    +
    +*Architecture overview*:
    +
    +The LAN access path differs from external access:
    +
    +**External access (*.f3s.foo.zone):**
    +
    +Internet → OpenBSD relayd (TLS termination, Let's Encrypt)
    +        → WireGuard tunnel
    +        → k3s Traefik :80 (HTTP)
    +        → Service
    +
    +
    +**LAN access (*.f3s.lan.foo.zone):**
    +
    +LAN → FreeBSD CARP VIP (192.168.1.138)
    +    → FreeBSD relayd (TCP forwarding)
    +    → k3s Traefik :443 (TLS termination, cert-manager)
    +    → Service
    +
    +
    +The key architectural decisions:
    +
    +
    +*Installing cert-manager*:
    +
    +First, install cert-manager to handle certificate lifecycle management for LAN services. The installation is automated with a Justfile:
    +
    +codeberg.org/snonux/conf/f3s/cert-manager
    +
    + +
    $ cd conf/f3s/cert-manager
    +$ just install
    +kubectl apply -f cert-manager.yaml
    +# ... cert-manager CRDs and resources created ...
    +kubectl apply -f self-signed-issuer.yaml
    +clusterissuer.cert-manager.io/selfsigned-issuer created
    +clusterissuer.cert-manager.io/selfsigned-ca-issuer created
    +kubectl apply -f ca-certificate.yaml
    +certificate.cert-manager.io/selfsigned-ca created
    +kubectl apply -f wildcard-certificate.yaml
    +certificate.cert-manager.io/f3s-lan-wildcard created
    +
    +
    +This creates:
    +
    +
    +Verify the certificates:
    +
    + +
    $ kubectl get certificate -n cert-manager
    +NAME               READY   SECRET                 AGE
    +f3s-lan-wildcard   True    f3s-lan-tls            5m
    +selfsigned-ca      True    selfsigned-ca-secret   5m
    +
    +
    +The wildcard certificate (f3s-lan-tls) needs to be copied to any namespace that uses it:
    +
    + +
    $ kubectl get secret f3s-lan-tls -n cert-manager -o yaml | \
    +    sed 's/namespace: cert-manager/namespace: services/' | \
    +    kubectl apply -f -
    +
    +
    +*Configuring FreeBSD relayd for LAN access*:
    +
    +On both FreeBSD hosts (f0, f1), install and configure relayd for TCP forwarding:
    +
    + +
    paul@f0:~ % doas pkg install -y relayd
    +
    +
    +Create /usr/local/etc/relayd.conf:
    +
    +
    +# k3s nodes backend table
    +table <k3s_nodes> { 192.168.1.120 192.168.1.121 192.168.1.122 }
    +
    +# TCP forwarding to Traefik (no TLS termination)
    +relay "lan_http" {
    +    listen on 192.168.1.138 port 80
    +    forward to <k3s_nodes> port 80 check tcp
    +}
    +
    +relay "lan_https" {
    +    listen on 192.168.1.138 port 443
    +    forward to <k3s_nodes> port 443 check tcp
    +}
    +
    +
    +Note: The IP addresses 192.168.1.120-122 are the LAN IPs of the k3s nodes (r0, r1, r2), not their WireGuard IPs. FreeBSD relayd requires PF (Packet Filter) to be enabled. Create a minimal /etc/pf.conf:
    +
    +
    +# Basic PF rules for relayd
    +set skip on lo0
    +pass in quick
    +pass out quick
    +
    +
    +Enable PF and relayd:
    +
    + +
    paul@f0:~ % doas sysrc pf_enable=YES pflog_enable=YES relayd_enable=YES
    +paul@f0:~ % doas service pf start
    +paul@f0:~ % doas service pflog start
    +paul@f0:~ % doas service relayd start
    +
    +
    +Verify relayd is listening on the CARP VIP:
    +
    + +
    paul@f0:~ % doas sockstat -4 -l | grep 192.168.1.138
    +_relayd  relayd   2903  11  tcp4   192.168.1.138:80      *:*
    +_relayd  relayd   2903  12  tcp4   192.168.1.138:443     *:*
    +
    +
    +Repeat the same configuration on f1. Both hosts will run relayd listening on the CARP VIP, but only the CARP MASTER will respond to traffic. When failover occurs, the new MASTER takes over seamlessly.
    +
    +*Adding LAN ingress to services*:
    +
    +To expose a service on the LAN, add a second Ingress resource to its Helm chart. Here's an example for Navidrome:
    +
    +
    +---
    +# LAN Ingress for navidrome.f3s.lan.foo.zone
    +apiVersion: networking.k8s.io/v1
    +kind: Ingress
    +metadata:
    +  name: navidrome-ingress-lan
    +  namespace: services
    +  annotations:
    +    spec.ingressClassName: traefik
    +    traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
    +spec:
    +  tls:
    +    - hosts:
    +        - navidrome.f3s.lan.foo.zone
    +      secretName: f3s-lan-tls
    +  rules:
    +    - host: navidrome.f3s.lan.foo.zone
    +      http:
    +        paths:
    +          - path: /
    +            pathType: Prefix
    +            backend:
    +              service:
    +                name: navidrome-service
    +                port:
    +                  number: 4533
    +
    +
    +Key points:
    +
    +
    +Apply the ingress and test:
    +
    + +
    $ kubectl apply -f navidrome-ingress-lan.yaml
    +ingress.networking.k8s.io/navidrome-ingress-lan created
    +
    +$ curl -k https://navidrome.f3s.lan.foo.zone
    +HTTP/2 302 
    +location: /app/
    +
    +
    +*Client-side DNS and CA setup*:
    +
    +To access LAN services, clients need DNS entries and must trust the self-signed CA.
    +
    +Add DNS entries to /etc/hosts on your laptop:
    +
    + +
    $ sudo tee -a /etc/hosts << 'EOF'
    +# f3s LAN services
    +192.168.1.138  navidrome.f3s.lan.foo.zone
    +EOF
    +
    +
    +The CARP VIP 192.168.1.138 provides high availability—traffic automatically fails over to the backup host if the master goes down.
    +
    +Export the self-signed CA certificate:
    +
    + +
    $ kubectl get secret selfsigned-ca-secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | \
    +    base64 -d > f3s-lan-ca.crt
    +
    +
    +Install the CA certificate on Linux (Fedora/Rocky):
    +
    + +
    $ sudo cp f3s-lan-ca.crt /etc/pki/ca-trust/source/anchors/
    +$ sudo update-ca-trust
    +
    +
    +After trusting the CA, browsers will accept the LAN certificates without warnings.
    +
    +*Scaling to other services*:
    +
    +The same pattern can be applied to any service. To add LAN access:
    +
    +1. Copy the f3s-lan-tls secret to the service's namespace (if not already there)
    +2. Add a LAN Ingress resource using the pattern above
    +3. Configure DNS: 192.168.1.138 service.f3s.lan.foo.zone
    +4. Commit and push (ArgoCD will deploy automatically)
    +
    +No changes needed to:
    +
    +
    +*TLS offloaders summary*:
    +
    +The f3s infrastructure now has three distinct TLS offloaders:
    +
    +
    +Each serves a different purpose with appropriate certificate management for its use case.
    +

    Deploying the private Docker image registry



    As not all Docker images I want to deploy are available on public Docker registries and as I also build some of them by myself, there is the need of a private registry.
    diff --git a/index.html b/index.html index 776d3d39..cee9696a 100644 --- a/index.html +++ b/index.html @@ -13,7 +13,7 @@

    Hello!



    -This site was generated at 2026-02-05T17:38:26+02:00 by Gemtexter
    +This site was generated at 2026-02-05T17:44:05+02:00 by Gemtexter

    Welcome to the foo.zone!

    diff --git a/uptime-stats.html b/uptime-stats.html index d6de3fb6..4d2cbb0b 100644 --- a/uptime-stats.html +++ b/uptime-stats.html @@ -13,7 +13,7 @@

    My machine uptime stats



    -This site was last updated at 2026-02-05T17:38:26+02:00
    +This site was last updated at 2026-02-05T17:44:05+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.

    -- cgit v1.2.3