Skip to content

luvcie/dotnixes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

287 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NixOS Configuration

My NixOS configuration files.

            lucie@T495
            OS NixOS
   (\ /)    Kernel 6.12.55
   ( . .)   Shell zsh
   c(")(")  WM wlroots wm

NH - Nix Helper

nh is a Nix helper tool that provides prettier output, automatic garbage collection, and better UX than raw nix commands.

Most Common Commands

Rebuild home configuration:

nh home switch .

Rebuild system configuration:

nh os switch

Update flake inputs and rebuild:

nh home switch . --update

Clean old generations and garbage collect:

nh clean all

Search for packages:

nh search <package-name>

Quick Start (Traditional Commands)

Apply system configuration:

sudo nixos-rebuild switch --flake .#<hostname>

Apply user configuration:

home-manager switch --flake .#<user>

Configuration Structure

  • configuration.nix - System-wide NixOS configuration
  • home.nix - User-specific home-manager configuration
  • flake.nix - Flake definition with inputs and outputs
  • hardware-configuration.nix - Hardware-specific settings
  • modules/ - Modular configuration components

System Administration

System Updates & Maintenance

Update flake inputs:

nix flake update

Rebuild and switch system configuration:

sudo nixos-rebuild switch --flake .#<hostname>

Test configuration without switching:

sudo nixos-rebuild test --flake .#<hostname>

Rebuild configuration without switching (bootable):

sudo nixos-rebuild boot --flake .#<hostname>

List system generations:

sudo nix-env --list-generations --profile /nix/var/nix/profiles/system

Rollback to previous generation:

sudo nixos-rebuild switch --rollback

Garbage Collection & Storage

System-wide garbage collection:

sudo nix-collect-garbage -d

User garbage collection:

nix-collect-garbage -d

Delete generations older than 30 days:

sudo nix-collect-garbage --delete-older-than 30d

Optimize nix store:

sudo nix-store --optimize

Check disk usage:

nix path-info -Sh /run/current-system

Package Management

Search for packages:

nix search nixpkgs <package-name>

Install package temporarily:

nix shell nixpkgs#<package-name>

Run package without installing:

nix run nixpkgs#<package-name>

Check package dependencies:

nix-store --query --references /run/current-system

Home Manager

Switch home configuration:

home-manager switch --flake .#<user>

List home generations:

home-manager generations

Check home-manager news:

home-manager news --flake .#<user>

Rollback home configuration:

home-manager switch --rollback

Development & Debugging

Enter development shell:

nix develop

Check flake configuration:

nix flake check

Show flake metadata:

nix flake metadata

Debug build issues:

nix log /nix/store/<derivation-path>

Show package information:

nix show-derivation nixpkgs#<package-name>

System Information

Show current system closure size:

nix path-info -Sh /run/current-system

List all installed packages:

nix-env -qa

Check service status:

systemctl status <service-name>

View system logs:

journalctl -u <service-name>

Git Workflow

Stage and commit changes:

git add .
git commit -m "description of changes"

Amend last commit:

git commit --amend

Reset to last commit:

git reset --hard

Reset to previous commit:

git reset --hard HEAD~1

Stash uncommitted changes:

git stash

Restore specific file:

git restore <file>

Running External Binaries

NixOS cannot run dynamically linked executables intended for generic Linux environments out of the box. This configuration includes nix-ld to provide compatibility.

Basic External Binaries

Most external binaries should work automatically with nix-ld enabled:

./some-external-binary

Adding Libraries for Complex Binaries

Configure additional libraries in system configuration:

programs.nix-ld = {
  enable = true;
  libraries = with pkgs; [
    stdenv.cc.cc
    openssl
    curl
    zlib
    # Add other libraries as needed
  ];
};

Using nix-alien for Complex Cases

For binaries requiring more complex setup:

# Install nix-alien
nix shell nixpkgs#nix-alien

# Run external binary through nix-alien
nix-alien ./external-binary

FHS Environment for Standard Linux Software

Create temporary standard Linux filesystem environment:

nix shell --impure nixpkgs#fhs --command bash
# Run your binary inside this environment

Additional Commands

Launch Steam games with GameMode:

gamemoderun %command%

Lab Services

i2pd

i2p router in rootless podman with --network=host.

  • web console: http://proxmox-lab.tail5296cb.ts.net:7070
  • http proxy: proxmox-lab.tail5296cb.ts.net:4444
  • socks proxy: proxmox-lab.tail5296cb.ts.net:4447
  • sam bridge: proxmox-lab.tail5296cb.ts.net:7656
  • i2pcontrol api: https://127.0.0.1:7650 (localhost only)
  • p2p port: 31000 (tcp/udp, forwarded on the router)
  • config: modules/i2pd.nix
  • data: ~/i2pd/

browsing .i2p sites in firefox

in about:config set these:

  • network.proxy.allow_hijacking_localhost to true
  • keyword.enabled to false
  • network.dns.blockDotOnion to false

then in firefox settings, network settings, manual proxy configuration:

  • http proxy: proxmox-lab.tail5296cb.ts.net, port 4444
  • check "also use this proxy for HTTPS"
  • check "proxy DNS when using SOCKS v5"

i2pcontrol api

for monitoring/automation, default password is itoopie, change it before using.

# get a token
curl -sk -X POST https://127.0.0.1:7650 \
  -d '{"id":1,"jsonrpc":"2.0","method":"Authenticate","params":{"API":1,"Password":"itoopie"},"Token":""}'

# query router info (use the token from above)
curl -sk -X POST https://127.0.0.1:7650 \
  -d '{"id":2,"jsonrpc":"2.0","method":"RouterInfo","params":{
    "i2p.router.status":"",
    "i2p.router.net.status":"",
    "i2p.router.net.tunnels.participating":"",
    "i2p.router.netdb.knownpeers":"",
    "i2p.router.uptime":"",
    "i2p.router.net.bw.inbound.1s":"",
    "i2p.router.net.bw.outbound.1s":""
  },"Token":"<TOKEN>"}'

methods: Authenticate, RouterInfo, RouterManager, NetworkSetting.

torrents (biglybt etc)

  1. enable i2p support in the client
  2. set i2p router host to proxmox-lab.tail5296cb.ts.net
  3. set sam port to 7656

networking stuff

  • --network=host because pasta caused i2pd to report symmetric NAT
  • i2pd auto-detects external ip through peer testing
  • port 31000 forwarded on the router (NAT/PAT) and allowed through ufw

yggdrasil

encrypted ipv6 mesh network (200::/7) in rootless podman with a socks5 proxy sidecar.

  • config: modules/yggdrasil.nix
  • private key: sops-managed (yggdrasil_private_key in vault)
  • container images: nix-built (official docker image stuck on 0.4.2)
  • socks proxy: proxmox-lab.tail5296cb.ts.net:1080

browsing yggdrasil sites in a browser

in browser proxy settings, set only the socks host:

  • socks host: proxmox-lab.tail5296cb.ts.net, port 1080, socks v5
  • check "proxy DNS when using SOCKS v5"
  • leave http/ssl/ftp proxy fields empty

site directory and service list: https://yggdrasil-network.github.io/services.html

managing the service

# check status
systemctl --user status yggdrasil
systemctl --user status yggdrasil-proxy

# restart
systemctl --user restart yggdrasil

proxmox

secure hypervisor access via tailscale.

  • url: https://proxmox-lab.tail5296cb.ts.net:8006
  • certs: automated via tailscale-certs + proxmox-cert-sync

funkwhale

federated music server (ActivityPub). shares libraries with friends.

  • url: https://funkwhale.luvcie.love
  • config: modules/funkwhale.nix
  • data: ~/funkwhale/data/
  • music mount: /mnt/media/music (read-only, same as navidrome)

admin

# create admin account
podman exec -it funkwhale manage createsuperuser

importing music

funkwhale does not auto-scan, must import manually via the container shell.

  1. create a library in the web ui (your profile > libraries)
  2. copy the library UUID from the url
  3. run the import:
podman exec funkwhale sh -c "manage import_files <library-uuid> /music --recursive --in-place --noinput" 2>/dev/null

2>/dev/null hides django deprecation warnings.

caddy (TLS reverse proxy)

caddy terminates TLS for internal services using tailscale certs. currently proxies CouchDB.

  • https endpoint: https://proxmox-lab.tail5296cb.ts.net:5443
  • config: modules/caddy.nix
  • data: ~/caddy/data/
  • image: docker.io/library/caddy:2
  • certs: tailscale certs from ~/.tailscale-certs/ (auto-renewed daily by tailscale-certs service)

managing the service

systemctl --user status caddy
systemctl --user restart caddy
curl -k https://proxmox-lab.tail5296cb.ts.net:5443/

couchdb (obsidian livesync)

self-hosted CouchDB for real-time obsidian vault sync via the Self-hosted LiveSync plugin. tailscale-only, behind caddy for TLS.

  • url: https://proxmox-lab.tail5296cb.ts.net:5443
  • fauxton dashboard: https://proxmox-lab.tail5296cb.ts.net:5443/_utils
  • local (no TLS): http://localhost:5984
  • config: modules/couchdb.nix
  • data: ~/couchdb/data/
  • credentials: sops-managed (couchdb_username, couchdb_password)
  • image: docker.io/library/couchdb:3

obsidian plugin setup (new device)

important: set up one device at a time. the first device creates the database and encryption salt, the second device must pull from it, not create its own.

  1. install Self-hosted LiveSync from community plugins
  2. open the plugin settings and configure the remote:
    • URI: https://proxmox-lab.tail5296cb.ts.net:5443
    • username/password: from sops vault (sops vault/encrypted-sops-secrets.yaml)
    • database name: use the same name on all devices (e.g. obsidianlucy)
    • encryption passphrase: use the same passphrase on all devices
  3. set sync mode to LiveSync under "Sync Settings"
  4. for the first device: just enable — it will create the database and push
  5. for additional devices: after entering the same settings, use "Rebuild everything → Fetch from Remote" to pull existing data. this ensures the device picks up the existing PBKDF2 salt instead of generating a new one
  6. AFTER EVERY SETUP OR REBUILD: GO TO SYNC SETTINGS AND SET THE SYNC MODE TO "LIVESYNC". it resets to on-demand/periodic after rebuilds and will NOT sync in real-time until you change it back, do this on every device.

do NOT run the "Self-hosted LiveSync config doctor" on a new device. the doctor changes settings (chunk size, case sensitivity, etc.) and then prompts you to overwrite the server with the current device's data. on a new/empty device this wipes the remote database clean and breaks sync for all other devices. only use the doctor on your primary device if you know what each setting does.

troubleshooting sync

  • nothing syncs: check that the sync mode is set to LiveSync (not periodic/on-demand). the plugin doesn't auto-start syncing after initial setup
  • Decryption with HKDF failed: the encryption salt doesn't match between devices. this happens when both devices were set up independently. fix: disable plugin on all devices, nuke the remote db (curl -sk -X DELETE https://proxmox-lab.tail5296cb.ts.net:5443/obsidianlucy -u user:pass), then set up from scratch — first device pushes, second device fetches
  • Load failed on specific notes: stale data in the local IndexedDB cache from a previous broken setup. use "Rebuild: Fetch everything from remote" to fix
  • 404 errors in dev console: normal. PouchDB checks for checkpoint documents that don't exist yet on a fresh setup. the plugin logs The above 404 is totally normal right after
  • dev console access: desktop Ctrl+Shift+I / mac Cmd+Option+I
  • the device must be on tailscale to reach the server

managing the service

systemctl --user status couchdb
systemctl --user restart couchdb
curl -u user:pass http://localhost:5984/

known issues (if modifying modules/couchdb.nix)

  • no :ro on ini mounts: the couchdb entrypoint runs chmod/chown on everything under /opt/couchdb/etc/ with set -e — a read-only mount causes a silent exit 1 with zero logs
  • [admins] section format: the entrypoint greps for \[admins\]\n[^;]\w+ — the admin username must be on the very next line after [admins], no blank lines allowed
  • put credentials in the ini, not env vars: COUCHDB_USER/COUCHDB_PASSWORD env vars are processed by the entrypoint, but require_valid_user = true in a custom ini triggers CouchDB's preflight check before the entrypoint injects the admin. define them under [admins] in the ini instead
  • sops template permissions: sops-nix renders templates as 0400 by default. couchdb runs as a non-root user inside the container. use mode = "0444" on the template
  • debugging silent crashes: override entrypoint with bash -c 'bash -x /docker-entrypoint.sh /opt/couchdb/bin/couchdb' to trace

copyparty

file server with sops-managed accounts.

  • url: https://files.luvcie.love
  • edit passwords: sops vault/encrypted-sops-secrets.yaml

sshchat

terminal chat room — users connect by SSHing into the server. no accounts, just pick a username.

  • url: ssh.luvcie.love (via cloudflare tunnel)
  • config: modules/sshchat.nix
  • binary: pre-built from github releases, fetched via fetchurl with pinned hash (fully reproducible)
  • host key: ~/sshchat/host_key — generated once on first activation, persists across rebuilds
  • service: systemctl --user status sshchat

connecting (for users)

requires cloudflared installed once on the client:

# install cloudflared (once)
# arch: yay -S cloudflared  |  mac: brew install cloudflared  |  others: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/

# add to ~/.ssh/config (once)
Host ssh.luvcie.love
    ProxyCommand cloudflared access ssh --hostname %h

# connect (pick any username)
ssh yourname@ssh.luvcie.love

managing the service

systemctl --user status sshchat
systemctl --user restart sshchat
journalctl --user -u sshchat -f

upgrading

update the version and hash in modules/sshchat.nix:

# get new hash
nix-prefetch-url --type sha256 https://github.com/shazow/ssh-chat/releases/download/vX.X/ssh-chat-linux_amd64.tgz
nix hash to-sri --type sha256 <hash>

then update version and hash in the module and run nh home switch ..

shell-bridge

websocket terminal bridge for the luvcie.love website terminal. runs the luvcie-lab podman container (nix-built) and exposes it over a websocket at wss://term.luvcie.love.

  • config: modules/shell-bridge.nix
  • image: nix-built via dockerTools.buildImage, single layer (not layered — avoids vfs disk waste)
  • service: systemctl --user status shell-bridge

the image marker file

to avoid reloading the container image on every nh home switch (podman load is slow and would trigger the activation timeout), the activation script uses a marker file:

~/.local/share/containers/luvcie-lab-loaded

this file contains the nix store path of the currently loaded image. on each activation, if the file exists and matches the current image derivation, podman load is skipped. if the paths differ (new build) or the file is missing, the image is reloaded.

if you delete the image in portainer, the marker still exists so nh home switch won't reload it. fix:

rm ~/.local/share/containers/luvcie-lab-loaded
nh home switch ~/dotnixes

managing the service

systemctl --user status shell-bridge
systemctl --user restart shell-bridge
journalctl --user -u shell-bridge -f

About

NixOS dotfiles

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors