First commit

This commit is contained in:
myve 2025-11-22 23:15:27 +00:00
commit 36ad41a2fc
18 changed files with 10005 additions and 0 deletions

39
README.md Normal file
View file

@ -0,0 +1,39 @@
# MyveArch
This repo is a compilation of installation scripts written in bash that install [Arch Linux](https://archlinux.org/) on any x86_64 EFI system. From a home server ([homelab.sh](homelab.sh)) to a laptop or desktop computer ([arch.sh](arch.sh)), these scripts are highly customizable and can be tailored to very specific needs.
## :: Pre-installation
Acquire an installation ISO and burn it into a USB drive:
```
dd bs=4M if=${/path/to/archlinux-version-x86_64.iso} of=${/dev/disk/by-id/usb-My_flash_drive} conv=fsync oflag=direct status=progress
```
## :: Usage
Download the script of choice and execute it in the terminal:
```
wget https://myvelabs.com/lab/archlinux/raw/branch/master/arch.sh
bash arch.sh
```
OR
```
curl --fail -s -L -O https://myvelabs.com/lab/archlinux/raw/branch/master/homelab.sh
bash homelab.sh
```
OR
```
git clone https://myvelabs.com/lab/archlinux.git
cd archlinux/
bash arch.sh
```
## :: Installation
The following flags are available:
```
-s, --ssh-key Authorized SSH public key (one entry per flag, enclosed in quotes)
-c, --cache Pacman cache server address
-k, --kernel Linux kernel (eg, linux, linux-lts, linux-hardened, linux-zen)
-f, --filesystem Choice of filesystem (eg, ext4, btrfs, zfs)
-o, --option Arch installation setup, if known
```
Fill out the prompts and you'll have a full-fledged Arch Linux system up and running in no time.

1755
arch.sh Executable file

File diff suppressed because it is too large Load diff

728
functions/chroot Executable file
View file

@ -0,0 +1,728 @@
#!/usr/bin/env bash
revision=0.1a
set -a
set -E
echo
# Environment variables
tee -a /etc/environment >/dev/null <<- environment
EDITOR=vim
SUDO_EDITOR=vim
environment
# Global bashrc
tee -a /etc/skel/.bashrc >/dev/null <<- 'bashglobal'
# Source bash functions
if [ -d ~/.local/functions ]
then
for file in $(find ~/.local/functions -type f)
do
. ${file}
done
fi
# Add local functions folder to path
export PATH=${PATH}:${HOME}/.local/bin:/zfs/bin:/opt/local/bin
export SUDO_PROMPT=$'\a'"$(tput rev)[sudo] password for %p:$(tput sgr0)"' '
# Colored prompts
alias diff='diff --color=auto'
alias ip='ip -color=auto'
export LESS='-R --use-color -Dd+r$Du+b$'
# Adjust terminal upon window resize
shopt -s checkwinsize
# Auto cd into directory
shopt -s autocd
# Enable tab complete for sudo
complete -c -f sudo
# Ignore duplicate and whitespace history entries
export HISTCONTROL=ignoreboth
#
# ~/.bash_aliases
#
# ZFS/btrfs
alias zfs='sudo zfs'
alias zpool='sudo zpool'
alias btrfs='sudo btrfs'
# Shutdown reboot
alias poweroff='sudo poweroff'
alias reboot='sudo reboot'
# Text editors
alias v='vim'
alias sv='sudo vim'
# Clear bash history
alias clearhistory='rm ${HISTFILE}; history -c -w'
# Miscellanous pacman
alias orphans='sudo pacman -Rcns $(pacman -Qtdq)'
alias unlockpacman='sudo rm /var/lib/pacman/db.lck && sudo pacman -Syyu'
# Rsync
alias rsync='rsync -v -h --progress --info=progress2 --partial --append-verify'
# --log-file=
# --remove-source-files
#
# ~/.bash_functions
#
# Pacman tools
function installer
{
/opt/local/bin/cacheserver
sudo pacman -S ${@}
echo
}
function uninstall
{
sudo pacman -Rcns ${@}
echo
}
function mirrors
{
echo
sudo reflector --country CA,US --age 24 --latest 20 --protocol https --fastest 25 --sort rate --save /etc/pacman.d/mirrorlist
echo
cat /etc/pacman.d/mirrorlist
echo
}
function syur
{
/opt/local/bin/syu &&
reboot
}
function syup
{
/opt/local/bin/syu &&
poweroff
}
# Update bash
function update-bash
{
vim ~/.bashrc &&
source ~/.bashrc
}
bashglobal
# Root bashrc
rsync -a /etc/skel/.bashrc ~/
mkdir -p ~/.local/functions/
cat > ~/.local/functions/bashrc <<- 'bashrc'
#!/usr/bin/env bash
# Root shell color
PS1="$(tput setaf 1)[\u@\h \W \$?]\$$(tput sgr0) "
# Colored prompts
alias ll='ls --color=auto -l -a -h'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
# Disable history
unset HISTFILE
rm -f ${HISTFILE}
history -c -w
bashrc
# Locale
sed '/#en_US.UTF-8 UTF-8/ s/#//' -i /etc/locale.gen
locale-gen >/dev/null
echo 'LANG=en_US.UTF-8' >>/etc/locale.conf
say as heading 'Locale configured'
# Time zone
if ls -l /dev/disk/* | grep -q 'VBOX\|virtio\|QEMU'
then
ln -s -f $(find /usr/share/zoneinfo/ | shuf -n 1) /etc/localtime
else
ln -s -f /usr/share/zoneinfo/UTC /etc/localtime
fi
hwclock --systohc --utc
say as heading 'Time zone configured'
# Hostname
echo ${hostname} >/etc/hostname
cat >>/etc/hosts <<HOSTS
127.0.0.1 localhost
127.0.1.1 ${hostname}
HOSTS
say as heading 'Hostname configured'
# User and superuser
useradd -m -g users -G wheel -s /usr/bin/bash ${username} || die 'User account creation has failed'
printf '%s\n' "${userpass}" "${userpass}" | passwd ${username} >/dev/null 2>&1
unset userpass userpass2
# Disable root account
passwd -l root >/dev/null 2>&1
# Sudoers
install -m 0440 /dev/stdin /etc/sudoers.d/01-DEFAULTS <<- DEFAULTS
Defaults passwd_timeout=0
Defaults timestamp_type=global
Defaults insults
DEFAULTS
install -m 0440 /dev/stdin /etc/sudoers.d/02-COMMANDS <<- COMMANDS
Cmnd_Alias POWER = /usr/bin/poweroff, /usr/bin/reboot
Cmnd_Alias ZFS = /usr/bin/zfs, /usr/bin/zpool
Cmnd_Alias BTRFS = /usr/bin/btrfs, /usr/bin/timeshift, /usr/bin/timeshift-gtk, /usr/bin/timeshift-launcher
Cmnd_Alias QEMU = /usr/bin/virsh, /usr/bin/qemu-system-x86_64, /usr/bin/virt-install
Cmnd_Alias FAIL2BAN = /usr/bin/fail2ban-client
Cmnd_Alias ARCHISO = /opt/local/bin/mkairgap, /opt/local/bin/mkiso
Cmnd_Alias PACMAN = /usr/bin/pacman -Sy
Cmnd_Alias IPTABLES = /usr/bin/iptables, /usr/bin/iptables-save
Cmnd_Alias MISC = /usr/bin/rsync
COMMANDS
install -m 0440 /dev/stdin /etc/sudoers.d/03-WHEEL <<- WHEEL
%wheel ALL=(ALL:ALL) ALL
%wheel ALL=(ALL:ALL) NOPASSWD: POWER, ZFS, BTRFS, QEMU, FAIL2BAN, ARCHISO, PACMAN, IPTABLES, MISC
WHEEL
install -m 0440 /dev/stdin /etc/sudoers.d/.zz-NOPASSWD <<- NOPASSWD
Defaults:${username} !authenticate
NOPASSWD
case ${filesystem} in
zfs)
# ZFS setup
zpool set cachefile=/etc/zfs/zpool.cache zroot
zgenhostid $(hostid)
# ZFS files
touch /zfs/snapshot-syu
chown ${username}:users /zfs/snapshot-syu
# Trim zroot monthly
cat >/etc/systemd/system/zfs-trim@.timer <<- 'TRIM'
[Unit]
Description=Monthly zpool trim on %i
[Timer]
OnCalendar=monthly
AccuracySec=1h
Persistent=true
[Install]
WantedBy=multi-user.target
TRIM
cat >/etc/systemd/system/zfs-trim@.service <<- 'TRIM'
[Unit]
Description=zpool trim on %i
Documentation=man:zpool-trim(8)
Requires=zfs.target
After=zfs.target
ConditionACPower=true
ConditionPathIsDirectory=/sys/module/zfs
[Service]
Nice=19
IOSchedulingClass=idle
KillSignal=SIGINT
ExecStart=/bin/sh -c '\
if /usr/bin/zpool status %i | grep "trimming"; then\
exec /usr/bin/zpool wait -t trim %i;\
else exec /usr/bin/zpool trim -w %i; fi'
ExecStop=-/bin/sh -c '/usr/bin/zpool trim -s %i 2>/dev/null || true'
[Install]
WantedBy=multi-user.target
TRIM
# Scrub zroot monthly
cat >/etc/systemd/system/zfs-scrub@.timer <<- 'SCRUB'
[Unit]
Description=Monthly zpool scrub on %i
[Timer]
OnCalendar=monthly
AccuracySec=1h
Persistent=true
[Install]
WantedBy=multi-user.target
SCRUB
cat >/etc/systemd/system/zfs-scrub@.service <<- 'SCRUB'
[Unit]
Description=zpool scrub on %i
[Service]
Nice=19
IOSchedulingClass=idle
KillSignal=SIGINT
ExecStart=/usr/bin/zpool scrub %i
[Install]
WantedBy=multi-user.target
SCRUB
# Pre and Post update backup hooks
cat >/etc/pacman.d/hooks/00-syu_pre.hook <<- pre
[Trigger]
Type = Path
Operation = Upgrade
Operation = Install
Operation = Remove
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/firmware/*
Target = usr/src/*/dkms.conf
[Action]
Description = Creating pre zroot snapshot...
When = PreTransaction
Exec = /usr/bin/bash -c 'zfs snapshot zroot/ROOT@pre-\$(cat /zfs/snapshot-syu)'
AbortOnFail
pre
cat >/etc/pacman.d/hooks/55-bootbackup_pre.hook <<- pre
[Trigger]
Operation = Upgrade
Operation = Install
Operation = Remove
Type = Path
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/firmware/*
Target = usr/src/*/dkms.conf
[Action]
Depends = rsync
Description = Backing up pre /boot...
When = PreTransaction
Exec = /usr/bin/bash -c 'mount /boot; rsync -a --mkpath --delete /boot/ "/.boot/\$(cat /zfs/snapshot-syu)_pre"/'
AbortOnFail
pre
cat >/etc/pacman.d/hooks/95-bootbackup_post.hook <<- post
[Trigger]
Operation = Upgrade
Operation = Install
Operation = Remove
Type = Path
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/firmware/*
Target = usr/src/*/dkms.conf
[Action]
Depends = rsync
Description = Backing up post /boot...
When = PostTransaction
Exec = /usr/bin/bash -c 'rsync -a --mkpath --delete /boot/ "/.boot/\$(cat /zfs/snapshot-syu)_post"/'
post
cat >/etc/pacman.d/hooks/zz-syu_post.hook <<- post
[Trigger]
Type = Path
Operation = Upgrade
Operation = Install
Operation = Remove
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/firmware/*
Target = usr/src/*/dkms.conf
[Action]
Description = Creating post zroot snapshot...
When = PostTransaction
Exec = /usr/bin/bash -c 'zfs snapshot zroot/ROOT@post-\$(cat /zfs/snapshot-syu)'
post
# Custom pacman wrapper
install /dev/stdin /opt/local/bin/syu <<- syu
#!/usr/bin/env bash
set -e
mirrorlist=
# Enable or disable pacman cache server
/opt/local/bin/cacheserver
# Fetch latest mirrors
sudo curl --fail --silent \${mirrorlist} -o /etc/pacman.d/mirrorlist
# Record current time
echo \$(date "+%Y-%m-%d-%H:%M:%S") >/zfs/snapshot-syu
# Check for new packages and continue if found
newpkg+=(\$(checkupdates --nocolor | awk '{print \$1}'))
if [ "\${newpkg}" ]
then
# Sync pacman dbs
sudo pacman --ask 4 -Sy >/dev/null
# Check zfs-linux kernel dependency
zfslinux=\$(pacman -Si zfs-${linux_kernel} | grep "Depends On" | sed "s|.*${linux_kernel}=||")
linux=\$(pacman -Si ${linux_kernel} | grep "Version" | awk '{print \$3}')
if [ \${zfslinux} != \${linux} ]
then
archzfs="--ignore zfs-utils,zfs-${linux_kernel},${linux_kernel}"
fi
# Update archlinux-keyring first
if [[ \${newpkg[@]} =~ "archlinux-keyring" ]]
then
sudo pacman --ask 4 -S archlinux-keyring
echo
fi
# Perform update if dependencies are satisfied
if sudo pacman --ask 4 -Syu \${archzfs} --needed
then
echo
sudo pacdiff
exit 0
fi
fi
syu
;;
*)
case ${filesystem} in
btrfs)
# Pre and post update backup hooks
cat >/etc/pacman.d/hooks/00-syu_pre.hook <<- pre
[Trigger]
Type = Path
Operation = Upgrade
Operation = Install
Operation = Remove
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/firmware/*
Target = usr/src/*/dkms.conf
[Action]
Depends = timeshift
Description = Creating pre root snapshot...
When = PreTransaction
Exec = /usr/bin/bash -c 'timeshift --create --comments "pre_\$(date "+%Y-%m-%d-%H:%M:%S")" >/dev/null'
AbortOnFail
pre
cat >/etc/pacman.d/hooks/55-bootbackup_pre.hook <<- pre
[Trigger]
Operation = Upgrade
Operation = Install
Operation = Remove
Type = Path
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/firmware/*
Target = usr/src/*/dkms.conf
[Action]
Depends = rsync
Description = Backing up pre /boot...
When = PreTransaction
Exec = /usr/bin/bash -c 'rsync -a --mkpath --delete --exclude 'header.img' /boot/ "/.boot/\$(date "+%Y-%m-%d-%H:%M:%S")_pre"/'
AbortOnFail
pre
cat >/etc/pacman.d/hooks/95-bootbackup_post.hook <<- post
[Trigger]
Operation = Upgrade
Operation = Install
Operation = Remove
Type = Path
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/firmware/*
Target = usr/src/*/dkms.conf
[Action]
Depends = rsync
Description = Backing up post /boot...
When = PostTransaction
Exec = /usr/bin/bash -c 'rsync -a --mkpath --delete --exclude 'header.img' /boot/ "/.boot/\$(date "+%Y-%m-%d-%H:%M:%S")_post"/'
post
cat >/etc/pacman.d/hooks/zz-syu_post.hook <<- post
[Trigger]
Type = Path
Operation = Upgrade
Operation = Install
Operation = Remove
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/firmware/*
Target = usr/src/*/dkms.conf
[Action]
Depends = timeshift
Description = Creating post root snapshot...
When = PostTransaction
Exec = /usr/bin/bash -c 'timeshift --create --comments "post_\$(date "+%Y-%m-%d-%H:%M:%S")" >/dev/null'
post
install /dev/stdin /usr/local/bin/timeshift-gui <<- 'timeshift'
#!/bin/sh
pkexec env WAYLAND_DISPLAY="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" XDG_RUNTIME_DIR=/run/user/0 timeshift-launcher
timeshift
;;
esac
# Custom pacman wrapper
install /dev/stdin /opt/local/bin/syu <<- syu
#!/usr/bin/env bash
set -e
mirrorlist=
# Enable or disable pacman cache server
/opt/local/bin/cacheserver
# Fetch latest mirrors
sudo curl --fail --silent \${mirrorlist} -o /etc/pacman.d/mirrorlist
# Check for new packages and continue if found
newpkg+=(\$(checkupdates --nocolor | awk '{print \$1}'))
if [ "\${newpkg}" ]
then
# Update archlinux-keyring first
if [[ \${newpkg[@]} =~ "archlinux-keyring" ]]
then
sudo pacman --ask 4 -S archlinux-keyring
echo
fi
# Perform update if dependencies are satisfied
if sudo pacman --ask 4 -Syu --needed
then
echo
sudo pacdiff
exit 0
fi
fi
syu
;;
esac
echo
# /opt/local/bin/cacheserver
install /dev/stdin /opt/local/bin/cacheserver <<- 'cacheserver'
#!/usr/bin/env bash
set -e
# Enable cacheserver if active
cacheserver=
port=
scheme=
if [ -z ${cacheserver} ]
then
exit 1
fi
if nc -z -4 -w 3 ${cacheserver} ${port:-80} >/dev/null 2>&1
then
if grep -q "CacheServer" /etc/pacman.conf
then
sudo sed "/CacheServer/ s/^\(#\)*//g" -i /etc/pacman.conf
else
sudo sed "/^\[core\]$\|^\[extra\]$\|^\[myvezfs\]$/a CacheServer = ${scheme:-http}://${cacheserver}:${port:-80}" -i /etc/pacman.conf
fi
else
sudo sed "/CacheServer/ s/^/#/g" -i /etc/pacman.conf
fi
cacheserver
if ls -l /dev/disk/* | grep -q 'VBOX\|virtio\|QEMU'
then
sed -e "/^cacheserver=/c cacheserver=192.168.122.1" \
-e "/^port=/c port=9090" \
-i /opt/local/bin/cacheserver
/opt/local/bin/cacheserver
fi
# mkinitcpio
say as heading 'Regenerating cpio image'
mkinitcpio -P
echo
# Install GRUB
if [[ ${arch} = [3567] ]]
then
say as heading 'Installing GRUB'
grub-install --target=x86_64-efi --bootloader-id="Arch Linux (${hostname})" --efi-directory=/boot/efi --recheck || die 'Grub installation failed'
grub-mkconfig -o /boot/grub/grub.cfg
echo
fi
# Sysctl custom settings
cat >/etc/sysctl.d/99-sysctl.conf <<- SYSCTL
net.core.netdev_max_backlog = 16384
net.core.somaxconn = 8192
net.core.rmem_default = 1048576
net.core.rmem_max = 16777216
net.core.wmem_default = 1048576
net.core.wmem_max = 16777216
net.core.optmem_max = 65536
net.ipv4.tcp_rmem = 4096 1048576 2097152
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_timestamps = 0
net.core.default_qdisc = cake
net.ipv4.tcp_congestion_control = bbr
vm.swappiness=10
vm.vfs_cache_pressure=50
SYSCTL
# iptables
cat >/etc/iptables/userinput.rules <<- IPTABLES
## User input
# SSH port
-A INPUT -p tcp -m tcp --dport ${port:-22} -j ACCEPT -m comment --comment "SSH Port"
## Simple Firewall
IPTABLES
sed "/OUTPUT ACCEPT/r /etc/iptables/userinput.rules" /etc/iptables/simple_firewall.rules >/etc/iptables/iptables.rules
# zram
echo 'zram' >/etc/modules-load.d/zram.conf
echo 'options zram num_devices=1' >/etc/modprobe.d/zram.conf
echo 'KERNEL=="zram0", ATTR{comp_algorithm}="lz4", ATTR{disksize}="512M" RUN="/usr/bin/mkswap /dev/zram0", TAG+="systemd"' >/etc/udev/rules.d/99-zram.rules
echo '/dev/zram0 none swap defaults 0 0' >>/etc/fstab
# Configure ssh and ssh_config.d/10-global.conf
ssh-keygen -q \
-t ed25519 \
-P "" \
-C "${USER}@${hostname}" \
-f ~/.ssh/id_ed25519
mkdir ~/.ssh/sockets/
cat >/etc/ssh/sshd_config.d/10-sshd.conf <<- sshd
PermitRootLogin no
PasswordAuthentication no
AuthenticationMethods publickey
sshd
cat >/etc/ssh/ssh_config.d/10-global.conf <<- 'sshconfig'
# Preferred ciphers
Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com
# Only use ipv4
AddressFamily inet
# Multiplex
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 10m
# Ease up on local area network devices
Host 192.168.*
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null
LogLevel Error
sshconfig
# Polkit
mkdir -p /etc/polkit-1/rules.d/
cat >/etc/polkit-1/rules.d/49-nopasswd_global.rules <<- 'polkit'
/* Allow members of the wheel group to execute any actions
* without password authentication, similar to "sudo NOPASSWD:"
*/
polkit.addRule(function(action, subject) {
if (subject.isInGroup("wheel")) {
return polkit.Result.YES;
}
});
polkit
# Persistent journal logging
mkdir -p /etc/systemd/journald.conf.d/
cat >/etc/systemd/journald.conf.d/zz-journald.conf <<- eof
[Journal]
Storage=persistent
eof
# makepkg
mkdir -p /etc/makepkg.conf.d/
cat >/etc/makepkg.conf.d/zz-makepkg.conf <<- makepkg
PKGEXT=".pkg.tar"
MAKEFLAGS="--jobs=$(nproc)"
COMPRESSZST=(zstd -c -T0 --auto-threads=logical -)
makepkg
# Virtual machine settings
if ls -l /dev/disk/* | grep -q 'VBOX\|virtio\|QEMU'
then
mv /etc/sudoers.d/.zz-NOPASSWD /etc/sudoers.d/zz-NOPASSWD
fi
##
## Hooks
##
# paccache
cat >/etc/pacman.d/hooks/zz-paccache.hook <<- paccache
[Trigger]
Operation = Upgrade
Operation = Install
Operation = Remove
Type = Package
Target = *
[Action]
Description = Cleaning pacman cache...
When = PostTransaction
Exec = /usr/bin/paccache --remove
paccache
# locale.gen.pacnew hook
install /dev/stdin /opt/local/hooks/localegen <<- hook
#!/usr/bin/env bash
if [ -f /etc/locale.gen.pacnew ]
then
sed '/#en_US.UTF-8 UTF-8/ s/#//' -i /etc/locale.gen.pacnew
mv /etc/locale.gen.pacnew /etc/locale.gen
locale-gen >/dev/null
fi
hook
# locale.gen.pacnew hook
cat >/etc/pacman.d/hooks/100-localegen.hook <<- localegen
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = glibc
[Action]
Description = Fixing locale.gen
When = PostTransaction
Exec = /opt/local/hooks/localegen
localegen
# iptables
cat >/etc/pacman.d/hooks/100-iptables.rules.hook <<iptables
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = iptables-nft
[Action]
Description = Fixing iptables rules
When = PostTransaction
Exec = /opt/local/hooks/iptables.rules
iptables
install /dev/stdin /opt/local/hooks/iptables.rules <<hook
#!/usr/bin/env bash
if [ -f /etc/iptables/iptables.rules.pacsave ]
then
sed "/OUTPUT ACCEPT/r /etc/iptables/userinput.rules" /etc/iptables/simple_firewall.rules >/etc/iptables/iptables.rules
rm /etc/iptables/iptables.rules.pacsave
fi
hook
su ${username} <<- "user"
curl --fail --silent https://git.myvelabs.com/lab/archlinux/raw/branch/master/functions/user -o /tmp/user
bash /tmp/user
user

670
functions/desktop Executable file
View file

@ -0,0 +1,670 @@
#!/usr/bin/env bash
revision='0.1f (feb 24/25)'
set -a
set -E
# Exit function
trap '[ "${?}" -ne 77 ] || exit 77' ERR
function die
{
if [ ${@} ]
then
echo
echo -e "\e[1;31mError encountered for the following reason:\e[0m
\e[33m${@}\e[0m
\e[1;31mScript aborted...\e[0m"
echo
else
echo
echo -e '\e[1;31mError encountered, script aborted...\e[0m'
echo
fi
exit 77
}
# Internet connection check
if nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || nc -z -w 1 google.com 443 >/dev/null 2>&1
then
sudo timedatectl set-ntp true
else
die 'No internet connectivity detected, plug in an ethernet cable or run \e[32miwd-connect\e[33m if using wifi and try again'
fi
totalde=21
cat <<- menu
$(tput setaf 5 bold)
Select a desktop$(tput sgr0)
$(tput smul setaf 7 dim)# none$(tput sgr0)
0) none
$(tput smul setaf 7 dim)# wayland$(tput sgr0)
1) sway
2) hyprland
3) qtile-wayland
4) river
5) plasma-wayland
6) gnome-wayland
7) cosmic
$(tput smul setaf 7 dim)# x11$(tput sgr0)
8) qtile-x11
9) bspwm
10) awesome
11) i3
12) i3-plasma
13) plasma-x11
14) gnome-x11
15) xfce4
16) budgie
17) cinnamon
18) deepin
19) mate
20) pantheon
21) cutefish
22) lxde
23) lxqt
menu
if [ ${1} ]
then
desktop=${1}
else
desktop=-1
fi
until [[ ${desktop} -ge 0 && ${desktop} -le ${totalde} ]]
do
read -p '> ' desktop
[[ ${desktop} -ge 0 && ${desktop} -le ${totalde} ]] ||\
echo -e "\n\n\e[1;31mInvalid selection, type an option from 0 to ${totalde}\e[0m"
done
# Configure btrfs
if findmnt / | grep -w -q btrfs
then
desktop_packages+=(btrfs-progs)
if pacman -Q | grep -q "^grub"
then
desktop_packages+=(grub-btrfs inotify-tools)
systemd_services+=(grub-btrfsd.service)
fi
# echo -e '\n\e[1;35mConfiguring snapper\e[0m'
# sudo pacman --sync --ask 4 snapper snap-pac
# echo
# sudo umount /.snapshots /home/.snapshots
# sudo rm -r /.snapshots /home/.snapshots
# sudo snapper -c root create-config /
# sudo snapper -c home create-config /home
# sudo sed -i 's/TIMELINE_LIMIT_HOURLY="10"/TIMELINE_LIMIT_HOURLY="4"/' /etc/snapper/configs/root
# sudo sed -i 's/TIMELINE_LIMIT_DAILY="10"/TIMELINE_LIMIT_DAILY="7"/' /etc/snapper/configs/root
# sudo sed -i 's/TIMELINE_LIMIT_MONTHLY="10"/TIMELINE_LIMIT_MONTHLY="1"/' /etc/snapper/configs/root
# sudo sed -i 's/TIMELINE_LIMIT_YEARLY="10"/TIMELINE_LIMIT_YEARLY="0"/' /etc/snapper/configs/root
# sudo sed -i 's/TIMELINE_CREATE="yes"/TIMELINE_CREATE="no"/' /etc/snapper/configs/home
# sudo btrfs subvolume delete /.snapshots
# sudo btrfs subvolume delete /home/.snapshots
# sudo mkdir -p --mode=750 /.snapshots /home/.snapshots
# sudo mount -a
# sudo systemctl --quiet enable --now snapper-cleanup.timer snapper-timeline.timer
# # Create snapshots for fresh installation
# sudo snapper -c root create --description "fresh install"
# sudo snapper -c home create --description "fresh install"
fi
# Assign DE variables
case ${desktop} in
0)
# TTY only
desktop_choice=none
echo
;;
*)
systemd_user_services+=(wireplumber.service pipewire-pulse.service pipewire.service)
desktop_packages+=(ttf-dejavu pipewire pipewire-audio pipewire-pulse pipewire-jack wireplumber)
case ${desktop} in
[1-7])
# Wayland
desktop_packages+=(wayland)
case ${desktop} in
1)
desktop_choice=sway
desktop_packages+=(sway seatd swaylock swayidle swaybg bemenu bemenu-wayland i3status foot kate dolphin konsole kompare kcalc breeze-icons kde-cli-tools brightnessctl gnome-keyring fakeroot qt5-wayland polkit-kde-agent)
systemd_services+=(seatd.service)
;;
2)
desktop_choice=hyprland
desktop_packages+=(hyprland uwsm swaylock swayidle bemenu bemenu-wayland waybar foot kate dolphin konsole kompare kcalc breeze-icons kde-cli-tools ttf-font-awesome brightnessctl gnome-keyring fakeroot qt5-wayland polkit-kde-agent)
systemd_user_services+=(foot-server.service)
;;
3)
desktop_choice=qtile-wayland
desktop_packages+=(qtile python-pywlroots xorg-xwayland foot)
systemd_user_services+=(foot-server.service)
;;
4)
desktop_choice=river
desktop_packages+=(river foot)
systemd_user_services+=(foot-server.service)
;;
5)
desktop_choice=plasma-wayland
desktop_packages+=($(pacman -Sgq plasma | grep -v 'discover\|oxygen\|plasma-nm') konsole foot kate dolphin kompare kcalc)
systemd_services+=(sddm.service)
systemd_user_services+=(foot-server.service)
;;
6)
desktop_choice=gnome-wayland
desktop_packages+=(gnome foot)
systemd_services+=(gdm.service)
systemd_user_services+=(foot-server.service)
;;
7)
desktop_choice=cosmic
desktop_packages+=(cosmic)
systemd_services+=(cosmic-greeter.service)
if ls -l /dev/disk/* | grep -q 'VBOX\|virtio\|QEMU'
then
desktop_packages+=(vulkan-virtio)
elif lspci | grep VGA | grep -q NVIDIA
then
desktop_packages+=(nvidia-utils)
elif lscpu | grep 'Model name:' | grep -q AMD
then
desktop_packages+=(amdvlk)
elif lscpu | grep 'Model name:' | grep -q Intel
then
desktop_packages+=(vulkan-intel)
fi
;;
esac
# Environment
sudo tee -a /etc/environment >/dev/null <<- environment
QT_QPA_PLATFORM=wayland
environment
;;
*)
# Xorg
desktop_packages+=(xorg)
case ${desktop} in
8)
desktop_choice=qtile-x11
desktop_packages+=(qtile xorg-xinit konsole)
;;
9)
desktop_choice=bspwm
desktop_packages+=(bspwm sxhkd xorg-xinit polybar konsole)
;;
10)
desktop_choice=awesome
desktop_packages+=(awesome xorg-xinit konsole)
;;
11)
desktop_choice=i3
desktop_packages+=(i3-wm i3status i3lock dmenu lightdm lightdm-gtk-greeter pavucontrol konsole kate dolphin kompare breeze-icons)
systemd_services+=(lightdm.service)
;;
12)
desktop_choice=i3-plasma
desktop_packages+=($(pacman -Sgq plasma | grep -v 'discover\|oxygen\|plasma-nm') konsole kate dolphin kompare kcalc i3-wm i3status dmenu wmctrl feh)
systemd_services+=(sddm.service)
;;
13)
desktop_choice=plasma-x11
desktop_packages+=($(pacman -Sgq plasma | grep -v 'discover\|oxygen\|plasma-nm') konsole kate dolphin kompare kcalc)
systemd_services+=(sddm.service)
;;
14)
desktop_choice=gnome-x11
desktop_packages+=(gnome)
systemd_services+=(gdm.service)
;;
15)
desktop_choice=xfce4
desktop_packages+=(xfce4 lightdm lightdm-gtk-greeter)
systemd_services+=(lightdm.service)
;;
16)
desktop_choice=budgie
desktop_packages+=(budgie lightdm lightdm-gtk-greeter tilix)
systemd_services+=(lightdm.service)
;;
17)
desktop_choice=cinnamon
desktop_packages+=(cinnamon lightdm lightdm-gtk-greeter gnome-console)
systemd_services+=(lightdm.service)
;;
18)
desktop_choice=deepin
desktop_packages+=(deepin deepin-kwin $(pacman -Sgq deepin-extra | grep -v deepin-reader) lightdm lightdm-gtk-greeter gnome-keyring)
systemd_services+=(lightdm.service)
if uname -r | grep -q 'lts\|hardened\|zen'
then
desktop_packages+=(deepin-anything-dkms)
else
desktop_packages+=(deepin-anything-arch)
fi
;;
19)
desktop_choice=mate
desktop_packages+=(mate mate-extra lightdm lightdm-gtk-greeter)
systemd_services+=(lightdm.service)
;;
20)
desktop_choice=pantheon
desktop_packages+=(pantheon lightdm-pantheon-greeter lightdm)
systemd_services+=(lightdm.service)
;;
21)
desktop_choice=cutefish
desktop_packages+=(cutefish sddm)
systemd_services+=(sddm.service)
;;
22)
desktop_choice=lxde
desktop_packages+=(lxde lxdm)
systemd_services+=(lxdm.service)
;;
23)
desktop_choice=lxqt
desktop_packages+=(lxqt sddm breeze-icons)
systemd_services+=(sddm.service)
;;
esac
;;
esac
echo
echo -e "\t\e[1mYou have chosen \e[32m${desktop_choice}\e[0m\e[1m desktop\e[0m"
echo
echo -e '\e[1;35mInstalling base packages\e[0m'
sudo pacman --sync --ask 4 ${desktop_packages[@]} || die 'Failed to install required packages'
echo
;;
esac
case ${desktop_choice} in
plasma-wayland)
mkdir -p ~/.config/{autostart-scripts,foot}/
# install /dev/stdin ~/.config/autostart-scripts/foot.sh <<- foot
# #!/bin/sh
# foot --server
# foot
cat >>~/.config/kglobalshortcutsrc <<- shortcuts
[services][footclient.desktop]
_launch=Alt+Return
[services][org.kde.konsole.desktop]
_launch=none
shortcuts
;;
gnome-wayland)
mkdir -p ~/.config/{autostart,foot}/
# cat > ~/.config/autostart/foot-server.desktop <<- foot
# [Desktop Entry]
# Type=Application
# Name=Foot server
# Exec=foot --server
# foot
gsettings set $(gsettings list-schemas | grep terminal) exec footclient
;;
cosmic)
mkdir -p ~/.config/foot/
;;
i3|i3-plasma)
# i3-config
mkdir -p ~/.config/i3/
curl --fail -s -L https://raw.githubusercontent.com/i3/i3/next/etc/config | sed 's/exec i3-config-wizard/# &/' > ~/.config/i3/config
case ${desktop_choice} in
i3-plasma)
kwriteconfig6 --file startkderc --group General --key systemdBoot false
sudo install /dev/stdin /opt/local/bin/plasma-i3.sh <<- EOF
#!/usr/bin/env bash
export KDEWM=/usr/bin/i3
/usr/bin/startplasma-x11
EOF
sudo tee /usr/share/xsessions/plasma-i3.desktop >/dev/null <<- EOF
[Desktop Entry]
Type=XSession
Exec=/opt/local/bin/plasma-i3.sh
DesktopNames=KDE
Name=Plasma (i3)
Comment=KDE Plasma with i3 as the WM
EOF
;;
esac
if ls -l /dev/disk/* | grep -q 'VBOX\|virtio\|QEMU'
then
cat >> ~/.config/i3/config <<- 'i3'
exec xrandr --output $(xrandr -q | grep -w 'connected primary' | awk '{print $1}') --mode 1920x1080
exec xrandr --dpi 192
exec spice-vdagent
exec VBoxClient-all
i3
fi
;;
qtile-x11)
echo 'exec qtile start' >~/.xinitrc
cat >> ~/.bash_profile <<- 'autostart'
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = 1 ]
then
exec startx
fi
autostart
;;
qtile-wayland)
mkdir -p ~/.config/foot/
cat >> ~/.bash_profile <<- 'autostart'
# Start sway on login from tty
if [ -z "${WAYLAND_DISPLAY}" ] && [ "${XDG_VTNR}" = 1 ]
then
exec qtile start -b wayland
fi
autostart
;;
river)
mkdir -p ~/.config/foot/
cat >> ~/.bash_profile <<- 'autostart'
# Start sway on login from tty
if [ -z "${WAYLAND_DISPLAY}" ] && [ "${XDG_VTNR}" = 1 ]
then
exec river
fi
autostart
;;
bspwm)
cat >> ~/.bash_profile <<- 'autostart'
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = 1 ]
then
exec startx /usr/bin/bspwm
fi
autostart
mkdir -p ~/.config/{bspwm,sxhkd,polybar}/
install -Dm755 /usr/share/doc/bspwm/examples/bspwmrc ~/.config/bspwm/bspwmrc
install -Dm644 /usr/share/doc/bspwm/examples/sxhkdrc ~/.config/sxhkd/sxhkdrc
cp /etc/polybar/config.ini ~/.config/polybar/
;;
awesome)
cat >> ~/.bash_profile <<- 'autostart'
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = 1 ]
then
exec startx /usr/bin/awesome
fi
autostart
mkdir -p ~/.config/awesome/
sed -e '/^terminal =/c terminal = "konsole"' \
-e '/^modkey =/c modkey = "Mod1"' /etc/xdg/awesome/rc.lua > ~/.config/awesome/
;;
sway)
# Sway
sudo gpasswd -a ${USER} seat >/dev/null
# Dolphin default apps
mkdir -p ~/.config/menus/
curl --fail -s -L https://raw.githubusercontent.com/KDE/plasma-workspace/master/menu/desktop/plasma-applications.menu -o ~/.config/menus/applications.menu
kbuildsycoca6 >/dev/null 2>&1
# Dolphin default terminal
cat >> ~/.config/kdeglobals <<- foot
[General]
TerminalApplication=footclient
foot
# Create conf directories
mkdir -p ~/.config/{sway/config.d,foot}/
# Identify conf locations
cat > ~/.config/sway/config <<- 'config'
include /etc/sway/config.d/*
include ~/.config/sway/config.d/*
config
# Default sway config
sed -e 's/mod Mod4/mod Mod1/' \
-e 's/term foot/&client/' \
-e '/set $menu/c set $menu bemenu-run -p "" --no-overlap --tb "#285577" --hb "#285577" --tf "#eeeeee" --hf "#eeeeee" --nf "#bbbbbb"' \
/etc/sway/config > ~/.config/sway/config.d/00-config
sed -n "/^# Status Bar:$/q;p" -i ~/.config/sway/config.d/00-config
# Sway config
cat > ~/.config/sway/config.d/zz-sway <<- 'config'
# Disable xwayland
xwayland disable
# Start foot terminal server
exec foot --server
# Use i3status
bar {
status_command i3status
}
# Floating windows
for_window [window_role="About"] floating enable
for_window [window_role="Organizer"] floating enable
for_window [window_role="Preferences"] floating enable
for_window [window_role="bubble"] floating enable
for_window [window_role="page-info"] floating enable
for_window [window_role="pop-up"] floating enable
for_window [window_role="task_dialog"] floating enable
for_window [window_role="toolbox"] floating enable
for_window [window_role="webconsole"] floating enable
for_window [window_type="dialog"] floating enable
for_window [window_type="menu"] floating enable
# Floating for KCalc
for_window [title="KCalc"] floating enable
# Bind keys for brightness
bindsym XF86MonBrightnessDown exec brightnessctl set 5%-
bindsym XF86MonBrightnessUp exec brightnessctl set 5%+
# Mouse and keyboard defaults
input type:keyboard xkb_numlock enabled
input type:touchpad {
tap enabled
natural_scroll enabled
}
config
# Display config
cat > ~/.config/sway/config.d/zz-display <<- 'display'
# # Declare output
# set $laptop eDP-1 (swaymsg -t get_outputs)
# Swayidle
exec swayidle -w \
timeout 300 'swaylock -e -f -c 000000' \
timeout 315 'swaymsg "output * power off"' \
resume 'swaymsg "output * power on"' \
timeout 600 'systemctl suspend' \
before-sleep 'swaylock -e -f -c 000000'
# Laptop lid switches
bindswitch --reload --locked lid:on output * disable
bindswitch --reload --locked lid:off output * enable
# Swaylock
bindsym Mod4+l exec swaylock -e -f -c 000000
# Solid black background
output * bg #000000 solid_color
# Prevent swayidle when a window is in fullscreen
for_window [class=".*"] inhibit_idle fullscreen
for_window [app_id=".*"] inhibit_idle fullscreen
display
# Polkit
cat > ~/.config/sway/config.d/zz-polkit <<- 'polkit'
exec "/usr/lib/polkit-kde-authentication-agent-1"
polkit
# Monitor
if ls -l /dev/disk/* | grep -q 'VBOX\|virtio\|QEMU'
then
cat > ~/.config/sway/config.d/zz-virtualmonitor <<- 'monitor'
# Virtual monitor
output Virtual-1 {
pos 0,0
mode 1920x1080@60Hz
scale 1.25
}
monitor
fi
# TTY sway autostart
cat >> ~/.bash_profile <<- 'sway'
# Start sway on login from tty
if [ -z "${WAYLAND_DISPLAY}" ] && [ "${XDG_VTNR}" = 1 ]
then
exec sway
fi
sway
;;
hyprland)
# Hyprland
mkdir -p ~/.config/{menus,hypr/scripts,foot,waybar}/
# Dolphin default apps
curl --fail -s -L https://raw.githubusercontent.com/KDE/plasma-workspace/master/menu/desktop/plasma-applications.menu -o ~/.config/menus/applications.menu
kbuildsycoca6 >/dev/null 2>&1
# Dolphin default terminal
cat >> ~/.config/kdeglobals <<- foot
[General]
TerminalApplication=footclient
foot
# Swayidle
install /dev/stdin ~/.config/hypr/scripts/sleep.sh <<- 'swayidle'
swayidle -w timeout 300 'swaylock -f -c 000000' \
timeout 600 'systemctl suspend' \
before-sleep 'swaylock -f -c 000000' &
swayidle
# Config
curl --silent --fail https://raw.githubusercontent.com/hyprwm/Hyprland/refs/heads/main/example/hyprland.conf |\
sed -e '/Autostart/i exec-once = /usr/lib/polkit-kde-authentication-agent-1' \
-e '/Autostart/i exec-once = waybar -c ~/.config/waybar/waybar.conf' \
-e '/Autostart/i exec-once = ~/.config/hypr/scripts/sleep.sh' \
-e '/^$terminal =/c $terminal = footclient' \
-e '/gaps_in =/c gaps_in = 0' \
-e '/gaps_out =/c gaps_out = 0' \
-e '/^$menu =/c $menu = bemenu-run -p "" --no-overlap --tb "##285577" --hb "##285577" --tf "##eeeeee" --hf "##eeeeee" --nf "##bbbbbb"' \
-e 's/bind = $mainMod, R, exec, $menu/bind = $mainMod, D, exec, $menu/' \
-e 's/bind = $mainMod, Q, exec, $terminal/bind = $mainMod, RETURN, exec, $terminal/' \
-e 's/bind = $mainMod, C, killactive/bind = $mainMod SHIFT, Q, killactive/' \
-e '/$mainMod =/c $mainMod = ALT' \
-e '/RETURN/a bind = SUPER, L, exec, swaylock -e -f -c 000000' \
> ~/.config/hypr/hyprland.conf
# -e '/Autostart/i exec-once = uwsm app -- foot --server' \
# QEMU monitor
if ls -l /dev/disk/* | grep -q 'VBOX\|virtio\|QEMU'
then
sed -i "/^monitor/c monitor = $(hyprctl monitors all | grep "^Monitor" | awk '{print $2}'), 1920x1080@60, 0x0, 1.5" ~/.config/hypr/hyprland.conf
fi
# Waybar
sed -e 's|sway/workspaces|sway/workspaces|g' \
-e 's|sway/mode|hyprland/submap|g' \
-e '/position/ s|//||' \
/etc/xdg/waybar/config.jsonc > ~/.config/waybar/waybar.conf
# TTY sway autostart
cat >> ~/.bash_profile <<- 'hyprland'
# Start sway on login from tty
if uwsm check may-start
then
exec uwsm start hyprland.desktop
fi
hyprland
;;
esac
# Foot terminal config (/etc/xdg/foot/foot.ini)
if [ -d ~/.config/foot/ ]
then
cat > ~/.config/foot/foot.ini <<- 'foot'
[main]
include=/usr/share/foot/themes/kitty
font=Source Code Pro:size=12
workers=32
[scrollback]
# lines=1000
foot
fi
# Add user to shared folder group if in virtualbox guest
if ls -l /dev/disk/* | grep -q VBOX
then
sudo gpasswd -a ${USER} vboxsf >/dev/null
echo
fi
# iwd status function
if pacman -Q | grep -w -q iwd
then
cat > ~/.local/functions/iwd-status <<- iwd
#!/usr/bin/env bash
# iwd connection status
function iwd-status
{
iwctl station "$(iwctl station list | grep connected | awk '{print $(NF-1)}')" show
}
alias iwctl='iwctl station $(iwctl station list | grep connected | awk '{print $(NF-1)}')'
iwd
fi
if [[ "${desktop_choice}" == "none" ]]
then
sudo rm -f ${0}
echo -e '\e[1;34mSetup complete, press any key to continue\e[5m...\e[0m\n'
read -n 1 -s -p ''
elif ls /usr/share/*sessions | grep -q desktop
then
install /dev/stdin ~/.local/bin/startup <<- 'EOF'
#!/usr/bin/env bash
# Internet connection check
if nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || nc -z -w 1 google.com 443 >/dev/null 2>&1
then
vim ~/.local/bin/startupscript
~/.local/bin/startupscript
rm -f ${0}
exit 0
else
echo -e '\n\e[31mNo internet connectivity detected'
echo -e 'Connect to a network and try again'
echo -e 'Aborting installer...\e[0m\n'
exit 1
fi
EOF
install /dev/stdin ~/.local/bin/startupscript <<- EOF
$(curl --fail --silent https://git.myvelabs.com/lab/archlinux/raw/branch/master/functions/startup)
EOF
sudo rm -f ${0}
echo -e '\e[1;34mDesktop installed, press any key to load '${desktop_choice}'\e[5m...\e[0m'
read -n 1 -s -p ''
echo
else
die 'Something does not feel right'
fi
# Systemd services
for service in ${systemd_user_services[@]}
do
systemctl --quiet --user enable --now ${service}
done
sudo systemctl --quiet enable --now ${systemd_services[@]}

297
functions/startup Executable file
View file

@ -0,0 +1,297 @@
#!/usr/bin/env bash
# AUR package list
aur_list=(
# nomachine
# realvnc-vnc-viewer
# jdownloader2
# ledger-live-bin
# czkawka-gui-bin
)
# Optional packages list
optional=(
firefox firefox-decentraleyes firefox-ublock-origin
ark okular shotwell mpv ffmpegthumbs
veracrypt keepassxc
# nextcloud-client
# ntfs-3g exfatprogs
# libreoffice-fresh
# remmina libvncserver
# torbrowser-launcher
# thunderbird
# filezilla
# chromium
# vlc
# gnome-disk-utility
# xdg-user-dirs
# noto-fonts-cjk
# noto-fonts-emoji
)
function INSTALL
{
sudo pacman --sync ${@} --ask 4
echo
}
# VirtualBox
until [[ ${install_virtualbox} = [yYnN] ]]
do
read -n 1 -p $'\n\e[1mWould you like to install Virtualbox? (y/n): \e[0m' install_virtualbox
[[ ${install_virtualbox} = [yYnN] ]] || echo -e -n '\n\n\e[1;31mNot a valid answer, type "y" or "n"\e[0m'
done
echo
# QEMU
until [[ ${install_qemu} = [yYnN] ]]
do
read -n 1 -p $'\n\e[1mWould you like to install QEMU? (y/n): \e[0m' install_qemu
[[ ${install_qemu} = [yYnN] ]] || echo -e -n '\n\n\e[1;31mNot a valid answer, type "y" or "n"\e[0m'
done
echo
echo
# Package groups installation
INSTALL ${optional[@]}
# Remmina
if [[ ${optional[@]} =~ "remmina" ]] && [ -d ~/.config/sway/config.d/ ]
then
# Remmina passthrough
cat > ~/.config/sway/config.d/zz-remmina <<- 'remmina'
# VNC passthrough
mode remmina {
bindsym Mod4+Shift+p mode default
}
bindsym Mod4+Shift+p mode remmina
remmina
fi
# Tor
if [[ ${optional[@]} =~ "torbrowser-launcher" ]]
then
torbrowser-launcher
fi
# Bluetooth
if pacman -Q | grep -q bluez-utils
then
INSTALL bluedevil
sudo systemctl --quiet enable --now bluetooth.service
fi
# AUR packages
if [ ${#aur_list[@]} -gt 0 ]
then
if ! pacman -Q | grep -q -w git
then
INSTALL git
fi
echo -e '#!/usr/bin/env bash' > ~/.local/functions/aur-packages
for aur_package in ${aur_list[@]}
do
cd
git clone https://aur.archlinux.org/${aur_package}.git
if echo ${aur_package} | grep -q nomachine
then
sed -i 's/_autoservice=n/_autoservice=y/' nomachine/PKGBUILD
sed -i 's/_autofirewall=n/_autofirewall=y/' nomachine/PKGBUILD
fi
cd ${aur_package}/
makepkg -csi
echo
cd ..
rm -r ${aur_package}/ -f
cat >> ~/.local/functions/aur-packages <<- aur
function aur-${aur_package}
{
cd ~/
git clone https://aur.archlinux.org/${aur_package}.git
cd ${aur_package}/
makepkg -csi
echo
cd ~/
rm -r ${aur_package}/ -f
}
aur
done
fi
# Optional AUR extras
# freefilesync
# pdfsam
# fslint pygtk
# Printers
# yay -S --ask 4 print-manager cups system-config-printer skanlite && echo && sudo systemctl --quiet enable --now org.cups.cupsd && sudo gpasswd -a ${USER} sys >/dev/null
# Webcam
# sudo gpasswd -a ${USER} video >/dev/null
# i3
if [ -f ~/.config/i3/config ]
then
cat >> ~/.config/i3/config <<- 'config'
# gaps inner 8
# gaps outer 4
# for_window [class="^.*"] border pixel 2
config
cat > ~/.local/functions/i3-config <<- 'config'
#!/usr/bin/env bash
# i3 config
function i3-config
{
vim ~/.config/i3/config
}
config
if [ -f /usr/share/xsessions/plasma-i3.desktop ]
then
tee -a ~/.config/i3/config >/dev/null <<- 'integration'
# >>> Plasma Integration <<<
# Try to kill the wallpaper set by Plasma (it takes up the entire workspace and hides everything)
exec --no-startup-id wmctrl -c Plasma
for_window [title="Desktop — Plasma"] kill; floating enable; border none
no_focus [class=”plasmashell”]
# Avoid tiling popups, dropdown windows from plasma
for_window [class="plasmashell"] floating enable
for_window [class="Plasma"] floating enable
for_window [class="krunner"] floating enable
for_window [class="Kmix"] floating enable
for_window [class="Klipper"] floating enable
for_window [class="Plasmoidviewer"] floating enable
# >>> Window Rules <<<
# >>> Avoid tiling for non-Plasma stuff <<<
for_window [window_role="pop-up"] floating enable
for_window [window_role="bubble"] floating enable
for_window [window_role="task_dialog"] floating enable
for_window [window_role="Preferences"] floating enable
for_window [window_role="About"] floating enable
for_window [window_type="dialog"] floating enable
for_window [window_type="menu"] floating enable
integration
install /dev/stdin ~/.local/bin/rotate-wallpapers <<- feh
#!/usr/bin/env bash
sleep 1
while true
do
feh --bg-max --randomize /home/${USER}/Pictures
sleep 15
done
feh
else
if ls -l /dev/disk/* | grep -q 'VBOX'
then
echo 'exec VBoxClient-all' >> ~/.config/i3/config
elif ls -l /dev/disk/* | grep -q 'virtio\|QEMU'
then
echo 'exec spice-vdagent' >> ~/.config/i3/config
fi
fi
fi
# Sway nextcloud
if [[ ${optional[@]} =~ "nextcloud-client" ]] && [ -f ~/.config/sway/config.d/zz-sway ]
then
cat > ~/.config/sway/config.d/zz-nextcloud <<- 'nextcloud'
# Nextcloud
exec nextcloud
for_window [title="Nextcloud Settings"] floating enable
nextcloud
fi
# Virtualbox
if [[ ${install_virtualbox} = [yY] ]]
then
echo 'Installing Virtualbox'
if uname -r | grep -q 'lts\|hardened\|zen'
then
host_modules='virtualbox-host-dkms'
else
host_modules='virtualbox-host-modules-arch'
fi
INSTALL virtualbox ${host_modules} virtualbox-guest-iso
echo
sudo gpasswd -a ${USER} vboxusers >/dev/null
echo
if findmnt '/' | grep -q -w 'btrfs'
then
mkdir ~/VirtualBox\ VMs/
chattr +C ~/VirtualBox\ VMs/
fi
fi
# QEMU
if [[ ${install_qemu} = [yY] ]]
then
echo 'Installing QEMU'
INSTALL qemu-desktop virt-manager edk2-ovmf \
dnsmasq dmidecode vde2 bridge-utils
echo
# Make host system a pacman cache server
sudo tee /etc/systemd/system/local-cacheserver.service >/dev/null <<- 'CACHESERVER'
[Unit]
Description=Python HTTP server for Pacman Cache Server
[Service]
ExecStart=/usr/bin/python3 -m http.server --directory /var/cache/pacman/pkg/ 9090
Restart=always
[Install]
WantedBy=multi-user.target
CACHESERVER
# Host iptables rules as a pacman cache server
sudo iptables -I INPUT -s 192.168.0.0/16 -p tcp -m tcp --dport 9090 -j ACCEPT -m comment --comment "Pacman cache server"
sudo sed -i '/## Simple Firewall/i\
# Pacman cache server\
-A INPUT -s 192.168.0.0/16 -p tcp -m tcp --dport 9090 -j ACCEPT -m comment --comment "Pacman cache server"\n' \
/etc/iptables/userinput.rules
sed "/OUTPUT ACCEPT/r /etc/iptables/userinput.rules" /etc/iptables/simple_firewall.rules | sudo tee /etc/iptables/iptables.rules >/dev/null
# QEMU pacman cache service
sudo tee /etc/systemd/system/local-update-virtpkg-cache.service >/dev/null <<- 'service'
[Unit]
Description=Refresh package cache twice daily
[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c "/usr/bin/pacman -Syw -d --ask 4 $(curl --fail -s -L https://git.myvelabs.com/lab/archlinux/raw/branch/master/pkg/qemu)"
service
# QEMU pacman cache timer
sudo tee /etc/systemd/system/local-update-virtpkg-cache.timer >/dev/null <<- 'timer'
[Unit]
Description=Refresh pacman package cache
[Timer]
OnCalendar=*-*-* 00/12:00:00
RandomizedDelaySec=12h
Persistent=true
[Install]
WantedBy=timers.target
timer
# Enable services
sudo systemctl --quiet enable --now libvirtd.service
sudo systemctl --quiet enable local-cacheserver.service local-update-virtpkg-cache.timer
sudo virsh -q net-start default
sudo virsh -q net-autostart default
sudo gpasswd -a ${USER} libvirt >/dev/null
echo
fi
rm -f ${0}
echo -e '\e[1;32mSupplementary installer completed, reboot one last time\e[0m\n'

110
functions/user Executable file
View file

@ -0,0 +1,110 @@
#!/usr/bin/env bash
revision=0.1a
set -a
set -E
# Create local paths
mkdir -p ~/.local/{bin,functions}
# Generate ssh identity
ssh-keygen -q \
-t ed25519 \
-P "" \
-C "${username}@${hostname}" \
-f ~/.ssh/id_ed25519
mkdir ~/.ssh/sockets/
# Custom bashrc
cat > ~/.local/functions/bashrc <<- 'BASHRC'
#!/usr/bin/env bash
# Shell color
PS1="$(tput setaf 6)[\u@\h \W \$?]\$ $(tput sgr0)"
# Colored prompts
alias ll='ls --color=auto -l -a -h'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
BASHRC
# Btrfs functions
if findmnt / | grep -w -q btrfs
then
cat > ~/.local/functions/btrfs <<- 'btrfs'
#!/usr/bin/env bash
# Btrfs check
function btrfs-check
{
sudo dmesg | grep -i btrfs
}
# # Snapper
# function snapshot-home
# {
# if [ "${*}" ]
# then
# sudo snapper -c home create --description "${*}"
# else
# sudo snapper -c home create --description "$(date)"
# fi
# }
#
# function snapshot-root
# {
# if [ "${*}" ]
# then
# sudo snapper -c root create --description "${*}"
# else
# sudo snapper -c root create --description "$(date)"
# fi
# }
#
# function snapshot-list
# {
# sudo -v
# echo -e '\n\e[1;33mRoot snapshots:\e[0m'
# sudo snapper -c root ls
# echo -e '\n\e[1;33mHome snapshots:\e[0m'
# sudo snapper -c home ls
# echo
# }
#
# function snapshot-delete
# {
# if ! grep -w -q 'root\|home' <<< "${1}" || [ -z "${2}" ]
# then
# echo -e '\n\t\e[1;31mInvalid option, use syntax: ${root,home} $snapshot\e[0m\n'
# return 1
# elif grep -w -q '1' <<< "${2}"
# then
# echo -e '\n\t\e[1;31mUnable to delete "fresh install" snapshot\e[0m\n'
# return 1
# fi
#
# if [[ "${1}" = "root" ]]
# then
# if ls /.snapshots | grep -q $(sed -e 's/-/\\\|/g' <<< "${2}")
# then
# sudo snapper -c root delete "${2}"
# elif ! [ -d /.snapshots/"${2}" ]
# then
# echo -e '\n\t\e[1;31mSnapshot doesn't exist, try again\e[0m\n'
# fi
# elif [[ "${1}" = "home" ]]
# then
# if ls /home/.snapshots | grep -q $(sed -e 's/-/\\\|/g' <<< "${2}")
# then
# sudo snapper -c home delete "${2}"
# elif ! [ -d /home/.snapshots/"${2}" ]
# then
# echo -e '\n\t\e[1;31mSnapshot doesn't exist, try again\e[0m\n'
# fi
# fi
# }
btrfs
fi
if pacman -Q | grep -q yubikey
then
install /dev/stdin ~/yksetup.sh <<- 'yubikey'
$(curl --fail --silent https://git.myvelabs.com/lab/archlinux/raw/branch/master/functions/yubikey)
yubikey
fi

86
functions/yubikey Executable file
View file

@ -0,0 +1,86 @@
#!/usr/bin/env bash
echo
[ -d ~/.config/Yubico ] || mkdir -p ~/.config/Yubico
sudo pacman -S --ask 4 pam-u2f yubico-pam
read -n 1 -s -p $'\n\e[1;33mInsert your yubikey and press the enter key to continue \e[0m'
echo -e '\n\e[1mTouch the yubikey when it starts blinking\e[0m'
pamu2fcfg > ~/.config/Yubico/u2f_keys
read -n 1 -p $'\n\e[1mWould you like to add another yubikey? (y/n): \e[0m' YUBIKEY
until [[ "$YUBIKEY" = [nN] ]]
do
if [[ "$YUBIKEY" != [yYnN] ]]
then
echo -e '\n\n\e[1;31mNot a valid answer, type "y" or "n"\e[0m'
read -n 1 -p $'\e[1mWould you like to add another yubikey? (y/n): \e[0m' YUBIKEY
elif [[ "$YUBIKEY" = [yY] ]]
then
read -n 1 -s -p $'\n\n\e[1;33mInsert the next yubikey and press the enter key to continue \e[0m'
echo -e '\n\e[1mTouch the yubikey when it starts blinking\e[0m'
pamu2fcfg -n >> ~/.config/Yubico/u2f_keys
read -n 1 -p $'\n\e[1mWould you like to add another yubikey? (y/n): \e[0m' YUBIKEY
fi
done
echo -e '\n\n\e[1;33mUpdating pam configs'
echo -e 'Open another terminal or tty and login as sudo in case an issue comes up'
read -n 1 -s -p $'Press the enter key once logged in as sudo in another terminal or tty \e[0m\n'
# System wide user authentication
sudo sed -i '/^auth .* required .* pam_faillock.so .* authsucc/a\
auth required pam_u2f.so' /etc/pam.d/system-auth
# Polkit authentication
sudo sed -i '/^#%PAM.*/a\
auth sufficient pam_u2f.so' /etc/pam.d/polkit-1
# Sudo authentication
sudo sed -i '/^#%PAM.*/a\
auth sufficient pam_u2f.so' /etc/pam.d/sudo
# KDE lockscreen authentication
sudo sed -i '/^#%PAM.*/a\
auth required pam_u2f.so' /etc/pam.d/kde
cat > ~/.local/functions/add-yubikey <<- 'ADDYUBIKEY'
# Add a new yubikey
function add-yubikey
{
read -n 1 -s -p $'\n\e[1;33mInsert your yubikey and press the enter key to continue \e[0m'
echo -e '\n\e[1mTouch the yubikey when it starts blinking\e[0m'
pamu2fcfg -n >> ~/.config/Yubico/u2f_keys
read -n 1 -p $'\n\e[1mWould you like to add another yubikey? (y/n): \e[0m' YUBIKEY
until [[ "$YUBIKEY" = [nN] ]]
do
if [[ "$YUBIKEY" != [yYnN] ]]
then
echo -e '\n\n\e[1;31mNot a valid answer, type "y" or "n"\e[0m'
read -n 1 -p $'\e[1mWould you like to add another yubikey? (y/n): \e[0m' YUBIKEY
elif [[ "$YUBIKEY" = [yY] ]]
then
read -n 1 -s -p $'\n\n\e[1;33mInsert the next yubikey and press the enter key to continue \e[0m'
echo -e '\n\e[1mTouch the yubikey when it starts blinking\e[0m'
pamu2fcfg -n >> ~/.config/Yubico/u2f_keys
read -n 1 -p $'\n\e[1mWould you like to add another yubikey? (y/n): \e[0m' YUBIKEY
fi
done
echo -e '\n\n\e[1;34mYubikeys updated'
echo -e 'Exiting...\e[0m\n'
}
ADDYUBIKEY
echo -e '\n\e[1;34mYubikey setup completed'
echo -e 'To update your saved yubikeys, run "add-yubikey" in the terminal'
echo -e 'Exiting...\e[0m\n'
rm -f ${0}

2315
homelab.sh Executable file

File diff suppressed because it is too large Load diff

67
installer.sh Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/env bash
download_url=git.myvelabs.com/lab/archlinux/raw/branch/master
# Detect network connectivity
if ! nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || ! nc -z -w 1 google.com 443 >/dev/null 2>&1
then
echo -e '\n\t\e[31mNo internet connection detected\e[0m\n'
exit 1
fi
# Function to list available script options
function listScripts
{
echo -e '\n\e[1;36mSelect a script to run\e[0m
1) Arch Linux
2) Arch Linux VM
3) Arch Linux Passthrough
4) Arch Linux Server
5) Recovery'
while true
do
read -n 1 -p '> ' script_selection
case ${script_selection} in
1) script=arch
break;;
2) script=virtual-machine
break;;
3) script=passthrough
break;;
4) script=homelab
break;;
5) script=recover
break;;
*) echo -e '\n\n\e[1;31mInvalid selection, type an option from 1 to 5\e[0m'
;;
esac
done
echo
}
# Detect script choice
case ${1} in
arch)
script=arch ;;
vm|virtual-machine)
script=virtual-machine ;;
passthrough)
script=passthrough ;;
server|homelab)
script=homelab ;;
recover)
script=recover ;;
*)
listScripts ;;
esac
# Run script if successful, abort installer otherwise
if curl --fail -s -L https://${download_url}/${script}.sh -o ./arch
then
/usr/bin/bash ./arch "${@:2}"
exit 0
else
echo -e '\e[31mInvalid script or server may be offline, make another selection or try again later\e[0m\n'
exit 1
fi

1582
notes/archvps.sh Executable file

File diff suppressed because it is too large Load diff

12
notes/sshkeys.pub Normal file
View file

@ -0,0 +1,12 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHGQ2rLYB6U2i3dyb1+Fn8fKSsfsTno87Vf++yFQkD2k user@zenbook
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPJnaY1RtJ+JdfAEJfUcO99yrSGuH0UQit0itzrpgeI user@dotfiles
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA5Zwmxt3kTIZT9fsQW+NCcTRYFz97Qp+hXbj7AcJXi6 root@mini
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIES0RiFcV2yoLwNrK6iB3xU3OlQ85vAWgxjoNaG3iuMp root@phone
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDUz2KdC9MWYLwYgGfjdxPGd0XZbdRLUJog4IbWp9EZl user@myvelabs
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGlaVV3oZo/IAGXF3F9qdaiSRTQLzc2aJ50h3MNdLUmI root@myvelabs
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIAnDy15V5hT9+TX/gZeEpStamJOJNpruKdx3PXpcIX6 user@docker
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDmgC/c0Rjyk6sL+PXhuxOfaBVw/sPTrWfX5GBGwqq/g user@desktop

48
notes/ubuntu-nginx Normal file
View file

@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Ubuntu - nginx-mainline
# https://nginx.org/en/linux_packages.html
# Install the prerequisites:
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring -y
# Import an official nginx signing key so apt could verify the packages authenticity. Fetch the key:
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# Verify that the downloaded file contains the proper key:
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg \
| grep -q 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 || exit 1
# The output should contain the full fingerprint 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 as follows:
#
# pub rsa2048 2011-08-19 [SC] [expires: 2027-05-24]
# 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
# uid nginx signing key <signing-key@nginx.com>
# Note that the output can contain other keys used to sign the packages.
# # To set up the apt repository for stable nginx packages, run the following command:
#
# echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
# http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
# | sudo tee /etc/apt/sources.list.d/nginx.list
# If you would like to use mainline nginx packages, run the following command instead:
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# Set up repository pinning to prefer our packages over distribution-provided ones:
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx
# To install nginx, run the following commands:
sudo apt update
sudo apt install nginx -y

73
notes/wireguard Normal file
View file

@ -0,0 +1,73 @@
############
# Key generation
############
for peer in {0..9}
do
wg genkey | (umask 0077 && tee peer${peer}.key) | wg pubkey > peer${peer}.pub
done
############
# Server configuration
############
/etc/wireguard/wg0.conf
############
[Interface]
Address = 10.200.200.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
# substitute eth0 in the following lines to match the Internet-facing interface
# the FORWARD rules will always be needed since traffic needs to be forwarded between the WireGuard
# interface and the other interfaces on the server.
# if the server is behind a router and receives traffic via NAT, specify static routing back to the
# 10.200.200.0/24 subnet, the NAT iptables rules are not needed but the FORWARD rules are needed.
# if the server is behind a router and receives traffic via NAT but one cannot specify static routing back to
# 10.200.200.0/24 subnet, both the NAT and FORWARD iptables rules are needed.
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# foo
PublicKey = PEER_FOO_PUBLIC_KEY
PresharedKey = PRE-SHARED_KEY
AllowedIPs = 10.200.200.2/32
[Peer]
# bar
PublicKey = PEER_BAR_PUBLIC_KEY
PresharedKey = PRE-SHARED_KEY
AllowedIPs = 10.200.200.3/32
###
# The interface may be brought up using wg-quick up wg0 respectively by starting and potentially enabling the interface via wg-quick@interface.service, e.g. wg-quick@wg0.service. To close the interface use wg-quick down wg0 respectively stop wg-quick@interface.service.
###
############
# Client configuration
############
foo.conf
[Interface]
Address = 10.200.200.2/32
PrivateKey = PEER_FOO_PRIVATE_KEY
DNS = 10.200.200.1
[Peer]
PublicKey = SERVER_PUBLICKEY
PresharedKey = PRE-SHARED_KEY
Endpoint = my.ddns.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
bar.conf
[Interface]
Address = 10.200.200.3/32
PrivateKey = PEER_BAR_PRIVATE_KEY
DNS = 10.200.200.1
[Peer]
PublicKey = SERVER_PUBLICKEY
PresharedKey = PRE-SHARED KEY
Endpoint = my.ddns.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
###
# Note: Users of NetworkManager, may need to enable the NetworkManager-wait-online.service and users of systemd-networkd may need to enable the systemd-networkd-wait-online.service to wait until devices are network-ready before attempting a WireGuard connection.
###

782
passthrough.sh Executable file
View file

@ -0,0 +1,782 @@
#!/usr/bin/env bash
set -a
set -E
# SSH public keys
sshkeys=''
## Tput codes
reset=$(tput sgr0)
bold=$(tput bold)
italic=$(tput sitm)
blink=$(tput blink)
black=${reset}$(tput setaf 0)
red=${reset}$(tput setaf 1)
green=${reset}$(tput setaf 2)
yellow=${reset}$(tput setaf 3)
blue=${reset}$(tput setaf 4)
magenta=${reset}$(tput setaf 5)
cyan=${reset}$(tput setaf 6)
white=${reset}$(tput setaf 7)
# Color codes
function say
{
for format in ${@:2}
do
echo -n ${!format}
done
echo -e "${1}"
echo -n ${reset}
}
function say_n
{
for format in ${@:2}
do
echo -n ${!format}
done
echo -e -n "${1}"
echo -n ${reset}
}
# Exit function
trap '[ "$?" -ne 77 ] || exit 77' ERR
function die
{
cat <<- abort
${red}
Error encountered for the following reason:
${yellow}
"${1}"
${red}
Script aborted...
${reset}
abort
exit 77
}
# Internet connection check
if nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || nc -z -w 1 google.com 443 >/dev/null 2>&1
then
timedatectl set-ntp true
else
die 'No internet connectivity detected, plug in an ethernet cable or run \e[32miwd-connect\e[33m if using wifi and try again'
fi
function returnUUID
{
for partuuid in \
$(blkid -s UUID -o value ${1}) \
$(lsblk -d -n -o uuid ${1}) \
$(ls -l -a /dev/disk/by-uuid | grep "$(echo ${1} | sed 's\/dev\\')" | awk '{print $9}')
do
if [ ${partuuid} ]
then
echo ${partuuid}
break
else
unset partuuid
fi
done
if [ -z ${partuuid} ]
then
die 'Unable to determine partition UUID'
fi
}
clear
cat <<title
${black}${bold}## rev ${revision}${reset}
${blue}${bold}
Arch Passthrough
${reset}${bold}
Press any key when ready...${reset}
title
read -n 1 -s
echo
if ls -l /dev/disk/* | grep -q 'virtio'
then
installation_disk='vda'
elif ls -l /dev/disk/* | grep -q 'QEMU'
then
installation_disk='sda'
fi
# Hostname
say "Create a name for your computer" blue
until [ ${hostname} ]
do
read -r -p 'Hostname: ' hostname
echo
[ ${hostname} ] || say "Hostname cannot be empty, try again" red
done
# User password
say "Set a password for user" blue
while true
do
read -s -r -p 'User password: ' userpass
echo
read -s -r -p 'Verify user password: ' userpass2
echo
echo
if [ -z ${userpass} ] || [ "${userpass}" = "${userpass2}" ]
then
break
else
say "Passwords did not match, try again" red
fi
done
say "user@${hostname}'s password has been saved" green
echo
# Superuser password
say "Create a root superuser password" blue
while true
do
read -s -r -p 'Superuser password: ' rootpass
echo
read -s -r -p $'Verify superuser password: ' rootpass2
echo
echo
if [ -z ${rootpass} ] || [ "${rootpass}" = "${rootpass2}" ]
then
break
else
say "Passwords did not match, try again" red
fi
done
say "Root superuser password has been saved" green
echo
# Assign system drive
say "Identify the system drive from the list of available devices below" blue
lsblk -d -o name,model,size,mountpoint | grep -v 'archiso'
say '## SSD and HDD device format begins with "sd" or "hd" (sda, sdb, sd[*])
## NVME and PCI device format is "nvme[*]n1" (nvme0n1, nvme1n1, nvme[*]n1)' black bold
lsblk -o name | grep -q -w ${installation_disk} ||
while true
do
read -r -p 'Installation device: ' installation_disk
if [ ${installation_disk} ] && lsblk -o name | grep -q -w ${installation_disk}
then
break
else
lsblk -d -o name,model,size,mountpoint | grep -v 'archiso'
if [ -z ${installation_disk} ]
then
echo
say "Field cannot be empty, try again" red
else
echo
say "Invalid selection or drive not available, try again" red
fi
fi
done
echo
say "Installation drive set as ${green}${reset}/dev/${installation_disk}" reset
# Choose a linux kernel
cat <<menu
${blue}
Select a linux kernel version${reset}
1) linux
2) linux-lts
3) linux-hardened
4) linux-zen
menu
until [[ ${kernel_choice} = [1-4] ]]
do
read -n 1 -p '> ' kernel_choice
echo
if ! [[ ${kernel_choice} = [1-4] ]]
then
echo
say 'Invalid selection, type an option from 1 to 4' red
fi
done
case ${kernel_choice} in
1)
linux_kernel='linux'
;;
2)
linux_kernel='linux-lts'
;;
3)
linux_kernel='linux-hardened'
;;
4)
linux_kernel='linux-zen'
;;
esac
echo
say " You have chosen ${green}${linux_kernel}${reset} as a kernel" reset
echo
# Unmount if mounted
if findmnt '/mnt' | grep -q -w '/mnt'
then
umount -R /mnt
fi
# Shred installation drive
say "Partitioning /dev/${installation_disk}" yellow bold
wipefs -f -a /dev/${installation_disk}
blkdiscard -f /dev/${installation_disk}
if [ -d /sys/firmware/efi/efivars ]
then
parted --script --align=optimal /dev/${installation_disk} \
mklabel gpt \
mkpart primary fat32 1MiB 100MiB \
mkpart primary ${partition} 100MiB 100% \
set 1 esp on
partprobe /dev/${installation_disk}
export {efivol,bootvol}=/dev/$(lsblk -l -o name | grep "${installation_disk}".*1$)
export {rootpart,rootvol}=/dev/$(lsblk -l -o name | grep "${installation_disk}".*2$)
echo
function bootLoader
{
# Systemd-boot
say "Configuring systemd-boot" yellow bold
bootctl --path=/boot install
echo -e 'title Arch Linux
linux /vmlinuz-'${linux_kernel}'
initrd /initramfs-'${linux_kernel}'.img
options quiet root=UUID='$(returnUUID ${rootpart})' rw' > /boot/loader/entries/arch.conf
echo -e 'default arch
timeout 0
console-mode max
editor no' > /boot/loader/loader.conf
systemdbootservice='systemd-boot-update.service'
}
else
bios='syslinux'
parted --script --align=optimal /dev/${installation_disk} \
mklabel msdos \
mkpart primary ${partition} 1MiB 100% \
set 1 boot on || die 'Disk partitioning failed'
partprobe /dev/${installation_disk}
export {rootpart,rootvol}=/dev/$(lsblk -l -o name | grep "${installation_disk}".*1$)
echo
function bootLoader
{
# Syslinux
say "Configuring syslinux" yellow bold
syslinux-install_update -i -a -m
sed -i 's\LINUX ../vmlinuz-linux.*\LINUX ../vmlinuz-'${linux_kernel}'\g' /boot/syslinux/syslinux.cfg
sed -i 's/APPEND root.*/APPEND root=UUID='"$(returnUUID ${rootpart})"' rw quiet/g' /boot/syslinux/syslinux.cfg
sed -i 's/.*PROMPT.*/PROMPT 0/g' /boot/syslinux/syslinux.cfg
sed -i 's/.*TIMEOUT.*/TIMEOUT 0/g' /boot/syslinux/syslinux.cfg
sed -i 's/.*UI menu.*/#UI menu/g' /boot/syslinux/syslinux.cfg
}
fi
say "Configuring volumes" yellow bold
yes | mkfs.ext4 ${rootvol}
mount ${rootvol} /mnt
if [ -d /sys/firmware/efi/efivars ]
then
mkdir /mnt/boot
yes | mkfs.fat -F 32 ${efivol}
mount ${bootvol} /mnt/boot
findmnt '/mnt/boot' | grep -q -w "${bootvol}" || die 'Boot partition has not been mounted properly'
echo
fi
say "Installing Arch Linux base packages on /dev/${installation_disk}" yellow bold
sed -i \
-e '/Color/c\Color' \
-e '/ParallelDownloads/c\ParallelDownloads = 10' \
-e 's#^\[core\]$\|^\[extra\]$#&\
CacheServer = http://192.168.122.1:9090#' \
/etc/pacman.conf
# Temporarily disable mkinitcpio
ln -s -f /dev/null /etc/pacman.d/hooks/90-mkinitcpio-install.hook
pacstrap -K /mnt ${linux_kernel} qemu-guest-agent base mkinitcpio sudo \
${bios} reflector openssh rsync \
wireguard-tools systemd-resolvconf \
pacman-contrib bash-completion vim
genfstab -U -p /mnt >> /mnt/etc/fstab
grep -q 'UUID' /mnt/etc/fstab || die
# Make custom directories
mkdir -p /mnt/etc/pacman.d/hooks /mnt/usr/bin/local
# pacman.conf hook
install /dev/stdin /mnt/usr/bin/local/hook-pacman.conf <<hook
#!/usr/bin/env bash
if [ -f /etc/pacman.conf.pacnew ]
then
sed -i \\
-e '/Color/c\Color' \\
-e '/ParallelDownloads/c\ParallelDownloads = 10' \\
-e 's#^\[core\]$\|^\[extra\]\$#&\\
CacheServer = http://192.168.122.1:9090#' /etc/pacman.conf.pacnew
mv /etc/pacman.conf.pacnew /etc/pacman.conf
fi
hook
cat >/mnt/etc/pacman.d/hooks/pacman.conf.hook <<pacman
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = pacman
[Action]
Description = Fixing pacman.conf
When = PostTransaction
Exec = /usr/bin/local/hook-pacman.conf
pacman
sed -i \
-e '/Color/c\Color' \
-e '/ParallelDownloads/c\ParallelDownloads = 10' \
-e 's#^\[core\]$\|^\[extra\]$#&\
CacheServer = http://192.168.122.1:9090#' \
/mnt/etc/pacman.conf
# Manually configure mkinitcpio
sed -e "s|%PKGBASE%|linux|g" \
-e "s/^fallback/#&/g" \
-e "s/ 'fallback'//" \
/mnt/usr/share/mkinitcpio/hook.preset >/mnt/etc/mkinitcpio.d/linux.preset
rm /mnt/usr/share/mkinitcpio/hook.preset
rsync -a /mnt/usr/lib/modules/*/vmlinuz /mnt/boot/vmlinuz-linux
# mkinitcpio preset hook
cat >/mnt/etc/pacman.d/hooks/linux.preset.hook <<preset
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = mkinitcpio
[Action]
Description = Updating mkinitcpio linux preset
When = PostTransaction
Exec = /usr/bin/local/hook-linux.preset
preset
install /dev/stdin /mnt/usr/bin/local/hook-linux.preset <<'hook'
#!/usr/bin/env bash
if [ -f /usr/share/mkinitcpio/hook.preset ]
then
sed \
-e "s|%PKGBASE%|linux|g" \
-e "s/^fallback/#&/g" \
-e "s/ 'fallback'//" \
/usr/share/mkinitcpio/hook.preset >/etc/mkinitcpio.d/linux.preset
rm /usr/share/mkinitcpio/hook.preset
fi
hook
arch-chroot /mnt mkinitcpio -P
# Networking
ln -s -f /run/systemd/resolve/stub-resolv.conf /mnt/etc/resolv.conf
rsync -a /etc/systemd/network/20-ethernet.network /mnt/etc/systemd/network
arch-chroot /mnt /bin/bash <<"SYU"
# Install bootloader
echo
bootLoader
echo
# Locale
sed -i '/#en_US.UTF-8 UTF-8/ s/#//' /etc/locale.gen
locale-gen >/dev/null
echo 'LANG=en_US.UTF-8' >>/etc/locale.conf
say 'Locale configured' yellow bold
# Time zone
ln -s -f /usr/share/zoneinfo/UTC /etc/localtime
hwclock --systohc --utc
say 'Time zone configured' yellow bold
# Hostname
echo ${hostname} >/etc/hostname
cat >>/etc/hosts <<HOSTS
127.0.0.1 localhost
127.0.1.1 ${hostname}
HOSTS
say 'Hostname configured' yellow bold
# User and superuser
useradd -m -g users -G wheel -s /bin/bash user || die
if [ ${userpass} ]
then
printf '%s\n' ${userpass} ${userpass} | passwd user &>/dev/null
echo '%wheel ALL=(ALL:ALL) ALL' > /etc/sudoers.d/wheel
else
echo -e '%wheel ALL=(ALL:ALL) NOPASSWD: ALL' > /etc/sudoers.d/wheel
mkdir -p /etc/systemd/system/getty@tty1.service.d
echo '[Service]
ExecStart=
ExecStart=-/usr/bin/agetty --autologin user --noclear %I $TERM' > /etc/systemd/system/getty@tty1.service.d/override.conf
fi
if [ "$rootpass" ]
then
printf '%s\n' "$rootpass" "$rootpass" | passwd &>/dev/null
fi
say "Configured superuser and user" yellow bold
echo
# Sysctl custom settings
echo -e 'net.core.netdev_max_backlog = 16384
net.core.somaxconn = 8192
net.core.rmem_default = 1048576
net.core.rmem_max = 16777216
net.core.wmem_default = 1048576
net.core.wmem_max = 16777216
net.core.optmem_max = 65536
net.ipv4.tcp_rmem = 4096 1048576 2097152
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_timestamps = 0
net.core.default_qdisc = cake
net.ipv4.tcp_congestion_control = bbr' > /etc/sysctl.d/99-sysctl.conf
# iptables
install /dev/stdin /usr/bin/local/iptables.hook <<IPTABLES
#!/usr/bin/env bash
iptables -N TCP
iptables -N UDP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -P INPUT DROP
iptables -A INPUT -s 192.168.122.0/24 -j ACCEPT
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
iptables-save -f \${1}
IPTABLES
/usr/bin/local/iptables.hook /etc/iptables/iptables.rules
# iptables hook
install /dev/stdin /usr/bin/local/hook-iptables.rules <<hook
#!/usr/bin/env bash
if [ -f /etc/iptables/iptables.rules.pacnew ]
then
/usr/bin/local/iptables.hook /etc/iptables/iptables.rules.pacnew
mv /etc/iptables/iptables.rules.pacnew /etc/iptables/iptables.rules
fi
hook
cat >/etc/pacman.d/hooks/iptables.rules.hook <<iptables
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = iptables*
[Action]
Description = Fixing iptables rules
When = PostTransaction
Exec = /usr/bin/local/hook-iptables.rules
iptables
# Paccache hook
cat >/etc/pacman.d/hooks/paccache.hook <<'paccache'
[Trigger]
Operation = Upgrade
Operation = Install
Operation = Remove
Type = Package
Target = *
[Action]
Description = Cleaning pacman cache...
When = PostTransaction
Exec = /usr/bin/paccache -r
paccache
# locale.gen.pacnew hook
install /dev/stdin /usr/bin/local/hook-localegen <<hook
#!/usr/bin/env bash
if [ -f /etc/locale.gen.pacnew ]
then
sed -i '/#en_US.UTF-8 UTF-8/ s/#//' /etc/locale.gen.pacnew
mv /etc/locale.gen.pacnew /etc/locale.gen
locale-gen >/dev/null
fi
hook
# locale.gen.pacnew hook
cat >/etc/pacman.d/hooks/localegen.hook <<localegen
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = glibc
[Action]
Description = Fixing locale.gen
When = PostTransaction
Exec = /usr/bin/local/hook-localegen
localegen
# ssh
cat >/etc/ssh/sshd_config.d/10-sshd.conf <<sshd
PermitRootLogin no
PasswordAuthentication no
AuthenticationMethods publickey
Protocol 2
sshd
cat >/etc/ssh/ssh_config.d/10-global.conf <<sshconfig
# Preferred ciphers
Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com
# Only use ipv4
AddressFamily inet
sshconfig
# Polkit
mkdir -p /etc/polkit-1/rules.d
cat >/etc/polkit-1/rules.d/49-nopasswd_global.rules <<'polkit'
/* Allow members of the wheel group to execute any actions
* without password authentication, similar to "sudo NOPASSWD:"
*/
polkit.addRule(function(action, subject) {
if (subject.isInGroup("wheel")) {
return polkit.Result.YES;
}
});
polkit
# Custom pacman wrapper
install /dev/stdin /usr/local/bin/syu <<syu
#!/usr/bin/env bash
sudo curl --fail -s -L wdas.sh/mirrorlist -o /etc/pacman.d/mirrorlist
if checkupdates | grep -q 'archlinux-keyring'
then
sudo pacman -Sy --noconfirm archlinux-keyring
echo
fi
if sudo pacman -Syu --noconfirm
then
echo
sudo pacdiff
fi
syu
# System services
systemctl -q enable systemd-networkd.service systemd-resolved.service sshd.service iptables.service qemu-guest-agent.service ${systemdbootservice}
su user <<"CHANGEUSER"
# SSH
ssh-keygen -t ed25519 -q -f ~/.ssh/id_ed25519 -P ""
echo "${sshkeys[@]}" > ~/.ssh/authorized_keys
# bash
# cp /etc/skel/.bash* ~/
cat >> ~/.bashrc <<'BASHRC'
unset HISTFILE
alias ll='ls -l -a -h'
# Grep color
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
# Adjust terminal upon window resize
shopt -s checkwinsize
# Auto cd into directory
shopt -s autocd
# Ignore duplicate and whitespace history entries
export HISTCONTROL=ignoreboth
#
# ~/.bash_aliases
#
# Reboot and poweroff
alias poweroff='sudo poweroff'
alias reboot='sudo reboot'
# Miscellanous pacman
alias orphans='pacman -Rcns $(pacman -Qtdq)'
alias unlockpacmandb='rm /var/lib/pacman/db.lck && pacman -Syy'
# Rsync
alias rsync='rsync --progress --info=progress2 -v -h'
#
# ~/.bash_functions
#
# Pacman tools
function installer
{
sudo pacman -S "$@"
echo
}
function uninstall
{
sudo pacman -Rcns "$@"
echo
}
function syur
{
/usr/local/bin/syu &&
reboot
}
function syup
{
/usr/local/bin/syu &&
poweroff
}
# Update configs
function update-bash
{
vim ~/.bashrc &&
source ~/.bashrc
}
BASHRC
CHANGEUSER
SYU
# Script for installing desktop environment
install /dev/stdin /mnt/usr/local/bin/desktop <<'DESKTOPINSTALL'
#!/usr/bin/env bash
set -a -E
# Exit function
trap '[ "$?" -ne 77 ] || exit 77' ERR
die()
{
echo -e '\e[1;31m\nError encountered, script aborted...\n\e[0m'
exit 77
}
# Internet connection check
if nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || nc -z -w 1 google.com 443 >/dev/null 2>&1
then
sudo timedatectl set-ntp true
else
echo -e '\n\e[31mNo internet connectivity detected'
echo -e 'Connect to a network and try again'
echo -e 'Aborting installer...\e[0m\n'
die
fi
echo -e '\n\e[1;35mSelect a desktop\e[0m'
echo -e '\t1) i3'
echo -e '\t2) none'
until [[ ${desktop} = [12] ]]
do
read -n 1 -p '> ' desktop
[[ ${desktop} = [12] ]] || echo -e '\n\n\e[1;31mInvalid selection, type an option from 1 to 2\e[0m'
done
# Assign DE variables
case ${desktop} in
1)
# Install and configure x
echo -e '\n\n\t\e[1mYou have chosen \e[32mi3\e[0m\e[1m desktop\e[0m'
echo -e '\n\e[1;35mInstalling base packages\e[0m'
sudo pacman -S --noconfirm spice-vdagent xf86-video-qxl xorg xorg-xinit phonon-qt5-gstreamer ttf-dejavu ttf-liberation noto-fonts noto-fonts-cjk noto-fonts-emoji firefox i3-gaps i3status i3lock dmenu lightdm lightdm-gtk-greeter pavucontrol konsole kate dolphin kompare breeze-icons
echo
echo 'exec i3' > ~/.xinitrc
echo -e '\nXDG_CURRENT_DESKTOP=gnome' | sudo tee -a /etc/environment >/dev/null
# i3
mkdir -p ~/.config/i3
curl -s -L https://raw.githubusercontent.com/i3/i3/next/etc/config | sed 's/exec i3-config-wizard/# &/' > ~/.config/i3/config
tee -a ~/.config/i3/config >/dev/null <<'I3CONFIG'
exec xrandr --output $(xrandr -q | grep -w 'connected primary' | awk '{print $1}') --mode 1920x1080
gaps inner 8
gaps outer 4
# for_window [class="^.*"] border pixel 2
exec spice-vdagent
I3CONFIG
# i3 function
echo -e '\n# i3 config
function i3-config
{
vim ~/.config/i3/config
}' >> ~/.bash_functions
cat >> ~/.bashrc <<'BASHRC'
# Autostart i3
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = 1 ]
then
exec startx
fi
BASHRC
;;
2) echo
;;
esac
sudo rm -f ${0}
case ${desktop} in
1)
echo -e '\e[1;34mDesktop installed, press any key to load i3\e[5m...\e[0m\n'
read -n 1 -s
sudo systemctl -q enable --now lightdm.service
;;
2)
echo -e '\e[1;34mSetup complete, press any key to continue\e[5m...\e[0m\n'
read -n 1 -s
;;
*)
die
;;
esac
DESKTOPINSTALL
# Reboot only if script succeeded
if /usr/bin/sh -c 'arch-chroot /mnt uname -a' | grep -q Linux
then
umount -R /mnt
echo -e '\e[1;34mInstaller has completed and system drive has been unmounted'
echo -e 'Boot into the new system, connect to a network and install a DE by running \e[35mdesktop\e[34m in the terminal'
echo -e 'Rebooting...\n\e[0m'
reboot
else
die
fi

139
pkg/homelab Normal file
View file

@ -0,0 +1,139 @@
amd-ucode
apache
apcupsd
archiso
ark
base
bash-completion
bemenu
bemenu-wayland
bluez
bluez-utils
breeze-icons
bridge-utils
brightnessctl
btrfs-progs
certbot
certbot-nginx
chromium
core/linux
dbus-broker-units
dmenu
dmidecode
dnsmasq
docker
docker-buildx
docker-compose
dolphin
dosfstools
edk2-ovmf
efibootmgr
exfatprogs
fail2ban
fakeroot
feh
ffmpegthumbs
filezilla
firefox
firefox-decentraleyes
firefox-ublock-origin
foot
git
gnome
gnome-keyring
grub
grub-btrfs
i3lock
i3status
i3-wm
inetutils
inotify-tools
intel-ucode
iptables-nft
iwd
jdk-openjdk
jre-openjdk
kate
kcalc
kde-cli-tools
keepassxc
kfind
kompare
konsole
libreoffice-fresh
libvncserver
lightdm
lightdm-gtk-greeter
linux-firmware
man-db
mkinitcpio
mkinitcpio-netconf
mkinitcpio-tinyssh
mpv
networkmanager
nextcloud-client
nginx-mainline
noto-fonts-cjk
ntfs-3g
nvidia-open
nvidia-settings
okular
openbsd-netcat
opendoas
openssh
pacman-contrib
pam-u2f
parted
pavucontrol
pipewire
pipewire-audio
pipewire-jack
pipewire-pulse
plasma
pv
qemu-desktop
qemu-guest-agent
reflector
remmina
rsync
seatd
shotwell
smartmontools
snap-pac
snapper
spice-vdagent
sshfs
sudo
sudo-rs
sway
swaybg
swayidle
swaylock
syslinux
systemd-resolvconf
thunderbird
tinyssh
torbrowser-launcher
ttf-dejavu
vde2
veracrypt
vim
virt-manager
virtualbox
virtualbox-guest-iso
virtualbox-guest-utils
virtualbox-host-modules-arch
wayland
wayvnc
wireguard-tools
wireplumber
wmctrl
xf86-video-qxl
xfce4
xorg
xorg-xinit
yubico-pam
yubikey-full-disk-encryption
yubikey-personalization
zfs-linux
zfs-utils

43
pkg/qemu Normal file
View file

@ -0,0 +1,43 @@
base
bash-completion
breeze-icons
btrfs-progs
chromium
dmenu
dolphin
ffmpegthumbs
firefox
firefox-decentraleyes
firefox-ublock-origin
git
i3lock
i3status
i3-wm
kate
kfind
kompare
konsole
linux
mkinitcpio
opendoas
openssh
pacman-contrib
pavucontrol
pipewire
pipewire-jack
qemu-guest-agent
reflector
rsync
spice-vdagent
sudo
sudo-rs
syslinux
systemd-resolvconf
ttf-dejavu
vim
virtualbox-guest-utils
wireguard-tools
wireplumber
xf86-video-qxl
xorg
xorg-xinit

347
recover.sh Executable file
View file

@ -0,0 +1,347 @@
#!/usr/bin/env bash
set -a -E
# Exit function
trap '[ "${?}" -ne 77 ] || exit 77' ERR
function die
{
echo -e '\n\e[1;31mError encountered, script aborted...\e[0m\n'
exit 77
}
# Internet connection check
if ! nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || ! nc -z -w 1 google.com 443 >/dev/null 2>&1
then
die 'No internet connectivity detected, plug in an ethernet cable or run \e[32miwd-connect\e[33m if using wifi and try again'
fi
clear
echo -e '\e[3m## rev '${revision}'\e[0m\n'
echo -e '\t\e[1;4;34mArch Linux Recovery\e[0m\n\n'
echo -e '\e[1mSelect a system configuration from the options below\e[0m\n'
echo -e '\t1) Basic'
echo -e '\t2) Full Disk LUKS Encryption with EFISTUB'
echo -e '\t3) Full Disk LUKS Encryption with Secured GRUB'
echo -e '\t4) Yubikey Full Disk Encryption with EFISTUB'
echo -e '\t5) Yubikey Full Disk Encryption with Secured GRUB'
if ls -l /dev/disk/* | grep -q 'virtio\|QEMU'
then
echo
until [[ ${arch} = [1-5] ]]
do
read -n 1 -p '> ' arch
[[ ${arch} = [1-5] ]] || echo -e '\n\n\e[1;31mInvalid selection, type an option from 1 to 5\e[0m'
done
else
echo -e '\t6) Full Disk Encryption with Detached LUKS Header and Secured GRUB'
echo -e '\t7) Yubikey Encrypted Detached LUKS Header with Secured GRUB\n'
until [[ ${arch} = [1-7] ]]
do
read -n 1 -p '> ' arch
[[ ${arch} = [1-7] ]] || echo -e '\n\n\e[1;31mInvalid selection, type an option from 1 to 7\e[0m'
done
fi
# Prevent continuing unless yubikey is detected, only applies to yubikey setups
if [[ ${arch} = [457] ]] && ! dmesg | grep -q -i YubiKey
then
echo -e '\n\n\e[1mYubikey not detected'
echo -e 'Insert one to continue\e[5m...\e[0m'
until dmesg | grep -q -i YubiKey
do
sleep 1
done
fi
# Installation drive
echo -e '\n\n\e[1;36mIdentify the system drive from the list of available devices below\e[0m'
lsblk -d -o name,model,size,mountpoint | grep -v 'archiso'
echo -e '\e[3m## SSD and HDD device format begins with "sd" or "hd" (sda, sdb, sd[*])'
echo -e '## NVME and PCI device format is "nvme[*]n1" (nvme0n1, nvme1n1, nvme[*]n1)\e[0m'
while true
do
read -r -p 'Installation device: ' installation_disk
lsblk -o name | grep -q -w ${installation_disk} && [ ${installation_disk} ] && break
lsblk -d -o name,model,size,mountpoint | grep -v 'archiso'
[ -z ${installation_disk} ] && echo -e '\e[1;31mField cannot be empty, try again\e[0m' ||
echo -e '\e[1;31mInvalid selection or drive not available, try again\e[0m'
done
echo -e '\n\e[1mInstallation drive set as \e[32m/dev/'${installation_disk}'\e[0m'
echo
# Detached boot drive
if [[ ${arch} = [67] ]]
then
echo -e '\e[1;34mIdentify the removable boot drive from the list of available devices below\e[0m'
lsblk -d -o name,model,size,mountpoint | grep -v "archiso\|${installation_disk}"
echo -e '\e[3m## Removable drives usually begin with "sd" (sda, sdb, sd[*])\e[0m'
while true
do
read -r -p 'Removable boot device: ' external_boot_disk
lsblk -o name | grep -v ${installation_disk} | grep -q -w ${external_boot_disk} && [ ${external_boot_disk} ] && break
lsblk -d -o name,model,size,mountpoint | grep -v "archiso\|${installation_disk}"
if [ -z ${external_boot_disk} ]
then
echo -e '\e[1;31mField cannot be empty, try again\e[0m'
elif [ ${external_boot_disk} = ${installation_disk} ]
then
echo -e '\e[1;31mBoot drive cannot be the same as the system drive, try again\e[0m'
else
echo -e '\e[1;31mInvalid selection or drive not available, try again\e[0m'
fi
done
echo -e '\n\e[1mDetached boot drive set as \e[32m/dev/'${external_boot_disk}'\e[0m'
echo
fi
if [[ ${arch} = [457] ]]
then
until [[ ${decrypt_root} = [yYnN] ]]
do
read -n 1 -p $'\n\e[1mDoes the yubikey automatically decrypt root upon boot (1FA)? (y/n): \e[0m' decrypt_root
[[ ${decrypt_root} = [yYnN] ]] || echo -e -n '\n\n\e[1;31mNot a valid answer, type "y" or "n"\e[0m'
done
echo
fi
# Functions
function decryptRootLuks
{
while true
do
unset lukspass
echo -e '\e[1;36mEnter the encryption passphrase for the system drive\e[0m'
until [ ${lukspass} ]
do
read -s -r -p 'Encryption password: ' lukspass
[ ${lukspass} ] || echo -e '\n\n\e[1;31mPassphrase field cannot be empty, try again\e[0m'
done
echo -e '\n\n\e[1;36mAttempting to decrypt '${rootpart}'\e[0m'
if printf '%s' "${lukspass}" | cryptsetup open -v ${rootpart} cryptroot ${luks_header}
then
unset lukspass
echo -e '\e[1;92mDecryption successful\e[0m'
break
else
echo -e '\e[1;31mPassphrase failed, try again\e[0m\n'
fi
done
}
function decryptRootYubikey
{
echo
yes | pacman -Sy &>/dev/null
for package in yubikey-personalization yubikey-full-disk-encryption
do
if ! pacman -Q | grep -q -w ${package}
then
missing_yubikey_req+=(${package})
fi
done
if [ ${missing_yubikey_req} ]
then
yes | pacman -Sy ${missing_yubikey_req[@]}
unset missing_yubikey_req
echo
fi
# # Custom challenge slot
# sed -i '/YKFDE_CHALLENGE_SLOT/c\YKFDE_CHALLENGE_SLOT="1"' /etc/ykfde.conf
while true
do
unset lukspass
echo -e '\e[1;36mEnter the encryption passphrase for the system drive\e[0m'
until [ ${lukspass} ]
do
read -s -r -p 'Encryption password: ' lukspass
[ ${lukspass} ] || echo -e '\n\n\e[1;31mPassphrase field cannot be empty, try again\e[0m'
done
if [[ ${decrypt_root} = [yY] ]]
then
sed -i '/YKFDE_CHALLENGE=/c\YKFDE_CHALLENGE="'"$(printf '%q' ${lukspass})"'"' /etc/ykfde.conf
fi
echo -e '\n\n\e[1;36mAttempting to decrypt '${rootpart}' with yubikey HMAC encryption\e[0m'
if printf '%s\n' "${lukspass}" | ykfde-open -d ${rootpart} -n cryptroot -- ${luks_header}
then
unset lukspass
echo -e '\e[1;92mDecryption successful\e[0m'
break
else
echo -e '\e[1;31mPassphrase failed, try again\e[0m\n'
fi
done
}
function decryptBootLuks
{
while true
do
unset grubpass
echo -e '\e[1;36mEnter the encryption passphrase for the bootloader\e[0m'
until [ ${grubpass} ]
do
read -s -r -p 'Bootloader password: ' grubpass
[ ${grubpass} ] || echo -e '\n\n\e[1;31mPassword field cannot be empty, try again\e[0m'
done
echo -e '\n\n\e[1;36mAttempting to decrypt bootloader...\e[0m'
if printf '%s' "${grubpass}" | cryptsetup open ${bootpart} cryptboot
then
unset grubpass
echo -e '\e[1;92mDecryption successful\e[0m'
break
else
echo -e '\e[1;31mPassphrase failed, try again\e[0m\n'
fi
done
}
function configureVolumes
{
echo -e '\n\e[1;36mMounting volumes\e[0m'
case $(blkid -s TYPE -o value ${rootvol}) in
zfs_member)
if ! zpool list | grep -q zroot
then
zpool import -R /mnt zroot -N -d ${rootvol}
fi
zfs mount zroot/ROOT
zfs mount -a
;;
btrfs)
mount ${rootvol} /mnt
;;
ext4)
mount ${rootvol} /mnt
mount ${bootvol} /mnt/boot
if [[ ${arch} = [3567] ]]
then
mount ${efivol} /mnt/boot/efi
fi
;;
esac
}
# Grab disk-id of ${drive}
installation_disk_id=$(ls -l /dev/disk/by-id/* | grep "${installation_disk}$" | grep 'wwn\|nvme-uuid\|nvme-nvme\|nvme-eui\|QEMU\|virtio\|VBOX' | awk '{print $9}' | head -1)
external_boot_disk_id=$(ls -l /dev/disk/by-id/* | grep "${external_boot_disk}$" | grep 'wwn\|nvme-uuid\|nvme-nvme\|nvme-eui\|QEMU\|virtio\|VBOX\|usb' | awk '{print $9}' | head -1)
# System configurations
case ${arch} in
1) # Basic
export {efivol,bootvol}=${installation_disk_id}-part1
export {rootpart,rootvol}=${installation_disk_id}-part2
configureVolumes
;;
2|4) # FDE with EFISTUB
export {efivol,bootvol}=${installation_disk_id}-part1
rootpart=${installation_disk_id}-part2
rootvol=/dev/mapper/cryptroot
case ${arch} in
2)
if [[ $(blkid -s TYPE -o value ${rootpart}) = "zfs_member" ]]
then
zpool import -R /mnt zroot -N -d ${rootpart}
printf '%s' "${lukspass}" | zfs load-key zroot
else
decryptRootLuks
fi
;;
4) decryptRootYubikey;;
esac
configureVolumes
;;
3|5) # FDE with Secured GRUB
efivol=${installation_disk_id}-part1
bootpart=${installation_disk_id}-part2
rootpart=${installation_disk_id}-part3
rootvol=/dev/mapper/cryptroot
bootvol=/dev/mapper/cryptboot
case ${arch} in
3) decryptRootLuks;;
5) decryptRootYubikey;;
esac
decryptBootLuks
configureVolumes
;;
6|7) # FDE with detached luks header
efivol=${external_boot_disk_id}-part1
bootpart=${external_boot_disk_id}-part2
rootpart=${installation_disk_id}
rootvol=/dev/mapper/cryptroot
bootvol=/dev/mapper/cryptboot
luks_header='--header /mnt/header.img'
decryptBootLuks
mount /dev/mapper/cryptboot /mnt
case ${arch} in
6) decryptRootLuks;;
7) decryptRootYubikey;;
esac
umount /mnt
configureVolumes
;;
esac
echo -e '\e[1;92mSystem successfully mounted...\e[0m\n'
if [[ $(blkid -s TYPE -o value ${rootvol}) = "btrfs" ]]
then
install /dev/stdin /usr/local/bin/btrfs-mount <<- BTRFSSU
#!/usr/bin/env bash
btrfsopts=$(awk '$2=="/"' /mnt/etc/fstab | awk '{print $4}' | sed 's/,subvol=.*//')
umount -R /mnt
echo
# Mount @root subvolume
mount -o ${btrfsopts},subvol=@ ${rootvol} /mnt
# Mount all subvolumes
arch-chroot /mnt mount --all
lsblk
echo -e '\n\t\e[1;92mBtrfs subvolumes successful mounted!\e[0m\n'
BTRFSSU
echo -e '\e[1mRun \e[92mbtrfs-mount\e[0m\e[1m to mount all the btrfs subvolumes\e[0m\n'
fi
if [[ ${arch} = [3567] ]]
then
install /dev/stdin /usr/local/bin/re-grub <<REGRUB
#!/usr/bin/env bash
set -e
if findmnt '/mnt/boot/efi' | grep -q "${efivol}" && findmnt '/mnt/boot' | grep -q "${bootvol}"
then
arch-chroot /mnt /bin/bash <<'GRUB'
grub-install --target=x86_64-efi --bootloader-id=GRUB --efi-directory=/boot/efi --recheck
grub-mkconfig -o /boot/grub/grub.cfg
echo -e '\n\t\e[1;92mGrub successfuly re-installed!\e[0m\n'
GRUB
else
echo -e '\n\t\e[1;31mEFI partition not mounted, try again\e[0m\n'
fi
REGRUB
echo -e '\e[1mRun \e[92mre-grub\e[0m\e[1m to regenerate grub\e[0m\n'
fi

912
virtual-machine.sh Executable file
View file

@ -0,0 +1,912 @@
#!/usr/bin/env bash
set -a
set -E
revision=1.0h
## Tput codes
reset=$(tput sgr0)
bold=$(tput bold)
italic=$(tput sitm)
blink=$(tput blink)
black=${reset}$(tput setaf 0)
red=${reset}$(tput setaf 1)
green=${reset}$(tput setaf 2)
yellow=${reset}$(tput setaf 3)
blue=${reset}$(tput setaf 4)
magenta=${reset}$(tput setaf 5)
cyan=${reset}$(tput setaf 6)
white=${reset}$(tput setaf 7)
# Color codes
function say
{
for format in ${@:2}
do
echo -n ${!format}
done
echo -e "${1}"
echo -n ${reset}
}
function say_n
{
for format in ${@:2}
do
echo -n ${!format}
done
echo -e -n "${1}"
echo -n ${reset}
}
# Exit function
trap '[ "${?}" -ne 77 ] || exit 77' ERR
function die
{
cat <<- abort
${red}
Error encountered for the following reason:
${yellow}
"${1}"
${red}
Script aborted...
${reset}
abort
exit 77
}
# Repeat a command until it exits with code 0
function repeat
{
until ${@}
do
sleep 3
done
}
# Read flags
rm -f sshkeys
while [ ${1} ]
do
case ${1} in
-s | --ssh-key )
if [ "${2}" ]
then
echo "${2}" >>sshkeys
if ! ssh-keygen -l -f sshkeys >/dev/null
then
die 'Invalid SSH public key detected'
fi
shift
fi
;;
-? | -h | --help )
cat <<- help
Parameters:
-s, --ssh-key Add SSH public key (enclosed in quotes)
-?, -h, --help This help screen
help
exit 0
;;
* ) die "Unknown flag: ${1}"
;;
esac
shift
done
# Ensure pacman.conf settings are properly set
if [ ! -f /etc/pacman.conf.bkp ]
then
cp /etc/pacman.conf /etc/pacman.conf.bkp
fi
sed -e "/Color/c Color" \
-e "/ParallelDownloads/c ParallelDownloads = 10" \
-e "/^\[core\]$\|^\[extra\]$/a CacheServer = http://192.168.122.1:9090" \
/etc/pacman.conf.bkp >/etc/pacman.conf
# Internet connection check
if nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || nc -z -w 1 google.com 443 >/dev/null 2>&1
then
timedatectl set-ntp true
curl --fail --silent https://git.myvelabs.com/lab/archlinux/raw/branch/master/mirrorlist -o /etc/pacman.d/mirrorlist || die "Unable to fetch latest mirrorlist"
else
die 'No internet connectivity detected, try again'
fi
clear
cat <<- title
$(tput setaf 7 smul dim)## rev ${revision}${reset}
${blue}${bold}
Arch VM
${reset}
title
# Default systemd services
systemd_services=(systemd-networkd.service systemd-resolved.service sshd.service iptables.service wireguard-startup.service)
# Firmware
if ls -l /dev/disk/* | grep -q VBOX
then
linux_firmware+=(virtualbox-guest-utils)
systemd_services+=(vboxservice.service)
installation_disk=sda
else
linux_firmware+=(qemu-guest-agent spice-vdagent)
systemd_services+=(qemu-guest-agent.service)
if ls -l /dev/disk/* | grep -q virtio
then
installation_disk=vda
elif ls -l /dev/disk/* | grep -q QEMU
then
installation_disk=sda
fi
fi
if lspci | grep VGA | grep -q QXL
then
linux_firmware+=(xf86-video-qxl)
fi
# Generate username and hostname
hostname=$(cat /dev/urandom | tr -d -c 'a-zA-Z' | fold -w 6 | head -n 1)
# Unmount if mounted
for mount in /mnt/boot /mnt
do
until ! mount | grep -q ${mount}
do
umount ${mount}
done
done
say "Partitioning /dev/${installation_disk}" yellow bold
wipefs -f -a /dev/${installation_disk}
echo
if [ -d /sys/firmware/efi/efivars/ ]
then
parted --script --align=optimal /dev/${installation_disk} \
mklabel gpt \
mkpart boot 1MiB 100MiB \
mkpart zroot 100MiB 100% \
set 1 esp on
partprobe /dev/${installation_disk}
else
bios=syslinux
parted --script --align=optimal /dev/${installation_disk} \
mklabel msdos \
mkpart primary 1MiB 100MiB \
mkpart primary 100MiB 100% \
set 1 boot on
partprobe /dev/${installation_disk}
fi
# Assign partitions
export {efivol,bootvol}=/dev/$(lsblk -l -o name | grep "${installation_disk}.*1$")
export {rootpart,rootvol}=/dev/$(lsblk -l -o name | grep "${installation_disk}.*2$")
say "Configuring volumes" yellow bold
yes | mkfs.ext4 ${rootvol}
mount -o noatime ${rootvol} /mnt
# Boot partition
yes | mkfs.fat -F 32 ${efivol}
mount --mkdir -o uid=0,gid=0,fmask=0077,dmask=0077 ${bootvol} /mnt/boot
echo
# Temporarily disable mkinitcpio
ln -s -f /dev/null /etc/pacman.d/hooks/90-mkinitcpio-install.hook
# Install Arch on new root
say "Installing Arch Linux on /dev/${installation_disk}" yellow bold
archpkgs="sudo-rs fakeroot \
${linux_firmware[@]} ${bios} \
reflector openssh vim \
git rsync pacman-contrib bash-completion ffmpegthumbs \
xorg xorg-xinit \
i3-wm i3status dmenu konsole kate dolphin kompare breeze-icons kde-cli-tools ttf-dejavu \
firefox firefox-decentraleyes firefox-ublock-origin \
chromium \
wireguard-tools systemd-resolvconf \
noto-fonts-cjk \
iptables-nft pipewire-jack \
openbsd-netcat debugedit"
# Pacstrap
repeat pacstrap -K /mnt --ask 4 \
linux base mkinitcpio \
${archpkgs}
echo
# Generate fs table
genfstab -U -p /mnt >>/mnt/etc/fstab
# Make custom directories
mkdir -p /mnt/etc/{pacman.d/hooks,makepkg.conf.d,systemd/journald.conf.d}/ \
/mnt/opt/local/{bin,hooks}/
# makepkg
cat >/mnt/etc/makepkg.conf.d/zz-makepkg.conf <<- makepkg
PKGEXT=".pkg.tar"
MAKEFLAGS="--jobs=$(nproc)"
COMPRESSZST=(zstd -c -T0 --auto-threads=logical -)
makepkg
# pacman.conf hook
install /dev/stdin /mnt/opt/local/hooks/pacman.conf <<'hook'
#!/usr/bin/env bash
if [ -f /etc/pacman.conf.pacnew ]
then
sed -e '/ParallelDownloads/c ParallelDownloads = 10' \
-e '/Color/c Color' \
-e '/^\[core\]$\|^\[extra\]$/a CacheServer = http://192.168.122.1:9090' \
/etc/pacman.conf.pacnew >/etc/pacman.conf
rm /etc/pacman.conf.pacnew
fi
hook
cat >/mnt/etc/pacman.d/hooks/100-pacman.hook <<- pacman
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = pacman
[Action]
Description = Fixing pacman.conf
When = PostTransaction
Exec = /opt/local/hooks/pacman.conf
pacman
# Configure pacman cache server
sed -e '/ParallelDownloads/c ParallelDownloads = 10' \
-e '/Color/c Color' \
-e '/^\[core\]$\|^\[extra\]$/a CacheServer = http://192.168.122.1:9090' \
-i /mnt/etc/pacman.conf
# Mkinitcpio decompress
echo 'MODULES_DECOMPRESS="yes"' >/mnt/etc/mkinitcpio.conf.d/zz-modules.conf
# Manually configure mkinitcpio
sed -e "s|%PKGBASE%|linux|g" \
-e "s/^fallback/#&/g" \
-e "s/ 'fallback'//" \
/mnt/usr/share/mkinitcpio/hook.preset >/mnt/etc/mkinitcpio.d/linux.preset
rsync -a /mnt/usr/lib/modules/*/vmlinuz /mnt/boot/vmlinuz-linux
# Networking
ln -s -f /run/systemd/resolve/stub-resolv.conf /mnt/etc/resolv.conf
rsync -a /etc/systemd/network/20-ethernet.network /mnt/etc/systemd/network/
if [ -d /sys/firmware/efi/efivars/ ]
then
# Systemd-boot
say "Configuring systemd-boot" yellow bold
arch-chroot -S /mnt bootctl --path=/boot/ install
cat >/mnt/boot/loader/entries/arch.conf <<- systemd-boot
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=${rootpart} rw quiet
systemd-boot
cat >/mnt/boot/loader/loader.conf <<- entry
default arch
timeout 0
console-mode max
editor no
entry
systemd_services+=(systemd-boot-update.service)
else
# Syslinux
say "Configuring syslinux" yellow bold
mkdir /mnt/boot/syslinux/
arch-chroot /mnt extlinux --install /boot/syslinux/
arch-chroot /mnt syslinux-install_update -i -a -m
cat >/mnt/boot/syslinux/syslinux.cfg <<-syslinux
DEFAULT arch
PROMPT 0
TIMEOUT 0
MENU TITLE Arch Linux
MENU COLOR border 30;44 #40ffffff #a0000000 std
MENU COLOR title 1;36;44 #9033ccff #a0000000 std
MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
MENU COLOR unsel 37;44 #50ffffff #a0000000 std
MENU COLOR help 37;40 #c0ffffff #a0000000 std
MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
MENU COLOR msg07 37;40 #90ffffff #a0000000 std
MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
LABEL arch
MENU LABEL Arch Linux
LINUX ../vmlinuz-linux
APPEND root=${rootpart} rw quiet
INITRD ../initramfs-linux.img
LABEL hdt
MENU LABEL HDT (Hardware Detection Tool)
COM32 hdt.c32
LABEL reboot
MENU LABEL Reboot
COM32 reboot.c32
LABEL poweroff
MENU LABEL Poweroff
COM32 poweroff.c32
syslinux
fi
echo
arch-chroot /mnt /usr/bin/bash <<- "CHROOT"
# Root bashrc
cat >> /etc/skel/.bashrc <<- 'bashrc'
# Add local functions folder to path
export PATH=${PATH}:/opt/local/bin
# Source bash functions
if [ -d ~/.local/functions ]
then
for file in $(find ~/.local/functions -type f)
do
. ${file}
done
fi
# Disable history
unset HISTFILE
rm -f ${HISTFILE}
history -c -w
# Rsync
alias rsync='rsync --progress --info=progress2 -v -h'
bashrc
cp /etc/skel/.bashrc ~/
# Locale
sed -i '/#en_US.UTF-8 UTF-8/ s/#//' /etc/locale.gen
locale-gen >/dev/null
echo 'LANG=en_US.UTF-8' >>/etc/locale.conf
say 'Locale configured' yellow bold
# Time zone
ln -s -f $(find /usr/share/zoneinfo/ | shuf -n 1) /etc/localtime
hwclock --systohc --utc
say 'Time zone configured' yellow bold
# Hostname
echo ${hostname} >/etc/hostname
cat >>/etc/hosts <<- HOSTS
127.0.0.1 localhost
127.0.1.1 ${hostname}
HOSTS
say 'Hostname configured' yellow bold
# User and superuser
useradd -m -g users -G wheel -s /usr/bin/bash user || die 'User account creation has failed'
# echo -e '%wheel ALL=(ALL:ALL) NOPASSWD: ALL' >/etc/sudoers.d/zz-NOPASSWD
# install -m 0440 /dev/stdin /etc/doas.conf <<- doas
# permit nopass :root
# permit nopass :wheel
# doas
# install /dev/stdin /usr/local/bin/sudo <<- 'doas'
# #!/usr/bin/env bash
# exec doas "${@/--preserve-env*/}"
# doas
cat >/etc/pam.d/sudo <<- 'sudo'
#%PAM-1.0
auth include system-auth
account include system-auth
session include system-auth
sudo
ln -s -f /etc/pam.d/sudo /etc/pam.d/sudo-i
install -m 0440 /dev/stdin /etc/sudoers-rs <<- 'DEFAULTS'
Defaults!/usr/bin/visudo env_keep += "SUDO_EDITOR EDITOR VISUAL"
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/bin"
root ALL=(ALL:ALL) ALL
%wheel ALL=(ALL:ALL) NOPASSWD: ALL
DEFAULTS
ln -s -f /usr/bin/sudo-rs /usr/local/bin/sudo
# Disable root account
passwd -dl root >/dev/null 2>&1
mkdir -p /etc/systemd/system/getty@tty1.service.d/
cat >/etc/systemd/system/getty@tty1.service.d/override.conf <<- 'autologin'
[Service]
ExecStart=
ExecStart=-/usr/bin/agetty --autologin user --noclear %I $TERM
autologin
say "Configured root user" yellow bold
echo
say "Regenerating cpio image" yellow bold
mkinitcpio -P
echo
# Paccache hook
cat >/etc/pacman.d/hooks/zz-paccache.hook <<paccache
[Trigger]
Operation = Upgrade
Operation = Install
Operation = Remove
Type = Package
Target = *
[Action]
Description = Cleaning pacman cache...
When = PostTransaction
Exec = /usr/bin/paccache --remove
paccache
# Sysctl custom settings
cat >/etc/sysctl.d/10-sysctl.conf <<- SYSCTL
net.core.netdev_max_backlog = 16384
net.core.somaxconn = 8192
net.core.rmem_default = 1048576
net.core.rmem_max = 16777216
net.core.wmem_default = 1048576
net.core.wmem_max = 16777216
net.core.optmem_max = 65536
net.ipv4.tcp_rmem = 4096 1048576 2097152
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_timestamps = 0
net.core.default_qdisc = cake
net.ipv4.tcp_congestion_control = bbr
vm.swappiness=10
vm.vfs_cache_pressure=50
SYSCTL
# iptables
cat >/etc/iptables/userinput.rules <<- IPTABLES
## User input
# Accept all connections from hypervisor subnet
-A INPUT -s 192.168.122.0/24 -j ACCEPT
## Simple Firewall
IPTABLES
sed "/OUTPUT ACCEPT/r /etc/iptables/userinput.rules" /etc/iptables/simple_firewall.rules >/etc/iptables/iptables.rules
# iptables hook
install /dev/stdin /opt/local/hooks/iptables <<hook
#!/usr/bin/env bash
if [ -f /etc/iptables/iptables.rules.pacsave ]
then
sed "/OUTPUT ACCEPT/r /etc/iptables/userinput.rules" /etc/iptables/simple_firewall.rules >/etc/iptables/iptables.rules.pacsave
mv /etc/iptables/iptables.rules.pacsave /etc/iptables/iptables.rules
fi
hook
cat >/etc/pacman.d/hooks/100-iptables.hook <<iptables
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = iptables-nft
[Action]
Description = Fixing iptables rules
When = PostTransaction
Exec = /opt/local/hooks/iptables
iptables
# locale.gen.pacnew hook
install /dev/stdin /opt/local/hooks/localegen <<hook
#!/usr/bin/env bash
if [ -f /etc/locale.gen.pacnew ]
then
sed -i '/#en_US.UTF-8 UTF-8/ s/#//' /etc/locale.gen.pacnew
mv /etc/locale.gen.pacnew /etc/locale.gen
locale-gen >/dev/null
fi
hook
# locale.gen.pacnew hook
cat >/etc/pacman.d/hooks/100-localegen.hook <<localegen
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = glibc
[Action]
Description = Fixing locale.gen
When = PostTransaction
Exec = /opt/local/hooks/localegen
localegen
# mkinitcpio conf hook
cat >/etc/pacman.d/hooks/85-mkinitcpio.conf.hook <<preset
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = mkinitcpio
[Action]
Description = Updating mkinitcpio.conf
When = PostTransaction
Exec = /opt/local/hooks/mkinitcpio
preset
install /dev/stdin /opt/local/hooks/mkinitcpio <<'hook'
#!/usr/bin/env bash
# Linux preset
sed -e "s|%PKGBASE%|linux|g" \
-e "s/^fallback/#&/g" \
-e "s/ 'fallback'//" \
/usr/share/mkinitcpio/hook.preset >/etc/mkinitcpio.d/linux.preset
hook
# Wireguard
install /dev/stdin /usr/local/bin/wireguard-startup <<- 'wireguard'
#!/usr/bin/env bash
wireguard=$(ls /etc/wireguard | shuf -n 1 | sed 's/.conf//')
/usr/bin/wg-quick up ${wireguard}
/usr/bin/wg-quick down ${wireguard}
/usr/bin/wg-quick up ${wireguard}
wireguard
cat >/etc/systemd/system/wireguard-startup.service <<- 'wireguard'
[Unit]
Description=Start wireguard on boot
[Service]
ExecStart=/usr/local/bin/wireguard-startup
[Install]
WantedBy=multi-user.target
wireguard
# SSH
cat >/etc/ssh/sshd_config.d/zz-sshd.conf <<sshd
PermitRootLogin no
PasswordAuthentication no
AuthenticationMethods publickey
sshd
cat >/etc/ssh/ssh_config.d/zz-ssh.conf <<sshconfig
# Preferred ciphers
Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com
# Only use ipv4
AddressFamily inet
sshconfig
# Polkit
mkdir -p /etc/polkit-1/rules.d/
cat >/etc/polkit-1/rules.d/49-nopasswd_global.rules <<'polkit'
/* Allow members of the wheel group to execute any actions
* without password authentication, similar to "sudo NOPASSWD:"
*/
polkit.addRule(function(action, subject) {
if (subject.isInGroup("wheel")) {
return polkit.Result.YES;
}
});
polkit
# Persistent journal logging
cat >/etc/systemd/journald.conf.d/zz-journald.conf <<- eof
[Journal]
Storage=persistent
SystemMaxUse=100M
eof
# Default environment vars
tee -a /etc/environment >/dev/null <<- environment
EDITOR=vim
SUDO_EDITOR=vim
environment
su user <<- "CHANGEUSER"
# ssh identity
ssh-keygen -q \
-t ed25519 \
-f ~/.ssh/id_ed25519 \
-C "user@${hostname}" \
-P ""
# Config dirs
mkdir -p ~/.local/functions/ \
~/.config/{i3,menus}/ \
~/.local/share/konsole/
# i3-config
curl --fail --silent https://raw.githubusercontent.com/i3/i3/next/etc/config | sed 's/exec i3-config-wizard/# &/' > ~/.config/i3/config
cat >> ~/.config/i3/config <<- 'i3'
exec xrandr --output $(xrandr -q | grep -w 'connected primary' | awk '{print $1}') --mode 1920x1080
exec xrandr --dpi 192
exec spice-vdagent
exec VBoxClient-all
i3
# Konsole
cat > ~/.config/konsolerc <<- konsole
[Desktop Entry]
DefaultProfile=profile.profile
[General]
ConfigVersion=1
[UiSettings]
ColorScheme=
konsole
cat >~/.local/share/konsole/profile.profile <<- 'profile'
[Appearance]
Font=monospace,16,-1,2,400,0,0,0,0,0,0,0,0,0,0,1
[General]
Name=profile
Parent=FALLBACK/
[Scrolling]
HistoryMode=2
profile
# Dolphin
curl --fail --silent https://raw.githubusercontent.com/KDE/plasma-workspace/master/menu/desktop/plasma-applications.menu -o ~/.config/menus/applications.menu
kbuildsycoca6 >/dev/null 2>&1
# Autostart i3
cat >> ~/.bash_profile <<- 'autostart'
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = 1 ]
then
exec startx /usr/bin/i3
fi
autostart
cat > ~/.local/functions/i3 <<- 'i3'
# Edit i3 config
function i3-config
{
vim ~/.config/i3/config
}
i3
cat > ~/.local/functions/alias <<- 'alias'
#
# ~/.bash_aliases
#
# ls
alias ll='ls -l -a -h'
# Grep color
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
# Ignore duplicate and whitespace history entries
export HISTCONTROL=ignoreboth
# Reboot and poweroff
alias poweroff='sudo poweroff'
alias reboot='sudo reboot'
# Miscellanous pacman
alias orphans='sudo pacman -Rcns $(pacman -Qtdq)'
alias unlockpacmandb='sudo rm /var/lib/pacman/db.lck && sudo pacman -Syy'
alias
cat > ~/.local/functions/functions <<- 'functions'
#
# ~/.bash_functions
#
# Pacman tools
function installer
{
sudo pacman -S ${@}
echo
}
function uninstall
{
sudo pacman -Rcns "$@"
echo
}
function syur
{
/opt/local/bin/syu &&
reboot
}
function syup
{
/opt/local/bin/syu &&
poweroff
}
# Update configs
function update-bash
{
vim ~/.bashrc &&
source ~/.bashrc
}
functions
cat > ~/.local/functions/wireguard <<- 'wg'
# Wireguard
function wglist
{
if [ ${1} ]
then
sudo ls /etc/wireguard | grep ${1}
else
sudo ls /etc/wireguard
fi
}
function wgupdate
{
if ls | grep -q ".*\.conf"
then
sudo find /etc/wireguard -type f -delete
sudo cp -v * /etc/wireguard
echo -e '\n\t\e[1;32mWireguard profiles updated\e[0m\n'
fi
}
function wd
{
for wireguard in $(sudo wg show | grep interface | awk '{print $2}')
do
sudo wg-quick down ${wireguard}
done
}
function wu
{
wd
if [ ${1} ]
then
sudo wg-quick up $(sudo ls /etc/wireguard | grep ${1} | shuf -n 1 | sed -e 's/.conf//')
else
sudo wg-quick up $(sudo ls /etc/wireguard | shuf -n 1 | sed -e 's/.conf//')
fi
}
wg
CHANGEUSER
CHROOT
# System services
arch-chroot /mnt systemctl enable ${systemd_services[@]} || die "Unable to start systemd services"
# SSH Authentication
if [ -f sshkeys ]
then
cat sshkeys >/mnt/home/user/.ssh/authorized_keys
fi
# Custom pacman wrapper
install /dev/stdin /mnt/opt/local/bin/syu <<- 'syu'
#!/usr/bin/env bash
set -e
# Fetch latest mirrors
sudo reflector --age 24 --latest 10 --protocol https --save /etc/pacman.d/mirrorlist
# Check for new packages and continue if found
newpkg=($(checkupdates --nocolor | awk '{print $1}'))
if [ "${newpkg}" ]
then
# Sync pacman dbs
sudo pacman --ask 4 -Sy >/dev/null
# Update archlinux-keyring first
if [[ ${newpkg[@]} =~ "archlinux-keyring" ]]
then
sudo pacman --ask 4 -S archlinux-keyring
echo
fi
# Perform update if dependencies are satisfied
if sudo pacman --ask 4 -Syu --needed
then
echo
sudo pacdiff
exit 0
fi
fi
syu
# Script for installing desktop environment
install /dev/stdin /mnt/opt/local/bin/startup <<'DESKTOPINSTALL'
#!/usr/bin/env bash
# Internet connection check
if nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || nc -z -w 1 google.com 443 >/dev/null 2>&1
then
sudo timedatectl set-ntp true
sudo vim /opt/local/bin/startupscript
/opt/local/bin/startupscript
exit 0
else
echo -e '\n\e[31mNo internet connectivity detected'
echo -e 'Connect to a network and try again'
echo -e 'Aborting installer...\e[0m\n'
exit 1
fi
DESKTOPINSTALL
install /dev/stdin /mnt/opt/local/bin/startupscript <<'DESKTOPINSTALL'
#!/usr/bin/env bash
# AUR package list
aur_list=(
# jdownloader2
# instaloader
# czkawka-gui-bin
# ledger-udev ledger-live-bin
)
function enable-audio
{
sudo pacman -S --ask 4 pipewire pipewire-audio pipewire-pulse wireplumber
echo
systemctl --user --quiet enable --now wireplumber.service pipewire-pulse.service pipewire.service
}
function wireguard-setup
{
if ! sudo wg show | grep -q interface
then
echo -e '\n\e[31mNo wireguard profile installed\e[0m\n'
exit 1
fi
}
function tor-installer
{
sudo pacman -S --ask 4 torbrowser-launcher
echo
torbrowser-launcher
}
wireguard-setup
tor-installer
# enable-audio # uncomment to enable audio
# AUR packages
if [ ${aur_list} ]
then
for package in ${aur_list[@]}
do
cd ~/
git clone https://aur.archlinux.org/${package}.git
cd ${package}/
makepkg -csi
echo
cd ~
rm -rf ${package}/
done
fi
# Add user to shared folder group if in virtualbox guest
if ls -l /dev/disk/* | grep -q VBOX
then
sudo gpasswd -a user vboxsf >/dev/null
fi
echo -e '\n\e[1;32mSupplementary installer completed, reboot one last time\e[0m'
sudo rm -f /opt/local/bin/startup*
sudo systemctl reboot
DESKTOPINSTALL
# Reboot only if script succeeded
if arch-chroot /mnt uname -a | grep -q Linux
then
for mount in /mnt/boot /mnt
do
until ! mount | grep -q ${mount}
do
umount ${mount}
done
done
echo -e '\e[1;34mInstaller has completed and system drive has been unmounted
Boot into the new system, connect to a network and install a DE by running \e[35mdesktop\e[34m in the terminal
Rebooting...\n\e[0m'
reboot
else
die 'Something does not feel right'
fi