💾 Archived View for perso.pw › blog › rss.xml captured on 2022-06-11 at 21:06:10.
⬅️ Previous capture (2022-06-03)
-=-=-=-=-=-=-
<?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>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:
$ 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> <item> <title>Reproducible clean $HOME in OpenBSD using impermanence</title> <description> <![CDATA[ <pre># Introduction Let me present you my latest project: home-impermanence, under this name is a reference to the NixOS community project impermanence. The name may not be obvious about what it is doing, let me explain. => https://nixos.wiki/wiki/Impermanence NixOS wiki about Impermanence, a community module => https://tildegit.org/solene/home-impermanence home-impermanence for OpenBSD The original goal of impermanence in NixOS is to have a fully reproducible system mounted on tmpfs where only user-defined files and directories are hooked into the temporary file system to be persistent (such as /var/lib, /var/lib and some /etc files for instance). Why this is something achievable on NixOS, on OpenBSD side we are far from having the tooling to go that deep so I wrote home-impermanence that allows an user to just do that at their $HOME level. What does it mean exactly? When you start your system, your $HOME directory will be mounted with an empty memory based file system (using mfs) and symbolic links to files and directories listed in the configuration file will be done in your $HOME. Every time you reboot, you will have the exact same set of files, extra files created meanwhile will be lost. When you hold a $HOME directory for long, you know you get many directories and files created in various ~/.config or ~/.local or directly as dotfiles in the top level of the home directory, with impermanence you can get ride of all the noise. A benefit is that you can run software as if it was their first run, in some software upgrade you will avoid old settings that would create troubles, or settings that would disturb a whole class of applications (like a gtk setting affecting all gtk programs), with impermanence the user can decide exactly what should remain across reboots or disappear. # Implementation My implementation is a Perl script relying on some libraries packaged on OpenBSD, it will run as root from a rc service and the settings done in rc.conf.local. It will read the configuration file from the persistent directory holding the user data and create symlinks in the target directory to the files and directories, doing some sanitizing in the process to prevent listed files to be included in listed directories which would nest symlinks incorrectly. I chose Perl because it's a stable language, OpenBSD ships with Perl and the very few dependencies required were already available in the ports tree. The program could easily be ported to Linux, FreeBSD and maybe NetBSD, the mount_mfs calls could be replaced by a mount_tmpfs and the directories symlinks could be done with a mount_bind or mount_nullfs which we don't have on OpenBSD, if someone wants to port my project to another system I could help adding the required logic. # How to use I wrote a complete README file explaining the installation and configuration process, for full instructions refer to this document and the man page that ships with home-impermanence. => https://tildegit.org/solene/home-impermanence/src/branch/main/README.md home-impermanence README ## Installation Quick method:
git clone https://tildegit.org/solene/home-impermanence/
cd home-impermanence
doas make install
doas rcctl enable impermanence
doas rcctl set impermanence flags -u user -d /home/persist/
doas install -d /home/persist/
From now, you may want to make things quickly, logout from your user and run these commands, this will move your user directory and prepare the mountpoint.
mv /home/user /home/persist/user
install -d -o user -g wheel /home/user
Now, it's time to configure impermanence before running it. ## Configuration Reusing the paths from the installation example, the configuration file should be in /home/persist/user/impermanence.yml , the file must be using YAML formatting. Here is my personal configuration file that you can use as a base.
size: 500m
files:
- .Xdefaults
- .Xresources
- .bashrc
- .gitconfig
- .kshrc
- .profile
- .xsession
- .tmux.conf
- .config/kwalletrc
directories:
- .claws-mail
- .config/Thunar
- .config/asciinema
- .config/gajim
- .config/kak
- .config/keepassxc
- .config/lagrange
- .config/mpv
- .config/musikcube
- .config/openttd
- .config/xfce4
- .config/zim
- .local/share/cozy
- .local/share/gajim
- .local/share/ibus-typing-booster
- .local/share/kwalletd
- .mozilla
- .ssh
- Documents
- Downloads
- Music
- bin
- dev
- notes
- tmp
When you think you are done, start the impermanence rc service with rcctl start impermanence and log-in. You should see all the symlinks you defined in your configuration file. ## Result Here is the content of my $HOME directory when I use impermanence.
solene@daru ~> ls -la
total 104
drwxr-xr-x 8 solene wheel 1024 Mar 15 12:10 .
drwxr-xr-x 17 root wheel 512 Mar 14 15:36 ..
-rw------- 1 solene wheel 165 Mar 15 09:08 .ICEauthority
-rw------- 1 solene solene 53 Mar 15 09:08 .Xauthority
lrwxr-xr-x 1 root wheel 34 Mar 15 09:08 .Xdefaults -> /home/permanent//solene/.Xdefaults
lrwxr-xr-x 1 root wheel 35 Mar 15 09:08 .Xresources -> /home/permanent//solene/.Xresources
-rw-r--r-- 1 solene wheel 48 Mar 15 12:07 .aspell.en.prepl
-rw-r--r-- 1 solene wheel 42 Mar 15 12:07 .aspell.en.pws
lrwxr-xr-x 1 root wheel 31 Mar 15 09:08 .bashrc -> /home/permanent//solene/.bashrc
drwxr-xr-x 9 solene wheel 512 Mar 15 12:10 .cache
lrwxr-xr-x 1 root wheel 35 Mar 15 09:08 .claws-mail -> /home/permanent//solene/.claws-mail
drwx------ 8 solene wheel 512 Mar 15 12:27 .config
drwx------ 3 solene wheel 512 Mar 15 09:08 .dbus
lrwxr-xr-x 1 root wheel 34 Mar 15 09:08 .gitconfig -> /home/permanent//solene/.gitconfig
drwx------ 3 solene wheel 512 Mar 15 12:32 .gnupg
lrwxr-xr-x 1 root wheel 30 Mar 15 09:08 .kshrc -> /home/permanent//solene/.kshrc
drwx------ 3 solene wheel 512 Mar 15 09:08 .local
lrwxr-xr-x 1 root wheel 32 Mar 15 09:08 .mozilla -> /home/permanent//solene/.mozilla
lrwxr-xr-x 1 root wheel 32 Mar 15 09:08 .profile -> /home/permanent//solene/.profile
lrwxr-xr-x 1 solene wheel 30 Mar 15 12:10 .sbclrc -> /home/permanent/solene/.sbclrc
drwxr-xr-x 2 solene wheel 512 Mar 15 09:08 .sndio
lrwxr-xr-x 1 root wheel 28 Mar 15 09:08 .ssh -> /home/permanent//solene/.ssh
lrwxr-xr-x 1 root wheel 34 Mar 15 09:08 .tmux.conf -> /home/permanent//solene/.tmux.conf
lrwxr-xr-x 1 root wheel 33 Mar 15 09:08 .xsession -> /home/permanent//solene/.xsession
-rw------- 1 solene wheel 25273 Mar 15 13:26 .xsession-errors
lrwxr-xr-x 1 root wheel 33 Mar 15 09:08 Documents -> /home/permanent//solene/Documents
lrwxr-xr-x 1 root wheel 33 Mar 15 09:08 Downloads -> /home/permanent//solene/Downloads
lrwxr-xr-x 1 root wheel 30 Mar 15 09:08 HANGAR -> /home/permanent//solene/HANGAR
lrwxr-xr-x 1 root wheel 27 Mar 15 09:08 dev -> /home/permanent//solene/dev
lrwxr-xr-x 1 root wheel 29 Mar 15 09:08 notes -> /home/permanent//solene/notes
lrwxr-xr-x 1 root wheel 33 Mar 15 09:08 quicklisp -> /home/permanent//solene/quicklisp
lrwxr-xr-x 1 root wheel 27 Mar 15 09:08 tmp -> /home/permanent//solene/tmp
## Rollback If you want to rollback it's easy, disable impermanence, move /home/persist/user to /home/user and you are done. # Conclusion I really don't want to go back to not using impermanence since I tried it on NixOS. I thought implementing it only for $HOME would be good enough as a start and started thinking about it, made a proof of concept to see if the symbolic links method was enough to make it work, and it was! I hope you will enjoy this as much as I do, feel free to contact me if you need some help understanding the setup. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/openbsd-impermanence.gmi</guid> <link>gemini://perso.pw/blog//articles/openbsd-impermanence.gmi</link> <pubDate>Tue, 15 Mar 2022 00:00:00 GMT</pubDate> </item> <item> <title>Reed-alert: five years later</title> <description> <![CDATA[ <pre># Introduction I wrote the program reed-alert five years ago, I've been using it since its first days, here is some feed back about it. The software reed-alert is meant to be used by system administrators who want to monitor their infrastructures and get alerts when things go wrong. I got a lot more experience in the monitoring field over time and I wanted to share some thoughts about this project. => https://tildegit.org/solene/reed-alert reed-alert source code # Reed-alert ## The name The software name is a pun I found in a Star Trek Enterprise episode. => https://memory-alpha.fandom.com/wiki/Red_alert#Notable_uses Reed alert pun origins ## Project finished The code didn't receive many commits over the last years, I consider the program to be complete with regard to features, but new probes could be added, or bug fixes could be done. But the core of the software itself is perfect to me. The probes are small parts of code allowing to monitor extra states, like http return code, working ping, service started etc... It's already easy to extend reed-alert using a shell command returning 0 or not 0 to define a custom probe. ## Reliability I don't remember having a single issue with reed-alert since I've set it up on my server. It's run by a cron job every 10 minutes, this mean a common lisp interpreter is loading the code, evaluating the configuration file, running the check commands and alerts commands if required, and stops. I chose a serviceless paradigm for reed-alert as it make the code and usage a lot simpler. With a running service, it could fail, leak memory, be exploited and certainly many other bugs I can't think of. Reed-alert is simple as it only need a common lisp interpreter, the most notable sbcl and ecl interpreters are absolutely reliable and change very little over time. Some unix standard commands are required for some checks or default alerts, such as ping, service, mail or curl but this defers all the work to well established binaries. The source code is minimal with 179 lines for reed-alert core and 159 lines for the probes, a total of 338 lines of code (including empty lines and comments), hacking on reed-alert is super easy and always a lot of fun for me. For whatever reason, my common lisp software often work at first try when I add new features, so it's always pleasant to work on them. ## Awesome features One aspect of reed-alert that may disturb users at first is the choice of common lisp code as a configuration file, this may look complicated at first, but a simple configuration doesn't require more common lisp knowledge than what is explained in reed-alert documentation. But it gives all its power when you need to loop over a data entry to run checks, allowing to make reed-alert dynamic instead of handwriting all the configuration. The use of common lisp as configuration has other advantages, it's possible to chain checks to easily prevent some checks to be done in case a condition is failing. Let me give a few examples for this:
(=> mail disk-usage :path "/" :limit 60 :desc "partition /")
(=> mail disk-usage :path "/var" :limit 70 :desc "partition /var")
(=> mail disk-usage :path "/home" :limit 95 :desc "partition /home")
(=> mail service :name "dovecot")
(=> mail service :name "spamd")
(=> mail service :name "dkimproxy_out")
(=> mail service :name "smtpd")
(=> mail service :name "ntpd")
(=> mail number-of-processes :limit 140)
;; check dataswamp server is working
(=> mail ping :host "dataswamp.org" :desc "Dataswamp")
;; check webzine related web servers
(and
(=> mail ping :host "openports.pl" :desc "Liaison Grifon.fr")
(=> mail curl-http-status :url "https://webzine.puffy.cafe" :desc "Webzine Puffy.cafe" :timeout 10)
(=> mail curl-http-status :url "https://puffy.cafe" :desc "Puffy.cafe" :timeout 10)
(=> mail ssl-expiration :host "webzine.puffy.cafe" :seconds (* 7 24 60 60))
(=> mail ssl-expiration :host "puffy.cafe" :seconds (* 7 24 60 60)))
;; check openports.pl is working
(and
(=> mail ping :host "46.23.90.152" :desc "Openports.pl ping")
(=> mail curl-http-status :url "http://46.23.90.152" :desc "Packages OpenBSD http" :timeout 10))
;; check www.openbsd.org website is replying under 10 seconds
(=> mail curl-http-status :url "https://www.openbsd.org" :desc "OpenBSD.org" :timeout 10)
;; check if a XML file is created regularly and valid
(=> mail file-updated :path "/var/www/htdocs/solene/openbsd-current.xml" :limit 1440)
(=> mail command :command (format nil "xmllint /var/www/htdocs/solene/openbsd-current.xml") :desc "XML openbsd-current.xml is not valid")
;; monitoring multiple gopher servers
(loop for host in '("grifon.fr" "dataswamp.org" "gopherproject.org")
do
(=> mail command
:try 6
:command (format nil "echo '/is-alive?done-by-solene-at-libera' | nc -w 3 ~a 70" host)
:desc (concatenate 'string "Gopher " host)))
(quit)
# Conclusion I wrote a simple software using an old programming language (Common LISP ANSI is from 1994), the result is that it's reliable over time, require no code maintenance and is fun to code on. => https://en.wikipedia.org/wiki/Common_Lisp Common Lisp on Wikipedia </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/five-years-of-reed-alert.gmi</guid> <link>gemini://perso.pw/blog//articles/five-years-of-reed-alert.gmi</link> <pubDate>Thu, 10 Feb 2022 00:00:00 GMT</pubDate> </item> <item> <title>Harden your NixOS workstation</title> <description> <![CDATA[ <pre># Introduction Coming from an OpenBSD background, I wanted to harden my NixOS system for better security. As you may know (or not), security mitigations must be thought against a security threat model. My model here is to prevent web browsers to leak data, prevent services to be exploitable remotely and prevent programs from being exploited to run malicious code. NixOS comes with a few settings to improve in these areas, I'll share a sample of configuration to increase the default security. Unrelated to security defense itself, but you should absolutely encrypt your filesystem, so in case of physical access to your computer no data could be extracted. # Use the hardened profile There are a few profiles available by default in NixOS which are files with a set of definitions and one of them is named "hardened" because it enables many security measures. => https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/hardened.nix Link to the hardened profile definition Here is a simplified list of important changes:
imports =
[
./hardware-configuration.nix
<nixpkgs/nixos/modules/profiles/hardened.nix>
];
# enable firewall and block all ports
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [];
networking.firewall.allowedUDPPorts = [];
# disable coredump that could be exploited later
# and also slow down the system when something crash
systemd.coredump.enable = false;
# required to run chromium
security.chromiumSuidSandbox.enable = true;
# enable firejail
programs.firejail.enable = true;
# create system-wide executables firefox and chromium
# that will wrap the real binaries so everything
# work out of the box.
programs.firejail.wrappedBinaries = {
firefox = {
executable = "${pkgs.lib.getBin pkgs.firefox}/bin/firefox";
profile = "${pkgs.firejail}/etc/firejail/firefox.profile";
};
chromium = {
executable = "${pkgs.lib.getBin pkgs.chromium}/bin/chromium";
profile = "${pkgs.firejail}/etc/firejail/chromium.profile";
};
};
# enable antivirus clamav and
# keep the signatures' database updated
services.clamav.daemon.enable = true;
services.clamav.updater.enable = true;
Rebuild the system, reboot and enjoy your new secure system. # Going further: network filtering If you want to absolutely control your network connections, I'd absolutely recommend the service OpenSnitch. This is a daemon that will listen to all the network done on the system and allow you to allow/block connections per executable/source/destination/protocol/many parameters. OpenSnitch comes with a GUI app called opensnitch-ui which is mandatory, if the ui is not running, no filtering is done. When the ui is running, every time a new connection is not matching an existing rule, you will be prompted with information telling you what executable is trying to do on which protocol with which host, then you can decide how long you allow this (or block). Just use `services.opensnitch.enable = true;` in the system configuration and run opensnitch-ui program in your graphical session. To have persistent rules, open opensnitch-ui, go in the Preferences menu and tab Database, choose "Database type: File" and pick a path to save it (it's a sqlite database). From this point, you will have to allow / block all network done on your system, it can be time-consuming at first, but it's user-friendly enough and rules can be done like "allow this entire executable" so you don't have to allow every website visited by your web browser (but you could!). You may be surprised by the amount of traffic done by non networking programs. After some time, the rule set should be able to cope with most of your needs without needing to add new entries. => https://github.com/evilsocket/opensnitch/wiki/Getting-started OpenSnitch wiki: getting started </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/nixos-hardened.gmi</guid> <link>gemini://perso.pw/blog//articles/nixos-hardened.gmi</link> <pubDate>Thu, 13 Jan 2022 00:00:00 GMT</pubDate> </item> <item> <title>How to pin a nix-shell environment using niv</title> <description> <![CDATA[ <pre># Introduction In the past I shared a bit about Nix nix-shell tool, allowing to have a "temporary" environment with a specific set of tools available. I'm using it on my blog to get all the dependencies required to rebuild it without having to remember what programs to install. But while this method was practical, as I'm running NixOS development version (called unstable channel), I have to download the new versions of the dependencies every time I use the nix shell. This is long on my DSL line, and also a waste of bandwidth. There is a way to pin the version of the packages, so I always use the exact same environment, whatever the version of my nix. # Use niv tool Let's introduce you to niv, a program to manage nix dependencies, for this how-to I will only use a fraction of its features. We just want it to init a directory with a default configuration pinning the nixpkgs repository to a branch / commit ID, and we will tell the shell to use this version. => https://github.com/nmattia/niv niv project GitHub homepage Let's start by running niv (you can get niv from nix package manager) in your directory:
niv init
It will create a nix/ directory with two files: sources.json and sources.nix, looking at the content is not fascinating here (you can take a look if you are curious though). The default is to use the latest nixpkgs release. # Create a shell.nix file My previous shell.nix file looked like this:
with (import <nixpkgs> {});
mkShell {
buildInputs = [
gnumake sbcl multimarkdown python3Full emacs-nox toot nawk mandoc libxml2
];
}
Yes, I need all of this for my blog to work because I have texts in org-mode/markdown/mandoc/gemtext/custom. The blog also requires toot (for mastodon), sbcl (for the generator), make (for building and publishing). Now, I will make a few changes to use the nix/sources.nix file to tell it where to get the nixpkgs information, instead of <nixpkgs> which is the system global.
let
sources = import ./nix/sources.nix;
pkgs = import sources.nixpkgs {};
in
with pkgs;
pkgs.mkShell {
buildInputs = [
gnumake sbcl multimarkdown python3Full emacs-nox
toot nawk mandoc libxml2
];
}
That's all! Now, when I run nix-shell in the directory, I always get the exact same shell and set of packages every day. # How to update? Because it's important to update from time to time, you can easily manage this using niv, it will bump the latest commit id of the branch of the nixpkgs repository:
niv update nixpkgs -b master
When a new release is out, you can switch to the new branch using:
niv modify nixpkgs -a branch=release-21.11
# Using niv with configuration.nix It's possible to use niv to pin the git revision you want to use to build your system, it's very practical for many reasons like following the development version on multiple machines with the exact same revision. The snippet to use sources.nix for rebuilding the system is a bit different. Replace "{ pkgs, config, ... }:" with:
{
sources ? import ./nix/sources.nix,
pkgs ? import sources.nixpkgs {},
config, ...
}:
Of course, you need to run "niv init" in /etc/nixos/ before if you want to manage your system with niv. # Extra tip: automatically run nix-shell with direnv It's particularly comfortable to have your shell to automatically load the environment when you cd into a project requiring a nix-shell, this is doable with the direnv program. => https://nixos.org/guides/declarative-and-reproducible-developer-environments.html#declarative-reproducible-envs nixos documentation about direnv usage => https://direnv.net/ direnv project homepage This can be done in 3 steps after you installed direnv in your profile: 1. create a file .envrc in the directory with the content "use nix" (without double quotes of course) 2. execute "direnv allow" 3. create the hook in your shell, so it knows how to do with direnv (do this only once) => https://direnv.net/docs/hook.html How to hook direnv in your shell Everytime you will cd into the directory, nix-shell will be automatically started. </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/nix-niv-shell.gmi</guid> <link>gemini://perso.pw/blog//articles/nix-niv-shell.gmi</link> <pubDate>Wed, 12 Jan 2022 00:00:00 GMT</pubDate> </item> <item> <title>My plans for 2022</title> <description> <![CDATA[ <pre>Greetings dear readers, I wish you a happy new year and all the best. Like I did previously at the new year time, although it's not a yearly exercise, I would like to talk about the blog and my plan for the next twelve months. # About me Let's talk about me first, it will make sense for the blog part after. I plan to find a new job, maybe switch into the cybersecurity field or work in some position allowing me to contribute to an open source project, it's not that easy to find, but I have hope. This year, I will work at getting new skills, this should help me find jobs, but I also think I've been a resting a bit about learning over the last two years. My plan is to dedicate 45 minutes every day to learn about a topic. I already started doing so with some security and D language readings. # About the blog With regular learning time, I'm not sure yet if I will have much desire to write here as often as I did in 2021. I'm absolutely sure the publication rate will drop, but I will try to maintain a minimum, because I'm learning I will want to share some ideas, experiences or knowledge hopefuly. I'm thanksful to readers community I have, I often get feedback by email or IRC or mastodon about my posts, so I can fix them, extend them or rework them if I was wrong. This is invaluable to me, it helps me to make connections to other people, and it's what make life interesting. # Podcast In December 2021, I had the chance to be interviewed by the people of the BSDNow podcast, I'm talking about how I got into open source, about my blog but also about the old laptop challenge I made last year. => https://www.bsdnow.tv/435 Access to the podcast link on BSDNow Thanks everyone! Let's have fun with computers!</pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/2022-new-year.gmi</guid> <link>gemini://perso.pw/blog//articles/2022-new-year.gmi</link> <pubDate>Sat, 08 Jan 2022 00:00:00 GMT</pubDate> </item> <item> <title>My NixOS configuration</title> <description> <![CDATA[ <pre># Introduction Let me share my NixOS configuration file, the one in /etc/nixos/configuration.nix that describe what is installed on my Lenovo T470 laptop. The base of NixOS is that you declare every user, services, network and system settings in a file, and finally it configures itself to match your expectations. You can also install global packages and per-user packages. It makes a system environment reproducible and reliable. # The file
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# run garbage collector at 19h00 everyday
# and remove stuff older than 60 days
nix.gc.automatic = true;
nix.gc.dates = "19:00";
nix.gc.persistent = true;
nix.gc.options = "--delete-older-than 60d";
# clean /tmp at boot
boot.cleanTmpDir = true;
# latest kernel
boot.kernelPackages = pkgs.linuxPackages_latest;
# sync disk when buffer reach 6% of memory
boot.kernel.sysctl = {
"vm.dirty_ratio" = 6;
};
# allow non free stuff
nixpkgs.config.allowUnfree = true;
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "t470";
time.timeZone = "Europe/Paris";
networking.networkmanager.enable = true;
# wireguard VPN
networking.wireguard.interfaces = {
wg0 = {
ips = [ "192.168.5.1/24" ];
listenPort = 1234;
privateKeyFile = "/root/wg-private";
peers = [
{ # server
publicKey = "MY PUB KEY";
endpoint = "SERVER:PORT";
allowedIPs = [ "192.168.5.0/24" ];
}];
};
};
# firejail firefox by default
programs.firejail.wrappedBinaries = {
firefox = {
executable = "${pkgs.lib.getBin pkgs.firefox}/bin/firefox";
profile = "${pkgs.firejail}/etc/firejail/firefox.profile";
};
};
# azerty keyboard <3
i18n.defaultLocale = "fr_FR.UTF-8";
console = {
# font = "Lat2-Terminus16";
keyMap = "fr";
};
# clean logs older than 2d
services.cron.systemCronJobs = [
"0 20 * * * root journalctl --vacuum-time=2d"
];
# nvidia prime offload rendering for eGPU
hardware.nvidia.modesetting.enable = true;
hardware.nvidia.prime.sync.allowExternalGpu = true;
hardware.nvidia.prime.offload.enable = true;
hardware.nvidia.prime.nvidiaBusId = "PCI:10:0:0";
hardware.nvidia.prime.intelBusId = "PCI:0:2:0";
services.xserver.videoDrivers = ["nvidia" ];
# programs
programs.steam.enable = true;
programs.firejail.enable = true;
programs.fish.enable = true;
programs.gamemode.enable = true;
programs.ssh.startAgent = true;
# services
services.acpid.enable = true;
services.thermald.enable = true;
services.fwupd.enable = true;
services.vnstat.enable = true;
# Enable the X11 windowing system.
services.xserver.enable = true;
services.xserver.displayManager.sddm.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
services.xserver.desktopManager.xfce.enable = false;
services.xserver.desktopManager.gnome.enable = false;
# Configure keymap in X11
services.xserver.layout = "fr";
services.xserver.xkbOptions = "eurosign:e";
# Enable sound.
sound.enable = true;
hardware.pulseaudio.enable = true;
# Enable touchpad support
services.xserver.libinput.enable = true;
users.users.solene = {
isNormalUser = true;
shell = pkgs.fish;
packages = with pkgs; [
gajim audacity chromium dmd dtools
kate kdeltachat pavucontrol rclone rclone-browser
zim claws-mail mpv musikcube git-annex
];
extraGroups = [ "wheel" "sudo" "networkmanager" ];
};
# my gaming users running steam/lutris/emulators
users.users.gaming = {
isNormalUser = true;
shell = pkgs.fish;
extraGroups = [ "networkmanager" "video" ];
packages = with pkgs; [ lutris firefox ];
};
users.users.aria = {
isNormalUser = true;
shell = pkgs.fish;
packages = with pkgs; [ aria2 ];
};
# global packages
environment.systemPackages = with pkgs; [
ncdu kakoune git rsync restic tmux fzf
];
# Enable the OpenSSH daemon.
services.openssh.enable = true;
# Open ports in the firewall.
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ];
networking.firewall.allowedUDPPorts = [ ];
# user aria can only use tun0
networking.firewall.extraCommands = "
iptables -A OUTPUT -o lo -m owner --uid-owner 1002 -j ACCEPT
iptables -A OUTPUT -o tun0 -m owner --uid-owner 1002 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner 1002 -j REJECT
";
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It‘s perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "21.11"; # Did you read the comment?
}
</pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/my-nixos.gmi</guid> <link>gemini://perso.pw/blog//articles/my-nixos.gmi</link> <pubDate>Tue, 21 Dec 2021 00:00:00 GMT</pubDate> </item> <item> <title>Restrict users to a network interface on Linux</title> <description> <![CDATA[ <pre># Introduction If for some reasons you want to prevent a system user to use network interfaces except one, it's doable with a couple of iptables commands. The use case would be to force your user to go through a VPN and make sure it can't reach the Internet if the VPN is not available. => https://linux.die.net/man/8/iptables iptables man page # Iptables We can use simple rules using the "owner" module, basically, we will allow traffic through tun0 interface (the VPN) for the user, and reject traffic for any other interface. Iptables is applying first matching rule, so if traffic is going through tun0, it's allowed and otherwise rejected. This is quite simple and reliable. We will need the user id (uid) of the user we want to restrict, this can be found as third field of /etc/passwd or by running "id the_user".
iptables -A OUTPUT -o lo -m owner --uid-owner 1002 -j ACCEPT
iptables -A OUTPUT -o tun0 -m owner --uid-owner 1002 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner 1002 -j REJECT
Note that instead of --uid-owner it's possible to use --gid-owner with a group ID if you want to make this rule for a whole group. To make the rules persistent across reboots, please check your Linux distribution documentation. # Going further I trust firewall rules to do what we expect from them. Some userland programs may be able to restrict the traffic, but we can't know for sure if it's truly blocking or not. With iptables, once you made sure the rules are persistent, you have a guarantee that the traffic will be blocked. There may be better ways to achieve the same restrictions, if you know one that is NOT complex, please share! </pre> ]]> </description> <guid>gemini://perso.pw/blog//articles/linux-forbid-user-except-vpn.gmi</guid> <link>gemini://perso.pw/blog//articles/linux-forbid-user-except-vpn.gmi</link> <pubDate>Mon, 20 Dec 2021 00:00:00 GMT</pubDate> </item> </channel> </rss>