NixOS flake: mbp (Asahi) + pc (x86), Hyprland/Zen/neovim, README
This commit is contained in:
commit
2c3b029c83
17 changed files with 1005 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# nix build outputs
|
||||||
|
result
|
||||||
|
result-*
|
||||||
161
README.md
Normal file
161
README.md
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
# mads — NixOS config (one flake, two machines)
|
||||||
|
|
||||||
|
Declarative NixOS for:
|
||||||
|
|
||||||
|
| host | `nixosConfigurations.<name>` | arch | notes |
|
||||||
|
|------|------------------------------|------|-------|
|
||||||
|
| MacBook (M1 Pro, Asahi) | `mbp` | `aarch64-linux` | Apple Silicon support module + vendored firmware |
|
||||||
|
| Arbitrary x86 PC | `pc` | `x86_64-linux` | plain NixOS |
|
||||||
|
|
||||||
|
Everything shared (Hyprland, greetd autologin, Zen+Tridactyl, neovim, zsh+starship,
|
||||||
|
packages, user) lives in the `common` / `home` modules in `flake.nix`. Host-specific
|
||||||
|
bits (Asahi firmware/cache vs. x86 boot) are the small inline modules per host.
|
||||||
|
|
||||||
|
```
|
||||||
|
flake.nix inputs + common/home modules + both hosts
|
||||||
|
hosts/mbp/hardware-configuration.nix ← DUMMY, regenerate on the Mac
|
||||||
|
hosts/pc/hardware-configuration.nix ← DUMMY, regenerate on the PC
|
||||||
|
config/ hypr eww fuzzel nvim raw configs (sourced by home-manager)
|
||||||
|
firmware/ Wi-Fi/BT blobs (Mac only, git-add at install)
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Keep this repo private** — the Mac firmware under `firmware/` is non-redistributable.
|
||||||
|
|
||||||
|
The `hardware-configuration.nix` files are placeholders so the flake evaluates
|
||||||
|
off-target; each is overwritten by `nixos-generate-config` during that machine's install.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rename a host / set your timezone
|
||||||
|
|
||||||
|
- Host name: change the `nixosConfigurations.<name>` key **and** its
|
||||||
|
`networking.hostName` in `flake.nix` (e.g. `pc` → `desktop`).
|
||||||
|
- `time.timeZone` is in the `common` module.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Install on the MacBook (Asahi + NixOS)
|
||||||
|
|
||||||
|
Follows the official guide — **always check the latest**, as steps change:
|
||||||
|
<https://github.com/nix-community/nixos-apple-silicon/blob/main/docs/uefi-standalone.md>
|
||||||
|
(this config tracks Asahi `main`; currently kernel `linux-asahi 7.0.13`).
|
||||||
|
|
||||||
|
> ⚠ **Back up first.** Damaging the GPT / first / last partition can brick the Mac
|
||||||
|
> and lose all data.
|
||||||
|
|
||||||
|
### 1. macOS → install the UEFI environment
|
||||||
|
In macOS Terminal (admin account):
|
||||||
|
```sh
|
||||||
|
curl https://alx.sh | sh
|
||||||
|
```
|
||||||
|
- `r` — resize macOS, leave ≥ 20 GB free for NixOS
|
||||||
|
- `f` — install into free space → **UEFI environment only**, name it `NixOS`
|
||||||
|
- Reboot into recovery when told; set **permissive security** for the new OS.
|
||||||
|
- It reboots into U-Boot (Asahi + U-Boot logos). Power off.
|
||||||
|
|
||||||
|
### 2. Build + write the installer USB
|
||||||
|
On any Linux box with Nix (or download a release ISO from the repo's Releases):
|
||||||
|
```sh
|
||||||
|
nix build github:nix-community/nixos-apple-silicon#installer-bootstrap -o installer
|
||||||
|
sudo dd if=installer/iso/nixos-*.iso of=/dev/sdX bs=4M conv=fsync status=progress
|
||||||
|
```
|
||||||
|
(`dd` only — not unetbootin.)
|
||||||
|
|
||||||
|
### 3. Boot the installer, partition, mount
|
||||||
|
Boot the USB (U-Boot → GRUB → installer), then:
|
||||||
|
```sh
|
||||||
|
sudo su
|
||||||
|
sgdisk /dev/nvme0n1 -n 0:0 -s # root fills free space
|
||||||
|
sgdisk /dev/nvme0n1 -p # find the new 8300 partition number (e.g. p5)
|
||||||
|
mkfs.ext4 -L nixos /dev/nvme0n1p5
|
||||||
|
|
||||||
|
mount /dev/disk/by-label/nixos /mnt
|
||||||
|
mkdir -p /mnt/boot
|
||||||
|
mount /dev/disk/by-partuuid/$(cat /proc/device-tree/chosen/asahi,efi-system-partition) /mnt/boot
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Hardware config + vendored firmware + this flake
|
||||||
|
```sh
|
||||||
|
nixos-generate-config --root /mnt
|
||||||
|
|
||||||
|
# get this repo onto the target (private remote or USB), e.g.:
|
||||||
|
git clone <your-private-remote> /mnt/etc/nixos/config && cd /mnt/etc/nixos/config
|
||||||
|
|
||||||
|
cp /mnt/etc/nixos/hardware-configuration.nix hosts/mbp/hardware-configuration.nix
|
||||||
|
|
||||||
|
# vendor the Wi-Fi/BT firmware (pure flakes can't read /boot/asahi)
|
||||||
|
mkdir -p firmware
|
||||||
|
cp /mnt/boot/asahi/all_firmware.tar.gz firmware/
|
||||||
|
cp /mnt/boot/asahi/kernelcache* firmware/
|
||||||
|
git add -f hosts/mbp/hardware-configuration.nix firmware/*
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Install
|
||||||
|
```sh
|
||||||
|
nixos-install --flake .#mbp # sets root password at the end
|
||||||
|
reboot
|
||||||
|
```
|
||||||
|
Boot picker: hold the power button. greetd autologins `mads` into Hyprland.
|
||||||
|
**First thing after login: `passwd`** (the config ships `initialPassword = "changeme"`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Install on an x86 PC
|
||||||
|
|
||||||
|
Standard NixOS install (<https://nixos.org/manual/nixos/stable/#sec-installation>),
|
||||||
|
just point `nixos-install` at `.#pc`.
|
||||||
|
|
||||||
|
### 1. Boot the NixOS ISO, get network, partition (UEFI/GPT)
|
||||||
|
```sh
|
||||||
|
sudo -i
|
||||||
|
parted /dev/nvme0n1 -- mklabel gpt
|
||||||
|
parted /dev/nvme0n1 -- mkpart ESP fat32 1MiB 512MiB
|
||||||
|
parted /dev/nvme0n1 -- set 1 esp on
|
||||||
|
parted /dev/nvme0n1 -- mkpart primary 512MiB 100%
|
||||||
|
|
||||||
|
mkfs.fat -F32 -n BOOT /dev/nvme0n1p1
|
||||||
|
mkfs.ext4 -L nixos /dev/nvme0n1p2
|
||||||
|
|
||||||
|
mount /dev/disk/by-label/nixos /mnt
|
||||||
|
mkdir -p /mnt/boot
|
||||||
|
mount /dev/disk/by-label/BOOT /mnt/boot
|
||||||
|
```
|
||||||
|
(The `BOOT` / `nixos` labels match the dummy `hosts/pc/hardware-configuration.nix`,
|
||||||
|
but the generated one below replaces it with real UUIDs anyway.)
|
||||||
|
|
||||||
|
### 2. Hardware config + this flake + install
|
||||||
|
```sh
|
||||||
|
nixos-generate-config --root /mnt
|
||||||
|
git clone <your-private-remote> /mnt/etc/nixos/config && cd /mnt/etc/nixos/config
|
||||||
|
cp /mnt/etc/nixos/hardware-configuration.nix hosts/pc/hardware-configuration.nix
|
||||||
|
|
||||||
|
nixos-install --flake .#pc
|
||||||
|
reboot
|
||||||
|
```
|
||||||
|
Then `passwd`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Day-to-day
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# apply config changes
|
||||||
|
sudo nixos-rebuild switch --flake ~/nixos#mbp # or #pc
|
||||||
|
|
||||||
|
# update everything (nixpkgs + asahi + zen + addons), then rebuild
|
||||||
|
nix flake update
|
||||||
|
sudo nixos-rebuild switch --flake ~/nixos#mbp
|
||||||
|
|
||||||
|
# roll back: pick a previous generation in the boot menu
|
||||||
|
```
|
||||||
|
|
||||||
|
Both `apple-silicon` and `nixpkgs` are cached (asahi via its Cachix), so updates
|
||||||
|
download rather than compile.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verify-on-first-boot (can't be checked off-machine)
|
||||||
|
|
||||||
|
- **greetd session** — the command is `uwsm start hyprland`. If you land on a blank
|
||||||
|
tty instead of Hyprland, change it to `command = "Hyprland"` in `common`.
|
||||||
|
- **Asahi `hardware.asahi.*`** — firmware path / sound options, per the guide above.
|
||||||
14
config/eww/eww.scss
Normal file
14
config/eww/eww.scss
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
* {
|
||||||
|
all: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.battery-popup {
|
||||||
|
background-color: #16181a;
|
||||||
|
padding: 6px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.battery-popup-text {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
17
config/eww/eww.yuck
Normal file
17
config/eww/eww.yuck
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
(defpoll battery-percent :interval "10s" "scripts/battery-capacity")
|
||||||
|
(defpoll battery-status :interval "10s" "scripts/battery-status")
|
||||||
|
|
||||||
|
(defwidget battery-popup []
|
||||||
|
(box :class "battery-popup"
|
||||||
|
:halign "center"
|
||||||
|
:valign "center"
|
||||||
|
(label :class "battery-popup-text"
|
||||||
|
:text "${battery-percent}% ${battery-status}")))
|
||||||
|
|
||||||
|
(defwindow battery-popup
|
||||||
|
:monitor 0
|
||||||
|
:geometry (geometry :anchor "center")
|
||||||
|
:stacking "overlay"
|
||||||
|
:exclusive false
|
||||||
|
:focusable false
|
||||||
|
(battery-popup))
|
||||||
8
config/eww/scripts/battery-capacity
Executable file
8
config/eww/scripts/battery-capacity
Executable file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Print the charge % of the first real battery. Portable across machines
|
||||||
|
# (macsmc-battery on Asahi, BAT0/BAT1 on x86).
|
||||||
|
for d in /sys/class/power_supply/*; do
|
||||||
|
[ "$(cat "$d/type" 2>/dev/null)" = "Battery" ] || continue
|
||||||
|
cat "$d/capacity" 2>/dev/null && exit 0
|
||||||
|
done
|
||||||
|
echo "?"
|
||||||
7
config/eww/scripts/battery-status
Executable file
7
config/eww/scripts/battery-status
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Print the charging status of the first real battery. Portable across machines.
|
||||||
|
for d in /sys/class/power_supply/*; do
|
||||||
|
[ "$(cat "$d/type" 2>/dev/null)" = "Battery" ] || continue
|
||||||
|
cat "$d/status" 2>/dev/null && exit 0
|
||||||
|
done
|
||||||
|
echo "Unknown"
|
||||||
19
config/fuzzel/fuzzel.ini
Normal file
19
config/fuzzel/fuzzel.ini
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
[main]
|
||||||
|
font=JetBrainsMono Nerd Font:size=12
|
||||||
|
terminal=kitty
|
||||||
|
lines=8
|
||||||
|
width=40
|
||||||
|
horizontal-pad=16
|
||||||
|
vertical-pad=12
|
||||||
|
inner-pad=4
|
||||||
|
|
||||||
|
[colors]
|
||||||
|
background=16181aff
|
||||||
|
text=ffffffff
|
||||||
|
match=ff6e5eff
|
||||||
|
selection=3c4048ff
|
||||||
|
selection-text=ffffffff
|
||||||
|
|
||||||
|
[border]
|
||||||
|
width=0
|
||||||
|
radius=0
|
||||||
21
config/hypr/hypridle.conf
Normal file
21
config/hypr/hypridle.conf
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
general {
|
||||||
|
lock_cmd = pidof hyprlock || hyprlock
|
||||||
|
before_sleep_cmd = loginctl lock-session
|
||||||
|
after_sleep_cmd = hyprctl dispatch dpms on
|
||||||
|
}
|
||||||
|
|
||||||
|
listener {
|
||||||
|
timeout = 300
|
||||||
|
on-timeout = brightnessctl -s set 10
|
||||||
|
on-resume = brightnessctl -r
|
||||||
|
}
|
||||||
|
|
||||||
|
listener {
|
||||||
|
timeout = 600
|
||||||
|
on-timeout = loginctl lock-session
|
||||||
|
}
|
||||||
|
|
||||||
|
listener {
|
||||||
|
timeout = 1800
|
||||||
|
on-timeout = systemctl suspend
|
||||||
|
}
|
||||||
146
config/hypr/hyprland.conf
Normal file
146
config/hypr/hyprland.conf
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
# -- Monitors & input defaults (overridable per-host) --
|
||||||
|
monitor = , preferred, auto, 2.0
|
||||||
|
|
||||||
|
device {
|
||||||
|
name = apple-spi-keyboard
|
||||||
|
kb_options = caps:ctrl_modifier,grp:win_space_toggle
|
||||||
|
}
|
||||||
|
|
||||||
|
# TrackPoint (Corne nipple): hold middle button + move to scroll, joystick-style
|
||||||
|
device {
|
||||||
|
name = corne-tp
|
||||||
|
scroll_method = on_button_down
|
||||||
|
scroll_button = 274 # BTN_MIDDLE
|
||||||
|
scroll_button_lock = false # set true to toggle scroll on/off with a tap instead of holding
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
kb_layout = us,dk
|
||||||
|
kb_options = grp:win_space_toggle
|
||||||
|
follow_mouse = 1
|
||||||
|
repeat_rate = 50
|
||||||
|
repeat_delay = 300
|
||||||
|
accel_profile = custom
|
||||||
|
scroll_points = 0.5 1.0 1.5 2.0 2.5
|
||||||
|
touchpad {
|
||||||
|
natural_scroll = true
|
||||||
|
scroll_factor = 0.9
|
||||||
|
tap-to-click = false
|
||||||
|
disable_while_typing = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
general {
|
||||||
|
gaps_in = 0
|
||||||
|
gaps_out = 0
|
||||||
|
border_size = 0
|
||||||
|
layout = dwindle
|
||||||
|
}
|
||||||
|
|
||||||
|
animations {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
dwindle {
|
||||||
|
preserve_split = true
|
||||||
|
force_split = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
misc {
|
||||||
|
disable_hyprland_logo = true
|
||||||
|
disable_splash_rendering = true
|
||||||
|
focus_on_activate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
ecosystem {
|
||||||
|
no_update_news = true
|
||||||
|
no_donation_nag = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# -- Environment --
|
||||||
|
env = XCURSOR_THEME,Bibata-Modern-Classic
|
||||||
|
env = XCURSOR_SIZE,24
|
||||||
|
env = QT_QPA_PLATFORMTHEME,qt6ct
|
||||||
|
env = QT_STYLE_OVERRIDE,Adwaita-Dark
|
||||||
|
env = XDG_SCREENSHOTS_DIR,$HOME/Pictures/Screenshots
|
||||||
|
|
||||||
|
# -- Autostart --
|
||||||
|
exec-once = swaybg -c '#16181a'
|
||||||
|
exec-once = GDK_BACKEND=wayland eww daemon
|
||||||
|
exec-once = systemctl --user start hyprpolkitagent
|
||||||
|
exec-once = hypridle
|
||||||
|
exec-once = hyprctl setcursor Bibata-Modern-Classic 24
|
||||||
|
|
||||||
|
# -- Core --
|
||||||
|
bind = SUPER, Return, exec, kitty
|
||||||
|
bind = SUPER, D, exec, fuzzel
|
||||||
|
bind = SUPER, B, exec, eww open battery-popup
|
||||||
|
bindr = SUPER, B, exec, eww close battery-popup
|
||||||
|
bind = SUPER, Q, killactive
|
||||||
|
bind = SUPER, F, fullscreen, 1
|
||||||
|
bind = SUPER SHIFT, Space, togglefloating
|
||||||
|
bind = CTRL, L, exec, hyprlock
|
||||||
|
|
||||||
|
# -- Focus --
|
||||||
|
bind = SUPER, h, movefocus, l
|
||||||
|
bind = SUPER, j, movefocus, d
|
||||||
|
bind = SUPER, k, movefocus, u
|
||||||
|
bind = SUPER, l, movefocus, r
|
||||||
|
|
||||||
|
# -- Move windows --
|
||||||
|
bind = SUPER SHIFT, h, movewindow, l
|
||||||
|
bind = SUPER SHIFT, j, movewindow, d
|
||||||
|
bind = SUPER SHIFT, k, movewindow, u
|
||||||
|
bind = SUPER SHIFT, l, movewindow, r
|
||||||
|
|
||||||
|
# -- Workspaces --
|
||||||
|
bind = SUPER, 1, workspace, 1
|
||||||
|
bind = SUPER, 2, workspace, 2
|
||||||
|
bind = SUPER, 3, workspace, 3
|
||||||
|
bind = SUPER, 4, workspace, 4
|
||||||
|
bind = SUPER, 5, workspace, 5
|
||||||
|
|
||||||
|
bind = SUPER SHIFT, 1, movetoworkspace, 1
|
||||||
|
bind = SUPER SHIFT, 2, movetoworkspace, 2
|
||||||
|
bind = SUPER SHIFT, 3, movetoworkspace, 3
|
||||||
|
bind = SUPER SHIFT, 4, movetoworkspace, 4
|
||||||
|
bind = SUPER SHIFT, 5, movetoworkspace, 5
|
||||||
|
|
||||||
|
# -- Move current workspace to another monitor --
|
||||||
|
bind = SUPER ALT, h, movecurrentworkspacetomonitor, l
|
||||||
|
bind = SUPER ALT, l, movecurrentworkspacetomonitor, r
|
||||||
|
|
||||||
|
# -- Resize (hold for repeat) --
|
||||||
|
binde = SUPER CTRL, h, resizeactive, -40 0
|
||||||
|
binde = SUPER CTRL, j, resizeactive, 0 40
|
||||||
|
binde = SUPER CTRL, k, resizeactive, 0 -40
|
||||||
|
binde = SUPER CTRL, l, resizeactive, 40 0
|
||||||
|
|
||||||
|
# -- Mouse --
|
||||||
|
bindm = SUPER, mouse:272, movewindow
|
||||||
|
bindm = SUPER, mouse:273, resizewindow
|
||||||
|
|
||||||
|
# -- Audio (bindel: locked + repeat; bindl: locked, no repeat) --
|
||||||
|
bindel = , XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+
|
||||||
|
bindel = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||||
|
bindl = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||||
|
bindl = , XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||||
|
|
||||||
|
# -- Brightness --
|
||||||
|
bindel = , XF86MonBrightnessUp, exec, brightnessctl set 5%+
|
||||||
|
bindel = , XF86MonBrightnessDown, exec, brightnessctl set 5%-
|
||||||
|
|
||||||
|
# -- Media --
|
||||||
|
bindl = , XF86AudioPlay, exec, playerctl play-pause
|
||||||
|
bindl = , XF86AudioNext, exec, playerctl next
|
||||||
|
bindl = , XF86AudioPrev, exec, playerctl previous
|
||||||
|
|
||||||
|
# -- Screenshots --
|
||||||
|
# Super+S: region -> clipboard
|
||||||
|
bind = SUPER, S, exec, grimblast --notify copy area
|
||||||
|
# Super+Ctrl+S: full screen -> file + clipboard
|
||||||
|
bind = SUPER CTRL, S, exec, grimblast --notify copysave screen
|
||||||
|
# Super+Shift+S: region -> file + clipboard + open in GIMP
|
||||||
|
bind = SUPER SHIFT, S, exec, bash -c 'mkdir -p "$HOME/Pictures/Screenshots"; f="$HOME/Pictures/Screenshots/$(date +%Y-%m-%dT%H-%M-%S).png"; grimblast --notify --freeze save area "$f" && wl-copy --type image/png < "$f" && gimp "$f"'
|
||||||
|
|
||||||
34
config/hypr/hyprlock.conf
Normal file
34
config/hypr/hyprlock.conf
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
general {
|
||||||
|
hide_cursor = true
|
||||||
|
grace = 0
|
||||||
|
disable_loading_bar = true
|
||||||
|
no_fade_in = true
|
||||||
|
no_fade_out = true
|
||||||
|
}
|
||||||
|
|
||||||
|
background {
|
||||||
|
monitor =
|
||||||
|
color = rgb(000000)
|
||||||
|
}
|
||||||
|
|
||||||
|
input-field {
|
||||||
|
monitor =
|
||||||
|
size = 400, 60
|
||||||
|
outline_thickness = 20
|
||||||
|
rounding = 0
|
||||||
|
outer_color = rgba(ffffffff)
|
||||||
|
inner_color = rgba(000000ff)
|
||||||
|
font_color = rgb(ffffff)
|
||||||
|
font_family = JetBrainsMono Nerd Font
|
||||||
|
font_size = 16
|
||||||
|
fade_on_empty = false
|
||||||
|
fade_timeout = 0
|
||||||
|
placeholder_text =
|
||||||
|
hide_input = true
|
||||||
|
fail_color = rgb(ff5555)
|
||||||
|
fail_text =
|
||||||
|
capslock_color = rgb(ffb000)
|
||||||
|
position = 0, 0
|
||||||
|
halign = center
|
||||||
|
valign = center
|
||||||
|
}
|
||||||
114
config/nvim/init.lua
Normal file
114
config/nvim/init.lua
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
vim.o.winborder = "rounded"
|
||||||
|
vim.o.tabstop = 2
|
||||||
|
vim.o.ignorecase = true
|
||||||
|
vim.o.shiftwidth = 2
|
||||||
|
vim.o.smartindent = true
|
||||||
|
vim.opt.wrap = false
|
||||||
|
vim.opt.number = true
|
||||||
|
vim.o.relativenumber = true
|
||||||
|
vim.o.termguicolors = true
|
||||||
|
vim.o.undofile = true
|
||||||
|
vim.o.incsearch = true
|
||||||
|
vim.o.signcolumn = "yes"
|
||||||
|
vim.opt.clipboard = "unnamedplus"
|
||||||
|
vim.opt.expandtab = true
|
||||||
|
|
||||||
|
-- On NixOS the flake provides plugins (vim.g.nix_managed set in the flake);
|
||||||
|
-- on Arch, vim.pack fetches them at runtime. Both paths keep working.
|
||||||
|
if not vim.g.nix_managed then
|
||||||
|
vim.pack.add({
|
||||||
|
{ src = "https://github.com/nvim-tree/nvim-web-devicons" },
|
||||||
|
{ src = "https://github.com/scottmckendry/cyberdream.nvim" },
|
||||||
|
{ src = "https://github.com/stevearc/oil.nvim" },
|
||||||
|
{ src = "https://github.com/neovim/nvim-lspconfig" },
|
||||||
|
{ src = "https://github.com/chomosuke/typst-preview.nvim" },
|
||||||
|
{ src = "https://github.com/saghen/blink.cmp" },
|
||||||
|
{ src = "https://github.com/dynamotn/Navigator.nvim" },
|
||||||
|
{ src = "https://github.com/folke/snacks.nvim" },
|
||||||
|
{ src = "https://github.com/folke/todo-comments.nvim" },
|
||||||
|
{ src = "https://github.com/folke/trouble.nvim" },
|
||||||
|
{ src = "https://github.com/nvim-treesitter/nvim-treesitter" },
|
||||||
|
{ src = "https://github.com/j-hui/fidget.nvim" },
|
||||||
|
{ src = "https://github.com/nvim-lualine/lualine.nvim" },
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
require("blink.cmp").setup()
|
||||||
|
require("Navigator").setup()
|
||||||
|
require("todo-comments").setup()
|
||||||
|
require("trouble").setup()
|
||||||
|
require("fidget").setup()
|
||||||
|
require("lualine").setup({
|
||||||
|
options = {
|
||||||
|
component_separators = { left = "|", right = "|" },
|
||||||
|
section_separators = { left = "|", right = "|" },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require("oil").setup({
|
||||||
|
default_file_explorer = true,
|
||||||
|
delete_to_trash = true,
|
||||||
|
skip_confirm_for_simple_edits = true,
|
||||||
|
view_options = { show_hidden = true },
|
||||||
|
keymaps = {
|
||||||
|
["g?"] = { "actions.show_help", mode = "n" },
|
||||||
|
["<CR>"] = "actions.select",
|
||||||
|
["-"] = { "actions.parent", mode = "n" },
|
||||||
|
["_"] = { "actions.open_cwd", mode = "n" },
|
||||||
|
["`"] = { "actions.cd", mode = "n" },
|
||||||
|
},
|
||||||
|
use_default_keymaps = false,
|
||||||
|
})
|
||||||
|
require("snacks").setup({ picker = { ui_select = true } })
|
||||||
|
|
||||||
|
vim.cmd("colorscheme cyberdream")
|
||||||
|
vim.api.nvim_create_autocmd("TextYankPost", {
|
||||||
|
callback = function()
|
||||||
|
vim.highlight.on_yank()
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
|
pattern = "typst",
|
||||||
|
callback = function()
|
||||||
|
vim.opt_local.wrap = true
|
||||||
|
vim.opt_local.linebreak = true
|
||||||
|
vim.opt_local.breakindent = true
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.lsp.enable({ "lua_ls", "svelte", "tinymist", "ts_ls", "rust_analyzer", "yamlls", "html", "cssls", "jsonls", "nixd", "zls" })
|
||||||
|
vim.api.nvim_create_autocmd("LspAttach", {
|
||||||
|
callback = function(ev)
|
||||||
|
vim.keymap.set('n', 'gd', vim.lsp.buf.definition)
|
||||||
|
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration)
|
||||||
|
vim.keymap.set('n', 'gr', Snacks.picker.lsp_references)
|
||||||
|
vim.keymap.set('n', 'gt', Snacks.picker.lsp_type_definitions)
|
||||||
|
vim.keymap.set('n', '<leader>ss', Snacks.picker.lsp_symbols)
|
||||||
|
vim.keymap.set('n', '<leader>sS', Snacks.picker.lsp_workspace_symbols)
|
||||||
|
vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action)
|
||||||
|
vim.keymap.set('n', '<leader>cr', vim.lsp.buf.rename)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.g.mapleader = " "
|
||||||
|
vim.keymap.set('n', '<leader>o', ':update<CR> :source<CR>')
|
||||||
|
vim.keymap.set('n', '<leader>w', ':write<CR>')
|
||||||
|
vim.keymap.set('n', '<leader>q', ':quit<CR>')
|
||||||
|
vim.keymap.set('n', '<leader>f', function() Snacks.picker.files() end)
|
||||||
|
vim.keymap.set('n', '<leader>sg', function() Snacks.picker.grep() end)
|
||||||
|
vim.keymap.set('n', '<leader>e', ':Oil<CR>')
|
||||||
|
vim.keymap.set({ 'n', 't' }, '<C-h>', ':NavigatorLeft<CR>')
|
||||||
|
vim.keymap.set({ 'n', 't' }, '<C-l>', ':NavigatorRight<CR>')
|
||||||
|
vim.keymap.set({ 'n', 't' }, '<C-k>', ':NavigatorUp<CR>')
|
||||||
|
vim.keymap.set({ 'n', 't' }, '<C-j>', ':NavigatorDown<CR>')
|
||||||
|
vim.keymap.set({ "n", "t" }, "<C-t>", function() Snacks.terminal.toggle("zsh") end) -- Open Snacks picker
|
||||||
|
vim.keymap.set('n', '<leader>g', function() Snacks.lazygit() end)
|
||||||
|
vim.keymap.set('n', '<leader>t', function() Snacks.picker.todo_comments() end)
|
||||||
|
vim.keymap.set('n', '<leader>x', ":Trouble diagnostics toggle filter.buf=0<CR>")
|
||||||
|
vim.keymap.set('n', '<leader>X', ":Trouble diagnostics<CR>")
|
||||||
|
vim.keymap.set('n', '<leader>|', ":vsplit<CR>")
|
||||||
|
vim.keymap.set('n', '<leader>_', ":split<CR>")
|
||||||
|
vim.keymap.set('n', '<ESC>', ":noh<CR>")
|
||||||
|
vim.keymap.set("v", ">", ">gv", { silent = true, desc = "Indent and reselect" })
|
||||||
|
vim.keymap.set("v", "<", "<gv", { silent = true, desc = "Unindent and reselect" })
|
||||||
|
vim.keymap.set('n', '<leader>lf', vim.lsp.buf.format)
|
||||||
68
config/nvim/nvim-pack-lock.json
Normal file
68
config/nvim/nvim-pack-lock.json
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
{
|
||||||
|
"plugins": {
|
||||||
|
"Navigator.nvim": {
|
||||||
|
"rev": "d43816089689ccffd23543bc02331e9a68f3ec2f",
|
||||||
|
"src": "https://github.com/dynamotn/Navigator.nvim"
|
||||||
|
},
|
||||||
|
"blink.cmp": {
|
||||||
|
"rev": "c573a15a62bd0bfd4006ee0849b24f5404395500",
|
||||||
|
"src": "https://github.com/saghen/blink.cmp"
|
||||||
|
},
|
||||||
|
"catppuccin": {
|
||||||
|
"rev": "e068ab5f8261f23f6f71ffd8791ae40315b77b9c",
|
||||||
|
"src": "https://github.com/catppuccin/nvim"
|
||||||
|
},
|
||||||
|
"copilot.lua": {
|
||||||
|
"rev": "ad7e729e9a6348f7da482be0271d452dbc4c8e2c",
|
||||||
|
"src": "https://github.com/zbirenbaum/copilot.lua"
|
||||||
|
},
|
||||||
|
"cyberdream.nvim": {
|
||||||
|
"rev": "39f69ebcd8de69c741bb7a65353aa37dd0680ad1",
|
||||||
|
"src": "https://github.com/scottmckendry/cyberdream.nvim"
|
||||||
|
},
|
||||||
|
"fidget.nvim": {
|
||||||
|
"rev": "889e2e96edef4e144965571d46f7a77bcc4d0ddf",
|
||||||
|
"src": "https://github.com/j-hui/fidget.nvim"
|
||||||
|
},
|
||||||
|
"lualine.nvim": {
|
||||||
|
"rev": "a905eeebc4e63fdc48b5135d3bf8aea5618fb21c",
|
||||||
|
"src": "https://github.com/nvim-lualine/lualine.nvim"
|
||||||
|
},
|
||||||
|
"nvim-lspconfig": {
|
||||||
|
"rev": "4b7fbaa239c5db6b36f424a4521ca9f1a401be33",
|
||||||
|
"src": "https://github.com/neovim/nvim-lspconfig"
|
||||||
|
},
|
||||||
|
"nvim-treesitter": {
|
||||||
|
"rev": "4916d6592ede8c07973490d9322f187e07dfefac",
|
||||||
|
"src": "https://github.com/nvim-treesitter/nvim-treesitter"
|
||||||
|
},
|
||||||
|
"nvim-web-devicons": {
|
||||||
|
"rev": "c72328a5494b4502947a022fe69c0c47e53b6aa6",
|
||||||
|
"src": "https://github.com/nvim-tree/nvim-web-devicons"
|
||||||
|
},
|
||||||
|
"oil.nvim": {
|
||||||
|
"rev": "0fcc83805ad11cf714a949c98c605ed717e0b83e",
|
||||||
|
"src": "https://github.com/stevearc/oil.nvim"
|
||||||
|
},
|
||||||
|
"snacks.nvim": {
|
||||||
|
"rev": "ad9ede6a9cddf16cedbd31b8932d6dcdee9b716e",
|
||||||
|
"src": "https://github.com/folke/snacks.nvim"
|
||||||
|
},
|
||||||
|
"todo-comments.nvim": {
|
||||||
|
"rev": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668",
|
||||||
|
"src": "https://github.com/folke/todo-comments.nvim"
|
||||||
|
},
|
||||||
|
"tree-sitter-surrealdb.nvim": {
|
||||||
|
"rev": "a875cb4be3035a0cb525c35c4c6f1512fb9fa27d",
|
||||||
|
"src": "https://github.com/dariuscorvus/tree-sitter-surrealdb.nvim"
|
||||||
|
},
|
||||||
|
"trouble.nvim": {
|
||||||
|
"rev": "bd67efe408d4816e25e8491cc5ad4088e708a69a",
|
||||||
|
"src": "https://github.com/folke/trouble.nvim"
|
||||||
|
},
|
||||||
|
"typst-preview.nvim": {
|
||||||
|
"rev": "87db18b8d19c8b0eed399f52e4c527ce5afe4817",
|
||||||
|
"src": "https://github.com/chomosuke/typst-preview.nvim"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
firmware/README.md
Normal file
25
firmware/README.md
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Asahi peripheral firmware (vendored)
|
||||||
|
|
||||||
|
`hardware.asahi.peripheralFirmwareDirectory` points here. A **pure** flake
|
||||||
|
cannot read `/boot/asahi`, so the Wi-Fi/Bluetooth firmware must live inside the
|
||||||
|
repo tree and be git-tracked.
|
||||||
|
|
||||||
|
## During install, on the Mac:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cp /boot/asahi/all_firmware.tar.gz ~/.dotfiles/firmware/
|
||||||
|
cp /boot/asahi/kernelcache* ~/.dotfiles/firmware/
|
||||||
|
git -C ~/.dotfiles add -f firmware/all_firmware.tar.gz firmware/kernelcache*
|
||||||
|
```
|
||||||
|
|
||||||
|
(They're `.gitignore`-exempt via `-f` if needed — but the flake only sees
|
||||||
|
**tracked** files, so they must be added.)
|
||||||
|
|
||||||
|
## ⚠ Keep this repository PRIVATE
|
||||||
|
|
||||||
|
This firmware is **non-free and non-redistributable**. Do not push it to a
|
||||||
|
public remote.
|
||||||
|
|
||||||
|
Until you copy these files in, `nixos-rebuild`/`nixos-install` will fail at the
|
||||||
|
firmware-extraction step — that's expected, same as the placeholder
|
||||||
|
`hardware-configuration.nix`.
|
||||||
132
flake.lock
Normal file
132
flake.lock
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"apple-silicon": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1782749693,
|
||||||
|
"narHash": "sha256-Dj2m93PXWyOoXyp9tQlyjtBPbpVobKUrgnVDNNsNT1o=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixos-apple-silicon",
|
||||||
|
"rev": "b6ed8c114eee6739e3a2c06d99e2e19ac608dedf",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixos-apple-silicon",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firefox-addons": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"dir": "pkgs/firefox-addons",
|
||||||
|
"lastModified": 1782878575,
|
||||||
|
"narHash": "sha256-sw0B1D//VBGXLQZJXXFLjunnMfO7hCZ5S1kv06BBO5A=",
|
||||||
|
"owner": "rycee",
|
||||||
|
"repo": "nur-expressions",
|
||||||
|
"rev": "e5d8f0375b4613d200e8efd64df2183a75290c4e",
|
||||||
|
"type": "gitlab"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"dir": "pkgs/firefox-addons",
|
||||||
|
"owner": "rycee",
|
||||||
|
"repo": "nur-expressions",
|
||||||
|
"type": "gitlab"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1761640442,
|
||||||
|
"narHash": "sha256-AtrEP6Jmdvrqiv4x2xa5mrtaIp3OEe8uBYCDZDS+hu8=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "4a56054d8ffc173222d09dad23adf4ba946c8884",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"home-manager": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1782881387,
|
||||||
|
"narHash": "sha256-HvlS1KDGXDjd1bNzzPvH1mkDJATlDAfVYfTh//wJBEA=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"rev": "d32537981c036473cf6990ae03176a5d84c43b29",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1782723713,
|
||||||
|
"narHash": "sha256-oPXCU/SSUokcGaJREHibG1CBX3+s/W7orDWQOZDsEeQ=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "b5aa0fbd538984f6e3d201be0005b4463d8b09f8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"apple-silicon": "apple-silicon",
|
||||||
|
"firefox-addons": "firefox-addons",
|
||||||
|
"home-manager": "home-manager",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"zen-browser": "zen-browser"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zen-browser": {
|
||||||
|
"inputs": {
|
||||||
|
"home-manager": [
|
||||||
|
"home-manager"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1782812215,
|
||||||
|
"narHash": "sha256-OPVK9WW9QsO2aj1R+Ln3p7fniFj5h441vb3LyrzpeE4=",
|
||||||
|
"owner": "0xc000022070",
|
||||||
|
"repo": "zen-browser-flake",
|
||||||
|
"rev": "a7c2a9a5e492e0e62072547f7e4c2abf138425c5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "0xc000022070",
|
||||||
|
"repo": "zen-browser-flake",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
208
flake.nix
Normal file
208
flake.nix
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
{
|
||||||
|
description = "mads — NixOS for Apple Silicon (mbp) and x86 (pc), one flake";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
|
apple-silicon = {
|
||||||
|
url = "github:nix-community/nixos-apple-silicon";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
home-manager = {
|
||||||
|
url = "github:nix-community/home-manager";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
firefox-addons = {
|
||||||
|
url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
zen-browser = {
|
||||||
|
url = "github:0xc000022070/zen-browser-flake";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.home-manager.follows = "home-manager";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, apple-silicon, home-manager, firefox-addons, zen-browser, ... }:
|
||||||
|
let
|
||||||
|
# ───────────────────── shared home-manager user ─────────────────────
|
||||||
|
home = { pkgs, ... }: {
|
||||||
|
imports = [ zen-browser.homeModules.beta ];
|
||||||
|
home.stateVersion = "25.11";
|
||||||
|
|
||||||
|
# Raw configs that stay files (no good native module).
|
||||||
|
xdg.configFile = {
|
||||||
|
"hypr".source = ./config/hypr;
|
||||||
|
"eww".source = ./config/eww;
|
||||||
|
"fuzzel".source = ./config/fuzzel;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Dark GTK apps (gimp, file dialogs).
|
||||||
|
gtk = {
|
||||||
|
enable = true;
|
||||||
|
theme = { name = "Adwaita-dark"; package = pkgs.gnome-themes-extra; };
|
||||||
|
gtk3.extraConfig.gtk-application-prefer-dark-theme = 1;
|
||||||
|
gtk4.extraConfig.gtk-application-prefer-dark-theme = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Neovim: init.lua verbatim; plugins + LSP pinned by Nix.
|
||||||
|
programs.neovim = {
|
||||||
|
enable = true;
|
||||||
|
withPython3 = false;
|
||||||
|
withRuby = false;
|
||||||
|
withNodeJs = false;
|
||||||
|
initLua = "vim.g.nix_managed = true\n"
|
||||||
|
+ builtins.readFile ./config/nvim/init.lua;
|
||||||
|
plugins = with pkgs.vimPlugins; [
|
||||||
|
nvim-web-devicons cyberdream-nvim oil-nvim nvim-lspconfig
|
||||||
|
typst-preview-nvim blink-cmp Navigator-nvim
|
||||||
|
snacks-nvim todo-comments-nvim trouble-nvim
|
||||||
|
nvim-treesitter.withAllGrammars
|
||||||
|
fidget-nvim lualine-nvim
|
||||||
|
];
|
||||||
|
extraPackages = with pkgs; [
|
||||||
|
lua-language-server rust-analyzer tinymist nixd zls
|
||||||
|
yaml-language-server vscode-langservers-extracted
|
||||||
|
typescript-language-server svelte-language-server
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Zen browser + Tridactyl, extensions pinned (works on aarch64 + x86).
|
||||||
|
programs.zen-browser = {
|
||||||
|
enable = true;
|
||||||
|
setAsDefaultBrowser = true;
|
||||||
|
profiles.default = {
|
||||||
|
settings = {
|
||||||
|
"browser.newtabpage.enabled" = false;
|
||||||
|
"privacy.donottrackheader.enabled" = true;
|
||||||
|
"signon.rememberSignons" = false;
|
||||||
|
};
|
||||||
|
extensions.packages = with firefox-addons.packages.${pkgs.stdenv.hostPlatform.system}; [
|
||||||
|
tridactyl
|
||||||
|
ublock-origin
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# zsh + starship, no framework.
|
||||||
|
programs.zsh = {
|
||||||
|
enable = true;
|
||||||
|
autosuggestion.enable = true;
|
||||||
|
syntaxHighlighting.enable = true;
|
||||||
|
shellAliases = { ll = "ls -alh"; gs = "git status"; };
|
||||||
|
};
|
||||||
|
programs.starship.enable = true;
|
||||||
|
|
||||||
|
home.packages = with pkgs; [ ripgrep fd tridactyl-native ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# ───────────────────── shared system (both hosts) ─────────────────────
|
||||||
|
common = { pkgs, ... }: {
|
||||||
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||||
|
|
||||||
|
networking.networkmanager.enable = true;
|
||||||
|
networking.networkmanager.wifi.backend = "iwd";
|
||||||
|
|
||||||
|
time.timeZone = "Europe/Copenhagen"; # set yours
|
||||||
|
i18n.defaultLocale = "en_US.UTF-8";
|
||||||
|
|
||||||
|
programs.hyprland = { enable = true; withUWSM = true; };
|
||||||
|
programs.hyprlock.enable = true;
|
||||||
|
services.hypridle.enable = true;
|
||||||
|
xdg.portal = {
|
||||||
|
enable = true;
|
||||||
|
extraPortals = [ pkgs.xdg-desktop-portal-hyprland ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# greetd autologins mads straight into Hyprland (via uwsm).
|
||||||
|
services.greetd = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
initial_session = { user = "mads"; command = "uwsm start hyprland"; };
|
||||||
|
default_session = { user = "mads"; command = "uwsm start hyprland"; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
hardware.bluetooth.enable = true;
|
||||||
|
programs.zsh.enable = true;
|
||||||
|
fonts.packages = [ pkgs.nerd-fonts.jetbrains-mono ];
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
git kitty fuzzel gimp
|
||||||
|
wl-clipboard grim slurp swaybg brightnessctl playerctl grimblast
|
||||||
|
hyprpolkitagent xdg-utils
|
||||||
|
];
|
||||||
|
|
||||||
|
users.users.mads = {
|
||||||
|
isNormalUser = true;
|
||||||
|
extraGroups = [ "wheel" "networkmanager" "video" ];
|
||||||
|
shell = pkgs.zsh;
|
||||||
|
initialPassword = "changeme"; # CHANGE after first boot (`passwd`)
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "25.11";
|
||||||
|
|
||||||
|
home-manager.useGlobalPkgs = true;
|
||||||
|
home-manager.useUserPackages = true;
|
||||||
|
home-manager.users.mads = home;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkHost = { system, modules }: nixpkgs.lib.nixosSystem {
|
||||||
|
inherit system;
|
||||||
|
modules = [ home-manager.nixosModules.home-manager common ] ++ modules;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
nixosConfigurations = {
|
||||||
|
# ── Apple Silicon MacBook (Asahi) ──
|
||||||
|
mbp = mkHost {
|
||||||
|
system = "aarch64-linux";
|
||||||
|
modules = [
|
||||||
|
apple-silicon.nixosModules.apple-silicon-support
|
||||||
|
./hosts/mbp/hardware-configuration.nix # generated on the Mac
|
||||||
|
({ ... }: {
|
||||||
|
networking.hostName = "mbp";
|
||||||
|
|
||||||
|
# Wi-Fi/BT firmware, vendored (a pure flake can't read /boot/asahi).
|
||||||
|
hardware.asahi.peripheralFirmwareDirectory = ./firmware;
|
||||||
|
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
boot.extraModprobeConfig = "options hid_apple fnmode=1";
|
||||||
|
boot.blacklistedKernelModules = [ "pcspkr" ];
|
||||||
|
|
||||||
|
# Asahi kernel + Mesa cache (else compile from source).
|
||||||
|
nix.settings = {
|
||||||
|
extra-substituters = [ "https://nixos-apple-silicon.cachix.org" ];
|
||||||
|
extra-trusted-public-keys = [
|
||||||
|
"nixos-apple-silicon.cachix.org-1:8psDu5SA5dAD7qA0zMy5UT292TxeEPzIz8VVEr2Js20="
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# ── Arbitrary x86_64 PC ──
|
||||||
|
pc = mkHost {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
modules = [
|
||||||
|
./hosts/pc/hardware-configuration.nix # generated on the PC
|
||||||
|
({ ... }: {
|
||||||
|
networking.hostName = "pc";
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
boot.loader.efi.canTouchEfiVariables = true; # normal x86 UEFI
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# `nix develop` on either arch.
|
||||||
|
devShells = nixpkgs.lib.genAttrs [ "aarch64-linux" "x86_64-linux" ] (system: {
|
||||||
|
default = nixpkgs.legacyPackages.${system}.mkShell {
|
||||||
|
packages = [ nixpkgs.legacyPackages.${system}.nodejs ];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
14
hosts/mbp/hardware-configuration.nix
Normal file
14
hosts/mbp/hardware-configuration.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# DUMMY hardware config — just enough for the flake to `nix eval`/build on a
|
||||||
|
# non-target machine. It is OVERWRITTEN at install:
|
||||||
|
#
|
||||||
|
# nixos-generate-config --root /mnt
|
||||||
|
# cp /mnt/etc/nixos/hardware-configuration.nix ~/nixos/
|
||||||
|
#
|
||||||
|
# The real file has your actual disk UUIDs and the Asahi EFI/boot mounts.
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
}
|
||||||
14
hosts/pc/hardware-configuration.nix
Normal file
14
hosts/pc/hardware-configuration.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# DUMMY x86 hardware config — just enough for `nix eval`/build off-target.
|
||||||
|
# OVERWRITTEN at install by: nixos-generate-config --root /mnt
|
||||||
|
# then copy /mnt/etc/nixos/hardware-configuration.nix here.
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
fileSystems."/boot" = {
|
||||||
|
device = "/dev/disk/by-label/BOOT";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue