Updating ShadowArch installer to default to UEFI for modern firmware & LVM by default

This commit is contained in:
DarkFeather 2023-11-30 05:07:36 -06:00
parent 18d2b861e0
commit ae2589bd86
Signed by: DarkFeather
GPG Key ID: 1CC1E3F4ED06F296
4 changed files with 108 additions and 194 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ __pycache__
*.pyc *.pyc
*.tar.xz *.tar.xz
*.tar.zst *.tar.zst
wiki/**

View File

@ -2,156 +2,115 @@
function header () { function header () {
tput setaf 1 tput setaf 1
tput bold echo $@ tput bold
echo $@
tput sgr0 tput sgr0
return return
} }
function help() { function help() {
echo Usage: ${0} '[OPTIONS]' cat <<EOM
echo '\-A -- Audio optimizations from the Arch Wiki' Usage: ${0} [OPTIONS]
echo '\-d DISK -- Use the disk.' -A -- Audio optimizations from the Arch Wiki
echo '\-e -- Encrypt the root partition' -d DISK -- Use the disk.
echo '\-g -- GUI packages and setup' -D diskspacer -- the disk spacer character, usually p for nvme
echo '\-h -- This helptext' -e -- Encrypt the root partition
echo '\-k -- Kali Linux-like package additions' -h -- This helptext
echo '\-l FILE -- Log to a file' -l FILE -- Log to a file
echo '\-p -- Productivity package additions' -m -- Skip disk operations and assume storage is mounted on /mnt. Use this to lay out LVM RAID.
echo '\-P -- Power saving for laptops' -M -- Tell pacman to use your local AniNIX/Maat caching
echo '\-s -- Create a layout for an AniNIX/Spartacus' -P -- Power saving for laptops
echo '\-m -- Skip disk operations and assume storage is mounted on /mnt' -s -- Increase the boot size to be able to accept ISOs
echo '\-v -- Verbose output.' -v -- Verbose output.
echo '\-z -- Try to add all the packages on AniNIX/Core'
Example default build for nvme local node:
$0 -M -d /dev/nvme0n1 -D p [ -e ]
EOM
exit 1; exit 1;
} }
# Partition controls
efipart=2;
bootpart=3;
rootpart=4;
partpoint=1;
partedcmd='mklabel gpt\nmkpart primary ext2 0 1MiB\nset 1 bios_grub on\n';
function addNextPartition() {
partsize="$1"
parttype="$2"
partfs="$3"
nextpartpoint=$(( $partpoint + $partsize ))
partedcmd="${partedcmd}mkpart $parttype $partfs ${partpoint}MiB ${nextpartpoint}MiB"'\n'
partpoint=$nextpartpoint
}
disk="/dev/sda" disk="/dev/sda"
unset diskspacer
bootsize=500; # Size in MB for /boot bootsize=500; # Size in MB for /boot
# TODO Add LVM as an argument while getopts "Ad:D:el:pmMsv" OPTION
while getopts "d:egkl:pmsvz" OPTION
do do
case $OPTION in case $OPTION in
A) audio=1 ;; A) audio=1 ;;
d) disk=${OPTARG} ;; d) disk=${OPTARG} ;;
D) diskspacer=${OPTARG} ;;
e) encrypt=1 ;; e) encrypt=1 ;;
g) gui=1 ;;
k) kali=1 ;;
l) exec script -e -f -c "/bin/bash $0 $(echo $@ | sed "s#-l ${OPTARG}##")" "${OPTARG}" ;; l) exec script -e -f -c "/bin/bash $0 $(echo $@ | sed "s#-l ${OPTARG}##")" "${OPTARG}" ;;
p) productivity=1; gui=1 ;;
P) powersave=1 ;;
m) nodiskbuild=1 ;; m) nodiskbuild=1 ;;
s) spartacus=1 ;; P) powersave=1 ;;
M) echo "Server = http://Maat.MSN0.AniNIX.net:9129/repo/archlinux/\$repo/os/\$arch" > /etc/pacman.d/mirrorlist ;;
s) bootsize=10000 ;;
v) set -x ;; v) set -x ;;
z) kitchensink=1 ;;
*) help *) help
esac esac
done done
header Confirm options: header Confirm options:
echo Spartacus set to: $spartacus cat <<EOM
echo Encryption set to: $encrypt Boot size as ${bootsize}
echo GUI: $gui Encryption set to: $encrypt
echo Productivity: $productivity Disk to use: $disk \(Skip disk building? $nodiskbuild \)
echo Kali tools: $kali EOM
echo All Core packages: $kitchensink read -p "Is this OK? Type YES to continue: " answer
echo Disk to use: $disk \(Skip disk building? $nodiskbuild \)
printf "Is this OK? Type YES to continue: "
read answer
if [ "$answer" != "YES" ]; then if [ "$answer" != "YES" ]; then
echo User did not confirm. echo User did not confirm.
exit 1; exit 1;
fi fi
echo >> /etc/pacman.conf <EOM
[AniNIX] umount /mnt/boot; umount /mnt
SigLevel = Optional TrustAll
Server = https://aninix.net/maat/
EOM
pacman -Syy pacman -Syy
if [ -z "$nodiskbuild" ]; then if [ -z "$nodiskbuild" ]; then
header Allocating space header Allocating space
dd if=/dev/zero of="$disk" bs=1M count=1000 dd if=/dev/zero of="$disk" bs=1M count=1000
if [ ! -z "$spartacus" ]; then parted -s "$disk" mklabel gpt
# Insert an ExFAT data partition ahead of the rest. parted -s "$disk" mkpart 1 fat32 1MiB ${bootsize}MiB
export datapart=$efipart; parted -s "$disk" toggle 1 boot
export efipart=$((efipart+1)) parted -s "$disk" mkpart 2 ext4 ${bootsize}MiB 100%FREE
export bootpart=$((bootpart+1))
export rootpart=$(($rootpart+1))
# Break the disk up into 4ths -- 2/4 go to data, 1/4 go to boot, and 1/4 to root
export disksize=$(($(fdisk -l $disk | head -n 1 | cut -f 5 -d ' ') / 1048576)) # Return disk size in MB
if [ "$disksize" == "" ]; then echo "Can't identify disk size"; exit 1; fi
if [ "$disksize" -lt 7788 ]; then echo "This drive is too small to be a Spartacus."; exit 1; fi # Must be 8GB or more to have 2GB root.
export bootsize=$(($disksize / 4))
export datasize=$(($disksize / 2))
addNextPartition $datasize primary ext4
fi
# 550MiB for EFI with boot toggle
addNextPartition 550 primary fat32
partedcmd="${partedcmd}toggle $efipart boot"'\n'
# /boot header Making fat esp partition on "$disk""$diskspacer""1"
addNextPartition $bootsize primary fat32 mkfs.fat -F32 "$disk""$diskspacer""1"
# / (root)
partedcmd="${partedcmd}mkpart primary ext4 ${partpoint}MiB 100%%FREE"'\nquit\n\n'
printf "$partedcmd" | parted "$disk"
if [ ! -z "$spartacus" ]; then
#create data partition
pacman -S exfat-utils --noconfirm
mkfs.exfat "$disk""$datapart"
exfatlabel "$disk""$datapart" "AS-XPLATFRM"
fi
header Making fat esp partition on "$disk""$efipart"
mkfs.fat -F32 "$disk""$efipart"
header Making boot partition on "$disk""$bootpart"
mkfs.vfat "$disk""$bootpart"
header Making root and mountpoints header Making root and mountpoints
header Making rootvg on "$disk""$diskspacer""2"
pvcreate "$disk""$diskspacer""2"
vgcreate rootvg "$disk""$diskspacer""2"
lvcreate -n rootlv -L5G rootvg
if [ ! -z "$encrypt" ]; then if [ ! -z "$encrypt" ]; then
header Making encrypted root on "$disk""$rootpart" header Making encrypted root on /dev/rootvg/rootlv
modprobe dm-crypt modprobe dm-crypt
modprobe serpent_generic modprobe serpent_generic
header Formatting root -- make sure to enter YES followed by a strong passphrase. header Formatting root -- make sure to enter YES followed by a strong passphrase.
cryptsetup luksFormat -c serpent-xts-plain64 -h sha512 --key-size 512 "$disk""$rootpart" cryptsetup luksFormat -c serpent-xts-plain64 -h sha512 --key-size 512 /dev/rootvg/rootlv
header Unlocking root header Unlocking root
cryptsetup luksOpen "$disk""$rootpart" cryptroot cryptsetup luksOpen /dev/rootvg/rootlv cryptroot
mkfs.xfs -f /dev/mapper/cryptroot mkfs.ext4 /dev/mapper/cryptroot
xfs_admin -L ROOT /dev/mapper/cryptroot #mkfs.xfs -f /dev/mapper/cryptroot
#xfs_admin -L ROOT /dev/mapper/cryptroot
mount /dev/mapper/cryptroot /mnt mount /dev/mapper/cryptroot /mnt
if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi
else else
header Making root on "$disk""$rootpart" header Making root on /dev/rootvg/rootlv
mkfs.xfs -f "$disk""$rootpart" mkfs.ext4 /dev/rootvg/rootlv
xfs_admin -L ROOT "$disk""$rootpart" #mkfs.xfs -f /dev/mapper/cryptroot
mount "$disk""$rootpart" /mnt #xfs_admin -L ROOT "$disk""$diskspacer""2"
mount /dev/rootvg/rootlv /mnt
if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi
fi fi
mkdir /mnt/boot mkdir /mnt/boot
mount "$disk""$bootpart" /mnt/boot mount "$disk""$diskspacer""1" /mnt/boot
if [ "$?" -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi
mkdir /mnt/boot/efi
mount "$disk""$efipart" /mnt/boot/efi
if [ "$?" -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi if [ "$?" -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi
fi fi
# Backup the installer
mkdir -p /mnt/root
cp /root/shadowarch /mnt/root/shadowarch.installer."$(date +%F-%R)"
# Install ArchLinux with basic clients for the AniNIX Services. # Install ArchLinux with basic clients for the AniNIX Services.
# * git for Foundation # * git for Foundation
@ -159,31 +118,8 @@ fi
# * openssh for SSH/SFTP # * openssh for SSH/SFTP
# * weechat for IRC # * weechat for IRC
# * make for source packages # * make for source packages
# * tor for anonymity
header Installing ArchLinux to device\(s\) on /mnt header Installing ArchLinux to device\(s\) on /mnt
export pkglist="base base-devel parted net-tools bind-tools git openssh make elinks weechat vim wget tor torsocks grub os-prober rsync openntpd tmux efibootmgr shadowarch" yes "" | pacstrap -K -i /mnt base base-devel linux linux-firmware parted net-tools bind-tools git openssh rsync make elinks weechat vim wget grub os-prober tmux efibootmgr xfsprogs chrony less lvm2 dmraid netctl dhcpcd openresolv python3 vim
if [ ! -z "$gui" ]; then
export pkglist="$pkglist"" xorg-server xfce4 hunspell hunspell-en_US thunar-archive-plugin thunar-media-tags-plugin thunar-volman chromium conky tigervnc xscreensaver"
fi
if [ ! -z "$spartacus" ]; then
export pkglist="$pkglist"" exfat-utils"
fi
if [ ! -z "$productivity" ]; then
export pkglist="$pkglist"" libreoffice-still gimp feh vlc evince openshot"
fi
if [ ! -z "$kali" ]; then
export pkglist="$pkglist"" extundelete testdisk nmap tcpdump hexedit dcfldd"
if [ ! -z "$gui" ]; then
export pkglist="$pkglist"" wireshark-gtk"
else
export pkglist="$pkglist"" wireshark-cli"
fi
fi
if [ ! -z "$kitchensink" ]; then
export pkglist="base base-devel $(wget -q -O - 'https://aninix.net/installed-packages.txt' | cut -f 1 -d ' ' | tr '\n' ' ')"
fi
yes "" | pacstrap -i /mnt $pkglist
if [ $? -ne 0 ]; then header ERROR: Cannot continue -- pacstrap failed; exit 1; fi if [ $? -ne 0 ]; then header ERROR: Cannot continue -- pacstrap failed; exit 1; fi
header Create FSTAB header Create FSTAB
@ -197,57 +133,35 @@ arch-chroot /mnt hwclock --systohc --utc
header Setup bootloader header Setup bootloader
if [ -z "$nodiskbuild" ]; then if [ -z "$nodiskbuild" ]; then
export rootuuid="$(blkid "$disk""$rootpart" | cut -f 2 -d '"')" export rootuuid="$(blkid "$disk""$diskspacer""2" | cut -f 2 -d '"')"
if [ ! -z "$encrypt" ]; then
export hookstring="$(grep 'HOOKS=' /mnt/etc/mkinitcpio.conf | grep -v '#')" export hookstring="$(grep 'HOOKS=' /mnt/etc/mkinitcpio.conf | grep -v '#')"
sed -i 's#'"$hookstring"'#HOOKS="base udev autodetect modconf block encrypt filesystems keyboard fsck"#' /mnt/etc/mkinitcpio.conf if [ ! -z "$encrypt" ]; then
sed -i 's#'"$hookstring"'#HOOKS="base udev autodetect modconf block lvm2 dmraid encrypt filesystems keyboard fsck"#' /mnt/etc/mkinitcpio.conf
sed -i 's#GRUB_CMDLINE_LINUX=""#GRUB_CMDLINE_LINUX="cryptdevice=UUID='$rootuuid':cryptroot"#' /mnt/etc/default/grub sed -i 's#GRUB_CMDLINE_LINUX=""#GRUB_CMDLINE_LINUX="cryptdevice=UUID='$rootuuid':cryptroot"#' /mnt/etc/default/grub
else
sed -i 's#'"$hookstring"'#HOOKS="base udev autodetect modconf block lvm2 dmraid filesystems keyboard fsck"#' /mnt/etc/mkinitcpio.conf
fi
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="panic=5 /' /etc/default/grub # Fix for CVE-2016-4484 sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="panic=5 /' /etc/default/grub # Fix for CVE-2016-4484
fi
fi
arch-chroot /mnt mkinitcpio -p linux
if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi
if [ -z "$nodiskbuild" ]; then
arch-chroot /mnt grub-install --target=x86_64-efi --removable --bootloader-id=grub --efi-directory /boot "$disk" arch-chroot /mnt grub-install --target=x86_64-efi --removable --bootloader-id=grub --efi-directory /boot "$disk"
if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi
arch-chroot /mnt grub-install --target=i386-pc "$disk"
if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi
fi fi
# Remake initramfs for new changes.
arch-chroot /mnt mkinitcpio -P
arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg
if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi if [ $? -ne 0 ]; then header ERROR: Cannot continue; exit 1; fi
header Set networking header Set networking
arch-chroot /mnt systemctl enable openntpd arch-chroot /mnt systemctl enable chronyd
arch-chroot /mnt systemctl enable netctl
export interface=$(ip link list | grep "state" | cut -f 2 -d ":" | cut -f 2 -d " " | grep -v lo) # This part may fail if there are multiple NICs. Given our hardware posture, this is rare.
export interface=$(ip link list | grep "state" | cut -f 2 -d ":" | cut -f 2 -d " " | grep -vE lo\|wlan)
cp /mnt/etc/netctl/examples/ethernet-dhcp /mnt/etc/netctl/$interface cp /mnt/etc/netctl/examples/ethernet-dhcp /mnt/etc/netctl/$interface
sed -i 's/eth0/'$interface'/' /mnt/etc/netctl/$interface sed -i 's/eth0/'$interface'/' /mnt/etc/netctl/$interface
echo 'DNSSearch="aninix.net"' >> /mnt/etc/netctl/$interface echo 'DNSSearch="aninix.net"' >> /mnt/etc/netctl/$interface
arch-chroot /mnt systemctl enable netctl arch-chroot /mnt systemctl enable netctl
arch-chroot /mnt netctl enable $interface arch-chroot /mnt netctl enable $interface
ln -sf /etc/skel/.bashrc /mnt/root/.bashrc
# Clone ConfigPackags from AniNIX::Foundation
arch-chroot /mnt git -C /usr/local/src/ clone https://aninix.net/foundation/ConfigPackages
arch-chroot /mnt git -C /usr/local/src/ clone https://aninix.net/foundation/MiscScripts
arch-chroot /mnt make -C /usr/local/src/MiscScripts/Shared install
arch-chroot /mnt make -C /usr/local/src/MiscScripts/Admin install
arch-chroot /mnt make -C /usr/local/src/MiscScripts/ShadowArch install
arch-chroot /mnt git -C /usr/local/src/ clone https://aur.archlinux.org/cower.git
arch-chroot /mnt groupadd tty-allow
arch-chroot /mnt useradd -u 1001 -G tty-allow -m depriv
arch-chroot /mnt usermod -G "$(getent group | grep root | cut -f 1 -d ':' | tr '\n' ',')""tty-allow" root
arch-chroot /mnt /bin/bash -c 'line="$(grep -E root"[[:space:]]"ALL /etc/sudoers)"; sed -i "s/$line/$line\ndepriv ALL=(ALL) ALL/" /etc/sudoers'
# Handle AUR Packages
if [ ! -z "$kali" ]; then
arch-chroot /mnt git -C /usr/local/src/ clone https://aur.archlinux.org/autopsy.git
fi
# Optimizations from https://wiki.archlinux.org/index.php/Power_management # Optimizations from https://wiki.archlinux.org/index.php/Power_management
if [ ! -z "$powersave" ]; then if [ ! -z "$powersave" ]; then
if [ `lspci | grep -i intel | grep -ic audio` -eq 1 ]; then if [ `lspci | grep -i intel | grep -ic audio` -eq 1 ]; then
@ -278,30 +192,18 @@ fi
# Set password # Set password
header Set new root passphrase and depriviledged user '(depriv)' password. header Set new root passphrase and depriviledged user '(depriv)' password.
arch-chroot /mnt useradd depriv
arch-chroot /mnt passwd arch-chroot /mnt passwd
arch-chroot /mnt passwd depriv arch-chroot /mnt passwd depriv
arch-chroot /mnt chown -R depriv:depriv /usr/local/src/
# Set SSH host keys # Set SSH host keys
arch-chroot /mnt ssh-keygen -A arch-chroot /mnt ssh-keygen -A
cp /root/shadowarch /mnt/root/shadowarch.installer."$(date +%F-%R)"
if [ ! -z "$gui" ]; then
echo "Remember to install your graphics drivers!
For NVidia, look at xf86-video-nouveau
For AMD, look at xf86-video-amdgpu
For Hyper-V, look at xf86-video-fbdev
For Virtual Box, look at virtualbox-guest-utils
For VMware, look at open-vm-tools"
fi
# Set hostname # Set hostname
header Set hostname header Set hostname
printf "What is your fully-qualified hostname? (i.e. host.site.example.com) " printf "What is your fully-qualified hostname? (i.e. host.site.example.com) "
read hostname read hostname
echo "$hostname" > /mnt/etc/hostname echo "$hostname" > /mnt/etc/hostname
hostname "$hostname"
header "Installed ShadowArch on $HOSTNAME!" header "Installed ShadowArch on $HOSTNAME!"
if [ ! -z "$nodiskbuild" ]; then if [ ! -z "$nodiskbuild" ]; then

View File

@ -6,8 +6,11 @@ compile: ${LIST}
install: compile install: compile
for i in ${LIST}; do make -C ./$$i install; done for i in ${LIST}; do make -C ./$$i install; done
reverse: clean:
@echo Please do this for each individual folder in ${LIST} rm -Rf `cat .gitignore`
uninstall:
@echo Please do this for each folder.
test: ${LIST} test: ${LIST}
@echo Please do this for each individual folder in ${LIST} @echo Please do this for each individual folder in ${LIST}
@ -15,12 +18,12 @@ test: ${LIST}
checkperm: checkperm:
@echo Please do this for each individual folder in ${LIST} @echo Please do this for each individual folder in ${LIST}
clean:
rm -Rf `cat .gitignore`
diff: diff:
@echo Please do this for each individual folder in ${LIST} @echo Please do this for each individual folder in ${LIST}
reverse:
@echo Please do this for each individual folder in ${LIST}
localinstall: localinstall:
mkdir -p ~/bin/ mkdir -p ~/bin/
for i in AdminScripts UserScripts; do cd $$i; for j in `ls -1 | grep -v Makefile`; do install -o ${USER} -m 0755 "$$j" /home/${USER}/bin/; done; cd ..; done for i in AdminScripts UserScripts; do cd $$i; for j in `ls -1 | grep -v Makefile`; do install -o ${USER} -m 0755 "$$j" /home/${USER}/bin/; done; cd ..; done

View File

@ -7,17 +7,11 @@ This package holds core files for our environment.
* AdminScripts: Scripts requiring root access for administration * AdminScripts: Scripts requiring root access for administration
* UserScripts: Useful user-space deprivileged scripts * UserScripts: Useful user-space deprivileged scripts
# How to Install ShadowArch # Etymology
The AniNIX provides an installer to install ShadowArch and some basic clients for its services, similar to the [KickStart concept from RHEL/CentOS](https://serverfault.com/questions/517908/how-to-create-a-custom-iso-image-in-centos#521672).
1. Acquire a read-write storage device and some hardware with at least 256M of RAM and one core. ShadowArch is a pun on Shadow IT, the concept of side projects developed outside the normal bounds, and ArchLinux, the system on which we work.
1. [https://archlinux.org/download Download the Arch ISO] and boot the VM or host from that.
1. Run the following to minimally install ShadowArch:
1. `wget https://aninix.net/shadowarch; vi shadowarch; bash shadowarch`
1. Some flags are listed below.
1. If you run across trouble, take a look at the Troubleshooting section at the bottom.
# Defaults # Relevant Files and Software
These are installed by default with the base package of ShadowArch, along with the ArchLinux base packages, grub, parted, os-prober, net-tools, bind-tools, and wget. These are installed by default with the base package of ShadowArch, along with the ArchLinux base packages, grub, parted, os-prober, net-tools, bind-tools, and wget.
* git for source-code access * git for source-code access
* elinks for browsing * elinks for browsing
@ -93,9 +87,19 @@ We include the following customizations:
1. [Chrome](https://www.google.com/chrome/) with [DuckDuckGo](https://duckduckgo.com/) as the default search engine is our browser recommendation. This can be bound to the ShadowArch-like keybind with Start > Chrome > Right-click > Open File Location > Right-click icon > Properties and set the shortcut key to B. We presently don't have a way to bind the Super key in the same way. 1. [Chrome](https://www.google.com/chrome/) with [DuckDuckGo](https://duckduckgo.com/) as the default search engine is our browser recommendation. This can be bound to the ShadowArch-like keybind with Start > Chrome > Right-click > Open File Location > Right-click icon > Properties and set the shortcut key to B. We presently don't have a way to bind the Super key in the same way.
1. Terminal Emulator can be provided by either Powershell or [PuTTY](http://www.putty.org/), depending on where shell activity should live. Use the same steps as the browser above to set the keybind. 1. Terminal Emulator can be provided by either Powershell or [PuTTY](http://www.putty.org/), depending on where shell activity should live. Use the same steps as the browser above to set the keybind.
1. Default Windows Explorer and its keybinds equate to the XFCE4 thunar application used by ShadowArch. The Run and Explorer keybinds natively present in Windows will map. 1. Default Windows Explorer and its keybinds equate to the XFCE4 thunar application used by ShadowArch. The Run and Explorer keybinds natively present in Windows will map.
1. Default Windows Aero window managment will map to the ShaodowArch keybinds. 1. Default Windows Aero window management will map to the ShadowArch keybinds.
1. Workspace management won't be quite the same, but this [CNET article](https://www.cnet.com/how-to/how-to-use-multiple-desktops-in-windows-10/) offers some help on understanding the difference. The Windows environment is a bit more dynamic so it requires more keybinds. 1. Workspace management won't be quite the same, but this [CNET article](https://www.cnet.com/how-to/how-to-use-multiple-desktops-in-windows-10/) offers some help on understanding the difference. The Windows environment is a bit more dynamic so it requires more keybinds.
# Available Clients
The AniNIX provides an installer to install ShadowArch and some basic clients for its services, similar to the [KickStart concept from RHEL/CentOS](https://serverfault.com/questions/517908/how-to-create-a-custom-iso-image-in-centos#521672).
1. Acquire a read-write storage device and some hardware with at least 256M of RAM and one core.
1. [https://archlinux.org/download Download the Arch ISO] and boot the VM or host from that.
1. Run the following to minimally install ShadowArch:
1. `wget https://aninix.net/shadowarch; vi shadowarch; bash shadowarch`
1. Some flags are listed below.
1. If you run across trouble, take a look at the Troubleshooting section at the bottom.
# References # References
* [The ArchLinux Wiki](https://wiki.archlinux.org/) is an invaluable source of information, particularly around packages deployed by ShadowArch hosts. * [The ArchLinux Wiki](https://wiki.archlinux.org/) is an invaluable source of information, particularly around packages deployed by ShadowArch hosts.
These are some known issues the users of ShadowArch have come across with weird reasons. These are some known issues the users of ShadowArch have come across with weird reasons.
@ -107,3 +111,7 @@ Make sure the user is in the audio group on the system and alsamixer is not mute
## No Desktop ## No Desktop
Run xfdesktop -- sometimes xinit loses this execution and the desktop doesn't display. Run xfdesktop -- sometimes xinit loses this execution and the desktop doesn't display.
# Equivalents or Competition
Raspberry Pi's Etcher, OVAs from other systems, etc. are all equivalent imaging projects.