<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Korkeala.info - web log</title><id>https://korkeala.info/feed.xml</id><subtitle>Recent Posts</subtitle><updated>2026-01-03T12:28:02Z</updated><link href="https://korkeala.info/feed.xml" rel="self" /><link href="https://korkeala.info" /><entry><title>Reproducible development boxes</title><id>https://korkeala.info/reproducible-development-boxes.html</id><author><name>Markku Korkeala</name><email>markku.korkeala@iki.fi</email></author><updated>2026-01-03T14:00:00Z</updated><link href="https://korkeala.info/reproducible-development-boxes.html" rel="alternate" /><content type="html">&lt;p&gt;For some time I've experimented and looked for a good solution for building (reproducible)
development boxes. These will be virtual machines aimed for development. In the beginning they
will be local virtual machines, but in the future they could also be remote machines.
Main reason for using the development boxes would be added
security by separating and isolating projects/customer work from each other. Each
VM would have projects for one customer and only required SSH/access keys. The actual
builds are also run in isolated containers and have even more reduced access
to resources. This will protect against supply-chain malware as they reduce significantly resources
the malware can read, like SSH keys and access tokens. Here are requirements for my setup:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Easy way to create and destroy virtual machines&lt;/li&gt;&lt;li&gt;Have automated way to set up basic configuration (installed packages, network configuration and user accounts)&lt;/li&gt;&lt;li&gt;Share folders from host computer to the virtual machine&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I will use multiple layers and tools for protection, using separate virtual machines
is just one of them. In this post, I'll focus on automating the creation and management
of these development boxes, in the next
post I will describe some other methods I use inside the VM for isolating builds.&lt;/p&gt;&lt;h2&gt;Automating local virtual machines&lt;/h2&gt;&lt;p&gt;Long time ago I used &lt;a href=&quot;https://developer.hashicorp.com/vagrant&quot;&gt;Vagrant&lt;/a&gt; to have reproducible
test environments on local virtual machines. This was the first tool on my list to test
for automating virtual machine management.  First thing I noticed when looking for suitable
image for the VM was, that many boxes have not been updated for some time. Maybe the community
is shrinking and not active anymore?&lt;/p&gt;&lt;p&gt;I created OpenSUSE boxes with Vagrant and used it for a couple of weeks. Vagrant is over 10 years
old so it has quite a lot of documentation and examples. Simple things are easy to configure,
like shared folders between host and guest. It also has good support running
different provisioning tools to configure the VM on creation.&lt;/p&gt;&lt;p&gt;During the couple of weeks test run I trouble suspending and resuming my box, it
seems every time I had to suspend/shutdown my laptop I had to also bring the Vagrant box
up. Also, Vagrant isn't fast, I had to wait long time for certain operations on Vagrant
box to finish.  So I decided to look for tools.&lt;/p&gt;&lt;h3&gt;Opentofu&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://www.opentofu.org&quot;&gt;Opentofu&lt;/a&gt; has a &lt;a href=&quot;https://search.opentofu.org/provider/dmacvicar/libvirt/latest&quot;&gt;provider for creating KVM virtual
machines&lt;/a&gt;. I use Opentofu
on other projects, so this could be good solution. With little HCL-configuration I was
able to create myself an OpenSUSE virtual machine. Searching for the right type of image was cumbersome,
would be nice to have a better way to get a list of images to use. Again booting virtual machines
took a while, though this mostly just my impression.&lt;/p&gt;&lt;p&gt;I had a script for sharing folders from host computers with SSHFS. It worked alright,
though it disconnects now and then. While I was testing this solution,
I found another interesting project for lightweight virtual
machines, &lt;a href=&quot;https://linuxcontainers.org/incus/&quot;&gt;incus&lt;/a&gt;.&lt;/p&gt;&lt;h2&gt;Incus&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://linuxcontainers.org/incus/&quot;&gt;Incus&lt;/a&gt; is a successor of an older project, LXD. Incus is a
platform running containers and lightweight VMs. The lightweight VMs seemed interesting option.
Fedora also had packages for it, so I decided to test it out.&lt;/p&gt;&lt;p&gt;After setting initial configurations, I checked available images:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;incus image list images&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There are images available for most current Linux distributions. After choosing to run OpenSUSE Tumbleweed,
I started a test VM to experiment different configuration options and sure the lightweight VM's booted very fast!&lt;/p&gt;&lt;p&gt;But initially they would not start properly, I could not connect to it via SSH or incus shell. I was also experimenting
with different configuration options, so perhaps I had put a bad configuration option? I could
not query information about the running system, although the incus documentation said
I should be able to. After a while, I noticed others had similar issues:
&lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=2389081&quot;&gt;incus-agent fails to run in virtual machines after recent update&lt;/a&gt;.
So the issue was with incus-agent on the virtual machine.  After I was able to set
a working incus-agent on the VM and proper &lt;a href=&quot;https://cloud-init.io/&quot;&gt;cloud-init&lt;/a&gt; configuration, I could access it
and start experimenting.&lt;/p&gt;&lt;p&gt;During testing, I noticed it is faster than previous tools I tested. Vagrant
has different options to provision configurations for the boxes. With incus,
I settled for &lt;a href=&quot;https://cloud-init.io/&quot;&gt;cloud-init&lt;/a&gt;, which cloud variants of the incus images support.
Incus also supports sharing folders from host computer with simple command
(&lt;code&gt;incus config device add &amp;lt;instance_name&amp;gt; &amp;lt;device_name&amp;gt; disk source=&amp;lt;path_on_host&amp;gt; path=&amp;lt;path_in_instance&amp;gt; shift=true&lt;/code&gt;)
and if I need further provisioning, I can execute pyinfra/ansible over SSH.
It's not fully reproducible system like GuixOS or NixOS, but it is a good
start for my current needs.&lt;/p&gt;&lt;h3&gt;Incus provider for Opentofu&lt;/h3&gt;&lt;p&gt;When I was writing this post, I noticed that incus has an
&lt;a href=&quot;https://search.opentofu.org/provider/lxc/incus/latest&quot;&gt;Opentofu provider&lt;/a&gt;
as well. I moved the configuration to the Opentofu to have a better management
of the virtual machines. Now I can have the VM configuration in code, which
makes provisioning similar development boxes trivial. Here is an example configuration
for an OpenSUSE box:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-terraform&quot;&gt;terraform {
  required_providers {
    incus = {
      source = &amp;quot;lxc/incus&amp;quot;
      version = &amp;quot;1.0.2&amp;quot;
    }
  }
}

provider &amp;quot;incus&amp;quot; {
  default_remote = &amp;quot;local&amp;quot;

  remote {
    name    = &amp;quot;local&amp;quot;
    address = &amp;quot;unix://&amp;quot;
  }

}

resource &amp;quot;incus_image&amp;quot; &amp;quot;opensuse_cloud&amp;quot; {
  source_image = {
    remote = &amp;quot;images&amp;quot;
    name   = &amp;quot;opensuse/tumbleweed/cloud&amp;quot;
    type   = &amp;quot;virtual-machine&amp;quot; 
  }
}
data &amp;quot;template_file&amp;quot; &amp;quot;cloudinit&amp;quot; {
  template = file(&amp;quot;${path.module}/cloud_init.cfg&amp;quot;)
  vars = {
    user_account = &amp;quot;user&amp;quot;
  }
}

resource &amp;quot;incus_instance&amp;quot; &amp;quot;devbox1&amp;quot; {
  name      = &amp;quot;devbox1&amp;quot;
  image     = incus_image.opensuse_cloud.fingerprint
  type      = &amp;quot;virtual-machine&amp;quot;
  ephemeral = false
  profiles  = [&amp;quot;default&amp;quot;]
  config = {
    &amp;quot;user.user-data&amp;quot; = data.template_file.cloudinit.rendered
    &amp;quot;limits.cpu&amp;quot; = 2
    &amp;quot;limits.memory&amp;quot; = &amp;quot;8192MiB&amp;quot;
  }
  wait_for {
    type = &amp;quot;agent&amp;quot;
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And an example cloud-init configuration (&lt;code&gt;cloud_init.cfg&lt;/code&gt;):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;#cloud-config
package_update: true
package_upgrade: true
timezone: Europe/Helsinki
ssh_pwauth: true
packages:
  - git
  - openssh
  - helix
  - vim
  - helix-bash-completion
  - make
  - lazygit
  - git-delta
  - chezmoi
users:
  - name: user
    groups: users, wheel
    password: &amp;lt;hash&amp;gt;
    ssh_pwauth: true
    lock_passwd: false
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-ed25519 &amp;lt;ssh_key_pub&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Current status and future&lt;/h2&gt;&lt;p&gt;The incus VM has worked well this autumn. I use OpenSUSE Tumbbleweed
as the OS, Opentofu to define the VMs and I have cloud-init configurations
to have some automation for setting up the box.&lt;/p&gt;&lt;p&gt;The actual VMs haven't required much configuration, mostly just installing different
development tools. After setting base configuration with cloud-init, I use &lt;a href=&quot;https://www.chezmoi.io/&quot;&gt;Chezmoi&lt;/a&gt;
to deploy same configurations for dotfiles. You can combine that with podman quadlets configured
in user's home directory to have container services for databases and other services.&lt;/p&gt;&lt;p&gt;Next step is to install Guix package manager on to have isolated Guix shell
environments. I would also like to see Guix image available for incus.&lt;/p&gt;</content></entry><entry><title>Signing and verifying Git commits with SSH keys</title><id>https://korkeala.info/signing-and-verifying-git-commits-with-ssh-keys.html</id><author><name>Markku Korkeala</name><email>markku.korkeala@iki.fi</email></author><updated>2024-06-02T20:30:00Z</updated><link href="https://korkeala.info/signing-and-verifying-git-commits-with-ssh-keys.html" rel="alternate" /><content type="html">&lt;p&gt;SSH commit signing support was added to &lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt; version &lt;a href=&quot;https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/2.34.0.txt&quot;&gt;2.34.0&lt;/a&gt;.
In this post I look at how to sign Git commits with SSH keys, preferably backed
with FIDO2 security keys. There are different opinions whether signing commits is worth the
extra effort. For example just recently &lt;a href=&quot;https://lobi.to&quot;&gt;Harley Watson&lt;/a&gt;
wrote &lt;a href=&quot;https://lobi.to/writes/wacksigning/&quot;&gt;how commit signing is still kinda wack&lt;/a&gt; and
&lt;a href=&quot;https://guix.gnu.org/en/blog/2024/authenticate-your-git-checkouts/&quot;&gt;Ludovic Courtès&lt;/a&gt; wrote on the
importance of signing and verifying commits. This post is about the technical aspects of signing commits.&lt;/p&gt;&lt;h2&gt;TLDR version&lt;/h2&gt;&lt;p&gt;You can sign Git commits with SSH keys:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# git config --local gpg.format ssh
# git config --local user.signingkey ~/.ssh/id_ed25519-sk.pub
# git commit -S&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To verify the Git commit create &lt;a href=&quot;https://man.openbsd.org/ssh-keygen.1#ALLOWED_SIGNERS&quot;&gt;allowed signers&lt;/a&gt;
file and configure your Git repository to use it. Then run &lt;strong&gt;git verify-commit&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# git config --local gpg.ssh.allowedSignersFile ./allowed_signers
# git verify-commit $commitid &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With little bit of scripting you can verify all new commits in a Git branch:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;commits=$(git log --pretty=&amp;quot;%H&amp;quot; main..$branch)
for commit in $commits; do
   git verify-commit $commit 
done&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can use FIDO2 security keys (like &lt;a href=&quot;https://solokeys.com/&quot;&gt;Solokeys&lt;/a&gt;) with OpenSSH. Create a non discoverable SSH key with
key type ed25519-sk or ecdsa-sk:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# ssh-keygen  -t ed25519-sk&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;SSH does not have similar Web of Trust (WoT) as the PGP ecosystem has. This limits
the discoverability and distribution of SSH keys. In an organisation, you can use SSH CA to
sign users SSH keys and make it easier to verify SSH signature and SSH key usage.&lt;/p&gt;&lt;h2&gt;Getting started&lt;/h2&gt;&lt;p&gt;Before you can sign Git commits, you need a SSH key. Probably you
already have one, but if not, you can create one with the following
command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# ssh-keygen  -t ed25519&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you have a FIDO2 security token, you can create SSH key with SSH key pairing.
See some notes about it in the Advanced usage section below.&lt;/p&gt;&lt;h3&gt;Signing commits&lt;/h3&gt;&lt;p&gt;When you have a SSH key, we can configure Git to sign commmits with it.
First configure your local Git repository to sign commits with SSH keys and set
your user.signingkey to the public SSH key. My examples use SSH keytype
ed25519-sk:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# git config --local user.email &amp;lt;you_email@example.com&amp;gt;
# git config --local gpg.format ssh
# git config --local user.signingkey ~/.ssh/id_ed25519-sk.pub&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After that make a Git commit with option &lt;strong&gt;-S&lt;/strong&gt;, which is the option for signing commits.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# git commit -S&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you want to use this configuration in all your Git repositories,
you can make the configuration global by replacing &lt;strong&gt;--local&lt;/strong&gt; with &lt;strong&gt;--global&lt;/strong&gt;.&lt;/p&gt;&lt;h2&gt;Verifying commits&lt;/h2&gt;&lt;p&gt;Verifying a Git commit does two things. First, the actual commit is verified against the cryptographic
signature in the commit to see that the signature is valid. Second, it verifies that the commit signature is made
with an allowed signing key. So now if you verify the commit, it should print something like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# git verify-commit &amp;lt;commitid&amp;gt;
Good &amp;quot;git&amp;quot; signature with ED25519-SK key SHA256:sxZkSe2TJJOKv3dQjadJ05RkCqXWWMB0HkCBU3D+pEM
No principal matched.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the actual signature is valid, but it did not find a principal for it. It means Git does not know which
keys are allowed to sign commits. When you verify Git commits signed with a GPG key, the signing keys
are checked against the GnuPG keyring. The SSH ecosystem does not have similar Web Of Trust (WoT) to
distribute and verify keys. You must define separately the SSH keys which are allowed to sign Git commits.
These are defined in an allowed
signers file. The format is defined in &lt;a href=&quot;https://man.openbsd.org/ssh-keygen.1#ALLOWED_SIGNERS&quot;&gt;manual page for ssh-keygen&lt;/a&gt;.
The file matches email addresses to the public SSH keys for users that are allowed to sign Git commits.
You can also set valid-after and valid-before timestamps for the keys. Example for the
allowed signers file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Comment here
user@example.org sk-ssh-ed25519@openssh.com AAA41...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Create the allowed signers file to the root of your Git repository as &lt;strong&gt;allowed_signers&lt;/strong&gt;,
use your email address, ssh key type and ssh public key in it.
Then configure the Git repository to use it in the root of the Git repository:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# git config --local gpg.ssh.allowedSignersFile ./allowed_signers&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After you have created and configured the allowed signers file you can verify Git commits
with the following command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# git verify-commit fe155257ece409c670c96a11e912538acf2b085d
Good &amp;quot;git&amp;quot; signature for user@example.org with ED25519-SK key SHA256:sxZkSe2TJJOKv3dQjadJ05RkCqXWWMB0HkCBU3D+pE&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Advanced usage&lt;/h2&gt;&lt;p&gt;Now let's look into more advanced usage. These include verifying Git commits in different use cases and
ways to secure the SSH keys.&lt;/p&gt;&lt;h3&gt;SSH keys paired with security keys&lt;/h3&gt;&lt;p&gt;OpenSSH introduced support for SSH-keys backed with security keys &lt;a href=&quot;https://www.openssh.com/txt/release-8.2&quot;&gt;in version 8.2&lt;/a&gt;.
These two new key types are &amp;quot;ecdsa-sk&amp;quot; and &amp;quot;ed25519-sk&amp;quot;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;FIDO/U2F Support
----------------

This release adds support for FIDO/U2F hardware authenticators to
OpenSSH. U2F/FIDO are open standards for inexpensive two-factor
authentication hardware that are widely used for website
authentication.  In OpenSSH FIDO devices are supported by new public
key types &amp;quot;ecdsa-sk&amp;quot; and &amp;quot;ed25519-sk&amp;quot;, along with corresponding
certificate types.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So creating and using using these new key types requires FIDO2 hardware security keys:
when you create a new SSH key it will pair the security key to our SSH key and the hardware
key is required when using the SSH key. It essentially acts as MFA (Multi Factor Authentication)
for your ssh key: if
you have set a password for your ssh key then that is the first factor, something you know. Then
the FIDO2 hardware token acts as a second factor, something you have. The security keys usually are
small tokens, that you plug into USB port or use through bluetooth or NFC. Using the key
requires some action, like pressing a button on the device or giving a PIN-code.&lt;/p&gt;&lt;p&gt;You can generate a security key backed SSH key with normal ssh-keygen flow, plug in the security key, run
&lt;strong&gt;ssh-keygen -t ed25519-sk&lt;/strong&gt; and follow the instructions.&lt;/p&gt;&lt;p&gt;You can also hook GnuPG keys to security keys that have smartcard features, like Yubikeys,
but it requires quite a bit work. I've used &lt;a href=&quot;https://github.com/drduh/YubiKey-Guide&quot;&gt;drduh's yubikey-guide&lt;/a&gt;
in the past and it is a frustrating process.&lt;/p&gt;&lt;p&gt;After you have created the key you can use it like a regular SSH key, but you have to have the
security key plugged in. One caveat is that the new SSH key types will require support
in the SSH-server as well, if you use to SSH connections. So services which use older
OpenSSH versions or some other SSH server software might not support the new key types
(I'm especially looking at you &lt;a href=&quot;https://bitbucket.org/&quot;&gt;Bitbucket&lt;/a&gt;).&lt;/p&gt;&lt;h3&gt;Verifying commits in pull-request flow&lt;/h3&gt;&lt;p&gt;For verifying Git commits from a branch in a pull-request
flow, you can use the approach below. It first fetches the main branch
from the Git origin and loads allowed_signers file from the main branch.
This makes sure that allowed signing keys are not updated in the
pull-request branch, so the signing keys for new committers must first
be added to the main branch before their changes can be accepted.&lt;/p&gt;&lt;p&gt;After loading allowed_signers, script gets commitIDs of new commits that
are not in the main branch and verifies them.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git fetch origin main:main
git show main:allowed_signers &amp;gt; ~/gitsigners
git config --local gpg.ssh.allowedSignersFile ~/gitsigners
commits=$(git log --pretty=&amp;quot;%H&amp;quot; main..$branch)
for commit in $commits; do
   echo &amp;quot;Verifying commit $commit&amp;quot;
   git verify-commit $commit 
done&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If verify-commit fails for any of the commits, it should fail the build.&lt;/p&gt;&lt;h3&gt;Guix git authenticate flow&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://guix.gnu.org&quot;&gt;Guix&lt;/a&gt; takes verifying Git commits further and offers
way to &lt;a href=&quot;https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-git-authenticate.html&quot;&gt;authenticate the whole git tree&lt;/a&gt;
from given Git commit. It also uses a separate file in the repository,
&lt;a href=&quot;https://guix.gnu.org/manual/devel/en/html_node/Specifying-Channel-Authorizations.html#channel_002dauthorizations&quot;&gt;.guix-authorizations&lt;/a&gt;,
which has a list of allowed signing keys for users. The signing key must be added to file in previous
commits before the signing key can be used to sign a commit.
Currently &lt;strong&gt;guix git authenticate&lt;/strong&gt; only supports PGP keys.&lt;/p&gt;&lt;p&gt;Below is a proof of concept of a bash function for similar behaviour.
It iterates through the Git commits from the given commit id and verifies
the commits. It fetches the allowed signers file from the parent commit and configures
the allowed signers file to the Git repository for the verification. Saving
the allowed signers file to a temp directory for the verification is quite
hackish.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;verify_commit() {
    # temp directory where extra files are stored for the verification
    local work_dir=$1
    #commit to start, for example: $(git log --pretty=&amp;quot;%H&amp;quot; | head -n 1 )
    local commitid=$2
    # original signers file: $(git config --get --local gpg.ssh.allowedSignersFile)
    local orig_signers=$3
    local parents=$(git log --pretty=%P -n 1 $commitid)
    if [ -z &amp;quot;$parents&amp;quot; ]; then
        echo &amp;quot;Parent ($parents) empty, we are finished&amp;quot;
        echo &amp;quot;Set back allow signers file to $orig_signers&amp;quot;
        git config --local gpg.ssh.allowedSignersFile $orig_signers
    else
        while IFS= read -r parentid; do
            GITSIGNERS=$(git show $parentid:allowed_signers)
            #echo -e &amp;quot;GIT signers $parentid \n$GITSIGNERS&amp;quot;
            echo &amp;quot;$GITSIGNERS&amp;quot; &amp;gt; $work_dir/$parentid.gitsigners
            git config --local gpg.ssh.allowedSignersFile $work_dir/$parentid.gitsigners
            git verify-commit $commitid
            local ret=$?
            if [ $ret -ne 0 ]; then
               echo &amp;quot;Verification failed for commit $commitid&amp;quot;
               echo &amp;quot;Set back allow signers file to $orig_signers&amp;quot;
               git config --local gpg.ssh.allowedSignersFile $orig_signers
               echo &amp;quot;Removing directory $work_dir&amp;quot;
               rm -r $work_dir
               exit 1
            fi
            verify_commit $work_dir $parentid $signers
        done &amp;lt;&amp;lt;&amp;lt; &amp;quot;$parents&amp;quot;
    fi

}&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;SSH CA support&lt;/h3&gt;&lt;p&gt;The &lt;a href=&quot;https://man.openbsd.org/ssh-keygen.1#ALLOWED_SIGNERS&quot;&gt;allowed signers file&lt;/a&gt;
supports also SSH certificate authority. In an organisation you can have a central
CA which you use to create SSH certificates for users. The CA creates a SSH certificate
by signing the given SSH key with certificate information, such as username identity of the user
and certificate valid times. You can have the following in the allowed signers file to
indicate SSH CA signing key:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Organisations cert-authoriy, public key for for the SSH CA
*@example.org cert-authority ssh-ed25519 AAA...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then if the Git commit principal matches the &amp;quot;*@example.org&amp;quot;, Git tries to verify that the commit
signing certificate is signed by the CA. Here is one article by Step CA about
&lt;a href=&quot;https://smallstep.com/blog/use-ssh-certificates/&quot;&gt;using SSH certificates&lt;/a&gt; in an organisation.
This simplifies the allowed signers file and can be make verification easier in an
organization, but requires setting up the CA for SSH keys.&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;After using GPG keys with Yubikey for couple of years, I've been impressed how easy
Fido2 hardware tokens with SSH keys have been to use. After the SSH key signing support was
added to Git, Git commit signing has been easy. Usually users already
have SSH keys, which makes it easier to start to signing Git commits with SSH keys.
One obstacle is that not all software in the Git ecosystem support SSH keys yet, like
&lt;a href=&quot;https://github.com/libgit2/libgit2/issues/6397&quot;&gt;libgit2&lt;/a&gt;, but slowly different tools have added
support for it. For the commit signing to succeed, better tools are required, not just for the
signing but for the verification of commits as well.&lt;/p&gt;</content></entry><entry><title>Adding DNS based ad blocking to Openwrt</title><id>https://korkeala.info/adding-dns-based-ad-blocking-to-openwrt.html</id><author><name>Markku Korkeala</name><email>markku.korkeala@iki.fi</email></author><updated>2023-05-18T20:00:00Z</updated><link href="https://korkeala.info/adding-dns-based-ad-blocking-to-openwrt.html" rel="alternate" /><content type="html">&lt;p&gt;I consider ads on the Internet a major hindrance. They usually are large
and flashy (especially video ads) and hence distract user from the task
at hand. They have are also being used to track users and even being used
to spread malware. I have used ad blocking on the browser for a long
time, currently I use &lt;a href=&quot;https://ublockorigin.com/&quot;&gt;UBlock Origin&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I became aware of the &lt;a href=&quot;https://pi-hole.net/&quot;&gt;Pi-Hole-project&lt;/a&gt; a few years ago, that seemed
like a good way to have ad blocking for all devices on the local network. It
operates as a DNS-level ad blocker, so every DNS-request to the DNS-server is
blocked if it matches an entry the ad block list. I myself use
&lt;a href=&quot;https://openwrt.org/&quot;&gt;Openwrt&lt;/a&gt; on my routers and noticed it has
adblock packages available that would make it operate like the pi-hole.
OpenWRT has seperate AD-blocking &lt;a href=&quot;https://openwrt.org/docs/guide-user/services/ad-blocking&quot;&gt;guide&lt;/a&gt;
you can use. I installed the following packages:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://openwrt.org/packages/pkgdata/adblock&quot;&gt;adblock&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://openwrt.org/packages/pkgdata/luci-app-adblock&quot;&gt;luci-app-adblock&lt;/a&gt; and &lt;a href=&quot;https://openwrt.org/packages/pkgdata/luci-i18n-adblock-lang&quot;&gt;luci-i18n-adblock-en&lt;/a&gt; (optional, for the LUCI web interface)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In addition to the adblock package, you will need SSL-support to fetch block lists over HTTPS.
I have the following packages installed:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;libustream-wolfssl20201210&lt;/li&gt;&lt;li&gt;libwolfssl5.5.4.ee39414e&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;After installing packages you can update the blocklist sources configuration, quite a few different
sources are supported. Just be aware, including many big blocklist sources might slow the router down.&lt;/p&gt;&lt;p&gt;You will also want refresh the list from time to time. The adblock package refreshes the list on startup,
so you can add crontab file to reload the adblock service. Like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;0 06 * * *    /etc/init.d/adblock reload&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I have been running the setup for few years and I am happy with it.&lt;/p&gt;</content></entry><entry><title>Linux on HP Dragonfly Elitebook G3</title><id>https://korkeala.info/linux-on-hp-dragonfly-elitebook-g3.html</id><author><name>Markku Korkeala</name><email>markku.korkeala@iki.fi</email></author><updated>2023-01-08T20:00:00Z</updated><link href="https://korkeala.info/linux-on-hp-dragonfly-elitebook-g3.html" rel="alternate" /><content type="html">&lt;p&gt;I recently got myself a new laptop, &lt;a href=&quot;https://www.hp.com/us-en/shop/pdp/hp-elitebook-dragonfly-g3-notebook-pc-customizable-4j032av-mb&quot;&gt;HP Dragonfly Elitebook Max G3&lt;/a&gt;.
Here are some impressions of the laptop and few thoughts about the Linux support for it.&lt;/p&gt;&lt;h2&gt;TLDR version&lt;/h2&gt;&lt;p&gt;For the busy people, here is the short summary: Linux support is good for the laptop, it is powerful
enough for my development work and light, hence very portable. I had few issues with it, mainly
getting the suspend to ram/resume to work, but otherwise I can
recommend it. For longer description and issues I had with it, please read on.&lt;/p&gt;&lt;h2&gt;Previous laptop&lt;/h2&gt;&lt;p&gt;I do not upgrade laptops very often. My previous main laptop was over 3 years old,
it was a Lenovo T480s. It started showing signs of failure, so before it would fail
completely I decided to get a new one. I wanted a powerful, lightweight
and easily portable laptop. Due to the COVID supply chain issues there were not many
options available when I was browsing the local retailers. I was interested
in &lt;a href=&quot;https://frame.work&quot;&gt;Framework laptops&lt;/a&gt;, but at the time they did not deliver
to my country. Previously I had been using Lenovo laptops and had been quite satisfied
with them. Their Linux support has been getting better with programs like the
&lt;a href=&quot;https://fedoramagazine.org/lenovo-fedora-now-available/&quot;&gt;preinstalled Linux on Lenovo&lt;/a&gt;.
But then again they have a history of putting questionable software on their
computers (see for example
&lt;a href=&quot;https://arstechnica.com/information-technology/2022/04/bugs-in-100-lenovo-models-fixed-to-prevent-unremovable-infections/&quot;&gt;arstechnica article&lt;/a&gt;)
or just search lenovo malware. So this time I decided to try other manufactor. With
not many options, I decided on the &lt;a href=&quot;https://www.hp.com/us-en/shop/pdp/hp-elitebook-dragonfly-g3-notebook-pc-customizable-4j032av-mb&quot;&gt;HP Dragonfly Elitebook Max G3&lt;/a&gt;.&lt;/p&gt;&lt;h2&gt;Hardware and Linux support&lt;/h2&gt;&lt;p&gt;The hardware is quite nice, 32 gigs of RAM, touchscreen and pen support (pen included),
13 inch screen, videocam + shutter to hide the camera and enough CPU power for my
development work. The laptop weights about 1kg, so very portable and easy to travel with.&lt;/p&gt;&lt;p&gt;I first installed Fedora 36 KDE Spin on the machine. I am a long time Gnome user, but I
recently wanted to see how well KDE performs. Installation itself was a breeze, like
it has been for years with Fedora and most things worked out of the box, like pen support,
wifi and
graphics. But two things did not work: the touchscreen and suspend/resume. As I searched
the touchscreen issue it seemed that KDE does not yet support touchscreens,
altough the pen worked fine. So I installed Gnome and switched back to the Gnome desktop environment,
which supports touchscreen and pen input.&lt;/p&gt;&lt;p&gt;The suspend to RAM issue was a little bit trickier. I use the functionality a lot, so it was
important to find a solution. After searching around and I eventually found a blog post about a similar issue
on a another HP laptop:
&lt;a href=&quot;https://blog.frehi.be/2022/05/07/debian-gnulinux-on-a-hp-elitebook-845-g8/&quot;&gt;Frederik Himpe's blog post&lt;/a&gt;.
It seems to require a firmware update. The Fedora already has fwupd installed by default so running:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# fwupdtool update&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;updated the firmware. After reboot the issue was fixed and suspending to RAM worked. Though sometimes returning from
suspension, the clock was wrong, it was 2 hours ahead (computer itself is in UTC time and my timezone is UTC + 2,
so something related to it). Restarting the &lt;a href=&quot;https://en.wikipedia.org/wiki/Network_Time_Protocol&quot;&gt;NTP-service&lt;/a&gt;
corrected the time. There were also some strange sound issues, sometimes after resuming sound had periodic
glitches and one could not enjoy listening to music or watching videos. I tried to restart pipewire for no gain,
but then noticed the clock was always off in those times. Restarting the NTP-service fixed this issue as well.&lt;/p&gt;&lt;p&gt;After that I tested the rest of the hardware as well and everything seemed to work well: WIFI, graphics,
fingerprint reader, webcam and bluetooth. Also the automatic screen rotation works when rotating the screen
and putting the laptop to stand up position.&lt;/p&gt;&lt;h2&gt;Daily usage&lt;/h2&gt;&lt;p&gt;So after getting everything working, this laptop has performed very well and I have been very happy
with it. The keyboard is okey, I mostly use external mechanical keyboards, but the laptop's keyboard is good enough
for typing a full day with it. The battery has been good enough for my usage. The laptop's portability is good. The only thing I miss
from the Lenovo laptops is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Pointing_stick&quot;&gt;trackpoint&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I have noticed that I have not used much the tablet mode, meaning using the laptop with touchscreen and pen.
I will try to explore it more thoroughly and write a separate post about it. The
few times I have tested it, it has worked smoothly and Gnome has a good support for touchscreen and pen usage.&lt;/p&gt;</content></entry></feed>