24 Commits

Author SHA1 Message Date
David Tomaschik
e2ec4e1f9c Update Brewfile 2026-07-23 12:41:19 -07:00
David Tomaschik
ba97442895 Fix iterm integration for zsh prompt 2026-07-13 15:55:34 -07:00
David Tomaschik
a9b68bfe1f New script to deploy a checkout 2026-07-09 20:31:01 -07:00
David Tomaschik
2814312d60 Optimize startup 2026-07-07 14:53:56 -07:00
David Tomaschik
a390d0a4d4 Improve SSH_AUTH_SOCK handling. 2026-07-07 14:28:37 -07:00
David Tomaschik
6caee04853 Update install_tool for ssh-agent-mux. 2026-07-07 10:10:59 -07:00
David Tomaschik
da1ee162c2 Script cleanup 2026-07-06 15:59:12 -07:00
David Tomaschik
22b3f2e049 Update install_tool 2026-07-01 12:15:39 -07:00
David Tomaschik
b81ca9703b Fix broken shenv merge 2026-06-30 12:24:00 -07:00
David Tomaschik
be903aeb2c Merge branch 'main' of https://github.com/Matir/skel 2026-06-30 12:22:44 -07:00
David Tomaschik
37816c7f72 Merge branch 'main' of https://github.com/Matir/skel 2026-06-30 12:20:24 -07:00
David Tomaschik
63f8bb9364 Update SSH socket handling 2026-06-30 12:20:00 -07:00
David Tomaschik
691b2a7c6f shenv update 2026-06-30 10:57:52 -07:00
David Tomaschik
8e42781710 Merge branch 'main' of https://github.com/Matir/skel 2026-06-30 10:47:42 -07:00
David Tomaschik
de601c4a83 Update dotfiles 2026-06-30 10:47:40 -07:00
David Tomaschik
684f6c6e95 Update update-authorized-keys 2026-06-29 23:01:21 -07:00
David Tomaschik
91972eed59 Update ssh keys 2026-06-29 22:49:37 -07:00
David Tomaschik
eca9a6bcb2 Merge branch 'main' of github.com:Matir/skel 2026-06-29 22:42:10 -07:00
David Tomaschik
3214af0617 Add authorized_keys.d 2026-06-29 22:35:18 -07:00
David Tomaschik
be3fdefd23 Bump brewfile 2026-06-24 13:22:53 -07:00
David Tomaschik
00eb8832c2 Move codex 2026-06-24 13:21:27 -07:00
David Tomaschik
5852b8564f Brewfile update for veracrypt 2026-06-24 13:06:28 -07:00
David Tomaschik
f56bcf4cdf bump brewfile 2026-06-19 14:20:59 -07:00
David Tomaschik
ad135fac37 Updates 2026-06-19 14:17:48 -07:00
30 changed files with 676 additions and 282 deletions

View File

@@ -1,6 +1,7 @@
tap "dart-lang/dart"
tap "holtwick/tap"
tap "sass/sass"
tap "dart-lang/dart", trusted: true
tap "espressif/eim"
tap "holtwick/tap", trusted: true
tap "sass/sass", trusted: true
brew "ack"
brew "acme.sh"
@@ -20,9 +21,10 @@ brew "devcontainer"
brew "dfu-util"
brew "difftastic"
brew "direnv"
brew "dua-cli"
brew "duck"
brew "dust"
brew "earthly"
brew "espressif/eim/eim", trusted: true
brew "esptool"
brew "fish"
brew "fq"
@@ -31,11 +33,14 @@ brew "ghidra", link: false
brew "git"
brew "git-delta"
brew "git-lfs"
brew "git-xet"
brew "glib"
brew "gnupg"
brew "go"
brew "gradle"
brew "hashcat"
brew "hf"
brew "holtwick/tap/bx"
brew "holtwick/tap/bx", trusted: true
brew "htop"
brew "httpie"
brew "hugo"
@@ -44,7 +49,9 @@ brew "john-jumbo"
brew "jq"
brew "kubeconform"
brew "kubectx"
brew "libgcrypt"
brew "librsvg"
brew "libslirp"
brew "lima"
brew "minikube"
brew "mise"
@@ -56,23 +63,27 @@ brew "ollama"
brew "p7zip"
brew "pipenv"
brew "pipx"
brew "pixman"
brew "pkgconf"
brew "protobuf"
brew "pwgen"
brew "pwntools"
brew "python@3.13"
brew "python@3.14"
brew "qemu"
brew "restic"
brew "ripgrep"
brew "ruby"
brew "ruby", link: false
brew "ruby@3.3"
brew "rustup"
brew "sass/sass/migrator"
brew "sass/sass/sass"
brew "sdl2-compat"
brew "shellcheck"
brew "smartmontools"
brew "starship"
brew "tmux"
brew "todoist-cli"
brew "uv"
brew "virtualenvwrapper"
brew "wget"
@@ -101,7 +112,6 @@ cask "raycast"
cask "rectangle"
cask "scroll-reverser"
cask "temurin"
cask "veracrypt"
cask "wezterm"
cask "zulu@17"
@@ -121,11 +131,12 @@ if !is_corp?
brew "virt-manager"
cask "claude-code"
cask "codex"
cask "cryptomator"
cask "keepassxc"
cask "gcloud-cli"
cask "google-cloud-sdk"
cask "keybase"
cask "orbstack"
cask "jordanbaird-ice"
cask "jordanbaird-ice@beta"
cask "veracrypt"
end

1
CLAUDE.md Symbolic link
View File

@@ -0,0 +1 @@
AGENTS.md

View File

@@ -4,7 +4,12 @@ set -ueo pipefail
shopt -s extglob
# get libraries
. ${HOME}/.local/lib/bash/tui.sh
if [[ -f "${HOME}/.local/lib/bash/tui.sh" ]]; then
. "${HOME}/.local/lib/bash/tui.sh"
else
echo "Error: ${HOME}/.local/lib/bash/tui.sh not found!" >&2
exit 1
fi
COMMANDS=(
gctx
@@ -43,7 +48,7 @@ _gctx_choose() {
--format='value(is_active, name, format("{} (as {})", properties.core.project, properties.core.account))')
local choice
if choice=$(printf "%-${maxnamelen}s %s\n" "${lines[@]}" | select_entry "gcloud config" "$default") ; then
_gctx_set "${choice}"
_gctx_set "$(echo "${choice}" | awk '{print $1}')"
else
echo "No option selected, leaving unchanged."
fi
@@ -68,7 +73,7 @@ _gctx_clone() {
local oldconfig=()
local line
while IFS= read -r line ; do
old_config+=("$line")
oldconfig+=("$line")
done < <(gcloud config configurations describe "$(_gctx_name)" --format='multi(properties:format="flattened[separator=\" \"]")')
# create new

View File

@@ -1,8 +1,22 @@
#!/bin/sh
env > ${TMPDIR}/env-pre
. ${HOME}/.shenv
env > ${TMPDIR}/env-post
for VAR in $(env | cut -d'=' -f1) ; do
/bin/launchctl setenv "${VAR}" "$(eval echo \$${VAR})"
done
set -o nounset
TMP_DIR="${TMPDIR:-/tmp}"
TMP_DIR="${TMP_DIR%/}"
env > "${TMP_DIR}/env-pre" 2>/dev/null || true
if [ -f "${HOME}/.shenv" ]; then
. "${HOME}/.shenv"
fi
env > "${TMP_DIR}/env-post" 2>/dev/null || true
if [ -x "/bin/launchctl" ]; then
for VAR in $(env | awk -F= '/^[a-zA-Z_][a-zA-Z0-9_]*=/ {print $1}') ; do
case "${VAR}" in
_|""|*[!a-zA-Z0-9_]*|[0-9]*) continue ;;
esac
eval "val=\${${VAR}:-}"
/bin/launchctl setenv "${VAR}" "${val}"
done
fi

View File

@@ -47,7 +47,7 @@ shift $((OPTIND - 1)) # Remove the parsed options
# --- Set target directory ---
# Use the first remaining argument as the target directory.
if [ -n "$1" ]; then
if [ "$#" -gt 0 ]; then
TARGET_DIR="$1"
fi
@@ -75,7 +75,7 @@ find "${TARGET_DIR}" -type l ! -exec test -e {} \; -print0 | while IFS= read -r
continue
fi
# Ask the user for confirmation.
read -p "Remove broken symlink '${link}'? [y/N] " -n 1 -r
read -p "Remove broken symlink '${link}'? [y/N] " -n 1 -r < /dev/tty
echo # Move to a new line after input.
if [[ $REPLY =~ ^[Yy]$ ]]; then

View File

@@ -3,7 +3,7 @@
# Installs Ansible, trying user-space methods first before falling back to sudo.
# This script is designed to be idempotent and safe to run multiple times.
set -e # Exit immediately if a command exits with a non-zero status.
set -euo pipefail # Exit immediately if a command exits with a non-zero status, undefined variable, or pipe failure.
# --- Helper Functions ---
info() { echo "[INFO] $1"; }
@@ -44,8 +44,8 @@ fi
# Try Python's venv module if pipx failed or wasn't present
VENV_PATH="${HOME}/.local/share/ansible_venv"
# Create a temp path to avoid clobbering a failed install
VENV_TEST_PATH="/tmp/ansible_venv_test_$$"
# Create a temp path securely to avoid clobbering a failed install
VENV_TEST_PATH="$(mktemp -d "${TMPDIR:-/tmp}/ansible_venv_test.XXXXXX")"
if python3 -m venv "${VENV_TEST_PATH}" >/dev/null 2>&1; then
rm -rf "${VENV_TEST_PATH}" # Clean up test
info "Python's venv module is available. Creating a virtual environment at ${VENV_PATH}..."
@@ -55,7 +55,7 @@ if python3 -m venv "${VENV_TEST_PATH}" >/dev/null 2>&1; then
info "Ansible installed successfully into a virtual environment."
info "To use it, run: '${VENV_PATH}/bin/ansible'"
info "To make it available everywhere, add its bin directory to your PATH:"
info " echo 'export PATH="${VENV_PATH}/bin:$PATH"' >> ~/.profile"
info " echo 'export PATH=\"${VENV_PATH}/bin:\$PATH\"' >> ~/.profile"
info "(You may need to source ~/.profile or restart your shell)."
exit 0
else
@@ -63,6 +63,7 @@ if python3 -m venv "${VENV_TEST_PATH}" >/dev/null 2>&1; then
rm -rf "${VENV_PATH}" # Clean up failed attempt
fi
else
rm -rf "${VENV_TEST_PATH}" # Clean up test after failure
info "Python's venv module not available or failed to create a test environment."
fi

View File

@@ -1,9 +1,11 @@
#!/bin/bash
set -ue
set -ueo pipefail
TMPDIR=$(mktemp -d)
SYS_TMPDIR="${TMPDIR:-/tmp}"
TMPDIR="$(mktemp -d "${SYS_TMPDIR%/}/install_tool.XXXXXX")"
trap 'rm -rf -- "${TMPDIR}"' EXIT
export -n TMPDIR 2>/dev/null || true
REINSTALL=0
PACKAGES=1
@@ -38,7 +40,7 @@ shift $((OPTIND-1))
function list_tools {
echo "Options:" >/dev/stderr
awk 'BEGIN {s=0;FS=")"};/main tool selection/{s=1};/^\s+\w+)$/{if(s==1){print $1}}' "$0" | sort | while read -r opt; do
awk 'BEGIN {s=0;FS=")"};/main tool selection/{s=1};/^\s+[a-zA-Z0-9_.-]+)$/{if(s==1){print $1}}' "$0" | sort | while read -r opt; do
echo -e "\\t${opt}" >/dev/stderr
done
}
@@ -124,11 +126,13 @@ function get_latest_github_release_url {
local repo="$1"
local glob="$2"
curl -s "https://api.github.com/repos/${repo}/releases/latest" | \
jq -r ".assets[] | select(.name|test(\"${glob}\")) | .browser_download_url"
jq -r --arg rx "${glob}" '.assets[] | select(.name | test($rx)) | .browser_download_url'
}
function require_pipx {
command -v pipx >/dev/null 2>&1 || die "Requires pipx"
function require {
local cmd="${1}"
local msg="${2:-Requires ${cmd}}"
command -v "${cmd}" >/dev/null 2>&1 || die "${msg}"
}
# Begin main tool selection
@@ -288,10 +292,7 @@ case ${TOOL} in
git clone "${src}" "${DESTDIR}"
;;
pwndbg)
if ! command -v gdb > /dev/null 2>&1 ; then
echo 'No gdb available!' >/dev/stderr
exit 1
fi
require gdb "No gdb available!"
git clone --depth 1 -b stable https://github.com/pwndbg/pwndbg.git "${DESTDIR}"
PY_PACKAGES=${DESTDIR}/vendor
mkdir -p "${PY_PACKAGES}"
@@ -311,10 +312,7 @@ case ${TOOL} in
;;
gef)
makedest_or_die
if ! command -v gdb > /dev/null 2>&1 ; then
echo 'No gdb available!' >/dev/stderr
exit 1
fi
require gdb "No gdb available!"
download \
https://github.com/hugsy/gef/raw/master/gef.py \
"${DESTDIR}/gef.py"
@@ -441,25 +439,19 @@ EOF
add_bin_symlink docker-compose
;;
tldr)
require_pipx
require pipx
pipx install tldr
;;
blint)
require_pipx
require pipx
pipx install blint
;;
dust)
if ! command -v cargo >/dev/null 2>&1 ; then
echo "This needs cargo (for rust)!" >/dev/stderr
exit 1
fi
require cargo "This needs cargo (for rust)!"
cargo install du-dust
;;
bottom)
if ! command -v cargo >/dev/null 2>&1 ; then
echo "This needs cargo (for rust)!" >/dev/stderr
exit 1
fi
require cargo "This needs cargo (for rust)!"
cargo install bottom
;;
delta)
@@ -476,7 +468,8 @@ EOF
ropper)
deb_only
install_pkgs python3-z3
pip3 install --user pyvex ropper
require pipx
pipx install ropper
;;
kubeconform)
go install github.com/yannh/kubeconform/cmd/kubeconform@latest
@@ -527,14 +520,11 @@ EOF
sh "${rustup_init}" --no-modify-path -y
;;
igrep)
if ! command -v cargo >/dev/null 2>&1 ; then
echo "This needs cargo (for rust)!" >/dev/stderr
exit 1
fi
require cargo "This needs cargo (for rust)!"
cargo install igrep
;;
unblob)
require_pipx
require pipx
pipx install unblob
;;
fq)
@@ -555,6 +545,37 @@ EOF
fi
fi
;;
speckit)
require uv
latest_version=$(curl -s "https://api.github.com/repos/github/spec-kit/releases/latest" | jq -r '.tag_name')
if [ -z "${latest_version}" ] || [ "${latest_version}" = "null" ]; then
die "Failed to determine latest release version for speckit."
fi
uv tool install specify-cli --from "git+https://github.com/github/spec-kit.git@${latest_version}"
;;
ssh-agent-mux)
makedest_or_die
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$(uname -m)" in
x86_64|amd64)
arch="amd64"
;;
aarch64|arm64)
arch="arm64"
;;
*)
die "Unsupported architecture: $(uname -m)"
;;
esac
tar_url=$(get_latest_github_release_url "overhacked/ssh-agent-mux" ".*${os}-${arch}\\.tar\\.gz$")
if [ -z "${tar_url}" ]; then
die "Could not find ssh-agent-mux release for ${os}-${arch}"
fi
download "${tar_url}" "${TMPDIR}/ssh-agent-mux.tar.gz"
tar zxf "${TMPDIR}/ssh-agent-mux.tar.gz" --strip-components=1 -C "${DESTDIR}"
chmod +x "${DESTDIR}/ssh-agent-mux"
add_bin_symlink ssh-agent-mux
;;
*)
echo "Unknown tool: ${TOOL}" >/dev/stderr
list_tools

View File

@@ -2,12 +2,20 @@
set -ue
if [ "$(id -u)" -ne 0 ]; then
echo "Error: This script must be run as root." >&2
exit 1
fi
cat >/usr/local/bin/x-resize <<"EOF"
#!/bin/sh
PATH=/usr/bin:/bin:/usr/local/bin
desktopuser=$(/bin/ps -ef | /bin/grep -oP '^\w+ (?=.*vdagent( |$))') || exit 0
desktopuser=$(/bin/ps -eo user,comm 2>/dev/null | awk '$2 ~ /vdagent/ {print $1; exit}')
[ -z "$desktopuser" ] && exit 0
desktophome=$(getent passwd "$desktopuser" | cut -d: -f6)
[ -z "$desktophome" ] && exit 0
export DISPLAY=:0
export XAUTHORITY=$(eval echo "~$desktopuser")/.Xauthority
export XAUTHORITY="${desktophome}/.Xauthority"
/usr/bin/xrandr --output $(/usr/bin/xrandr | awk '/ connected/{print $1; exit; }') --auto
EOF
chmod 755 /usr/local/bin/x-resize

View File

@@ -182,13 +182,14 @@ if [[ -f "$TARGET_FILE" && "$OVERWRITE" != "true" ]]; then
fi
# 4. If the path ends in .md (case-insensitive), generate appropriate YAML front matter and write it to the new file.
if [[ "${TARGET_BASE,,}" == *.md ]]; then
if [[ "$TARGET_BASE" =~ \.[mM][dD]$ ]]; then
NOTE_TITLE="${TARGET_BASE%.*}"
NOTE_TITLE_ESCAPED="${NOTE_TITLE//\"/\\\"}"
CURRENT_DATE="$(date +"%Y-%m-%d %H:%M")"
cat << EOF > "$TARGET_FILE"
---
title: "$NOTE_TITLE"
title: "$NOTE_TITLE_ESCAPED"
date: $CURRENT_DATE
tags: []
---

View File

@@ -18,7 +18,7 @@ HOST_SPECIFIC_SCRIPT="${RESTIC_SCRIPTS_DIR}/${HOSTNAME}"
# Check if the script exists and is executable
if [[ -f "${HOST_SPECIFIC_SCRIPT}" && -x "${HOST_SPECIFIC_SCRIPT}" ]]; then
echo "Executing restic script for hostname: ${HOSTNAME}"
"${HOST_SPECIFIC_SCRIPT}"
"${HOST_SPECIFIC_SCRIPT}" "$@"
else
echo "Error: No executable restic script found for hostname '${HOSTNAME}' at '${HOST_SPECIFIC_SCRIPT}'." >&2
echo "Please create an executable script at that path if you want to use this functionality." >&2

View File

@@ -12,8 +12,8 @@ set -o pipefail
# For this script, we assume the user's home directory.
SOURCE_DIR="${HOME}"
# Exclude file location. We'll create a default one next to the script.
EXCLUDE_FILE="$HOME/.restic_exclude.darwin"
# Exclude file location.
EXCLUDE_FILE="${HOME}/.restic_exclude.darwin"
# --- Functions ---
usage() {
@@ -34,7 +34,7 @@ EOF
# --- Main Script ---
# Check if restic is installed
if ! command -v restic &> /dev/null; then
if ! command -v restic >/dev/null 2>&1; then
echo "Error: restic command not found." >&2
echo "Please install restic first: https://restic.net/" >&2
exit 1
@@ -57,7 +57,7 @@ while getopts ":l:bu:h" opt; do
;;
b)
BACKUP_MODE="b2"
if [[ ${OPTIND} -le $# && "${!OPTIND}" != -* ]]; then
if [[ ${OPTIND} -le $# && "${!OPTIND:-}" != -* ]]; then
REPO="b2:${!OPTIND}:"
OPTIND=$((OPTIND + 1))
fi
@@ -91,18 +91,19 @@ fi
if [[ "${BACKUP_MODE}" == "b2" ]]; then
if [[ -f "${HOME}/.resticb2" ]] ; then
# shellcheck disable=SC1090
. "${HOME}/.resticb2"
fi
export B2_ACCOUNT_ID
export B2_ACCOUNT_KEY
export B2_BUCKET_NAME
if [[ -z "${B2_ACCOUNT_ID:-}" || -z "${B2_ACCOUNT_KEY:-}" ]]; then
export B2_ACCOUNT_ID="${B2_ACCOUNT_ID:-}"
export B2_ACCOUNT_KEY="${B2_ACCOUNT_KEY:-}"
export B2_BUCKET_NAME="${B2_BUCKET_NAME:-}"
if [[ -z "${B2_ACCOUNT_ID}" || -z "${B2_ACCOUNT_KEY}" ]]; then
echo "Error: For Backblaze B2 backups, you must set the B2_ACCOUNT_ID and B2_ACCOUNT_KEY environment variables." >&2
exit 1
fi
if [[ -z "${REPO:-}" ]]; then
if [[ -n "${B2_BUCKET_NAME:-}" ]]; then
if [[ -z "${REPO}" ]]; then
if [[ -n "${B2_BUCKET_NAME}" ]]; then
REPO="b2:${B2_BUCKET_NAME}:"
else
echo "Error: Backup mode is B2 but no bucket name was provided and the B2_BUCKET_NAME environment variable is not set." >&2
@@ -113,41 +114,56 @@ if [[ "${BACKUP_MODE}" == "b2" ]]; then
fi
KEYCHAIN_ENTRY_NAME="restic_repo_password"
if security find-generic-password -a "$(whoami)" -s "${KEYCHAIN_ENTRY_NAME}" >/dev/null 2>&1 ; then
export RESTIC_PASSWORD_COMMAND="security find-generic-password -a \"$(whoami)\" -s \"${KEYCHAIN_ENTRY_NAME}\" -w"
local_user="$(id -un 2>/dev/null || whoami)"
if security find-generic-password -a "${local_user}" -s "${KEYCHAIN_ENTRY_NAME}" >/dev/null 2>&1 ; then
printf -v RESTIC_PASSWORD_COMMAND 'security find-generic-password -a %q -s %q -w' "${local_user}" "${KEYCHAIN_ENTRY_NAME}"
export RESTIC_PASSWORD_COMMAND
# Source file?
elif [[ -f "${HOME}/.resticpass" ]] ; then
export RESTIC_PASSWORD_FILE="${HOME}/.resticpass"
fi
# Ensure exclude file exists so restic does not fail when checking exclusions.
if [[ ! -f "${EXCLUDE_FILE}" ]]; then
echo "Exclude file '${EXCLUDE_FILE}' not found. Creating a default macOS exclude file..."
cat << 'EOF' > "${EXCLUDE_FILE}"
# Default restic exclusions for macOS
.Trash
Library/Caches
Library/Logs
.CFUserTextEncoding
EOF
fi
# If the repository does not exist, initialize it.
# The user will be prompted for a password, which will be required for all
# future interactions with the repository.
if ! restic -r "${REPO}" snapshots &> /dev/null; then
if ! restic -r "${REPO}" snapshots >/dev/null 2>&1; then
echo "Restic repository not found or not accessible. Initializing..."
restic init -r "${REPO}"
fi
# --- Run Backup ---
echo "Starting restic backup..."
echo "Source: ${SOURCE_DIR}"
echo "Repository: ${REPO}"
BACKUP_CMD="restic backup \
--verbose \
--repo \"${REPO}\" \
--exclude-file \"${EXCLUDE_FILE}\" \
--one-file-system \
--tag \"macbook-backup\""
BACKUP_ARGS=(
"restic" "backup"
"--verbose"
"--repo" "${REPO}"
"--exclude-file" "${EXCLUDE_FILE}"
"--one-file-system"
"--tag" "macbook-backup"
)
if [[ -n "${UPLOAD_LIMIT}" ]]; then
BACKUP_CMD="${BACKUP_CMD} --limit-upload ${UPLOAD_LIMIT}"
BACKUP_ARGS+=("--limit-upload" "${UPLOAD_LIMIT}")
fi
BACKUP_CMD="${BACKUP_CMD} \"${SOURCE_DIR}\""
BACKUP_ARGS+=("${SOURCE_DIR}")
eval "${BACKUP_CMD}"
"${BACKUP_ARGS[@]}"
echo "Backup complete."

View File

@@ -72,15 +72,51 @@ shift # Consume the subcommand
# Separate arguments from the file to be signed
declare -a remaining_args
file_to_sign=""
f_provided=false
n_provided=false
I_provided=false
s_provided=false
while [[ "$#" -gt 0 ]]; do
# If we see a non-flag argument, assume it's the file to sign.
# This works because the file to sign is the only positional argument.
if [[ "$1" != -* ]] && [[ -z "$file_to_sign" ]]; then
file_to_sign="$1"
else
remaining_args+=("$1")
case "$1" in
-f)
[[ -z "${2:-}" ]] && error "Option -f requires an argument."
remaining_args+=("-f" "$2")
f_provided=true
shift 2
;;
-n)
[[ -z "${2:-}" ]] && error "Option -n requires an argument."
remaining_args+=("-n" "$2")
n_provided=true
shift 2
;;
-I)
[[ -z "${2:-}" ]] && error "Option -I requires an argument."
remaining_args+=("-I" "$2")
I_provided=true
shift 2
;;
-s)
[[ -z "${2:-}" ]] && error "Option -s requires an argument."
remaining_args+=("-s" "$2")
s_provided=true
shift 2
;;
-h|--help)
usage
;;
-*)
error "Unknown option: $1"
;;
*)
if [[ -n "$file_to_sign" ]]; then
error "Unexpected positional argument '$1' (already specified '$file_to_sign')."
fi
file_to_sign="$1"
shift
;;
esac
done
# --- Build command based on subcommand ---
@@ -90,18 +126,6 @@ CMD_ARGS=("ssh-keygen" "-Y" "$SUBCOMMAND")
# Append all the flag-based arguments (-f, -n, -I, -s)
CMD_ARGS+=("${remaining_args[@]}")
# Scan for provided flags to handle defaults correctly
f_provided=false
n_provided=false
I_provided=false
s_provided=false
for arg in "${remaining_args[@]}"; do
[[ "$arg" == "-f" ]] && f_provided=true
[[ "$arg" == "-n" ]] && n_provided=true
[[ "$arg" == "-I" ]] && I_provided=true
[[ "$arg" == "-s" ]] && s_provided=true
done
if [[ "$SUBCOMMAND" == "sign" ]]; then
if [[ -z "$file_to_sign" ]]; then
error "Path to file to be signed is required for 'sign' command."

View File

@@ -76,7 +76,8 @@ run_self_test() {
cat <<EOF > "${target}"
${key_man}
${key1} # This should be removed as it's now managed
# This is a manual annotation for key1
${key1}
EOF
echo "Executing script in test mode..."
@@ -107,6 +108,9 @@ EOF
echo -n "Check masking... "
if ! grep -q "masked" "${target}"; then echo "OK"; else echo "FAIL"; exit 1; fi
echo -n "Check user comment preservation... "
if grep -q "This is a manual annotation for key1" "${target}"; then echo "OK"; else echo "FAIL"; exit 1; fi
echo "Self-test passed successfully!"
exit 0
}
@@ -138,6 +142,40 @@ mkdir -p "$(dirname "${TARGET_FILE}")"
TMP_FILE=$(mktemp)
CLEANUP_FILES+=("${TMP_FILE}")
# Build a map of key-signature -> user comments from the existing target file.
# Comments above keys are preserved into the managed block (# Source: lines are excluded).
# Multiple comment lines are joined with SUBSEP (\034) for safe transport through AWK.
USER_COMMENTS_FILE=$(mktemp)
CLEANUP_FILES+=("${USER_COMMENTS_FILE}")
if [[ -f "${TARGET_FILE}" ]]; then
awk -v begin="${BEGIN_MARKER}" -v end="${END_MARKER}" '
BEGIN { pending="" }
$0 == begin { pending=""; next }
$0 == end { pending=""; next }
/^# Source:/ { next }
/^[[:space:]]*#/ {
pending = (pending == "" ? $0 : pending SUBSEP $0)
next
}
/^[[:space:]]*$/ { pending=""; next }
{
n = split($0, parts, " ")
sig = ""
for (i=1; i<=n; i++) {
sig = (sig == "" ? parts[i] : sig " " parts[i])
if (parts[i] ~ /^(ssh-|ecdsa-|sk-)/ && i < n) {
sig = sig " " parts[i+1]
break
}
}
if (sig != "" && pending != "") {
print sig "\t" pending
}
pending = ""
}
' "${TARGET_FILE}" > "${USER_COMMENTS_FILE}"
fi
collect_keys() {
local dirs=("${@}")
for dir in "${dirs[@]}"; do
@@ -158,7 +196,17 @@ collect_keys() {
}
# Use a HEREDOC for the complex AWK script to avoid shell interpolation issues
MANAGED_BLOCK=$(collect_keys "${SOURCE_DIRS[@]}" | awk -F'\t' '
MANAGED_BLOCK=$(collect_keys "${SOURCE_DIRS[@]}" | awk -F'\t' -v user_comments_file="${USER_COMMENTS_FILE}" '
BEGIN {
while ((getline line < user_comments_file) > 0) {
tab = index(line, "\t")
if (tab > 0) {
sig = substr(line, 1, tab - 1)
user_comments[sig] = substr(line, tab + 1)
}
}
close(user_comments_file)
}
{
# Splitting on the first tab manually to be robust
tab_idx = index($0, "\t")
@@ -191,6 +239,12 @@ END {
for (i=1; i<=count; i++) {
sig = order[i]
print "# Source: " sources[sig]
if (sig in user_comments) {
n = split(user_comments[sig], comment_lines, SUBSEP)
for (j=1; j<=n; j++) {
print comment_lines[j]
}
}
print keys[sig]
}
}')
@@ -206,6 +260,7 @@ if [[ -f "${TARGET_FILE}" ]]; then
fi
MANAGED_SIGS_TMP=$(mktemp)
CLEANUP_FILES+=("${MANAGED_SIGS_TMP}")
echo "${MANAGED_BLOCK}" | awk '/^[^#]/ {
n = split($0, parts, " ")
sig = ""

View File

@@ -1,7 +1,49 @@
#!/bin/sh
set -e
SKEL_DIR=$(dirname -- "$(readlink -f -- "$HOME/.profile")")
cd -- "$SKEL_DIR"
cd -- "$(git rev-parse --show-toplevel)"
set -eu
resolve_symlink() {
_target="$1"
if command -v readlink >/dev/null 2>&1 && readlink -f -- "$_target" >/dev/null 2>&1; then
readlink -f -- "$_target"
elif command -v python3 >/dev/null 2>&1; then
python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$_target"
else
while [ -L "$_target" ]; do
_dir=$(cd -P "$(dirname -- "$_target")" >/dev/null 2>&1 && pwd)
_target=$(readlink "$_target")
case "$_target" in
/*) ;;
*) _target="$_dir/$_target" ;;
esac
done
echo "$_target"
fi
}
if [ -e "$HOME/.profile" ]; then
TARGET=$(resolve_symlink "$HOME/.profile")
SKEL_DIR=$(dirname -- "$TARGET")
else
SKEL_DIR=""
fi
REPO_ROOT=""
if [ -n "$SKEL_DIR" ] && cd -- "$SKEL_DIR" 2>/dev/null; then
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
fi
if [ -z "$REPO_ROOT" ] || [ ! -f "$REPO_ROOT/install.sh" ]; then
SCRIPT_DIR=$(dirname -- "$(resolve_symlink "$0")")
if cd -- "$SCRIPT_DIR" 2>/dev/null; then
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
fi
if [ -z "$REPO_ROOT" ] || [ ! -f "$REPO_ROOT/install.sh" ]; then
echo "Error: Could not determine skel repository root." >&2
exit 1
fi
fi
cd -- "$REPO_ROOT"
git pull
./install.sh
./install.sh "$@"

65
deploy_checkout.sh Executable file
View File

@@ -0,0 +1,65 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
echo "Usage: $(basename "$0") [--dry-run] user@host" >&2
exit 1
}
DRY_RUN=0
REMOTE=
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run)
DRY_RUN=1
shift
;;
-h|--help)
usage
;;
--)
shift
break
;;
-*)
usage
;;
*)
if [[ -n "${REMOTE}" ]]; then
usage
fi
REMOTE="$1"
shift
;;
esac
done
if [[ $# -gt 0 || -z "${REMOTE}" ]]; then
usage
fi
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
if ! git -C "$SCRIPT_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "Error: $SCRIPT_DIR is not inside a git repository." >&2
exit 1
fi
if [[ "$DRY_RUN" -eq 1 ]]; then
archive_list="$(git -C "$SCRIPT_DIR" archive --format=tar HEAD | tar -tf - | sed 's#^\./##' | sed '/^$/d;/^\.$/d' | sort)"
remote_list="$(ssh "$REMOTE" 'if [ -d "$HOME/.skel" ]; then cd "$HOME/.skel" && find . | sed "s#^\./##" | sed "/^$/d;/^\.$/d" | sort; fi' || true)"
printf 'Would deploy HEAD from %s to %s:%s\n' "$SCRIPT_DIR" "$REMOTE" '$HOME/.skel'
printf 'Would replace remote ~/.skel with %s tracked paths\n' "$(printf '%s' "$archive_list" | awk 'NF { n++ } END { print n + 0 }')"
if [[ -n "$remote_list" ]]; then
printf 'Would remove %s existing remote paths not present in HEAD\n' "$(comm -13 <(printf '%s\n' "$archive_list") <(printf '%s\n' "$remote_list") | awk 'NF { n++ } END { print n + 0 }')"
else
printf 'Remote ~/.skel does not exist or is empty\n'
fi
exit 0
fi
git -C "$SCRIPT_DIR" archive --format=tar HEAD | \
ssh "$REMOTE" 'rm -rf "$HOME/.skel" && mkdir -p "$HOME/.skel" && tar -xf - -C "$HOME/.skel"'

View File

@@ -28,6 +28,9 @@ alias clear-gpg-agent="echo RELOADAGENT | gpg-connect-agent"
# Earthly ssh
alias earthly='earthly --ssh-auth-sock ""'
# ESP-IDF
alias activate_idf="source ~/.espressif/tools/activate_idf_v*.sh"
if [ "$(uname)" = "Linux" ]; then
# Cryptsetup alias
alias luksFormat='cryptsetup luksFormat --type=luks2 --pbkdf-memory=2560000 --pbkdf=argon2id -i 15000 -s 512 -h sha256 -c aes-xts-plain64'

View File

@@ -104,3 +104,9 @@
[rerere]
enabled = true
[lfs]
concurrenttransfers = 3
[lfs "customtransfer.xet"]
path = git-xet
args = transfer
concurrent = true

View File

@@ -4,16 +4,17 @@
# Should only use POSIX constructs.
# Always load ENV
test -f "$HOME/.shenv" && . "$HOME/.shenv"
test -f "${HOME}/.shenv" && . "${HOME}/.shenv"
# Setup GREP_COLORS
export GREP_COLOR='01;31'
export GREP_COLORS='mt=01;31:mc=01;31:ms=01;31'
# Setup LS_COLORS
if whence dircolors >/dev/null 2>&1 ; then
test -f "${HOME}/.dircolors" && \
eval "$(dircolors "${HOME}/.dircolors")"
if command -v dircolors >/dev/null 2>&1 && test -f "${HOME}/.dircolors" ; then
eval "$(dircolors -b "${HOME}/.dircolors" 2>/dev/null)"
elif command -v gdircolors >/dev/null 2>&1 && test -f "${HOME}/.dircolors" ; then
eval "$(gdircolors -b "${HOME}/.dircolors" 2>/dev/null)"
else
# Static solarized LS_COLORS
LS_COLORS='no=00:fi=00:di=34:ow=34;40:ln=35:pi=30;44:so=35;44:do=35;44:bd=33;44:cd=37;44:or=05;37;41:mi=05;37;41:ex=01;31:*.cmd=01;31:*.exe=01;31:*.com=01;31:*.bat=01;31:*.reg=01;31:*.app=01;31:*.txt=32:*.org=32:*.md=32:*.mkd=32:*.h=32:*.hpp=32:*.c=32:*.C=32:*.cc=32:*.cpp=32:*.cxx=32:*.objc=32:*.cl=32:*.sh=32:*.bash=32:*.csh=32:*.zsh=32:*.el=32:*.vim=32:*.java=32:*.pl=32:*.pm=32:*.py=32:*.rb=32:*.hs=32:*.php=32:*.htm=32:*.html=32:*.shtml=32:*.erb=32:*.haml=32:*.xml=32:*.rdf=32:*.css=32:*.sass=32:*.scss=32:*.less=32:*.js=32:*.coffee=32:*.man=32:*.0=32:*.1=32:*.2=32:*.3=32:*.4=32:*.5=32:*.6=32:*.7=32:*.8=32:*.9=32:*.l=32:*.n=32:*.p=32:*.pod=32:*.tex=32:*.go=32:*.sql=32:*.csv=32:*.sv=32:*.svh=32:*.v=32:*.vh=32:*.vhd=32:*.bmp=33:*.cgm=33:*.dl=33:*.dvi=33:*.emf=33:*.eps=33:*.gif=33:*.jpeg=33:*.jpg=33:*.JPG=33:*.mng=33:*.pbm=33:*.pcx=33:*.pdf=33:*.pgm=33:*.png=33:*.PNG=33:*.ppm=33:*.pps=33:*.ppsx=33:*.ps=33:*.svg=33:*.svgz=33:*.tga=33:*.tif=33:*.tiff=33:*.xbm=33:*.xcf=33:*.xpm=33:*.xwd=33:*.xwd=33:*.yuv=33:*.aac=33:*.au=33:*.flac=33:*.m4a=33:*.mid=33:*.midi=33:*.mka=33:*.mp3=33:*.mpa=33:*.mpeg=33:*.mpg=33:*.ogg=33:*.opus=33:*.ra=33:*.wav=33:*.anx=33:*.asf=33:*.avi=33:*.axv=33:*.flc=33:*.fli=33:*.flv=33:*.gl=33:*.m2v=33:*.m4v=33:*.mkv=33:*.mov=33:*.MOV=33:*.mp4=33:*.mp4v=33:*.mpeg=33:*.mpg=33:*.nuv=33:*.ogm=33:*.ogv=33:*.ogx=33:*.qt=33:*.rm=33:*.rmvb=33:*.swf=33:*.vob=33:*.webm=33:*.wmv=33:*.doc=31:*.docx=31:*.rtf=31:*.odt=31:*.dot=31:*.dotx=31:*.ott=31:*.xls=31:*.xlsx=31:*.ods=31:*.ots=31:*.ppt=31:*.pptx=31:*.odp=31:*.otp=31:*.fla=31:*.psd=31:*.7z=1;35:*.apk=1;35:*.arj=1;35:*.bin=1;35:*.bz=1;35:*.bz2=1;35:*.cab=1;35:*.deb=1;35:*.dmg=1;35:*.gem=1;35:*.gz=1;35:*.iso=1;35:*.jar=1;35:*.msi=1;35:*.rar=1;35:*.rpm=1;35:*.tar=1;35:*.tbz=1;35:*.tbz2=1;35:*.tgz=1;35:*.tx=1;35:*.war=1;35:*.xpi=1;35:*.xz=1;35:*.z=1;35:*.Z=1;35:*.zip=1;35:*.ANSI-30-black=30:*.ANSI-01;30-brblack=01;30:*.ANSI-31-red=31:*.ANSI-01;31-brred=01;31:*.ANSI-32-green=32:*.ANSI-01;32-brgreen=01;32:*.ANSI-33-yellow=33:*.ANSI-01;33-bryellow=01;33:*.ANSI-34-blue=34:*.ANSI-01;34-brblue=01;34:*.ANSI-35-magenta=35:*.ANSI-01;35-brmagenta=01;35:*.ANSI-36-cyan=36:*.ANSI-01;36-brcyan=01;36:*.ANSI-37-white=37:*.ANSI-01;37-brwhite=01;37:*.log=01;32:*~=01;32:*#=01;32:*.bak=01;33:*.BAK=01;33:*.old=01;33:*.OLD=01;33:*.org_archive=01;33:*.off=01;33:*.OFF=01;33:*.dist=01;33:*.DIST=01;33:*.orig=01;33:*.ORIG=01;33:*.swp=01;33:*.swo=01;33:*,v=01;33:*.gpg=34:*.gpg=34:*.pgp=34:*.asc=34:*.3des=34:*.aes=34:*.enc=34:*.sqlite=34:';
@@ -27,16 +28,16 @@ if [ "$(uname)" = "Darwin" ] ; then
fi
# Setup for libvirt
if [ -z "${LIBVIRT_DEFAULT_URI}" ] ; then
if [ "$(id -u)" = "0" ] || (id -g -n | grep -q "\blibvirt\b") ; then
LIBVIRT_DEFAULT_URI="qemu:///system"
export LIBVIRT_DEFAULT_URI
fi
if [ -z "${LIBVIRT_DEFAULT_URI:-}" ] ; then
export LIBVIRT_DEFAULT_URI="qemu:///system"
fi
# Got rust? (gvim, etc.)
if test -d "${HOME}/.cargo/bin" ; then
PATH="${PATH}:${HOME}/.cargo/bin"
case ":${PATH}:" in
*:"${HOME}/.cargo/bin":*) ;;
*) PATH="${PATH}:${HOME}/.cargo/bin" ;;
esac
fi
test -f "${HOME}/.profile.local" && . "${HOME}/.profile.local"

View File

@@ -45,3 +45,6 @@
hibernationfile
sleepimage
swapfile
# Android and other big tools
/Users/*/.android

View File

@@ -29,6 +29,9 @@ export WORKON_HOME="$HOME/.virtualenvs"
# GPG full key id
export GPG_ID=7FD58D9A196DCEEEAD671F94F4D7A7915DEA789B
# Capture uname early
_UNAME="$(uname)"
# things we need in all interactive shells
case "$-" in
*i*)
@@ -86,7 +89,6 @@ case "$-" in
;;
esac
# Opt out of .net telemetry
export DOTNET_CLI_TELEMETRY_OPTOUT=1
@@ -97,78 +99,145 @@ export LVM_SUPPRESS_FD_WARNINGS=1
export EARTHLY_SSH_AUTH_SOCK=""
# Handle SSH_AUTH_SOCK for tmux consistency
_SSH_AUTH_LINK="${HOME}/.ssh/ssh_auth_sock"
case "$-" in
*i*)
_SSH_AUTH_LINK="${HOME}/.ssh/ssh_auth_sock"
# Helper to check if a path is our link or points to it
_is_link_path() {
# Helper to check if a path is our link or points to it
_is_link_path() {
[ -z "$1" ] && return 1
[ "$1" = "${_SSH_AUTH_LINK}" ] && return 0
_target="${_SSH_AUTH_LINK:-${HOME}/.ssh/ssh_auth_sock}"
[ "$1" = "${_target}" ] && { unset -v _target; return 0; }
if [ -L "$1" ] && command -v readlink >/dev/null 2>&1; then
_T=$(readlink "$1")
# Handle relative symlinks
case "${_T}" in /*) ;; *) _T="$(dirname "$1")/${_T}" ;; esac
[ "${_T}" = "${_SSH_AUTH_LINK}" ] && return 0
[ "${_T}" = "${_target}" ] && { unset -v _target _T; return 0; }
unset -v _T
fi
unset -v _target
return 1
}
}
_CANDIDATE=""
# Helper to check if an SSH socket is valid and useful
_is_valid_ssh_sock() {
[ -z "$1" ] && return 1
[ -S "$1" ] || return 1
# 1. If current environment has a valid socket that is NOT our link, it's a prime candidate
# (e.g. fresh SSH login: sshd sets SSH_AUTH_SOCK to the raw forwarded socket before ssh/rc
# rewrites it to the stable symlink; the shell inherits the original raw path).
if [ -S "${SSH_AUTH_SOCK:-}" ] && ! _is_link_path "${SSH_AUTH_SOCK}"; then
_CANDIDATE="${SSH_AUTH_SOCK}"
fi
if command -v nc >/dev/null 2>&1; then
# Use nc to quickly check if the socket is listening.
# We use -N to shutdown the socket after EOF on stdin (for OpenBSD netcat compatibility).
if echo '' | nc -w 1 -N -U "$1" >/dev/null 2>&1; then
return 0
fi
fi
# 2. Only look for a system agent if the stable link is already broken. If the link is
# valid (e.g. a tmux pane where SSH_AUTH_SOCK points to our symlink which ssh/rc just
# updated to the forwarded socket), leave it alone — don't clobber it with a local agent.
if [ -z "${_CANDIDATE}" ] && [ ! -S "${_SSH_AUTH_LINK}" ]; then
_FOUND=""
if command -v ssh-add >/dev/null 2>&1; then
SSH_AUTH_SOCK="$1" ssh-add -l >/dev/null 2>&1
case "$?" in
0|1) return 0 ;;
*) return 1 ;;
esac
fi
if command -v nc >/dev/null 2>&1; then
return 1
fi
return 0
}
# Function to get the path to the socket for the local ssh-agent
get_local_ssh_agent_sock() {
_found=""
if [ "$(uname)" = "Darwin" ]; then
_FOUND=$(launchctl getenv SSH_AUTH_SOCK 2>/dev/null)
_found=$(launchctl getenv SSH_AUTH_SOCK 2>/dev/null)
elif command -v systemctl >/dev/null 2>&1; then
# Query systemd socket units directly to avoid environment overrides.
for _u in ssh-agent.socket openssh-agent.socket gcr-ssh-agent.socket gpg-agent-ssh.socket; do
_P=$(systemctl --user show "${_u}" -p Listen 2>/dev/null | cut -d= -f2- | cut -d' ' -f1)
if [ -S "${_P}" ]; then
_FOUND="${_P}"
_p=$(systemctl --user show "${_u}" -p Listen 2>/dev/null | cut -d= -f2- | cut -d' ' -f1)
if ! _is_link_path "${_p}" && _is_valid_ssh_sock "${_p}"; then
_found="${_p}"
break
fi
done
# Fallback to systemd environment
if [ -z "${_FOUND}" ] || _is_link_path "${_FOUND}"; then
_FOUND=$(systemctl --user show-environment 2>/dev/null | grep "^SSH_AUTH_SOCK=" | cut -d= -f2-)
if [ -z "${_found}" ] || _is_link_path "${_found}" || ! _is_valid_ssh_sock "${_found}"; then
_found=$(systemctl --user show-environment 2>/dev/null | grep "^SSH_AUTH_SOCK=" | cut -d= -f2-)
fi
fi
if [ -S "${_FOUND}" ] && ! _is_link_path "${_FOUND}"; then
_CANDIDATE="${_FOUND}"
if [ -n "${_found}" ] && ! _is_link_path "${_found}" && _is_valid_ssh_sock "${_found}"; then
echo "${_found}"
unset -v _found _u _p
return 0
fi
fi
# 3. Last resort: search common paths if we still don't have a candidate and the link is broken.
if [ ! -S "${_CANDIDATE}" ] && [ ! -S "${_SSH_AUTH_LINK}" ]; then
_U=$(id -u)
for _p in "/run/user/${_U}/keyring/ssh" "/run/user/${_U}/ssh-agent.socket" "/run/user/${_U}/openssh_agent" "/run/user/${_U}/gnupg/S.gpg-agent.ssh"; do
if [ -S "${_p}" ] && ! _is_link_path "${_p}"; then
_CANDIDATE="${_p}"
break
# Search common fallback paths
_u=$(id -u)
for _p in "/run/user/${_u}/keyring/ssh" "/run/user/${_u}/ssh-agent.socket" "/run/user/${_u}/openssh_agent" "/run/user/${_u}/gnupg/S.gpg-agent.ssh"; do
if ! _is_link_path "${_p}" && _is_valid_ssh_sock "${_p}"; then
echo "${_p}"
unset -v _found _u _p
return 0
fi
done
if [ -z "${_CANDIDATE}" ]; then
# Build search path list based on what actually exists
_SEARCH=""
for _d in "/run/user/${_U}" /tmp; do [ -d "${_d}" ] && _SEARCH="${_SEARCH} ${_d}"; done
if [ -n "${_SEARCH}" ]; then
_CANDIDATE=$(find ${_SEARCH} -maxdepth 2 -type s -name 'agent.*' 2>/dev/null | grep -F -v "${_SSH_AUTH_LINK}" | head -n 1)
fi
fi
fi
# 4. Sync the stable link if we found a valid "real" socket.
if [ -S "${_CANDIDATE}" ] && ! _is_link_path "${_CANDIDATE}"; then
# Search /run/user/UID and /tmp for agent.* sockets
_search=""
for _d in "/run/user/${_u}" /tmp; do [ -d "${_d}" ] && _search="${_search} ${_d}"; done
if [ -n "${_search}" ]; then
for _p in $(find ${_search} -maxdepth 2 -type s -name 'agent.*' 2>/dev/null); do
if ! _is_link_path "${_p}" && _is_valid_ssh_sock "${_p}"; then
echo "${_p}"
unset -v _found _u _p _search _d
return 0
fi
done
fi
unset -v _found _u _p _search _d
return 1
}
# Function to reset SSH_AUTH_SOCK to the local ssh-agent
reset_ssh_socket() {
_rss_sock=$(get_local_ssh_agent_sock)
if [ -n "${_rss_sock}" ]; then
_rss_link="${HOME}/.ssh/ssh_auth_sock"
mkdir -p "$(dirname "${_rss_link}")"
ln -sf "${_rss_sock}" "${_rss_link}"
export SSH_AUTH_SOCK="${_rss_link}"
if command -v systemctl >/dev/null 2>&1; then
systemctl --user set-environment SSH_AUTH_SOCK="${_rss_link}" 2>/dev/null
fi
echo "Reset SSH_AUTH_SOCK to ${_rss_link} -> ${_rss_sock}"
unset -v _rss_sock _rss_link
return 0
else
echo "reset_ssh_socket: no valid local ssh-agent socket found." >&2
unset -v _rss_sock
return 1
fi
}
_CANDIDATE=""
# 1. If current environment has a valid socket that is NOT our link, it's a prime candidate
# (e.g. fresh SSH login: sshd sets SSH_AUTH_SOCK to the raw forwarded socket before ssh/rc
# rewrites it to the stable symlink; the shell inherits the original raw path).
if ! _is_link_path "${SSH_AUTH_SOCK:-}" && _is_valid_ssh_sock "${SSH_AUTH_SOCK:-}"; then
_CANDIDATE="${SSH_AUTH_SOCK}"
fi
# 2. Only look for a system agent if the stable link is already broken. If the link is
# valid (e.g. a tmux pane where SSH_AUTH_SOCK points to our symlink which ssh/rc just
# updated to the forwarded socket), leave it alone — don't clobber it with a local agent.
if [ -z "${_CANDIDATE}" ] && ! _is_valid_ssh_sock "${_SSH_AUTH_LINK}"; then
_CANDIDATE=$(get_local_ssh_agent_sock)
fi
# 3. Sync the stable link if we found a valid "real" socket.
if [ -n "${_CANDIDATE}" ] && ! _is_link_path "${_CANDIDATE}" && _is_valid_ssh_sock "${_CANDIDATE}"; then
mkdir -p "$(dirname "${_SSH_AUTH_LINK}")"
ln -sf "${_CANDIDATE}" "${_SSH_AUTH_LINK}"
export SSH_AUTH_SOCK="${_SSH_AUTH_LINK}"
@@ -176,17 +245,18 @@ if [ -S "${_CANDIDATE}" ] && ! _is_link_path "${_CANDIDATE}"; then
if command -v systemctl >/dev/null 2>&1; then
systemctl --user set-environment SSH_AUTH_SOCK="${_SSH_AUTH_LINK}" 2>/dev/null
fi
elif [ -S "${_SSH_AUTH_LINK}" ]; then
elif _is_valid_ssh_sock "${_SSH_AUTH_LINK}"; then
# If we found nothing better but the link is valid, use it.
export SSH_AUTH_SOCK="${_SSH_AUTH_LINK}"
fi
fi
unset _SSH_AUTH_LINK _CANDIDATE _FOUND _T _P _U _u _SEARCH _d
unset -f _is_link_path
unset _SSH_AUTH_LINK _CANDIDATE
;;
esac
# Setup XDG-like dirs on MacOS
# Based on https://leebyron.com/til/mac-xdg/
if [ "$(uname)" = "Darwin" ] ; then
if [ "${_UNAME}" = "Darwin" ] ; then
export XDG_BIN_HOME="${XDG_BIN_HOME:-$HOME/.local/bin}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/Library/Caches}"
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
@@ -195,10 +265,12 @@ if [ "$(uname)" = "Darwin" ] ; then
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-$TMPDIR/runtime-$(id -u)}"
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
export PATH="${HOME}/bin/macos:${PATH}"
elif [ "$(uname)" = "Linux" ] ; then
elif [ "${_UNAME}" = "Linux" ] ; then
export PATH="${HOME}/bin/linux:${PATH}"
fi
unset _UNAME
if test -e "$HOME/.localenv"; then
# shellcheck source=/dev/null
. "$HOME/.localenv"

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDYQOAB5bJ9DjMXyY67GEI99kK1LG8XF+cWJ4md52rPnOeJd0da7l26bn9NtXCma6DP5gZQArfxHsPh7I4SbYJRYxTCCCE/Jsd8mLB22DcoeY+MqPA2g71j3KrYsvuJC++9GHK2Xc7ZRmhAugEmC/NAdtORBVhtBSAUgyCmUczKHoCAqHmq8j54En8kRYjbvlHPpDsNoRuhcH5uDGBIVkbV7UtBl2oUlRNVw7grs6XS7cPU2zCQSxcrRRuAfV4hmGG2eKaPpieNg0MAAbR0G5ssWW3IuYwd1ys5wA0YQuWUhxadUuYc46/cqyyoVIFlfjxCVTX+2w3900SDPOF/YrOwctAb23+78WN6GPnAmmS3zcmXTGsJiw/mmyBlqYI/JdSgrgI+COlcP0rlF/uklzEywfD91m1lno1u2IApdAumZWHR8aFnpHQXfI6rWc1o/V+RBpz5Xe6D2h9CPT3AE303BV09HGmidb0t6bCKoabTDwvE+KojIcbKBji6g8V6KTM=

View File

@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOP0EQthckpi83EoFXtbPnn4Ytd7FYW6Nb3W9ZahqOKhNAqv1owot957ihKHtGKFnYr0Jwgp0TNOdpz6nV9wwCo= david@zazu

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINFlZdKMzY8S/znw16R3X9jO+BaJ30NloH9XWtftjYh6 david@baymax.local

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBeDzE5KLJh2a9p0u702H9+rvaB1HoLLBU1I2Lx6NUbC david@scar

View File

@@ -0,0 +1 @@
sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBF8YzO0pEZ9DKHyqgPZpwlv6s4FBYDunIV23R4VUfiC3dw3P1vX9+tDO2+K65v+0vL2rAuBr5ZAHmDxiY8PzDwoAAAAEc3NoOg== david@zazu-sk

View File

@@ -1,8 +1,11 @@
# For interactive shells
[[ -n "$ZSH_PROFILE" ]] && {
zmodload zsh/datetime
zshrc_start_time=$EPOCHREALTIME
zmodload zsh/zprof
export PS4='+[%D{%f} / %D{%s.%N}] %N:%i> '
exec 3>&2 2>/tmp/zsh_startup.log
set -x
zshrc_start_time=$EPOCHREALTIME
}
HISTFILE=~/.zhistory
HISTSIZE=10000
@@ -129,7 +132,12 @@ case $TERM in
else
# this will also work in tmux but is not what we want
# Set the terminal title to include the command being run
# Skip adding (cmd) in iTerm2 — shell integration already injects the job name
if [[ -z "$ITERM_SESSION_ID" ]]; then
print -Pn "\e]0;%n@%m: %~ ($cmd)\a"
else
print -Pn "\e]0;%n@%m: %~\a"
fi
fi
}
# Add the hooks to zsh
@@ -298,6 +306,8 @@ typeset -U PATH
if [[ -n "$ZSH_PROFILE" ]]; then
zshrc_end_time=$EPOCHREALTIME
set +x
exec 2>&3 3>&-
# Calculation in ms using zsh floating point math
elapsed_ms=$(( (zshrc_end_time - zshrc_start_time) * 1000 ))
printf "zshrc done: %.0fms\n" "$elapsed_ms"

View File

@@ -14,4 +14,8 @@
have_command docker && \
missing_comp _docker && \
docker completion zsh > $COMPDIR/_docker || true
have_command resticprofile && \
missing_comp _resticprofile && \
resticprofile generate --zsh-completion > $COMPDIR/_resticprofile || true
} &>/dev/null &!

View File

@@ -72,3 +72,27 @@ function generate_secure_key {
local BYTES=$((BITS/8))
head -c "${BYTES}" /dev/urandom | ${(s: :)ENCODE}
}
function reset-ssh-socket {
reset_ssh_socket "$@"
}
function with-local-ssh-agent {
local sock
sock=$(get_local_ssh_agent_sock)
if [[ -z "${sock}" ]] ; then
echo "with-local-ssh-agent: no valid local ssh-agent socket found." >&2
return 1
fi
if [ "$#" -eq 0 ] ; then
(
export SSH_AUTH_SOCK="${sock}"
"${SHELL:-zsh}"
)
else
(
export SSH_AUTH_SOCK="${sock}"
eval "$@"
)
fi
}

View File

@@ -86,48 +86,6 @@ link_directory_contents() {
done
}
ssh_key_already_installed() {
# Return 1 if the key isn't already installed, 0 if it is
local AK="${HOME}/.ssh/authorized_keys"
if [[ ! -f "$AK" ]] ; then
return 1
fi
# Extract the key data (field 2) from the key file, ignoring comments
local key_data
key_data=$(awk '/^(ssh|ecdsa|sk)-/ {print $2}' "$1")
if [[ -z "${key_data}" ]]; then
# Not a valid key file
return 1
fi
# Use grep with fixed-string matching to see if the key is present.
# The exit code of grep is 0 on match, 1 on no match, which is perfect.
grep -F -q -- "${key_data}" "${AK}"
}
install_ssh_keys() {
# Install SSH keys
verbose 'Installing SSH keys...'
local AK="${HOME}/.ssh/authorized_keys"
local key
local keydir
if [[ "${TRUST_ALL_KEYS}" = 1 ]] ; then
keydir="${BASEDIR}/keys/ssh"
else
keydir="${BASEDIR}/keys/ssh/trusted"
fi
for key in "${keydir}"/* ; do
if [[ ! -f "${key}" ]] ; then
continue
fi
if ssh_key_already_installed "${key}" ; then
verbose "Key $(basename "${key}") already installed..."
continue
fi
echo "# $(basename "${key}") added from skel on $(date +%Y-%m-%d)" >> "${AK}"
cat "${key}" >> "${AK}"
done
}
install_gpg_keys() {
have_command gpg || \
return 0
@@ -172,7 +130,10 @@ install_known_hosts() {
}
install_keys() {
install_ssh_keys
if [[ -x "${BASEDIR}/bin/update-authorized-keys" ]]; then
verbose 'Installing SSH keys via update-authorized-keys...'
printf 'y\n' | "${BASEDIR}/bin/update-authorized-keys"
fi
install_gpg_keys
install_known_hosts
}
@@ -190,13 +151,12 @@ read_saved_prefs() {
save_prefs() {
[[ "$SAVE" = 1 ]] || return 0
local pref_file=${BASEDIR}/.installed-prefs
local pref_file="${BASEDIR}/.installed-prefs"
{
echo "BASEDIR=\"${BASEDIR}\""
echo "MINIMAL=\"${MINIMAL}\""
echo "INSTALL_KEYS=\"${INSTALL_KEYS}\""
echo "TRUST_ALL_KEYS=\"${TRUST_ALL_KEYS}\""
echo "VERBOSE=\"${VERBOSE}\""
printf 'BASEDIR=%q\n' "${BASEDIR}"
printf 'MINIMAL=%q\n' "${MINIMAL}"
printf 'INSTALL_KEYS=%q\n' "${INSTALL_KEYS}"
printf 'VERBOSE=%q\n' "${VERBOSE}"
} >| "$pref_file"
}
@@ -245,8 +205,7 @@ install_starship() {
echo "apt-get install starship failed, installing locally" >&2
fi
local tmpd
tmpd="$(mktemp -d tmp.starship.XXXXXX)" || return 1
trap '[[ -n "${tmpd}" && -d "${tmpd}" ]] && rm -rf "${tmpd}"' EXIT
tmpd="$(mktemp -d "${TMPDIR:-/tmp}/starship.XXXXXX")" || return 1
local install_path="${tmpd}/install.sh"
if have_command curl ; then
@@ -256,7 +215,6 @@ install_starship() {
else
echo "No curl or wget available!!" >&2
rm -rf "${tmpd}"
trap - EXIT
return 1
fi
local dl_hash
@@ -265,20 +223,17 @@ install_starship() {
echo "Hash check failed!!" >&2
echo "Expected: ${STARSHIP_INSTALL_HASH}, got ${dl_hash} on ${install_path}" >&2
rm -rf "${tmpd}"
trap - EXIT
return 1
fi
if sudo_group ; then
if maybe_sudo sh "${install_path}" ; then
rm -rf "${tmpd}"
trap - EXIT
return 0
fi
echo "root installation failed, falling back to user-local" >&2
fi
sh "${install_path}" -b "${LOCAL_BIN}"
rm -rf "${tmpd}"
trap - EXIT
}
install_main() {
@@ -353,7 +308,6 @@ read_saved_prefs
: ${BASEDIR:=${SCRIPT_DIR}}
: ${MINIMAL:=0}
: ${INSTALL_KEYS:=1}
: ${TRUST_ALL_KEYS:=0}
: ${VERBOSE:=0}
: ${SAVE:=1}

View File

@@ -1,3 +1,51 @@
|1|ZWm0E5aueYzKuoY8OrGAI2ZUdWI=|L8KgVjGyomaw47OGrhpPnipXDKU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKX08QrgyP7du28Re9NlKxLm6aJFUD4F2vWBCuiqo7KNrIPbgjVP9yOwy2gXueC6fbuVQj/C4BdnkgHw9hFXbC0=
|1|MjwrIkZqV0wbZ7pWue9nsFREyhk=|lGN2O8BcMHleUkD4yBtYRXSm1Yw= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwbTUJWJ3mytxrYPKrzRDIuBRd+/X/3T/QT2gudQfDN/mxkAMTg+uLoObXnUOtfhXD+lXP/s/GKXoPmsV/ausSz2YxBrQQXH7SwCpUq5GRXcl5s43JAJ1MbQq2EA5pa1CEBzUgd/Osu/WaVsKwfABV7QeKhblMfM0a5XcsfawqVbMJ0q/egYiSsWRVTU2iNMXILChJT6WUVoUiDENRnW98iy1qQgY0ge6hr7Gh6m23Fg6yfYDBQrqszbTfFYlqGe54bGlnxZvGp+Ybas02D29whAHwdNCSmDWXW0EvSpyt9WZUm0WOQt3t9RXpKeKLrWH4V/5BFYrONY1GsKuE783tw==
|1|UsEB5ylyIdmc4gs4TsYqE570DWY=|HAKqUTgFyTzodg8h6veV5jIa9GY= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC75TncmMQKEnnyw1S/uHcvs88d2M1NTMSUZyqdvFbx/uRB2rlrJiQHK8vyvN+fgRH5x8vde+vz/lAFgySV9RoS676cMuBIC8usF8REX2ghSXiSoGw35gd2ztGiDdU7FLUQYW+8FkR1soRjKZgyHqP/NCr4jBXjqDawDE33MA5LdmYy7fl1RN3oK4sY+LIoUWVv5x1aJdV86m0zbciavpU5szL++rnwcx+nWjDFFP4ntH1XyPGftyYpIAZwX+2Vl0+uMgv6sHazOx1E6vOIMx1UapCeLyWXzJ49P8K4iBZcNPH6h9aYllF4PIJ97Auh+fpFKBPfmHLq4iKCz4kKByy7
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
ts-jumpbox.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKwbpYiRqlgLKbaUlt1k4ms14+vTW8LKequepWdqDUUx
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
ts-jumpbox.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2itf2fAUO5OB7BNAL9Js8pmxIwzLnOxRMexf5KGswUQRvaZwtw1CitJiyEcYWBt7zksd/Pupmp42ikPVoH7myQlWRbeEmJEIlMvkFF0pjAWj9kGKVLyFDbqXSkewKtXwbJHSo0l+mEOyq8NLlOwAA977BzNTn4z3KQEfYBQQEqISa8NuLpVOFvtQfvBlW+Xeh6+rIm54gdJVDWRimvZ5/FUMaRHPBdMFcXZW1GpraAHjHMeJXTIJs10qFy+5RwGTL5UlvssI+IPAIAW7o0goWmCnrlTjhvJ3Mnwq2lQhAuH/aDqVTptXwMni8tkvPFEC4LeoXG9pmb04Fd6bxY4RnvWuTmcvqOGAxJmZcqOYp1qWhyIF4TTB5l4h3J27sUtluEkTbIGtxTcPjFYLLC1lyIweoQSjWTmi5Z4wz1qfxIYZY1UXnyAjILvLAA5XAIpTgVfDx9KMAFdRrqaKN1MMFvfkTy7CZOfIkWhBwuOxMmtknsiJi8INZc+2CWUuI3Q8=
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
ts-jumpbox.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFs4yUU1aYjy5kq0vr8PFEJUA5s90lYzFTXwHuL9JwtL/wi7tC3I1ifyQnzfZIT8ORMHNGdz/DjNyKkE/rfDhEc=
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
omega.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQD7TIDPujGWOMkltfBUKoXOIX9W6KBbqT4qfANNivyjvYeS2joncfoCHTws3vTofHjfyzUSFpnjJSjbwoqTK38CsqSMx06KgpOiiz03+OVbtoBKiwY7smYXh2/vB53+EV4fnM1u/6AqAn0FYT/lUjaY6kBWDppW7PbFKRtO+wShMNfbaY1BTDyEEZRU3PCxR4UDXFO7fQLBiQb/XOyxsSXdRtP6BPrpqxUSq/hNchRo4AP08wtEY5iW9po1RMOFAMKPDND34CyWGbtfnpUCAk9jwKrKDRibRZgIe/xWNcXY9P9zuCSMByB3npo2lG2Em/usiO2awY1pcfrHrlfxJFnD+rzQ9LELwvSB8kPd5xlxZjqmNIvACGEYzR2zdbeOXy+G7biQ7cgELIFRF9aDKOe68sSss3SdS2suAXpqtNBE6l8T9u2jUD0po5EsDcNXPHCS8YLq4wyTpkeDAchX4xm8srycvPD9h4UAE9k+QqjkkbUQw/xpx0SL4pq8Xi6VuO0=
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
omega.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL9cVRkixwE7KL112abP+GosO9+MiVUZQqUdRh4ps5O733cJ8tvkqLVkJhEejIFX6BLlmh/l+j/mD4Z8dL/YqmU=
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
omega.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMoxyWy+cXdpxh/KOhbvzB8Tq7NgWTHofOOpeVzuESe0
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
xi.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCosFo3gGbGQ7PvHzVZ50umQNEILsqkHWnDi2FqHBCV/pQKUlZVuBO2HT0MiV3QkascJ58P4Jj1Ft/ILKvrU5/dDsW8xVs3vJlmHPrmovD93VwuarzlokmzxWPFOEPZIPcQcQcMCt6k4p/6Pb6hbmPGML2N7XGQHGVDFcflusx07wj56lP9xUtdOLcIo9u3rgw2puXqxUNRtx12Dfo9rjGiFFCXCrvFV5BG4utHKSyAOckJQ/oTzy++idM7jaPbnQ0qjH4GMHm2HN8bmWJdHjc6BeBEW4iQrUxNeisM/hKiICZ3kUmeEynx6IlgEXm0UT+AhxZL7BQo9X45pj5AvaU5
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
xi.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN49oL4rzjwfz5F7cUuVhqe9vRzDAE16O5NQvslhpOx3VA7g8qjyK4SmhhRll+N7vS7OvUqswjEIOXFdK2DUGq8=
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
xi.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIg6N+lwA6feLnLDlm6Ssp45YjnaeCCQSBzeidmAb7FY
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
chi.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7jSON+Pum/scQMwiBH0jI2fKfQ4q6YKBf/Q/uU7RiEzr3g5lRLA3RtFfWYlxSVqRdlQgeTvIRqG6VMQjtxm/UiLaNT82dVSgoSwJnODVWsKzWQNY1nkhGgd/Ue/XQrBi6UFB7QU7iiIHn8FmJDh05jLv4ymp3DuUM6W066cHqVMSslVhsioAJeZJdpFFK0WXbWs8PT83LT1LERP8CMWuaVlF4UxWwaxROA4WwWaUtiMm0e7T9AgCkHmmEWJemrJqkKUBU0BaqyIvF2bP4tNrZXM8EzT+2Dg25BWS6DzP/d7m8umrpQrYP7cbhK0jzNXw/niEjQ7f8ZiuguRGwWBKX0XjMPY36uiBE/bkGiyF2t27nSPyoA/I2CYtArAabVmiNTeK6qpgf1Xo+aBFuotS3+4Ql+9kfzO9ZL05xIBC2PzvL1pqWmTHI4GICLS2EdMks8LW5ZxvjMS0OdrVf1KaMgmr8TbJT+NIqs1SF3H5kmWUtMvQd4YJgU+o88/sO9LM=
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
chi.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIo6eEuZ1F1GGnkJqkyUTj4oGZlcADbmdahSiwif6pWcx6uGdSemPjQmhFknPbzpzH8HIUtrg/NSBGAjwVINz5Q=
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
chi.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINVUVuOLnuVRiUptQxn+HlUtgv4i5+DMK4uyN4voCB1R
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
tau.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMUffrd05Q6iyHj1vbvBzD+xWqR6c/YivTieWVim+b2wHEEYyh7eHXzldXZdLP3QOQHXWc68QwfSav5jsrVhsxk=
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
tau.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/vDSvxXQa20+5OjgQpzxMQZR3m80fsIzHNqfjjAGlVTfPuccMnfCXNgQc8mY8qQTMxbBU4ZlSjntjyIBhWoj5flrTpVjHJgAkntu1dhtDYOp8sd+9CsR/40SX/1l8d6fRzuPSZaVO+RpF9Ym/MrxYH8YprBswl4pzT3/DVCgq3DDNocLzmyjMCgQJXxYpKhlnRSxhLvPHeAi4p0/gHmYhtQe4r0DZ/QaU6a/4bU2shGQyKBUUJbRTrNYwAEukZk+U5AkoQ7N43THB1PtdC0PwmaD2yXHiKzR/6SfLWRBE6TqyQKB0R8+lWWIU5s0Nu512UUS78bchkTtU0mgTpQWP
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
tau.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9+GZcp2imEoxDKY3rxdwGARZ6o/vmPCqrRF9ghxhLa
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4
zeta.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBOPOADAIuJ/khxquXi1/wHyJUp1LqmfLVuHnGoqYouZc7AKcwWDOd30p5bSbrgGMXQC6oflMUsL1VL8hyqZPhs=
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4
zeta.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWTvGafS9utruAmLpDdohEiEWSWVq3H6Mj1Z/hwnjVn67UncYDwLJjZem22r6qnW9h8hF9qpIG+XtU9Yk4iEvUk2H9S3gb7UOxwJ29lx2ckFp8V8Ml9t9gwrNpCVL+oiLm+iCmYMctksWbNXuiGRX22/qfeiM2zwyV3tEWbs/ePtVs5RX0EhbqPR5NHazy0NspE+lLsKeoGT5KsjyehStY69ER4iPKJzeiUxYfXj9wafniNiPZPV9jCDH4DIhkUWoOc1DF0cItVGLRnAWFoAEaWoIfC4ou33cuIfk810kf9uwSTgjVtGiGOC9Pemfc3RsFiUtlg4wpyAerBIvJlvrMAdPRhd1Pteg6QzWYbz0/3dGtyURjRg3uZQIiMre3zHHSKDQbdBL5C+9dM+d/PMdN+86GgwfymPHLoUsRpoY/1yxxqq8Zjc7D40amParpXHOkPzMLJy1F8d10QB52ZDx/7ivuPK55WaWiL3jcBLdim/I2te8EWwR0IgKGlkRYL88=
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4
zeta.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLOty9tztaPoyNUY50daxN3l8rM5+Eg1vMfqefgHWLT
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4