-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbootstrap.sh
More file actions
executable file
Β·125 lines (115 loc) Β· 5.47 KB
/
Copy pathbootstrap.sh
File metadata and controls
executable file
Β·125 lines (115 loc) Β· 5.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env bash
# dotfiles-Defense/bootstrap.sh
# Wire the defensive (blue) role layer onto an already-provisioned box.
# Distro-agnostic: does NOT install OS packages (your OS-native layer does that).
# Idempotent. Stacks: vendored Core + your OS-native layer + DEFENSE role.
#
# ./bootstrap.sh # symlinks + loader + tool/docker checks
# ./bootstrap.sh --links-only # just (re)create symlinks
# ./bootstrap.sh --no-check # skip the host-tool / docker probe
set -euo pipefail
DOTFILES="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}"
LINKS_ONLY=0
DO_CHECK=1
for a in "$@"; do case "$a" in
--links-only) LINKS_ONLY=1 ;;
--no-check) DO_CHECK=0 ;;
-h | --help)
sed -n '2,12p' "$0"
exit 0
;;
*)
echo "unknown arg: $a" >&2
exit 1
;;
esac done
say() { printf '\e[36m::\e[0m %s\n' "$*"; }
ok() { printf '\e[32m+\e[0m %s\n' "$*"; }
warn() { printf '\e[33m!\e[0m %s\n' "$*"; }
# ββ core/ subtree present? ββββββββββββββββββββββββββββββββββββββββββββββββββββ
if [[ ! -d "$DOTFILES/core/zsh" ]]; then
echo "core/ subtree missing. One time, from the repo root run:" >&2
echo " git subtree add --prefix=core <dotfiles-core remote> main --squash" >&2
exit 1
fi
link() {
local src="$1" dst="$2"
mkdir -p "$(dirname "$dst")"
if [[ -L "$dst" ]]; then
rm -f "$dst"
elif [[ -e "$dst" ]]; then mv "$dst" "$dst.pre-dotfiles.$(date +%s)"; fi
ln -s "$src" "$dst" || { echo "link failed: $dst" >&2; return 1; }
}
# ββ Host-tool / docker probe (report only β never installs) ββββββββββββββββββ
check_tools() {
say "checking host tools (install missing ones via your OS layer β see install/README.md)"
local t missing=0
for t in docker jq tshark zeek suricata chainsaw hayabusa sigma yara velociraptor vol log2timeline.py; do
if command -v "$t" >/dev/null 2>&1; then
ok "found: $t"
else
warn "missing: $t"
missing=$((missing + 1))
fi
done
if command -v docker >/dev/null 2>&1; then
if docker compose version >/dev/null 2>&1 || command -v docker-compose >/dev/null 2>&1; then
ok "docker compose available β \`siemup\` will work"
else warn "docker present but compose plugin missing β siemup needs it"; fi
fi
if ((missing == 0)); then
ok "all probed tools present"
else warn "$missing tool(s) missing (optional β install what you need)"; fi
}
wire_links() {
local f
say "symlinking Core"
for f in "$DOTFILES"/core/zsh/*.zsh; do link "$f" "$CONFIG/zsh/$(basename "$f")"; done
[[ -f "$DOTFILES/core/tmux/tmux.conf" ]] && link "$DOTFILES/core/tmux/tmux.conf" "$CONFIG/tmux/tmux.conf"
[[ -f "$DOTFILES/core/tmux/tmux.reset.conf" ]] && link "$DOTFILES/core/tmux/tmux.reset.conf" "$CONFIG/tmux/tmux.reset.conf"
if [[ -d "$DOTFILES/core/tmux/scripts" ]]; then
link "$DOTFILES/core/tmux/scripts" "$CONFIG/tmux/scripts"
chmod +x "$DOTFILES"/core/tmux/scripts/*.sh 2>/dev/null || true
fi
[[ -f "$DOTFILES/core/starship/starship.toml" ]] && link "$DOTFILES/core/starship/starship.toml" "$CONFIG/starship.toml"
[[ -d "$DOTFILES/core/nvim" ]] && link "$DOTFILES/core/nvim" "$CONFIG/nvim"
[[ -f "$DOTFILES/core/git/gitconfig" ]] && link "$DOTFILES/core/git/gitconfig" "$HOME/.gitconfig"
say "symlinking DEFENSE role layer"
# v4: the loader globs NUMBERED fragments ($ZSH_CFG/NN-*.zsh). The defense role stage is
# band 85 β it sorts AFTER the OS layer (80-os.zsh, from the OS-native repo) and BEFORE
# host-local (99-local.zsh), preserving the old `β¦ os defense local` order. Drop any stale
# pre-v4 unnumbered link so the loader doesn't see a dead entry.
[[ -L "$CONFIG/zsh/defense.zsh" ]] && rm -f "$CONFIG/zsh/defense.zsh"
link "$DOTFILES/defense/defense.zsh" "$CONFIG/zsh/85-defense.zsh"
[[ -d "$DOTFILES/defense/templates" ]] && link "$DOTFILES/defense/templates" "$CONFIG/defense/templates"
if [[ ! -f "$HOME/.zshrc" ]] || ! grep -q "dotfiles-managed v4" "$HOME/.zshrc" 2>/dev/null; then
say "writing .zshrc loader (v4 numbered fragments; the defense stage rides band 85)"
[[ -f "$HOME/.zshrc" ]] && cp "$HOME/.zshrc" "$HOME/.zshrc.pre-dotfiles.$(date +%s)"
cat >"$HOME/.zshrc" <<'ZRC'
# dotfiles-managed v4 β do not hand-edit; local tweaks go in ~/.config/zsh/99-local.zsh
: "${XDG_CONFIG_HOME:=$HOME/.config}"
export EDITOR=nvim VISUAL=nvim
: "${ZDOTDIR:=$XDG_CONFIG_HOME/zsh}"
export ZDOTDIR
ZSH_CFG="$ZDOTDIR"
# v4: the loader globs $ZSH_CFG/NN-*.zsh and sources by numeric prefix. It no longer
# takes a module-name list β the load order is the numbering itself: Core 00-69, the
# OS layer at 80-os.zsh, this repo's defense stage at 85-defense.zsh, host-local at
# 99-local.zsh. (So `β¦ os defense local` is preserved without an explicit array.)
if [[ -r "$ZSH_CFG/loader.zsh" ]]; then
source "$ZSH_CFG/loader.zsh"
else
print -u2 -- "zshrc: Core loader not found at $ZSH_CFG/loader.zsh β re-run the dotfiles bootstrap."
fi
ZRC
fi
ok "symlinks wired"
}
# --links-only skips the host-tool/docker probe too (it's the "just wire symlinks" path);
# without consulting LINKS_ONLY here, --links-only would still run the probe and the flag
# would be dead. --no-check skips it independently.
((DO_CHECK && !LINKS_ONLY)) && check_tools
wire_links
say "case data lives in ~/cases (outside this repo) β run \`mkcase <name>\` to start one"
ok "Defense bootstrap complete β open a new shell, or: exec zsh"