added stuff

This commit is contained in:
vali 2024-04-09 23:11:33 +02:00
commit 236b8c2a6b
907 changed files with 70990 additions and 0 deletions

View file

@ -0,0 +1,14 @@
{
imports = [
./docs # internal module system documentation and linking
./device # device-specific declarations, hardware-specific
./meta # internal read-only system manifests for easy access to system details
./profiles # profiles allow the system to batch enable programs without hassle
./system # system-level declarations, software-specific
./theme # theme packages and configurations
./usrEnv # user environment, such as main system user or
./removed.nix # options that have been fully deprecated
./renamed.nix # options that have been moved or relocated. Will throw a warning if they are used
];
}

View file

@ -0,0 +1,25 @@
{lib, ...}: let
inherit (lib) mkOption types;
in {
options.modules.device = {
# bluetooth is an insecure protocol if left unchedked, so while this defaults to true
# but the bluetooth.enable option does and should not.
hasBluetooth = mkOption {
type = types.bool;
default = true;
description = "Whether or not the system has bluetooth support";
};
hasSound = mkOption {
type = types.bool;
default = true;
description = "Whether the system has sound support (usually true except for servers)";
};
hasTPM = mkOption {
type = types.bool;
default = false;
description = "Whether the system has tpm support";
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./capabilities.nix
./hardware.nix
];
}

View file

@ -0,0 +1,82 @@
{lib, ...}: let
inherit (lib) mkOption mkEnableOption types;
in {
options.modules.device = {
type = mkOption {
type = types.enum ["laptop" "desktop" "server" "hybrid" "lite" "vm"];
default = "";
description = ''
The type/purpose of the device that will be used within the rest of the configuration.
- laptop: portable devices with batter optimizations
- desktop: stationary devices configured for maximum performance
- server: server and infrastructure
- hybrid: provide both desktop and server functionality
- lite: a lite device, such as a raspberry pi
- vm: a virtual machine
'';
};
# the type of cpu your system has - vm and regular cpus currently do not differ
# as I do not work with vms, but they have been added for forward-compatibility
# TODO: make this a list - apparently more than one cpu on a device is still doable
cpu = {
type = mkOption {
type = with types; nullOr (enum ["pi" "intel" "vm-intel" "amd" "vm-amd"]);
default = null;
description = ''
The manifaturer/type of the primary system CPU.
Determines which ucode services will be enabled and provides additional kernel packages
'';
};
amd = {
pstate.enable = mkEnableOption "AMD P-State Driver";
zenpower = {
enable = mkEnableOption "AMD Zenpower Driver";
args = mkOption {
type = types.str;
default = "-p 0 -v 3C -f A0"; # Pstate 0, 1.175 voltage, 4000 clock speed
description = ''
The percentage of the maximum clock speed that the CPU will be limited to.
This is useful for reducing power consumption and heat generation on laptops
and desktops
'';
};
};
};
};
gpu = {
type = mkOption {
type = with types; nullOr (enum ["pi" "amd" "intel" "nvidia" "hybrid-nv" "hybrid-amd"]);
default = null;
description = ''
The manifaturer/type of the primary system GPU. Allows the correct GPU
drivers to be loaded, potentially optimizing video output performance
'';
};
};
monitors = mkOption {
type = with types; listOf str;
default = [];
description = ''
A list of monitors connected to the system.
This does not affect any drivers and such, it is only necessary for
declaring things like monitors in window manager configurations.
It is not necessary to declare this, but wallpaper and workspace
configurations will be affected by the monitors list
::: {.tip}
Monitors should be listed from left to right in the order they are placed
assuming the leftmost (first element) is the primary one. This is not a
solution to the possibility of a monitor being placed above or below another
but it currently works.
:::
'';
};
};
}

View file

@ -0,0 +1,449 @@
// Define variables for commonly used colors and font sizes
$primary-color: #8dc8f4;
$secondary-color: #7fb3dc;
$link-hover-color: #6ac7da;
$link-active-color: #6ac7da;
$text-color: #afbded;
$background-color: #1e1e2e;
$heading-color: #8cc6f2;
$blockquote-color: #afbded;
$table-header-bg: #afbded;
$table-border-color: #2e2e46;
$font-family: Roboto, Georgia, Palatino, Times, "Times New Roman", Lexend, serif;
$monospace-font: monospace;
$base-font-size: 14px;
// Define mixins for commonly used styles
@mixin heading-styles {
color: $heading-color;
line-height: 125%;
margin-top: 2em;
font-weight: normal;
}
@mixin media-query($breakpoint) {
@media only screen and (min-width: $breakpoint) {
@content;
}
}
@keyframes bounce {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-5px);
}
}
// Begin SCSS stylesheet
html {
font-size: 100%;
overflow-y: scroll;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
body {
color: $text-color;
font-family: $font-family;
font-size: $base-font-size;
line-height: 1.7;
padding: 1em;
margin: auto;
max-width: 42em;
background: $background-color;
@include media-query(480px) {
font-size: 14px;
}
@include media-query(768px) {
font-size: 16px;
}
}
a {
color: $primary-color;
text-decoration: none;
&:visited {
color: $secondary-color;
}
&:hover {
color: $link-hover-color;
}
&:active {
color: $link-active-color;
}
&:focus {
outline: thin dotted;
}
&::-moz-selection {
background: rgba($primary-color, 0.3);
color: $text-color;
}
&::selection {
background: rgba($primary-color, 0.3);
color: $text-color;
}
&::-moz-selection {
background: rgba($primary-color, 0.3);
color: $primary-color;
}
&::selection {
background: rgba($primary-color, 0.3);
color: $primary-color;
}
}
p {
margin: 1em 0;
}
img {
max-width: 100%;
}
h1,
h2,
h3,
h4,
h5,
h6 {
@include heading-styles;
h4,
h5,
h6 {
font-weight: bold;
}
h1 {
font-size: 2.5em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.5em;
}
h4 {
font-size: 1.2em;
}
h5 {
font-size: 1em;
}
h6 {
font-size: 0.9em;
}
}
blockquote {
color: $blockquote-color;
margin: 0;
padding-left: 3em;
border-left: 0.5em $background-color solid;
}
hr {
display: block;
height: 2px;
border: 0;
border-top: 1px solid $table-border-color;
border-bottom: 1px solid $background-color;
margin: 1em 0;
padding: 0;
}
pre,
code,
kbd,
samp {
color: $text-color;
font-family: $monospace-font;
_font-family: "courier new", monospace;
font-size: 0.98em;
}
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
b,
strong {
font-weight: bold;
}
dfn {
font-style: italic;
}
ins {
background: $primary-color;
color: $text-color;
text-decoration: none;
}
mark {
background: $primary-color;
color: $text-color;
font-style: italic;
font-weight: bold;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
}
ul,
ol {
margin: 1em 0;
padding: 0 0 0 2em;
ul ul,
ol ol {
margin: 0.3em 0;
}
}
dl {
margin-bottom: 1em;
}
dt {
font-weight: bold;
margin-bottom: 0.8em;
}
dd {
margin: 0 0 0.8em 2em;
&:last-child {
margin-bottom: 0;
}
}
img {
border: 0;
-ms-interpolation-mode: bicubic;
vertical-align: middle;
}
figure {
display: block;
text-align: center;
margin: 1em 0;
img {
border: none;
margin: 0 auto;
}
figcaption {
font-size: 0.8em;
font-style: italic;
margin: 0 0 0.8em;
}
}
table {
margin-bottom: 2em;
border-bottom: 1px solid $table-border-color;
border-right: 1px solid $table-border-color;
border-spacing: 0;
border-collapse: collapse;
th {
padding: 0.2em 1em;
background-color: $table-header-bg;
border-top: 1px solid $table-border-color;
border-left: 1px solid $table-border-color;
}
td {
padding: 0.2em 1em;
border-top: 1px solid $table-border-color;
border-left: 1px solid $table-border-color;
vertical-align: top;
}
}
.author {
font-size: 1.2em;
text-align: center;
}
@media print {
* {
background: transparent !important;
color: $text-color !important;
filter: none !important;
-ms-filter: none !important;
}
body {
font-size: 12pt;
max-width: 100%;
}
a,
a:visited {
text-decoration: underline;
}
hr {
height: 1px;
border: 0;
border-bottom: 1px solid $text-color;
}
a[href]:after {
content: " (" attr(href) ")";
}
abbr[title]:after {
content: " (" attr(title) ")";
}
.ir a:after,
a[href^="javascript:"]:after,
a[href^="#"]:after {
content: "";
}
pre,
blockquote {
border: 1px solid $text-color;
padding-right: 1em;
page-break-inside: avoid;
}
tr,
img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
@page :left {
margin: 15mm 20mm 15mm 10mm;
}
@page :right {
margin: 15mm 10mm 15mm 20mm;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
}
// Sidebar style, contains the ToC with clickable links
.sidebar {
position: fixed;
top: 0;
left: -1000px; // Initially hidden by being yoten offscreen
height: 100%;
width: 490px; // Static content width. FIXME: ugh
background-color: darken($background-color, 2%);
overflow-x: hidden; // Horizontal scrollbar
overflow-y: auto; // Vertical scrollbar if needed
transition: left 0.3s; // "Smooth" slide animation
padding: 10px;
z-index: 1000; // Ensure sidebar is above content
}
.sidebar.show {
left: 0; // Show sidebar when toggled
border: 1px solid darken($background-color, 5%);
}
// Togglee sidebar
.toggle-btn {
position: fixed;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
color: lighten($text-color, 2%);
font-size: 16px;
transition: left 0.3s;
&:hover {
color: lighten($text-color, 4%);
}
}
.toggle-btn.left {
left: 20px;
}
.toggle-btn.right {
left: 520px;
}
// Go back button
.go-back-btn {
position: fixed;
bottom: 20px;
right: 20px;
width: 50px;
height: 50px;
background-color: lighten($background-color, 4%);
color: $text-color;
border-radius: 10px;
cursor: pointer;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.3s ease;
&:hover {
color: lighten($background-color, 4%);
background-color: lighten($background-color, 8%);
}
i {
font-size: 20px;
}
}

View file

@ -0,0 +1,117 @@
<!doctype html>
<html
xmlns="http://www.w3.org/1999/xhtml"
lang="$lang$"
xml:lang="$lang$"
$if(dir)$
dir="$dir$"
$endif$
>
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=yes"
/>
$for(author-meta)$
<meta name="author" content="$author-meta$" />
$endfor$ $if(date-meta)$
<meta name="dcterms.date" content="$date-meta$" />
$endif$ $if(keywords)$
<meta
name="keywords"
content="$for(keywords)$$keywords$$sep$, $endfor$"
/>
$endif$ $if(description-meta)$
<meta name="description" content="$description-meta$" />
$endif$
<title>$if(title-prefix)$$title-prefix$ $endif$$pagetitle$</title>
<style>
$styles.html()$
</style>
$for(css)$
<link rel="stylesheet" href="$css$" />
$endfor$ $for(header-includes)$ $header-includes$ $endfor$ $if(math)$
$if(mathjax)$
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
$endif$ $math$ $endif$
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
<!-- Font Awesome -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
/>
</head>
<body>
$for(include-before)$ $include-before$ $endfor$ $if(title)$
<header id="title-block-header">
<h1 class="title">$title$</h1>
$if(subtitle)$
<p class="subtitle">$subtitle$</p>
$endif$ $for(author)$
<p class="author">$author$</p>
$endfor$ $if(date)$
<p class="date">$date$</p>
$endif$ $if(abstract)$
<div class="abstract">
<div class="abstract-title">$abstract-title$</div>
$abstract$
</div>
$endif$
</header>
$endif$
<!-- Toggle button -->
<div class="toggle-btn left" onclick="toggleSidebar()">
<i class="fa-solid fa-chevron-right" id="toggle-icon"></i>
</div>
<!-- Sidebar -->
<div class="sidebar" id="sidebar">
<div class="sidebar-content">
<nav id="$idprefix$TOC" role="doc-toc">
$if(toc-title)$
<h2 id="$idprefix$toc-title">$toc-title$</h2>
$endif$ $table-of-contents$
</nav>
</div>
</div>
<!-- Main Body -->
<div class="content" id="content">$body$</div>
<!-- "Go back" button -->
<div class="go-back-btn" onclick="goToTop()">
<i class="fas fa-arrow-up"></i>
</div>
<!-- JS for toggle button -->
<script>
function toggleSidebar() {
var sidebar = document.getElementById("sidebar");
var toggleBtn = document.querySelector(".toggle-btn");
var toggleIcon = document.getElementById("toggle-icon");
sidebar.classList.toggle("show");
if (sidebar.classList.contains("show")) {
toggleBtn.classList.remove("left");
toggleBtn.classList.add("right");
toggleIcon.classList.remove("fa-chevron-right");
toggleIcon.classList.add("fa-chevron-left");
} else {
toggleBtn.classList.remove("right");
toggleBtn.classList.add("left");
toggleIcon.classList.remove("fa-chevron-left");
toggleIcon.classList.add("fa-chevron-right");
}
}
function goToTop() {
window.scrollTo({ top: 0, behavior: "smooth" });
}
</script>
$for(include-after)$ $include-after$ $endfor$
</body>
</html>

View file

@ -0,0 +1,211 @@
{
"text-color": null,
"background-color": null,
"line-number-color": "#aaaaaa",
"line-number-background-color": null,
"text-styles": {
"Alert": {
"text-color": "#ff0000",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"Annotation": {
"text-color": "#60a0b0",
"background-color": null,
"bold": true,
"italic": true,
"underline": false
},
"Attribute": {
"text-color": "#7d9029",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"BaseN": {
"text-color": "#40a070",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"BuiltIn": {
"text-color": "#008000",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Char": {
"text-color": "#4070a0",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Comment": {
"text-color": "#60a0b0",
"background-color": null,
"bold": false,
"italic": true,
"underline": false
},
"CommentVar": {
"text-color": "#60a0b0",
"background-color": null,
"bold": true,
"italic": true,
"underline": false
},
"Constant": {
"text-color": "#880000",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"ControlFlow": {
"text-color": "#007020",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"DataType": {
"text-color": "#902000",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"DecVal": {
"text-color": "#40a070",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Documentation": {
"text-color": "#ba2121",
"background-color": null,
"bold": false,
"italic": true,
"underline": false
},
"Error": {
"text-color": "#ff0000",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"Extension": {
"text-color": null,
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Float": {
"text-color": "#40a070",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Function": {
"text-color": "#06287e",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Import": {
"text-color": "#008000",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"Information": {
"text-color": "#60a0b0",
"background-color": null,
"bold": true,
"italic": true,
"underline": false
},
"Keyword": {
"text-color": "#007020",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"Operator": {
"text-color": "#666666",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Other": {
"text-color": "#007020",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Preprocessor": {
"text-color": "#bc7a00",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"SpecialChar": {
"text-color": "#4070a0",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"SpecialString": {
"text-color": "#bb6688",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"String": {
"text-color": "#4070a0",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Variable": {
"text-color": "#19177c",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"VerbatimString": {
"text-color": "#4070a0",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Warning": {
"text-color": "#60a0b0",
"background-color": null,
"bold": true,
"italic": true,
"underline": false
}
}
}

View file

@ -0,0 +1,101 @@
{
options,
config,
pkgs,
lib,
...
}: let
inherit (lib.options) mkEnableOption mkOption literalExpression;
inherit (lib.types) nullOr path str package;
inherit (lib.strings) optionalString;
cfg = config.modules.documentation;
configMD =
(pkgs.nixosOptionsDoc {
options = options.modules;
documentType = "appendix";
inherit (cfg) warningsAreErrors;
})
.optionsCommonMark;
compileCss = pkgs.runCommandLocal "compile-css" {} ''
mkdir -p $out
${cfg.scssExecutable} -t expanded ${cfg.scss} > $out/sys-docs-style.css
'';
docs-html = pkgs.runCommand "nyxos-docs" {nativeBuildInputs = [pkgs.pandoc];} (
''
# convert to pandoc markdown instead of using commonmark directly,
# as the former automatically generates heading ids and TOC links.
pandoc \
--from commonmark \
--to markdown \
${configMD} |
# convert pandoc markdown to html using our own template and css files
# where available. --sandbox is passed for extra security.
pandoc \
--sandbox \
--from markdown \
--to html \
--metadata title="NyxOS Docs" \
--toc \
--standalone \
''
+ optionalString (cfg.templatePath != null) ''--template ${cfg.templatePath} \''
+ optionalString (cfg.scss != null) ''--css=${compileCss.outPath}/sys-docs-style.css \''
+ "-o $out"
);
in {
options.modules.documentation = {
enable = mkEnableOption ''
generation of internal module documentation for my system configuration. If enabled
the module options will be rendered with pandoc and linked to `/etc/nyxos`
'';
warningsAreErrors = mkEnableOption ''
enforcing build failure on missing option descriptions. While disabled, warnings will be
displayed, but will not cause the build to fail.
'';
scss = mkOption {
default = ./assets/default-style.scss;
type = nullOr path;
description = "CSS to apply to the docs";
};
scssExecutable = mkOption {
default = lib.getExe' pkgs.sass "scss";
example = literalExpression "${pkgs.dart-sass}/bin/sass";
type = nullOr str;
description = "Path to the sass executable";
};
templatePath = mkOption {
default = ./assets/default-template.html;
type = nullOr path;
description = "The template to use for the docs";
};
# the following are exposed as module options for us to be able to build them in isolation
# i.e. without building the rest of the system
markdownPackage = mkOption {
default = configMD;
type = nullOr package;
readOnly = true;
description = "The package containing generated markdown";
};
htmlPackage = mkOption {
default = docs-html;
type = nullOr package;
readOnly = true;
description = "The package containing generated HTML";
};
# TODO: custom syntax highlighting via syntax.json path OR attrset to json
# we love json. yaml is json. we should use yaml. yes.
};
}

View file

@ -0,0 +1,52 @@
{
config,
lib,
...
}: let
inherit (lib) types;
inherit (lib.options) mkOption;
env = config.modules.usrEnv;
in {
options.meta = {
hostname = mkOption {
type = types.str;
default = config.networking.hostName;
readOnly = true;
description = ''
The canonical hostname of the machine.
Is usually used to identify - i.e name machines internally
or on the same Headscale network. This option must be declared
in `hosts.nix` alongside host system.
'';
};
system = mkOption {
type = types.str;
default = config.system.build.toplevel.system;
readOnly = true;
description = ''
The architecture of the machine.
'';
};
isWayland = mkOption {
type = types.bool;
# TODO: there must be a better way to do this
default = with env.desktops; (sway.enable || hyprland.enable);
# readOnly = true; # TODO
description = ''
Whether to enable Wayland exclusive modules, this contains a wariety
of packages, modules, overlays, XDG portals and so on.
Generally includes:
- Wayland nixpkgs overlay
- Wayland only services
- Wayland only programs
- Wayland compatible versions of packages as opposed
to the defaults
'';
};
};
}

View file

@ -0,0 +1,20 @@
{lib, ...}: let
inherit (lib) mkEnableOption;
in {
options.modules.profiles = {
workstation.enable = mkEnableOption ''
the Desktop profile
This profile is intended for systems that are workstations: i.e
systems that must contain a suite of applications tailored for
daily usage, mainly for working, studying or programming.
'';
gaming.enable = mkEnableOption ''
the Gaming profile
This profile contains basic platforms and utilities that can be
used for gaming, such as but not limited to Steam and Lutris.
'';
};
}

View file

@ -0,0 +1,22 @@
{lib, ...}: let
inherit (lib) mkRemovedOptionModule;
in {
imports = [
(mkRemovedOptionModule ["modules" "services" "override"] ''
service overrides have been removed in favor of the new `modules.services.<name>.enable` syntax
'')
(mkRemovedOptionModule ["modules" "usrEnv" "noiseSuppressor"] ''
`modules.usrEnv.noiseSuppressor` has been removed as programs managed by the module
are better enabled manually and individually under `modules.system.programs.<name>.enable`
'')
/*
(mkRemovedOptionModule ["modules" "usrEnv" "isWayland"] ''
`isWayland` has been moved to the meta module as a read-only option that will be set internally
based on the desktop environments the host is running, and can no longer be set manually. Please
move to using `modules.usrEnv.desktop` and `modules.usrEnv.dektops.<name>.enable` instead.
'')
*/
];
}

View file

@ -0,0 +1,30 @@
{lib, ...}: let
inherit (lib) mkRenamedOptionModule;
in {
imports = [
# renamed modules for the device module
(mkRenamedOptionModule ["modules" "device" "yubikeySupport"] ["modules" "system" "yubikeySupport"])
# renamed modules for the userEnv module
(mkRenamedOptionModule ["modules" "usrEnv" "autologin"] ["modules" "system" "autoLogin"])
(mkRenamedOptionModule ["modules" "usrEnv" "isWayland"] ["meta" "isWayland"])
# renamed options for the system module
(mkRenamedOptionModule ["modules" "system" "networking" "wirelessBackend"] ["modules" "system" "networking" "wireless" "backend"])
(mkRenamedOptionModule ["modules" "system" "networking" "useTailscale"] ["modules" "system" "networking" "tailscale" "client" "enable"])
(mkRenamedOptionModule ["modules" "system" "networking" "tailscale" "defaultFlags"] ["modules" "system" "networking" "tailscale" "flags" "default"])
(mkRenamedOptionModule ["modules" "system" "networking" "tailscale" "client" "enable"] ["modules" "system" "networking" "tailscale" "isClient"])
(mkRenamedOptionModule ["modules" "system" "networking" "tailscale" "server" "enable"] ["modules" "system" "networking" "tailscale" "isServer"])
(mkRenamedOptionModule ["modules" "system" "services" "atticd" "enable"] ["modules" "system" "services" "bincache" "atticd" "enable"])
(mkRenamedOptionModule ["modules" "system" "services" "wireguard" "enable"] ["modules" "system" "services" "networking" "wireguard" "enable"])
(mkRenamedOptionModule ["modules" "system" "services" "headscale" "enable"] ["modules" "system" "services" "networking" "headscale" "enable"])
(mkRenamedOptionModule ["modules" "system" "boot" "enableInitrdTweaks"] ["modules" "system" "boot" "initrd" "enableTweaks"])
(mkRenamedOptionModule ["modules" "system" "security" "secureBoot"] ["modules" "system" "boot" "secureBoot"])
(mkRenamedOptionModule ["modules" "system" "services" "gitea" "enable"] ["modules" "system" "services" "forgejo" "enable"])
(mkRenamedOptionModule ["modules" "system" "services" "mastodon" "enable"] ["modules" "system" "services" "social" "mastodon" "enable"])
(mkRenamedOptionModule ["modules" "system" "services" "matrix" "enable"] ["modules" "system" "services" "social" "matrix" "enable"])
];
}

View file

@ -0,0 +1,7 @@
{lib, ...}: let
inherit (lib) mkEnableOption;
in {
options.modules.system.activation = {
diffGenerations = mkEnableOption "diff view between rebuilds";
};
}

View file

@ -0,0 +1,133 @@
{
config,
lib,
pkgs,
...
}: let
inherit (lib) literalExpression mkEnableOption mkOption types;
cfg = config.modules.system.boot;
in {
# pre-boot and bootloader configurations
options.modules.system.boot = {
enableKernelTweaks = mkEnableOption "security and performance related kernel parameters";
recommendedLoaderConfig = mkEnableOption "tweaks for common bootloader configs per my liking";
loadRecommendedModules = mkEnableOption "kernel modules that accommodate for most use cases";
tmpOnTmpfs =
mkEnableOption ''
`/tmp` living on tmpfs. false means it will be cleared manually on each reboot
This option defaults to `true` if the host provides patches to the kernel package in
`boot.kernelPatches`
''
// {default = config.boot.kernelPatches == [];};
secureBoot = mkEnableOption ''
secure-boot with the necessary packages. Requires systemd-boot to be disabled
'';
silentBoot =
mkEnableOption ''
almost entirely silent boot process through `quiet` kernel parameter
''
// {default = config.modules.system.boot.plymouth.enable;};
initrd = {
enableTweaks = mkEnableOption "quality of life tweaks for the initrd stage";
optimizeCompressor = mkEnableOption ''
initrd compression algorithm optimizations for size.
Enabling this option will force initrd to use zstd (default) with
level 19 and -T0 (STDIN). This will reduce the initrd size greatly
at the cost of compression speed.
Not recommended for low-end hardware.
'';
};
kernel = mkOption {
type = with types; nullOr raw;
default = pkgs.linuxPackages_latest;
example = literalExpression "pkgs.linuxPackages_latest";
description = "The kernel to use for the system.";
};
extraModprobeConfig = mkOption {
type = types.str;
default = ''options hid_apple fnmode=1'';
description = "Extra modprobe config that will be passed to system modprobe config.";
};
extraKernelParams = mkOption {
type = with types; listOf str;
default = [];
description = "Extra kernel parameters to be added to the kernel command line.";
};
extraModulePackages = mkOption {
type = with types; listOf package;
default = [];
example = literalExpression ''with config.boot.kernelPackages; [acpi_call]'';
description = "Extra kernel modules to be loaded.";
};
loader = mkOption {
type = types.enum ["none" "grub" "systemd-boot"];
default = "none";
description = "The bootloader that should be used for the device.";
};
grub = {
device = mkOption {
type = with types; nullOr str;
default = "nodev";
description = "The device to install the bootloader to.";
};
};
plymouth = {
enable = mkEnableOption "Plymouth boot splash";
withThemes = mkEnableOption ''
Whether or not themes from https://github.com/adi1090x/plymouth-themes
should be enabled and configured
'';
pack = mkOption {
type = types.enum [1 2 3 4];
default = 3;
description = "The pack number for the theme to be selected from.";
};
theme = mkOption {
type = types.str;
default = "hud_3";
description = "The theme name from the selected theme pack";
};
};
memtest = {
enable = mkEnableOption "memtest86+";
package = mkOption {
type = types.package;
default = pkgs.memtest86plus;
description = "The memtest package to use.";
};
};
};
config = {
assertions = [
{
assertion = cfg.kernel != null;
message = ''
Your system does not specify a kernel package. This is intended behaviour
and is to avoid specifying default kernels that are not compatible with
active hardware.
To supress this error, you must set `config.modules.system.boot.kernel`
to a valid kernel package.
'';
}
];
};
}

View file

@ -0,0 +1,45 @@
{
config,
lib,
...
}: let
inherit (lib) mkEnableOption mkOption types literalExpression;
cfg = config.modules.system.containers;
in {
options.modules.system.containers = {
enable = mkEnableOption "systemd-nspawn containers";
availableContainers = mkOption {
type = with types; listOf str;
default = ["alpha" "beta" "gamma"];
readOnly = true;
internal = true;
description = ''
Containers that are made available to the host system, and can freely be enabled using
the {option}`enabledContainers` option.
Do keep in mind that nspawn-containers not yet provide host isolation, and elevated privileges
inside the container can be used to escape the container and gain access to the host system.
Only enable containers that you know are properly sandboxed.
'';
};
enabledContainers = mkOption {
type = with types; listOf (enum cfg.availableContainers);
default = [];
example = literalExpression ''["alpha" "beta"]'';
description = ''
A list of enabled containers selected from the list of available containers.
Enabling a container may not always mean it will start automatically, and must
done so with care.
Container Specialization:
- alpha: Sandboxed playground for testing software, networking and builds.
- beta: Minimal container for running an ephemeral PostgreSQL database.
'';
};
};
}

View file

@ -0,0 +1,128 @@
{
config,
lib,
...
}: let
inherit (lib) optionals mkEnableOption mkOption types;
in {
imports = [
# configuration options for nixos activation scripts
./activation.nix
# boot/impermanence mounts
./boot.nix
./impermanence.nix
# network and overall hardening
./networking
./security.nix
./encryption.nix
# emulation and virtualization
./emulation.nix
./virtualization.nix
# package and program related options
./services
./programs
# systemd-nspawn containers
./containers.nix
];
config = {
warnings =
(optionals (config.modules.system.fs == []) [
''
You have not added any filesystems to be supported by your system. You may end up with an unbootable system!
Consider setting {option}`config.modules.system.fs` in your configuration
''
])
++ (optionals (config.modules.system.users == []) [
''
You have not added any users to be supported by your system. You may end up with an unbootable system!
Consider setting {option}`config.modules.system.users` in your configuration
''
]);
};
options.modules.system = {
mainUser = mkOption {
type = types.enum config.modules.system.users;
default = builtins.elemAt config.modules.system.users 0;
description = ''
The username of the main user for your system.
In case of a multiple systems, this will be the user with priority in ordered lists and enabled options.
'';
};
users = mkOption {
type = with types; listOf str;
default = ["notashelf"];
description = "A list of home-manager users on the system.";
};
autoLogin = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable passwordless login. This is generally useful on systems with
FDE (Full Disk Encryption) enabled. It is a security risk for systems without FDE.
'';
};
fs = mkOption {
type = with types; listOf str;
default = ["vfat" "ext4" "btrfs"]; # TODO: zfs, ntfs
description = ''
A list of filesystems available supported by the system
it will enable services based on what strings are found in the list.
It would be a good idea to keep vfat and ext4 so you can mount common external storage.
'';
};
yubikeySupport = {
enable = mkEnableOption "yubikey support";
deviceType = mkOption {
type = with types; nullOr (enum ["NFC5" "nano"]);
default = null;
description = "A list of device models to enable Yubikey support for";
};
};
sound = {
enable = mkEnableOption "sound related programs and audio-dependent programs";
};
video = {
enable = mkEnableOption "video drivers and programs that require a graphical user interface";
};
bluetooth = {
enable = mkEnableOption "bluetooth modules, drivers and configuration program(s)";
};
# should the device enable printing module and try to load common printer modules
# you might need to add more drivers to the printing module for your printer to work
printing = {
enable = mkEnableOption "printing";
extraDrivers = mkOption {
type = with types; listOf str;
default = [];
description = "A list of extra drivers to enable for printing";
};
"3d" = {
enable = mkEnableOption "3D printing suite";
extraPrograms = mkOption {
type = with types; listOf package;
default = [];
description = "A list of extra programs to enable for 3D printing";
};
};
};
};
}

View file

@ -0,0 +1,29 @@
{
pkgs,
lib,
...
}: let
inherit (lib) mkEnableOption mkOption types;
in {
options.modules.system.emulation = {
# should we enable emulation for additional architechtures?
# enabling this option will make it so that you can build for, e.g.
# aarch64 on x86_&4 and vice verse - not recommended on weaker machines
enable = mkEnableOption ''
emulation of additional arcitechtures via binfmt. Enabling this option will make it so that the system can build for
addiitonal systems such as aarc64 on x86_64 and vice versa.
'';
systems = mkOption {
type = with types; listOf str;
# default = ["x86_64-linux" "aarch64-linux" "i686-linux"];
default = builtins.filter (system: system != pkgs.system) ["aarch64-linux" "i686-linux"];
description = ''
Systems that will be emulated by the host system.
If overriding the default, you must make sure that the list of systems does not contain the same system as the host
in order to avoid an unbootable machine.
'';
};
};
}

View file

@ -0,0 +1,57 @@
{
config,
lib,
...
}: let
inherit (lib) mkEnableOption mkOption types mkIf;
in {
config = mkIf config.modules.system.encryption.enable {
warnings =
if config.modules.system.encryption.device == ""
then [
''
You have enabled LUKS encryption, but have not selected a device, you may not be able to decrypt your disk on boot.
''
]
else [];
};
options.modules.system.encryption = {
enable = mkEnableOption "LUKS encryption";
device = mkOption {
type = types.str; # this should actually be a list
default = "";
description = ''
The LUKS label for the device that will be decrypted on boot.
Currently does not support multiple devices at once.
'';
};
keyFile = mkOption {
type = with types; nullOr str;
default = null;
description = ''
The path to the keyfile that will be used to decrypt the device.
Needs to be an absolute path, and the file must exist. Set to `null`
to disable.
'';
};
keySize = mkOption {
type = types.int;
default = 4096;
description = ''
The size of the keyfile in bytes.
'';
};
fallbackToPassword = mkOption {
type = types.bool;
default = !config.boot.initrd.systemd.enable;
description = ''
Whether or not to fallback to password authentication if the keyfile
is not present.
'';
};
};
}

View file

@ -0,0 +1,87 @@
{
config,
lib,
...
}: let
inherit (lib) mkEnableOption mkOption literalExpression;
cfg = config.modules.system.impermanence;
in {
options.modules.system.impermanence = {
enable = mkOption {
default = cfg.root.enable || cfg.home.enable;
readOnly = true;
description = ''
Internal option for deciding if Impermanence module is enabled
based on the values of `modules.system.impermanence.root.enable`
and `modules.system.impermanence.home.enable`.
'';
};
root = {
enable = mkEnableOption ''
the Impermanence module for persisting important state directories.
By default, Impermanence will not touch user's $HOME, which is not
ephemeral unlike root.
'';
extraFiles = mkOption {
default = [];
example = literalExpression ''["/etc/nix/id_rsa"]'';
description = ''
Additional files in the root to link to persistent storage.
'';
};
extraDirectories = mkOption {
default = [];
example = literalExpression ''["/var/lib/libvirt"]'';
description = ''
Additional directories in the root to link to persistent
storage.
'';
};
};
home = {
enable = mkEnableOption ''
the Impermanence module for persisting important state directories.
This option will also make user's home ephemeral, on top of the root subvolume
'';
mountDotfiles = mkOption {
default = true;
description = ''
Whether the repository with my configuration flake should be bound to a location
in $HOME after a rebuild. It will symlink ''${self} to ~/.config/nyx where I
usually put my configuration files
'';
};
extraFiles = mkOption {
default = [];
example = literalExpression ''
[
".gnupg/pubring.kbx"
".gnupg/sshcontrol"
".gnupg/trustdb.gpg"
".gnupg/random_seed"
]
'';
description = ''
Additional files in the home directory to link to persistent
storage.
'';
};
extraDirectories = mkOption {
default = [];
example = literalExpression ''[".config/gsconnect"]'';
description = ''
Additional directories in the home directory to link to
persistent storage.
'';
};
};
};
}

View file

@ -0,0 +1,36 @@
{lib, ...}: let
inherit (lib) mkEnableOption mkOption types;
in {
imports = [
./nftables.nix
./tailscale.nix
];
options.modules.system.networking = {
nftables.enable = mkEnableOption "nftables firewall";
tarpit.enable = mkEnableOption "endlessh-go tarpit";
optimizeTcp = mkEnableOption "TCP optimizations";
wireless = {
allowImperative = mkEnableOption ''
imperative networking via wpa_cli.
Enabling this option will make it so that users in the wheel group will
be able to manage networking via wpa_cli.
'';
backend = mkOption {
type = types.enum ["iwd" "wpa_supplicant"];
default = "wpa_supplicant";
description = ''
Backend that will be used for wireless connections using either
`networking.wireless` or `networking.networkmanager.wifi.backend`
Defaults to wpa_supplicant until iwd is stable.
'';
};
};
# TODO: optionally use encrypted DNS
# encryptDns = mkOption {};
};
}

View file

@ -0,0 +1,82 @@
{lib, ...}: let
inherit (lib) mkTable mkPrerouteChain mkForwardChain mkOutputChain mkInputChain mkPostrouteChain mkIngressChain;
in {
options.networking.nftables.rules = {
# man nft(8)
netdev = mkTable "netdev address family netfilter table" {
filter.ingress = mkIngressChain "netdev";
};
bridge = mkTable "bridge address family netfilter table" {
filter = {
prerouting = mkPrerouteChain "bridge";
input = mkInputChain "bridge";
forward = mkForwardChain "bridge";
output = mkOutputChain "bridge";
postrouting = mkPostrouteChain "bridge";
};
};
inet = mkTable "internet (IPv4/IPv6) address family netfilter table" {
filter = {
prerouting = mkPrerouteChain "inet";
input = mkInputChain "inet";
forward = mkForwardChain "inet";
output = mkOutputChain "inet";
postrouting = mkPostrouteChain "inet";
};
nat = {
prerouting = mkPrerouteChain "inet";
input = mkInputChain "inet";
output = mkOutputChain "inet";
postrouting = mkPostrouteChain "inet";
};
};
arp = mkTable "ARP (IPv4) address family netfilter table" {
filter = {
input = mkInputChain "arp";
output = mkOutputChain "arp";
};
};
ip = mkTable "internet (IPv4) address family netfilter table" {
filter = {
prerouting = mkPrerouteChain "ip";
input = mkInputChain "ip";
forward = mkForwardChain "ip";
output = mkOutputChain "ip";
postrouting = mkPostrouteChain "ip";
};
nat = {
prerouting = mkPrerouteChain "ip";
input = mkInputChain "ip";
output = mkOutputChain "ip";
postrouting = mkPostrouteChain "ip";
};
route.output = mkForwardChain "ip";
};
ip6 = mkTable "internet (IPv6) address family netfilter table" {
filter = {
prerouting = mkPrerouteChain "ip6";
input = mkInputChain "ip6";
forward = mkForwardChain "ip6";
output = mkOutputChain "ip6";
postrouting = mkPostrouteChain "ip6";
};
nat = {
prerouting = mkPrerouteChain "ip6";
input = mkInputChain "ip6";
output = mkOutputChain "ip6";
postrouting = mkPostrouteChain "ip6";
};
route.output = mkForwardChain "ip6";
};
};
}

View file

@ -0,0 +1,76 @@
{
config,
lib,
...
}: let
inherit (lib) mkEnableOption mkOption types;
sys = config.modules.system;
cfg = sys.networking.tailscale;
in {
options.modules.system.networking.tailscale = {
enable = mkEnableOption "Tailscale VPN";
autoLogin = mkEnableOption ''
systemd-service for bootstrapping a Tailscale connection automatically
'';
endpoint = mkOption {
type = types.str;
default = "https://hs.notashelf.dev";
description = ''
The URL of the Tailscale control server to use. In case you
would like to use a self-hosted Headscale server, such as
the default value, you may change this value accordingly.
'';
};
operator = mkOption {
type = types.str;
default = sys.mainUser;
description = ''
The name of the Tailscale operator to use. This is used to
avoid using sudo in command-line operations and if set, will
run the auto-authentication service as the specified user.
'';
};
flags = {
default = mkOption {
type = with types; listOf str;
default = ["--ssh"];
description = ''
A list of command-line flags that will be passed to the Tailscale
daemon automatically when it is started, using
{option}`config.services.tailscale.extraUpFlags`
If `isServer` is set to true, the server-specific values will be
appended to the list defined in this option.
'';
};
};
isClient = mkOption {
type = types.bool;
default = cfg.enable;
example = true;
description = ''
Whether the target host should utilize Tailscale client features";
This option is mutually exlusive with {option}`tailscale.isServer`
as they both configure Taiscale, but with different flags
'';
};
isServer = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether the target host should utilize Tailscale server features.
This option is mutually exlusive with {option}`tailscale.isClient`
as they both configure Taiscale, but with different flags
'';
};
};
}

View file

@ -0,0 +1,94 @@
{lib, ...}: let
inherit (lib) mkEnableOption mkOption types;
in {
imports = [
./gaming.nix
];
options.modules.system.programs = {
gui.enable = mkEnableOption "GUI package sets" // {default = true;};
cli.enable = mkEnableOption "CLI package sets" // {default = true;};
dev.enable = mkEnableOption "development related package sets";
libreoffice.enable = mkEnableOption "LibreOffice suite";
discord.enable = mkEnableOption "Discord messenger";
element.enable = mkEnableOption "Element Matrix client";
obs.enable = mkEnableOption "OBS Studio";
spotify.enable = mkEnableOption "Spotify music player";
thunderbird.enable = mkEnableOption "Thunderbird mail client";
vscode.enable = mkEnableOption "Visual Studio Code";
steam.enable = mkEnableOption "Steam game client";
kdeconnect.enable = mkEnableOption "KDE Connect utility";
webcord.enable = mkEnableOption "Webcord Discord client";
zathura.enable = mkEnableOption "Zathura document viewer";
nextcloud.enable = mkEnableOption "Nextcloud sync client";
rnnoise.enable = mkEnableOption "RNNoise noise suppression plugin";
noisetorch.enable = mkEnableOption "NoiseTorch noise suppression plugin";
chromium = {
enable = mkEnableOption "Chromium browser";
ungoogle = mkOption {
type = types.bool;
default = true;
description = "Enable ungoogled-chromium features";
};
};
firefox = {
enable = mkEnableOption "Firefox browser";
schizofox.enable = mkOption {
type = types.bool;
default = true;
description = "Enable Schizofox Firefox Tweaks";
};
};
editors = {
neovim.enable = mkEnableOption "Neovim text editor";
helix.enable = mkEnableOption "Helix text editor";
};
terminals = {
kitty.enable = mkEnableOption "Kitty terminal emulator";
wezterm.enable = mkEnableOption "WezTerm terminal emulator";
foot.enable = mkEnableOption "Foot terminal emulator";
};
git = {
signingKey = mkOption {
type = types.str;
default = "";
description = "The default gpg key used for signing commits";
};
};
# default program options
default = {
# what program should be used as the default terminal
terminal = mkOption {
type = types.enum ["foot" "kitty" "wezterm"];
default = "kitty";
};
fileManager = mkOption {
type = types.enum ["thunar" "dolphin" "nemo"];
default = "dolphin";
};
browser = mkOption {
type = types.enum ["firefox" "librewolf" "chromium"];
default = "firefox";
};
editor = mkOption {
type = types.enum ["neovim" "helix" "emacs"];
default = "neovim";
};
launcher = mkOption {
type = types.enum ["rofi" "wofi" "anyrun"];
default = "rofi";
};
};
};
}

View file

@ -0,0 +1,24 @@
{
config,
lib,
...
}: let
inherit (lib.options) mkEnableOption;
inherit (config) modules;
prg = modules.system.programs;
in {
options.modules.system.programs.gaming = {
enable = mkEnableOption ''
packages, services and warappers required for the device to be gaming-ready.
Setting this option to true will also enable certain other options with
the option to disable them explicitly.
'';
steam.enable = mkEnableOption "Steam client" // {default = prg.gaming.enable;};
gamemode.enable = mkEnableOption "Feral-Interactive's Gamemode with userspace optimizations" // {default = prg.gaming.enable;};
gamescope.enable = mkEnableOption "Gamescope compositing manager" // {default = prg.gaming.enable;};
mangohud.enable = mkEnableOption "MangoHud overlay" // {default = prg.gaming.enable;};
};
}

View file

@ -0,0 +1,138 @@
{
pkgs,
lib,
...
}: let
inherit (lib) mkOption mkEnableOption types;
in {
options.modules.system.security = {
fixWebcam = mkEnableOption "the purposefully disabled webcam by un-blacklisting the related kernel module.";
fprint.enable = mkEnableOption "Fingerprint reader service";
tor.enable = mkEnableOption "Tor daemon";
usbguard.enable = mkEnableOption "USBGuard service for blocking unauthorized USB devices";
lockModules = mkEnableOption ''
kernel module locking to prevent kernel modules that are not specified in the config from being loaded
This is a highly breaking option, and will break many things including virtualization
and firewall if the required modules are not explicitly loaded in your kernel configuration.
'';
mitigations = {
disable = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to disable spectre and meltdown mitigations in the kernel. This is rather a sandbox
option than something you should consider on a production/mission critical system. Unless
you know what *exactly* you are doing, do not enable this.
'';
};
acceptRisk = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
You are either really stupid, or very knowledable. In either case,
this must be explicitly true in order to ensure users know what they are doing
when they disable security mitigations.
'';
};
};
selinux = {
enable = mkEnableOption "system SELinux support + kernel patches";
state = mkOption {
type = with types; enum ["enforcing" "permissive" "disabled"];
default = "enforcing";
description = ''
SELinux state to boot with. The default is enforcing.
'';
};
type = mkOption {
type = with types; enum ["targeted" "minimum" "mls"];
default = "targeted";
description = ''
SELinux policy type to boot with. The default is targeted.
'';
};
};
auditd = {
enable = mkEnableOption "the audit daemon.";
autoPrune = {
enable = mkEnableOption "auto-pruning of old audit logs.";
size = mkOption {
type = types.int;
default = 524288000; # roughly 500 megabytes
description = "The maximum size of the audit log in bytes. The default is 500MBs";
};
dates = mkOption {
type = types.str;
default = "daily";
example = "weekly";
description = "How often cleaning is triggered. Passed to systemd.time";
};
};
};
clamav = {
enable = mkEnableOption "ClamAV daemon.";
daemon = {
settings = mkOption {
type = with types; attrsOf (oneOf [bool int str (listOf str)]);
default = {
LogFile = "/var/log/clamd.log";
LogTime = true;
DetectPUA = true;
VirusEvent = lib.escapeShellArgs [
"${pkgs.libnotify}/bin/notify-send"
"--"
"ClamAV Virus Scan"
"Found virus: %v"
];
};
description = ''
ClamAV configuration. Refer to <https://linux.die.net/man/5/clamd.conf>,
for details on supported values.
'';
};
};
updater = {
enable = mkEnableOption "ClamAV freshclam updater";
frequency = mkOption {
type = types.int;
default = 12;
description = ''
Number of database checks per day.
'';
};
interval = mkOption {
type = types.str;
default = "hourly";
description = ''
How often freshclam is invoked. See systemd.time(7) for more
information about the format.
'';
};
settings = mkOption {
type = with types; attrsOf (oneOf [bool int str (listOf str)]);
default = {};
description = ''
freshclam configuration. Refer to <https://linux.die.net/man/5/freshclam.conf>,
for details on supported values.
'';
};
};
};
};
}

View file

@ -0,0 +1,21 @@
{lib, ...}: let
inherit (lib) mkModule;
in {
options.modules.system.services = {
# binary cache backends
bincache = {
harmonia = mkModule {
name = "Harmonia";
type = "binary cache";
host = "[::]";
port = 5000;
};
atticd = mkModule {
name = "Atticd";
type = "binary cache";
port = 8100;
};
};
};
}

View file

@ -0,0 +1,38 @@
{lib, ...}: let
inherit (lib) mkModule;
in {
options.modules.system.services = {
# database backends
database = {
mysql = mkModule {
name = "MySQL";
type = "database";
port = 3306;
};
mongodb = mkModule {
name = "MongoDB";
type = "database";
port = 27017;
};
redis = mkModule {
name = "Redis";
type = "database";
port = 6379;
};
postgresql = mkModule {
name = "PostgreSQL";
type = "database";
port = 5432;
};
garage = mkModule {
name = "Garage";
type = "S3 storage";
port = 5432;
};
};
};
}

View file

@ -0,0 +1,79 @@
{lib, ...}: let
inherit (lib) mkEnableOption mkModule;
in {
imports = [
./bincache.nix
./databases.nix
./monitoring.nix
./networking.nix
./social.nix
];
options.modules.system = {
services = {
mailserver.enable = mkEnableOption "nixos-mailserver service";
mkm.enable = mkEnableOption "mkm-ticketing service";
nextcloud = mkModule {
name = "Nextcloud";
type = "cloud storage";
};
nginx = mkModule {
name = "Nginx";
type = "webserver";
};
vaultwarden = mkModule {
name = "Vaultwarden";
type = "password manager";
port = 8222;
host = "127.0.0.1";
};
forgejo = mkModule {
name = "Forgejo";
type = "forge";
port = 7000;
};
quassel = mkModule {
name = "Quassel";
type = "IRC";
port = 4242;
};
jellyfin = mkModule {
name = "Jellyfin";
type = "media";
port = 8096;
};
searxng = mkModule {
name = "Searxng";
type = "meta search engine";
port = 8888;
};
miniflux = mkModule {
name = "Miniflux";
type = "RSS reader";
};
reposilite = mkModule {
name = "Reposilite";
port = 8084;
};
elasticsearch = mkModule {
name = "Elasticsearch";
port = 9200;
};
kanidm = mkModule {
name = "Kanidm";
port = 8443;
};
};
};
}

View file

@ -0,0 +1,26 @@
{
config,
lib,
...
}: let
inherit (lib) mkEnableOption;
sys = config.modules.system;
cfg = sys.services;
# mkEnableOption is the same as mkEnableOption but with the default value being equal to cfg.monitoring.enable
mkEnableOption' = desc: mkEnableOption "${desc}" // {default = cfg.monitoring.enable;};
in {
options.modules.system.services = {
# monitoring tools
# TODO: how do I mkModule those? they feature multiple host-specific parts
# that need to be adressed
monitoring = {
enable = mkEnableOption "system monitoring stack";
prometheus.enable = mkEnableOption' "Prometheus monitoring service";
grafana.enable = mkEnableOption' "Grafana monitoring service";
loki.enable = mkEnableOption' "Loki monitoring service";
uptime-kuma.enable = mkEnableOption' "Uptime Kuma monitoring service";
};
};
}

View file

@ -0,0 +1,25 @@
{lib, ...}: let
inherit (lib) mkEnableOption mkModule;
inherit (lib.types) str;
in {
options.modules.system.services = {
# networking
networking = {
wireguard.enable = mkEnableOption "Wireguard service";
headscale = mkModule {
name = "Headscale";
type = "networking";
port = 8085;
/*
extraOptions = {
domain = mkOption {
type = str;
example = "headscale.example.com";
description = "The domain name to use for headscale";
};
};
*/
};
};
};
}

View file

@ -0,0 +1,18 @@
{lib, ...}: let
inherit (lib) mkModule;
in {
options.modules.system.services = {
# self-hosted/decentralized social networks
social = {
mastodon = mkModule {
name = "Mastodon";
type = "social";
};
matrix = mkModule {
name = "Matrix";
type = "social";
port = 8008;
};
};
};
}

View file

@ -0,0 +1,13 @@
{lib, ...}: let
inherit (lib) mkEnableOption;
in {
options.modules.system.virtualization = {
enable = mkEnableOption "virtualization";
libvirt = {enable = mkEnableOption "libvirt";};
docker = {enable = mkEnableOption "docker";};
podman = {enable = mkEnableOption "podman";};
qemu = {enable = mkEnableOption "qemu";};
waydroid = {enable = mkEnableOption "waydroid";};
distrobox = {enable = mkEnableOption "distrobox";};
};
}

View file

@ -0,0 +1,98 @@
{
config,
lib,
...
}: let
inherit (lib.options) mkOption literalExpression;
inherit (lib.types) str nullOr enum mkOptionType attrsOf coercedTo;
inherit (lib.strings) removePrefix hasPrefix isString;
inherit (lib) serializeTheme;
cfg = config.modules.style;
hexColorType = mkOptionType {
name = "hex-color";
descriptionClass = "noun";
description = "RGB color in hex format";
check = x: isString x && !(hasPrefix "#" x);
};
colorType = attrsOf (coercedTo str (removePrefix "#") hexColorType);
getPaletteFromScheme = slug:
if builtins.pathExists ./palettes/${slug}.nix
then (import ./palettes/${slug}.nix).colorscheme.palette
else throw "The following colorscheme was imported but not found: ${slug}";
in {
options.modules.style = {
# choose a colorscheme
colorScheme = {
# "Name Of The Scheme"
name = mkOption {
type = nullOr (enum ["Catppuccin Mocha" "Tokyonight Storm" "Oxocarbon Dark"]);
description = "The colorscheme that should be used globally to theme your system.";
default = "Catppuccin Mocha";
};
# "name-of-the-scheme"
slug = mkOption {
type = str;
default = serializeTheme "${toString cfg.colorScheme.name}"; # toString to avoid type errors if null, returns ""
description = ''
The serialized slug for the colorScheme you are using.
Defaults to a lowercased version of the theme name with spaces
replaced with hyphens.
Must only be changed if the slug is expected to be different than
the serialized theme name."
'';
};
# this module option is taken from nix-colors by Misterio77
# and is adapted for my personal use. Main difference is that
# certain additional options (e.g. author or palette) have been
# removed as they are handled by the rest of the style module.
# <https://github.com/Misterio77/nix-colors/blob/main/module/colorscheme.nix>
colors = mkOption {
type = colorType;
default = getPaletteFromScheme cfg.colorScheme.slug;
description = ''
An attribute set containing active colors of the system. Follows base16
scheme by default but can be expanded to base24 or anything "above" as
seen fit as the module option is actually not checked in any way
'';
example = literalExpression ''
{
base00 = "#002635";
base01 = "#00384d";
base02 = "#517F8D";
base03 = "#6C8B91";
base04 = "#869696";
base05 = "#a1a19a";
base06 = "#e6e6dc";
base07 = "#fafaf8";
base08 = "#ff5a67";
base09 = "#f08e48";
base0A = "#ffcc1b";
base0B = "#7fc06e";
base0C = "#14747e";
base0D = "#5dd7b9";
base0E = "#9a70a4";
base0F = "#c43060";
}
'';
};
variant = mkOption {
type = enum ["dark" "light"];
default =
if builtins.substring 0 1 cfg.colorScheme.colors.base00 < "5"
then "dark"
else "light";
description = ''
Whether the scheme is dark or light
'';
};
};
};
}

View file

@ -0,0 +1,44 @@
{
pkgs,
lib,
...
}: let
inherit (lib) mkOption mkEnableOption types;
in {
imports = [
./gtk.nix
./qt.nix
./colors.nix
];
options.modules.style = {
forceGtk = mkEnableOption "Force GTK applications to use the GTK theme";
useKvantum = mkEnableOption "Use Kvantum to theme QT applications";
pointerCursor = {
package = mkOption {
type = types.package;
description = "The package providing the cursors";
default = pkgs.catppuccin-cursors.mochaDark;
};
name = mkOption {
type = types.str;
description = "The name of the cursor inside the package";
default = "Catppuccin-Mocha-Dark-Cursors";
};
size = mkOption {
type = types.int;
description = "The size of the cursor";
default = 24;
};
};
wallpapers = mkOption {
type = with types; either str (listOf str);
description = "Wallpaper or wallpapers to use";
default = [];
};
};
}

View file

@ -0,0 +1,70 @@
{
lib,
pkgs,
...
}: let
inherit (lib) mkOption mkEnableOption types;
in {
options = {
modules = {
style = {
# gtk specific options
gtk = {
enable = mkEnableOption "GTK theming optionss";
usePortal = mkEnableOption "native desktop portal use for filepickers";
theme = {
name = mkOption {
type = types.str;
default = "Catppuccin-Mocha-Standard-Blue-dark";
description = "The name for the GTK theme package";
};
package = mkOption {
type = types.package;
description = "The theme package to be used for GTK programs";
default = pkgs.catppuccin-gtk.override {
size = "standard";
accents = ["blue"];
variant = "mocha";
tweaks = ["normal"];
};
};
};
iconTheme = {
name = mkOption {
type = types.str;
description = "The name for the icon theme that will be used for GTK programs";
default = "Papirus-Dark";
};
package = mkOption {
type = types.package;
description = "The GTK icon theme to be used";
default = pkgs.catppuccin-papirus-folders.override {
accent = "blue";
flavor = "mocha";
};
};
};
font = {
name = mkOption {
type = types.str;
description = "The name of the font that will be used for GTK applications";
default = "Lexend";
};
size = mkOption {
type = types.int;
description = "The size of the font";
default = 14;
};
};
};
};
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "angel-light";
name = "Angel";
variant = "light";
palette = {
base00 = "#140e10";
base01 = "#8E7C86";
base02 = "#C47E81";
base03 = "#988791";
base04 = "#AB9196";
base05 = "#B39BA8";
base06 = "#CEA6A9";
base07 = "#e2d4d8";
base08 = "#9e9497";
base09 = "#8E7C86";
base0A = "#C47E81";
base0B = "#988791";
base0C = "#AB9196";
base0D = "#B39BA8";
base0E = "#CEA6A9";
base0F = "#e2d4d8";
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "black-metal";
name = "Black Metal";
variant = "dark";
palette = {
base00 = "#000000";
base01 = "#121212";
base02 = "#222222";
base03 = "#333333";
base04 = "#999999";
base05 = "#c1c1c1";
base06 = "#999999";
base07 = "#c1c1c1";
base08 = "#5f8787";
base09 = "#aaaaaa";
base0A = "#a06666";
base0B = "#dd9999";
base0C = "#aaaaaa";
base0D = "#888888";
base0E = "#999999";
base0F = "#444444";
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "carbon-dark";
name = "Carbon Dark";
variant = "dark";
valette = {
base00 = "#161616";
base01 = "#262626";
base02 = "#393939";
base03 = "#525252";
base04 = "#6F6F6F";
base05 = "#FAFAFA";
base06 = "#FAFAFA";
base07 = "#FFFFFF";
base08 = "#be95ff";
base09 = "#3ddbd9";
base0A = "#0043ce";
base0B = "#33b1ff";
base0C = "#ff7eb6";
base0D = "#42be65";
base0E = "#be95ff";
base0F = "#3ddbd9";
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "catppuccin-frappe";
name = "Catppuccin Frappe";
variant = "dark";
palette = {
base00 = "#303446"; # Base
base01 = "#292c3c"; # Mantle
base02 = "#414559"; # Surface0
base03 = "#51576d"; # Surface1
base04 = "#626880"; # Surface2
base05 = "#c6d0f5"; # Text
base06 = "#f2d5cf"; # Rosewater
base07 = "#babbf1"; # Lavender
base08 = "#e78284"; # Red
base09 = "#ef9f76"; # Peach
base0A = "#e5c890"; # Yellow
base0B = "#a6d189"; # Green
base0C = "#81c8be"; # Teal
base0D = "#8caaee"; # Blue
base0E = "#ca9ee6"; # Mauve
base0F = "#eebebe"; # Flamingo
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "catppuccin-mocha";
name = "Catppuccin Mocha";
variant = "dark";
palette = {
base00 = "#24273a"; # Base
base01 = "#1e2030"; # Mantle
base02 = "#363a4f"; # Surface0
base03 = "#494d64"; # Surface1
base04 = "#5b6078"; # Surface2
base05 = "#cad3f5"; # Text
base06 = "#f4dbd6"; # Rosewater
base07 = "#b7bdf8"; # Lavender
base08 = "#ed8796"; # Red
base09 = "#f5a97f"; # Peach
base0A = "#eed49f"; # Yellow
base0B = "#a6da95"; # Green
base0C = "#8bd5ca"; # Teal
base0D = "#8aadf4"; # Blue
base0E = "#c5a0f6"; # Mauve
base0F = "#f0c6c6"; # Flamingo
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "catppuccin-mocha";
name = "Catppuccin Mocha";
variant = "dark";
palette = {
base00 = "#1e1e2e"; # Base
base01 = "#181825"; # Mantle
base02 = "#313244"; # Surface0
base03 = "#45475a"; # Surface1
base04 = "#585b70"; # Surface2
base05 = "#cdd6f4"; # text
base06 = "#f5e0dc"; # rosewater
base07 = "#b4befe"; # lavender
base08 = "#f38ba8"; # red
base09 = "#fab387"; # peach
base0A = "#a6e3a1"; # yellow
base0B = "#94e2d5"; # green
base0C = "#94e2d5"; # teal
base0D = "#89b4fa"; # blue
base0E = "#cba6f7"; # mauve
base0F = "#f2cdcd"; # flamingo
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "decay-dark";
name = "Decay Dark";
variant = "dark";
palette = {
base00 = "#10101a"; # Base
base01 = "#12121c"; # Mantle
base02 = "#171721"; # Surface0
base03 = "#1c1c26"; # Surface1
base04 = "#2b2b35"; # Surface2
base05 = "#c3cddb"; # text
base06 = "#c3cddb"; # "
base07 = "#c8d2e0"; # white
base08 = "#c8d2e0"; # "
base09 = "#fa9a9a"; # red
base0A = "#f8e7b7"; # yellow
base0B = "#b0e2ae"; # green
base0C = "#93cff7"; # teal
base0D = "#8cbef7"; # blue
base0E = "#bfa6fa"; # magenta
base0F = "#fa9a9a"; # red again
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "default-dark";
name = "Default Dark";
variant = "dark";
palette = {
base00 = "#181818";
base01 = "#282828";
base02 = "#383838";
base03 = "#585858";
base04 = "#b8b8b8";
base05 = "#d8d8d8";
base06 = "#e8e8e8";
base07 = "#f8f8f8";
base08 = "#ab4642";
base09 = "#dc9656";
base0A = "#f7ca88";
base0B = "#a1b56c";
base0C = "#86c1b9";
base0D = "#7cafc2";
base0E = "#ba8baf";
base0F = "#a16946";
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "monochrome";
name = "monochrome";
variant = "dark";
palette = {
base00 = "#121517"; # Base
base01 = "#2e3338"; # Mantle
base02 = "#4a5159"; # Surface0
base03 = "#6c757d"; # Surface1
base04 = "#6c757d"; # Surface2
base05 = "#e9ecef"; # text
base06 = "#e9ecef"; # "
base07 = "#f8f9fa"; # white
base08 = "#f8f9fa"; # white
base09 = "#f8f9fa"; # white
base0A = "#f8f9fa"; # white
base0B = "#f8f9fa"; # white
base0C = "#f8f9fa"; # white
base0D = "#f8f9fa"; # white
base0E = "#f8f9fa"; # white
base0F = "#f8f9fa"; # white
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "noelle";
name = "noelle";
variant = "dark";
palette = {
base00 = "#111111"; # Base
base01 = "#282a2e"; # Mantle
base02 = "#373b41"; # Surface0
base03 = "#373b41"; # Surface1
base04 = "#626880"; # Surface2
base05 = "#eae7ee"; # Text
base06 = "#c5c8c6"; # Rosewater
base07 = "#c6c8c6"; # Lavender
base08 = "#922b3c"; # Red
base09 = "#a84757"; # Peach
base0A = "#bd8964"; # Yellow
base0B = "#a3ad64"; # Green
base0C = "#922b3c"; # Teal
base0D = "#a84757"; # Blue
base0E = "#9876a4"; # Magenta
base0F = "#ae93b7"; # Flamingo
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "oxocarbon-dark";
name = "Oxocarbon Dark";
variant = "dark";
palette = {
base00 = "#161616";
base01 = "#262626";
base02 = "#393939";
base03 = "#525252";
base04 = "#dde1e6";
base05 = "#f2f4f8";
base06 = "#ffffff";
base07 = "#08bdba";
base08 = "#3ddbd9";
base09 = "#78a9ff";
base0A = "#ee5396";
base0B = "#33b1ff";
base0C = "#ff7eb6";
base0D = "#42be65";
base0E = "#be95ff";
base0F = "#82cfff";
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "tokyo-night";
name = "Tokyo Night";
variant = "dark"; # bet
palette = {
base00 = "#24283b";
base01 = "#1f2335";
base02 = "#292e42";
base03 = "#565f89";
base04 = "#a9b1d6";
base05 = "#c0caf5";
base06 = "#c0caf5";
base07 = "#c0caf5";
base08 = "#c0caf5";
base09 = "#f7768e";
base0A = "#e0af68";
base0B = "#9ece6a";
base0C = "#1abc9c";
base0D = "#41a6b5";
base0E = "#bb9af7";
base0F = "#ff007c";
};
};
}

View file

@ -0,0 +1,25 @@
{
colorscheme = {
slug = "varda-theme";
name = "Varda Theme";
variant = "dark";
palette = {
base00 = "#0C0E11"; # Base
base01 = "#141619"; # Mantle
base02 = "#2E3436"; # Surface0
base03 = "#3b4444"; # Surface1
base04 = "#3b4444"; # Surface2
base05 = "#D0EBEE"; # text
base06 = "#D0EBEE"; # "
base07 = "#E5FFFF"; # white
base08 = "#E5FFFF"; # "
base09 = "#733447"; # red
base0A = "#C78C56"; # yellow
base0B = "#257B76"; # green
base0C = "#52677C"; # teal
base0D = "#52677C"; # blue
base0E = "#604575"; # magenta
base0F = "#733447"; # red again
};
};
}

View file

@ -0,0 +1,43 @@
{
lib,
pkgs,
config,
...
}: let
inherit (lib) mkOption types mkEnableOption;
cfg = config.modules.style;
in {
options = {
modules = {
style = {
qt = {
enable = mkEnableOption "QT Style Module";
theme = {
package = mkOption {
type = types.package;
default = pkgs.catppuccin-kde.override {
flavour = ["mocha"];
accents = ["blue"];
winDecStyles = ["modern"];
};
description = "The theme package to be used for QT programs";
};
name = mkOption {
type = types.str;
default = "Catppuccin-Mocha-Dark";
description = "The name for the QT theme package";
};
};
kdeglobals.source = mkOption {
type = types.path;
default = "${cfg.qt.theme.package}/share/color-schemes/CatppuccinMochaBlue.colors";
description = "The source file for the kdeglobals file. Usually provided by the qt theme package";
};
};
};
};
};
}

View file

@ -0,0 +1,58 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib.options) mkOption;
inherit (lib.types) ints bool enum package;
cfg = config.modules.usrEnv.brightness;
in {
options.modules.usrEnv.brightness = {
enable = mkOption {
type = bool;
default = false;
description = ''
Enable brightness management with systemd.
'';
};
package = mkOption {
type = package;
default = pkgs.writeShellApplication {
name = "set-system-brightness";
runtimeInputs = with pkgs; [brightnessctl];
text = "brightnessctl set ${cfg.value}";
};
};
value = mkOption {
type = ints.between 0 100;
default = 85; # try to save some battery on laptops
description = ''
The screen brightness that will be set once the graphical target is reached.
'';
};
service = {
type = mkOption {
type = enum ["oneshot" "simple"];
default = "oneshot";
description = ''
The type of the service to be used for setting brightness on graphical session start.
'';
};
target = mkOption {
type = enum ["graphical-session.target" "multi-user.target"];
default = "graphical-session.target";
description = ''
The target that the systemd-brightnessd service will be bound to.
This effectively sets the `after` attribute in the serviceConfig
'';
};
};
};
}

View file

@ -0,0 +1,9 @@
{
imports = [
./programs
./services
./brightness.nix
./desktop.nix
];
}

View file

@ -0,0 +1,85 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib) mkOption types;
cfg = config.modules.usrEnv;
sys = config.modules.system;
in {
options.modules.usrEnv = {
desktop = mkOption {
type = types.enum ["none" "Hyprland" "sway" "awesomewm" "i3"];
default = "none";
description = ''
The desktop environment to be used.
'';
};
desktops = {
hyprland.enable = mkOption {
type = types.bool;
default = cfg.desktop == "Hyprland";
description = ''
Whether to enable Hyprland wayland compositor.
Will be enabled automatically when `modules.usrEnv.desktop` is set to "Hyprland".
'';
};
sway.enable = mkOption {
type = types.bool;
default = cfg.desktop == "sway";
description = ''
Whether to enable Sway wayland compositor.
Will be enabled automatically when `modules.usrEnv.desktop` is set to "sway".
'';
};
awesomwm.enable = mkOption {
type = types.bool;
default = cfg.desktop == "awesomewm";
description = ''
Whether to enable Awesome window manager
Will be enabled automatically when `modules.usrEnv.desktop` is set to "awesomewm".
'';
};
i3.enable = mkOption {
type = types.bool;
default = cfg.desktop == "i3";
description = ''
Whether to enable i3 window manager
Will be enabled automatically when `modules.usrEnv.desktop` is set to "i3".
'';
};
};
useHomeManager = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable the usage of home-manager for user home management. Maps the list
of users to their home directories inside the `homes/` directory in the repository
root.
Username via `modules.system.mainUser` must be set if this option is enabled.
'';
};
};
config = {
assertions = [
{
assertion = cfg.useHomeManager -> sys.mainUser != null;
message = "modules.system.mainUser must be set while modules.usrEnv.useHomeManager is enabled";
}
];
};
}

View file

@ -0,0 +1,8 @@
{
imports = [
./gaming.nix
./launchers.nix
./lockers.nix
./media.nix
];
}

View file

@ -0,0 +1,19 @@
{
config,
lib,
...
}: let
inherit (lib.options) mkEnableOption;
inherit (config) modules;
sys = modules.system;
prg = sys.programs;
in {
options.modules.usrEnv.programs.gaming = {
enable = mkEnableOption "userspace gaming programs" // {default = prg.gaming.enable;};
emulation.enable = mkEnableOption "programs required to emulate other platforms" // {default = prg.gaming.enable;};
minecraft.enable = mkEnableOption "Minecraft launcher & JDKs" // {default = prg.gaming.enable;};
chess.enable = mkEnableOption "Chess programs and engines" // {default = prg.gaming.enable;};
mangohud.enable = mkEnableOption "MangoHud overlay" // {default = prg.gaming.enable;};
};
}

View file

@ -0,0 +1,9 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption;
in {
options.modules.usrEnv.programs.launchers = {
anyrun.enable = mkEnableOption "anyrun application launcher";
rofi.enable = mkEnableOption "rofi application launcher";
tofi.enable = mkEnableOption "tofi application launcher";
};
}

View file

@ -0,0 +1,27 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib.types) package;
inherit (lib.options) mkEnableOption mkOption;
cfg = config.modules.usrEnv.programs.screenlock;
pkg =
if cfg.gtklock.enable
then pkgs.gtklock
else pkgs.swaylock-effects;
in {
options.modules.usrEnv.programs.screenlock = {
gtklock.enable = mkEnableOption "gtklock screenlocker";
swaylock.enable = mkEnableOption "swaylock screenlocker";
package = mkOption {
type = package;
default = pkg;
readOnly = true;
description = "The screenlocker package";
};
};
}

View file

@ -0,0 +1,63 @@
{
inputs',
config,
pkgs,
lib,
...
}: let
inherit (lib) mkEnableOption mkOption types literalExpression;
in {
options.modules.usrEnv.programs.media = {
addDefaultPackages = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable the default list of media-related packages ranging from audio taggers
to video editors.
'';
};
extraPackages = mkOption {
type = with types; listOf package;
default = [];
description = ''
Additional packages that will be appended to media related packages.
'';
};
ncmpcpp.enable = mkEnableOption "ncmpcpp TUI music player";
beets.enable =
mkEnableOption ''
beets media library system.
Will be enabled automatically if {option}`config.modules.usrEnv.services.mpd.enabled`
is set to true
''
// {default = config.modules.usrEnv.services.media.mpd.enable;};
mpv = {
enable = mkEnableOption "mpv media player";
scripts = mkOption {
type = with types; listOf package;
description = "A list of MPV scripts that will be enabled";
example = literalExpression ''[ pkgs.mpvScripts.cutter ]'';
default = with pkgs.mpvScripts; [
# from nixpkgs
cutter # cut and automatically concat videos
mpris # MPRIS plugin
thumbnail # OSC seekbar thumbnails
thumbfast # on-the-fly thumbnailer
sponsorblock # skip sponsored segments
uosc # proximity UI
quality-menu # ytdl-format quality menu
seekTo # seek to spefici pos.
# from nyxpkgs
inputs'.nyxpkgs.packages.mpv-history # save a history of played files with timestamps
];
};
};
};
}

View file

@ -0,0 +1,5 @@
{
imports = [
./media.nix
];
}

View file

@ -0,0 +1,7 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption;
in {
options.modules.usrEnv.services.media = {
mpd.enable = mkEnableOption "mpd service";
};
}