# # ~/.bashrc # # If not running interactively, don't do anything [[ $- != *i* ]] && return alias ls='ls --color=auto' PS1='[\u@\h \W]\$ ' # Source machine-specific config [[ -f ~/.machine_config ]] && source ~/.machine_config # nnn if [ -f /usr/share/nnn/quitcd/quitcd.bash_sh_zsh ]; then source /usr/share/nnn/quitcd/quitcd.bash_sh_zsh fi alias ssh="TERM=xterm-256color ssh" # NNN configuration alias nnn="VISUAL=$HOME/.local/bin/vim-wrapper nnn -e" # SSH without checking or adding host keys to known_hosts # Useful for cloud server rescue environment & installation alias sshtmp="ssh -o 'UserKnownHostsFile /dev/null' -o 'StrictHostKeyChecking no'" alias moshtmp="mosh --ssh=\"ssh -o 'UserKnownHostsFile /dev/null' -o 'StrictHostKeyChecking no'\"" # SSH with automatic "screen" function sshscr() { [ -z "$1" ] && return ssh -t $@ screen -RR -d } function moshscr() { [ -z "$1" ] && return mosh $@ -- screen -RR -d } # Alternative SSH session for unlocking remote encrypted servers # This requires a standalone known hosts file function sshunlock() { set -o pipefail pass show "$2" | wl-copy if [ $? -ne 0 ]; then echo "key not found" return fi ssh -o UserKnownHostsFile=~/.ssh/known_hosts_unlock root@$1 echo "" | wl-copy set +o pipefail } # Show a menu of all known Tailscale nodes for the user to select from function tsselect() { local jq_filter="$1" [ -z "$jq_filter" ] && jq_filter=".Peer[] | .DNSName" local items=() while read -r line; do [ -z "$line" ] && continue [[ "$line" =~ ^\# ]] && continue items+=("$line") done <<< $(tailscale status -json | jq -r "$jq_filter" | sort) _COLUMNS=$COLUMNS # Force options to display in one column COLUMNS=80 while [ "${#items[@]}" -gt 1 ]; do select item in "${items[@]}" Cancel; do if [[ "$REPLY" =~ ^[0-9]+$ ]]; then # Number selections -- break immediately if [ $REPLY -eq $((1 + ${#items[@]})) ]; then items=("") break elif [ $REPLY -le ${#items[@]} ]; then items=("${items[$((REPLY - 1))]}") break fi fi # Not a number selection -- filter the items items=($(printf "%s\n" "${items[@]}" | grep -E "^$REPLY")) break done done COLUMNS=$_COLUMNS if ! ([[ "$REPLY" =~ ^[0-9]+$ ]] || [ "$REPLY" == "${items[0]}" ]); then echo -n "${items[0]}? (y/n) " >&2 read yn [ "$yn" == "y" ] || return 1 fi echo "${items[0]}" } # SSH shorthands, same as before but for tailscale nodes function moshscrts() { moshscr $(tsselect) } function sshscrts() { sshscr $(tsselect) } function _ssh() { [ -z "$1" ] && return ssh $@ } function sshts() { _ssh $(tsselect) } # SSH shorthands for WezTerm function assert_wezterm() { [ "$TERM_PROGRAM" == "WezTerm" ] } # sshwez and sshmuxwez are used for spawning tabs in WezTerm # that uses its native multiplexer; this is useful for connecting # to home servers etc. and make use of WezTerm's native panes function sshwez() { assert_wezterm || return wezterm cli spawn --domain-name "SSH:$1" } function sshmuxwez() { assert_wezterm || return wezterm cli spawn --domain-name "SSHMUX:$1" } # moshwez{,ts,scrts} simply runs mosh inside a new WezTerm tab # Ideal for remote connections function moshwez() { assert_wezterm || return wezterm cli spawn -- mosh "$@" } function moshwezts() { moshwez $(tsselect) } function moshwezscrts() { moshwez $(tsselect) -- screen -RR -d } # Switch tailscale exit nodes function tsexit() { echo "Current exit node: $(tailscale status -json | jq -r ".Peer[] | select(.ExitNode == true) | .DNSName")" local newsel="$(tsselect ".Peer[] | select(.ExitNodeOption == true) | .DNSName")" [ -z "$newsel" ] || sudo tailscale set --exit-node="$newsel" --exit-node-allow-lan-access=true } function tsnoexit() { sudo tailscale set --exit-node="" --exit-node-allow-lan-access=false } # Add local to path export PATH="$PATH:~/.local/bin" # Password Store export PASSWORD_STORE_ENABLE_EXTENSIONS=true # Use gpg-agent-ssh export SSH_AUTH_SOCK=/run/user/$(id -u)/gnupg/S.gpg-agent.ssh # Miscellaneous utilities function clamp_filename() { [[ -z "$1" ]] && return 1 local len="$1" for file in *; do local filename_len=$(echo "$file" | wc -c) if [ $filename_len -gt $len ]; then local extension="${file##*.}" local filename="${filename%.*}" if [ ${#extension} -gt 5 ]; then filename="$file" extension="" fi local clamped_filename="$(echo "$file" | cut -c1-$((len - ${#extension})) | iconv -f utf8 -t utf8 -c -)" if [ ${#extension} -gt 0 ]; then clamped_filename="$clamped_filename.$extension" fi echo "File '$PWD/$file' clamped to '$PWD/$clamped_filename'" mv "$file" "$clamped_filename" file="$clamped_filename" fi if [ -d "$file" ]; then pushd "$file" > /dev/null clamp_filename "$1" popd > /dev/null fi done } function open_nas_decrypt() { gocryptfs -passfile /dev/stdin "$MACHINE_NAS_CIPHER_PATH" "$MACHINE_NAS_DECRYPT_PATH" <<< "$(pass gocrypt show "$MACHINE_NAS_CIPHER_PASS")" } function close_nas_decrypt() { fusermount -u "$MACHINE_NAS_DECRYPT_PATH" }