Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Useful Dosbox-X config values

I've recently had to switch even my Windows 3.1 Dosbox guest to Dosbox-X. I was getting weird display glitches even just loading Windows 3.1, not even any of the games yet.

I've come across some very useful settings that I want to use for any DOSBox-X instances.

[sdl]
# Capture the mouse
autolock  = true
# Hide the KRNL386 garbage data in the titlebar
showbasic = false
[dosbox]
# Show this in the titlebar
title     = win31games
[render]
# Keep the 4:3 aspect ratio at all times, which makes full-screening the application still look nice.
aspect    = true

On a Devuan system, the useful document files are these.

  • /usr/share/dosbox-x/dosbox-x.reference.conf
  • /usr/share/dosbox-x/dosbox-x.reference.full.conf

Xbright: adjust X11 brightness

Years ago I found a small program on the Internet that makes it easier to adjust screen brightness within X11. You can of course use xrandr, but this makes it easier when you're not thinking that deeply.

It isn't sufficient for adjusting gamma. I need to adjust gamma for playing games like Portal that are just too dark.

xgamma -gamma 1.5

Maybe I should add it as a slider, but I haven't bothered to do that yet.

Keepass2: fix puffy ui and fonts

It feels like the tech I wish to use wants to fight me. It's getting frustrating. (Or maybe I'm just getting old.)

I did a medium-dive into DPI on Linux again, because the Mono-based application keepass2 wanted to look really puffy and bloated. I have a 1920x1080 display, with no special scaling at all. I know I've had to tell QT applications what scaling to use, because they apparently guess wrong on basic 1920x1080.

Wrong view (bloated):

Right view (not bloated):

This time, for some dumb reason KeePass wanted everything to look like it's scaled up kinda big and puffy. The solution to this is to uncheck the setting "Force usage of system font (Unix only)."

The setting:

I don't know why it sometimes flips. Maybe it's like that other setting that magically changes.

Aborted research

GDK_SCALE=1 GDK_DPI_SCALE=1
xrdb -override <<< "Xft.dpi:96"
xrdb -query
MONO_MWF_NATIVE=1
MONO_OPTIONS="--debug"

Unhelpful references

  1. HiDPI - ArchWiki#Mono applications
  2. MonitorDPI - Debian Wiki
  3. KeePass 2.28 released - KeePass

add outbound link icon on links

tl;dr

Add to your css the following.

@font-face {
    font-family: "SymbolsNerdFont";
    src: url("../fonts/SymbolsNerdFont.ttf") format("truetype");
}
a:not(:has(img))[href*='/outbound/']:not([href^='/']):after,
a:not(:has(img))[href^='http']:not([href^='https://bgstack15.ddns.net']):after
{
    font-family: SymbolsNerdFont;
    content: "";
    padding-left: 0.25rem;
}

Add to your ../fonts directory SymbolsNerdFont.

For me

I had to add that css to my nikola theme assets/css/blog.css file.

I also had to place the aforementioned font file to assets/fonts. Then a normal build and deploy adds the new feature!

Inspiration

I was inspired when I saw Suggested Mods - 0x7be.de. I like the idea of making it clear when you're going to leave my site. I don't want you to leave my site; my site is the only one of consequence.

Fetch assets from vendor portal

I think this vendor uses a generic Salesforce or similar SAAS for their customer support portal, so this might be applicable to more than just this one vendor.

Load your secrets, in this case from ~/.config/helpcenter, and then dot-source the library. Then authenticate, and if it prints a success message, you can then download large assets.

. download-vendor-asset.sh
auth_to_vendor4
fetch_vendor4 https://release.example.com/downLoadArtifact?id=8823

It supports any number of assets all on one line.

Read more…

Passkeys from Vaultwarden or KeepassXC

I recently was forced to start using passkeys to retain access to a bank website where I've already been able to log in using conventional means for years. The site completely disabled the use of passwords, except to set up a passkey, along with an emailed 2fa code. I hate passkeys, and hate that technology is being used against users.

If you are forced to use passkeys, here are two current options that do not depend on mobile devices or other locked-down tech.

Read more…

Upgrading contentdb narrative

I run an Internal ContentDB for Luanti users. I know the upstream ContentDB receives updates to its code.

I was months and months behind the upstream codebase, so I decided to try to upgrade my code. The most visible feature that I could use to confirm I had a new version is the display of "AI disclosure" on a package.

The code uses python3, flask, and SqlAlchemy. I've used all these technologies before, but not as deeply as the ContentDB team! It does make me happy that I have approximately the same skillset as that team.

The actions

In a containerized application, you normally run docker pull <imagename>, but there aren't pre-built images for this project. But it's not hard to run docker build . to build it yourself. So I did that, and then tried restarting the container, and it failed.

I failed to keep the exact error messages, but it boiled down to a "circular dependency problem."

I then connected to the running container to manually run alembic commands to upgrade the database. You can see the changes to the database schema. I've never used alembic directly before; I've always used flask db upgrade, and I eventually figured how to do that in this containerized fashion. But I had learned a lot about what I needed to add to the alembic configs so it could find its components. They're scribbled somewhere, but I'm not going to look for them because the flask db upgrade is a better and simpler way.

So the database could get upgraded, but I still cannot run the flask app because of the circular dependency problem. utils kept trying to import app.utils or vice versa. This was the real problem of my upgrade, which was solved after I looked through the code history and found Commit fa3697a: Split up app/utils/__init__.py to reduce issues. The problem still happens though, because of how the container loads the app from a mounted volume, into the location where it will run.

That file, app/utils/__init__.py, was deleted, but when the container startup script copies all files in, it doesn't remove files. It's one of those classic computer science problems, where it won't clean up a deleted file. It doesn't know that file exists, and doesn't care. It's not rsync with a --delete-after parameter. Therefore, I had to go into the container and delete app/utils/__init__.py. Then I could run that flask db upgrade from the utility script, and then start up the application.

The reason that file was deleted, was because you cannot have a python module import another module of the same name. That means directory name, even if it's a different directory. So utils cannot import app.utils, and vice versa. So I'm glad the ContentDB team rewrote it so one of them no longer has a module (__init__.py) directly, to choke.

And now for some reason, every time I restart the container, I have to re-run the flask db upgrade step. That's weird, but I can live with it.

Uninformed rant on Rust

This is barely adapted from a rant I gave in irc a month ago, which was not logged as far as I know. Now it's logged! This is all my opinion, and not very informed at that. Feel free to correct me in the comments!

Rust wants to move fast and change requirements all the time. It doesn't seem like a stable thing like C++11, etc. I've heard it doesn't support all the architectures that the breadth of GNU/Linux cares about.

Read more…

Drag-and-drop to sign code

I set up a simpler hands-on process for signing binary assets of various kinds. There are apparently still people in the world who don't want to "sign every rubbish binary blob the software developers produce." (Read: give developers a CI/CD with automatic signing, so that they can produce whatever malware they want and get a company signature on it.) For small-scale operations, this suffices to manually sign assets.

The Windows world calls this "Authenticode." There is no direct equivalent in the Free Software world, because official software comes from gpg-signed rpm or apt repositories. Additional installation assets are usually published with checksums on https pages.

The solution involves the signing process with a specific certificate identified by thumbprint. Windows really wants to identify certificates by thumbprint rather than by serial number. Sometimes that means you can get a new certificate with the exact same thumbprint, which I'm sure is useful somewhere. (It also means you're using the same private key, which may or may not be within your certificate policy to allow.)

Yes, this is partially vibecoded. It's my standard format of a library that can be loaded into the current shell (I forgot how and why to use modules.)

files/2026/listings/Sign-Code.ps1 (Source)

#!/bin/pwsh
# File: Sign-Code.ps1
# Last-Modified: 2026-04-01T11:07:34-0400
# Locations:
#     \\utility5\e$\CodeSign\Scripts
# Author: bgstack15
# Startdate: 2026-03-31
# Title: Sign-Code
# Project: Codesign
# Purpose: Functions for easily signing binaries on utility5
# History:
# Usage:
#    As a library, . .\Sign-Code.ps1
#    Or directly, ".\Sign-Code.ps1"
# References:
#     https://www.scriptinglibrary.com/languages/powershell/how-to-modify-your-proxy-settings-with-powershell/
#     https://4sysops.com/archives/how-to-create-an-open-file-folder-dialog-box-with-powershell/
# Improve:
# Dependencies:
#    Cert loaded in Cert:\LocalMachine\My
# Documentation:
<#
.SYNOPSIS
    Functions for easily signing binaries on the utility server.
.DESCRIPTION
    This script provides functions to configure proxy settings, select files via a dialog,
    sign binaries using signtool.exe, and move signed files to a destination folder.
    It supports being dot-sourced as a library or run directly to invoke the signing process.
.NOTES
.USAGE
    As a library (import functions for manual use):
        . .\Sign-Code.ps1
    Run directly (sign files from default or specified folders):
        .\Sign-Code.ps1
.PARAMETER Set-Proxy
    Configures the user's system proxy settings by modifying registry keys.
.PARAMETER Get-File-Dialog
    Opens a Windows File Open dialog to select one or more files.
.PARAMETER Sign-File
    Signs each file using signtool.exe and moves successfully signed files to a destination folder.
.PARAMETER Ask-Sign-Files
    Main function to select files, and sign them.
.DEPENDENCIES
    - Windows signtool.exe located at the specified path.
    - Code signing certificate loaded in Cert:\LocalMachine\My.
    - User has write permissions to destination folders.
.REFERENCES
    - https://www.scriptinglibrary.com/languages/powershell/how-to-modify-your-proxy-settings-with-powershell/
    - https://4sysops.com/archives/how-to-create-an-open-file-folder-dialog-box-with-powershell/
#>
#region Proxy Configuration Function
Function Set-Proxy {
    <#
    .SYNOPSIS
        Sets the system proxy server and port for the current user.
    .PARAMETER Server
        The proxy server address (e.g., proxy.example.com).
    .PARAMETER Port
        The proxy server port number (e.g., 8080).
    .EXAMPLE
        Set-Proxy -Server proxy.example.com -Port 8080
    #>
    [CmdletBinding()]
    [Alias('proxy')]
    [OutputType([string])]
    Param
    (
        [Parameter(Mandatory = $true,
            ValueFromPipelineByPropertyName = $true,
            Position = 0)]
        [string]$Server,
        [Parameter(Mandatory = $true,
            ValueFromPipelineByPropertyName = $true,
            Position = 1)]
        [int]$Port
    )
    # Set proxy server address and enable proxy in the user's registry
    Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -Name ProxyServer -Value "$($Server):$($Port)"
    Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -Name ProxyEnable -Value 1
    # (Optional) Display the current proxy settings
    # Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' | Select-Object ProxyServer, ProxyEnable
}
#endregion Proxy Configuration Function
#region File Selection Function
Function Get-File-Dialog {
    <#
    .SYNOPSIS
        Opens a file open dialog for the user to select one or multiple files.
    .PARAMETER InitialFolder
        The folder that the dialog will open initially.
    .OUTPUTS
        String[] - Full paths of the selected files.
    .EXAMPLE
        $files = Get-File-Dialog -InitialFolder "E:\CodeSign\ToBeSigned"
    #>
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $false)]
        [string]$InitialFolder = "E:\CodeSign\ToBeSigned"
    )
    # Load Windows Forms assembly for GUI dialog
    Add-Type -AssemblyName System.Windows.Forms
    # Configure and show OpenFileDialog allowing multi-selection
    $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
        InitialDirectory = $InitialFolder;
        Title = "Choose file(s) to sign";
        MultiSelect = $true
    }
    $null = $FileBrowser.ShowDialog()
    # Return array of selected file paths
    return $FileBrowser.FileNames
}
#endregion File Selection Function
#region File Signing Function
Function Sign-File {
    <#
    .SYNOPSIS
        Signs one or more files using signtool.exe and moves successfully signed files.
    .PARAMETER FilePath
        One or more full file paths to sign. Supports pipeline input.
    .PARAMETER DestinationFolder
        Directory where successfully signed files will be moved.
    .NOTES
        Requires signtool.exe at specified path and appropriate certificates installed.
    .EXAMPLE
        $files | Sign-File -DestinationFolder "E:\CodeSign\SignedCode"
    #>
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true,
                   Position = 0)]
        [string[]]$FilePath,
        [Parameter(Mandatory = $true)]
        [string]$DestinationFolder
    )
    Process {
        foreach ($file in $FilePath) {
            Write-Host "Signing file: $file"
            # Execute signtool.exe with specified options
            & "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe" sign `
                /fd sha256 /td sha256 /v `
                /f "E:\CodeSign\cert2025\example.cer" `
                /sha1 B38EXAMPLE17340436A80B0A2FDC3BEC9352250F `
                /kc CodeSignExample2025 `
                /csp "Safenet Key Storage Provider" `
                /tr http://timestamp.digicert.com `
                $file
            $exitCode = $LASTEXITCODE
            if ($exitCode -eq 0) {
                # Signing succeeded; ensure destination folder exists
                if (-not (Test-Path -Path $DestinationFolder)) {
                    New-Item -Path $DestinationFolder -ItemType Directory -Force | Out-Null
                }
                # Move signed file to destination folder
                $destinationPath = Join-Path -Path $DestinationFolder -ChildPath (Split-Path $file -Leaf)
                try {
                    Move-Item -Path $file -Destination $destinationPath -Force
                    Write-Host "Moved file to $destinationPath"
                }
                catch {
                    Write-Warning "Failed to move file $file to ${destinationPath}: $_"
                }
            }
            else {
                Write-Warning "Signing failed for $file with exit code $exitCode. File not moved."
            }
        }
    }
}
#endregion File Signing Function
#region Main Orchestration Function
Function Ask-Sign-Files {
    <#
    .SYNOPSIS
        Orchestrates proxy setup, file selection, and signing of files.
    .PARAMETER DestinationFolder
        Optional. Destination folder for signed files. Defaults to "E:\CodeSign\SignedCode".
    .PARAMETER InitialFolder
        Optional. Initial folder for the file selection dialog.
    .EXAMPLE
        Ask-Sign-Files -InitialFolder "E:\CodeSign\ToBeSigned" -DestinationFolder "E:\CodeSign\SignedCode"
    #>
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $false)]
        [string]$DestinationFolder = "E:\CodeSign\SignedCode",
        [Parameter(Mandatory = $false)]
        [string]$InitialFolder
    )
    # Configure proxy settings for the user environment
    Set-Proxy -Server proxy.example.com -Port 8080
    # Get files to sign via file dialog
    $Infiles = Get-File-Dialog -InitialFolder $InitialFolder
    # Pass files and destination folder to signing function
    $Infiles | Sign-File -DestinationFolder $DestinationFolder
}
#endregion Main Orchestration Function
#region Script Execution Control
# Check if script is being run directly or dot-sourced/imported
# If called directly, with more than 0 arguments
if ($args.Count -gt 0) {
    # Files were dropped onto the script or shortcut, process them directly
    # Assuming the DestinationFolder is set or can be defaulted
    $destinationFolder = "E:\CodeSign\SignedCode"
    # Validate that all args are files
    $filesToSign = $args | Where-Object { Test-Path $_ -PathType Leaf }
    if ($filesToSign.Count -eq 0) {
        Write-Warning "No valid files passed as arguments."
        exit 1
    }
    # Call Sign-File with the files from args
    $filesToSign | Sign-File -DestinationFolder $destinationFolder
}
elseif ($MyInvocation.InvocationName.Contains($MyInvocation.MyCommand.Name) -or
    $MyInvocation.InvocationName -eq $PSCommandPath) {
    # Script is being run directly; invoke main function with default folders
    Ask-Sign-Files -InitialFolder "E:\CodeSign\ToBeSigned" -DestinationFolder "E:\CodeSign\SignedCode"
}
#endregion Script Execution Control

And somehow in the loss of progress, you cannot set up a shortcut to run powershell, and have it accept parameters. (Or I never learned. I'm sure the comments will correct me shortly.) So you can do that with the following batch script.

files/2026/listings/Sign-Code.bat (Source)

@echo off
REM File: Sign-Code.bat
REM Purpose: make it possible to drop files onto this
:: Check for admin rights by trying to create a folder in %windir%
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (
    echo Requesting administrative privileges...
    powershell.exe -Command "Start-Process -FilePath '%~f0' -ArgumentList '%*' -Verb RunAs"
    exit /b
)
:: If we get here, we have admin rights
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "E:\CodeSign\Scripts\Sign-Code.ps1" %*
pause

Set up a shortcut to the script. You don't need to customize parameters; it will already handle them correctly. Set up your .lnk to point to C:\Path\Sign-Code.bat and that is all.