#!/bin/bash # first-boot.sh — Iron Legion Fleet Node Post-Install Bootstrap # Run manually AFTER confirming autoinstall boots successfully # Date: May 23, 2026 set -euo pipefail # ========== CONFIG ========== TRUENAS_IP="192.168.16.254" NFS_SHARE="/mnt/Ice/Backup/swarm-data" LOCAL_MOUNT="/mnt/swarm-data" ANSIBLE_REPO="https://gitea.nb.bobbysh.me/Iron-Legion/ansible-pull-deploy.git" ANSIBLE_DIR="/var/lib/ansible/local" TAILSCALE_API_KEY="${TAILSCALE_API_KEY:-}" # Set before running, or hardcode for unattended # ========== DOCKER ========== echo "[1/6] Installing Docker CE..." if ! command -v docker >/dev/null 2>&1; then curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable docker systemctl start docker usermod -aG docker jarvis echo "Docker installed." else echo "Docker already present." fi # ========== NFS AUTOMOUNT ========== echo "[2/6] Configuring NFS automount for TrueNAS..." mkdir -p "$LOCAL_MOUNT" if ! grep -q "$TRUENAS_IP:$NFS_SHARE" /etc/fstab; then echo "$TRUENAS_IP:$NFS_SHARE $LOCAL_MOUNT nfs defaults,_netdev 0 0" >> /etc/fstab mount "$LOCAL_MOUNT" echo "NFS mount added to fstab and mounted." else echo "NFS fstab entry already exists." fi # ========== ANSIBLE-PULL REPO ========== echo "[3/6] Cloning ansible-pull repo..." mkdir -p "$ANSIBLE_DIR" if [ ! -d "$ANSIBLE_DIR/.git" ]; then cd "$ANSIBLE_DIR" git clone "$ANSIBLE_REPO" . echo "Ansible repo cloned." else echo "Ansible repo already present." fi # ========== TAILSCALE ========== echo "[4/6] Installing Tailscale..." if ! command -v tailscale >/dev/null 2>&1; then curl -fsSL https://tailscale.com/install.sh | sh echo "Tailscale installed." else echo "Tailscale already present." fi if [ -n "$TAILSCALE_API_KEY" ]; then echo "[5/6] Joining Tailnet..." tailscale up --auth-key="$TAILSCALE_API_KEY" --ssh --accept-routes echo "Tailscale joined." else echo "[5/6] TAILSCALE_API_KEY not set. Run manually:" echo " export TAILSCALE_API_KEY=tskey-..." echo " tailscale up --auth-key=\$TAILSCALE_API_KEY --ssh --accept-routes" fi # ========== ENABLE SERVICES ========== echo "[6/6] Enabling services..." systemctl enable ssh docker systemctl restart ssh docker # ========== DONE ========== echo "" echo "========================================" echo " Fleet node bootstrap complete" echo "========================================" echo "Docker: $(docker --version)" echo "Tailscale: $(tailscale version 2>/dev/null | head -1 || echo 'not joined')" echo "NFS mount: $(df -h | grep swarm-data || echo 'not mounted')" echo "Ansible: $(ansible --version | head -1 || echo 'not checked')" echo "" echo "Next: run ansible-pull from $ANSIBLE_DIR" echo " cd $ANSIBLE_DIR && ansible-pull -d . -U $ANSIBLE_REPO"