feat: Debian prep hardening, verify script, and quality pass
- 00-system-prep.sh: bootstrap sudo when run as root; on Debian enable contrib/non-free-firmware (SKIP_NONFREE to opt out) + install needrestart - scripts/verify-debian.sh: non-destructive post-install sanity checker (exit 0/1) covering OS, tools, Debian renames, upstream tooling, .NET/Podman/Postgres, groups, flatpak, dotfile symlinks - 01-package-install.sh: auto-detect current Kubernetes minor from upstream (fallback v1.36, override K8S_MINOR) instead of stale v1.32 pin - fix shellcheck findings (SC2155, SC2207, SC2088); all scripts clean at warning severity - docs: fold decisions/status into plan; README lists new tools
This commit is contained in:
@@ -51,11 +51,12 @@ Distro-agnostic .NET development environment:
|
|||||||
|
|
||||||
The setup is broken down into focused scripts:
|
The setup is broken down into focused scripts:
|
||||||
|
|
||||||
- `00-system-prep.sh` - System updates and Flathub setup
|
- `00-system-prep.sh` - System updates, `sudo` bootstrap, Debian `contrib`/`non-free-firmware` + `needrestart`, Flathub setup
|
||||||
- `01-package-install.sh` - Core packages, upstream tooling, and Flatpak apps
|
- `01-package-install.sh` - Core packages, upstream tooling, and Flatpak apps
|
||||||
- `02-dev-tools-setup.sh` - Development tools (Neovim, Go, Rust, Oh-My-Posh, Helm, kubectx, stern, dive, trivy, AWS CLI)
|
- `02-dev-tools-setup.sh` - Development tools (Neovim, Go, Rust, Oh-My-Posh, Helm, kubectx, stern, dive, trivy, AWS CLI)
|
||||||
- `03-dotnet-setup.sh` - .NET SDK + PostgreSQL + Podman (distro-agnostic)
|
- `03-dotnet-setup.sh` - .NET SDK + PostgreSQL + Podman (distro-agnostic)
|
||||||
- `04-config-symlinks.sh` - Dotfile symlinking
|
- `04-config-symlinks.sh` - Dotfile symlinking
|
||||||
|
- `verify-debian.sh` - Post-install sanity checker (run manually, no root needed)
|
||||||
|
|
||||||
You can run individual scripts if you only need specific components.
|
You can run individual scripts if you only need specific components.
|
||||||
|
|
||||||
|
|||||||
@@ -46,87 +46,60 @@ The repo is mostly distro-agnostic already (shell rc files, aliases, nvim via Nv
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. File-by-file plan
|
## 3. File-by-file status (as of 2026-09-02)
|
||||||
|
|
||||||
### `main-setup.sh`
|
### `main-setup.sh` — DONE
|
||||||
- [ ] Keep existing `detect_linux_distro()` — already returns `debian` for trixie (`ID=debian`). Verify `sudo` present; if missing, warn to `su -`/install `sudo` first (or auto-detect root).
|
- [x] `detect_linux_distro()` returns `debian` for trixie; `PACKAGE_MANAGER=apt`.
|
||||||
- [ ] Replace the Fedora-only prompt for `03-fedora-dotnet-setup.sh` with a distro-agnostic `.NET` prompt (new `03-dotnet-setup.sh`), OR gate on both `fedora` and `debian`.
|
- [x] Preflight: if non-root and `sudo` missing → clear guidance (run as root or install `sudo`); `sudo -n` note.
|
||||||
- [ ] Consider exporting `DEBIAN_CODENAME`/`DISTRO_VERSION` (from `/etc/os-release`) for downstream repo URLs.
|
- [x] `.NET` prompt is now distro-agnostic → runs `03-dotnet-setup.sh` on every supported distro.
|
||||||
|
|
||||||
### `scripts/00-system-prep.sh`
|
### `scripts/00-system-prep.sh` — DONE
|
||||||
- [ ] `apt update && apt upgrade` path already correct. Add optional: install `sudo`, `curl`, `gnupg`, `ca-certificates`, `software-properties-common`/`apt-transport-https` prerequisites early.
|
- [x] `sudo` bootstrap when running as root on a fresh install (apt/dnf).
|
||||||
- [ ] (Optional) enable `contrib`/`non-free-firmware` components in `/etc/apt/sources.list.d/debian.sources` — needed for some firmware/tools.
|
- [x] Debian: idempotently add `contrib` + `non-free-firmware` to `debian.sources` (deb822) or legacy `sources.list` (skip with `SKIP_NONFREE=1`); `needrestart` installed on apt.
|
||||||
|
|
||||||
### `scripts/01-package-install.sh`
|
### `scripts/01-package-install.sh` — DONE
|
||||||
- [ ] Split `BASE_PACKAGE_LIST` into truly-common + distro lists; on Debian drop anything not in trixie and add Debian equivalents.
|
- [x] Split base vs distro lists; `dnsutils` → `bind9-dnsutils`; `bat` → `batcat` symlink; libvirt/QEMU stack (`libvirt-daemon-system`, `libvirt-clients`, `qemu-system-x86`, `virtinst`, `bridge-utils`); prereqs (`sudo`, `ca-certificates`, `gnupg`, `curl`).
|
||||||
- [ ] **Rename fixes (Debian branch of `DISTRO_SPECIFIC_PACKAGES`):**
|
- [x] `setup_upstream_tooling()`: vendor repos for `gh` (GitHub CLI), `terraform` (HashiCorp), `kubectl` (pkgs.k8s.io); `k9s` (GitHub tarball) + `minikube` (official `.deb`) on apt; best-effort `dnf` on Fedora.
|
||||||
- `dnsutils` → `bind9-dnsutils`
|
- [x] Kubernetes minor auto-detected from the latest k8s release (fallback `v1.36`; override with `K8S_MINOR`).
|
||||||
- add `bat` handling: after install, `ln -sf /usr/bin/batcat /usr/local/bin/bat`
|
- [x] Flatpak list unchanged (VS Code stays Flatpak per decision).
|
||||||
- add `sudo`, `ca-certificates`, `gnupg`, `curl` (ensure present)
|
|
||||||
- add `libvirt-daemon-system`, `virtinst`, `qemu-kvm`, `bridge-utils` for virt-manager
|
|
||||||
- add `zsh` post: `chsh -s /usr/bin/zsh` (or instruct)
|
|
||||||
- `python3-pip` stays, but flag PEP 668 handling (see 02)
|
|
||||||
- `docker.io` + `docker-compose` **or** wire Docker CE repo (defer to decision in §4)
|
|
||||||
- [ ] **Upstream repo tools not in Debian main** — install in this script or a new `05-` script:
|
|
||||||
- `gh` → GitHub CLI apt repo (`https://cli.github.com/packages`)
|
|
||||||
- `terraform` → HashiCorp apt repo
|
|
||||||
- `kubectl` → Kubernetes apt repo (`pkgs.k8s.io`)
|
|
||||||
- `k9s`, `minikube` → GitHub `.deb` releases (minikube official `.deb` exists)
|
|
||||||
- [ ] Flatpak list unchanged (distro-agnostic). Note VS Code Flatpak vs MS repo decision in §4.
|
|
||||||
|
|
||||||
### `scripts/02-dev-tools-setup.sh`
|
### `scripts/02-dev-tools-setup.sh` — DONE
|
||||||
- [ ] **pynvim PEP 668 fix:** replace `pip install --user pynvim` with `python3 -m pip install --user --break-system-packages pynvim`, or (cleaner) install into NvChad's venv, or note `pipx`.
|
- [x] `pynvim` PEP 668 fix: try `pip install --user`, fall back to `--break-system-packages`.
|
||||||
- [ ] Rest is GitHub-download based → distro-agnostic; verify `unzip`, `tar`, `wget` present.
|
|
||||||
- [ ] `dive` already handles `.deb` via `dpkg -i` on apt — good.
|
|
||||||
- [ ] Go/Rust/Nerd Font/Oh-My-Posh/Helm/kubectx/stern/trivy/AWS — no changes needed.
|
|
||||||
|
|
||||||
### `scripts/03-fedora-dotnet-setup.sh` → split/generalize
|
### `scripts/03-fedora-dotnet-setup.sh` → `03-dotnet-setup.sh` — DONE
|
||||||
- [ ] Rename to **`03-dotnet-setup.sh`** and branch by `$PACKAGE_MANAGER`:
|
- [x] Renamed to `03-dotnet-setup.sh`, distro-agnostic (apt/dnf).
|
||||||
- **Fedora:** keep existing RPM/MS-repo path.
|
- [x] `.NET SDK` via official `dotnet-install.sh` (channel `STS`, override `DOTNET_CHANNEL`) → `~/.dotnet`, PATH added to `bashrc`/`zshrc`.
|
||||||
- **Debian:** add MS Debian repo `https://packages.microsoft.com/config/debian/13/packages-microsoft-prod.deb` (verify trixie support; fall back to `dotnet-install.sh` if repo is unavailable for trixie) then `apt install dotnet-sdk-10.0` (or 8/9 fallback loop like Fedora).
|
- [x] PostgreSQL: auto-cluster on Debian; `--initdb` only on Fedora.
|
||||||
- Alternatively use official **`dotnet-install.sh`** for both — fully distro-agnostic, no repo dependency.
|
- [x] Containers = **Podman** + `podman-compose` + `podman-docker` (Docker-CLI shim). No MS repo, no moby/docker-ce.
|
||||||
- [ ] Replace Fedora-specific db/container section with Debian equivalents:
|
|
||||||
- PostgreSQL: `apt install postgresql` (cluster auto-init — remove `postgresql-setup --initdb` step for Debian; just `systemctl enable --now postgresql`).
|
|
||||||
- Docker: `docker.io` + `docker-compose` + add user to `docker` group, or Docker CE repo.
|
|
||||||
- [ ] Update `main-setup.sh` gate accordingly.
|
|
||||||
|
|
||||||
### `scripts/04-config-symlinks.sh`
|
### `scripts/04-config-symlinks.sh` — no changes required
|
||||||
- [ ] No functional changes needed (pure symlinking). Optionally handle `~/.bash_aliases` (Debian's default bashrc sources it) or leave as-is since `bashrc` sources `aliases.bash` directly.
|
- [x] Pure symlinking; distro-agnostic as-is.
|
||||||
|
|
||||||
### Shell rc files (`bashrc`, `zshrc`, aliases)
|
### Shell rc files (`bashrc`, `zshrc`, aliases) — DONE
|
||||||
- [ ] Already distro-agnostic (PATH for `/usr/local/go`, `~/.local/bin`, cargo, nvm). No Fedora-specific bits.
|
- [x] `zshrc` oh-my-zsh remnants purged (plain zsh + Oh-My-Posh).
|
||||||
- [ ] Note: `zshrc` still references **oh-my-zsh** (`$ZSH/oh-my-zsh.sh`, `plugins=(git)`) but no script installs it anymore (repo moved to Oh-My-Posh). On a fresh Debian this will fail silently. Decide: purge oh-my-zsh remnants or restore its install step. Recommend purging on this branch.
|
- [x] Duplicate Go `PATH` lines (appended by an old 02 run) removed from `bashrc`/`zshrc`.
|
||||||
- [ ] Ensure `~/.fzf.zsh` / `~/.fzf.bash` generation (`fzf --zsh`/`--bash`) or skip gracefully (already guarded).
|
- [x] `nvim/nvim` + `nushell/nushell` self-symlink targets updated to `/home/blake`.
|
||||||
|
|
||||||
### `README.md`
|
### `README.md` — DONE
|
||||||
- [ ] Update "Supported Distributions" / feature matrix to reflect **Debian 13 = first-class**, Fedora optional.
|
- [x] Debian 13 first-class; feature lists, modular architecture, post-install steps, and supported-distro matrix updated (Podman, Flatpak VS Code, libvirt/kvm groups, rootless podman socket).
|
||||||
- [ ] Rename "Fedora-Specific (.NET)" section → ".NET Development" with per-distro notes.
|
|
||||||
- [ ] Update post-install steps (group names `docker`, `libvirt`; remove Fedora-only log-out note if not applicable; add PEP 668 note).
|
### Tooling / quality — DONE (this pass)
|
||||||
- [ ] Update file listing for `03-*.sh` renames.
|
- [x] **`scripts/verify-debian.sh`** added — non-destructive end-to-end sanity checker (OS, binaries, Debian renames, upstream tools, dev tools, .NET/Podman/Postgres, groups, flatpak, dotfile symlinks); exit code 0/1.
|
||||||
|
- [x] **ShellCheck** (v0.11.0) run on all scripts — clean at warning severity (remaining notes are pre-existing info/style only).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Open decisions (need your input)
|
## 4. Decisions (confirmed)
|
||||||
|
1. **Container runtime:** Podman (`podman-docker` provides the `docker` shim so existing aliases keep working).
|
||||||
|
2. **VS Code:** Flatpak `com.visualstudio.code` (no MS editor repo).
|
||||||
|
3. **.NET:** official `dotnet-install.sh` (no MS vendor repo).
|
||||||
|
4. **oh-my-zsh:** purged from `zshrc`.
|
||||||
|
5. **Scope:** full rework (applied).
|
||||||
|
|
||||||
1. **Container runtime on Debian:** `docker.io` (Debian pkg) vs official **Docker CE** repo vs **Podman** (since Fedora used Podman Desktop + `moby-engine`)? This repo mixes docker aliases and Podman Desktop flatpak.
|
## 5. Remaining work / next steps
|
||||||
2. **VS Code source:** keep **Flatpak** `com.visualstudio.code` (already in list) or switch to MS apt repo `.deb` like Fedora's RPM setup did?
|
- [ ] **Test end-to-end on a real Debian 13 box**: run `./main-setup.sh`, then `bash scripts/verify-debian.sh`, and fix anything the checker flags.
|
||||||
3. **.NET SDK version to target:** repo tries 8.0 → 9.0 on Fedora; pick a default for Debian (e.g. SDK 10 on trixie) or keep the fallback loop.
|
- [ ] Decide whether to keep Fedora/dnf support long-term or trim it later (kept for now).
|
||||||
4. **oh-my-zsh remnants in `zshrc`:** purge (recommended) or keep?
|
- [ ] Merge `debian-13` → `master` after validation.
|
||||||
5. **Scope of this branch:** full rework of all scripts, or a lighter pass (fix names + PEP 668 + .NET script) to validate on a live trixie box first?
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Suggested execution order
|
|
||||||
|
|
||||||
1. Do the cheap, high-confidence fixes:
|
|
||||||
- `main-setup.sh` gating + `.NET` prompt
|
|
||||||
- `01-package-install.sh` Debian package renames (`bind9-dnsutils`, `bat` symlink, prerequisites, virt stack)
|
|
||||||
- `02-dev-tools-setup.sh` PEP 668 pynvim fix
|
|
||||||
2. Rename/generalize `03-fedora-dotnet-setup.sh` → `03-dotnet-setup.sh`.
|
|
||||||
3. Add upstream repo/bootstrap logic for `gh`, `terraform`, `kubectl`, `minikube`, `k9s`.
|
|
||||||
4. Purge oh-my-zsh remnants from `zshrc`.
|
|
||||||
5. Update `README.md`.
|
|
||||||
6. Test end-to-end on a Debian 13 VM (or real install) before merging to `master`.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ prompt_yes_no() {
|
|||||||
# Function to run a script if approved
|
# Function to run a script if approved
|
||||||
run_script() {
|
run_script() {
|
||||||
local script_path="$1"
|
local script_path="$1"
|
||||||
local script_name="$(basename "$script_path")"
|
local script_name
|
||||||
|
script_name="$(basename "$script_path")"
|
||||||
|
|
||||||
if ! bash "$script_path"; then
|
if ! bash "$script_path"; then
|
||||||
echo "ERROR: $script_name failed."
|
echo "ERROR: $script_name failed."
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# 00-system-prep.sh
|
# 00-system-prep.sh
|
||||||
# Updates system and sets up Flathub.
|
# Updates system, bootstraps sudo, enables Debian extra components,
|
||||||
|
# and sets up Flathub.
|
||||||
# Relies on DISTRO and PACKAGE_MANAGER being set by the caller.
|
# Relies on DISTRO and PACKAGE_MANAGER being set by the caller.
|
||||||
|
|
||||||
echo "--- Starting System Preparation ---"
|
echo "--- Starting System Preparation ---"
|
||||||
@@ -11,6 +12,27 @@ if [ -z "$DISTRO" ] || [ -z "$PACKAGE_MANAGER" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Ensure 'sudo' exists so all later scripts can use it.
|
||||||
|
# - Running as root on a fresh Debian: installing sudo lets root invoke
|
||||||
|
# `sudo ...` directly (root is not subject to sudoers).
|
||||||
|
# - Non-root users without sudo are handled by main-setup.sh's preflight.
|
||||||
|
if ! command -v sudo &>/dev/null; then
|
||||||
|
echo "sudo not found. Bootstrapping it..."
|
||||||
|
if [ "$(id -u)" -eq 0 ]; then
|
||||||
|
if [ "$PACKAGE_MANAGER" == "apt" ]; then
|
||||||
|
apt-get update && apt-get install -y sudo
|
||||||
|
elif [ "$PACKAGE_MANAGER" == "dnf" ]; then
|
||||||
|
dnf install -y sudo
|
||||||
|
fi
|
||||||
|
echo "sudo installed. Add your normal user to the sudo group if desired:"
|
||||||
|
echo " usermod -aG sudo <your-user> (then log out/in)"
|
||||||
|
else
|
||||||
|
echo "ERROR: 'sudo' is required but missing, and you are not root."
|
||||||
|
echo "As root, run: apt install -y sudo && usermod -aG sudo \$USER"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Update system before installing packages
|
# Update system before installing packages
|
||||||
echo "Updating system packages..."
|
echo "Updating system packages..."
|
||||||
if [ "$PACKAGE_MANAGER" == "dnf" ]; then
|
if [ "$PACKAGE_MANAGER" == "dnf" ]; then
|
||||||
@@ -21,6 +43,66 @@ else
|
|||||||
echo "WARNING: Unknown package manager '$PACKAGE_MANAGER'. Skipping system update."
|
echo "WARNING: Unknown package manager '$PACKAGE_MANAGER'. Skipping system update."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Debian extras (only on Debian; idempotent)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
if [ "$DISTRO" == "debian" ]; then
|
||||||
|
|
||||||
|
# Enable contrib + non-free-firmware components on the main archive.
|
||||||
|
# Needed for some WiFi/GPU firmware and non-free tooling. Skip with SKIP_NONFREE=1.
|
||||||
|
if [ -z "$SKIP_NONFREE" ]; then
|
||||||
|
echo "Enabling 'contrib' and 'non-free-firmware' apt components..."
|
||||||
|
_enable_debian_components() {
|
||||||
|
local f="/etc/apt/sources.list.d/debian.sources"
|
||||||
|
local tmp
|
||||||
|
# deb822 format used by Debian 12+ (trixie ships debian.sources)
|
||||||
|
if [ -f "$f" ]; then
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
if awk '
|
||||||
|
/^URIs:[[:space:]]/ { in_archive = ($0 ~ /deb\.debian\.org\/debian/) }
|
||||||
|
in_archive && /^Components:/ && $0 !~ /contrib/ {
|
||||||
|
print $0 " contrib non-free-firmware"
|
||||||
|
in_archive = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
' "$f" > "$tmp"; then
|
||||||
|
if ! diff -q "$f" "$tmp" >/dev/null; then
|
||||||
|
sudo cp "$f" "${f}.bak"
|
||||||
|
sudo mv "$tmp" "$f"
|
||||||
|
echo " -> updated ${f}"
|
||||||
|
else
|
||||||
|
rm -f "$tmp"
|
||||||
|
echo " -> components already present in ${f}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
rm -f "$tmp"
|
||||||
|
echo "WARNING: could not parse ${f}; skipping component changes."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# Legacy single-line /etc/apt/sources.list fallback
|
||||||
|
if [ -f /etc/apt/sources.list ] \
|
||||||
|
&& grep -qE '^deb[[:space:]]+https?://deb\.debian\.org/debian' /etc/apt/sources.list \
|
||||||
|
&& ! grep -qE '^deb[[:space:]]+https?://deb\.debian\.org/debian[^#]*non-free-firmware' /etc/apt/sources.list; then
|
||||||
|
sudo sed -i -E 's/^(deb[[:space:]]+https?:\/\/deb\.debian\.org\/debian[^#]*main)([[:space:]]|$)/\1 contrib non-free-firmware/' /etc/apt/sources.list
|
||||||
|
echo " -> updated /etc/apt/sources.list"
|
||||||
|
fi
|
||||||
|
sudo apt update
|
||||||
|
}
|
||||||
|
_enable_debian_components
|
||||||
|
else
|
||||||
|
echo "SKIP_NONFREE is set - leaving apt components unchanged."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# needrestart prompts (or auto-restarts) services after library upgrades.
|
||||||
|
if ! dpkg-query -W -f='${Status}' needrestart 2>/dev/null | grep -q "ok installed"; then
|
||||||
|
echo "Installing needrestart..."
|
||||||
|
sudo apt install -y needrestart
|
||||||
|
else
|
||||||
|
echo "needrestart already installed."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Setup Flatpak
|
# Setup Flatpak
|
||||||
echo "Setting up Flathub repository..."
|
echo "Setting up Flathub repository..."
|
||||||
if command -v flatpak &> /dev/null; then
|
if command -v flatpak &> /dev/null; then
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ fi
|
|||||||
|
|
||||||
# Combine package lists
|
# Combine package lists
|
||||||
PACKAGE_LIST=("${BASE_PACKAGE_LIST[@]}" "${DISTRO_SPECIFIC_PACKAGES[@]}")
|
PACKAGE_LIST=("${BASE_PACKAGE_LIST[@]}" "${DISTRO_SPECIFIC_PACKAGES[@]}")
|
||||||
PACKAGE_LIST=($(printf "%s\n" "${PACKAGE_LIST[@]}" | LC_ALL=C sort -u))
|
mapfile -t PACKAGE_LIST < <(printf "%s\n" "${PACKAGE_LIST[@]}" | LC_ALL=C sort -u)
|
||||||
|
|
||||||
# --- apt helpers ---------------------------------------------------------
|
# --- apt helpers ---------------------------------------------------------
|
||||||
_apt_is_installed() {
|
_apt_is_installed() {
|
||||||
@@ -210,10 +210,21 @@ _apt_add_hashicorp_repo() {
|
|||||||
| sudo tee /etc/apt/sources.list.d/hashicorp.list >/dev/null
|
| sudo tee /etc/apt/sources.list.d/hashicorp.list >/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
# Kubernetes apt repo. Bump K8S_MINOR to track the current stable minor.
|
# Kubernetes apt repo. Auto-detects the latest stable minor from the
|
||||||
K8S_MINOR="v1.32"
|
# kubernetes/kubernetes GitHub release feed, falling back to a pinned minor
|
||||||
|
# if the API is unreachable. Override explicitly with K8S_MINOR=...
|
||||||
|
K8S_MINOR_FALLBACK="v1.36"
|
||||||
|
_k8s_latest_minor() {
|
||||||
|
local tag minor
|
||||||
|
tag="$(curl -fsSL --max-time 10 https://api.github.com/repos/kubernetes/kubernetes/releases/latest \
|
||||||
|
| grep '"tag_name"' | cut -d'"' -f4)" || return 1
|
||||||
|
minor="${tag#v}" # e.g. 1.36.0
|
||||||
|
minor="${minor%.*}" # strip patch -> 1.36
|
||||||
|
echo "v${minor}"
|
||||||
|
}
|
||||||
_apt_add_kubernetes_repo() {
|
_apt_add_kubernetes_repo() {
|
||||||
[ -f /etc/apt/sources.list.d/kubernetes.list ] && { echo "Kubernetes repo already configured."; return 0; }
|
[ -f /etc/apt/sources.list.d/kubernetes.list ] && { echo "Kubernetes repo already configured."; return 0; }
|
||||||
|
K8S_MINOR="${K8S_MINOR:-$(_k8s_latest_minor || echo "$K8S_MINOR_FALLBACK")}"
|
||||||
echo "Adding Kubernetes apt repository (${K8S_MINOR})..."
|
echo "Adding Kubernetes apt repository (${K8S_MINOR})..."
|
||||||
curl -fsSL "https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/deb/Release.key" \
|
curl -fsSL "https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/deb/Release.key" \
|
||||||
| sudo gpg --dearmor -o /usr/share/keyrings/kubernetes-archive-keyring.gpg
|
| sudo gpg --dearmor -o /usr/share/keyrings/kubernetes-archive-keyring.gpg
|
||||||
|
|||||||
176
scripts/verify-debian.sh
Executable file
176
scripts/verify-debian.sh
Executable file
@@ -0,0 +1,176 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# verify-debian.sh
|
||||||
|
# Non-destructive sanity checks for a freshly set-up Debian 13 machine.
|
||||||
|
# Verifies the pieces that 00-03 + 04-config-symlinks.sh are expected to leave behind.
|
||||||
|
# Exit code: 0 = all critical checks passed; 1 = at least one critical check failed.
|
||||||
|
#
|
||||||
|
# Usage: bash scripts/verify-debian.sh (no root needed)
|
||||||
|
|
||||||
|
# --- output helpers -------------------------------------------------------
|
||||||
|
if [ -t 1 ]; then
|
||||||
|
C_GREEN=$'\e[32m'; C_RED=$'\e[31m'; C_YELLOW=$'\e[33m'; C_BOLD=$'\e[1m'; C_OFF=$'\e[0m'
|
||||||
|
else
|
||||||
|
C_GREEN=""; C_RED=""; C_YELLOW=""; C_BOLD=""; C_OFF=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
PASS=0
|
||||||
|
WARN=0
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
ok() { PASS=$((PASS+1)); echo "${C_GREEN}✔${C_OFF} $1"; }
|
||||||
|
warn() { WARN=$((WARN+1)); echo "${C_YELLOW}⚠${C_OFF} $1"; }
|
||||||
|
bad() { FAIL=$((FAIL+1)); echo "${C_RED}✘${C_OFF} $1"; }
|
||||||
|
|
||||||
|
# --- helpers --------------------------------------------------------------
|
||||||
|
check_cmd() { # check_cmd "label" "command-name"
|
||||||
|
if command -v "$2" &>/dev/null; then ok "$1: found ($(command -v "$2"))"; else bad "$1: NOT FOUND"; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_symlink_target() { # check_symlink_target "label" "link-path" "expected-target"
|
||||||
|
if [ -L "$2" ]; then
|
||||||
|
local target; target="$(readlink -f "$2")"
|
||||||
|
if [ "$target" = "$3" ] || [ "$(basename "$target")" = "$(basename "$3")" ]; then
|
||||||
|
ok "$1: $2 -> $target"
|
||||||
|
else
|
||||||
|
warn "$1: $2 points to $target (expected $3)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "$1: $2 is not a symlink"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_service() { # check_service "label" "unit"
|
||||||
|
if systemctl is-active --quiet "$2" 2>/dev/null; then ok "$1: active"; else warn "$1: not active"; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- 1. OS ------------------------------------------------------------------
|
||||||
|
echo "${C_BOLD}== OS ==${C_OFF}"
|
||||||
|
. /etc/os-release
|
||||||
|
echo " distro: $PRETTY_NAME (id=$ID, codename=${VERSION_CODENAME:-unknown})"
|
||||||
|
if [ "$ID" = "debian" ]; then
|
||||||
|
ok "Debian detected"
|
||||||
|
else
|
||||||
|
warn "Not Debian (id=$ID) - this script targets Debian 13"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 2. Package manager ------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== Package manager ==${C_OFF}"
|
||||||
|
if command -v apt-get &>/dev/null; then ok "apt present"; else bad "apt missing"; fi
|
||||||
|
if command -v dpkg-query &>/dev/null; then :; else bad "dpkg missing"; fi
|
||||||
|
|
||||||
|
# --- 3. Core packages ---------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== Core tools ==${C_OFF}"
|
||||||
|
for c in git curl wget jq ripgrep tmux zsh fzf zoxide eza unzip btop direnv tldr socat mtr nmap whois traceroute tcpdump iperf3 httpie ansible virt-manager flatpak python3; do
|
||||||
|
check_cmd "$c" "$c"
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- 4. Debian binary renames -------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== Debian binary renames ==${C_OFF}"
|
||||||
|
if command -v batcat &>/dev/null; then
|
||||||
|
check_symlink_target "bat -> batcat" "/usr/local/bin/bat" "/usr/bin/batcat"
|
||||||
|
elif command -v bat &>/dev/null; then
|
||||||
|
ok "bat present directly"
|
||||||
|
else
|
||||||
|
bad "bat/batcat not found"
|
||||||
|
fi
|
||||||
|
if command -v fdfind &>/dev/null; then
|
||||||
|
check_symlink_target "fd -> fdfind" "/usr/local/bin/fd" "/usr/bin/fdfind"
|
||||||
|
elif command -v fd &>/dev/null; then
|
||||||
|
ok "fd present directly"
|
||||||
|
else
|
||||||
|
bad "fd/fdfind not found"
|
||||||
|
fi
|
||||||
|
if command -v dig &>/dev/null; then ok "dig present"; else bad "dig missing (install bind9-dnsutils)"; fi
|
||||||
|
|
||||||
|
# --- 5. Upstream-only tools ----------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== Upstream tooling ==${C_OFF}"
|
||||||
|
for c in gh terraform kubectl k9s minikube; do check_cmd "$c" "$c"; done
|
||||||
|
|
||||||
|
# --- 6. Development tools -------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== Development tools ==${C_OFF}"
|
||||||
|
for c in nvim go rustc cargo oh-my-posh helm kubectx kubens stern dive trivy aws; do check_cmd "$c" "$c"; done
|
||||||
|
|
||||||
|
# Go binary path sanity
|
||||||
|
if command -v go &>/dev/null; then ok "GOPATH=$(go env GOPATH 2>/dev/null)"; fi
|
||||||
|
|
||||||
|
# pynvim (PEP 668 note: system pip is externally managed on Debian 13)
|
||||||
|
if /usr/bin/python3 -m pip show pynvim &>/dev/null; then
|
||||||
|
ok "pynvim installed for python3"
|
||||||
|
else
|
||||||
|
warn "pynvim not found for /usr/bin/python3 (install with --break-system-packages if wanted)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 7. .NET / backend -----------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== .NET / backend services ==${C_OFF}"
|
||||||
|
if command -v dotnet &>/dev/null; then
|
||||||
|
ok "dotnet: $(dotnet --version 2>/dev/null)"
|
||||||
|
else
|
||||||
|
bad "dotnet not on PATH (install via 03-dotnet-setup.sh or add ~/.dotnet to PATH)"
|
||||||
|
fi
|
||||||
|
check_cmd "podman" "podman"
|
||||||
|
if command -v docker &>/dev/null; then
|
||||||
|
ok "docker shim present ($(readlink -f "$(command -v docker)" 2>/dev/null || echo docker))"
|
||||||
|
else
|
||||||
|
warn "docker shim missing (install podman-docker)"
|
||||||
|
fi
|
||||||
|
if command -v podman-compose &>/dev/null; then ok "podman-compose present"; else warn "podman-compose missing"; fi
|
||||||
|
check_service "postgresql" "postgresql"
|
||||||
|
check_service "libvirtd" "libvirtd"
|
||||||
|
|
||||||
|
# --- 8. Groups -------------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== Group membership ==${C_OFF}"
|
||||||
|
for g in libvirt kvm; do
|
||||||
|
if id -nG 2>/dev/null | tr ' ' '\n' | grep -qx "$g"; then
|
||||||
|
ok "in group '$g'"
|
||||||
|
else
|
||||||
|
warn "not in group '$g' (needed for virt-manager/KVM; log out/in after usermod)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- 9. Flatpak --------------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== Flatpak ==${C_OFF}"
|
||||||
|
if command -v flatpak &>/dev/null && flatpak remotes 2>/dev/null | grep -q flathub; then
|
||||||
|
ok "flathub remote present"
|
||||||
|
else
|
||||||
|
warn "flathub remote not configured"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 10. Shell rc symlinks ----------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}== Dotfile symlinks ==${C_OFF}"
|
||||||
|
for d in bashrc zshrc gitconfig aliases.bash aliases.zsh; do
|
||||||
|
if [ -e "$HOME/.$d" ] || [ -L "$HOME/.$d" ]; then
|
||||||
|
# shellcheck disable=SC2088
|
||||||
|
ok "~/.$d linked"
|
||||||
|
else
|
||||||
|
# shellcheck disable=SC2088
|
||||||
|
warn "~/.$d missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
check_symlink_target "oh-my-posh theme" "$HOME/.config/oh-my-posh/theme.omp.json" "theme.omp.json"
|
||||||
|
check_symlink_target "nvim config" "$HOME/.config/nvim" "nvim"
|
||||||
|
check_symlink_target "nushell config" "$HOME/.config/nushell" "nushell"
|
||||||
|
|
||||||
|
# --- Summary ------------------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "${C_BOLD}========================================${C_OFF}"
|
||||||
|
echo "${C_GREEN}✔${C_OFF} ${PASS} passed ${C_YELLOW}⚠${C_OFF} ${WARN} warnings ${C_RED}✘${C_OFF} ${FAIL} failed"
|
||||||
|
echo "${C_BOLD}========================================${C_OFF}"
|
||||||
|
echo ""
|
||||||
|
if [ "$FAIL" -gt 0 ]; then
|
||||||
|
echo "Some critical checks failed. See ✘ items above."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "All critical checks passed. Warnings above are optional/suggested."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user