178 lines
No EOL
5 KiB
Bash
178 lines
No EOL
5 KiB
Bash
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
# ---------- Safety / logging ----------
|
|
trap 'echo "Error on line $LINENO. Exiting." >&2' ERR
|
|
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "This script must be run as root." >&2
|
|
exit 1
|
|
fi
|
|
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
|
|
MARKER_DIR="/var/lib/lancommander"
|
|
MARKER_FILE="$MARKER_DIR/setup.done"
|
|
|
|
# ---------- One-time guard ----------
|
|
if [[ -f "$MARKER_FILE" ]]; then
|
|
echo "Setup already completed previously ($MARKER_FILE exists)."
|
|
echo "Skipping installation steps."
|
|
else
|
|
mkdir -p "$MARKER_DIR"
|
|
fi
|
|
|
|
# ---------- Helpers ----------
|
|
ensure_user() {
|
|
local name="$1"
|
|
local home="$2"
|
|
# Use nologin shell for service accounts
|
|
if id -u "$name" >/dev/null 2>&1; then
|
|
echo "User '$name' already exists. Skipping creation."
|
|
else
|
|
useradd -m -d "$home" -s /usr/sbin/nologin "$name"
|
|
echo "Created user '$name' with home '$home'."
|
|
fi
|
|
}
|
|
|
|
ensure_dir_owned() {
|
|
local path="$1"
|
|
local owner="$2"
|
|
local group="$3"
|
|
install -d -m 0755 -o "$owner" -g "$group" "$path"
|
|
}
|
|
|
|
apt_update_once() {
|
|
# Run apt-get update only once per invocation when needed
|
|
if [[ -z "${_APT_UPDATED:-}" ]]; then
|
|
apt-get update
|
|
_APT_UPDATED=1
|
|
fi
|
|
}
|
|
|
|
apt_install() {
|
|
apt_update_once
|
|
apt-get install -y --no-install-recommends "$@"
|
|
}
|
|
|
|
# ---------- yt-dlp + ffmpeg ----------
|
|
install_ytdlp() {
|
|
echo "Installing yt-dlp and ffmpeg..."
|
|
|
|
apt_install ffmpeg curl ca-certificates
|
|
|
|
if [[ -x "/usr/local/bin/yt-dlp" ]]; then
|
|
echo "yt-dlp already installed. Skipping download."
|
|
else
|
|
# Use the self-contained binary (bundles its own Python) instead of the
|
|
# bare "yt-dlp" zipapp asset, which requires a system python3.
|
|
case "$(uname -m)" in
|
|
x86_64|amd64) ytdlp_asset="yt-dlp_linux" ;;
|
|
aarch64|arm64) ytdlp_asset="yt-dlp_linux_aarch64" ;;
|
|
armv7l) ytdlp_asset="yt-dlp_linux_armv7l" ;;
|
|
*) ytdlp_asset="yt-dlp_linux" ;;
|
|
esac
|
|
|
|
echo "Downloading yt-dlp ($ytdlp_asset)..."
|
|
curl -fsSL "https://github.com/yt-dlp/yt-dlp/releases/latest/download/${ytdlp_asset}" -o /usr/local/bin/yt-dlp
|
|
chmod +x /usr/local/bin/yt-dlp
|
|
echo "yt-dlp installed."
|
|
fi
|
|
}
|
|
|
|
# ---------- SteamCMD ----------
|
|
install_steamcmd() {
|
|
echo "Installing SteamCMD..."
|
|
|
|
apt_install wget ca-certificates software-properties-common lib32gcc-s1 lib32stdc++6
|
|
|
|
# Create SteamCMD directory in /app/Data/Steam for persistence
|
|
STEAMCMD_DIR="/app/Data/Steam"
|
|
mkdir -p "$STEAMCMD_DIR"
|
|
|
|
# Create .steam directory for credential persistence
|
|
mkdir -p "$STEAMCMD_DIR/.steam/steamcmd"
|
|
|
|
# Set permissions to allow the app to use SteamCMD
|
|
chmod -R 755 "$STEAMCMD_DIR"
|
|
|
|
if [[ -x "$STEAMCMD_DIR/steamcmd.sh" ]]; then
|
|
echo "SteamCMD already present. Skipping download."
|
|
else
|
|
echo "Downloading SteamCMD..."
|
|
tmpdir="$(mktemp -d)"
|
|
(
|
|
cd "$tmpdir"
|
|
wget -qO steamcmd_linux.tar.gz "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz"
|
|
tar -xzf steamcmd_linux.tar.gz -C "$STEAMCMD_DIR"
|
|
)
|
|
rm -rf "$tmpdir"
|
|
chmod +x "$STEAMCMD_DIR/steamcmd.sh"
|
|
echo "SteamCMD installed to $STEAMCMD_DIR."
|
|
fi
|
|
|
|
# Ensure .steam directory exists for credential persistence
|
|
mkdir -p "$STEAMCMD_DIR/.steam/steamcmd"
|
|
chmod -R 755 "$STEAMCMD_DIR/.steam"
|
|
}
|
|
|
|
# ---------- WINE ----------
|
|
install_wine() {
|
|
echo "Installing WINE..."
|
|
|
|
apt_install wine wine32 wine64 libwine fonts-wine winetricks cabextract unzip wget ca-certificates
|
|
|
|
ensure_user "wine" "/home/wine"
|
|
ensure_dir_owned "/home/wine/.wine" "wine" "wine"
|
|
|
|
# Initialize wine prefix once (headless-friendly)
|
|
if [[ -f "/home/wine/.wine/system.reg" ]]; then
|
|
echo "WINE prefix already initialized. Skipping winecfg."
|
|
else
|
|
echo "Initializing WINE prefix..."
|
|
# Suppress noisy logs and run a minimal init
|
|
su -s /bin/bash -c 'WINEDEBUG=-all WINEARCH=win64 wineboot -u || true' wine
|
|
fi
|
|
|
|
echo "WINE setup complete."
|
|
}
|
|
|
|
# ---------- Conditional execution (only if first run or explicitly requested again) ----------
|
|
if [[ ! -f "$MARKER_FILE" ]]; then
|
|
install_ytdlp
|
|
|
|
if [[ "${STEAMCMD:-0}" == "1" ]]; then
|
|
echo "STEAMCMD=1 detected, installing SteamCMD..."
|
|
install_steamcmd
|
|
else
|
|
echo "STEAMCMD not set to 1, skipping SteamCMD installation."
|
|
fi
|
|
|
|
if [[ "${WINE:-0}" == "1" ]]; then
|
|
echo "WINE=1 detected, installing WINE..."
|
|
install_wine
|
|
else
|
|
echo "WINE not set to 1, skipping WINE installation."
|
|
fi
|
|
|
|
# Mark as completed
|
|
date -Is > "$MARKER_FILE"
|
|
echo "Setup steps completed. Marker written to $MARKER_FILE"
|
|
else
|
|
# Even if previously completed, allow user to force re-run parts by setting REINSTALL=1
|
|
if [[ "${REINSTALL:-0}" == "1" ]]; then
|
|
echo "REINSTALL=1 set — re-running requested installers if toggled."
|
|
install_ytdlp
|
|
if [[ "${STEAMCMD:-0}" == "1" ]]; then install_steamcmd; fi
|
|
if [[ "${WINE:-0}" == "1" ]]; then install_wine; fi
|
|
date -Is > "$MARKER_FILE"
|
|
fi
|
|
fi
|
|
|
|
# ---------- Start app ----------
|
|
echo "Switching to /app..."
|
|
cd /app
|
|
|
|
echo "Starting LANCommander Server..."
|
|
exec dotnet LANCommander.Server.dll --docker |