better-argo-tunnels/deploy/sms/bootstrap-to-sms.sh

89 lines
3.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Copy tunnel authorized_keys from ingress to sms.taylor-co.com and install
# this directory's compose/Caddy example into /opt/taylor-sms-edge (or $INSTALL_DIR).
#
# export SMS_SSH=root@sms.taylor-co.com
# export INGRESS_SSH=root@ingress.nixc.us
# ./bootstrap-to-sms.sh
#
# First-time SSH: you may need to connect once to accept host keys, or set
# export SSH_EXTRA_OPTS='-o StrictHostKeyChecking=accept-new'
#
# Prereq: your SSH key can reach INGRESS and SMS as the given users.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
: "${INGRESS_SSH:=root@ingress.nixc.us}"
: "${INGRESS_AUTHORIZED_KEYS:=/home/tunnel/.ssh/authorized_keys}"
: "${SMS_SSH:=root@sms.taylor-co.com}"
# User on SMS whose ~/.ssh/authorized_keys receives the tunnel pubkeys (append, deduped)
: "${SMS_KEYS_USER:=root}"
: "${INSTALL_DIR:=/opt/taylor-sms-edge}"
# Optional: use a local file instead of scp from ingress
: "${AUTHORIZED_KEYS_LOCAL:=}"
SSH_OPTS=(${SSH_EXTRA_OPTS-})
tmp=
cleanup() { [[ -n "${tmp:-}" && -f "$tmp" ]] && rm -f "$tmp"; }
trap cleanup EXIT
if [[ -n "$AUTHORIZED_KEYS_LOCAL" ]]; then
tmp="$AUTHORIZED_KEYS_LOCAL"
[[ -f "$tmp" ]] || { echo "missing AUTHORIZED_KEYS_LOCAL=$tmp" >&2; exit 1; }
else
tmp="$(mktemp)"
echo "-> scp $INGRESS_SSH:$INGRESS_AUTHORIZED_KEYS"
scp "${SSH_OPTS[@]}" "$INGRESS_SSH:$INGRESS_AUTHORIZED_KEYS" "$tmp"
fi
echo "-> scp stack/Caddy to $SMS_SSH:$INSTALL_DIR"
ssh "${SSH_OPTS[@]}" "$SMS_SSH" "mkdir -p '$INSTALL_DIR'"
akeys_name="authorized_keys.from-ingress"
scp "${SSH_OPTS[@]}" \
"$SCRIPT_DIR/ssh-relay.compose.yml" \
"$SCRIPT_DIR/http-edge.compose.yml" \
"$SCRIPT_DIR/Caddyfile.example" \
"$SCRIPT_DIR/README.md" \
"$SMS_SSH:$INSTALL_DIR/"
scp "${SSH_OPTS[@]}" "$tmp" "$SMS_SSH:$INSTALL_DIR/$akeys_name"
echo "-> merge $akeys_name into $SMS_KEYS_USER on $SMS_SSH"
ssh "${SSH_OPTS[@]}" "$SMS_SSH" bash -s -- "$INSTALL_DIR" "$akeys_name" "$SMS_KEYS_USER" <<'REM'
set -euo pipefail
INST="$1"
F="$2"
USERX="$3"
H="$(getent passwd "$USERX" | cut -d: -f6)"
[[ -n "$H" ]] || { echo "no such user: $USERX" >&2; exit 1; }
install -d -m 700 "$H/.ssh"
KEYFILE="$H/.ssh/authorized_keys"
if [[ -f "$KEYFILE" ]]; then
cp -a "$KEYFILE" "$KEYFILE.bak.$(date +%Y%m%d%H%M%S)"
fi
touch "$KEYFILE"
chmod 600 "$KEYFILE"
# Append lines that are not already present
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line#"${line%%[![:space:]]*}"}"
line="${line%"${line##*[![:space:]]}"}"
[[ -z "$line" || "$line" == \#* ]] && continue
if ! grep -qxF -- "$line" "$KEYFILE" 2>/dev/null; then
echo "$line" >> "$KEYFILE"
fi
done < "$INST/$F"
# ownership
U="$(id -u "$USERX")" G="$(id -g "$USERX")"
chown -R "$U:$G" "$H/.ssh"
echo "-> installed keys for $USERX; backup may exist beside $KEYFILE"
REM
echo "-> done. On SMS:"
echo " cd $INSTALL_DIR && cp -n Caddyfile.example Caddyfile && \${EDITOR:-vi} Caddyfile"
echo " export INGRESS=138.197.167.216 RELAY_UPSTREAM=ingress.nixc.us:2222"
echo " docker compose -f http-edge.compose.yml up -d"
echo " docker compose -f ssh-relay.compose.yml up -d"
echo