I've leveled up my home network and it means only one thing: a new cringe-worthy WiFi name.
Moving on from "Make WiFi Great Again"... the new SSID is:
"It Hurts when IP"
Send me your best/worst tech puns, I need more! 👇
I've leveled up my home network and it means only one thing: a new cringe-worthy WiFi name.
Moving on from "Make WiFi Great Again"... the new SSID is:
"It Hurts when IP"
Send me your best/worst tech puns, I need more! 👇
This morning, I took my wife to the hospital for routine blood tests that had been scheduled for some time. Everything was going smoothly: check-in, number, waiting room. Suddenly, everything came to a halt and shut down. I was connected to the hospital’s public Wi-Fi and noticed that my connection also went down.
Having managed a couple of similar facilities, I immediately understood what had happened. I saw the staff panicking and calling the technicians, but they quickly reorganized within 10 minutes. They managed to process everyone who already had a number and then proceeded with the others in the order of their arrival. Despite the ten-minute delay (even though people started complaining right away), they were extremely efficient.
I later confirmed that the entire booking, check-in, and queue system is “in the cloud.” The hospital experienced a connectivity interruption, and all related services stopped. The staff no longer had access to anything, so a technician sent the lists to a manager via another channel, and everything resumed manually.
For years, I’ve insisted that certain things MUST be local. The healthcare facilities I manage have all the necessary systems for the operation of the facility internally, including patient records. External services like websites, emails, etc., are secondary.
Everything essential must always be accessible locally and, in special cases, it should be possible to physically access the servers and connect directly to them, bypassing any network/switch failures.
There has been only one interruption in the past, due to human error. Today, we have redundant servers (not HA on virtualizers, but two machines running the same software with replicated databases - on separate power lines) so such an issue shouldn’t happen anymore.
Not everything can be anticipated, but history is a great teacher. The Internet connection will eventually be interrupted :-)
When it comes to the health and survival of people, there are no compromises.
#IT #Internet #Networking #Outage #Health #HA #Cloud #CloudComputing #OwnYourData
Sometimes surprises come when you least expect them. A few months ago, I helped an acquaintance install a #MikroTik router at his house. He is very happy with it; it does excellent load balancing and failover over 4G.
A little while ago, he sent me a message about how "Back to Home" helped him bypass the limited connection at the hotel he is currently in.
I hadn't tried it yet, so I did a couple of tests.
It's really practical and quick to set up. Well done, MikroTik! @mikrotik
One day, we will read about the heroic efforts Palestinian networking engineers did throughout experiencing genocide to keep the network routers on, the cables connected, and getting the signal out there.
Actual war stories on a hope that we hear them asking is anyone out there who will help them. #Networking #Palestine #Genocide #DevOps
OSPF area types.
Backbone
Stub
Totally stubby
Not so stubby
Totally not so stubby (yes, it really is a thing).
My proposed OSPF areas.
Not so backbone
Thighbone
Lovebone
So-so stubby
Not so so-so stubby
totally not so totally stubby
tubular
totally tubular
not so tubular
totally not so tubular and stubby
A continuation of the same idea
I had already explored the same problem with snac and nginx in two previous posts: Improving snac Performance with Nginx Proxy Cache (https://it-notes.dragas.net/2025/01/29/improving-snac-performance-with-nginx-proxy-cache/) and Caching snac Proxied Media with Nginx (https://it-notes.dragas.net/2025/02/08/caching-snac-proxied-media-with-nginx/). In both cases, the idea was that the reverse proxy should absorb repeated public requests instead of letting them consume snac resources.Why there is almost no media
Before talking about HAProxy, it is worth mentioning one of the most important optimizations, which is not in the proxy configuration at all.The homepage is static because it can be static
The main homepage follows the same logic.Many countries, one entry point
FediMeteo is made of many country instances. Each one runs in its own jail and listens on its own internal address and port. From the outside, however, they all live under the same domain structure:fedimeteo.comAnd many more.
www.fedimeteo.com
it.fedimeteo.com
uk.fedimeteo.com
jp.fedimeteo.com
us.fedimeteo.com
usa.fedimeteo.com
can.fedimeteo.com
canada.fedimeteo.com
fedimeteo.com backend_fedimeteoThe frontend then needs only one rule:
www.fedimeteo.com backend_fedimeteo
it.fedimeteo.com backend_it
uk.fedimeteo.com backend_uk
jp.fedimeteo.com backend_jp
us.fedimeteo.com backend_us
usa.fedimeteo.com backend_us
can.fedimeteo.com backend_ca
canada.fedimeteo.com backend_ca
use_backend %[req.hdr(host),field(1,:),lower,map(/usr/local/etc/fedimeteo.map,backend_fedimeteo)]This reads the
Host header, removes the port if present, lowercases the result, and looks it up in /usr/local/etc/fedimeteo.map. If nothing matches, it falls back to the main FediMeteo backend.Backends as small compartments
The country backends are deliberately plain:backend backend_itOne backend, one jail, one snac instance. This is exactly the same organizational principle as the rest of the project. If I need to reason about Italy, I look at the Italian jail. If I need to reason about the United Kingdom, I look at the UK jail. If one day I need to move a country elsewhere, the separation is already there.
mode http
http-reuse safe
server srv1 10.0.0.2:8001 maxconn 30
backend backend_uk
mode http
http-reuse safe
server srv1 10.0.0.7:8001 maxconn 30
backend backend_jp
mode http
http-reuse safe
server srv1 10.0.0.32:8001 maxconn 30
maxconn 30 value is not a magic number. It is a ceiling. I want each small backend to have a visible limit in front of it. If something starts hammering a country instance, I prefer the pressure to appear at the HAProxy layer instead of becoming unlimited concurrent work inside snac.http-reuse safe lets HAProxy reuse backend connections where appropriate. This is another small reduction in unnecessary work. Opening connections repeatedly is not the biggest problem in the world, but avoiding it is still better, especially when many small services sit behind the same proxy.The front door
The HTTPS frontend listens on IPv4 and IPv6 and offers both HTTP/2 and HTTP/1.1:frontend https_inTLS defaults are set globally:
bind :::443 v4v6 ssl crt /usr/local/etc/certs/ alpn h2,http/1.1
mode http
option http-keep-alive
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256Port 80 only redirects to HTTPS, except for Let's Encrypt challenges:
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
acl letsencrypt-acl path_beg /.well-known/acme-challenge/In the HTTPS frontend I also set the usual forwarding headers:
http-request redirect scheme https code 301 unless letsencrypt-acl
use_backend letsencrypt-backend if letsencrypt-acl
http-request set-header X-Real-IP %[src]And I add HSTS:
http-request set-header X-Forwarded-Proto https
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"None of this is unusual, and that is fine. The interesting parts of an infrastructure are not always the parts that should be unusual.
Two caches, because the requests are different
The HAProxy configuration defines two caches:cache mediacacheI keep media and ActivityPub JSON separate because they are not the same kind of traffic.
total-max-size 128
max-object-size 10000000
max-age 3600
process-vary on
max-secondary-entries 12
cache jsoncache
total-max-size 16
max-object-size 1000000
max-age 60
process-vary on
max-secondary-entries 12
Recognizing media
For media, the ACL is based on file extensions:acl is_media path_end -i .jpg .jpeg .png .gif .webp .svg .ico .mp4 .webm .mp3 .ogg .wav .flac .mov .avi .mkv .m4vThen I store the result in a transaction variable:
http-request set-var(txn.is_media) bool(true) if is_mediaThe cache lookup is straightforward:
http-request cache-use mediacache if { var(txn.is_media) -m bool true }
And on the response side:http-response set-header Cache-Control "max-age=3600, public" if { var(txn.is_media) -m bool true }
http-response del-header Set-Cookie if { var(txn.is_media) -m bool true }
http-response del-header Vary if { var(txn.is_media) -m bool true }
http-response cache-store mediacache if { var(txn.is_media) -m bool true }
The Cache-Control header makes the intent explicit. Set-Cookie is removed because a public media object should not carry session information. Vary is removed because I do not want the same avatar to fragment into many cache entries because of harmless header differences.http-request del-header Authorization if { var(txn.is_media) -m bool true }
http-request del-header Cookie if { var(txn.is_media) -m bool true }
I would not do this globally. I do it after deciding that the request is media. Scope is what makes these rules safe.ActivityPub JSON microcaching
The ActivityPub side starts from theAccept header:acl is_ap_json req.hdr(Accept),lower -m sub application/activity+jsonThis part matters because ActivityPub uses content negotiation. The same path may return HTML to a browser and JSON to a remote instance. If the proxy pretends that a URL is always one thing, it will eventually cache the wrong representation.
acl is_ap_ldjson req.hdr(Accept),lower -m sub application/ld+json
acl is_outbox path_end /outbox
acl is_get method GET
acl has_auth req.hdr(Authorization) -m found
acl has_cookie req.hdr(Cookie) -m found
http-request set-var(txn.is_activitypub) bool(true) if is_get !is_outbox is_ap_json !has_auth !has_cookieThere are several decisions here, all important.
http-request set-var(txn.is_activitypub) bool(true) if is_get !is_outbox is_ap_ldjson !has_auth !has_cookie
GET, because I am not caching deliveries or anything that changes state. It must not be /outbox, because outbox collections are not the traffic I want to cache here. It must not have Authorization, and it must not have cookies, because authenticated or user-specific requests do not belong in a shared public cache.http-request cache-use jsoncache if { var(txn.is_activitypub) -m bool true }
http-response set-header Cache-Control "max-age=60, public" if { var(txn.is_activitypub) -m bool true }
http-response cache-store jsoncache if { var(txn.is_activitypub) -m bool true }
Sixty seconds is short, but useful. Federation often creates small clusters of identical requests. A remote server fetches an actor, another fetches the same actor, something asks for the same object, something retries. I do not need to cache these responses for hours. I only need HAProxy to answer the second and third identical request during the same small burst.Static media paths
There is also a rule for static paths:acl is_short_path path_reg ^/[^/]+/s/This comes from the same observation that led me to cache snac media with nginx. snac uses static media paths, and those paths often represent the kind of public, repeatable traffic that should not consume backend threads if the proxy can serve it. I call them "short", not because they are, but because the first time I saw them, I thought the 's' stood for "short", not "static". The name just stuck.
http-request cache-use mediacache if is_short_path
Vary, but not without limits
process-vary onI want HAProxy to process
max-secondary-entries 12
Vary, because content negotiation is real, especially when ActivityPub is involved. But I also want variation to be bounded. If every slightly different header creates another cache entry, the cache becomes a complicated way to miss.Vary before storing the response. A shared avatar does not need to vary by Accept. For ActivityPub JSON, I am more careful because the representation matters.Seeing whether it works
During rollout, I like to expose a very small diagnostic header:http-response set-header X-Cache-Status HIT if !{ srv_id -m found }
http-response set-header X-Cache-Status MISS if { srv_id -m found }
This is intentionally simple. If HAProxy selected a backend server, I call it a miss. If no backend server was selected, the response came from cache, so I call it a hit. It is not a complete observability system, but it is enough to answer the first question I usually have after changing a cache rule.curl -I https://it.fedimeteo.com/path/to/avatar.pngThe second request should be a hit.
curl -I https://it.fedimeteo.com/path/to/avatar.png
Accept header:curl -I \And I also want to verify that cookies and authorization prevent public caching:
-H 'Accept: application/activity+json' \
https://it.fedimeteo.com/some/activitypub/object
curl -I \A cache that works should be visible. A cache that is invisible can be correct, but it can also be silently wrong. I prefer to know.
-H 'Cookie: test=value' \
-H 'Accept: application/activity+json' \
https://it.fedimeteo.com/some/activitypub/object
curl -I \
-H 'Authorization: Bearer fake' \
-H 'Accept: application/activity+json' \
https://it.fedimeteo.com/some/activitypub/object
Compression and operational paths
HAProxy also handles gzip compression:filter compressionThis keeps another common responsibility at the edge. The country instances can stay focused on snac and the forecast data, while HAProxy deals with client-facing compression for HTML, JSON, and ActivityPub responses.
compression algo gzip
compression type text/css text/html text/javascript application/javascript text/plain text/xml application/json application/activity+json
frontend prometheusAnd I keep internal operational paths, such as statistics and Grafana, handled before the hostname map. These are small details, but ordering matters. Special paths should be explicit and early. The hostname map is for FediMeteo routing, not for every internal tool I happen to expose behind the same proxy.
bind 127.0.0.1:8405
mode http
http-request use-service prometheus-exporter
no log
What this changes in practice
The nice thing about this configuration is that none of its parts is particularly surprising.Caveats
This configuration is not a universal HAProxy recipe for ActivityPub services.Conclusion
FediMeteo started as a small idea and became larger than I expected, but I still want it to feel small in the right ways. Small does not mean fragile. Small means understandable. It means that each part has a reason to exist, and that unnecessary work is removed before it becomes a problem.As a female professional, I am passionate about fostering deep, meaningful connections and pursuing collaborative synergies with other women in my field. 🏳️🌈✨ #Networking #WomenInLeadership #AuthenticConnections
curl libcurl
Just in case you have forgotten how to curl a file from a server here's a extensive howto with screenshots
`-L` redirect
https://everything.curl.dev/http/browserlike.html?highlight=-L#redirects
`-o` filename
https://everything.curl.dev/usingcurl/downloads/url-named.html#download-to-a-file-named-by-the-url
`-C -` resume
https://everything.curl.dev/usingcurl/downloads/resume.html#resuming-and-ranges
`curl --verbose -C - -L -o lp_someband_some_name_disc1side2.flac archive.org/download/lp_someband_somename-v/disc1/lp_someband_somename_disc1side2.flac`
#curl #get #programming #technology #fetch #networking #https #http #ftp #OpenSource #POSIX #BSD #freeBSD #ghostBSD #openBSD #Linux #win64 #mac
So it seems #LoRa is a proprietary standard. @meshtastic @meshcore @reticulum - don't we have an open drop-in alternative yet? #Zmesh?
How can we really build a resilient ecosystem for the people, when the core technology is owned by a single company?
That's like if all TCP/IP hardware was on a license from IBM.
Especially in the times of rising political tensions this looks like a bad idea.
Am I just missing something?
Source: https://aernetworks.com/blog/the-problem-with-lora-being-patented/
My latest blog post: Keeping it old school, Unix style, with inetd services!
https://mikecoats.com/simple-inetd-services/
How to build quick and dirty network services, the Unixy, way with the venerable inetd approach.
Hey people,
I recently graduated from my #SysAdmin apprenticeship and I am looking for an entry position in the field of #Linux/ #Networking Administration/Engineering or #DevOps in #NRW, #Germany (ideally around #Düsseldorf), or Remote.
As part of the apprenticeship I conducted an internship at a Neuroscience Institute of Research Centre Juelich, where I accomplished my project of automating #OpenBSD routers using #pyinfra #GitOps.
1/2
Boosts appreciated 🙏🏻
#degoogle #linux #storage #networking #cloud #homelab #privacy
Layered schematic view of the project I'm working on for my private own cloud. Just to visualize it and for other people to see.
I'm currently working at the syncthing layer. But progress is smooth.
iptables imply the existence of ipchairs and other ipfurnitures.
You can get them at ipkea.
https://www.europesays.com/3275335/ Latina Women’s Conference brings entrepreneurs together in Fresno #19867287 #business #Entrepreneurship #Fresno #HispanicChamberOfCommerce #LatinaEntrepreneurs #LatinaWomen'sConference #Networking #SmallBusiness #timely #WomenInBusiness #WomenEmpowerment