12 KiB
Install
./install.sh takes a machine with nothing but Arch on it to a running Blob
desktop. Every step is idempotent, reports what it did, and can be previewed
with --check.
Layout
| Path | Role |
|---|---|
install.sh |
flags and the order the steps run in |
install/helpers/lib.sh |
reporting, file copies, unit queries |
install/helpers/as-root.sh |
as_root, a no-op when already root |
install/steps/directories.sh |
the directories the shell and scripts expect |
install/steps/packages.sh |
repo and AUR packages, and the yay bootstrap |
install/steps/config.sh |
the BLOB_PATH symlink, everything under ~/.config, and the login shell profile |
install/steps/services.sh |
system services, systemd drop-ins, user units |
install/steps/theme.sh |
the wallpaper link, the first theme, the first background |
install/steps/login.sh |
SDDM, the session entry, and the first launch |
Steps
-
Directories are created first, because nothing below can write into a directory that is not there:
~/.config/blob,~/.config/systemd/user/app.slice.d,~/.local/state/blob,~/.local/shareand~/.cache/blob. A fresh Arch install has none of them. -
BLOB_PATHis symlinked to the checkout at~/.local/share/blob. Nothing underbin/,shell/,themes/ordefault/is ever copied.lndoes not create the parent of a link, so this step makes~/.local/shareitself rather than assuming step 1 ran. -
Packages come from
packages/blob.packagesandpackages/blob-aur.packages. A machine with no AUR helper getsyay-binbuilt once withmakepkg. A failed batch refreshes the databases and retries, then falls back to one package at a time, so a single name that no longer resolves cannot cost you the other hundred and the config, service and login steps below. See packages.md. -
Config is copied into
~/.config:hypr/, the themed app configs,blob/shell.json, the uwsm environment,fontconfig/fonts.conf, and the icon font, and the font cache is refreshed. The shell draws every icon as a Nerd Font glyph in themonospacefamily, and on a fresh Arch install fontconfig resolves that to a font with no such glyphs, so the bar and its panels come up full of blanks.fonts.confbindsmonospacetoJetBrainsMono Nerd Font;blob font setrewrites the same file, and the installer then reports it as a local change and keeps your choice.~/.bashrcgets one line sourcingsession/bashrc, which is what starts the starship prompt and putsblobonPATHin an interactive shell. The line is added once, a.bakis kept, and a~/.bashrcthat already has it is left alone.session/profile.shalso goes to/etc/profile.d/blob.sh, which sourcessession/env-bootstrapand is what putsblobonPATHin a login shell. Without itBLOB_PATHand$BLOB_PATH/binare only set by~/.config/uwsm/env.d/10-blob, which uwsm reads when the graphical session starts, soblobis not found from a TTY. A shell that was already open when the installer ran keeps its oldPATH; open a new one, orsource ~/.local/share/blob/session/env-bootstrap. -
The first theme is applied.
~/wallpapersis symlinked to the checkout'swallpapers/,flatsis applied withBLOB_THEME_HEADLESS=1(no shell or session bus exists yet), and the background symlink is pointed at the first image in~/wallpapers. Without this the first login has no palette and no wallpaper, which draws as a black desktop. It then links the per-app theme files the pipeline renders but no app would otherwise find:~/.config/btop/themes/current.theme(btop'scolor_theme = "current") and, only when~/.config/nvim/lua/pluginsalready exists,theme.luathere. Every step is skipped when a theme, a background, a wallpaper directory or a theme file of your own is already in place. A theme counts as in place only when the staged theme under~/.local/state/blob/current/themeis there too, so a recorded theme name left without its palette is applied again rather than skipped. -
User units land in
~/.config/systemd/userand are enabled, not started: they are allWantedBy=graphical-session.target, so they come up with the session.blob-speaker-tuning.serviceis left out, becauseblob-audio-tuninginstalls it only on machines with a tuning profile. -
systemd drop-ins are written under
/etc: the shutdown timeouts, the oomd pressure thresholds, the plocate prune paths, and the sleep hooks. -
System services are enabled: NetworkManager, resolved, bluetooth, cups, avahi, docker, power-profiles-daemon, and oomd.
NetworkManager-wait-online.serviceis masked so a slow DHCP lease cannot hold up the login screen, andplymouth-start.serviceandplymouth-quit-wait.serviceare masked because Blob configures no boot splash: an unconfigured plymouth holds the console and leaves the machine with neither a greeter nor a TTY. See packages.md. -
The login screen is SDDM. It has to be installed first: if
sddm.serviceis not there, the installer says whether the package is missing or whether systemd has simply not re-read its units yet, and carries on without enabling anything. A unit counts as present whensystemctl catfinds it or when its file is under/etc/systemd/system,/run/systemd/system,/usr/local/lib/systemd/systemor/usr/lib/systemd/system-systemctlgoes through the service manager, so it reports a perfectly good unit as missing inside a chroot or right after pacman wrote it.Three pieces have to be in place:
File Why /usr/local/share/wayland-sessions/blob.desktopthe session SDDM offers /etc/sddm.conf.d/zz-blob.confWayland greeter, run on Hyprland, stock theme, remember the last session /etc/sddm/hyprland-greeter.luathe greeter's own tiny Hyprland config /usr/local/bin/blob-hw-gpu-acceleratedthe renderer check that config runs, where SDDM's user can read it /etc/pam.d/blob-lock-passwordthe PAM stack the lock screen authenticates against The greeter config matters more than it looks: SDDM's stock Wayland greeter runs on
weston, which Blob does not install, so a default SDDM would fail to draw anything. The installer checks that theCompositorCommandnamed inzz-blob.confis actually installed and warns when it is not, because SDDM with a compositor command it cannot run starts, fails, and leaves the machine sitting at a text console with no explanation. That greeter config has to be Lua: Hyprland dropped the old hyprlang format, and a config it cannot parse leaves the greeter with no compositor and the screen black.sddm.serviceis enabled and the default systemd target is set tographical.target, which an Arch install without a display manager does not have.The
zz-prefix is load-bearing. SDDM reads/etc/sddm.conf.din alphabetical order and the last file wins, so a leftover10-wayland.conf,10-theme.conforautologin.conffrom another desktop would otherwise override Blob's. For the same reasonzz-blob.confblanksThemeandAutologin: a greeter pointed at an uninstalled theme, or an autologin pointed at a session entry that no longer exists, leaves SDDM on a black screen it never falls back from, and the only way in is a TTY.The Omarchy ISO wrote exactly such an autologin, owned by no package, so it outlives Omarchy. The installer reports it and overrides it; deleting it stops the warning:
sudo rm /etc/sddm.conf.d/autologin.conf--autologinwriteszzz-blob-autologin.conf, the only file that sorts afterzz-blob.conf. -
Launch.
sddm,hyprland,quickshellanduwsmare checked one last time and any that are missing are named, because that is the whole difference between a desktop and a console. Then, when the installer was run from a console and nothing graphical is running, it startssddm.serviceso the desktop appears without a reboot.--no-launchprints the command instead.--autologinwrites/etc/sddm.conf.d/zzz-blob-autologin.conffor the current user.
Flags
| Flag | Effect |
|---|---|
--check |
report every change, write nothing, exit 1 if anything differs |
--force |
overwrite files that differ from the repo copy |
--skip-packages |
directories, config and services only |
--autologin |
skip the SDDM prompt for this user |
--no-launch |
leave the login screen for the next reboot |
The lock screen
The lock plugin watches /etc/pam.d/blob-lock-password and refuses to lock at
all when it is not there - blob system lock returns missing-pam and nothing
appears, which reads as a keybinding that does nothing. The installer writes it;
it is one line including system-auth, the same stack every other Wayland
locker on Arch authenticates against.
Fingerprint unlock is separate and opt-in: blob setup-security-fingerprint
writes /etc/pam.d/blob-lock-fingerprint, and the lock only offers fingerprint
when that file and a reader are both present.
Choosing a renderer
Hyprland renders through Mesa, and on an adapter Mesa has no driver for it exits
with failed to create dri2 screen instead of drawing. The greeter is Hyprland
too, so that is a black screen at boot and a second one after login, which is
how a machine with no real GPU behind its display arrives.
blob-hw-gpu-accelerated decides which way to go. It reads the kernel driver of
each /sys/class/drm/card* from sysfs, not from lspci, which reads PCI config
space and resumes runtime-suspended GPUs. A card driven by amdgpu, i915,
nouveau, nvidia, nvidia-drm, radeon or xe is a real integrated or
dedicated GPU and hardware rendering is left alone. Everything else - vmwgfx,
vboxvideo, qxl, bochs-drm, cirrus, simpledrm, vkms, virtio_gpu -
is virtual or framebuffer-only, and two settings are applied:
| Setting | Effect |
|---|---|
LIBGL_ALWAYS_SOFTWARE=1 |
Mesa uses llvmpipe, which renders on the CPU |
WLR_NO_HARDWARE_CURSORS=1, cursor:no_hardware_cursors |
the cursor is drawn by the compositor, since there is no plane to put it on |
llvmpipe is slow and it draws. A machine with a real GPU never touches it.
Two places read the detector, because they run as different users:
| Where | How |
|---|---|
| the session | default/hypr/renderer.lua, required from envs.lua beside nvidia.lua, through $BLOB_PATH/bin |
| the greeter | default/sddm/hyprland-greeter.lua, through /usr/local/bin/blob-hw-gpu-accelerated |
The greeter runs as SDDM's own user, with no BLOB_PATH and no read access to
your home directory, so install.sh copies the detector to /usr/local/bin.
A detector that is not there yet reads as no acceleration, which is the fallback
that always draws.
To add a driver to the accelerated list, edit accelerated_drivers in
bin/blob-hw-gpu-accelerated and rerun ./install.sh so the greeter's copy
follows. virtio_gpu is deliberately not on it: QEMU only accelerates it when
the host enables virgl, and Mesa fails the same way when it does not.
To see the difference by hand, from a console:
Hyprland # fails with the dri2 error
LIBGL_ALWAYS_SOFTWARE=1 Hyprland # starts
Uninstall
./uninstall.sh removes the config, the user units, the /etc drop-ins, the
session entry, the wallpaper link and the symlink, restoring any .bak the
installer left. --keep-session keeps the session entry and the SDDM config,
--keep-state keeps ~/.local/state/blob. sddm.service is left enabled either way, so the
machine still reaches a login screen.