Skip to content

Instantly share code, notes, and snippets.

@marcg1968
Last active April 21, 2025 21:18
Show Gist options
  • Save marcg1968/d85370b80526ed0fccc26141c55fd8f5 to your computer and use it in GitHub Desktop.
Save marcg1968/d85370b80526ed0fccc26141c55fd8f5 to your computer and use it in GitHub Desktop.
Setup ubuntu script 2025-04-22
#!/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