-
Notifications
You must be signed in to change notification settings - Fork 1
/
bootstrap
281 lines (254 loc) · 10.2 KB
/
bootstrap
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# This script should be sourced, not executed
# Can be sourced in bash or zsh
# vim: filetype=bash
SECONDS=0
# Functions for coloured echo
redc=$(tput setaf 1)
gren=$(tput setaf 2)
yelw=$(tput setaf 3)
norm=$(tput sgr0)
red_echo() {
echo "${redc}$1${norm}"
}
green_echo() {
echo "${gren}$1${norm}"
}
yellow_echo() {
echo "${yelw}$1${norm}"
}
# Determine distro
eval "$(source /etc/os-release 2>/dev/null && typeset -p ID)"
[[ $(uname -o) == Android ]] && ID=android
# Alias gum for first run
if [[ $ID != android ]]; then
if ! command -v gum > /dev/null; then
alias gum=~/.dotfiles/bin/$(arch)/gum
fi
fi
# Update packages
if [[ $1 != --skip-update ]]; then
if [[ $ID =~ ^(rhel|fedora.*|amzn|ol|rocky)$ ]]; then
[[ $ID == ol ]] && repo=ol9_developer_EPEL
sudo dnf config-manager --set-enabled $repo
sudo dnf upgrade -y || \
{ red_echo "Failed: packages update" >&2; return 1; }
elif [[ $ID =~ ^(debian|ubuntu|pop|raspbian)$ ]]; then
gum spin --spinner.width=1 \
--title "Updating packages" --show-output -- \
sudo apt-get update -qq && \
sudo apt-get upgrade -y && \
sudo apt autoremove -y || \
{ red_echo "Failed: packages update" >&2; return 1; }
elif [[ $ID == android ]]; then
gum spin --spinner.width=1 \
--title "Updating packages" --show-output -- \
sh -c "yes | pkg upgrade" || \
{ red_echo "Failed: packages update" >&2; return 1; }
fi
fi
# Pull dotfiles origin/master
git -C ~/.dotfiles remote update
[[ $(git -C ~/.dotfiles rev-parse HEAD) == \
$(git -C ~/.dotfiles ls-remote $(git -C ~/.dotfiles rev-parse --abbrev-ref '@{u}' | \
sed 's/\// /g') | cut -f1) ]] && echo Local repository is up to date || \
echo Local repository has diverged from remote. Updating now.. && {
git -C ~/.dotfiles diff-index --quiet HEAD || stash=true
[[ $stash ]] && git -C ~/.dotfiles stash push --quiet
git -C ~/.dotfiles pull --no-ff
[[ $stash ]] && git -C ~/.dotfiles stash pop --quiet
unset stash
}
# Define xdg base directories if first run
# (sourcing separate file as it's difficult to
# make this to work on both bash and zsh and
# it only needs to be run on bash anyway)
if [[ -n $BASH_VERSION ]] && [[ -z $VIMINIT ]] && [[ $ID != android ]]; then
source ~/.dotfiles/bin/scripts/xdg-base-directories
fi
# Install/uninstall some native packages
[[ $ID =~ ^(rhel|fedora.*|amzn|ol|rocky)$ ]] && pkmngcmd='dnf'
[[ $ID =~ ^(debian|ubuntu|pop|raspbian)$ ]] && pkmngcmd='apt-get'
if [[ $pkmngcmd ]]; then
if ! cmp --silent ~/.dotfiles/packages $XDG_STATE_HOME/bootstrap_packages; then
source ~/.dotfiles/packages; sudo $pkmngcmd install -y -- "${packages[@]}" || \
{ red_echo "Failed: package installation" >&2; return 1; }
installed=("${packages[@]}") && unset packages
removed=("${rmmvpkgs[@]}") && unset rmmvpkgs
if [[ -e $XDG_STATE_HOME/bootstrap_packages ]]; then
source $XDG_STATE_HOME/bootstrap_packages
for i in "${installed[@]}"; do packages=("${packages[@]//*$i*}"); done
for k in "${removed[@]}"; do rmmvpkgs=("${rmmvpkgs[@]//*$k*}"); done
sudo $pkmngcmd remove -y -- "${packages[@]}" "${rmmvpkgs[@]}" || \
{ red_echo "Failed: package removal" >&2; return 1; }
fi
command cp ~/.dotfiles/packages $XDG_STATE_HOME/bootstrap_packages
unset packages rmmvpkgs installed removed
fi
unset pkmngcmd
fi
# Stow binaries
if [[ $UID -ne 0 ]] && [[ $EUID -ne 0 ]] && [[ ! $ID == android ]]; then
gum spin --spinner.width=1 --title "Stowing binaries" -- \
sudo ~/.dotfiles/bin/scripts/stow-bin.sh && \
echo "Binaries stowed" || \
{ red_echo "Failed: stow-bin.sh" >&2; return 1; }
else
gum spin --spinner.width=1 --title "Stowing binaries" -- \
sh -c "~/.dotfiles/bin/scripts/stow-bin.sh --nosudo" && \
echo "Binaries stowed" || \
{ red_echo "Failed: stow-bin.sh" >&2; return 1; }
fi
# Stow dotfiles
gum spin --spinner.width=1 --title "Stowing dotfiles" -- \
sh -c ~/.dotfiles/bin/scripts/stow-dotfiles.sh && \
echo "Dotfiles stowed" || \
{ red_echo "Failed: stow-dotfiles.sh" >&2; return 1; }
# Don't do this stuff on Android ----------------------------------------------
if [[ $ID != android ]]; then
# Install/update nix package manager
if [[ ! $(command -v nix) ]]; then
sudo mkdir /etc/nix
sudo sh -c 'printf "%s\n%s\n" \
"use-xdg-base-directories = true" \
"experimental-features = nix-command flakes" \
> /etc/nix/nix.conf'
{ gum spin --spinner.width=1 --title "Installing nix package manager" -- \
sh <(curl -sL https://nixos.org/nix/install) --yes --no-modify-profile && \
yellow_echo Nix package manager installed; } && \
source $XDG_STATE_HOME/nix/profile/etc/profile.d/nix.sh || \
{ red_echo "Failed: nix package manager installation" >&2; return 1; }
fi
nix-channel --add https://nixos.org/channels/nixos-23.11 stbpkgs
nix-channel --update
{ gum spin --spinner.width=1 --title "Nix garbage collecting" --show-output -- \
nix-collect-garbage --delete-old && \
echo Nix garbage collected; }
# Install & uninstall nix packages
if ! cmp --silent ~/.dotfiles/nix.pkgs $XDG_STATE_HOME/nix_packages; then
source ~/.dotfiles/nix.pkgs
newpkgs=("${nixpkgs[@]}") && unset nixpkgs
if [[ -e $XDG_STATE_HOME/nix_packages ]]; then
source $XDG_STATE_HOME/nix_packages
oldpkgs=("${nixpkgs[@]}") && unset nixpkgs
newpkgs=($(comm -2 -3 <(printf "%s\n" "${newpkgs[@]}" | sort) \
<(printf "%s\n" "${oldpkgs[@]}" | sort) | sort -n))
fi
export NIXPKGS_ALLOW_UNFREE=1
for addpkg in "${newpkgs[@]}"; do
if [[ $addpkg != ${addpkg#nixpkgs.} ]]; then
nix-env -iA $addpkg \
&& green_echo "${addpkg#nixpkgs.} installed" || \
{ red_echo "Failed: ${addpkg#nixpkgs.} nix package installation" >&2
return 1; }
elif [[ $addpkg != ${addpkg#stbpkgs.} ]]; then
nix-env -iA $addpkg \
&& green_echo "${addpkg#stbpkgs.} (stable channel) installed" || \
{ red_echo "Failed: ${addpkg#stbpkgs.} nix package installation" >&2
return 1; }
fi
done
unset newpkgs
if [[ -e $XDG_STATE_HOME/nix_packages ]]; then
source $XDG_STATE_HOME/nix_packages
oldpkgs=("${nixpkgs[@]}") && unset nixpkgs
source ~/.dotfiles/nix.pkgs
newpkgs=("${nixpkgs[@]}") && unset nixpkgs
oldpkgs=($(comm -1 -3 <(printf "%s\n" "${newpkgs[@]}" | sort) \
<(printf "%s\n" "${oldpkgs[@]}" | sort) | sort -n))
for rempkg in "${oldpkgs[@]}"; do
if [[ $rempkg != ${rempkg#nixpkgs.} ]]; then
nix-env --uninstall ${rempkg#nixpkgs.} \
&& yellow_echo "${rempkg#nixpkgs.} uninstalled" || \
{ red_echo "Failed: ${rempkg#nixpkgs.} nix package removal" >&2
return 1; }
elif [[ $rempkg != ${rempkg#stbpkgs.} ]]; then
nix-env --uninstall ${rempkg#stbpkgs.} \
&& yellow_echo "${rempkg#stbpkgs.} (stable channel) uninstalled" || \
{ red_echo "Failed: ${rempkg#stbpkgs.} nix package removal" >&2
return 1; }
fi
done
unset oldpkgs
fi
command cp ~/.dotfiles/nix.pkgs $XDG_STATE_HOME/nix_packages
fi
# Enable passwordless sudo
# (already enabled on cloud instances through cloud-init)
if ! sudo grep -Eqr "$USER +ALL" /etc/sudoers.d/; then
printf "$USER ALL=(ALL:ALL) NOPASSWD: ALL\n" | sudo tee /etc/sudoers.d/$USER
sudo chmod 440 /etc/sudoers.d/$USER
yellow_echo "Passwordless sudo enabled"
fi
# Change default shell to zsh if it is not already
if [[ $(basename "$(grep $(whoami) /etc/passwd)") != zsh ]]; then
sudo chsh --shell /bin/zsh $(whoami)
yellow_echo "Default shell changed to z-shell"
fi
# On WSL do some stuff to set it up
if grep -qi microsoft /proc/version; then
gum spin --spinner.width=1 --title "Configuring Windows" -- \
~/.dotfiles/bin/scripts/setup_wsl.sh && \
echo "Windows Subsystem for Linux configured" || \
{ red_echo "Failed: Windows Subsystem for Linux setup" >&2; return 1; }
fi
# Generate British locale if not available
if [[ $ID =~ ^(debian|ubuntu|pop|raspbian)$ ]]; then
if ! validlocale en_GB.UTF-8 &>/dev/null; then
sudo locale-gen en_GB.UTF-8 && \
yellow_echo "Locale generated: en_GB.UTF-8"
fi
fi
# Install and configure fail2ban on bastion hosts
if [[ $(hostname -s) =~ ^(bastet|baal|jump|gateway|firewall)$ ]]; then
sudo ~/.dotfiles/bin/scripts/install_fail2ban.sh
fi
# Install or update golang
sudo ~/.dotfiles/bin/scripts/install_golang.sh
# Add Hashicorp repository
sudo ~/.dotfiles/bin/scripts/repo-add-hashcorp.sh && \
yellow_echo "Hashicorp repository added"
# Check if kernel has been updated
if ! grep -qi microsoft /proc/version; then
~/.dotfiles/bin/scripts/kernel-update-check.sh
fi
# Get current SSH key from Dashlane vault and add to ssh-agent
# on (non-WSL) client machines (hostname starts with h)
if [[ $(hostname -s) =~ ^(h.+)$ ]]; then
if ! grep -qi microsoft /proc/version; then
if [[ ! -O ~/.ssh/id_ed25519 ]]; then
dcli sync
dcli note id_ed25519.pem > ~/.ssh/id_ed25519
dcli logout
chmod 600 ~/.ssh/id_ed25519
ssh-add
fi
fi
fi
fi
## End of Android exclusion ---------------------------------------------------
# Change to ssh protocol if keys are available through ssh-agent
if [[ $(git -C ~/.dotfiles remote -v) =~ https ]] && ssh-add -l &>/dev/null; then
git remote set-url origin [email protected]:eggbean/.dotfiles.git && \
yellow_echo "Repository remote switched ssh access"
fi
# Setup/update antidote
if [[ $ZSH_VERSION ]]; then
if [[ ! -d ~/.cache/antidote ]]; then
git clone --depth=1 https://github.com/mattmc3/antidote.git ~/.cache/antidote
fi
source ~/.cache/antidote/antidote.zsh
antidote load ~/.dotfiles/config/.includes/zsh_plugins.txt
antidote update | grep -Ev "(^antidote: checking for updates|^$)"
fi
# Check if repository is encryption locked
git config -f ~/.dotfiles/.git/config --get filter.git-crypt.smudge >/dev/null || \
yellow_echo "Repository is locked"
# Print time taken
printf 'Time taken %d:%02d:%02d\n' \
$((SECONDS/3600)) $(((SECONDS/60)%60)) $((SECONDS%60))
# Initialise shell
if [[ $BASH_VERSION ]]; then
exec bash
elif [[ $ZSH_VERSION ]]; then
exec zsh
fi