Last active
April 21, 2025 21:18
-
-
Save marcg1968/d85370b80526ed0fccc26141c55fd8f5 to your computer and use it in GitHub Desktop.
Setup ubuntu script 2025-04-22
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# run as root | |
# | |
# GIST_URL="<e.g. https://gist.githubusercontent.com/marcg1968/...>" | |
# wget -O - "$GIST_URL" | bash | |
# | |
# force script to run as root | |
[ $(id -u) == "0" ] || { sudo "$0" "$@"; exit $?; } | |
USR="marc" | |
declare -a GRP=('sudo' 'root') | |
GIT_DOTFILES="[email protected]:marcg68/dotfiles.git" | |
STD_PW='$6$MHykSRTZR$pMzhgfXfi.teazwqqvnKoM.OGavCukKDN6q8Im32FyfyNBJ.yE9v9gbE0OEho599eyjLl.RBfErcZzZBPrvxE1' | |
ERROR_CODE=0 | |
declare -a PKG_LIST=() | |
# populate PKG_LIST var | |
pkgs_server() { | |
read -r -d '' LIST <<'EOF' | |
anacron | |
apt-utils | |
at | |
checksecurity | |
cron | |
curl | |
dialog | |
dnsutils | |
dos2unix | |
eog | |
exiv2 | |
fdupes | |
ffmpeg | |
file | |
g++ | |
gcc | |
git | |
host | |
htop | |
imagemagick | |
inotify-tools | |
iperf | |
jq | |
logrotate | |
lynx | |
make | |
man | |
mc | |
meson | |
net-tools | |
netcat | |
nmap | |
npm | |
openssh-server | |
pv | |
rename | |
screen | |
sqlite3 | |
sshfs | |
sshpass | |
sudo | |
vim | |
wget | |
whiptail | |
whois | |
EOF | |
readarray -t PKG_LIST <<<"${LIST}" | |
} | |
set_default_user() { | |
local USERNAME="" | |
local YN="" | |
### regex for valid username cf https://stackoverflow.com/a/17421041 | |
local RE="^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$)$" | |
if [[ $USR =~ $RE ]]; then | |
YN="y" | |
read -p "Use '"$USR"' as standard non-root (admin) user? (Y/n) " -n 1 -r </dev/tty | |
[[ "$REPLY" =~ ^[Nn]$ ]] && YN="n" | |
fi | |
if [[ "$YN" == "y" ]]; then | |
echo "Using '"$USR"' as standard non-root (admin) user" | |
return | |
fi | |
# reset var USR | |
USR="" | |
read -p "Specify standard non-root (admin) user: " U </dev/tty | |
if [[ $U =~ $RE ]]; then | |
echo "Username '"$U"' passes muster. Using '"$U"' as the default (admin) user." | |
USR="$U" | |
else | |
echo -n "The entered value '"$U"' is not valid as a username. " | |
set_default_user | |
fi | |
} | |
check_usr_exists() { | |
(($#>1)) || return 1 | |
local _USR="$1" | |
local _PW="$2" | |
echo -n "Checking if user $_USR exists ... " | |
# check user exists, if not, try to create using supplied pw | |
if ! id "$_USR" >/dev/null 2>&1; then | |
useradd -m -p "$_PW" -s /bin/bash "$_USR" && echo ADDED. | |
fi | |
# again check user exists, exiting if not | |
if ! id "$_USR" >/dev/null 2>&1; then | |
ERROR_CODE=2 | |
else | |
echo 'Good news! User '$_USR" exists." | |
fi | |
} | |
user_grp_env() { | |
(($#>0)) || return 1 | |
local _USR="$1" | |
for i in "${GRP[@]}"; do | |
if ! egrep -q $i'.+'$_USR /etc/group; then | |
echo -n "Adding user $_USR to group '"$i"' ... " | |
usermod -aG "$i" $USR | |
echo done | |
fi | |
done | |
echo -n "/usr/local and below must be writable by group 'root', enacting ... " | |
chmod g+w /usr/local -R | |
echo done. | |
echo -n "/opt and below must be writable by group 'root', enacting ... " | |
chmod g+w /opt -R | |
echo done. | |
} | |
generate_id_rsa() { | |
(($#>0)) || return 1 | |
local _USR="$1" | |
#[ -e /home/$_USR/.ssh/id_rsa ] && echo id_rsa exists || ssh-keygen -q -t rsa -N '' -f /home/$_USR/.ssh/id_rsa <<<y >/dev/null 2>&1 | |
if [ -e /home/$_USR/.ssh/id_rsa ]; then | |
echo id_rsa exists | |
else | |
su -c "ssh-keygen -q -t rsa -N '' -f /home/$_USR/.ssh/id_rsa <<<y >/dev/null 2>&1" $_USR | |
fi | |
[ -e /home/$_USR/.ssh/id_rsa ] && chown $_USR: /home/$_USR/.ssh -R | |
echo | |
echo "Public key: " | |
cat /home/$_USR/.ssh/id_rsa.pub | |
echo | |
} | |
bash_history_logging() { | |
(($#>0)) || return 1 | |
local _USR="$1" | |
local RS | |
FP_LOGS="/home/$_USR/.logs" | |
echo -n "Creating directory $FP_LOGS ... " | |
[[ ! -d $FP_LOGS ]] && mkdir $FP_LOGS && echo done. | |
[[ ! -d $FP_LOGS ]] && echo failed | |
chown -R "${_USR}:" $FP_LOGS | |
if ! egrep -q 'PROMPT_COMMAND.*~/\.logs/' /home/$_USR/.bashrc ; then | |
echo -n "Setting up PROMPT_COMMAND ... " | |
echo 'export PROMPT_COMMAND='"'"'if [ "$(id -u)" -ne 0 ]; then echo "$(date "+%Y-%m-%d.%H:%M:%S") $(pwd) $(history 1)" >> ~/.logs/bash-history-$(date "+%Y-%m-%d").log; fi'"'"'' | tee -a /home/$_USR/.bashrc | |
RS="$?" | |
[[ "$RS" == "0" ]] && echo done. || echo FAILED. | |
else | |
echo "PROMPT_COMMAND already set up in .bashrc ." | |
fi | |
} | |
install_pkgs() { | |
## generate pkg list into var $PKGS | |
# pkg_list | |
local PLURAL="s" | |
local YN="y" | |
[[ ${#PKG_LIST[@]} == 1 ]] && PLURAL="" | |
echo "A list of "${#PKG_LIST[@]}" package"${PLURAL}" are listed to be installed ... " | |
read -p "Continue? (Y/n) " -n 1 -r </dev/tty | |
[[ "$REPLY" =~ ^[Nn]$ ]] && YN="n" | |
if [[ $YN == "n" ]]; then | |
echo "aborting... " | |
fi | |
echo "Doing ``apt update`` and installing basic necessary apt packages ... " | |
apt-get update || return 1 | |
for i in "${PKG_LIST[@]}"; do | |
echo -n "$i ... " | |
# cf https://askubuntu.com/a/319312 | |
if dpkg --get-selections | grep -q "^${i}[[:space:]]*install$" >/dev/null; then | |
echo "already installed." | |
else | |
apt-get -qq install "$i" && echo "success installing" || echo "error installing" | |
fi | |
done | |
echo Completed installing apt packages. | |
# # special handling for keepassx (older version) | |
# pkg="keepassx" | |
# local NEED_TO_INSTALL="" | |
# local URL | |
# local TEMP_DEB | |
# echo -n "$pkg ... " | |
# dpkg --get-selections | grep -q "^${pkg}[[:space:]]*install$" >/dev/null && echo "already installed." || NEED_TO_INSTALL="1" | |
# if [ ! -z "$NEED_TO_INSTALL" ]; then | |
# # cf https://askubuntu.com/a/51859 | |
# URL="http://security.ubuntu.com/ubuntu/pool/universe/k/keepassx/keepassx_0.4.3+dfsg-0.1ubuntu1_amd64.deb" | |
# TEMP_DEB="$(mktemp)" | |
# echo TEMP_DEB=$TEMP_DEB | |
# wget -O "$TEMP_DEB" "$URL" >/dev/null || echo failed to wget $URL | |
# [ -s $TEMP_DEB ] && dpkg -i "$TEMP_DEB" && echo installed. || echo failed. | |
# rm -f "$TEMP_DEB" | |
# # then pin it so is not later updated | |
# echo -n "pinning version of $pkg to prevent later updates ..." | |
# echo "keepassx hold" | sudo dpkg --set-selections && echo done. || echo failed. | |
# fi | |
echo | |
} | |
git_etc() { | |
local $VAR | |
# make vim the default git editor | |
echo -n "making vim the default git editor ... " | |
git config --global core.editor "vim" && echo done. || echo failed. | |
if [[ ! -d /etc/.git ]]; then | |
echo "Putting /etc under git version control ... " | |
cd /etc | |
if [[ ! -f /etc/.gitignore ]]; then | |
read -r -d '' VAR <<'EOF' | |
*~ | |
*.lock | |
*.lck | |
*.sw? | |
/.pwd.lock | |
/adjtime | |
/aliases.db | |
/alternatives/* | |
/apparmor.d/cache | |
/cups/subscriptions.conf* | |
/cups/printers.conf* | |
/ld.so.cache | |
/mtab | |
/rc?.d | |
/ssl/certs | |
!/passwd~ | |
!/group~ | |
!/gshadow~ | |
!/shadow~ | |
# password files | |
/apache2/htpasswd | |
/exim4/passwd.client | |
/apt/trusted.gpg | |
EOF | |
echo -n "now creating standard .gitignore for /etc ... " | |
echo "$VAR" | tee -a /etc/.gitignore && echo "done." | |
fi | |
git config --global user.email "root@`hostname`" | |
git config --global user.name "root on `hostname`" | |
git init && git add . && git commit -m'initial commit' | |
fi | |
# make /etc root's home dir | |
egrep -q 'cd /etc' /root/.bashrc || echo -e '\n## change to /etc dir \ncd /etc\n\n' | sudo tee -a /root/.bashrc | |
} | |
do_mounts_onstart() { | |
if [ ! -e /etc/rc.local ]; then | |
echo "setting up /etc/rc.local to do mounts on start ... " | |
cat <<EOF | sudo tee -a /etc/rc.local | |
#!/bin/sh -e | |
# | |
# rc.local | |
# | |
# This script is executed at the end of each multiuser runlevel. | |
# Make sure that the script will "exit 0" on success or any other | |
# value on error. | |
# | |
# In order to enable or disable this script just change the execution | |
# bits. | |
# | |
# By default this script does nothing. | |
EOF | |
chmod +x /etc/rc.local | |
fi | |
egrep -q 'mount -a' /etc/rc.local || echo -e '\n\nsleep 10\nmount -a\n\n' | sudo tee -a /etc/rc.local | |
echo done. | |
echo | |
} | |
install_nvm() { | |
(($#>0)) || return 1 | |
local _USR="$1" | |
# sudo bash -c "sudo -u marc bash -c 'echo I am $USER, with uid $UID and HOME $HOME'" | |
local _HOME="$(sudo -u marc bash -c 'echo $HOME')" | |
sudo -u $_USR bash -c 'curl -s -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash' | |
#sudo -u $_USR bash -c 'source /home/marc/.bashrc' | |
local NVM_DIR="$_HOME/.nvm" | |
#[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm | |
#[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion | |
#sudo -u $_USR bash -c '\. "$NVM_DIR/nvm.sh"' | |
#sudo -u $_USR bash -c '\. "$NVM_DIR/bash_completion"' | |
#sudo -u $_USR bash -c 'nvm install --lts' | |
} | |
install_yarn() { | |
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - | |
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list | |
sudo apt-get update && sudo apt-get install yarn -y | |
} | |
set_default_user | |
# check standar admin user exists, if not, try to create using std pw | |
check_usr_exists "$USR" "$STD_PW" | |
# set permissions etc | |
user_grp_env "$USR" | |
# set up bash history logging | |
bash_history_logging "$USR" | |
generate_id_rsa "$USR" | |
# put /etc under version control | |
git_etc | |
pkgs_server | |
echo "+++" | |
echo PKG_LIST: | |
echo ${PKG_LIST[*]} | |
echo "+++" | |
install_pkgs | |
#exit 256 | |
install_nvm "$USR" | |
install_yarn | |
do_mounts_onstart |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment