# jan-piet mens

Published articles for jan-piet mens.

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## Root DNSSEC trust anchors

DevFeed: [Root DNSSEC trust anchors](<https://devfeed.tech/articles/root-dnssec-trust-anchors-87242.md>)

Original publisher: [Read original article](<https://jpmens.net/2026/10/14/root-dnssec-trust-anchors/>)

Author: Jan-Piet Mens

Published: 2026-10-13T22:00:00Z

Content type: article

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [DNSSEC](<https://devfeed.tech/topics/dnssec.md>), [DNS security](<https://devfeed.tech/topics/dns-security.md>), [Domain Name System (DNS)](<https://devfeed.tech/topics/dns-resolution-process.md>), [powerdns](<https://devfeed.tech/topics/powerdns.md>)

Tags: [dns](<https://devfeed.tech/tags/dns.md>), [dnssec](<https://devfeed.tech/tags/dnssec.md>), [infrastructure](<https://devfeed.tech/tags/infrastructure.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [ksk](<https://devfeed.tech/tags/ksk.md>), [root-zone](<https://devfeed.tech/tags/root-zone.md>), [server](<https://devfeed.tech/tags/server.md>), [trust](<https://devfeed.tech/tags/trust.md>)

### AI overview

This article explains how DNSSEC trust anchors support validation from the signed DNS root through recursive resolvers. It walks through the recent root Key Signing Key rollover, ways to verify and configure the current trust anchor, and how an outdated trust anchor in Gematik connectors is implicated in an ongoing infrastructure failure.

### Source excerpt

The root DNSSEC trust anchor, the Key Signing Key or KSK as it's called, was rolled, i.e. renewed, on Sunday 2026-10-11. To be precise the key was created two years ago, but it is now used for signing the root DNSKEY resource record set (RRset). I'm not involved in the process, but I am an avid follower, and as such I tooted before the event and after: The second screen shot shows an arrow pointing at 38696 which is the key tag (or key id) of this new key, and dig(1) is showing how it was used to sign the set of DNSKEY resource records. During a discussion on Tuesday which began because of a quite disastrous and currently ongoing failure in the German medical IT infrastructure of Gematik, it turns out that some people I thought would know all about this don't, so I'll jot down some notes about how I think it ties in together. Let's begin with trust anchor; what is that? DNSSEC validation is performed by a recursive resolver which obtains cryptographically signed answers to queries. These signatures, created by the the authoritative DNS server responsible for the data, need to be verified, and the verification process needs a form of trust. Just like you trust the content your favorite Web site offers you because you trust your Web browser and it trusts that site, we need a similar chain of trust for the DNS. So resolvers need to begin their chain of trust somewhere, but how should they do that? The need to trust the signed DNS root zone, and from thereon down to the name of your favorite Web site (e.g. www.example.com). (Many moons ago I created a diagram to depict the DNSSEC chain of trust.) The current root signing key, the Key Signing Key code-named KSK-2024, was actually generated in April of 2024 during what is known as a key ceremony, and you can watch the video of how that happens at the Root KSK Ceremony 53. It's quite interesting to watch, but let me say you won't need popcorn: it's a long and tedious thing, but it's interesting nevertheless to scroll throu

## Yet another password manager: pass with Pass for iOS

DevFeed: [Yet another password manager: pass with Pass for iOS](<https://devfeed.tech/articles/yet-another-password-manager-pass-with-pass-for-ios-41909.md>)

Original publisher: [Read original article](<https://jpmens.net/2026/08/11/yet-another-password-manager/>)

Author: Jan-Piet Mens

Published: 2026-08-10T22:00:00Z

Content type: opinion

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [pass](<https://devfeed.tech/topics/password-store.md>), [passwords](<https://devfeed.tech/topics/passwords.md>), [iOS](<https://devfeed.tech/topics/ios.md>), [Command-line interface](<https://devfeed.tech/topics/cli.md>), [Ansible](<https://devfeed.tech/topics/ansible.md>), [Git](<https://devfeed.tech/topics/git.md>), [forgejo](<https://devfeed.tech/topics/forgejo.md>)

Tags: [ansible](<https://devfeed.tech/tags/ansible.md>), [forgejo](<https://devfeed.tech/tags/forgejo.md>), [git](<https://devfeed.tech/tags/git.md>), [ios](<https://devfeed.tech/tags/ios.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [pass](<https://devfeed.tech/tags/pass.md>), [password](<https://devfeed.tech/tags/password.md>), [password-manager](<https://devfeed.tech/tags/password-manager.md>), [terminal](<https://devfeed.tech/tags/terminal.md>)

### AI overview

A personal review of pass, the standard Unix password manager, and Pass for iOS. The article describes pass's GPG-encrypted file-based store, optional Git-based synchronization, terminal workflow, and relevance to Ansible password lookups.

### Source excerpt

I remember the good times, when I had a single password for all (the two?) services I used. Then came a phase of managing passwords on sticky notes stuck below the keyboard (much more secure than stuck to the monitor!), until I migrated to one of the first note-taking apps and had passwords written in clear like on the sticky notes but copy/pasteable. Those were the days! Then came the first "real" password manager which for me was 1Password. It worked, I synced with a local store (i.e. sans Internet) until the company decided to convert my "paid for life" (which never exists) into a subscription model. I spent days thinking and rethinking and settled for Enpass which I've used since on macOS and iOS. It's okay, and does what I want from it, but its enshitification is in progress. There are others, lots of others, and I looked closely at KeePassXC, but can't seem to make the jump. One of the password managers I kept an eye upon for a while was pass, a.k.a. passwordstore. It must have been a dozen years ago that I fell for the cool little tool which lives in my terminal, but as there wasn't an iOS pendant, I kept pushing it aside. Interestingly, for years now, I've mentioned it in my Ansible trainings when I very briefly explain the passwordstore lookup plugin when going through a short list of lookups. Moving forward, I stumbled across a program which piqued my interest yesterday: Pass for iOS, and decided to take a closer look to see whether the combination of that plus pass might tickle me again. pass the standard unix password manager pass calls itself the standard unix password manager, and with that it is in line with ed, the standard unix text editor. Both have no frills and no AI. In pass individual passwords live in gpg-encrypted files whose name is the title of the site or resource the password is for. These files can be organized into hierarchies, for instance: $ pass Password Store ├── ansible │ └── vaultsecret ├── jpmens │ └── org │ └── repo └── testing

## Automating Conversion of reveal.js Slides to PDF

DevFeed: [Automating Conversion of reveal.js Slides to PDF](<https://devfeed.tech/articles/rediscovering-converting-reveal-js-slides-to-pdf-41908.md>)

Original publisher: [Read original article](<https://jpmens.net/2026/07/11/rediscovering-reveal-js-to-pdf/>)

Author: Jan-Piet Mens

Published: 2026-07-10T22:00:00Z

Content type: article

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [Automation](<https://devfeed.tech/topics/automation.md>), [Emacs](<https://devfeed.tech/topics/emacs.md>), [Org mode](<https://devfeed.tech/topics/orgmode.md>), [HTML](<https://devfeed.tech/topics/html.md>), [make](<https://devfeed.tech/topics/make.md>), [browser](<https://devfeed.tech/topics/browser.md>), [Command-line interface](<https://devfeed.tech/topics/cli.md>), [Google Chrome](<https://devfeed.tech/topics/google-chrome.md>), [Docker](<https://devfeed.tech/topics/docker.md>), [npm](<https://devfeed.tech/topics/npm.md>), [Script](<https://devfeed.tech/topics/script.md>), [Server](<https://devfeed.tech/topics/server.md>)

Tags: [automation](<https://devfeed.tech/tags/automation.md>), [browser](<https://devfeed.tech/tags/browser.md>), [chrome](<https://devfeed.tech/tags/chrome.md>), [command-line](<https://devfeed.tech/tags/command-line.md>), [docker](<https://devfeed.tech/tags/docker.md>), [emacs](<https://devfeed.tech/tags/emacs.md>), [html](<https://devfeed.tech/tags/html.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [make](<https://devfeed.tech/tags/make.md>), [npm](<https://devfeed.tech/tags/npm.md>), [script](<https://devfeed.tech/tags/script.md>)

### AI overview

The author describes using Emacs Org-mode and reveal.js to create training slide decks, then automating their conversion from HTML to PDF with decktape. They compare Docker-based and local installations, noting differences in Chrome and font rendering, and use a small shell script to run an HTTP server, invoke decktape, and clean up the process.

### Source excerpt

A few years ago I began using Emacs Org-mode and reveal.js to generate slide decks I use in trainings, and I've been pleased with the results. (I believe it was Carsten who got me hooked.) It took me a bit to get the settings just the way I wanted to have them, but since then it's been a matter of typing make in a command line to generate the HTML from the .org file using this in my Makefile, and the resulting *.html is what I open in a browser for display. presentation.html: presentation.org emacs -u jpm \ --batch presentation.org \ --eval '(load user-init-file)' \ -f org-reveal-export-to-html For printing and handouts I want a PDF, but that's always required a bit of manual work to convert the HTML to PDF, because the tools I tried back then didn't produce the result I could get manually by opening in a Chrome browser with a ?print-pdf attached the the URL and then a judicious print-to-PDF and save. My idea was to automate that, and I was prompted a few days ago to revisit decktape. I shy away from installing NPM stuff because like Maven, Rust, and whatnot, they typically make me download half an internet, so I began by using the docker image as described at decktape. However I disliked the fonts and the overall impression of the generated PDF. "Disliked" is possibly unfair, but it just looked different... It dawned on me then, obviously, that the docker image was running some incantation of Chrome on Linux, whereas I'm used to Chrome on Mac and its fonts, etc., so I then did actually install decktape locally with the resulting PDF looking exactly like what I was used to! I've now got "automation" to (mostly) get the PDF output the way I wish to have it with a small script I've named runoff.sh (yes, the name is intentional :-) #!/bin/sh set -e python3 -m http.server --bind 127.0.0.1 8108 & httpid=$! trap "{ echo Killing http.server on $httpid; kill $httpid; exit 0; }" 0 1 2 15 echo PID=$httpid npm exec decktape -- \ --size 998x780 \ --pdf-author "Jan-Piet Mens" \ --

## A wiki from a single Go binary: LeoMoon Wiki-Go

DevFeed: [A wiki from a single Go binary: LeoMoon Wiki-Go](<https://devfeed.tech/articles/a-wiki-from-a-single-go-binary-leomoon-wiki-go-41907.md>)

Original publisher: [Read original article](<https://jpmens.net/2026/05/05/a-wiki-from-a-single-go-binary-leomoon-wiki-go/>)

Author: Jan-Piet Mens

Published: 2026-05-04T22:00:00Z

Content type: article

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [Wiki](<https://devfeed.tech/topics/wiki.md>), [Go Language](<https://devfeed.tech/topics/go-language.md>), [Filesystems](<https://devfeed.tech/topics/filesystems.md>), [Markdown](<https://devfeed.tech/topics/markdown.md>), [Docker](<https://devfeed.tech/topics/docker.md>), [REST API](<https://devfeed.tech/topics/rest-api.md>), [Kanban](<https://devfeed.tech/topics/kanban.md>), [YAML](<https://devfeed.tech/topics/yaml.md>), [Open Source](<https://devfeed.tech/topics/open-source.md>)

Tags: [docker](<https://devfeed.tech/tags/docker.md>), [file-system](<https://devfeed.tech/tags/file-system.md>), [go](<https://devfeed.tech/tags/go.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [kanban](<https://devfeed.tech/tags/kanban.md>), [markdown](<https://devfeed.tech/tags/markdown.md>), [open-source](<https://devfeed.tech/tags/open-source.md>), [rest-api](<https://devfeed.tech/tags/rest-api.md>), [wiki](<https://devfeed.tech/tags/wiki.md>), [yaml](<https://devfeed.tech/tags/yaml.md>)

### AI overview

This article reviews LeoMoon Wiki-Go, an open-source wiki platform delivered as a single Go binary or Docker image. It stores wiki pages, Kanban boards, and link-management pages as Markdown files in a flat-file directory, with a REST API, web-based settings, user roles, and YAML configuration.

### Source excerpt

LeoMoon Wiki-Go calls itself a modern, feature-rich, databaseless, flat-file wiki platform built with Go, and it is all that. Wiki-Go is a single-binary Go program, but there is a docker image for those who want it. I download the binary for my platform and launch it; this creates a data/ directory and its configuration file. If need be I configure a port number for it plus a timezone and the odd other setting and relaunch the binary. The program has all the features I need and more, and what I most appreciate is that I can simply drop Markdown files, images, videos, etc. into a directory to have Wiki-Go serve them. I can also move documents to other pages, so for instance, when I've finished working on the Cascade page, I'll move it into DNS/. The program also boasts an interactive Markdown editor which certainly fulfills all I expect of one, including being able to format text, add links, insert images, etc. In addition to wiki pages, the program supports the creation of Kanban boards and Link management pages, all of which are stored in *.md Markdown files. There is a REST API with examples, which might be interesting to programmatically add comments, say, but if I have access to the server, I copy files into their directories. There's a web-based settings dialog where I can add users and configure roles, but I can also add these to the YAML configuration file manually: users: - username: admin password: $2a$14$V0SkqSKvFPmJMICFqrW6qO9ufQh0befHwHE7uuJZdudK1DcGgPlY. role: admin - username: jp password: $2a$10$KdlXhhVpMiP1QPkggskUQOp4LBZ2JaSADm2ccfyl8JalN10dqmR7W role: viewer groups: - dns - tech This is really a lovely piece of work, and it is open source, and IMO its major features: Markdown in flat files on the file system, which makes it easy for me to synchronize the data directory onto my laptop and use a separate instance of Wiki-Go on that.

## Deploying SSH host keys and certificates with Ansible

DevFeed: [Deploying SSH host keys and certificates with Ansible](<https://devfeed.tech/articles/deploying-ssh-host-keys-and-certificates-with-ansible-41906.md>)

Original publisher: [Read original article](<https://jpmens.net/2026/04/07/deploying-ssh-host-keys-and-certificates-with-ansible/>)

Author: Jan-Piet Mens

Published: 2026-04-06T22:00:00Z

Content type: tutorial

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [Ansible](<https://devfeed.tech/topics/ansible.md>), [OpenSSH](<https://devfeed.tech/topics/openssh.md>), [Deployment](<https://devfeed.tech/topics/deployment.md>), [private key](<https://devfeed.tech/topics/private-key.md>), [public key](<https://devfeed.tech/topics/public-key.md>), [passwords](<https://devfeed.tech/topics/passwords.md>)

Tags: [ansible](<https://devfeed.tech/tags/ansible.md>), [certificates](<https://devfeed.tech/tags/certificates.md>), [configuration](<https://devfeed.tech/tags/configuration.md>), [deploy](<https://devfeed.tech/tags/deploy.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [openssh](<https://devfeed.tech/tags/openssh.md>), [private-key](<https://devfeed.tech/tags/private-key.md>), [public-key](<https://devfeed.tech/tags/public-key.md>)

### AI overview

A practical Ansible playbook deploys SSH host keys and certificates to nodes. It generates host key pairs on each node, delegates local temporary-file handling and certificate signing to the Ansible controller, and uses an SSH agent-held CA key.

### Source excerpt

If all you have is a hammer ... It occurs to me that we can deploy SSH host keys and their certificates to nodes using Ansible, as it has two existing modules we can use for the task: community.crypto.openssh_keypair generates OpenSSH private public key pairs community.crypto.openssh_cert generates OpenSSH user or host certificates Assuming we want a host's private key to be generated on a node and reside on the node only, and assuming our SSH CA (certification authority) is on the Ansible controller, we can use delegation to localhost for the bits which should happen on the controller. In the following simple playbook I use a block in which I create a temporary unique directory locally into which the public key from the host is copied and signed, and the always portion of the block ensures the directory is cleared out even on error within the block. The public portion of the SSH key pair is returned in openssh_keypair's metadata. - hosts: d13 gather_facts: yes remote_user: jp vars: dirname: "/etc/ssh" tasks: - name: Generate ED25519 SSH host key on node community.crypto.openssh_keypair: backend: "opensshbin" path: "{{ dirname }}/ssh_host_ed25519_key" comment: "ansible-made™ for host {{ inventory_hostname }}" type: "ed25519" become: true register: keydata - debug: var=keydata - block: - name: Create a local temporary directory ansible.builtin.tempfile: prefix: "jp" suffix: "cert" state: directory register: p delegate_to: localhost - name: Save public host key to local temporary file ansible.builtin.copy: content: "{{ keydata.public_key }}" dest: "{{ p.path }}/{{ keydata.filename | basename }}" delegate_to: localhost - name: Sign SSH certificate on local copy of public host key community.crypto.openssh_cert: identifier: "{{ inventory_hostname }}" public_key: "{{ p.path }}/{{ keydata.filename | basename }}" principals: "{{ [ ansible_fqdn ] + ansible_all_ipv4_addresses }}" path: "{{ p.path }}/{{ keydata.filename | basename }}-cert.pub" serial_number: 10 signing_key: "../

## SSH certificates: the better SSH experience

DevFeed: [SSH certificates: the better SSH experience](<https://devfeed.tech/articles/ssh-certificates-the-better-ssh-experience-41905.md>)

Original publisher: [Read original article](<https://jpmens.net/2026/04/03/ssh-certificates-the-better-ssh-experience/>)

Author: Jan-Piet Mens

Published: 2026-04-02T22:00:00Z

Content type: tutorial

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [OpenSSH](<https://devfeed.tech/topics/openssh.md>), [ssh](<https://devfeed.tech/topics/ssh.md>), [private key](<https://devfeed.tech/topics/private-key.md>), [public key](<https://devfeed.tech/topics/public-key.md>), [trust](<https://devfeed.tech/topics/trust.md>), [passwords](<https://devfeed.tech/topics/passwords.md>), [Server](<https://devfeed.tech/topics/server.md>), [Shell](<https://devfeed.tech/topics/shell.md>), [ed25519](<https://devfeed.tech/topics/ed25519.md>), [sha256](<https://devfeed.tech/topics/sha256.md>)

Tags: [ed25519](<https://devfeed.tech/tags/ed25519.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [password](<https://devfeed.tech/tags/password.md>), [private-key](<https://devfeed.tech/tags/private-key.md>), [public-key](<https://devfeed.tech/tags/public-key.md>), [server](<https://devfeed.tech/tags/server.md>), [sha256](<https://devfeed.tech/tags/sha256.md>), [shell](<https://devfeed.tech/tags/shell.md>), [ssh](<https://devfeed.tech/tags/ssh.md>), [trust](<https://devfeed.tech/tags/trust.md>)

### AI overview

A practical explanation of SSH host verification and key-based authentication. It covers checking host fingerprints, Trust on First Use, SSH key pairs, passphrases, and using an SSH agent to avoid repeated passphrase entry.

### Source excerpt

When I ssh into a server for the first time, I'm confronted with a dialog which asks me to verify I'm actually talking to the machine I expect to be talking to. $ ssh -l jp 192.0.2.65 The authenticity of host '192.0.2.65 (192.0.2.65)' can't be established. ED25519 key fingerprint is SHA256:4WTRnq2OR1m03TpnHCfkFdlh1gN/PBXE4vDi0WnjFEc. No matching host key fingerprint found in DNS. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? It is likely that the majority of users cross their fingers and type 'yes', which is not really a clever response. This Trust on First Use (TOFU) is what permits SSH to ensure that my SSH client verifies which server it's talking to. I ought to have asked the administrator of the server to tell me its fingerprint, and if I am the administrator I ought to know how to do this: (in the following examples, a shell prompt % indicates I'm working as `root) % ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key 256 SHA256:4WTRnq2OR1m03TpnHCfkFdlh1gN/PBXE4vDi0WnjFEc root@d13 (ED25519) If the two fingerprints compare equal, I can trust that I am connecting to the correct server and can continue with 'yes' or I paste a known host fingerprint into the prompt: trust on first use is accomplished. (Utilities such as ssh-keyscan gather public keys from remote hosts, but I still ought to verify out-of-band whether I'm talking to the correct machine. SSH fingerprints can also be in the DNS, what can't?, but that's a different story.) The session then possibly continues with me being asked for the target user's password which, if entered correctly, grants me access to the machine. SSH key pairs If I create an SSH key pair, install my public key in the correct location (typically $HOME/.ssh/authorized_keys on the target node), and present the private key upon connection, then I don't need to type the target user's password; instead I enter the key's passphrase, a hopefully much more complicated combination

## Providing zone transfers directly from Netbox DNS

DevFeed: [Providing zone transfers directly from Netbox DNS](<https://devfeed.tech/articles/providing-zone-transfers-directly-from-netbox-dns-41904.md>)

Original publisher: [Read original article](<https://jpmens.net/2026/01/23/providing-zone-transfers-directly-from-netbox-dns/>)

Author: Jan-Piet Mens

Published: 2026-01-22T23:00:00Z

Content type: tutorial

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [NetBox](<https://devfeed.tech/topics/netbox.md>), [NetBox Plugin](<https://devfeed.tech/topics/netbox-plugin.md>), [Server](<https://devfeed.tech/topics/server.md>), [Provisioning](<https://devfeed.tech/topics/provisioning.md>)

Tags: [catalog](<https://devfeed.tech/tags/catalog.md>), [hmac](<https://devfeed.tech/tags/hmac.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [netbox](<https://devfeed.tech/tags/netbox.md>), [plugin](<https://devfeed.tech/tags/plugin.md>), [powerdns](<https://devfeed.tech/tags/powerdns.md>), [rfc](<https://devfeed.tech/tags/rfc.md>), [sha256](<https://devfeed.tech/tags/sha256.md>), [tcp](<https://devfeed.tech/tags/tcp.md>)

### AI overview

This technical walkthrough describes netbox-plugin-dns-bridge, a NetBox plugin that provides a small DNS server for AXFR zone transfers. It also explains configuring TSIG keys and using Catalog Zones to provision DNS servers from NetBox.

### Source excerpt

When I first wrote about discovering Netbox DNS I mentioned that the combination of Netbox and the DNS plugin don't actually create a DNS server and zone transfers directly from Netbox are thus impossible. I also went on to describe how there exist programs which can export the data into, say, zone master files for further provisioning DNS servers, but the times, they are changing. Sven Luethi has created a bridge between Peter Eckel's netbox-plugin-dns, the NetBox plugin for managing DNS data, and the DNS. It is called netbox-plugin-dns-bridge (previously netbox-plugin-bind-provisioner) and implements a small DNS server within Netbox which provides for zone transfers (AXFR) in order for compliant clients to transfer whole zones. (Naming things is hard in IT, as we sometimes jokingly say, and I'd like to specifically point out that this is not just for a BIND name server - any compliant name server can transfer zones from netbox-plugin-dns-bridge.) Setting this up is quite straightforward, and is well described in the README. I generate a TSIG key which I configure into the plugin. PLUGINS = [ "netbox_dns", "netbox_dns_bridge", "netbox_dhcp" ] PLUGINS_CONFIG = { ..., "netbox_dns_bridge": { "tsig_keys": { "external": { "keyname": "pext", "algorithm": "hmac-sha256", "secret": "kjMj2tWFtBVn56xvhjxcJRoGjDRgHB5fdAkJRb9Imlg=" } } } } What this does is to configure the provisioner to provide transfers for zones in the "external" view when a transfer is requested with the specified TSIG key. I can configure any number of views as long as I use distinct TSIG keys for each; this is the only way the mini DNS server can determine from which view it should serve a zone (or zones). After restarting Netbox I test a zone transfer using dig(1). The TCP port of the mini DNS server is configurable, but I've used the default here. (Note also how the port is specified in the example named.conf stanza below.) I specify the filename containing the TSIG key, the IP address of the mini DNS

## Ansible lookup plugin for generating TSIG keys

DevFeed: [Ansible lookup plugin for generating TSIG keys](<https://devfeed.tech/articles/ansible-lookup-plugin-for-generating-tsig-keys-41902.md>)

Original publisher: [Read original article](<https://jpmens.net/2026/01/02/ansible-lookup-plugin-for-tsig-keys/>)

Author: Jan-Piet Mens

Published: 2026-01-01T23:00:00Z

Content type: tutorial

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [Ansible](<https://devfeed.tech/topics/ansible.md>), [Server](<https://devfeed.tech/topics/server.md>), [sha256](<https://devfeed.tech/topics/sha256.md>)

Tags: [ansible](<https://devfeed.tech/tags/ansible.md>), [debug](<https://devfeed.tech/tags/debug.md>), [dns](<https://devfeed.tech/tags/dns.md>), [file](<https://devfeed.tech/tags/file.md>), [idempotency](<https://devfeed.tech/tags/idempotency.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [plugin](<https://devfeed.tech/tags/plugin.md>), [secret](<https://devfeed.tech/tags/secret.md>), [server](<https://devfeed.tech/tags/server.md>), [sha256](<https://devfeed.tech/tags/sha256.md>)

### AI overview

This tutorial presents an Ansible lookup plugin that generates BIND-compatible TSIG key files and returns their components as a dictionary. It addresses lazy lookup evaluation, demonstrates idempotent use in a playbook, and verifies compatibility with BIND-generated keys.

### Source excerpt

I need to generate TSIG key files for a DNS server using Ansible, and while I could use something like the community.general.random_string lookup, due to Ansible's lazy evaluation of lookups, using that in a vars would cause the lookup to be re-evaluated upon use meaning I cannot actually use it more than once in a playbook. So I create a lookup plugin which generates BIND-compatible TSIG key files and returns their individual components as a dict. To verify the key files are compatible, I generate a TSIG key using BIND's utility: $ tsig-keygen blog-demo > bind.key $ cat bind.key key "blog-demo" { algorithm hmac-sha256; secret "/akt2yQEYmZ1L+yao06mkRuS31m4/Dn994KMDq6PtHE="; }; The short playbook will demo the idempotency of the lookup: - hosts: localhost gather_facts: false vars: tk: "{{ lookup('tsig_key', 'tsig.f2', tsig_name='example-net') }}" tasks: - debug: msg="{{ lookup('tsig_key', 'bind.key') }}" - debug: msg="{{ tk }}" $ ansible-playbook gen-key.yml PLAY [localhost] *************************************************************************** TASK [debug] ******************************************************************************* ok: [localhost] => { "msg": { "tsig_algo": "hmac-sha256", "tsig_file": "bind.key", "tsig_name": "blog-demo", "tsig_secret": "/akt2yQEYmZ1L+yao06mkRuS31m4/Dn994KMDq6PtHE=" } } TASK [debug] ******************************************************************************* ok: [localhost] => { "msg": { "tsig_algo": "hmac-sha256", "tsig_file": "tsig.f2", "tsig_name": "example-net", "tsig_secret": "OV/xk8C2JeqZBcdMeS/BUFKscdDFDkipGiFy6bGuc24=" } } $ cat tsig.f2 # hmac-sha256:example-net:OV/xk8C2JeqZBcdMeS/BUFKscdDFDkipGiFy6bGuc24= key "example-net" { algorithm hmac-sha256; secret "OV/xk8C2JeqZBcdMeS/BUFKscdDFDkipGiFy6bGuc24="; }; The files generated by the tsig_key lookup include a comment in the key file containing colon-separated algorithm, key name, and key secret, in case I ever want to automatically extract that and use in dig(1)'s -

## Notes to self: Semaphore-UI secrets

DevFeed: [Notes to self: Semaphore-UI secrets](<https://devfeed.tech/articles/notes-to-self-semaphore-ui-secrets-41901.md>)

Original publisher: [Read original article](<https://jpmens.net/2025/10/28/notes-to-self-semaphore-ui-secrets/>)

Author: Jan-Piet Mens

Published: 2025-10-27T23:00:00Z

Content type: article

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [Encryption](<https://devfeed.tech/topics/encryption.md>), [Cryptography](<https://devfeed.tech/topics/cryptography.md>), [SQLite](<https://devfeed.tech/topics/sqlite.md>), [ssh](<https://devfeed.tech/topics/ssh.md>), [data](<https://devfeed.tech/topics/data.md>), [private key](<https://devfeed.tech/topics/private-key.md>), [openssl](<https://devfeed.tech/topics/openssl.md>), [Code](<https://devfeed.tech/topics/code.md>), [ed25519](<https://devfeed.tech/topics/ed25519.md>), [software-development](<https://devfeed.tech/topics/software-development.md>)

Tags: [code](<https://devfeed.tech/tags/code.md>), [database](<https://devfeed.tech/tags/database.md>), [ed25519](<https://devfeed.tech/tags/ed25519.md>), [encryption](<https://devfeed.tech/tags/encryption.md>), [environment-variables](<https://devfeed.tech/tags/environment-variables.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [openssl](<https://devfeed.tech/tags/openssl.md>), [private-key](<https://devfeed.tech/tags/private-key.md>), [secrets](<https://devfeed.tech/tags/secrets.md>), [sql](<https://devfeed.tech/tags/sql.md>), [ssh](<https://devfeed.tech/tags/ssh.md>)

### AI overview

The article examines how Semaphore UI stores configured secrets, including variable-group secrets, SSH keys, and login credentials. It describes AES encryption at rest in the database, identifies the nonce placement and authenticated-encryption limitation of openssl enc, and adapts Semaphore UI source code to decrypt the stored values.

### Source excerpt

I've been looking a bit more closely at Semaphore UI and was curious how secrets I can configure for it are stored. There are two distinct kinds of secrets as far as I've been able to ascertain, and they're in either variable groups or in one or more key stores (one key store for the CE edition, more than one for the Pro). I create three such secret values, using the UI: a secret in a variable group; secret environment variables in a variable group are also encrypted and work like "normal" secret variables: an SSH key in a key store into which I paste the SSH key's passphrase and the private key, generated with ssh-keygen -C DemoKey -t ed25519 -f sema1: a login/password combination a playbook can, say, use to login to "something": These values are then encrypted at rest with AES into the database, which is what the documentation states, and an SQL select confirms base64-encoded data in the secret column (id 1 was placed there by the setup routine): sqlite> SELECT id, name, type, SUBSTR(secret, 1, 25) AS secret FROM access_key; ┌────┬──────────────┬────────────────┬───────────────────────────┐ │ id │ name │ type │ secret │ ├────┼──────────────┼────────────────┼───────────────────────────┤ │ 1 │ None │ none │ │ │ 2 │ mug │ string │ cIRZIUUaFCxajOak6I51agLyq │ │ 3 │ dev-hosts │ ssh │ EzLAwD/CB7y23x/XABElWrF9g │ │ 4 │ router-creds │ login_password │ 6in0q49PmW1XrhQ33wTEO/GuG │ └────┴──────────────┴────────────────┴───────────────────────────┘ I spend a futile 20 minutes trying to decrypt the binary data (i.e. after base64 decoding) using openssl enc -d, futile because I only find out later that the nonce is actually in the first 12 bytes of the encrypted blob. I also spend an impossible amount of time consulting a robot which insists on hallucinating and leading me up the garden path until I'm breathless. And then, finally, I read in enc's documentation: This command does not support authenticated encryption modes like CCM and GCM, and will not support such modes in the

## Recovering Data from an Abandoned Server and Converting a MySQL Database to SQLite

DevFeed: [Recovering Data from an Abandoned Server and Converting a MySQL Database to SQLite](<https://devfeed.tech/articles/a-friend-in-need-41900.md>)

Original publisher: [Read original article](<https://jpmens.net/2025/08/31/a-friend-in-need/>)

Author: Jan-Piet Mens

Published: 2025-08-30T22:00:00Z

Content type: article

Language: en

Sources: [Jan-Piet Mens](<https://devfeed.tech/sources/jan-piet-mens.md>)

Topics: [data](<https://devfeed.tech/topics/data.md>), [Database](<https://devfeed.tech/topics/database.md>), [SQLite](<https://devfeed.tech/topics/sqlite.md>), [Content Management System](<https://devfeed.tech/topics/cms.md>), [Disk image](<https://devfeed.tech/topics/disk-image.md>), [MySQL](<https://devfeed.tech/topics/mysql.md>), [container](<https://devfeed.tech/topics/container.md>), [mount](<https://devfeed.tech/topics/mount.md>), [Server](<https://devfeed.tech/topics/server.md>), [Proxmox](<https://devfeed.tech/topics/proxmox.md>), [qemu](<https://devfeed.tech/topics/qemu.md>), [USB](<https://devfeed.tech/topics/usb.md>)

Tags: [content-management-system](<https://devfeed.tech/tags/content-management-system.md>), [data](<https://devfeed.tech/tags/data.md>), [database](<https://devfeed.tech/tags/database.md>), [jan-piet-mens](<https://devfeed.tech/tags/jan-piet-mens.md>), [jpm](<https://devfeed.tech/tags/jpm.md>), [jpmens](<https://devfeed.tech/tags/jpmens.md>), [mount](<https://devfeed.tech/tags/mount.md>), [mysql](<https://devfeed.tech/tags/mysql.md>), [proxmox](<https://devfeed.tech/tags/proxmox.md>), [qemu](<https://devfeed.tech/tags/qemu.md>), [sqlite](<https://devfeed.tech/tags/sqlite.md>)

### AI overview

A friend asks the author to recover data from an abandoned server once used to run a proprietary content management system. The author networks the machine, accesses its Proxmox-hosted container, extracts the disk image, copies the data, creates a MySQL dump, and converts it to a SQLite database for viewing.

### Source excerpt

Three years ago, a friend of mine purchased a server (one of those horrendously loud things most of us mere mortals thankfully seldom or never get to hear) from a hosting company. The server held a to-him precious application served by a proprietary content management system. He abandoned the CMS at the time because, as I understand it, the monthly price of the CMS was to increase four-fold. Stuck in a basement, the server itself gathered more dust for three years until my friend decided he wanted the data. The hosting company had told him "just connect it to the internet and you can access your data" which, obviously, is total bollocks - it begins with not owning the domain and ends with a hard-coded IP which belongs to said hosting company. He asked me for help. I sighed. I helped. For the first time in quite some years I really got my hands dirty, so to speak. I went to his house at 17:30 and got home again past midnight. I was, though, given a nice dinner, and the lady of the house had baked my favorite cake! I'd brought a router/switch which we used to get this screaming beast lying on the table before us networked. I then had to remember what little I knew of Proxmox, and got as far as seeing there was a qemu container with id 100. The guest tools (if I recall the name correctly) weren't installed in the container so I couldn't do much from outside, but I was able to vzdump the container into a file on the host which thankfully had sufficient disk space. After extracting that dump I had the disk image which I could losetup / mount, and a chroot later I was "in". I asked for and received a small brandy. I copied the data onto a portable USB disks (my can those things be slow!) and created a MySQL dump of the database. All in all some 20 GB of data were shuffled in and out. This morning, then finally, I discovered an absolutely gorgeous little tool called mysql2sqlite with which I created a SQLite database file which I zipped up and sent to my friend with the in