← Home

Dotfile · Bash

Arch setup script

One Bash script that turns a fresh Arch base install into the machine I actually work on — locale, user, services, bootloader and desktop, with sane prompts along the way.

What this is

A post-install script, not an installer

Arch doesn't hold your hand, and I like it that way — but I don't enjoy re-typing the same twenty commands every time I set up a machine. So this script picks up after the base system is installed (once you've partitioned, run pacstrap and genfstab, and entered the new system with arch-chroot) and carries it the rest of the way to a usable desktop.

It's deliberately readable and interactive: it asks for your passwords, username and bootloader choice rather than hiding them in config. Nothing here is magic — it's the manual Arch install, written down once so I never lose it.

How to run it

From inside the chroot

Download it and run it — don't pipe straight into bash, because the script is interactive and needs its own stdin for the prompts.

curl -fsSL https://cdn.archdev.in/content/archiso/arch-setup.sh -o arch-setup.sh
bash arch-setup.sh

Read before you run. This is my personal setup — en_IN locale, Asia/Kolkata time, KDE Plasma, an amd-ucode for my CPU. Skim it and swap those for your own before running it on real hardware.

Reference

Every command, explained

Expand any line to see exactly what it does. This is the whole script, in order — nothing hidden.

1 · Base packages, locale & clock

pacman -Sy neovim zsh networkmanager git github-cli glab ntfs-3g --noconfirm
Syncs the package database and installs the essentials in one go: the neovim editor, the zsh shell, networkmanager for networking, Git plus the GitHub (gh) and GitLab (glab) CLIs, and ntfs-3g so Windows/NTFS drives are readable. --noconfirm skips the yes/no prompts.
pacman -S amd-ucode --noconfirm
Installs AMD CPU microcode — early firmware fixes the bootloader loads before the kernel. On an Intel machine you'd swap this for intel-ucode.
echo "en_IN UTF-8" > /etc/locale.gen
Un-comments (by writing) the Indian English UTF-8 locale in the list of locales to generate. Change this to your own, e.g. en_US.UTF-8 UTF-8.
locale-gen
Actually builds the locale data for whatever's listed in /etc/locale.gen. Without this the language settings have nothing to point at.
echo "LANG=en_IN.UTF-8" > /etc/locale.conf
Sets the system-wide language. LANG is the default every program falls back to for text, dates and number formatting.
ln -sf /usr/share/zoneinfo/Asia/Kolkata /etc/localtime
Points the system clock at a timezone by symlinking the zoneinfo file. Swap Asia/Kolkata for your region, e.g. Europe/London.
hwclock --systohc --utc
Writes the current system time back to the hardware (BIOS) clock and records that it's kept in UTC — the sane default on Linux, and what avoids the "clock is wrong after dual-booting" mess.

2 · Services & the multilib repo

systemctl enable NetworkManager
Marks NetworkManager to start automatically on every boot — so you have internet the first time the installed system comes up, not just in the live environment.
systemctl enable fstrim.timer
Enables a weekly fstrim that tells your SSD which blocks are free. It keeps solid-state drives fast and healthy over time.
echo "[multilib]" >> /etc/pacman.conf  (+ Include line)
Appends the [multilib] repository to pacman's config (the >> means "add to the end"). Multilib holds 32-bit packages you need for Steam, Wine and some games.
pacman -Sy
Re-syncs the package databases so the newly-enabled multilib repo is actually known to pacman.

3 · Root, your user & sudo

passwd  # root, looped until it succeeds
Sets the root (administrator) password. The script wraps this in a loop so a typo or mismatch just asks you to try again instead of moving on with no password set.
read -p "Enter the new username: " username
Prompts for your everyday username, then validates it (must start with a letter/underscore, only lowercase letters, digits, dashes and underscores) and checks it doesn't already exist — the same rules Linux itself enforces.
useradd -m -g users -G wheel,storage,power -s /bin/zsh "$username"
Creates your account: -m makes a home directory, -g users sets the primary group, -G adds it to wheel (for sudo), storage and power, and -s /bin/zsh makes Zsh your login shell.
passwd "$username"
Sets the password for the account you just created — also looped so it can't silently fail.
echo "%wheel ALL=(ALL) ALL" >> /etc/sudoers
Grants everyone in the wheel group permission to use sudo. This is the line that lets your normal user run admin commands.
echo "Defaults rootpw" >> /etc/sudoers
A personal preference: makes sudo ask for the root password rather than your user's. Remove this line if you prefer the usual behaviour.
echo "Defaults !tty_tickets" >> /etc/sudoers
Makes a single sudo authentication apply across all your terminals for the timeout window, instead of per-terminal. Convenience over strictness — drop it if you want each terminal to re-prompt.

4 · Bootloader (your choice: GRUB / systemd-boot / skip)

bootctl --path=/boot install
Installs systemd-boot's files into your EFI partition. Both paths use this; GRUB then layers on top, while "direct boot" uses systemd-boot by itself.
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
The GRUB path. Installs the GRUB bootloader into the EFI directory. GRUB is the better pick if you dual-boot, since os-prober can detect Windows and other OSes.
grub-mkconfig -o /boot/grub/grub.cfg
Scans your kernels (and other operating systems) and writes GRUB's boot menu configuration. Run this again any time you want the menu regenerated.
echo "title / linux / initrd ..." > /boot/loader/entries/arch.conf
The systemd-boot "direct" path. Writes a tiny boot entry naming the kernel (vmlinuz-linux) and initramfs — a leaner alternative to GRUB when you're not dual-booting.
blkid -s PARTUUID -o value /dev/$partname
Looks up the stable PARTUUID of your root partition and writes it into the boot entry as root=PARTUUID=… rw. Using the UUID (not /dev/sda2) means booting still works if device names shuffle around.

5 · Hostname, desktop & the AUR

echo "KEYMAP=us" > /etc/vconsole.conf
Sets the keyboard layout for the text console (before a desktop loads). Change us if you use a different physical layout.
echo "arch" > /etc/hostname
Names the machine on the network. Purely cosmetic — set it to whatever you like to see at your shell prompt.
pacman -S plasma cosmic firefox dolphin
Installs the actual desktop: KDE plasma, the newer cosmic desktop to try, the Firefox browser, and the Dolphin file manager. This is the step that turns a terminal into a graphical machine.
git clone https://aur.archlinux.org/yay.git
Clones yay, an AUR helper. Once built, it lets you install from the Arch User Repository as easily as official packages — yay -S <anything>.

Next

The reasoning, in long form

If you want the why — why Arch, how the install actually works, and where this script fits — I wrote a full walkthrough: Arch Linux, and why I keep coming back to it. It ends exactly where this script begins.