Compare commits

...

26 Commits

Author SHA1 Message Date
4c1ccd22ff wip: attic
All checks were successful
build / build-sydpc (push) Successful in 33s
build / build-fruitbook (push) Successful in 30s
build / build-deertopia (push) Successful in 40s
2026-03-05 11:29:12 -07:00
70068bf0d9 feat(vaultwarden): init
All checks were successful
build / build-sydpc (push) Successful in 1m52s
build / build-fruitbook (push) Successful in 23s
build / build-deertopia (push) Successful in 49s
2026-03-03 21:42:02 -07:00
165806ba2c feat: build action
All checks were successful
build / build-sydpc (push) Successful in 51s
build / build-fruitbook (push) Successful in 47s
build / build-deertopia (push) Successful in 55s
2026-03-01 02:54:00 -07:00
76605c04b9 fix(gitea-actions-runner): add nix to path 2026-03-01 02:42:40 -07:00
e0506fc3e0 feat(gitea-actions-runner): init 2026-03-01 02:11:40 -07:00
93e801c332 chore(fcitx5): bump syd-fcitx5-tables 2026-02-20 12:23:30 -07:00
2b85764f11 chore(fruitbook): enable kdeconnect 2026-02-18 16:43:42 -07:00
f22ccc40a0 fix(lldap): warning 2026-02-18 16:43:42 -07:00
f1e239b13b fix(emacs): keep custom out of init.el 2026-02-18 16:43:42 -07:00
6c7c1f1b17 fix(emacs): keep bookmarks and transient out of vc 2026-02-18 16:43:02 -07:00
8c083dfc17 fix: typo io'm such a fat fucking chud god i know no words at all 2026-02-16 19:40:53 -07:00
aea4a3da97 fix(emacs): load lsp 2026-02-14 10:22:24 -07:00
f0ff7b5c51 feat(emacs): korean irregularity class template 2026-02-11 14:00:17 -07:00
ba794c28dd doc(gitea): cole*: i expect full credit somewhere
}:3 ♥
2026-02-08 22:00:38 -07:00
070bbe575b chore(gitea): gupHub now 2026-02-08 21:49:18 -07:00
e4fdd52d51 bring readme up to date 2026-02-08 21:46:41 -07:00
ca8f14118b feat(gitea): init 2026-02-08 21:45:30 -07:00
c790ebec29 feat(www,copyparty): vault msyds public 2026-02-08 19:05:38 -07:00
096dd77726 feat(copyparty,authelia): personal storage & webDAV 2026-02-08 17:46:27 -07:00
7b5a43954c feat(gc): init 2026-02-08 15:55:46 -07:00
77a2249a71 feat(msyds): enable qalc 2026-02-07 13:21:37 -07:00
e9ea2d48ad feat(emacs): more cider binds 2026-02-07 13:20:03 -07:00
3ca8359834 feat(kdeconnect): init 2026-02-07 13:19:35 -07:00
bd2964f894 feat(emacs): bind C-o in cider inspector 2026-02-02 16:34:01 -07:00
81aa3fb89f fix: persist terraria 2026-01-31 16:23:16 -07:00
785d78660f fix(emacs): no :ensure eshell 2026-01-30 14:13:54 -07:00
32 changed files with 554 additions and 93 deletions

View File

@@ -0,0 +1,29 @@
name: build
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
on: [push]
jobs:
build-sydpc:
runs-on: nixos
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: build sydpc
run: nix build -L .#nixosConfigurations.sydpc.config.system.build.toplevel
build-fruitbook:
runs-on: nixos
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: build fruitbook
run: nix build -L .#nixosConfigurations.fruitbook.config.system.build.toplevel
build-deertopia:
runs-on: nixos
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: build deertopia
run: nix build -L .#nixosConfigurations.deertopia.config.system.build.toplevel

View File

@@ -1,20 +1,4 @@
#+title: Sydnix
#+author: Madeleine Sydney Ślaga
Hello! These are my dotfiles for all my software and Nix machines. My TODO lists and READMEs tend to share a file, so I've moved it out of version-control. A link will be here soon enough.
* Overview
** Modules
Nix modules are Sydnix's primary mode of organisation. The modules in this repository are categorised by the scope of their applicability, be it user-specific, machine-specific, Sydnix-specific, or releasable. These sum of these categories resembles a hierarchy wherein modules become less generally-applicable as they build off one another. This all goes to say, in a very roundabout fashion, that we are using the [[https://www.nayuki.io/pe/designing-better-file-organization-around-tags-not-hierarchies][accursed]] hierarchical file-system as god intended:
#+begin_example
«TODO: Annotated diagram explaining the structore of modules/»
#+end_example
User modules may be configurations using a host-specific module, which itself may be a configuration of a Sydnix-specific module.
# Local Variables:
# jinx-local-words: "dotfiles"
# End:
these are my disgusting undocumented dotfiles. someday they'll be documented. maybe. }:)

18
flake.lock generated
View File

@@ -782,17 +782,17 @@
"nixpkgs": "nixpkgs_9"
},
"locked": {
"lastModified": 1762339715,
"narHash": "sha256-rzEJjyZat0juOF133YPSJMgOSeuBlk92PTOu22W1B6w=",
"owner": "msyds",
"repo": "syd-fcitx5-tables",
"rev": "2b66c43dcc524030a45ab6fdd5aab69c229dd290",
"type": "gitlab"
"lastModified": 1771615370,
"narHash": "sha256-UD/9fs1GYuwDGqrpKunrwOPrvkahLQ/6eeRy/0ejHNA=",
"ref": "refs/heads/main",
"rev": "41111bead687315ca1f55a826509234ca2f0e0ce",
"revCount": 8,
"type": "git",
"url": "https://git.deertopia.net/msyds/syd-fcitx5-tables"
},
"original": {
"owner": "msyds",
"repo": "syd-fcitx5-tables",
"type": "gitlab"
"type": "git",
"url": "https://git.deertopia.net/msyds/syd-fcitx5-tables"
}
},
"sydpkgs": {

View File

@@ -27,7 +27,8 @@
inputs.nixpkgs.follows = "nixpkgs";
};
tf2-nix.url = "gitlab:msyds/tf2-nix";
syd-fcitx5-tables.url = "gitlab:msyds/syd-fcitx5-tables";
syd-fcitx5-tables.url =
"git+https://git.deertopia.net/msyds/syd-fcitx5-tables";
sydpkgs.url = "github:msyds/sydpkgs";
};

View File

@@ -10,6 +10,7 @@
filesystemType = "btrfs";
stylix.enable = true;
gc.enable = true;
openssh.enable = true;
sydpkgs.overlay.enable = true;
@@ -48,6 +49,8 @@
deertopia = {
authelia.enable = true;
atticd.enable = true;
gitea.enable = true;
quiver.enable = true;
www.enable = true;
bepasty.enable = true;
@@ -64,6 +67,7 @@
# umurmur.enable = true;
murmur.enable = true;
anki-sync-server.enable = true;
vaultwarden.enable = true;
servarr = {
enable = true;
prowlarr.enable = true;

View File

@@ -17,6 +17,7 @@
openssh.enable = true;
sydpkgs.overlay.enable = true;
dank-material-shell.enable = true;
kdeconnect.enable = true;
users.users = [
"crumb"

View File

@@ -25,14 +25,24 @@
openssh.enable = true;
sydpkgs.overlay.enable = true;
dank-material-shell.enable = true;
kdeconnect.enable = true;
gitea-actions-runner.enable = true;
sops = {
enable = true;
keyFile = "/persist/private-keys/age/deertopia";
};
steam = {
enable = true;
impermanenceUsers = ["crumb" "msyds"];
impermanenceUsers = [
# "crumb"
"msyds"
];
};
users.users = [
"crumb"
# "crumb"
"msyds"
];

View File

@@ -0,0 +1,20 @@
{ config, lib, pkgs, osConfig, ... }:
let cfg = config.sydnix.kdeconnect;
in {
options.sydnix.kdeconnect = {
enable = lib.mkEnableOption "KDE Connect";
};
config = lib.mkIf cfg.enable {
services.kdeconnect = {
enable = true;
indicator = true;
};
warnings = lib.optional (!osConfig.sydnix.kdeconnect.openFirewall) ''
The KDE Connect ports were not opened in the NixOS config. Make
sure someone's allowing these ports!!!
'';
};
}

14
modules/home/terraria.nix Normal file
View File

@@ -0,0 +1,14 @@
{ config, lib, pkgs, ... }:
let cfg = config.sydnix.terraria;
in {
options.sydnix.terraria = {
enable = lib.mkEnableOption "Terraria";
};
config = lib.mkIf cfg.enable {
sydnix.impermanence.directories = [
".local/share/Terraria"
];
};
}

View File

@@ -71,9 +71,11 @@ the unwritable tidbits."
(setq-local register-alist
(cl-remove-if-not #'savehist-printable register-alist)))))
(with-eval-after-load 'bookmark
;; Stay out of my config dir!
(setq bookmark-default-file (file-name-concat syd-data-dir "bookmarks")))
;; Stay out of my config dir!
(setq bookmark-default-file
(file-name-concat syd-data-dir "bookmarks")
transient-history-file
(file-name-concat syd-data-dir "transient/history.el"))
(provide 'syd-autosave)

View File

@@ -62,4 +62,6 @@
syd/agda
syd/eshell
syd/treesit
syd/grammatical-framework))
syd/grammatical-framework
syd/lsp
syd/custom))

View File

@@ -44,13 +44,11 @@
;; functionality.
(cider-download-java-sources t))
:general
;; DEPRECATED: Remove once a `map!' equivalent is implemented.
(:keymaps 'cider-repl-mode-map
:states '(normal insert)
"C-k" #'cider-repl-backward-input
"C-j" #'cider-repl-forward-input
"C-s" #'consult-history)
;; DEPRECATED: Remove once a `map!' equivalent is implemented.
(:keymaps '(cider-repl-mode-map clojure-mode-map)
:states '(normal visual motion emacs insert)
:major-modes t
@@ -74,10 +72,15 @@
"T n" #'cider-test-run-ns-tests
"T r" #'cider-test-rerun-failed-tests
"T R" #'cider-test-rerun-test
"x" #'cider-scratch)
"x" #'cider-scratch
"i" #'cider-inspect-last-result)
(:keymaps 'cider-repl-mode-map
:states 'insert
"S-<return>" #'cider-repl-newline-and-indent)
(:keymaps 'cider-inspector-mode-map
:states '(motion insert)
"C-o" #'cider-inspector-pop
"C-i" #'cider-inspector-push)
:config
(add-hook 'cider-mode-hook #'eldoc-mode)
(with-eval-after-load 'consult

View File

@@ -0,0 +1,8 @@
;;; -*- lexical-binding: t -*-
(require 'syd/base)
;; Stay out of version-control!!!!!
(setq custom-file (file-name-concat syd-data-dir "custom.el"))
(provide 'syd/custom)

View File

@@ -127,7 +127,6 @@ if FILE-NAME has no TRAMP prefix."
(cons nil file-name)))
(use-package eshell
:ensure nil
:defer t
:init
(defvar syd-eshell-data-dir

View File

@@ -77,7 +77,10 @@
:target (file ,default-target-file-name))
("K" "Today's Korean" plain
(file ,(syd-emacs-file "lisp/syd/org/roam/todays-korean.org"))
:target (file "todays-korean/%<%Y-%m-%d>.org"))))))
:target (file "todays-korean/%<%Y-%m-%d>.org"))
("I" "Korean irregularity class" plain
(file ,(syd-emacs-file "lisp/syd/org/roam/irregularity-class.org"))
:target (file ,default-target-file-name))))))
:config
(add-to-list 'org-agenda-files org-roam-directory)
(with-eval-after-load 'org-roam-dailies

View File

@@ -0,0 +1,12 @@
:PROPERTIES:
:ROAM_ALIASES: "%^{Irregular ending: } 불규칙"
:END:
#+title: %\1-irregularity
In [[id:e4ae4140-b842-4f16-b4da-9306eb3c2c1a][Korean morphology]], a *%\1-irregular verb* (ko: *%\1 불규칙 동사*) is a type of [[id:764f5ddf-472a-4142-9f76-cfb19f462be4][irregular verb]] whose stem ends in %\1.
* Inflection
* Examples
** Non-examples

View File

@@ -0,0 +1,40 @@
{ config, lib, pkgs, ... }:
let cfg = config.sydnix.deertopia.atticd;
in {
options.sydnix.deertopia.atticd = {
enable = lib.mkEnableOption "Atticd";
port = lib.mkOption {
default = 8012;
type = lib.types.port;
};
};
# sudo atticd-atticadm make-token --sub msyds --validity '1 year' --pull 'msyds-*' --push 'msyds-*' --create-cache 'msyds-*' --configure-cache 'msyds-*'
config = lib.mkIf cfg.enable {
sydnix.sops.secrets.atticd-environment-file = {
# owner = config.services.atticd.user;
# group = config.services.atticd.group;
};
services.atticd = {
enable = true;
environmentFile =
config.sops.secrets.atticd-environment-file.path;
settings = {
api-endpoint = "https://attic.deertopia.net/";
listen = "[::]:${toString cfg.port}";
garbage-collection = {
default-retention-period = "3 months";
};
};
};
sydnix.deertopia.nginx.vhosts."attic".vhost = {
forceSSL = true;
enableACME = true;
locations."/".proxyPass =
"http://127.0.0.1:${toString cfg.port}";
};
};
}

View File

@@ -65,9 +65,22 @@ in {
server = {
address = "tcp://:${builtins.toString cfg.httpPort}";
# asset_path = "${authelia-state-dir}/assets";
endpoints.authz = {
# Necessary for Nginx integration. No, I do not understand what it
# does.
endpoints.authz.auth-request.implementation = "AuthRequest";
auth-request = {
implementation = "AuthRequest";
authn_strategies = [
{
name = "HeaderAuthorization";
schemes = [ "Basic" ];
}
{
name = "CookieSession";
}
];
};
};
};
authentication_backend =
let base-dn = config.services.lldap.settings.ldap_base_dn;

View File

@@ -13,8 +13,13 @@ in {
};
};
imports = [ ./copyparty/vault.nix ];
config = lib.mkIf cfg.enable {
sydnix.deertopia.copyparty.vault.enable = true;
sydnix.impermanence.directories = [
"/var/lib/copyparty"
];
nixpkgs.overlays = [ inputs.copyparty.overlays.default ];

View File

@@ -0,0 +1,46 @@
{ config, lib, pkgs, ... }:
let cfg = config.sydnix.deertopia.copyparty.vault;
in {
options.sydnix.deertopia.copyparty.vault = {
enable = lib.mkEnableOption "personal storage under Copyparty";
};
config = lib.mkIf cfg.enable {
sydnix.impermanence.directories = [ "/vault" ];
# HACK: Ad-hoc permissions, as typical.
users.groups.vault = {};
users.users.copyparty.extraGroups = [ "vault" ];
systemd.tmpfiles.settings."50-vault" =
let e = {
z.group = "vault";
z.mode = "2775";
v.group = "vault";
v.mode = "2775";
};
in {
"/vault" = e;
"/vault/~msyds" = e;
};
services.copyparty.volumes = {
"/~msyds" = {
path = "/vault/~msyds";
access.A = [ "msyds" ];
};
"/~msyds/zotero" = {
path = "/vault/~msyds/zotero";
flags.daw = true;
access.A = [ "msyds" ];
access.rwmd = [ "zotero" ];
};
"/~msyds/public" = {
path = "/vault/~msyds/public";
access.A = [ "msyds" ];
access.r = [ "*" ];
};
};
};
}

View File

@@ -0,0 +1,60 @@
{ config, lib, pkgs, ... }:
let cfg = config.sydnix.deertopia.gitea;
in {
options.sydnix.deertopia.gitea = {
enable = lib.mkEnableOption "Gitea";
};
config = lib.mkIf cfg.enable {
sydnix.impermanence.directories = [
{
directory = config.services.gitea.stateDir;
inherit (config.services.gitea) user group;
}
];
sydnix.deertopia.nginx.vhosts."git" = {
directory = null;
vhost = {
forceSSL = true;
enableACME = true;
locations."/".extraConfig =
let port = builtins.toString config.services.gitea
.settings.server.HTTP_PORT;
in ''
proxy_pass http://127.0.0.1:${port}/;
'';
};
};
users.users.git = {
description = "Gitea Service";
home = config.services.gitea.stateDir;
useDefaultShell = true;
group = config.services.gitea.group;
isSystemUser = true;
};
users.groups.git = { };
# sudo -u git gitea admin auth add-ldap --name gitea --port 3890 --bind-dn 'uid=gitea,ou=people,dc=deertopia,dc=net' --bind-password «password» --user-search-base 'ou=people,dc=deertopia,dc=net' --user-filter '(&(memberof=cn=git,ou=groups,dc=deertopia,dc=net)(|(uid=%[1]s)(mail=%[1]s)))' --username-attribute uid --firstname-attribute givenName --surname-attribute sn --email-attribute mail --avatar-attribute jpegPhoto --security-protocol unencrypted --host 127.0.0.1 --config /var/lib/gitea/custom/conf/app.ini --synchronize-users
services.gitea = {
enable = true;
user = "git";
group = "git";
appName = "GupHub"; # Name per my darling Colestar ♥
settings = {
server = {
ROOT_URL = "https://git.deertopia.net/";
HTTP_PORT = 3000;
DOMAIN = "deertopia.net";
};
service = {
DISABLE_REGISTRATION = true;
};
};
};
};
}

View File

@@ -62,6 +62,7 @@ in {
ldap_base_dn = cfg.baseDN;
ldap_user_dn = "lain";
ldap_user_email = "lain@deertopia.net";
force_ldap_user_pass_reset = "always";
ldaps_options = {
enabled = true;
port = 6360;

View File

@@ -0,0 +1,45 @@
{ config, lib, pkgs, ... }:
let cfg = config.sydnix.deertopia.vaultwarden;
in {
options.sydnix.deertopia.vaultwarden = {
enable = lib.mkEnableOption "Vaultwarden";
};
config = lib.mkIf cfg.enable {
services.vaultwarden = {
enable = true;
config = {
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8222;
DOMAIN = "https://vault.deertopia.net";
};
};
sydnix.impermanence.directories = [
"/var/backup/vaultwarden"
];
services.nginx.upstreams.vaultwarden.servers =
let port = toString config.services.vaultwarden.config.ROCKET_PORT;
in {
"127.0.0.1:${port}" = { };
};
sydnix.deertopia.nginx.vhosts."vault".vhost = {
forceSSL = true;
enableACME = true;
locations = {
"/".proxyPass = "http://vaultwarden";
"= /notifications/anonymous-hub" = {
proxyPass = "http://vaultwarden";
proxyWebsockets = true;
};
"= /notifications/hub" = {
proxyPass = "http://vaultwarden";
proxyWebsockets = true;
};
};
};
};
}

View File

@@ -29,6 +29,8 @@ in {
};
};
imports = [ ./copyparty/vault.nix ];
config = mkIf cfg.enable {
users.users.${cfg.user} = {
isSystemUser = true;

View File

@@ -34,6 +34,7 @@ in {
extraConfig = ''
location /~msyds/ {
index index.html;
alias /vault/~msyds/public/;
}
location /~liv/ {
index index.html;

16
modules/nixos/gc.nix Normal file
View File

@@ -0,0 +1,16 @@
{ config, lib, pkgs, ... }:
let cfg = config.sydnix.gc;
in {
options.sydnix.gc = {
enable = lib.mkEnableOption "the automatic Nix garbage collector";
};
config = lib.mkIf cfg.enable {
nix.gc = {
automatic = true;
randomizedDelaySec = "14m";
options = "--delete-older-than 30d";
};
};
}

View File

@@ -0,0 +1,103 @@
# Stolen from https://git.neet.dev/zuckerberg/nix-config/src/branch/master/common/server/gitea-actions-runner.nix
{ config, lib, pkgs, ... }:
let
cfg = config.sydnix.gitea-actions-runner;
container-name = "gitea-actions-runner";
gitea-actions-runner-uid = 991;
gitea-actions-runner-gid = 989;
token-file = config.sops.secrets.gitea-actions-runner-token.path;
in {
options.sydnix.gitea-actions-runner = {
enable = lib.mkEnableOption "Gitea actions runner";
};
config = lib.mkIf cfg.enable {
sydnix.sops.secrets.gitea-actions-runner-token = {};
sydnix.impermanence.directories = [ "/var/lib/gitea-actions-runner" ];
containers.${container-name} = {
autoStart = true;
ephemeral = true;
bindMounts = {
${token-file} = {
hostPath = token-file;
isReadOnly = true;
};
"/var/lib/gitea-actions-runner" = {
hostPath = "/var/lib/gitea-actions-runner";
isReadOnly = false;
};
};
config = { config, lib, pkgs, ... }: {
system.stateVersion = "25.11";
services.gitea-actions-runner.instances.sydpc = {
enable = true;
name = "sydpc";
url = "https://git.deertopia.net/";
tokenFile = token-file;
labels = [ "nixos:host" ];
hostPackages = with pkgs; [
bash
coreutils
curl
gawk
gitMinimal
gnused
nodejs
wget
nix
];
};
# Disable dynamic user so runner state persists via bind mount
assertions = [{
assertion = config.systemd.services.gitea-actions-runner-sydpc.enable;
message = ''
Expected systemd service 'gitea-actions-runner-sydpc' is not
enabled the gitea-actions-runner module may have changed
its naming scheme.
'';
}];
systemd.services.gitea-actions-runner-sydpc.serviceConfig.DynamicUser
= lib.mkForce false;
users.users.gitea-actions-runner = {
uid = gitea-actions-runner-uid;
home = "/var/lib/gitea-actions-runner";
group = "gitea-actions-runner";
isSystemUser = true;
createHome = true;
};
users.groups.gitea-actions-runner.gid = gitea-actions-runner-gid;
nix.settings.experimental-features = [ "nix-command" "flakes" ];
environment.systemPackages = with pkgs; [
git
nodejs
jq
attic-client
];
};
};
# Needs to be outside of the container because container uses's
# the host's nix-daemon
nix.settings.trusted-users = [ "gitea-actions-runner" ];
# Matching user on host — the container's gitea-actions-runner UID must be
# recognized by the host's nix-daemon as trusted (shared UID namespace)
users.users.gitea-actions-runner = {
uid = gitea-actions-runner-uid;
home = "/var/lib/gitea-actions-runner";
group = "gitea-actions-runner";
isSystemUser = true;
createHome = true;
};
users.groups.gitea-actions-runner.gid = gitea-actions-runner-gid;
};
}

View File

@@ -70,6 +70,10 @@ in {
};
# O_O what the fuck did i write this for.... CONCERNING.
#
# oh because of these types of errors:
# Directory "/var/lib/private" already exists, but has mode 0755
# that is too permissive (0700 was requested), refusing.
systemd.tmpfiles.settings."10-varlibprivate" = {
"/var/lib/private" = {
z.group = "root";
@@ -78,6 +82,13 @@ in {
};
};
# Workaround for https://github.com/nix-community/impermanence/issues/254.
systemd.services."systemd-tmpfiles-resetup" = {
serviceConfig = {
RemainAfterExit = lib.mkForce false;
};
};
# Permit members of `cfg.persistGroupName` to read, write, and execute
# /persist.
systemd.tmpfiles.settings."10-persist" = {

View File

@@ -29,7 +29,7 @@ in {
mkdir -p /btrfs-tmp
mount -t btrfs "${cfg.device}" /btrfs-tmp
# If the moribound subvolume exists, send it do 'death row' (old-roots),
# If the moribund subvolume exists, send it do 'death row' (old-roots),
# where live for about three days before its eventual deletion.
if [[ -e "/btrfs-tmp/${cfg.subvolume}" ]]; then
mkdir -p /btrfs-tmp/old-roots

View File

@@ -0,0 +1,21 @@
{ config, lib, pkgs, ... }:
let cfg = config.sydnix.kdeconnect;
in {
options.sydnix.kdeconnect = {
enable = lib.mkEnableOption "KDE Connect";
openFirewall = lib.mkOption {
description = ''Open required ports for KDE Connect'';
type = lib.types.bool;
default = true;
};
};
config = lib.mkIf cfg.enable
(let
port-range = lib.optional cfg.openFirewall { from = 1714; to = 1764; };
in {
networking.firewall.allowedTCPPortRanges = port-range;
networking.firewall.allowedUDPPortRanges = port-range;
});
}

File diff suppressed because one or more lines are too long

View File

@@ -37,6 +37,9 @@
desktop-environment.enable = true;
clojure.enable = true;
capitaine-cursors.enable = true;
terraria.enable = true;
kdeconnect.enable = true;
qalculate.enable = true;
sops = {
enable = true;
keyFile = "/persist/private-keys/age/crumb";