-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprovision_pi
executable file
·359 lines (300 loc) · 12.8 KB
/
provision_pi
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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#!/usr/bin/env bash
set -euo pipefail -o errtrace
CONFIG=/boot/config.txt
PASSWORD=""
PATH_TO_SSH_KEY="$HOME/.ssh/id_ed25519"
GIT_USER_EMAIL=''
GIT_USER_NAME=''
HOSTNAME="raspberrypi"
ENABLE_SPI=false
SHOULD_DELETE_SELF=false
usage(){
echo "Usage: $(basename "${0}") -p <PASSWORD> [-h <HOSTNAME>] [-i <PATH_TO_SSH_KEY>] [-s] [-r]"
echo "Run this from the raspberry pi."
echo " -p PASSWORD : Password for the raspberry pi's user account."
echo " -h HOSTNAME : Set the hostname. Defaults to $HOSTNAME."
echo " -i PATH_TO_SSH_KEY : defaults to: $PATH_TO_SSH_KEY"
echo " -e GIT_USER_EMAIL : email address for git"
echo " -f GIT_USER_NAME : user name for git"
echo " -s : Enable SPI"
echo " -r : delete self (this script) after running"
exit 1
}
main(){
trap 'fail $? $LINENO' ERR
parseOpts "$@"
setupSshKey
updateAndInstallPackages
setupGit
setupGitDelta
installRmate
clonePiTools
changeAndSetupShell
installReadlineHack
setTimezone
setOverVoltage
setTempSoftLimit
maybeEnableSpi
# Setting the hostname should be as close to the last step as possible. Anything after this step that
# requires `sudo` will emit a warning: "sudo: unable to resolve host raspberrypi: Name or service not known".
# Note that `sudo` will still work; it's just a "warning".
setHostname
maybeDeleteSelf
info "\\nRestarting..."
info "Pi will be available via:\\n"
info " ssh $USER@$HOSTNAME.local\\n"
# Hide the "sudo: unable to resolve host raspberrypi: Name or service not known" output by
# redirecting stderr. This it to avoid someone thinking something didn't work (it's fine).
# Related to changing the hostname via setHostname above.
sudo shutdown -r now 2>/dev/null
}
parseOpts(){
while getopts ":p:h:i:e:f:sr" opt; do
case ${opt} in
p) PASSWORD=${OPTARG} ;;
h)
if [[ "$OPTARG" =~ ^[a-z]([a-z0-9-]*[a-z0-9])?$ ]]; then
HOSTNAME=${OPTARG}
else
warn "Invalid hostname."
usage
fi
;;
i) PATH_TO_SSH_KEY=${OPTARG} ;;
e) GIT_USER_EMAIL=${OPTARG} ;;
f) GIT_USER_NAME=${OPTARG} ;;
s) ENABLE_SPI=true ;;
r) SHOULD_DELETE_SELF=true ;;
\?)
warn "Invalid option: -$OPTARG"
usage
;;
:)
warn "Option -$OPTARG requires an argument."
usage
;;
*) usage ;;
esac
done
# Validation
local has_usage_errors
has_usage_errors=false
if [ -z "$PASSWORD" ]; then
has_usage_errors=true
warn "Please supply a password for the raspberry pi's user account with the flag: -p"
fi
if [[ $has_usage_errors == "true" ]]; then
usage
fi
}
setupSshKey(){
info "\\nSetting up ssh key... If you still need to add this key to your github account, see: "
info "https://docs.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account"
info "https://github.com/settings/keys"
eval "$(ssh-agent -s)"
ssh-add "$PATH_TO_SSH_KEY"
sleep 1 # ssh setup is randomly slow to complete. Wait a bit to avoid cloberring subsequent output lines.
}
updateAndInstallPackages(){
info "\\nUpdating and installing packages..."
sudo apt update
sudo apt -y install git mlocate vim zsh zsh-syntax-highlighting python3-pip
sudo apt -y full-upgrade
sudo PIP_BREAK_SYSTEM_PACKAGES=1 python3 -m pip install --upgrade speedtest-cli
}
setupGit(){
info "\\nSetting up git..."
# Use diff-highlight as the `git diff` tool / pager. This may be overwritten by git delta
# (see setupGitDelta).
sudo make -C /usr/share/doc/git/contrib/diff-highlight
git config --global core.pager '/usr/share/doc/git/contrib/diff-highlight/diff-highlight | less'
if [[ -n ${GIT_USER_EMAIL} ]]; then
info "\\nSetting git user email to $GIT_USER_EMAIL..."
git config --global user.email "$GIT_USER_EMAIL"
fi
if [[ -n ${GIT_USER_NAME} ]]; then
info "\\nSetting git user name to $GIT_USER_NAME..."
git config --global user.name "$GIT_USER_NAME"
fi
git config --global pull.rebase true
}
# Better git diff: https://github.com/dandavison/delta
setupGitDelta(){
info "\\nSetting up git delta..."
# See: https://github.com/dandavison/delta/releases
local os_suffix='armhf';
if [[ $(getconf LONG_BIT) == '64' ]] ; then
os_suffix='arm64'
fi
curl -L "https://github.com/dandavison/delta/releases/download/0.16.5/git-delta_0.16.5_$os_suffix.deb" > /tmp/delta.deb
sudo dpkg -i /tmp/delta.deb
# See: https://github.com/dandavison/delta/issues/162#issuecomment-625952288
# https://github.com/sharkdp/bat/releases
curl -L "https://github.com/sharkdp/bat/releases/download/v0.23.0/bat_0.23.0_$os_suffix.deb" > /tmp/bat.deb
sudo dpkg -i /tmp/bat.deb
mkdir -p ~/.config/bat/syntaxes
curl https://gist.githubusercontent.com/dasl-/9ea0d83cd478f36f6c7deaa737480492/raw/d2276cb45a41180304d7ad8b287b17c948c4d8a0/PHP.sublime-syntax > ~/.config/bat/syntaxes/PHP.sublime-syntax
mkdir -p ~/.config/bat/themes
curl 'https://gist.githubusercontent.com/dasl-/255b183383bd412356d347c61d77181d/raw/4b4b41dfc1d705f13d40244c7fcf420c70a31d86/Monokai%2520(SL).tmTheme' > ~/.config/bat/themes/'Monokai (SL).tmTheme'
bat cache --clear
bat cache --build
# See: https://github.com/dandavison/delta#get-started
git config --global core.pager 'delta --true-color always --syntax-theme "Monokai (SL)"'
git config --global interactive.diffFilter 'delta --true-color always --syntax-theme "Monokai (SL)" --color-only'
git config --global delta.navigate 'true'
git config --global delta.light 'false'
git config --global merge.conflictstyle 'diff3'
git config --global diff.colorMoved 'default'
# My delta customizations:
git config --global delta.minus-style 'syntax auto'
git config --global delta.word-diff-regex '.' # https://github.com/dandavison/delta/issues/184
}
# allows `subl path_to_file.txt` to use sublime text to edit the file on the pi
#
# This requires setting up ssh port forwarding for our port in the computer we are sshing from.
installRmate(){
info "\\nInstalling rmate..."
sudo wget -O /usr/local/bin/subl https://raw.githubusercontent.com/aurora/rmate/master/rmate
sudo chmod a+x /usr/local/bin/subl
# set subl as default git editor
git config --global core.editor 'subl -w'
}
# Useful for the wifi_config script, shairport-sync installation, etc
clonePiTools(){
info "\\nInstalling pitools..."
dev_dir="$HOME/development"
mkdir -p "$dev_dir"
git -C "$dev_dir" clone https://github.com/dasl-/pitools.git
}
changeAndSetupShell(){
info "\\nSetting up zsh shell..."
# change default shell
echo "$PASSWORD" | chsh -s /usr/bin/zsh
# oh-my-zsh
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# iterm shell integration
curl -L https://iterm2.com/shell_integration/zsh -o ~/.iterm2_shell_integration.zsh
# fzf
# We don't use apt to install fzf because the apt version is sometimes too old to be compatible with fzf-tab.
# See: https://github.com/Aloxaf/fzf-tab/issues/189
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install --key-bindings --completion --no-update-rc
# fzf-tab: change native zsh autocomplete to always use fzf
# https://github.com/Aloxaf/fzf-tab#install
fzf_tab_dir="$HOME/.config/zsh"
mkdir -p "$fzf_tab_dir"
git -C "$fzf_tab_dir" clone https://github.com/Aloxaf/fzf-tab
curl https://raw.githubusercontent.com/dasl-/pitools/main/homedir/.zshrc > "$HOME/.zshrc"
curl https://raw.githubusercontent.com/dasl-/pitools/main/homedir/zsh_fix_history > "$HOME/zsh_fix_history"
sudo chmod a+x "$HOME/zsh_fix_history"
}
# Enable fzf history search in any application that uses libreadline.
# See: https://github.com/lincheney/fzf-tab-completion#readline
installReadlineHack(){
info "\\nInstalling readline hack..."
curl https://raw.githubusercontent.com/dasl-/pitools/main/homedir/.inputrc > "$HOME/.inputrc"
mkdir -p ~/readline-hack
local so_suffix='32bit';
if [[ $(getconf LONG_BIT) == '64' ]] ; then
so_suffix='64bit'
fi
curl "https://raw.githubusercontent.com/dasl-/pitools/main/homedir/readline-hack/librl_custom_function_$so_suffix.so" > "$HOME/readline-hack/librl_custom_function.so"
curl "https://raw.githubusercontent.com/dasl-/pitools/main/homedir/readline-hack/librl_custom_isearch_$so_suffix.so" > "$HOME/readline-hack/librl_custom_isearch.so"
mkdir -p ~/bin
curl https://raw.githubusercontent.com/lincheney/rl_custom_isearch/master/bin/rl_custom_isearch > "$HOME/bin/rl_custom_isearch"
chmod a+x "$HOME/bin/rl_custom_isearch"
# readline-hack workaround: https://gist.github.com/dasl-/8530db0b95a8793756cb5ce671651acf
sudo ln -s /usr/lib/arm-linux-gnueabihf/libreadline.so.8.1 /usr/lib/libreadline.so
}
setTimezone(){
sudo timedatectl set-timezone UTC
}
# See: https://forums.raspberrypi.com/viewtopic.php?t=334876
setOverVoltage(){
local over_voltage
over_voltage=$(vcgencmd get_config over_voltage | sed -n 's/over_voltage=\(.*\)/\1/p')
if (( over_voltage >= 2 )); then
info "over_voltage was already high enough ( $over_voltage )..."
return
fi
force_turbo=$(vcgencmd get_config force_turbo | sed -n 's/force_turbo=\(.*\)/\1/p')
if (( force_turbo == 1 )); then
# See: https://www.raspberrypi.com/documentation/computers/config_txt.html#overclocking-options
warn "WARNING: not setting over_voltage because force_turbo is enabled and we don't " \
"want to set your warranty bit. This might result in wifi or video playback issues."
return
fi
# Set over_voltage.
info "Setting over_voltage to 2..."
# comment out existing over_voltage lines in config
sudo sed $CONFIG -i -e "s/^\(over_voltage=.*\)/#\1/"
echo -e 'over_voltage=2' | sudo tee -a $CONFIG >/dev/null
}
# See:
# https://www.raspberrypi.com/documentation/computers/config_txt.html#monitoring-core-temperature
# https://www.raspberrypi.com/documentation/computers/config_txt.html#overclocking
#
# Only applicable to raspberry pi 3A+/3B+. The default soft limit of 60 is low enough that we'd
# occasionally see spurious CPU throttling occur. Let's set it to the max allowed: 70.
# I think we're unlikely to reach 70 degrees doing anything we normally do with the pis.
# Thus the point of having a soft limit is moot for our use case - it will just result in
# unnecessary throttling.
setTempSoftLimit(){
if ! grep -q 'Raspberry Pi 3 Model [AB] Plus' /proc/device-tree/model ; then
info "not setting temp_soft_limit because this is not a Raspberry Pi 3A+/3B+"
return
fi
local temp_soft_limit
temp_soft_limit=$(vcgencmd get_config temp_soft_limit | sed -n 's/temp_soft_limit=\(.*\)/\1/p')
if (( temp_soft_limit >= 70 )); then
info "temp_soft_limit was already high enough ( $temp_soft_limit )..."
return
fi
# Set temp_soft_limit.
info "Setting temp_soft_limit to 70..."
# comment out existing temp_soft_limit lines in config
sudo sed $CONFIG -i -e "s/^\(temp_soft_limit=.*\)/#\1/"
echo -e 'temp_soft_limit=70' | sudo tee -a $CONFIG >/dev/null
}
maybeEnableSpi(){
if [[ ${ENABLE_SPI} == "true" ]]; then
info "\\nEnabling SPI..."
# https://raspberrypi.stackexchange.com/a/96679
sudo raspi-config nonint do_spi 0
fi
}
# Allows sshing and hitting the pifi webpage via "<hostname>.local"
# See: https://www.raspberrypi.org/documentation/remote-access/ip-address.md "Resolving raspberrypi.local with mDNS"
setHostname(){
info "\\nSetting hostname to: $HOSTNAME"
echo "$HOSTNAME" | sudo tee /etc/hostname >/dev/null 2>&1
sudo sed -i -E 's/(127\.0\.1\.1\s+)[^ ]+/\1'"$HOSTNAME"'/g' /etc/hosts
}
maybeDeleteSelf() {
if [[ ${SHOULD_DELETE_SELF} == "true" ]]; then
SCRIPT_DIR="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
SCRIPT_NAME=$(basename -- "${BASH_SOURCE[0]}")
SCRIPT_PATH="$SCRIPT_DIR/$SCRIPT_NAME"
info "\\nDeleting self ( $SCRIPT_PATH )..."
rm "$SCRIPT_PATH"
fi
}
fail(){
local exit_code=$1
local line_no=$2
local script_name
script_name=$(basename "${BASH_SOURCE[0]}")
die "Error in $script_name at line number: $line_no with exit code: $exit_code"
}
info(){
echo -e "\x1b[32m$*\x1b[0m" # green stdout
}
warn(){
echo -e "\x1b[33m$*\x1b[0m" # yellow stdout
}
die(){
echo
echo -e "\x1b[31m$*\x1b[0m" >&2 # red stderr
exit 1
}
main "$@"