-
Notifications
You must be signed in to change notification settings - Fork 0
/
bootstrap.sh
executable file
·301 lines (267 loc) · 8.31 KB
/
bootstrap.sh
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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#!/bin/bash
# Directory of .dotfile (hosting that script)
DOTFILES_DIR=$(dirname "$0" | xargs readlink -f)
# Files to ignore while LSing .dotfile/ for files to simlink into $HOME
LS_IGNORE='-I . -I .. -I *.md -I LICENSE -I NOTICE -I *.sh -I *.txt -I *.swp -I *.bak -I *.bkp -I *.old -I ~* -I *.tmp -I .gitignore -I .git -I .gnupg'
# Check if a logout is needed for applying changes
LOGOUTNEEDED="0"
# Need to detect WSL2 as docker deamon is installed on the host instead of the guest
ONWSL2="$(uname -r | grep -c WSL2)"
function die() {
local rc=$1
shift
local msg=$*
[ -z "$msg" ] || echo "$msg" >&2
exit "$rc"
}
# Install a set of packages
function installpkgs() {
# Refuse to run as root as a couple of things (such as OMZ) would install on
# the root account instead of current account.
[ "$(whoami)" == "root" ] && die 1 "error: don't run as root; sudo is used where needed."
printf "updating apt-sources ..."
sudo apt-get update -y > /dev/null || die 1 # -q=2 does not disable enough output
echo " success"
printf "installing packages ..."
sudo apt-get install -y \
rng-tools \
zsh \
curl \
dnsutils \
wget \
direnv \
expect \
zip unzip \
jq \
dos2unix \
golang \
python3 \
python3-pip \
python3-setuptools \
tmux \
vim \
neovim \
exuberant-ctags \
make \
automake \
autoconf \
cmake \
graphviz \
openjdk-11-jdk \
gpg \
gnupg2 \
pinentry-tty \
shellcheck \
awscli \
> /dev/null \
|| die 1
echo " success"
}
# Default shell to ZSH
function defaulttozsh() {
printf "setting zsh default shell ..."
DEFAULT_SHELL=$(getent passwd "$LOGNAME" | cut -d: -f7)
if [[ "$DEFAULT_SHELL" == "/usr/bin/zsh" ]]; then
echo " success"
else
sudo chsh -s "$(which zsh)" "$USER" || die 1 # need sudo as chsh usually prompts for user's password. $USER is passed through sudo.
echo " success"
fi
}
# Install docker
# Installs docker.io instead of docker-ce. While is lags a bit behind upstream
# it's officially supported and tested on the OS. Unless bleeding edge features
# are needed docker.io is the way to go for me.
function installdocker() {
printf "installing docker.io ..."
sudo apt-get install -y docker.io > /dev/null || die 1
sudo usermod -aG docker "$USER" || die 1 # -q=2 does not disable enough output
echo " success"
# Enable docker daemon only on true Linux, not WSL
printf "enabling docker daemon ..."
if [ "$ONWSL2" == "1" ]; then
echo " skipping (WSL v2)"
else
# On a pure Linux
sudo systemctl -q start docker || die 1
sudo systemctl -q enable docker || die 1
echo " success"
fi
}
# Create a link $2 pointing to a file $1
# Does nothing if the link exist
# Replace any existing link to a different target
# Backup any file with $2 before linking
function linkfile() {
local fn=$1 # the target file in .dotfiles/
local ln=$2 # the link in $HOME/ pointing to $fn
printf "linking %s -> %s ..." "$ln" "$fn"
if [ -e "$ln" ]; then
# $ln exists already
if [ -L "$ln" ];then
# it's a symlink
if [ "$(readlink -f "$ln")" == "$(readlink --canonicalize "$fn")" ]; then
# already linked to the right target
echo " found"
else
# linked to a different target
rm -f "$ln" || die 1
ln -s "$fn" "$ln" || die 1
echo " relinked"
fi
else
# it's not a symlink, conflict
mv "$ln" "$ln.pre_dotfiles" || die 1
ln -s "$fn" "$ln" || die 1
echo " updated"
fi
else
# does not exist, link
ln -s "$fn" "$ln" || die 1
echo " success"
fi
}
# Link all files in .dotfiles from $HOME
function setuplinks() {
for fn in $(ls $LS_IGNORE -a "$DOTFILES_DIR") ; do
fn="${DOTFILES_DIR}/${fn}"
ln="${HOME}/$(basename "$fn")"
linkfile "$fn" "$ln"
done
}
# Install vim-plug for nvim
function installnvimplug() {
printf "installing vim-plug for nvim ..."
curl -sfLo "${HOME}/.local/share/nvim/site/autoload/plug.vim" --create-dirs https://github.com/raw/junegunn/vim-plug/master/plug.vim
echo " success"
printf "installing nvim plugins ..."
nvim +PlugInstall +qall
echo " success"
}
function installlocalbins() {
printf "creating %s/bin ..." "$HOME"
if [ -d "${HOME}/.bin" ]; then
echo " found"
else
mkdir -p "${HOME}/.bin" || die 1
chmod 750 "${HOME}/.bin" || die 1
echo " success"
fi
}
function acquiresudo() {
printf "acquiring sudo ..."
if sudo -n true 2>/dev/null; then
echo " success"
else
echo " failure"
sudo touch /dev/null || die 1 # a noop only for prompting the user
fi
}
function fixz {
# Z install tends not to create ~/.z and complain on 1st directory change
touch ~/.z
}
# Fix premissions on self, often messed up by the lack of a properly set umaks
# prior to running that script and loading out
function fixselfperms() {
find "$DOTFILES_DIR" -type f -print0 | xargs -0 chmod 640 || die 1
find "$DOTFILES_DIR" -type f -name "*.sh" -print0 | xargs -0 chmod 750 || die 1
find "$DOTFILES_DIR" -type d -print0 | xargs -0 chmod 750 || die 1
}
function forcezpluginstall() {
printf "changing shell to zsh ..."
exec zsh -s <<EOF
echo " success";
printf "installing zplug ...";
source $HOME/.zshenv;
source $HOME/.zshrc;
echo " success";
[[ "$LOGOUTNEEDED" == "1" ]] && echo "LOGOUT NEEDED BY SOME CHANGES"
EOF
}
function gitdefaults() {
printf "setting git config ..."
# Forces newly cloned/inited repos to bet set with a local user name and
# email, avoiding the default one to leak...
git config --global user.useConfigOnly true || die 1
# Keep credentials cached for 24h
git config --global credentials.helper 'cache --timeout=86400' || die 1
# unsecure: git config --global credentials.helper store
# Auto-sign commits by default
# need conditional includes: git config --global commit.gpgsign true || die 1
echo " success"
}
# Check the distribution is supported
function checkdistro() {
printf "checking distro ..."
DISTRO=$(lsb_release -d | awk -F '\t' '{print $2}')
if [ "$(echo "$DISTRO" | grep -c 'Ubuntu 20.')" == "1" ]; then
echo " ok ($DISTRO)"
else
echo " unsupported ($DISTRO)"
die 1 "error: requires Ubuntu 20.x, found $DISTRO"
fi
}
# Link ~/.gnupg/gpg.conf to .dotfiles/.gnupg/gpg.conf
# Does not use the general linking mechanism as ~/.gnupg/ contains dynamic
# files that shall not be under .dotfiles/
function setgnupg() {
printf "creating %s/.gnupg ..." "$HOME"
if [ ! -d "${HOME}/.gnupg" ]; then
mkdir -p "${HOME}/.gnupg" || die 1
chmod 700 "${HOME}/.gnupg" || die 1
echo " success"
else
echo " found"
fi
if [ "$(pgrep gpg-agent | wc -l)" == "1" ]; then
# stop agent as it would prevent changes in ~/.gnupg
# it will restart on its own when needed
printf "stopping gpg-agent ..."
pkill gpg-agent || die 1
echo " success"
fi
linkfile "$DOTFILES_DIR/.gnupg/gpg.conf" "${HOME}/.gnupg/gpg.conf" || die 1
linkfile "$DOTFILES_DIR/.gnupg/gpg-agent.conf" "${HOME}/.gnupg/gpg-agent.conf" || die 1
}
function createdotssh() {
printf "creating %s ..." "$HOME/.ssh"
if [ ! -d "$HOME/.ssh" ]; then
mkdir -p "$HOME/.ssh" || die 1
chmod 700 "$HOME/.ssh" || die 1
echo " success"
else
echo " found"
fi
printf "configuring ssh key caching ..."
if [ "$(grep -s AddKeysToAgent "${HOME}/.ssh/config" || echo doit)" == "doit" ]; then
tee -a "${HOME}/.ssh/config" > /dev/null <<EOF || die 1
AddKeysToAgent yes
EOF
echo " success"
else
echo " found"
fi
}
function installpipenv() {
printf "installing pipenv ..."
pip3 -q install --user pipenv || die 1
echo " success"
}
umask 022
checkdistro
acquiresudo
fixselfperms
installpkgs
defaulttozsh
installdocker
setuplinks
installnvimplug
installlocalbins
setgnupg
fixz
createdotssh
installpipenv
# DON'T ADD LINES BELOW HERE AS THE FUNCTION ABOVE CREATES A NEW SHELL
forcezpluginstall
[[ "$LOGOUTNEEDED" == "1" ]] && echo "LOGOUT NEEDED BY SOME CHANGES"