Files
pxe-server/download-packages.sh
cproudlock 18537acbbc PXE server: fix WinPE re-image SMB connection loss
WinPE clients re-imaging the same machine hit "System error 53 -
network path not found" on the second attempt. systemctl restart smbd
did not help; only a full server power cycle cleared the state.

Root cause is kernel nf_conntrack: the default TCP ESTABLISHED timeout
is 5 days (432000s), so a session from the first WinPE run whose
client rebooted abnormally leaves an ASSURED ESTABLISHED entry that
ufw's state-tracking rules then mis-classify the new SYN against.

Fix applied in three layers:
- /etc/sysctl.d/99-pxe-conntrack.conf drops TCP ESTABLISHED timeout
  to 1 hour and shortens the half-closed states to 30s each.
- smb.conf gains socket options TCP_NODELAY SO_KEEPALIVE IPTOS_LOWDELAY
  plus keepalive = 30 and deadtime = 5. Active sessions refresh the
  conntrack timer every 30s via keepalives so they never age out;
  dead ones expire in an hour.
- /usr/local/sbin/smb-diag.sh snapshots kernel + Samba state for
  remote diagnosis; /usr/local/sbin/smb-soft-reset.sh walks a
  progressive recovery (nmbd/smbd restart, conntrack flush, arp
  flush, ss -K) as an alternative to power-cycling.

conntrack package added to download-packages.sh and playbook verify
list so the offline .deb bundle ships with it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 13:00:43 -04:00

96 lines
2.6 KiB
Bash
Executable File

#!/bin/bash
#
# download-packages.sh — Download all .deb packages needed for offline PXE server setup
#
# Run this on a machine with internet access running Ubuntu 24.04 (Noble).
# It downloads every .deb needed by the Ansible playbook into a local directory,
# which then gets bundled onto the installer USB.
#
# Usage:
# ./download-packages.sh [output_directory]
#
# Default output: ./offline-packages/
set -euo pipefail
OUT_DIR="${1:-./offline-packages}"
mkdir -p "$OUT_DIR"
# Packages installed by the Ansible playbook (pxe_server_setup.yml)
PLAYBOOK_PACKAGES=(
ansible
dnsmasq
apache2
samba
unzip
ufw
cron
wimtools
p7zip-full
grub-efi-amd64-bin
grub-common
conntrack
)
# Packages installed during autoinstall late-commands (NetworkManager, WiFi, etc.)
# These are already in your ubuntu_playbook/*.deb files, but we can refresh them here too.
AUTOINSTALL_PACKAGES=(
network-manager
wpasupplicant
wireless-tools
linux-firmware
firmware-sof-signed
)
ALL_PACKAGES=("${PLAYBOOK_PACKAGES[@]}" "${AUTOINSTALL_PACKAGES[@]}")
echo "============================================"
echo "Offline Package Downloader"
echo "============================================"
echo "Output directory: $OUT_DIR"
echo ""
echo "Packages to resolve:"
printf ' - %s\n' "${ALL_PACKAGES[@]}"
echo ""
# Update package cache
echo "[1/3] Updating package cache..."
sudo apt-get update -qq
# Simulate install to find all dependencies
echo "[2/3] Resolving dependencies..."
DEPS=$(apt-get install --simulate "${ALL_PACKAGES[@]}" 2>&1 \
| grep "^Inst " \
| awk '{print $2}' \
| sort -u)
DEP_COUNT=$(echo "$DEPS" | wc -l)
echo " Found $DEP_COUNT packages (including dependencies)"
# Download all packages
echo "[3/4] Downloading .deb packages to $OUT_DIR..."
cd "$OUT_DIR"
apt-get download $DEPS 2>&1 | tail -5
DEB_COUNT=$(ls -1 *.deb 2>/dev/null | wc -l)
TOTAL_SIZE=$(du -sh . | cut -f1)
echo " $DEB_COUNT packages ($TOTAL_SIZE)"
# Download pip wheels for Flask webapp (offline install)
echo "[4/4] Downloading Python wheels for webapp..."
PIP_DIR="$(dirname "$OUT_DIR")/pip-wheels"
mkdir -p "$PIP_DIR"
pip3 download -d "$PIP_DIR" flask lxml 2>&1 | tail -5
WHL_COUNT=$(ls -1 "$PIP_DIR"/*.whl "$PIP_DIR"/*.tar.gz 2>/dev/null | wc -l)
echo " $WHL_COUNT Python packages downloaded to pip-wheels/"
echo ""
echo "============================================"
echo "Download complete!"
echo "============================================"
echo " .deb packages: $DEB_COUNT ($TOTAL_SIZE) in $OUT_DIR/"
echo " Python wheels: $WHL_COUNT in $PIP_DIR/"
echo ""