196 lines
6.4 KiB
Bash
Executable File
196 lines
6.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
WORKDIR=${WORKDIR:-/root/tailrescue-live}
|
|
OUTDIR=${OUTDIR:-/root/tailrescue-dist}
|
|
ISO_NAME=${ISO_NAME:-tailrescue-headscale-$(date +%Y%m%d-%H%M).iso}
|
|
DIST=${DIST:-bookworm}
|
|
RESCUE_ENV=${RESCUE_ENV:-rescue.env}
|
|
AUTHORIZED_KEYS=${AUTHORIZED_KEYS:-templates/authorized_keys}
|
|
|
|
if [[ ! -f "$RESCUE_ENV" ]]; then
|
|
echo "missing $RESCUE_ENV; copy templates/rescue.env.example and fill field secrets" >&2
|
|
exit 2
|
|
fi
|
|
|
|
install -d "$WORKDIR" "$OUTDIR"
|
|
rm -rf "$WORKDIR"
|
|
mkdir -p "$WORKDIR"
|
|
cd "$WORKDIR"
|
|
|
|
lb config \
|
|
--distribution "$DIST" \
|
|
--archive-areas "main contrib non-free non-free-firmware" \
|
|
--binary-images iso-hybrid \
|
|
--bootappend-live "boot=live components hostname=tailrescue username=rescue"
|
|
|
|
cat > config/package-lists/tailrescue.list.chroot <<"PKGS"
|
|
systemd-sysv
|
|
openssh-server
|
|
sudo
|
|
curl
|
|
ca-certificates
|
|
gnupg
|
|
iptables
|
|
nftables
|
|
iproute2
|
|
iputils-ping
|
|
dnsutils
|
|
net-tools
|
|
isc-dhcp-client
|
|
pciutils
|
|
usbutils
|
|
lshw
|
|
parted
|
|
gdisk
|
|
fdisk
|
|
ntfs-3g
|
|
rsync
|
|
rclone
|
|
restic
|
|
smartmontools
|
|
gddrescue
|
|
pv
|
|
jq
|
|
tmux
|
|
vim-tiny
|
|
less
|
|
firmware-linux
|
|
firmware-linux-free
|
|
firmware-linux-nonfree
|
|
firmware-misc-nonfree
|
|
firmware-realtek
|
|
firmware-atheros
|
|
firmware-brcm80211
|
|
firmware-bnx2
|
|
firmware-bnx2x
|
|
firmware-iwlwifi
|
|
firmware-libertas
|
|
PKGS
|
|
|
|
mkdir -p config/includes.chroot/etc/apt/keyrings config/includes.chroot/etc/apt/sources.list.d
|
|
curl -fsSL https://pkgs.tailscale.com/stable/debian/${DIST}.noarmor.gpg \
|
|
-o config/includes.chroot/etc/apt/keyrings/tailscale-archive-keyring.gpg
|
|
cat > config/includes.chroot/etc/apt/sources.list.d/tailscale.list <<TAILSRC
|
|
deb [signed-by=/etc/apt/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/debian ${DIST} main
|
|
TAILSRC
|
|
mkdir -p config/packages.chroot
|
|
(cd config/packages.chroot && apt-get download tailscale)
|
|
|
|
mkdir -p config/includes.chroot/etc/tailrescue
|
|
cp "$OLDPWD/$RESCUE_ENV" config/includes.chroot/etc/tailrescue/rescue.env
|
|
chmod 600 config/includes.chroot/etc/tailrescue/rescue.env
|
|
|
|
mkdir -p config/includes.chroot/usr/local/bin config/includes.chroot/etc/systemd/system
|
|
cat > config/includes.chroot/usr/local/bin/rescue-status <<"RS"
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
echo "== TailRescue Status =="
|
|
echo "Hostname: $(hostname)"
|
|
echo "Date: $(date -Is)"
|
|
echo "LAN IPs:"
|
|
ip -br addr || true
|
|
echo
|
|
echo "Routes:"
|
|
ip route || true
|
|
echo
|
|
echo "Tailscale:"
|
|
tailscale status || true
|
|
echo
|
|
echo "Disks:"
|
|
lsblk -o NAME,SIZE,FSTYPE,LABEL,UUID,MOUNTPOINTS,MODEL || true
|
|
echo
|
|
echo "SSH: ssh rescue@<tailscale-ip>"
|
|
RS
|
|
chmod +x config/includes.chroot/usr/local/bin/rescue-status
|
|
|
|
cat > config/includes.chroot/usr/local/bin/list-disks <<"LD"
|
|
#!/bin/bash
|
|
exec lsblk -o NAME,TYPE,SIZE,FSTYPE,LABEL,UUID,MOUNTPOINTS,MODEL,SERIAL "$@"
|
|
LD
|
|
chmod +x config/includes.chroot/usr/local/bin/list-disks
|
|
|
|
cat > config/includes.chroot/usr/local/bin/mount-ntfs-ro <<"MN"
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
if [ "$#" -ne 2 ]; then echo "usage: mount-ntfs-ro /dev/sdXN /mnt/windows" >&2; exit 2; fi
|
|
mkdir -p "$2"
|
|
exec ntfs-3g -o ro,show_sys_files,streams_interface=windows "$1" "$2"
|
|
MN
|
|
chmod +x config/includes.chroot/usr/local/bin/mount-ntfs-ro
|
|
|
|
cat > config/includes.chroot/usr/local/bin/tailrescue-firstboot <<"FB"
|
|
#!/bin/bash
|
|
set -u
|
|
exec > >(tee -a /var/log/tailrescue-firstboot.log) 2>&1
|
|
set -x
|
|
ENV_FILE=/etc/tailrescue/rescue.env
|
|
[ -f "$ENV_FILE" ] && . "$ENV_FILE"
|
|
RESCUE_USER=${RESCUE_USER:-rescue}
|
|
TAILSCALE_LOGIN_SERVER=${TAILSCALE_LOGIN_SERVER:-https://head.pharmq.kr}
|
|
TAILSCALE_TAGS=${TAILSCALE_TAGS:-tag:rescue}
|
|
mkdir -p /run/sshd
|
|
systemctl enable --now ssh || systemctl enable --now sshd || service ssh restart || /usr/sbin/sshd || true
|
|
systemctl enable --now tailscaled || service tailscaled start || true
|
|
sleep 3
|
|
if [ -n "${TAILSCALE_AUTHKEY:-}" ]; then
|
|
tailscale up --login-server "$TAILSCALE_LOGIN_SERVER" --authkey "$TAILSCALE_AUTHKEY" --hostname "tailrescue-$(cat /etc/machine-id | cut -c1-8)" --advertise-tags "$TAILSCALE_TAGS" || true
|
|
fi
|
|
rescue-status || true
|
|
FB
|
|
chmod +x config/includes.chroot/usr/local/bin/tailrescue-firstboot
|
|
|
|
cat > config/includes.chroot/etc/systemd/system/tailrescue-firstboot.service <<"SVC"
|
|
[Unit]
|
|
Description=TailRescue first boot SSH and Headscale enrollment
|
|
After=network-online.target tailscaled.service ssh.service
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/bin/tailrescue-firstboot
|
|
RemainAfterExit=yes
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
SVC
|
|
ln -sf /etc/systemd/system/tailrescue-firstboot.service config/includes.chroot/etc/systemd/system/multi-user.target.wants/tailrescue-firstboot.service 2>/dev/null || true
|
|
|
|
mkdir -p config/hooks/normal
|
|
cat > config/hooks/normal/0900-tailrescue-users.hook.chroot <<"HOOK"
|
|
#!/bin/bash
|
|
set -eux
|
|
. /etc/tailrescue/rescue.env || true
|
|
USER_NAME=${RESCUE_USER:-rescue}
|
|
PASS_PLAIN=${RESCUE_PASSWORD:-}
|
|
if ! id "$USER_NAME" >/dev/null 2>&1; then useradd -m -s /bin/bash "$USER_NAME"; fi
|
|
if [ -n "$PASS_PLAIN" ]; then echo "$USER_NAME:$PASS_PLAIN" | chpasswd; fi
|
|
usermod -aG sudo "$USER_NAME"
|
|
echo "$USER_NAME ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/90-rescue
|
|
chmod 0440 /etc/sudoers.d/90-rescue
|
|
mkdir -p /home/$USER_NAME/.ssh /root/.ssh
|
|
if [ -f /etc/tailrescue/authorized_keys ]; then
|
|
cp /etc/tailrescue/authorized_keys /home/$USER_NAME/.ssh/authorized_keys
|
|
cp /etc/tailrescue/authorized_keys /root/.ssh/authorized_keys
|
|
fi
|
|
chown -R $USER_NAME:$USER_NAME /home/$USER_NAME/.ssh
|
|
chmod 700 /home/$USER_NAME/.ssh /root/.ssh
|
|
chmod 600 /home/$USER_NAME/.ssh/authorized_keys /root/.ssh/authorized_keys 2>/dev/null || true
|
|
sed -i "s/^#\?PasswordAuthentication .*/PasswordAuthentication yes/" /etc/ssh/sshd_config || true
|
|
sed -i "s/^#\?PermitRootLogin .*/PermitRootLogin prohibit-password/" /etc/ssh/sshd_config || true
|
|
sed -i "s/^#\?PubkeyAuthentication .*/PubkeyAuthentication yes/" /etc/ssh/sshd_config || true
|
|
grep -q "^AllowUsers " /etc/ssh/sshd_config && sed -i "s/^AllowUsers .*/AllowUsers $USER_NAME root/" /etc/ssh/sshd_config || echo "AllowUsers $USER_NAME root" >> /etc/ssh/sshd_config
|
|
HOOK
|
|
chmod +x config/hooks/normal/0900-tailrescue-users.hook.chroot
|
|
|
|
if [[ -f "$OLDPWD/$AUTHORIZED_KEYS" ]]; then
|
|
cp "$OLDPWD/$AUTHORIZED_KEYS" config/includes.chroot/etc/tailrescue/authorized_keys
|
|
elif [[ -f "$OLDPWD/templates/authorized_keys.example" ]]; then
|
|
cp "$OLDPWD/templates/authorized_keys.example" config/includes.chroot/etc/tailrescue/authorized_keys
|
|
fi
|
|
|
|
lb build
|
|
cp -f live-image-amd64.hybrid.iso "$OUTDIR/$ISO_NAME"
|
|
(cd "$OUTDIR" && sha256sum "$ISO_NAME" > SHA256SUMS && echo "$ISO_NAME" > latest.txt)
|
|
echo "$OUTDIR/$ISO_NAME"
|