Wednesday, 25. December 2024 Week 52

A win for net neutrality

ComCom orders: Swisscom must operate zero-settlement peering with Init7

This will cause implications in the industry at home and abroad. The proceedings revealed that Swisscom together with Deutsche Telekom had formed a cartel in order to force payments from content providers. Internet providers have a technical monopoly on access to their end customers and Swisscom acted as a kind of gatekeeper; only those who paid “enough” could send traffic (e.g. video streaming) to their end customers [...].
Monday, 23. December 2024 Week 52
Sunday, 22. December 2024 Week 51

Pseudoscripting with <noscript>

In the Pseudoscripting with <noscript> article, James McKee explains a nice trick for writing CSS that detects when Javascript is disabled.
It combines the <noscript> element with a Container Style Query, to provide clearly defined CSS classes that are active/inactive whenever Javascript is enabled/disabled.

I took this as inspiration to make some recently added Javascript-only pages on the blog degrade a bit more gracefully for non-Javascript users.
In the case of the On this day page and the Search page, there is now a message shown explaining that this functionality requires Javascript.
This is done simply with the <noscript> element and works well.

Additionally I used a trick similar to the one from the article to hide the Javascript-only content with CSS on these pages (eg. the search form).
This is achieved with the following CSS class definition which hides elements when Javascript is not enabled.

<noscript>
  <style>
    .js-only { display: none !important; }
  </style>
</noscript>

With this in place, I can now mark all Javascript-only elements with the js-only class.
They are then hidden when someone uses the page with Javascript disabled, and visible for everyone else.

Saturday, 21. December 2024 Week 51
Thursday, 19. December 2024 Week 51
Tuesday, 17. December 2024 Week 51

How to avoid third-party CSRF cookies when embedding snippets from Opengist

While integrating Opengist to serve code snippets in the blog, I discovered that everytime a snippet is loaded a _csrf cookie is set by Opengist.
This is not very cool, and I've found a way to prevent this using nginx.

Why is this _csrf cookie not cool on embedded code snippets?

  1. It is not necessary (as the embedded code snippet does not provide any links/actions to perform on the Opengist instance where CSRF protection would be needed).
  2. It sets a third-party cookie for everyone visiting the blog.
  3. It breaks caching of the embedded code snippets on browser side (as the cookie is updated on every request).

How did I prevent the _csrf cookie with nginx?

I'm using the following (simplified) nginx reverse proxy config in front of the Opengist docker container.
It has a conditional if section where the headers-more-nginx-module is used to remove the Set-Cookie HTTP header, on the responses for the embedded code snippets.
The if condition is specific to my username and will need to be adjusted to your setup of course.

server {
	server_name gist.x-way.org;

	location / {
		if ( $uri ~* ^/x-way/[0-9a-fA-F]+\.js$ ) {
			more_clear_headers "Set-Cookie";
		}

		proxy_pass http://127.0.0.1:6157;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
	}
}

This is a quite ugly hack. I submitted a pull-request for Opengist to exclude the embedded code snippets from the CSRF middleware.
Let's see where this leads 🤞

Sunday, 15. December 2024 Week 50

Switching to self-hosted Opengist

Decided to self-host the handful of code snippets I embedded into the blogposts over time.
This will be one less dependency on an external service (GitHub Gist) for running this site :-)

I choose Opengist for hosting my code snippets.
Although I already run a GitBucket instance, I decided not to use it for hosting the code snippets of the blog.
This because in the past I had some performance issues and crashes that were triggered by Bots overloading the Docker container.

The installation of Opengist went very smooth.
It does not come with many dependencies and brings it's own SQLite database file (which should be more than enough for the code snippets in the blog).

I was positively surprised by the MFA and seamless Passkey integration it provides out of the box.
Also can it be configured to allow embedding/sharing of snippets for everyone while restricting the listing and editing to logged in users only.
And as an additional security benefit it helps to reduce the complexity of my CSP policy 🔐

If you're curious to see how the code snippets are rendered, have a look at the blogposts here or here.

Wednesday, 11. December 2024 Week 50

The seven rules of writing consistent git commit messages

  1. Separate subject from body with a blank line
  2. Limit the subject line to 50 characters (I often break this when there’s no message body)
  3. Capitalize the subject line
  4. Do not end the subject line with a period
  5. Use the imperative mood in the subject line
  6. Wrap the body at 72 characters
  7. Use the body to explain what and why vs. how

(via)

Tuesday, 10. December 2024 Week 50
Sunday, 8. December 2024 Week 49

New search functionality

I added a client-side search functionality to this static blog.

Similar to what is explained in this article by Stephan Miller, I added a search functionality to the blog.
The challenge was to do this while keeping the blog a static generated site.
Thus the choice to do all of the search client-side in JavaScript.

The way my current implementation works, is that there is a JSON blob with all the posts ever written in this blog.
This is loaded to the browser and indexed using Lunr.js.
The resulting search index is then used to provide the search functionality.
It comes with some convenient built-in search modifiers such as +, - and *.

To avoid reloading the whole JSON blob for each follow-up query on the search page, it intercepts the default form submit action and handles the search client-side.
Thus re-using the computed search index and saving the additional roundtrips accross the network.