<rss version="2.0">
  <channel>
    <title>ivanpollak.com</title>
    <link>https://ivanpollak.com</link>
    <description>ivanpollak.com - Blog</description>
    <generator>Zine -- https://zine-ssg.io</generator>
    <language>en-US</language>
    <lastBuildDate>Thu, 18 Jun 2026 10:47:45 +0000</lastBuildDate>
    
      <item>
        <title>alpine linux on a hackberry pi</title>
        <description>&lt;h2&gt;Why Alpine&lt;/h2&gt;&lt;p&gt;I recently got into Alpine, mostly because of CI and then because of my home-labbing server. I really enjoy working and using this distribution because everything is so lightweight, even the init system.&lt;/p&gt;&lt;p&gt;Because it is so lightweight, it is a perfect fit for the Hackberry Pi Zero 2 W.&lt;/p&gt;&lt;h2&gt;Configuring the SD-Card&lt;/h2&gt;&lt;p&gt;First, an SD-Card, a Computer with an SD-Card reader and a Raspberry Pi Zero 2 W is needed. To flash Alpine on the SD-Card, I used the &lt;a href=&quot;https://www.raspberrypi.com/software/&quot; target=&quot;_blank&quot;&gt;Raspberry Pi Imager&lt;/a&gt;. In there, I’ve chose &lt;code&gt;Raspberry Pi Zero 2 W&lt;/code&gt;&gt;&lt;code&gt;Other general-purpose OS&lt;/code&gt;&gt;&lt;code&gt;Alpine Linux&lt;/code&gt;&gt;&lt;code&gt;Alpine Linux (64 Bit)&lt;/code&gt;. Afterwards, I chose my SD-Card and flashed the OS.&lt;/p&gt;&lt;p&gt;If the SD-Card is now inserted, no video output will be displayed. This is because the device tree’s need to be loaded via the &lt;code&gt;usercfg.txt&lt;/code&gt; file. This is a bit different from normal &lt;em&gt;Raspberry Pi OS&lt;/em&gt;, because the config doesn’t happen in &lt;code&gt;config.txt&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;So create a file, located at &lt;code&gt;Path/To/Your/SD-Card/&lt;/code&gt; (NOT &lt;code&gt;/boot/usercfg.txt&lt;/code&gt;), called &lt;code&gt;usercfg.txt&lt;/code&gt;. Add the following contents:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# Enable DRM VC4 V3D driver
dtoverlay=vc4-kms-v3d
max_framebuffers=2

# Don&amp;apos;t have the firmware create an initial video= setting in cmdline.txt.
# Use the kernel&amp;apos;s default instead.
disable_fw_kms_setup=1

# Hackberry Pi
dtoverlay=vc4-kms-dpi-hyperpixel4sq
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, insert the SD-Card into the Hackberry Pi, and boot it up. Wait until the LED on top is not blinking anymore, shut it down again and boot it up again.&lt;/p&gt;&lt;p&gt;Afterwards, the display should show the OpenRC boot process.&lt;/p&gt;&lt;h2&gt;Setup&lt;/h2&gt;&lt;p&gt;Login as &lt;code&gt;root&lt;/code&gt;. Runt the normal &lt;a href=&quot;https://wiki.alpinelinux.org/wiki/Alpine_configuration_management_scripts#setup-alpine&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;setup-alpine&lt;/code&gt;&lt;/a&gt; script until the &lt;code&gt;Disk &amp;amp; Install&lt;/code&gt; section. Here it displays, that &lt;code&gt;No disks available&lt;/code&gt; and if it should try the boot media. Enter &lt;code&gt;y&lt;/code&gt; for &lt;em&gt;yes&lt;/em&gt;. Next, select your disk. In my case it is &lt;code&gt;mmcblk0&lt;/code&gt;. This may vary in your setup. On the next step, I’ve chose &lt;code&gt;sys&lt;/code&gt;. You might want to change this. The &lt;code&gt;?&lt;/code&gt; option is very useful for selecting the best option. Afterwards, confirm that you want to erase the disk. Enter &lt;code&gt;y&lt;/code&gt; for yes. Afterwards reboot using &lt;code&gt;reboot now&lt;/code&gt;. Now the Hackberry has Alpine installed, however, we again need to use another computer to configure the video output. This is documented in the &lt;em&gt;Configuring the SD-Card&lt;/em&gt; section.&lt;/p&gt;&lt;h2&gt;Sources&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://wiki.alpinelinux.org/wiki/Raspberry_Pi#Linux_Kernel_Graphics_Modes&quot; target=&quot;_blank&quot;&gt;wiki.alpinelinux.org&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/ZitaoTech/Hackberry-Pi_Zero/tree/main/Screen#raspberry-pi-os-after-04042022-or-later&quot; target=&quot;_blank&quot;&gt;github.com/ZitaoTech&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</description>
        <link>https://ivanpollak.com/alpine_linux_on_a_hackberry_pi/</link>
        <pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate>
        <guid>https://ivanpollak.com/alpine_linux_on_a_hackberry_pi/</guid>
      </item>
    
      <item>
        <title>alpine linux as a server</title>
        <description>&lt;p&gt;This is a direct follow-up of the &lt;a href=&quot;https://ivanpollak.com/installing_alpine_linux/&quot;&gt;previous blog post&lt;/a&gt;. Because the whole setup (installing and configuring the server) would result in a really long blog post, I decided to split those two “chapters” into two different blog posts.&lt;/p&gt;&lt;p&gt;The services, that will be installed on my server are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://netbird.io/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;netbird&lt;/strong&gt;&lt;/a&gt;: an european alternative to tailscale&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://miniflux.app/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;miniflux&lt;/strong&gt;&lt;/a&gt;: a minimalistic rss reader&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Updating the repositories&lt;/h2&gt;&lt;p&gt;To use all the packages, that alpine linux provides, the user needs to enable them. This can be done via manually editing &lt;code&gt;/etc/apk/repositories&lt;/code&gt;. In here, the &lt;code&gt;community&lt;/code&gt; repository is commented out by default. However many packages are in this &lt;code&gt;community&lt;/code&gt; repository. To change this, just remove the &lt;code&gt;#&lt;/code&gt; in front of the url. A adjusted config could look like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;#/media/sda/apks
http://dl-cdn.alpinelinux.org/alpine/v3.23/main
http://dl-cdn.alpinelinux.org/alpine/v3.23/community
http://alpine.ethz.ch/alpine/v3.23/main
http://alpine.ethz.ch/alpine/v3.23/community
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If everything worked correctly, &lt;code&gt;btop&lt;/code&gt; for example, now should be installable.&lt;/p&gt;&lt;h2&gt;Installing NetBird&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://netbird.io/&quot; target=&quot;_blank&quot;&gt;NetBird&lt;/a&gt; is an &lt;a href=&quot;https://netbird.io/imprint&quot; target=&quot;_blank&quot;&gt;european alternative&lt;/a&gt; to tailscale. Because I like sovereignty, I prefer local companies, thus NetBird will be used on my server.&lt;/p&gt;&lt;p&gt;Because NetBird doesn’t have a package (or rather doesnt have one that works), I had to install &lt;code&gt;curl&lt;/code&gt; and then paste some command that they provide on their website. Please note, that this command might be outdated at the time of reading. Take this command (and every other &lt;em&gt;curl | sh&lt;/em&gt; command) with a grain of salt.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Install curl&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;curl&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Install NetBird&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-fsSL&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;https://pkgs.netbird.io/install.sh&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;constant function&quot;&gt;sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After the installation was complete, to setup NetBird, just run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;netbird&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;up&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will prompt the user to go to a website and confirm that the device should be added to the account. When this is confirmed, the device is now available in the mesh.&lt;/p&gt;&lt;h2&gt;Installing miniflux&lt;/h2&gt;&lt;p&gt;There is an &lt;a href=&quot;https://miniflux.app/docs/alpine.html&quot; target=&quot;_blank&quot;&gt;official guide&lt;/a&gt; on the miniflux website, on how to setup the &lt;em&gt;miniflux&lt;/em&gt; service on alpine. The following section will largely be similar to the instructions over there.&lt;/p&gt;&lt;p&gt;Install all the needed packages using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;miniflux&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;miniflux-openrc&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;miniflux-doc&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;postgresql&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;postgresql-contrib&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Start the database service:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Launch database on startup&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;rc-update&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;postgresql&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Launch the database now&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;rc-service&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;postgresql&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setup the database:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Switch to the postgres user&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-su&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;postgres&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Create the database for miniflux&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;createdb&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;miniflux2&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Exit out of postgres user shell&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To now configure miniflux, open the &lt;code&gt;/etc/miniflux.conf&lt;/code&gt; file. In here, we need to define the environment variables, because the &lt;em&gt;miniflux service&lt;/em&gt; is superviced by &lt;code&gt;supervise-daemon&lt;/code&gt; by OpenRC (instead of systemd).&lt;/p&gt;&lt;p&gt;To achieve the required configuration, insert the configuration below into &lt;code&gt;/etc/miniflux.conf&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;property&quot;&gt;LOG_DATE_TIME&lt;/span&gt;=yes
&lt;span class=&quot;property&quot;&gt;LISTEN_ADDR&lt;/span&gt;=127.0.0.1:8080
&lt;span class=&quot;property&quot;&gt;DATABASE_URL&lt;/span&gt;=user=postgres &lt;span class=&quot;property&quot;&gt;password&lt;/span&gt;=secret &lt;span class=&quot;property&quot;&gt;dbname&lt;/span&gt;=miniflux2 &lt;span class=&quot;property&quot;&gt;sslmode&lt;/span&gt;=disable

&lt;span class=&quot;comment&quot;&gt;# Run SQL migrations automatically:&lt;/span&gt;
&lt;span class=&quot;property&quot;&gt;RUN_MIGRATIONS&lt;/span&gt;=1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To now finalize the configuration, run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Create database tables, etc&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;miniflux&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;/etc/miniflux.conf&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-migrate&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Create admin user&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;miniflux&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;/etc/miniflux.conf&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-create-admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lastly, start the miniflux service using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;miniflux&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
</description>
        <link>https://ivanpollak.com/alpine_linux_as_a_server/</link>
        <pubDate>Mon, 04 May 2026 00:00:00 +0000</pubDate>
        <guid>https://ivanpollak.com/alpine_linux_as_a_server/</guid>
      </item>
    
      <item>
        <title>installing alpine linux</title>
        <description>&lt;p&gt;This blog post contains information on my journey to install &lt;a href=&quot;https://alpinelinux.org&quot; target=&quot;_blank&quot;&gt;Alpine Linux&lt;/a&gt; on my homelabbing server. This “server” actually is just an old laptop, that I do not actively use anymore. Since it is powerful enough to run as a server and quite efficient while doing so, I’ve decided to repurpose it as my server.&lt;/p&gt;&lt;h2&gt;Setting up the boot drive&lt;/h2&gt;&lt;p&gt;The first step of all new OS installations is to obtain an image for the given operating system. For alpine, they have a &lt;a href=&quot;https://alpinelinux.org/downloads/&quot; target=&quot;_blank&quot;&gt;downloads&lt;/a&gt; page with various options to choose from. Due to the fact, that I will use a laptop, I’ve decided to go with the &lt;code&gt;extended&lt;/code&gt; option. This should include “&lt;em&gt;AMD and Intel microcode updates.&lt;/em&gt;”&lt;/p&gt;&lt;p&gt;After flashing the device with &lt;code&gt;dd&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;if=alpine-extended-3.23.4-x86_64.iso&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;of=/dev/disk4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’ve proceeded to the &lt;a href=&quot;https://docs.alpinelinux.org/user-handbook/0.1a/Installing/setup_alpine.html&quot; target=&quot;_blank&quot;&gt;installing&lt;/a&gt; section of alpine’s &lt;a href=&quot;https://docs.alpinelinux.org/user-handbook/0.1a/index.html&quot; target=&quot;_blank&quot;&gt;User Handbook&lt;/a&gt;. There I found out, that the &lt;code&gt;setup-alpine&lt;/code&gt; script, which is used for easily installing alpine linux on a system, does not setup WiFi connections by itself.&lt;/p&gt;&lt;p&gt;Since I will use WiFi as the main way to communicate with my server, this ment that I would need to configure networking manually.&lt;/p&gt;&lt;h2&gt;Issues with WiFI&lt;/h2&gt;&lt;p&gt;Sadly, setting up WiFi wasn’t as easy as I thought. Because alpine is a pretty minimalistic distribution, the driver for my network device (&lt;code&gt;Intel(R) Wi-Fi 6E AX211 160MHz&lt;/code&gt;) was missing. This was probably due to the fact that &lt;code&gt;apk info&lt;/code&gt; (alpine’s way to list all installed packages) did not show any &lt;code&gt;linux-firmware-intel&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;So after searching an ethernet cable and doing the same for a free ethernet port, I was finally able to run &lt;code&gt;setup-alpine -q&lt;/code&gt; to start using alpine. This allowed me to ping an external website for the first time. After running the &lt;code&gt;-q&lt;/code&gt; (quick) version of the &lt;code&gt;setup-alpine&lt;/code&gt; command, and testing the connection, the real installation began.&lt;/p&gt;&lt;h2&gt;Installing alpine&lt;/h2&gt;&lt;p&gt;Alpine linux has a pretty handy script, called &lt;code&gt;setup-alpine&lt;/code&gt; this will guide the user through the installation process, asking him various questions on how the system should be installed. This includes; setting the keyboard layout, changing the hostname, setup the primary (wired) interface, use dhcp or not and various other things. All of those are described in the &lt;a href=&quot;https://docs.alpinelinux.org/user-handbook/0.1a/Installing/setup_alpine.html&quot; target=&quot;_blank&quot;&gt;user handbook&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Most values, I’ve left to their defaults. If I did not understand the options, entering the &lt;code&gt;?&lt;/code&gt; instead of any option, outputted a very detailed and easy to understand description of what option does what. What I think is notable, is that you even can select between different implementations (for example you can choose between &lt;code&gt;openssh&lt;/code&gt; and other ssh servers, if you want). Also, the help menu will describe when to use what. For example; if the user is not sure, how to use the disk, the help menu describes what option is better for what purpose. &lt;code&gt;sys&lt;/code&gt; is best for &lt;em&gt;development boxes&lt;/em&gt;, &lt;em&gt;desktops&lt;/em&gt; and &lt;em&gt;virtual servers&lt;/em&gt;, &lt;code&gt;crypt&lt;/code&gt; is the same as &lt;code&gt;sys&lt;/code&gt; but with encription, etc.&lt;/p&gt;&lt;p&gt;Because only I have physical access to this system, it was save for me, to choose the &lt;code&gt;sys&lt;/code&gt; option.&lt;/p&gt;&lt;p&gt;After the installation was finished, I was prompted to reboot the system. I’ve done what the computer told me and look at that, alpine is now installed.&lt;/p&gt;&lt;h2&gt;Setting up WiFi&lt;/h2&gt;&lt;p&gt;After the installation worked as it should, it was now time to make it possible to use the computer without an ethernet connection. I’ve &lt;code&gt;apk add&lt;/code&gt;-ed the previously mentioned &lt;code&gt;linux-firmware-intel&lt;/code&gt; and finally &lt;code&gt;ip addr&lt;/code&gt; showed my &lt;code&gt;wlan0&lt;/code&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Actually, I think, that the &lt;code&gt;setup-alpine&lt;/code&gt; script already installed the &lt;code&gt;linux-firmware-intel&lt;/code&gt; package alongside with some other common &lt;code&gt;linux-firmware-*&lt;/code&gt; packages.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Alpine supports both &lt;code&gt;wpa_supplicant&lt;/code&gt; and &lt;code&gt;iwd&lt;/code&gt;, however the wiki &lt;a href=&quot;https://wiki.alpinelinux.org/wiki/Wi-Fi#Troubleshooting&quot; target=&quot;_blank&quot;&gt;entry for wifi&lt;/a&gt; uses &lt;code&gt;wpa_supplicant&lt;/code&gt;, thus I proceeded to use this tool instead of &lt;code&gt;iwd&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;To add my network, I used the following command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Enter root shell&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;su&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Generate the config and put it into the correct file&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;wpa_passphrase&lt;/span&gt; &lt;span class=&quot;string constant&quot;&gt;&amp;apos;ExampleWifiSSID&amp;apos;&lt;/span&gt; &lt;span class=&quot;string constant&quot;&gt;&amp;apos;ExampleWifiPassword&amp;apos;&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;&amp;gt;&lt;/span&gt; /etc/wpa_supplicant/wpa_supplicant.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After this, I was able to test my wifi connection using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;wpa_supplicant&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;wlan0&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;/etc/wpa_supplicant/wpa_supplicant.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;-i&lt;/code&gt;, I assume, is for &lt;em&gt;interface&lt;/em&gt; and &lt;code&gt;-c&lt;/code&gt; for &lt;em&gt;config file&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;After testing, &lt;code&gt;wpa_supplicant&lt;/code&gt; was put into the background (daemon) using &lt;code&gt;-B&lt;/code&gt;. Also I setup dhcp, using &lt;code&gt;udhcpc&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Daemonize the command above&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;wpa_supplicant&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-B&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;wlan0&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;/etc/wpa_supplicant/wpa_supplicant.conf&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Obtain a dhcp lease&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;udhcpc&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;wlan0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To check, if the dchp stuff worked correctly:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;ip&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;wlan0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should now output an ip address next to the &lt;code&gt;inet&lt;/code&gt; field.&lt;/p&gt;&lt;p&gt;Configuring the gateway for my &lt;code&gt;wlan0&lt;/code&gt; interface was pretty straight-forward. Since I will use a dhcp, I did not need to set and gateway, static ip or a subnet mask. I could just open &lt;code&gt;/etc/network/interfaces&lt;/code&gt; and basically copy the &lt;code&gt;eth0&lt;/code&gt; configuration. My final file looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto wlan0
iface wlan0 inet dhcp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To now apply the configuration, first bring the interface down and then restart the &lt;code&gt;networking&lt;/code&gt; service. Lastly bring the interface back up again:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Bring interface down&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;ip&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;wlan0&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;down&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Restart networking&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;rc-service&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;networking&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;--quiet&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;restart&lt;/span&gt; &amp;amp;

&lt;span class=&quot;comment&quot;&gt;# Bring interface up again&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;ip&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;wlan0&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;up&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After all of this, I finally was able to &lt;code&gt;ping ivanpollak.com&lt;/code&gt;. This ment, that my laptop was finally ready for server usage.&lt;/p&gt;&lt;h2&gt;Setting up an SSH server&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt;SSH changed my life&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Because this is a &lt;em&gt;server&lt;/em&gt;, it should probably have &lt;em&gt;SSH&lt;/em&gt;. Also, I do not want to sit in front of this computer, each time I need to administrate something.&lt;/p&gt;&lt;p&gt;For the implementation, I chose &lt;a href=&quot;https://www.openssh.org/&quot; target=&quot;_blank&quot;&gt;OpenSSH&lt;/a&gt;, mainly because i already knew it. Also the &lt;a href=&quot;https://wiki.alpinelinux.org/wiki/Power_management#Busybox_acpid&quot; target=&quot;_blank&quot;&gt;wiki entry&lt;/a&gt; used it.&lt;/p&gt;&lt;p&gt;Installing OpenSSH was pretty straight-forward:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;openssh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This installed the &lt;code&gt;sshd&lt;/code&gt; service, as well as a default configuratoin in &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;. In the latter file, I adjusted the settings to my prefered ones (mainly setting &lt;code&gt;PermitRootMode no&lt;/code&gt; to disable root login).&lt;/p&gt;&lt;p&gt;Also, because I want to disable password login altogether, I quickly needed to start the &lt;code&gt;sshd&lt;/code&gt;-service with allowing passwords (to then copy over my ssh public key to the server).&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;rc-service&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;sshd&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On my client, I now ran:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;ssh-copy-id&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;user@hostname&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I quickly verified, that my passwordless login worked via &lt;code&gt;ssh user@hostname&lt;/code&gt;. This worked and this ment, that I could throw my server into a corner in my room.&lt;/p&gt;&lt;p&gt;Next, I edited the &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; again, to not allow any logins by just using the password. This was done via the &lt;code&gt;PasswordAuthentication no&lt;/code&gt; option.&lt;/p&gt;&lt;p&gt;All that was left, was to restart the service and add the service to &lt;code&gt;rc-update&lt;/code&gt; (launch the service at boot):&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;constant function&quot;&gt;doas&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;rc-service&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;sshd&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;restart&lt;/span&gt;
&lt;span class=&quot;constant function&quot;&gt;rc-update&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;sshd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Lid-close behaviour&lt;/h2&gt;&lt;p&gt;A standard alpine linux installation uses a basic &lt;a href=&quot;https://wiki.alpinelinux.org/wiki/Power_management#Busybox_acpid&quot; target=&quot;_blank&quot;&gt;acpid&lt;/a&gt; implementation. By default, there is nothing configured and thus, nothing will happen when the lid of the laptop is closed. If this is wanted, &lt;code&gt;/etc/acpi.map&lt;/code&gt; can be created and edited. This however is out of the scope of this blog entry.&lt;/p&gt;&lt;h2&gt;Reflecting&lt;/h2&gt;&lt;p&gt;The process of installing alpine linux on a laptop to use as a server, might not be as easy as other operating systems. It requires a background in linux technologies and a basic understanding of errors in linux. With that said, the alpine linux wiki is very extensive and easy to read. It covers almost every question that an user might have during setup. This makes it, if you have some linux knowledge, pretty okay to install, especially if you’re used to read through wiki entries.&lt;/p&gt;</description>
        <link>https://ivanpollak.com/installing_alpine_linux/</link>
        <pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate>
        <guid>https://ivanpollak.com/installing_alpine_linux/</guid>
      </item>
    
      <item>
        <title>foochr</title>
        <description>&lt;h2&gt;What is foochr?&lt;/h2&gt;&lt;p&gt;From the project’s README:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;foochr&lt;/em&gt; is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Text-based_user_interface&quot; target=&quot;_blank&quot;&gt;text-based user interface&lt;/a&gt; (TUI) program to help keep track of commands with flags, other TUI’s and even allows for a bit of scripting.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;It is basically just a fancier way for bash aliases. Instead of having an alias for &lt;code&gt;cha -MV&lt;/code&gt; or for &lt;code&gt;bluetui&lt;/code&gt;, the user can just write those down, giving the commands a name and then launch &lt;em&gt;foochr&lt;/em&gt; to get a list of all those commands&lt;/p&gt;&lt;p&gt;My initial idea for this project came a while back, when I started using &lt;a href=&quot;https://en.wikipedia.org/wiki/Command-line_interface&quot; target=&quot;_blank&quot;&gt;cli&lt;/a&gt;’s and &lt;a href=&quot;https://en.wikipedia.org/wiki/Text-based_user_interface&quot; target=&quot;_blank&quot;&gt;tui&lt;/a&gt;’s more and more. My issue back then was, that i kept forgetting the names of especially those programs, that i did not use that often. For examle &lt;a href=&quot;https://github.com/pythops/impala&quot; target=&quot;_blank&quot;&gt;impala&lt;/a&gt; and &lt;a href=&quot;https://github.com/pythops/bluetui&quot; target=&quot;_blank&quot;&gt;bluetui&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Also I wanted to learn &lt;a href=&quot;https://en.wikipedia.org/wiki/Ncurses&quot; target=&quot;_blank&quot;&gt;ncurses&lt;/a&gt;, as well as &lt;a href=&quot;https://en.wikipedia.org/wiki/C_(programming_language)&quot; target=&quot;_blank&quot;&gt;c&lt;/a&gt;. This is because i had another project that i wanted to code, that was larger and much more complicated than this. I thought, that this could be an &lt;em&gt;easy&lt;/em&gt; introduction to those two components.&lt;/p&gt;&lt;h2&gt;Getting started&lt;/h2&gt;&lt;p&gt;My &lt;a href=&quot;https://git.sr.ht/~ivanpollak/foochr/tree/7baef85dd170ad0730cc780691ffb964c159bcb4&quot; target=&quot;_blank&quot;&gt;first version&lt;/a&gt; was quickly written, thanks to the very useful guide for ncurses over at the &lt;a href=&quot;https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/&quot; target=&quot;_blank&quot;&gt;tldp&lt;/a&gt; website. However, one might notice, that all of the applications were &lt;a href=&quot;https://git.sr.ht/~ivanpollak/foochr/tree/7baef85dd170ad0730cc780691ffb964c159bcb4/item/src/main.c&quot; target=&quot;_blank&quot;&gt;hard-coded&lt;/a&gt; inside of the binary, thus making adjustments to this “configuration” very painfully.&lt;/p&gt;&lt;p&gt;Because I did not have much knowledge about how to parse a config file, I asked my chatbot of choice, that he should create me such a feature. This has worked pretty well, however I wasnt really happy that I needed help from an ai for such a &lt;em&gt;simple&lt;/em&gt; task.&lt;/p&gt;&lt;p&gt;I generally think that AI is &lt;strong&gt;not&lt;/strong&gt; sustainable and that this technology should not be used. Thus, my decision was made, to rewrite this piece of software.&lt;/p&gt;&lt;h2&gt;Writing my first config parser&lt;/h2&gt;&lt;p&gt;About a week ago, I started coding this new version, fully free of AI-slop. Because parsing the config would be one of the first things that will be done in the application, I also started with this step. It is actually not quite as difficult as I thought. Reading the first line can be done pretty easily, as well as getting an absolute path to the &lt;code&gt;.config&lt;/code&gt; directory via &lt;code&gt;getenv()&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;I noticed my lacking knowledge of the c standard library very quickly. I didn’t know that there was a function to “&lt;em&gt;tokenize&lt;/em&gt;” a given input, etc. This however did not prevent me from implementing the parser. (acutally even without the &lt;code&gt;strtok()&lt;/code&gt; function)&lt;/p&gt;&lt;p&gt;Okay now to the technicalities. A config file for &lt;em&gt;foochr&lt;/em&gt; can look like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;foochr.conf&quot;&gt;&lt;span class=&quot;punctuation_bracket function&quot;&gt;chawan=cha&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;-MV&lt;/span&gt;
&lt;span class=&quot;punctuation_bracket function&quot;&gt;system&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;monitor=btop&lt;/span&gt;
&lt;span class=&quot;function&quot;&gt;wifi=impala&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For parsing the config, I mostly used the &lt;code&gt;fgetch()&lt;/code&gt; function, which reads the next character in a given &lt;em&gt;stream&lt;/em&gt; and returns it. With this, it is possible to just loop over the file and based on the character that gets returned, do something differently. In my case, this looks something like this:&lt;/p&gt;&lt;p&gt;First there is a struct, where the config entries get stored.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// This struct stores the key and the value for a given entry.&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;type&quot;&gt;KeyValue&lt;/span&gt;
{
  &lt;span class=&quot;type&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;property&quot;&gt;key&lt;/span&gt;[&lt;span class=&quot;number&quot;&gt;127&lt;/span&gt;]&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;comment&quot;&gt;// This stores the value that will be shown in the tui&lt;/span&gt;
  &lt;span class=&quot;type&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;property&quot;&gt;value&lt;/span&gt;[&lt;span class=&quot;number&quot;&gt;127&lt;/span&gt;]&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;// This stores the command that will be run&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, some values that later will be used get initialized. &lt;code&gt;config_values[]&lt;/code&gt; is an array of the struct above. In this example, the maximum amount that a configuration can have, is 15 lines. In the actual program, this memory will be allocated and has not a fixed value. &lt;code&gt;config_index&lt;/code&gt; is the current position in the &lt;code&gt;config_values[]&lt;/code&gt; array. This will be useful to determine, where the next character should be inserted into. &lt;code&gt;is_value&lt;/code&gt; stores if the next characters should be inserted into the &lt;code&gt;key[]&lt;/code&gt; array or the &lt;code&gt;value[]&lt;/code&gt; array.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;type&quot;&gt;KeyValue&lt;/span&gt; &lt;span class=&quot;constant variable&quot;&gt;config_values&lt;/span&gt;[&lt;span class=&quot;number&quot;&gt;15&lt;/span&gt;]&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;constant variable&quot;&gt;config_index&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;type&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;constant variable&quot;&gt;is_value&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; false&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And lastly, there is a while block, that does multiple things. It checks if the current character is a &lt;code&gt;\n&lt;/code&gt;. If so, the &lt;code&gt;config_index&lt;/code&gt; should be incremented. This is because in the config file, each new-line indicates a new command that should be displayed in the ui/executed using &lt;em&gt;foochr&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;If the current character is a &lt;code&gt;=&lt;/code&gt;, the boolean &lt;code&gt;is_value&lt;/code&gt; is switched, thus allowing the next characters to flow into the &lt;code&gt;value&lt;/code&gt; instead of the &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (true)
{
  &lt;span class=&quot;constant variable&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;constant variable function&quot;&gt;fgetch&lt;/span&gt;(&lt;span class=&quot;constant variable&quot;&gt;fp&lt;/span&gt;)&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;constant variable&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;&amp;apos;\n&amp;apos;&lt;/span&gt;)
  {
    &lt;span class=&quot;constant variable&quot;&gt;is_value&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; !&lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;constant variable&quot;&gt;is_value&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;constant variable&quot;&gt;config_index&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;
  }
  &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;constant variable&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;&amp;apos;=&amp;apos;&lt;/span&gt;)
  {
    &lt;span class=&quot;constant variable&quot;&gt;is_value&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;constant variable&quot;&gt;is_value&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;;&lt;/span&gt;
  }
  &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;constant variable&quot;&gt;is_value&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;==&lt;/span&gt; true)
  {
    &lt;span class=&quot;constant variable function&quot;&gt;strcat&lt;/span&gt;(
      &lt;span class=&quot;constant variable&quot;&gt;config_values&lt;/span&gt;[&lt;span class=&quot;constant variable&quot;&gt;config_index&lt;/span&gt;]&lt;span class=&quot;delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;property&quot;&gt;value&lt;/span&gt;,
      (&lt;span class=&quot;type&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;*&lt;/span&gt;)&lt;span class=&quot;operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;constant variable&quot;&gt;character&lt;/span&gt;
    )
  }
  &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;
  {
    &lt;span class=&quot;constant variable function&quot;&gt;strcat&lt;/span&gt;(
      &lt;span class=&quot;constant variable&quot;&gt;config_values&lt;/span&gt;[&lt;span class=&quot;constant variable&quot;&gt;config_index&lt;/span&gt;]&lt;span class=&quot;delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;property&quot;&gt;key&lt;/span&gt;,
      (&lt;span class=&quot;type&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;*&lt;/span&gt;)&lt;span class=&quot;operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;constant variable&quot;&gt;character&lt;/span&gt;
    )
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All of this above is just a very simple example. This is not how the code actually looks like. To see, what the code looks like; you can find it &lt;a href=&quot;https://git.sr.ht/~ivanpollak/foochr/tree/main/item/config.c&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;h2&gt;Whats left?&lt;/h2&gt;&lt;p&gt;The config-file parsing was the main part, that I did not know how to implement. With that out of the way, all that was left, were the &lt;a href=&quot;https://en.wikipedia.org/wiki/Ncurses&quot; target=&quot;_blank&quot;&gt;ncurses&lt;/a&gt; things, which I already knew from the first version of &lt;em&gt;foochr&lt;/em&gt; and some Makefile shenanigans for allowing the program to be packaged.&lt;/p&gt;&lt;h2&gt;Reflecting&lt;/h2&gt;&lt;p&gt;To be honest, not using AI in the whole process, from start to end, made me realize, how useless AI actually is. If you know the general concepts of programming and know how to search if you have an issue, you’re probably better off without any LLM’s.&lt;/p&gt;&lt;p&gt;Also some people say, that with LLM’s you actually write the same code but faster. I do not think that this is true. Almost everybody I know, that uses AI either spends half the time waiting for the prompt to be processed or to be mad at the chatbot because it did not write the code that they wanted. This is especially true with low-level programming, but applies to general programming as well.&lt;/p&gt;&lt;p&gt;So; don’t forget that just because some huge tech companies tell everybody how &lt;em&gt;their product&lt;/em&gt; will replace you, that this statement is actually true. They most likey (as with almost all other companies) just want you to spend money.&lt;/p&gt;&lt;p&gt;Have a great day!&lt;/p&gt;</description>
        <link>https://ivanpollak.com/foochr/</link>
        <pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate>
        <guid>https://ivanpollak.com/foochr/</guid>
      </item>
    
  </channel>
</rss>
