3595 lines
117 KiB
HTML
3595 lines
117 KiB
HTML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||
<head>
|
||
<!-- 2026-02-22 zo 23:03 -->
|
||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>‎</title>
|
||
<meta name="author" content="henrov" />
|
||
<meta name="generator" content="Org Mode" />
|
||
<style type="text/css">
|
||
#content { max-width: 60em; margin: auto; }
|
||
.title { text-align: center;
|
||
margin-bottom: .2em; }
|
||
.subtitle { text-align: center;
|
||
font-size: medium;
|
||
font-weight: bold;
|
||
margin-top:0; }
|
||
.todo { font-family: monospace; color: red; }
|
||
.done { font-family: monospace; color: green; }
|
||
.priority { font-family: monospace; color: orange; }
|
||
.tag { background-color: #eee; font-family: monospace;
|
||
padding: 2px; font-size: 80%; font-weight: normal; }
|
||
.timestamp { color: #bebebe; }
|
||
.timestamp-kwd { color: #5f9ea0; }
|
||
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
|
||
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
|
||
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
|
||
.underline { text-decoration: underline; }
|
||
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
|
||
p.verse { margin-left: 3%; }
|
||
pre {
|
||
border: 1px solid #e6e6e6;
|
||
border-radius: 3px;
|
||
background-color: #f2f2f2;
|
||
padding: 8pt;
|
||
font-family: monospace;
|
||
overflow: auto;
|
||
margin: 1.2em;
|
||
}
|
||
pre.src {
|
||
position: relative;
|
||
overflow: auto;
|
||
}
|
||
pre.src:before {
|
||
display: none;
|
||
position: absolute;
|
||
top: -8px;
|
||
right: 12px;
|
||
padding: 3px;
|
||
color: #555;
|
||
background-color: #f2f2f299;
|
||
}
|
||
pre.src:hover:before { display: inline; margin-top: 14px;}
|
||
/* Languages per Org manual */
|
||
pre.src-asymptote:before { content: 'Asymptote'; }
|
||
pre.src-awk:before { content: 'Awk'; }
|
||
pre.src-authinfo::before { content: 'Authinfo'; }
|
||
pre.src-C:before { content: 'C'; }
|
||
/* pre.src-C++ doesn't work in CSS */
|
||
pre.src-clojure:before { content: 'Clojure'; }
|
||
pre.src-css:before { content: 'CSS'; }
|
||
pre.src-D:before { content: 'D'; }
|
||
pre.src-ditaa:before { content: 'ditaa'; }
|
||
pre.src-dot:before { content: 'Graphviz'; }
|
||
pre.src-calc:before { content: 'Emacs Calc'; }
|
||
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
|
||
pre.src-fortran:before { content: 'Fortran'; }
|
||
pre.src-gnuplot:before { content: 'gnuplot'; }
|
||
pre.src-haskell:before { content: 'Haskell'; }
|
||
pre.src-hledger:before { content: 'hledger'; }
|
||
pre.src-java:before { content: 'Java'; }
|
||
pre.src-js:before { content: 'Javascript'; }
|
||
pre.src-latex:before { content: 'LaTeX'; }
|
||
pre.src-ledger:before { content: 'Ledger'; }
|
||
pre.src-lisp:before { content: 'Lisp'; }
|
||
pre.src-lilypond:before { content: 'Lilypond'; }
|
||
pre.src-lua:before { content: 'Lua'; }
|
||
pre.src-matlab:before { content: 'MATLAB'; }
|
||
pre.src-mscgen:before { content: 'Mscgen'; }
|
||
pre.src-ocaml:before { content: 'Objective Caml'; }
|
||
pre.src-octave:before { content: 'Octave'; }
|
||
pre.src-org:before { content: 'Org mode'; }
|
||
pre.src-oz:before { content: 'OZ'; }
|
||
pre.src-plantuml:before { content: 'Plantuml'; }
|
||
pre.src-processing:before { content: 'Processing.js'; }
|
||
pre.src-python:before { content: 'Python'; }
|
||
pre.src-R:before { content: 'R'; }
|
||
pre.src-ruby:before { content: 'Ruby'; }
|
||
pre.src-sass:before { content: 'Sass'; }
|
||
pre.src-scheme:before { content: 'Scheme'; }
|
||
pre.src-screen:before { content: 'Gnu Screen'; }
|
||
pre.src-sed:before { content: 'Sed'; }
|
||
pre.src-sh:before { content: 'shell'; }
|
||
pre.src-sql:before { content: 'SQL'; }
|
||
pre.src-sqlite:before { content: 'SQLite'; }
|
||
/* additional languages in org.el's org-babel-load-languages alist */
|
||
pre.src-forth:before { content: 'Forth'; }
|
||
pre.src-io:before { content: 'IO'; }
|
||
pre.src-J:before { content: 'J'; }
|
||
pre.src-makefile:before { content: 'Makefile'; }
|
||
pre.src-maxima:before { content: 'Maxima'; }
|
||
pre.src-perl:before { content: 'Perl'; }
|
||
pre.src-picolisp:before { content: 'Pico Lisp'; }
|
||
pre.src-scala:before { content: 'Scala'; }
|
||
pre.src-shell:before { content: 'Shell Script'; }
|
||
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
|
||
/* additional language identifiers per "defun org-babel-execute"
|
||
in ob-*.el */
|
||
pre.src-cpp:before { content: 'C++'; }
|
||
pre.src-abc:before { content: 'ABC'; }
|
||
pre.src-coq:before { content: 'Coq'; }
|
||
pre.src-groovy:before { content: 'Groovy'; }
|
||
/* additional language identifiers from org-babel-shell-names in
|
||
ob-shell.el: ob-shell is the only babel language using a lambda to put
|
||
the execution function name together. */
|
||
pre.src-bash:before { content: 'bash'; }
|
||
pre.src-csh:before { content: 'csh'; }
|
||
pre.src-ash:before { content: 'ash'; }
|
||
pre.src-dash:before { content: 'dash'; }
|
||
pre.src-ksh:before { content: 'ksh'; }
|
||
pre.src-mksh:before { content: 'mksh'; }
|
||
pre.src-posh:before { content: 'posh'; }
|
||
/* Additional Emacs modes also supported by the LaTeX listings package */
|
||
pre.src-ada:before { content: 'Ada'; }
|
||
pre.src-asm:before { content: 'Assembler'; }
|
||
pre.src-caml:before { content: 'Caml'; }
|
||
pre.src-delphi:before { content: 'Delphi'; }
|
||
pre.src-html:before { content: 'HTML'; }
|
||
pre.src-idl:before { content: 'IDL'; }
|
||
pre.src-mercury:before { content: 'Mercury'; }
|
||
pre.src-metapost:before { content: 'MetaPost'; }
|
||
pre.src-modula-2:before { content: 'Modula-2'; }
|
||
pre.src-pascal:before { content: 'Pascal'; }
|
||
pre.src-ps:before { content: 'PostScript'; }
|
||
pre.src-prolog:before { content: 'Prolog'; }
|
||
pre.src-simula:before { content: 'Simula'; }
|
||
pre.src-tcl:before { content: 'tcl'; }
|
||
pre.src-tex:before { content: 'TeX'; }
|
||
pre.src-plain-tex:before { content: 'Plain TeX'; }
|
||
pre.src-verilog:before { content: 'Verilog'; }
|
||
pre.src-vhdl:before { content: 'VHDL'; }
|
||
pre.src-xml:before { content: 'XML'; }
|
||
pre.src-nxml:before { content: 'XML'; }
|
||
/* add a generic configuration mode; LaTeX export needs an additional
|
||
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
|
||
pre.src-conf:before { content: 'Configuration File'; }
|
||
|
||
table { border-collapse:collapse; }
|
||
caption.t-above { caption-side: top; }
|
||
caption.t-bottom { caption-side: bottom; }
|
||
td, th { vertical-align:top; }
|
||
th.org-right { text-align: center; }
|
||
th.org-left { text-align: center; }
|
||
th.org-center { text-align: center; }
|
||
td.org-right { text-align: right; }
|
||
td.org-left { text-align: left; }
|
||
td.org-center { text-align: center; }
|
||
dt { font-weight: bold; }
|
||
.footpara { display: inline; }
|
||
.footdef { margin-bottom: 1em; }
|
||
.figure { padding: 1em; }
|
||
.figure p { text-align: center; }
|
||
.equation-container {
|
||
display: table;
|
||
text-align: center;
|
||
width: 100%;
|
||
}
|
||
.equation {
|
||
vertical-align: middle;
|
||
}
|
||
.equation-label {
|
||
display: table-cell;
|
||
text-align: right;
|
||
vertical-align: middle;
|
||
}
|
||
.inlinetask {
|
||
padding: 10px;
|
||
border: 2px solid gray;
|
||
margin: 10px;
|
||
background: #ffffcc;
|
||
}
|
||
#org-div-home-and-up
|
||
{ text-align: right; font-size: 70%; white-space: nowrap; }
|
||
textarea { overflow-x: auto; }
|
||
.linenr { font-size: smaller }
|
||
.code-highlighted { background-color: #ffff00; }
|
||
.org-info-js_info-navigation { border-style: none; }
|
||
#org-info-js_console-label
|
||
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
|
||
.org-info-js_search-highlight
|
||
{ background-color: #ffff00; color: #000000; font-weight: bold; }
|
||
.org-svg { }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="content" class="content">
|
||
<div id="table-of-contents" role="doc-toc">
|
||
<h2>Table of Contents</h2>
|
||
<div id="text-table-of-contents" role="doc-toc">
|
||
<ul>
|
||
<li><a href="#org31bfb6d">1. Introduction</a></li>
|
||
<li><a href="#org7f8a126">2. Pre-requisites to edit this setup</a></li>
|
||
<li><a href="#orgf14a5ad">3. machine1 — template machine</a></li>
|
||
<li><a href="#org5052ca0">4. <code>flake.lock</code> for pinning input versions.</a></li>
|
||
<li><a href="#org0ac27c7">5. <code>assets/*</code> for non-Nix-managed artifacts such as images and wallpapers.</a>
|
||
<ul>
|
||
<li><a href="#org1be9af3">5.1. Emacs + Org + Tangle</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#org6e6fcf0">6. [Emacs](https://www.gnu.org/software/emacs/][Emacs) is used as the editor and execution environment for this literate configuration.</a></li>
|
||
<li><a href="#org4f4a920">7. [Org](https://orgmode.org/][Org) mode provides the document structure and the source block execution model used here.</a></li>
|
||
<li><a href="#orgb020d8b">8. Tangling exports source blocks from this Org document into the corresponding configuration files.</a>
|
||
<ul>
|
||
<li><a href="#orga62cf78">8.1. Nix & NixOS</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#org1c99dd9">9. [Nix](https://nix.dev/][Nix) is used to define packages, environments, and configuration as pure expressions.</a></li>
|
||
<li><a href="#org455382c">10. [NixOS](https://nixos.org/][NixOS) evaluates Nix expressions into a complete system configuration that can be applied by rebuild operations.</a>
|
||
<ul>
|
||
<li><a href="#orgb6939f7">10.1. Repository layout and folder conventions</a></li>
|
||
<li><a href="#org696da14">10.2. Shared domain folders</a></li>
|
||
<li><a href="#orgaad11ff">10.3. Full tree (including unchanged parts)</a></li>
|
||
<li><a href="#org41062b8">10.4. Notes</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#orga5f53d2">11. TLDR App List</a></li>
|
||
<li><a href="#org6a0add1">12. Configuration Variables</a></li>
|
||
<li><a href="#org66d9b42">13. Flake Inputs</a></li>
|
||
<li><a href="#org553c334">14. Flake Output</a>
|
||
<ul>
|
||
<li><a href="#orgbd89a09">14.1. Envrc + Direnv</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#orgd2a37f4">15. Machines</a>
|
||
<ul>
|
||
<li>
|
||
<ul>
|
||
<li><a href="#orgccae45d">15.0.1. Other Utils</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#orga9bac2c">16. Hardware</a></li>
|
||
<li><a href="#org181a7f5">17. Configuration</a>
|
||
<ul>
|
||
<li><a href="#orge0f8111">17.1. Apps section</a></li>
|
||
<li><a href="#org0e41d2b">17.2. install<sub>packages.nix</sub></a></li>
|
||
<li><a href="#org1ca1ff9">17.3. install<sub>flatpaks.nix</sub></a></li>
|
||
<li><a href="#org5bb846e">17.4. Nix Settings</a></li>
|
||
<li><a href="#org2aa422c">17.5. Boot</a></li>
|
||
<li><a href="#org643f41c">17.6. Login</a></li>
|
||
<li><a href="#orgae739e2">17.7. Tuigreet</a></li>
|
||
<li><a href="#org858c232">17.8. LightDM</a></li>
|
||
<li><a href="#orgcd37f26">17.9. Terminal (default system)</a></li>
|
||
<li><a href="#orgd4ad109">17.10. Files</a></li>
|
||
<li><a href="#org0c9a1d4">17.11. Locale</a></li>
|
||
<li><a href="#org1a964f0">17.12. Networking</a></li>
|
||
<li><a href="#orgb3a713c">17.13. Hyprland</a></li>
|
||
<li><a href="#org94c6abe">17.14. Services</a></li>
|
||
<li><a href="#org2b9de4a">17.15. Audio</a></li>
|
||
<li><a href="#org0f989af">17.16. Miscellaneous Packages and Programs</a></li>
|
||
<li><a href="#org5bf1dee">17.17. Fonts</a></li>
|
||
<li><a href="#org0e44064">17.18. User Config</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#org2a2c26b">18. Home</a>
|
||
<ul>
|
||
<li><a href="#org3ac8cb9">18.1. default.nix</a></li>
|
||
<li><a href="#org9dc5e82">18.2. Wallpaper</a></li>
|
||
<li><a href="#orgfabb720">18.3. Waybar</a></li>
|
||
<li><a href="#org2b30ed7">18.4. Lock Screen</a></li>
|
||
<li><a href="#org9ab6667">18.5. Idle Screen</a></li>
|
||
<li><a href="#org0f8983c">18.6. Hyprshell</a></li>
|
||
<li><a href="#orge55154f">18.7. Hyprland</a></li>
|
||
<li><a href="#org58f70c6">18.8. Walker</a></li>
|
||
<li><a href="#org699cddb">18.9. Theme</a></li>
|
||
<li><a href="#orgfe67f7b">18.10. Default-apps</a></li>
|
||
<li><a href="#org99eea47">18.11. Hyperexpo</a></li>
|
||
<li><a href="#org0e841c5">18.12. Alacritty</a></li>
|
||
<li><a href="#orga81b73b">18.13. Dev Tools</a></li>
|
||
<li><a href="#orgf27ff36">18.14. Kitty</a></li>
|
||
<li><a href="#orga78066f">18.15. Shells</a></li>
|
||
<li><a href="#org15f6166">18.16. Zsh</a></li>
|
||
<li><a href="#org5b42cf9">18.17. Starship</a></li>
|
||
<li><a href="#org31d22d5">18.18. Other Settings</a>
|
||
<ul>
|
||
<li><a href="#org7e22fc0">18.18.1. Home User</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#org123eb2a">19. Emacs</a>
|
||
<ul>
|
||
<li><a href="#org74de044">19.1. Early Initialization</a></li>
|
||
<li><a href="#org04e483b">19.2. Initialization</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#orge6efaa4">20. Machines</a>
|
||
<ul>
|
||
<li><a href="#org0b8a9b5">20.1. Traveldroid</a>
|
||
<ul>
|
||
<li><a href="#org2048e57">20.1.1. System Level</a></li>
|
||
<li><a href="#org8326f51">20.1.2. Hardware</a></li>
|
||
<li><a href="#org40e701a">20.1.3. Home</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#orgaa2a768">21. README Utils</a>
|
||
<ul>
|
||
<li>
|
||
<ul>
|
||
<li><a href="#orgc2a81c8">21.0.1. Headers</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<p>
|
||
gf#+OPTIONS: toc:nil broken-links:t
|
||
</p>
|
||
<div align="center">
|
||
<div>
|
||
<img src="./.github/images/nixos.svg" width="100px" alt="NixOS" />
|
||
<img src="./.github/images/emacs.svg" width="100px" alt="Emacs" />
|
||
</div>
|
||
<br />
|
||
<h1>Henrov's Literate System Configuration</h1>
|
||
<div>
|
||
<a href="https://orgmode.org/index.html">
|
||
<img src="https://img.shields.io/badge/org_mode-9.7-blue.svg?style=for-the-badge&labelColor=1e1e2e&logo=org&logoColor=a6e3a1&color=1e1e2e" alt="Org mode" />
|
||
</a>
|
||
<a href="https://nixos.org">
|
||
<img src="https://img.shields.io/badge/NixOS-unstable-blue.svg?style=for-the-badge&labelColor=1e1e2e&logo=NixOS&logoColor=89b4fa&color=1e1e2e" alt="NixOS" />
|
||
</a>
|
||
<a href="https://www.gnu.org/software/emacs/">
|
||
<img src="https://img.shields.io/badge/emacs-30-blue.svg?style=for-the-badge&labelColor=1e1e2e&logo=gnuemacs&logoColor=cba6f7&color=1e1e2e" alt="Emacs" />
|
||
</a>
|
||
<a href="https://gitea.data-pro.nu/system/blob/main/LICENSE">
|
||
<img src="https://img.shields.io/static/v1.svg?style=for-the-badge&label=License&message=GPL&colorA=1e1e2e&colorB=f38ba8&logo=unlicense&logoColor=f9e2af" alt="License" />
|
||
</a>
|
||
<a href="https://gitea.data-pro.nu/system/actions/workflows/tangle.yml">
|
||
<img src="https://img.shields.io/github/actions/workflow/status/gamedolphin/system/tangle.yml?style=for-the-badge&label=Tangle&colorA=1e1e2e&colorB=a6e3a1&logo=github&logoColor=cdd6f4" alt="Tangle workflow" />
|
||
</a>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org31bfb6d" class="outline-2">
|
||
<h2 id="org31bfb6d"><span class="section-number-2">1.</span> Introduction</h2>
|
||
<div class="outline-text-2" id="text-1">
|
||
<div align="center"><img src="./.github/images/need to create screenshot.png" width="100%" alt="Screenshot" /></div>
|
||
|
||
<p>
|
||
This repository contains a literate NixOS configuration built using Emacs Org mode. The primary source of truth is this document itself, which embeds configuration blocks that are tangled into individual files. These generated files are evaluated as a NixOS flake, resulting in an immutable, reproducible system configuration.
|
||
</p>
|
||
|
||
<p>
|
||
This work is based on the foundational efforts of Sandeep Nambiar (<a href="https://github.com/gamedolphin">https://github.com/gamedolphin</a>).
|
||
All credit for the original structure, methodology, and guidance belongs to him. His work provided the architectural basis and practical direction upon which this repository is built. This project would not have been possible without his prior contributions, and much of the instructional approach preserved here originates from his documentation.
|
||
</p>
|
||
|
||
<p>
|
||
The purpose of this repository is to offer a structured, minimal starting point for deploying a functional NixOS system. It is intentionally not a complete desktop environment, nor is it a “batteries-included” distribution. Instead, it provides a clean and extensible foundation that can be adapted and expanded after installation.
|
||
</p>
|
||
|
||
<p>
|
||
Customization is designed to occur primarily through modular .conf files, allowing the system to evolve incrementally while maintaining clarity and separation of concerns. The goal is to enable users to build their own tailored NixOS setup on top of a coherent and reproducible base.
|
||
</p>
|
||
|
||
<p>
|
||
Before proceeding with installation, it is strongly recommended to read this documentation carefully. Understanding the structure and design philosophy will help ensure a smooth setup and provide the necessary context for extending the system effectively.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org7f8a126" class="outline-2">
|
||
<h2 id="org7f8a126"><span class="section-number-2">2.</span> Pre-requisites to edit this setup</h2>
|
||
<div class="outline-text-2" id="text-2">
|
||
<ul class="org-ul">
|
||
<li>a NIXOS system installed (can be bare-bones)</li>
|
||
<li>an internet connection</li>
|
||
</ul>
|
||
|
||
<p>
|
||
To set up a connection from cli:
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-bash"># Check if NetworkManager service is running
|
||
systemctl status NetworkManager
|
||
# If not running, start it temporarily
|
||
sudo systemctl start NetworkManager
|
||
# Enable Wi-Fi radio (in case it is disabled)
|
||
nmcli radio wifi on
|
||
# List available Wi-Fi networks
|
||
nmcli device wifi list
|
||
# Connect to a Wi-Fi network (replace SSID and PASSWORD)
|
||
nmcli device wifi connect "SSID_NAME" password "YOUR_PASSWORD"
|
||
# Verify that the connection is active
|
||
nmcli connection show --active
|
||
# Optional: show device status
|
||
nmcli device status
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgf14a5ad" class="outline-2">
|
||
<h2 id="orgf14a5ad"><span class="section-number-2">3.</span> machine1 — template machine</h2>
|
||
<div class="outline-text-2" id="text-3">
|
||
<p>
|
||
To generate the Nix files:
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-bash">emacs README.org --batch -f org-babel-tangle
|
||
</pre>
|
||
</div>
|
||
|
||
<p>
|
||
Test the build while being able to reboot to previous version
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-bash">sudo nixos-rebuild test --flake .#machine1
|
||
</pre>
|
||
</div>
|
||
<p>
|
||
Build and switch to this version on the next reboot
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-bash">sudo nixos-rebuild switch --flake .#machine1
|
||
</pre>
|
||
</div>
|
||
<p>
|
||
Build and run in a virtual machine (qemu must be installed)
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-bash">sudo nixos-rebuild build-vm --flake ~/nixos-henrov#machine1
|
||
# running the vm:
|
||
./result/bin/run-nixos-vm
|
||
</pre>
|
||
</div>
|
||
<p>
|
||
un this VM with result/
|
||
</p>
|
||
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-bash">emacs README.org --batch -f org-babel-tangle
|
||
</pre>
|
||
</div>
|
||
|
||
<p>
|
||
Once the Nix files are generated, deploy using:
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-bash">nixos-rebuild switch --flake .#<machine>
|
||
</pre>
|
||
</div>
|
||
|
||
<p>
|
||
Other files in this repo include:
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org5052ca0" class="outline-2">
|
||
<h2 id="org5052ca0"><span class="section-number-2">4.</span> <code>flake.lock</code> for pinning input versions.</h2>
|
||
</div>
|
||
<div id="outline-container-org0ac27c7" class="outline-2">
|
||
<h2 id="org0ac27c7"><span class="section-number-2">5.</span> <code>assets/*</code> for non-Nix-managed artifacts such as images and wallpapers.</h2>
|
||
<div class="outline-text-2" id="text-5">
|
||
<p>
|
||
Generated outputs should not be edited directly. A CI workflow can tangle and commit generated outputs when they differ.
|
||
</p>
|
||
</div>
|
||
<div id="outline-container-org1be9af3" class="outline-3">
|
||
<h3 id="org1be9af3"><span class="section-number-3">5.1.</span> Emacs + Org + Tangle</h3>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org6e6fcf0" class="outline-2">
|
||
<h2 id="org6e6fcf0"><span class="section-number-2">6.</span> [<a href="https://www.gnu.org/software/emacs/">Emacs](https://www.gnu.org/software/emacs/][Emacs)</a> is used as the editor and execution environment for this literate configuration.</h2>
|
||
</div>
|
||
<div id="outline-container-org4f4a920" class="outline-2">
|
||
<h2 id="org4f4a920"><span class="section-number-2">7.</span> [<a href="https://orgmode.org/">Org](https://orgmode.org/][Org) mode</a> provides the document structure and the source block execution model used here.</h2>
|
||
</div>
|
||
<div id="outline-container-orgb020d8b" class="outline-2">
|
||
<h2 id="orgb020d8b"><span class="section-number-2">8.</span> Tangling exports source blocks from this Org document into the corresponding configuration files.</h2>
|
||
<div class="outline-text-2" id="text-8">
|
||
<ul class="org-ul">
|
||
<li>References of the form <code><<code-id>></code> are noweb placeholders that are expanded from other blocks during tangling.</li>
|
||
</ul>
|
||
</div>
|
||
<div id="outline-container-orga62cf78" class="outline-3">
|
||
<h3 id="orga62cf78"><span class="section-number-3">8.1.</span> Nix & NixOS</h3>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org1c99dd9" class="outline-2">
|
||
<h2 id="org1c99dd9"><span class="section-number-2">9.</span> [<a href="https://nix.dev/">Nix](https://nix.dev/][Nix)</a> is used to define packages, environments, and configuration as pure expressions.</h2>
|
||
</div>
|
||
<div id="outline-container-org455382c" class="outline-2">
|
||
<h2 id="org455382c"><span class="section-number-2">10.</span> [<a href="https://nixos.org/">NixOS](https://nixos.org/][NixOS)</a> evaluates Nix expressions into a complete system configuration that can be applied by rebuild operations.</h2>
|
||
<div class="outline-text-2" id="text-10">
|
||
</div>
|
||
<div id="outline-container-orgb6939f7" class="outline-3">
|
||
<h3 id="orgb6939f7"><span class="section-number-3">10.1.</span> Repository layout and folder conventions</h3>
|
||
<div class="outline-text-3" id="text-10-1">
|
||
<p>
|
||
This repository contains system modules, user modules, and configuration fragments. The following directories are treated as separate layers:
|
||
<code>./configuration</code> (NixOS modules), <code>./home</code> (Home Manager modules), and <code>./assets/conf</code> (configuration fragments referenced or deployed by the modules).
|
||
</p>
|
||
<p>
|
||
To keep navigation consistent, the same internal substructure is used in all three locations. Each layer keeps its role; only the internal grouping is standardized.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org696da14" class="outline-3">
|
||
<h3 id="org696da14"><span class="section-number-3">10.2.</span> Shared domain folders</h3>
|
||
<div class="outline-text-3" id="text-10-2">
|
||
<ul>
|
||
<li><code>core/</code> – base settings and common infrastructure</li>
|
||
<li><code>desktop/</code> – graphical session, compositor, UI components, and integration</li>
|
||
<li><code>apps/</code> – application enablement and application-level configuration</li>
|
||
<li><code>services/</code> – background services and daemons</li>
|
||
<li><code>security/</code> – secrets handling and security-related configuration</li>
|
||
<li><code>dev/</code> – developer tooling and editor configuration</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgaad11ff" class="outline-3">
|
||
<h3 id="orgaad11ff"><span class="section-number-3">10.3.</span> Full tree (including unchanged parts)</h3>
|
||
<div class="outline-text-3" id="text-10-3">
|
||
<p>
|
||
The tree below shows the full repository layout, with the standardized internal structure applied only inside
|
||
<code>configuration/</code>, <code>home/</code>, and <code>assets/conf/</code>.
|
||
</p>
|
||
|
||
<pre><code>.
|
||
├── assets
|
||
│ ├── background.png
|
||
│ ├── conf
|
||
│ │ ├── apps
|
||
│ │ │ ├── flatpaks.conf
|
||
│ │ │ └── packages.conf
|
||
│ │ ├── core
|
||
│ │ │ └── lightdm.conf
|
||
│ │ ├── desktop
|
||
│ │ │ ├── hypr
|
||
│ │ │ │ ├── bindings.conf
|
||
│ │ │ │ └── hyprland.conf
|
||
│ │ │ ├── wallpaper
|
||
│ │ │ │ └── wallpaper.conf
|
||
│ │ │ └── waybar
|
||
│ │ │ ├── config.jsonc
|
||
│ │ │ └── style.css
|
||
│ │ ├── dev
|
||
│ │ │ ├── hyprshell
|
||
│ │ │ │ ├── config.ron.bak
|
||
│ │ │ │ └── styles.css.bak
|
||
│ │ │ └── terminal
|
||
│ │ │ ├── alacritty.toml
|
||
│ │ │ ├── aliases.conf
|
||
│ │ │ ├── enabled_shells.conf
|
||
│ │ │ ├── kitty.conf
|
||
│ │ │ ├── starship.toml
|
||
│ │ │ └── zsh.conf
|
||
│ │ ├── security
|
||
│ │ │ └── ssh
|
||
│ │ │ └── ssh-client.conf
|
||
│ │ └── services
|
||
│ ├── lock.png
|
||
│ ├── scripts
|
||
│ └── wallpapers
|
||
│ ├── gif
|
||
│ ├── pictures
|
||
│ │ ├── background.png
|
||
│ │ ├── background1.png
|
||
│ │ ├── background2.png
|
||
│ │ ├── background3.png
|
||
│ │ ├── background4.png
|
||
│ │ └── background5.png
|
||
│ └── videos
|
||
│ ├── dark_water_large.mp4
|
||
│ └── white_blobs_small.mp4
|
||
├── configuration
|
||
│ ├── apps
|
||
│ │ ├── install_flatpaks.nix
|
||
│ │ └── install_packages.nix
|
||
│ ├── core
|
||
│ │ ├── boot.nix
|
||
│ │ ├── files.nix
|
||
│ │ ├── locale.nix
|
||
│ │ ├── networking.nix
|
||
│ │ └── nix-settings.nix
|
||
│ ├── default.nix
|
||
│ ├── desktop
|
||
│ │ ├── audio.nix
|
||
│ │ ├── hyprland.nix
|
||
│ │ └── login-tuigreeter.nix
|
||
│ ├── dev
|
||
│ │ └── terminal.nix
|
||
│ ├── security
|
||
│ └── services
|
||
│ └── services.nix
|
||
├── flake.lock
|
||
├── flake.nix
|
||
├── hardware
|
||
│ └── hardware.nix
|
||
├── home
|
||
│ ├── apps
|
||
│ │ ├── defaults-apps.nix
|
||
│ │ └── theme.nix
|
||
│ ├── default.nix
|
||
│ ├── desktop
|
||
│ │ ├── hyprexpo.nix
|
||
│ │ ├── hyprland.nix
|
||
│ │ ├── hyprlock.nix
|
||
│ │ ├── hypridle.nix
|
||
│ │ ├── hyprshell.nix
|
||
│ │ ├── walker.nix
|
||
│ │ ├── wallpaper.nix
|
||
│ │ └── waybar.nix
|
||
│ ├── dev
|
||
│ │ ├── alacritty.nix
|
||
│ │ ├── dev.nix
|
||
│ │ ├── emacs
|
||
│ │ │ ├── default.nix
|
||
│ │ │ ├── early-init.el
|
||
│ │ │ └── init.el
|
||
│ │ ├── kitty.nix
|
||
│ │ ├── shells.nix
|
||
│ │ └── starship.nix
|
||
│ └── zsh.nix
|
||
├── LICENSE
|
||
├── machines
|
||
│ └── traveldroid
|
||
│ ├── configuration.nix
|
||
│ ├── hardware-configuration.nix
|
||
│ └── home.nix
|
||
├── README.org
|
||
├── secrets
|
||
│ └── secrets.yaml
|
||
└── user.nix
|
||
</code></pre>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org41062b8" class="outline-3">
|
||
<h3 id="org41062b8"><span class="section-number-3">10.4.</span> Notes</h3>
|
||
<div class="outline-text-3" id="text-10-4">
|
||
<ul>
|
||
<li>Only the internal layout of <code>configuration/</code>, <code>home/</code>, and <code>assets/conf/</code> is standardized; all other paths remain as currently organized.</li>
|
||
<li>The <code>services/</code> and <code>security/</code> folders are included for completeness even if initially empty in some layers.</li>
|
||
</ul>
|
||
|
||
<p>
|
||
<code>YourNixCode(Input) -> System Configuration</code>
|
||
</p>
|
||
|
||
<p>
|
||
I use <a href="https://nixos.wiki/wiki/Flakes">nix flakes</a> which means that the entry point for the nix evaluation is a file called <code>flake.nix</code> which has two parts (among other things)
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{
|
||
inputs: # describes the function input, consisting mainly of package sources
|
||
outputs: # what the function outputs, a nixos configuration in our case
|
||
}
|
||
</pre>
|
||
</div>
|
||
|
||
<p>
|
||
Nix flakes is still behind an <code>experimental</code> flag, but it is de facto the standard by most of the community.
|
||
Flakes allow us to pin the input package versions using a <code>flake.lock</code> file.
|
||
This prevents unwanted and surprise updates when rebuilding without changing the configuration.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orga5f53d2" class="outline-2">
|
||
<h2 id="orga5f53d2"><span class="section-number-2">11.</span> TLDR App List</h2>
|
||
<div class="outline-text-2" id="text-11">
|
||
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
||
|
||
|
||
<colgroup>
|
||
<col class="org-left" />
|
||
|
||
<col class="org-left" />
|
||
</colgroup>
|
||
<tbody>
|
||
<tr>
|
||
<td class="org-left">Window Manager</td>
|
||
<td class="org-left"><a href="https://hyprland.org/">Hyprland</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Bar</td>
|
||
<td class="org-left"><a href="https://github.com/Alexays/Waybar">Waybar</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Application Launcher</td>
|
||
<td class="org-left"><a href="https://github.com/abenz1267/walker">Walker</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Notification Daemon</td>
|
||
<td class="org-left"><a href="https://github.com/dunst-project/dunst">Dunst</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Terminal Emulator</td>
|
||
<td class="org-left"><a href="https://alacritty.org/">Alacritty</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Shell</td>
|
||
<td class="org-left"><a href="https://ohmyz.sh/">Zsh</a> and <a href="https://starship.rs/">Starship</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Text Editor</td>
|
||
<td class="org-left"><a href="https://www.gnu.org/software/emacs/">Emacs</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">File Manager</td>
|
||
<td class="org-left"><a href="https://docs.xfce.org/xfce/thunar/start">Thunar</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Fonts</td>
|
||
<td class="org-left"><a href="https://protesilaos.com/codelog/2025-02-12-aporetic-fonts-version-1-1-0/">Aporeti</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Colors</td>
|
||
<td class="org-left"><a href="https://catppuccin.com/">Catppuccin</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Icons</td>
|
||
<td class="org-left"><a href="https://nix.catppuccin.com/">Catppuccin Nix </a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Lock Screen</td>
|
||
<td class="org-left"><a href="https://wiki.hyprland.org/Hypr-Ecosystem/hyprlock/">Hyprlock</a></td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td class="org-left">Wallpapers</td>
|
||
<td class="org-left"><a href="https://github.com/hyprwm/hyprpaper">Hyprpaper</a></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org6a0add1" class="outline-2">
|
||
<h2 id="org6a0add1"><span class="section-number-2">12.</span> Configuration Variables</h2>
|
||
<div class="outline-text-2" id="text-12">
|
||
<p>
|
||
I have a bunch of constant strings that I would rather put in a file. Thats what <code>user.nix</code> is.
|
||
The values are imported at the beginning and are available to almost all the functions being called to configure the system.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{
|
||
system = "x86_64-linux";
|
||
username = "henrov";
|
||
stateVersion = "25.11";
|
||
locale = "nl_NL.UTF-8";
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org66d9b42" class="outline-2">
|
||
<h2 id="org66d9b42"><span class="section-number-2">13.</span> Flake Inputs</h2>
|
||
<div class="outline-text-2" id="text-13">
|
||
<p>
|
||
The inputs for my system's configuration are very simple
|
||
</p>
|
||
<ol class="org-ol">
|
||
<li><a href="https://search.nixos.org/packages">nixpkgs</a> - the main nix repository of packages. Its huge and growing. Pinned to the unstable release channel.
|
||
Sometimes pinned to a specific commit because unstable broke something and the fix hasn't made it into the release yet.</li>
|
||
<li><a href="https://nix-community.github.io/home-manager/">home-manager</a> - a nix module that helps keep track of user specific dotfiles and configurations as part of my nix config.</li>
|
||
<li><a href="https://github.com/nix-community/emacs-overlay">emacs-overlay</a> - this has more configuration options and generally a newer emacs available provided by the community.</li>
|
||
<li><a href="https://nix.catppuccin.com/">catppuccin</a> - nix module that allows everything to be catppuccin themed.</li>
|
||
</ol>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{
|
||
description = "Henrov's nixos configuration";
|
||
inputs = {
|
||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||
home-manager = {
|
||
url = "github:nix-community/home-manager";
|
||
inputs.nixpkgs.follows = "nixpkgs";
|
||
};
|
||
emacs-overlay = {
|
||
url = "github:nix-community/emacs-overlay";
|
||
inputs.nixpkgs.follows = "nixpkgs";
|
||
};
|
||
catppuccin = {
|
||
url = "github:catppuccin/nix";
|
||
inputs.nixpkgs.follows = "nixpkgs";
|
||
};
|
||
zen-browser = {
|
||
url = "github:youwen5/zen-browser-flake";
|
||
inputs.nixpkgs.follows = "nixpkgs";
|
||
};
|
||
};
|
||
<<flake-outputs>>
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org553c334" class="outline-2">
|
||
<h2 id="org553c334"><span class="section-number-2">14.</span> Flake Output</h2>
|
||
<div class="outline-text-2" id="text-14">
|
||
<p>
|
||
Now that the inputs are ready, the outputs define what the system will actually look like. I also define the machines that this configuration specifies early on. Finally, I iterate over the <code>machines</code> list and pull files from <code>/.machines/${name}</code> subdirectory. This allows me to have configuration that has machine specific configuration limited to those files while also keeping a modular reusable base.
|
||
We also add a devshell that makes editing this repository easier in emacs.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="org4f3f25c">outputs = inputs@{
|
||
nixpkgs,
|
||
home-manager,
|
||
emacs-overlay,
|
||
catppuccin,
|
||
...
|
||
}:
|
||
let
|
||
user = import ./user.nix;
|
||
lib = nixpkgs.lib;
|
||
machines = [
|
||
"traveldroid"
|
||
];
|
||
pkgs = import nixpkgs {
|
||
inherit (user) system;
|
||
};
|
||
in
|
||
{
|
||
nixosConfigurations = builtins.listToAttrs (
|
||
builtins.map (machine: {
|
||
name = machine;
|
||
value = lib.nixosSystem {
|
||
modules = [
|
||
<<flake-emacs-module>>
|
||
<<flake-config-module>>
|
||
<<flake-home-module>>
|
||
catppuccin.nixosModules.catppuccin # theme
|
||
];
|
||
|
||
specialArgs = {
|
||
hostname = machine;
|
||
inherit user;
|
||
inherit inputs;
|
||
flakeRoot = inputs.self;
|
||
};
|
||
};
|
||
}) machines
|
||
);
|
||
|
||
devShells.${user.system}.default = pkgs.mkShell {
|
||
buildInputs = with pkgs; [
|
||
nil
|
||
nixfmt-rfc-style
|
||
];
|
||
};
|
||
};
|
||
|
||
</pre>
|
||
</div>
|
||
|
||
<p>
|
||
Lets look at the individual modules
|
||
</p>
|
||
<ol class="org-ol">
|
||
<li><p>
|
||
Emacs
|
||
The first is the emacs overlay so that it uses the nix-community emacs overlay from the inputs instead of the nixpkgs one.
|
||
Overlays are a special nix way to override existing packages within a repository.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="org0e6283f">({ ... }: {
|
||
nixpkgs.overlays = [ emacs-overlay.overlays.default ];
|
||
})
|
||
</pre>
|
||
</div></li>
|
||
|
||
<li><p>
|
||
Then the machine specific configuration, in this case, just "traveldroid".
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="org2b21236">./machines/${machine}/configuration.nix
|
||
</pre>
|
||
</div></li>
|
||
|
||
<li><p>
|
||
And finally the home-manager module.
|
||
This can be initialized and managed on its own but I'd rather use the <code>nixos-rebuild</code> command to build everything instead of managing userland dotfiles separately.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="org9e2d3d1">home-manager.nixosModules.home-manager
|
||
{
|
||
home-manager.useGlobalPkgs = true;
|
||
home-manager.useUserPackages = true;
|
||
|
||
home-manager.extraSpecialArgs = {
|
||
inherit user inputs;
|
||
flakeRoot = inputs.self;
|
||
};
|
||
|
||
<<flake-home-backup>>
|
||
<<flake-home-config>>
|
||
}
|
||
|
||
</pre>
|
||
</div>
|
||
|
||
<ul class="org-ul">
|
||
<li><p>
|
||
Home-Manager will not overwrite existing configuration files and that is good in most cases, but when everything is declarative like it is here, I'd rather that home-manager create a <code>.backup</code> and replace the file.
|
||
</p></li>
|
||
</ul>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">home-manager.backupFileExtension = "backup";
|
||
</pre>
|
||
</div>
|
||
|
||
<ul class="org-ul">
|
||
<li><p>
|
||
Finally I pull in the machine specific home configuration. Along with the overrides from catppuccin.
|
||
</p></li>
|
||
</ul>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">home-manager.users.${user.username} = {
|
||
imports = [
|
||
./machines/${machine}/home.nix
|
||
catppuccin.homeModules.catppuccin
|
||
];
|
||
};
|
||
</pre>
|
||
</div></li>
|
||
</ol>
|
||
</div>
|
||
<div id="outline-container-orgbd89a09" class="outline-3">
|
||
<h3 id="orgbd89a09"><span class="section-number-3">14.1.</span> Envrc + Direnv</h3>
|
||
<div class="outline-text-3" id="text-14-1">
|
||
<p>
|
||
Editing this file will be much nicer if we have the dev environment configured.
|
||
That is done in the devshells section. But to auto load this dev shell, we need a .envrc file.
|
||
This tells <a href="https://direnv.net/">direnv</a> to load the devshell in the flake.
|
||
#Finally, we also look for a .envrc-private file and try to load that. That contains devshell specific secrets.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">use flake
|
||
|
||
watch_file .envrc.private
|
||
if [[ -f .envrc.private ]]; then
|
||
source_env .envrc.private
|
||
fi
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgd2a37f4" class="outline-2">
|
||
<h2 id="orgd2a37f4"><span class="section-number-2">15.</span> Machines</h2>
|
||
<div class="outline-text-2" id="text-15">
|
||
<p>
|
||
The individual machines subdirectory is configured as follows :-
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-ditaa" id="orgedc6cf4">+--machine
|
||
| +--configuration.nix
|
||
| +--home.nix
|
||
| +--hardware-configuration.nix
|
||
</pre>
|
||
</div>
|
||
|
||
<ul class="org-ul">
|
||
<li>configuration.nix has the system configuration.</li>
|
||
<li>home.nix has the user level configuration.</li>
|
||
<li>hardware-configuration.nix has the unique hardware configuration.</li>
|
||
|
||
<li>Note about imports
|
||
<code>imports = []</code> in a nix file will pull in the function/object from the list of files provided.
|
||
This imported object (or function result) is just trivially merged into a common object.</li>
|
||
</ul>
|
||
|
||
<p>
|
||
We can take a look at that the common hardware options I have for all my machines.
|
||
</p>
|
||
</div>
|
||
<div id="outline-container-orgccae45d" class="outline-4">
|
||
<h4 id="orgccae45d"><span class="section-number-4">15.0.1.</span> Other Utils</h4>
|
||
<div class="outline-text-4" id="text-15-0-1">
|
||
</div>
|
||
<ol class="org-ol">
|
||
<li><a id="orga9799fd"></a>Updates<br />
|
||
<div class="outline-text-5" id="text-15-0-1-1">
|
||
<p>
|
||
To update the computer, I just need to update the <code>flake.lock</code> file to have references to the latest repository. This is done with :-
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-bash">nix flake update
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orga9bac2c" class="outline-2">
|
||
<h2 id="orga9bac2c"><span class="section-number-2">16.</span> Hardware</h2>
|
||
<div class="outline-text-2" id="text-16">
|
||
<p>
|
||
I'll let the code comments explain the file here.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, lib, user, config, ...} :
|
||
{
|
||
nixpkgs.hostPlatform = lib.mkDefault user.system; # x86_64-linux
|
||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; # enable power saving on the cpu
|
||
|
||
# update cpu microcode with firmware that allows redistribution
|
||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||
|
||
hardware = {
|
||
# always enable bluetooth
|
||
bluetooth.enable = true;
|
||
|
||
# always enable graphics drivers and enable a bunch of layers for it (including vulkan validation)
|
||
graphics = {
|
||
enable = true;
|
||
extraPackages = with pkgs; [
|
||
vulkan-validation-layers # helps catch and debug vulkan crashes
|
||
];
|
||
};
|
||
};
|
||
|
||
hardware.enableAllFirmware = true; # enable all firmware regardless of license
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org181a7f5" class="outline-2">
|
||
<h2 id="org181a7f5"><span class="section-number-2">17.</span> Configuration</h2>
|
||
<div class="outline-text-2" id="text-17">
|
||
<p>
|
||
This section describes the main system configuration for the computers that I have. Nix will look for a <code>default.nix</code> file if you give it a path to a folder to import. And <code>default.nix</code> looks as follows :-
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix"> { pkgs, user, ... } :
|
||
{
|
||
imports = [
|
||
./apps/install_flatpaks.nix
|
||
./apps/install_packages.nix
|
||
./core/files.nix
|
||
./core/locale.nix
|
||
./core/networking.nix
|
||
./core/nix-settings.nix
|
||
#./core/login-tuigreeter.nix
|
||
./core/login-lightdm.nix
|
||
./desktop/audio.nix
|
||
./desktop/hyprland.nix
|
||
./dev/terminal.nix
|
||
./core/boot.nix
|
||
./services/services.nix
|
||
];
|
||
|
||
<<config-system-packages>>
|
||
|
||
<<config-user>>
|
||
|
||
<<config-programs>>
|
||
|
||
<<config-fonts>>
|
||
|
||
# enable the catppuccin theme for everything with mocha + blue accents
|
||
catppuccin.enable = true;
|
||
catppuccin.flavor = "mocha";
|
||
catppuccin.accent = "blue";
|
||
|
||
system.stateVersion = user.stateVersion;
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orge0f8111" class="outline-3">
|
||
<h3 id="orge0f8111"><span class="section-number-3">17.1.</span> Apps section</h3>
|
||
<div class="outline-text-3" id="text-17-1">
|
||
<p>
|
||
This section describes a way of installing packages, either through nixpkgs orr flatpak. What apps to instal is decided in the files ./assets/conf/apps/packages.conf and flatpaks.conf
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org0e41d2b" class="outline-3">
|
||
<h3 id="org0e41d2b"><span class="section-number-3">17.2.</span> install<sub>packages.nix</sub></h3>
|
||
<div class="outline-text-3" id="text-17-2">
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, lib, pkgs, flakeRoot, inputs, ... }:
|
||
|
||
let
|
||
packagesConfPath = flakeRoot + "/assets/conf/apps/packages.conf";
|
||
raw = builtins.readFile packagesConfPath;
|
||
|
||
# IMPORTANT: explicit "\n" so we never accidentally split into characters
|
||
rawLines = lib.splitString "\n" raw;
|
||
|
||
# Guard: if we accidentally split into characters, rawLines length ~= stringLength raw
|
||
_guard = assert !(
|
||
builtins.stringLength raw > 1 &&
|
||
builtins.length rawLines == builtins.stringLength raw
|
||
); true;
|
||
|
||
cleanLine = l:
|
||
let
|
||
noCR = lib.replaceStrings [ "\r" ] [ "" ] l;
|
||
noInlineComment = lib.head (lib.splitString "#" noCR);
|
||
in
|
||
lib.strings.trim noInlineComment;
|
||
|
||
entries =
|
||
builtins.filter (l: l != "")
|
||
(map cleanLine rawLines);
|
||
|
||
resolvePkg = name:
|
||
let
|
||
parts = lib.splitString "." name;
|
||
found = lib.attrByPath parts null pkgs;
|
||
in
|
||
if found == null then
|
||
throw ''
|
||
install_packages.nix: package not found in pkgs
|
||
|
||
Token : ${builtins.toJSON name}
|
||
packages.conf : ${toString packagesConfPath}
|
||
Hint : check the attribute name on search.nixos.org/packages
|
||
''
|
||
else
|
||
found;
|
||
|
||
packages = builtins.seq _guard (map resolvePkg entries);
|
||
|
||
zenBrowser =
|
||
inputs.zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||
|
||
in
|
||
{
|
||
environment.systemPackages =
|
||
packages
|
||
++ [ zenBrowser ];
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org1ca1ff9" class="outline-3">
|
||
<h3 id="org1ca1ff9"><span class="section-number-3">17.3.</span> install<sub>flatpaks.nix</sub></h3>
|
||
<div class="outline-text-3" id="text-17-3">
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, flakeRoot, ... }:
|
||
|
||
let
|
||
moduleName = "install-flatpaks";
|
||
flatpakConfPath = flakeRoot + "/assets/conf/apps/flatpaks.conf";
|
||
raw = builtins.readFile flatpakConfPath;
|
||
|
||
# Explicit "\n" so we never accidentally split into characters
|
||
rawLines = lib.splitString "\n" raw;
|
||
|
||
# Guard: if we accidentally split into characters, rawLines length ~= stringLength raw
|
||
_guard = assert !(
|
||
builtins.stringLength raw > 1 &&
|
||
builtins.length rawLines == builtins.stringLength raw
|
||
); true;
|
||
|
||
cleanLine = l:
|
||
let
|
||
noCR = lib.replaceStrings [ "\r" ] [ "" ] l;
|
||
noInlineComment = lib.head (lib.splitString "#" noCR);
|
||
in
|
||
lib.strings.trim noInlineComment;
|
||
|
||
entries =
|
||
builtins.filter (l: l != "")
|
||
(map cleanLine rawLines);
|
||
|
||
# Flatpak app IDs are reverse-DNS style like org.example.App (at least 2 dots).
|
||
# We'll validate and fail early with a clear message.
|
||
dotCount = s: builtins.length (lib.splitString "." s) - 1;
|
||
|
||
isValidId = s:
|
||
(dotCount s) >= 2; # matches the error you're seeing: "at least 2 periods"
|
||
|
||
_validate =
|
||
builtins.seq _guard (
|
||
builtins.map (id:
|
||
if isValidId id then true else
|
||
throw ''
|
||
${moduleName}: invalid Flatpak ID in flatpaks.conf (needs reverse-DNS with at least 2 dots)
|
||
|
||
Token : ${builtins.toJSON id}
|
||
flatpaks.conf : ${toString flatpakConfPath}
|
||
|
||
Fix: remove stray tokens/headers, or comment them out with '#'.
|
||
''
|
||
) entries
|
||
);
|
||
|
||
# Use validated entries
|
||
flatpakApps = builtins.seq _validate entries;
|
||
|
||
syncFlatpaks = pkgs.writeShellScript "sync-flatpaks" ''
|
||
set -euo pipefail
|
||
|
||
# Use the deployed config path (matches environment.etc below)
|
||
CONF="/etc/flatpak/flatpaks.conf"
|
||
if [[ -f "$CONF" ]]; then
|
||
echo "flatpak-sync: using $CONF"
|
||
else
|
||
echo "flatpak-sync: WARNING: $CONF not found, using embedded list"
|
||
fi
|
||
|
||
if ! flatpak remotes --system --columns=name | grep -qx flathub; then
|
||
flatpak remote-add --system --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||
fi
|
||
|
||
desired_apps=(
|
||
${lib.concatStringsSep "\n" (map (a: ''"${a}"'') flatpakApps)}
|
||
)
|
||
|
||
for app in "''${desired_apps[@]}"; do
|
||
if ! flatpak info --system "$app" >/dev/null 2>&1; then
|
||
flatpak install --system -y --noninteractive flathub "$app"
|
||
fi
|
||
done
|
||
'';
|
||
in
|
||
{
|
||
services.flatpak.enable = true;
|
||
|
||
xdg.portal = {
|
||
enable = true;
|
||
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
|
||
};
|
||
|
||
# Deploy the config file for runtime visibility/debugging
|
||
environment.etc."flatpak/flatpaks.conf".source = flatpakConfPath;
|
||
|
||
systemd.services.flatpak-sync = {
|
||
description = "Install Flatpak apps listed in flatpaks.conf";
|
||
wantedBy = [ "multi-user.target" ];
|
||
wants = [ "network-online.target" ];
|
||
after = [ "network-online.target" ];
|
||
|
||
serviceConfig = {
|
||
Type = "oneshot";
|
||
ExecStart = syncFlatpaks;
|
||
};
|
||
|
||
restartTriggers = [ flatpakConfPath ];
|
||
path = [ pkgs.flatpak pkgs.coreutils pkgs.gnugrep pkgs.gnused ];
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org5bb846e" class="outline-3">
|
||
<h3 id="org5bb846e"><span class="section-number-3">17.4.</span> Nix Settings</h3>
|
||
<div class="outline-text-3" id="text-17-4">
|
||
<p>
|
||
These are global nix settings that configure the settings for the actual tool.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, user, ... } :
|
||
{
|
||
nix.settings = {
|
||
# enable flakes
|
||
experimental-features = ["nix-command" "flakes"];
|
||
|
||
# add a cache that speed up new applications by downloading binaries
|
||
# from the trusted cache instead of compiling from sourcer
|
||
substituters = [
|
||
"https://nix-community.cachix.org"
|
||
];
|
||
# trust the cache public key
|
||
trusted-public-keys = [
|
||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||
];
|
||
};
|
||
|
||
# allow proprietary software on this machine. I'm not a purist.
|
||
nixpkgs.config.allowUnfree = true;
|
||
# unityhub depends on this... for now
|
||
nixpkgs.config.permittedInsecurePackages = [ "libxml2-2.13.8" ];
|
||
|
||
# this declares how often old configurations are cleared up.
|
||
# i cleanup anything older than a week, every week.
|
||
nix.gc = {
|
||
automatic = true;
|
||
options = "--delete-older-than 7d";
|
||
dates = "weekly";
|
||
};
|
||
|
||
programs = {
|
||
# command line utility that makes applying changes easy and pretty
|
||
nh = {
|
||
enable = true;
|
||
flake = "/home/${user.username}/system";
|
||
};
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org2aa422c" class="outline-3">
|
||
<h3 id="org2aa422c"><span class="section-number-3">17.5.</span> Boot</h3>
|
||
<div class="outline-text-3" id="text-17-5">
|
||
<p>
|
||
This file has most of the settings the control how the computer boots up.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, ... } :
|
||
{
|
||
boot = {
|
||
initrd = {
|
||
verbose = false; # its a lot of logs. dont need it, unless we do.
|
||
kernelModules = [ ]; # no kernel modules on boot
|
||
};
|
||
|
||
extraModulePackages = [ ]; # no extra packages on boot either
|
||
kernelPackages = pkgs.linuxPackages_latest; # latest greatest linux kernel
|
||
kernelParams = [ "silent" ]; # quiet those logs
|
||
|
||
consoleLogLevel = 0; # quiten more logs
|
||
plymouth.enable = true; # graphical boot animation instead
|
||
|
||
supportedFilesystems = [ "ntfs" ]; # should see the ntfs (windows)
|
||
|
||
loader = {
|
||
systemd-boot.enable = true; # systemd-boot
|
||
systemd-boot.configurationLimit = 10;
|
||
efi.canTouchEfiVariables = true; # allow editing efi to edit the boot loader
|
||
|
||
|
||
timeout = 5; # grub timeout to make a selection
|
||
};
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org643f41c" class="outline-3">
|
||
<h3 id="org643f41c"><span class="section-number-3">17.6.</span> Login</h3>
|
||
<div class="outline-text-3" id="text-17-6">
|
||
<p>
|
||
Here we control what the login screen would look like. In configuration/default.nix you can choose whether to use tuigreet (very minimalistic) or LightDM (nicer, themeable)
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgae739e2" class="outline-3">
|
||
<h3 id="orgae739e2"><span class="section-number-3">17.7.</span> Tuigreet</h3>
|
||
<div class="outline-text-3" id="text-17-7">
|
||
<p>
|
||
Doesn't match the rest of the aesthetic of the system (with hyprland), but I like its simplicity.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, user, ... } :
|
||
{
|
||
environment.systemPackages = with pkgs; [
|
||
tuigreet
|
||
];
|
||
services.greetd = {
|
||
enable = true;
|
||
settings = {
|
||
default_session = {
|
||
command = pkgs.lib.mkForce "${pkgs.tuigreet}/bin/tuigreet --remember --time --time-format '%I:%M %p | %a • %h | %F'";
|
||
};
|
||
};
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org858c232" class="outline-3">
|
||
<h3 id="org858c232"><span class="section-number-3">17.8.</span> LightDM</h3>
|
||
<div class="outline-text-3" id="text-17-8">
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, ... }:
|
||
|
||
let
|
||
lightdmConf = builtins.readFile ../../assets/conf/core/lightdm.conf;
|
||
lockPng = ../../assets/lock.png;
|
||
|
||
greeterConfPath = ../../assets/conf/core/lightdm-gtk-greeter.conf;
|
||
greeterRaw = builtins.readFile greeterConfPath;
|
||
|
||
# Extract "key = value" from the greeter conf.
|
||
# Returns null if not found.
|
||
getIniValue = key:
|
||
let
|
||
lines = lib.splitString "\n" greeterRaw;
|
||
|
||
# Captures the value part (group 0) from a single line.
|
||
# We match line-by-line because Nix regex does NOT support PCRE flags like (?s).
|
||
m =
|
||
let
|
||
ms = builtins.filter (x: x != null) (map (line:
|
||
builtins.match
|
||
("^[[:space:]]*" + key + "[[:space:]]*=[[:space:]]*([^#;]+).*$")
|
||
line
|
||
) lines);
|
||
in
|
||
if ms == [] then null else builtins.elemAt ms 0;
|
||
in
|
||
if m == null then null else lib.strings.trim (builtins.elemAt m 0);
|
||
|
||
# In your greeter.conf these are *package keys*, not theme names.
|
||
themePkgKey = getIniValue "theme-name";
|
||
iconPkgKey = getIniValue "icon-theme-name";
|
||
cursorPkgKey = getIniValue "cursor-theme-name";
|
||
|
||
cursorSizeStr = getIniValue "cursor-theme-size";
|
||
cursorSize =
|
||
if cursorSizeStr == null then null
|
||
else lib.toInt (lib.strings.trim cursorSizeStr);
|
||
|
||
# Map package-keys (from greeter.conf) -> { package, name }
|
||
#
|
||
# IMPORTANT:
|
||
# - "name" must be the real theme/icon/cursor NAME as seen under share/themes or share/icons.
|
||
# - "package" is the Nixpkgs derivation providing it.
|
||
pkgMap = {
|
||
catppuccinThemePkg = {
|
||
package = pkgs.catppuccin-gtk.override {
|
||
accents = [ "blue" ];
|
||
variant = "mocha";
|
||
size = "standard";
|
||
tweaks = [ ];
|
||
};
|
||
name = "Catppuccin-Mocha-Standard-Blue-Dark";
|
||
};
|
||
|
||
papirus-icon-theme = {
|
||
package = pkgs.papirus-icon-theme;
|
||
name = "Papirus-Dark";
|
||
};
|
||
|
||
bibata-cursors = {
|
||
package = pkgs.bibata-cursors;
|
||
name = "Bibata-Modern-Ice";
|
||
};
|
||
};
|
||
|
||
pick = key:
|
||
if key == null then
|
||
throw "lightdm: missing required key in ${toString greeterConfPath}"
|
||
else if !(pkgMap ? "${key}") then
|
||
throw "lightdm: unknown package key '${key}' in ${toString greeterConfPath}. Known keys: ${lib.concatStringsSep ", " (builtins.attrNames pkgMap)}"
|
||
else
|
||
pkgMap."${key}";
|
||
|
||
themeSel = pick themePkgKey;
|
||
iconSel = pick iconPkgKey;
|
||
cursorSel = pick cursorPkgKey;
|
||
|
||
# Rewrite greeter.conf so LightDM sees REAL names, not package keys.
|
||
# Also force background to lockPng.
|
||
greeterFixed =
|
||
''
|
||
[greeter]
|
||
theme-name = ${themeSel.name}
|
||
icon-theme-name = ${iconSel.name}
|
||
cursor-theme-name = ${cursorSel.name}
|
||
${lib.optionalString (cursorSize != null) "cursor-theme-size = ${toString cursorSize}"}
|
||
''
|
||
+ "\n"
|
||
+ greeterRaw;
|
||
in
|
||
{
|
||
services.greetd.enable = false;
|
||
|
||
services.xserver = {
|
||
enable = true;
|
||
desktopManager.xterm.enable = false;
|
||
|
||
displayManager.lightdm = {
|
||
enable = true;
|
||
background = lockPng;
|
||
|
||
greeters.gtk = {
|
||
enable = true;
|
||
|
||
theme = {
|
||
name = themeSel.name;
|
||
package = themeSel.package;
|
||
};
|
||
|
||
iconTheme = {
|
||
name = iconSel.name;
|
||
package = iconSel.package;
|
||
};
|
||
|
||
cursorTheme = {
|
||
name = cursorSel.name;
|
||
package = cursorSel.package;
|
||
} // lib.optionalAttrs (cursorSize != null) {
|
||
size = cursorSize;
|
||
};
|
||
|
||
# This includes your (rewritten) greeter config.
|
||
extraConfig = greeterFixed;
|
||
};
|
||
|
||
extraConfig = lightdmConf;
|
||
};
|
||
};
|
||
|
||
programs.hyprland.enable = true;
|
||
|
||
# Optional: make them available system-wide as well
|
||
environment.systemPackages = [
|
||
themeSel.package
|
||
iconSel.package
|
||
cursorSel.package
|
||
];
|
||
}
|
||
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgcd37f26" class="outline-3">
|
||
<h3 id="orgcd37f26"><span class="section-number-3">17.9.</span> Terminal (default system)</h3>
|
||
<div class="outline-text-3" id="text-17-9">
|
||
<p>
|
||
This is the initial system level configuration for the terminal that I use on this machine. Its just <a href="https://ohmyz.sh/">zsh</a>.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, user, ... }:
|
||
{
|
||
console.useXkbConfig = true;
|
||
users.users.${user.username}.shell = pkgs.zsh;
|
||
programs.zsh.enable = true;
|
||
environment.shells = [ pkgs.zsh ];
|
||
environment.pathsToLink = [ "/share/zsh" ];
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgd4ad109" class="outline-3">
|
||
<h3 id="orgd4ad109"><span class="section-number-3">17.10.</span> Files</h3>
|
||
<div class="outline-text-3" id="text-17-10">
|
||
<p>
|
||
I use Thunar as the file explorer. Also setup a few plugins for <a href="https://docs.xfce.org/xfce/thunar/start">Thunar</a> in this config.
|
||
Along with that, a few other utilities like zip and enabling services to automount usb drives.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, user, config, ... }:
|
||
{
|
||
environment.systemPackages = with pkgs; [
|
||
zip
|
||
unzip
|
||
p7zip
|
||
usbutils
|
||
udiskie
|
||
file-roller
|
||
];
|
||
|
||
programs.thunar = {
|
||
enable = true;
|
||
plugins = with pkgs; [
|
||
thunar-archive-plugin
|
||
thunar-media-tags-plugin
|
||
thunar-volman
|
||
thunar-vcs-plugin
|
||
];
|
||
};
|
||
|
||
programs.xfconf.enable = true; # to save thunar settings
|
||
|
||
services = {
|
||
gvfs.enable = true; # Mount, trash, and other functionalities
|
||
tumbler.enable = true; # Thumbnail support for images
|
||
udisks2.enable = true; # Auto mount usb drives
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org0c9a1d4" class="outline-3">
|
||
<h3 id="org0c9a1d4"><span class="section-number-3">17.11.</span> Locale</h3>
|
||
<div class="outline-text-3" id="text-17-11">
|
||
<p>
|
||
I live in Netherlands and would like all my locale and timezone settings to match. Except my default locale.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ user, ... } :
|
||
let
|
||
locale = user.locale;
|
||
defaultLocale = "nl_NL.UTF-8";
|
||
in
|
||
{
|
||
# Set your time zone.
|
||
time.timeZone = "Europe/Amsterdam";
|
||
|
||
# Select internationalisation properties.
|
||
i18n.defaultLocale = defaultLocale;
|
||
|
||
i18n.extraLocaleSettings = {
|
||
LC_ADDRESS = locale;
|
||
LC_IDENTIFICATION = locale;
|
||
LC_MEASUREMENT = locale;
|
||
LC_MONETARY = locale;
|
||
LC_NAME = locale;
|
||
LC_NUMERIC = locale;
|
||
LC_PAPER = locale;
|
||
LC_TELEPHONE = locale;
|
||
LC_TIME = defaultLocale;
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org1a964f0" class="outline-3">
|
||
<h3 id="org1a964f0"><span class="section-number-3">17.12.</span> Networking</h3>
|
||
<div class="outline-text-3" id="text-17-12">
|
||
<p>
|
||
Not much to see here. I want networking to be enabled. I want firewall as well.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, lib, ... }:
|
||
{
|
||
networking = {
|
||
useDHCP = lib.mkDefault true;
|
||
networkmanager.enable = true;
|
||
networkmanager.wifi.backend = "iwd";
|
||
wireless.iwd.enable = true;
|
||
wireless.userControlled.enable = true;
|
||
firewall = {
|
||
enable = true;
|
||
# KDE Connect: discovery + encrypted connections
|
||
allowedTCPPortRanges = [
|
||
{ from = 1714; to = 1764; }
|
||
];
|
||
allowedUDPPortRanges = [
|
||
{ from = 1714; to = 1764; }
|
||
];
|
||
};
|
||
};
|
||
environment.systemPackages = with pkgs; [ impala ];
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgb3a713c" class="outline-3">
|
||
<h3 id="orgb3a713c"><span class="section-number-3">17.13.</span> Hyprland</h3>
|
||
<div class="outline-text-3" id="text-17-13">
|
||
<p>
|
||
This is a big one because the DE needs so much configuration. This section mostly installs <a href="https://hyprland.org/">Hyprland</a>.
|
||
The configuration is done in the home manager section.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, ... }:
|
||
{
|
||
nix.settings = {
|
||
substituters = [ "https://hyprland.cachix.org" ];
|
||
trusted-public-keys = [
|
||
"hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
|
||
];
|
||
};
|
||
services.dbus.enable = true;
|
||
security.polkit.enable = true;
|
||
services.flatpak.enable = true;
|
||
services.pipewire = {
|
||
enable = true;
|
||
alsa.enable = true;
|
||
alsa.support32Bit = true;
|
||
pulse.enable = true;
|
||
wireplumber.enable = true;
|
||
};
|
||
services.gvfs.enable = true;
|
||
xdg.portal = {
|
||
enable = true;
|
||
extraPortals = with pkgs; [
|
||
xdg-desktop-portal-hyprland
|
||
xdg-desktop-portal-gtk
|
||
];
|
||
config.common.default = [ "hyprland" "gtk" ];
|
||
};
|
||
environment.systemPackages = with pkgs; [
|
||
walker
|
||
uwsm
|
||
hyprland-qtutils
|
||
hyprpolkitagent
|
||
grimblast
|
||
];
|
||
programs = {
|
||
uwsm.enable = true;
|
||
uwsm.waylandCompositors.hyprland = {
|
||
prettyName = "Hyprland";
|
||
comment = "Hyprland compositor managed by UWSM";
|
||
binPath = "/run/current-system/sw/bin/Hyprland";
|
||
};
|
||
hyprland = {
|
||
withUWSM = true;
|
||
enable = true;
|
||
xwayland.enable = true;
|
||
};
|
||
};
|
||
environment.sessionVariables = {
|
||
XDG_SESSION_TYPE = "wayland";
|
||
XDG_CURRENT_DESKTOP = "Hyprland";
|
||
XDG_SESSION_DESKTOP = "Hyprland";
|
||
NIXOS_OZONE_WL = "1";
|
||
XCURSOR_SIZE = "24";
|
||
};
|
||
security.pam.services.hyprlock = { };
|
||
# Optional; GNOME-specific (keep only if you really use gnome-keyring integration)
|
||
security.pam.services.gdm.enableGnomeKeyring = true;
|
||
}
|
||
|
||
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org94c6abe" class="outline-3">
|
||
<h3 id="org94c6abe"><span class="section-number-3">17.14.</span> Services</h3>
|
||
<div class="outline-text-3" id="text-17-14">
|
||
<p>
|
||
These are some of the services that I enable at the system level. Explanation in the comments.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ user, ...} :
|
||
{
|
||
services = {
|
||
blueman.enable = true; # bluetooth manager
|
||
fwupd.enable = true; # firmware updating service
|
||
fstrim.enable = true; # ssd maintenance service
|
||
thermald.enable = true; # thermal regulation service
|
||
printing.enable = true; # printing services, cups
|
||
gnome.gnome-keyring.enable = true; # keyring
|
||
flatpak.enable = true; # allow installing things from flatpaks
|
||
#flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||
|
||
# printer discovery
|
||
avahi = {
|
||
enable = true;
|
||
nssmdns4 = true;
|
||
openFirewall = true;
|
||
};
|
||
};
|
||
|
||
virtualisation.docker.enable = true; # enable docker
|
||
users.users.${user.username}.extraGroups = [ "docker" ]; # add self to docker user group
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org2b9de4a" class="outline-3">
|
||
<h3 id="org2b9de4a"><span class="section-number-3">17.15.</span> Audio</h3>
|
||
<div class="outline-text-3" id="text-17-15">
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, ... }:
|
||
|
||
{
|
||
environment.systemPackages = with pkgs; [
|
||
pipewire
|
||
wireplumber
|
||
alsa-utils
|
||
pulseaudio
|
||
pamixer
|
||
pavucontrol
|
||
];
|
||
|
||
services.pipewire = {
|
||
enable = true;
|
||
alsa.enable = true;
|
||
alsa.support32Bit = true;
|
||
pulse.enable = true;
|
||
jack.enable = true;
|
||
wireplumber.enable = true;
|
||
};
|
||
|
||
security.rtkit.enable = true;
|
||
|
||
# Helps on many laptops (Intel SOF etc.)
|
||
hardware.enableRedistributableFirmware = true;
|
||
|
||
# Prefer analog over HDMI/DP in a machine-agnostic way
|
||
services.pipewire.wireplumber.extraConfig."51-audio-priorities" = {
|
||
"monitor.alsa.rules" = [
|
||
# De-prioritize HDMI / DisplayPort sinks
|
||
{
|
||
matches = [
|
||
{ "node.name" = "~alsa_output\\..*HDMI.*"; }
|
||
{ "node.name" = "~alsa_output\\..*DisplayPort.*"; }
|
||
];
|
||
actions.update-props = {
|
||
"priority.session" = 100;
|
||
"priority.driver" = 100;
|
||
};
|
||
}
|
||
|
||
# Prefer analog sinks (speakers/headphones)
|
||
{
|
||
matches = [
|
||
{ "node.name" = "~alsa_output\\..*analog.*"; }
|
||
{ "node.name" = "~alsa_output\\..*Headphones.*"; }
|
||
{ "node.name" = "~alsa_output\\..*Speaker.*"; }
|
||
];
|
||
actions.update-props = {
|
||
"priority.session" = 2000;
|
||
"priority.driver" = 2000;
|
||
};
|
||
}
|
||
];
|
||
};
|
||
|
||
# Optional: clear "sticky" user-selected defaults so priority rules win
|
||
systemd.user.services.wireplumber-clear-default-nodes = {
|
||
description = "Clear WirePlumber saved default nodes (avoid HDMI becoming sticky)";
|
||
|
||
after = [ "wireplumber.service" ];
|
||
partOf = [ "wireplumber.service" ];
|
||
wantedBy = [ "default.target" ];
|
||
|
||
serviceConfig = {
|
||
Type = "oneshot";
|
||
ExecStart = "${pkgs.coreutils}/bin/rm -f %h/.local/state/wireplumber/default-nodes";
|
||
};
|
||
};
|
||
}
|
||
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org0f989af" class="outline-3">
|
||
<h3 id="org0f989af"><span class="section-number-3">17.16.</span> Miscellaneous Packages and Programs</h3>
|
||
<div class="outline-text-3" id="text-17-16">
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="org37eab5d">environment.systemPackages = with pkgs; [
|
||
wget # fetch utility
|
||
curl # more fetch utility
|
||
binutils # executable utilities, like ld
|
||
dmidecode # tool for dumping system info
|
||
libnotify # notification daemon
|
||
python3 # nice to have this ready for quick things
|
||
cacert # certificate authority
|
||
remmina # remote desktop app
|
||
#rg # ripgrep
|
||
wev # for finding keypresses
|
||
tree # list foldetrtree's
|
||
file # filinfo
|
||
htop # sysmonitor
|
||
solaar # logitech controller
|
||
git # source control
|
||
# jetbrains.pycharm # Dev and course environment
|
||
|
||
|
||
];
|
||
|
||
# to enable icons with wlogout
|
||
# https://github.com/catppuccin/nix/issues/584
|
||
programs.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
|
||
</pre>
|
||
</div>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="orgaba7986">programs = {
|
||
nix-ld.enable = true; # helps with linking troubles with dynamic libraries
|
||
appimage.enable = true; # allow appimage installations
|
||
dconf.enable = true; # to save user settings
|
||
gnupg.agent = {
|
||
# pgp client
|
||
enable = true;
|
||
enableSSHSupport = true;
|
||
};
|
||
firefox.enable = true; # browser
|
||
wireshark.enable = true; # vpn
|
||
};
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org5bf1dee" class="outline-3">
|
||
<h3 id="org5bf1dee"><span class="section-number-3">17.17.</span> Fonts</h3>
|
||
<div class="outline-text-3" id="text-17-17">
|
||
<p>
|
||
Nothing much to see here. I love <a href="https://protesilaos.com/codelog/2025-02-12-aporetic-fonts-version-1-1-0/">Aporetic</a>, and I use it everywhere.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="org54de4d8">fonts.packages = with pkgs; [
|
||
aporetic
|
||
nerd-fonts.iosevka
|
||
];
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org0e44064" class="outline-3">
|
||
<h3 id="org0e44064"><span class="section-number-3">17.18.</span> User Config</h3>
|
||
<div class="outline-text-3" id="text-17-18">
|
||
<p>
|
||
This creates the user profile that I login with. Initially created during install.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="org76f462e">users.users.${user.username} = {
|
||
isNormalUser = true;
|
||
description = "henrov";
|
||
extraGroups = [
|
||
"networkmanager" # allow editing network connections
|
||
"wheel" # can do sudo
|
||
"scanner" # access to the network scanner
|
||
"lp" # access to the printer
|
||
];
|
||
};
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org2a2c26b" class="outline-2">
|
||
<h2 id="org2a2c26b"><span class="section-number-2">18.</span> Home</h2>
|
||
<div class="outline-text-2" id="text-18">
|
||
<p>
|
||
I use home-manager to manage my user level dotfiles and configurations.
|
||
Most of the "theme" of the system is decided here.
|
||
I also use it to install programs that are okay with being installed at the user level instead of the system.
|
||
</p>
|
||
</div>
|
||
<div id="outline-container-org3ac8cb9" class="outline-3">
|
||
<h3 id="org3ac8cb9"><span class="section-number-3">18.1.</span> default.nix</h3>
|
||
<div class="outline-text-3" id="text-18-1">
|
||
<p>
|
||
This module will import all necessities.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, user, ... } :
|
||
{
|
||
imports = [
|
||
#./apps/default-apps.nix
|
||
./apps/theme.nix
|
||
./desktop/hypridle.nix
|
||
./desktop/hyprland.nix
|
||
./desktop/hyprexpo.nix
|
||
./desktop/hyprlock.nix
|
||
./desktop/hyprshell.nix
|
||
./desktop/wallpaper.nix
|
||
./desktop/waybar.nix
|
||
./desktop/walker.nix
|
||
./dev/dev.nix
|
||
./dev/shells.nix
|
||
./dev/starship.nix
|
||
./dev/emacs
|
||
];
|
||
|
||
<<home-user>>
|
||
|
||
<<home-packages>>
|
||
|
||
programs.home-manager.enable = true;
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org9dc5e82" class="outline-3">
|
||
<h3 id="org9dc5e82"><span class="section-number-3">18.2.</span> Wallpaper</h3>
|
||
<div class="outline-text-3" id="text-18-2">
|
||
<p>
|
||
wallpaper.nix installs wpaperd and deploys your wallpaper files from the repo (./assets/conf/desktop/wallpaper/pictures/) into ~/conf/desktop/wallpaper/pictures. It also deploys the default wallpaper configuration from assets/conf/desktop/wallpaper/wallpaper.conf into ~/conf/desktop/wallpaper/wallpaper.conf, which is the file you can edit as a user override.
|
||
Finally, it creates a systemd user service (wpaperd.service) that automatically starts wpaperd at login and keeps it running, using your override config so wallpapers rotate according to your settings.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, flakeRoot, ... }:
|
||
let
|
||
repoWallpaperDir = flakeRoot + "/assets/conf/desktop/wallpaper";
|
||
repoWallpaperConf = flakeRoot + "/assets/conf/desktop/wallpaper/wallpaper.conf";
|
||
userRelRoot = "nixos_conf/wallpaperstuff";
|
||
userAbsRoot = "${config.home.homeDirectory}/${userRelRoot}";
|
||
userConfPath = "${userAbsRoot}/wallpaper.conf";
|
||
# Exclude wallpaper.conf so HM does NOT manage it (avoids backup collisions)
|
||
repoWallpapersOnly = lib.cleanSourceWith {
|
||
src = repoWallpaperDir;
|
||
filter = path: type:
|
||
(builtins.baseNameOf path) != "wallpaper.conf";
|
||
};
|
||
in
|
||
{
|
||
home.packages = [ pkgs.wpaperd ];
|
||
# Sync everything *except* wallpaper.conf into ~/nixos_conf/wallpaperstuff
|
||
home.file."${userRelRoot}" = {
|
||
source = repoWallpapersOnly;
|
||
recursive = true;
|
||
};
|
||
# Now safely overwrite the config every activation (no HM collision)
|
||
home.activation.wallpaperConfForce =
|
||
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||
set -euo pipefail
|
||
mkdir -p "${userAbsRoot}"
|
||
install -m 0644 "${repoWallpaperConf}" "${userConfPath}"
|
||
'';
|
||
systemd.user.services.wpaperd = {
|
||
Unit = {
|
||
Description = "wpaperd wallpaper daemon";
|
||
After = [ "default.target" ];
|
||
};
|
||
Service = {
|
||
Type = "simple";
|
||
ExecStart = "${pkgs.wpaperd}/bin/wpaperd --config ${userConfPath}";
|
||
Restart = "on-failure";
|
||
RestartSec = 1;
|
||
};
|
||
Install.WantedBy = [ "default.target" ];
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgfabb720" class="outline-3">
|
||
<h3 id="orgfabb720"><span class="section-number-3">18.3.</span> Waybar</h3>
|
||
<div class="outline-text-3" id="text-18-3">
|
||
|
||
<div id="org9b2158d" class="figure">
|
||
<p><img src="./.github/images/waybar.png" alt="waybar.png" />
|
||
</p>
|
||
</div>
|
||
|
||
<p>
|
||
Mostly styling and enabling modules in the <a href="https://github.com/Alexays/Waybar">top bar</a>.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, lib, pkgs, flakeRoot, ... }:
|
||
let
|
||
repoWaybarDir = flakeRoot + "/assets/conf/desktop/waybar";
|
||
in
|
||
{
|
||
programs.waybar.enable = true;
|
||
|
||
# Ensure config matches repo (HM-managed symlink, not user-editable)
|
||
xdg.configFile."waybar/config" = {
|
||
source = repoWaybarDir + "/config.jsonc";
|
||
force = true;
|
||
};
|
||
|
||
# Override HM's internally-generated waybar-style.css derivation
|
||
# and use your repo file instead.
|
||
xdg.configFile."waybar/style.css" = {
|
||
source = lib.mkForce (repoWaybarDir + "/style.css");
|
||
force = true;
|
||
};
|
||
|
||
# Prevent HM from also trying to generate style content via programs.waybar.style
|
||
# (not strictly required once mkForce is in place, but keeps intent clear)
|
||
programs.waybar.style = "";
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org2b30ed7" class="outline-3">
|
||
<h3 id="org2b30ed7"><span class="section-number-3">18.4.</span> Lock Screen</h3>
|
||
<div class="outline-text-3" id="text-18-4">
|
||
<p>
|
||
The lock screen configured using <a href="https://wiki.hyprland.org/Hypr-Ecosystem/hyprlock/">hyprlock</a>.
|
||
I use <a href="https://wiki.hyprland.org/Hypr-Ecosystem/hypridle/">hypridle</a> to detect idle time and use wlogout to show a logout menu.
|
||
They are configured below.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{config, lib, pkgs, flakeRoot, ... }:
|
||
let
|
||
lockPngSrc = flakeRoot + "/assets/lock.png";
|
||
hyprlockConf = flakeRoot + "/assets/conf/desktop/hypr/hyprlock.conf";
|
||
in
|
||
{
|
||
home.packages = [ pkgs.hyprlock ];
|
||
xdg.configFile."hypr/lock.png".source = lockPngSrc;
|
||
xdg.configFile."hypr/hyprlock.conf".source = hyprlockConf;
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org9ab6667" class="outline-3">
|
||
<h3 id="org9ab6667"><span class="section-number-3">18.5.</span> Idle Screen</h3>
|
||
<div class="outline-text-3" id="text-18-5">
|
||
<p>
|
||
<henro: needs instruction>
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, lib, pkgs, flakeRoot, ... }:
|
||
let
|
||
hypridleConf = flakeRoot + "/assets/conf/desktop/hypr/hypridle.conf";
|
||
in
|
||
{
|
||
home.packages = [ pkgs.hypridle ];
|
||
xdg.configFile."hypr/hypridle.conf".source = hypridleConf;
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org0f8983c" class="outline-3">
|
||
<h3 id="org0f8983c"><span class="section-number-3">18.6.</span> Hyprshell</h3>
|
||
<div class="outline-text-3" id="text-18-6">
|
||
<p>
|
||
For nice task-starting and -switching
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix"># home/desktop/hyprshell.nix (Home-Manager module)
|
||
{ config, pkgs, lib, flakeRoot, ... }:
|
||
let
|
||
repoDir = flakeRoot + "/assets/conf/desktop/hypr/hyprshell";
|
||
cfgRon = repoDir + "/config.ron";
|
||
cssFile = repoDir + "/styles.css";
|
||
in
|
||
{
|
||
xdg.enable = true;
|
||
home.packages = [ pkgs.hyprshell ];
|
||
# Link repo -> ~/.config/hyprshell/...
|
||
xdg.configFile."hyprshell/config.ron".source = cfgRon;
|
||
xdg.configFile."hyprshell/styles.css".source = cssFile;
|
||
# Autostart (systemd user service)
|
||
systemd.user.services.hyprshell = {
|
||
Unit = {
|
||
Description = "Hyprshell (window switcher / launcher)";
|
||
PartOf = [ "graphical-session.target" ];
|
||
After = [ "graphical-session.target" ];
|
||
};
|
||
Service = {
|
||
ExecStart = "${pkgs.hyprshell}/bin/hyprshell";
|
||
Restart = "on-failure";
|
||
RestartSec = 1;
|
||
};
|
||
Install = {
|
||
WantedBy = [ "graphical-session.target" ];
|
||
};
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orge55154f" class="outline-3">
|
||
<h3 id="orge55154f"><span class="section-number-3">18.7.</span> Hyprland</h3>
|
||
<div class="outline-text-3" id="text-18-7">
|
||
<p>
|
||
This configures the desktop environment along with the peripherals. The comments should explain whats happening.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, lib, pkgs, flakeRoot, ... }:
|
||
let
|
||
hyprConf = flakeRoot + "/assets/conf/desktop/hypr/hyprland.conf";
|
||
bindingsConf = flakeRoot + "/assets/conf/desktop/hypr/bindings.conf";
|
||
in
|
||
{
|
||
programs.kitty.enable = true;
|
||
|
||
wayland.windowManager.hyprland = {
|
||
enable = true;
|
||
# Load base config + bindings from repo files
|
||
extraConfig =
|
||
(builtins.readFile hyprConf)
|
||
+ "\n\n# --- Repo keybindings ---\n"
|
||
+ (builtins.readFile bindingsConf)
|
||
+ "\n";
|
||
};
|
||
|
||
xdg.configFile."hypr/scripts/lid-lock.sh" = {
|
||
source = flakeRoot + "/assets/conf/desktop/hypr/scripts/lid-lock.sh";
|
||
executable = true;
|
||
};
|
||
xdg.portal = {
|
||
enable = true;
|
||
|
||
extraPortals = with pkgs; [
|
||
xdg-desktop-portal-gtk
|
||
xdg-desktop-portal-hyprland
|
||
];
|
||
|
||
# GTK als algemene backend (OpenURI is daar betrouwbaar)
|
||
config.common.default = [ "gtk" ];
|
||
|
||
# Hyprland alleen voor screensharing / remote desktop
|
||
config.hyprland = {
|
||
"org.freedesktop.impl.portal.Screencast" = [ "hyprland" ];
|
||
"org.freedesktop.impl.portal.RemoteDesktop" = [ "hyprland" ];
|
||
};
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org58f70c6" class="outline-3">
|
||
<h3 id="org58f70c6"><span class="section-number-3">18.8.</span> Walker</h3>
|
||
<div class="outline-text-3" id="text-18-8">
|
||
<p>
|
||
<a href="https://github.com/abenz1267/walker">This</a> is how I launch applications. It is bound to Win+Space in the ./asstes/conf/desktop/hypr/bindings.conf.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, inputs ? null, ... }:
|
||
|
||
let
|
||
walkerPkg =
|
||
if inputs != null && inputs ? walker
|
||
then inputs.walker.packages.${pkgs.system}.default
|
||
else pkgs.walker;
|
||
|
||
elephantPkg =
|
||
if inputs != null && inputs ? elephant
|
||
then inputs.elephant.packages.${pkgs.system}.default
|
||
else pkgs.elephant;
|
||
|
||
sessionTarget = "graphical-session.target";
|
||
in
|
||
{
|
||
xdg.enable = true;
|
||
|
||
home.packages = [
|
||
walkerPkg
|
||
elephantPkg
|
||
];
|
||
|
||
systemd.user.services.elephant = {
|
||
Unit = {
|
||
Description = "Elephant backend for Walker";
|
||
PartOf = [ sessionTarget ];
|
||
After = [ sessionTarget ];
|
||
};
|
||
|
||
Service = {
|
||
Type = "simple";
|
||
ExecStart = "${elephantPkg}/bin/elephant";
|
||
|
||
Restart = "on-failure";
|
||
RestartSec = 1;
|
||
|
||
# Ensure Elephant can create its socket under:
|
||
# /run/user/$UID/elephant/...
|
||
RuntimeDirectory = "elephant";
|
||
RuntimeDirectoryMode = "0700";
|
||
|
||
# Light hardening (DO NOT use ProtectSystem=strict here)
|
||
NoNewPrivileges = true;
|
||
PrivateTmp = true;
|
||
ProtectKernelTunables = true;
|
||
ProtectKernelModules = true;
|
||
ProtectControlGroups = true;
|
||
LockPersonality = true;
|
||
RestrictRealtime = true;
|
||
RestrictSUIDSGID = true;
|
||
SystemCallArchitectures = "native";
|
||
};
|
||
|
||
Install = {
|
||
WantedBy = [ sessionTarget ];
|
||
};
|
||
};
|
||
|
||
systemd.user.services.walker = {
|
||
Unit = {
|
||
Description = "Walker GApplication service";
|
||
PartOf = [ sessionTarget ];
|
||
After = [ sessionTarget "elephant.service" ];
|
||
Wants = [ "elephant.service" ];
|
||
};
|
||
|
||
Service = {
|
||
Type = "simple";
|
||
ExecStart = "${walkerPkg}/bin/walker --gapplication-service";
|
||
|
||
Restart = "on-failure";
|
||
RestartSec = 1;
|
||
|
||
# Light hardening
|
||
NoNewPrivileges = true;
|
||
PrivateTmp = true;
|
||
ProtectKernelTunables = true;
|
||
ProtectKernelModules = true;
|
||
ProtectControlGroups = true;
|
||
LockPersonality = true;
|
||
RestrictRealtime = true;
|
||
RestrictSUIDSGID = true;
|
||
SystemCallArchitectures = "native";
|
||
};
|
||
|
||
Install = {
|
||
WantedBy = [ sessionTarget ];
|
||
};
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org699cddb" class="outline-3">
|
||
<h3 id="org699cddb"><span class="section-number-3">18.9.</span> Theme</h3>
|
||
<div class="outline-text-3" id="text-18-9">
|
||
<p>
|
||
I use the <a href="https://catppuccin.com/">Catppuccin</a> almost everywhere. The nix module integrates almost automatically everywhere (except gtk).
|
||
You'll notice the color values in multiple places outside this as well.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, ...}:
|
||
{
|
||
gtk = {
|
||
enable = true;
|
||
colorScheme = "dark";
|
||
theme = {
|
||
name = "Catppuccin-GTK-Grey-Dark-Compact";
|
||
package = (pkgs.magnetic-catppuccin-gtk.override {
|
||
accent = [ "grey" ];
|
||
shade = "dark";
|
||
tweaks = [ "black" ];
|
||
size = "compact";
|
||
});
|
||
};
|
||
iconTheme.name = "Papirus-Dark";
|
||
};
|
||
catppuccin.enable = true;
|
||
catppuccin.flavor = "mocha";
|
||
catppuccin.accent = "blue";
|
||
catppuccin.gtk.icon.enable = true;
|
||
catppuccin.cursors.enable = true;
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgfe67f7b" class="outline-3">
|
||
<h3 id="orgfe67f7b"><span class="section-number-3">18.10.</span> Default-apps</h3>
|
||
<div class="outline-text-3" id="text-18-10">
|
||
<p>
|
||
This is where you can set defaults
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, ... }:
|
||
{
|
||
xdg.mimeApps.enable = true;
|
||
xdg.mimeApps.defaultApplications = {
|
||
"x-scheme-handler/http" = [ "app.zen_browser.zen.desktop" ];
|
||
"x-scheme-handler/https" = [ "app.zen_browser.zen.desktop" ];
|
||
"text/html" = [ "app.zen_browser.zen.desktop" ];
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org99eea47" class="outline-3">
|
||
<h3 id="org99eea47"><span class="section-number-3">18.11.</span> Hyperexpo</h3>
|
||
<div class="outline-text-3" id="text-18-11">
|
||
<p>
|
||
hyprexpo gets installed and configured
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, lib, pkgs, ... }:
|
||
|
||
{
|
||
wayland.windowManager.hyprland = {
|
||
# Load the Hyprexpo plugin (from nixpkgs)
|
||
plugins = [
|
||
pkgs.hyprlandPlugins.hyprexpo
|
||
];
|
||
|
||
# Append plugin config + keybind after your existing hyprland.conf
|
||
extraConfig = lib.mkAfter ''
|
||
############################
|
||
# Hyprexpo (workspace/window overview)
|
||
############################
|
||
|
||
# Basic plugin config (tweak as you like)
|
||
plugin {
|
||
hyprexpo {
|
||
columns = 3
|
||
gaps_in = 5
|
||
gaps_out = 20
|
||
|
||
# Optional; comment out if you don't want it
|
||
# workspace_method = center current
|
||
}
|
||
}
|
||
'';
|
||
};
|
||
}
|
||
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org0e841c5" class="outline-3">
|
||
<h3 id="org0e841c5"><span class="section-number-3">18.12.</span> Alacritty</h3>
|
||
<div class="outline-text-3" id="text-18-12">
|
||
<p>
|
||
Alacritty gets installed and configured
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, flakeRoot, ... }:
|
||
let
|
||
repoAlacrittyConf = flakeRoot + "/assets/conf/dev/alacritty.toml";
|
||
in
|
||
{
|
||
xdg.enable = true;
|
||
programs.alacritty.enable = true;
|
||
# Override the config generated by programs.alacritty
|
||
xdg.configFile."alacritty/alacritty.toml".source = lib.mkForce repoAlacrittyConf;
|
||
catppuccin.alacritty.enable = true;
|
||
catppuccin.alacritty.flavor = "mocha";
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orga81b73b" class="outline-3">
|
||
<h3 id="orga81b73b"><span class="section-number-3">18.13.</span> Dev Tools</h3>
|
||
<div class="outline-text-3" id="text-18-13">
|
||
<p>
|
||
All the miscellaneous dev tools on this computer.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, ... }:
|
||
{
|
||
programs = {
|
||
vscode.enable = true;
|
||
vim.enable = true;
|
||
ripgrep.enable = true;
|
||
btop.enable = true;
|
||
|
||
fzf = {
|
||
enable = true;
|
||
enableZshIntegration = true;
|
||
enableBashIntegration = true;
|
||
};
|
||
|
||
zoxide = {
|
||
enable = true;
|
||
enableZshIntegration = true;
|
||
enableBashIntegration = true;
|
||
};
|
||
|
||
eza = {
|
||
enable = true;
|
||
enableZshIntegration = true;
|
||
enableBashIntegration = true;
|
||
};
|
||
|
||
direnv = {
|
||
enable = true;
|
||
enableZshIntegration = true;
|
||
enableBashIntegration = true;
|
||
nix-direnv.enable = true;
|
||
};
|
||
|
||
# Zsh-specific config belongs here
|
||
zsh = {
|
||
# for emacs-eat package
|
||
initContent = lib.mkOrder 1200 ''
|
||
[ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \
|
||
source "$EAT_SHELL_INTEGRATION_DIR/zsh"
|
||
'';
|
||
};
|
||
|
||
git = {
|
||
enable = true;
|
||
lfs.enable = true;
|
||
};
|
||
};
|
||
}
|
||
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgf27ff36" class="outline-3">
|
||
<h3 id="orgf27ff36"><span class="section-number-3">18.14.</span> Kitty</h3>
|
||
<div class="outline-text-3" id="text-18-14">
|
||
<p>
|
||
Kitty gets installed and configured
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, flakeRoot, ... }:
|
||
let
|
||
repoKittyConf = flakeRoot + "/assets/conf/dev/kitty.conf";
|
||
in
|
||
{
|
||
xdg.enable = true;
|
||
programs.kitty.enable = true;
|
||
catppuccin.alacritty.enable = true;
|
||
catppuccin.alacritty.flavor = "mocha";
|
||
syntaxHighlighting.enable = true;
|
||
autosuggestion.enable = true;
|
||
enableCompletion = true;
|
||
xdg.configFile."kitty/kitty.conf".source = repoKittyConf;
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orga78066f" class="outline-3">
|
||
<h3 id="orga78066f"><span class="section-number-3">18.15.</span> Shells</h3>
|
||
<div class="outline-text-3" id="text-18-15">
|
||
<p>
|
||
The aliases mentioned in ./assets/conf/dev/terminal/shells.conf will be added to enabled shells
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix"># shells.nix — Home-Manager module
|
||
#
|
||
# Reads:
|
||
# ${flakeRoot}/assets/conf/dev/terminal/enabled_shells.conf
|
||
# ${flakeRoot}/assets/conf/dev/terminal/aliases.conf
|
||
#
|
||
# For each enabled shell in [enabled_shells]:
|
||
# - installs/enables shell (where HM has an enable option)
|
||
# - if ${flakeRoot}/assets/conf/dev/terminal/<shell>.conf exists, sources it
|
||
# - ensures a *user-editable* aliases file exists in the shell’s default location
|
||
# - if a shell is disabled, its aliases file is removed
|
||
# .
|
||
# Notes on “editable”:
|
||
# - We do NOT manage the aliases file with xdg.configFile/home.file (those would be overwritten).
|
||
# - Instead, we create/remove files via home.activation (create only if missing).
|
||
{ config, pkgs, lib, flakeRoot, ... }:
|
||
let
|
||
terminalDir = flakeRoot + "/assets/conf/dev/terminal";
|
||
enabledFile = terminalDir + "/enabled_shells.conf";
|
||
aliasesFile = terminalDir + "/aliases.conf";
|
||
trim = lib.strings.trim;
|
||
# ---------- minimal INI-ish parser (sections + raw lines) ----------
|
||
readMaybe = p: if builtins.pathExists p then builtins.readFile p else "";
|
||
normalizeLine = l: trim (lib.replaceStrings [ "\r" ] [ "" ] l);
|
||
parseSections = text:
|
||
let
|
||
lines = map normalizeLine (lib.splitString "\n" text);
|
||
isHeader = l:
|
||
let s = l;
|
||
in lib.hasPrefix "[" s
|
||
&& lib.hasSuffix "]" s
|
||
&& builtins.stringLength s >= 3;
|
||
nameOf = l: lib.removeSuffix "]" (lib.removePrefix "[" l);
|
||
folded =
|
||
builtins.foldl'
|
||
(st: l:
|
||
if l == "" then st else
|
||
if isHeader l then st // { current = nameOf l; }
|
||
else
|
||
let
|
||
cur = st.current;
|
||
prev = st.sections.${cur} or [];
|
||
in
|
||
st // { sections = st.sections // { ${cur} = prev ++ [ l ]; }; }
|
||
)
|
||
{ current = "__root__"; sections = {}; }
|
||
lines;
|
||
in
|
||
folded.sections;
|
||
|
||
enabledSections = parseSections (readMaybe enabledFile);
|
||
aliasSections = parseSections (readMaybe aliasesFile);
|
||
# [enabled_shells] lines: key = yes/no
|
||
enabledShells =
|
||
let
|
||
raw = enabledSections.enabled_shells or [];
|
||
parseKV = l:
|
||
let m = builtins.match ''^([A-Za-z0-9_-]+)[[:space:]]*=[[:space:]]*(.*)$'' l;
|
||
in if m == null then null else {
|
||
k = trim (builtins.elemAt m 0);
|
||
v = lib.toLower (trim (builtins.elemAt m 1));
|
||
};
|
||
kvs = builtins.filter (x: x != null) (map parseKV raw);
|
||
in
|
||
map (x: x.k) (builtins.filter (x: x.v == "yes" || x.v == "true" || x.v == "1") kvs);
|
||
shellEnabled = shell: builtins.elem shell enabledShells;
|
||
# ---------- per-shell repo config file (<shell>.conf) ----------
|
||
shellConfPath = shell: terminalDir + "/${shell}.conf";
|
||
shellConfExists = shell: builtins.pathExists (shellConfPath shell);
|
||
sourceIfExistsSh = p: ''
|
||
if [ -f "${toString p}" ]; then
|
||
source "${toString p}"
|
||
fi
|
||
'';
|
||
# ---------- aliases section helpers ----------
|
||
secLines = name: aliasSections.${name} or [];
|
||
secText = name: lib.concatStringsSep "\n" (secLines name);
|
||
# Default alias-file locations
|
||
bashAliasesPath = "${config.home.homeDirectory}/.bash_aliases";
|
||
zshAliasesPath = "${config.home.homeDirectory}/.zsh_aliases";
|
||
fishAliasesPath = "${config.xdg.configHome}/fish/conf.d/aliases.fish";
|
||
# Seeds (created once; user can edit afterwards)
|
||
bashSeed = ''
|
||
# Created once from: ${toString aliasesFile}
|
||
# Edit freely; Home Manager will not overwrite this file.
|
||
#
|
||
${secText "bash_zsh"}
|
||
${secText "bash_specific"}
|
||
'';
|
||
zshSeed = ''
|
||
# Created once from: ${toString aliasesFile}
|
||
# Edit freely; Home Manager will not overwrite this file.
|
||
#
|
||
${secText "bash_zsh"}
|
||
${secText "zsh_specific"}
|
||
'';
|
||
# Fish: translate [bash_zsh] POSIX alias lines + append [fish_specific] as-is
|
||
parsePosixAlias = l:
|
||
let
|
||
m = builtins.match ''^[[:space:]]*alias[[:space:]]+([A-Za-z0-9_+-]+)=(.*)$'' l;
|
||
in
|
||
if m == null then null else
|
||
let
|
||
name = trim (builtins.elemAt m 0);
|
||
rhs0 = trim (builtins.elemAt m 1);
|
||
unquote =
|
||
if lib.hasPrefix "'" rhs0 && lib.hasSuffix "'" rhs0 then
|
||
lib.removeSuffix "'" (lib.removePrefix "'" rhs0)
|
||
else if lib.hasPrefix "\"" rhs0 && lib.hasSuffix "\"" rhs0 then
|
||
lib.removeSuffix "\"" (lib.removePrefix "\"" rhs0)
|
||
else
|
||
rhs0;
|
||
in
|
||
{ inherit name; cmd = unquote; };
|
||
escapeForFish = s:
|
||
lib.replaceStrings
|
||
[ "\\" "\"" "$" "`" ]
|
||
[ "\\\\" "\\\"" "\\$" "\\`" ]
|
||
s;
|
||
fishTranslated =
|
||
let
|
||
parsed = builtins.filter (x: x != null) (map parsePosixAlias (secLines "bash_zsh"));
|
||
in
|
||
lib.concatStringsSep "\n" (map (a: ''alias ${a.name} "${escapeForFish a.cmd}"'') parsed);
|
||
fishSeed = ''
|
||
# Created once from: ${toString aliasesFile}
|
||
# Edit freely; Home Manager will not overwrite this file.
|
||
status is-interactive; or exit
|
||
|
||
# Translated from [bash_zsh]:
|
||
${fishTranslated}
|
||
|
||
# From [fish_specific]:
|
||
${secText "fish_specific"}
|
||
'';
|
||
in
|
||
{
|
||
xdg.enable = true;
|
||
# Install/enable shells (no login-shell changes)
|
||
programs.bash.enable = shellEnabled "bash";
|
||
programs.zsh.enable = shellEnabled "zsh";
|
||
programs.fish.enable = shellEnabled "fish";
|
||
home.packages =
|
||
(lib.optionals (shellEnabled "dash") [ pkgs.dash ]) ++
|
||
(lib.optionals (shellEnabled "nushell") [ pkgs.nushell ]);
|
||
# Source per-shell repo config (if present) AND source the user alias file (if it exists).
|
||
# Important: define each option only ONCE.
|
||
programs.bash.bashrcExtra = lib.mkIf (shellEnabled "bash") (lib.mkAfter ''
|
||
${lib.optionalString (shellConfExists "bash") (sourceIfExistsSh (shellConfPath "bash"))}
|
||
if [ -f "${bashAliasesPath}" ]; then
|
||
source "${bashAliasesPath}"
|
||
fi
|
||
'');
|
||
programs.zsh.initContent = lib.mkIf (shellEnabled "zsh") (lib.mkAfter ''
|
||
${lib.optionalString (shellConfExists "zsh") (sourceIfExistsSh (shellConfPath "zsh"))}
|
||
if [ -f "${zshAliasesPath}" ]; then
|
||
source "${zshAliasesPath}"
|
||
fi
|
||
'');
|
||
programs.fish.interactiveShellInit = lib.mkIf (shellEnabled "fish") (lib.mkAfter ''
|
||
${lib.optionalString (shellConfExists "fish") ''
|
||
if test -f "${toString (shellConfPath "fish")}"
|
||
source "${toString (shellConfPath "fish")}"
|
||
end
|
||
''}
|
||
if test -f "${fishAliasesPath}"
|
||
source "${fishAliasesPath}"
|
||
end
|
||
'');
|
||
# Create/remove alias files based on enabled shells
|
||
home.activation.shellAliasesFiles = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||
set -euo pipefail
|
||
|
||
# bash -------------------------------------------------------
|
||
if ${if shellEnabled "bash" then "true" else "false"}; then
|
||
cat > "${bashAliasesPath}" <<'EOF'
|
||
${bashSeed}
|
||
EOF
|
||
else
|
||
rm -f "${bashAliasesPath}"
|
||
fi
|
||
|
||
# zsh -------------------------------------------------------
|
||
if ${if shellEnabled "zsh" then "true" else "false"}; then
|
||
cat > "${zshAliasesPath}" <<'EOF'
|
||
${zshSeed}
|
||
EOF
|
||
else
|
||
rm -f "${zshAliasesPath}"
|
||
fi
|
||
|
||
# fish -------------------------------------------------------
|
||
if ${if shellEnabled "fish" then "true" else "false"}; then
|
||
mkdir -p "$(dirname "${fishAliasesPath}")"
|
||
cat > "${fishAliasesPath}" <<'EOF'
|
||
${fishSeed}
|
||
EOF
|
||
else
|
||
rm -f "${fishAliasesPath}"
|
||
fi
|
||
# fish
|
||
if ${if shellEnabled "fish" then "true" else "false"}; then
|
||
mkdir -p "$(dirname "${fishAliasesPath}")"
|
||
if [ ! -f "${fishAliasesPath}" ]; then
|
||
cat > "${fishAliasesPath}" <<'EOF'
|
||
${fishSeed}
|
||
EOF
|
||
fi
|
||
else
|
||
rm -f "${fishAliasesPath}"
|
||
fi
|
||
'';
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org15f6166" class="outline-3">
|
||
<h3 id="org15f6166"><span class="section-number-3">18.16.</span> Zsh</h3>
|
||
<div class="outline-text-3" id="text-18-16">
|
||
<p>
|
||
Zsh gets installed and configured
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, flakeRoot, ... }:
|
||
let
|
||
repoZshConf = flakeRoot + "/assets/conf/dev/terminal/zsh.conf";
|
||
in
|
||
{
|
||
programs.zsh = {
|
||
enable = true;
|
||
syntaxHighlighting.enable = true;
|
||
autosuggestions.enable = true;
|
||
enableCompletion = true;
|
||
autocd = true;
|
||
dotDir = config.home.homeDirectory;
|
||
# ---- Oh My Zsh ----
|
||
oh-my-zsh = {
|
||
enable = true;
|
||
theme = "";
|
||
plugins = [
|
||
"git"
|
||
"sudo"
|
||
"extract"
|
||
"colored-man-pages"
|
||
"command-not-found"
|
||
"history"
|
||
"docker"
|
||
"kubectl"
|
||
# IMPORTANT: these should be last
|
||
"zsh-autosuggestions"
|
||
"zsh-syntax-highlighting"
|
||
];
|
||
};
|
||
'';
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org5b42cf9" class="outline-3">
|
||
<h3 id="org5b42cf9"><span class="section-number-3">18.17.</span> Starship</h3>
|
||
<div class="outline-text-3" id="text-18-17">
|
||
<p>
|
||
The configuration mentioned in ./assets/conf/dev/terminal/starship.toml will be added to enabled shells
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ config, pkgs, lib, flakeRoot, ... }:
|
||
|
||
let
|
||
repoStarshipToml = flakeRoot + "/assets/conf/dev/terminal/starship.toml";
|
||
|
||
# The exact key that appears in the error:
|
||
targetKey = "${config.home.homeDirectory}/.config/starship.toml";
|
||
in
|
||
{
|
||
xdg.enable = true;
|
||
|
||
programs.starship = {
|
||
enable = true;
|
||
enableZshIntegration = true;
|
||
enableBashIntegration = true;
|
||
enableFishIntegration = true;
|
||
};
|
||
|
||
# Force the *actual conflicting option* (home.file."<abs path>".source)
|
||
home.file."${targetKey}".source = lib.mkForce repoStarshipToml;
|
||
}
|
||
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org31d22d5" class="outline-3">
|
||
<h3 id="org31d22d5"><span class="section-number-3">18.18.</span> Other Settings</h3>
|
||
<div class="outline-text-3" id="text-18-18">
|
||
<p>
|
||
Some repeated info from the configuration.
|
||
</p>
|
||
</div>
|
||
<div id="outline-container-org7e22fc0" class="outline-4">
|
||
<h4 id="org7e22fc0"><span class="section-number-4">18.18.1.</span> Home User</h4>
|
||
<div class="outline-text-4" id="text-18-18-1">
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix" id="orgb890f5f">home.username = "${user.username}";
|
||
home.homeDirectory = pkgs.lib.mkDefault "/home/${user.username}";
|
||
home.stateVersion = user.stateVersion;
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org123eb2a" class="outline-2">
|
||
<h2 id="org123eb2a"><span class="section-number-2">19.</span> Emacs</h2>
|
||
<div class="outline-text-2" id="text-19">
|
||
<p>
|
||
I practically live inside emacs. The configuration for it is a mix between init.el and the nix configuration.
|
||
Nix allows me to install emacs packages as part of the configuration which is most of the following file.
|
||
I install the nix community provided emacs overlay that lets me have the latest emacs with pgtk ui (for wayland).
|
||
Comments describe the emacs package and what it does.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, ... }:
|
||
{
|
||
programs.emacs = {
|
||
enable = true;
|
||
# install with tree sitter enabled
|
||
package = (pkgs.emacs-pgtk.override { withTreeSitter = true; });
|
||
extraPackages = epkgs: [
|
||
# also install all tree sitter grammars
|
||
epkgs.manualPackages.treesit-grammars.with-all-grammars
|
||
epkgs.nerd-icons # nerd fonts support
|
||
epkgs.doom-modeline # model line
|
||
epkgs.diminish # hides modes from modeline
|
||
epkgs.eldoc # doc support
|
||
epkgs.pulsar # pulses the cursor when jumping about
|
||
epkgs.which-key # help porcelain
|
||
epkgs.expreg # expand region
|
||
epkgs.vundo # undo tree
|
||
epkgs.puni # structured editing
|
||
epkgs.avy # jumping utility
|
||
epkgs.consult # emacs right click
|
||
epkgs.vertico # minibuffer completion
|
||
epkgs.marginalia # annotations for completions
|
||
epkgs.crux # utilities
|
||
epkgs.magit # git porcelain
|
||
epkgs.nerd-icons-corfu # nerd icons for completion
|
||
epkgs.corfu # completion
|
||
epkgs.cape # completion extensions
|
||
epkgs.orderless # search paradigm
|
||
epkgs.yasnippet # snippets support
|
||
epkgs.yasnippet-snippets # commonly used snippets
|
||
epkgs.rg # ripgrep
|
||
epkgs.exec-path-from-shell # load env and path
|
||
epkgs.eat # better shell
|
||
epkgs.rust-mode # rust mode (when rust-ts doesn't cut it)
|
||
epkgs.rustic # more rust things
|
||
epkgs.nix-mode # nix lang
|
||
epkgs.hcl-mode # hashicorp file mode
|
||
epkgs.shell-pop # quick shell popup
|
||
epkgs.envrc # support for loading .envrc
|
||
epkgs.nixpkgs-fmt # format nix files
|
||
epkgs.f # string + file utilities
|
||
epkgs.gptel # llm chat (mainly claude)
|
||
epkgs.catppuccin-theme # catppuccin theme
|
||
epkgs.eldoc-box # docs in a box
|
||
epkgs.sideline # mainly for flymake errors on the side
|
||
epkgs.sideline-flymake # mainly for flymake errors on the side
|
||
epkgs.sideline-eglot # mainly for flymake errors on the side
|
||
];
|
||
};
|
||
home.sessionVariables = {
|
||
EDITOR = "emacs";
|
||
XDG_SCREENSHOTS_DIR = "~/screenshots";
|
||
};
|
||
home.file = {
|
||
emacs-init = {
|
||
source = ./early-init.el;
|
||
target = ".emacs.d/early-init.el";
|
||
};
|
||
emacs = {
|
||
source = ./init.el;
|
||
target = ".emacs.d/init.el";
|
||
};
|
||
};
|
||
services.nextcloud-client = {
|
||
enable = true;
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org74de044" class="outline-3">
|
||
<h3 id="org74de044"><span class="section-number-3">19.1.</span> Early Initialization</h3>
|
||
<div class="outline-text-3" id="text-19-1">
|
||
<p>
|
||
There are some emacs settings that can be configured before the gui shows up.
|
||
And some of them help increase performance and let the gui show up that much faster.
|
||
These are listed here.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-emacs-lisp">;;; package --- early init -*- lexical-binding: t -*-
|
||
;;; Commentary:
|
||
;;; Prevents white flash and better Emacs defaults
|
||
;;; Code:
|
||
(set-language-environment "UTF-8")
|
||
(setq-default
|
||
default-frame-alist
|
||
'((background-color . "#1e1e2e")
|
||
(bottom-divider-width . 1) ; Thin horizontal window divider
|
||
(foreground-color . "#bac2de") ; Default foreground color
|
||
(fullscreen . maximized) ; Maximize the window by default
|
||
(horizontal-scroll-bars . nil) ; No horizontal scroll-bars
|
||
(left-fringe . 8) ; Thin left fringe
|
||
(menu-bar-lines . 0) ; No menu bar
|
||
(right-divider-width . 1) ; Thin vertical window divider
|
||
(right-fringe . 8) ; Thin right fringe
|
||
(tool-bar-lines . 0) ; No tool bar
|
||
(undecorated . t) ; Remove extraneous X decorations
|
||
(vertical-scroll-bars . nil)) ; No vertical scroll-bars
|
||
user-full-name "Henrov henrov" ; ME!
|
||
;; memory configuration
|
||
;; Higher garbage collection threshold, prevents frequent gc locks, reset later
|
||
gc-cons-threshold most-positive-fixnum
|
||
;; Ignore warnings for (obsolete) elisp compilations
|
||
byte-compile-warnings '(not obsolete)
|
||
;; And other log types completely
|
||
warning-suppress-log-types '((comp) (bytecomp))
|
||
;; Large files are okay in the new millenium.
|
||
large-file-warning-threshold 100000000
|
||
;; dont show garbage collection messages at startup, will reset later
|
||
garbage-collection-messages nil
|
||
;; native compilation
|
||
package-native-compile t
|
||
native-comp-warning-on-missing-source nil
|
||
native-comp-async-report-warnings-errors 'silent
|
||
;; Read more based on system pipe capacity
|
||
read-process-output-max (max (* 10240 10240) read-process-output-max)
|
||
;; scroll configuration
|
||
scroll-margin 0 ; Lets scroll to the end of the margin
|
||
scroll-conservatively 100000 ; Never recenter the window
|
||
scroll-preserve-screen-position 1 ; Scrolling back and forth
|
||
;; frame config
|
||
;; Improve emacs startup time by not resizing to adjust for custom settings
|
||
frame-inhibit-implied-resize t
|
||
;; Dont resize based on character height / width but to exact pixels
|
||
frame-resize-pixelwise t
|
||
;; backups & files
|
||
backup-directory-alist '(("." . "~/.backups/")) ; Don't clutter
|
||
backup-by-copying t ; Don't clobber symlinks
|
||
create-lockfiles nil ; Don't have temp files
|
||
delete-old-versions t ; Cleanup automatically
|
||
kept-new-versions 6 ; Update every few times
|
||
kept-old-versions 2 ; And cleanup even more
|
||
version-control t ; Version them backups
|
||
delete-by-moving-to-trash t ; Dont delete, send to trash instead
|
||
;; startup
|
||
inhibit-startup-screen t ; I have already done the tutorial. Twice
|
||
inhibit-startup-message t ; I know I am ready
|
||
inhibit-startup-echo-area-message t ; Yep, still know it
|
||
initial-scratch-message nil ; I know it is the scratch buffer!
|
||
initial-buffer-choice nil
|
||
inhibit-startup-buffer-menu t
|
||
inhibit-x-resources t
|
||
initial-major-mode 'fundamental-mode
|
||
pgtk-wait-for-event-timeout 0.001 ; faster child frames
|
||
ad-redefinition-action 'accept ; dont care about legacy things being redefined
|
||
inhibit-compacting-font-caches t
|
||
;; tabs
|
||
tab-width 4 ; Always tab 4 spaces.
|
||
indent-tabs-mode nil ; Never use actual tabs.
|
||
;; rendering
|
||
cursor-in-non-selected-windows nil ; dont render cursors other windows
|
||
;; packages
|
||
use-package-always-defer t
|
||
load-prefer-newer t
|
||
default-input-method nil
|
||
use-dialog-box nil
|
||
use-file-dialog nil
|
||
use-package-expand-minimally t
|
||
package-enable-at-startup nil
|
||
use-package-enable-imenu-support t
|
||
auto-mode-case-fold nil ; No second pass of case-insensitive search over auto-mode-alist.
|
||
package-archives '(("melpa" . "https://melpa.org/packages/")
|
||
("gnu" . "https://elpa.gnu.org/packages/")
|
||
("nongnu" . "https://elpa.nongnu.org/nongnu/")
|
||
("melpa-stable" . "https://stable.melpa.org/packages/"))
|
||
package-archive-priorities '(("gnu" . 99)
|
||
("nongnu" . 80)
|
||
("melpa" . 70)
|
||
("melpa-stable" . 50))
|
||
)
|
||
;;; early-init.el ends here
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org04e483b" class="outline-3">
|
||
<h3 id="org04e483b"><span class="section-number-3">19.2.</span> Initialization</h3>
|
||
<div class="outline-text-3" id="text-19-2">
|
||
<p>
|
||
Now starts the main emacs configuration.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-emacs-lisp"> ;;; package --- Summary - My minimal Emacs init file -*- lexical-binding: t -*-
|
||
|
||
;;; Commentary:
|
||
;;; Simple Emacs setup I carry everywhere
|
||
|
||
;;; Code:
|
||
(setq custom-file (locate-user-emacs-file "custom.el"))
|
||
(load custom-file 'noerror) ;; no error on missing custom file
|
||
|
||
(require 'package)
|
||
(package-initialize)
|
||
|
||
(defun reset-custom-vars ()
|
||
"Resets the custom variables that were set to crazy numbers"
|
||
(setopt gc-cons-threshold (* 1024 1024 100))
|
||
(setopt garbage-collection-messages t))
|
||
|
||
(use-package emacs
|
||
:custom
|
||
(native-comp-async-query-on-exit t)
|
||
(read-answer-short t)
|
||
(use-short-answers t)
|
||
(enable-recursive-minibuffers t)
|
||
(which-func-update-delay 1.0)
|
||
(visible-bell nil)
|
||
(custom-buffer-done-kill t)
|
||
(whitespace-line-column nil)
|
||
(x-underline-at-descent-line t)
|
||
(imenu-auto-rescan t)
|
||
(uniquify-buffer-name-style 'forward)
|
||
(confirm-nonexistent-file-or-buffer nil)
|
||
(create-lockfiles nil)
|
||
(make-backup-files nil)
|
||
(kill-do-not-save-duplicates t)
|
||
(sentence-end-double-space nil)
|
||
(treesit-enabled-modes t)
|
||
:init
|
||
;; base visual
|
||
(menu-bar-mode -1) ;; no menu bar
|
||
(toggle-scroll-bar -1) ;; no scroll bar
|
||
(tool-bar-mode -1) ;; no tool bar either
|
||
(blink-cursor-mode -1) ;; stop blinking
|
||
|
||
;; font of the century
|
||
(set-frame-font "Aporetic Sans Mono 12" nil t)
|
||
|
||
:bind
|
||
(("C-<wheel-up>" . pixel-scroll-precision) ; dont zoom in please, just scroll
|
||
("C-<wheel-down>" . pixel-scroll-precision) ; dont zoom in either, just scroll
|
||
("C-x k" . kill-current-buffer)) ; kill the buffer, dont ask
|
||
:hook
|
||
(text-mode . delete-trailing-whitespace-mode)
|
||
(prog-mode . delete-trailing-whitespace-mode)
|
||
(after-init . global-display-line-numbers-mode) ;; always show line numbers
|
||
(after-init . column-number-mode) ;; column number in the mode line
|
||
(after-init . size-indication-mode) ;; file size in the mode line
|
||
(after-init . pixel-scroll-precision-mode) ;; smooth mouse scroll
|
||
(after-init . electric-pair-mode) ;; i mean ... parens should auto create
|
||
(after-init . reset-custom-vars)
|
||
)
|
||
|
||
(use-package autorevert
|
||
:ensure nil
|
||
:custom
|
||
(auto-revert-interval 3)
|
||
(auto-revert-remote-files nil)
|
||
(auto-revert-use-notify t)
|
||
(auto-revert-avoid-polling nil)
|
||
(auto-revert-verbose t)
|
||
:hook
|
||
(after-init . global-auto-revert-mode))
|
||
|
||
(use-package recentf
|
||
:ensure nil
|
||
:commands (recentf-mode recentf-cleanup)
|
||
:hook
|
||
(after-init . recentf-mode)
|
||
:custom
|
||
(recentf-auto-cleanup 'never)
|
||
(recentf-exclude
|
||
(list "\\.tar$" "\\.tbz2$" "\\.tbz$" "\\.tgz$" "\\.bz2$"
|
||
"\\.bz$" "\\.gz$" "\\.gzip$" "\\.xz$" "\\.zip$"
|
||
"\\.7z$" "\\.rar$"
|
||
"COMMIT_EDITMSG\\'"
|
||
"\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\|bmp\\|xpm\\)$"
|
||
"-autoloads\\.el$" "autoload\\.el$"))
|
||
|
||
:config
|
||
;; A cleanup depth of -90 ensures that `recentf-cleanup' runs before
|
||
;; `recentf-save-list', allowing stale entries to be removed before the list
|
||
;; is saved by `recentf-save-list', which is automatically added to
|
||
;; `kill-emacs-hook' by `recentf-mode'.
|
||
(add-hook 'kill-emacs-hook #'recentf-cleanup -90))
|
||
|
||
(use-package savehist
|
||
:ensure nil
|
||
:commands (savehist-mode savehist-save)
|
||
:hook
|
||
(after-init . savehist-mode)
|
||
:custom
|
||
(savehist-autosave-interval 600)
|
||
(savehist-additional-variables
|
||
'(kill-ring ; clipboard
|
||
register-alist ; macros
|
||
mark-ring global-mark-ring ; marks
|
||
search-ring regexp-search-ring)))
|
||
|
||
(use-package hl-line
|
||
:ensure nil
|
||
:custom
|
||
(hl-line-sticky-flag nil)
|
||
(global-hl-line-sticky-flag nil)
|
||
:hook
|
||
(after-init . global-hl-line-mode))
|
||
|
||
(use-package saveplace
|
||
:ensure nil
|
||
:commands (save-place-mode save-place-local-mode)
|
||
:hook
|
||
(after-init . save-place-mode)
|
||
:custom
|
||
(save-place-limit 400))
|
||
|
||
(use-package nerd-icons
|
||
:custom
|
||
;; disable bright icon colors
|
||
(nerd-icons-color-icons nil))
|
||
|
||
(use-package doom-modeline
|
||
:custom
|
||
(inhibit-compacting-font-caches t) ;; speed
|
||
(doom-modeline-buffer-file-name-style 'relative-from-project)
|
||
(doom-modeline-major-mode-icon nil) ;; distracting icons, no thank you
|
||
(doom-modeline-buffer-encoding nil) ;; everything is utf-8 anyway
|
||
(doom-modeline-buffer-state-icon nil) ;; the filename already shows me
|
||
(doom-modeline-lsp nil) ;; lsp state is too distracting, too often
|
||
:hook (after-init . doom-modeline-mode))
|
||
|
||
(load-theme 'catppuccin :no-confirm)
|
||
|
||
(use-package diminish :demand t) ;; declutter the modeline
|
||
(use-package eldoc
|
||
:diminish eldoc-mode
|
||
:custom
|
||
(eldoc-echo-area-use-multiline-p nil)) ;; docs for everything
|
||
|
||
(use-package eldoc-box
|
||
:defer t
|
||
:config
|
||
(set-face-background 'eldoc-box-border (catppuccin-color 'green))
|
||
(set-face-background 'eldoc-box-body (catppuccin-color 'base))
|
||
:bind
|
||
(("M-h" . eldoc-box-help-at-point)))
|
||
|
||
(use-package pulsar
|
||
:commands pulsar-global-mode pulsar-recenter-top pulsar-reveal-entry
|
||
:init
|
||
(defface pulsar-catppuccin
|
||
`((default :extend t)
|
||
(((class color) (min-colors 88) (background light))
|
||
:background ,(catppuccin-color 'sapphire))
|
||
(((class color) (min-colors 88) (background dark))
|
||
:background ,(catppuccin-color 'sapphire))
|
||
(t :inverse-video t))
|
||
"Alternative nord face for `pulsar-face'."
|
||
:group 'pulsar-faces)
|
||
:custom
|
||
(pulsar-face 'pulsar-catppuccin)
|
||
:hook
|
||
(after-init . pulsar-global-mode))
|
||
|
||
(use-package which-key
|
||
:commands which-key-mode
|
||
:diminish which-key-mode
|
||
:hook
|
||
(after-init . which-key-mode))
|
||
|
||
(use-package expreg
|
||
:bind ("M-m" . expreg-expand))
|
||
|
||
(use-package vundo) ;; undo tree
|
||
|
||
;; better structured editing
|
||
(use-package puni
|
||
:commands puni-global-mode
|
||
:hook
|
||
(after-init . puni-global-mode))
|
||
|
||
(use-package avy
|
||
:bind
|
||
("M-i" . avy-goto-char-2)
|
||
:custom
|
||
(avy-background t))
|
||
|
||
(use-package consult
|
||
:bind
|
||
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
|
||
("M-y" . consult-yank-pop) ;; orig. yank-pop
|
||
("M-g M-g" . consult-goto-line) ;; orig. goto-line
|
||
("M-g i" . consult-imenu) ;; consult version is interactive
|
||
("M-g r" . consult-ripgrep) ;; find in project also works
|
||
:custom
|
||
(consult-narrow-key "<"))
|
||
|
||
(use-package vertico
|
||
:commands vertico-mode
|
||
:custom
|
||
(read-file-name-completion-ignore-case t)
|
||
(read-buffer-completion-ignore-case t)
|
||
(completion-ignore-case t)
|
||
(enable-recursive-minibuffers t)
|
||
(minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt))
|
||
:init
|
||
(vertico-mode)
|
||
:hook
|
||
(minibuffer-setup-hook . cursor-intangible-mode))
|
||
|
||
(use-package marginalia
|
||
:commands marginalia-mode
|
||
:hook (after-init . marginalia-mode))
|
||
|
||
(use-package crux
|
||
:bind
|
||
("C-c M-e" . crux-find-user-init-file)
|
||
("C-c C-w" . crux-transpose-windows)
|
||
("C-c M-d" . crux-find-current-directory-dir-locals-file)
|
||
("C-a" . crux-move-beginning-of-line))
|
||
|
||
(use-package magit
|
||
:bind (("C-M-g" . magit-status)))
|
||
|
||
(use-package nerd-icons-corfu
|
||
:commands nerd-icons-corfu-formatter
|
||
:defines corfu-margin-formatters)
|
||
|
||
(use-package corfu
|
||
:commands global-corfu-mode
|
||
:custom
|
||
(corfu-cycle t)
|
||
(corfu-auto t)
|
||
(corfu-auto-delay 1)
|
||
(corfu-auto-prefix 3)
|
||
(corfu-separator ?_)
|
||
:hook
|
||
(after-init . global-corfu-mode)
|
||
:config
|
||
(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
|
||
|
||
(use-package cape)
|
||
|
||
(use-package orderless
|
||
:custom
|
||
(completion-styles '(orderless partial-completion basic))
|
||
(completion-category-defaults nil)
|
||
(completion-category-overrides nil))
|
||
|
||
(use-package yasnippet
|
||
:commands yas-global-mode
|
||
:diminish yas-minor-mode
|
||
:hook
|
||
(after-init . yas-global-mode))
|
||
|
||
(use-package yasnippet-snippets :after yasnippet)
|
||
|
||
(use-package exec-path-from-shell
|
||
:commands exec-path-from-shell-initialize
|
||
:custom
|
||
(exec-path-from-shell-arguments nil)
|
||
:hook
|
||
(after-init . exec-path-from-shell-initialize))
|
||
|
||
(use-package nixpkgs-fmt
|
||
:custom
|
||
(nixpkgs-fmt-command "nixfmt"))
|
||
|
||
(use-package eat
|
||
:bind
|
||
(("C-c e p" . eat-project)
|
||
("C-c e t" . eat)))
|
||
|
||
(use-package f :demand t)
|
||
|
||
(use-package envrc
|
||
:commands envrc-global-mode
|
||
:hook
|
||
(after-init . envrc-global-mode))
|
||
|
||
(use-package gptel
|
||
:commands gptel-make-anthropic f-read-text
|
||
:config
|
||
(gptel-make-anthropic "Claude"
|
||
:stream t :key (f-read-text "/run/secrets/claude_key")))
|
||
|
||
(use-package sideline-flymake)
|
||
(use-package sideline-eglot)
|
||
(use-package sideline
|
||
:custom
|
||
(sideline-backends-right '(sideline-flymake sideline-eglot))
|
||
:hook
|
||
(eglot-managed-mode . sideline-mode)
|
||
(flymake-mode . sideline-mode))
|
||
|
||
(use-package eglot
|
||
:custom
|
||
(eglot-extend-to-xref t)
|
||
(eglot-ignored-server-capabilities '(:inlayHintProvider))
|
||
(jsonrpc-event-hook nil)
|
||
:hook
|
||
(eglot-managed-mode . eldoc-box-hover-mode)
|
||
(before-save . eldoc-format-buffer)
|
||
:bind
|
||
(:map eglot-mode-map
|
||
("C-c l a" . eglot-code-actions)
|
||
("C-c l r" . eglot-rename)
|
||
("C-c l h" . eldoc)
|
||
("C-c l g" . xref-find-references)
|
||
("C-c l w" . eglot-reconnect)))
|
||
|
||
(use-package proced
|
||
:custom
|
||
(proced-auto-update-flag t)
|
||
(proced-auto-update-interval 3)
|
||
(proced-enable-color-flag t)
|
||
(proced-show-remote-processes t))
|
||
|
||
(use-package org
|
||
:ensure t
|
||
:defer t
|
||
:commands (org-mode org-capture org-agenda)
|
||
:init
|
||
(defvar org-journal-file "~/nextcloud/org/journal.org")
|
||
(defvar org-archive-file "~/nextcloud/org/archive.org")
|
||
(defvar org-notes-file "~/nextcloud/org/notes.org")
|
||
(defvar org-inbox-file "~/nextcloud/org/inbox.org")
|
||
(defvar org-work-file "~/nextcloud/org/work.org")
|
||
(defun my/org-capture-project-target-heading ()
|
||
"Determine Org target headings from the current file's project path.
|
||
|
||
This function assumes a directory structure like '~/projects/COMPANY/PROJECT/'.
|
||
It extracts 'COMPANY' and 'PROJECT' to use as nested headlines
|
||
for an Org capture template.
|
||
|
||
If the current buffer is not visi
|
||
ting a file within such a
|
||
project structure, it returns nil, causing capture to default to
|
||
the top of the file."
|
||
(when-let* ((path (buffer-file-name))) ; Ensure we are in a file-visiting buffer
|
||
(let ((path-parts (split-string path "/" t " ")))
|
||
(when-let* ((projects-pos (cl-position "projects" path-parts :test #'string=))
|
||
(company (nth (+ 1 projects-pos) path-parts))
|
||
(project (nth (+ 2 projects-pos) path-parts)))
|
||
;; Return a list of headlines for Org to find or create.
|
||
(list company project)))))
|
||
:bind
|
||
(("C-c c" . org-capture)
|
||
("C-c i" . org-store-link)
|
||
("C-c a" . org-agenda)
|
||
:map org-mode-map
|
||
("C-c t" . org-toggle-inline-images)
|
||
("C-c l" . org-toggle-link-display))
|
||
:custom
|
||
(org-agenda-files (list org-inbox-file org-journal-file))
|
||
(org-directory "~/nextcloud/org")
|
||
(org-default-notes-file org-inbox-file)
|
||
(org-archive-location (concat org-archive-file "::* From %s"))
|
||
(org-log-done 'time)
|
||
(org-log-into-drawer t)
|
||
(org-hide-emphasis-markers t)
|
||
(org-src-fontify-natively t)
|
||
(org-src-tab-acts-natively t)
|
||
(org-capture-templates '(("t" "Todo" entry (file org-inbox-file)
|
||
"* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n)")
|
||
("j" "Journal" entry (file+olp+datetree org-journal-file)
|
||
"* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n")
|
||
("n" "Note" entry (file org-notes-file)
|
||
"* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n")
|
||
("p" "Project Task" item
|
||
(file+function org-work-file my/org-capture-project-target-heading)
|
||
"* TODO %? \n CLOCK: %U"
|
||
))
|
||
)
|
||
:config
|
||
;; Enable syntax highlighting in code blocks
|
||
(add-hook 'org-mode-hook 'turn-on-font-lock)
|
||
(add-hook 'org-mode-hook 'org-indent-mode))
|
||
|
||
;; extras
|
||
(use-package comp-run
|
||
:ensure nil
|
||
:config
|
||
(push "tramp-loaddefs.el.gz" native-comp-jit-compilation-deny-list)
|
||
(push "cl-loaddefs.el.gz" native-comp-jit-compilation-deny-list))
|
||
|
||
(use-package rustic
|
||
:custom
|
||
(rustic-lsp-client 'eglot))
|
||
|
||
(provide 'init)
|
||
|
||
;;; init.el ends here
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orge6efaa4" class="outline-2">
|
||
<h2 id="orge6efaa4"><span class="section-number-2">20.</span> Machines</h2>
|
||
<div class="outline-text-2" id="text-20">
|
||
<p>
|
||
Only a few more things left. Specifically the machine level extra settings.
|
||
</p>
|
||
</div>
|
||
<div id="outline-container-org0b8a9b5" class="outline-3">
|
||
<h3 id="org0b8a9b5"><span class="section-number-3">20.1.</span> Traveldroid</h3>
|
||
<div class="outline-text-3" id="text-20-1">
|
||
<p>
|
||
The configuration for the laptop does not change much. Most changes are because the hardware is different.
|
||
</p>
|
||
</div>
|
||
<div id="outline-container-org2048e57" class="outline-4">
|
||
<h4 id="org2048e57"><span class="section-number-4">20.1.1.</span> System Level</h4>
|
||
<div class="outline-text-4" id="text-20-1-1">
|
||
<p>
|
||
Nothing specific for the laptop.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ user, ... } : {
|
||
imports =
|
||
[
|
||
./hardware-configuration.nix
|
||
../../configuration
|
||
];
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org8326f51" class="outline-4">
|
||
<h4 id="org8326f51"><span class="section-number-4">20.1.2.</span> Hardware</h4>
|
||
<div class="outline-text-4" id="text-20-1-2">
|
||
<p>
|
||
This is the most different. Mostly taken from hardware-configuration.nix setup at first install.
|
||
</p>
|
||
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{
|
||
hostname,
|
||
pkgs,
|
||
lib,
|
||
modulesPath,
|
||
user,
|
||
config,
|
||
...
|
||
}:
|
||
{
|
||
imports = [
|
||
(modulesPath + "/installer/scan/not-detected.nix")
|
||
../../hardware/hardware.nix
|
||
];
|
||
|
||
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_usb_sdmmc" ];
|
||
boot.initrd.kernelModules = [ ];
|
||
boot.kernelModules = [ "kvm-intel" ];
|
||
boot.extraModulePackages = [ ];
|
||
|
||
fileSystems."/" =
|
||
{ device = "/dev/disk/by-uuid/69433a14-fbaf-401b-af85-cd1bbf02b4e2";
|
||
fsType = "ext4";
|
||
};
|
||
|
||
fileSystems."/boot" =
|
||
{ device = "/dev/disk/by-uuid/811D-0676";
|
||
fsType = "vfat";
|
||
options = [ "fmask=0077" "dmask=0077" ];
|
||
};
|
||
|
||
swapDevices =
|
||
[ { device = "/dev/disk/by-uuid/b6c557c2-7682-460b-a5e7-8f6f2f429a3a"; }
|
||
];
|
||
|
||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-org40e701a" class="outline-4">
|
||
<h4 id="org40e701a"><span class="section-number-4">20.1.3.</span> Home</h4>
|
||
<div class="outline-text-4" id="text-20-1-3">
|
||
<p>
|
||
This is mostly about configuring the monitor. And laptop specific utilities.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-nix">{ pkgs, ... }:
|
||
{
|
||
imports = [
|
||
../../home
|
||
];
|
||
home.packages = with pkgs; [
|
||
brightnessctl
|
||
];
|
||
wayland.windowManager.hyprland = {
|
||
extraConfig = ''
|
||
# Default portable monitor rule
|
||
monitor=DP-1,3840x1080@144,1920x0,1
|
||
'';
|
||
};
|
||
}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="outline-container-orgaa2a768" class="outline-2">
|
||
<h2 id="orgaa2a768"><span class="section-number-2">21.</span> README Utils</h2>
|
||
<div class="outline-text-2" id="text-21">
|
||
</div>
|
||
<div id="outline-container-orgc2a81c8" class="outline-4">
|
||
<h4 id="orgc2a81c8"><span class="section-number-4">21.0.1.</span> Headers</h4>
|
||
<div class="outline-text-4" id="text-21-0-1">
|
||
<p>
|
||
This script adds a <code>DO NOT MODIFY</code> header to all the generated nix files.
|
||
</p>
|
||
<div class="org-src-container">
|
||
<pre class="src src-emacs-lisp" id="org088569b">(progn
|
||
(defun add-tangle-headers ()
|
||
(message "running in %s" (buffer-file-name))
|
||
(when (string= (file-name-extension (buffer-file-name)) "nix")
|
||
(goto-char (point-min))
|
||
(insert "# WARNING : This file was generated by README.org\n# DO NOT MODIFY THIS FILE!\n# Any changes made here will be overwritten.\n")
|
||
(save-buffer))
|
||
(save-buffer))
|
||
(add-hook 'org-babel-post-tangle-hook 'add-tangle-headers))
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="postamble" class="status">
|
||
<p class="author">Author: henrov</p>
|
||
<p class="date">Created: 2026-02-22 zo 23:03</p>
|
||
<p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
|
||
</div>
|
||
</body>
|
||
</html>
|