Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Devuan preseed, July 2023 edition

And here's the latest version of my [un?]popular series on Devuan GNU+Linux preseed virtual machine installations. I don't think a whole lot has changed really, except of course the Devuan release number.

# File: /mnt/public/Support/Platforms/devuan/preseed/preseed.cfg
# Locations:
#    /mnt/public/Support/Platforms/devuan/preseed/preseed.cfg
# Author: bgstack15
# Startdate: 2019-06-25
# Title: Preseed for devuan vms for
# Purpose: To provide an easy installation for VMs and other systems in the Internal network
# History:
#    2017-06 I learned how to use kickstart files for the RHCSA EX-200 exam
#    2017-08-08 Added notifyemail to --extra-args
#    2017-10-29 major revision to use local repository
#    2019-06-25 fork from centos7-ks.cfg
#    2018-12-29 fix up repos and in-target conclusion stuff
#    2020-02-27 heavy rewrite to use ascii 2.1
#    2021-05-16 bump to chimaera which upgrades self to ceres
#    2023-01-20 kernel cmdline, remove newmoon
#    2023-02-28 add ssh_config EnableEscapeCommandline yes, disable apparmor for sssd
#    2023-06-26 add
# Usage with virt-install:
#    vm=d2-04a ; time sudo virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=debiantesting -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/Linux/devuan_daedalus_5.0.preview-20230116_amd64_netinstall.iso --initrd-inject=/mnt/public/Support/Platforms/devuan/preseed/preseed.cfg --extra-args " interface=auto netcfg/get_hostname=${vm}" --debug --network type=bridge,source=br0 --noautoconsole
#    vm=d2-04a; sudo virsh destroy "${vm}"; sudo virsh undefine --remove-all-storage "${vm}";
# Reference:
#    /mnt/public/Support/Platforms/CentOS7/install-vm.txt
#    syntax for --location
#    example preseed
#    skip next dvd question
#    grub problem caused by consolekit:amd64
#    /mnt/public/Support/Platforms/devuan/fix-virt-manager.txt
#    sudo debconf-get-selections -c /mnt/public/Support/Platforms/devuan/preseed/preseed.cfg
#    on d2-03a: sudo debconf-get-selections --installer
# Improve:
#    discover how to send email, using postfix or sendmail. Don't care which, but exclude exim4.
#    echo "$( hostname ) has IP $( ip -4 -o a s eth0 | awk '{print $4}' | sed -r -e 's/\/.*$//' )" | 
# Dependencies:
#    configure-postfix uses my gmail+smtp+oauth2 postfix relay

d-i debian-installer/country string US
d-i debian-installer/keymap select us
d-i debian-installer/language string en
d-i debian-installer/locale string en_US
d-i localechooser/supported-locales string en_US.UTF-8

d-i keyboard-configuration/layoutcode string us
d-i keyboard-configuration/variantcode string
d-i keyboard-configuration/xkb-keymap select us

d-i netcfg/disable_autoconfig boolean false
# The hostname is supposed to come from the kernel cmdline in the virt-install invocation
#d-i netcfg/get_hostname string NONE
d-i netcfg/get_domain string
d-i netcfg/wireless_wep string
# disable asking for non-free firmware, because this is a vm and has none
d-i hw-detect/load_firmware boolean false

#d-i apt-setup/enable-source-repositories boolean false
# ORIGINAL d-i apt-setup/services-select multiselect security updates, release updates, backported software
d-i apt-setup/services-select multiselect release updates
d-i apt-setup/contrib boolean true
d-i apt-setup/disable-cdrom-entries boolean true
d-i apt-setup/non-free boolean true
d-i apt-setup/use_mirror boolean true
d-i mirror/country string manual
d-i mirror/http/directory string /merged
d-i mirror/http/hostname string
d-i mirror/http/proxy string
d-i mirror/protocol string http
d-i mirror/suite string testing

d-i apt-setup/cdrom/set-failed boolean false
d-i apt-setup/cdrom/set-first boolean false
d-i apt-setup/cdrom/set-next boolean false

## my repos and ceres
d-i apt-setup/local0/comment    string internaldeb
d-i apt-setup/local0/key        string
d-i apt-setup/local0/repository string /
d-i apt-setup/local1/comment    string devuan-deb
d-i apt-setup/local1/key        string
d-i apt-setup/local1/repository string /
d-i apt-setup/local2/comment    string ceres
d-i apt-setup/local2/key        string
d-i apt-setup/local2/repository string ceres main contrib non-free
#d-i apt-setup/local2/key        string
#d-i apt-setup/local2/repository string ceres main contrib non-free
d-i apt-setup/local3/comment    string obsmirror
d-i apt-setup/local3/key        string
d-i apt-setup/local3/repository string /
d-i apt-setup/local4/comment    string obsmirror-gtk3-classic
d-i apt-setup/local4/key        string
d-i apt-setup/local4/repository string /
# if for some reason I really need to turn off the gpg key check:
#d-i debian-installer/allow_unauthenticated boolean false

#tasksel tasksel/first multiselect standard, ssh-server
tasksel tasksel/first multiselect none

# adapted from /mnt/public/Support/Platforms/devuan/devuan.txt, main fluxbox desktop, but for a vm
# no xscreensaver, for a vm.
#d-i pkgsel/include string \
#   alsamixergui alttab apt-transport-https bgconf bgscripts bgscripts-core \
#   cifs-utils curl fluxbox freeipa-client git grub lightdm lightdm-gtk-greeter \
#   mlocate net-tools nfs-common ntpdate openssh-server \
#   p7zip palemoon palemoon-ublock-origin parted qemu-guest-agent rsync scite \
#   screen spice-vdagent strace sudo tcpdump vim vlc volumeicon-alsa waterfox \
#   xfce4-terminal xfe xserver-xorg-video-qxl fluxbox-themes-stackrpms
#d-i pkgsel/include string cifs-utils curl grub lightdm vim sudo vlc screen p7zip nfs-common
d-i pkgsel/include string openssh-server wget curl

d-i pkgsel/upgrade select none

popularity-contest popularity-contest/participate boolean true

d-i clock-setup/ntp boolean true
d-i clock-setup/ntp-server string
d-i time/zone string America/New_York

# skip grub during main part, because we will do it in late_command
#d-i grub-installer/skip boolean true
#d-i grub-installer/skip-again boolean true
#d-i grub-installer/skip-confirm boolean true
#d-i grub-installer/confirm_skip boolean true
#d-i nobootloader/confirmation_common boolean true
d-i     choose-init/select_init select  sysvinit
d-i     choose-init/selected_sysvinit bool   true
grub-installer  grub-installer/choose_bootdev   select  /dev/vda

d-i lilo-installer/skip boolean true
#d-i grub-installer/with_other_os boolean true
d-i grub-installer/only_debian boolean true
d-i grub-installer/grub2_instead_of_grub_legacy boolean true
#d-i grub-installer/bootdev string /dev/vda
#d-i grub-installer/choose_bootdev select /dev/vda
#grub-installer grub-installer/force-efi-extra-removable boolean false

d-i passwd/root-password password plaintextexamplepw
d-i passwd/root-password-again password plaintextexamplepw

d-i partman-auto/choose_recipe select home
d-i partman-auto-crypto/erase_disks boolean false
d-i partman-auto/disk string /dev/vda
d-i partman-auto/init_automatically_partition select biggest_free
d-i partman-auto/method string lvm
d-i partman/choose_label string gpt
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman/confirm_write_new_label boolean true
d-i partman/default_label string gpt
#d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-md/confirm_nooverwrite boolean true
#d-i partman/mount_style select uuid
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman-auto-lvm/guided_size string 100%

# Uncomment this to add multiarch configuration for i386
#d-i apt-setup/multiarch string i386

d-i passwd/make-user boolean true
d-i passwd/user-fullname string bgstack15-local
d-i passwd/username string bgstack15-local
d-i passwd/user-password-crypted password $6$BxyYQfM7A1TEeS6X$SEXAMPLE6.n6SU21s.ojeQ9F06AMcnEXAMPLEHTufeWXLpNu6EmpsDN7eEXAMPLEU4moiXVgzIiTJYXatdGBz0/
d-i passwd/user-default-groups string audio cdrom video

d-i finish-install/reboot_in_progress note
d-i cdrom-detect/eject boolean true

# additional application stuff just in case it works and is useful
# LDAP server URI:
d-i shared/ldapns/ldap-server   string  ldapi:///

d-i openssh-server/password-authentication  boolean true
d-i openssh-server/permit-root-login    boolean false

# Sometimes the update-devuan has to happen before the laundry list of packages, because upgrading from some stable release to Ceres causes package numbering-name mismatches.
d-i preseed/late_command string mkdir -p /target/etc/apt/sources.list.d /target/mnt/bgstack15 /target/mnt/public /target/etc/apt/sources.list.d /target/root/input ; touch /target/etc/apt/sources.list.d/empty ; cd /target/etc/apt ; \
   in-target apt-get install -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" gpg grub-pc sudo ; \
   in-target curl --no-progress-meter --output /root/ ; in-target sh /root/ ; \
   in-target curl --no-progress-meter --output /root/input/52apt-file-stackrpms.conf ; in-target curl --no-progress-meter --output /root/ ; in-target sh /root/ || : ; \
   in-target rm /etc/apt/trusted.gpg.d/ceres.gpg || : ; \
   in-target curl --no-progress-meter --output /usr/local/share/ca-certificates/ && in-target update-ca-certificates || : ; \
   in-target wget -O /root/ ; in-target sh /root/ preseed ; \
   in-target apt-get install -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" alsamixergui alttab bgconf bgscripts bgscripts-core ca-certificates cifs-utils curl desktop-base fluxbox fluxbox-themes-stackrpms freeipa-client freeipa-helper git grub-pc gtk3-automnemonics gtk3-nocsd gtk3-nooverlayscrollbar krb5-auth-dialog librewolf logout-manager man mlocate net-tools nfs-common ntpdate p7zip parted postfix qemu-guest-agent rsync scite screen spice-vdagent strace sudo tcpdump ublock-origin-combined vim vlc volumeicon-alsa xdgmenumaker xfce4-terminal xfe xserver-xorg-input-libinput xserver-xorg-video-qxl ; \
   rm -f /target/etc/apt/sources.list.d/empty || : ; \
   in-target sed -i -r -e '/^\s*linux/s/(\s*console=.{1,7}[0-9])*\s*$/ console=tty0 console=ttyS0/;' /boot/grub/grub.cfg || : ; \
   in-target sed -i -r -e '/^\s*kernel/s/(\s*console=.{1,7}[0-9])*\s*$/ console=tty0 console=ttyS0/;' /boot/grub/menu.lst || : ; \
   in-target sed -i -r -e '$aT0:23:respawn:/sbin/getty -L ttyS0 9600 vt100' /etc/inittab ; \
   in-target apt-get update ; \
   in-target apt-get purge -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" consolekit exim4\* lxqt\* udev ; \
   in-target curl --no-progress-meter --output /root/ ; in-target sh /root/ -y ; \
   in-target su bgstack15-local -c "sudo /usr/bin/ -d 10 1>/home/bgstack15-local/clone.log 2>&1" ; \
   in-target updateval -a -v /etc/ssh/ssh_config '^\s*EnableEscapeCommandline.*' 'EnableEscapeCommandline yes' ; \
   in-target ln -sf /etc/apparmor.d/usr.sbin.sssd /etc/apparmor.d/disable/ ; \
   in-target apparmor_parser -R /etc/apparmor.d/usr.sbin.sssd ; \
   in-target curl --no-progress-meter --output /root/ ; in-target sh /root/ ; \
   in-target curl --no-progress-meter --output /root/ ; in-target sh /root/ ;


And of course, most of the logic is in all the included scripts.


# Startdate: 2020-03-12
# Purpose: Replace original devuan repos with my local devuan mirror
# History:
#    2021-01-27 remove prebuilt file. Just use heredoc
#    2023-02-28 add new repo section non-free-firmware
# Documentation:
# Use the network file if available, otherwise, use this hardcoded heredoc.
touch "${tf}"
   cat <<'EOF'
# file: /mnt/public/Support/Platforms/devuan/sources.list
# date: 2023-02-28
# the 3 main ones: ascii main/security/updates
# uncomment all of them when needing winehq-staging for AoC.
# If using ascii, there are multiple lines: ascii ascii-security ascii-updates
#deb ceres main contrib non-free non-free-firmware
deb ceres main contrib non-free non-free-firmware
deb-src ceres main
} > "${tf}"


# File: /mnt/public/Support/Platforms/devuan/
# Location:
# Author: bgstack15
# Startdate: 2019-08-10 16:02
# Title: Script that Establishes the repos needed for Devuan
# Purpose: Set up the 3 repos I always need on devuan clients
# History:
#    2020-02-01 customize clients for devuan-archive
#    2020-10-23 add apt-file compatibility
#    2021-01-27 disable devuan-archive
# Usage:
#    sudo
# Reference:
#    /mnt/public/Support/Platforms/devuan/devuan.txt
# Improve:
#    need to control the sources.list file itself to have the main, contrib, etc., for ceres.
# Documentation:
test -z "${ALLREPOSGLOB}" && ALLREPOSGLOB="/etc/apt/sources.list /etc/apt/sources.list.d/*"
test -z "${REPOSBASE}" && REPOSBASE="/etc/apt/sources.list.d"
test -z "${PREFSBASE}" && PREFSBASE="/etc/apt/preferences.d"
test -z "${ADDLCONFBASE}" && ADDLCONFBASE="/etc/apt/apt.conf.d"
# confirm key
confirm_key() {
   # call: confirm_key "${PRETTYNAME}" "${SEARCHPHRASE}" "${URL_OF_KEY}"
   if apt-key list 2>/dev/null | grep -qe "${___ck_sp}" ;
      # not found so please add it
      echo "Adding key for ${___ck_repo}" 1>&2
      #wget -O- "${___ck_url}" | sudo apt-key add -
      ___ck_keyfile="/etc/apt/trusted.gpg.d/$( echo "${___ck_repo}" | tr '[: ]' '_' ).gpg"
      wget -O- --quiet "${___ck_url}" | gpg --dearmor | sudo tee "${___ck_keyfile}" 1>/dev/null
# confirm repo
confirm_repo() {
   if ! grep -E -qe "${___cr_sp}" ${___cr_sf} ;
      # not found so please add it to preferred file
      echo "Adding repo ${___cr_repo}" 1>&2
      if test "${___cr_overwrite}" = "true" ;
         # overwrite, instead of append
         echo "${___cr_full}" > "${REPOSBASE}/${___cr_pref:-99_misc.list}"
         echo "${___cr_full}" >> "${REPOSBASE}/${___cr_pref:-99_misc.list}"
confirm_preferences() {
   # call: confirm_preferences "${PRETTYNAME}" "${FILENAME}" "{PACKAGE}" "${PIN_EXPRESSION}" "{PRIORITY}"
   ___cp_tempfile="$( mktemp )"
      echo "Package: ${___cp_package}"
      echo "Pin: ${___cp_pin_expression}"
      echo "Pin-Priority: ${___cp_priority}"
   } > "${___cp_tempfile}"
   diff "${PREFSBASE}/${___cp_pref}" "${___cp_tempfile}" 1>/dev/null 2>&1 || {
      echo "Setting preferences for ${___cp_prettyname}"
      touch "${PREFSBASE}/${___cp_pref}" ; chmod 0644 "${PREFSBASE}/${___cp_pref}"
      cat "${___cp_tempfile}" > "${PREFSBASE}/${___cp_pref}"
   rm -f "${___cp_tempfile:-NOTHINGTODEL}" 1>/dev/null 2>&1
# REPO 1: local internaldeb
confirm_key "internaldeb" "bgstack15.*www\.no-ip\.biz" ""
confirm_repo "internaldeb" "target.*internal\/repo\/deb" "${ALLREPOSGLOB}" "deb [target-=Contents-deb target+=Contents-stackrpms] /" "internaldeb.list" "true"
# REPO 2: local devuan-deb
confirm_key "devuan-deb" "bgstack15.*www\.no-ip\.biz" ""
confirm_repo "devuan-deb" "target.*internal\/repo\/devuan-deb" "${ALLREPOSGLOB}" "deb [target-=Contents-deb target+=Contents-stackrpms] /" "devuan-deb.list" "true"
# REPO 3: local obs
# Thankfully I re-sign this with my own key.
#confirm_key "OBS bgstack15" "bgstack15@build\.opensuse\.org" ""
#confirm_repo "OBS bgstack15" "repositories\/home:\/bgstack15\/Debian_Unstable" "${ALLREPOSGLOB}" "deb /" "home:bgstack15.list"
confirm_key "OBS bgstack15" "bgstack15@build\.opensuse\.org" ""
confirm_repo "OBS bgstack15" "mirror\/obs" "${ALLREPOSGLOB}" "deb /" "home:bgstack15.list"
# REPO 4: local devuan-archive
# deprecated circa 2021-05
#confirm_key "devuan-archive" "bgstack15.*www\.no-ip\.biz" ""
#confirm_repo "devuan-archive" "target.*server1((\.ipa)?\.internal\.com)?(:180)?.*internal\/repo\/devuan-archive" "${ALLREPOSGLOB}" "deb [target-=Contents-deb target+=Contents-stackrpms] /" "devuan-archive.list" "true"
#confirm_preferences "devuan-archive" "puddletag" "*" "origin" "700"
# REPO 5: local obs-aftermozilla key for non-local aftermozilla repo
# just the key
#confirm_key "OBS bgstack15 aftermozilla" "bgstack15@build\.opensuse\.org" ""
# REPO 5: local obs-AfterMozilla
confirm_key "OBS bgstack15" "bgstack15@build\.opensuse\.org" ""
confirm_repo "OBS bgstack15 AfterMozilla" "mirror\/obs-AfterMozilla" "${ALLREPOSGLOB}" "deb /" "home:bgstack15:AfterMozilla.list"
# REPO 6: local obs-gtk3-classic
confirm_key "OBS bgstack15" "bgstack15@build\.opensuse\.org" ""
confirm_repo "OBS bgstack15 gtk3-classic" "mirror\/obs-gtk3-classic" "${ALLREPOSGLOB}" "deb /" "home:bgstack15:gtk3-classic.list"
# important for the [target] stuff to work on repos so apt-file can work
cp -p "$( dirname "$( readlink -f "${0}" )")/input/52apt-file-stackrpms.conf" "${ADDLCONFBASE}/"

And supporting file 52apt-file-stackrpms.conf:

# File: /etc/apt/apt.preferences.d/52apt-file-stackrpms.conf
# Part of support devuan scripts
# This enables the flat apt repos in internal to be supported by apt-file
Acquire::IndexTargets {
    deb::Contents-stackrpms {
        MetaKey "Contents-$(ARCHITECTURE)";
        ShortDescription "Contents-$(ARCHITECTURE)";
        Description "$(RELEASE) $(ARCHITECTURE) Contents (deb)";

        flatMetaKey "Contents-$(ARCHITECTURE)";
        flatDescription "$(RELEASE) Contents (deb)";
        PDiffs "true";
        KeepCompressed "true";
        DefaultEnabled "false";
        Identifier "Contents-deb";


I've talked about this before, but here's the current version in case it's different. You think I QA this stuff before I paste+scrub this contents?

# File:
# Location: /mnt/public/Support/Platforms/devuan
# Author: bgstack15
# Startdate: 2019-07-01 18:48
# Title: The command to run for mostly-unattended updates on Devuan
# Purpose: Mostly-unattended apt-get dist-upgrade
# History:
#    2019-12-15 add the y/n if dist-upgrade will remove packages
#    2020-02-26 add --allow-downgrades for the libqt5core5a which was customized for freefilesync or similar
#    2023-02-28-3 19:47 add dbus-on which populates the dbus machine-id baloney for the dbus package
# Usage:
# Reference:
# Improve:
# Documentation:
export PATH=$PATH:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
test "${1}" = "preseed" && extrastring="--allow-downgrades"
mkdir -p ~/log
myupdate() {
   sudo dbus-on || :
   sudo apt-get update ;
   sudo DEBIAN_FRONTEND=noninteractive apt-get -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-overwrite" upgrade ;
   ___remove_count="$( yes no | sudo apt-get dist-upgrade 2>&1 | grep -oiE '[0-9]+ to remove' | grep -oE '[0-9]*' )"
   if test "${___remove_count}" = "0" ;
      ___to_remove="$( yes no | sudo apt-get dist-upgrade 2>&1 | awk 'BEGIN{a=0} /^[ \s]/{ if(a==1)print;} /^[a-zA-Z]/ {if(/REMOVED/ || /NEW /){a=1;print} else {a=0}}' )"
      echo "${___to_remove}" 1>&2
      echo "WARNING: are you sure you want to do this [yN]? " 1>&2
      test -z "${extrastring}" && { read response ; } || ___do_run="yes"
      if test "$( echo "${response}" | cut -c1 2>/dev/null | tr '[A-Z]' '[a-z]' )" = "y" ; then ___do_run="yes" ; fi
   if test "${___do_run}" = "yes" ;
      sudo DEBIAN_FRONTEND=noninteractive apt-get -q ${extrastring} -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-overwrite" dist-upgrade ;__f=$? ;
   date ; return ${__f} ;
} ; myupdate 2>&1 | tee -a ~/log/apt-get.upgrade.$( date "+%F" ).log

And dbus-on is a shell script from bgscripts that runs:

dbus-uuidgen | sudo tee /var/lib/dbus/machine-id 1>/dev/null 2>&1


I'm not sure this script is necessary. It was necessary in the past, and it doesn't hurt anyway, so I still just run it.

# Reference:
# Startdate: 2019-08-11
# History:
#    2020-04-30 updated
# only for devuan ceres
echo " ${@} " | grep -qE -e " -y " && export YESSTRING="-y"
sudo apt-get install "${YESSTRING}" --no-install-recommends policykit-1 libpam-elogind lightdm lightdm-gtk-greeter
sudo sed -i -r -e '/session\s+optional\s+pam_systemd\.so/s/systemd/elogind/;' /etc/pam.d/lightdm-greeter


This is the newest thing I can think of. It sets up postfix to connect to my smtp relay on my network that handles the gmail oauth2 authentication.

# Startdate: 2023-06-26-2 16:40
# Purpose: configure postfix, primarily for new VMs
# Documentation:
#    keep my network details out of the preseed.cfg
set -x
postconf -e 'relayhost ='


Looking at this now, I'm shocked and embarrassed in the complexity I've wrapped around sending an email.

# File:
# Startdate: 2021-05-17 08:59
# Purpose: send email message from newly build VM to myself with new hostname and IP address
# Usage:
# Dependencies:
#    bgscripts-core (>=1.5.0)
test -z "${ADDRESS}" && export ADDRESS="${1}" # use ADDRESS environment variable or else use first parameter
test -z "${ADDRESS}" && export
test -z "${SERVER}" && export SERVER="$( hostname --fqdn )"
# Ensure PATH contains /sbin and /usr/sbin for ip and sendmail (called by send)
echo "${PATH}" | grep -qE '^\/usr\/sbin|:\/usr\/sbin' || export PATH="${PATH}:/usr/sbin"
echo "${PATH}" | grep -qE '^\/sbin|:\/sbin'           || export PATH="${PATH}:/sbin"
# Modified and improved from bgscripts 2021-02-16a
thisip="$( ip -4 -o a s | awk '$1 !~ /^lo$/ && $2 !~ /^lo$/ && ($1 ~ /^e/ || $2 ~/^e/) {print $3,$4}' | awk -F'/' '{print $1}' | tr -dc '[0-9\.]' )"
# Send message
   echo "${SERVER} has IP address ${thisip}."
   echo "system finished build at $( TZ=UTC date "+%FT%TZ" )"
# leave cat INFILE unquoted in case it is inaccessible
} | send -f "root@${SERVER}" -h -s "${SERVER} is ${thisip}" "${ADDRESS}"