docs: update readme

This commit is contained in:
Youwen Wu 2025-01-16 17:10:06 -08:00
parent 01afc09c18
commit ef7beee001
Signed by: youwen5
GPG key ID: 865658ED1FE61EC3

278
README.md
View file

@ -1,203 +1,129 @@
# liminalOS
This is a repository that implements liminalOS, my personal Linux distribution
based on [NixOS](https://nixos.org/).
Time wasted writing Nix code:
![](https://wakatime.com/badge/user/018dc5b8-ba5a-4572-a38a-b526d1b28240/project/c59b3d5e-0c9c-4bd5-a752-e75522ab0cdc.svg) + [![wakatime](https://wakatime.com/badge/user/018dc5b8-ba5a-4572-a38a-b526d1b28240/project/de5e82f8-8a09-42cb-ae45-9c80f2ab5a41.svg)](https://wakatime.com/badge/user/018dc5b8-ba5a-4572-a38a-b526d1b28240/project/de5e82f8-8a09-42cb-ae45-9c80f2ab5a41)
based on [NixOS](https://nixos.org/). The most overengineered personal
computing environment, ever. Imagine having to `vim` into source code and
recompile an entire operating system to change a font. Yes, I use this on a
daily basis.
This repository exposes a NixOS module that declares the entire liminalOS
operating system. It aims to be an easy way to both set up a brand new system
with my opinionated configurations, and also inject into an existing NixOS
configuration.
Reference implementations of liminalOS on actual working systems is in
[./reference](./reference).
My reference implementations of liminalOS on actual working systems are
available [here](./reference).
liminalOS is currently in a heavily experimental state, but it is used in
production every day!
You can try it with `nix flake init -t github:youwen5/liminalOS#liminalOS`,
which will create a sample configuration flake along with corresponding files.
You can try it with `nix flake init -t github:youwen5/liminalOS`, which will
create a sample configuration flake along with corresponding files. Keep in
mind you'll have to do a little bit of work in these files to get a working
system configuration. Some Nix knowledge is expected, but comments are there to
help!
Many have written at length about the virtues of NixOS and _declarative
configuration_ and _immutability_ and such. I doubt what I have to say is
particularly novel, but I'll leave a few thoughts about Nix and NixOS and why
they do things better anyways. In particular, instead of immediately
evangelizing about the virtues of Nix, I'll first motivate the reasons for why
I chose a tool with exactly its properties, based on my use case (but not to
worry, the evangelizing will come later).
```
flowchart TB
subgraph "Core System Layer"
NixOS["NixOS/Darwin Base"]
SysMod["System Modules"]:::sysmod
HM["Home Manager"]:::hm
end
Essentially: allow me to introduce you to the
origins of [NixOS God
Complex](https://www.reddit.com/r/NixOS/comments/kauf1m/dealing_with_post_nixflake_god_complex/).
subgraph "Platform Modules"
subgraph "Linux Modules"
LinuxCore["Linux Core"]:::linux
Desktop["Desktop Environment"]:::linux
Audio["Audio System"]:::linux
Gaming["Gaming Support"]:::linux
Graphics["Graphics"]:::linux
end
If you would like advice on whether or not to use NixOS:
subgraph "Darwin Modules"
DarwinCore["Darwin Core"]:::darwin
Homebrew["Homebrew"]:::darwin
WM["Window Management"]:::darwin
end
end
<details> <summary>see <a
href="https://github.com/hlissner/dotfiles">hlissner's</a> breakdown,
reproduced below:</summary> Should I use NixOS?
subgraph "Home Manager Layer"
CommonMod["Common Modules"]:::hmmod
ShellEnv["Shell Environment"]:::hmmod
Tools["Essential Tools"]:::hmmod
Short answer: no.
subgraph "Platform-Specific HM"
LinuxHM["Linux Config"]:::linux
Theming["Linux Theming"]:::linux
Hyprland["Hyprland Config"]:::linux
DarwinHM["Darwin Config"]:::darwin
end
end
Long answer: no really. Don't.
subgraph "Package Management"
Packages["Custom Packages"]:::pkg
Overlays["Overlays"]:::pkg
end
Long long answer: I'm not kidding. Don't.
subgraph "Host Configuration"
RefHosts["Reference Hosts"]:::host
Templates["Host Templates"]:::host
end
Unsigned long long answer: Alright alright. Here's why not:
subgraph "Build System"
Flake["Flake Entry Point"]:::build
Builder["Build System"]:::build
end
Its learning curve is steep. You will trial and error your way to
enlightenment, if you survive the frustration long enough. NixOS is unlike
other Linux distros. Your issues will be unique and difficult to google. A
decent grasp of Linux and your chosen services is a must, if only to
distinguish Nix(OS) issues from Linux (or upstream) issues -- as well as to
debug them or report them to the correct authority (and coherently). If words
like "declarative", "generational", and "immutable" don't put your sexuality in
jeopardy, you're considering NixOS for the wrong reasons. The overhead of
managing a NixOS config will rarely pay for itself with 3 systems or fewer
(perhaps another distro with nix on top would suit you better?). Official
documentation for Nix(OS) is vast, but shallow. Unofficial resources and
example configs are sparse and tend toward too simple or too complex (and most
are outdated). Case in point: this repo. The Nix language is obtuse and its
toolchain is not intuitive. Your experience will be infinitely worse if
functional languages are alien to you, however, learning Nix is a must to do
even a fraction of what makes NixOS worth the trouble. If you need somebody
else to tell you whether or not you need NixOS, you don't need NixOS.
</details>
%% Relationships
NixOS --> SysMod
SysMod --> LinuxCore & DarwinCore
HM --> CommonMod
CommonMod --> ShellEnv & Tools
CommonMod --> LinuxHM & DarwinHM
LinuxHM --> Theming & Hyprland
DarwinCore --> Homebrew & WM
LinuxCore --> Desktop & Audio & Gaming & Graphics
Flake --> Builder
Builder --> RefHosts
Templates --> RefHosts
Packages --> Overlays
Overlays --> Builder
<hr />
%% Click Events
click SysMod "https://github.com/youwen5/liminalOS/tree/main/modules"
click LinuxCore "https://github.com/youwen5/liminalOS/tree/main/modules/linux/core"
click DarwinCore "https://github.com/youwen5/liminalOS/tree/main/modules/darwin"
click HM "https://github.com/youwen5/liminalOS/tree/main/hm"
click CommonMod "https://github.com/youwen5/liminalOS/tree/main/hm/modules/common"
click ShellEnv "https://github.com/youwen5/liminalOS/tree/main/hm/modules/common/shellenv"
click Tools "https://github.com/youwen5/liminalOS/tree/main/hm/modules/common/essentials"
click Desktop "https://github.com/youwen5/liminalOS/tree/main/modules/linux/desktop-environment"
click Audio "https://github.com/youwen5/liminalOS/tree/main/modules/linux/audio"
click Gaming "https://github.com/youwen5/liminalOS/tree/main/modules/linux/gaming"
click Graphics "https://github.com/youwen5/liminalOS/tree/main/modules/linux/graphics"
click Homebrew "https://github.com/youwen5/liminalOS/blob/main/modules/darwin/homebrew.nix"
click WM "https://github.com/youwen5/liminalOS/blob/main/modules/darwin/yabai.nix"
click RefHosts "https://github.com/youwen5/liminalOS/tree/main/reference/hosts"
click Templates "https://github.com/youwen5/liminalOS/tree/main/templates/minimal"
click Packages "https://github.com/youwen5/liminalOS/tree/main/pkgs/by-name"
click Overlays "https://github.com/youwen5/liminalOS/tree/main/overlays"
click Theming "https://github.com/youwen5/liminalOS/tree/main/hm/modules/linux/theming"
click Hyprland "https://github.com/youwen5/liminalOS/tree/main/hm/modules/linux/desktop-environment/hyprland"
click Builder "https://github.com/youwen5/liminalOS/blob/main/lib/buildLiminalOS.nix"
click Flake "https://github.com/youwen5/liminalOS/blob/main/flake.nix"
<!-- prettier-ignore -->
> **lim·i·nal**
> 1. between or belonging to two different places, states, etc.
The goal of liminalOS is to allow my computing environment to exist in
different computers at the same time, and to be absolutely unbreakable while
doing so. Let's talk about existing in multiple computers first, or otherwise
known as some form of "settings sync". To the typical user, stuck in the
_imperative world_, this sounds unrealistic at worst, and janky at best.
Generally, people encounter environment or settings syncing in two ways: either
the entire service is ran in the cloud, so it's really the _same_ environment
accessed from multiple places, or it's some often half baked opaque solution
involving you making an account and sending all your settings to a sync server
(see: Mozilla Firefox).
The more technically minded may instead opt to create a "dotfiles" repository,
holding their vast corpus of meticulously crafted configuration files. These
repos often come with a janky `install.sh` that does its best to throw all the
files into the correct place. This usually works the first time, but trying to
keep the installed dotfiles in sync with a central repository is a whole other
problem.
But these solutions are generally used for singular services or applications.
Keeping an entire _system_ synced up across computers down to the minute
configurations and applications seems incredibly unwieldy, through our usual
conception of how we interact with our operating systems.
The more obsessive system tweakers might try a dotfile manager like `chezmoi`
or GNU Stow. I have not tried these so I make no judgements on their utility
for their intended purpose, but generally these solutions miss a key feature:
they provide the configuration, but don't install the software. But the
software and the configuration are fundamentally tied together; these are not
concerns to be separated. If the software is installed, it almost always needs
to be configured anyways. If the configuration exists, the software should be
installed. These solutions may work well for managing configuration, but they
have the same issue as before: you also need to install the software you're
configuring!
So, *nix hackers reach for things like [Ansible](https://www.ansible.com/), that
promise automatic configuration of entire systems. Though Ansible was designed
to deploy cloud servers quickly through the Infrastructure-as-Code approach,
some people opt to use it for deploying their systems quickly as well. I have
not tried it, but from what I've heard, it works fine for simple deployment but
gets quite unwieldy for more complex purposes (especially for personal systems,
which aren't expected to be as ephemeral as servers).
If you agree with the premises I've laid out up to this point, you might come
to the conclusion that I've made: to solve this issue, we need a solution that
does _all of it_. A unified tool for deploying software and managing systems.
And it must necessarily be declarative and reproducible, because that is the
only way to sanely manage a system. Imagine working on a programming project
where recompiling with the same source code would non-deterministically produce
different results based on the environment!
Well, [Nix](https://nixos.org/) is the _purely functional_ package manager
(i.e. declarative, reproducible), and NixOS is a Linux distribution that is
managed entirely by Nix. Essentially, Nix provides a solution to the problem of
_software deployment_, and in fact was purpose built to do so in Eelco
Dolstra's seminal [PhD
thesis](https://edolstra.github.io/pubs/phd-thesis.pdf). NixOS is a system that
takes the power of Nix and applies it to declaratively configure an _entire
Linux system_. All of the software can be specified precisely using the Nix
expression language, a purely functional DSL used by Nix. And alongside the
software, it also configures it, effectively acting as a dotfile manager.
Indeed, many core NixOS services and a wide range of programs can be set up
through _NixOS modules_, where the program is installed and configured in the
same place. (and many programs like `fzf`, `btop`, etc have similar
corresponding `home-manager` modules).
NixOS is also _immutable_, which means that the system cannot be modified after
it is built from the Nix files that declare it. How do you make changes to the
system then? Obviously, we just create a new system where the changed programs
and files are included, and the old ones are removed. But they are not deleted
from the hard drive, they still exist in the _Nix store_. So, the system can
provide precise atomic rollbacks between each "generation" of itself. Broke
your GRUB configuration so your system won't boot? Messed up your kernel
settings? Just select an older working generation from the boot menu and you
instantly have a working system again. You never worry about breaking things
during either routine or massive system updates.
And because the system is fully declarative, and modifying the system is done
only through modifying its Nix configuration files, you can version and sync
them up with Git. This solves the problem of keeping system environments in
sync; now, you truly only have to keep one repository of all your configuration
in sync, and all the software installation and deployment is handled for you by
a system designed precisely for that purpose.
This makes it possible for me to share common configuration between a multitude
of entirely distinct machines, including an `x86_64` desktop, an `x86_64`
laptop, an Apple Silicon Macbook running NixOS `aarch64` using [Asahi
Linux](https://asahilinux.org/), and the same Macbook running macOS with
`nix-darwin`, sharing `home-manager` configuration with NixOS. Specific
configuration necessary to adjust hardware-specific details between each
machines are isolated to the [hosts](./hosts) directory.
This works exceptionally well, evidenced by the fact that I have (almost) the
exact same environment across three separate machines, spanning two entirely
distinct CPU architectures.
In essence, the primary failure of deployment scripts, Ansible and the like is
that they are _imperative_ - they must specify precisely _how_ to set up the
system, down to minute details, whereas in a _declarative_ approach, the user
can simply specify what the system _should look like_, and abstractions take
care of the _how_. This is what NixOS does, and it gives you remote syncing,
versioning (via `git`), and rollbacks _for free_.
## Installation guide
Currently there is no streamlined installer. Please see [the reference
implementations](./reference) for an idea on how to set up a liminalOS system.
## FAQ
### This looks like a collection of NixOS configuration files and modules. What makes it a distinct distribution?
Most Linux[^1] users will agree that any self-respecting distribution must
include at least the following: installer, package manager, and some set of
default packages. Therefore, anything that implements the aforementioned items
must also be a Linux distribution.
liminalOS comes with the Nix package manager (nobody said you need a _unique_
package manager - Ubuntu and Debian are distinct distributions yet both use
`apt`), a custom desktop environment comprised of Waybar, Hyprland, rofi, as
well as various applications installed by default, and
[the means to generate an installer](https://nixos.wiki/wiki/Creating_a_NixOS_live_CD).
Therefore, liminalOS is a Linux distribution. QED.[^2]
### Should I actually install this?
Sure.
%% Styling
classDef default fill:#f9f9f9,stroke:#333,stroke-width:2px;
classDef sysmod fill:#a8d1f0,stroke:#333;
classDef hm fill:#b8e6b8,stroke:#333;
classDef hmmod fill:#d1f0a8,stroke:#333;
classDef linux fill:#f0a8a8,stroke:#333;
classDef darwin fill:#f0d1a8,stroke:#333;
classDef pkg fill:#d1a8f0,stroke:#333;
classDef host fill:#a8f0d1,stroke:#333;
classDef build fill:#f0f0a8,stroke:#333;
```
## Hosts