<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title></title>
    <link href="https://pierrelouis.pakupaku.me/atom.xml" rel="self"/>
    <link href="https://pierrelouis.pakupaku.me"/>
    <updated>2026-09-22T11:02:07+0000</updated>
    <id>https://pierrelouis.pakupaku.me</id>

    
    
    
    
        
    
    
    
        
        
            
            <entry>
                <title>Installing VoidLinux with BTRFS and FDE</title>
                <link href="https://pierrelouis.pakupaku.me/blog/voidlinux-install/"/>
                <updated>2026-09-22T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/voidlinux-install/</id>
                <content type="html">&amp;lt;p&amp;gt;This file was lingering on my computer for a few months. It is at the sime time
similar and different to &amp;lt;a href=&amp;quot;../debian-root-cryptsetup-keyfile/&amp;quot;&amp;gt;this previous
post&amp;lt;/a&amp;gt;. Note that the format is mostly a list of
instructions without long detailed explanations.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;basic-installation&amp;quot;&amp;gt;Basic Installation&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Let&amp;#39;s assume the following disk layout:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# lsblk&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;NAME&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;vda&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    253:0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;    0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    32G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; disk&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;├─vda1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; 253:1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;    0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;   512M&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;├─vda2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; 253:2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;    0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;     1G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;└─vda3&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; 253:4&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;    0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;  30.5G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;We format as follows:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mkfs.vfat -F32 /dev/vda1&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# cryptsetup luksFormat --type luks1 /dev/vda2&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# cryptsetup luksOpen /dev/vda2 cryptboot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mkfs.ext4 /dev/mapper/cryptboot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# cryptsetup luksFormat --type luks2 /dev/vda3&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# cryptsetup luksOpen /dev/vda3 cryptroot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mkfs.btrfs /dev/mapper/cryptroot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Let&amp;#39;s create the basic file system structure:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount /dev/mapper/cryptroot /mnt/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# btrfs subvolume create /mnt/@&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# btrfs subvolume create /mnt/@home&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# btrfs subvolume create /mnt/@log&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# btrfs subvolume create /mnt/@cache&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# btrfs subvolume create /mnt/@snapshots&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# btrfs subvolume create /mnt/@vartmp&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# btrfs subvolume create /mnt/@swap&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# umount /mnt&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount -o subvol=@,compress=zstd /dev/mapper/cryptroot /mnt/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mkdir -p /mnt/{.snapshots,home,var/log,var/cache,var/tmp,var/swap}&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount -o subvol=@home,compress=zstd /dev/mapper/cryptroot /mnt/home&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount -o subvol=@log,compress=zstd /dev/mapper/cryptroot /mnt/var/log&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount -o subvol=@cache,compress=zstd /dev/mapper/cryptroot /mnt/var/cache&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount -o subvol=@snapshots,compress=zstd /dev/mapper/cryptroot /mnt/.snapshots&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount -o subvol=@vartmp,compress=zstd /dev/mapper/cryptroot /mnt/var/tmp&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount -o subvol=@swap,compress=none /dev/mapper/cryptroot /mnt/var/swap&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mkdir  /mnt/boot/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount /dev/mapper/cryptboot /mnt/boot/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mkdir  /mnt/boot/efi&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount /dev/vda1 /mnt/boot/efi/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;And then install the base OS (VoidLinux, libc variant, xbps method):&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# export REPO=https://repo-default.voidlinux.org/current&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# export ARCH=x86_64&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mkdir -p /mnt/var/db/xbps/keys&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# cp /var/db/xbps/keys/* /mnt/var/db/xbps/keys/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# XBPS_ARCH=$ARCH xbps-install -S -r /mnt -R &amp;amp;quot;$REPO&amp;amp;quot; base-system \&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;    grub-x86_64-efi&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; linux snapper cryptsetup grub-btrfs btrfs-progs htop&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; \&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    btop ripgrep neovim&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# btrfs filesystem mkswapfile --size 4G /mnt/var/swap/swapfile&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# swapon /mnt/var/swap/swapfile&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xgenfstab -U /mnt/ &amp;amp;gt; /mnt/etc/fstab&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;After which we chroot into our new installation:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xchroot /mnt /bin/bash&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Let&amp;#39;s configure the basic things first:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# echo HOSTNAME &amp;amp;gt; /etc/hostname&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /usr/share/zoneinfo/&amp;amp;lt;TIMEZONE&amp;amp;gt; /etc/localtime&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# nvim /etc/rc.conf     # go through and check the options&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# nvim /etc/default/libc-locales&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-reconfigure -f glibc-locales&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# passwd    # set root password&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Then let&amp;#39;s deal with encryption. You can find the partition UUID with the
&amp;lt;code&amp;gt;blkid /dev/vda&amp;amp;lt;X&amp;amp;gt;&amp;lt;/code&amp;gt; command.&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# echo GRUB_ENABLE_CRYPTODISK=y &amp;amp;gt;&amp;amp;gt; /etc/default/grub&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# sed -i &amp;amp;#39;s/^GRUB_CMDLINE_LINUX_DEFAULT=&amp;amp;quot;.*&amp;amp;quot;/GRUB_CMDLINE_LINUX_DEFAULT=&amp;amp;quot;rd.luks.uuid=&amp;amp;lt;UUID-VDA4&amp;amp;gt; loglevel=4&amp;amp;quot;/&amp;amp;#39; /etc/default/grub&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# dd bs=1 count=64 if=/dev/urandom of=/boot/root.key&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# cryptsetup luksAddKey /dev/vda3 /boot/root.key&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# chmod 000 /boot/root.key&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# chmod -R g-rwx,o-rwx /boot/root.key&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# dd bs=1 count=64 if=/dev/urandom of=/boot.key&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# cryptsetup luksAddKey /dev/vda2 /boot.key&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# chmod 000 /boot.key&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# echo -e &amp;amp;#39;cryptboot /dev/disk/by-uuid/&amp;amp;lt;UUID-VDA2&amp;amp;gt; /boot.key    luks,discard\ncryptroot /dev/disk/by-uuid/&amp;amp;lt;UUID-VDA4&amp;amp;gt; /boot/root.key    luks,discard&amp;amp;#39; &amp;amp;gt;&amp;amp;gt; /etc/crypttab&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# echo -e &amp;amp;#39;install_items+=&amp;amp;quot; /boot/root.key /etc/crypttab &amp;amp;quot;&amp;amp;#39; &amp;amp;gt; /etc/dracut.conf.d/10-crypt.conf&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Void&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-reconfigure -fa  # will generate the grub config&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;You can now exit the chroot, unmount and close the different (encrypted)
partitions, and reboot.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;btrfs-snapshots&amp;quot;&amp;gt;Btrfs Snapshots&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;https://wiki.archlinux.org/title/Snapper&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;need dbus on voidlinux:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /etc/sv/dbus /var/service/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# reboot    # sv start dbus fails: &amp;amp;quot;fail: dbus: unable to change to service directory: file does not exist&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Then:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# umount /.snapshots&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# rm -rf /.snapshots&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# snapper -c root create-config /&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mount -a        # remount /.snapshots&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# nvim /etc/snapper/configs/root  # enable or disable auto-snapshotting, etc...&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# snapper -c root create --description &amp;amp;quot;initial snapshot of working system&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;You can edit &amp;lt;code&amp;gt;/etc/snapper/configs/root&amp;lt;/code&amp;gt; to configure automatic snapshots and other things.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;select-closer-mirrors&amp;quot;&amp;gt;Select Closer Mirrors&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-install xmirror&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xmirror&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h2 id=&amp;quot;useful-services&amp;quot;&amp;gt;Useful Services&amp;lt;/h2&amp;gt;
&amp;lt;h3 id=&amp;quot;power-management&amp;quot;&amp;gt;Power Management&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-install elogind polkit&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /etc/sv/dbus /var/service/     # if not done already&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /etc/sv/elogind /var/service/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h3 id=&amp;quot;ntp&amp;quot;&amp;gt;NTP&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-install chrony&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /etc/sv/chronyd /var/service/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h3 id=&amp;quot;wireless&amp;quot;&amp;gt;Wireless&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-install iwd&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /etc/sv/iwd /var/service/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /etc/sv/dhcpcd /var/service/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# usermod -aG network &amp;amp;lt;USERNAME&amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-install impala&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h3 id=&amp;quot;intel-microcode&amp;quot;&amp;gt;Intel Microcode&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;xbps-install&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; void-repo-nonfree&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;xbps-install&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -S&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;xbps-install&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; intel-ucode&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h2 id=&amp;quot;graphical-interface&amp;quot;&amp;gt;Graphical Interface&amp;lt;/h2&amp;gt;
&amp;lt;h3 id=&amp;quot;sway&amp;quot;&amp;gt;Sway&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-install mesa-dri intel-media-driver seatd xorg-server-xwayland noto-fonts-ttf noto-fonts-cjk nerd-fonts dejavu-fonts-ttf xdg-desktop-portal-gtk sway swaylock swayidle swaybg ghostty fuzzel&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /etc/sv/seatd /var/service/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# usermod -aG _seatd &amp;amp;lt;USERNAME&amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;ly&amp;lt;/code&amp;gt; is not in the VoidLinux packages, so we need to compile it by ourselves:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo xbps-install curl wget xz&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mkdir&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -p&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; ~/workspace/voidlinux&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; cd ~workspace/voidlinux&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; wget https://ziglang.org/download/0.16.0/zig-x86_64-linux-0.16.0.tar.xz&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; tar xf zig-x86_64-linux-0.16.0.tar.xz&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; cd ~workspace/voidlinux&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo xbps-install git pam-devel brightnessctl libxcb libxcb-devel make gcc&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo usermod&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -aG&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; input,plugdev,storage&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; &amp;amp;lt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;USERNAM&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;&amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; git clone https://github.com/fairyglade/ly.git&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; cd ly&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; ../zig-x86_64-linux-0.16.0/zig build&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo zig build installexe&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -Dinit_system=runit&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo ln&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -sf&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; /etc/sv/ly /var/service/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo rm /var/service/agetty-tty2&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Before finishing, let&amp;#39;s get an initial sway configuration:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mkdir&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -p&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; .config/sway&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; cp /etc/sway/config ~/.config/sway/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;We need to change the default terminal and menu applications:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;set $term ghostty&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;set $menu fuzzel&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;We can now login to sway via ly.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;sound&amp;quot;&amp;gt;Sound&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-install pipewire wireplumber libjack-pipewire wiremix&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# mkdir -p /etc/pipewire/pipewire.conf.d&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -s /usr/share/examples/wireplumber/10-wireplumber.conf /etc/pipewire/pipewire.conf.d/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -s /usr/share/examples/pipewire/20-pipewire-pulse.conf /etc/pipewire/pipewire.conf.d/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# echo &amp;amp;quot;/usr/lib/pipewire-0.3/jack&amp;amp;quot; &amp;amp;gt; /etc/ld.so.conf.d/pipewire-jack.conf&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# reboot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Start &amp;lt;code&amp;gt;pipewire&amp;lt;/code&amp;gt; from your session manager so that it automatically start when you log-in.
(Note that I don&amp;#39;t have any sound via the jack plug...)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;wiremix&amp;lt;/code&amp;gt; is a TUI-based application to control the pipewire.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;bluetooth&amp;quot;&amp;gt;Bluetooth&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# xbps-install libspa-bluetooth bluez bluetui&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# ln -sf /etc/sv/bluetoothd /var/service/&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;bluetui&amp;lt;/code&amp;gt; is a TUI-based application written in Rust to control
the Bluetooth.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;japanese-keyboard&amp;quot;&amp;gt;Japanese Keyboard&amp;lt;/h3&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; xbps-install fcitx5-mozc fcitx5-configtool&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;fcitx5-configtool&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Edit Sway configuration to start fcitx on log-in.&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;exec fcitx5&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h2 id=&amp;quot;post-installation&amp;quot;&amp;gt;Post-Installation&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Install several useful applications:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo xbps-install screen yazi rsync firefox vlc meld beancount fava baobab&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;If you use the tridactyl extension, to navigate in Firefox with vim-like keybindings, and want smooth scrolling:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;:set smoothscroll true&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Install &amp;lt;code&amp;gt;marimo&amp;lt;/code&amp;gt; (like jupyter notebooks but in Python):&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo xbps-install uv&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mkdir ~/workspace/voidlinux/marimo-uv&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; cd ~/workspace/voidlinux/marimo-uv&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; uv init&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; uv add&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; &amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;marimo[recommended]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;</content>
            </entry>
            
        
            
            <entry>
                <title>To LLM or not to LLM</title>
                <link href="https://pierrelouis.pakupaku.me/blog/about-llm/"/>
                <updated>2026-05-30T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/about-llm/</id>
                <content type="html">&amp;lt;h2 id=&amp;quot;foreword&amp;quot;&amp;gt;Foreword&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Whatever our opinions on the matter, Large-Language Models (LLM for short),
dubbed &amp;quot;AI&amp;quot; by the layman, are around us and here to stay.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;After some time lurking on &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://lobste.rs&amp;quot;&amp;gt;lobste.rs&amp;lt;/a&amp;gt;, it feels like there
are two distinct camps: (1) LLMs are great and we should embrace them; or (2)
LLMs are bad and we should not use them, resist and ban them (one such example
is &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://airesistlist.org/&amp;quot;&amp;gt;airesistlist.org&amp;lt;/a&amp;gt;). Actually, banned AI/Robots
is a recurrent theme in Sci-Fi works: Dune, Asimov&amp;#39;s universe, Blade Runner,
Battlestar Galactica, Mass Effect, and so on. (Note that there are also works
where sentient machines co-exist with humans, e.g., Star Wars).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;I&amp;#39;ve personally used LLMs a bit to generate text, simple scripts, or images. It
can be helpful, but my current impression is this is the case only when the
Human in the loop knows about the discussed subject; these systems are too
prone to hallucination and too persuasive. As for generating images, my excuse
is my skills are stuck at drawing stick figures.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In this post I&amp;#39;d like to explore a few thoughts on this topic.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;who-created-the-output&amp;quot;&amp;gt;Who Created the Output?&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;A typical discussion about LLM and copyright can quickly turns into stating
that LLMs have been fed with copyrighted material without any regard for the
rules, whatever we might think about those rules. Going a bit further, we can
ask ourselves who created the result the LLM produces.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;I clearly remember the first time I asked an LLM to write a scientific-looking
text. I was just curious. While the text was not too bad, I didn&amp;#39;t feel like I
owned it. It was not my text; it was written by someone else. How could I claim
this text is my contribution if I am not the one having written it? By analogy
to books, I was the publisher while the LLM was the writer.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Other criticisms I&amp;#39;ve read are:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;the LLM can change the voice of the author, potentially cleverly integrating
its creator&amp;#39;s agenda due to training bias;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;one doesn&amp;#39;t learn how to write, how to express himself, when asking an LLM
to write text;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;why would one bother reading text that was not thoughtfully created?&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h2 id=&amp;quot;the-artistic-nature-of-humankind&amp;quot;&amp;gt;The Artistic Nature of Humankind&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Another topic that comes often in discussions is whether machines will replace
humans or not. Looking in the (not too distant past), I&amp;#39;m pretty sure painters
had similar questions at the dawn of photography.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;As we can observe, photography didn&amp;#39;t replace paintings. Painters adapted their
style to something more abstract, less realistic, because realistic painting
didn&amp;#39;t make sense anymore. It took some times to adapt, sure; there was a
period of turmoil where no one knew what would come out of it, and I believe we
are in the same situation at the time of writing this.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Even more recently, digital photography and good cameras on smartphones didn&amp;#39;t
kill professional photographers. What they did was merely decreasing the cost
of taking a picture, similar to photography decreasing the cost of saving an
instant compared to painting. Some people also reflected on this situation and
tried to make their pictures special, not just showing what something looked
like, but how it felt. I&amp;#39;m thinking of street photography in particular: the
photographer conveys emotions in addition to a visual copy of a given
situation.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Expressing emotions in photography was one of my reasons to get a new DSLR
(it&amp;#39;s expensive, I need reasons to justify the expense). My phone is for
non-artistic pictures, for things I need to remember for later (the price of an
object, the title of a book), while the DSLR is for artistic purposes. I cannot
claim I am good at it; this is only the direction I aim for.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Another analogy would be craftmanship vs mass production. On one side we have a
unique product that takes time and skill to make; on the other side we have a
bland, standardized product devoid of any human touch. Not that one is worse
than the other (everyone nowadays possesses tons of mass produced products),
they are just different.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In short, after having industrialised labour in the past decades, LLMs
industrialise creativity. I think both can co-exist the same way painting and
photography, music concert and music players, or craftmanship and mass
production. Depending on the task, person, and other factors, one can prefer
one or the other.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;the-darkside-of-llms&amp;quot;&amp;gt;The Darkside of LLMs&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Ideally, technology is neither good nor bad, it is the way we use it that makes
it good or bad. However, I think there is something bad about the current state
of LLMs: the current framework of our society.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Which LLMs does the layman person know? The most famous ones are created and
maintained by private companies who do not really have their users&amp;#39; best
interests in mind: collection and use of data without users&amp;#39; consent, absence
of guardrails to prevent misuses or disinformation, prioritize quick economic
returns instead of long-term well-being, etc.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;If people would be less interested in their own personal gains, if there were
more guardrails and regulations, more accountability, better education, and
less pressure tactics from the people in control then maybe we could achieve a
better society.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;about-the-environment&amp;quot;&amp;gt;About the Environment&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;There exists numerous complaints about the impact of LLMs on the environment.
Some people claim that, well, the power consumption is not too bad, renewable
energies are used when possible, the hardware is getting more efficient, etc.
Well, bad news, doing a computation, whatever its efficiency is, consumes more
energy than not doing it.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;For many things in life we seem to forget to ask whether it is worth it. It is
not because we can do something that we should do it. I believe that mass
adoption of LLMs is not worth the damage. Yes, LLMs and other technics under
the AI/machine learning umbrella can be useful in some cases, but this is not
something we should push in every corner of society for the sake of riding the
buzzword train.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;We need to slow down and consider the long-term effects first. Homo Sapiens
appeared ~300,000 years ago, writing is commonly recognized to having been
invented ~5000 years ago, the industrial revolution was a couple of centuries
ago, and the term &amp;quot;machine learning&amp;quot; appeared less than 70 years ago. We do not
need to disrupt our lives every minute and rush towards destruction. Let&amp;#39;s
preserve what we have and consider the history of humanity as a marathon, not a
sprint.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;What&amp;#39;s the worst case? Long-term suffering on one hand, or not being able to
get our dopamine rush in the next 5 seconds on the other hand.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;what-s-next&amp;quot;&amp;gt;What&amp;#39;s next&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Is the solution a total boycott of LLMs? I do not believe so because it is
already too late and not realistic. Instead, we can reflect on our relationship
with them and respect ourselves by making them ethical and safer.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Instead of using closed-source models trained on unknown, potentially
copyrighted content, we can use open-source ones. Instead of using the models
of big, monopolistic corporations we can use the ones of companies that care
for our privacy as well as the environment (LLMs run locally are also a
solution to be considered). And, all-in-all, let&amp;#39;s not forget that we are a
social species; interaction with a program will never replace interaction with
another real human.&amp;lt;/p&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Leveraging Trusted Execution Environments to make Online Video Games Cheat-Resistant</title>
                <link href="https://pierrelouis.pakupaku.me/blog/gangi/"/>
                <updated>2026-05-14T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/gangi/</id>
                <content type="html">&amp;lt;h1 id=&amp;quot;introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;Even though video games have strong performance requirements, protecting online
video games by leveraging TEEs is not a trivial task due to the inherent
limitations of TEEs: (i) memory size limitation; (2) no direct access to I/O
operations; and (3) non negligible performance overhead to ensure security
properties of the TEE.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The challenges of this research project are three-fold: 1) how to design an
effective method to partition the game code into a secure and unsecure part, to
keep the memory footprint small; 2) how to provide trusted I/O; and 3) how to
ensure acceptable performance.&amp;lt;/p&amp;gt;
&amp;lt;h1 id=&amp;quot;projects&amp;quot;&amp;gt;Projects&amp;lt;/h1&amp;gt;
&amp;lt;h2 id=&amp;quot;gangi&amp;quot;&amp;gt;Gangi&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;The global online video game industry has become a more than one hundred
billion dollar market. Cheating is one of the major issues in multiplayer
online video games. Cheat prevention is challenging because of the unique
threat model of online games. Because the cheaters physically possess their own
game computers, they can install cheat tools at the user level and OS and can
access the physical DRAM bus to tamper with the game process.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;We propose to efficiently prevent memory tampering cheats by leveraging a trusted
execution environment (TEE), Intel Client SGX. It provides strong integrity
protection against memory tampering. Unfortunately, its strong protection comes
with a severe size limitation of the available enclave memory. Running the
entire game process inside the enclave exceeds the memory limit.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/gangi/gangi.jpg&amp;quot; alt=&amp;quot;Gangi architecture&amp;quot; title=&amp;quot;Gangi architecture&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;We present Gangi (architecture depicted above), a library that efficiently
protects the integrity-sensitive game state that exceeds the available enclave
memory. Gangi places the game state outside the enclave to reduce memory
consumption inside the enclave while ensuring the integrity of the game state
by hash-based validation. Our benchmarking results show that a Gangi-protected
game outperforms the EPC swapping approach with the entire game state being
inside the enclave.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;hybrid-tee&amp;quot;&amp;gt;Hybrid TEE&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;With cyber threats on the rise, the security of computer applications is
critical. One practical solution to secure applications is to employ a
Trusted Execution Environments (TEE): a secure area within the processor
that protects code and data against a strong attacker.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;A major issue faced by current architectures is the trade-off between
guaranteeing freshness (i.e., data is up-to-date) and proposing a large
secure memory. Without guaranteeing freshness, applications are vulnerable
to unauthorized access or computing wrong results. Unfortunately, existing
solutions either do not scale beyond a few hundred MB or weaken security.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/gangi/hybridtee.jpg&amp;quot; alt=&amp;quot;Hybrid TEE achitecture&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;We propose a hybrid approach that combines both types of TEEs. Key
challenges include: (i) application suitability; (ii) secure application
partitioning; (iii) robust multi-TEE attestation; and (iv) efficient
cross-TEE communication. We are currently addressing the above challenges
via three use cases: a Database, Machine Learning, and Web applications.
Implementation is under way on the Gem5 simulator with the RISC-V
open-source architecture.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;secure-i-o&amp;quot;&amp;gt;Secure I/O&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Protecting the integrity and confidentiality of user input (I/O) is a
fundamental challenge in computer security. Modern systems remain vulnerable
to a wide spectrum of attacks, ranging from physical hardware implants
(e.g., hardware keyloggers) to kernel-level malware. While Trusted Execution
Environments (TEEs) like Intel SGX have enabled isolated processing on the
host, existing secure I/O solutions often assume the trustworthiness of the
peripheral device and the integrity of the physical connection, failing to
protect against &amp;quot;Evil Maid&amp;quot; attacks or compromised peripheral firmware.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/gangi/secureio.png&amp;quot; alt=&amp;quot;Secure I/O achitecture&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In this project we propose a novel architecture that establishes a distributed
root of trust spanning both the I/O peripheral and the host (see figure above).
By leveraging ARM TrustZone on both the client (Cortex-A) and the input device
(Cortex-M), it becomes possible to create an authenticated, encrypted channel
using DTLS over Ethernet-over-USB. This design bypasses vulnerable legacy USB
stacks and operating system kernels. We propose a protocol for secure firmware
updates, multi-application isolation via secure port switching, and mutual
attestation verifiable via an out-of-band mobile application.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;An implementation on a Raspberry Pi 3 (leveraging the OP-TEE framework) and a
Raspberry Pi Pico 2W, as well as a real keyboard, is currently in progress.
Current results are promising (see below), we measured the communication
throughput and latency of TCP, UDP and DTLS on a pair of Raspberry Pi3
connected via an ethernet cable (100Mpbs of bandwidth). First, UDP throughput
(resp. latency) is higher (resp. lower) than TCP by 20% (resp. 17%), which
strengthens our choice to base our protocol on DTLS instead of TLS. Second,
DTLS overhead compared to UDP is less than 10%. Around 1400 scancodes can be
sent and received every second, which is higher than the speed of high-end
human interface peripherals, and higher than human reflexes.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/gangi/secureio_perf.png&amp;quot; alt=&amp;quot;Secure I/O performance&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;secure-camera&amp;quot;&amp;gt;Secure Camera&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;The era of fake news is upon us. Manipulated images are a particular potent
medium. Current state-of-the-art methods rely on image processing techniques,
which is unfortunately not sufficient to detect manipulations.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In this project we propose the Trusted Camera Framework, an alternative
approach that aims at creating secure images by leveraging Trusted Execution
Environments. It transparently embeds cryptographic signatures into the image
file to prove its authenticity and to correctly detail which post-processing
modifications have been applied.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Our implementation leverages the PNG file format. An evaluation on several
Raspberry Pi devices, with performance similar to recent smartphones,
demonstrates they can create such secure images without compromising their
image acquisition performance.&amp;lt;/p&amp;gt;
&amp;lt;h1 id=&amp;quot;outputs&amp;quot;&amp;gt;Outputs&amp;lt;/h1&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Terufumi Hata, Kenta Ishiguro, Pierre-Louis Aublin, Kenji Kono, Gangi:
Preventing Memory Tampering Cheats in Online Games, Journal of Information
Processing, 2025, 33 巻, p. 901-912, 公開日 2025/11/15, Online ISSN
1882-6652, &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://doi.org/10.2197/ipsjjip.33.901&amp;quot;&amp;gt;doi&amp;lt;/a&amp;gt;,
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.jstage.jst.go.jp/article/ipsjjip/33/0/33_901/_article/-char/ja&amp;quot;&amp;gt;paper&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;P.-L. Aublin, &amp;quot;What You See Is Not What You Get: Introducing the Trusted
Camera Framework to Combat Fake News,&amp;quot; 2025 IEEE Conference on Dependable,
Autonomic and Secure Computing (DASC), Hakodate, Japan, 2025, pp. 15-22, &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://doi.org/10.1109/DASC68382.2025.00010&amp;quot;&amp;gt;doi&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Bijun Li and Pierre-Louis Aublin. 2023. Transparent Management of BFT Systems
with TEE. In Proceedings of the 6th Workshop on System Software for Trusted
Execution (SysTEX &amp;#39;23). Association for Computing Machinery, New York, NY,
USA, 17–19. &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://doi.org/10.1145/3578359.3593041&amp;quot;&amp;gt;doi&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Aublin, Pierre-Louis, Mohammad Mahhouk, and Rüdiger Kapitza. &amp;quot;Towards TEEs
with large secure memory and integrity protection against HW attacks.&amp;quot;
SysTEX’22: 5th Workshop on System Software for Trusted Execution, February
28, 2022, Lausanne, Switzerland. 2022, &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://systex22.github.io/papers/systex22-final15.pdf&amp;quot;&amp;gt;paper&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h1 id=&amp;quot;grant-details&amp;quot;&amp;gt;Grant details&amp;lt;/h1&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Grant number: &amp;lt;a href=&amp;quot;https://kaken.nii.ac.jp/en/grant/KAKENHI-PROJECT-21K17726/&amp;quot;&amp;gt;21K17726&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Type: JSPS KAKENHI Grant-in-Aid for Early-Career Scientists&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Timeline: FY 2021-2025 (April 2021 to March 2025)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Budget: budget: ¥2.6M&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Hacking the Bebird R1 camera device</title>
                <link href="https://pierrelouis.pakupaku.me/blog/bebird-camera/"/>
                <updated>2026-04-29T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/bebird-camera/</id>
                <content type="html">&amp;lt;h2 id=&amp;quot;introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;I have a Bebird R1 &amp;quot;smart visual ear cleaner&amp;quot;. It&amp;#39;s a pen-like small device
with a small camera at the end that can be introduced in various cavities such
as the ears or nose to see details, and as advertised to clean them. Besides
its primary goal it is also fun to see details invisible to the naked eyes on
various surfaces: fabric (see the image below), screen pixels, etc.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/bebird-camera/bebirdr1.jpg&amp;quot; alt=&amp;quot;Bebird R1&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/bebird-camera/fabric.jpg&amp;quot; alt=&amp;quot;Bebird R1&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;It is ok to use, especially for its low price, but I have two complaints:&amp;lt;/p&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;it requires using the official application for iOS/Android;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;the camera claims to be HD, yet the stream I receive on the application is
not HD.&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;p&amp;gt;Below is a screenshot of the app interface on my tablet. You can see that it
uses a small portion of the screen (in both portrait or landscape modes).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/bebird-camera/app.jpg&amp;quot; alt=&amp;quot;App interface&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;So, let&amp;#39;s explore how it works and whether we can lift these restrictions!&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;getting-access-to-the-stream&amp;quot;&amp;gt;Getting access to the stream&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;The Bebird creates a Wifi access point when turned on (that could have been a
third complaint; I prefer cables).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Let&amp;#39;s connect the PC to it and scan for open ports:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; arp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -n&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;Address&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;                  HWtype  HWaddress           Flags Mask            Iface&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;192.168.5.1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;              ether   fc:58:4a:ea:ad:63   C                     wlan0&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; sudo nmap&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -sS -sU -p- -T4 192.168.5.1&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;Nmap&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; scan report for&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 192.168.5.1&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;Host&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; is up&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (0.0055s&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; latency&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;Not&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; shown:&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 65532&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; closed tcp ports&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (reset), 65530 closed udp ports (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;port-unreach&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;      STATE         SERVICE&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;58050/tcp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; open          unknown&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;58090/tcp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; open          unknown&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;58098/tcp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; open          unknown&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;53/udp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    open          domain&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;67/udp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    open&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;filtered&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; dhcps&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;58080/udp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; open&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;filtered&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; unknown&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;58090/udp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; open&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;filtered&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; unknown&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;58098/udp&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; open&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;filtered&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; unknown&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;MAC&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; Address: FC:58:4A:EA:AD:63&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (xiamenshi&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; c-chip technology&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;I tried to connect my browser to the various TCP port, which quickly led me to
discover a web interface at &amp;lt;code&amp;gt;http://192.168.5.1:58050&amp;lt;/code&amp;gt;. Hooray!&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/bebird-camera/webinterface.png&amp;quot; alt=&amp;quot;Web interface&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Looking at the webpage source, I&amp;#39;ve also found the address of the MPEG stream,
which I can then open in e.g., VLC: &amp;lt;code&amp;gt;http://192.168.5.1:58050/live&amp;lt;/code&amp;gt;. However,
this is only 480x480, not HD at all.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;hacking-the-application-protocol&amp;quot;&amp;gt;Hacking the application protocol&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;I can now access the camera from my computer, in fullscreen, but the stream
quality is not very good (only 480x480 pixels). Maybe if I analyse the messages
exchanged between the camera and the app I could find the HD stream address?&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;communication-protocol-analysis&amp;quot;&amp;gt;Communication Protocol Analysis&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;To record the network packets exchanged between the application on my tablet
and the bebird I use PCAPDroid (available on F-Droid). It can record a pcap
file that can then be copied to the computer for further analysis in Wireshark.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Here is a short version of the exchanged bytes:
&amp;lt;svg id=&amp;quot;mermaid-1777886773322-cft8x6ja8&amp;quot; width=&amp;quot;100%&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; style=&amp;quot;max-width: 784px;&amp;quot; viewBox=&amp;quot;-50 -10 784 1012&amp;quot; role=&amp;quot;graphics-document document&amp;quot; aria-roledescription=&amp;quot;sequence&amp;quot;&amp;gt;&amp;lt;rect x=&amp;quot;64&amp;quot; y=&amp;quot;832&amp;quot; fill=&amp;quot;rgba(200, 0, 0, 0.9)&amp;quot; width=&amp;quot;556&amp;quot; height=&amp;quot;74&amp;quot; class=&amp;quot;rect&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;lt;rect x=&amp;quot;64&amp;quot; y=&amp;quot;267&amp;quot; fill=&amp;quot;rgba(191, 223, 255, 0.7)&amp;quot; width=&amp;quot;556&amp;quot; height=&amp;quot;506&amp;quot; class=&amp;quot;rect&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;lt;rect x=&amp;quot;64&amp;quot; y=&amp;quot;75&amp;quot; fill=&amp;quot;rgba(221, 201, 47, 0.7)&amp;quot; width=&amp;quot;556&amp;quot; height=&amp;quot;182&amp;quot; class=&amp;quot;rect&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;lt;g&amp;gt;&amp;lt;rect x=&amp;quot;534&amp;quot; y=&amp;quot;926&amp;quot; fill=&amp;quot;#eaeaea&amp;quot; stroke=&amp;quot;#666&amp;quot; width=&amp;quot;150&amp;quot; height=&amp;quot;65&amp;quot; name=&amp;quot;Camera&amp;quot; rx=&amp;quot;3&amp;quot; ry=&amp;quot;3&amp;quot; class=&amp;quot;actor actor-bottom&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;lt;text x=&amp;quot;609&amp;quot; y=&amp;quot;958.5&amp;quot; style=&amp;quot;text-anchor: middle; font-size: 16px; font-weight: 400;&amp;quot; dominant-baseline=&amp;quot;central&amp;quot; alignment-baseline=&amp;quot;central&amp;quot; class=&amp;quot;actor actor-box&amp;quot;&amp;gt;&amp;lt;tspan x=&amp;quot;609&amp;quot; dy=&amp;quot;0&amp;quot;&amp;gt;Camera&amp;lt;/tspan&amp;gt;&amp;lt;/text&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;g&amp;gt;&amp;lt;rect x=&amp;quot;0&amp;quot; y=&amp;quot;926&amp;quot; fill=&amp;quot;#eaeaea&amp;quot; stroke=&amp;quot;#666&amp;quot; width=&amp;quot;150&amp;quot; height=&amp;quot;65&amp;quot; name=&amp;quot;App&amp;quot; rx=&amp;quot;3&amp;quot; ry=&amp;quot;3&amp;quot; class=&amp;quot;actor actor-bottom&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;lt;text x=&amp;quot;75&amp;quot; y=&amp;quot;958.5&amp;quot; style=&amp;quot;text-anchor: middle; font-size: 16px; font-weight: 400;&amp;quot; dominant-baseline=&amp;quot;central&amp;quot; alignment-baseline=&amp;quot;central&amp;quot; class=&amp;quot;actor actor-box&amp;quot;&amp;gt;&amp;lt;tspan x=&amp;quot;75&amp;quot; dy=&amp;quot;0&amp;quot;&amp;gt;App&amp;lt;/tspan&amp;gt;&amp;lt;/text&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;g&amp;gt;&amp;lt;line id=&amp;quot;actor181&amp;quot; x1=&amp;quot;609&amp;quot; y1=&amp;quot;65&amp;quot; x2=&amp;quot;609&amp;quot; y2=&amp;quot;926&amp;quot; class=&amp;quot;actor-line 200&amp;quot; stroke-width=&amp;quot;0.5px&amp;quot; stroke=&amp;quot;#999&amp;quot; name=&amp;quot;Camera&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;g id=&amp;quot;root-181&amp;quot;&amp;gt;&amp;lt;rect x=&amp;quot;534&amp;quot; y=&amp;quot;0&amp;quot; fill=&amp;quot;#eaeaea&amp;quot; stroke=&amp;quot;#666&amp;quot; width=&amp;quot;150&amp;quot; height=&amp;quot;65&amp;quot; name=&amp;quot;Camera&amp;quot; rx=&amp;quot;3&amp;quot; ry=&amp;quot;3&amp;quot; class=&amp;quot;actor actor-top&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;lt;text x=&amp;quot;609&amp;quot; y=&amp;quot;32.5&amp;quot; style=&amp;quot;text-anchor: middle; font-size: 16px; font-weight: 400;&amp;quot; dominant-baseline=&amp;quot;central&amp;quot; alignment-baseline=&amp;quot;central&amp;quot; class=&amp;quot;actor actor-box&amp;quot;&amp;gt;&amp;lt;tspan x=&amp;quot;609&amp;quot; dy=&amp;quot;0&amp;quot;&amp;gt;Camera&amp;lt;/tspan&amp;gt;&amp;lt;/text&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;g&amp;gt;&amp;lt;line id=&amp;quot;actor180&amp;quot; x1=&amp;quot;75&amp;quot; y1=&amp;quot;65&amp;quot; x2=&amp;quot;75&amp;quot; y2=&amp;quot;926&amp;quot; class=&amp;quot;actor-line 200&amp;quot; stroke-width=&amp;quot;0.5px&amp;quot; stroke=&amp;quot;#999&amp;quot; name=&amp;quot;App&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;g id=&amp;quot;root-180&amp;quot;&amp;gt;&amp;lt;rect x=&amp;quot;0&amp;quot; y=&amp;quot;0&amp;quot; fill=&amp;quot;#eaeaea&amp;quot; stroke=&amp;quot;#666&amp;quot; width=&amp;quot;150&amp;quot; height=&amp;quot;65&amp;quot; name=&amp;quot;App&amp;quot; rx=&amp;quot;3&amp;quot; ry=&amp;quot;3&amp;quot; class=&amp;quot;actor actor-top&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;lt;text x=&amp;quot;75&amp;quot; y=&amp;quot;32.5&amp;quot; style=&amp;quot;text-anchor: middle; font-size: 16px; font-weight: 400;&amp;quot; dominant-baseline=&amp;quot;central&amp;quot; alignment-baseline=&amp;quot;central&amp;quot; class=&amp;quot;actor actor-box&amp;quot;&amp;gt;&amp;lt;tspan x=&amp;quot;75&amp;quot; dy=&amp;quot;0&amp;quot;&amp;gt;App&amp;lt;/tspan&amp;gt;&amp;lt;/text&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;style&amp;gt;#mermaid-1777886773322-cft8x6ja8{font-family:&amp;quot;trebuchet ms&amp;quot;,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-1777886773322-cft8x6ja8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-1777886773322-cft8x6ja8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-1777886773322-cft8x6ja8 .error-icon{fill:#552222;}#mermaid-1777886773322-cft8x6ja8 .error-text{fill:#552222;stroke:#552222;}#mermaid-1777886773322-cft8x6ja8 .edge-thickness-normal{stroke-width:1px;}#mermaid-1777886773322-cft8x6ja8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1777886773322-cft8x6ja8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1777886773322-cft8x6ja8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-1777886773322-cft8x6ja8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1777886773322-cft8x6ja8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1777886773322-cft8x6ja8 .marker{fill:#333333;stroke:#333333;}#mermaid-1777886773322-cft8x6ja8 .marker.cross{stroke:#333333;}#mermaid-1777886773322-cft8x6ja8 svg{font-family:&amp;quot;trebuchet ms&amp;quot;,verdana,arial,sans-serif;font-size:16px;}#mermaid-1777886773322-cft8x6ja8 p{margin:0;}#mermaid-1777886773322-cft8x6ja8 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-1777886773322-cft8x6ja8 text.actor&amp;amp;gt;tspan{fill:black;stroke:none;}#mermaid-1777886773322-cft8x6ja8 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-1777886773322-cft8x6ja8 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-1777886773322-cft8x6ja8 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-1777886773322-cft8x6ja8 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-1777886773322-cft8x6ja8 #arrowhead path{fill:#333;stroke:#333;}#mermaid-1777886773322-cft8x6ja8 .sequenceNumber{fill:white;}#mermaid-1777886773322-cft8x6ja8 #sequencenumber{fill:#333;}#mermaid-1777886773322-cft8x6ja8 #crosshead path{fill:#333;stroke:#333;}#mermaid-1777886773322-cft8x6ja8 .messageText{fill:#333;stroke:none;}#mermaid-1777886773322-cft8x6ja8 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-1777886773322-cft8x6ja8 .labelText,#mermaid-1777886773322-cft8x6ja8 .labelText&amp;amp;gt;tspan{fill:black;stroke:none;}#mermaid-1777886773322-cft8x6ja8 .loopText,#mermaid-1777886773322-cft8x6ja8 .loopText&amp;amp;gt;tspan{fill:black;stroke:none;}#mermaid-1777886773322-cft8x6ja8 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-1777886773322-cft8x6ja8 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-1777886773322-cft8x6ja8 .noteText,#mermaid-1777886773322-cft8x6ja8 .noteText&amp;amp;gt;tspan{fill:black;stroke:none;}#mermaid-1777886773322-cft8x6ja8 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-1777886773322-cft8x6ja8 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-1777886773322-cft8x6ja8 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-1777886773322-cft8x6ja8 .actorPopupMenu{position:absolute;}#mermaid-1777886773322-cft8x6ja8 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-1777886773322-cft8x6ja8 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-1777886773322-cft8x6ja8 .actor-man circle,#mermaid-1777886773322-cft8x6ja8 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-1777886773322-cft8x6ja8 :root{--mermaid-font-family:&amp;quot;trebuchet ms&amp;quot;,verdana,arial,sans-serif;}&amp;lt;/style&amp;gt;&amp;lt;g&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;defs&amp;gt;&amp;lt;symbol id=&amp;quot;computer&amp;quot; width=&amp;quot;24&amp;quot; height=&amp;quot;24&amp;quot;&amp;gt;&amp;lt;path transform=&amp;quot;scale(.5)&amp;quot; d=&amp;quot;M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/symbol&amp;gt;&amp;lt;/defs&amp;gt;&amp;lt;defs&amp;gt;&amp;lt;symbol id=&amp;quot;database&amp;quot; fill-rule=&amp;quot;evenodd&amp;quot; clip-rule=&amp;quot;evenodd&amp;quot;&amp;gt;&amp;lt;path transform=&amp;quot;scale(.5)&amp;quot; d=&amp;quot;M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/symbol&amp;gt;&amp;lt;/defs&amp;gt;&amp;lt;defs&amp;gt;&amp;lt;symbol id=&amp;quot;clock&amp;quot; width=&amp;quot;24&amp;quot; height=&amp;quot;24&amp;quot;&amp;gt;&amp;lt;path transform=&amp;quot;scale(.5)&amp;quot; d=&amp;quot;M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/symbol&amp;gt;&amp;lt;/defs&amp;gt;&amp;lt;defs&amp;gt;&amp;lt;marker id=&amp;quot;arrowhead&amp;quot; refX=&amp;quot;7.9&amp;quot; refY=&amp;quot;5&amp;quot; markerUnits=&amp;quot;userSpaceOnUse&amp;quot; markerWidth=&amp;quot;12&amp;quot; markerHeight=&amp;quot;12&amp;quot; orient=&amp;quot;auto-start-reverse&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M -1 0 L 10 5 L 0 10 z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/marker&amp;gt;&amp;lt;/defs&amp;gt;&amp;lt;defs&amp;gt;&amp;lt;marker id=&amp;quot;crosshead&amp;quot; markerWidth=&amp;quot;15&amp;quot; markerHeight=&amp;quot;8&amp;quot; orient=&amp;quot;auto&amp;quot; refX=&amp;quot;4&amp;quot; refY=&amp;quot;4.5&amp;quot;&amp;gt;&amp;lt;path fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#000000&amp;quot; style=&amp;quot;stroke-dasharray: 0px, 0px;&amp;quot; stroke-width=&amp;quot;1pt&amp;quot; d=&amp;quot;M 1,2 L 6,7 M 6,2 L 1,7&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/marker&amp;gt;&amp;lt;/defs&amp;gt;&amp;lt;defs&amp;gt;&amp;lt;marker id=&amp;quot;filled-head&amp;quot; refX=&amp;quot;15.5&amp;quot; refY=&amp;quot;7&amp;quot; markerWidth=&amp;quot;20&amp;quot; markerHeight=&amp;quot;28&amp;quot; orient=&amp;quot;auto&amp;quot;&amp;gt;&amp;lt;path d=&amp;quot;M 18,7 L9,13 L14,7 L9,1 Z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;lt;/marker&amp;gt;&amp;lt;/defs&amp;gt;&amp;lt;defs&amp;gt;&amp;lt;marker id=&amp;quot;sequencenumber&amp;quot; refX=&amp;quot;15&amp;quot; refY=&amp;quot;15&amp;quot; markerWidth=&amp;quot;60&amp;quot; markerHeight=&amp;quot;40&amp;quot; orient=&amp;quot;auto&amp;quot;&amp;gt;&amp;lt;circle cx=&amp;quot;15&amp;quot; cy=&amp;quot;15&amp;quot; r=&amp;quot;6&amp;quot;&amp;gt;&amp;lt;/circle&amp;gt;&amp;lt;/marker&amp;gt;&amp;lt;/defs&amp;gt;&amp;lt;g&amp;gt;&amp;lt;rect x=&amp;quot;50&amp;quot; y=&amp;quot;783&amp;quot; fill=&amp;quot;#EDF2AE&amp;quot; stroke=&amp;quot;#666&amp;quot; width=&amp;quot;584&amp;quot; height=&amp;quot;39&amp;quot; class=&amp;quot;note&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;lt;text x=&amp;quot;342&amp;quot; y=&amp;quot;788&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;noteText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;&amp;lt;tspan x=&amp;quot;342&amp;quot;&amp;gt;The above block repeats until the stream is disconnected&amp;lt;/tspan&amp;gt;&amp;lt;/text&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;text x=&amp;quot;341&amp;quot; y=&amp;quot;100&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;66 3a (UDP port 58090)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;76&amp;quot; y1=&amp;quot;139&amp;quot; x2=&amp;quot;605&amp;quot; y2=&amp;quot;139&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;154&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 02 00 64&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;193&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;193&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;341&amp;quot; y=&amp;quot;208&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;20 36 (UDP port 58080)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;76&amp;quot; y1=&amp;quot;247&amp;quot; x2=&amp;quot;605&amp;quot; y2=&amp;quot;247&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;292&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 00 01 08 ff d8 ff e0 00 10 4a 46 49 46 00 01... (1468 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;331&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;331&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;346&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 00 02 08 a3 14 00 b8 a3 14 84 26 29 d8 a0 03... (1468 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;385&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;385&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;400&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 00 03 08 00 51 40 05 14 80 28 a6 21 40 a5 a4... (1468 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;439&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;439&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;454&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 00 04 08 98 0a 6a 16 34 00 94 53 10 a3 93 4f... (1468 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;493&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;493&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;508&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 00 05 08 f2 a0 63 0d a4 27 a2 91 f4 26 9a d6... (1468 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;547&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;547&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;562&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 00 06 08 26 59 b4 19 95 9b b0 5f e7 57 2a 84... (1468 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;601&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;601&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;616&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 00 07 08 00 14 50 06 6f 51 8f 4a 63 1c 1c 0f... (1468 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;655&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;655&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;344&amp;quot; y=&amp;quot;670&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;00 02 08 02 83 4c 44 aa 2a 40 28 01 71 52 44 bb... (288 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;608&amp;quot; y1=&amp;quot;709&amp;quot; x2=&amp;quot;79&amp;quot; y2=&amp;quot;709&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;341&amp;quot; y=&amp;quot;724&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;99 99 17 10 74 07 00 00 00 00 00 00 00 00 00 00... (24 bytes)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;76&amp;quot; y1=&amp;quot;763&amp;quot; x2=&amp;quot;605&amp;quot; y2=&amp;quot;763&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;text x=&amp;quot;341&amp;quot; y=&amp;quot;857&amp;quot; text-anchor=&amp;quot;middle&amp;quot; dominant-baseline=&amp;quot;middle&amp;quot; alignment-baseline=&amp;quot;middle&amp;quot; style=&amp;quot;font-size: 16px; font-weight: 400;&amp;quot; class=&amp;quot;messageText&amp;quot; dy=&amp;quot;1em&amp;quot;&amp;gt;86 06 00 (UDP port 58098)&amp;lt;/text&amp;gt;&amp;lt;line x1=&amp;quot;76&amp;quot; y1=&amp;quot;896&amp;quot; x2=&amp;quot;605&amp;quot; y2=&amp;quot;896&amp;quot; class=&amp;quot;messageLine0&amp;quot; stroke-width=&amp;quot;2&amp;quot; stroke=&amp;quot;none&amp;quot; style=&amp;quot;fill: none;&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;&amp;gt;&amp;lt;/line&amp;gt;&amp;lt;/svg&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;!--
mermaid code:
sequenceDiagram
   rect rgba(221, 201, 47, 0.2)
   App-&amp;gt;&amp;gt;Camera: 66 3a (UDP port 58090)
   Camera-&amp;gt;&amp;gt;App: 00 02 00 64
   App-&amp;gt;&amp;gt;Camera: 20 36 (UDP port 58080)
   end

   rect rgba(191, 223, 255, 0.2)
   Camera-&amp;gt;&amp;gt;App: 00 00 01 08 ff d8 ff e0 00 10 4a 46 49 46 00 01... (1468 bytes)
   Camera-&amp;gt;&amp;gt;App: 00 00 02 08 a3 14 00 b8 a3 14 84 26 29 d8 a0 03... (1468 bytes)
   Camera-&amp;gt;&amp;gt;App: 00 00 03 08 00 51 40 05 14 80 28 a6 21 40 a5 a4... (1468 bytes)
   Camera-&amp;gt;&amp;gt;App: 00 00 04 08 98 0a 6a 16 34 00 94 53 10 a3 93 4f... (1468 bytes)
   Camera-&amp;gt;&amp;gt;App: 00 00 05 08 f2 a0 63 0d a4 27 a2 91 f4 26 9a d6... (1468 bytes)
   Camera-&amp;gt;&amp;gt;App: 00 00 06 08 26 59 b4 19 95 9b b0 5f e7 57 2a 84... (1468 bytes)
   Camera-&amp;gt;&amp;gt;App: 00 00 07 08 00 14 50 06 6f 51 8f 4a 63 1c 1c 0f... (1468 bytes)
   Camera-&amp;gt;&amp;gt;App: 00 02 08 02 83 4c 44 aa 2a 40 28 01 71 52 44 bb... (288 bytes)
   App-&amp;gt;&amp;gt;Camera: 99 99 17 10 74 07 00 00 00 00 00 00 00 00 00 00... (24 bytes)
   end

   Note over Camera,App: The above block repeats until the stream is disconnected

   rect rgba(200, 0, 0, 0.9)
   App-&amp;gt;&amp;gt;Camera: 86 06 00 (UDP port 58098)
   end
--&amp;gt;
&amp;lt;p&amp;gt;The first block of messages seems to be some control data. I believe the first
pair of messages is the app asking the camera its status (name, battery
charge): the app shows &amp;quot;Bebird R1&amp;quot; as well as the battery charge on the first
screen. Then, the third message might be asking the camera to start the video
stream.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The second block of message is a single video frame. Due to UDP maximum packet
length of 1500 bytes it needs to be split into several packets, but when
recollecting them we obtain a single JPG image of size 11kB and 480x480 pixels.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/bebird-camera/packet.jpg&amp;quot; alt=&amp;quot;Single frame&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;How to know it is JPG? The first packet contains &amp;lt;code&amp;gt;ff d8 ff&amp;lt;/code&amp;gt;, which signifies
the start of a JPG image, and then &amp;lt;code&amp;gt;4a 46 49 46&amp;lt;/code&amp;gt;, which reads as &amp;lt;code&amp;gt;JFIF&amp;lt;/code&amp;gt;, stands
for &amp;lt;em&amp;gt;JPEG File Interchange Format&amp;lt;/em&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In the second block, the last message sent by the app is probably an
acknowledgement. In my tests I did not need to send it.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Finally, once the application disconnects, it sends &amp;lt;code&amp;gt;86 06 00&amp;lt;/code&amp;gt; to the camera.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;simulating-the-application&amp;quot;&amp;gt;Simulating the application&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;Now that we understand a bit more the communication protocol between the
application and the camera we can try to re-create it and see if we can unlock
an HD stream.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Here is the Python script I used:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;python&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;import&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; io&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;import&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; socket&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;import&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; sys&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;import&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; threading&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;import&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; time&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;from&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt; PIL&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt; import&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; Image&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# Configuration&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;CAMERA_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; &amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;192.168.5.1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;LOCAL_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; &amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;192.168.5.100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;PACKET_1_LOCAL_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 38516&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;PACKET_1_REMOTE_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 58090&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;PACKET_2_LOCAL_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 54717&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;PACKET_2_REMOTE_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 58080&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;def&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; get_video_feed&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;():&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;    &amp;amp;quot;&amp;amp;quot;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;Sends the &amp;amp;#39;66 3a&amp;amp;#39; command&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;amp;quot;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    sock1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;AF_INET&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt; socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;SOCK_DGRAM&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    sock1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;bind&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;((&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;LOCAL_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt; PACKET_1_LOCAL_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;))&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    cmd&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt; bytes&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;fromhex&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;66 36&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;    print&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;f&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;&amp;amp;quot;Sending 1st command to &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;CAMERA_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;PACKET_1_REMOTE_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;...&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    sock1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;sendto&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;cmd&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;, (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;CAMERA_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt; PACKET_1_REMOTE_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;))&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;    &amp;amp;quot;&amp;amp;quot;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;Sends the &amp;amp;#39;20 36&amp;amp;#39; command&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;amp;quot;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    sock2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;AF_INET&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt; socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;SOCK_DGRAM&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    sock2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;bind&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;((&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;LOCAL_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt; PACKET_2_LOCAL_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;))&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    sock2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;settimeout&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;1.0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    cmd&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt; bytes&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;fromhex&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;20 36&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;    print&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;f&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;&amp;amp;quot;Sending 2nd command to &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;CAMERA_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;PACKET_2_REMOTE_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;...&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    sock2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;sendto&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;cmd&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;, (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;CAMERA_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt; PACKET_2_REMOTE_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;))&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;    &amp;amp;quot;&amp;amp;quot;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;Listens for UDP packets and extract JPEG frames&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;amp;quot;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;    print&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;        f&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;&amp;amp;quot;Listens for UDP packets from &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;CAMERA_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;PACKET_2_REMOTE_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; to &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;LOCAL_IP&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;font-weight: bold;&amp;quot;&amp;gt;PACKET_2_LOCAL_PORT&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;...&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;    )&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;    # Buffer to store incoming UDP data&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;    udp_buffer&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt; bytearray&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;()&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;    while&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; True&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;        try&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;            data&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; _addr&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; sock2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;recvfrom&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;65536&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;        except&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; socket&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;timeout&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;            break&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;        udp_buffer&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;extend&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;data&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;        # print(&amp;amp;quot;Received packet of length {}&amp;amp;quot;, len(data))&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;        # Look for Start of Image (FFD8) and End of Image (FFD9)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;        start_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; udp_buffer&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;find&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;b&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;\xff\xd8&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;        end_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; udp_buffer&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;find&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;b&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;\xff\xd9&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt; start_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;        if&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; start_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; != -&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt; and&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; end_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; != -&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt; and&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; end_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; &amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; start_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;            # Extract the complete JPEG frame&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;            # We slice from the start of the FOUND frame to the end&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;            frame_data&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt; bytes&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;udp_buffer&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;start_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; :&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt; end_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;])&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;            # Clear buffer up to this point to prevent memory growth&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;            # But keep any partial data after the end just in case&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;            udp_buffer&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt; bytearray&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;udp_buffer&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;end_index&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; :])&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;            try&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;                img&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; Image&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;open&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;io&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;BytesIO&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;frame_data&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;))&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;                print&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;                    f&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;&amp;amp;quot;Received Image: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;img&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;width&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;x&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;img&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;height&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; (Size: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;len&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;frame_data&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; bytes)&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;                )&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;            except&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt; Exception&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt; as&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; e&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;                print&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;f&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;&amp;amp;quot;Corrupt frame data: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D5C4A1;&amp;quot;&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;if&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; __name__&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ==&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; &amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;__main__&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;:&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;    get_video_feed&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;()&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;With this script I could confirm the received image size and change the control
bytes sent at the beginning to see if there is a way to get an HD stream.
Unfortunately, it didn&amp;#39;t work.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;taking-screenshots&amp;quot;&amp;gt;Taking Screenshots&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;The app and webpage provide a button to take a screenshot.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The webpage contains the following Javascript function, which simply takes a
screenshot of the displayed canvas, so 480x480 pixels.&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;javascript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt; Ee&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;() {&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;  var&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; z&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;  // 1. Get the hidden &amp;amp;lt;a&amp;amp;gt; tag with id=&amp;amp;quot;save&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;  const&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; N&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; document&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;save&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;        E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; document&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;createElement&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;canvas&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;        S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; document&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;querySelector&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;.ears-view&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt; // Selects the &amp;amp;lt;img&amp;amp;gt; tag showing the stream&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;  // 2. Match canvas size to the video stream size&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;  E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;width&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ==&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; null&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ? void&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; :&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;width&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;  E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;height&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ==&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; null&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ? void&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; :&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;height&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;  document&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;body&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;appendChild&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;E&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;  // 3. Draw the current frame from the &amp;amp;lt;img&amp;amp;gt; onto the canvas&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;  const&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; j&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;getContext&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;2d&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;  j&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ==&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; null&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt; ||&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; j&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;drawImage&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ==&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; null&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ? void&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; :&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;naturalWidth&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ==&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; null&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ? void&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; :&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; S&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;naturalHeight&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;width&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;height&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt;  try&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; {&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;    // 4. Convert canvas to a Data URL (Base64 JPEG)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;    const&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; $&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;toDataURL&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;()&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;    N&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;href&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; $&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;    // 5. Generate a timestamped filename and trigger download&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;    const&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; re&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt; new&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; Date&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;    N&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;download&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; re&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;getFullYear&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;()&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;re&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;getMonth&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;()&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 1&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;))&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;slice&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;2&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; re&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;getDate&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;())&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;slice&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;2&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; re&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;getHours&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;())&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;slice&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;2&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; re&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;getMinutes&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;())&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;slice&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;2&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; re&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;getSeconds&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;())&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;slice&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;2&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; +&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; &amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;.png&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;  }&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt; catch&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; {&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;    console&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;$&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;  }&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;  // 6. Cleanup: Remove the temporary canvas&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;  (&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;z&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; =&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ==&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; null&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ? void&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; 0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; :&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; E&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;parentNode&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; ==&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; null&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FB4934;&amp;quot;&amp;gt; ||&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt; z&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;removeChild&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #83A598;&amp;quot;&amp;gt;E&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;When taking a screenshot from the app, it sends a special command  to the
camera which then returns a JPG file. What happens is probably that the camera
stops the stream, takes a full-resolution image from its sensor, and then sends
it back to the app. But then something weird happens: the image saved by the
app is 1.36MB, with a resolution of 2828x3258 pixels (8.9 megapixels). It looks
like the app is doing interpolation, upscaling the image (because why not I
guess).&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;findings-summary&amp;quot;&amp;gt;Findings Summary&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;This fun adventure hacking the Bebird camera is at least half a success: from
now on I can use it without the proprietary smartphone/tablet application.
However, there is no such thing as a HD stream.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;I could fake an HD stream by repeatedly taking screenshots in my python script,
but the result would be a very laggy video stream.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In retrospect, the &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://bebird.com/products/earsight-r1-earwax-removal-tool&amp;quot;&amp;gt;official product
description&amp;lt;/a&amp;gt; feels
more like marketing information than real technical details that make sense:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;1080P HD Vision with 6 LED Lights&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;3-megapixel high-precision lens&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Maximum framerate of 30fps&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Image transmission of 20fps&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;20 or 30fps? 1080P is around 2MP, not 3. The reviews are also all great, but
with definitely not HD images.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;One final thing I checked is information about the network device (xiamenshi
c-chip technology) found in the &amp;lt;code&amp;gt;nmap&amp;lt;/code&amp;gt; output. According to &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://manuals.plus/m/fd734e69f3e7d9af4d5d65780279fcbe15b052acba33338328a2e9ce700c4826_optim&amp;quot;&amp;gt;the
manual&amp;lt;/a&amp;gt;,
it supports Wifi 802.11 b/g/n with a maximum transmission rate of 72.2 Mbps, so
should be enough for full HD which requires less than 10Mbps.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;What I think happens is that while the Wifi chip and camera sensors might be
able to do full HD, the embedded CPU in the camera is probably not powerful
enough. So, to ensure a smooth and stable stream and avoid overheating (the
device already gets warm when being used), the software does not allow more
than 480p streaming.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Further investigating this claim would necessitate opening the device, which I
do not really want to do as I am using it.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;acknowledgements&amp;quot;&amp;gt;Acknowledgements&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;I have used the &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://euria.infomaniak.com/&amp;quot;&amp;gt;Euria&amp;lt;/a&amp;gt; LLM to guide me through
the hack. Euria is provided by
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.infomaniak.com/en&amp;quot;&amp;gt;Infomaniak&amp;lt;/a&amp;gt;, a Swiss-based company that focuses
on privacy, security, and sustainable solutions.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Nonetheless this article has been written by myself without LLM assistance.&amp;lt;/p&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Software Setup — 2026 Edition</title>
                <link href="https://pierrelouis.pakupaku.me/blog/software-setup/"/>
                <updated>2026-03-04T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/software-setup/</id>
                <content type="html">&amp;lt;p&amp;gt;Stopping a Mouse Infestation: A Keyboard-Only Haven&amp;lt;/p&amp;gt;
&amp;lt;span id=&amp;quot;continue-reading&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;h1 id=&amp;quot;introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;For some years I have been trying to reduce my usage of the mouse. My precision
is not very good and using it for extended periods leads to discomfort (moving
the hand off the keyboard, clicking, moving the cursor across the screen).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Last year I have also done some research and experiments with custom
(mechanical, split, ortholinear) keyboards and layouts. Many designs consider
the mouse as a second-class citizen, minimizing the need to divert attention
from typing. As a side note, &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.justinmklam.com/posts/2026/02/beginners-guide-split-keyboards/&amp;quot;&amp;gt;this
article&amp;lt;/a&amp;gt;
about split keyboards is a good read.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;I have made some small experiments in the past (e.g., with &amp;lt;code&amp;gt;vimperator&amp;lt;/code&amp;gt;, or
using a tiling window manager), yet never really dedicated time to get rid of
the mouse. Nevertheless, one thing that has been true forever is I largely
prefer a command-line application over a GUI.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;This post is a response to the problem. Besides listing softwares that can be
controlled mostly with the keyboard, it also aims at being a tutorial/basic
reference for a daily use.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;It is broken down into multiple parts:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;https://pierrelouis.pakupaku.me/blog/software-setup/#part-0-the-foundation&amp;quot;&amp;gt;Part 0: The Foundation&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h1 id=&amp;quot;a-small-note-on-hardware&amp;quot;&amp;gt;A Small Note on Hardware&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;Summarizing which hardware I use can help to understand some choices.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;I use laptops, mainly (old) Thinkpads from 2015 to 2021, ranging from 12&amp;quot; to
14&amp;quot;, with at least 8GB of RAM and 2-cores (4 threads). They all run GNU/Linux
(Arch, Debian, Fedora) or FreeBSD. They work very well for my usages despite
their age, and given the current state-of-the-world (price hikes, climate
change), I believe it is better to &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://xn--gckvb8fzb.com/hold-on-to-your-hardware/&amp;quot;&amp;gt;hold on them as long as
possible&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;When using an external screen, it is either a 16:9 1440p or an ultra-wide
3440x1440.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;I also have a bunch of custom keyboards, 34-keys split Chocofi, 58-keys split
Lily58, 48-keys ortholinear Planck, and a Keychron K3 Pro.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;This has several implications for the software side:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;need to unify the configuration;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;need to minimize memory usage;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;need to minimize mouse movements on the ultra-wide screen.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h1 id=&amp;quot;part-0-the-foundation&amp;quot;&amp;gt;Part 0: The Foundation&amp;lt;/h1&amp;gt;
&amp;lt;h2 id=&amp;quot;window-manager-i3-sway&amp;quot;&amp;gt;Window Manager: i3/Sway&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;My window manager of choice is &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://i3wm.org/&amp;quot;&amp;gt;i3&amp;lt;/a&amp;gt; (on X) or
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://swaywm.org/&amp;quot;&amp;gt;Sway&amp;lt;/a&amp;gt; (on Wayland). Sway is designed to be compatible
with i3, meaning I can switch from one to the other with minimal configuration
changes.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;I tend to have one or two applications at most per workspace, having windows
side-by-side, and dedicating a workspace to a particular task.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;terminal-emulator-ghostty&amp;quot;&amp;gt;Terminal Emulator: Ghostty&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;I recently moved from &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://alacritty.org/&amp;quot;&amp;gt;Alacritty&amp;lt;/a&amp;gt; to
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://ghostty.org/&amp;quot;&amp;gt;Ghostty&amp;lt;/a&amp;gt;, mainly for the possibility to split the window
(useful when starting a new terminal would mess up with my current window
layout) and for being able to display images in the terminal.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://ricoberger.de/cheat-sheets/ghostty/&amp;quot;&amp;gt;Cheat sheets&amp;lt;/a&amp;gt; are a precious tool to learn how to use it.
&amp;lt;a href=&amp;quot;https://pierrelouis.pakupaku.me/blog/software-setup/ghostty-cheat-sheet.png&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/software-setup/ghostty-cheat-sheet.png&amp;quot; alt=&amp;quot;Ghostty cheat sheet&amp;quot; /&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;I&amp;#39;ve added the following to the configuration (&amp;lt;code&amp;gt;~/.config/ghostty/config&amp;lt;/code&amp;gt;) so
that new windows open in the home directory instead of the directory of the
previously opened window.&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;gtk-single-instance = false&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;working-directory = home&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;window-inherit-working-directory = true&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;One important feature for a mouse-less environment is to be able to select
text in the terminal window via the keyboard only. There is no easy way to do
this in Ghostty. The simplest solution I&amp;#39;ve found is to follow this procedure:&amp;lt;/p&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;Type the name of your text editor of choice (nvim, vi, vim...)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Press &amp;lt;code&amp;gt;super+ctrl+shift+j&amp;lt;/code&amp;gt; to save the screen content to a file and copy the
file path to the clipboard&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Press &amp;lt;code&amp;gt;ctrl+shift+v&amp;lt;/code&amp;gt; to paste the screen file path to the terminal&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Type &amp;lt;code&amp;gt;enter&amp;lt;/code&amp;gt;. You are now in your editor, where you can do whatever you
want, e.g., copy text&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Exit your editor and paste the text into the command line&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;p&amp;gt;This makes a great transition to discuss about my text editor.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;text-editor-neovim&amp;quot;&amp;gt;Text editor: Neovim&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;I install &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://neovim.io/&amp;quot;&amp;gt;neovim&amp;lt;/a&amp;gt; everywhere I need a text editor, and I
use it for every kind of text, be it a todo list, code, etc. The rationale
includes: similarities with vi (installed almost anywhere), does not need a
GUI, no superfluous functionalities, no crazy shortcuts to run some commands
(thinking of Emacs here). In short, it does the job.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The main plugins I have installed are:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/nvim-telescope/telescope.nvim&amp;quot;&amp;gt;telescope&amp;lt;/a&amp;gt;, used to search
for a string in many files; useful for browsing through code. The main
shortcuts are (I should look at the documentation and add useful ones):
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;&amp;amp;lt;leader&amp;amp;gt;ff&amp;lt;/code&amp;gt;: find files&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;&amp;amp;lt;leader&amp;amp;gt;fg&amp;lt;/code&amp;gt;: search for a string across the current working directory&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;&amp;amp;lt;leader&amp;amp;gt;fb&amp;lt;/code&amp;gt;: list opened buffers&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/jannis-baum/vivify&amp;quot;&amp;gt;vivify&amp;lt;/a&amp;gt; to preview markdown files while editing&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;LSP for Rust, C, markdown, LaTeX, Python&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;And my &amp;lt;code&amp;gt;&amp;amp;lt;leader&amp;amp;gt;&amp;lt;/code&amp;gt; key is &amp;lt;code&amp;gt;space&amp;lt;/code&amp;gt;, because why not, it&amp;#39;s easily accessible.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;file-explorer-yazi&amp;quot;&amp;gt;File Explorer: Yazi&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;While I mostly use the standard UNIX tools to manage files (&amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cp&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt;,
and so on), if I need a file-explorer then it is the TUI-based
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://yazi-rs.github.io/&amp;quot;&amp;gt;Yazi&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;One use-case for Yazi over the terminal is when searching for some image or
document: the built-in preview makes it simpler than opening files until I find
the right one.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Yazi supports plugins. An interesting one is &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/yazi-rs/plugins/tree/main/mount.yazi&amp;quot;&amp;gt;a mount
manager&amp;lt;/a&amp;gt; (does not
seem to support *BSD at the time of writing).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://ricoberger.de/cheat-sheets/yazi/&amp;quot;&amp;gt;Here&amp;lt;/a&amp;gt; is Yazi cheat sheet:
&amp;lt;a href=&amp;quot;https://pierrelouis.pakupaku.me/blog/software-setup/yazi-cheat-sheet.png&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/software-setup/yazi-cheat-sheet.png&amp;quot; alt=&amp;quot;Yazi cheat sheet&amp;quot; /&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;wifi-and-bluetooth-managers&amp;quot;&amp;gt;Wifi and Bluetooth Managers&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/pythops/bluetui&amp;quot;&amp;gt;bluetui&amp;lt;/a&amp;gt; and
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/pythops/impala&amp;quot;&amp;gt;impala&amp;lt;/a&amp;gt; are both TUI manager for
respectively Bluetooth and Wifi. Unfortunately they do not run on FreeBSD,
where I need to do everything by hand.&amp;lt;/p&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Unlock Debian encrypted root partition with a keyfile</title>
                <link href="https://pierrelouis.pakupaku.me/blog/debian-root-cryptsetup-keyfile/"/>
                <updated>2025-09-05T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/debian-root-cryptsetup-keyfile/</id>
                <content type="html">&amp;lt;h2 id=&amp;quot;introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;A common method for securing the root partition of a system is through
encryption using a passphrase. While effective, this approach requires manual
input every time the machine starts, which poses a challenge for headless
machines that lack a keyboard or screen.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;To address this, we can store the keyfile on a USB key, allowing the system to
automatically access the encryption key during boot. Alternatively, the keyfile
can be stored on the network, providing a convenient solution for multiple
machines, but we will see that one day, maybe.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;(Edit 2026-01-26: &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://jyn.dev/remotely-unlocking-an-encrypted-hard-disk/&amp;quot;&amp;gt;Modifying the
&amp;lt;code&amp;gt;initramfs&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt; seems
to be a good starting point.)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In this blog post we will install Debian 13 using debootstrap without setting up
a passphrase. Although we could run the installer, which supports LUKS
encryption with a passphrase, and add the keyfile later, where would be the
fun?&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;debian-installation&amp;quot;&amp;gt;Debian Installation&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;First, grab (a tea and) a live version of Debian, install it on a usb
key (it&amp;#39;s 2025, who still burns Linux distributions to CDs?), boot
on it, and open a terminal.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;We need to install a few packages:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; apt update&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; apt install debootstrap arch-install-scripts&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Let&amp;#39;s assume you have the following setup:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;sda&amp;lt;/code&amp;gt; is the disk where we are going to install the system (with its
partitions being efi, boot and root, in that order);&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;sdb&amp;lt;/code&amp;gt; is the live usb key;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;sdc&amp;lt;/code&amp;gt; is the usb key where we will install the keyfile.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;NAME&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    SIZE RO TYPE    UUID&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sda&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;       1T&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; disk&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;├─sda1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    1G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part    00a1&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;├─sda2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    1G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part    00a2&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;└─sda3&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;  958G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part    00a3&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sdb&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;     7.6G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; disk&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;├─sdb1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;  3.5G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;└─sdb2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;  3.2M&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sdc&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;       8G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; disk&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;├─sdc1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;    8G&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;  0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; part    00c1&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;We will start with creating a 64B keyfile. You can adjust the command to your
liking, e.g., if you want a larger key, or if you want it to contain text, an
image, etc.:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;mkdir&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; /tmp/usbkey&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mount /dev/sdc1 /tmp/usbkey&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;dd&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; if=/dev/urandom of=/tmp/usbkey/luks-keyfile bs=&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; count=&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt;64&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;We can now create our new filesystem:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mkfs.vfat&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -F32&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; /dev/sda1&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mkfs.ext4 /dev/sda2&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; cryptsetup luksFormat /dev/sda3&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; --key-file&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; /tmp/usbkey/luks-keyfile&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; cryptsetup open /dev/sda3 cryptroot&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; --key-file&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; /tmp/usbkey/luks-keyfile&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mkfs.ext4 /dev/mapper/cryptroot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; umount /tmp/usbkey&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;And mount it:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mount /dev/mapper/cryptroot /mnt&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mkdir /mnt/boot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mount /dev/sda2 /mnt/boot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mkdir /mnt/boot/efi&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; mount /dev/sda1 /mnt/boot/efi&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;And install a basic Debian system:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; debootstrap stable /mnt http://deb.debian.org/debian&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Let&amp;#39;s also generate a few files (if the usb key with the keyfile is still
plugged in, you might want to remove it from &amp;lt;code&amp;gt;/mnt/etc/fstab&amp;lt;/code&amp;gt;):&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;sudo bash -c &amp;amp;#39;genfstab -U /mnt &amp;amp;gt; /mnt/etc/fstab&amp;amp;#39;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h2 id=&amp;quot;chroot-to-the-new-system&amp;quot;&amp;gt;&amp;lt;code&amp;gt;chroot&amp;lt;/code&amp;gt; to the new system&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;To enter our new system:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; arch-chroot /mnt&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;arch-chroot&amp;lt;/code&amp;gt; is provided by the &amp;lt;code&amp;gt;arch-install-scripts&amp;lt;/code&amp;gt; package
installed earlier. It is a quicker and more convenient way to mount the
required file systems needed in the chroot and then chroot.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;new-installation-setup&amp;quot;&amp;gt;New installation setup&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;Install a few necessary tools:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;apt&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; update&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;apt&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; install neovim grub-efi openssh-server cryptsetup-initramfs&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; \&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;linux-image-amd64&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; linux-headers-amd64 initramfs-tools efibootmgr locales&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Configure a few necessary things:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# root password&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;passwd&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# hostname&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FE8019;&amp;quot;&amp;gt;echo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; my-encrypted-host&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; &amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; /etc/hostname&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sed&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; -i&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; &amp;amp;#39;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;s/debian/my-encrypted-host/&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;&amp;amp;#39;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; /etc/hosts&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# setting the time &amp;amp;amp; locales&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;dpkg-reconfigure&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; tzdata&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;dpkg-reconfigure&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; locales&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic;&amp;quot;&amp;gt;# setting up the network&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;cat&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; &amp;amp;lt;&amp;amp;lt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt; EOF&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt; &amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; /etc/systemd/network/&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #8EC07C;&amp;quot;&amp;gt;&amp;amp;lt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;interface-name&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;.network&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;[Match]&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;Name=&amp;amp;lt;interface-name&amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;[Network]&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt;DHCP=yes&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #A89984;&amp;quot;&amp;gt;EOF&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;You might also want to allow password authentication for root via ssh,
just at the beginning for debug purposes:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;nvim /etc/ssh/sshd_config&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;PermitRootLogin yes&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;We can now enable the services:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;systemctl&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; enable sshd&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;systemctl&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; enable systemd-networkd&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h3 id=&amp;quot;encrypted-root-configuration&amp;quot;&amp;gt;Encrypted root configuration&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;Add a new entry in &amp;lt;code&amp;gt;/etc/crypttab&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;cryptroot	/dev/sda3	/dev/disk/by-uuid/00c1:/luks-keyfile	luks,discard,keyscript=/lib/cryptsetup/scripts/passdev&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Also add a few modules in &amp;lt;code&amp;gt;/etc/initramfs-tools/modules&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;ext4        # this is because our root partition uses ext4&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;nls_cp437&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;nls_ascii&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Update Initramfs:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;update-initramfs -u -k all&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Install the bootloader:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;grub-install&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #D3869B;&amp;quot;&amp;gt; --target=x86_64-efi --efi-directory=/boot/efi&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;update-grub&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Et voilà! You can now exit the chroot, unmount the different disks, and
reboot.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Note: please properly close the cryptroot mapping after unmounting
&amp;lt;code&amp;gt;/mnt&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;shellscript&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #FABD2F;&amp;quot;&amp;gt;sudo&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #B8BB26;&amp;quot;&amp;gt; cryptsetup close /dev/mapper/cryptroot&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h2 id=&amp;quot;some-references&amp;quot;&amp;gt;Some references&amp;lt;/h2&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://semjonov.de/posts/2021-09/minimal-ubuntu-installation-with-debootstrap/&amp;quot;&amp;gt;install ubuntu with debootstrap&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.reddit.com/r/debian/comments/se1a3e/having_a_ton_of_trouble_setting_up_encrypted_lvm/&amp;quot;&amp;gt;reddit&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Fault-Tolerance for LLM Inference</title>
                <link href="https://pierrelouis.pakupaku.me/blog/llm-inference/"/>
                <updated>2024-11-15T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/llm-inference/</id>
                <content type="html">&amp;lt;h2 id=&amp;quot;introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Large Language Models (LLM) are becoming increasingly popular for numerous
tasks, including chatbots, content generation (text, images or videos),
translation, etc.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;LLM users interact with such systems by sending a &amp;lt;strong&amp;gt;prompt&amp;lt;/strong&amp;gt;, a text describing
their request. The LLM then generates the answer by leveraging a set of GPUs in
a process called &amp;lt;strong&amp;gt;inference&amp;lt;/strong&amp;gt;, after which they send back the answer to the
user.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Compared to previous machine learning systems, state-of-the-art LLMs require
hundreds of GB of GPU memory, while high-end GPUs such as the NVIDIA A100
possess only 80GB of RAM. This requires splitting the model on multiple GPUs.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Unfortunately, large-scale GPU deployments are prone to failures, as
demonstrated by &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.usenix.org/conference/nsdi22/presentation/eisenman&amp;quot;&amp;gt;Eisenman et al.&amp;lt;/a&amp;gt;
and &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://semianalysis.com/2024/09/04/multi-datacenter-training-openais/?utm_source=post-email-title&amp;amp;amp;publication_id=329241&amp;amp;amp;post_id=148471080&amp;amp;amp;utm_campaign=email-post-title&amp;amp;amp;isFreemail=true&amp;amp;amp;r=3ks5kd&amp;amp;amp;triedRedirect=true&amp;amp;amp;utm_medium=email&amp;quot;&amp;gt;Patel et al.&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;When a failure occurs during inference, the user request needs to be recomputed
from the beginning, which incurs additional latency and computation.
Some researchers are thus making LLM inference fault-tolerant.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In this post we will detail the LLM inference mechanism, present some
experiments done on A100 GPUs, and finally describe the DéjàVu system for
fault-tolerant LLM inference.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;llm-inference-in-a-nutshell&amp;quot;&amp;gt;LLM inference in a nutshell&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;LLM inference is a multi-phases process, as shown in the below figure with a
user sending the prompt &amp;quot;Tokyo is&amp;quot;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/llm-inference/llm_inference.png&amp;quot; alt=&amp;quot;LLM Inference process&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The model first tokenizes it and outputs a set of numerical values, called
&amp;lt;strong&amp;gt;tokens&amp;lt;/strong&amp;gt;, understandable only by the model. The tokens are then processed by
the LLM for one iteration. These two computations define the &amp;lt;strong&amp;gt;prompt
processing phase&amp;lt;/strong&amp;gt;. This phase outputs both a &amp;lt;strong&amp;gt;context&amp;lt;/strong&amp;gt;, saved in a
&amp;lt;strong&amp;gt;Key-Value cache&amp;lt;/strong&amp;gt; (KV cache), and a new token.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The second phase of inference is the &amp;lt;strong&amp;gt;token generation phase&amp;lt;/strong&amp;gt;, where all the
remaining tokens of the answer are computed. A single LLM iteration computes
one new token, with the previous context (stored in the KV cache) and token as
inputs. It outputs the new context that will be saved in the KV cache and a new
token.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Finally, the LLM translates the tokens to human readable output in a process
similar to accessing a lookup table. This output (&amp;quot;Tokyo is the capital of
Japan&amp;quot; in the above figure) is sent back to the client.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;To tolerate faults, one idea is to persist the KV cache so that the request can
be recomputed from its latest state before the failure rather than from the
beginning.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;our-experiments&amp;quot;&amp;gt;Our experiments&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;We run several experiments on two A100 GPUs (each having 80GB of RAM) with the
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://huggingface.co/facebook/opt-13b&amp;quot;&amp;gt;OPT-13B&amp;lt;/a&amp;gt; model. Loading the model
allocates 40GB of memory per GPU. Batch size is set to 8. The goal is to
evaluate the potential latency gain by implementing a persistent KV cache.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In a first experiment we measure the average processing time of each inference
stages average processing time. The experiment stops after having generated a
total of 2000 tokens (including the 40 tokens of the prompt). As can be
observed in the figure below prompt processing takes 1.7s while a single token
generation takes 2.4s. A single failure during inference thus leads to several
seconds of delay.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/llm-inference/processing_time.png&amp;quot; alt=&amp;quot;Inference processing time&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In a second experiment we replay the &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/Azure/AzurePublicDataset/blob/master/AzureLLMInferenceDataset2023.md&amp;quot;&amp;gt;Microsoft Azure code
trace&amp;lt;/a&amp;gt;
while introducing failures. A given percentage of requests fails, that is to
say the GPU has to recompute it from the start.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Results are reported in the figure below. Without failures, the entire trace is
replayed in 253 minutes (a bit over 4 hours). When introducing failures, this
execution time increases: 277 minutes with 10% of failed requests, 303 minutes
with 20%, and so on, up to 507 minutes with 100% of failed requests (i.e., all
requests need to be executed twice). This represents an increase from 9% (10%
failures) to 100% (100% failures).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/llm-inference/faults.png&amp;quot; alt=&amp;quot;Inference under failures&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;dejavu&amp;quot;&amp;gt;DéjàVu&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://proceedings.mlr.press/v235/strati24a.html&amp;quot;&amp;gt;DéjàVu&amp;lt;/a&amp;gt; is a fault-tolerant
system for LLM inference system is a system presented by Strati et al. at the
41st International Conference on Machine Learning (2024).
The figure below, taken from the research paper, describes its architecture.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/llm-inference/dejavu_arch.png&amp;quot; alt=&amp;quot;DéjàVu architecture&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;DéjàVu replicates the KV cache in persistent storage or main memory. In case of
failures, the KV cache can be restored from the latest available backup instead
of having to redo the inference from zero.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;To be able to detect a failure, GPUs periodically send heartbeat messages to a
central controller component. If he does not receive a heartbeat from a
particular GPU after a given period of time, then it assumes the GPU to be
faulty.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;To efficiently stream (i.e., send) the KV cache to the host CPU, DéjàVu
aggregates KV cache updates in a single continuous area of the GPU memory. This
makes GPU transfers more efficient, as they can use the full GPU bandwidth,
compared to transferring small and non-contiguous GPU memory areas one at a
time.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;DéjàVu proposes other optimisations, such as executing prompt processing and
token generation on different sets of GPUs to avoid conflicts between these two
tasks.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;DéjàVu has been evaluated on real hardware, with A100 GPUs. The authors show
that, in the fault-free case, it outperforms FasterTransformer (the baseline)
by 2x while providing low latency (see below).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/llm-inference/dejavu_faultfree.png&amp;quot; alt=&amp;quot;DéjàVu performance in the fault-free case&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In the faulty case, DéjàVu is able to finish execution 16% faster than the
baseline thanks to its fault-tolerant replicated KV cache (see figure below).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/llm-inference/dejavu_faulty.png&amp;quot; alt=&amp;quot;DéjàVu performance under failures&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;conclusion&amp;quot;&amp;gt;Conclusion&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;In this post we have argued that failures during the LLM inference process is a
problem, as requests need to be re-executed from zero, which increases the
latency perceived by the client.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;We ran several experiments on two A100 GPUs, increasing the percentage of
faulty requests (i.e., requests that need to be re-executed). A low percentage
of failures such as 10% already means that executing the entire set of requests
will take 10% more time.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Finally, we presented DéjàVu, a system that brings fault-tolerance to LLM
inference by smartly replicating the KV cache, storing the intermediate state
of the LLM inference process. As a result, requests can be restarted from a
point close to the GPU failure instead of from zero.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;acknowledgements&amp;quot;&amp;gt;Acknowledgements&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;We are grateful to IIJ Cloud Division for giving us access to their GPUs.&amp;lt;/p&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Toward Trusted Pictures to Combat Fake News</title>
                <link href="https://pierrelouis.pakupaku.me/blog/trusted-pictures/"/>
                <updated>2024-07-05T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/trusted-pictures/</id>
                <content type="html">&amp;lt;h2 id=&amp;quot;introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Fake news, i.e. the forgery of news information, can have dramatic consequences,
from personal harm and legal issues to societal unrest, health risks, financial
losses, and threats to democratic processes, to the extent that governments are
considering new legislation to combat this threat, e.g.,
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.msn.com/en-us/news/technology/over-300-global-experts-urge-governments-to-tackle-deepfake-threats/ar-BB1iFZPY&amp;quot;&amp;gt;here&amp;lt;/a&amp;gt;
or
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.weforum.org/agenda/2024/02/ai-deepfakes-legislation-trust/&amp;quot;&amp;gt;there&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Manipulated images are a particular potent medium, where an image is taken
out-of-context, with its original message altered to suit one agenda. Current
state-of-the-art methods rely on image processing techniques, which, as we will
show in this article, are unfortunately not sufficient to detect manipulations.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Fortunately, several actors are working on this problem. We will present two
such solutions: &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://contentauthenticity.org/&amp;quot;&amp;gt;CAI&amp;lt;/a&amp;gt; and
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.serelay.com/&amp;quot;&amp;gt;Serelay&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Before diving into the details, one might ask why an ISP such as IIJ should
care about these fake news. Internet actors are already filtering attacks over
the network such as spam, viruses, or Denial-of-Service. We believe they also
have some responsibility to stop the dissemination of fake news.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;the-problem-of-detecting-manipulated-images&amp;quot;&amp;gt;The problem of detecting manipulated images&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;There exists a lot of tools to detect fake images:
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://fake-inversion.github.io/&amp;quot;&amp;gt;fake-inversion&amp;lt;/a&amp;gt;,
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://fotoforensics.com/&amp;quot;&amp;gt;fotoforensics&amp;lt;/a&amp;gt;, &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.invid-project.eu/tools-and-services/invid-verification-plugin/&amp;quot;&amp;gt;invid
plugin&amp;lt;/a&amp;gt;,
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.fakeimagedetector.com/&amp;quot;&amp;gt;fakeimagedetector&amp;lt;/a&amp;gt;, etc.
They either rely on pixels analysis via machine learning, image processing
techniques, or search for similar images over the Internet to find the origin
of an image.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Unfortunately, these tools are not sufficient, as we show with the following
three images:
&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/trusted-pictures/wwf.jpg&amp;quot; alt=&amp;quot;WWF deforestation&amp;quot; /&amp;gt;
&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/trusted-pictures/kissin.jpg&amp;quot; alt=&amp;quot;Kiss-in protest&amp;quot; /&amp;gt;
&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/trusted-pictures/rheinII.jpg&amp;quot; alt=&amp;quot;Rhein II&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The first image originates from a &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://twitter.com/climateconco/status/1087550447005646849/photo/1&amp;quot;&amp;gt;WWF contest in
2019&amp;lt;/a&amp;gt;. It
shows the extent of deforestation in the Amazon forest by comparing the same
forest over a ten years period. The second image has been presented on some
social medias as an &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.dw.com/en/fact-check-no-anti-vaxxer-kiss-in-in-germany/a-60062668&amp;quot;&amp;gt;anti-vaccine protest in Germany in
2021&amp;lt;/a&amp;gt;.
The third image, named &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.theguardian.com/artanddesign/2011/nov/11/andreas-gursky-rhine-ii-photograph&amp;quot;&amp;gt;&amp;quot;Rhein
II&amp;quot;&amp;lt;/a&amp;gt;,
was taken by Andreas Gursky in 1999. The artist then edited the image to remove
unnecessary details to create this simple and abstract composition.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;We ran these images on the
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.fakeimagedetector.com/&amp;quot;&amp;gt;fakeimagedetector&amp;lt;/a&amp;gt; tool. This tool uses
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://en.wikipedia.org/wiki/Error_level_analysis&amp;quot;&amp;gt;Error Level Analysis
(ELA)&amp;lt;/a&amp;gt; to detect pixel
manipulations. The results are quite surprising: the first image looks
authentic, while the second and third ones are deemed computer generated or
modified.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Actually, the first image does not show the same spot over a ten years period:
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.huffpost.com/archive/qc/entry/10yearschallenge-defenseurs-environnement-defi_qc_5cccd7c5e4b089f526c7704c&amp;quot;&amp;gt;both sides come from the same
image&amp;lt;/a&amp;gt;.
While deforestation is a real problem, such forgeries might make more harm than
good and damage the reputation of associations fighting for the climate.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Regarding the second image, it is authentic, but was taken in &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://actipedia.org/project/chilean-kiss&amp;quot;&amp;gt;Chile in 2011
during some students protest&amp;lt;/a&amp;gt;, not
in Germany in 2021. It is easy to reuse an image for one&amp;#39;s own agenda without
having access to additional metadata on the image, such as the time when this
image was taken or GPS coordinates.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The third image is also authentic, but was indeed slightly post-processed by
its author. The point we make in this third example is that the difference
between AI-generated and real images is now very thin, with &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://scitechdaily.com/unmasking-the-illusion-ai-generated-faces-challenge-perceptions/&amp;quot;&amp;gt;people believing
AI-generated images to be
real&amp;lt;/a&amp;gt;.
Without any authenticity record it would be very easy to deceive someone by
pretending an image is AI-generated or not.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;One may think the &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://archive.org/details/exif-specs-3.0-dc-008-translation-2023-e/mode/2up&amp;quot;&amp;gt;Exif
metadata&amp;lt;/a&amp;gt;
could help to detect these manipulations by showing detailed information to the
viewer about the situation in which they have been taken (camera model, GPS
location, time and date, etc.). Unfortunately, there are several problems.
First, there are no mandatory fields. Camera manufacturers can decide what
metadata will be (or not) embedded into the file, and users can modify some
settings prior to taking an image. Second, this metadata can be modified or
removed by any editing software. Third, image file formats are not secure: they
do not embed any signature or similar mechanism to prove their authenticity,
keep their integrity against unauthorized modifications, or store confidential
information that could prove the image authenticity (e.g., the GPS location of
an image taken during a conflict).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;To summarize, image processing techniques can detect if the pixels of an image
have been manipulated (e.g., part of the image have been modified), but cannot
detect whether an image and its associated message are misleading the viewer,
for example by pretending an image has been taken at a different place or
different time. Part of the problem is the lack of any secure metadata (e.g.,
when and where the image has been taken) in current image formats: it is
relatively easy to remove or alter the Exif metadata.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;existing-solutions&amp;quot;&amp;gt;Existing solutions&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;We now present two existing solutions to build trusted images, that is to say
images whose provenance and history can be certified.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;content-authenticity-initiative&amp;quot;&amp;gt;Content Authenticity Initiative&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;The &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://contentauthenticity.org/&amp;quot;&amp;gt;Content Authenticity Initiative (CAI)&amp;lt;/a&amp;gt;
was co-founded by Adobe, The New York Times and Twitter in 2019. Its goal is to
promote an industry standard for provenance metadata. Since its inception, new
actors have joined this initiative, in particular the BBC, ARM, Qualcomm, or
even Nikon.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;CAI proposes an end-to-end system that adds secure metadata to an image at
different stages of its creation, when it is taken by the camera and when it is
post-processed (see image below). This secure metadata contains additional
information regarding the provenance of the image: when it was taken, who took
it, who published it, how it was altered, etc.) This additional information is
then secured with hashes and digital signatures. When a user views the image,
he can then check the authenticity and provenance of the metadata, effectively
increasing his trust in the image.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/trusted-pictures/cai.png&amp;quot; alt=&amp;quot;CAI file structure&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;By embedding secure metadata into the image format instead of storing the
secure metadata in another place (a server or another file), this system is
transparent to users: they do not need to contact a remote server, thus not
needing an Internet connection to check for an image authenticity, and they do
not need to store or exchange another file alongside the image.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;One downside of this approach is the need for a secure camera. If the image is
taken by a normal camera, its authenticity cannot be asserted. Fortunately,
smartphones and camera manufacturers are working on new devices compatible with
CAI, e.g.,
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://leica-camera.com/en-US/photography/content-credentials#&amp;quot;&amp;gt;Leica&amp;lt;/a&amp;gt;,
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://contentauthenticity.org/secure-mode-enabled&amp;quot;&amp;gt;Qualcomm&amp;lt;/a&amp;gt;, or
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.nikon.com/company/news/2022/1019_exhibition_01.html&amp;quot;&amp;gt;Nikon&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;serelay&amp;quot;&amp;gt;Serelay&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.serelay.com/&amp;quot;&amp;gt;Serelay&amp;lt;/a&amp;gt; proposes two phone applications to take
secure images and an SDK to verify the authenticity of an image. When taking an
image, Serelay application performs dozens of checks to make sure the photographer is not
trying to spoof the device location or time, by leveraging GPS coordinates,
nearby wifi networks, timezone, as well as analyzing the image to detect for
example whether the user is taking an image of another (two-dimensional)
image instead of a real scene.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The application then extracts and sends hundreds of datapoints from the image
to Serelay servers (which amount to 15kB only according to them). By leveraging
their SDK, other users can then check the image authenticity.
The figure below shows one such example.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/trusted-pictures/serelay.jpg&amp;quot; alt=&amp;quot;Serelay dashboard&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Similarly to CAI, users need to take images with a special camera (in this
case, Serelay smartphones application). However, Serelay does not embed the
secure metadata with the image, but instead relies on its own servers.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;summary&amp;quot;&amp;gt;Summary&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Existing image processing techniques are not sufficient to detect images
manipulated to alter their message. This is a problem in the fight against fake
news. Fortunately, several solutions are being developed. These solutions aim
at building trust into the image from the moment it is taken by the camera, and
then associate additional, secure metadata to the image to prove its
authenticity.&amp;lt;/p&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Development on a SiFive HiFive1 RevB in 2024</title>
                <link href="https://pierrelouis.pakupaku.me/blog/hifive1b/"/>
                <updated>2024-06-01T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/hifive1b/</id>
                <content type="html">&amp;lt;h2 id=&amp;quot;introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;My local electronic shop was selling a bunch of SiFive HiFive1 RevB at a 85%
discount, so even before asking whether I need one, I bought one. No way I&amp;#39;d
pass the opportunity to try a RISC-V board!&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The board, released around March 2019, is Arduino compatible and embeds a
micro-B USB connection, JTAG capabilities, a WiFi and Bluetooth module (needs
an external module), I/O headers, a SiFive FE310-G0002 microcontroller, and
more.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The processor inside the board microcontroller is a E31 RISC-V RV32IMAC CPU.
This is a 32-bit processor running at 320MHz with 16kB of SRAM, 16kB of L1
instruction cache, and 32Mb of flash memory.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Many resources can be found online, including code and documentation. However,
the main issue I encountered is the lack of code updates in the recent years:
the Freedom Studio or Freedom E SDK (which I will use below) github
repositories, necessary to develop for the board, have not been updated since
2021. I also had the problem of the documentation being for Ubuntu while I use
ArchLinux.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;getting-started&amp;quot;&amp;gt;Getting started&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;The first thing to do is read the &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.starfivetech.com/uploads/hifive1b-getting-started-guide_v1.2.pdf&amp;quot;&amp;gt;Getting Started
guide&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Software development can be done either via &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/sifive/freedom-studio&amp;quot;&amp;gt;Freedom
Studio&amp;lt;/a&amp;gt;, an Eclipse-based IDE plus
all the tools necessary for development, or a bit more manually with the
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/sifive/freedom-e-sdk&amp;quot;&amp;gt;Freedom E SDK&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;update&amp;quot;&amp;gt;Update&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;My solution in the next sections was more complicated than necessary. Thanks
to Python support for virtual environments, we can easily use the board on a
modern system.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;First, let&amp;#39;s download a few packages: &amp;lt;code&amp;gt;jlink-software-and-documentation&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;python38&amp;lt;/code&amp;gt;.
Two remarks:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;with Python3.9 the compilation of one package installed by &amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt; fails, so I
stick to 3.8 (it&amp;#39;s the same version I had in the Docker container);&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;there seems to be something missing when using &amp;lt;code&amp;gt;riscv64-unknown-elf-gcc&amp;lt;/code&amp;gt;
(&amp;lt;code&amp;gt;ld&amp;lt;/code&amp;gt; fails, unable to find &amp;lt;code&amp;gt;-lc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-lgloss&amp;lt;/code&amp;gt;), so I instead use the one of
FreedomStudio.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;Then, we need the Freedom tools.&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ cd &amp;amp;lt;BASE_DIR&amp;amp;gt; # where you install the board tools&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ mkdir FreedomStudio &amp;amp;amp;&amp;amp;amp; cd FreedomStudio&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ wget &amp;amp;quot;https://static.dev.sifive.com/dev-tools/FreedomStudio/2019.03.4/FreedomStudio-4.7.2.2019-03-4-linux.gtk.x86_64.tar.gz&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ tar -xf FreedomStudio-4.7.2.2019-03-4-linux.gtk.x86_64.tar.gz&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ cd ..&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ git clone --recursive https://github.com/sifive/freedom-e-sdk.git&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;We&amp;#39;ll now tell the SDK to build the virtual environment with Python 3.8 intead of the latest one in Arch repos:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ cd &amp;amp;lt;BASE_DIR&amp;amp;gt;/freedom-e-sdk&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sed --in-place &amp;amp;#39;s/python3 -m venv/python3.8 -m venv/&amp;amp;#39; scripts/virtualenv.mk&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;It&amp;#39;s now time to compile and run some code.&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ export RISCV_PATH=&amp;amp;lt;BASE_DIR&amp;amp;gt;/FreedomStudio/SiFive/toolchain/riscv64-unknown-elf-gcc-8.2.0-2019.02.0&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ cd &amp;amp;lt;BASE_DIR&amp;amp;gt;/freedom-e-sdk&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ make BSP=metal PROGRAM=hello TARGET=sifive-hifive1-revb software upload&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Et voilà !&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;unefficient-solution&amp;quot;&amp;gt;Unefficient Solution&amp;lt;/h2&amp;gt;
&amp;lt;h3 id=&amp;quot;first-try-on-archlinux&amp;quot;&amp;gt;First try on ArchLinux&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;Innocently, I tried to follow the guide while running on ArchLinux, installing
the two following packages for the prerequisite:
&amp;lt;code&amp;gt;jlink-software-and-documentation&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;riscv64-unknown-elf-gcc&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Most of it went fine, until the &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; command to build one of the Freedom E
SDK examples. More specifically, the Makefile runs a Python script that tries
to import the &amp;lt;code&amp;gt;distutils&amp;lt;/code&amp;gt; module, deprecated since Python 3.10, while I have
Python 3.12 installed.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Maybe there is a simple solution to this problem, but I could not find one, so
I switched to Ubuntu (in a Docker container).&amp;lt;/p&amp;gt;
&amp;lt;h3 id=&amp;quot;successful-try-on-ubuntu-in-docker&amp;quot;&amp;gt;Successful try on Ubuntu (in Docker)&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;Last code update on github is around 2021? Let&amp;#39;s install Ubuntu 20.04 LTS then!
I do not want to remove my ArchLinux, and a virtual machine would be too
cumbersome (especially since I need to be able to access the board from the
Ubuntu installation), so I created a new Docker container.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;The first step is to install Docker:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ paru -S docker&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sudo systemctl enable docker&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sudo systemctl start docker&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Then we can get the Ubuntu 20.04 image and install some packages:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sudo docker pull ubuntu:20.04&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sudo docker run -ti --rm ubuntu:20.04 /bin/bash&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;# # inside the container from this point&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;# apt update &amp;amp;amp;&amp;amp;amp; apt upgrade &amp;amp;amp;&amp;amp;amp; apt install build-essential screen git ...&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;# do NOT exit the container before the next step!&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Once done, we will create a new image from the container, so that we do not
need to do the above steps each time we want to run the container (the
container ID will be different in your case). After this step it is safe to
exit the container. Note that you need to redo the commit everytime you install
a new software.&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sudo docker ps&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;CONTAINER ID   IMAGE          COMMAND       CREATED       STATUS       PORTS     NAMES&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;0b79278c9c68   ubuntu:20.04   &amp;amp;quot;/bin/bash&amp;amp;quot;   2 hours ago   Up 2 hours             great_khayyam&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sudo docker commit -p 0b79278c9c68 ubuntu20.04_hifive1b_dev&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;h3 id=&amp;quot;compiling-and-running-the-hello-example&amp;quot;&amp;gt;Compiling and running the hello example&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;Let&amp;#39;s connect the board to the computer!&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;You need to connect the board before running the container, otherwise the
container will not be able to access it via &amp;lt;code&amp;gt;/dev/&amp;lt;/code&amp;gt;. Another solution, not
tried, would be to copy the compiled application to the board from the host.
This should be possible as the board appears to the host as a USB device.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;You can run the container again. As I do not want to put the SDK and my code
inside the image -- that would increase its size beyond something acceptable --
I am mounting a local folder inside the container. And I also need to pass the
&amp;lt;code&amp;gt;--privileged&amp;lt;/code&amp;gt; flag to the &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt; command to access the board serial
console (in &amp;lt;code&amp;gt;/dev/ttyACM0&amp;lt;/code&amp;gt;). The new command is:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sudo docker run --privileged -ti -v /absolute/path/to/local/folder/shared/with/container:/data ubuntu20.04_hifive1b_dev /bin/bash&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;From inside the container, for some reason installing the RISC-V toolchain was
stalling. And I&amp;#39;m not sure how to install the required JLink tools. So I
changed my strategy: I downloaded and extracted &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://static.dev.sifive.com/dev-tools/FreedomStudio/2019.03.4/FreedomStudio-4.7.2.2019-03-4-linux.gtk.x86_64.tar.gz&amp;quot;&amp;gt;Freedom
Studio&amp;lt;/a&amp;gt;
inside the shared folder. It already contains the RISC-V toolchain and JLink
tools, quite convenient! As I did on ArchLinux, I also downloaded the Freedom E
SDK.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Once done, we need to tell the SDK where to find the tools:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;export PATH=/data/FreedomStudio-4.7.2/SiFive/jlink/jlink-6.44.0-2019.03.0:${PATH}&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;export RISCV_PATH=/data/FreedomStudio-4.7.2/SiFive/toolchain/riscv64-unknown-elf-gcc-8.2.0-2019.02.0&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;To access the board serial console (from the container or host), run the
following command (we&amp;#39;ll use it to check whether our application runs
correctly):&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;$ sudo screen /dev/ttyACM0 115200 # remove sudo if already root&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Finally, we can build the code (here the &amp;lt;code&amp;gt;hello&amp;lt;/code&amp;gt; example from the SDK) and
&amp;lt;code&amp;gt;upload&amp;lt;/code&amp;gt; it to the board in one command:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;giallo&amp;quot; style=&amp;quot;color: #EBDBB2; background-color: #282828;&amp;quot; &amp;gt;&amp;lt;code data-lang=&amp;quot;plain&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;giallo-l&amp;quot;&amp;gt;&amp;lt;span&amp;gt;make BSP=metal PROGRAM=hello TARGET=sifive-hifive1-revb software upload&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;Just press the &amp;lt;code&amp;gt;RESET&amp;lt;/code&amp;gt; button on the board to restart it with the new program,
and voilà! You should see &amp;lt;code&amp;gt;Hello, World!&amp;lt;/code&amp;gt; appearing in the serial console.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Now the fun begins. I think I&amp;#39;ll try to &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://github.com/rustbox/rustbox-hifive1-revb&amp;quot;&amp;gt;write an OS in
Rust&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Making Internet Applications Trustworthy</title>
                <link href="https://pierrelouis.pakupaku.me/blog/trustworthyinternet/"/>
                <updated>2024-04-08T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/trustworthyinternet/</id>
                <content type="html">&amp;lt;h2 id=&amp;quot;context-and-motivation&amp;quot;&amp;gt;Context and motivation&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;&amp;quot;The Internet’s potential is unlimited. As a worldwide resource, the Internet supports commerce,
recreation, research, education, entertainment, and everything in between. But with different
stakeholders and competing demands of the network, safeguarding the future of the Internet can seem
like an impossible task.&amp;quot;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;-- &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.internetsociety.org/wp-content/uploads/2021/11/Enablers-of-OGST-EN.pdf&amp;quot;&amp;gt;The Internet Society&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;One important aspect to enable the above vision is trustworthiness. This can be
enabled at various levels of the Internet infrastructure, from the low-level
routing infrastructure to the high-level Internet applications. In this project
we are concerned only with the later, high-level Internet applications: with
this project, our goal is is to make Internet applications trustworthy.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;a-definition-of-trustworthy&amp;quot;&amp;gt;A definition of Trustworthy&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;In this context, what does trustworthy mean? The Internet Society teaches us
that &amp;quot;a trustworthy Internet meets the expectations of its users by offering a
resilient and reliable base for applications and services&amp;quot;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Trustworthy encompasses several concepts:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;reliability: the service is delivered as promised (e.g., a messaging
application correctly delivers messages between the participants);&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;resilience: the application continues to deliver its service even in the
presence of errors or malicious behaviours;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;availability: the application is ready to answer users&amp;#39; requests;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;accountability: application operators and users can be identified and held
responsible for their actions;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;privacy: users can control and understand what information about them is
collected, how it is collected, and can control how this information is used
and shared with others. Users might also prefer to remain anonymous. As an
example, the &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://gdpr-info.eu/&amp;quot;&amp;gt;GDPR&amp;lt;/a&amp;gt; is a good example of a regulation
aimed at protecting users&amp;#39; privacy on the Internet;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;confidentiality: eavesdroppers and attackers cannot observe sensitive data,
both in transit and at rest;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;integrity: while confidentiality prevents malicious entities to learn
something, integrity prevents them to alter it, for example a malicious cloud
storage provider could replace a valid encrypted file with another, valid,
encrypted file.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h2 id=&amp;quot;this-project&amp;quot;&amp;gt;This project&amp;lt;/h2&amp;gt;
&amp;lt;h3 id=&amp;quot;purpose&amp;quot;&amp;gt;Purpose&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;There are different levels where practitioners should increase the trust users
have in the Internet infrastructure, from the low-level routing infrastructure
to the high-level Internet applications. In this project we are concerned only
with the later, high-level Internet applications (web server, database, file
sharing service, etc.).&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Our goal is is to make Internet applications trustworthy, i.e.,&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Internet users have guarantees (security, fault tolerance, provided service,
...) on the applications they use (e.g., web server, storage service,
streaming);&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;companies running such applications are accountable for their behaviour;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;the Internet is a secure and resilient place without any single point of
failure or single controlling entity. The Internet has started as a
decentralized platform, and we want to keep it that way. Centralization not
only creates single points of failure, but it also enable some companies or
governments to use everyone&amp;#39;s data for their own benefits.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3 id=&amp;quot;approach&amp;quot;&amp;gt;Approach&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;Our approach is based on our previous knowledge in fault-tolerance and
security. More precisely, we are working on improving the fault-tolerance and
security of existing Internet applications, both on the server and client side.
Nevertheless, our aim is to empower Internet users: our solutions should
benefits users more than for the companies providing such services.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Security and fault-tolerance are generally costly techniques that can decrease
the performance of an application. We are exploring &amp;lt;em&amp;gt;practical&amp;lt;/em&amp;gt; solutions that
minimize this overhead so that practitioners can deploy our solutions on the
real Internet without losing their customers.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;We are also considering the sustainability of our solutions. With climate
change and international conflicts, it is not absurd to consider a &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://en.wikipedia.org/wiki/2020%E2%80%932023_global_chip_shortage&amp;quot;&amp;gt;shortage of
electronic
components&amp;lt;/a&amp;gt;,
an &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.zdnet.com/article/as-moores-law-slows-high-end-applications-may-feel-the-effect-mit-scientist-warns/&amp;quot;&amp;gt;innovation
slowdown&amp;lt;/a&amp;gt;
or &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://news.mit.edu/2022/how-can-we-reduce-carbon-footprint-global-computing-0428&amp;quot;&amp;gt;increasing demand on environmental-friendly
solutions&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;past-results&amp;quot;&amp;gt;Past results&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;My past research works have addressed this project goal in several ways, as can be seen in the figure below.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&amp;quot;https://pierrelouis.pakupaku.me/blog/trustworthyinternet/pastresearch.jpg&amp;quot; alt=&amp;quot;Past research&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Notable projects are:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;RBFT, Next 700 are Byzantine Fault tolerant protocols designed to
ensure good performance even in the presence of faults, where research works
usually focuses on improving the performance in the best case scenario where
no faults occur. The next 700 also empowers clients, as they are able to
change the behaviour of the protocol if they suspect a fault;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;FullReview makes distributed systems accountable even in the presence of
selfish participants, i.e., participants that want to maximise their benefits
without contributing their fare share into the system;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;LibSEAL is a SEcure Auditing Library for internet services. It allows to
detect integrity violations of internet services without the need to trust
the service operator, by leveraging a Trusted Execution Environment;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Endbox is a scalable and secure middlebox framework. It executes middlebox
functions inside a Trusted Execution Environment on client machines. Despite
its decentralised model, EndBox&amp;#39;s middlebox functions remain maintainable,
practical and scalable.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h2 id=&amp;quot;what-s-next&amp;quot;&amp;gt;What&amp;#39;s next?&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Making Internet Applications Trustworthy is a never ending endeavour. We tackle it one step at a time.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Here is a non-exhaustive list of potential sub-projects:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;making Byzantine Fault-Tolerance more practical;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;fault-tolerance for AI systems;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;decentralized and secure Internet;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;securing input devices (keyboard, mouse, etc.) against attacks
(&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://en.wikipedia.org/wiki/BadUSB&amp;quot;&amp;gt;badUSB&amp;lt;/a&amp;gt;, &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://counterespionage.com/malicious-usb-cables/&amp;quot;&amp;gt;malicious
cables&amp;lt;/a&amp;gt;,
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://en.wikipedia.org/wiki/Keystroke_logging&amp;quot;&amp;gt;keyloggers&amp;lt;/a&amp;gt;);&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;novel Trusted Execution Environments;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;combat fake news;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;etc.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;Please do not hesitate to &amp;lt;a href=&amp;quot;../../about&amp;quot;&amp;gt;contact me&amp;lt;/a&amp;gt; if you are interested in
such projects!&amp;lt;/p&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>Hardware timestamping</title>
                <link href="https://pierrelouis.pakupaku.me/blog/hardware-timestamping/"/>
                <updated>2023-10-30T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/hardware-timestamping/</id>
                <content type="html">&amp;lt;p&amp;gt;Network interfaces become smarter and smarter, being able to execute
functionalities traditionaly managed by the OS. When wanting to develop such a
functionality, a natural question is, &amp;quot;how much latency can I save ?&amp;quot;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Hardware timestamping, an obscure functionality of (recent? Not too old?) NICs,
inserts in a received network packet the current hardware timestamp. If the NIC
clock and host CPU clock are synchronised, it becomes possible to measure the
time it took from the NIC receiving the packet to the OS/application receiving
it, ultimately answering how much latency one can save by offloading a
functionality to the NIC.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;With &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://sys.cs.fau.de/person/vogel&amp;quot;&amp;gt;Arne Vogel&amp;lt;/a&amp;gt;, a PhD student from FAU
Erlangen in Germany with whom I have been working this summer, we have written
a blog article so that everyone can make use of this functionality:&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://eng-blog.iij.ad.jp/archives/21198&amp;quot;&amp;gt;In English&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://eng-blog.iij.ad.jp/archives/21208&amp;quot;&amp;gt;In Japanese&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;An appendix of this article can be found
&amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.arnevogel.com/network-latency-measurements/&amp;quot;&amp;gt;here&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
</content>
            </entry>
            
        
            
            <entry>
                <title>SmartNetStack: Network Stack Offloading on SoC-based smartNIC</title>
                <link href="https://pierrelouis.pakupaku.me/blog/smartnetstack/"/>
                <updated>2021-06-01T00:00:00+0000</updated>
                <id>https://pierrelouis.pakupaku.me/blog/smartnetstack/</id>
                <content type="html">&amp;lt;p&amp;gt;PI: &amp;lt;a rel=&amp;quot;external&amp;quot; href=&amp;quot;https://www.iijlab.net/en/members/pierrelouis.html&amp;quot;&amp;gt;Pierre Louis Aublin&amp;lt;/a&amp;gt;,
IIJ Research Laboratory&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In today&amp;#39;s architectures, cloud applications (such as web servers, key-value
stores or databases) execute both the application logic and the network stack
on the host CPU. As network speeds increase to more than 100Gbps, this becomes
inefficient: when executing the Redis key-value store on a 40Gbps network, more
than 38% of the CPU cycles are dedicated to TCP/IP processing [MOON20]; this
increases as the network speed increases.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Network vendors now propose smartNICs, special network cards that embed
additional hardware functionalities for custom packet processing, cryptographic
operations, checksum computation, and so on. Recent smartNICs, such as the
SoC-based Mellanox BlueField smartNICs, are drawing the attention of
researchers [KIM20, LIU21] thanks to their flexibility and ease-of-programming.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Researchers have successfully offloaded parts of the network stack to the
smartNIC [LE17, KIM20, MOON20]. However, offloading the entire network stack is
believed to be impractical due to hardware limitations, performance and
security issues, and so on [MOGUL03, PISMENNY21].&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In this project we would like to challenge this assumption and explore the
performance of cloud applications when the entire network stack is offloaded to
the smartNIC, in particular the TCP/IP stack. The benefits are multiple: better
CPU utilization by the application logic, lower network latency, better DMA
bandwidth utilization, and better energy efficiency.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;This project is divided into three steps: (i) measure the design and
performance characteristics of user-level network stacks such as DPDK-ANS
[ANS21], mTCP [JEONG14] or lwIP [DUNKELS01]; (ii) develop a fast DMA library to
efficiently send application payload between the smartNIC and the host
application; and (iii) propose a novel programming interface for applications
to make efficient use of this architecture.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In the first step we will extend the analysis performed by Liu et al. [LIU21]
on BlueField-2 smartNICs by measuring the design and performance
characteristics of user-level network stacks such as DPDK-ANS [ANS21], mTCP
[JEONG14] or lwIP [DUNKELS01]. Liu et al.&amp;#39;s network analysis focused only on
the Linux kernel network stack, which is inefficient as it involves expensive
system calls.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;In a second step, we will develop a fast DMA library to efficiently send
application payload between the smartNIC and the host application. As the
network stack is entirely executed on the smartNIC, the application payload can
be directly sent to the application. This removes metadata (such as the IP and
TCP headers), increases the data transferred size (as small network packets are
aggregated on the smartNIC), and improves the DMA bandwidth utilization.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Finally, we will propose a novel programming interface for applications to make
efficient use of this architecture. Application developers do not need to rely
on the socket API anymore. In particular network-related code (for example to
manage connections or re-transmit messages) is moved to the smartNIC, with the
application only receiving and sending its specific payload to the smartNIC.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;This project will leverage the BlueField-2 smartNICs available at CloudLab. We
will first focus on one applications: the Nginx web server [NGINX21]. We will
measure the application performance, network throughput, latency (including
average and tail latency), CPU usage, DMA bandwidth, and so on. Extensions to
this work are multiple: optimizing the performance of other types of
applications (key-value store, databases, machine learning, etc.); offloading
additional network functionalities (in particular TLS), etc.&amp;lt;/p&amp;gt;
&amp;lt;h2 id=&amp;quot;publications&amp;quot;&amp;gt;Publications&amp;lt;/h2&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;A Secure Network Stack for the Untrusted Cloud&amp;lt;/strong&amp;gt;. Keita Aihara, Pierre-Louis Aublin, and Kenji Kono. In the Fifteen European Conference on Computer Systems (EuroSys). April 2020.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;secureTCP: Securing the TCP/IP stack using a Trusted Execution Environment&amp;lt;/strong&amp;gt;. Keita Aihara, Pierre-Louis Aublin, and Kenji Kono. In the Information Processing Society of Japan System Software and Operating System conference (ComSys). December 2019.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h2 id=&amp;quot;references&amp;quot;&amp;gt;References&amp;lt;/h2&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;[ANS21] ANS team, &amp;quot;ANS: DPDK Native Accelerated Network Stack,&amp;quot; 2021. Available: http://www.ansyun.com/&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[DUNKELS01] Dunkels, Adam. &amp;quot;Design and Implementation of the lwIP TCP/IP Stack.&amp;quot; Swedish Institute of Computer Science 2.77 (2001).&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[JEONG14] Jeong, EunYoung, et al. &amp;quot;mtcp: a highly scalable user-level {TCP} stack for multicore systems.&amp;quot; 11th {USENIX} Symposium on Networked Systems Design and Implementation ({NSDI} 14). 2014.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[KIM20] Kim, Duckwoo, SeungEon Lee, and KyoungSoo Park. &amp;quot;A Case for SmartNIC-accelerated Private Communication.&amp;quot; 4th Asia-Pacific Workshop on Networking. 2020.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[LE17] Le, Yanfang, et al. &amp;quot;UNO: Uniflying host and smart NIC offload for flexible packet processing.&amp;quot; Proceedings of the 2017 Symposium on Cloud Computing. 2017.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[LIU21] Liu, Jianshen, et al. &amp;quot;Performance Characteristics of the BlueField-2 SmartNIC.&amp;quot; arXiv preprint arXiv:2105.06619 (2021).&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[MEMCACHED21] Memcached team, &amp;quot;High-performance, distributed memory object caching system.&amp;quot; 2021. Available: https://memcached.org/&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[MOGUL03] Mogul, Jeffrey C. &amp;quot;TCP Offload Is a Dumb Idea Whose Time Has Come.&amp;quot; HotOS. 2003.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[MOON20] Moon, YoungGyoun, et al. &amp;quot;Acceltcp: Accelerating network applications with stateful TCP offloading.&amp;quot; 17th USENIX Symposium on Networked Systems Design and Implementation (NSDI 20). 2020.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[NGINX21] Nginx team, &amp;quot;Nginx: High performance Load Balancer, Web Server &amp;amp;amp; Reverse Proxy.&amp;quot; 2021. Available: https://www.nginx.com/&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;[PISMENNY21] Pismenny, Boris, et al. &amp;quot;Autonomous NIC offloads.&amp;quot; Proceedings of the 26th ACM International Conference on Architectural Support for Programming Languages and Operating Systems. 2021.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
</content>
            </entry>
            
        
    
</feed>
