diff --git a/.gitignore b/.gitignore index d4ba081..f18cdab 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ _gen # downloaded by nix -themes +themes/poison diff --git a/layouts/.gitkeep b/content/posts/_index.md similarity index 100% rename from layouts/.gitkeep rename to content/posts/_index.md diff --git a/content/posts/keeping-scrapers-out/chat-screenshot.png b/content/posts/keeping-scrapers-out/chat-screenshot.png deleted file mode 100644 index 7b81668..0000000 Binary files a/content/posts/keeping-scrapers-out/chat-screenshot.png and /dev/null differ diff --git a/content/posts/keeping-scrapers-out/index.md b/content/posts/keeping-scrapers-out/index.md deleted file mode 100644 index a545015..0000000 --- a/content/posts/keeping-scrapers-out/index.md +++ /dev/null @@ -1,228 +0,0 @@ -+++ -date = '2025-09-15T20:00:00+02:00' -title = 'Keeping scrapers out' -tags = ['nix', 'nginx', 'anubis'] -+++ - -After reading an [LWN article on high AI scraper traffic](https://lwn.net/Articles/1008897/), I also wanted to do something to "protect" the blog. -I do not see any continuous load peaks, but I dislike the idea of giant corporations profiting off of my writing without any negotiation. - -One solution that stands out currently is [anubis](https://anubis.techaro.lol/). -It tries to challenge requests in a way that is hard or resource intensive for scrapers at scale, but easy and resource-light for normal users. - -I could not find a good summary on how to proxy an nginx virtual host through anubis, so here we go. - - - -### Starting configuration - -The following examples are based on the configuration of this blog. -Most things not relevant here are removed, but you can take a look at the [original](https://git.berlin.ccc.de/vinzenz/nixos-configuration/src/commit/5f5c7267dc8c734eca2de87b5c0168523c9fa3b3/hosts/hetzner-vpn2/nginx.nix). - -```nix -{ pkgs, ... }: -{ - services.nginx = { - enable = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - recommendedGzipSettings = true; - recommendedOptimisation = true; - - virtualHosts = { - "zerforschen.plus" = { - addSSL = true; - enableACME = true; - root = pkgs.zerforschen-plus-content; - }; - }; - }; -} -``` - -### Hide real host - -The first thing to do is hiding the real website. -Otherwise, a scraper can just use whatever we rename it to. - -I wanted to forward everything through unix domain socket. -The kind I'll use behave like a file, which means we do not have to make sure that e.g. the application only listens on localhost. -It also makes permission management trivial, but we'll see that later. - -```nix -{ pkgs, ... }: -let - # /run/nginx already exists - blog-domain-socket = "/run/nginx/blog.sock"; -in -{ - services.nginx = { - enable = true; - virtualHosts = { - "zerforschen.plus" = { - addSSL = true; - enableACME = true; - # we do not have anything hosted here anymore - }; - # a new virtual host contains the site now - "blog-in-anubis" = { - root = pkgs.zerforschen-plus-content; - # specifying any listen overrides the defaults - listen = [ - { - # this makes nginx create the unix domain socket - addr = "unix:" + blog-domain-socket; - } - ]; - }; - }; - }; -} -``` - -### Create anubis instance - -Next, we need an anubis service that forwards to the socket created by nginx. - -```nix -{ pkgs, ... }: -let - blog-domain-socket = "/run/nginx/blog.sock"; -in -{ - services = { - # previous nginx config - - anubis.instances.main = { - enable = true; - settings = { - TARGET = "unix://" + blog-domain-socket; - }; - }; - }; -} -``` - -### Forward public host to anubis - -Now we have an anubis instance running, but no way to access it from outside. - -I did not want to expose anubis to the public internet directly, so I configured another unix domain socket for this purpose. - -```nix -{ pkgs, ... }: -let - blog-domain-socket = "/run/nginx/blog.sock"; - anubis-domain-socket = "/run/anubis/anubis-blog.sock"; -in -{ - services = { - nginx = { - enable = true; - virtualHosts = { - "zerforschen.plus" = { - addSSL = true; - enableACME = true; - locations."/" = { - # HTTP over unix domain socket - proxyPass = "http://unix:" + anubis-domain-socket; - }; - }; - # "blog-in-anubis" = { ... }; - }; - }; - - anubis.instances.main = { - enable = true; - settings = { - # this makes anubis create and listen to the socket - BIND = anubis-domain-socket; - TARGET = "unix://" + blog-domain-socket; - }; - }; - }; -} - -``` - -### Socket permissions - -The config is nearly complete now. -Applying the configuration now produces permission errors when trying to access the site, because the sockets are owned by the service user and grou with a 660 permission. -In my case, I simply added the services to each others groups. -If this was a server I was making my living with, I'd probably create a new group and folder and add both services to that one. - -```nix -{ pkgs, ... }: -{ - systemd.services = { - nginx.serviceConfig.SupplementaryGroups = [ "anubis" ]; - anubis-main.serviceConfig.SupplementaryGroups = [ "nginx" ]; - }; -} -``` - -### Final configuration - -Overall, I think NixOS makes the configuration required easy to read and write. -The [NixOS options search](https://search.nixos.org/options) is a great storage of knowledge for any software configurable through the NixOS configuration. -If the [default policy](https://github.com/TecharoHQ/anubis/blob/f745d37d9006c3431bf3d435c61565250ab53a3e/data/botPolicies.yaml) does not fit your needs, that would be another step required[^1]. - -Update: Asking ChatGPT about this article indicates everything is working as intended: - - -My [final configuration](https://git.berlin.ccc.de/vinzenz/nixos-configuration/src/commit/7a17930dd4f225cda4047f1df7d650249c91f29b/nixosConfigurations/hetzner-vpn2/nginx.nix#) for nginx and anubis was as follows: - -```nix -{ pkgs, ... }: -let - blog-domain-socket = "/run/nginx/blog.sock"; - anubis-domain-socket = "/run/anubis/anubis-blog.sock"; -in -{ - systemd.services = { - nginx.serviceConfig.SupplementaryGroups = [ "anubis" ]; - anubis-main.serviceConfig.SupplementaryGroups = [ "nginx" ]; - }; - - services = { - nginx = { - enable = true; - - recommendedProxySettings = true; - recommendedTlsSettings = true; - recommendedGzipSettings = true; - recommendedOptimisation = true; - - virtualHosts = { - "zerforschen.plus" = { - addSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://unix:" + anubis-domain-socket; - }; - }; - - "blog-in-anubis" = { - root = pkgs.zerforschen-plus-content; - listen = [ - { - addr = "unix:" + blog-domain-socket; - } - ]; - }; - }; - }; - - anubis.instances.main = { - enable = true; - settings = { - BIND = anubis-domain-socket; - TARGET = "unix://" + blog-domain-socket; - }; - }; - }; -} -``` - -[^1]: Part of the reason I am writing this article is to check if my RSS reader can handle it. diff --git a/content/posts/why-2025/day0/angel-badge.jpg b/content/posts/why-2025/day0/angel-badge.jpg deleted file mode 100644 index 79609e0..0000000 Binary files a/content/posts/why-2025/day0/angel-badge.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/cold-shower.jpg b/content/posts/why-2025/day0/cold-shower.jpg deleted file mode 100644 index e9e6653..0000000 Binary files a/content/posts/why-2025/day0/cold-shower.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/datenklo.jpg b/content/posts/why-2025/day0/datenklo.jpg deleted file mode 100644 index 80aca8d..0000000 Binary files a/content/posts/why-2025/day0/datenklo.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/dome.jpg b/content/posts/why-2025/day0/dome.jpg deleted file mode 100644 index 47bdf96..0000000 Binary files a/content/posts/why-2025/day0/dome.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/future.jpg b/content/posts/why-2025/day0/future.jpg deleted file mode 100644 index ed9aded..0000000 Binary files a/content/posts/why-2025/day0/future.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/index.md b/content/posts/why-2025/day0/index.md deleted file mode 100644 index b097949..0000000 --- a/content/posts/why-2025/day0/index.md +++ /dev/null @@ -1,154 +0,0 @@ -+++ -date = '2025-08-07T18:00:00+02:00' -published = '2025-08-09T19:00:00+02:00' -modified = '2025-08-17T12:00:00+02:00' -title = 'WHY 2025 - Day 0' -tags = ['travel', 'WHY 2025'] -+++ - -I went to WHY2025, a Dutch hacker camp. - -This is the second part of my travel log, covering everything happening on day 0 after arriving on the site. - - - -{{< details summary="Disclaimer WHY2025" >}} -{{< why-disclaimer >}} -{{< /details>}} - -### Entrance - - - -The shuttle dropped us off on a parking lot next to the event area. -To my surprise, there was also a team you could pass your luggage to that were driving everything to the info tent. -I wondered what would happen if there were issues with your ticket in that case. -Also, I did not want to have to search where I could get my tent back in case time mattered to get a good spot, -and I wanted my tent near the border between the cyan and red fields, which meant I did not have to walk _as_ far. - -The ticket checking was very fast without any queue. -This year's ribbon is dark blue with star patterns on it - pretty! -I also liked the fact you only had to show your ID in case you wanted an additional "18+" ribbon to be able to buy alcohol and so on (and you did not need an ID later to get drinks). -I felt kind of flattered by the fact I had to show mine, as I started getting self conscious about my age when someone guessed 10y too high a year ago. - - - -People were handed a paper goodie bag which were supposed to also include stickers, but ended up mostly containing ads for the sponsors of the event. -I usually _really_ dislike ads, but in this case I liked the organisations beaing advertised for (e.g. NIST and Support for Ukraine), so I did not mind. -It also contained _one_ sticket and a paper map as well as guidance for muggles that did not read the wiki. - -### Tent - -I found a good spot exactly where I wanted one. It ended up right next to a power station, which meant my short extension/splitter was enough to reach it. Being able to charge laptop and phone overnight in your tent is a _must_ on a hacker camp. - - - -At CCCamp, I did bring a router and long ethernet cable, but did not end up using it much because there was great WiFi coverage. -This time I did not, and because life is hard and unfair, neither my laptop nor phone were able to keep a connection while in the tent. -That meant I sadly did not use a _Datenklo_ (data toilet). - - - -While I got my home base ready, the sound check on the stages started, as stated on signs at the entrance earlier. The next half hour was filled with an instrumental version of "Never gonna give you up" with different equalizer settings and volumes. - -### Buildup - -With events like this, the days are literally numbered, with day one being the day of the opening. -A big team consisting of mostly unpaid volunteers had already spent a week on site building up the infrastructure. -As with the German camp, the existing fixed infrastructure is not enough for the thousands of people going to the toilet, expecting cooled mate, playing on [arcade machines](https://wiki.why2025.org/Project:Arcade) or running [pop-up data centers](https://wiki.why2025.org/Village:Yolocation). On Day 0 (also sometimes called Day -0), heavy machinery was still driving around when I started exploring. - - - -### 😱🍾💸 - -Being near the food court had the advantage that the first thing I found was a bar, so I wanted to get a mate. -I was shocked (_shocked!_) twice. - -The first thing was the mate itself. -I was used to choosing between brands, Flora Power being my favorite, but here it was all the different flavors of Club-Mate. - -// FIXME: ask at the bar to take a photo of the fridge and put it here - -The other thing was that they did not acccept any cash. -The German hacker events I went to were very proud about _not_ accepting digital payments (_Jede Kartenzahlung wird überwacht_), and here it was the other way around! -There was a way to pay pseudonymously though, and that was to charge an event payment card with cash at the info desk. -According to the sticker on the card, you can reprogram them to do something else afterwards, which is nice. - - - -What this prepaid card did not solve though was that you cannot pay if power is down. -Later in the evening one of the bars had to close early due to exactly this issue. -Whenever power was cut, the switch that provided PoE and internet to the payment terminals had to reboot, which took a while. -Because they were frequent enough, that process repeated mutliple times without them being able to sell anything. - - - -As with the mate, I think there would be a good middle ground somewhere in between. -Maybe there could have been one cash register per bar at WHY and one accepting cards at C3. -But I am not an organizer of things like this, so what do I know. - -I continued exploring properly caffeinated. - -### Light and sound installation - -// FIXME: ask V what it is called - -Near the entrance of the event, there was a hill with a huge sign on it. -A colorful contruction caught my eye, so I wanted to take a closer look. - - - -I got to know the artist, let's call them V here, who was still setting it up. -They built a tent out of foamy, semi-translucent packing material, with RDB light strips adding movement. -It looked like a giant isopod crawling up the hill. - -The installation noticed when someone was outside and made an old rotary dial phone inside ring, which prompted the visitor to go inside and listen to the voice on the other end. - - - -### Angel badge - -As I was already exhausted, I did not feel like volunteering that day, but I still got my angel status set to arrived and got the very pretty badge: - - - -### Milliways - -I also checked Milliways, the restaurant at the end of the universe. -They have a village or assembly at many hacker events and seem to have grown a lot over the years. -Hacking area, bar, kitchen and midnight snacks all in one. - -As usual, they brought their geodesic dome, this time decorated to feel jungle-like inside. -The dome was one of the places playing techno most day and night. - - - -What I did not know was that they usually get [challenge coins](https://wiki.milliways.info/index.php?title=Challenge_coins) made to finance the material costs. -They were very pretty, but only payable in cash. -As I hoped to not have to go to the next ATM in Alkmaar because of the cashless bars and food court, so I made a mental note to come back at the end of the event. - -### Need a pillow? - -I found V at one of the other bars and we talked for a while. -As this was their first hacker event, it was a great opportunity to share some great experiences I had at other events while drinking our first [Tschunk](https://entropia.de/Tschunk). -When I told him that when someone needs anything, it can usually be found, they asked for advice regarding camping gear. -V did not know this was a camp before coming here, which was also why the installation was tent-shaped. -I told them to ask at the info desk, which apparently worked great as they just got handed a blanket and pillow there for free. - -I was yearning for exploration, so we went our separate ways. -Even though the opening was still more than half a day in the future, the camp was already glowing in all colors of the rainbow. -Parties and hackers everywhere, I had a great time finding orientation in the big area. -My phone said I walked around 13,5k steps before 12 am. - -### Going to sleep - -The sanitary conditions were _great_ for a festival, and would still have been okay for a conference. -After such a long day, I was not going to sleep without a proper shower. -Without control over the temperature, I did not expect it to be super comfortable, but I really struggled cleaning myself because the water was _freezing_. -Maybe it was my tiredness at 3:30 am after being awake for 21h, but I did not take a shower as cold in a decade. -The next day the water was heated and maybe even too warm, so I do not know what happened there. - -UPDATE: As it turned out, the gas for the water heater was just empty. -They later put up a sign. - - diff --git a/content/posts/why-2025/day0/isopod.jpg b/content/posts/why-2025/day0/isopod.jpg deleted file mode 100644 index c80cf4d..0000000 Binary files a/content/posts/why-2025/day0/isopod.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/map.png b/content/posts/why-2025/day0/map.png deleted file mode 100644 index 598daf5..0000000 Binary files a/content/posts/why-2025/day0/map.png and /dev/null differ diff --git a/content/posts/why-2025/day0/payment-card.jpg b/content/posts/why-2025/day0/payment-card.jpg deleted file mode 100644 index d459a06..0000000 Binary files a/content/posts/why-2025/day0/payment-card.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/power-station.jpg b/content/posts/why-2025/day0/power-station.jpg deleted file mode 100644 index 7073cf2..0000000 Binary files a/content/posts/why-2025/day0/power-station.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/ribbons.jpg b/content/posts/why-2025/day0/ribbons.jpg deleted file mode 100644 index bd54bd3..0000000 Binary files a/content/posts/why-2025/day0/ribbons.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/switch.jpg b/content/posts/why-2025/day0/switch.jpg deleted file mode 100644 index 9a09b3b..0000000 Binary files a/content/posts/why-2025/day0/switch.jpg and /dev/null differ diff --git a/content/posts/why-2025/day0/unicorns.jpg b/content/posts/why-2025/day0/unicorns.jpg deleted file mode 100644 index 9514a99..0000000 Binary files a/content/posts/why-2025/day0/unicorns.jpg and /dev/null differ diff --git a/content/posts/why-2025/day1/firewall_off.jpg b/content/posts/why-2025/day1/firewall_off.jpg deleted file mode 100644 index 4afab2a..0000000 Binary files a/content/posts/why-2025/day1/firewall_off.jpg and /dev/null differ diff --git a/content/posts/why-2025/day1/firewall_on.webm b/content/posts/why-2025/day1/firewall_on.webm deleted file mode 100644 index afef153..0000000 Binary files a/content/posts/why-2025/day1/firewall_on.webm and /dev/null differ diff --git a/content/posts/why-2025/day1/index.md b/content/posts/why-2025/day1/index.md deleted file mode 100644 index 7647bbc..0000000 --- a/content/posts/why-2025/day1/index.md +++ /dev/null @@ -1,111 +0,0 @@ -+++ -date = '2025-08-08T12:00:00+02:00' -published = '2025-08-16T23:00:00+02:00' -modified = '2025-08-17T12:00:00+02:00' -title = 'WHY 2025 - Day 1' -tags = ['travel', 'WHY 2025'] -+++ - -I went to WHY2025, a Dutch hacker camp. - -This is the third part of my travel log, covering everything happening on day 1. - - - -{{< details summary="Disclaimer WHY2025" >}} -{{< why-disclaimer >}} -{{< /details>}} - -### Waking up - -At day 1 I woke up in a warm tent to ABBAs "Gimme Gimme", making further sleep impossible. -The weather service now predicted hotter weather than originally planned for, so I had to ration my cooler clothing for the hottest days, which had yet to come. - -I got a pancake in the food court and continued writing. -After saturation settled in, the next level in the pyramid of needs was social connections, so I walked around a bit. - -### Angry Nerds - -After a while I came across a village by the "Angry Nerds" podcast, which is sadly in Dutch so I was not familiar with it. -One of the creators of it was there and we talked for a while about differences between the German and Dutch hacker events. -WHY20205 feels less political than the events by CCC. -This may seem weird given that there is a big support for Ukraine tent, but at Congress there is a bunch of talks and assemblies about civil rights and climate action, by e.g. Netzpolitik.org or Bits&Bäume. - -He also pointed out the preparations of the firewall (marked by big flames on the map) and showed me a sneak peek. -Without being told, I could not have guessed what those grey boxes do. - - - -As we can time travel here, you can also see the firewall at night already: - -{{< gif src="./firewall_on.webm" >}} - -After a while, I did not want to bother my captive audience anymore so I continued exploring. - -### Anderstorps - -I walked past a bar at one of the villages playing very loud music to something you could describe as art. -I had just found Anderstorps, right next to BornHack. - -// FIXME: add picture of intact art piece - -As it seems like I do not have a picture of the art piece intact, here is a short description. -There was a pavillion with a white table in the middle. -On the table there was a black iron cage containing an accordeon. -In front of the table there was a huge "accordeons forbidden" sign. - -When asked about it, the inhabitants told me to come back later as they were too hung over from the night of Day 0, when different music will be playing. -As I wanted to sit down and write some more, I used the provided shade here. -Not much later, I noticed they were _literally_ playing the same music, as in looping a single track. - -🎵 Faxe Kondi by Klumben & Raske Penge - -On Day 3 or so, the cage including the instrument were gone, which may or may not have been planned beforehands. -They did not provide any further context apart from "have you heard what they sound like?". - - - -### First talk - -Next up was a talk that made me realize more stuff that was different from CCCamp. -It expected a talk about either cloud security in general, or one about finding vulnerabilities in a deployment. -Instead, this talk was about securing _proprietary_ Microsoft Azure services (a company still rightiously considered evil in many parts of the chaos) using other proprietary Microsoft Azure services. -Whenever there was a security issue, the solution was to use more Azure services. -There was barely enough context to figure out how to generalize what was said for other products, so it was not really helpfull for me. -The following questions were also about specific products and services. -I am pretty sure this would not have been on the Fahrplan in Germany, and as stated by others this would also have raised eyebrows in the Dutch hacker community one or two decades ago. - -### Power issues - -I wanted to get a new mate, but had to walk to a different bar because of issues with the payment system again. -As Heaven announced, the power outage was not on site and affected all of North Holland. -This meant that everything that was attached to the regional power grid, which was meant to be more stable than the on-site generators, did not work. -Because of this, all talks for the rest of the day were cancelled and mostly rescheduled in the following days. -At least bar payments were possible again shortly thereafter. - -When the sun started to settle, the soundcheck of a Metallica tribute band fittingly called _Sad but Tribute_ started. -From then on, the evening was filled with surprisingly close covers. -The castle-shaped stage ("party area") and the flamethrowers attached to the towers were visible from all over the camping grounds. - -### What the fog - -In the nights, it got really foggy, and I mean _really_ foggy. -This made all the lights everywhere stand out even more. - - - -Combine this with a bunch of very strong fog machines and you could maybe see two meters into the distance. - -
-