Compare commits

...
12 Commits
Author SHA1 Message Date
mk ce5041bc50 todo md 2026-07-28 07:23:10 +03:00
mk 9f164f61ef angie(debian): pin VERSION_ID in apt repo URL — needs angie/<ID>/<VERSION_ID>/ (debian/13/dists/trixie/) not angie/<ID>/ (debian/dists/trixie/ -> 404 'no Release file') on trixie; suite stays VERSION_CODENAME
packages(debian): rm stale /etc/apt/sources.list.d/eza.list + gierens.gpg left by the pre-fix run that used the now-dead apt.fury.io PPA — otherwise 'apt-get update' keeps hitting the 401 forever even though we now install eza from GH releases
2026-07-28 07:11:22 +03:00
mk 0cfe10e387 packages(debian): fix eza+starship+zoxide installs
- eza: apt.fury.io PPA is dead (401 Unauthorized); install the single binary from the upstream GitHub release tarball (eza_x86_64-unknown-linux-gnu.tar.gz) into /usr/local/bin — no apt repo, system-wide
- starship: scrub $ARCH/$PLATFORM from the installer env — our lib/detect.sh exports ARCH=amd64, which the starship installer reuses (it checks ${ARCH-}) and skips its own amd64->x86_64 mapping, producing an unsupported 'amd64-unknown-linux-musl' target. Default bin dir is /usr/local/bin anyway
- zoxide: install system-wide (--bin-dir /usr/local/bin) instead of ~/.local/bin — when run as root the default landed in /root (wrong user for the create-user path) and wasn't on $PATH
2026-07-28 07:08:04 +03:00
mk efdf056352 hardening(angie): default_server needs a cert on its 443 listener or 'angie -t' fails with 'no ssl_certificate defined' — generate a one-time self-signed dummy (CN=bootstrap-default, 10y) in /etc/angie/ssl so unknown-SNI clients handshake then get 444; mark listen 443 as ssl explicitly 2026-07-28 06:55:31 +03:00
mk 435d66aad2 shell-zsh: derive ZSH/ZDOTDIR from $TARGET_HOME unconditionally — ignore inherited $ZSH env var (omz exports it, which pinned paths to the old home e.g. /root while the chown step retargeted to the new user, causing 'insecure completion dirs' owned by the wrong user) 2026-07-28 06:16:45 +03:00
mk 94a0bac9f4 hardening(angie): resolve mime.types from whichever path the package ships (angie-bin=/etc/angie, Arch source=/etc/nginx via mailcap dep) — fixes 'angie -t' 'open() mime.types failed' on source path; fallback ships a minimal mime.types; ensure modules/ include dirs exist before glob 2026-07-28 06:04:57 +03:00
mk 26185978ac hardening(angie): source-angie bridge — symlink /etc/nginx/nginx.conf -> /etc/angie/angie.conf so the _on/targets layout actually loads under the source AUR package's '/usr/bin/nginx' service (angie-bin/Debian already read /etc/angie directly); backup original once 2026-07-28 05:59:08 +03:00
mk cb0e517a7d hardening(angie): fix 'angie_user: unbound variable' under set -u — init extraction locals to empty; also read source AUR package's /etc/nginx/nginx.conf as alt stock config path 2026-07-28 05:57:44 +03:00
mk b653191de2 angie(arch): prefer angie-bin (repackaged upstream .deb, instant) over source build; verified http_acme/ssl/v2/v3/realip all compiled in; fall back to aur/angie if bin unavailable 2026-07-28 05:53:43 +03:00
mk ca8f01083c packages(arch): route byobu through yay (AUR-only); split official vs AUR lists so pacman --needed can't abort on a missing target; as_user prefers TARGET_USER for AUR builds 2026-07-28 05:44:45 +03:00
mk ff9fc4db4e fix(sanity): hostname missing on minimal Arch (not in coreutils) — use uname -n with fallbacks; refresh TLS follow-up to angie-issue 2026-07-28 05:35:40 +03:00
mk f7e4bb96d7 fix(zsh plugins): correct clone orgs — zsh-users/zsh-history-substring-search, Aloxaf/fzf-tab (were typos causing github auth prompts) 2026-07-28 05:28:20 +03:00
7 changed files with 179 additions and 48 deletions

No files matched your search

+5 -4
View File
@@ -9,12 +9,13 @@ ok() { printf '\033[1;32mok\033[0m %s\n' "$*"; }
# run a command as root when not already root # run a command as root when not already root
sudo_() { if (( EUID == 0 )); then "$@"; else sudo "$@"; fi; } sudo_() { if (( EUID == 0 )); then "$@"; else sudo "$@"; fi; }
# run a command AS the invoking (non-root) user — used for AUR builds, etc. # run a command AS the target non-root user — used for AUR builds, nvm, etc.
# when root: drop to SUDO_USER (or USER) via runuser; when not root: run directly. # precedence (when running as root): TARGET_USER (set by create-user) > SUDO_USER > USER.
# when not root: run directly as ourselves.
as_user() { as_user() {
local u="$USER" local u="${SUDO_USER:-$USER}"
if (( EUID == 0 )); then if (( EUID == 0 )); then
u="${SUDO_USER:-$USER}" u="${TARGET_USER:-${SUDO_USER:-$USER}}"
command -v runuser >/dev/null 2>&1 && runuser -u "$u" -- "$@" || su "$u" -c "$*" command -v runuser >/dev/null 2>&1 && runuser -u "$u" -- "$@" || su "$u" -c "$*"
else else
"$@" "$@"
+62 -19
View File
@@ -20,32 +20,54 @@ run_packages() {
} }
# ── arch ───────────────────────────────────────────────────────────────────── # ── arch ─────────────────────────────────────────────────────────────────────
_pkg_arch() { # official-repo packages (verified in extra/core). Any name not in the official
sudo_ pacman -Sy --noconfirm --needed base-devel openssh # repos would abort the whole `pacman --needed` batch, so keep this list clean
# most tools live in extra/community (the merged repos); names map 1:1 # and route AUR-only tools through _install_aur_packages instead.
local p=(git byobu ufw mosh btop fzf ripgrep fd bat dust procs jq yq tree ARCH_OFFICIAL=(git ufw mosh btop fzf ripgrep fd bat dust procs jq yq tree
ncdu duf tldr httpie rsync lazygit neovim curl unzip less starship ncdu duf tldr httpie rsync lazygit neovim curl unzip less starship
eza zoxide openssh) eza zoxide openssh)
sudo_ pacman -Sy --noconfirm --needed "${p[@]}"
_install_yay
# AUR-only packages (not in official repos) — installed through yay after build.
ARCH_AUR=(byobu)
_pkg_arch() {
sudo_ pacman -Sy --noconfirm --needed base-devel openssh
sudo_ pacman -Sy --noconfirm --needed "${ARCH_OFFICIAL[@]}"
_install_yay
_install_aur_packages
# fd/bat ship with their real names on arch — no shims needed # fd/bat ship with their real names on arch — no shims needed
} }
_install_yay() { _install_yay() {
if command -v yay >/dev/null 2>&1; then ok "yay already installed"; return; fi if command -v yay >/dev/null 2>&1; then ok "yay already installed"; return; fi
log "building yay from AUR (requires a non-root sudoer)" log "building yay from AUR (requires a non-root sudoer)"
if (( EUID == 0 )) && [[ -z "${SUDO_USER:-}" ]]; then if (( EUID == 0 )) && [[ -z "${TARGET_USER:-${SUDO_USER:-}}" ]]; then
err "running as root with no SUDO_USER — yay cannot build. Re-run bootstrap as a normal user with sudo." err "running as root with no target/sudo user — yay cannot build. Run the create-user step first, or re-run bootstrap as a normal user with sudo."
return 1 return 1
fi fi
local tmp; tmp="$(mktemp -d)" local tmp; tmp="$(mktemp -d)"
# chown the build dir so the non-root build user can write into it
if (( EUID == 0 )); then
chown -R "${TARGET_USER:-${SUDO_USER}}" "$tmp"
fi
as_user git clone --depth 1 https://aur.archlinux.org/yay.git "$tmp/yay" as_user git clone --depth 1 https://aur.archlinux.org/yay.git "$tmp/yay"
( cd "$tmp/yay" && as_user makepkg -si --noconfirm ) ( cd "$tmp/yay" && as_user makepkg -si --noconfirm )
rm -rf "$tmp" rm -rf "$tmp"
command -v yay >/dev/null 2>&1 && ok "yay installed" || warn "yay install may need a manual pass" command -v yay >/dev/null 2>&1 && ok "yay installed" || warn "yay install may need a manual pass"
} }
_install_aur_packages() {
[[ "${#ARCH_AUR[@]}" -eq 0 ]] && return
if ! command -v yay >/dev/null 2>&1; then
warn "yay not available — skipping AUR packages: ${ARCH_AUR[*]}"
return
fi
log "installing AUR-only packages: ${ARCH_AUR[*]}"
# yay -S as the non-root target user (makepkg refuses root; TARGET_USER via as_user).
as_user yay -S --noconfirm --needed "${ARCH_AUR[@]}" \
|| warn "some AUR packages failed: ${ARCH_AUR[*]} (install manually with: yay -S ${ARCH_AUR[*]})"
}
# ── debian/ubuntu ──────────────────────────────────────────────────────────── # ── debian/ubuntu ────────────────────────────────────────────────────────────
_pkg_debian() { _pkg_debian() {
sudo_ apt-get update -y sudo_ apt-get update -y
@@ -56,24 +78,45 @@ _pkg_debian() {
# rename packages: fd -> fdfind, bat -> batcat (fix via aliases in zsh) # rename packages: fd -> fdfind, bat -> batcat (fix via aliases in zsh)
sudo_ apt-get install -y fdfind batcat 2>/dev/null || true sudo_ apt-get install -y fdfind batcat 2>/dev/null || true
# eza via the gierens PPA (debs not in base apt) # eza: the old apt.fury.io/gierens PPA is dead (401 Unauthorized). Install the
# single binary from the upstream GitHub release tarball into /usr/local/bin
# (system-wide — works for root and every sudo user; no HOME dependency).
# Remove a stale eza.list left by the old (pre-fix) run that used the now-dead
# apt.fury.io PPA — otherwise 'apt-get update' keeps hitting the 401 forever.
sudo_ rm -f /etc/apt/sources.list.d/eza.list /etc/apt/keyrings/gierens.gpg
if ! command -v eza >/dev/null 2>&1; then if ! command -v eza >/dev/null 2>&1; then
sudo_ install -m 0755 -d /etc/apt/keyrings local eza_arch; case "$ARCH" in
curl -fsSL https://raw.githubusercontent.com/eza-community/eza/main/deb.asc \ amd64) eza_arch=x86_64-unknown-linux-gnu ;;
| sudo_ tee /etc/apt/keyrings/gierens.gpg >/dev/null arm64) eza_arch=aarch64-unknown-linux-gnu ;;
echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://apt.fury.io/eza/ /" \ *) eza_arch="${ARCH}-unknown-linux-gnu" ;;
| sudo_ tee /etc/apt/sources.list.d/eza.list >/dev/null esac
sudo_ apt-get update -y && sudo_ apt-get install -y eza || warn "eza PPA failed" local url="https://github.com/eza-community/eza/releases/latest/download/eza_${eza_arch}.tar.gz"
local tmp; tmp="$(mktemp -d)"
if wget -qO "$tmp/eza.tgz" "$url" && tar xzf "$tmp/eza.tgz" -C "$tmp"; then
sudo_ install -m 0755 "$tmp/eza" /usr/local/bin/eza
else
warn "eza download failed ($url)"
fi
rm -rf "$tmp"
fi fi
# starship: official installer # starship: official installer. NOTE — scrub $ARCH/$PLATFORM from the env first:
# the installer reuses a pre-set ARCH (our lib/detect.sh exports ARCH=amd64) and
# skips its own amd64->x86_64 mapping, yielding an unsupported 'amd64-unknown-linux-
# musl' target ('builds for amd64-unknown-linux-musl are not yet available').
# Default bin dir is /usr/local/bin (system-wide).
if ! command -v starship >/dev/null 2>&1; then if ! command -v starship >/dev/null 2>&1; then
curl -sS https://starship.rs/install.sh | sh -s -- -y || warn "starship install failed" curl -sS https://starship.rs/install.sh \
| env -u ARCH -u PLATFORM sh -s -- -y || warn "starship install failed"
fi fi
# zoxide: official installer # zoxide: official installer. Install system-wide (/usr/local/bin) instead of the
# default ~/.local/bin — when run as root the default lands in /root (wrong user
# for the create-user path) and isn't on $PATH; /usr/local/bin is on PATH for all.
if ! command -v zoxide >/dev/null 2>&1; then if ! command -v zoxide >/dev/null 2>&1; then
curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash || warn "zoxide install failed" curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh \
| env -u ARCH sh -s -- --bin-dir /usr/local/bin --man-dir /usr/local/share/man \
|| warn "zoxide install failed"
fi fi
# yq: direct binary from mikefarah/yq releases (stable URL) # yq: direct binary from mikefarah/yq releases (stable URL)
+23 -6
View File
@@ -27,12 +27,25 @@ run_angie() {
} }
_angie_arch() { _angie_arch() {
if command -v yay >/dev/null 2>&1; then if ! command -v yay >/dev/null 2>&1; then
as_user yay -S --noconfirm angie 2>/dev/null \ warn "yay not available — install angie manually from AUR: yay -S angie-bin"
|| as_user yay -S --noconfirm aur/angie 2>/dev/null \ return
|| warn "angie AUR build failed — try: yay -S angie" fi
# Prefer angie-bin: it repackages the upstream official Ubuntu .deb, so it's
# instant (no source compile) and carries the same compiled-in modules our
# config relies on — http_acme, http_ssl, http_v2/v3, http_realip, stream*
# (verified via the .deb's 'angie -V'). Drop back to the source 'angie'
# package only if the binary package is unavailable.
log "AUR install: angie-bin first, fall back to angie (source build)"
if as_user yay -S --noconfirm --needed angie-bin 2>/dev/null; then
ok "angie-bin installed from AUR"
return
fi
log "angie-bin unavailable/failed — building angie from source (may take a few minutes)"
if as_user yay -S --noconfirm --needed aur/angie 2>/dev/null; then
ok "angie (source) installed from AUR"
else else
warn "yay not available — install angie manually from AUR: yay -S angie" warn "angie install failed — try manually: yay -S angie-bin (or: yay -S angie)"
fi fi
} }
@@ -41,7 +54,11 @@ _angie_debian() {
sudo_ install -m 0755 -d /etc/apt/keyrings sudo_ install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://angie.software/keys/angie-signing.gpg \ curl -fsSL https://angie.software/keys/angie-signing.gpg \
| sudo_ tee /etc/apt/keyrings/angie-signing.gpg >/dev/null | sudo_ tee /etc/apt/keyrings/angie-signing.gpg >/dev/null
echo "deb [signed-by=/etc/apt/keyrings/angie-signing.gpg] https://download.angie.software/angie/${ID}/ ${VERSION_CODENAME} main" \ # Repo path is angie/<ID>/<VERSION_ID>/ with the codename as the apt suite, e.g.
# debian/13/dists/trixie/ or ubuntu/22.04/dists/jammy/. Omitting VERSION_ID (just
# angie/debian/) fetches debian/dists/trixie -> 404 'no Release file' — must pin the
# numeric version in the URL path.
echo "deb [signed-by=/etc/apt/keyrings/angie-signing.gpg] https://download.angie.software/angie/${ID}/${VERSION_ID}/ ${VERSION_CODENAME} main" \
| sudo_ tee /etc/apt/sources.list.d/angie.list >/dev/null | sudo_ tee /etc/apt/sources.list.d/angie.list >/dev/null
sudo_ apt-get update -y sudo_ apt-get update -y
sudo_ apt-get install -y angie sudo_ apt-get install -y angie
+9 -5
View File
@@ -6,9 +6,13 @@ step_desc="zsh + oh-my-zsh + plugins, set default shell, ship config"
step_run="run_zsh" step_run="run_zsh"
# All paths resolve against the config TARGET (set by 05-create-user). # All paths resolve against the config TARGET (set by 05-create-user).
ZSH="${ZSH:-$TARGET_HOME/.oh-my-zsh}" # NOTE: we deliberately do NOT honor an inherited $ZSH env var — oh-my-zsh exports
ZSH_CUSTOM="${ZSH_CUSTOM:-$ZSH/custom}" # ZSH when it loads, so a setup.sh run from an omz-equipped shell would otherwise
ZDOTDIR_TARGET="${ZDOTDIR_TARGET:-$TARGET_HOME/.config/zsh}" # pin these to the *old* home (e.g. /root) while the chown step retargets to the
# *new* user, mis-owning the wrong tree (the 'insecure completion dirs' bug).
ZSH="$TARGET_HOME/.oh-my-zsh"
ZSH_CUSTOM="$ZSH/custom"
ZDOTDIR_TARGET="$TARGET_HOME/.config/zsh"
run_zsh() { run_zsh() {
log "installing zsh + oh-my-zsh" log "installing zsh + oh-my-zsh"
@@ -53,8 +57,8 @@ _install_plugins() {
_clone_plugin zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions" _clone_plugin zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
_clone_plugin zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" _clone_plugin zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
_clone_plugin zsh-users/zsh-completions "$ZSH_CUSTOM/plugins/zsh-completions" _clone_plugin zsh-users/zsh-completions "$ZSH_CUSTOM/plugins/zsh-completions"
_clone_plugin Aloofenlore/history-substring-search "$ZSH_CUSTOM/plugins/history-substring-search" _clone_plugin zsh-users/zsh-history-substring-search "$ZSH_CUSTOM/plugins/history-substring-search"
_clone_plugin Aloof98/fzf-tab "$ZSH_CUSTOM/plugins/fzf-tab" _clone_plugin Aloxaf/fzf-tab "$ZSH_CUSTOM/plugins/fzf-tab"
} }
_clone_plugin() { # repo dest _clone_plugin() { # repo dest
+77 -12
View File
@@ -206,20 +206,38 @@ _h_angie_config() {
sudo_ install -d -m 0755 "$d/_on" "$d/targets" "$d/modules" "$d/modules/http" sudo_ install -d -m 0755 "$d/_on" "$d/targets" "$d/modules" "$d/modules/http"
# ── extract packaging-specific values from the stock angie.conf ── # ── extract packaging-specific values from the stock angie.conf ──
# Angie packages set user/pid/error_log differently per distro; preserve them. # Different Angie packages set user/pid/error_log differently (Arch source
local oldcfg="$d/angie.conf" angie_user angie_pid angie_err angie_modules="" # package → /etc/nginx/nginx.conf with 'user http'; angie-bin / Debian .deb
if [[ -f "$oldcfg" ]]; then # → /etc/angie/angie.conf with 'user angie'). Preserve them when present,
angie_user=$(grep -E '^\s*user\s+' "$oldcfg" | head -1 | awk '{print $2}' | tr -d ';') # fall back to sane defaults otherwise (defaults cover all distros here).
angie_pid=$(grep -E '^\s*pid\s+' "$oldcfg" | head -1 | awk '{print $2}' | tr -d ';') local oldcfg="$d/angie.conf"
angie_err=$(grep -E '^\s*error_log\s+' "$oldcfg" | head -1 | awk '{print $2}' | tr -d ';') local altcfg="/etc/nginx/nginx.conf" # the source AUR package's path
local stock="$oldcfg"
[[ -f "$oldcfg" ]] || stock="$altcfg"
local angie_user="" angie_pid="" angie_err="" angie_modules=""
if [[ -f "$stock" ]]; then
angie_user=$(grep -E '^\s*user\s+' "$stock" | head -1 | awk '{print $2}' | tr -d ';')
angie_pid=$(grep -E '^\s*pid\s+' "$stock" | head -1 | awk '{print $2}' | tr -d ';')
angie_err=$(grep -E '^\s*error_log\s+' "$stock" | head -1 | awk '{print $2}' | tr -d ';')
# collect any load_module lines (dynamic modules) # collect any load_module lines (dynamic modules)
angie_modules=$(grep -E '^\s*load_module\s+' "$oldcfg" || true) angie_modules=$(grep -E '^\s*load_module\s+' "$stock" || true)
fi fi
# sane defaults if not found # sane defaults if not found
[[ -z "$angie_user" ]] && angie_user=$({ [[ "$DISTRO" == "arch" ]] && echo http || echo angie; }) [[ -z "$angie_user" ]] && angie_user=$({ [[ "${DISTRO:-}" == "arch" ]] && echo http || echo angie; })
[[ -z "$angie_pid" ]] && angie_pid=/run/angie.pid [[ -z "$angie_pid" ]] && angie_pid=/run/angie.pid
[[ -z "$angie_err" ]] && angie_err=/var/log/angie/error.log [[ -z "$angie_err" ]] && angie_err=/var/log/angie/error.log
# locate mime.types: angie-bin/Debian ship /etc/angie/mime.types; the Arch source
# 'angie' package instead pulls it from the 'mailcap' dep at /etc/nginx/mime.types
# (and deletes its own). Pick whichever exists so 'angie -t' doesn't fail on include.
local angie_mime=""
for m in "$d/mime.types" /etc/nginx/mime.types /etc/mime.types; do
[[ -f "$m" ]] && { angie_mime="$m"; break; }
done
[[ -z "$angie_mime" ]] && { warn "no mime.types found; installing a minimal one"; _angie_install_mime "$d/mime.types"; angie_mime="$d/mime.types"; }
# the modules/ include dir must exist or the glob fails the config test
sudo_ install -d -m 0755 "$d/modules" "$d/modules/http"
# backup the original once # backup the original once
if [[ -f "$oldcfg" && ! -f "$oldcfg.orig.bootstrap" ]]; then if [[ -f "$oldcfg" && ! -f "$oldcfg.orig.bootstrap" ]]; then
sudo_ cp -a "$oldcfg" "$oldcfg.orig.bootstrap" sudo_ cp -a "$oldcfg" "$oldcfg.orig.bootstrap"
@@ -248,7 +266,7 @@ events {
} }
http { http {
include /etc/angie/mime.types; include $angie_mime;
default_type application/octet-stream; default_type application/octet-stream;
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" ' log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
@@ -304,14 +322,25 @@ EOF
# ── default catch-all server: unmatched Host -> drop ── # ── default catch-all server: unmatched Host -> drop ──
if [[ ! -f "$d/_on/00-default.conf" ]]; then if [[ ! -f "$d/_on/00-default.conf" ]]; then
# The default_server also listens on 443 to catch unknown-SNI TLS clients.
# It needs SOME cert to complete the handshake before `return 444` drops them;
# angie won't start a 443 listener without ssl_certificate. Generate a self-signed
# dummy once (CN='bootstrap-default', 10y) so unknown-SNI clients get dropped
# after connecting while real vhosts are picked by SNI.
if [[ ! -f "$d/ssl/bootstrap-default.crt" ]]; then
sudo_ install -d -m 0755 "$d/ssl"
sudo_ openssl req -x509 -newkey rsa:2048 -nodes -days 3650 -keyout "$d/ssl/bootstrap-default.key" -out "$d/ssl/bootstrap-default.crt" -subj "/CN=bootstrap-default/O=bootstrap" 2>/dev/null
fi
sudo_ tee "$d/_on/00-default.conf" >/dev/null <<'EOF' sudo_ tee "$d/_on/00-default.conf" >/dev/null <<'EOF'
# default_server: drop requests that match no enabled host (drive-by scanners, bare-IP) # default_server: drop requests that match no enabled host (drive-by scanners, bare-IP)
server { server {
listen 80 default_server; listen 80 default_server;
listen [::]:80 default_server; listen [::]:80 default_server;
listen 443 default_server; listen 443 ssl default_server;
listen [::]:443 default_server; listen [::]:443 ssl default_server;
server_name _; server_name _;
ssl_certificate /etc/angie/ssl/bootstrap-default.crt;
ssl_certificate_key /etc/angie/ssl/bootstrap-default.key;
return 444; return 444;
} }
EOF EOF
@@ -320,7 +349,25 @@ EOF
# ── angie-enable / angie-disable helpers ── # ── angie-enable / angie-disable helpers ──
_angie_helpers _angie_helpers
# validate + (best-effort) reload # ── source-angie bridge: point /etc/nginx/nginx.conf at our /etc/angie layout ─
# The source AUR 'angie' package compiles --conf-path=/etc/nginx/nginx.conf and
# its service runs '/usr/bin/nginx' with no -c flag, so it ignores /etc/angie.
# When that path is where angie actually reads, back it up once and symlink it to
# our managed angie.conf so the _on/targetsmodules layout takes effect. The
# angie-bin / Debian packages already read /etc/angie/angie.conf directly.
if [[ -f /etc/nginx/nginx.conf && -f "$d/angie.conf" ]]; then
local nginxconf=/etc/nginx/nginx.conf
if [[ "$(readlink -f "$nginxconf" 2>/dev/null)" == "$d/angie.conf" ]]; then
ok "$nginxconf already symlinks to $d/angie.conf"
else
if [[ ! -f "${nginxconf}.orig.bootstrap" && ! -L "$nginxconf" ]]; then
sudo_ cp -a "$nginxconf" "${nginxconf}.orig.bootstrap"
fi
sudo_ ln -sfn "$d/angie.conf" "$nginxconf"
ok "symlinked $nginxconf -> $d/angie.conf (source-angie bridge); backup at ${nginxconf}.orig.bootstrap"
fi
fi
if sudo_ angie -t 2>&1; then if sudo_ angie -t 2>&1; then
ok "angie config valid" ok "angie config valid"
if command -v systemctl >/dev/null 2>&1 && systemctl is-active angie >/dev/null 2>&1; then if command -v systemctl >/dev/null 2>&1 && systemctl is-active angie >/dev/null 2>&1; then
@@ -339,6 +386,24 @@ EOF
# ufw already opened 80/443 in _h_ufw # ufw already opened 80/443 in _h_ufw
} }
_angie_install_mime() { # dest — write a minimal mime.types if none exists on the host
sudo_ tee "$1" >/dev/null <<'EOF'
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
image/png png;
image/svg+xml svg svgz;
application/javascript js;
application/json json;
application/pdf pdf;
application/zip zip;
application/octet-stream bin exe dll so deb dmg iso img;
}
EOF
}
_angie_helpers() { _angie_helpers() {
sudo_ tee /usr/local/bin/angie-enable >/dev/null <<'EOF' sudo_ tee /usr/local/bin/angie-enable >/dev/null <<'EOF'
#!/usr/bin/env bash #!/usr/bin/env bash
+2 -2
View File
@@ -15,7 +15,7 @@ run_sanity() {
echo " memory : $(free -h | awk '/^Mem/ {print $2}') total" echo " memory : $(free -h | awk '/^Mem/ {print $2}') total"
echo " swap : $(swapon --show 2>/dev/null | awk 'NR>1{print $3; found=1} END{if(!found) print "none"}')" echo " swap : $(swapon --show 2>/dev/null | awk 'NR>1{print $3; found=1} END{if(!found) print "none"}')"
echo " timezone : $(timedatectl show -p Timezone --value 2>/dev/null || cat /etc/timezone 2>/dev/null || echo '?')" echo " timezone : $(timedatectl show -p Timezone --value 2>/dev/null || cat /etc/timezone 2>/dev/null || echo '?')"
echo " hostname : $(hostname)" echo " hostname : $(uname -n 2>/dev/null || hostnamectl --static 2>/dev/null || cat /etc/hostname 2>/dev/null || echo '?')"
echo " locale : $(locale 2>/dev/null | awk -F= '/^LANG/ {print $2}')" echo " locale : $(locale 2>/dev/null | awk -F= '/^LANG/ {print $2}')"
echo " ufw : $(sudo_ ufw status 2>/dev/null | head -1 || echo 'not installed')" echo " ufw : $(sudo_ ufw status 2>/dev/null | head -1 || echo 'not installed')"
echo " fail2ban : $(sudo_ fail2ban-client status 2>/dev/null | head -2 || echo 'not running')" echo " fail2ban : $(sudo_ fail2ban-client status 2>/dev/null | head -2 || echo 'not running')"
@@ -32,7 +32,7 @@ run_sanity() {
- Add starship config if you want a custom prompt: starship preset list - Add starship config if you want a custom prompt: starship preset list
(defaults ship with the bootstrap). (defaults ship with the bootstrap).
- Consider 'newgrp docker' or re-login to activate the docker group. - Consider 'newgrp docker' or re-login to activate the docker group.
- Install domain + TLS for angie separately (certbot/acme.sh), not handled here. - Issue TLS certs for angie hosts with: angie-issue <domain> you@email.com
EOF EOF
ok "bootstrap sanity report done." ok "bootstrap sanity report done."
} }
+1
View File
@@ -0,0 +1 @@
- [ ] pm2