Scientific Computing

Public WiFi SSL mangling

Check the desired website’s SSL certificate with a service like Qualys SSL Labs to see if the certificate is valid and properly configured. If the certificate is valid but you still encounter SSL errors, it’s possible that the public WiFi network is interfering with the SSL connection. Also try using command line web programs to see if there are any SSL errors or warnings in the output. Examples:

curl -v https://www.scivision.dev

python -c "import requests; print(requests.get('https://www.scivision.dev').status_code)"

If these fail, try without SSL

curl -v http://www.neverssl.com

python -c "import requests; print(requests.get('http://www.neverssl.com').status_code)"

An example of the curl output when even HTTP connections are interfered with:

curl -v http://neverssl.com
* Host neverssl.com:80 was resolved.
* IPv6: (none)
* IPv4: x.x.x.x
*   Trying x.x.x.x:80...
* connect to x.x.x.x port 80 from 0.0.0.0 port 58197 failed: Timed out
* Failed to connect to neverssl.com port 80 after 21104 ms: Could not connect to server
* closing connection #0
curl: (28) Failed to connect to neverssl.com port 80 after 21104 ms: Could not connect to server

CB Radio AM Auto-Squelch characteristics

Since the introduction by President Electronics of the patented Auto-Squelch feature in CB radios in 1998-1999, auto-squelch (a.k.a. ASC or ASQ) for AM and FM has become widespread in CB radios. The auto-squelch feature allows one to detect weaker signals than would be practical with a manual squelch when driving around or scanning channels because the background noise is automatically accounted for. Auto-squelch is not implemented for SSB, which remains on manual threshold setting of AGC-based squelch. Algorithms exist for voice-activated squelch for SSB, but they are generally not yet implemented in CB (or amateur) radios.

A key innovation was including RF signal strength along with the out-of-band baseband noise level commonly used in FM auto-squelch to determine the squelch threshold. This allows the squelch threshold to be set lower when a strong signal is present, which allows weaker signals to be heard. The auto-squelch algorithm is not perfect, however, and is often fooled into closing by overmodulated AM signals, which can cause the squelch to open and close rapidly, making the signal difficult to understand. The movement by prominent CB radio technicians to avoid overmodulation is to be lauded generally for not fruitlessly disrupting adjacent channel users, and especially to preserve the functioning of auto-squelch. The false closing of squelch even for on-channel strong overmodulated signals is due to the large amount of out-of-band distortion products generated by overmodulation, which can cause the auto-squelch algorithm to incorrectly determine that this is an undesired strong signal present and close the squelch.

In practice, one might use auto-squelch for general driving around and scanning channels, but switch to manual squelch when trying to listen to a known channel with a strong signal that is overmodulated. For reception of weak signals, switching to the manual squelch and leaving the squelch open is generally optimal. These characteristics are why it’s so important when buying a CB radio to get one that also has the “NRC” noise reduction algorithms, which make listening far less fatiguing on any voice mode AM / FM / SSB. It’s a shame that so many are blindly buying the “Cobra 29” style legacy radios when for the same price and often less money, they could get a CB radio with NRC and other features like scanning that make the CB radio experience much more enjoyable and productive.

AFCI circuit protection trip from amateur radio transmission

AFCI protection comes in the form of circuit breakers, outlets, and dead-front outlets that protect downstream circuits from arc faults, which can lead to fires. Today’s AFCI protection is typically Combination AFCI with GFCI, which detects series or parallel arc faults and provides ground fault protection. AFCI are designed to detect and interrupt electrical arcs that can lead to fires, but they can sometimes be sensitive to the electromagnetic interference (EMI) generated by radio transmissions. Amateur radio and CB radio operators have reported instances where their radio transmissions cause AFCI (Arc Fault Circuit Interrupter) circuit protection to trip. Many early reported false trips were due to RF getting into the circuit and AFCI protection. As noted in the linked articles, a first solution may be replacing the AFCI with a newer model that has improved false-trip reduction.

AFCI can also be sensitive to current variation implicit in single-sideband (SSB) transmissions, which can cause the circuit breaker to trip if the rapidly varying current is interpreted as a series arc fault. We have observed that once the current draw on an AFCI circuit is above a certain threshold (say 5-10 amps), the AFCI becomes sensitive to the rapidly varying current draw of an SSB transmitter and falsely trips–even in the transmitter is only drawing say 1-2 amps at 120 volts. This can happen from having an electric heater or other high-current device on the same circuit as the radio, which can cause the AFCI to trip when the radio is transmitting at the same time the high-current device is drawing power. This can be verified by using a battery power supply for the transmitter, to help ensure it’s not coupled RF causing the issue. If the AFCI is new, the only solution may be to put the steady high-current loads and SSB transmitter on separate circuits. AFCI protection should not be removed, as it has proven effective in preventing fires.

Docker on GitHub Actions

Docker images are useful for reproducibility and ease of setup and for software binary distribution on platforms not natively available on GitHub Actions runner images. While one can setup a custom Docker image, it’s often possible to simply use an existing official image from Docker Hub.

Example: Ubuntu 20.04

This example GitHub Actions workflow uses the Ubuntu 20.04 image to build a C++ binary with the GNU C++ compiler. For APT operations, the “-y” option is necessary. Environment variable DEBIAN_FRONTEND is set to “noninteractive” to avoid interactive prompts for certain operations despite “-y”. Don’t use “sudo” as the container user is root and the “sudo” package is not installed.

A special feature of this example is using Kitware’s CMake APT repo to install the latest version of CMake on an EOL Ubuntu distro.

name: ubuntu-20.04

on: [push]

# avoid wasted runs
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  ubuntu-20.04:
    runs-on: ubuntu-latest
    container:
      image: ubuntu:20.04
      env:
        DEBIAN_FRONTEND: noninteractive

    strategy:
      fail-fast: false
      matrix:
        gcc-version: [7, 8]

    env:
      CC: gcc-${{ matrix.gcc-version }}
      CXX: g++-${{ matrix.gcc-version }}
      FC: gfortran-${{ matrix.gcc-version }}

    steps:

    - name: install compilers
      run: |
        apt update -y
        apt install -y --no-install-recommends ca-certificates gpg curl ninja-build ${{ env.CC }} ${{ env.CXX }} ${{ env.FC }}

    - name: install CMake
      run: |
        curl -s https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
        echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
        apt-get update
        test -f /usr/share/doc/kitware-archive-keyring/copyright || rm /usr/share/keyrings/kitware-archive-keyring.gpg
        apt-get install --no-install-recommends -y kitware-archive-keyring
        apt-get install --no-install-recommends -y cmake

    - uses: actions/checkout

    - name: CMake configure
      run: cmake -B build

    - name: CMake build
      run: cmake --build build

    - name: CMake test
      run: ctest --test-dir build

Example: Alpine Linux

This example GitHub Actions workflow uses the Alpine Linux image with the MUSL C library to build a statically-linked binary.

name: alpine-musl

on: [push]

jobs:
  musl:
    runs-on: ubuntu-latest
    container:
      image: alpine

    steps:
    - uses: actions/checkout

    - name: install build tools
      run: apk add --no-cache ninja-build cmake make gfortran openmpi-dev

    - name: print MUSL version
      continue-on-error: true
      run: ldd --version

    - name: CMake configure
      run: cmake -B build

    - name: CMake build
      run: cmake --build build

# Good idea to ensure self-tests pass before packaging
    - name: CMake test
      run: ctest --test-dir build

(Optional) If a CPack archive is desired add step:

    - name: CMake package
      if: success()
      run: cpack --config build/CPackConfig.cmake

The binary artifact or CPack archive can be uploaded by step upload-artifact:

    - name: .exe for release
      uses: actions/upload-artifact@v7
      archive: false
      if: success()
      with:
        name: my.exe
        path: build/my.exe

GitHub Actions upload CMakeConfigureLog.yaml

When CMake fails on the configure or generate steps in a CI workflow, having CMakeConfigureLog.yaml uploaded a as a file can help debug the issue. Add this step to the GitHub Actions workflow YAML file:

  - name: Configure CMake
    run: cmake -B build

# other steps ...

  - name: upload CMakeConfigureLog.yaml
    if: failure() && hashFiles('build/CMakeFiles/CMakeConfigureLog.yaml') != ''
    uses: actions/upload-artifact@v7
    archive: false
    with:
      name: ${{ runner.os }}-${{ env.CC }}-CMakeConfigureLog.yaml
      path: build/CMakeFiles/CMakeConfigureLog.yaml
      retention-days: 5

The “retention-days” parameter is optional. Ensure the “name” parameter is unique to avoid conflicts with other jobs in the workflow. Here we assume that the OS and C compiler are unique between jobs.

Git commit PGP signing

Git signed commits help verify the Git author’s identity using PGP. Optionally, a user or organization can set rules requiring Git PGP signed commits on Git hosting providers such as GitHub and GitLab

PGP public keys can help verify author identity of Git commits, social media, website, etc. Setup GPG on the laptop:

  • Linux: apt install gnupg
  • macOS: brew install gnupg
  • Windows: winget install --id=GnuPG.Gpg4win

Generate a GPG keypair if one doesn’t already exist for yourself.

Export the GPG public and private key and import into GPG:

If one has Keybase, first export Keybase.io PGP key to GPG. If one does NOT have Keybase, use gpg --full-generate-key to generate a GPG keypair.

Verify PGP key:

gpg --list-secret-keys --keyid-format LONG

The first lines will be like:

sec   rsa4096/<public_hex>

The hexadecimal part after the / is a public reference to the GPG keypair.


Add Git provider such as GitHub or GitLab verified email address to the PGP key. To make commits “Verified” with the Git provider, at least one of the Git provider verified email addresses must match:

git config --get user.email

Use the GPG public ID below:

gpg --edit-key <public_hex>

In the interactive GPG session that launches, type

adduid

and enter Name and the Email address–which must exactly match the GitHub verified email address. I also add the @users.noreply.github.com fake email that I always use to avoid spam. Do adduid twice–once for the real GitHub verified email address and again for the github_username@users.noreply.github.com fake email.

Add “trust” from the GPG> prompt:

trust

Since it’s you, perhaps a trust level of 5 is appropriate. type

save

to save changes, which may not show up until exiting and reentering the GPG> prompt.

Configure Git to use the GPG public hex ID like:

git config --global user.signingkey <public_hex>

git config --global commit.gpgsign true

On Windows, even though “gpg” works from Windows Terminal, it’s essential to tell Git the full path to GPG.exe, otherwise Git will fail to sign commits.

git config --global gpg.program "C:\Program Files\GnuPG\bin\gpg.ex"

Find the path with:

where.exe gpg

Add the GPG public key to the Git provider. Copy and paste the output from this command into GPG Key of GitHub or GitLab. This is done only once per human, not once per device.

gpg --armor --export <public_hex>

Usage

GPG can be used to sign Git commits and tags, and can also be disabled per commit.

Verify Git PGP commit sign

Make a git commit after the procedure above, and see the signature notes:

git log --show-signature

it will start with

gpg: Signature made

Temporary disable Git commit sign

If you temporarily lose access to the GPG password, you won’t be able to git commit. A temporary workaround is to set

git config commit.gpgsign false

or simply add the --no-gpg-sign option like:

git commit -am "msg" --no-gpg-sign

If not signing as default, sign only certain commits by

git commit -S

Note that’s a capital “S”.

Troubleshooting

Signing subkey expired

If you get gpg: signing failed: No secret key or gpg: skipped "...": No secret key, the signing subkey may have expired. GPG subkeys (encryption, signing) expire independently from the main key.

Check which subkeys are expired:

gpg --list-secret-keys

Look for subkeys marked expired. To extend them:

gpg --edit-key <public_hex>
key 1
expire
1y
save

The key N selects which subkey to extend (1 for first, 2 for second, etc.). Then export the updated key to GitHub.

Password prompt not working (macOS)

On macOS if entering the password on git commit doesn’t work, try:

brew install pinentry-mac

and add to ~/.zshrc:

export GPG_TTY=$TTY

Git SSH over port 443

Certain networks may block traffic on port 22, which causes failure for Git operations like:

ssh: connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository.

The solution for this is to at least temporarily configure SSH to use port 443, which is typically open for HTTPS traffic. This can be persistently done by editing the user SSH config file usually located at “/.ssh/config”, here for GitHub, where “/.ssh/github” comes from GitHub SSH key setup.

Likewise for

Host github.com
  User git
  IdentityFile ~/.ssh/github
  Hostname ssh.github.com
  Port 443

Host gitlab.com
  User git
  IdentityFile ~/.ssh/gitlab
  Hostname altssh.gitlab.com
  Port 443

Host bitbucket.org
  User git
  IdentityFile ~/.ssh/atlassian
  Hostname altssh.bitbucket.org
  Port 443

An alternative is to specify the port directly in the Git remote URL like:

git push ssh://user@host:PORT/path/to/repo.git main

Or specify environment variable GIT_SSH_COMMAND.

SSH post-quantum warning

macOS 26.3 upgraded the OpenSSH client to OpenSSH 10.2, which added a warning about SSH server key exchange with non-post-quantum algorithms. The warning was added in OpenSSH 10.1, but macOS 26.3 is the first macOS release to include it from Apple. The warning is meant to alert users that their SSH server may not be using these newer, more secure kex algorithms.

** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to “store now, decrypt later” attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html

The message will hopefully get the SSH server system admin to upgrade their SSH server to support post-quantum key exchange algorithms, which will provide better security against future quantum computer attacks. The OpenSSH PQ page has more information about the post-quantum key exchange algorithms and how to disable the warning on the client side if necessary. Disable the warning per host so you’re not totally blind to the security of the SSH servers you connect to.

Recursively convert line endings with dos2unix + mac2unix

To recursively convert line endings from DOS \r\n and old macOS \r to Unix \n format in all files recursively, use “dos2unix” and “mac2unix” commands. For example, it’s not uncommonn that Matlab .m files shared among groups end up with DOS line endings, which can cause issues across different operating systems. When viewed with “git diff” or similar, files might have ^M characters at the end of lines, indicating DOS or old macOS line endings. Run the following command using GNU Find to convert in place all .m files:

find . -type f -name "*.m" -exec sh -c 'dos2unix -e "$1" && mac2unix -e "$1"' _ {} \;

Set Git to use the correct line endings to avoid line ending conflicts in Git repositories.

Windows Git Credential Manager

Git over SSH can use SSH-agent to remember SSH keys for Linux and Windows. For those not using Git over SSH but tiring of typing the Git password, on Windows the Git Credential Manager can fix that situation. The install is small and quick, and to use Git Credential Manager, be sure via

git remote -v

that the connection is https:// and not ssh:// where appropriate. Upon trying to git push or git pull, the Git Credential Manager will appear. It works with 2-factor Authentication as well, storing in Windows Credential Manager. The keys can be deleted from Windows Credential Manager if needed, and / or the Personal Access Token automatically generated can be deleted from GitHub.

Note: If using automatic Git push SSH that would need to be disabled to allow git push to use https so that Git Credential Manager is invoked.