초기 구현: TailRescue Headscale ISO 프로젝트 정리
This commit is contained in:
195
scripts/build-live-iso.sh
Executable file
195
scripts/build-live-iso.sh
Executable file
@@ -0,0 +1,195 @@
|
||||
#!/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"
|
||||
Reference in New Issue
Block a user