general fixes
[distro-setup] / brc2
diff --git a/brc2 b/brc2
index a28d7b7e970a94cc580735002110a3ea675df1b4..6ac51839640d6b111de332c2196a89468ff154f4 100644 (file)
--- a/brc2
+++ b/brc2
@@ -83,15 +83,6 @@ else
   export NOT_MAIL_HOST_P=t
 fi
 
-
-source /a/bin/log-quiet/logq-function
-
-# not used
-# if [[ -s /a/opt/alacritty/extra/completions/alacritty.bash ]]; then
-#   source /a/opt/alacritty/extra/completions/alacritty.bash
-# fi
-
-
 source /a/bin/ds/beet-data
 
 
@@ -181,7 +172,7 @@ slemacs() {
 
 sle() { # sl emacs
   local f=/home/iank/.emacs.d/init.el
-  sl --sl-test-cmd ". /etc/os-release ; printf %s \${VERSION//[^a-zA-Z0-9]/}; test -e $f && stat -c%Y $f" --sl-test-hook slemacs "$@"
+  sl --sl-test-cmd "sed -rn '/^VERSION=/{s/^.*=//;s/[^[:alnum:]]//gp}' /etc/os-release; test -e $f && stat -c%Y $f" --sl-test-hook slemacs "$@"
 }
 ccomp ssh sle
 
@@ -450,7 +441,7 @@ ralerts() { # remote alerts
 ap() {
   # pushd in case current directory has an ansible.cfg file
   pushd /a/xans >/dev/null
-  ansible-playbook -v -l ${1:- $(hostname -f)} site.yml
+  ansible-playbook -v -i ${1:- $(hostname -f)}, site.yml
   popd >/dev/null
 }
 aw() {
@@ -840,9 +831,10 @@ mpvrpc-loadfile() {
 # q quit
 # ret next
 #
+# todo: enter should also unpause
 beetag()  {
   local last_genre_i fstring tag id char new_item char_i genre tag remove doplay i j random path
-  local do_rare_genres read_wait help line lsout tmp ls_line skip_lookback
+  local do_rare_genres read_wait line lsout tmp ls_line skip_lookback
   local escape_char escaped_input expected_input skip_input_regex right_pad erasable_line seek_sec
   local pl_state_path pl_state_dir pl_state_file tmpstr
   local new_random pl_seed_path seed_num seed_file fmt first_play repeat1
@@ -1512,7 +1504,6 @@ btrbk-host-debug() {
 
 # $ dig ns1.gnu.org @b0.org.afilias-nst.org.
 
-# todo: make sm pull/push use systemd instead of the journal cat command
 bbk() { # btrbk wrapper
   local ret=0
   c /
@@ -1791,21 +1782,13 @@ bindpush() {
   dsign iankelling.org expertpathologyreview.com zroe.org amnimal.ninja
   lipush
   for h in li bk; do
-    e sshing $h
-    ssh $h.b8.nz <<'EOF'
-source ~/.bashrc
-m dnsup
-EOF
+    m ssh $h.b8.nz dnsup
   done
 }
 bindpushb8() {
   lipush
   for h in li bk; do
-    e sshing $h
-    ssh $h.b8.nz <<'EOF'
-source ~/.bashrc
-m dnsb8
-EOF
+    m ssh $h.b8.nz dnsb8
   done
 }
 
@@ -1816,8 +1799,18 @@ dnsup() {
 dnsb8() {
   local f=/var/lib/bind/db.b8.nz
   m ser stop named
-  m sleep 1
-  m sudo rm -fv $f.jnl $f.signed.jnl
+  # jbk is like a temp file. dunno if removing it helps
+
+  i=0
+  while pgrep '^named$' &>/dev/null; do
+    sleep .5
+    i=$(( i + 1 ))
+    if (( i > 100 )); then
+      echo "dnsb8: error: timeout waiting for named to exit"
+      return 1
+    fi
+  done
+  m sudo rm -fv $f.jnl $f.signed.jnl $f.jbk
   m sudo install -m 644 -o bind -g bind /p/c/machine_specific/vps/bind-initial/db.b8.nz $f
   m ser restart named
 }
@@ -1861,7 +1854,13 @@ dsign() {
 # set day start for use in other programs.
 # expected to do be in a format like 830, or 800 or 1300.
 ds() {
+  local regex
+  regex='[0-9]?[0-9]?[0-9][0-9]'
   if [[ $1 ]]; then
+    if [[ ! $1 =~ $regex ]]; then
+      echo "ds: error. expected \$1 to match $regex, got \$1: $1"
+      return 1
+    fi
     echo $1 >/b/data/daystart
   else
     cat /b/data/daystart
@@ -2004,8 +2003,8 @@ apache-header() {
 # https://www.gnu.org/licenses/license-recommendations.en.html. They
 # recommend that small programs, < 300 lines, be licensed under the
 # Apache License 2.0. This file contains or is part of one or more small
-# programs. If a small program grows beyond 300 lines, I plan to switch
-# its license to GPL.
+# programs. If a small program grows beyond 300 lines, I plan to change
+# to a recommended GPL license.
 
 # Copyright 2024 Ian Kelling
 
@@ -2055,6 +2054,7 @@ apache-apply() {
 }
 # strip out the apache license from a file.
 apache-strip() {
+  # shellcheck disable=SC2044 # meh
   for f in $(find . -type f -maxdepth 1); do if head -n1 "$f"| grep -E '^#!/bin/bash\b' &>/dev/null; then { head -n 20 $f | tac | sed '/^# limitations under the License.$/,/^# Copyright.*Ian Kelling$/d' | tac; tail -n+21 $f; } |sponge $f; fi ; done
 }
 
@@ -2345,8 +2345,8 @@ rename-test() {
   # test whether missing files were renamed, generally for use with fsdiff
   # $1 = fsdiff output file, $2 = directory to compare to. pwd = fsdiff dir
   # echos non-renamed files
-  local x y found
-  unset sums
+  local x line found renamed
+  local -a sums
   for x in "$2"/*; do
     { sums+=( "$(md5sum < "$x")" ) ; } 2>/dev/null
   done
@@ -2398,8 +2398,8 @@ gup() { /a/f/gnulib/build-aux/gnupload "$@"; }
 
 dejagnu() { /a/opt/dejagnu/dejagnu "$@"; }
 
+# do git status on published repos.
 hstatus() {
-  # do git status on published repos.
   c /a/bin/githtml
   for x in *; do
     cd "$(readlink -f $x)"/..
@@ -2413,6 +2413,16 @@ hstatus() {
   done
 }
 
+hsk() {
+  local x
+  c /a/bin/githtml
+  for x in *; do
+    cd "$(readlink -f $x)"/..
+    skgit
+    cd /a/bin/githtml
+  done
+}
+
 ## work log
 #
 # note: database location is specified in ~/.timetrap.yml, currently /p/.timetrap.db
@@ -2570,10 +2580,13 @@ ilog-local() {
   done
 }
 ilog() {
-  local chan
+  local chan tmpf
+  tmpf=$(mktemp)
   chan="${1:-#fsfsys}"
   # use * instead of -r since that does sorted order
-  sl root@iankelling.org ilog-local "$chan" | less +G
+  sl root@li.b8.nz ilog-local "$chan" > $tmpf
+  less +G $tmpf
+  rm -f $tmpf
 }
 
 o() {
@@ -2628,22 +2641,147 @@ wgkey() {
   umask $umask_orig
 }
 
-declare -A vpn_ips
-vpn_ips[kd]=2
-# note: 1, 4, 5 are occupied by mail wireguard
-vpn_ips[x3]=8
-vpn_ips[sy]=12
-vpn_ips[x2]=13
-vpn_ips[kw]=27
-vpn_ips[bo]=28
-vpn_ips[frodo]=34
-vpn_ips[s23b]=49
+host-info-all() {
+  host-info-update
+
+  bindpushb8
+  # for wireguard configs
+  ssh iank@li.b8.nz conflink
+  wrt-setup
+}
+
+
+
+
+
+## for updating host info like ip, location, update /p/c/host-info and
+## host_info below. the host_info array should probably be in its own
+## file that gets sourced so that it can be more easily updated.
+
+# todo: this is so long that it becomes confusing,
+# try to split it up.
+#
+# To make some changes take effect, run host-info-all.
+host-info-update() {
+
+  local -A vpn_ips host_ips host_macs portfw_ips nonvpn_ips all_ips
+  local -a root_hosts nonroot_hosts
+
+  # the hosts with no mac
+  root_hosts=( bk je li b8.nz )
+  for h in ${root_hosts[@]}; do
+    root_hosts+=(${h}ex)
+  done
+  root_hosts+=(cmc)
+
+  while read -r ip host mac opts; do
+    if [[ $ip == *#*  || ! $host ]]; then continue; fi
+
+    # opt parsing
+    vpn=false
+    root=false
+    for opt in $opts; do
+      case $opt in
+        user=root)
+          root=true
+          ;;
+        vpn)
+          vpn=true
+          ;;
+      esac
+    done
+
+    all_ips[$host]=$ip
+    if $vpn; then
+      portfw_ips[$host]=$ip
+      vpn_ips[$host]=$ip
+    else
+      nonvpn_ips[$host]=$ip
+    fi
+    if $root; then
+      # note: the reason we have b8.nz suffix here but not for non_root
+      # hosts is that it is for the User part, the IdentityFile part is
+      # redundant to *.b8.nz. Also note ${host}i, we only setup those for vpn hosts, but there is no harm in overspecifying here.
+      root_hosts+=($host ${host}i $host.b8.nz ${host}i.b8.nz)
+      root_hosts_a[$host]=t  # a for associative array
+    else
+      nonroot_hosts+=($host ${host}i)
+    fi
+    host_ips[$host]=$ip
+    if [[ $mac ]]; then
+      host_macs[$host]=$mac
+    fi
+
+  done </p/c/host-info
+
+  {
+    cat <<EOF
+Host ${nonroot_hosts[@]}
+User iank
+IdentityFile ~/.ssh/home
+
+Host ${root_hosts[@]}
+IdentityFile ~/.ssh/home
+
+EOF
+    for host in ${!vpn_ips[@]}; do
+      ipsuf=${vpn_ips[$host]}
+      cat <<EOF
+Host ${host}i ${host}i.b8.nz
+Port $((2200 + ipsuf))
+EOF
+    done
+
+    # convenience of one auth key entry
+    for host in ${!all_ips[@]}; do
+      cat <<EOF
+Host $host ${host}i $host.b8.nz ${host}i.b8.nz
+HostKeyAlias $host.b8.nz
+EOF
+    done
+  } | cedit -e /p/c/subdir_files/.ssh/config-static
+
+  {
+    # hack to please emacs parser
+    here_begin="cat <<EOF"
+    echo "$here_begin"
+    for host in ${!vpn_ips[@]}; do
+      ipsuf=${vpn_ips[$host]}
+      i_port=$(( 2200 + ipsuf ))
+      cat <<EOF
+config redirect
+option name ssh$host
+option src              wan
+option src_dport        $i_port
+option dest_port        22
+option dest_ip          \$l.$ipsuf
+option dest             lan
+config rule
+option src              wan
+option target           ACCEPT
+option dest_port        $i_port
+EOF
+    done
+    echo "EOF"
+  } >/p/c/cmc-firewall-data
+
 
-vpn-ips-update() {
   local host ipsuf f files
+
+  # shellcheck disable=SC2016 # shellcheck doesnt know this is sed
+  sedi '/edits below here are made automatically/,$d' /p/c/machine_specific/li/filesystem/etc/wireguard/wgmail.conf
   for host in ${!vpn_ips[@]}; do
+    if [[ ${root_hosts_a[$host]} ]]; then
+      # root machines dont actually need vpn, but
+      # the classification still helps with other
+      # configurations.
+      continue
+    fi
     ipsuf=${vpn_ips[$host]}
     wghole $host $ipsuf
+    u /b/ds/machine_specific/li/filesystem/etc/openvpn/client-config-hole/$host <<EOF
+ifconfig-push 10.5.5.${vpn_ips[$host]} 255.255.255.0
+EOF
     u /a/bin/ds/machine_specific/$host/filesystem/etc/systemd/system/openvpn-client-tr@.service <<EOF
 [Unit]
 Description=OpenVPN tunnel for %I
@@ -2685,15 +2823,36 @@ EOF
   done
 
   {
-    for host in ${!vpn_ips[@]}; do
-      ipsuf=${vpn_ips[$host]}
-      cat <<EOF
-local-data-ptr: "10.2.0.$ipsuf $host.b8.nz"
-EOF
+    echo "cat <<EOF"
+    for host in ${!host_ips[@]}; do
+      ipsuf=${host_ips[$host]}
+      # shellcheck disable=SC2016 # intentional
+      echo 'local-data-ptr: "$l.'$ipsuf $host.b8.nz'"'
     done
-  } | u /b/ds/ptr-data
+    echo "EOF"
+  } | u /p/c/ptr-data
 
   {
+    echo "cat <<EOF"
+    for host in ${!host_macs[@]}; do
+      ipsuf=${host_ips[$host]}
+      echo "dhcp-host=${host_macs[$host]},set:$host,\$l.$ipsuf,$host"
+    done
+    echo "EOF"
+  } | u /p/c/dnsmasq-data
+
+
+  b8_ip=$(dig +short b8.nz @iankelling.org | tail -1)
+  if [[ ! $b8_ip ]]; then
+    echo "$0: error: got empty b8.nz ip. returning 1"
+    return 1
+  fi
+  {
+    echo "@    A       $b8_ip"
+    for host in ${!nonvpn_ips[@]}; do
+      ipsuf=${nonvpn_ips[$host]}
+      echo "$host      A       10.2.0.$ipsuf"
+    done
     for host in ${!vpn_ips[@]}; do
       ipsuf=${vpn_ips[$host]}
       cat <<EOF
@@ -2701,38 +2860,131 @@ $host  A       10.2.0.$ipsuf
 ${host}wg      A       10.8.0.$ipsuf
 ${host}vp      A       10.5.5.$ipsuf
 ${host}tr      A       10.174.$ipsuf.2
+${host}i       A       $b8_ip
 EOF
     done
-  } | cedit vpn-ips-update /p/c/machine_specific/vps/bind-initial/db.b8.nz ||:
+  } | cedit -e vpn-ips-update /p/c/machine_specific/vps/bind-initial/db.b8.nz
 
 
   echo checking for stray files:
 
-  initial_dir=$PWD
-  cd /a/bin/ds/machine_specific
-  ngset
-  files=( */filesystem/etc/systemd/system/openvpn-client-tr@.service )
-  ngreset
-  cd $initial_dir
+  initial_dir="$PWD"
+  while read -r dir path; do
+    cd $dir
+    ngset
+    files=( */$path )
+    ngreset
+    cd "$initial_dir"
+    for f in "${files[@]}"; do
+      host=${f%%/*}
+      if [[ ! ${vpn_ips[$host]} ]]; then
+        e rm $dir/$f
+      fi
+    done
+  done <<'EOF'
+/a/bin/ds/machine_specific filesystem/etc/systemd/system/openvpn-client-tr@.service
+/p/c/machine_specific filesystem/etc/wireguard/wghole.conf
+EOF
+
+  files=( /b/ds/machine_specific/li/filesystem/etc/openvpn/client-config-hole/* )
   for f in "${files[@]}"; do
-    host=${f%%/*}
+    host=${f##*/}
     if [[ ! ${vpn_ips[$host]} ]]; then
-      e /a/bin/ds/machine_specific/$host/filesystem/etc/systemd/system/openvpn-client-tr@.service
+      e rm $f
+      e ssh root@li.b8.nz rm -f $f
     fi
   done
 
-  cd /p/c/machine_specific
-  ngset
-  files=( */filesystem/etc/wireguard/wghole.conf )
-  ngreset
-  cd $initial_dir
-  for f in "${files[@]}"; do
-    host=${f%%/*}
-    if [[ ! ${vpn_ips[$host]} ]]; then
-      e /p/c/machine_specific/$host/filesystem/etc/wireguard/wghole.conf
-      e cedit -s $host /p/c/machine_specific/li/filesystem/etc/wireguard/wgmail.conf '<<<""'
+  tmpf=$(mktemp)
+  {
+    printf "%s" "Host * "
+    sed -n '/^Host /h;/^IdentityFile .*\/home/{g;s/^Host//;s/ / !/gp}' /p/c/subdir_files/.ssh/config-static | tr '\n' ' '
+    echo
+    echo "IdentityFile ~/.ssh/work"
+  } >$tmpf
+  cedit -e work-identity /p/c/subdir_files/.ssh/config-static <$tmpf
+  rm -f $tmpf
+
+  ### begin focus on hosts file update ###
+  #
+  # This started as its own function, but it actually
+  # needed to alter the ssh config, so combined it.
+  #
+  # background: This is finally doing dynamic ip resolution via the hosts
+  # file. I considered detecting where each host was dynamically or
+  # something, but ultimately decided to mostly avoid that, other than
+  # detecting the status of the current machine I'm on.  I want to be able
+  # to move it around without having to manually type much of anything.
+  local -a host_domain_suffix hosts
+  local -A ip_to_hosts
+  local suf ip i host at_home suf_from_here
+
+  source /p/c/domain-info
+
+  at_home=false
+  if ip n | grep -q "10.2.0.1 .* b4:75:0e:fd:06:4a"; then
+    at_home=true
+  fi
+
+  for i in ${host_domain_suffix[@]}; do
+    if [[ $i == *.* ]]; then
+      suf=$i
+      continue
+    fi
+    hosts+=($i)
+    if [[ $i == "$HOSTNAME" ]]; then
+      unset "portfw_ips[$i]"
+      continue
+    fi
+
+    suf_from_here=$suf
+    if ! $at_home && [[ $suf == .b8.nz || $suf == [wc].b8.nz ]]; then
+      suf_from_here=i.b8.nz
+    else
+      unset "portfw_ips[$i]"
+    fi
+
+    ip=$(getent ahostsv4 "$i$suf_from_here" | awk '{ print $1 }' | head -n1) ||:
+    if [[ ! $ip ]]; then
+      if [[ $suf == .office.fsf.org ]]; then
+        suf_from_here=wg.b8.nz
+        ip=$(getent ahostsv4 "$i$suf_from_here" | awk '{ print $1 }' | head -n1) ||:
+      fi
+      if [[ ! $ip ]]; then
+        echo error: failed to get ip of "$i$suf_from_here"
+        return 1
+      fi
     fi
+    ip_to_hosts[$ip]+=" $i"
   done
+
+  for ip in "${!ip_to_hosts[@]}"; do
+    echo "$ip${ip_to_hosts[$ip]}"
+  done | s cedit -e hosts-file-up /etc/hosts
+  for host in ${hosts[@]}; do
+    echo $host
+  done >/p/c/subdir_files/.dsh/group/btrbk
+  ### end focus on hosts file update ###
+
+
+  # note: note sure if this is a great way to check.
+  # todo: think about it
+
+  if $at_home; then
+    # possible that in the future we want to create
+    # a dynamic file here, and then we can move the cat
+    # command above out of the conditional
+    rsync -a /p/c/subdir_files/.ssh/config-static ~/.ssh/config
+  else
+    for host in ${!portfw_ips[@]}; do
+      ipsuf=${portfw_ips[$host]}
+      cat <<EOF
+Host ${host}
+Port $((2200 + ipsuf))
+EOF
+    done > ~/.ssh/config-dynamic
+    cat /p/c/subdir_files/.ssh/config-static ~/.ssh/config-dynamic  >~/.ssh/config
+  fi
 }
 
 # usage host ipsuf [extrahost]
@@ -2950,7 +3202,7 @@ mdenable() {
 
   two=false
   case $1 in
-    -2) two=true shift ;;
+    -2) two=true; shift ;;
   esac
 
   for md; do
@@ -3132,8 +3384,8 @@ myprof() {
   pushd /home/iank/.local/share/profanity/chatlogs/iank_at_fsf.org/rooms/office_at_conference.fsf.org
   logs=(*)
   logcount=${#logs[@]}
-  if (( logcount > 15 )); then
-    i=$(( logcount - 15 ))
+  if (( logcount > 16 )); then
+    i=$(( logcount - 16 ))
   else
     i=0
   fi
@@ -4127,13 +4379,18 @@ monero() {
 }
 
 
+# grep + find
+gef() {
+  faf | grep -E "$@" ||:
+  rgv "$@"
+}
+
 # rg my main files
 rgm() {
   rg "$@" /p/w.org /a/t.org /a/work.org /b
 }
 
 # re all my files more expansively
-
 rem() {
   local paths
   paths="/p/c /b/"
@@ -4416,7 +4673,7 @@ hssh-update() {
   case $HOSTNAME in
     sy|kd)
       hosts=(
-        kd x3.office.fsf.org syw
+        kd.b8.nz x3.office.fsf.org syw x2.b8.nz
       )
       ;;
     x3)
@@ -4515,6 +4772,23 @@ tclear() {
   done
 }
 
+opensslcertinfo() {
+  openssl x509 -txt -in "$@"
+}
+
+# dsh on btrbk hosts
+dsb() {
+:
+  }
+
+# dsh a file and run it
+dsa() {
+  local ret file
+  if ! parallel -j 10 scp x {}:/tmp <~/.dsh/group/btrbk; then
+    echo parallel scp failed. dsa returning $ret
+    fi
+  dsh -g btrbk
+  }
 
 export BASEFILE_DIR=/a/bin/fai-basefiles