<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><title>IT Notes - bssg</title><link>https://it-notes.dragas.net/categories/bssg/</link><description>Articles in category bssg</description><atom:link href="https://it-notes.dragas.net/categories/bssg/feed.xml" rel="self"/><language>en</language><lastBuildDate>Tue, 22 Apr 2025 07:30:36 +0200</lastBuildDate><atom:link href="https://it-notes.dragas.net/categories/bssg/feed.xml" rel="self" type="application/rss+xml"/><item><title>Make Your Own Internet Presence with NetBSD and a 1 euro VPS – Part 1: Your Blog</title><link>https://it-notes.dragas.net/2025/04/22/make-your-own-internet-presence-with-netbsd-and-a-1-euro-vps-part-1-your-blog/</link><description>&lt;p&gt;&lt;img src="https://it-notes.dragas.net/featured/terminal_htop.webp" alt="Photo: Terminal screen with htop"&gt;&lt;/p&gt;&lt;h2&gt;Why NetBSD?&lt;/h2&gt;
&lt;p&gt;For many years, I've been using (and appreciating) &lt;a href="https://www.netbsd.org/"&gt;NetBSD&lt;/a&gt; because it's stable, efficient, and reliable. The codebase has proven its reliability, &lt;a href="https://it-notes.dragas.net/2023/08/27/that-old-netbsd-server-running-since-2010/"&gt;running without reboots for years without issues&lt;/a&gt;. It supports ZFS (though differently than FreeBSD), LVM (useful for those accustomed to it on Linux), the ability to take filesystem snapshots (UFS2, making ZFS less crucial), and it's an &lt;a href="https://www.netbsd.org/docs/guide/en/chap-virt.html"&gt;excellent virtualization platform&lt;/a&gt;. Installation and updates are easy (including via &lt;a href="https://www.netbsd.org/docs/guide/en/chap-upgrading.html#using-sysupgrade"&gt;sysupgrade&lt;/a&gt; - which I'll cover in a future article). Since it focuses on portable and optimized code (running on ancient architectures requires cleanliness and correctness), it's particularly efficient on low-power devices, like embedded systems or cheap VMs. Therefore, it's one of the best solutions for a small personal setup that can still deliver excellent results and simple management.&lt;/p&gt;
&lt;p&gt;Indeed, the market offers very cheap VPS, often with just a single core and little RAM. But a modern single core packs power that a multi-core from just a few years ago could only dream of, and often, the I/O of these machines (a bottleneck for many services) is still decent. I personally use 1 euro per month VPS (VAT included - for those not subject to it, that's less than one euro per month!) with a public IPv4 address and (often) a /64 IPv6 block, ensuring full reachability across the entire network.
I'm not providing direct links as I have no affiliations, but netcup's "piko" VPS are among the types I use most often (&lt;a href="https://it-notes.dragas.net/2025/02/26/fedimeteo-how-a-tiny-freebsd-vps-became-a-global-weather-service-for-thousands/"&gt;a 4 euro/month netcup VM handles the entire FediMeteo project&lt;/a&gt;), and this type of VM is ideal for our purpose because some providers (like netcup) allow you to upload your own ISO and install your preferred operating system. On VPS like these, I've installed everything - including &lt;a href="https://omnios.org/"&gt;OmniOS&lt;/a&gt; and &lt;a href="https://www.tritondatacenter.com/smartos"&gt;SmartOS&lt;/a&gt; - without problems. And even such a small VPS, with an efficient operating system, can be extremely satisfying.&lt;/p&gt;
&lt;h2&gt;Why BSSG?&lt;/h2&gt;
&lt;p&gt;In this article, I'll describe how to create and publish a blog using &lt;a href="https://bssg.dragas.net"&gt;BSSG&lt;/a&gt; as it exemplifies my concept of portability and minimalism. BSSG on NetBSD currently doesn't leverage parallelism provided by tools like GNU Parallel, but for small to medium-sized blogs, this won't be an issue, especially considering these small VMs only have 1 core. Obviously, you can use any Static Site Generator (SSG) (like Hugo, Nikola, 11ty, Pelican, Zola, etc.) - the important thing is to have a static site served by a simple web server.&lt;/p&gt;
&lt;h2&gt;Let's Start with the Installation&lt;/h2&gt;
&lt;p&gt;Installing NetBSD is quite straightforward and is clearly covered, complete with explanatory screenshots, in the &lt;a href="https://www.netbsd.org/docs/guide/en/chap-exinst.html"&gt;excellent official NetBSD documentation&lt;/a&gt;, which I recommend using as a reference during the process, especially if it's your first time.&lt;/p&gt;
&lt;p&gt;In my case, I made sure to use the proposed disk geometry, use the standard automatic partitioning, but &lt;strong&gt;enable the "log" and "noatime" options for the filesystem&lt;/strong&gt;.
Both these options will provide a huge advantage in I/O operations, especially with BSSG, as the first enables journaling and the second prevents updating file metadata on every access. BSSG is more I/O bound than CPU bound, so any optimization is beneficial.&lt;/p&gt;
&lt;p&gt;Moving forward, I also recommend configuring the network (although installation can be done from packages on the installation ISO). For netcup, you can use DHCPv4 (even though it's a bit slow and sometimes seems to fail, the DHCP client will continue running in the background and eventually work).&lt;/p&gt;
&lt;p&gt;For IPv6, I usually configure it manually later, so I'll describe that further down.&lt;/p&gt;
&lt;p&gt;I also recommend enabling SSH, adding a regular user (and adding them to the &lt;code&gt;wheel&lt;/code&gt; group so they can gain root privileges) - in this case, I'll call the user &lt;em&gt;blog&lt;/em&gt;. Also, enable the installation of binary packages, as it will be convenient later to use &lt;code&gt;pkgin&lt;/code&gt; to install and update all necessary packages. All these steps are described clearly and in detail in the &lt;a href="https://www.netbsd.org/docs/guide/en/chap-exinst.html"&gt;guide&lt;/a&gt;, so I won't detail them here. But they are simple and logical, like all operations on BSD systems.&lt;/p&gt;
&lt;p&gt;After installation, reboot. If everything went correctly, you should be able to log in via console or SSH using the "blog" user (or whatever you named it).&lt;/p&gt;
&lt;p&gt;First, I suggest configuring the IPv6 address and installing the necessary packages.&lt;/p&gt;
&lt;p&gt;For IPv6, in the case of netcup, simply add one of the assigned addresses to the interface. In NetBSD, &lt;a href="https://www.netbsd.org/docs/guide/en/chap-net-practice.html"&gt;network interface configurations are stored (similar to OpenBSD) in specific files&lt;/a&gt;. For the first virtio interface, the file will be &lt;code&gt;/etc/ifconfig.vioif0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You need to elevate your privileges to root, open that file with your preferred editor, and add the configuration to the file itself:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ su -l
nb1euro# vi /etc/ifconfig.vioif0

inet6 your-ipv6-addr/64
up
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To test everything, perform a reboot and try pinging an IPv6 address (I often use &lt;code&gt;ping6 google.com&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;If all goes well, after a few seconds, you should see ping replies, confirming everything is configured correctly.&lt;/p&gt;
&lt;p&gt;Regarding packages, the only two strictly necessary ones are &lt;code&gt;bash&lt;/code&gt; and a markdown processor (by default, BSSG will use &lt;code&gt;commonmark&lt;/code&gt;; otherwise, it can be configured to use &lt;code&gt;pandoc&lt;/code&gt; or &lt;code&gt;Markdown.pl&lt;/code&gt;). &lt;code&gt;rsync&lt;/code&gt; can be useful for deployment. &lt;code&gt;sudo&lt;/code&gt; (or &lt;code&gt;doas&lt;/code&gt;) can be useful for elevating privileges for certain operations, at least at this stage.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ su -l
nb1euro# pkgin in bash cmark rsync sudo
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you're used to Linux, you can also install the "nano" editor:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro# pkgin in nano
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If &lt;code&gt;sudo&lt;/code&gt; was installed, it's now appropriate to grant users in the "wheel" group (like the regular user created during installation) the ability to elevate privileges. Edit the &lt;code&gt;sudoers&lt;/code&gt; file (I suggest using the &lt;code&gt;visudo&lt;/code&gt; command) and uncomment this line:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;## Uncomment to allow members of group wheel to execute any command
%wheel ALL=(ALL:ALL) ALL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point, you can switch back to operating as the regular user, downloading and unpacking BSSG:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ ftp https://brew.bsd.cafe/stefano/BSSG/archive/0.15.1.tar.gz
nb1euro$ tar zxfv 0.15.1.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that BSSG is ready, just initialize a directory with the structure for the new site:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ cd bssg
nb1euro$ ./bssg.sh init /home/blog/myblog
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Everything is set to start generating your blog. I recommend reading BSSG's &lt;code&gt;README.md&lt;/code&gt;. There are many options, themes, etc., but to get started, you just need to set the site's public URL. For example, if the site will be published as &lt;em&gt;myblog.example.com&lt;/em&gt; - just create a file at &lt;code&gt;/home/blog/myblog/config.sh.local&lt;/code&gt; (the path defined by the init command) and set the public URL:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;SITE_URL=&amp;quot;https://myblog.example.com&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way, all URLs will be absolute URLs, which is necessary to ensure the correct functioning of RSS feeds, sitemaps, etc. This setting assumes HTTPS - if you just want to test the site over HTTP, simply use &lt;code&gt;http&lt;/code&gt; and then, optionally, change it to &lt;code&gt;https&lt;/code&gt; and regenerate the site later.&lt;/p&gt;
&lt;p&gt;You can already create your first test post, directly from the BSSG directory:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ ./bssg.sh post
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The system will use &lt;code&gt;nano&lt;/code&gt; if it's installed, otherwise it will use &lt;code&gt;vi&lt;/code&gt;. Don't worry, in the latter case, BSSG will write the procedure for exiting &lt;code&gt;vi&lt;/code&gt; as the post's text 🙂&lt;/p&gt;
&lt;p&gt;Once you save the post, BSSG will automatically generate the site. If everything went well, the &lt;code&gt;/home/blog/myblog/output&lt;/code&gt; directory will contain the final result. We are therefore ready for the first deployment, which can be done in many different ways. I will cover three:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Using &lt;a href="http://www.eterna23.net/bozohttpd/"&gt;bozohttpd&lt;/a&gt;, present &lt;a href="https://man.netbsd.org/httpd.8"&gt;by default in NetBSD's base system&lt;/a&gt;. It can be used via &lt;code&gt;inetd&lt;/code&gt; (launching an httpd process for each connection) or as a daemon. I'll describe the first option, showing in the final benchmarks how, even when used as a daemon, it remains a less performant solution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using nginx&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using Caddy&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First, it's advisable to obtain a certificate to configure and use HTTPS. If you only want to test using HTTP, this part can be safely bypassed. For solutions 1 and 2, I'll use &lt;code&gt;certbot&lt;/code&gt;, which is well-known to many users with Linux experience. Caddy, on the other hand, manages certificates automatically, so there's no need for other solutions and thus no need to install &lt;code&gt;certbot&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo pkgin in py313-certbot
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To use &lt;code&gt;bozohttpd&lt;/code&gt;, no further installation is necessary. At this point, the options diverge.&lt;/p&gt;
&lt;h2&gt;Using NetBSD's Integrated httpd&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;bozohttpd&lt;/code&gt; is integrated into NetBSD and, by default, can be launched directly via &lt;code&gt;inetd&lt;/code&gt;. This solution, while not extremely efficient or scalable, is simple and requires few resources. It's fine if you expect only a few visits per day, but when used via &lt;code&gt;inetd&lt;/code&gt;, the initial latency for each connection is tangible. It can still be useful for some tests or small deployments.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;/etc/inetd.conf&lt;/code&gt; file already contains the options to handle this situation:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;#http           stream  tcp     nowait:600      _httpd  /usr/libexec/httpd      httpd /var/www
#http           stream  tcp6    nowait:600      _httpd  /usr/libexec/httpd      httpd /var/www
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By uncommenting these two lines and restarting &lt;code&gt;inetd&lt;/code&gt; (&lt;code&gt;service inetd restart&lt;/code&gt;), the server will start responding to HTTP requests on both IPv4 and IPv6.&lt;/p&gt;
&lt;p&gt;If you want to add HTTPS support, no problem. Just request a certificate via &lt;code&gt;certbot&lt;/code&gt; and specify the webroot.&lt;/p&gt;
&lt;p&gt;Run:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo certbot-3.13 certonly
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Choose option 2 - the one where you specify the webroot - enter the domain, and when prompted, provide &lt;code&gt;/var/www/&lt;/code&gt; as the webroot.&lt;/p&gt;
&lt;p&gt;The certificate will be created. Then, modify the &lt;code&gt;/etc/inetd.conf&lt;/code&gt; file to also include support for HTTPS, adding two lines similar to these (obviously, change the certificate paths):&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;https            stream  tcp     nowait:600      _httpd  /usr/libexec/httpd      httpd -Z /usr/pkg/etc/letsencrypt/live/myblog.example.com/fullchain.pem /usr/pkg/etc/letsencrypt/live/myblog.example.com/privkey.pem /var/www
https            stream  tcp6    nowait:600      _httpd  /usr/libexec/httpd      httpd -Z /usr/pkg/etc/letsencrypt/live/myblog.example.com/fullchain.pem /usr/pkg/etc/letsencrypt/live/myblog.example.com/privkey.pem /var/www
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: &lt;code&gt;httpd&lt;/code&gt; will run with the permissions of the &lt;code&gt;_httpd&lt;/code&gt; user, so make sure all certificates are readable by that user:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro# chown -R _httpd /usr/pkg/etc/letsencrypt/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Restart &lt;code&gt;inetd&lt;/code&gt;, and the server will also respond over HTTPS.&lt;/p&gt;
&lt;p&gt;To make your blog public, simply copy the files from the site's output directory to &lt;code&gt;/var/www/&lt;/code&gt; - this time using &lt;code&gt;sudo&lt;/code&gt; to bypass permission issues:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo rsync -avhHPx /home/blog/myblog/output/ /var/www/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The site will be immediately visible.&lt;/p&gt;
&lt;h2&gt;Using nginx&lt;/h2&gt;
&lt;p&gt;Nginx is fast and efficient, and the performance difference is noticeable (some benchmarks follow below). For an efficient setup ready for a high number of visits, it's advisable to use a web server suited for the purpose, just like nginx.&lt;/p&gt;
&lt;p&gt;First, install nginx and the certbot plugin for nginx. This will simplify the installation and renewal of certificates:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo pkgin in py313-certbot-nginx nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Copy the startup script to &lt;code&gt;/etc/rc.d&lt;/code&gt; - as indicated by the post-installation message. In NetBSD, this operation must be done manually, but it's always pointed out:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo cp /usr/pkg/share/examples/rc.d/nginx /etc/rc.d
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: If you previously used &lt;code&gt;httpd&lt;/code&gt; from &lt;code&gt;inetd&lt;/code&gt; following the previous solution, you must disable it in &lt;code&gt;inetd.conf&lt;/code&gt; and restart &lt;code&gt;inetd&lt;/code&gt; to free up ports 80 and 443.&lt;/p&gt;
&lt;p&gt;Now you can create a virtual host for our new site.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo vi /usr/pkg/etc/nginx/nginx.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and add, at the end of the file and before the final closing curly brace:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;server {
        listen 80;
        # If you also have configured IPv6 support
        listen [::]:80;

        root /var/www;
        index index.html index.htm;

        server_name myblog.example.com;

        # If you want a long cache for media and css - be careful, this means that if you change to a new theme, it might not be visible immediately as the browser might still use the old cached one
        location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
            expires 30d;
            add_header Cache-Control &amp;quot;public, no-transform&amp;quot;;
        }

        location / {
                try_files $uri $uri/ =404;
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, it's time to configure the system to enable nginx. Just edit &lt;code&gt;/etc/rc.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo vi /etc/rc.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and add:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nginx=YES
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, you can start nginx:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo service nginx start
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nginx will start listening on port 80. Generating and installing the certificate is very simple:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo certbot-3.13 --nginx -d myblog.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This command will request the certificate and install it, so nginx will already be configured to use it.&lt;/p&gt;
&lt;p&gt;As with the previous method, to make your blog public, simply copy the files from the site's output directory to &lt;code&gt;/var/www/&lt;/code&gt; - using &lt;code&gt;sudo&lt;/code&gt; to bypass permission issues:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo rsync -avhHPx /home/blog/myblog/output/ /var/www/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The site will be immediately visible.&lt;/p&gt;
&lt;h2&gt;Using Caddy&lt;/h2&gt;
&lt;p&gt;Caddy is a convenient and all-in-one solution, efficient and fast. It's packaged for NetBSD and allows you to go online in a flash. I won't delve into the configuration because there are many tutorials (&lt;a href="https://caddyserver.com/docs/getting-started"&gt;including the official ones&lt;/a&gt;), but you just need to install it and run it:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo pkgin in caddy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once installed, go to the directory you want to serve (e.g., &lt;code&gt;/var/www&lt;/code&gt; or directly &lt;code&gt;/home/blog/myblog/output&lt;/code&gt;) and run:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;nb1euro$ sudo caddy file-server --domain myblog.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Caddy will start, request the certificate, and begin serving your blog over HTTPS as well. To install Caddy as a service (i.e., with a configuration file, etc.), you can proceed similarly to how it's done on Linux. The NetBSD Caddy package doesn't include the &lt;code&gt;rc.d&lt;/code&gt; script, but you can copy and paste one (into &lt;code&gt;/etc/rc.d/caddy&lt;/code&gt;) from &lt;a href="https://www.unitedbsd.com/d/1406-caddy-service/4"&gt;a thread posted on UnitedBSD&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Performance Comparison&lt;/h2&gt;
&lt;p&gt;I performed some performance tests on these solutions. Here are the results, on a single-core 1 euro/month VPS, from my home connection (which also has its own limitations):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NetBSD httpd via inetd:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;Running 10s test @ https://myblog.example.com/
  4 threads and 50 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   213.52ms  173.10ms   1.11s    76.01%
    Req/Sec    12.92      9.19    50.00     75.91%
  371 requests in 10.10s, 1.39MB read
Requests/sec:     36.72
Transfer/sec:    140.65KB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These numbers are quite poor, linked to high latency caused by having to launch &lt;code&gt;bozohttpd&lt;/code&gt; for each incoming connection.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NetBSD httpd as a daemon:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;Running 10s test @ https://myblog.example.com/
  4 threads and 50 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    35.74ms    6.96ms 108.80ms   81.36%
    Req/Sec    18.29      9.45    50.00     70.88%
  676 requests in 10.10s, 2.53MB read
Requests/sec:     66.92
Transfer/sec:    256.32KB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here the situation is decidedly better, but not exceptional. &lt;code&gt;httpd&lt;/code&gt; isn't designed for high loads or performance.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nginx as a daemon, 1 worker:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;Running 10s test @ https://myblog.example.com/
  4 threads and 50 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    30.69ms    4.87ms  64.14ms   66.01%
    Req/Sec   379.39     65.94   464.00     90.91%
  15026 requests in 10.04s, 56.50MB read
Requests/sec:   1496.65
Transfer/sec:      5.63MB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we are on another level, showing truly solid performance. This type of result can handle significantly high loads without particular difficulty. The efficiency of both NetBSD and nginx pays off.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Caddy:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight"&gt;&lt;code class="language-plaintext"&gt;Running 10s test @ https://myblog.example.net/
  4 threads and 50 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    32.10ms    5.75ms  95.04ms   87.44%
    Req/Sec   362.74     64.29   434.00     91.67%
  14374 requests in 10.05s, 54.63MB read
Requests/sec:   1430.82
Transfer/sec:      5.44MB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Caddy shows results comparable to nginx, so the choice between them depends solely on the type of configuration you want to achieve and the experience each person has with the specific platforms.&lt;/p&gt;
&lt;h2&gt;Conclusion: Efficient Minimalism&lt;/h2&gt;
&lt;p&gt;We've seen how it's possible to create a personal, professional, and performant online presence with minimal investment. This solution, based on NetBSD and a 1€/month VPS, offers several advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Negligible Cost&lt;/strong&gt;: For 12€ per year, you can have a website (and more!) completely under your control.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Surprising Performance&lt;/strong&gt;: As demonstrated by the benchmarks, excellent performance can be achieved even with limited resources (up to 1400-1500 requests/second with nginx or Caddy).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security and Stability&lt;/strong&gt;: NetBSD is renowned for its reliability and security, fundamental characteristics for any online service.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total Control&lt;/strong&gt;: Unlike free blogging platforms, you have full control over every aspect of your site.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learning Experience&lt;/strong&gt;: Managing a BSD system allows you to acquire valuable system administration skills.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This minimalist configuration demonstrates that you don't need to invest in expensive cloud solutions or oversized VPS to have a quality online presence. In an era where the tendency is to think "moooar powaaaar = better results", NetBSD reminds us that efficiency and good design can yield excellent results even with limited resources.&lt;/p&gt;
&lt;p&gt;After all, you don't need a thousand-node cloud to write something worth reading.&lt;/p&gt;
&lt;p&gt;In the upcoming articles in this series, we will explore how to expand this basic installation with other useful services and how to keep the system updated and secure over time.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefano Marinelli</dc:creator><pubDate>Tue, 22 Apr 2025 07:30:36 +0200</pubDate><guid isPermaLink="true">https://it-notes.dragas.net/2025/04/22/make-your-own-internet-presence-with-netbsd-and-a-1-euro-vps-part-1-your-blog/</guid><category>netbsd</category><category>bssg</category><category>ssg</category><category>ownyourdata</category><category>server</category><category>web</category><category>blogging</category><category>tutorial</category><category>series</category></item><item><title>Launching BSSG - My Journey from Dynamic CMS to Bash Static Site Generator</title><link>https://it-notes.dragas.net/2025/04/07/launching-bssg-my-journey-from-dynamic-cms-to-bash-static-site-generator/</link><description>&lt;p&gt;&lt;img src="https://unsplash.com/photos/0gkw_9fy0eQ/download?ixid=M3wxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNzQzOTQ2ODgyfA&amp;force=true&amp;w=1920" alt="Photo by Patrick Fore on Unsplash"&gt;&lt;/p&gt;&lt;p&gt;I've had my own website practically forever. Back in the late '90s, I already had a web page on my ISP's server, and since at least 2001, I've had my own homepage on my own server. I've never been a great graphic designer, let alone a skilled webmaster, so I've always tried to keep things minimal and compatible.&lt;/p&gt;
&lt;p&gt;Initially, like many others, I wrote HTML pages by hand. Then I used WYSIWYG creation tools, and eventually, I landed on CMS (Content Management Systems).&lt;/p&gt;
&lt;h2&gt;The Era of Dynamic CMS&lt;/h2&gt;
&lt;p&gt;I liked &lt;a href="https://en.wikipedia.org/wiki/Content_management_system"&gt;CMS&lt;/a&gt; because they allowed me to focus on the content and not on the correctness of the generated HTML. Thanks to them, I started writing my first blog shortly afterward.&lt;/p&gt;
&lt;p&gt;Over the years, I've used many tools like PHPNuke, FlatNuke (created and developed by my friend &lt;a href="https://simonevellei.com/"&gt;Simone Vellei&lt;/a&gt;), eventually moving through Joomla and Wordpress. Wordpress always seemed like the most suitable tool for the job, and I used it for many years. Even today, mainly on the sysadmin side, I manage hundreds of Wordpress sites, and they are reasonably reliable, aside from the plugins (because &lt;a href="https://www.youtube.com/live/_IdH5YTBAGs?t=9801"&gt;the problem with Wordpress isn't the software itself, but many of the external plugins&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;But this is precisely the problem: all dynamic CMS require constant and continuous security updates because, without them, the chances of defacement are extremely high.&lt;/p&gt;
&lt;h2&gt;Discovering Static Site Generators&lt;/h2&gt;
&lt;p&gt;And that's precisely why, when I discovered Carlos Fenollosa's &lt;a href="https://github.com/cfenollosa/bashblog"&gt;bashblog&lt;/a&gt; in 2014, it immediately became clear that, indeed, there was no reason to continue down the path of dynamic CMS. I don't write often, I don't update often, there's no reason to regenerate all the content with every visit. Sure, WordPress caching plugins are often quite effective, but they are still add-ons that need to be kept up to date. And I'm not a fan of adding things to streamline. Often, less is more.&lt;/p&gt;
&lt;p&gt;So, I started using bashblog for some 'secondary' projects until, in 2015, I &lt;a href="https://www.dragas.net/posts/da-wordpress-a-pelican/"&gt;migrated my 'old' Italian blog from WordPress to Pelican&lt;/a&gt;. Shortly after, I &lt;a href="https://www.dragas.net/posts/da-pelican-a-nikola/"&gt;moved from Pelican to Nikola&lt;/a&gt;, and that blog is still generated by Nikola, although (that blog's) updates are now extremely rare (so much so that I consider it almost abandoned). I also created the first Docker container for Nikola and, for a long time, it was listed among the deployment methods on their site.&lt;/p&gt;
&lt;h2&gt;Building My Own: BSSG&lt;/h2&gt;
&lt;p&gt;But bashblog continued to fascinate me. So in 2015, for fun, I started developing my own Static Site Generator from scratch. I called it (with little imagination), &lt;a href="https://bssg.dragas.net"&gt;BSSG - Bash Static Site Generator&lt;/a&gt;. The plan was for it to be compatible with the main OSes I use, to remain sufficiently simple and straightforward (!!!), and to be tailored to my needs. I intended to use it only and exclusively for small private things, starting with a sort of diary of mine - more professional than personal - and leave the 'official' blogs to more tested and 'professional' tools.&lt;/p&gt;
&lt;p&gt;As time went by, I added some small features I liked: theming support, archives, tags (initially absent). Over time, many functions were added, and the script grew large – large enough to make me pause and ask myself some questions about the long-term stability of this solution. So, it remained only for my 'diary', which, however, grew year after year to the point where I needed to devise some kind of optimization. I then developed (more for fun than out of real necessity) a caching system. On rebuild, only what needs to be rebuilt is reconstructed, making the operation sufficiently fast even as the number of posts grows. Obviously, there are limits: using bash and external tools, the efficiency cannot be compared to that of a proper programming language.&lt;/p&gt;
&lt;h2&gt;Brief Detour: ITNBlog&lt;/h2&gt;
&lt;p&gt;And it's here that I decided, in preparation for opening a new blog (this one), to create a new tool called &lt;a href="https://itnblog.dragas.net"&gt;ITNBlog&lt;/a&gt;. I would develop it in Python and focus a bit more on performance and completeness. But ITNBlog stalled very quickly: time was limited, I'm not a full-time developer, so I realized I would spend too much time on development and too little on content creation.&lt;/p&gt;
&lt;p&gt;Therefore, in 2018, I launched this blog but using &lt;a href="https://ghost.org/"&gt;Ghost&lt;/a&gt;, a solution that gave me good results, including performance-wise. I chose Ghost because I thought that, writing content also from my phone while on the go, a real CMS would be useful. Spoiler: no, it didn't turn out that way, so a few years later I decided to migrate this blog to &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt;. Nevertheless, I continued to develop ITNBlog on and off, as a hobby, without any particular ambitions.&lt;/p&gt;
&lt;p&gt;At some point, however, I found myself in a particular situation: Hugo deprecated some features, and the theme I had chosen moved forward. But I ended up in an unpleasant situation: using the latest version of Hugo and the current version of the theme would produce unacceptable output; staying with the old version of Hugo while waiting for the theme update meant making a compromise. I actually build the blog from different devices, and they all have different versions of Hugo installed. Change the theme? Feasible, but I would have had to modify almost the entire site.&lt;/p&gt;
&lt;p&gt;I considered migrating to &lt;a href="https://github.com/gyptazy/manpageblog"&gt;manpageblog&lt;/a&gt; by &lt;a href="https://gyptazy.com/"&gt;gyptazy&lt;/a&gt; – I personally love its simplicity and retro look, and it was the main candidate to replace Hugo. I also created a script and migrated all my posts into the correct format.&lt;/p&gt;
&lt;h2&gt;BSSG to the Rescue (and ITNBlog's Role)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;That's when I realized: I would implement the few missing features needed to make ITNBlog sufficiently complete, and this blog would be published using it, ensuring I'd be committed to its development. However, ITNBlog is not mature enough to be released publicly, so for now, it will remain the engine just for my blog. Then I thought again about BSSG – development had stalled some time ago, but it was still in use – and figured that perhaps, with a little tidying up, I could release &lt;em&gt;it&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Because I'm tired of seeing people use dynamic CMS even to implement primarily static blogs or websites – and BSSG, despite its limitations and inefficiencies, works. And there are many themes to choose from. In short, you can install it and generate your blog in seconds.&lt;/p&gt;
&lt;h2&gt;Why Choose BSSG?&lt;/h2&gt;
&lt;p&gt;BSSG is the result of a 10-year evolution. The code isn't extremely consistent, some interesting features are missing (which I plan to implement), and it could use refactoring as the build script is monstrously large. But it works, it's portable (and much of the complexity increased precisely because of portability), and it generates sites that achieve very high accessibility and speed scores.&lt;/p&gt;
&lt;p&gt;Here are some highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Portability:&lt;/strong&gt; Uses native OS tools (e.g., &lt;code&gt;md5sum&lt;/code&gt; on Linux, &lt;code&gt;md5&lt;/code&gt; on OpenBSD and NetBSD). Portability itself added much of the complexity!&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Simple Theming:&lt;/strong&gt; Themes are just simple CSS files, so the structure remains the same – simplifying theme switching or creating new ones. More than 50 themes &lt;a href="https://bssg.dragas.net/example"&gt;are already available&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Essential Features:&lt;/strong&gt; Supports RSS feed generation, sitemap.xml, OpenGraph tags (to improve social sharing), internationalization (the blog can be in languages other than English – but not multilingual, at least for now), etc.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Built-in Backup and Restore script:&lt;/strong&gt; It will just copy the configuration file, posts, and pages. Nothing else.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Minimal Dependencies.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Markdown Support:&lt;/strong&gt; Posts and pages are in Markdown (CommonMark, Pandoc, and markdown.pl are supported).&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Feature Images.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Optional GNU Parallel Integration:&lt;/strong&gt; To speed up build times when there are many posts. This feature significantly impacts the code and has caused me numerous headaches over time. But it's optional (if &lt;code&gt;parallel&lt;/code&gt; isn't found, it proceeds traditionally) and only provides benefits when the number of posts increases: with few posts, performance actually degrades.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;High Accessibility and Performance Scores:&lt;/strong&gt; Sites built with BSSG achieve excellent scores.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;BSD Licensed:&lt;/strong&gt; Released under a BSD license.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One of the problems I've always had with all CMS and SSGs has been choosing a theme. In some cases (like Hugo), the theme heavily influences the output, which is both good and bad. Good because it makes each site unique, but bad because it makes switching themes difficult. In the past, I've sometimes found myself having to change themes because they were abandoned and no longer updated. BSSG works differently: theming comes from using a different CSS file, which makes its structure more rigid, but switching from one theme to another is trivial. To help with the choice, I created a script that will build your site using all the themes present in the &lt;code&gt;themes&lt;/code&gt; directory, just like on the examples page of the official website. This way, it will be easy to see and test your site with all available themes. If you want to add a touch of originality, you can choose the 'random' theme, and one will be chosen randomly from the list at each site regeneration.&lt;/p&gt;
&lt;h2&gt;Admin Interface (Experimental)&lt;/h2&gt;
&lt;p&gt;BSSG is in production use by some clients (for their internal sites), for whom I also created a basic admin interface (using Node Express, partly to chew on a bit of Node), but I don't feel ready to release it immediately as it's not sufficiently tested. It has an integrated Markdown editor and allows post scheduling, generating the files and launching BSSG with the right options at the right time. This could be that connecting link between traditional CMS and SSGs. There are others, but this one is tightly integrated with BSSG.&lt;/p&gt;
&lt;h2&gt;BSSG is Available Today&lt;/h2&gt;
&lt;p&gt;Starting today, BSSG is publicly available. It's not perfect, it probably doesn't make sense to do something of this complexity in bash, development will proceed slowly – but it's here, available to anyone who might find it useful.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bssg.dragas.net"&gt;Happy blogging everyone!&lt;/a&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefano Marinelli</dc:creator><pubDate>Mon, 07 Apr 2025 08:11:36 +0200</pubDate><guid isPermaLink="true">https://it-notes.dragas.net/2025/04/07/launching-bssg-my-journey-from-dynamic-cms-to-bash-static-site-generator/</guid><category>bssg</category><category>ssg</category><category>ownyourdata</category><category>freebsd</category><category>openbsd</category><category>netbsd</category><category>linux</category><category>server</category><category>web</category><category>blogging</category></item></channel></rss>