💾 Archived View for perso.pw › blog › rss.xml captured on 2022-07-16 at 14:48:21.
⬅️ Previous capture (2022-06-11)
-=-=-=-=-=-=-
<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <channel> <title>Solene'%</title> <description></description> <link>gemini://perso.pw/blog/</link> <atom:link href="gemini://perso.pw/blog/rss.xml" rel="self" type="application/rss+xml" /> <item> <title>Storing information on paper using the Pen To Paper protocol</title> <description> <![CDATA[ <pre># Introduction Here is a draft for a protocol named PTPDT, an acronym standing for Pen To Paper Data Transfer. It comes with its companion specification Paper To Brain. The protocol describes how a pen can be used to write data on a sheet of paper. Maybe it would be better named as Brain To Paper Protocol. # Terminology Some words refer to specific concepts:
+------------+ +----------------------------+
| wait for | | Accounting time for today |
| input | Type Enter | Internet is enabled |
| |------------------->| |
| Internet | | display time used |
| offline | | today |
+------------+ +----------------------------+
^ v
| press ctrl+C |
| (which is trapped to run a func) |
+-----------------------------------------+
As the way to disable / enable internet is specific to every one, the script has two empty fuctions: NETON and NETOFF, they enable or disable Internet access. On my Linux computer I found an easy way to achieve this by adding a bogus default route with a metric 1, bypassing my default route. Because the default route doesn't work my system can't reach the Internet, but it let my LAN in a working state. => https://perso.pw/internet-accounting.sh My own version of prahou's script (I made some little changes) # How's life? So far, it's easy to remember I don't have Internet all the time, but with my Internet usage it works fine. I use the script to "start" Internet, check my emails, read IRC channels and reply, and then I disconnect. By using small amount of time, I can achieve most of my needs in less than a minute. However, that wouldn't be practical if I had to download anything big, and people with a fast Internet access (= not me) would have an advantage. My guess about this first day being easy is that as I don't use any streaming service, I don't need to be connected all the time. All my data are saved locally, and most of my communication needs can be done asynchronously. Even publishing this blog post shouldn't consume more than 20 seconds. # Let's go for a week I suppose it will be easy to forget about limited Internet time, so it will be best for me to run the accounting script in a terminal (disabling Internet until I manually accept to enable it), and think a bit ahead if I will need more time later so I can be more conservative about time usage. So far, it's a great experience I enjoy a lot. I hope other participant will enjoy it as much as I do. We will start gathering and aggregating reports soon, so you could enjoy all the reports from our community. # It's not late to join Despite the challenge officially started today (10th July), it's not late to start it yourself. The important is to have fun, if you want to try, you could just use a chronometer and see if you could hold with only 60 minutes a day. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/old-computer-challenge-v2-day1.gmi</guid> <link>gemini://perso.pw/blog//articles/old-computer-challenge-v2-day1.gmi</link> <pubDate>Sun, 10 Jul 2022 00:00:00 GMT</pubDate> </item> <item> <title>The Old Computer Challenge V2: back to RTC</title> <description> <![CDATA[ <pre># Introduction Hello! Let me start straight into the topic: The Old Computer Challenge, second edition! => https://dataswamp.org/~solene/tag-oldcomputerchallenge.html Some readings if you don't know about the first Old Computer Challenge The first edition of the challenge consisted into spending a week (during your non-work time) using an old computer, the recommended machine specifications were 1 core and 512 MB of memory at best, however some people enjoyed doing this challenge with other specifications and requirements, and it's fine, the purpose of the challenge is to have fun. While experimenting the challenge last year, a small but solid community gathered on IRC, we shared tips and our feelings about the challenge, it was very fun and a good opportunity to meet new people. One year later, the community is still there and over the last months we had regular ideas exchange for renewing the challenge. I didn't want to do the same challenge again, the fun would be spoiled, and it would have a feeling of déjà vu. I recently shared a new idea and many adopted it, and it was clear this would be the main topic of the new challenge. # The Old Computer Challenge v2 This new challenge will embrace the old time of RTC modems with a monthly time budget. Back in these days, in France at least, people had to subscribe to an ISP for a given price, but you would be able to connect only for 10, 20, 30, 40... hours a month depending on your subscription. Any extra hour was very expensive. We used the Internet the most efficiently possible because it was time limited (and very slow, 4 kB/s at best). Little story, phone lines were not available while a modem was connected, and we had to be careful not to forget to manually disconnect the modem after use, otherwise it would stay connected and wasting the precious Internet time! (and making expensive bills) The new challenge rules are easy: you are allowed to _connect_ your computer to the Internet for a maximum cumulated time of 1h per day, from 10th to 17th July included. This mean you can connect six times for ten minutes, twice for thirty minutes, or once for one hour in the day. Remember, the challenge is about having fun and helping you to step back on your computer habits, it's also recommended to share your thoughts and feeling a few times over the challenge week on your usual medias. There is nothing to prove to anyone, if you want to cheat or do the challenge with two or six hours a day, please do as you prefer. => static/challenge-v2.png The old computer challenge v2 cover This artwork was created by our community member prahou (thanks!), and is under the license CC BY-NC-ND 4.0, you can reuse it as-this. It features a CD because back in the RTC time, ISP were offering CDs to connect to the Internet and subscribe from home, I remember using those as flying discs. => https://triapul.cz/occ A page gathering the reports from all the participants # Time accounting While I don't have any implementation yet, here is an ideas list to help you to accounting your Internet time:
GAMEPAD_DPAD_RIGHT seek +30
GAMEPAD_DPAD_LEFT seek -30
GAMEPAD_DPAD_UP add chapter 1
GAMEPAD_DPAD_DOWN add chapter -1
GAMEPAD_ACTION_DOWN cycle pause
GAMEPAD_ACTION_UP cycle fullscreen
GAMEPAD_RIGHT_TRIGGER multiply speed 1.2
GAMEPAD_LEFT_TRIGGER set speed 1.0
You can find the actions list in mpv man page, or by looking at the sample inputs.conf that should be provided with mpv package. # Run mpv By default, mpv won't look for gamepad inputs, you need to add --input-gamepad=yes parameter when you run mpv, or add "input-gamepad=yes" as a newline in ~/.config/mpv/mpv.conf mpv configuration file. If you use a button on the gamepad while mpv is running from a terminal, you will have some debug output showing you which button was pressed, including its name, this is helpful to find the inputs names. # Conclusion Using the gamepad instead of a dedicated remote is very convenient for me, no extra expense, and it's very fun to use. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/mpv-gamepad.gmi</guid> <link>gemini://perso.pw/blog//articles/mpv-gamepad.gmi</link> <pubDate>Tue, 21 Jun 2022 00:00:00 GMT</pubDate> </item> <item> <title>How to make a local NixOS cache server</title> <description> <![CDATA[ <pre># Introduction If like me, you have multiple NixOS system behind the same router, you may want to have a local shared cache to avoid downloading packages multiple time. This can be done simply by using nginx as a reverse proxy toward the official repository and by enabling caching the result. => https://github.com/nh2/nix-binary-cache-proxy nix-binary-cache-proxy project I used as a base # Server side configuration We will declare a nginx service on the server, using http protocol only to make setup easier. The packages are signed, so their authenticity can't be faked. In this setup, using https would add anonymity which is not much of a concern in a local network, for my use case. In the following setup, the LAN cache server will be reachable at the address 10.42.42.150, and will be using the DNS resolver 10.42.42.42 every time it needs to reach the upstream server.
services.nginx = {
enable = true;
appendHttpConfig = ''
proxy_cache_path /tmp/pkgcache levels=1:2 keys_zone=cachecache:100m max_size=20g inactive=365d use_temp_path=off;
# Cache only success status codes; in particular we don't want to cache 404s.
# See https://serverfault.com/a/690258/128321
map $status $cache_header {
200 "public";
302 "public";
default "no-cache";
}
access_log /var/log/nginx/access.log;
'';
virtualHosts."10.42.42.150" = {
locations."/" = {
root = "/var/public-nix-cache";
extraConfig = ''
expires max;
add_header Cache-Control $cache_header always;
# Ask the upstream server if a file isn't available locally
error_page 404 = @fallback;
'';
};
extraConfig = ''
# Using a variable for the upstream endpoint to ensure that it is
# resolved at runtime as opposed to once when the config file is loaded
# and then cached forever (we don't want that):
# see https://tenzer.dk/nginx-with-dynamic-upstreams/
# This fixes errors like
# nginx: [emerg] host not found in upstream "upstream.example.com"
# when the upstream host is not reachable for a short time when
# nginx is started.
resolver 10.42.42.42;
set $upstream_endpoint http://cache.nixos.org;
'';
locations."@fallback" = {
proxyPass = "$upstream_endpoint";
extraConfig = ''
proxy_cache cachecache;
proxy_cache_valid 200 302 60d;
expires max;
add_header Cache-Control $cache_header always;
'';
};
# We always want to copy cache.nixos.org's nix-cache-info file,
# and ignore our own, because `nix-push` by default generates one
# without `Priority` field, and thus that file by default has priority
# 50 (compared to cache.nixos.org's `Priority: 40`), which will make
# download clients prefer `cache.nixos.org` over our binary cache.
locations."= /nix-cache-info" = {
# Note: This is duplicated with the `@fallback` above,
# would be nicer if we could redirect to the @fallback instead.
proxyPass = "$upstream_endpoint";
extraConfig = ''
proxy_cache cachecache;
proxy_cache_valid 200 302 60d;
expires max;
add_header Cache-Control $cache_header always;
'';
};
};
};
Be careful, the default cache is located under /tmp/ but the nginx systemd service is hardened and its /tmp/ is faked in a temporary directory, meaning if you restart nginx you lose the cache. I'd advise using a directory like /var/cache/nginx/ if you want your cache to persist across restarts. # Client side configuration Using the cache server on a system is really easy. We will define the binary cache to our new local server, the official cache is silently added so we don't have to list it.
nix.binaryCaches = [ "http://10.42.42.150/" ];
Note that you have to use this on the cache server itself if you want the system to use the cache for its own needs. # Conclusion Using a local cache can save a lot of bandwidth when you have more than one computer at home (or if you extensively use nix-shell and often run the garbage collector). Due to NixOS packages names being unique, we won't have any issues of a newer package version behind hidden by a local copy cached, which make the setup really easy. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/nixos-local-cache.gmi</guid> <link>gemini://perso.pw/blog//articles/nixos-local-cache.gmi</link> <pubDate>Thu, 02 Jun 2022 00:00:00 GMT</pubDate> </item> <item> <title>Creating a NixOS thin gaming client live USB</title> <description> <![CDATA[ <pre># Introduction This article will cover a use case I suppose very personal, but I love the way I solved it so let me share this story. I'm a gamer, mostly on computer, but I have a big rig running Windows because many games still don't work well with Linux, but I also play video games on my Linux laptop. Unfortunately, my laptop only has an intel integrated graphic card, so many games won't run well enough to be played, so I'm using an external GPU for some games. But it's not ideal, the eGPU is big (think of it as a big shoes box), doesn't have mouse/keyboard/usb connectors, so I've put it into another room with a screen at a height to play while standing up, controller in hands. This doesn't solve everything, but I can play most games running on it and allowing a controller. But if I install a game on both the big rig and the laptop, I have to manually sync the saves (I'm buying most of the games on GOG which doesn't have a Linux client to sync saves), it's highly boring and error-prone. So, thanks to NixOS, I made a recipe to generate a USB live media to play on the big rig, using the data from the laptop, so it's acting as a thin client. The idea of a read only media to boot from is very nice, because USB memory sticks are terrible if you try to install Linux on them (I tried many times, it always ended with I/O errors quickly) and there is exactly what you need, generated from a declarative file. What does it solve concretely? I can play some games on my laptop anywhere on the small screen, I can also play with my eGPU on the standing desk, but now I can also play all the installed games from the big rig with mouse/keyboard/144hz screen. # What's in the live image? The generated ISO (USB capable) should come with a desktop environment like Xfce, Nvidia drivers, Steam, Lutris, Minigalaxy and some other programs I like to use, I keep the programs list minimal because I could still use nix-shell to run a program later. For the system configuration, I declare the user "gaming" with the same uid as the user on my laptop, and use an NFS mount at boot time. I'm not using Network Manager because I need the system to get an IP before connecting to a user account. # The code I'll be using flakes for this, it makes pinning so much easier. I have two files, "flake.nix" and "iso.nix" in the same directory. flake.nix file:
{
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs, ... }@inputs:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; config = { allowUnfree = true; }; };
lib = nixpkgs.lib;
in
{
nixosConfigurations.isoimage = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./iso.nix
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-base.nix"
];
};
};
}
And iso.nix file:
{ config, pkgs, ... }:
{
# compress 6x faster than default
# but iso is 15% bigger
# tradeoff acceptable because we don't want to distribute
# default is xz which is very slow
isoImage.squashfsCompression = "zstd -Xcompression-level 6";
# my azerty keyboard
i18n.defaultLocale = "fr_FR.UTF-8";
services.xserver.layout = "fr";
console = {
keyMap = "fr";
};
# xanmod kernel for better performance
# see https://xanmod.org/
boot.kernelPackages = pkgs.linuxPackages_xanmod;
# prevent GPU to stay at 100% performance
hardware.nvidia.powerManagement.enable = true;
# sound support
hardware.pulseaudio.enable = true;
# getting IP from dhcp
# no network manager
networking.dhcpcd.enable = true;
networking.hostName = "biggy"; # Define your hostname.
networking.wireless.enable = false;
# many programs I use are under a non-free licence
nixpkgs.config.allowUnfree = true;
# enable steam
programs.steam.enable = true;
# enable ACPI
services.acpid.enable = true;
# thermal CPU management
services.thermald.enable = true;
# enable XFCE, nvidia driver and autologin
services.xserver.desktopManager.xfce.enable = true;
services.xserver.displayManager.lightdm.autoLogin.timeout = 10;
services.xserver.displayManager.lightdm.enable = true;
services.xserver.enable = true;
services.xserver.libinput.enable = true;
services.xserver.videoDrivers = [ "nvidia" ];
services.xserver.xkbOptions = "eurosign:e";
time.timeZone = "Europe/Paris";
# declare the gaming user and its fixed password
users.mutableUsers = false;
users.users.gaming.initialHashedPassword = "$6$bVayIA6aEVMCIGaX$FYkalbiet783049zEfpugGjZ167XxirQ19vk63t.GSRjzxw74rRi6IcpyEdeSuNTHSxi3q1xsaZkzy6clqBU4b0";
users.users.gaming = {
isNormalUser = true;
shell = pkgs.fish;
uid = 1001;
extraGroups = [ "networkmanager" "video" ];
};
services.xserver.displayManager.autoLogin = {
enable = true;
user = "gaming";
};
# mount the NFS before login
systemd.services.mount-gaming = {
path = with pkgs; [ nfs-utils ];
serviceConfig.Type = "oneshot";
script = ''
mount.nfs -o fsc,nfsvers=4.2,wsize=1048576,rsize=1048576,async,noatime t470-eth.local:/home/jeux/ /home/jeux/
'';
before = [ "display-manager.service" ];
wantedBy = [ "display-manager.service" ];
after = [ "network-online.target" ];
};
# useful packages
environment.systemPackages = with pkgs; [
bwm_ng
chiaki
dunst # for notify-send required in Dead Cells
file
fzf
kakoune
libstrangle
lutris
mangohud
minigalaxy
ncdu
nfs-utils
steam
steam-run
tmux
unzip
vlc
xorg.libXcursor
zip
];
}
Then I can update the sources using "nix flake lock --update-input nixpkgs", that will tell you the date of the nixpkgs repository image you are using, and you can compare the dates for updating. I recommend using a program like git to keep track of your files, if you see a failure with a more recent nixpkgs after the lock update, you can have fun pinpointing the issue and reporting it, or restoring the lock to the previous version and be able to continue building ISOs. You can build the iso with the command "nix build .#nixosConfigurations.isoimage.config.system.build.isoImage", this will create a symlink "result" in the directory, containing the ISO that you can burn on a disk or copy to a memory stick using dd. # Server side Of course, because I'm using NFS to share the data, I need to configure my laptop to serves the files over NFS, this is easy to achieve, just add the following code to your "configuration.nix" file and rebuild the system:
services.nfs.server.enable = true;
services.nfs.server.exports = ''
/home/gaming 10.42.42.141(rw,nohide,insecure,no_subtree_check)
'';
If like me you are using the firewall, I'd recommend opening the NFS 4.2 port (TCP/2049) on the Ethernet interface only:
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [ ];
networking.firewall.allowedUDPPorts = [ ];
networking.firewall.interfaces.enp0s31f6.allowedTCPPorts = [ 2049 ];
In this case, you can see my NFS client is 10.42.42.141, and previously the NFS server was referred to as laptop-ethernet.local which I declare in my LAN unbound DNS server. You could make a specialisation for the NFS server part, so it would only be enabled when you choose this option at boot. # NFS performance improvement If you have a few GB of spare memory on the gaming computer, you can enable cachefilesd, a service that will cache some NFS accesses to make the experience even smoother. You need memory because the cache will have to be stored in the tmpfs and it needs a few gigabytes to be useful. If you want to enable it, just add the code to the iso.nix file, this will create a 10 MB * 300 cache disk. As tmpfs lacks user_xattr mount option, we need to create a raw disk on the tmpfs root partition and format it with ext4, then mount on the fscache directory used by cachefilesd.
services.cachefilesd.enable = true;
services.cachefilesd.extraConfig = ''
brun 6%
bcull 3%
bstop 1%
frun 6%
fcull 3%
fstop 1%
'';
systemd.services.tmpfs-cache = {
path = with pkgs; [ e2fsprogs busybox ];
serviceConfig.Type = "oneshot";
script = ''
if [ ! -f /disk0 ]; then
dd if=/dev/zero of=/disk0 bs=10M count=600
echo 'y' | mkfs.ext4 /disk0
fi
mkdir -p /var/cache/fscache
mount | grep fscache || mount /disk0 /var/cache/fscache -t ext4 -o loop,user_xattr
'';
before = [ "cachefilesd.service" ];
wantedBy = [ "cachefilesd.service" ];
};
# Security consideration Opening an NFS server on the network must be done only in a safe LAN, however I don't consider my gaming account to contain any important secret, but it would be bad if someone on the LAN mount it and delete all the files. However, there are two NFS alternatives that could be used:
environment.gnome.excludePackages = with pkgs.gnome; [
pkgs.orca
epiphany
yelp
totem
gnome-weather
gnome-calendar
gnome-contacts
gnome-logs
gnome-maps
gnome-music
pkgs.gnome-photos
];
## Wine I found that Wine came with the Windows compiler as a dependency, but yet it doesn't seem useful for running games in Lutris. => https://discourse.nixos.org/t/wine-installing-mingw32-compiler/19944?u=solene NixOS discourse: Wine installing mingw32 compiler? It's possible to rebuild Wine used by Lutris without support for the mingw compiler, replace the lutris line in the "systemPackages" list with the following code:
(lutris-free.override {
lutris-unwrapped = lutris-unwrapped.override {
wine = wineWowPackages.staging.override {
mingwSupport = false;
};
};
})
Note that I'm using lutris-free which doesn't support Steam because it makes it a bit lighter and I don't need to manage my Steam games with Lutris. # Possible improvements It could be possible to try getting a package from the nix-store on the NFS server before trying cache.nixos.org which would improve bandwidth usage, it's easy to achieve but yet I need to try it in this context. # Issue I found Steam games running with Proton are slow to start. I made a bug report on the Steam Linux client github. => https://github.com/ValveSoftware/steam-for-linux/issues/8603 Github: Proton games takes around 5 minutes to start from a network share This can be solved partially by mounting ~/.local/share/Steam/steamapps/common/SteamLinuxRuntime_soldier/var as tmpfs, it will uses less than 650MB. # Conclusion I really love this setup, I can backup my games and saves from the laptop, play on the laptop, but now I can extend all this with a bigger and more comfortable setup. The USB live media doesn't take long to be copied to a USB memory stick, so in case one is defective, I can just recopy the image. The live media can be booted all in memory then be unplugged, this gives a crazy fast responsive desktop and can't be altered. My previous attempts at installing Linux on an USB memory stick all gave bad results, it was extremely slow, i/o errors were common enough that the system became unusable after a few hours. I could add a small partition to one disk of the big rig or add a new disk, but this will increase the maintenance of a system that doesn't do much. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/nixos-thin-gaming-client.gmi</guid> <link>gemini://perso.pw/blog//articles/nixos-thin-gaming-client.gmi</link> <pubDate>Fri, 20 May 2022 00:00:00 GMT</pubDate> </item> <item> <title>Using a game engine to write a graphical interface to the OpenBSD package manager</title> <description> <![CDATA[ <pre># Introduction I'm really trying hard to lower the barrier entry to OpenBSD, I realize most of my efforts are toward making OpenBSD easier. One thing I often mumbled about on OpenBSD was the lack of a user interface to browse packages and install them, there was a console program named pkg_mgr, but I never got it to work. Of course, I'm totally able to install packages using the command line, but I like to stroll looking for packages I wouldn't know about, a GUI is perfect for doing so, and is also useful for people less comfortable with the command line. So, today, I made a graphical user interface (GUI) using OpenBSD, using a game engine. Don't worry, all the packages operations are delegated to pkg_add and pkg_delete because they are doing they job fine. => https://tildegit.org/solene/AppManager OpenBSD AppManager project website => static/appmanager-list.png AppManager main menu => static/appmanager-recap.png AppManager giving a summary of changes # What is it doing? The purpose of this program is simple, display the list of available packages, highlight in yellow the one you have installed on your system, and let you select new packages to install or installed packages to remove. It features a search input instead of displaying a blunt list of a dozen of thousands of entries. The development was made on my Thinkpad T400 (core 2 duo), performance are excellent. One simple feature I'm proud of is the automatic classification of packages into three categories: GUI programs, terminal/console user interface programs and others. While this is not perfect because we don't have this metadata anywhere, I'm reusing the dependencies' information to guess in which category each package belongs, so far it's giving great results. # About the engine I rarely write GUI application because it's often very tedious and give poor results, so the ratio time/result is very bad. I've been playing with the Godot game engine for a week now, and I was astonished when I've been told the engine editor is done using the engine itself. As it was blazing fast and easy to make small games, I wondered if this would be suitable for a simple program like a package manager interface. First thing I checked was if it was supporting sqlite or json data natively without much work. This was important as the data used to query the package list is originally found in a sqlite database provided by the sqlports package, however the sqlite support was only available through 3rd party code while JSON was natively supported. When writing then simple script converting data from the sqlite database into a json, I took the opportunity to add the logic to determine if it's a GUI or a TUI (Terminal UI) and make the data format very easy to reuse. Finally, I got a proof of concept within 2h, it was able to install packages from a list. Then I added support for displaying already installed packages and then to delete packages. The polishing of the interfaces took the most time, but the whole project didn't take more than 8h which is unbelievable for me. # Conclusion From today, I'll seriously think about using Godot for writing GUI application, did I say it's cross platform? AppManager can be run on Linux or Windows (given you have pkg.json), except it will just fail at installing packages, but the whole UI works. Thinking about it, it could be easy to reuse it for another package manager. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/i-wrote-a-gui-frontend-with-a-game-engine.gmi</guid> <link>gemini://perso.pw/blog//articles/i-wrote-a-gui-frontend-with-a-game-engine.gmi</link> <pubDate>Thu, 05 May 2022 00:00:00 GMT</pubDate> </item> <item> <title>Managing OpenBSD installed packages declaratively</title> <description> <![CDATA[ <pre># Introduction I wrote a simple utility to manage OpenBSD packages on a system using a declarative way. => https://tildegit.org/solene/pkgset pkgset git repository Instead of running many pkg_add or pkg_delete commands to manage my packages, now I can use a configuration file (allowing includes) to define which package should be installed, and the installed but not listed packages should be removed. After using NixOS too long, it's a must have for me to manage packages this way. # How does it work? pkgset works by marking extra packages as "auto installed" (the opposite is manually installed, see pkg_info -m), and by installing missing packages. After those steps, pkgset runs "pkg_delete -a" to remove unused packages (the one marked as auto installed) if they are not a dependency of another required package. # How to install? The installation is easy, download the sources and run make install as root, it will install pkgset and its man page on your system.
$ git clone https://tildegit.org/solene/pkgset.git
$ cd pkgset
$ doas make install
# Configuration file example Here is the /etc/pkgset.conf file on my laptop.
borgbackup--%1.2
bwm-ng
fish
fzf
git
git-annex
gnupg
godot
kakoune
musikcube
ncdu
rlwrap
sbcl
vim--no_x11
vlc
xclip
xfce
xfce-extras
yacreader
# Limitations The only "issue" with pkgset is that for some packages that "pkg_add" may find ambiguous due to multiples versions or favors available without a default one, you must define the exact package version/flavor you want to install. # Risks If you use it incorrectly, running pkgset doesn't have more risks than losing some or all installed packages. # Why not use pkg_add -l ? I know pkg_add as an option to install packages from a list, but it won't remove the extra packages. I may look at adding the "pkgset" feature to pkg_add one day maybe. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/openbsd-declarative-packages-with-pkgset.gmi</guid> <link>gemini://perso.pw/blog//articles/openbsd-declarative-packages-with-pkgset.gmi</link> <pubDate>Thu, 05 May 2022 00:00:00 GMT</pubDate> </item> <item> <title>How to contribute to the OpenBSD project</title> <description> <![CDATA[ <pre># Intro You like OpenBSD? Then, I'm quite sure you can contribute to it! Let me explain the many ways your skills can be used to improve the project and contribute back. => https://www.openbsd.org/faq/faq1.html#Support Official FAQ section about how to support the Project # Contributing to OpenBSD I proposed to update the official FAQ with this content, but it has been dismissed, so I'm posting it here as I'm convinced it's valuable. ## Writing and reviewing code Programmers who enjoy writing operating systems are naturally always welcome. The team would appreciate your skills on the base system, kernel, userland. => https://www.openbsd.org/faq/faq5.html#Diff How create a diff to share a change with other There is also place for volunteers willing to help at packaging and maintaing software up to date in our ports tree. => https://www.openbsd.org/faq/ports/index.html The porter guide ## Use the development version Switch your systems to the branch -current and report system or packages regressions. With more users testing the development version, the releases are more likely to be bug free. Why not join the => https://www.openbsd.org/faq/current.html What is -current, how to use it It's also important to use the packages regularly on the development branch to report any issue. => https://www.openbsd.org/faq/ports/testing.html FAQ guide to testing packages Try OpenBSD on as many hardware as you can, send a bug report if you find incompatibility or regressions. => https://www.openbsd.org/report.html How to write an useful bug report => https://www.openbsd.org/plat.html Supported hardware platform ## Documentation Help maintain documentation by submitting new FAQ material to the misc@openbsd.org mailing list. Challenging the documentation accuracy and relevance on a regular basis is a good way to contribute for everyone. ## Community Follow the mailing lists, you may be able to help answer questions from other users. This is also a good opportunity to proofread submitted changes proposed by others or to try those and report how it works for you. => https://www.openbsd.org/mail.html The OpenBSD mailing lists Form or join a local group and get your friends hooked on OpenBSD. => https://www.openbsd.org/groups.html List of OpenBSD user groups Spread the word on social networks, show the project under a good light, share your experiences and your use cases. OpenBSD is definitely not a niche operating system anymore. Make a case to your employer for using OpenBSD at work. If you're a student, talk to your professors about using OpenBSD as a learning tool for Computer Science or Engineering courses. ## Donate money or hardware The project has a constant need for cash to pay for equipment, network connectivity, etc. Even small donations make a profound difference, donating money or hardware is important. => https://www.openbsd.org/donations.html Donating money => https://www.openbsd.org/want.html Donate equipment and parts (wishlist) </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/contributing-to-openbsd.gmi</guid> <link>gemini://perso.pw/blog//articles/contributing-to-openbsd.gmi</link> <pubDate>Tue, 03 May 2022 00:00:00 GMT</pubDate> </item> <item> <title>Blog post: just having fun making games</title> <description> <![CDATA[ <pre>Hi! Just a short blog entry about making games. I've been enjoying learning how to use a game engine for three days now. I also published my two last days on the itch.io platform for independant video games. I'm experimenting a lot with various ideas, a new game must be different than the other to try new mechanics, new features and new gameplay. This is absolutely refreshing to have a tool in hand that let me create interactive content, this is really fantastic. I wish I studied this earlier. Despite my games being very short and simplistic, I'm quite proud of the accomplished work. If someone in the world had fun with them even for 20 seconds, this is a win for me. => https://rsolene.itch.io/ My profile on itch.io (for potential future game publications) </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/making-games.gmi</guid> <link>gemini://perso.pw/blog//articles/making-games.gmi</link> <pubDate>Fri, 29 Apr 2022 00:00:00 GMT</pubDate> </item> <item> <title>Writing my first OpenBSD game using Godot</title> <description> <![CDATA[ <pre># Introduction I'm a huge fan of video games but never really thought about writing one. Well, this crossed my mind a few times, but I don't know anything about writing a GUI software or using OpenGL, but a few days ago I discovered the open source game engine Godot. This game engine is a full-featured tool allowing to easily write 2D or 3D games that are portables on Android, Mac, Windows, Linux, HTML5 (using WebASM) and operating systems where the Godot engine is available, like OpenBSD. => https://godotengine.org/ Godot engine project website # Learning Godot offers a GUI to write games, the GUI itself being a Godot game, it's full featured and come with a code editor, documentation, 2D/3D views, animation, tile set management, and much more. The documentation is well written and gives introduction to the concepts, and then will just teach you how to write a simple 2D game! It only took me a couple of hours to be able to start creating my very own first game and getting the grasps. => https://docs.godotengine.org/en/stable/ Godot documentation I had no experience into writing games but only programming experience. The documentation is excellent and give simple examples that can be easily reused thanks to the way Godot is designed. The forums are also a good way to find a solution for common problems. # Demo I wrote a simple game, OpenBSD themed, especially themed against its 6.8 version for which the artwork is dedicated to the movie "Hackers". It took me like 8 hours I think to write it, it's long, but I didn't see time passing at all, and I learned a lot. I have a very interesting game in my mind, but I need to learn a lot more to be able to do it, so starting with simple games is a nice training for me. It's easy to play and fun (I hope so), give it a try! => https://perso.pw/hack_planet/puffy-bubble.html Play it on the web browser => https://perso.pw/hack_planet/puffy-bubble.x86_64 Play it on Linux => https://perso.pw/hack_planet/puffy-bubble.exe Play it on Windows If you wish to play on OpenBSD or any other operating system having Godot, download the Linux binary and run "godot --main-pack puffy-bubble.x86_64" and enjoy. I chose a neon style to fit to the theme, it's certainly not everyone's taste :) => static/puffy-bubble.png A screenshot of the game, displaying a simple maze in the neon style, a Puffy mascot, the text "Hack the planet" and a bubble on the top of the maze. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/writing-a-game-with-godot.gmi</guid> <link>gemini://perso.pw/blog//articles/writing-a-game-with-godot.gmi</link> <pubDate>Thu, 28 Apr 2022 00:00:00 GMT</pubDate> </item> <item> <title>Routing a specific user on a specific network interface on Linux</title> <description> <![CDATA[ <pre># Introduction I have a special network need on Linux, I must have a single user going through specific VPN tunnel. This can't be done using a different metric for the VPN or by telling the program to bind on a specific interface. # How does it work The setup is easy once you find how to proceed on Linux: we define a new routing table named 42 and add a rule assigning user with uid 1002 to this routing table. It's important to declare the VPN default route on the exact same table to make it work.
REMOTEGW=YOUR_VPN_REMOTE_GATEWAY_IP
LOCALIP=YOUR_VPN_LOCAL_IP
INTERFACE=tun0
ip route add table 42 $REMOTEGW dev tun0
ip route add table 42 default via $REMOTEGW dev tun0 src $LOCALIP
ip rule add pref 500 uidrange 1002-1002 lookup 42
ip rule add from $LOCALIP table 42
# Conclusion It's quite complicated to achieve this on Linux because there are many ways to proceed like netns (network namespace), iptables or vrf but the routing solution is quite elegant, and the documentation are never obvious for this use case. I'd like to thank @loweel@bbs.keinpfusch.net from the Fediverse for giving me the first bits about ip rules and using a different route table. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/linux-user-on-specific-interface.gmi</guid> <link>gemini://perso.pw/blog//articles/linux-user-on-specific-interface.gmi</link> <pubDate>Sat, 23 Apr 2022 00:00:00 GMT</pubDate> </item> <item> <title>Video guide to install OpenBSD 7.1 with the GNOME desktop</title> <description> <![CDATA[ <pre># Introduction I asked the community recently if they would like to have a video tutorial about installing OpenBSD, many people answered yes so here it is! I hope you will enjoy it, I'm quite happy of the result while I'm not myself fan of watching video tutorials. # The links The videos are published on Peertube, but you are free to reupload them on YouTube if you want to, the licence permits it. I won't publish on YouTube because I don't want to feed this platform. The English video has Italian subtitles that have been provided by a fellow reader. => https://videos.pair2jeux.tube/w/rAfEsfT7goA4yps4HQMmt5 [English] Guide to install OpenBSD 7.1 with the GNOME desktop => https://videos.pair2jeux.tube/w/hmjvVdN8vDnJWwp8Czd866 [French] Guide vidéo d'installation d'OpenBSD de A à Z avec l'environnement GNOME # Why not having used a VM? I really wanted to use a real hardware (an IBM ThinkPad T400 with an old Core 2 Duo) instead of a virtual machine because it feels a lot more real (WoW :D) and has real world quirks like firmwares that would be avoided in a VM. # Youtube Links If you prefer YouTube, someone republished the video on this Google proprietary platform. => https://youtu.be/_ntBSbbsQT4 [YOUTUBE] [English] Guide to install OpenBSD 7.1 with the GNOME desktop => https://youtu.be/js9suODs8A0 [YOUTUBE] [French] Guide vidéo d'installation d'OpenBSD de A à Z avec l'environnement GNOME # Making-off I rarely make videos, and it was a first time for me to create this, so I wanted to share about how I made it because it was very amateurish and weird :D My first setup trying to record the screen of a laptop using another laptop and an USB camera, it didn't work well => static/setup_0.jpg My first setup trying to record the screen of a laptop using another laptop and an USB camera, it didn't work well My second setup, with a GoPro camera more or less correctly aligned with the laptop screen => static/setup_1.jpg My second setup, with a GoPro camera more or less correctly aligned with the laptop screen The first part on Linux was recorded locally with ffmpeg from the T400 computer, the rest is recorded with the GoPro camera, I applied a few filters with the shotcut video editing software to flatten the picture (the lens is crazy on the GoPro). I spent like 8 hours to create the video, most of the time was editing, blurring my Wi-Fi password, adjusting the speed of the sequences, and once the video was done I recorded my audio comment (using a USB Rode microphone) while watching it, I did it in English and in French, and used shotcut again to sync the audio with the video and merge them together. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/openbsd-video-tutorial-installation.gmi</guid> <link>gemini://perso.pw/blog//articles/openbsd-video-tutorial-installation.gmi</link> <pubDate>Sat, 23 Apr 2022 00:00:00 GMT</pubDate> </item> <item> <title>Reduce httpd web server bandwidth usage by serving compressed files</title> <description> <![CDATA[ <pre># Introduction When reaching a website, most web browsers will send a header (some metadata about the requestion) informing the web server that you supported compressed content. In OpenBSD 7.1, the httpd web server received a new feature allowing it to serves a pre-compressed file of a requested file if the web browser supports compression. The benefits are a bandwidth usage reduced by 2x to 10x depending on the file content, this is particularly interesting for people who self-host and for high traffic websites. # Configuration In your httpd.conf, in a server block add the "gzip-static" keyword, save the file and reload the httpd service. A simple server block would look like this:
server "perso.pw" {
root "/htdocs/solene"
listen on * port 80
gzip-static
}
# Creating the files In addition to this change, I added a new flag to the gzip command to easily compress files while keeping the original files. Run "gzip -k" on the files you want to serve compressed when the clients support the feature. It's best to compress text files, such as HTML, JS or CSS for the most commons. Compressing binary files like archives, pictures, audio or videos files won't provide any benefit. # How does it work? When the client connects to the httpd server requesting "foobar.html", if gzip-static is used for this location/server, httpd will look for a file named "foobar.html.gz" that is not older than "foobar.html". When found, "foobar.html.gz" is transparently transferred to the client requesting "foobar.html". Take care to regenerate the gz files when you update the original files, remember that the gz files must be newer to be used. # Conclusion This is for me a major milestone for using httpd in self-hosting and with static websites. We battle tested this change with the webzine server often hitting big news websites leading to many people visiting the website in a short time span, this drastically reduced the bandwidth usage of the server, allowing it to support more clients per second. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/openbsd-httpd-gzip.gmi</guid> <link>gemini://perso.pw/blog//articles/openbsd-httpd-gzip.gmi</link> <pubDate>Fri, 22 Apr 2022 00:00:00 GMT</pubDate> </item> <item> <title>OpenBSD 7.1: fan noise and high temperature solution</title> <description> <![CDATA[ <pre># Introduction OpenBSD 7.1 has been released with a change that will set the CPU to max speed when plugged to the wall. This brings better performance and entirely let the CPU and mainboard do the frequency throttling. However, it may doesn't throttle well for some users, resulting in huge power usage even when idle, heat from the CPU and also fan noise. As the usual "automatic" frequency scheduling mode is no longer available when connected to powergrid, I wrote a simple utility to manage the frequency when the system is plugged to the wall, I took the opportunity to improve it, giving better performance than the previous automatic mode, but also giving more battery life when using on a laptop on battery. => https://tildegit.org/solene/obsdfreqd obsdfreqd project page # Installation The project README or man page explains how to install, but here are the instructions to proceed. It's important to remove the automatic mode from apmd which would kill obsdfreqd, apmd can be kept to have its ability to run commands on resume/suspend etc...
doas pkg_add git
cd /tmp/ && git clone https://tildegit.org/solene/obsdfreqd.git
cd obsdfreqd
make
doas make install
rcctl ls on | grep ^apmd && doas rcctl set apmd flags -L && doas rcctl restart apmd
doas rcctl enable obsdfreqd
doas rcctl start obsdfreqd
# Configuration No configuration are required, it works out of the box with a battery saving profile when on battery and a performance profile when connected to power. If you feel adventurous, obsdfreqd man page will give you information about all the parameters available if you want to tailor yourself a specific profile. Note that obsdfreqd can target a specific temperature limit using -T parameter, see the man page for explanations. # FAQ Using hw.perfpolicy="auto" sysctl won't help, the kernel code entirely bypass the frequency management if the system is not running on battery. => https://github.com/openbsd/src/blob/0294e0be5821991219b454f4fdc27f570d30a6fd/sys/kern/sched_bsd.c#L547 sched_bsd.c line shipped in OpenBSD 7.1 Using apmd -A doesn't solve the issue because apmd was simply setting the sysctl hw.perfpolicy to auto, which as explained above set the frequency to full speed when not on battery. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/openbsd-71-fan-noise-temperature.gmi</guid> <link>gemini://perso.pw/blog//articles/openbsd-71-fan-noise-temperature.gmi</link> <pubDate>Thu, 21 Apr 2022 00:00:00 GMT</pubDate> </item> <item> <title>Operating systems battle: OpenBSD vs NixOS</title> <description> <![CDATA[ <pre># Introduction While I'm an OpenBSD contributor, I also enjoy using Linux especially the NixOS distribution which I consider a system apart from the other Linux distributions because of how different it is. Because I use both, I have two SSDs in my laptop with each system installed and I can jump from one to another depending on the task I'm doing or which I want to use. My main system, the one with all my data, is OpenBSD, unfortunately the lack of an interoperable and good file system between NixOS and OpenBSD make it difficult to share data between them without using a network storage offering a protocol they have in common. # OpenBSD and NixOS Let me quickly introduce the two operating systems if you don't know them. OpenBSD is a 25+ years old fork of NetBSD, it's full of history and a solid system, it's also the place where OpenSSH or tmux are developed. It's a BSD system with its own kernel and own drivers, it's not related to Linux but will share most of well known open source programs you can have on Linux, they are provided as packages (programs such as GIMP, Libreoffice, Firefox, Chromium etc...). The whole OpenBSD system (kernel, drivers, userland and packages) is managed by a team of approximately 150 persons (without counting people sending updates and who don't have a commit access). => https://www.openbsd.org/ The OpenBSD project website NixOS will be soon a 20 years old Linux distribution based on the nix package manager. It's offering a new approach to system management, based on reproducible builds and declarative configurations, basically you define how your computer should be configured (packages, services, name, users etc..) in a configuration file and "build" the system to configure itself, if you share this configuration file on another computer, you should be able to reproduce the exact same system. Packages are not installed in a standard file hierarchy but each package files are stored into a dedicated directory and the users profiles are made of symbolic links and many environment variables to permit programs to find libraries or dependencies, for example the path to Firefox may look like something like /nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1/bin/firefox. => https://nixos.org/ The NixOS project website => https://nixos.org/guides/how-nix-works.html NixOS wiki: How Nix works ## Performance OpenBSD is lacking hardware acceleration for encoding/decoding video, this make it a lot slower when working with videos. Interactive desktop usage and I/O also feel slower on OpenBSD, on the other hand the Linux kernel used in NixOS benefits from many people working full time at improving its performance, we have to admit the efforts pay off. Although OpenBSD is slower than Linux, it's actually usable for most tasks one may need to achieve. ## Hardware support OpenBSD doesn't support as many devices as NixOS and its Linux kernel. On NixOS I can use an external NVIDIA card using a thunderbolt case, OpenBSD doesn't have support for this case nor has it a driver for NVIDIA cards (which is mostly NVIDIA's fault for not providing documentation). However, OpenBSD barely requires any configuration to work, if the hardware is supported, it will work. Finally, OpenBSD can be used on old computers from various architectures, like i386, old Apple powerpc, risc, arm, while NixOS is only focusing on modern hardware such as Amd64 and Arm64. ## Software choice Both systems provide a huge packages set, but the one from Nix has more choice. It's not that bad on the OpenBSD side though, most common packages are available and often with a recent version, I also found many times a package available in OpenBSD but not in Nix. Most notably, I feel the quality of OpenBSD packages is slightly higher than on Nix, they have less issues (Nix packages sometimes have issues that may be related to nix unusual file hierarchy) and are sometimes patched to have better defaults (for instance I'm thinking of disabling network accesses opened by default in some GUI applications). Both of them make a new release every six months, but while OpenBSD only backport packages security fixes for its latest release, NixOS provides a lot more updates to its packages for the release users. Updating packages is painless on OpenBSD and NixOS, but it's easier to find which version you are currently using on OpenBSD. This may be because I don't know enough the nix shell but I find it very hard to know if I'm actually using a program that has been updated (after a CVE I often check that) or if it's not. => https://openports.pl/ OpenBSD packages list => https://search.nixos.org/packages NixOS packages list ## Network Network is certainly the area where OpenBSD is the most well-known, its firewall Packet Filter is easy to use/configure and efficient. OpenBSD provides mechanisms such as routing tables/domains to assign a network interface to an entire separated network, allowing to expose a program/user to a specific interface reliably, I didn't find how to achieve this on Linux yet. OpenBSD comes with all the required daemons to manage a network (dhcp, slaacd, rpki, email, http, NAT, ftp, tftp etc...) within its base system. The performance when dealing with network throughput may be sub-par on OpenBSD compared to Linux but for the average user or server it's fine, it will mostly depend on the network card used and its driver support. I don't really enjoy playing with network on Linux as I find it very complicated, I never found how to aggregate wifi and Ethernet interfaces to transparently switch from one to the other when I (un)plug the rj45 cable on my laptop, doing this is easy to achieve on OpenBSD (I don't enjoy losing all my TCP connections when moving the laptop around). ## Maintenance The maintenance topic will be very personal, for a personal workstation/server case and not a farm of hundreds of servers. OpenBSD doesn't change much, it has a new release every six months but the upgrades are always easy to handle, most corner cases are documented in the upgrade guide and I'm ALWAYS confident when I have to update an OpenBSD system. NixOS is also easy to update and keep clean, I never had any issue when upgrading yet and it would still be possible to rollback to the previous version in case something is going wrong. I can say they have both a different approach but they both work well. ## Documentation I have to say the NixOS documentation is rather huge but yet not always useful. There is a nice man page named "configuration.nix" giving all the options to parameter a system, but it's generated from the Nix code and is often lacking explanations in addition to describe an API. There are also a few guides and manual available on NixOS website but they are either redundant or not really describing how to solve real world problems. => https://nixos.org/learn.html NixOS documentation On the OpenBSD side, the website provides a simple "Frequently Asked Questions" section for some use case, and then all the system and its internal are detailed in very well written man pages, it may feel unfriendly or complicated at first but once you taste the OpenBSD man pages you easily get sad when looking at another documentation. If you had to setup an OpenBSD system for some task relying on components from the base system (= not packages), I'm confident to say you could do it offline with only the man pages. OpenBSD is not a system that you find its documentation on various forums or github gists, while I often feel this with NixOS :( => https://www.openbsd.org/faq/index.html OpenBSD FAQ => https://man.openbsd.org/ OpenBSD man pages ## Contributing I would say NixOS have a modern contribution system, it relies on github and a bot automatically do many checks to the contributions, helping contributors to check their work quickly without "wasting" the time of someone who would have to read every submitted code. OpenBSD is doing exactly that, changes to the code are done on a mailing list, only between humans. It doesn't scale very well but the human contact will give better explanations than a bot, but this is when your work is interesting someone who want to spend time on it, sometimes you will never get any feedback and it's a bit sad we are losing updates and contributors because of this. # Conclusion I can't say one is better to the other nor that one is doing absolutely better at one task. My love for OpenBSD may come from its small community, made of humans that like working on something different. I know how OpenBSD works, when something is wrong it's easy to debug because the system has been kept relatively simple. It's painless, when your hardware is supported, it just works fine. The default configuration is good and I don't have to worry about it. But I also love NixOS, it's adventurous, it offers a new experience (transactional updates, reproducibility) that I feel are the future of computing, but it also make the whole very complicated to understand and debug. It's a huge piece of software that could be bend to many forms given you are a good Nix arcanist. I'd be happy to hear about your experiences with regards to OpenBSD and NixOS, feel free to write me (mastodon or email) about this! </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/openbsd-vs-nixos.gmi</guid> <link>gemini://perso.pw/blog//articles/openbsd-vs-nixos.gmi</link> <pubDate>Mon, 18 Apr 2022 00:00:00 GMT</pubDate> </item> <item> <title>Keep your OpenBSD system cool with obsdfreqd</title> <description> <![CDATA[ <pre># Introduction Last week I wrote a system daemon to manage the CPU frequency from userland, entirely bypassing the kernel automatic mode. While this was more of a toy at first because I only implemented the same automatic mode used in the kernel but with all the variables being easily changed, I found it valuable for many use case to improve battery life or even temperature. The coolest feature I added today is to support a maximum temperature and let the program do its best to keep the CPU temperature below the limit. => https://tildegit.org/solene/obsdfreqd obsdfreqd project page # Installation As said in the "Too Long Didn't Read" section of the project README, a simple `make install` as root and starting the service is enough. # Results A nice benchmark to run was to start the compilation of the rust package with all the four cores of my T470 laptop and run obsdfreqd with various temperature limits and see how it goes. The program did a good job at reducing the CPU frequency to keep the temperature around the threshold. => static/bench_freq_temp.png Diagram of benchmark results of various temperature limitation # Conclusion While this is ultimately not a replacement for the in-kernel frequency scheduler, it can be used to keep a computer a lot cooler or make a system comply with some specific requirements (performance for given battery life or maximum temperature). The customization is so that you can have various settings depending if the system is running on battery or not, which can be tailored to suit every kind of user. The defaults are made to provide good performance when on AC, and provide a balanced performance/battery life mode when on battery. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/openbsd-cool-frequency.gmi</guid> <link>gemini://perso.pw/blog//articles/openbsd-cool-frequency.gmi</link> <pubDate>Mon, 21 Mar 2022 00:00:00 GMT</pubDate> </item> </channel> </rss>