max / alloy
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
17 files changed,
+1576 insertions,
-0 deletions
| @@ -27,6 +27,11 @@ | |||
| 27 | 27 | ||
| 28 | 28 | ## Docs | |
| 29 | 29 | ||
| 30 | + | The [manual](docs/manual/README.md) is for people who run Alloy: building an | |
| 31 | + | image, installing, the keybindings, how software gets installed, how to roll | |
| 32 | + | back, troubleshooting. Everything below it is design rationale, written for | |
| 33 | + | whoever works on Alloy. | |
| 34 | + | ||
| 30 | 35 | - [`docs/MANIFESTO.md`](docs/MANIFESTO.md) — what Alloy is, who it's for, the thesis. | |
| 31 | 36 | - [`docs/STACK.md`](docs/STACK.md) — every pick (base, compositor, bar, lock, launcher, notifications, screenshot, file manager) with reasoning and what was rejected. | |
| 32 | 37 | - [`docs/MARQUEE-APPS.md`](docs/MARQUEE-APPS.md) — the egui design-system app pipeline. |
| @@ -1,0 +1,56 @@ | |||
| 1 | + | # 1. What Alloy is | |
| 2 | + | ||
| 3 | + | Alloy is a curated desktop built on Fedora's atomic base. The pieces: | |
| 4 | + | ||
| 5 | + | - **Fedora bootc as the base.** The operating system is a container image. It | |
| 6 | + | is not modified in place; a new version is staged and swapped at boot, and | |
| 7 | + | the previous one stays on disk to roll back to. | |
| 8 | + | - **sway as the compositor.** i3-style manual tiling on Wayland. Workspaces, | |
| 9 | + | splits, tabs, and stacks. No scrolling columns, no animation. | |
| 10 | + | - **A terminal-first stack.** rio for the terminal, nushell for the shell, | |
| 11 | + | helix for the editor, yazi for files, bottom for processes, zathura for PDFs, | |
| 12 | + | imv for images, mpv for video. | |
| 13 | + | - **One authored program, the `alloy` console.** Network, audio, displays, | |
| 14 | + | packages, settings, sync, and the installer, all as terminal views sharing | |
| 15 | + | one keymap and one palette. | |
| 16 | + | ||
| 17 | + | Alloy adopts everything graphical it needs (swaylock, mako, swaybar, swayosd) | |
| 18 | + | and authors nothing that a terminal can serve. | |
| 19 | + | ||
| 20 | + | ## Who it is for | |
| 21 | + | ||
| 22 | + | Developers and keyboard-driven users who prefer configuring once to configuring | |
| 23 | + | often, and who are comfortable in a terminal. Alloy assumes you would rather | |
| 24 | + | read one page about how the system is put together than click through settings | |
| 25 | + | looking for a checkbox. | |
| 26 | + | ||
| 27 | + | It is not a gaming distro, not a GNOME spin, and not a fork of Universal Blue's | |
| 28 | + | images. | |
| 29 | + | ||
| 30 | + | ## What is different from a normal Linux desktop | |
| 31 | + | ||
| 32 | + | Three things surprise people, in roughly this order. | |
| 33 | + | ||
| 34 | + | **You cannot `dnf install` into the running system.** The root filesystem is | |
| 35 | + | read only. Software goes to one of three places instead, and chapter 7 is about | |
| 36 | + | choosing between them. | |
| 37 | + | ||
| 38 | + | **There is no graphical settings app.** Settings live in `alloy settings` and | |
| 39 | + | the other console verbs. Anything the console does not cover is a config file | |
| 40 | + | under `~/.config`, and `alloy settings` can edit most of those too. | |
| 41 | + | ||
| 42 | + | **Your machine is meant to be disposable.** The interesting state is your files | |
| 43 | + | and your identity, both of which can follow you to the next install. Chapter 12 | |
| 44 | + | covers the two enrollments that make that true. | |
| 45 | + | ||
| 46 | + | ## What Alloy deliberately does not have | |
| 47 | + | ||
| 48 | + | - No emoji font, and no fallback that draws them. Emoji in a web page render as | |
| 49 | + | missing glyphs. | |
| 50 | + | - No screen recorder. The picked tool is not packaged for Fedora yet. | |
| 51 | + | - No scanner support. Printing is driverless only (chapter 13). | |
| 52 | + | - No automatic updates of any kind. | |
| 53 | + | - No graphical file manager, launcher, or editor. Each has a terminal answer. | |
| 54 | + | ||
| 55 | + | These are positions, not omissions waiting to be fixed. Where one turns out to | |
| 56 | + | be wrong, it changes in a release rather than in a preference toggle. |
| @@ -1,0 +1,87 @@ | |||
| 1 | + | # 2. Building your image | |
| 2 | + | ||
| 3 | + | Alloy publishes source and never publishes a binary image. You build the | |
| 4 | + | installer ISO yourself, on a machine you already own. | |
| 5 | + | ||
| 6 | + | That is not an interim state waiting on infrastructure. It is the distribution | |
| 7 | + | model: what you boot is the thing you configured, and Make Creative hosts no | |
| 8 | + | registry, signs no images, and redistributes nobody's binaries. | |
| 9 | + | ||
| 10 | + | ## What you need | |
| 11 | + | ||
| 12 | + | - **A Linux machine with podman.** The build runs rootful. | |
| 13 | + | - **Disk.** The image, the container cache, and the ISO working directory | |
| 14 | + | together want tens of gigabytes free. | |
| 15 | + | - **Time.** A cold build compiles nothing of Fedora but does pull around 600 | |
| 16 | + | packages and compress a squashfs. Budget an hour on a laptop, more on slow | |
| 17 | + | storage. | |
| 18 | + | ||
| 19 | + | There is no path to an Alloy ISO from macOS or Windows. The build needs Linux | |
| 20 | + | with podman, and nothing emulates that cheaply enough to recommend. | |
| 21 | + | ||
| 22 | + | ## Get the source | |
| 23 | + | ||
| 24 | + | git clone https://makenot.work/git/max/alloy | |
| 25 | + | cd alloy | |
| 26 | + | ||
| 27 | + | ## Build the ISO | |
| 28 | + | ||
| 29 | + | build/build-iso.sh | |
| 30 | + | ||
| 31 | + | That builds the bootc image (`localhost/alloy:local`), then wraps it into an | |
| 32 | + | installer ISO under `output/`. The ISO carries the image twice: once as the | |
| 33 | + | live system you boot, and once as the source that gets installed to the disk. | |
| 34 | + | ||
| 35 | + | Useful flags: | |
| 36 | + | ||
| 37 | + | | Flag | What it does | | |
| 38 | + | |---|---| | |
| 39 | + | | `--skip-build` | Reuse the image already in container storage | | |
| 40 | + | | `--fast` | Reuse the image and compress cheaply. For iterating on the boot chain | | |
| 41 | + | | `--skip-source` | Omit the install source. The ISO boots but cannot install | | |
| 42 | + | | `--update-target host:5000/alloy:43` | Bake an update registry into the medium (development builds only) | | |
| 43 | + | ||
| 44 | + | Without `--update-target`, machines installed from the medium never fetch | |
| 45 | + | updates. That is the intended state for anything but a development build. | |
| 46 | + | ||
| 47 | + | ## Write it to a USB stick | |
| 48 | + | ||
| 49 | + | Any of the usual tools work on the ISO in `output/`. If you would rather have | |
| 50 | + | the write checked for you, the disk-image path has guards: | |
| 51 | + | ||
| 52 | + | build/build-image.sh --skip-bib --write /dev/sdX | |
| 53 | + | ||
| 54 | + | It refuses partitions, refuses anything with a mounted filesystem, demands an | |
| 55 | + | explicit device path plus a typed confirmation, and verifies the result with | |
| 56 | + | `cmp` before claiming success. | |
| 57 | + | ||
| 58 | + | ## Building a disk image instead | |
| 59 | + | ||
| 60 | + | `build/build-image.sh` produces raw or qcow2 disk images through | |
| 61 | + | bootc-image-builder, which is what you want for a VM: | |
| 62 | + | ||
| 63 | + | build/build-image.sh --type qcow2 | |
| 64 | + | ||
| 65 | + | It refuses to build ISOs on purpose. Every ISO type that tool offers composes | |
| 66 | + | an Anaconda installer, and an Anaconda install of Alloy leaves a machine with | |
| 67 | + | no account and a locked root. The Alloy installer ISO comes from | |
| 68 | + | `build/build-iso.sh` and nowhere else. | |
| 69 | + | ||
| 70 | + | ## Changing what goes in | |
| 71 | + | ||
| 72 | + | The Containerfile at the repo root is the whole package list, and it is meant | |
| 73 | + | to be read and edited. Adding a package is a line in the right group; removing | |
| 74 | + | one is deleting a line. Two cautions: | |
| 75 | + | ||
| 76 | + | - The build asserts a number of things it depends on (that `satty`, `grim`, | |
| 77 | + | `slurp`, `jq` and `notify-send` exist for the screenshot script, that the | |
| 78 | + | fontconfig picks resolve, that the polkit rules name actions that exist). | |
| 79 | + | Removing a package can trip an assertion, which is the build telling you the | |
| 80 | + | removal has consequences somewhere else. | |
| 81 | + | - Anything you add that Alloy ships should get a line in | |
| 82 | + | `crates/alloy/credits.toml`, which is what the installer's credits page | |
| 83 | + | reads. It is hand-curated on purpose, so nothing adds itself. | |
| 84 | + | ||
| 85 | + | Two builds a week apart can differ: the RPM set is not pinned to a snapshot | |
| 86 | + | yet. Fonts and the Rust dependency tree are pinned; the Fedora packages are | |
| 87 | + | not. |
| @@ -1,0 +1,72 @@ | |||
| 1 | + | # 3. Installing | |
| 2 | + | ||
| 3 | + | Boot the USB stick you wrote in chapter 2. The live system starts the Alloy | |
| 4 | + | installer by itself; there is nothing to type at a prompt and no desktop to | |
| 5 | + | find it in. On an already-installed machine the same unit is inert, so the | |
| 6 | + | installer cannot fire by accident. | |
| 7 | + | ||
| 8 | + | The installer is `alloy install`, a wizard over `bootc install to-disk`. bootc | |
| 9 | + | does the real work: partitioning, the ostree deploy, and the bootloader. The | |
| 10 | + | wizard asks four questions, shows you what it is about to run, and runs it. | |
| 11 | + | ||
| 12 | + | ## The six screens | |
| 13 | + | ||
| 14 | + | **1. Disk.** Every disk the machine can see, with its size and model. This is | |
| 15 | + | the one answer nothing later recovers from, so it comes first: if the disk you | |
| 16 | + | expect is not listed, stop here rather than after typing a password. | |
| 17 | + | ||
| 18 | + | **2. Hostname.** What the machine is called on your network and in your | |
| 19 | + | prompt. | |
| 20 | + | ||
| 21 | + | **3. Account.** Your username and password. Alloy creates one account and does | |
| 22 | + | not enable a root login. | |
| 23 | + | ||
| 24 | + | **4. Encryption.** Optional, and if you say yes you type a passphrase and then | |
| 25 | + | see a recovery phrase. Read the next section before deciding. | |
| 26 | + | ||
| 27 | + | **5. Summary.** Every command the installer is about to run, in order, before | |
| 28 | + | any of them runs. Nothing is hidden behind a progress bar. | |
| 29 | + | ||
| 30 | + | **6. Credits.** What Alloy ships, each project's license, and its URL. It is | |
| 31 | + | the only screen that asks nothing, and the install starts from here rather than | |
| 32 | + | from the summary: the last screen before a disk is erased should be the one | |
| 33 | + | naming whose work is about to be written to it. | |
| 34 | + | ||
| 35 | + | Then the install runs, streaming its output, for the several minutes bootc | |
| 36 | + | takes. | |
| 37 | + | ||
| 38 | + | ## Encryption and the recovery phrase | |
| 39 | + | ||
| 40 | + | Choosing encryption sets up LUKS on the root filesystem and binds it to the | |
| 41 | + | machine's TPM, so the disk unlocks at boot without a password prompt. | |
| 42 | + | ||
| 43 | + | That binding has one failure mode that ends in permanent data loss: the TPM | |
| 44 | + | stops answering. Clearing it, replacing the board, or moving the disk to | |
| 45 | + | another machine all do that. So Alloy enrolls two ways in rather than one: | |
| 46 | + | ||
| 47 | + | - **Your passphrase**, the one you typed. | |
| 48 | + | - **A recovery phrase**, eight words the installer generates and shows you | |
| 49 | + | once. | |
| 50 | + | ||
| 51 | + | Write the recovery phrase down on paper. It is not stored anywhere you can read | |
| 52 | + | it back from later, it is never rotated, and it is what stands between a dead | |
| 53 | + | TPM and a lost disk. Words rather than a random key string because this is a | |
| 54 | + | phrase a person reads off one screen and types into another, months later. | |
| 55 | + | ||
| 56 | + | If you skip encryption, none of this applies and the disk is readable by anyone | |
| 57 | + | holding it. | |
| 58 | + | ||
| 59 | + | ## After the install | |
| 60 | + | ||
| 61 | + | Reboot and remove the medium. You land on the greeter (tuigreet on VT1), sign | |
| 62 | + | in with the account you made, and sway starts. | |
| 63 | + | ||
| 64 | + | A machine installed from a locally built medium has its update timer disabled. | |
| 65 | + | It will never poll anything. Chapter 8 covers what updating means instead. | |
| 66 | + | ||
| 67 | + | ## Installing without a screen | |
| 68 | + | ||
| 69 | + | `alloy install` needs a terminal, which means a headless install is not a | |
| 70 | + | one-command flow today. Collecting an SSH key at install time, and minting | |
| 71 | + | media with a key and hostname already baked in, are both filed work rather than | |
| 72 | + | shipped features. For now, install on a machine with a display attached. |
| @@ -1,0 +1,108 @@ | |||
| 1 | + | # 4. The first fifteen minutes | |
| 2 | + | ||
| 3 | + | You have signed in and the screen is mostly empty: a bar across the top, a | |
| 4 | + | wallpaper colour behind it, and nothing else. That is correct. Alloy opens no | |
| 5 | + | windows for you. | |
| 6 | + | ||
| 7 | + | Throughout this manual **Mod** means the Super key (the one between Ctrl and | |
| 8 | + | Alt on most keyboards). | |
| 9 | + | ||
| 10 | + | ## The screen that greets you once | |
| 11 | + | ||
| 12 | + | The first time you log in, a terminal opens on `alloy setup`. It offers two | |
| 13 | + | enrollments, both optional: | |
| 14 | + | ||
| 15 | + | - **Network identity** (Tailscale), so this machine can reach your others. | |
| 16 | + | - **File sync** (Syncthing), so your files follow you onto this machine. | |
| 17 | + | ||
| 18 | + | Skipping is fine and reversible. `alloy mesh` and `alloy sync` do the same | |
| 19 | + | enrollments later. Press `q` when you are done. The screen appears once; typing | |
| 20 | + | `alloy setup` by hand always opens it again. | |
| 21 | + | ||
| 22 | + | ## Open a terminal | |
| 23 | + | ||
| 24 | + | Mod+Return | |
| 25 | + | ||
| 26 | + | That is rio, running nushell. It is where you will spend most of your time. | |
| 27 | + | ||
| 28 | + | If you would rather find a graphical app by name than type a binary: | |
| 29 | + | ||
| 30 | + | Mod+D | |
| 31 | + | ||
| 32 | + | That is the launcher: a fuzzy picker over installed desktop entries, running in | |
| 33 | + | a floating terminal. Two keys, two jobs. `Mod+Return` is for typing commands, | |
| 34 | + | `Mod+D` is for the apps whose binary name nobody remembers. | |
| 35 | + | ||
| 36 | + | ## Move a window around | |
| 37 | + | ||
| 38 | + | Open two or three terminals with `Mod+Return`. They tile automatically. | |
| 39 | + | ||
| 40 | + | - `Mod+H/J/K/L` moves focus left, down, up, right. | |
| 41 | + | - `Mod+Shift+H/J/K/L` moves the window itself. | |
| 42 | + | - `Mod+Q` closes the focused window. | |
| 43 | + | - `Mod+F` makes it fullscreen. | |
| 44 | + | - `Mod+1` through `Mod+4` switch workspaces; `Mod+Shift+1` and friends send the | |
| 45 | + | window with you. | |
| 46 | + | ||
| 47 | + | Chapter 5 has the whole list. Those six get you through the day. | |
| 48 | + | ||
| 49 | + | ## Meet the console | |
| 50 | + | ||
| 51 | + | alloy | |
| 52 | + | ||
| 53 | + | is not a command by itself. Every surface is a verb: | |
| 54 | + | ||
| 55 | + | alloy net # wifi and connections | |
| 56 | + | alloy audio # outputs, inputs, and which stream goes where | |
| 57 | + | alloy display # scale, rotation, which outputs are on | |
| 58 | + | alloy settings # time, hostname, locale, theme, and app configs | |
| 59 | + | alloy pkg # what is installed and where it lives | |
| 60 | + | alloy update # what image is booted, what is staged, how to go back | |
| 61 | + | ||
| 62 | + | Every one of them has the same shape: Tab moves between panes, arrow keys or | |
| 63 | + | `j`/`k` move within a list, Enter acts, Esc cancels, `q` quits, `?` shows help. | |
| 64 | + | ||
| 65 | + | Every action prints the command it ran in a pane at the bottom. That is | |
| 66 | + | deliberate. The console is not hiding the CLI from you, it is showing you which | |
| 67 | + | one to learn. | |
| 68 | + | ||
| 69 | + | ## Get online | |
| 70 | + | ||
| 71 | + | alloy net | |
| 72 | + | ||
| 73 | + | Pick your network, press Enter. Joining a network you have never joined before | |
| 74 | + | needs authorization the console does not yet ask for, so for a brand new wifi | |
| 75 | + | network use: | |
| 76 | + | ||
| 77 | + | run0 nmcli device wifi connect "Network Name" --ask | |
| 78 | + | ||
| 79 | + | `run0` is how you become root on Alloy. There is no `sudo` habit to keep here. | |
| 80 | + | ||
| 81 | + | ## Set the volume | |
| 82 | + | ||
| 83 | + | The Fn keys work: volume up, down, mute, and the media keys, all with an | |
| 84 | + | on-screen indicator. For anything more precise, `alloy audio` shows every | |
| 85 | + | stream and every device and lets you move one onto the other. | |
| 86 | + | ||
| 87 | + | ## Take a screenshot | |
| 88 | + | ||
| 89 | + | - `Print` captures the whole output. | |
| 90 | + | - `Shift+Print` selects a region. | |
| 91 | + | - `Ctrl+Print` captures the active window. | |
| 92 | + | - `Mod+Print` opens the most recent capture in satty to annotate it. | |
| 93 | + | ||
| 94 | + | Captures land in `~/Pictures/Screenshots` and raise a notification saying so. | |
| 95 | + | ||
| 96 | + | ## Lock the screen | |
| 97 | + | ||
| 98 | + | Mod+Ctrl+L | |
| 99 | + | ||
| 100 | + | The session also dims after four and a half minutes, locks at five, and turns | |
| 101 | + | the displays off at ten. A closed lid always locks before suspending. | |
| 102 | + | ||
| 103 | + | ## Then what | |
| 104 | + | ||
| 105 | + | - Chapter 7 if you want to install software. Read it before reaching for a | |
| 106 | + | package manager; the answer is not `dnf`. | |
| 107 | + | - Chapter 11 if the light theme is not what you want at night. | |
| 108 | + | - Chapter 12 if this machine should share files with your other ones. |
| @@ -1,0 +1,94 @@ | |||
| 1 | + | # 5. Keybindings | |
| 2 | + | ||
| 3 | + | **Mod** is the Super key. These are the shipped defaults, from | |
| 4 | + | `~/.config/sway/config`. Edit that file and press `Mod+Shift+C` to reload. | |
| 5 | + | ||
| 6 | + | ## Session | |
| 7 | + | ||
| 8 | + | | Keys | Action | | |
| 9 | + | |---|---| | |
| 10 | + | | `Mod+Return` | Open a terminal | | |
| 11 | + | | `Mod+D` | Launcher: fuzzy picker over installed apps | | |
| 12 | + | | `Mod+Shift+V` | Clipboard history picker | | |
| 13 | + | | `Mod+Ctrl+L` | Lock the screen | | |
| 14 | + | | `Mod+Shift+C` | Reload the sway config | | |
| 15 | + | | `Mod+Shift+E` | Exit the session | | |
| 16 | + | ||
| 17 | + | ## Windows | |
| 18 | + | ||
| 19 | + | | Keys | Action | | |
| 20 | + | |---|---| | |
| 21 | + | | `Mod+Q` | Close the focused window | | |
| 22 | + | | `Mod+F` | Fullscreen | | |
| 23 | + | | `Mod+Shift+F` | Fullscreen across all outputs | | |
| 24 | + | | `Mod+H` `Mod+J` `Mod+K` `Mod+L` | Focus left, down, up, right | | |
| 25 | + | | `Mod+Shift+H/J/K/L` | Move the window left, down, up, right | | |
| 26 | + | | `Mod+Shift+Space` | Toggle floating | | |
| 27 | + | | `Mod+Space` | Move focus between tiled and floating | | |
| 28 | + | ||
| 29 | + | ## Layout | |
| 30 | + | ||
| 31 | + | | Keys | Action | | |
| 32 | + | |---|---| | |
| 33 | + | | `Mod+B` | Split horizontally | | |
| 34 | + | | `Mod+V` | Split vertically | | |
| 35 | + | | `Mod+W` | Tabbed layout | | |
| 36 | + | | `Mod+S` | Stacking layout | | |
| 37 | + | | `Mod+E` | Toggle split direction | | |
| 38 | + | | `Mod+R` | Resize mode: `h/j/k/l` resize, Enter or Esc leaves | | |
| 39 | + | | `Mod+-` | Shrink width by 10% | | |
| 40 | + | | `Mod+=` | Grow width by 10% | | |
| 41 | + | ||
| 42 | + | ## Workspaces | |
| 43 | + | ||
| 44 | + | | Keys | Action | | |
| 45 | + | |---|---| | |
| 46 | + | | `Mod+1` .. `Mod+4` | Switch to workspace 1 through 4 | | |
| 47 | + | | `Mod+Shift+1` .. `Mod+Shift+4` | Move the window to that workspace | | |
| 48 | + | | `Mod+N` | Switch to the `notes` workspace | | |
| 49 | + | | `Mod+M` | Switch to the `main` workspace | | |
| 50 | + | ||
| 51 | + | ## Screenshots | |
| 52 | + | ||
| 53 | + | | Keys | Action | | |
| 54 | + | |---|---| | |
| 55 | + | | `Print` | Capture the whole output | | |
| 56 | + | | `Shift+Print` | Select a region (Esc cancels) | | |
| 57 | + | | `Ctrl+Print` | Capture the active window | | |
| 58 | + | | `Mod+Print` | Annotate the most recent capture in satty | | |
| 59 | + | ||
| 60 | + | Every capture goes to `~/Pictures/Screenshots` and raises a notification. | |
| 61 | + | ||
| 62 | + | ## Media and hardware keys | |
| 63 | + | ||
| 64 | + | | Keys | Action | | |
| 65 | + | |---|---| | |
| 66 | + | | Volume up / down / mute | Output volume, with an on-screen indicator | | |
| 67 | + | | Mic mute | Input mute | | |
| 68 | + | | Brightness up / down | Backlight | | |
| 69 | + | | Play / pause / next / previous | Whatever is playing, over MPRIS | | |
| 70 | + | | Caps Lock | Shows a caps indicator | | |
| 71 | + | ||
| 72 | + | ## Inside the console | |
| 73 | + | ||
| 74 | + | Every `alloy` view shares one keymap. | |
| 75 | + | ||
| 76 | + | | Keys | Action | | |
| 77 | + | |---|---| | |
| 78 | + | | `Tab` / `Shift+Tab` | Move between panes | | |
| 79 | + | | `j` / `k` or arrows | Move within a list | | |
| 80 | + | | `Enter` | Activate the selection | | |
| 81 | + | | `Space` | Toggle a switch, or fold a section in a form | | |
| 82 | + | | `Esc` | Cancel. In a view with nothing to cancel, leave | | |
| 83 | + | | `Ctrl+S` | Save, in a file-backed form | | |
| 84 | + | | `?` | Help | | |
| 85 | + | | `q` | Quit | | |
| 86 | + | ||
| 87 | + | Views with tabs switch between them with `h` and `l`. A field being edited owns | |
| 88 | + | every key while it is open, so `q` types a `q` there rather than quitting. | |
| 89 | + | ||
| 90 | + | ## Inside the other tools | |
| 91 | + | ||
| 92 | + | Alloy does not rebind the applications it adopts. helix, yazi, zathura, imv, | |
| 93 | + | mpv and bottom keep their own upstream keys, all of them vim-shaped. Their own | |
| 94 | + | help (`?` in yazi and bottom, `:tutor` in helix) is the reference. |
| @@ -1,0 +1,79 @@ | |||
| 1 | + | # 6. The console | |
| 2 | + | ||
| 3 | + | `alloy` is the one program Alloy authors. It is a set of terminal views over | |
| 4 | + | the CLIs that already run the system, sharing one palette, one keymap, and one | |
| 5 | + | habit: every action shows the command it ran. | |
| 6 | + | ||
| 7 | + | That last part is the point. The console is not a layer over the system you | |
| 8 | + | have to learn instead of the system. It shows you `nmcli connection up 'Coffee | |
| 9 | + | Shop Wifi'` in a pane at the bottom of the screen, and the day you want to | |
| 10 | + | script that, you already know what to type. | |
| 11 | + | ||
| 12 | + | ## The verbs | |
| 13 | + | ||
| 14 | + | | Command | What it shows | | |
| 15 | + | |---|---| | |
| 16 | + | | `alloy net` | Interfaces, connections, the wifi radio | | |
| 17 | + | | `alloy audio` | Streams, outputs and inputs, and which is routed where | | |
| 18 | + | | `alloy display` | Outputs sway is driving: scale, rotation, on or off | | |
| 19 | + | | `alloy mesh` | Mesh VPN peers and exit node (alias: `alloy tail`) | | |
| 20 | + | | `alloy sync` | Synchronized folders, devices, and pending invitations | | |
| 21 | + | | `alloy pkg` | What is installed and where it lives | | |
| 22 | + | | `alloy update` | The booted image, the staged one, and rollback | | |
| 23 | + | | `alloy settings` | System settings and application configs | | |
| 24 | + | | `alloy config <path>` | One config file, opened directly | | |
| 25 | + | | `alloy setup` | The first-boot enrollment offer | | |
| 26 | + | | `alloy install` | The installer | | |
| 27 | + | | `alloy theme apply` | Put the day or night skeleton in place | | |
| 28 | + | | `alloy status --bar` | The status line, as JSON. Run by the bar, not by you | | |
| 29 | + | ||
| 30 | + | `alloy --help` lists them, and `alloy <verb> --help` covers the flags. | |
| 31 | + | ||
| 32 | + | ## Settings | |
| 33 | + | ||
| 34 | + | `alloy settings` is two tabs over one form. | |
| 35 | + | ||
| 36 | + | **System** holds live state: timezone, network time, hostname, locale, keymap, | |
| 37 | + | and the theme. Rows here commit as you edit them, because setting a timezone is | |
| 38 | + | atomic on its own. Each writing row runs exactly one command, and each of those | |
| 39 | + | is narrowly granted so it does not prompt for a password. | |
| 40 | + | ||
| 41 | + | The clock is shown and never settable. Moving a system clock invalidates | |
| 42 | + | certificates and reorders logs; the row is there so you can see what changing | |
| 43 | + | the timezone did. | |
| 44 | + | ||
| 45 | + | **Applications** holds config files, listed by the app they configure rather | |
| 46 | + | than by path. You pick `rio`, not `~/.config/rio/config.toml`. Editing here is | |
| 47 | + | schema-driven: fields carry types, ranges, allowed values, and their own help | |
| 48 | + | text, and the file keeps its comments and key order when it is written back. | |
| 49 | + | ||
| 50 | + | File-backed forms save with `Ctrl+S`. Live-state rows have nothing to save. | |
| 51 | + | ||
| 52 | + | An app with no schema still appears in the list and opens a plain text editor | |
| 53 | + | with syntax highlighting, so looking for "where do I configure sway" finds an | |
| 54 | + | answer rather than a blank. | |
| 55 | + | ||
| 56 | + | ## A row that says it cannot do something | |
| 57 | + | ||
| 58 | + | If a row is shown but not settable, and says why, that is deliberate. A tool | |
| 59 | + | that did not answer, or a vocabulary that came back empty, gets reported rather | |
| 60 | + | than hidden: hiding it would answer "where do I set this" with silence, and | |
| 61 | + | offering it would promise a command that is not there. | |
| 62 | + | ||
| 63 | + | ## What the console will not do | |
| 64 | + | ||
| 65 | + | - **It does not browse or search a catalog.** `alloy pkg` shows what is | |
| 66 | + | installed, where it lives, and what each surface costs. It will not help you | |
| 67 | + | find software you have not named. | |
| 68 | + | - **It is not a systemd control panel.** `systemctl` is fine. | |
| 69 | + | - **It is not a launcher or a shell.** You invoke it for a task and close it. | |
| 70 | + | ||
| 71 | + | ## Not built yet | |
| 72 | + | ||
| 73 | + | - `alloy theme <name>` for swapping the runtime theme without logging out. | |
| 74 | + | Today the theme is chosen in `alloy settings` and applied at the next login. | |
| 75 | + | - A Bluetooth view. Pairing is `bluetoothctl` for now (chapter 13). | |
| 76 | + | - MagicDNS lookup and share/unshare in `alloy mesh`. | |
| 77 | + | - Editing an existing folder's share list in `alloy sync`. | |
| 78 | + | - Multi-output mode picking in `alloy display`. Scale and enable work; the mode | |
| 79 | + | picker waits on a machine with two displays to test against. |
| @@ -1,0 +1,110 @@ | |||
| 1 | + | # 7. Installing software | |
| 2 | + | ||
| 3 | + | This is the chapter that makes an atomic system make sense. It is also the | |
| 4 | + | thing Alloy is most opinionated about. | |
| 5 | + | ||
| 6 | + | On a normal distro there is one question: install it or not. Here there are | |
| 7 | + | three places software can live, and picking the right one is most of the skill. | |
| 8 | + | Alloy replaces "which tool" with one question: **how much of your machine | |
| 9 | + | should this software be able to reach?** | |
| 10 | + | ||
| 11 | + | ## The isolation dial | |
| 12 | + | ||
| 13 | + | | Level | Sees | Use it for | | |
| 14 | + | |---|---|---| | |
| 15 | + | | `host` | Your whole home directory, your devices, the session bus | Development toolchains, anything that must feel installed | | |
| 16 | + | | `workspace` | Its own private home, plus the directories you name | Running someone else's build, a package manager over untrusted code | | |
| 17 | + | | `sandboxed` | What a portal hands it: a file picker, permission-gated devices | Graphical apps you did not write | | |
| 18 | + | ||
| 19 | + | You pick the level. Alloy picks the implementation behind it: distrobox for | |
| 20 | + | `host`, podman directly for `workspace`, flatpak for `sandboxed`. The level is | |
| 21 | + | the stable interface, which is why the backend can change later without your | |
| 22 | + | boxes changing. | |
| 23 | + | ||
| 24 | + | **Be clear about what `workspace` is.** A rootless container with a bind mount | |
| 25 | + | limits blast radius. It is not a security boundary and Alloy will not call it | |
| 26 | + | one. `sandboxed` is the only level with a real isolation model behind it. | |
| 27 | + | ||
| 28 | + | ## Boxes | |
| 29 | + | ||
| 30 | + | alloy pkg box | |
| 31 | + | ||
| 32 | + | lists every box on the machine, including ones created outside Alloy with a | |
| 33 | + | bare `podman run` or a direct `flatpak install`. An inventory that hid those | |
| 34 | + | would be lying. Rows mark which boxes are declared (reproducible) and which are | |
| 35 | + | ad hoc (gone on a rebuild). | |
| 36 | + | ||
| 37 | + | From that tab you can start, stop, enter, remove, and export a box. | |
| 38 | + | ||
| 39 | + | **Entering** a box hands the terminal over to it, so the console tears itself | |
| 40 | + | down and comes back when you exit. | |
| 41 | + | ||
| 42 | + | **Exporting** puts a command from inside a box onto your host `PATH`, at | |
| 43 | + | `~/.local/bin`, which Fedora already searches. Running `rg` then runs it inside | |
| 44 | + | its box, in the right directory, starting the box first if it was stopped. | |
| 45 | + | ||
| 46 | + | One caution: an exported wrapper takes the plain name of the binary, so | |
| 47 | + | exporting something the host already has puts the box's copy ahead of the | |
| 48 | + | system one. | |
| 49 | + | ||
| 50 | + | ## Declaring boxes | |
| 51 | + | ||
| 52 | + | Boxes can be described in TOML, which makes them reproducible and syncable: | |
| 53 | + | ||
| 54 | + | ```toml | |
| 55 | + | [box.dev] | |
| 56 | + | level = "host" | |
| 57 | + | image = "registry.fedoraproject.org/fedora-toolbox:43" | |
| 58 | + | export = { bin = ["rg", "fd", "hx"] } | |
| 59 | + | ||
| 60 | + | [box.scratch] | |
| 61 | + | level = "workspace" | |
| 62 | + | image = "registry.fedoraproject.org/fedora-toolbox:43" | |
| 63 | + | mounts = ["~/code/thing"] | |
| 64 | + | ||
| 65 | + | [box.somegui] | |
| 66 | + | level = "sandboxed" | |
| 67 | + | app = "org.example.SomeApp" | |
| 68 | + | ``` | |
| 69 | + | ||
| 70 | + | `host` and `workspace` boxes take an `image`; a `sandboxed` box is one app, so | |
| 71 | + | it takes an `app`. | |
| 72 | + | ||
| 73 | + | ## Layering onto the base image | |
| 74 | + | ||
| 75 | + | The fourth option is putting a package into the operating system itself: | |
| 76 | + | ||
| 77 | + | rpm-ostree install <package> | |
| 78 | + | ||
| 79 | + | This does not change the running system. It stages a new deployment that takes | |
| 80 | + | effect at the next boot. `alloy pkg install` shows what is layered and which | |
| 81 | + | rows are staged rather than active, which is the single most confusing thing | |
| 82 | + | about an atomic base and the reason that tab exists. | |
| 83 | + | ||
| 84 | + | Layer sparingly. Every layered package slows down every future image update, | |
| 85 | + | and a package you layer is one that has to keep resolving against a base that | |
| 86 | + | moves. If it can be a box, make it a box. | |
| 87 | + | ||
| 88 | + | Removing one is `rpm-ostree uninstall <package>`, and it stages the removal the | |
| 89 | + | same way. | |
| 90 | + | ||
| 91 | + | ## Flathub | |
| 92 | + | ||
| 93 | + | The `flatpak` client is in the image and no Flatpaks are provisioned. Adding | |
| 94 | + | Flathub and pulling an app is the ordinary thing: | |
| 95 | + | ||
| 96 | + | flatpak install flathub org.example.SomeApp | |
| 97 | + | ||
| 98 | + | Alloy ships no graphical file manager, so this is where one comes from if you | |
| 99 | + | want one. | |
| 100 | + | ||
| 101 | + | ## Which one, in practice | |
| 102 | + | ||
| 103 | + | - **A CLI tool you use daily and Fedora has it.** Layer it, or put it in a | |
| 104 | + | `host` box and export it. Layering is simpler; the box keeps the base clean. | |
| 105 | + | - **A language toolchain for one project.** `workspace`, with the project | |
| 106 | + | directory mounted. | |
| 107 | + | - **A graphical app from the internet.** `sandboxed`. | |
| 108 | + | - **Something the desktop itself needs to work** (a compositor piece, a font, a | |
| 109 | + | daemon). Edit the Containerfile and rebuild. That is what the builder model | |
| 110 | + | is for. |
| @@ -1,0 +1,82 @@ | |||
| 1 | + | # 8. Updating and rolling back | |
| 2 | + | ||
| 3 | + | Alloy publishes no images, so there is nothing for your machine to download. | |
| 4 | + | Updating means rebuilding the image on a machine you own and switching to it. | |
| 5 | + | Rolling back means picking last boot's deployment from the boot menu. | |
| 6 | + | ||
| 7 | + | ## What your machine is running | |
| 8 | + | ||
| 9 | + | alloy update | |
| 10 | + | ||
| 11 | + | shows the deployments: which image is booted, which is staged for the next | |
| 12 | + | boot, and what can be rolled back to. It fronts `rpm-ostree status`, so the | |
| 13 | + | same information is available as: | |
| 14 | + | ||
| 15 | + | rpm-ostree status | |
| 16 | + | ||
| 17 | + | Deployments are the whole model. Nothing is ever edited in place. An update, | |
| 18 | + | a layered package, and a rollback all produce or select a deployment, and the | |
| 19 | + | switch happens at boot. | |
| 20 | + | ||
| 21 | + | ## Updating | |
| 22 | + | ||
| 23 | + | On the machine where you keep the source: | |
| 24 | + | ||
| 25 | + | cd alloy | |
| 26 | + | git pull | |
| 27 | + | build/build-iso.sh --skip-source # or build/build-image.sh --skip-bib | |
| 28 | + | ||
| 29 | + | Either one rebuilds `localhost/alloy:local`. Then, on the machine to update: | |
| 30 | + | ||
| 31 | + | bootc switch --transport containers-storage localhost/alloy:local | |
| 32 | + | systemctl reboot | |
| 33 | + | ||
| 34 | + | That adopts the locally built image in place. It is staged with A/B rollback, | |
| 35 | + | exactly like a registry-fed update would be, with the image coming from local | |
| 36 | + | container storage instead of the network. | |
| 37 | + | ||
| 38 | + | You do not reinstall. Your home directory, your accounts, and your layered | |
| 39 | + | packages survive. What you give up against a published image is the build time, | |
| 40 | + | not the machine. | |
| 41 | + | ||
| 42 | + | If the build happened somewhere else, move the image the way you would move any | |
| 43 | + | container image (`podman save` / `podman load`, or a local registry) and switch | |
| 44 | + | against that. | |
| 45 | + | ||
| 46 | + | ## Rolling back | |
| 47 | + | ||
| 48 | + | If a new image is worse: | |
| 49 | + | ||
| 50 | + | rpm-ostree rollback | |
| 51 | + | systemctl reboot | |
| 52 | + | ||
| 53 | + | The previous deployment is still on disk, so this is fast and does not need a | |
| 54 | + | network. It swaps which deployment boots by default. | |
| 55 | + | ||
| 56 | + | You can also do it without booting the broken image at all: hold `Esc` or | |
| 57 | + | `Shift` at boot to get the GRUB menu, and pick the older entry. That boots it | |
| 58 | + | once. If the older one is the one you want to keep, run `rpm-ostree rollback` | |
| 59 | + | from it. | |
| 60 | + | ||
| 61 | + | ## Why nothing updates itself | |
| 62 | + | ||
| 63 | + | An installed machine does not poll for updates. The timer that would do it is | |
| 64 | + | enabled only when the installer medium named an update target, which only a | |
| 65 | + | development build does. | |
| 66 | + | ||
| 67 | + | The consequence worth stating: **an image built in January and run until June | |
| 68 | + | carries January's packages**, including the browser, which is the program on | |
| 69 | + | your machine that faces the whole internet all day. If you run Alloy as a daily | |
| 70 | + | driver, rebuild on a rhythm you decide rather than when something breaks. | |
| 71 | + | ||
| 72 | + | `alloy update` reporting how far behind the image has fallen, with the browser | |
| 73 | + | called out rather than buried in a package count, is filed work and not yet | |
| 74 | + | shipped. Until it is, the honest answer is that the date of your last rebuild | |
| 75 | + | is the number that matters, and only you know it. | |
| 76 | + | ||
| 77 | + | ## What about `bootc upgrade` | |
| 78 | + | ||
| 79 | + | It works, and does nothing useful here: there is no registry for it to fetch | |
| 80 | + | from unless you set one up yourself. If you run your own registry, point the | |
| 81 | + | build at it with `build/build-iso.sh --update-target <registry>/alloy:43` and | |
| 82 | + | the installed machines will use the standard bootc update path. |
| @@ -1,0 +1,110 @@ | |||
| 1 | + | # 9. Files, editing, and media | |
| 2 | + | ||
| 3 | + | Alloy ships one default per job. All of them are keyboard-driven, and most of | |
| 4 | + | them are vim-shaped. | |
| 5 | + | ||
| 6 | + | ## Files: yazi | |
| 7 | + | ||
| 8 | + | yazi | |
| 9 | + | ||
| 10 | + | A two-pane file manager in the terminal, with previews. Under rio it renders | |
| 11 | + | images inline using the kitty graphics protocol rather than falling back to | |
| 12 | + | coloured blocks, which is most of the reason rio is the terminal. | |
| 13 | + | ||
| 14 | + | `?` lists its keys. `q` leaves. | |
| 15 | + | ||
| 16 | + | There is no graphical file manager in the image. Apps that need to open or save | |
| 17 | + | a file get a portal dialog, which is what a browser uses, so the daily case is | |
| 18 | + | covered. If you want one anyway, it comes from Flathub (chapter 7). | |
| 19 | + | ||
| 20 | + | ## Editing: helix | |
| 21 | + | ||
| 22 | + | hx <file> | |
| 23 | + | ||
| 24 | + | Modal, selection-first: you select and then act, so it is `3wd` where vim is | |
| 25 | + | `d3w`. Language servers, tree-sitter highlighting, and formatters are built in | |
| 26 | + | rather than assembled from plugins. It is useful with no configuration. | |
| 27 | + | ||
| 28 | + | `EDITOR` is set to `hx`, so git commit messages and everything else that | |
| 29 | + | respects `$EDITOR` open here. | |
| 30 | + | ||
| 31 | + | Alloy ships the Akari theme and a small config at `~/.config/helix/`. If you | |
| 32 | + | have vim muscle memory, expect a week or two of friction; the grammar is a real | |
| 33 | + | improvement but it is not the one your fingers know. `:tutor` is the fastest | |
| 34 | + | way through. | |
| 35 | + | ||
| 36 | + | ## PDFs: zathura | |
| 37 | + | ||
| 38 | + | zathura <file.pdf> | |
| 39 | + | ||
| 40 | + | vim keys, statusbar-only chrome. `i` toggles recolouring, which is off in the | |
| 41 | + | day theme (the page already agrees with the chrome) and on at night (an | |
| 42 | + | unrecoloured PDF in a dark session is a floodlight). | |
| 43 | + | ||
| 44 | + | zathura reads. It does not annotate, and Alloy does not ship an annotator. | |
| 45 | + | ||
| 46 | + | ## Images: imv | |
| 47 | + | ||
| 48 | + | imv <file> | |
| 49 | + | ||
| 50 | + | Wayland-native, tiny, vi-like keys. The overlay is hidden until you ask for it. | |
| 51 | + | ||
| 52 | + | ## Video and audio: mpv | |
| 53 | + | ||
| 54 | + | mpv <file-or-url> | |
| 55 | + | ||
| 56 | + | No chrome by default, hardware decoding on, screenshots to | |
| 57 | + | `~/Pictures/Screenshots`. It plays streams through yt-dlp, capped at 1080p in | |
| 58 | + | the shipped config. | |
| 59 | + | ||
| 60 | + | A fullscreen mpv window holds the screen lock off. A windowed one does not, | |
| 61 | + | because a windowed video is usually something being glanced at. | |
| 62 | + | ||
| 63 | + | ## System monitoring: bottom | |
| 64 | + | ||
| 65 | + | btm | |
| 66 | + | ||
| 67 | + | or `top`, which is aliased to it. ratatui-based, same visual family as the | |
| 68 | + | console. Clicking is disabled on purpose; it is keyboard-only. | |
| 69 | + | ||
| 70 | + | ## Disk usage: dua | |
| 71 | + | ||
| 72 | + | du | |
| 73 | + | ||
| 74 | + | is aliased to `dua interactive`. Navigate with vim keys, mark things for | |
| 75 | + | deletion, delete them. | |
| 76 | + | ||
| 77 | + | ## Clipboard history | |
| 78 | + | ||
| 79 | + | Everything you copy is recorded, text and images both. `Mod+Shift+V` opens a | |
| 80 | + | picker over the history; choose an entry and it goes back on the clipboard. | |
| 81 | + | ||
| 82 | + | The store is at `~/.local/share/cliphist/db` and needs no configuration. If you | |
| 83 | + | want a copy to never be recorded, there is no per-copy exclusion today; clear | |
| 84 | + | the history with `cliphist wipe`. | |
| 85 | + | ||
| 86 | + | ## Screenshots and annotation | |
| 87 | + | ||
| 88 | + | Covered in chapter 5. The one thing worth repeating here: `Mod+Print` opens the | |
| 89 | + | most recent capture in satty, which is where you crop, arrow, and blur before | |
| 90 | + | sending it somewhere. | |
| 91 | + | ||
| 92 | + | ## The browser | |
| 93 | + | ||
| 94 | + | Helium ships in the image as the default browser, unconfigured. It is | |
| 95 | + | ungoogled-chromium with ad blocking, tracker blocking, cookie-banner handling | |
| 96 | + | and anti-fingerprinting already on upstream, and it makes no network request on | |
| 97 | + | first launch. | |
| 98 | + | ||
| 99 | + | Alloy ships no policy file, no preference seed, no chrome CSS and no pinned | |
| 100 | + | extension for it. That is why it is the default: an app earns a recommendation | |
| 101 | + | here by not needing to be configured. Anything past what a well-behaved app | |
| 102 | + | reads from the system (light or dark, the GTK theme for dialogs, the cursor, | |
| 103 | + | the fonts) is yours to set in the browser's own settings. | |
| 104 | + | ||
| 105 | + | Firefox is one line in the Containerfile if you want Gecko, and would ship with | |
| 106 | + | no Alloy configuration on it either. | |
| 107 | + | ||
| 108 | + | Two honest notes. The browser is packaged from an upstream binary rather than | |
| 109 | + | built from source, and it is pre-1.0. And because it lives in the image, it | |
| 110 | + | updates when you rebuild the image and not before (chapter 8). |
| @@ -1,0 +1,79 @@ | |||
| 1 | + | # 10. The shell | |
| 2 | + | ||
| 3 | + | Your login shell is **nushell**. Its pipelines carry structured data rather | |
| 4 | + | than lines of text, so `ls | where size > 10mb | sort-by modified` is a whole | |
| 5 | + | pipeline and not an awk exercise. | |
| 6 | + | ||
| 7 | + | bash is untouched at `/bin/sh` and `/bin/bash`. Nothing that runs a shell | |
| 8 | + | script cares which login shell you use, so the `curl | sh` pattern and every | |
| 9 | + | system script behave exactly as they would anywhere else. If you want bash | |
| 10 | + | back: | |
| 11 | + | ||
| 12 | + | chsh -s /bin/bash | |
| 13 | + | ||
| 14 | + | ## What is already wired up | |
| 15 | + | ||
| 16 | + | - **starship** draws the prompt. | |
| 17 | + | - **zoxide** tracks directories you visit, so `z alloy` lands in that project | |
| 18 | + | from anywhere. | |
| 19 | + | - **direnv** loads a directory's `.envrc` when you enter it and unloads it when | |
| 20 | + | you leave. After editing an `.envrc`, run `direnv-reload`. | |
| 21 | + | ||
| 22 | + | All three are live at first login with nothing to set up. | |
| 23 | + | ||
| 24 | + | ## Aliases | |
| 25 | + | ||
| 26 | + | A short list, in `~/.config/nushell/aliases.nu`: | |
| 27 | + | ||
| 28 | + | | Alias | Runs | | |
| 29 | + | |---|---| | |
| 30 | + | | `ll`, `la` | `ls -la`, `ls -a` | | |
| 31 | + | | `..`, `...`, `....` | Up one, two, three directories | | |
| 32 | + | | `gs` `gd` `ga` `gc` `gp` `gl` | git status, diff, add, commit, push, log | | |
| 33 | + | | `vim`, `vi` | `hx` | | |
| 34 | + | | `du` | `dua interactive` | | |
| 35 | + | | `top` | `btm` | | |
| 36 | + | ||
| 37 | + | It is meant to stay short. If the file grows past about thirty lines, the next | |
| 38 | + | alias probably has not earned its place. | |
| 39 | + | ||
| 40 | + | ## Config | |
| 41 | + | ||
| 42 | + | | File | Holds | | |
| 43 | + | |---|---| | |
| 44 | + | | `~/.config/nushell/env.nu` | Environment: `EDITOR`, cursor theme, paths | | |
| 45 | + | | `~/.config/nushell/config.nu` | Shell behaviour | | |
| 46 | + | | `~/.config/nushell/aliases.nu` | The list above | | |
| 47 | + | | `~/.config/starship.toml` | Prompt | | |
| 48 | + | ||
| 49 | + | Note that nushell is not bash: `export FOO=bar` is `$env.FOO = "bar"`, and | |
| 50 | + | command substitution is `(...)` rather than backticks. Its own book covers the | |
| 51 | + | differences, and the migration is smaller than it looks because scripts keep | |
| 52 | + | running under bash. | |
| 53 | + | ||
| 54 | + | ## Becoming root | |
| 55 | + | ||
| 56 | + | run0 <command> | |
| 57 | + | ||
| 58 | + | `run0` is systemd's, and it is what Alloy documents instead of `sudo`. It | |
| 59 | + | authenticates through polkit rather than by setuid, and it runs the command in | |
| 60 | + | a fresh session rather than in your shell's. | |
| 61 | + | ||
| 62 | + | `sudo` still exists; nothing removes it. Alloy just does not build habits | |
| 63 | + | around it. | |
| 64 | + | ||
| 65 | + | ## Secrets | |
| 66 | + | ||
| 67 | + | Two different jobs, and they get confused for each other constantly: | |
| 68 | + | ||
| 69 | + | - **gnome-keyring** is the Secret Service provider. It is what programs call | |
| 70 | + | when they need to store a credential. You do not use it directly; it is there | |
| 71 | + | so applications that expect it work. | |
| 72 | + | - **gopass** is where you keep your own logins. It uses an age identity for | |
| 73 | + | encryption and git for syncing, so a store is a git repository of ciphertext | |
| 74 | + | and a concurrent edit is a merge conflict rather than a silently duplicated | |
| 75 | + | file. | |
| 76 | + | ||
| 77 | + | Alloy provisions neither with any content. `gopass init` sets up a store when | |
| 78 | + | you want one, and the age identity that decrypts it should never live in the | |
| 79 | + | repository it decrypts or travel with it. |
| @@ -1,0 +1,116 @@ | |||
| 1 | + | # 11. Appearance | |
| 2 | + | ||
| 3 | + | Alloy ships one design language, Akari, in two renders: **Akari Dawn** for day | |
| 4 | + | and **Akari Night** for dark. Everything the system draws is themed from it, | |
| 5 | + | including the terminal, the editor, the bar, the lock screen, notifications, | |
| 6 | + | the console, GTK dialogs, and even the virtual consoles. | |
| 7 | + | ||
| 8 | + | ## Switching between day and night | |
| 9 | + | ||
| 10 | + | alloy settings | |
| 11 | + | ||
| 12 | + | then the theme row on the System tab. Two things happen when you set it: the | |
| 13 | + | console re-themes immediately, and a mode file at `~/.config/alloy/mode` records | |
| 14 | + | your choice. | |
| 15 | + | ||
| 16 | + | The rest of the desktop follows **at your next login**. The reason is sway: it | |
| 17 | + | reads its config once at start, and the config is one of the themed files, so | |
| 18 | + | applying mid-session would need a reload and would still leave everything | |
| 19 | + | already running on the old palette. | |
| 20 | + | ||
| 21 | + | Under the hood, the login wrapper runs: | |
| 22 | + | ||
| 23 | + | alloy theme apply | |
| 24 | + | ||
| 25 | + | which copies the matching render of every themed config into your home | |
| 26 | + | directory. You can run it by hand: | |
| 27 | + | ||
| 28 | + | | Command | Effect | | |
| 29 | + | |---|---| | |
| 30 | + | | `alloy theme apply --dry-run` | Report what would change, write nothing | | |
| 31 | + | | `alloy theme apply --mode night` | Apply the night render for this run without changing your saved choice | | |
| 32 | + | | `alloy theme apply --verbose` | Name every file, including unchanged ones | | |
| 33 | + | | `alloy theme apply --force` | Overwrite files you have edited, keeping a `.alloy-bak` | | |
| 34 | + | ||
| 35 | + | **Files you have edited are never replaced.** If a config matches neither the | |
| 36 | + | day nor the night render, `alloy theme apply` treats it as yours, keeps it, and | |
| 37 | + | names it in its output. `--force` is the only way past that, and it leaves a | |
| 38 | + | backup. | |
| 39 | + | ||
| 40 | + | Swapping the theme in place, without logging out, is filed as `alloy theme | |
| 41 | + | <name>` and is not built yet. | |
| 42 | + | ||
| 43 | + | ## What the greeter does | |
| 44 | + | ||
| 45 | + | The login screen and every virtual console carry the Akari palette, applied as | |
| 46 | + | the kernel's console colour table plus a small unit at boot. There is one | |
| 47 | + | limitation worth knowing: boot and login are always Dawn, whatever your session | |
| 48 | + | is set to. Choosing between the two tables needs a system-wide setting that | |
| 49 | + | does not exist yet, since the greeter runs before any user is known. | |
| 50 | + | ||
| 51 | + | ## Wallpaper | |
| 52 | + | ||
| 53 | + | The default background is a flat colour from the palette. Alloy ships **swww** | |
| 54 | + | for image wallpapers but starts no daemon and provisions no images: | |
| 55 | + | ||
| 56 | + | swww-daemon & | |
| 57 | + | swww img ~/Pictures/wallpaper.jpg | |
| 58 | + | ||
| 59 | + | Add those to `~/.config/sway/config` if you want them at login. The curated | |
| 60 | + | wallpaper collection the design docs describe (public-domain impressionist | |
| 61 | + | paintings, chosen because they are tonally restrained and treat light as | |
| 62 | + | information) is not in the image yet. | |
| 63 | + | ||
| 64 | + | ## Night colour temperature | |
| 65 | + | ||
| 66 | + | **gammastep** is installed and not enabled. Its config at | |
| 67 | + | `~/.config/gammastep/config.ini` is set to 3700K at night and 6500K by day with | |
| 68 | + | a fade, and carries a placeholder location you have to fill in: | |
| 69 | + | ||
| 70 | + | systemctl --user enable --now gammastep | |
| 71 | + | ||
| 72 | + | This is separate from the light and dark theme. One changes what colours the | |
| 73 | + | system draws; the other changes the colour temperature of the whole display. | |
| 74 | + | ||
| 75 | + | ## Fonts | |
| 76 | + | ||
| 77 | + | | Role | Font | | |
| 78 | + | |---|---| | |
| 79 | + | | Monospace | IosevkaTerm Nerd Font Mono | | |
| 80 | + | | Sans | Atkinson Hyperlegible | | |
| 81 | + | | Serif | Not shipped; falls through to Fedora's default | | |
| 82 | + | | Emoji | Not shipped | | |
| 83 | + | ||
| 84 | + | Atkinson Hyperlegible is designed by the Braille Institute to make letters as | |
| 85 | + | distinguishable from each other as possible, which is the most literal answer | |
| 86 | + | to "make UI text readable". If you want something more conventional, Inter is a | |
| 87 | + | one-line swap in `~/.config/fontconfig/fonts.conf` and the GTK settings. | |
| 88 | + | ||
| 89 | + | CJK, Arabic, Hebrew, Indic and Thai coverage comes from Fedora's font | |
| 90 | + | metapackages, so web pages in those scripts render. **Emoji do not.** No emoji | |
| 91 | + | font is installed and the fontconfig alias for them was removed rather than | |
| 92 | + | left pointing at something absent. Emoji show as missing glyphs. Installing any | |
| 93 | + | emoji font makes them work with no further configuration. | |
| 94 | + | ||
| 95 | + | ## Cursor | |
| 96 | + | ||
| 97 | + | Bibata Modern Classic at size 24, set three ways because different apps read | |
| 98 | + | the cursor from different places: `~/.icons/default/index.theme`, the GTK | |
| 99 | + | settings files, and `XCURSOR_THEME` in the nushell environment. Change all | |
| 100 | + | three if you change it at all. | |
| 101 | + | ||
| 102 | + | ## GTK apps | |
| 103 | + | ||
| 104 | + | GTK 3 and 4 apps get the Akari palette layered over adw-gtk3, through | |
| 105 | + | `~/.config/gtk-3.0/gtk.css` and `~/.config/gtk-4.0/gtk.css`. That covers the | |
| 106 | + | portal file dialogs, swayosd's overlays, and most modern GTK apps. | |
| 107 | + | ||
| 108 | + | Two gaps, stated rather than discovered: there is no dark-mode variant of the | |
| 109 | + | GTK patch yet (it is light-first), and Qt apps are not themed at all. | |
| 110 | + | ||
| 111 | + | ## Terminal, editor, and everything else | |
| 112 | + | ||
| 113 | + | Each adopted tool has its own themed config under `~/.config/`, rendered from | |
| 114 | + | the same palette: rio, helix, yazi, mako, swaylock, satty, bottom, zathura, | |
| 115 | + | imv, mpv, swayosd, and the sway config itself. Editing one is fine; the theme | |
| 116 | + | system will notice and stop overwriting it. |
| @@ -1,0 +1,101 @@ | |||
| 1 | + | # 12. Network, mesh, sync, and backup | |
| 2 | + | ||
| 3 | + | Alloy assumes the machine is disposable and your state is not. An install | |
| 4 | + | should be rejoinable: build the medium, install, sign in to two things, and | |
| 5 | + | your files and your other machines are there. | |
| 6 | + | ||
| 7 | + | Both enrollments are opt-in. Nothing connects to anything until you say so. | |
| 8 | + | ||
| 9 | + | ## Wifi and wired networking | |
| 10 | + | ||
| 11 | + | alloy net | |
| 12 | + | ||
| 13 | + | lists interfaces and connections. Connecting, disconnecting, and toggling the | |
| 14 | + | wifi radio all work without any privilege, because NetworkManager grants those | |
| 15 | + | to an active session. | |
| 16 | + | ||
| 17 | + | Joining a network you have never joined before is a different permission, and | |
| 18 | + | the console does not yet ask for it. For a new network: | |
| 19 | + | ||
| 20 | + | run0 nmcli device wifi connect "Network Name" --ask | |
| 21 | + | ||
| 22 | + | Once it is saved, `alloy net` connects to it like any other. | |
| 23 | + | ||
| 24 | + | ## Mesh: Tailscale | |
| 25 | + | ||
| 26 | + | alloy mesh | |
| 27 | + | ||
| 28 | + | A machine that has not joined anything shows an offer rather than an empty | |
| 29 | + | list. Press `e` to set the control server before signing in: leave it empty for | |
| 30 | + | tailscale.com, or enter a URL for a self-hosted Headscale. | |
| 31 | + | ||
| 32 | + | Signing in escalates to root and then waits on a browser login, so the console | |
| 33 | + | gets out of the way while that happens and comes back into the peer list | |
| 34 | + | afterwards. | |
| 35 | + | ||
| 36 | + | Once enrolled, the view lists your peers, whether each is online, when it was | |
| 37 | + | last seen, and lets you pick or clear an exit node. This machine is listed | |
| 38 | + | first. If you are on a self-hosted control plane, the title says so. | |
| 39 | + | ||
| 40 | + | The plain command is `run0 tailscale up`, and `alloy tail` is kept as an alias | |
| 41 | + | for the verb. | |
| 42 | + | ||
| 43 | + | Alloy does not ship a Headscale server. That is fleet-admin work, not | |
| 44 | + | client-OS work. | |
| 45 | + | ||
| 46 | + | ## File sync: Syncthing | |
| 47 | + | ||
| 48 | + | alloy sync | |
| 49 | + | ||
| 50 | + | Three tabs: **folders**, **devices**, and **pending**. | |
| 51 | + | ||
| 52 | + | - Folders shows each synchronized folder's path, share mode, and whether it is | |
| 53 | + | paused. `a` adds one, `d` removes one, and both confirms tell you what is | |
| 54 | + | *not* deleted, because "remove folder" must never read as "delete my | |
| 55 | + | documents". | |
| 56 | + | - Devices shows connection state, this machine first. | |
| 57 | + | - Pending lists devices that have added you and are knocking. Accepting one | |
| 58 | + | finishes the pairing. | |
| 59 | + | ||
| 60 | + | Enrollment is a user service and needs no root: | |
| 61 | + | ||
| 62 | + | systemctl --user enable --now syncthing.service | |
| 63 | + | ||
| 64 | + | One asymmetry to know about: you can accept a pending device but not decline | |
| 65 | + | it. The command-line client Syncthing ships has no verb for dropping a pending | |
| 66 | + | entry, so an unaccepted device stays listed. The view says so when you press | |
| 67 | + | `d` there. | |
| 68 | + | ||
| 69 | + | Syncthing's own web UI is still at `127.0.0.1:8384` for anything the console | |
| 70 | + | does not cover. | |
| 71 | + | ||
| 72 | + | ## Backup: restic | |
| 73 | + | ||
| 74 | + | restic is in the image and Alloy prescribes no policy. Where you back up to is | |
| 75 | + | answerable only by you, so there is no default repository, schedule, or | |
| 76 | + | retention. | |
| 77 | + | ||
| 78 | + | This matters more than it looks. Sync is mesh plus latest-wins; it gets your | |
| 79 | + | files onto the new machine. It does not get back the file you deleted three | |
| 80 | + | weeks ago and only just noticed. That case needs versioned backup, which means | |
| 81 | + | configuring restic: | |
| 82 | + | ||
| 83 | + | restic init --repo <destination> | |
| 84 | + | restic backup ~/Documents ~/Pictures | |
| 85 | + | restic snapshots | |
| 86 | + | ||
| 87 | + | Any of restic's backends work: local disk, SFTP, S3, B2, rclone. A systemd | |
| 88 | + | user timer is the usual way to make it recurring. | |
| 89 | + | ||
| 90 | + | There is no `alloy backup` view. It is a candidate, not a plan. | |
| 91 | + | ||
| 92 | + | ## What is deliberately not synced | |
| 93 | + | ||
| 94 | + | - **Secrets.** Too personal, and the security models vary too much for a | |
| 95 | + | defensible default. gopass (chapter 10) is the shipped tool, and you decide | |
| 96 | + | what it holds and where it goes. | |
| 97 | + | - **Dotfiles.** Syncthing can carry `~/.config` and Alloy does not set that up | |
| 98 | + | for you. | |
| 99 | + | - **The first-boot marker.** Deliberately never replicated: a synced copy would | |
| 100 | + | suppress the enrollment screen on the next machine you set up, which is | |
| 101 | + | exactly the machine that needs it. |
| @@ -1,0 +1,135 @@ | |||
| 1 | + | # 13. Hardware and peripherals | |
| 2 | + | ||
| 3 | + | ## Displays | |
| 4 | + | ||
| 5 | + | alloy display | |
| 6 | + | ||
| 7 | + | lists the outputs sway is driving, with their scale and whether they are on. | |
| 8 | + | `s` walks the scale ladder. The console writes what it changes to | |
| 9 | + | `~/.config/sway/config.d/50-display.conf`, which the shipped sway config | |
| 10 | + | includes after the system drop-ins, so your setting beats the image's. | |
| 11 | + | ||
| 12 | + | A fresh install seeds that file at install time by reading the panel's size out | |
| 13 | + | of EDID and snapping to the nearest scale, so a high-density laptop boots at a | |
| 14 | + | sensible scale rather than at 1.0. A panel that cannot be read seeds nothing, | |
| 15 | + | which means 1.0 and one keypress from correct. | |
| 16 | + | ||
| 17 | + | Mode picking (refresh rate and resolution) is not built. Multi-output setups | |
| 18 | + | are the untested case: nothing has attached a second display to an Alloy | |
| 19 | + | machine yet, so if you do, expect the display view to be the rough part. | |
| 20 | + | ||
| 21 | + | Anything the view does not cover is a sway `output` line in that same file. | |
| 22 | + | `swaymsg -t get_outputs` names your outputs. | |
| 23 | + | ||
| 24 | + | ## Audio | |
| 25 | + | ||
| 26 | + | alloy audio | |
| 27 | + | ||
| 28 | + | Two panes: the streams that are playing and the devices they could play | |
| 29 | + | through. Move a stream from one to the other, change volumes, pick defaults. | |
| 30 | + | The Fn keys handle the everyday case with an on-screen indicator. | |
| 31 | + | ||
| 32 | + | Underneath is PipeWire, and `pactl` is the command the view shows you. | |
| 33 | + | ||
| 34 | + | ## Brightness | |
| 35 | + | ||
| 36 | + | The brightness keys work, through the same on-screen indicator. If they do not, | |
| 37 | + | see the note in chapter 14: it takes two separate grants (a udev rule and your | |
| 38 | + | account being in the `video` group) and either one alone leaves the keys dead | |
| 39 | + | silently. | |
| 40 | + | ||
| 41 | + | Screen dimming before the lock is separate, and handled by `alloy-dim` from the | |
| 42 | + | idle configuration. | |
| 43 | + | ||
| 44 | + | ## Power and idle | |
| 45 | + | ||
| 46 | + | The shipped idle behaviour, in `~/.config/sway/config`: | |
| 47 | + | ||
| 48 | + | | After | What happens | | |
| 49 | + | |---|---| | |
| 50 | + | | 4.5 minutes | The screen dims. Move the mouse or type and it comes back | | |
| 51 | + | | 5 minutes | swaylock takes over | | |
| 52 | + | | 10 minutes | Displays power off | | |
| 53 | + | | Lid close or suspend | Always locks first | | |
| 54 | + | ||
| 55 | + | The dim stage is the closest thing to a grace period on offer: upstream | |
| 56 | + | swaylock has no `--grace` flag, and thirty seconds of dimmed screen is enough | |
| 57 | + | to notice before the lock arrives. | |
| 58 | + | ||
| 59 | + | Fullscreen mpv, imv, and the browser hold the lock off. A fullscreen terminal | |
| 60 | + | deliberately does not: walking away from a shell should not leave the machine | |
| 61 | + | unlocked indefinitely. | |
| 62 | + | ||
| 63 | + | ## Fingerprint reader | |
| 64 | + | ||
| 65 | + | fprintd is installed, and nothing is enrolled, so nothing asks for a finger | |
| 66 | + | until you do: | |
| 67 | + | ||
| 68 | + | fprintd-enroll | |
| 69 | + | ||
| 70 | + | Once enrolled, the lock screen, the greeter and `run0` all accept it from that | |
| 71 | + | one step, because they share a PAM stack. A finger that does not match, a | |
| 72 | + | reader that is busy, and a user with nothing enrolled all fall through to the | |
| 73 | + | password prompt. | |
| 74 | + | ||
| 75 | + | ## Printing | |
| 76 | + | ||
| 77 | + | Alloy prints to **IPP Everywhere (driverless) printers and nothing else**. | |
| 78 | + | There are no vendor driver packages in the image, and there will not be. Nearly | |
| 79 | + | every printer sold since about 2015 speaks the protocol. | |
| 80 | + | ||
| 81 | + | A driverless printer on the same network appears by itself; discovery over mDNS | |
| 82 | + | is already set up. The surface for anything else is CUPS' own web interface: | |
| 83 | + | ||
| 84 | + | http://localhost:631 | |
| 85 | + | ||
| 86 | + | The daemon is socket-activated, so nothing runs until something connects to it. | |
| 87 | + | ||
| 88 | + | A printer that needs a vendor driver is not supported. Saying so here is better | |
| 89 | + | than you discovering it at the moment you need to print. | |
| 90 | + | ||
| 91 | + | ## Scanning | |
| 92 | + | ||
| 93 | + | Not shipped. Scanning means per-device backends and USB permission work with | |
| 94 | + | opaque failures, and no one has needed one yet. If you do: | |
| 95 | + | ||
| 96 | + | rpm-ostree install sane-backends | |
| 97 | + | ||
| 98 | + | Worth trying first: most network scanners scan to a folder or to email with no | |
| 99 | + | host driver at all. | |
| 100 | + | ||
| 101 | + | ## Bluetooth | |
| 102 | + | ||
| 103 | + | bluez is installed and running. PipeWire's Bluetooth plugins are in the image, | |
| 104 | + | LC3 and AAC included, so a paired headset plays. | |
| 105 | + | ||
| 106 | + | What is missing is a view, not a daemon. Pairing today is the interactive | |
| 107 | + | prompt: | |
| 108 | + | ||
| 109 | + | bluetoothctl | |
| 110 | + | # scan on, pair <MAC>, trust <MAC>, connect <MAC> | |
| 111 | + | ||
| 112 | + | An `alloy bluetooth` view is intended and not built. | |
| 113 | + | ||
| 114 | + | ## USB storage | |
| 115 | + | ||
| 116 | + | There is no automounter. Plugging in a stick makes the kernel see it and | |
| 117 | + | nothing else happens on screen. | |
| 118 | + | ||
| 119 | + | lsblk | |
| 120 | + | run0 mkdir -p /mnt/stick | |
| 121 | + | run0 mount /dev/sdX1 /mnt/stick | |
| 122 | + | # and when you are done | |
| 123 | + | run0 umount /mnt/stick | |
| 124 | + | ||
| 125 | + | This is a known gap rather than a position. | |
| 126 | + | ||
| 127 | + | ## Locale and keymap | |
| 128 | + | ||
| 129 | + | Both are rows on the System tab of `alloy settings`, fronting `localectl`. | |
| 130 | + | ||
| 131 | + | One caveat: the image carries a minimal set of glibc language packs. Setting a | |
| 132 | + | locale the image cannot deliver records your choice and gives you no | |
| 133 | + | translations, because the data is not there. If you need a locale beyond | |
| 134 | + | English, layer its `glibc-langpack-*` package (chapter 7) or add it to the | |
| 135 | + | Containerfile and rebuild. |
| @@ -1,0 +1,199 @@ | |||
| 1 | + | # 14. Troubleshooting | |
| 2 | + | ||
| 3 | + | ## The general moves | |
| 4 | + | ||
| 5 | + | **Get a console that is not sway.** `Ctrl+Alt+F2` through `F6` are virtual | |
| 6 | + | terminals. They are themed the same way and they work when the session does | |
| 7 | + | not. `Ctrl+Alt+F1` goes back to the greeter. | |
| 8 | + | ||
| 9 | + | **Read the logs.** | |
| 10 | + | ||
| 11 | + | journalctl -b -p err # this boot, errors and worse | |
| 12 | + | journalctl --user -b # your session's services | |
| 13 | + | journalctl -b -u greetd # the login screen | |
| 14 | + | ||
| 15 | + | **Reload sway** after editing its config: `Mod+Shift+C`. | |
| 16 | + | ||
| 17 | + | **Boot the previous image.** Hold `Esc` or `Shift` at boot for the GRUB menu | |
| 18 | + | and pick the older deployment. Nothing you do to the running system can take | |
| 19 | + | that away, which is the point of an atomic base. | |
| 20 | + | ||
| 21 | + | --- | |
| 22 | + | ||
| 23 | + | ## The session | |
| 24 | + | ||
| 25 | + | ### Nothing opens when I press Mod+Return | |
| 26 | + | ||
| 27 | + | Check the config's terminal name. Fedora packages the terminal as `rio` but | |
| 28 | + | installs its binary as `rioterm`, and a config naming `rio` leaves you with no | |
| 29 | + | way to open a terminal at all. | |
| 30 | + | ||
| 31 | + | Two ways out that do not need a terminal: `Mod+D` opens the launcher, and | |
| 32 | + | `Ctrl+Alt+F2` gets you a virtual console where you can edit | |
| 33 | + | `~/.config/sway/config` and log back in. | |
| 34 | + | ||
| 35 | + | ### I edited the sway config and the session will not start | |
| 36 | + | ||
| 37 | + | Log in on a virtual console and check it: | |
| 38 | + | ||
| 39 | + | sway --validate | |
| 40 | + | ||
| 41 | + | Then fix the file, or move it aside to fall back to the shipped one: | |
| 42 | + | ||
| 43 | + | mv ~/.config/sway/config ~/.config/sway/config.broken | |
| 44 | + | alloy theme apply | |
| 45 | + | ||
| 46 | + | ### The screen locked and I cannot unlock it | |
| 47 | + | ||
| 48 | + | Type your password even if nothing is drawn; swaylock accepts input before it | |
| 49 | + | has anything to show. If the lock has genuinely crashed, switch to a virtual | |
| 50 | + | console and kill it: | |
| 51 | + | ||
| 52 | + | pkill swaylock | |
| 53 | + | ||
| 54 | + | That leaves an unlocked session, so do it only at a machine you trust. | |
| 55 | + | ||
| 56 | + | ### My session locks while I am watching a video | |
| 57 | + | ||
| 58 | + | Only a handful of applications hold the lock off, and only when fullscreen: | |
| 59 | + | mpv, imv, and the browser. Add yours in `~/.config/sway/config` next to the | |
| 60 | + | existing `inhibit_idle fullscreen` lines. A blanket rule is deliberately not | |
| 61 | + | shipped, because it would make walking away from a fullscreen terminal leave | |
| 62 | + | the machine unlocked. | |
| 63 | + | ||
| 64 | + | --- | |
| 65 | + | ||
| 66 | + | ## Hardware | |
| 67 | + | ||
| 68 | + | ### The brightness keys do nothing | |
| 69 | + | ||
| 70 | + | This one is silent by design of the underlying pieces, so check both halves: | |
| 71 | + | ||
| 72 | + | groups | grep video # your account is in the video group | |
| 73 | + | ls -l /sys/class/backlight/*/brightness # group-writable, group video | |
| 74 | + | ||
| 75 | + | Brightness is a direct write to a sysfs file. It takes a udev rule to make that | |
| 76 | + | file writable and your account being in the `video` group for the rule to grant | |
| 77 | + | anything. Either one alone leaves the keys dead with no error anywhere: the | |
| 78 | + | process that would have complained has nowhere to log. | |
| 79 | + | ||
| 80 | + | Volume keys use a different path entirely (PipeWire, no privilege), which is | |
| 81 | + | why one can work while the other does not. | |
| 82 | + | ||
| 83 | + | ### The volume overlay never appears | |
| 84 | + | ||
| 85 | + | `swayosd-server` is started by the sway config, not by a systemd unit. If it | |
| 86 | + | died, restart it: | |
| 87 | + | ||
| 88 | + | swayosd-server & | |
| 89 | + | ||
| 90 | + | ### Print Screen seems to do nothing | |
| 91 | + | ||
| 92 | + | It probably worked. Check `~/Pictures/Screenshots`. Every capture also raises a | |
| 93 | + | notification, so if you get neither the file nor the notification, run the | |
| 94 | + | script by hand to see the error: | |
| 95 | + | ||
| 96 | + | alloy-shot output | |
| 97 | + | ||
| 98 | + | ### A second monitor is not behaving | |
| 99 | + | ||
| 100 | + | This is the least tested part of the system. `swaymsg -t get_outputs` shows | |
| 101 | + | what sway sees, and `~/.config/sway/config.d/50-display.conf` is where to write | |
| 102 | + | `output` lines by hand. `alloy display` will not pick modes yet. | |
| 103 | + | ||
| 104 | + | --- | |
| 105 | + | ||
| 106 | + | ## The console | |
| 107 | + | ||
| 108 | + | ### alloy net cannot join a new network | |
| 109 | + | ||
| 110 | + | Connecting to a saved network needs no privilege; creating one does, and the | |
| 111 | + | console does not escalate yet. Use: | |
| 112 | + | ||
| 113 | + | run0 nmcli device wifi connect "Network Name" --ask | |
| 114 | + | ||
| 115 | + | ### alloy pkg or alloy update says it cannot read the system | |
| 116 | + | ||
| 117 | + | Those two tabs front `rpm-ostree`, which exists only on an ostree system. If | |
| 118 | + | you are running the console somewhere else, that message is correct rather than | |
| 119 | + | broken. | |
| 120 | + | ||
| 121 | + | ### The console will not start at all | |
| 122 | + | ||
| 123 | + | It needs a theme on its search path and fails loudly if there is none. Two | |
| 124 | + | verbs deliberately survive that, because they are on the login path: | |
| 125 | + | `alloy theme apply` and `alloy status --bar`. If the console is broken but the | |
| 126 | + | bar still draws, the theme directory is what to look at | |
| 127 | + | (`/usr/share/alloy/themes`). | |
| 128 | + | ||
| 129 | + | --- | |
| 130 | + | ||
| 131 | + | ## Appearance | |
| 132 | + | ||
| 133 | + | ### I switched to night and nothing changed | |
| 134 | + | ||
| 135 | + | The switch applies at the next login. Log out and back in, or run | |
| 136 | + | `alloy theme apply` and restart the affected programs. sway itself needs the | |
| 137 | + | re-login regardless, because it reads its config exactly once. | |
| 138 | + | ||
| 139 | + | ### alloy theme apply says it skipped my files | |
| 140 | + | ||
| 141 | + | It found a config that matches neither the day nor the night render, decided it | |
| 142 | + | was yours, and left it alone. That is the intended behaviour. If you want the | |
| 143 | + | shipped render back: | |
| 144 | + | ||
| 145 | + | alloy theme apply --force | |
| 146 | + | ||
| 147 | + | which keeps your version as a `.alloy-bak` beside it. | |
| 148 | + | ||
| 149 | + | ### Some characters render as boxes | |
| 150 | + | ||
| 151 | + | If they are emoji, that is expected: no emoji font is installed. Install any | |
| 152 | + | one and fontconfig picks it up with no further configuration. | |
| 153 | + | ||
| 154 | + | If they are not emoji, `fc-list :lang=<code>` will say whether anything in the | |
| 155 | + | image covers that script. | |
| 156 | + | ||
| 157 | + | ### The browser is light when my desktop is dark | |
| 158 | + | ||
| 159 | + | System appearance reaches the browser through the desktop portal rather than | |
| 160 | + | through any file Alloy ships, and that path has not been verified on real | |
| 161 | + | hardware yet. If it does not work, set the theme in the browser's own settings; | |
| 162 | + | Alloy does not ship browser configuration to fix it with. | |
| 163 | + | ||
| 164 | + | --- | |
| 165 | + | ||
| 166 | + | ## Disks and boot | |
| 167 | + | ||
| 168 | + | ### The machine asks for a passphrase it never asked for before | |
| 169 | + | ||
| 170 | + | The TPM stopped answering: it was cleared, the board changed, or the disk moved | |
| 171 | + | to another machine. Type the passphrase you set at install. If you do not have | |
| 172 | + | it, this is what the eight-word recovery phrase from the installer is for. | |
| 173 | + | ||
| 174 | + | Without either one, the data is gone. That is what encryption means. | |
| 175 | + | ||
| 176 | + | ### The new image is worse than the old one | |
| 177 | + | ||
| 178 | + | rpm-ostree rollback | |
| 179 | + | systemctl reboot | |
| 180 | + | ||
| 181 | + | Or pick the previous entry in the GRUB menu at boot. See chapter 8. | |
| 182 | + | ||
| 183 | + | ### I layered a package and now the system will not boot | |
| 184 | + | ||
| 185 | + | Boot the previous deployment from the GRUB menu, then remove it: | |
| 186 | + | ||
| 187 | + | rpm-ostree uninstall <package> | |
| 188 | + | ||
| 189 | + | Layered packages are the most common way to break an otherwise reliable base, | |
| 190 | + | which is the argument in chapter 7 for putting things in boxes instead. | |
| 191 | + | ||
| 192 | + | --- | |
| 193 | + | ||
| 194 | + | ## Reporting something | |
| 195 | + | ||
| 196 | + | Alloy is pre-v0 and this manual describes a moving system. If something here is | |
| 197 | + | wrong, the repository is at `makenot.work/git/max/alloy` and the design | |
| 198 | + | documents in `docs/` say what each piece is supposed to do, which is usually | |
| 199 | + | enough to tell a bug from a decision. |
| @@ -1,0 +1,100 @@ | |||
| 1 | + | # 15. Questions | |
| 2 | + | ||
| 3 | + | **Where do I download Alloy?** | |
| 4 | + | ||
| 5 | + | You do not. You build it. Alloy publishes source and never publishes a binary | |
| 6 | + | image, so what you boot is the thing you configured on your own machine. See | |
| 7 | + | chapter 2. | |
| 8 | + | ||
| 9 | + | **Can I build it on a Mac or on Windows?** | |
| 10 | + | ||
| 11 | + | No. The build needs Linux with podman, real disk, and a long wall clock. There | |
| 12 | + | is no path to an Alloy ISO from either. | |
| 13 | + | ||
| 14 | + | **How do I install software?** | |
| 15 | + | ||
| 16 | + | Not with `dnf`. Chapter 7 is the whole answer: pick how much of your machine | |
| 17 | + | the software should reach, and Alloy picks the mechanism from that. | |
| 18 | + | ||
| 19 | + | **How do I update?** | |
| 20 | + | ||
| 21 | + | Rebuild the image and `bootc switch` to it. Your home directory and your | |
| 22 | + | layered packages survive; you never reinstall. Chapter 8. | |
| 23 | + | ||
| 24 | + | **Does Alloy phone home?** | |
| 25 | + | ||
| 26 | + | No. Nothing enrolls, checks, or reports without you asking. The update timer is | |
| 27 | + | disabled on any machine installed from a locally built medium, Tailscale and | |
| 28 | + | Syncthing are both off until you enroll them, and the browser makes no network | |
| 29 | + | request on first launch. | |
| 30 | + | ||
| 31 | + | **Is it Rust?** | |
| 32 | + | ||
| 33 | + | The parts Alloy writes are. The parts it adopts are whatever they are: sway is | |
| 34 | + | C, Tailscale and Syncthing are Go, CUPS is C. Where a competitive Rust option | |
| 35 | + | exists it gets picked, and where one does not the gap is named rather than | |
| 36 | + | papered over. | |
| 37 | + | ||
| 38 | + | **Why sway and not Hyprland or niri?** | |
| 39 | + | ||
| 40 | + | Alloy wants the i3 model: predictable, workspace-based, no scrolling columns | |
| 41 | + | and no animation. sway is that model, mature, and well packaged, and the whole | |
| 42 | + | sway ecosystem (lock, idle, bar, OSD) fits behind it with no glue. | |
| 43 | + | ||
| 44 | + | **Why is there no settings app?** | |
| 45 | + | ||
| 46 | + | There is: it is `alloy settings`, and it runs in a terminal. Every action it | |
| 47 | + | takes prints the command it ran, so the console teaches the system instead of | |
| 48 | + | hiding it. | |
| 49 | + | ||
| 50 | + | **Can I use bash instead of nushell?** | |
| 51 | + | ||
| 52 | + | Yes: `chsh -s /bin/bash`. bash is untouched at `/bin/sh` and `/bin/bash`, so | |
| 53 | + | nothing else on the system changes either way. | |
| 54 | + | ||
| 55 | + | **Can I use vim instead of helix?** | |
| 56 | + | ||
| 57 | + | Yes, install it. helix is the default because it is useful with no | |
| 58 | + | configuration, which is the same test that picked every other default here. If | |
| 59 | + | you would rather assemble your editor from plugins, nothing stops you. | |
| 60 | + | ||
| 61 | + | **Why does my emoji not render?** | |
| 62 | + | ||
| 63 | + | No emoji font is shipped. Alloy uses none in its own interface, so it carries | |
| 64 | + | none. Install any emoji font and it works immediately. | |
| 65 | + | ||
| 66 | + | **Can I put GNOME or KDE on it?** | |
| 67 | + | ||
| 68 | + | You can layer whatever you want, but at that point you are running Fedora with | |
| 69 | + | extra steps. Alloy is the curation; removing it leaves the base. | |
| 70 | + | ||
| 71 | + | **Is my data safe if I lose the machine?** | |
| 72 | + | ||
| 73 | + | Only if you encrypted the disk at install (chapter 3). Alloy does not encrypt | |
| 74 | + | by default and does not pretend to. | |
| 75 | + | ||
| 76 | + | **What happens if the TPM fails on an encrypted machine?** | |
| 77 | + | ||
| 78 | + | You type the passphrase you set, or the eight-word recovery phrase the | |
| 79 | + | installer showed you. Both are enrolled precisely because a TPM-only setup has | |
| 80 | + | one failure mode that ends in a lost disk. | |
| 81 | + | ||
| 82 | + | **Is there a graphical file manager, launcher, or editor?** | |
| 83 | + | ||
| 84 | + | No. yazi, `Mod+D`, and helix are the answers. If you want a graphical file | |
| 85 | + | manager, Flathub has several and chapter 7 explains how to install one. | |
| 86 | + | ||
| 87 | + | **How stable is this?** | |
| 88 | + | ||
| 89 | + | Pre-v0. The base underneath it is Fedora and is as stable as Fedora, but the | |
| 90 | + | console, the installer and the image composition are young, and parts of the | |
| 91 | + | system named in this manual are not built yet. Every one of those is called out | |
| 92 | + | where it comes up rather than described in the future tense. | |
| 93 | + | ||
| 94 | + | **Where is the rest of the documentation?** | |
| 95 | + | ||
| 96 | + | `docs/` in the repository. `MANIFESTO.md` is what Alloy is and who it is for, | |
| 97 | + | `STACK.md` is every pick with its reasoning and what was rejected, `CONSOLE.md` | |
| 98 | + | is the console's design, `IMAGE.md` is how the image is composed, and | |
| 99 | + | `CONTINUITY.md` is the sync and mesh story. They are written for people working | |
| 100 | + | on Alloy, and they are the honest record of why each default is what it is. |
| @@ -1,0 +1,43 @@ | |||
| 1 | + | # The Alloy Manual | |
| 2 | + | ||
| 3 | + | Alloy is an opinionated tiling user layer for Fedora Silverblue: an immutable | |
| 4 | + | base, the sway compositor, a curated terminal-first stack, and one authored | |
| 5 | + | control surface, the `alloy` console. | |
| 6 | + | ||
| 7 | + | This manual is for people who run Alloy. It says what the system does, which | |
| 8 | + | keys do it, and what to do when something does not work. The design documents | |
| 9 | + | one directory up (`docs/MANIFESTO.md`, `docs/STACK.md`, `docs/CONSOLE.md` and | |
| 10 | + | the rest) explain why each pick was made; they are written for whoever works on | |
| 11 | + | Alloy, not for whoever uses it. Nothing here replaces them. | |
| 12 | + | ||
| 13 | + | Alloy is pre-v0. Where a thing is not built yet, this manual says so instead of | |
| 14 | + | describing it in the future tense. | |
| 15 | + | ||
| 16 | + | ## Chapters | |
| 17 | + | ||
| 18 | + | 1. [What Alloy is](01-what-alloy-is.md) | |
| 19 | + | 2. [Building your image](02-building-your-image.md) | |
| 20 | + | 3. [Installing](03-installing.md) | |
| 21 | + | 4. [The first fifteen minutes](04-first-fifteen-minutes.md) | |
| 22 | + | 5. [Keybindings](05-keybindings.md) | |
| 23 | + | 6. [The console](06-the-console.md) | |
| 24 | + | 7. [Installing software](07-installing-software.md) | |
| 25 | + | 8. [Updating and rolling back](08-updating-and-rolling-back.md) | |
| 26 | + | 9. [Files, editing, and media](09-files-and-apps.md) | |
| 27 | + | 10. [The shell](10-the-shell.md) | |
| 28 | + | 11. [Appearance](11-appearance.md) | |
| 29 | + | 12. [Network, mesh, sync, and backup](12-continuity.md) | |
| 30 | + | 13. [Hardware and peripherals](13-hardware.md) | |
| 31 | + | 14. [Troubleshooting](14-troubleshooting.md) | |
| 32 | + | 15. [Questions](15-faq.md) | |
| 33 | + | ||
| 34 | + | ## Two things to know before anything else | |
| 35 | + | ||
| 36 | + | **Nobody downloads Alloy.** There is no image to fetch and no registry to pull | |
| 37 | + | from. You take the source, build an installer ISO on your own Linux machine, | |
| 38 | + | and write it to a USB stick. Chapter 2 covers it. | |
| 39 | + | ||
| 40 | + | **An installed machine never reaches out on its own.** It does not check for | |
| 41 | + | updates, does not phone home, and does not enroll in anything until you ask. | |
| 42 | + | Updating means rebuilding the image and switching to it, which chapter 8 | |
| 43 | + | covers. |