aboutsummaryrefslogtreecommitdiff
path: root/src/blog
diff options
context:
space:
mode:
Diffstat (limited to 'src/blog')
-rw-r--r--src/blog/2022-06-12-shell-ide-sed/shell-ide-sed.md2
-rw-r--r--src/blog/2022-08-14-website/website.md6
-rw-r--r--src/blog/2022-11-23-git-host/git-host.md18
-rw-r--r--src/blog/2022-12-30-blog-ready/blog-ready.md5
-rw-r--r--src/blog/2023-07-11-feed/feed.md2
-rw-r--r--src/blog/2024-04-30-taming-cpp-motivation/taming-cpp-motivation.md12
-rw-r--r--src/blog/2024-12-03-2fa/2fa.md4
-rw-r--r--src/blog/2024-12-26-taming-cpp-raii/taming-cpp-raii.md6
-rw-r--r--src/blog/2025-01-21-taming-cpp-templates/taming-cpp-templates.md24
-rw-r--r--src/blog/2025-02-27-elliptic-curves-javascript/ecm.md6
-rw-r--r--src/blog/2025-06-06-webdev/webdev.md20
-rw-r--r--src/blog/2025-06-26-borrow-checker/borrow-checker.md5
-rw-r--r--src/blog/2025-11-29-aoc-download/aoc-download.md2
-rw-r--r--src/blog/2026-03-27-programming-20-years/20-years-of-programming.md5
-rw-r--r--src/blog/2026-08-15-dotfiles/dotfiles.md88
-rw-r--r--src/blog/2026-09-05-cgit/cgit.md141
-rw-r--r--src/blog/2026-09-13-host-migration/host-migration.md172
17 files changed, 461 insertions, 57 deletions
diff --git a/src/blog/2022-06-12-shell-ide-sed/shell-ide-sed.md b/src/blog/2022-06-12-shell-ide-sed/shell-ide-sed.md
index 410d2ce..bcb97d0 100644
--- a/src/blog/2022-06-12-shell-ide-sed/shell-ide-sed.md
+++ b/src/blog/2022-06-12-shell-ide-sed/shell-ide-sed.md
@@ -117,7 +117,7 @@ $ cth do_ src/*
117``` 117```
118 118
119And it works! You can now find 119And it works! You can now find
120[this script](https://git.tronto.net/scripts/file/cth%2Ehtml) 120[this script](https://git.tronto.net/scripts/tree/cth)
121among my other [scripts](https://git.tronto.net/scripts). 121among my other [scripts](https://git.tronto.net/scripts).
122 122
123*Remark: in bash one can simply do `sed -n "/^$1/,/^}/ p" ${@:2}` to match 123*Remark: in bash one can simply do `sed -n "/^$1/,/^}/ p" ${@:2}` to match
diff --git a/src/blog/2022-08-14-website/website.md b/src/blog/2022-08-14-website/website.md
index 8019c60..f76c5f2 100644
--- a/src/blog/2022-08-14-website/website.md
+++ b/src/blog/2022-08-14-website/website.md
@@ -23,7 +23,7 @@ files, writing a script that adds a header and a footer to the output of
23[lowdown](https://kristaps.bsd.lv/lowdown/), and using 23[lowdown](https://kristaps.bsd.lv/lowdown/), and using
24[rsync](https://en.wikipedia.org/wiki/Rsync) to deploy the files to my server. 24[rsync](https://en.wikipedia.org/wiki/Rsync) to deploy the files to my server.
25All of this is available on 25All of this is available on
26[my git page](https://git.tronto.net/sebastiano.tronto.net/), but I won't 26[my git page](https://git.tronto.net/sebastiano.tronto.net), but I won't
27explain every detail of these build scripts here. In particular, my script 27explain every detail of these build scripts here. In particular, my script
28also builds a [gemini](https://sebastiano.tronto.net/blog/2022-06-04-gemini/) 28also builds a [gemini](https://sebastiano.tronto.net/blog/2022-06-04-gemini/)
29version of my website, which I won't discuss here. 29version of my website, which I won't discuss here.
@@ -88,9 +88,9 @@ Without this trick the correct URL would have been
88`sebastiano.tronto.net/git.html` or something, which I don't like. 88`sebastiano.tronto.net/git.html` or something, which I don't like.
89 89
90The main working directory also contains the 90The main working directory also contains the
91[`top.html`](https://git.tronto.net/sebastiano.tronto.net/file/top%2Ehtml%2Ehtml) 91[`top.html`](https://git.tronto.net/sebastiano.tronto.net/tree/top.html)
92and 92and
93[`bottom.html`](https://git.tronto.net/sebastiano.tronto.net/file/bottom%2Ehtml%2Ehtml) 93[`bottom.html`](https://git.tronto.net/sebastiano.tronto.net/tree/bottom.html)
94files. These files are not uploaded directly to my server - they are not 94files. These files are not uploaded directly to my server - they are not
95even well-formed html files! - but they are used to build all other 95even well-formed html files! - but they are used to build all other
96html pages. 96html pages.
diff --git a/src/blog/2022-11-23-git-host/git-host.md b/src/blog/2022-11-23-git-host/git-host.md
index cc9fc27..8087d80 100644
--- a/src/blog/2022-11-23-git-host/git-host.md
+++ b/src/blog/2022-11-23-git-host/git-host.md
@@ -1,5 +1,11 @@
1# Self-hosted git pages with stagit (featuring ed, the standard editor) 1# Self-hosted git pages with stagit (featuring ed, the standard editor)
2 2
3*Update 2026-08-30: Since August 2026, I am no longer using stagit to
4host my git pages. Instead, I use [cgit](https://git.zx2c4.com/cgit/about).
5I have updated all the links in this page to point to a frozen copy of
6my stagit-based git page before the switch. If you want to visit my new
7git page, go to [git.tronto.net](https://git.tronto.net).*
8
3This is a follow-up to my earlier blog entry 9This is a follow-up to my earlier blog entry
4[How I update my website](../2022-08-14-website). 10[How I update my website](../2022-08-14-website).
5 11
@@ -14,9 +20,9 @@ via web pages, on your personal server? In this post I am going to show
14you how I do it, in the usual minimalist and 20you how I do it, in the usual minimalist and
15not-using-what-I-do-not-understand style. 21not-using-what-I-do-not-understand style.
16 22
17You can see the final result on my [git pages](https://git.tronto.net). 23You can see the final result on my [git pages](https://stagit.tronto.net).
18The scripts and other files I use to set this up are accessible 24The scripts and other files I use to set this up are accessible
19[here](https://git.tronto.net/git-hooks). 25[here](https://stagit.tronto.net/git-hooks).
20 26
21## Hosting git repositories on your own server 27## Hosting git repositories on your own server
22 28
@@ -54,7 +60,7 @@ a bunch of html files that you can simply move to your www hosting directory.
54After generating the pages you can personalize them by copying your logo, 60After generating the pages you can personalize them by copying your logo,
55[favicon](https://en.wikipedia.org/wiki/Favicon) or CSS style sheet. You can 61[favicon](https://en.wikipedia.org/wiki/Favicon) or CSS style sheet. You can
56use `stagit-index` to generate 62use `stagit-index` to generate
57[an index page for your repositories](https://git.tronto.net/). Since everything 63[an index page for your repositories](https://stagit.tronto.net/). Since everything
58consists of html files, you can simply edit them to personalize your git pages 64consists of html files, you can simply edit them to personalize your git pages
59even further - and below you'll see some examples. 65even further - and below you'll see some examples.
60 66
@@ -155,8 +161,8 @@ add or change:
155* I would like to have a download button so that people who don't use git 161* I would like to have a download button so that people who don't use git
156 can still download my files. This makes sense especially for those 162 can still download my files. This makes sense especially for those
157 repos that are mostly documents, such as my 163 repos that are mostly documents, such as my
158 [lecture notes](https://git.tronto.net/mathsoftware) or my 164 [lecture notes](https://stagit.tronto.net/mathsoftware) or my
159 [FMC tutorial](https://git.tronto.net/fmctutorial). 165 [FMC tutorial](https://stagit.tronto.net/fmctutorial).
160* I would like to convert README.md files to html. 166* I would like to convert README.md files to html.
161 167
162If I were calling stagit by hand after each `git push`, I 168If I were calling stagit by hand after each `git push`, I
@@ -280,7 +286,7 @@ stagit-index /home/git/*.git | sed 's|/log\.html||g' > "$basedir/index.html"
280And that's it. Well, I also copy the style files and add a bottom bar, 286And that's it. Well, I also copy the style files and add a bottom bar,
281and change the title from a `<span class="desc">` to an `<h1>` element, 287and change the title from a `<span class="desc">` to an `<h1>` element,
282again using `ed`. If you want to see the details you can check them out 288again using `ed`. If you want to see the details you can check them out
283[here](https://git.tronto.net/git-hooks/file/post-receive-stagit.html). 289[here](https://stagit.tronto.net/git-hooks/file/post-receive-stagit.html).
284 290
285## Conclusions 291## Conclusions
286 292
diff --git a/src/blog/2022-12-30-blog-ready/blog-ready.md b/src/blog/2022-12-30-blog-ready/blog-ready.md
index 144e5e2..a6f0ff0 100644
--- a/src/blog/2022-12-30-blog-ready/blog-ready.md
+++ b/src/blog/2022-12-30-blog-ready/blog-ready.md
@@ -13,10 +13,9 @@ messy at some point! It would be nice to divide these posts by year...
13## Adding year sections to my blog index 13## Adding year sections to my blog index
14 14
15Very easy: in my 15Very easy: in my
16[build.sh](https://git.tronto.net/sebastiano.tronto.net/file/build.sh.html) 16[build.sh](https://git.tronto.net/sebastiano.tronto.net/tree/build.sh)
17script that I run to 17script that I run to
18[build my website](../2022-08-14-website), there is a 18[build my website](../2022-08-14-website), there is a `makeblog()`
19[`makeblog()`](https://git.tronto.net/sebastiano.tronto.net/file/build.sh.html#l52)
20function that takes care of building the index page and RSS feed for my blog. 19function that takes care of building the index page and RSS feed for my blog.
21 20
22It is enough to add the following lines inside its main loop: 21It is enough to add the following lines inside its main loop:
diff --git a/src/blog/2023-07-11-feed/feed.md b/src/blog/2023-07-11-feed/feed.md
index feb5cd6..9c56bcb 100644
--- a/src/blog/2023-07-11-feed/feed.md
+++ b/src/blog/2023-07-11-feed/feed.md
@@ -62,7 +62,7 @@ reader UI.
62In the first version I made, my feeds were separated in folders, 62In the first version I made, my feeds were separated in folders,
63one per file, and one could select multiple feeds or even entire 63one per file, and one could select multiple feeds or even entire
64folders via dmenu using 64folders via dmenu using
65[dmenu-filepicker](https://git.tronto.net/scripts/file/dmenu-filepicker.html) 65[dmenu-filepicker](https://git.tronto.net/scripts/tree/dmenu-filepicker)
66for file selection. 66for file selection.
67Once the session was terminated, all shown feeds were marked as 67Once the session was terminated, all shown feeds were marked as
68"read" by writing the timestamp of the last read item on a cache 68"read" by writing the timestamp of the last read item on a cache
diff --git a/src/blog/2024-04-30-taming-cpp-motivation/taming-cpp-motivation.md b/src/blog/2024-04-30-taming-cpp-motivation/taming-cpp-motivation.md
index 3181eb0..532a0dd 100644
--- a/src/blog/2024-04-30-taming-cpp-motivation/taming-cpp-motivation.md
+++ b/src/blog/2024-04-30-taming-cpp-motivation/taming-cpp-motivation.md
@@ -40,7 +40,7 @@ You can find the code I wrote in
40 40
41To sort a list of a hundred million integers, in C we can use `qsort()` 41To sort a list of a hundred million integers, in C we can use `qsort()`
42from `stdlib.h` (see 42from `stdlib.h` (see
43[sort.c](https://git.tronto.net/taming-cpp/file/sort-benchmark/integers/sort.c.html)): 43[sort.c](https://git.tronto.net/taming-cpp/tree/sort-benchmark/integers/sort.c)):
44 44
45``` 45```
46qsort(a, ARRAYSIZE, sizeof(int), compar); 46qsort(a, ARRAYSIZE, sizeof(int), compar);
@@ -55,7 +55,7 @@ int compar(const void *x, const void *y) {
55``` 55```
56 56
57In C++ we can use `sort()` from `algorithm` (see 57In C++ we can use `sort()` from `algorithm` (see
58[sort.cpp](https://git.tronto.net/taming-cpp/file/sort-benchmark/integers/sort.cpp.html)): 58[sort.cpp](https://git.tronto.net/taming-cpp/tree/sort-benchmark/integers/sort.cpp)):
59 59
60``` 60```
61std::sort(a, a+ARRAYSIZE, 61std::sort(a, a+ARRAYSIZE,
@@ -69,7 +69,7 @@ instead of a comparison function.
69Modern C++ also offers parallelized 69Modern C++ also offers parallelized
70version of common algorithms as part of the standard library, so if 70version of common algorithms as part of the standard library, so if
71we want to completely humiliate poor C we can use this (see 71we want to completely humiliate poor C we can use this (see
72[sort_parallel.cpp](https://git.tronto.net/taming-cpp/file/sort-benchmark/integers/sort_parallel.cpp.html)): 72[sort_parallel.cpp](https://git.tronto.net/taming-cpp/tree/sort-benchmark/integers/sort_parallel.cpp)):
73 73
74``` 74```
75std::sort(std::execution::par, a, a+ARRAYSIZE, 75std::sort(std::execution::par, a, a+ARRAYSIZE,
@@ -94,9 +94,9 @@ Even without parallelization, C++ is twice as fast as C!
94You might think that C++ is somehow optimizing for integer 94You might think that C++ is somehow optimizing for integer
95sorting. But this is not the case, as demonstrated by a similar experiment 95sorting. But this is not the case, as demonstrated by a similar experiment
96with *pairs* of integers (see 96with *pairs* of integers (see
97[sort.c](https://git.tronto.net/taming-cpp/file/sort-benchmark/pairs/sort.c.html), 97[sort.c](https://git.tronto.net/taming-cpp/tree/sort-benchmark/pairs/sort.c),
98[sort.cpp](https://git.tronto.net/taming-cpp/file/sort-benchmark/pairs/sort.cpp.html) and 98[sort.cpp](https://git.tronto.net/taming-cpp/tree/sort-benchmark/pairs/sort.cpp) and
99[sort_parallel.cpp](https://git.tronto.net/taming-cpp/file/sort-benchmark/pairs/sort_parallel.cpp.html) 99[sort_parallel.cpp](https://git.tronto.net/taming-cpp/tree/sort-benchmark/pairs/sort_parallel.cpp)
100- I used a non-standard mixed lexicographic order to be reasonably sure the 100- I used a non-standard mixed lexicographic order to be reasonably sure the
101compiler does not come up with any ad-hoc optimization): 101compiler does not come up with any ad-hoc optimization):
102 102
diff --git a/src/blog/2024-12-03-2fa/2fa.md b/src/blog/2024-12-03-2fa/2fa.md
index 66f3661..3a84682 100644
--- a/src/blog/2024-12-03-2fa/2fa.md
+++ b/src/blog/2024-12-03-2fa/2fa.md
@@ -64,9 +64,9 @@ $ athtool -b --totp "SECRET_KEY"
64And that's it. However, you should not write you secret key in plain text 64And that's it. However, you should not write you secret key in plain text
65like this: instead you should keep it encrypted and decrypt it just 65like this: instead you should keep it encrypted and decrypt it just
66when you need it to generate a code. I do this by using my simple 66when you need it to generate a code. I do this by using my simple
67[2fa](https://git.tronto.net/scripts/file/2fa.html) 67[2fa](https://git.tronto.net/scripts/tree/2fa)
68script, which is based on my 68script, which is based on my
69[secret](https://git.tronto.net/scripts/file/secret.html) 69[secret](https://git.tronto.net/scripts/tree/secret)
70tool that encrypts and decrypts stuff using openssl and a master 70tool that encrypts and decrypts stuff using openssl and a master
71password - which is obviously 71password - which is obviously
72[correcthorsebatterystaple](https://xkcd.com/936/). 72[correcthorsebatterystaple](https://xkcd.com/936/).
diff --git a/src/blog/2024-12-26-taming-cpp-raii/taming-cpp-raii.md b/src/blog/2024-12-26-taming-cpp-raii/taming-cpp-raii.md
index 6450521..a7c1bae 100644
--- a/src/blog/2024-12-26-taming-cpp-raii/taming-cpp-raii.md
+++ b/src/blog/2024-12-26-taming-cpp-raii/taming-cpp-raii.md
@@ -61,7 +61,7 @@ But there is a more interesting way to make this program fail by only
61changing the definition of `BadType`. In fact, you can make this program 61changing the definition of `BadType`. In fact, you can make this program
62do pretty much everything you want by changing `BadType`'s *constructor* 62do pretty much everything you want by changing `BadType`'s *constructor*
63to suit your needs (see 63to suit your needs (see
64[surprising-error.cpp](https://git.tronto.net/taming-cpp/file/raii/surprising-error.cpp.html)): 64[surprising-error.cpp](https://git.tronto.net/taming-cpp/tree/raii/surprising-error.cpp)):
65 65
66``` 66```
67class BadType { 67class BadType {
@@ -83,7 +83,7 @@ And it does not stop here either: whenever a variable
83of a class type goes out of scope, the corresponding 83of a class type goes out of scope, the corresponding
84[destructor](https://en.cppreference.com/w/cpp/language/destructor) 84[destructor](https://en.cppreference.com/w/cpp/language/destructor)
85is called - see 85is called - see
86[constructor-hello-world.cpp](https://git.tronto.net/taming-cpp/file/raii/constructor-hello-world.cpp.html): 86[constructor-hello-world.cpp](https://git.tronto.net/taming-cpp/tree/raii/constructor-hello-world.cpp):
87 87
88``` 88```
89#include <iostream> 89#include <iostream>
@@ -254,7 +254,7 @@ from a function is a classic example, but they also come up when using
254[smart pointers](https://en.cppreference.com/book/intro/smart_pointers). 254[smart pointers](https://en.cppreference.com/book/intro/smart_pointers).
255 255
256I made a 256I made a
257[comprehensive example](https://git.tronto.net/taming-cpp/file/raii/all-constructors.cpp.html) 257[comprehensive example](https://git.tronto.net/taming-cpp/tree/raii/all-constructors.cpp)
258of how all of these operations work, so you can see when exactly each 258of how all of these operations work, so you can see when exactly each
259of them is called. Do check it out if you are interested! 259of them is called. Do check it out if you are interested!
260 260
diff --git a/src/blog/2025-01-21-taming-cpp-templates/taming-cpp-templates.md b/src/blog/2025-01-21-taming-cpp-templates/taming-cpp-templates.md
index bce440f..903a1ff 100644
--- a/src/blog/2025-01-21-taming-cpp-templates/taming-cpp-templates.md
+++ b/src/blog/2025-01-21-taming-cpp-templates/taming-cpp-templates.md
@@ -44,7 +44,7 @@ You can find the code examples for this post in the
44[companion repository for this series](https://git.tronto.net/taming-cpp), 44[companion repository for this series](https://git.tronto.net/taming-cpp),
45and if you want you can also have a look at the final version 45and if you want you can also have a look at the final version
46of my tiny library 46of my tiny library
47[on my git page](https://git.tronto.net/zmodn/file/README.md.html). For 47[on my git page](https://git.tronto.net/zmodn). For
48this post I am going to use Clang as a compiler, because I find its 48this post I am going to use Clang as a compiler, because I find its
49error messages more readable most of the times. 49error messages more readable most of the times.
50 50
@@ -69,7 +69,7 @@ cannot, for example, assign an `std::vector<int>` object to an
69As an example, let's take a simple standard library class such as 69As an example, let's take a simple standard library class such as
70[`std::pair`](https://en.cppreference.com/w/cpp/utility/pair). 70[`std::pair`](https://en.cppreference.com/w/cpp/utility/pair).
71It could be implemented as follows (see 71It could be implemented as follows (see
72[pair.cpp](https://git.tronto.net/taming-cpp/file/templates/pair.cpp.html)): 72[pair.cpp](https://git.tronto.net/taming-cpp/tree/templates/pair.cpp)):
73 73
74``` 74```
75template<typename S, typename T> 75template<typename S, typename T>
@@ -151,7 +151,7 @@ which in case you don't know are just a simplified syntax for pointers.)
151Let's take this simple example to show an important property of templates. 151Let's take this simple example to show an important property of templates.
152Let's say that, perhaps by mistake, we implemented the swap function 152Let's say that, perhaps by mistake, we implemented the swap function
153using different template types for `a` and `b` (see 153using different template types for `a` and `b` (see
154[swap.cpp](https://git.tronto.net/taming-cpp/file/templates/swap.cpp.html)): 154[swap.cpp](https://git.tronto.net/taming-cpp/tree/templates/swap.cpp)):
155 155
156``` 156```
157template<typename S, typename T> 157template<typename S, typename T>
@@ -204,7 +204,7 @@ to make these error messages more meaningful - we'll see some examples below.
204Objects, not just types, can be template parameters. A classic example 204Objects, not just types, can be template parameters. A classic example
205is [`std::array`](https://en.cppreference.com/w/cpp/container/array), 205is [`std::array`](https://en.cppreference.com/w/cpp/container/array),
206a fixed-size container where the capacity is fixed at compile time (see 206a fixed-size container where the capacity is fixed at compile time (see
207[std_array.cpp](https://git.tronto.net/taming-cpp/file/templates/std_array.cpp.html) 207[std_array.cpp](https://git.tronto.net/taming-cpp/tree/templates/std_array.cpp)
208for an example). 208for an example).
209 209
210Non-type parameters can be constants of any *structural type* - see 210Non-type parameters can be constants of any *structural type* - see
@@ -213,13 +213,13 @@ for a precise definition. Remember that you can only specialize them
213with compile-time (i.e. `constexpr`) constants! 213with compile-time (i.e. `constexpr`) constants!
214 214
215With non-type parameter you can do pretty wild stuff, see for example 215With non-type parameter you can do pretty wild stuff, see for example
216[factorial.cpp](https://git.tronto.net/taming-cpp/file/templates/factorial.cpp.html) 216[factorial.cpp](https://git.tronto.net/taming-cpp/tree/templates/factorial.cpp)
217- although this specific example is not very useful, since it can easily 217- although this specific example is not very useful, since it can easily
218be replaced by a constexpr function. 218be replaced by a constexpr function.
219 219
220Fun fact: if you use `auto`, you don't even have to specify a type for 220Fun fact: if you use `auto`, you don't even have to specify a type for
221a non-type parameter. For example, the following code works just fine (see 221a non-type parameter. For example, the following code works just fine (see
222[println.cpp](https://git.tronto.net/taming-cpp/file/templates/println.cpp.html)): 222[println.cpp](https://git.tronto.net/taming-cpp/tree/templates/println.cpp)):
223 223
224``` 224```
225#include <iostream> 225#include <iostream>
@@ -278,7 +278,7 @@ template for
278where `N` is a fixed at compile-time. 278where `N` is a fixed at compile-time.
279 279
280We may start with something like this (see 280We may start with something like this (see
281[zmodn-1.cpp](https://git.tronto.net/taming-cpp/file/templates/zmodn-1.cpp.html)): 281[zmodn-1.cpp](https://git.tronto.net/taming-cpp/tree/templates/zmodn-1.cpp)):
282 282
283``` 283```
284#include <iostream> 284#include <iostream>
@@ -355,7 +355,7 @@ are a way to prevent nasty run-time errors and / or make compiler errors
355more meaningful when using templates; they were added in C++20. 355more meaningful when using templates; they were added in C++20.
356 356
357In our case, introducing our constraint is quite simple (see 357In our case, introducing our constraint is quite simple (see
358[zmodn-2.cpp](https://git.tronto.net/taming-cpp/file/templates/zmodn-2.cpp.html)): 358[zmodn-2.cpp](https://git.tronto.net/taming-cpp/tree/templates/zmodn-2.cpp)):
359 359
360``` 360```
361template<int N> 361template<int N>
@@ -392,7 +392,7 @@ type of N.
392 392
393In order to do so, I can use a non-type parameter declared `auto` and 393In order to do so, I can use a non-type parameter declared `auto` and
394[`decltype()`](https://en.cppreference.com/w/cpp/language/decltype) (see 394[`decltype()`](https://en.cppreference.com/w/cpp/language/decltype) (see
395[zmodn-3.cpp](https://git.tronto.net/taming-cpp/file/templates/zmodn-3.cpp.html)): 395[zmodn-3.cpp](https://git.tronto.net/taming-cpp/tree/templates/zmodn-3.cpp)):
396 396
397``` 397```
398template<auto N> 398template<auto N>
@@ -409,7 +409,7 @@ public:
409 409
410And of course I should also templatize the `extended_gcd()` function - 410And of course I should also templatize the `extended_gcd()` function -
411you can see the full code in 411you can see the full code in
412[zmodn-3.cpp](https://git.tronto.net/taming-cpp/file/templates/zmodn-3.cpp.html). 412[zmodn-3.cpp](https://git.tronto.net/taming-cpp/tree/templates/zmodn-3.cpp).
413 413
414Now we can use any type as a "base" for our modular integer! Well, almost. 414Now we can use any type as a "base" for our modular integer! Well, almost.
415I mentioned above that the type we use must be *structural*, but that is 415I mentioned above that the type we use must be *structural*, but that is
@@ -417,7 +417,7 @@ relatively easy to satisfy. A bigger problem is that our type must
417allow for compile-time constants - so we need, at least, a `constexpr` 417allow for compile-time constants - so we need, at least, a `constexpr`
418constructor. I could not find a suitable library online, so I ended 418constructor. I could not find a suitable library online, so I ended
419up writing my own - see 419up writing my own - see
420[bigint.h](https://git.tronto.net/taming-cpp/file/templates/bigint.h.html). 420[bigint.h](https://git.tronto.net/taming-cpp/tree/templates/bigint.h).
421 421
422The code is simple and not very efficient, but this library is not meant 422The code is simple and not very efficient, but this library is not meant
423to be efficient. I am just using it for educational purposes. 423to be efficient. I am just using it for educational purposes.
@@ -477,7 +477,7 @@ Along with constraints, C++20 also introduced the possibility to define
477and name a custom set of requirements. This can be done with *concepts*. 477and name a custom set of requirements. This can be done with *concepts*.
478In our example, we can require that our type supports all the operations 478In our example, we can require that our type supports all the operations
479we need (see 479we need (see
480[zmodn-4.cpp](https://git.tronto.net/taming-cpp/file/templates/zmodn-4.cpp.html)): 480[zmodn-4.cpp](https://git.tronto.net/taming-cpp/tree/templates/zmodn-4.cpp)):
481 481
482``` 482```
483template<typename T> 483template<typename T>
diff --git a/src/blog/2025-02-27-elliptic-curves-javascript/ecm.md b/src/blog/2025-02-27-elliptic-curves-javascript/ecm.md
index 56b876c..27e5021 100644
--- a/src/blog/2025-02-27-elliptic-curves-javascript/ecm.md
+++ b/src/blog/2025-02-27-elliptic-curves-javascript/ecm.md
@@ -40,7 +40,7 @@ Recently I have been learning C++, and I wanted to experiment with some
40of its more advanced features. So I decided to rewrite the whole thing. 40of its more advanced features. So I decided to rewrite the whole thing.
41 41
42I had a clear idea of where I wanted to start: a small 42I had a clear idea of where I wanted to start: a small
43[library for modular arithmetic](https://git.tronto.net/zmodn/file/README.md.html), 43[library for modular arithmetic](https://git.tronto.net/zmodn),
44with compile-time fixed 44with compile-time fixed
45[modulus](https://en.wikipedia.org/wiki/Modular_arithmetic) via templates 45[modulus](https://en.wikipedia.org/wiki/Modular_arithmetic) via templates
46and heavy use of 46and heavy use of
@@ -57,7 +57,7 @@ algorithm with very large numbers. Unfortunately, I did not take into
57account that with my setup I needed a big integer class that supported 57account that with my setup I needed a big integer class that supported
58*compile-time constants* - for example in the form of `constexpr` 58*compile-time constants* - for example in the form of `constexpr`
59constructors. I could not find any, so I decided to write 59constructors. I could not find any, so I decided to write
60[my own big integer class](https://git.tronto.net/zmodn/file/bigint.h.html). 60[my own big integer class](https://git.tronto.net/zmodn/tree/bigint.h).
61This was less successful: implementing an *efficient* big integer library 61This was less successful: implementing an *efficient* big integer library
62was not as straightforward as the modular integers library. I decided 62was not as straightforward as the modular integers library. I decided
63not to care about efficiency for the time being, but that would come 63not to care about efficiency for the time being, but that would come
@@ -258,7 +258,7 @@ pieces of text and pictures in the slides - shoutout to
258my friend [Jared](https://guissmo.com) for telling me about 258my friend [Jared](https://guissmo.com) for telling me about
259it. Apart from this I don't have anything interesting to comment 259it. Apart from this I don't have anything interesting to comment
260about the CSS part of the slides. You can check the full code 260about the CSS part of the slides. You can check the full code
261[here](https://git.tronto.net/ecm/file/index.html.html) if you want; 261[here](https://git.tronto.net/ecm/tree/index.html) if you want;
262everything is in a single HTML file. 262everything is in a single HTML file.
263 263
264The result looks fine, but it does not work perfectly will every screen 264The result looks fine, but it does not work perfectly will every screen
diff --git a/src/blog/2025-06-06-webdev/webdev.md b/src/blog/2025-06-06-webdev/webdev.md
index 50b14d9..b712a85 100644
--- a/src/blog/2025-06-06-webdev/webdev.md
+++ b/src/blog/2025-06-06-webdev/webdev.md
@@ -19,7 +19,7 @@
19## Introduction 19## Introduction
20 20
21I have recently worked on making a web application out of 21I have recently worked on making a web application out of
22[my latest Rubik's cube optimal solver](https://git.tronto.net/nissy-core/file/README.md.html). 22[my latest Rubik's cube optimal solver](https://git.tronto.net/nissy-core).
23This involved building a rather complex C code base (with 23This involved building a rather complex C code base (with
24multithreading, SIMD, callback functions and whatnot) to 24multithreading, SIMD, callback functions and whatnot) to
25[WebAssembly](https://en.wikipedia.org/wiki/WebAssembly) via 25[WebAssembly](https://en.wikipedia.org/wiki/WebAssembly) via
@@ -27,7 +27,7 @@ multithreading, SIMD, callback functions and whatnot) to
27JavaScript and HTML for the frontend. 27JavaScript and HTML for the frontend.
28 28
29This whole process was complex, tiring and at times frustrating - 29This whole process was complex, tiring and at times frustrating -
30but eventually [it was a success](https://tronto.net:48)! Not only 30but eventually [it was a success](https://h48.tronto.net)! Not only
31I accomplished my goal, but I have learnt a lot along the way. After 31I accomplished my goal, but I have learnt a lot along the way. After
32finishing the work, I decided to write down all that I have learnt and 32finishing the work, I decided to write down all that I have learnt and
33share it with the world with this post. 33share it with the world with this post.
@@ -77,7 +77,7 @@ With this out of the way, let's get started!
77 77
78The examples used in this tutorial are all contained in a git repository, 78The examples used in this tutorial are all contained in a git repository,
79which you can find either on 79which you can find either on
80[my git page](https://git.tronto.net/emscripten-tutorial/file/README.md.html) or 80[my git page](https://git.tronto.net/emscripten-tutorial) or
81[on github](https://github.com/sebastianotronto/emscripten-tutorial). 81[on github](https://github.com/sebastianotronto/emscripten-tutorial).
82 82
83In order to follow them you are going to need: 83In order to follow them you are going to need:
@@ -161,7 +161,7 @@ but in case you are interested you can check out
161You can find the code for this example, as well as scripts to 161You can find the code for this example, as well as scripts to
162build it and run the web server, in the directory `00_hello_world` 162build it and run the web server, in the directory `00_hello_world`
163of the git repository 163of the git repository
164([git.tronto.net](https://git.tronto.net/emscripten-tutorial/file/README.md.html), 164([git.tronto.net](https://git.tronto.net/emscripten-tutorial),
165[github](https://github.com/sebastianotronto/emscripten-tutorial)). 165[github](https://github.com/sebastianotronto/emscripten-tutorial)).
166 166
167Anyway, now we can build our C code to run in a web page. But this is 167Anyway, now we can build our C code to run in a web page. But this is
@@ -324,7 +324,7 @@ The answer is 42
324 324
325The code for this example can be found in the `01_library` folder in 325The code for this example can be found in the `01_library` folder in
326the git repository 326the git repository
327([git.tronto.net](https://git.tronto.net/emscripten-tutorial/file/README.md.html), 327([git.tronto.net](https://git.tronto.net/emscripten-tutorial),
328[github](https://github.com/sebastianotronto/emscripten-tutorial)). 328[github](https://github.com/sebastianotronto/emscripten-tutorial)).
329 329
330## Intermezzo II: JavaScript and the DOM 330## Intermezzo II: JavaScript and the DOM
@@ -593,7 +593,7 @@ is included directly in `script.mjs`.
593 593
594You can find the full the code for this example the folder 594You can find the full the code for this example the folder
595`02_library_modularized` in the git repository 595`02_library_modularized` in the git repository
596([git.tronto.net](https://git.tronto.net/emscripten-tutorial/file/README.md.html), 596([git.tronto.net](https://git.tronto.net/emscripten-tutorial),
597[github](https://github.com/sebastianotronto/emscripten-tutorial)). 597[github](https://github.com/sebastianotronto/emscripten-tutorial)).
598 598
599## Multithreading 599## Multithreading
@@ -740,7 +740,7 @@ the server you are using; with darkhttpd you can use the `--header` option.
740With your server correctly set up, you can enjoy a multithreaded program 740With your server correctly set up, you can enjoy a multithreaded program
741running in your browser! As always, you can check out this example from 741running in your browser! As always, you can check out this example from
742the `03_threads` folder of the git repository 742the `03_threads` folder of the git repository
743([git.tronto.net](https://git.tronto.net/emscripten-tutorial/file/README.md.html), 743([git.tronto.net](https://git.tronto.net/emscripten-tutorial),
744[github](https://github.com/sebastianotronto/emscripten-tutorial)). 744[github](https://github.com/sebastianotronto/emscripten-tutorial)).
745 745
746## Intermezzo III: Web Workers and Spectre 746## Intermezzo III: Web Workers and Spectre
@@ -860,7 +860,7 @@ whose `data` property contains the object that was sent with `postMessage()`.
860 860
861You can check out this example in the directory `04_no_block` in the 861You can check out this example in the directory `04_no_block` in the
862repository 862repository
863([git.tronto.net](https://git.tronto.net/emscripten-tutorial/file/README.md.html), 863([git.tronto.net](https://git.tronto.net/emscripten-tutorial),
864[github](https://github.com/sebastianotronto/emscripten-tutorial)). 864[github](https://github.com/sebastianotronto/emscripten-tutorial)).
865Try also large numbers, in the range of millions or tens of millions, and 865Try also large numbers, in the range of millions or tens of millions, and
866compare it with the previous example - but not don't go too large, we 866compare it with the previous example - but not don't go too large, we
@@ -948,7 +948,7 @@ Other than that, you just need to add a couple of compiler flags:
948 out module at runtime with `addFunction()`. 948 out module at runtime with `addFunction()`.
949 949
950And as you can check by running the example `05_callback` from the repo 950And as you can check by running the example `05_callback` from the repo
951([git.tronto.net](https://git.tronto.net/emscripten-tutorial/file/README.md.html), 951([git.tronto.net](https://git.tronto.net/emscripten-tutorial),
952[github](https://github.com/sebastianotronto/emscripten-tutorial)), 952[github](https://github.com/sebastianotronto/emscripten-tutorial)),
953everything works as expected, both in Node.js and in a web page. To make 953everything works as expected, both in Node.js and in a web page. To make
954the examples more interesting, the web page one is not only not logging the 954the examples more interesting, the web page one is not only not logging the
@@ -1120,7 +1120,7 @@ And with all this, we are ready to run our optimized version of the
1120`primes_in_range()` algorithm, all from within our browser! As always, 1120`primes_in_range()` algorithm, all from within our browser! As always,
1121you can check out the complete code in the folder `06_storage` of 1121you can check out the complete code in the folder `06_storage` of
1122the repository 1122the repository
1123([git.tronto.net](https://git.tronto.net/emscripten-tutorial/file/README.md.html), 1123([git.tronto.net](https://git.tronto.net/emscripten-tutorial),
1124[github](https://github.com/sebastianotronto/emscripten-tutorial)). 1124[github](https://github.com/sebastianotronto/emscripten-tutorial)).
1125 1125
1126If generating this data on the user's side seems redundant, you can 1126If generating this data on the user's side seems redundant, you can
diff --git a/src/blog/2025-06-26-borrow-checker/borrow-checker.md b/src/blog/2025-06-26-borrow-checker/borrow-checker.md
index b22d741..10c4ac5 100644
--- a/src/blog/2025-06-26-borrow-checker/borrow-checker.md
+++ b/src/blog/2025-06-26-borrow-checker/borrow-checker.md
@@ -2,12 +2,11 @@
2 2
3As I mentioned in my [last post](../2025-06-13-cargo-culture-shock), 3As I mentioned in my [last post](../2025-06-13-cargo-culture-shock),
4in the last couple of weeks I have been learning Rust. I have written 4in the last couple of weeks I have been learning Rust. I have written
5[a small library](https://git.tronto.net/zmodn-rs/file/README.md.html) for 5[a small library](https://git.tronto.net/zmodn-rs) for
6[integers modulo N](https://en.wikipedia.org/wiki/Modular_arithmetic) 6[integers modulo N](https://en.wikipedia.org/wiki/Modular_arithmetic)
7(the original C++ version was mentioned in 7(the original C++ version was mentioned in
8[this post](../2025-01-21-taming-cpp-templates), rewritten 8[this post](../2025-01-21-taming-cpp-templates), rewritten
9[my implementation](https://git.tronto.net/ecm/file/README.md.html) 9[my implementation](https://git.tronto.net/ecm) of the
10of the
11[ECM algorithm](https://en.wikipedia.org/wiki/Lenstra_elliptic-curve_factorization) 10[ECM algorithm](https://en.wikipedia.org/wiki/Lenstra_elliptic-curve_factorization)
12(mentioned in [this other post](../2025-02-27-elliptic-curves-javascript)) 11(mentioned in [this other post](../2025-02-27-elliptic-curves-javascript))
13and I am now playing around with some past 12and I am now playing around with some past
diff --git a/src/blog/2025-11-29-aoc-download/aoc-download.md b/src/blog/2025-11-29-aoc-download/aoc-download.md
index 29e56fc..bbde45e 100644
--- a/src/blog/2025-11-29-aoc-download/aoc-download.md
+++ b/src/blog/2025-11-29-aoc-download/aoc-download.md
@@ -79,7 +79,7 @@ And you are good to go!
79Typing out the full command above may look cooler than downloading the file 79Typing out the full command above may look cooler than downloading the file
80by right-clicking "Save page as", but it is just as annoying. So obviously I 80by right-clicking "Save page as", but it is just as annoying. So obviously I
81saved that command to 81saved that command to
82[a script](https://git.tronto.net/scripts/file/aoc.html) 82[a script](https://git.tronto.net/scripts/tree/aoc)
83that also detects the correct file to download based on the current date 83that also detects the correct file to download based on the current date
84(or on two optional parameters for the year and the day). My script also 84(or on two optional parameters for the year and the day). My script also
85opens up an editor and [Lynx](https://en.wikipedia.org/wiki/Lynx_(web_browser)) 85opens up an editor and [Lynx](https://en.wikipedia.org/wiki/Lynx_(web_browser))
diff --git a/src/blog/2026-03-27-programming-20-years/20-years-of-programming.md b/src/blog/2026-03-27-programming-20-years/20-years-of-programming.md
index 8e5b1a2..1daa441 100644
--- a/src/blog/2026-03-27-programming-20-years/20-years-of-programming.md
+++ b/src/blog/2026-03-27-programming-20-years/20-years-of-programming.md
@@ -60,7 +60,7 @@ it creates a few more.
60 60
61I managed to recover some of the 61I managed to recover some of the
62programs I wrote between 2006 and 2010 in [a git 62programs I wrote between 2006 and 2010 in [a git
63repository](https://git.tronto.net/ancient-projects/file/README.md.html). 63repository](https://git.tronto.net/ancient-projects).
64The most successful one is JBriscola, a single-player game of 64The most successful one is JBriscola, a single-player game of
65[briscola](https://en.wikipedia.org/wiki/Briscola) with a decent AI. It is 65[briscola](https://en.wikipedia.org/wiki/Briscola) with a decent AI. It is
66actually quite fun to play, and a few of my friends played it regularly 66actually quite fun to play, and a few of my friends played it regularly
@@ -153,8 +153,7 @@ a PhD. But at the beginning of my PhD, in 2019, I wrote
153some code for work: my supervisor and a colleague of mine had 153some code for work: my supervisor and a colleague of mine had
154devised an algorithm to compute the degrees of certain [field 154devised an algorithm to compute the degrees of certain [field
155extensions](https://en.wikipedia.org/wiki/Field_extension), 155extensions](https://en.wikipedia.org/wiki/Field_extension),
156and I [implemented 156and I [implemented it](https://git.tronto.net/kummer-degrees).
157it](https://git.tronto.net/kummer-degrees/file/README.md.html).
158 157
159I don't know if this is what got me back into coding for fun, or if it 158I don't know if this is what got me back into coding for fun, or if it
160was just a matter of time, but by the end of 2019 I was already thinking 159was just a matter of time, but by the end of 2019 I was already thinking
diff --git a/src/blog/2026-08-15-dotfiles/dotfiles.md b/src/blog/2026-08-15-dotfiles/dotfiles.md
new file mode 100644
index 0000000..ce10ef0
--- /dev/null
+++ b/src/blog/2026-08-15-dotfiles/dotfiles.md
@@ -0,0 +1,88 @@
1# Dotfiles backup and bootstrap
2
3It took me more than 18 years of using Linux, but I have finally bought
4a used [Thinkpad](https://en.wikipedia.org/wiki/ThinkPad), thus becoming
5a *real* Linux user. To be specific, I got a Thinkpad L13 from ~2020 with
6an Intel i5 CPU and 8Gb of RAM.
7
8After I bought the laptop, it was time to set it up to my likings. I usually
9do this by installing a Linux distro and then manually copying my
10configuration files (a.k.a. *dotfiles*) from some messy backup folder. Since
11I do this quite rarely, and since when I do I also tend to pick a different distro
12just to try it out, I have never bothered automating this process...
13
14...But not anymore! This time I decided to set things up properly.
15
16## OS choice: Alpine Linux
17
18For the operating system, I chose [Alpine Linux](https://alpinelinux.org/).
19It is an extremely simple Linux distribution that relies on minimalistic
20core tools - for example, it uses [busybox](https://busybox.net/) instead of
21[GNU coreutils](https://www.gnu.org/software/coreutils/) and
22[OpenRC](https://en.wikipedia.org/wiki/OpenRC) instead of
23[SystemD](https://en.wikipedia.org/wiki/SystemD). Its package manager is incredibly
24fast (and it can be used [declaratively](../2025-08-16-alpine-declarative)) and
25it's [wiki](https://wiki.alpinelinux.org/wiki/Main_Page) is well-maintained.
26I am liking it a lot, but your mileage may vary - especially because it uses
27[musl](https://musl.libc.org/) as the system C library, breaking compatibility
28with some pre-built applications and, notably, with video streaming platforms
29that rely on [DRM](https://en.wikipedia.org/wiki/Digital_rights_management).
30
31Other options I considered were [Void Linux](https://voidlinux.org),
32that I have happily used since 2020, [OpenBSD](https://www.openbsd.org),
33that I am using on my server and on my old [netbook](../2022-09-10-netbooks),
34[Debian](https://www.debian.org), that I am using on my [gaming
35desktop](../2023-10-15-build-time) and [Slackware](http://www.slackware.com),
36the old time favorite that I used back in 2009-2013. I am not going to explain
37the reasons why I settled on Alpine in the end; it is mostly a matter of
38personal preference anyway.
39
40## Configuration files as a git repository
41
42As for my configuration files, they are now managed via a [git
43repository](https://git.tronto.net/config), as explained in [this blog post
44by Drew De Vault](https://drewdevault.com/blog/dotfiles). In short:
45
46* My home directory is a git repository.
47* All files are ignored by default (my `.gitignore` contains a single line: `*`).
48* Configuration files that I wish to track are manually added with
49 `git add -f my_file`.
50
51This way, the path of each file is preserved in the structure of the
52repository, and cloning it into a new system's `$HOME` makes everything
53fall into place.
54
55There is a small caveat with this setup: every file and directory that is
56directly or indirectly contained in my home, even if `gitignore`'d, is now
57part of this git repository. This includes other git repositories, and this
58could break certain development tools - for example, I had issues with
59[ty](https://docs.astral.sh/ty) ignoring all files due to them being
60`gitignore`'d by my configuration file repository.
61
62While I was at it, I have also moved my [scripts](https://git.tronto.net/scripts)
63into this repository, since they are part of my desktop setup anyway.
64
65## Bootstrapping
66
67Copying configuration files into the right place is not the only thing
68I need to do when I set up a new laptop. I also need to install packages,
69build some software from source (for example, [dwm](https://dwm.suckless.org)),
70edit some configuration files that are outside of `$HOME` (for example,
71in `/etc`), and so on.
72
73I tried to automate these steps as much as I could turned them into [a
74script](https://git.tronto.net/config/tree/scripts/setup-config-alpine). I
75won't explain everything it does here, you can just read through it if you want -
76it is pretty self-explanatory. This script also takes care of cloning the dotfiles
77repository I mentioned above, so when I set up a new system I just need to download
78a copy of this script from my server and run it.
79
80The script ends by printing some instruction on the remaining manual steps,
81such as uploading my SSH keys into some machines that I regularly
82access remotely and copying copying some secrets into `.ssh`.
83
84## Conclusion
85
86This setup may be a bit overengineered, but it gives me a consistent way to
87quickly set up a new computer, and it also serves as documentation on my local
88configuration.
diff --git a/src/blog/2026-09-05-cgit/cgit.md b/src/blog/2026-09-05-cgit/cgit.md
new file mode 100644
index 0000000..29d92ba
--- /dev/null
+++ b/src/blog/2026-09-05-cgit/cgit.md
@@ -0,0 +1,141 @@
1# From stagit to cgit
2
3When I first set up this website back in 2022, I also started self-hosting
4my git repositories. To make them accessible via web I used
5[stagit](https://codemadness.org/stagit.html), and I wrote about this
6in [an old blog post](..//2022-11-23-git-host/). In short, I used a custom
7post-receive [git
8hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) that used
9stagit to generate the HTML pages for [my git
10website](https://stagit.tronto.net).
11
12This script ran every time I pushed some changes to a repository.
13After calling stagit, the script would also modify the generated
14pages to add a custom Download button at the top, which was not
15efficient. For my largest repositories, this took around
16a couple of minutes for every `git push`. Moreover, having all the file
17contents both in the git folder and in the HTML pages wasted some
18space on my small VM.
19
20So I looked for alternatives, and I found
21[cgit](https://git.zx2c4.com/cgit/about/), which works quite differently
22from stagit. I gave it a try, and I am quite happy with the result! If
23you want to check it out, go to [git.tronto.net](https://git.tronto.net).
24A frozen version of the old stagit-generated pages is still available at
25[stagit.tronto.net](https://stagit.tronto.net).
26
27## Static pages versus CGI
28
29Instead of generating pages to be served by a
30[web server](https://en.wikipedia.org/wiki/Web_server), cgit is
31based on [CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface).
32To put it simply, cgit is a program that continuously runs on a server,
33generating on the fly each page a visitor requests.
34
35There is an obvious trade-off between disk space and CPU usage here:
36on the one hand we don't need to store all the HTML pages that are
37essentially a duplicate of what can already be found in the git
38repository's folder; on the other hand, computing the page on the
39go takes some work for the server's CPU. However, cgit can also
40cache the most recently viewed pages, so it does not have to re-compute
41the most requested ones all that often.
42
43Of course, another cost is the more complex setup, as we are now dealing with
44a full-blown web application instead of plain and simple static HTML files.
45We'll get into some of the problems that this causes in the next section.
46
47## OpenBSD and cgit
48
49As you may know, the [VM](https://en.wikipedia.org/wiki/Virtual_machine)
50that hosts this website has historically been running on
51[OpenBSD](https://openbsd.org) (spoiler: this is no longer the case).
52When it comes to hosting cgit, or any CGI application, this comes with
53some pros and some cons.
54
55First off, the pros: OpenBSD's base system already has a web server
56([httpd](https://man.openbsd.org/httpd.8)) and a FastCGI server
57([slowcgi](https://man.openbsd.org/slowcgi.8)) that are capable of
58running cgit. So no external program is strictly needed other than
59cgit itself - see [this short
60tutorial](https://codemadness.org/openbsd-httpd-and-cgit.html) for
61details.
62
63But there are some points of friction that arise from one of httpd's
64most-loved security features: the fact that it works in a
65[chroot](https://en.wikipedia.org/wiki/Chroot) environment, by default
66rooted at `/var/www`. This means that httpd cannot see any file outside
67of `/var/www`. So any file that cgit needs, including all the git
68repositories that one wants to show, must be inside `/var/www`.
69
70And while it is not much effort to put them there, I have been
71managing my repositories via a dedicated `git` user, keeping them in
72`/home/git`. So I would have to either change this user's home directory
73to something in `/var/www`, or change the relative path of each repository.
74Either way, it wouldn't be as nice as my current setup.
75
76But the repositories are not all cgit may want to know about. For example,
77one can *filter* README files through a Markdown parser, such as
78[lowdown](https://kristaps.bsd.lv/lowdown/), to display more nicely on the
79web - see [this README](https://git.tronto.net/nissy-core/about/) for an
80example. The parser, too, must live within httpd's chroot. Same for any
81[dynamic library](https://en.wikipedia.org/wiki/Dynamic_library) it
82depends on. To make this work, I ended up creating `usr/bin` and `usr/lib`
83folders inside `/var/www` and manually copied some executables and libraries
84there - not the cleanest solution.
85
86Alternatively, one may configure httpd to chroot at `/`, making things
87more practical but loosing the security benefits. But at this point,
88I decided I wanted to try out a different stack - new VPS provider, new
89OS, new web server. This is something I had been thinking about for
90about a year at this point, and I'll talk about the reasons in [my
91next post](../2026-09-13-host-migration).
92
93But if you plan to host cgit on OpenBSD, do not be discouraged!
94Everything can be set up with just a little manual work.
95
96## My cgit configuration
97
98My new cgit instance is hosted on an [Alpine Linux](https://alpinelinux.org)
99VM and it is running via [Lighttpd](https://www.lighttpd.net).
100For the basic setup, I followed [this wiki
101page](https://wiki.alpinelinux.org/wiki/Cgit) (note that lighttpd has a
102`mod_cgi` module that replaces fcgiwrap entirely). Not much
103to say here, just a little fiddling with lighttpd's configuration.
104
105As for customization, my configuration files are available in my
106[cgit-config](https://git.tronto.net/cgit-config) repository. The
107main configuration file,
108[cgitrc](https://git.tronto.net/cgit-config/tree/cgitrc), is
109well-commented, and won't require further explanation.
110
111There are a bunch of other files too, such as the custom
112[about-filter.sh](https://git.tronto.net/cgit-config/tree/custom/about-filter.sh)
113which, is used to display README files more nicely. As for the custom
114[css](https://git.tronto.net/cgit-config/tree/custom/cgit.css), the
115main feature is making the website a little more comfortable to
116browse on mobile; I shamelessly copied this part from [another cgit
117user](https://git.matejamaric.com/responsive-cgit-css).
118
119## Pros and con(cern)s
120
121So far, cgit seems to run pretty fast on my new VM with a single CPU
122core and 1GB of RAM. It also looks pretty cool, even though I liked
123stagit's simplicity.
124
125Unfortunately, the nice download button that I added to each of my
126repositories is now gone. cgit allows downloading tarballs of a repo,
127but only from tags, not for the current state of the master branch.
128Overall, stagit's simplicity also allowed for great deal of customizability.
129
130I am also a bit concerned about AI
131[crawlers](https://en.wikipedia.org/wiki/Web_crawler). I have heard horror
132stories of people having to make their repositories private because of
133bots scanning their pages to feed the slop machine overloading their servers.
134However, I hope cgit being quite small compared to a
135[forge](https://en.wikipedia.org/wiki/Forge_(software)) such as
136[GitLab](https://en.wikipedia.org/wiki/GitLab) or
137[Gitea](https://en.wikipedia.org/wiki/Gitea) will help my server
138sustain the extra effort - if any bot is interested in my code at all.
139
140In conclusion, stagit served me well for a while, and I think
141cgit is better suited to my needs now.
diff --git a/src/blog/2026-09-13-host-migration/host-migration.md b/src/blog/2026-09-13-host-migration/host-migration.md
new file mode 100644
index 0000000..72a26ef
--- /dev/null
+++ b/src/blog/2026-09-13-host-migration/host-migration.md
@@ -0,0 +1,172 @@
1# Host migration
2
3Since this website went online in 2022, It has lived
4in a virtual machine on server 14 at [OpenBSD
5Amsterdam](https://openbsd.amsterdam). This is a small, independent
6VPS provider that donates large part of their profit to the
7[OpenBSD foundation](https://www.openbsdfoundation.org). They
8are pretty cool, and their service worked quite well for me.
9
10Nonetheless, I have recently migrated to another provider, and I
11am not going to renew my OpenBSD Amsterdam subscription next year.
12There are a few reasons for this.
13
14## Why switch?
15
16First of all, I want to make clear that I did not have any issue
17with OpenBSD Amsterdam. In fact, I think it was the right choice for
18me 4 years ago, and I can strongly recommend it.
19
20OpenBSD as well was a great OS choice, at the beginning.
21The convenience of having many of the services I needed - such as
22[httpd](https://man.openbsd.org/httpd),
23[rsync](https://man.openbsd.org/openrsync),
24[ssh](https://man.openbsd.org/ssh) - included in the base system and
25well-documented was big. But OpenBSD is also an
26[opinionated](https://www.merriam-webster.com/dictionary/opinionated)
27piece of software,
28and some of its "opinions" started feeling a bit restrictive.
29
30For example, OpenBSD nudges you into using separate
31[partitions](https://en.wikipedia.org/wiki/Disk_partitioning) for
32different system folders, for security reasons. This is how the 50GB
33of my OpenBSD Amsterdam VM are currently allocated:
34
35```
36[pizoc ~] $ df -h
37Filesystem Size Used Avail Capacity Mounted on
38/dev/sd0a 986M 111M 825M 12% /
39/dev/sd0k 17.4G 3.9G 12.6G 24% /home
40/dev/sd0d 3.2G 8.0K 3.0G 1% /tmp
41/dev/sd0f 5.2G 1.7G 3.3G 34% /usr
42/dev/sd0g 986M 545M 392M 59% /usr/X11R6
43/dev/sd0h 6.7G 184M 6.2G 3% /usr/local
44/dev/sd0j 5.8G 2.0K 5.5G 1% /usr/obj
45/dev/sd0i 1.9G 2.0K 1.8G 1% /usr/src
46/dev/sd0e 5.0G 4.4G 423M 92% /var
47```
48
49My websites are in `/var/www`, and as you can see that partition
50is almost full. I also use `/home` extensively - my git repositories
51are in `/home/git` and a shared
52[syncthing](https://syncthing.net) folder is in `/home/sebastiano`.
53I have plenty of space still available in `/home`, but I can't
54esily use it for hosting websites, because of httpd's chroot. See
55[my previous post](../2026-09-05-cgit) for details on what this means.
56
57Another downside of httpd is that it is not as feature-complete
58as other web server. This can be considered an advantage, but
59occasionally it requires some extra setup for certain use cases.
60For example, [until
61recently](https://undeadly.org/cgi?action=article;sid=20260725103657)
62it did not support custom HTTP headers, so I had to combine it
63with relayd when I wanted to experiment with a [web
64application](https://h48.tronto.net) I was working on - see also
65[my post on WebAssembly](../2025-06-06-webdev/) for context.
66Once again, this was not a showstopper, but
67it was unnecessary additional friction.
68
69Lastly, my provider was a bit more expensive than I would have
70liked: 71€ per year for a VM with 1GB of RAM and 50GB of
71storage. For comparison, I am now paying 22€ per year for
72a VM with the same RAM and 30GB of storage. To be fair,
73OpenBSD Amsterdam is a small, independent provider, and they
74donate a most of their revenuw to the OpenBSD foundation; I was
75happy to support them. But I am also happy to save 49€
76per year.
77
78## The new stack
79
80My new provider is [netcup](https://www.netcup.com/en), an established
81German company. I don't personally know anyone hosting there,
82but their prices are good and the reviews are positive. Their [smallest
83VPS](https://www.netcup.com/en/server/vps-lite) is only 1.87€ per
84month, and it is enough for my needs.
85
86They support any operating system that can boot from a
87[Qcow](https://en.wikipedia.org/wiki/Qcow) image, as you can upload your
88own; so technically I could have stayed with OpenBSD. But I wanted
89to change the OS for the reasons I gave in the previous section, so I
90went with [Alpine Linux](https://alpinelinux.org), a lightweight
91Linux distribution that I have been pleasantly using on my laptop for a
92while now.
93
94As for the web server, I did not give it much thought.
95[Lighttpd](https://www.lighttpd.net) seems fairly lightweight and it
96does what I need it to do, so I went with that.
97
98## Migration hiccups
99
100I initially planned to migrate my [git server](../2026-09-05-cgit)
101and this website one at the time, but soon I realized that it would have
102been less work and less risk to do everything at once. So I set aside
103a full Sunday afternoon to move everything over.
104
105Unfortunately, I had some issues. The biggest one, that took me over
106three hours to work around, was related to setting up my SSL
107certificates - the "S" in [HTTPS](https://en.wikipedia.org/wiki/HTTPS).
108I wanted to use the same software I was using on OpenBSD,
109[acme-client](https://man.openbsd.org/acme-client.1), but something
110went wrong. I kept getting an HTTP 409 error with the following
111explanation:
112
113```
114acme-client: transfer buffer: [{
115"type": "urn:ietf:params:acme:error:conflict",
116"detail": "Unable to update challenge :: failed to mark authz as processing: Authorization is already being validated. This may indicate your client attempted the same challenge multiple times, possibly due to a client bug.",
117"status": 409
118}] (296 bytes)
119acme-client: bad exit: netproc(31648): 1
120```
121
122Searching online, I found out that I was [not the only
123one](https://www.reddit.com/r/openbsd/comments/1vz4mcg/acmeclient_bad_http_409)
124with this problem, so I decided to use [certbot](https://certbot.eff.org)
125as a temporary workaround. But I still want to go back to
126acme-client at some point.
127
128The other issue was AI. And I am not talking about OpenAI's and
129Anthropic's bots accessing my git pages every 0.9 seconds (that
130is not an exaggeration, I `tail -f`'d the log file). I am
131talking about actually trying to use these chatbots for their
132intended purpose. Namely, instead of reading the manual pages
133for lighttpd and writing a configuration file from scratch,
134I asked AI (either [duck.ai](https://duck.ai)) or
135[Kagi Assistant](https://kagi.com/assistant/), I forgot which one)
136to translate my httpd configuration file to a lighttpd one. Then
137I could look up the documentation for just the settings I was
138using, saving some time. Or so I thought.
139
140First of all, the initial response had more stuff than
141I wanted. The bot just allucinated features that were not included
142in the original configuration. But that's alright, it's just how
143the slop machine works.
144
145But then there were also errors, in particular with setting
146up the redirects from my `http://*.tronto.net` domains to their
147`https://` counterparts. I went through various iterations of
148"this does not work, it does X instead of Y, please fix" and
149"You are absolutely right! Here is the fixed version",
150but somehow the bots could
151never come up with a working configuration. I ended up fixing
152it by hand like a caveman, as I should have done from the
153beginning. What a waste of time.
154
155But by the end of the afternoon, almost everything was working
156as intended.
157
158## My experience so far
159
160So far everything is working smoothly. Once in a while I notice
161a minor mistake I made during the setup and I fix it - for example,
162I have just noticed this morning that lighttpd's access log was
163eating most of my storage, so I disabled it. But everything is now
164up and running, and this page you are reading is served by my new
165stack - unless you are reading it years after I published this
166post and I have changed my setup again in the meantime.
167
168The only real difference I noticed is that when I use `rsync`
169to update my website, the whole process is much, much faster
170- like 10x faster. I don't know if this is because the new
171server has a much faster hard drive or because OpenBSD's `rsync`
172was much slower. In any case, it is a nice surprise!

Generated with cgit - Back to sebastiano.tronto.net