various fixes
authorIan Kelling <iank@fsf.org>
Wed, 9 Aug 2017 00:27:07 +0000 (17:27 -0700)
committerIan Kelling <iank@fsf.org>
Wed, 9 Aug 2017 00:27:07 +0000 (17:27 -0700)
15 files changed:
btrbk-run
check-subvol-stale
desktop-apps [new file with mode: 0755]
distro-begin
distro-end
dynamic-ip-update.sh
fsf-get-mail [new file with mode: 0755]
input-setup
mail-setup
music-tag-sync [new file with mode: 0644]
myunison
offlineimap-sync
radicale-setup
rew [new file with mode: 0755]
switch-mail-host [new file with mode: 0755]

index 7a1d946c88f064eafae23ae27bccd53511114aad..eb8a7b5db7e9c89ea051095f55399de541d7e31d 100755 (executable)
--- a/btrbk-run
+++ b/btrbk-run
@@ -17,6 +17,7 @@ set -eE -o pipefail
 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 
 [[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+
 usage() {
     echo "top of script file:"
     sed -n '1,/^[# ]*end command line/{p;b};q' "$0"
@@ -27,33 +28,32 @@ script_dir=$(dirname $(readlink -f "$BASH_SOURCE"))
 
 # note q is owned by root:1000
 # note p/m is owned 1000:1000 and chmod 700
-mountpoints=(/a)
-private_mountpoints=(/q)
+
+
+targets=()
+mountpoints=()
+
 rsync_mountpoint=/q
 
 conf_only=false
 dry_run=false # mostly for testing
 resume_arg=
-do_i=true
-if [[ $HOSTNAME == $MAIL_HOST ]]; then
-    do_o=true
-else
-    do_o=false
-fi
 
 default_args_file=/etc/btrbk-run.conf
-if [[ -r $default_args_file ]]; then
+if [[ -s $default_args_file ]]; then
+    echo "$0: warning: options file default options set:"
+    cat $default_args_file
+    sleep 5
     set -- $(< $default_args_file) "$@"
 fi
 
-temp=$(getopt -l help hcinoprt: "$@") || usage 1
+temp=$(getopt -l help hcm:nprt: "$@") || usage 1
 eval set -- "$temp"
 while true; do
     case $1 in
         -c) conf_only=true; shift ;;
-        -i) do_i=false; shift ;;
+        -m) IFS=, mountpoints=($2); unset IFS; shift 2 ;;
         -n) dry_run=true; dry_run_arg=-n; shift ;;
-        -o) do_o=false; shift ;;
         -p) progress_arg="--progress"; shift ;;
         # btrbk arg: Resume only. Skips snapshot creation.
         -r) resume_arg=-r; shift ;;
@@ -64,10 +64,54 @@ while true; do
     esac
 done
 
-if $do_o; then
-    private_mountpoints+=(/o)
+echo "$0: options: conf_only=$conf_only, dry_run=$dry_run, resume_arg=$resume_arg"
+
+# set default targets
+if ! (( ${#targets[@]} )); then
+    case $HOSTNAME in
+        x2)
+            if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
+                targets=($HOME_DOMAIN)
+            fi
+            ;;
+        treetowl)
+            targets=(frodo)
+            if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
+                if timeout -s 9 10 ssh x2 :; then
+                    targets+=(x2)
+                fi
+            fi
+            ;;
+        *)
+            echo "$0: error: no default targets for this host, use -t"
+            exit 1
+            ;;
+    esac
+fi
+
+echo "targets: ${targets[*]}"
+
+
+
+# set default mountpoints
+if ! (( ${#mountpoints[@]} )); then
+    prospective_mps=(/a /q)
+    if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
+        prospective_mps+=(/o)
+    fi
+    for tg in ${targets[@]}; do
+        if [[ $tg == frodo && $HOSTNAME == treetowl ]]; then
+            prospective_mps+=(/i)
+        fi
+    done
+    for mp in ${prospective_mps[@]}; do # default mountpoints to sync
+        if awk '{print $2}' /etc/fstab | grep -xF $mp &>/dev/null; then
+            mountpoints+=($mp)
+        fi
+    done
 fi
-read primary <<<"$@" # not yet used
+
+echo "mountpoints: ${mountpoints[*]}"
 
 ##### end command line parsing ########
 
@@ -132,82 +176,41 @@ target_preserve_min 4h
 # btrbk -l debug -v dryrun
 EOF
 
-for mp in ${private_mountpoints[@]}; do # private mountpoints
-    if awk '{print $2}' /etc/fstab | grep -xF $mp &>/dev/null; then
-        mountpoints+=($mp)
-    fi
-done
 
 # if our mountpoints are from stale snapshots,
 # it doesn't make sense to do a backup.
 check-subvol-stale ${mountpoints[@]} || exit 1
 
-if [[ ! $targets ]]; then
-    case $HOSTNAME in
-        tp|x2)
-            if ! timeout -s 9 10 ssh frodo :; then
-                targets=($HOME_DOMAIN)
-            fi
-            ;;
-        treetowl)
-            targets=(frodo)
-            if timeout -s 9 10 ssh x2 :; then
-                targets+=(x2)
-            fi
-            ;;
-        *)
-            targets=(frodo)
-            ;;
-    esac
-fi
-
-
-echo "targets: ${targets[*]}"
-
-
-# for i, we just do a 1 way sync from master to backup,
-# and manually manage any changes to that.
-i_possible=false
 for tg in ${targets[@]}; do
     # for an initial run, btrbk requires the dir to exist
     ssh root@$tg mkdir -p /mnt/root/btrbk
-    if [[ $tg == frodo && $HOSTNAME == treetowl ]]; then
-        i_possible=true
-    fi
 done
-if ! $i_possible; then
-    do_i=false
-fi
 
 
-vol=/mnt/root
-vol-conf
 for m in ${mountpoints[@]}; do
-    sub=${m##*/}
-    sub-conf
-    for tg in ${targets[@]}; do
+    # for /i, some special cases. there is just one static target and direction.
+    if [[ $m == /i ]]; then
+        vol=/mnt/iroot
+        vol-conf
+        sub=i
+        sub-conf
+        tg=frodo
+        vol=/mnt/root
         tg-conf
-    done
+    else
+        vol=/mnt/root
+        vol-conf
+        sub=${m##*/}
+        sub-conf
+        for tg in ${targets[@]}; do
+            tg-conf
+        done
+    fi
 done
 
-if $do_i; then
-    vol=/mnt/iroot
-    vol-conf
-    sub=i
-    sub-conf
-    tg=frodo
-    vol=/mnt/root
-    tg-conf
-fi
-
-
 
 # todo: umount first to ensure we don't have any errors
 # todo: do some kill fuser stuff to make umount more reliable
-# todo: run this on a systemd timer on $primary, once per hour,
-# and if primary is, change that timer over to primary, and make
-# sure we mount the latest
-
 
 
 if $conf_only; then
index 127718257ba1000ac95dbe65964d296b726b4584..b977f763f5a85849e7da464c544724e4c908b06c 100644 (file)
@@ -58,7 +58,7 @@ for d; do
         ret=1
         continue
     fi
-    stale=true
+
     # check that $d has $last_snap as a snapshot,
     # or else $d is a snapshot of $last_snap. In the second
     # case, we use a uuid comparison, which if I remember from the
@@ -67,17 +67,42 @@ for d; do
             grep -xF btrbk/$last_snap &>/dev/null; then
         stale=false
     else
-        last_uuid=$(btrfs sub show $last_snap| awk '$1 == "UUID:" {print $2}')
-        if btrfs sub show $d| grep "^\s*Parent UUID:\s*$last_uuid$" &>/dev/null; then
+        last_snap_uuid=$(btrfs sub show $last_snap| awk '$1 == "UUID:" {print $2}')
+        if btrfs sub show $d| grep "^\s*Parent UUID:\s*$last_snap_uuid$" &>/dev/null; then
             stale=false
         fi
     fi
+
+    # check if $d is a snapshot of any of the btrbk backups
+    if [[ ! $stale ]]; then
+        for f in ${snaps[@]}; do
+            if [[ $f == $last_snap ]]; then continue; fi
+            uuid=$(btrfs sub show $f| awk '$1 == "UUID:" {print $2}')
+            if btrfs sub show $d| grep "^\s*Parent UUID:\s*$uuid$" &>/dev/null; then
+                stale=true
+                echo "$d stale: it's a snapshot of $f"
+                break
+            fi
+        done
+    fi
+    # check if $d generation is later than last_snap
+    if [[ ! $stale ]]; then
+        last_snap_gen=$(btrfs sub show $last_snap| awk '$1 == "Generation:" {print $2}')
+        d_gen=$(btrfs sub show $d| awk '$1 == "Generation:" {print $2}')
+        if (( last_snap_gen < d_gen )); then
+            stale=false
+        else
+            echo "$d stale: it's generation, $d_gen, is earlier than the last snapshot's, $last_snap_gen"
+            stale=true
+        fi
+    fi
+
+
     stale_dir=/nocow/btrfs-stale
     stale_file=$stale_dir/$vol
     if $stale; then
         mkdir -p $stale_dir
         printf "%s\n" $last_snap > $stale_file
-        echo "$d stale"
         ret=1
         continue
     else
diff --git a/desktop-apps b/desktop-apps
new file mode 100755 (executable)
index 0000000..ae275f2
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+if ! pgrep -u $EUID emacs; then
+    emacs --daemon &
+fi
+pidgin &
+linphone &
+if ! pgrep -u $EUID -f "firefox -P sfw"; then
+    firefox -P sfw &
+fi
+nagstamon &
index 2577879339c47c007f0608f6c466a0726e485c91..1822afe1db53c3d525ca61fafdfae8641d9fc759 100755 (executable)
@@ -285,6 +285,7 @@ pi trash-cli
 
 
 s lnf -T /a/bin /b
+s lnf -T /nocow/t /t
 
 if has_p; then
     lnf -T /p/News ~/News
index 4fb10dbf1291d2e3e905b64b3c831e51a96c1ba0..6625799d450e951f2c39bc6edd7ccd69626fa678 100755 (executable)
@@ -87,6 +87,7 @@ case $HOSTNAME in
             fdupes
             feh
             filelight
+            flashrom
             gawk-doc
             gcc-doc
             gdb
@@ -118,6 +119,7 @@ case $HOSTNAME in
             nginx-doc
             nmap
             offlineimap
+            oathtool
             p7zip
             paprefs
             parted-doc
@@ -130,6 +132,7 @@ case $HOSTNAME in
             python-autopep8
             python3-doc
             python3-mutagen
+            qrencode
             reportbug
             $(aptitude show ruby | sed -rn 's/Depends: (.*)/\1/p')-doc
             sqlite3-doc
@@ -592,6 +595,7 @@ EOF
 
         ############# end setup mastodon ##############
 
+        # we use nsupdate to update the ip of home
         pi bind9
 
         echo "$0: $(date): ending now)"
@@ -1671,7 +1675,7 @@ if [[ $HOSTNAME == treetowl ]]; then
     # path: k/music. Then copied the file
     # /p/c/subdir_files/.kodi/userdata/sources.xml to save that setting.
     s a2enmod dav dav_fs
-    web-conf -r /a/c/playlists - apache2 dav.iank.pw <<'EOF'
+    web-conf -r /a/c/playlists - apache2 dav.$HOME_DOMAIN <<'EOF'
 <Directory /a/c/playlists>
     DAV On
   AuthType Basic
@@ -1686,7 +1690,7 @@ if [[ $HOSTNAME == treetowl ]]; then
 EOF
     s mkdir -p /var/www/davlock
     s chown www-data:www-data /var/www/davlock
-    s sed -i "1i DavLockDB /var/www/davlock/davlock" /etc/apache2/sites-enabled/dav.iank.pw.conf
+    s sed -i "1i DavLockDB /var/www/davlock/davlock" /etc/apache2/sites-enabled/dav.$HOME_DOMAIN.conf
     ser reload apache2
 
     teeu /etc/exports "/k/music *(ro,nohide,async,no_subtree_check,insecure)"
index 923da11464a95fbbbbcdf96493baa88510e38022..42dab1f2e67b93055daaa37fc3e83589973adfe8 100755 (executable)
@@ -4,7 +4,7 @@ set -eE -o pipefail
 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 
 
-cur="$(host -4 iank.pw iankelling.org | sed -rn 's/.*has address (.*)/\1/p;T;q')"
+cur="$(host -4 iank.life iankelling.org | sed -rn 's/.*has address (.*)/\1/p;T;q')"
 ip=$(curl -s4 https://iankelling.org/cgi/pubip)
 
 # note, a simpler way to do this would be to ssh and use
@@ -12,28 +12,29 @@ ip=$(curl -s4 https://iankelling.org/cgi/pubip)
 # to update bind if needed.
 
 if [[ $cur != $ip ]]; then
-    nsupdate -k /p/c/machine_specific/li/filesystem/etc/bind/Kiank.pw.*.private <<EOF
+    nsupdate -k /p/c/machine_specific/li/filesystem/etc/bind/Kiank.life.*.private <<EOF
 server iankelling.org
-zone iank.pw
-update delete iank.pw. A
-update add iank.pw. 300 A $ip
-update delete *.iank.pw. A
-update add *.iank.pw. 300 A $ip
+zone iank.life
+update delete iank.life. A
+update add iank.life. 300 A $ip
+update delete *.iank.life. A
+update add *.iank.life. 300 A $ip
 show
 send
 EOF
 fi
 
 # persistent initial setup for this:
-# mkc /p/c/machine_specific/li/filesystem/etc/bind
-# s dnssec-keygen -a HMAC-MD5 -b 512 -n HOST iank.pw
-# s chown ian:ian *
-
-# f=key.iank.pw
-# cat >$f <<EOF
-# key iank.pw. {
-# algorithm HMAC-MD5;
-# secret "$(awk '$1 == "Key:" {print $2}' Kiank.pw.*.private)";
-# };
-# EOF
-# chmod 640 $f
+#mkc /p/c/machine_specific/li/filesystem/etc/bind
+#s dnssec-keygen -a HMAC-MD5 -b 512 -n HOST iank.life
+#s chown ian:ian *
+
+f=key.iank.life
+cat >$f <<EOF
+key iank.life. {
+algorithm HMAC-MD5;
+secret "$(awk '$1 == "Key:" {print $2}' Kiank.life.*.private)";
+};
+EOF
+
+chmod 640 $f
diff --git a/fsf-get-mail b/fsf-get-mail
new file mode 100755 (executable)
index 0000000..c9b1db0
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+offlineimap -a fsf
+sieve-filter -eW -o mail_location=maildir:/nocow/user/fsfmd:LAYOUT=fs:INBOX=/nocow/user/fsfmd/INBOX /a/c/fsf.sieve INBOX &>/tmp/fsfsieve.log
index 91bede690083f595581a6237530a7768d96b4e93..9cff413c2d4da99c2a1e3450b6af97746dffaa1c 100755 (executable)
@@ -1,4 +1,5 @@
 #!/bin/bash -l
+set -x
 # Copyright (C) 2016 Ian Kelling
 
 # Licensed under the Apache License, Version 2.0 (the "License");
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# set to oppsite if the order is flipped.
+k2flip=falsesf-
+if $k2flip; then
+k2inorder=false
+else
+    k2inorder=true
+    fi
+
 case $HOSTNAME in
     x2|tp) type=laptop ;;
     treetowl*|iank-dev|frodo) type=kinesis ;;
@@ -39,9 +48,15 @@ ms() {
     mi "$1"
 }
 set_device_id() {
-    if device_id=$(xinput --list | grep -m 1 "$1"); then
+    if [[ $2 ]] && $2; then
+        cmd="tail -n1"
+    else
+        cmd="head -n1"
+    fi
+    if device_id=$(xinput --list | grep "$1" | $cmd); then
         device_id=${device_id##*id=}
         device_id=${device_id%%[[:space:]]*}
+        echo "2:$2 device_id=$device_id"
     else
         return 1
     fi
@@ -68,15 +83,23 @@ case $type in
 
             xset r rate 200 13 # decrease rate delay
             cd / # so xbindkeys does not hold open mountpoints
+            killall xbindkeys # having some lag, thinking this might help.
             xbindkeys # configured to grab left and right scroll button presses
         fi
 
-
+        kinesis2=false
         #right scroll wheel, change from button 4 & 5 to 13 and 14.
         # also changes the middle click to 12, even though I'm not using it anymore
         if set_device_id "04d9:048e"; then
             xinput --set-button-map "$device_id" 1 12 3 13 14 6 7
+        else
+            kinesis2=true # if we are using the 2nd kinesis which has different device ids
         fi
+        if $kinesis2 && set_device_id "USB OPTICAL MOUSE" $k2flip; then
+            xinput --set-button-map "$device_id" 1 12 3 14 13 6 7
+        fi
+
+
 
         ms 'Kensington Kensington Slimblade Trackball' 100 4000/1 7 6.5 1.5
         xinput --set-button-map 'Kensington Kensington Slimblade Trackball' 0 0 0 4 5 6 7 0 9 10 11 12
@@ -98,12 +121,21 @@ case $type in
         fi
 
 
-        # disable the mouse movements of my mouse-wheel only mouse
-        if set_device_id "USB Optical Mouse"; then
-            xinput --set-prop "$device_id" 'Device Accel Constant Deceleration' 10000
-            # 12 is to effectively disable the middle click button
-            xinput --set-button-map "$device_id" 1 12 3 10 11 6 7
+        # disable the mouse movements mouse wheel
+        if $kinesis2; then
+            if set_device_id "USB OPTICAL MOUSE" $k2inorder; then
+                xinput --set-prop "$device_id" 'Device Accel Constant Deceleration' 10000
+                # 12 is to effectively disable the middle click button
+                xinput --set-button-map "$device_id" 1 12 3 11 10 6 7
+            fi
+        else
+            if set_device_id "USB Optical Mouse"; then
+                xinput --set-prop "$device_id" 'Device Accel Constant Deceleration' 10000
+                # 12 is to effectively disable the middle click button
+                xinput --set-button-map "$device_id" 1 12 3 10 11 6 7
+            fi
         fi
+
         . /a/bin/bash_unpublished/duplicity-gpg-agent-setup
         ;;
 esac
index 33ad75a0b3af2719e63ecd3328f77070c0227605..09c33d773e758917d5b0f5600bc02c9e301a67ac 100755 (executable)
@@ -622,7 +622,7 @@ EOF
         # sieve option, we wouldn\'t need this, but I\'d rather not modify a
         # default config if not needed. This won\'t work as a symlink in /a/c
         # unfortunately.
-        sudo -u $postmaster /a/exe/lnf -T sieve/main.sieve ~$postmaster/.dovecot.sieve
+        sudo -u $postmaster /a/exe/lnf -T sieve/main.sieve $(eval echo ~$postmaster)/.dovecot.sieve
 
         sed -ri -f - /etc/dovecot/conf.d/10-mail.conf <<'EOF'
 1i mail_location = maildir:/m/md:LAYOUT=fs:INBOX=/m/md/INBOX
@@ -817,6 +817,18 @@ fi
 systemctl restart $type
 systemctl enable $type
 
+# MAIL_HOST also does radicale, and easier to start and stop it here
+# for when MAIL_HOST changes, so radicale gets the synced files and
+# does not stop us from remounting /o.
+if dpkg -s radicale &>/dev/null; then
+    if [[ $HOSTNAME == $MAIL_HOST ]]; then
+        systemctl restart radicale
+        systemctl enable radicale
+    else
+        systemctl stop radicale
+        systemctl disable radicale
+    fi
+fi
 
 # if I wanted the from address to be renamed and sent to a different address,
 # echo "sdx@localhost development@localhost" | sudo dd of=/etc/postfix/recipient_canonical
diff --git a/music-tag-sync b/music-tag-sync
new file mode 100644 (file)
index 0000000..0f6e7d9
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/bash -l
+set -eE -o pipefail
+trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
+# cd /k/music
+# find -type f -name '*.flac' | while read -r f; do
+#     mkdir -p "../flacs/$(dirname "$f")"
+#     mv -T "$f" ../flacs/"$f"
+# done
+
+
+
+# todo, add settings from /etc/default/nfs-{common,kernel-server}
+# todo: do mysql setup. kodi install. mysql backup.
+
+# in kodi, music, add files, named source, add network share,
+# server address: iank.life
+# path: k/music
+
+
+
+rm -f /a/tmp/y.sql
+
+cd /k/music
+find -type f \( -name '*.flac' -or -name '*.mp3' -or -name '*.m4a' \) | while read -r f; do
+    rating=$(kid3-cli -c "get RATING" "$f")
+    if [[ ! $rating ]]; then
+           echo $f
+           continue
+    fi
+    rating=$((rating*2))
+
+    ## begin sql escaping
+    f="${f//\"/\\\"}"
+    f="${f//\'/\\\'}"
+    f="${f//_/\\_}"
+    f="${f//%/\\%}"
+    ## end sql escaping
+    d=${f%/*}
+    d=${d#./}/ # use exact dir format that is in database
+    cat >>/a/tmp/y.sql <<EOF
+update song
+inner join path on song.idPath = path.idPath
+set song.userrating = $rating
+where song.strFileName = '${f##*/}' and path.strPath = 'nfs://iank.life/k/music/$d';
+EOF
+done
index 493d79594de5177a87081da5e1c611e2fce55c52..30ee1cbe3e99b24851849e7e71de8d25bfa37786 100755 (executable)
--- a/myunison
+++ b/myunison
@@ -9,13 +9,13 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 # which did not have the whole p subvol.
 
 gen_args=()
-do_snapshot=true
+do_snapshot=false
 batch=false
 while [[ $1 ]]; do
     case $1 in
         -ob) gen_args+=(--ours -b); batch=true; shift ;;
         -b) gen_args+=(-b); batch=true; shift ;;
-        -n) do_snapshot=false; shift ;;
+        -n) do_snapshot=true; shift ;;
         -h|--help)
             echo "$0: help is head of $BASH_SOURCE:"
             head -n 30 "$BASH_SOURCE"
index a179b36e732133d261507978d0027b12bf839356..21361b90c189114c071c5255f85561b515915980 100755 (executable)
@@ -6,7 +6,7 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 offlineimap -u quiet
 shopt -s nullglob
 
-omv() { # offlineimap mv
+omv() { # offlineimap mv. move mail files within $src_base/$1 to /m/md/$2
     src="$1"
     dst="$2"
     found_files=false
@@ -29,5 +29,10 @@ if $found_files; then
     omv offlineimaptmp INBOX
     # remove messages from remote host
     offlineimap -u quiet
-    mu index &>/dev/null ||:
+    # this makes us sit and wait when we want to use mu and this is running in a cronjob.
+    # todo: emacs updates the index much faster. what command is it running? I'd like
+    # to just run that
+    # looks like it might be mu index --lazy-check, but that still takes like 10 seconds,
+    # figure out if that is the same speed, or if we can make it faster.
+    #mu index &>/dev/null ||:
 fi
index 2f22e642b6429c8917547478bdd8e2951ccad544..cb27eda4ec1d93165c50723d72d10f59a7938fea 100755 (executable)
@@ -9,10 +9,28 @@
 # http://radicale.org/user_documentation/
 # https://davdroid.bitfire.at/configuration/
 
+# note on debugging: if radicale can't bind to the address,
+# in the log it just says "Starting Radicale". If you run
+# it in the foreground, it will give more info. Background
+# plus debug does not help.
+# sudo -u radicale radicale -D -f
 
 # created password file with:
 # htpasswd -c /etc/davpass dav
 
+d=/etc/systemd/system/radicale.service.d
+mkdir -p $d
+sudo dd of=$d/override.conf <<'EOF'
+[Unit]
+# this unit is configured to start and stop whenever openvpn-client@mail.service
+# does
+After=network.target
+BindsTo=openvpn-client@mail.service
+After=openvpn-client@mail.service
+
+[Install]
+RequiredBy=openvpn-client@mail.service
+EOF
 
 pi radicale
 
@@ -36,31 +54,44 @@ setini() {
 
 # comments say default is 0.0.0.0:5232
 setini hosts 10.8.0.4:5232 server
-sgo radicale
 
-# davdroid from f-droid.
+if [[ $HOSTNAME == $MAIL_HOST ]]; then
+    sgo radicale
+fi
+
+# disable power management feature, set to 240 min sync interval,
+# so it shouldn't be bad.
+
+# davdroid from f-druid.
 # login with url and user name
 # username ian,
 # url https://cal.iankelling.org
 # username ian
 # pass, see password manager
-# I disabled power management feature, it's got 240 min sync interval,
-# so it shouldn't be bad.
 #
-
-# when setting up davdroid, switch to groups are per-contact categories,
-# per https://davdroid.bitfire.at/configuration/radicale/
+# add account dialog:
 #
 # set account name as ian@iankelling.org, per help text below the
 # field.
 #
+# switch to groups are per-contact categories,
+# per https://davdroid.bitfire.at/configuration/radicale/
+#
+#
 # After setting up account, I added one address book, named
-# ian. calender was already created, named ian. checked boxes under
+# ianaddr. calender was already created, named ian. checked boxes under
 # both. synced.
 #
+# To restore from old phone to new phone, I wiped all data out, then copied over the newly created files. I think
+#
 # ignorable background info:
 #
-# When debugging, tailed /var/log/radicale/radicale.log and nginx log,
+# opentasks uses the calendar file.
+#
+# The address book I created got a uuid as a name for the file. Note
+# the .props file says if it's a calendar or addressbook.
+#
+# When debugging, tailed /var/log/radicale/radicale.log and apache log,
 # both show the requests happening. Without creating the address book,
 # after creating a contact, a sync would delete it.
 #
diff --git a/rew b/rew
new file mode 100755 (executable)
index 0000000..860a303
--- /dev/null
+++ b/rew
@@ -0,0 +1,13 @@
+#!/bin/bash
+p="$(lsof -i tcp:31416 -Fp -a -c java | sed -rn 's/^p//p')"
+if [[ $p ]]; then
+    kill $p
+fi
+cd /a/opt/gnirehtet
+./gnirehtet rt &>/tmp/rt &
+# note, to kill it, you need to also kill
+# lsof -i tcp:31416
+# and maybe unplug adb cable
+# note, ping results in log message: dropping invalid packet
+
+tail -F /tmp/rt ||:
diff --git a/switch-mail-host b/switch-mail-host
new file mode 100755 (executable)
index 0000000..61e8966
--- /dev/null
@@ -0,0 +1,150 @@
+#!/bin/bash
+set -x
+set -eE -o pipefail
+trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
+
+usage() {
+    cat <<EOF
+Usage: ${0##*/} OLD_HOST NEW_HOST
+
+Adjust home network dns so NEW_HOST resolves locally if it is on the
+local network.  Turn off mail receiving on OLD_HOST, run btrbk to move
+mail to NEW_HOST, turn on mail receiving on NEW_HOST.
+
+
+-h|--help  Print help and exit.
+
+Note: Uses GNU getopt options parsing style
+EOF
+    exit $1
+}
+
+##### begin command line parsing ########
+
+if (( $# != 2 )) || [[ $1 == -* || $2 == -* ]]; then
+    usage 1
+fi
+
+old_host=$1
+new_host=$2
+
+if [[ $old_host != $MAIL_HOST ]]; then
+    read -p "warning: \$old_host != \$MAIL_HOST: $old_host != $MAIL_HOST, proceed? y/N "
+    if [[ $REPLY != [yY] ]]; then
+        exit 1
+    fi
+fi
+
+if [[ $new_host == "$HOSTNAME" ]]; then
+    localhost_new=true
+    ssh_prefix=ssh
+else
+    localhost_new=false
+    ssh_prefix=
+fi
+if [[ ! $new_host || ! $old_host ]]; then
+    echo "$0: bad args. see script"
+    exit 1
+fi
+
+at_home=false
+if timeout -s 9 10 ssh root@wrt.lan :; then
+    at_home=true
+fi
+
+source /a/bin/bash_unpublished/source-semi-priv
+#### begin convert private hostnames to public hostnames ####
+if ! $at_home; then
+    for var in old_host new_host; do
+        case ${!var} in
+            treetowl)
+                eval $var=$HOME_DOMAIN
+                ;;
+        esac
+    done
+fi
+####  end convert private hostnames to public hostnames ####
+
+
+# because our port forward is not robust enough, we can't use proxy command,
+# todo: just open an ssh port to the world on wrt
+if ! $at_home; then
+    ssh_cmd="ssh $HOME_DOMAIN ssh wrt"
+else
+    ssh_cmd="ssh wrt"
+fi
+# if new_host is not on home network, make mail.iankelling.org not resolve
+# on the home network.
+if [[ $new_host == $HOSTNAME ]] && ! $at_home; then
+    echo | $ssh_cmd cedit mail_host /etc/hosts
+else
+    $ssh_cmd bash -s <<EOFOUTER
+    cedit mail_host /etc/hosts <<'EOF' || /etc/init.d/dnsmasq restart
+\$(grep "\b$new_host\b" /etc/hosts | awk '{print $1}') mail.iankelling.org
+EOF
+EOFOUTER
+fi
+
+mail-setup() {
+    shell="$1"
+    $shell sed -ri "s/MAIL_HOST=.*/MAIL_HOST=$new_host/" /a/bin/bash_unpublished/source-semi-priv
+    $shell /a/bin/distro-setup/mail-setup exim4
+}
+
+mail-setup "ssh $old_host"
+
+sudo dd of=/etc/btrbk.conf <<'EOF'
+ssh_identity /root/.ssh/id_rsa
+# Just a guess that local7 is a good facility to pick.
+# It's a bit odd that the transaction log has to be logged to
+# a file or syslog, while other output is sent to std out.
+# The man does not mention a way for them to be together, but
+# I dunno if setting a log level like warn might also output
+# transaction info.
+transaction_syslog local7
+
+# so we only run one at a time
+lockfile                   /var/lock/btrbk.lock
+
+# default format of short does not accomidate hourly preservation setting
+timestamp_format long-iso
+
+# only make a snapshot if things have changed
+snapshot_create onchange
+# I could make this different from target_preserve,
+# if one disk had less space.
+# for now, keeping them equal.
+snapshot_preserve 36h 14d 8w 24m
+snapshot_preserve_min 4h
+snapshot_dir btrbk
+
+# so, total backups = ~89
+target_preserve 36h 14d 8w 24m
+target_preserve_min 4h
+
+# if something fails and it's not obvious, try doing
+# btrbk -l debug -v dryrun
+
+
+EOF
+
+
+if $localhost_new; then
+    btrbk_src=ssh://$old_host/mnt/root
+    btrbk_dst=/mnt/root/btrbk
+else
+    btrbk_src=/mnt/root
+    btrbk_dst=ssh://$old_host/mnt/root/btrbk
+fi
+
+sudo tee -a /etc/btrbk.conf <<EOF
+volume $btrbk_src
+subvolume o
+target send-receive $btrbk_dst
+EOF
+
+
+sudo btrbk --progress run
+$ssh_prefix $new_host mount-latest-subvol
+
+mail-setup