Initial import: bare-metal stacks, Server UI, GPU fan, tutorials.
Infrastructure configs for GMKtec K11 (Docker, vLLM, LocalAI, ComfyUI, control-plane, gpu-fan agent, Server UI with CLI/file explorer/GPU fan curve). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Executable
+421
@@ -0,0 +1,421 @@
|
||||
#!/usr/bin/env bash
|
||||
# Statyczne IP na dwóch kartach Ethernet — GMKtec K11 (gmktec-k11)
|
||||
#
|
||||
# Skanuje link na eno1 / enp3s0, pokazuje menu CLI i generuje Netplan.
|
||||
# Rollback: scripts/restore-dhcp-network.sh
|
||||
set -euo pipefail
|
||||
|
||||
NETPLAN_FILE="/etc/netplan/00-installer-config.yaml"
|
||||
NIC_A="eno1"
|
||||
NIC_B="enp3s0"
|
||||
IP80="192.168.100.80/24"
|
||||
IP90="192.168.100.90/24"
|
||||
GATEWAY="192.168.100.1"
|
||||
DNS="192.168.100.1"
|
||||
|
||||
DRY_RUN=false
|
||||
NON_INTERACTIVE=false
|
||||
PROFILE=""
|
||||
|
||||
# Po wyborze profilu (ustawiane przez apply_profile)
|
||||
GW_NIC=""
|
||||
ENO1_IPS=""
|
||||
ENP3S0_IPS=""
|
||||
PROFILE_NAME=""
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Użycie: sudo ./configure-static-dual-nic.sh [opcje]
|
||||
|
||||
Opcje:
|
||||
--dry-run Skan + menu (lub profil) + YAML, bez zapisu i apply
|
||||
--non-interactive Pomiń menu (wymaga --profile)
|
||||
--profile <nazwa> Profil konfiguracji (patrz niżej)
|
||||
-h, --help Ta pomoc
|
||||
|
||||
Profile (--non-interactive):
|
||||
dual-eno1 eno1=.80+brama, enp3s0=.90
|
||||
dual-enp3s0 enp3s0=.80+brama, eno1=.90
|
||||
single-eno1-80 tylko eno1: .80+brama
|
||||
single-eno1-both tylko eno1: .80+.90+brama
|
||||
single-enp3s0-90 tylko enp3s0: .90+brama
|
||||
single-enp3s0-80 tylko enp3s0: .80+brama
|
||||
single-enp3s0-both tylko enp3s0: .80+.90+brama
|
||||
|
||||
Interaktywnie skrypt skanuje kable i pokazuje tylko pasujące opcje.
|
||||
|
||||
Rollback: sudo ./restore-dhcp-network.sh
|
||||
EOF
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--non-interactive) NON_INTERACTIVE=true; shift ;;
|
||||
--profile)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "BŁĄD: --profile wymaga nazwy." >&2
|
||||
exit 1
|
||||
fi
|
||||
PROFILE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "Nieznana opcja: $1" >&2; usage >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
||||
echo "BŁĄD: Uruchom skrypt jako root (sudo)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v netplan >/dev/null 2>&1; then
|
||||
echo "BŁĄD: netplan nie jest zainstalowany." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for nic in "$NIC_A" "$NIC_B"; do
|
||||
if ! ip link show "$nic" &>/dev/null; then
|
||||
echo "BŁĄD: Interfejs $nic nie istnieje." >&2
|
||||
ip -br link || true
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
has_link() {
|
||||
local nic="$1"
|
||||
if command -v ethtool >/dev/null 2>&1; then
|
||||
ethtool "$nic" 2>/dev/null | grep -q "Link detected: yes"
|
||||
return $?
|
||||
fi
|
||||
ip link show "$nic" | grep -q "LOWER_UP"
|
||||
}
|
||||
|
||||
current_ipv4() {
|
||||
local nic="$1"
|
||||
ip -4 -br addr show "$nic" 2>/dev/null | awk '{print $3}' | head -1
|
||||
}
|
||||
|
||||
# Zwraca: LINK_ENO1 LINK_ENP3S0 (yes/no)
|
||||
scan_nics() {
|
||||
LINK_ENO1="no"
|
||||
LINK_ENP3S0="no"
|
||||
has_link "$NIC_A" && LINK_ENO1="yes"
|
||||
has_link "$NIC_B" && LINK_ENP3S0="yes"
|
||||
|
||||
echo "=== Skan interfejsów ==="
|
||||
printf " %-8s %-6s %-8s %s\n" "Interfejs" "Stan" "Link" "IPv4"
|
||||
for nic in "$NIC_A" "$NIC_B"; do
|
||||
local state link_flag ipv4
|
||||
state=$(ip -br link show "$nic" | awk '{print $2}')
|
||||
if has_link "$nic"; then link_flag="TAK"; else link_flag="NIE"; fi
|
||||
ipv4=$(current_ipv4 "$nic")
|
||||
ipv4="${ipv4:-—}"
|
||||
printf " %-8s %-6s %-8s %s\n" "$nic" "$state" "$link_flag" "$ipv4"
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
ips_has() {
|
||||
local list="$1"
|
||||
local which="$2"
|
||||
[[ " $list " == *" $which "* ]]
|
||||
}
|
||||
|
||||
apply_profile() {
|
||||
local key="$1"
|
||||
PROFILE_NAME="$key"
|
||||
case "$key" in
|
||||
dual-eno1)
|
||||
GW_NIC="$NIC_A"; ENO1_IPS="80"; ENP3S0_IPS="90" ;;
|
||||
dual-enp3s0)
|
||||
GW_NIC="$NIC_B"; ENO1_IPS="90"; ENP3S0_IPS="80" ;;
|
||||
single-eno1-80)
|
||||
GW_NIC="$NIC_A"; ENO1_IPS="80"; ENP3S0_IPS="" ;;
|
||||
single-eno1-both)
|
||||
GW_NIC="$NIC_A"; ENO1_IPS="80 90"; ENP3S0_IPS="" ;;
|
||||
single-enp3s0-90)
|
||||
GW_NIC="$NIC_B"; ENO1_IPS=""; ENP3S0_IPS="90" ;;
|
||||
single-enp3s0-80)
|
||||
GW_NIC="$NIC_B"; ENO1_IPS=""; ENP3S0_IPS="80" ;;
|
||||
single-enp3s0-both)
|
||||
GW_NIC="$NIC_B"; ENO1_IPS=""; ENP3S0_IPS="80 90" ;;
|
||||
*)
|
||||
echo "BŁĄD: Nieznany profil: $key" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
profile_description() {
|
||||
local key="$1"
|
||||
case "$key" in
|
||||
dual-eno1) echo "eno1=.80+brama, enp3s0=.90" ;;
|
||||
dual-enp3s0) echo "enp3s0=.80+brama, eno1=.90" ;;
|
||||
single-eno1-80) echo "eno1=.80+brama (enp3s0 bez adresu)" ;;
|
||||
single-eno1-both) echo "eno1=.80+.90+brama (oba IP na eno1)" ;;
|
||||
single-enp3s0-90) echo "enp3s0=.90+brama (usługi LAN)" ;;
|
||||
single-enp3s0-80) echo "enp3s0=.80+brama" ;;
|
||||
single-enp3s0-both) echo "enp3s0=.80+.90+brama (oba IP na enp3s0)" ;;
|
||||
*) echo "$key" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# MENU_KEYS[], MENU_LABELS[] — numeracja od 1
|
||||
declare -a MENU_KEYS=()
|
||||
declare -a MENU_LABELS=()
|
||||
|
||||
build_menu() {
|
||||
MENU_KEYS=()
|
||||
MENU_LABELS=()
|
||||
|
||||
if [[ "$LINK_ENO1" == "yes" && "$LINK_ENP3S0" == "yes" ]]; then
|
||||
MENU_KEYS+=(dual-eno1 dual-enp3s0)
|
||||
MENU_LABELS+=(
|
||||
"Dual: eno1=.80+brama, enp3s0=.90 (zalecane)"
|
||||
"Dual odwrócony: enp3s0=.80+brama, eno1=.90"
|
||||
)
|
||||
elif [[ "$LINK_ENO1" == "yes" ]]; then
|
||||
MENU_KEYS+=(single-eno1-80 single-eno1-both)
|
||||
MENU_LABELS+=(
|
||||
"Pojedynczy eno1: .80+brama"
|
||||
"Pojedynczy eno1: .80+.90+brama (awaryjnie, oba IP na jednej karcie)"
|
||||
)
|
||||
elif [[ "$LINK_ENP3S0" == "yes" ]]; then
|
||||
MENU_KEYS+=(single-enp3s0-90 single-enp3s0-80 single-enp3s0-both)
|
||||
MENU_LABELS+=(
|
||||
"Pojedynczy enp3s0: .90+brama (zalecane — usługi Docker)"
|
||||
"Pojedynczy enp3s0: .80+brama"
|
||||
"Pojedynczy enp3s0: .80+.90+brama (oba IP na jednej karcie)"
|
||||
)
|
||||
else
|
||||
echo "BŁĄD: Żaden interfejs nie ma aktywnego linku (kabel sieciowy)." >&2
|
||||
echo " Podłącz kabel do eno1 lub enp3s0 i uruchom skrypt ponownie." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
show_menu() {
|
||||
echo "=== Wybierz konfigurację ==="
|
||||
local i
|
||||
for i in "${!MENU_KEYS[@]}"; do
|
||||
printf " %d) %s\n" "$((i + 1))" "${MENU_LABELS[$i]}"
|
||||
done
|
||||
printf " 0) Anuluj\n"
|
||||
echo ""
|
||||
}
|
||||
|
||||
pick_profile_interactive() {
|
||||
build_menu
|
||||
show_menu
|
||||
|
||||
local choice
|
||||
while true; do
|
||||
read -r -p "Wybór [1-${#MENU_KEYS[@]}, domyślnie 1]: " choice
|
||||
choice="${choice:-1}"
|
||||
if [[ "$choice" == "0" ]]; then
|
||||
echo "Anulowano."
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#MENU_KEYS[@]} )); then
|
||||
apply_profile "${MENU_KEYS[$((choice - 1))]}"
|
||||
return 0
|
||||
fi
|
||||
echo "Nieprawidłowy wybór."
|
||||
done
|
||||
}
|
||||
|
||||
pick_profile() {
|
||||
if [[ -n "$PROFILE" ]]; then
|
||||
apply_profile "$PROFILE"
|
||||
elif [[ "$NON_INTERACTIVE" == true ]]; then
|
||||
echo "BŁĄD: --non-interactive wymaga --profile <nazwa>." >&2
|
||||
exit 1
|
||||
else
|
||||
pick_profile_interactive
|
||||
fi
|
||||
}
|
||||
|
||||
build_nic_block() {
|
||||
local nic="$1"
|
||||
local ips="$2"
|
||||
local is_gw="$3"
|
||||
local has_cable="$4"
|
||||
|
||||
local optional="true"
|
||||
[[ "$is_gw" == "yes" ]] && optional="false"
|
||||
|
||||
echo " ${nic}:"
|
||||
echo " dhcp4: false"
|
||||
echo " dhcp6: false"
|
||||
echo " optional: ${optional}"
|
||||
|
||||
if [[ -n "$ips" ]]; then
|
||||
echo " ignore-carrier: true"
|
||||
echo " addresses:"
|
||||
ips_has "$ips" "80" && echo " - ${IP80}"
|
||||
ips_has "$ips" "90" && echo " - ${IP90}"
|
||||
fi
|
||||
|
||||
if [[ "$is_gw" == "yes" ]]; then
|
||||
echo " routes:"
|
||||
echo " - to: default"
|
||||
echo " via: ${GATEWAY}"
|
||||
echo " metric: 100"
|
||||
echo " nameservers:"
|
||||
echo " addresses:"
|
||||
echo " - ${DNS}"
|
||||
fi
|
||||
}
|
||||
|
||||
write_netplan_file() {
|
||||
local content="$1"
|
||||
local tmp
|
||||
tmp=$(mktemp) || { echo "BŁĄD: mktemp nie powiódł się." >&2; return 1; }
|
||||
chmod 600 "$tmp"
|
||||
printf '%s\n' "$content" > "$tmp"
|
||||
mv -f "$tmp" "$NETPLAN_FILE"
|
||||
chmod 600 "$NETPLAN_FILE"
|
||||
}
|
||||
|
||||
render_netplan() {
|
||||
local eno1_gw="no" enp3_gw="no"
|
||||
[[ "$GW_NIC" == "$NIC_A" ]] && eno1_gw="yes"
|
||||
[[ "$GW_NIC" == "$NIC_B" ]] && enp3_gw="yes"
|
||||
|
||||
{
|
||||
echo "network:"
|
||||
echo " version: 2"
|
||||
echo " renderer: networkd"
|
||||
echo " ethernets:"
|
||||
build_nic_block "$NIC_A" "$ENO1_IPS" "$eno1_gw" "$LINK_ENO1"
|
||||
build_nic_block "$NIC_B" "$ENP3S0_IPS" "$enp3_gw" "$LINK_ENP3S0"
|
||||
}
|
||||
}
|
||||
|
||||
expected_ips_for_nic() {
|
||||
local nic="$1"
|
||||
local ips=""
|
||||
if [[ "$nic" == "$NIC_A" ]]; then ips="$ENO1_IPS"; else ips="$ENP3S0_IPS"; fi
|
||||
if ips_has "$ips" "80"; then echo "192.168.100.80"; fi
|
||||
if ips_has "$ips" "90"; then echo "192.168.100.90"; fi
|
||||
}
|
||||
|
||||
verify_config() {
|
||||
local ok=true
|
||||
echo "=== Weryfikacja ==="
|
||||
|
||||
for nic in "$NIC_A" "$NIC_B"; do
|
||||
local ip
|
||||
while read -r ip; do
|
||||
[[ -z "$ip" ]] && continue
|
||||
if ip -4 addr show dev "$nic" | grep -q "inet ${ip}/"; then
|
||||
echo " ${nic}: ${ip} OK"
|
||||
else
|
||||
echo " ${nic}: ${ip} BRAK — próbuję networkctl reconfigure ..."
|
||||
networkctl reconfigure "$nic" 2>/dev/null || true
|
||||
sleep 2
|
||||
if ip -4 addr show dev "$nic" | grep -q "inet ${ip}/"; then
|
||||
echo " ${nic}: ${ip} OK (po reconfigure)"
|
||||
else
|
||||
echo " ${nic}: ${ip} NADAL BRAK"
|
||||
ok=false
|
||||
fi
|
||||
fi
|
||||
done < <(expected_ips_for_nic "$nic")
|
||||
done
|
||||
|
||||
ip -br addr show "$NIC_A" "$NIC_B" 2>/dev/null || ip -br addr show "$NIC_A" "$NIC_B"
|
||||
echo "--- trasy ---"
|
||||
ip route show default || echo " (brak trasy domyślnej)"
|
||||
|
||||
if ping -c 1 -W 3 -I "$GW_NIC" "$GATEWAY" &>/dev/null; then
|
||||
echo " ping -I ${GW_NIC} ${GATEWAY}: OK"
|
||||
else
|
||||
echo " ping -I ${GW_NIC} ${GATEWAY}: NIEUDANY"
|
||||
ok=false
|
||||
fi
|
||||
|
||||
if [[ "$ok" != true ]]; then
|
||||
echo ""
|
||||
echo "WERYFIKACJA NIEUDANA — sprawdź kable, rezerwację IP na routerze."
|
||||
echo "Rollback: sudo $(dirname "$0")/restore-dhcp-network.sh"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
wait_for_ips() {
|
||||
local attempt
|
||||
for attempt in $(seq 1 15); do
|
||||
local missing=false
|
||||
for nic in "$NIC_A" "$NIC_B"; do
|
||||
local ip
|
||||
while read -r ip; do
|
||||
[[ -z "$ip" ]] && continue
|
||||
ip -4 addr show dev "$nic" | grep -q "inet ${ip}/" || missing=true
|
||||
done < <(expected_ips_for_nic "$nic")
|
||||
done
|
||||
[[ "$missing" == false ]] && return 0
|
||||
networkctl reconfigure "$NIC_A" 2>/dev/null || true
|
||||
networkctl reconfigure "$NIC_B" 2>/dev/null || true
|
||||
sleep 1
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# --- main ---
|
||||
scan_nics
|
||||
pick_profile
|
||||
|
||||
STATIC_YAML=$(render_netplan)
|
||||
|
||||
echo "=== Wybrany profil: ${PROFILE_NAME} ==="
|
||||
echo " $(profile_description "$PROFILE_NAME")"
|
||||
echo " Brama domyślna: ${GW_NIC}"
|
||||
echo ""
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo "=== DRY-RUN: docelowy Netplan ($NETPLAN_FILE) ==="
|
||||
echo "$STATIC_YAML"
|
||||
echo ""
|
||||
echo "Dry-run: backup, zapis i netplan apply zostały pominięte."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "=== Backup Netplan ==="
|
||||
if [[ -f "$NETPLAN_FILE" ]]; then
|
||||
backup="${NETPLAN_FILE}.bak.$(date +%Y%m%d%H%M%S)"
|
||||
cp -a "$NETPLAN_FILE" "$backup"
|
||||
echo " Zapisano: $backup"
|
||||
else
|
||||
echo " Brak istniejącego $NETPLAN_FILE — backup pominięty."
|
||||
fi
|
||||
|
||||
echo "=== Zapis statycznej konfiguracji ==="
|
||||
write_netplan_file "$STATIC_YAML"
|
||||
echo " Zapisano: $NETPLAN_FILE"
|
||||
|
||||
echo "=== netplan generate ==="
|
||||
if ! netplan generate 2>&1; then
|
||||
echo ""
|
||||
echo "BŁĄD: netplan generate nie powiódł się. Przywróć backup lub uruchom restore-dhcp-network.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== netplan apply ==="
|
||||
netplan apply
|
||||
|
||||
wait_for_ips || true
|
||||
verify_config || exit 1
|
||||
|
||||
echo ""
|
||||
echo "=== GOTOWE ==="
|
||||
echo " Profil: ${PROFILE_NAME} — $(profile_description "$PROFILE_NAME")"
|
||||
echo " Brama: ${GW_NIC} -> ${GATEWAY}"
|
||||
[[ -n "$ENO1_IPS" ]] && echo " eno1: ${ENO1_IPS} -> 192.168.100.{${ENO1_IPS// /,}}"
|
||||
[[ -n "$ENP3S0_IPS" ]] && echo " enp3s0: ${ENP3S0_IPS} -> 192.168.100.{${ENP3S0_IPS// /,}}"
|
||||
echo ""
|
||||
echo "SSH: sprawdź ip -br addr (adresy .80 / .90 na aktywnych kartach)"
|
||||
echo "Rollback: sudo $(dirname "$0")/restore-dhcp-network.sh"
|
||||
Executable
+189
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env bash
|
||||
# Przywrócenie automatycznego IP (DHCP) — GMKtec K11 (gmktec-k11)
|
||||
#
|
||||
# Kolejność:
|
||||
# 1. Przywróć najnowszy *poprawny* backup /etc/netplan/00-installer-config.yaml.bak.*
|
||||
# 2. Jeśli brak poprawnego backupu — szablon DHCP na eno1 i enp3s0
|
||||
#
|
||||
# Wymaga: sudo
|
||||
set -euo pipefail
|
||||
|
||||
NETPLAN_FILE="/etc/netplan/00-installer-config.yaml"
|
||||
NIC_PRIMARY="eno1"
|
||||
NIC_LAN="enp3s0"
|
||||
|
||||
DRY_RUN=false
|
||||
FORCE_DHCP=false
|
||||
BACKUP_FILE=""
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Użycie: sudo ./restore-dhcp-network.sh [opcje]
|
||||
|
||||
Opcje:
|
||||
--dry-run Pokaż plan bez zapisu ani netplan apply
|
||||
--force-dhcp Pomiń backupy — od razu szablon DHCP
|
||||
--backup <ścieżka> Przywróć wskazany plik backupu (musi przejść netplan generate)
|
||||
-h, --help Ta pomoc
|
||||
|
||||
Po rollbacku sprawdź: ip -br addr
|
||||
Sesja SSH może być pod starym adresem DHCP (np. 192.168.100.2).
|
||||
|
||||
Ponowna konfiguracja statyczna (skan + menu):
|
||||
sudo ./configure-static-dual-nic.sh
|
||||
EOF
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--force-dhcp) FORCE_DHCP=true; shift ;;
|
||||
--backup)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "BŁĄD: --backup wymaga ścieżki." >&2
|
||||
exit 1
|
||||
fi
|
||||
BACKUP_FILE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "Nieznana opcja: $1" >&2; usage >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
||||
echo "BŁĄD: Uruchom skrypt jako root (sudo)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v netplan >/dev/null 2>&1; then
|
||||
echo "BŁĄD: netplan nie jest zainstalowany." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DHCP_YAML=$(cat <<EOF
|
||||
network:
|
||||
version: 2
|
||||
ethernets:
|
||||
${NIC_PRIMARY}:
|
||||
dhcp4: true
|
||||
${NIC_LAN}:
|
||||
dhcp4: true
|
||||
EOF
|
||||
)
|
||||
|
||||
write_netplan_file() {
|
||||
local content="$1"
|
||||
local tmp
|
||||
tmp=$(mktemp) || { echo "BŁĄD: mktemp nie powiódł się." >&2; return 1; }
|
||||
chmod 600 "$tmp"
|
||||
printf '%s\n' "$content" > "$tmp"
|
||||
mv -f "$tmp" "$NETPLAN_FILE"
|
||||
chmod 600 "$NETPLAN_FILE"
|
||||
}
|
||||
|
||||
netplan_file_valid() {
|
||||
local file="$1"
|
||||
local tmpdir
|
||||
[[ -f "$file" ]] || return 1
|
||||
tmpdir=$(mktemp -d) || return 1
|
||||
mkdir -p "$tmpdir/etc/netplan"
|
||||
cp "$file" "$tmpdir/etc/netplan/00-installer-config.yaml"
|
||||
if netplan generate --root-dir "$tmpdir" &>/dev/null; then
|
||||
rm -rf "$tmpdir"
|
||||
return 0
|
||||
fi
|
||||
rm -rf "$tmpdir"
|
||||
return 1
|
||||
}
|
||||
|
||||
find_valid_backup() {
|
||||
local f
|
||||
if [[ -n "$BACKUP_FILE" ]]; then
|
||||
if netplan_file_valid "$BACKUP_FILE"; then
|
||||
echo "$BACKUP_FILE"
|
||||
return 0
|
||||
fi
|
||||
echo "BŁĄD: Backup nie przechodzi netplan generate: $BACKUP_FILE" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Najpierw najnowsze poprawne; pomijaj zepsute backupy ze skryptu statycznego
|
||||
while IFS= read -r f; do
|
||||
[[ -z "$f" ]] && continue
|
||||
if netplan_file_valid "$f"; then
|
||||
echo "$f"
|
||||
return 0
|
||||
fi
|
||||
echo " Pomijam niepoprawny backup: $f" >&2
|
||||
done < <(ls -1t "${NETPLAN_FILE}.bak."* 2>/dev/null || true)
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "=== Przywracanie DHCP ==="
|
||||
|
||||
source_file=""
|
||||
action="dhcp-fallback"
|
||||
|
||||
if [[ "$FORCE_DHCP" != true ]]; then
|
||||
if backup_path=$(find_valid_backup); then
|
||||
echo " Źródło: backup $backup_path"
|
||||
source_file="$backup_path"
|
||||
action="restore-backup"
|
||||
else
|
||||
echo " Brak poprawnego backupu — używam szablonu DHCP."
|
||||
fi
|
||||
else
|
||||
echo " --force-dhcp: szablon DHCP (bez backupów)."
|
||||
fi
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo "=== DRY-RUN ==="
|
||||
if [[ "$action" == "restore-backup" ]]; then
|
||||
echo "Przywrócono by został plik z: $source_file"
|
||||
echo "--- zawartość backupu ---"
|
||||
cat "$source_file"
|
||||
else
|
||||
echo "Zapisano by został $NETPLAN_FILE:"
|
||||
echo "$DHCP_YAML"
|
||||
fi
|
||||
echo ""
|
||||
echo "Dry-run: netplan apply pominięty."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$action" == "restore-backup" ]]; then
|
||||
cp -a "$source_file" "$NETPLAN_FILE"
|
||||
echo " Przywrócono: $NETPLAN_FILE <- $source_file"
|
||||
else
|
||||
write_netplan_file "$DHCP_YAML"
|
||||
echo " Zapisano szablon DHCP: $NETPLAN_FILE"
|
||||
fi
|
||||
|
||||
echo "=== netplan generate ==="
|
||||
if ! netplan generate 2>&1; then
|
||||
echo ""
|
||||
echo "BŁĄD: netplan generate nie powiódł się."
|
||||
if [[ "$action" == "restore-backup" ]]; then
|
||||
echo "Próbuję szablon DHCP..."
|
||||
write_netplan_file "$DHCP_YAML"
|
||||
netplan generate
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "=== netplan apply ==="
|
||||
netplan apply
|
||||
|
||||
sleep 2
|
||||
|
||||
echo "=== Weryfikacja ==="
|
||||
ip -br addr show "$NIC_PRIMARY" "$NIC_LAN" 2>/dev/null || ip -br addr
|
||||
|
||||
echo ""
|
||||
echo "=== GOTOWE (DHCP) ==="
|
||||
echo "Sprawdź aktualne adresy: ip -br addr"
|
||||
echo "Połącz się ponownie SSH pod adresem DHCP (np. ip addr show enp3s0)."
|
||||
echo "Aby ponownie ustawić statyczne IP: sudo $(dirname "$0")/configure-static-dual-nic.sh"
|
||||
Executable
+106
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env bash
|
||||
# Setup 1TB data disk on GMKtec K11
|
||||
# nvme0n1 = 1TB data | nvme1n1 = 128GB system
|
||||
set -euo pipefail
|
||||
|
||||
DATA_DISK=/dev/nvme0n1
|
||||
DATA_PART=/dev/nvme0n1p1
|
||||
MOUNT_POINT=/data
|
||||
|
||||
echo "=== Sprawdzam dyski ==="
|
||||
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,MODEL
|
||||
|
||||
# Safety: refuse if DATA_DISK has mountpoints (system disk)
|
||||
if lsblk -n -o MOUNTPOINT "$DATA_DISK" | grep -q '/'; then
|
||||
echo "BŁĄD: $DATA_DISK ma partycje zamontowane — przerwanie!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create partition if missing
|
||||
if ! lsblk -n "$DATA_PART" &>/dev/null; then
|
||||
echo "=== Partycjonowanie $DATA_DISK ==="
|
||||
parted -s "$DATA_DISK" mklabel gpt
|
||||
parted -s "$DATA_DISK" mkpart primary ext4 0% 100%
|
||||
partprobe "$DATA_DISK"
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
# Format if no filesystem
|
||||
if ! blkid -o value -s TYPE "$DATA_PART" 2>/dev/null | grep -q ext4; then
|
||||
echo "=== Formatowanie $DATA_PART (ext4) ==="
|
||||
mkfs.ext4 -F -L data1tb "$DATA_PART"
|
||||
fi
|
||||
|
||||
UUID=$(blkid -o value -s UUID "$DATA_PART")
|
||||
echo "UUID=$UUID"
|
||||
|
||||
# Mount point
|
||||
mkdir -p "$MOUNT_POINT"
|
||||
if ! mountpoint -q "$MOUNT_POINT"; then
|
||||
echo "=== Montowanie $DATA_PART -> $MOUNT_POINT ==="
|
||||
mount "$DATA_PART" "$MOUNT_POINT"
|
||||
fi
|
||||
|
||||
# fstab
|
||||
FSTAB_LINE="UUID=${UUID} ${MOUNT_POINT} ext4 defaults,noatime 0 2"
|
||||
if ! grep -q "$MOUNT_POINT" /etc/fstab; then
|
||||
echo "=== Dodaję wpis do /etc/fstab ==="
|
||||
cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d%H%M%S)
|
||||
echo "$FSTAB_LINE" >> /etc/fstab
|
||||
else
|
||||
echo "=== fstab już zawiera $MOUNT_POINT ==="
|
||||
fi
|
||||
|
||||
mount -a
|
||||
df -h "$MOUNT_POINT"
|
||||
|
||||
# Directory structure
|
||||
echo "=== Tworzę strukturę katalogów ==="
|
||||
mkdir -p "$MOUNT_POINT/docker"
|
||||
mkdir -p "$MOUNT_POINT/apps/vllm/huggingface"
|
||||
mkdir -p "$MOUNT_POINT/apps/gguf/"{qwen3.6-27b,gemma-4-12b}
|
||||
mkdir -p "$MOUNT_POINT/apps/localai/"{models,backends,configuration,images,data}
|
||||
mkdir -p "$MOUNT_POINT/apps/comfyui/storage"
|
||||
mkdir -p "$MOUNT_POINT/apps/comfyui/cache/"{hf-hub,torch-hub}
|
||||
mkdir -p "$MOUNT_POINT/apps/comfyui/"{models,input,output,custom_nodes,workflows}
|
||||
chown -R tomasz-syn-grzegorza:tomasz-syn-grzegorza "$MOUNT_POINT/apps"
|
||||
|
||||
# Docker data-root migration
|
||||
echo "=== Migracja Docker data-root ==="
|
||||
systemctl stop docker docker.socket 2>/dev/null || true
|
||||
|
||||
if [ -d /var/lib/docker ] && [ "$(ls -A /var/lib/docker 2>/dev/null)" ]; then
|
||||
echo "Kopiuję /var/lib/docker -> $MOUNT_POINT/docker ..."
|
||||
rsync -aHAX /var/lib/docker/ "$MOUNT_POINT/docker/"
|
||||
fi
|
||||
|
||||
mkdir -p "$MOUNT_POINT/docker"
|
||||
|
||||
python3 <<'PYEOF'
|
||||
import json
|
||||
from pathlib import Path
|
||||
p = Path("/etc/docker/daemon.json")
|
||||
cfg = json.loads(p.read_text()) if p.exists() else {}
|
||||
cfg["data-root"] = "/data/docker"
|
||||
p.write_text(json.dumps(cfg, indent=2) + "\n")
|
||||
print(p.read_text())
|
||||
PYEOF
|
||||
|
||||
systemctl start docker
|
||||
sleep 2
|
||||
|
||||
echo "=== Weryfikacja ==="
|
||||
docker info | grep "Docker Root Dir"
|
||||
df -h / "$MOUNT_POINT"
|
||||
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,MODEL
|
||||
|
||||
echo "=== Test Docker ==="
|
||||
docker run --rm hello-world
|
||||
docker run --rm --gpus all nvidia/cuda:12.6.0-base-ubuntu24.04 nvidia-smi
|
||||
|
||||
echo ""
|
||||
echo "=== GOTOWE ==="
|
||||
echo "Dysk danych: $MOUNT_POINT ($UUID)"
|
||||
echo "Docker Root: /data/docker"
|
||||
echo "Modele vLLM: /data/apps/vllm/huggingface"
|
||||
echo "LocalAI: /data/apps/localai/models"
|
||||
Reference in New Issue
Block a user