treewide: move nixos modules
This commit is contained in:
parent
d84be7c616
commit
8eff4c5e4f
73 changed files with 62 additions and 62 deletions
19
modules/nixos/base/bluetooth/default.nix
Normal file
19
modules/nixos/base/bluetooth/default.nix
Normal file
|
@ -0,0 +1,19 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.base.bluetooth.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.base.bluetooth.enable {
|
||||
chvp.base.zfs.systemLinks = [{ path = "/var/lib/bluetooth"; type = "cache"; }];
|
||||
|
||||
hardware.bluetooth.enable = true;
|
||||
services.blueman.enable = true;
|
||||
|
||||
home-manager.users.charlotte = lib.mkIf config.chvp.graphical.enable ({ ... }: {
|
||||
services.blueman-applet.enable = true;
|
||||
});
|
||||
};
|
||||
}
|
134
modules/nixos/base/default.nix
Normal file
134
modules/nixos/base/default.nix
Normal file
|
@ -0,0 +1,134 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./bluetooth
|
||||
./emacs
|
||||
./mail
|
||||
./network
|
||||
./nix
|
||||
./phone-push
|
||||
./smartd
|
||||
./ssh
|
||||
./sshd
|
||||
./telegraf
|
||||
./tmux
|
||||
./zfs
|
||||
./zsh
|
||||
];
|
||||
|
||||
options.chvp = {
|
||||
stateVersion = lib.mkOption {
|
||||
example = "20.09";
|
||||
};
|
||||
|
||||
dataPrefix = lib.mkOption {
|
||||
default = "";
|
||||
example = "/data";
|
||||
};
|
||||
|
||||
cachePrefix = lib.mkOption {
|
||||
default = "";
|
||||
example = "/cache";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
home-manager.useGlobalPkgs = true;
|
||||
|
||||
system = {
|
||||
stateVersion = config.chvp.stateVersion;
|
||||
autoUpgrade = {
|
||||
enable = true;
|
||||
flake = "gitlab:chvp/nixos-config?host=git.chvp.be";
|
||||
dates = "01/4:00";
|
||||
randomizedDelaySec = "10min";
|
||||
};
|
||||
};
|
||||
home-manager.users = {
|
||||
charlotte = { ... }: {
|
||||
home.stateVersion = config.chvp.stateVersion;
|
||||
systemd.user.sessionVariables = config.home-manager.users.charlotte.home.sessionVariables;
|
||||
};
|
||||
root = { ... }: {
|
||||
home.stateVersion = config.chvp.stateVersion;
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [ git htop moreutils ncdu ripgrep unzip zip ];
|
||||
|
||||
boot.kernelParams = [ "mitigations=off" ];
|
||||
|
||||
console = {
|
||||
colors = [
|
||||
"51576d"
|
||||
"e78284"
|
||||
"a6d189"
|
||||
"e5c890"
|
||||
"8caaee"
|
||||
"f4b8e4"
|
||||
"81c8be"
|
||||
"b5bfe2"
|
||||
"626880"
|
||||
"e78284"
|
||||
"a6d189"
|
||||
"e5c890"
|
||||
"8caaee"
|
||||
"f4b8e4"
|
||||
"81c8be"
|
||||
"a5adce"
|
||||
];
|
||||
earlySetup = true;
|
||||
font = "Lat2-Terminus16";
|
||||
keyMap = "us";
|
||||
};
|
||||
|
||||
i18n = {
|
||||
defaultLocale = "en_IE.UTF-8";
|
||||
extraLocaleSettings = {
|
||||
LC_TIME = "en_GB.UTF-8";
|
||||
};
|
||||
supportedLocales = [
|
||||
"en_GB.UTF-8/UTF-8"
|
||||
"en_IE.UTF-8/UTF-8"
|
||||
"en_US.UTF-8/UTF-8"
|
||||
];
|
||||
};
|
||||
|
||||
security = {
|
||||
sudo.enable = false;
|
||||
doas = {
|
||||
enable = true;
|
||||
extraRules = [
|
||||
{
|
||||
users = [ "charlotte" ];
|
||||
noPass = true;
|
||||
cmd = "nix-collect-garbage";
|
||||
runAs = "root";
|
||||
}
|
||||
];
|
||||
};
|
||||
polkit.enable = true;
|
||||
};
|
||||
|
||||
services.fwupd.enable = true;
|
||||
|
||||
users = {
|
||||
mutableUsers = false;
|
||||
defaultUserShell = pkgs.zsh;
|
||||
users = {
|
||||
charlotte = {
|
||||
isNormalUser = true;
|
||||
home = "/home/charlotte";
|
||||
description = "Charlotte Van Petegem";
|
||||
extraGroups = [ "systemd-journal" ];
|
||||
hashedPasswordFile = config.age.secrets."passwords/users/charlotte".path;
|
||||
};
|
||||
root.hashedPasswordFile = config.age.secrets."passwords/users/root".path;
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."passwords/users/charlotte".file = ../../../secrets/passwords/users/charlotte.age;
|
||||
age.secrets."passwords/users/root".file = ../../../secrets/passwords/users/root.age;
|
||||
};
|
||||
}
|
349
modules/nixos/base/emacs/base-init.el
Normal file
349
modules/nixos/base/emacs/base-init.el
Normal file
|
@ -0,0 +1,349 @@
|
|||
;;; init --- My emacs init file
|
||||
;;; Commentary:
|
||||
;;; Code:
|
||||
(eval-when-compile
|
||||
(require 'use-package)
|
||||
(require 'use-package-ensure)
|
||||
(setq use-package-verbose nil)
|
||||
(setq use-package-always-ensure t))
|
||||
|
||||
;; Dependencies that inject `:keywords' into `use-package' should be
|
||||
;; included before all other packages.
|
||||
;; For :diminish in (use-package). Hides minor modes from the status line.
|
||||
(use-package diminish)
|
||||
;; For :general in (use-package). Keybinding management framework.
|
||||
(use-package general
|
||||
:after evil
|
||||
:config
|
||||
(general-evil-setup t)
|
||||
|
||||
(defun chvp--kill-current-buffer ()
|
||||
(interactive)
|
||||
(kill-buffer (current-buffer))
|
||||
)
|
||||
|
||||
;; Create bindings under the leader
|
||||
(general-create-definer lmap
|
||||
:states '(normal visual insert emacs motion)
|
||||
:prefix "SPC"
|
||||
:global-prefix "C-SPC"
|
||||
)
|
||||
|
||||
(nmap "<escape>" 'save-buffer)
|
||||
(lmap
|
||||
"" nil ;; Unbind SPC, I don't use it for navigation anyway.
|
||||
|
||||
"SPC" '(:ignore t :which-key "mode")
|
||||
|
||||
":" '(eval-expression :which-key "eval")
|
||||
|
||||
"b" '(:ignore t :which-key "buffer")
|
||||
"bd" '(chvp--kill-current-buffer :which-key "kill")
|
||||
"br" '(rename-buffer :which-key "rename")
|
||||
|
||||
"f" '(:ignore t :which-key "file")
|
||||
"ff" '(find-file :which-key "find")
|
||||
"fs" '(save-buffer :which-key "save")
|
||||
|
||||
"h" '(:ignore t :which-key "help")
|
||||
"hb" '(describe-bindings :which-key "bindings")
|
||||
"hf" '(describe-function :which-key "function")
|
||||
"hv" '(describe-variable :which-key "variable")
|
||||
|
||||
"q" '(:ignore t :which-key "quit")
|
||||
"qq" '(delete-frame :which-key "quit")
|
||||
|
||||
"s" '(:ignore t :which-key "search")
|
||||
|
||||
"w" '(:ignore t :which-key "window")
|
||||
"wv" '(split-window-vertically :which-key "split vertical")
|
||||
"ws" '(split-window-horizontally :which-key "split horizontal")
|
||||
"wd" '(delete-window :which-key "delete")
|
||||
"w-" '(text-scale-decrease :which-key "decrease font size")
|
||||
"w+" '(text-scale-increase :which-key "increase font size")
|
||||
|
||||
"x" '(execute-extended-command :which-key "exec")
|
||||
)
|
||||
)
|
||||
|
||||
;; Vim keybindings
|
||||
(use-package evil
|
||||
:custom
|
||||
(evil-want-keybinding nil "Disable default evil keybindings, since
|
||||
evil-collection is a superset. See
|
||||
https://github.com/emacs-evil/evil-collection/issues/60.")
|
||||
(evil-want-integration t "Also needed for evil-collection")
|
||||
:config
|
||||
(defalias 'mu4e--main-action-str 'mu4e~main-action-str)
|
||||
(defalias 'mu4e--main-view-queue 'mu4e~main-view-queue)
|
||||
(evil-mode 1)
|
||||
)
|
||||
|
||||
;; Vim keybindings in other packages
|
||||
(use-package evil-collection
|
||||
:after (evil)
|
||||
:diminish (evil-collection-unimpaired-mode)
|
||||
:config (evil-collection-init)
|
||||
)
|
||||
|
||||
;; Easymotion-like jumping
|
||||
(use-package avy
|
||||
:custom
|
||||
(avy-style 'pre "Insert decision characters instead of overwriting")
|
||||
:general
|
||||
(lmap
|
||||
"jc" '(avy-goto-char :which-key "Jump to character")
|
||||
"j2" '(avy-goto-char-2 :which-key "Jump to 2 character sequence")
|
||||
"jl" '(avy-goto-line :which-key "Jump to line number")
|
||||
"jw" '(avy-goto-word-0 :which-key "Jump to word")
|
||||
"js" '(avy-goto-word-1 :which-key "Jump to word starting with character")
|
||||
)
|
||||
)
|
||||
|
||||
;; Better defaults that aren't defaults for some reason.
|
||||
(use-package better-defaults
|
||||
;; But don't enable ido-mode...
|
||||
:config (ido-mode nil)
|
||||
)
|
||||
|
||||
;; Handy completion-at-point-functions
|
||||
(use-package cape
|
||||
:hook
|
||||
(prog-mode . chvp--setup-capfs)
|
||||
(text-mode . chvp--setup-capfs)
|
||||
:config
|
||||
(defun chvp--setup-capfs ()
|
||||
(add-hook 'completion-at-point-functions #'tempel-complete -50 t)
|
||||
(add-hook 'completion-at-point-functions #'cape-file 10 t)
|
||||
(add-hook 'completion-at-point-functions #'cape-dabbrev 15 t)
|
||||
(add-hook 'completion-at-point-functions #'cape-line 20 t)
|
||||
)
|
||||
)
|
||||
|
||||
;; Autocomplete
|
||||
(use-package corfu
|
||||
:diminish (corfu-mode)
|
||||
:custom
|
||||
(corfu-cycle t "Enable cycling through completions")
|
||||
(corfu-auto t "Show completion preview by default")
|
||||
(corfu-auto-prefix 2 "Show completion after two characters")
|
||||
(corfu-quit-no-match t "Space occurs too often in my normal workflow to not quit on no match")
|
||||
;; Only confirm autocompletion with TAB
|
||||
:bind (:map corfu-map ("RET" . nil))
|
||||
:config
|
||||
(global-corfu-mode)
|
||||
)
|
||||
|
||||
(use-package corfu-popupinfo
|
||||
:ensure nil ;; Part of corfu
|
||||
:config (corfu-popupinfo-mode)
|
||||
)
|
||||
|
||||
;; Prescient in corfu
|
||||
(use-package corfu-prescient
|
||||
:after (corfu prescient)
|
||||
:custom (corfu-prescient-enable-filtering nil "Orderless handles filtering")
|
||||
:config (corfu-prescient-mode 1)
|
||||
)
|
||||
|
||||
;; Replacements for emacs built-ins that better integrate with `vertico'.
|
||||
(use-package consult
|
||||
:commands (consult-ripgrep)
|
||||
:general
|
||||
(lmap
|
||||
"bb" '(consult-buffer :which-key "switch")
|
||||
"fr" '(consult-recent-file :which-key "recent")
|
||||
"ha" '(consult-apropos :which-key "apropos")
|
||||
"ss" '(consult-line :which-key "search")
|
||||
)
|
||||
)
|
||||
|
||||
;; General emacs settings
|
||||
(use-package emacs
|
||||
:ensure nil ;; Not a real package, but a place to collect global settings
|
||||
:demand t
|
||||
:hook
|
||||
;; Always display line numbers for text-based modes
|
||||
((text-mode prog-mode) . display-line-numbers-mode)
|
||||
;; Enable basic auto pairs. Maybe replace this with something more
|
||||
;; advanced later? Look into configuring pairs for frequently used
|
||||
;; major modes.
|
||||
((text-mode prog-mode) . electric-pair-mode)
|
||||
;; Always highlight the current line in text modes
|
||||
((text-mode prog-mode) . hl-line-mode)
|
||||
:custom
|
||||
(use-short-answers t "Allow short answers on yes/no prompt")
|
||||
(fill-column 80 "Fill at column 80 instead of 70")
|
||||
(create-lockfiles nil "I'm the only user on my devices and use emacs as a daemon, so don't clutter with lockfiles")
|
||||
(inhibit-startup-screen t "Don't show default startup screen")
|
||||
(comp-deferred-compilation nil "Don't do native-comp at runtime")
|
||||
(project-vc-merge-submodules nil "Don't consider submodules as the same project")
|
||||
:config
|
||||
|
||||
;; Font configuration
|
||||
(defun font-settings ()
|
||||
"Setup font settings."
|
||||
(when window-system (set-frame-font "Hack 9"))
|
||||
(set-fontset-font t 'symbol "Noto Color Emoji")
|
||||
(set-fontset-font t 'symbol "Symbola" nil 'append))
|
||||
;; Make sure DISPLAY is set correctly in env.
|
||||
(defun display-env-hack ()
|
||||
"Hack DISPLAY env variable back into env."
|
||||
(setenv "DISPLAY" ":0")
|
||||
)
|
||||
(if (daemonp)
|
||||
(progn
|
||||
(add-hook 'server-after-make-frame-hook #'font-settings)
|
||||
(add-hook 'server-after-make-frame-hook #'display-env-hack))
|
||||
(font-settings))
|
||||
|
||||
;; Always display column number in mode line
|
||||
(column-number-mode)
|
||||
)
|
||||
|
||||
;; Linting
|
||||
(use-package flycheck
|
||||
:custom (flycheck-checker-error-threshold 10000 "Set error threshold a lot higher")
|
||||
:hook ((text-mode prog-mode) . flycheck-mode)
|
||||
:diminish (flycheck-mode)
|
||||
)
|
||||
|
||||
(use-package flycheck-languagetool
|
||||
:hook (text-mode . flycheck-languagetool-setup)
|
||||
:custom
|
||||
(flycheck-languagetool-url "http://localhost:15151")
|
||||
)
|
||||
|
||||
;; Annotations in selection interface
|
||||
(use-package marginalia
|
||||
:after (vertico)
|
||||
:custom
|
||||
(marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
|
||||
:config
|
||||
(marginalia-mode)
|
||||
:general
|
||||
(minibuffer-local-map "M-a" 'marginalia-cycle)
|
||||
)
|
||||
|
||||
;; Theming
|
||||
(use-package catppuccin-theme
|
||||
:custom (catppuccin-flavor 'latte)
|
||||
:config (load-theme 'catppuccin :no-confirm)
|
||||
)
|
||||
|
||||
(use-package no-littering
|
||||
:custom
|
||||
(user-emacs-directory (expand-file-name "~/.cache/emacs/") "Don't put files into .emacs.d")
|
||||
:config
|
||||
;; Also make sure auto-save files are saved out-of-tree
|
||||
(setq auto-save-file-name-transforms `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))
|
||||
)
|
||||
|
||||
;; Orderless filtering
|
||||
(use-package orderless
|
||||
:after (vertico)
|
||||
:custom
|
||||
(completion-styles '(orderless basic) "Use orderless for filtering")
|
||||
(orderless-matching-styles '(orderless-literal orderless-initialism orderless-prefixes) "More matching styles for more flexible matching.")
|
||||
)
|
||||
|
||||
;; Org
|
||||
(use-package org
|
||||
:hook
|
||||
(org-insert-heading . set-creation-date-heading-property)
|
||||
:custom
|
||||
(org-directory "~/sync/Notes" "Store org journal in synced directory")
|
||||
(org-default-notes-file (concat org-directory "/inbox.org") "Capture in inbox by default")
|
||||
(org-agenda-files '("~/sync/Notes") "Let's say all files can contain events for now")
|
||||
(org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "DOING(i)" "DONE(d)")) "Add next and doing states")
|
||||
(org-log-into-drawer "LOGBOOK" "Log repeated task state changes into drawer named LOGBOOK")
|
||||
:demand t
|
||||
:config
|
||||
(defun find-file-in-org-directory ()
|
||||
(interactive)
|
||||
(ido-find-file-in-dir org-directory)
|
||||
)
|
||||
(defun set-creation-date-heading-property () (org-set-property "CREATED" (format-time-string (org-time-stamp-format t t))))
|
||||
(defun chvp--org-inbox-length ()
|
||||
(length (org-map-entries t t (list (concat org-directory "/inbox.org"))))
|
||||
)
|
||||
(defun chvp--org-inbox-length-modeline ()
|
||||
(let ((org-len (chvp--org-inbox-length)))
|
||||
(if (<= org-len 0) nil
|
||||
(concat "Org inbox: " (propertize (format "%d" org-len) 'face 'error)))))
|
||||
(add-to-list 'global-mode-string '(:eval (chvp--org-inbox-length-modeline)))
|
||||
:general
|
||||
(lmap
|
||||
:keymaps 'org-mode-map
|
||||
"SPC a" '(org-archive-subtree :which-key "Archive subtree")
|
||||
"SPC i" '(org-insert-heading :which-key "Insert heading")
|
||||
"SPC <" '(org-promote-subtree :which-key "Decrease level")
|
||||
"SPC >" '(org-demote-subtree :which-key "Increase level")
|
||||
"SPC c" '(orc-clone-subtree-with-time-shift :which-key "Repeat subtree")
|
||||
"SPC x" '(org-cut-subtree :which-key "Cut subtree")
|
||||
"SPC p" '(org-paste-subtree :which-key "Paste subtree")
|
||||
"SPC t" '(org-todo :which-key "Cycle todo state")
|
||||
)
|
||||
(lmap
|
||||
"o a" '(org-agenda-list :which-key "Agenda")
|
||||
"o t" '(org-todo-list :which-key "Todo list")
|
||||
"o o" '(find-file-in-org-directory :which-key "Find org file")
|
||||
)
|
||||
)
|
||||
|
||||
;; Citations with citeproc in org
|
||||
(use-package citeproc)
|
||||
|
||||
;; Sorting when filtering
|
||||
(use-package prescient
|
||||
:custom
|
||||
(prescient-aggressive-file-save t "Be aggressive with saving prescient data since we're in daemon mode")
|
||||
(prescient-history-length 100000 "Save a lot of history")
|
||||
(prescient-frequency-threshold 0.00005 "Save a lot of history")
|
||||
:config (prescient-persist-mode 1)
|
||||
)
|
||||
|
||||
;; Rainbow delimiters
|
||||
(use-package rainbow-delimiters
|
||||
:hook (prog-mode . rainbow-delimiters-mode))
|
||||
|
||||
;; Side window with symbols or headline
|
||||
(use-package sr-speedbar
|
||||
:custom
|
||||
(speedbar-use-images nil "Don't use images in speedbar")
|
||||
:general
|
||||
(lmap
|
||||
"wb" '(sr-speedbar-toggle :which-key "Outline bar"))
|
||||
)
|
||||
|
||||
;; Tempel (snippet expansion)
|
||||
(use-package tempel
|
||||
:demand t
|
||||
:after cape
|
||||
;; This is not very nice, but let's just assume that development machines have my nixos-config checked out
|
||||
:custom (tempel-path "/home/charlotte/repos/nixos-config/modules/base/emacs/snippets/*.eld")
|
||||
:general
|
||||
(lmap
|
||||
"t i" '(tempel-insert :which-key "Insert template")
|
||||
)
|
||||
)
|
||||
|
||||
;; List item selection interface
|
||||
(use-package vertico
|
||||
:custom (vertico-count 20 "Allow selector to be a bit higher")
|
||||
:config (vertico-mode)
|
||||
:diminish (vertico-mode)
|
||||
)
|
||||
|
||||
;; Prescient integration in vertico
|
||||
(use-package vertico-prescient
|
||||
:after (vertico prescient)
|
||||
:custom (vertico-prescient-enable-filtering nil "`orderless' manages the filtering part.")
|
||||
:config (vertico-prescient-mode 1))
|
||||
|
||||
;; Show keybindings
|
||||
(use-package which-key
|
||||
:diminish (which-key-mode)
|
||||
:config (which-key-mode)
|
||||
)
|
||||
|
57
modules/nixos/base/emacs/default.nix
Normal file
57
modules/nixos/base/emacs/default.nix
Normal file
|
@ -0,0 +1,57 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.base.emacs = {
|
||||
fullConfig = lib.mkOption {
|
||||
readOnly = true;
|
||||
default = builtins.readFile ./base-init.el + (lib.concatStringsSep "\n" config.chvp.base.emacs.extraConfig) + ''
|
||||
(provide 'init)
|
||||
;;; init.el ends here
|
||||
'';
|
||||
};
|
||||
extraConfig = lib.mkOption {
|
||||
default = [ ];
|
||||
};
|
||||
package = lib.mkOption {
|
||||
readOnly = true;
|
||||
default = pkgs.emacsWithPackagesFromUsePackage {
|
||||
config = config.chvp.base.emacs.fullConfig;
|
||||
package = pkgs.emacs-pgtk;
|
||||
alwaysEnsure = true;
|
||||
extraEmacsPackages = epkgs: lib.optional config.chvp.graphical.mail.enable epkgs.mu4e;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".cache/emacs"; type = "cache"; }
|
||||
];
|
||||
|
||||
services.languagetool = {
|
||||
enable = true;
|
||||
port = 15151;
|
||||
settings.cacheSize = 10000;
|
||||
};
|
||||
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
services.emacs = {
|
||||
enable = true;
|
||||
client.enable = true;
|
||||
socketActivation.enable = true;
|
||||
package = config.chvp.base.emacs.package;
|
||||
};
|
||||
home = {
|
||||
packages = [
|
||||
(pkgs.writeShellScriptBin "emacs" ''${config.chvp.base.emacs.package}/bin/emacsclient -c "$@"'')
|
||||
(pkgs.writeShellScriptBin "emacsclient" ''${config.chvp.base.emacs.package}/bin/emacsclient "$@"'')
|
||||
];
|
||||
sessionVariables = { EDITOR = "emacs"; };
|
||||
};
|
||||
xdg.configFile = {
|
||||
"emacs/init.el".text = config.chvp.base.emacs.fullConfig;
|
||||
"emacs/early-init.el".source = ./early-init.el;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
32
modules/nixos/base/emacs/early-init.el
Normal file
32
modules/nixos/base/emacs/early-init.el
Normal file
|
@ -0,0 +1,32 @@
|
|||
;;; early-init --- My emacs early init file
|
||||
;;; Commentary:
|
||||
;;; Code:
|
||||
(defun hm/reduce-gc ()
|
||||
"Reduce the frequency of garbage collection."
|
||||
(setq gc-cons-threshold most-positive-fixnum
|
||||
gc-cons-percentage 0.6))
|
||||
|
||||
(defun hm/restore-gc ()
|
||||
"Restore the frequency of garbage collection."
|
||||
(setq gc-cons-threshold 16777216
|
||||
gc-cons-percentage 0.1))
|
||||
|
||||
;; Make GC more rare during init, while minibuffer is active, and
|
||||
;; when shutting down. In the latter two cases we try doing the
|
||||
;; reduction early in the hook.
|
||||
(hm/reduce-gc)
|
||||
(add-hook 'minibuffer-setup-hook #'hm/reduce-gc -50)
|
||||
(add-hook 'kill-emacs-hook #'hm/reduce-gc -50)
|
||||
|
||||
;; But make it more regular after startup and after closing minibuffer.
|
||||
(add-hook 'emacs-startup-hook #'hm/restore-gc)
|
||||
(add-hook 'minibuffer-exit-hook #'hm/restore-gc)
|
||||
|
||||
;; Nix manages our packages
|
||||
(setq package-enable-at-startup nil)
|
||||
|
||||
;; Avoid expensive frame resizing. Inspired by Doom Emacs.
|
||||
(setq frame-inhibit-implied-resize t)
|
||||
|
||||
(provide 'early-init)
|
||||
;;; early-init.el ends here
|
6
modules/nixos/base/emacs/snippets/fundamental.eld
Normal file
6
modules/nixos/base/emacs/snippets/fundamental.eld
Normal file
|
@ -0,0 +1,6 @@
|
|||
fundamental-mode
|
||||
|
||||
(today (format-time-string "%Y-%m-%d"))
|
||||
(NOW (format-time-string "<%Y-%0m-%0d %a %H:%0M>"))
|
||||
(yesterday (format-time-string "%Y-%0m-%0d" (time-subtract nil (* 24 60 60))))
|
||||
(tomorrow (format-time-string "%Y-%0m-%0d" (time-add nil (* 24 60 60))))
|
7
modules/nixos/base/emacs/snippets/java.eld
Normal file
7
modules/nixos/base/emacs/snippets/java.eld
Normal file
|
@ -0,0 +1,7 @@
|
|||
java-mode
|
||||
|
||||
(sout "System.out.println(" r ");")
|
||||
(serr "System.err.println(" r ");")
|
||||
|
||||
(class "public class " p " {" n> q n "}")
|
||||
(main "public static void main(String[] args) {" n> q n "}")
|
49
modules/nixos/base/emacs/snippets/mu4e-compose.eld
Normal file
49
modules/nixos/base/emacs/snippets/mu4e-compose.eld
Normal file
|
@ -0,0 +1,49 @@
|
|||
mu4e-compose-mode
|
||||
|
||||
(mvg
|
||||
"Met vriendelijke groeten" n
|
||||
"Charlotte Van Petegem"
|
||||
)
|
||||
|
||||
(spelletjesavond-schulden
|
||||
"Dag " p n n
|
||||
"Na de spelletjesavond van vrijdag zou je mij € " q " moeten. Kan je dat overschrijven op BE08 8908 0409 9113? Alvast bedankt!" n n
|
||||
"Groetjes" n
|
||||
"Charlotte"
|
||||
)
|
||||
|
||||
(teacher-reply
|
||||
"Dag " q n n
|
||||
r n
|
||||
"Welkom op Dodona! Zou je het volgende formulier kunnen invullen?" n n
|
||||
"https://dodona.ugent.be/rights_requests/new/" n n
|
||||
"Zo hebben we meteen alle info die we nodig hebben om je lesgeversrechten te geven op Dodona." n n
|
||||
"Met vriendelijke groeten" n
|
||||
"Charlotte Van Petegem"
|
||||
)
|
||||
|
||||
(twist-exam-nag-en
|
||||
"Hi " q n n
|
||||
"A part of being a member of the TWIST department is contributing to exam supervision. Since the department board meeting of september 2022 it was decided to ask a bit more of people who don't contribute or contribute less to education during the semester, to allow the people who have to mark a lot of exams to concentrate on that. You are expected to do 3 supervisions, but as far as I can see that is not the case yet. Can I ask that you register for a number of exam supervisions? You can do so via the following spreadsheet: https://sharepoint.ugent.be/teams/WE02/_layouts/15/WopiFrame2.aspx?sourcedoc=%7BAA66A430-5240-4002-9D47-F6D06CF819AA%7D&file=Examentoezichten.xlsx&action=default&IsList=1&ListId=%7BA2BEB5ED-0C41-4A4B-ADCA-8F7CD56C2BBB%7D&ListItemId=2 (see also the email that was sent to the department mailing list at the end of the semester)." n n
|
||||
"If you received this mail in error, please let me know, then I won't bother you in the future." n n
|
||||
"Kind regards" n
|
||||
"Charlotte Van Petegem"
|
||||
)
|
||||
|
||||
(twist-exam-nag-nl
|
||||
"Dag " q n n
|
||||
"Een deel van lid zijn van de TWIST vakgroep is het bijdragen aan de toezichten bij de examens. Sinds de vakgroepraad van september 2022 is er ook besloten om iets meer te vragen van mensen die minder (of niet) aan onderwijs bijdragen om de mensen met veel verbeterwerk toe te laten om zich daarop te kunnen concentreren. Jij wordt verwacht 3 toezichten te doen, maar voor zover ik kan zien is dat nog niet het geval. Mag ik vragen van je te registreren voor een aantal examentoezichten? Dat kan via de volgende spreadsheet: https://sharepoint.ugent.be/teams/WE02/_layouts/15/WopiFrame2.aspx?sourcedoc=%7BAA66A430-5240-4002-9D47-F6D06CF819AA%7D&file=Examentoezichten.xlsx&action=default&IsList=1&ListId=%7BA2BEB5ED-0C41-4A4B-ADCA-8F7CD56C2BBB%7D&ListItemId=2 (zie ook de mail die op het einde van het semester naar de mailinglijst van de vakgroep werd verstuurd)?" n
|
||||
"Als je deze mail foutief gekregen hebt, laat het mij dan zeker weten, dan val ik je in de toekomst niet meer lastig." n n
|
||||
"Alvast bedankt" n
|
||||
"Met vriendelijke groeten" n
|
||||
"Charlotte Van Petegem"
|
||||
)
|
||||
|
||||
(rode-kruis-vrijwilliger-cursussen
|
||||
"Dag " p n n
|
||||
"Je wil vrijwilliger worden bij het Rode Kruis. Super! Daarom krijg je bij het inschrijven voor de cursussen ook wat voorrang, zodat je je zeker kan inschrijven. Dit zijn de opties:" n n
|
||||
q n n
|
||||
"Kan je een seintje geven wanneer je dit gedaan hebt (of moest het niet passen)? Dan kan ik daarna de mail naar het grote publiek sturen om in te schrijven." n n
|
||||
"Met vriendelijke groeten" n
|
||||
"Charlotte Van Petegem"
|
||||
)
|
14
modules/nixos/base/emacs/snippets/python.eld
Normal file
14
modules/nixos/base/emacs/snippets/python.eld
Normal file
|
@ -0,0 +1,14 @@
|
|||
python-mode
|
||||
|
||||
(class "class " p ":"
|
||||
n> "\"\"\""
|
||||
n> p
|
||||
n> "\"\"\""
|
||||
n> "def __init__(self" (p ", *args, **kwargs") "):"
|
||||
n> "\"\"\""
|
||||
n> p
|
||||
n> "\"\"\""
|
||||
n> q
|
||||
)
|
||||
|
||||
(def "def " p "(" (p "*args, **kwargs") "):" n> "\"\"\"" n> p n> "\"\"\"" n> q)
|
21
modules/nixos/base/mail/default.nix
Normal file
21
modules/nixos/base/mail/default.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
programs.msmtp = {
|
||||
enable = lib.mkDefault true;
|
||||
accounts.default = {
|
||||
auth = true;
|
||||
from = "webmaster@vanpetegem.me";
|
||||
host = "mail.vanpetegem.me";
|
||||
passwordeval = ''${pkgs.coreutils}/bin/cat ${config.age.secrets."passwords/services/ssmtp-pass".path}'';
|
||||
port = 465;
|
||||
tls = true;
|
||||
tls_starttls = false;
|
||||
tls_trust_file = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
user = "webmaster@vanpetegem.me";
|
||||
};
|
||||
setSendmail = true;
|
||||
};
|
||||
|
||||
age.secrets."passwords/services/ssmtp-pass".file = ../../../../secrets/passwords/services/ssmtp-pass.age;
|
||||
}
|
9
modules/nixos/base/network/default.nix
Normal file
9
modules/nixos/base/network/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./mobile.nix
|
||||
./ovh.nix
|
||||
./wireguard.nix
|
||||
];
|
||||
}
|
93
modules/nixos/base/network/mobile.nix
Normal file
93
modules/nixos/base/network/mobile.nix
Normal file
|
@ -0,0 +1,93 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.base.network.mobile = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
wireless-interface = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "wlp2s0";
|
||||
};
|
||||
wired-interfaces = lib.mkOption {
|
||||
example = { "enp0s29f0u1u2" = { macAddress = "10:65:30:85:bb:18"; }; };
|
||||
};
|
||||
};
|
||||
|
||||
config = with config.chvp.base.network.mobile; lib.mkIf enable {
|
||||
environment.systemPackages = [ pkgs.wpa_supplicant_gui ];
|
||||
users.users.charlotte.extraGroups = [ "network" ];
|
||||
users.groups.network = { };
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
wireless = {
|
||||
enable = true;
|
||||
interfaces = [ wireless-interface ];
|
||||
environmentFile = config.age.secrets."passwords/networks.age".path;
|
||||
userControlled = {
|
||||
enable = true;
|
||||
group = "network";
|
||||
};
|
||||
networks = {
|
||||
"Public Universal Friend".psk = "@PSK_PUF@";
|
||||
AndroidAP.psk = "@PSK_AndroidAP@";
|
||||
draadloosnw.psk = "@PSK_draadloosnw@";
|
||||
werknet.psk = "@PSK_werknet@";
|
||||
Secorima.psk = "@PSK_Secorima@";
|
||||
"Mediaraven Guest".psk = "@PSK_Mediaraven@";
|
||||
"down".psk = "@PSK_down@";
|
||||
"Zeus WPI" = {
|
||||
psk = "@PSK_Zeus@";
|
||||
hidden = true;
|
||||
};
|
||||
"Zeus Event 5G".psk = "@PSK_Zeus@";
|
||||
"Rode Kruis-Gent (internet)".psk = "@PSK_RKG@";
|
||||
"CityStayNet".psk = "@PSK_CityStayNet@";
|
||||
eduroam = {
|
||||
authProtocols = [ "WPA-EAP" ];
|
||||
auth = ''
|
||||
eap=PEAP
|
||||
identity="@EDUROAM_USER@"
|
||||
password="@EDUROAM_PASS@"
|
||||
'';
|
||||
extraConfig = ''
|
||||
phase1="peaplabel=0"
|
||||
phase2="auth=MSCHAPV2"
|
||||
group=CCMP TKIP
|
||||
ca_cert="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
|
||||
altsubject_match="DNS:radius.ugent.be"
|
||||
'';
|
||||
};
|
||||
"GUK-huis".psk = "@PSK_GUKhuis@";
|
||||
"DasNetwerk".psk = "@PSK_DasNetwerk@";
|
||||
};
|
||||
};
|
||||
};
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
networks = {
|
||||
"${wireless-interface}" = {
|
||||
enable = true;
|
||||
DHCP = "yes";
|
||||
matchConfig = { Name = wireless-interface; };
|
||||
dhcpV4Config = { RouteMetric = 20; };
|
||||
ipv6AcceptRAConfig = { RouteMetric = 20; };
|
||||
};
|
||||
} // lib.mapAttrs
|
||||
(name: attrs: {
|
||||
enable = true;
|
||||
DHCP = "yes";
|
||||
matchConfig = { Name = name; };
|
||||
dhcpV4Config = { RouteMetric = 10; };
|
||||
ipv6AcceptRAConfig = { RouteMetric = 10; };
|
||||
} // attrs)
|
||||
wired-interfaces;
|
||||
wait-online.anyInterface = true;
|
||||
};
|
||||
|
||||
age.secrets."passwords/networks.age" = {
|
||||
file = ../../../../secrets/passwords/networks.age;
|
||||
};
|
||||
};
|
||||
}
|
63
modules/nixos/base/network/ovh.nix
Normal file
63
modules/nixos/base/network/ovh.nix
Normal file
|
@ -0,0 +1,63 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.chvp.base.network.ovh = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
publicIPV4 = lib.mkOption {
|
||||
example = {
|
||||
ip = "1.2.3.4";
|
||||
gateway = "1.2.3.254";
|
||||
};
|
||||
};
|
||||
publicIPV6 = lib.mkOption {
|
||||
example = {
|
||||
ip = "1:2:3:4::";
|
||||
gateway = "1:2:3:ff:ff:ff:ff:ff";
|
||||
};
|
||||
};
|
||||
internalIPV4 = lib.mkOption {
|
||||
example = "192.168.0.1";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.base.network.ovh.enable {
|
||||
networking.useDHCP = false;
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
networks = with config.chvp.base.network.ovh; {
|
||||
eno3 = {
|
||||
enable = true;
|
||||
matchConfig = { Name = "eno3"; };
|
||||
address = [
|
||||
"${publicIPV4.ip}/24"
|
||||
"${publicIPV6.ip}/64"
|
||||
];
|
||||
gateway = [ publicIPV4.gateway ];
|
||||
routes = [
|
||||
{
|
||||
Gateway = publicIPV6.gateway;
|
||||
GatewayOnLink = true;
|
||||
}
|
||||
];
|
||||
dns = [
|
||||
"1.1.1.1"
|
||||
"1.0.0.1"
|
||||
"2606:4700:4700::1111"
|
||||
"2606:4700:4700::1001"
|
||||
];
|
||||
};
|
||||
eno4 = {
|
||||
enable = true;
|
||||
matchConfig = { Name = "eno4"; };
|
||||
address = [ "${internalIPV4}/16" ];
|
||||
routes = [
|
||||
{ Destination = "${internalIPV4}/16"; }
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
141
modules/nixos/base/network/wireguard.nix
Normal file
141
modules/nixos/base/network/wireguard.nix
Normal file
|
@ -0,0 +1,141 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
data = {
|
||||
fairphone = {
|
||||
pubkey = "mHAq+2AP1EZdlSZIxA8UCret8EStrR3nEIU2x6NVETE=";
|
||||
ip = "10.240.0.4";
|
||||
};
|
||||
kholinar = {
|
||||
pubkey = "oRA22ymFeNQBeRx6Jyd6Gd8EOUpAv9QSFkGs+Br7yEk=";
|
||||
privkeyFile = config.age.secrets."files/wireguard/kholinar.privkey".path;
|
||||
ip = "10.240.0.3";
|
||||
};
|
||||
lasting-integrity = {
|
||||
pubkey = "mid3XfCY2jaNK0J6C9ltFLAbxL0IApwMw9K1Z+PU8C0=";
|
||||
privkeyFile = config.age.secrets."files/wireguard/lasting-integrity.privkey".path;
|
||||
ip = "10.240.0.1";
|
||||
};
|
||||
urithiru = {
|
||||
pubkey = "f4bnm/qNhMW5iXdQcBMmP8IUN6n+pDS15Ikct7QPr0E=";
|
||||
privkeyFile = config.age.secrets."files/wireguard/urithiru.privkey".path;
|
||||
ip = "10.240.0.2";
|
||||
};
|
||||
};
|
||||
subnet = "10.240.0.0/24";
|
||||
pskFile = config.age.secrets."files/wireguard/psk".path;
|
||||
in
|
||||
{
|
||||
options.chvp.base.network.wireguard = {
|
||||
server = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
onCorporate = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
networking.firewall = {
|
||||
allowedUDPPorts = lib.optional config.chvp.base.network.wireguard.server 51820;
|
||||
allowedTCPPorts = lib.optional config.chvp.base.network.wireguard.server 8080;
|
||||
trustedInterfaces = [ "wg0" ];
|
||||
};
|
||||
boot.kernel.sysctl = lib.mkIf config.chvp.base.network.wireguard.server { "net.ipv4.ip_forward" = 1; };
|
||||
services.unbound = lib.mkIf config.chvp.base.network.wireguard.server {
|
||||
enable = true;
|
||||
resolveLocalQueries = true;
|
||||
settings = {
|
||||
server = {
|
||||
interface = [ "10.240.0.1" "127.0.0.1" "::1" ];
|
||||
access-control = [
|
||||
"127.0.0.0/8 allow"
|
||||
"10.240.0.0/24 allow"
|
||||
];
|
||||
private-domain = "internal";
|
||||
domain-insecure = "internal";
|
||||
local-zone = builtins.map (name: ''"${name}.internal" redirect'') (builtins.attrNames data);
|
||||
local-data = builtins.map (name: ''"${name}.internal IN A ${data.${name}.ip}"'') (builtins.attrNames data);
|
||||
};
|
||||
forward-zone = {
|
||||
name = ''"."'';
|
||||
forward-addr = [
|
||||
"1.1.1.1@853"
|
||||
"1.0.0.1@853"
|
||||
"2606:4700:4700::1111@853"
|
||||
"2606:4700:4700::1001@853"
|
||||
];
|
||||
forward-tls-upstream = "yes";
|
||||
};
|
||||
};
|
||||
};
|
||||
systemd = {
|
||||
network = {
|
||||
netdevs.wg0 = {
|
||||
enable = true;
|
||||
netdevConfig = {
|
||||
Name = "wg0";
|
||||
Kind = "wireguard";
|
||||
MTUBytes = "1342";
|
||||
};
|
||||
wireguardConfig =
|
||||
if config.chvp.base.network.wireguard.server then {
|
||||
PrivateKeyFile = data.${config.networking.hostName}.privkeyFile;
|
||||
ListenPort = 51820;
|
||||
} else {
|
||||
PrivateKeyFile = data.${config.networking.hostName}.privkeyFile;
|
||||
};
|
||||
wireguardPeers =
|
||||
if config.chvp.base.network.wireguard.server then
|
||||
(builtins.map
|
||||
(name: {
|
||||
PublicKey = data.${name}.pubkey;
|
||||
AllowedIPs = "${data.${name}.ip}/32";
|
||||
PresharedKeyFile = pskFile;
|
||||
})
|
||||
(builtins.filter (name: name != config.networking.hostName) (builtins.attrNames data)))
|
||||
else
|
||||
([{
|
||||
PublicKey = data.lasting-integrity.pubkey;
|
||||
AllowedIPs = subnet;
|
||||
Endpoint =
|
||||
if config.chvp.base.network.wireguard.onCorporate
|
||||
then "127.0.0.1:51820"
|
||||
else "lasting-integrity.vanpetegem.me:51820";
|
||||
PresharedKeyFile = pskFile;
|
||||
PersistentKeepalive = 25;
|
||||
}]);
|
||||
};
|
||||
networks.wg0 = {
|
||||
enable = true;
|
||||
name = "wg0";
|
||||
address = [ "${data.${config.networking.hostName}.ip}/32" ];
|
||||
domains = [ "internal" ];
|
||||
dns = [ data.lasting-integrity.ip ];
|
||||
linkConfig.MTUBytes = "1342";
|
||||
routes = [
|
||||
(
|
||||
if config.chvp.base.network.wireguard.server then {
|
||||
Gateway = "${data.${config.networking.hostName}.ip}";
|
||||
Destination = subnet;
|
||||
} else {
|
||||
Gateway = "${data.lasting-integrity.ip}";
|
||||
Destination = subnet;
|
||||
GatewayOnLink = true;
|
||||
}
|
||||
)
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
age.secrets."files/wireguard/psk" = {
|
||||
file = ../../../../secrets/files/wireguard/psk.age;
|
||||
owner = "systemd-network";
|
||||
};
|
||||
age.secrets."files/wireguard/${config.networking.hostName}.privkey" = {
|
||||
file = ../../../../secrets/files/wireguard + "/${config.networking.hostName}.privkey.age";
|
||||
owner = "systemd-network";
|
||||
};
|
||||
};
|
||||
}
|
95
modules/nixos/base/nix/default.nix
Normal file
95
modules/nixos/base/nix/default.nix
Normal file
|
@ -0,0 +1,95 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
baseDirenv = {
|
||||
programs.direnv = {
|
||||
enable = true;
|
||||
enableZshIntegration = true;
|
||||
nix-direnv.enable = true;
|
||||
};
|
||||
};
|
||||
baseNixIndex = {
|
||||
programs.command-not-found.enable = false;
|
||||
programs.nix-index = {
|
||||
enable = true;
|
||||
package = config.programs.nix-index.package;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.chvp.base.nix = {
|
||||
enableDirenv = lib.mkOption {
|
||||
default = true;
|
||||
example = false;
|
||||
};
|
||||
slowGc = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
# Used in /flake.nix, since we have to use it at nixpkgs import time
|
||||
unfreePackages = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [ "teams" ];
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
programs.command-not-found.enable = false;
|
||||
chvp.base = {
|
||||
emacs.extraConfig = [
|
||||
''
|
||||
;; Nix syntax support
|
||||
(use-package nix-mode
|
||||
:mode "\\.nix\\'"
|
||||
)
|
||||
''
|
||||
] ++ lib.optional config.chvp.base.nix.enableDirenv ''
|
||||
;; Direnv integration in emacs.
|
||||
(use-package direnv
|
||||
:config (direnv-mode)
|
||||
)
|
||||
'';
|
||||
zfs = {
|
||||
homeLinks =
|
||||
(lib.optional config.chvp.base.nix.enableDirenv { path = ".local/share/direnv"; type = "cache"; });
|
||||
systemLinks =
|
||||
(lib.optional config.chvp.base.nix.enableDirenv { path = "/root/.local/share/direnv"; type = "cache"; });
|
||||
};
|
||||
};
|
||||
|
||||
nix = {
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = if config.chvp.base.nix.slowGc then "daily" else "hourly";
|
||||
options = "--delete-older-than 7d";
|
||||
};
|
||||
settings = {
|
||||
auto-optimise-store = true;
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
"https://accentor.cachix.org"
|
||||
"https://chvp.cachix.org"
|
||||
"https://lanzaboote.cachix.org"
|
||||
"https://nix-community.cachix.org"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"accentor.cachix.org-1:QP+oJwzmeq5Fsyp4Vk501UgUSbl5VIna/ard/XOePH8="
|
||||
"chvp.cachix.org-1:eIG26KkeA+R3tCpvmaayA9i3KVVL06G+qB5ci4dHBT4="
|
||||
"lanzaboote.cachix.org-1:Nt9//zGmqkg1k5iu+B3bkj3OmHKjSw9pvf3faffLLNk="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
];
|
||||
trusted-users = [ "@wheel" ];
|
||||
};
|
||||
extraOptions = lib.mkIf config.chvp.base.nix.enableDirenv ''
|
||||
keep-outputs = true
|
||||
keep-derivations = true
|
||||
'';
|
||||
};
|
||||
|
||||
home-manager.users.charlotte = { ... }:
|
||||
lib.recursiveUpdate
|
||||
(lib.optionalAttrs config.chvp.base.nix.enableDirenv baseDirenv)
|
||||
baseNixIndex;
|
||||
home-manager.users.root = { ... }: baseNixIndex;
|
||||
};
|
||||
}
|
15
modules/nixos/base/phone-push/default.nix
Normal file
15
modules/nixos/base/phone-push/default.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
phone-push = pkgs.writeShellScriptBin "phone-push" ''
|
||||
curl $(cat ${config.age.secrets."files/services/phone-push-url".path}) -d "$(hostname): $@"
|
||||
'';
|
||||
in
|
||||
{
|
||||
environment.systemPackages = [ phone-push ];
|
||||
|
||||
age.secrets."files/services/phone-push-url" = {
|
||||
file = ../../../../secrets/files/services/phone-push-url.age;
|
||||
owner = "charlotte";
|
||||
};
|
||||
}
|
17
modules/nixos/base/smartd/default.nix
Normal file
17
modules/nixos/base/smartd/default.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
environment.systemPackages = [ pkgs.smartmontools ];
|
||||
services.smartd = {
|
||||
enable = true;
|
||||
autodetect = true;
|
||||
notifications = {
|
||||
mail = {
|
||||
enable = true;
|
||||
sender = "${config.networking.hostName}@vanpetegem.me";
|
||||
recipient = "webmaster@vanpetegem.me";
|
||||
};
|
||||
wall.enable = false;
|
||||
};
|
||||
};
|
||||
}
|
44
modules/nixos/base/ssh/default.nix
Normal file
44
modules/nixos/base/ssh/default.nix
Normal file
|
@ -0,0 +1,44 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
ssh = pkgs.symlinkJoin {
|
||||
name = "ssh";
|
||||
paths = [
|
||||
(
|
||||
pkgs.writeShellScriptBin "ssh" ''
|
||||
export TERM=xterm-256color
|
||||
${pkgs.openssh}/bin/ssh "$@"
|
||||
''
|
||||
)
|
||||
pkgs.openssh
|
||||
];
|
||||
};
|
||||
base = home: user: {
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
package = if config.chvp.graphical.enable then ssh else pkgs.openssh;
|
||||
compression = true;
|
||||
controlMaster = "auto";
|
||||
controlPersist = "10m";
|
||||
hashKnownHosts = true;
|
||||
userKnownHostsFile = "${config.chvp.cachePrefix}${home}/.ssh/known_hosts";
|
||||
serverAliveInterval = 10;
|
||||
extraOptionOverrides = {
|
||||
Include = config.age.secrets."files/programs/ssh/host_configuration_${user}".path;
|
||||
IdentityFile = "${config.chvp.dataPrefix}${home}/.ssh/id_ed25519";
|
||||
HostKeyAlgorithms = "ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa";
|
||||
};
|
||||
};
|
||||
home.packages = lib.mkIf config.chvp.graphical.enable [ pkgs.sshfs ];
|
||||
};
|
||||
in
|
||||
{
|
||||
home-manager.users.root = { ... }: (base "/root" "root");
|
||||
home-manager.users.charlotte = { ... }: (base "/home/charlotte" "charlotte");
|
||||
age.secrets."files/programs/ssh/host_configuration_charlotte" = {
|
||||
file = ../../../../secrets/files/programs/ssh/host_configuration.age;
|
||||
owner = "charlotte";
|
||||
};
|
||||
age.secrets."files/programs/ssh/host_configuration_root" = {
|
||||
file = ../../../../secrets/files/programs/ssh/host_configuration.age;
|
||||
};
|
||||
}
|
31
modules/nixos/base/sshd/default.nix
Normal file
31
modules/nixos/base/sshd/default.nix
Normal file
|
@ -0,0 +1,31 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
chvp.base.zfs = {
|
||||
ensureSystemExists = [ "${config.chvp.dataPrefix}/etc/ssh" ];
|
||||
ensureHomeExists = [ ".ssh" ];
|
||||
};
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
hostKeys = [
|
||||
{ bits = 4096; path = "${config.chvp.dataPrefix}/etc/ssh/ssh_host_rsa_key"; type = "rsa"; }
|
||||
{ path = "${config.chvp.dataPrefix}/etc/ssh/ssh_host_ed25519_key"; type = "ed25519"; }
|
||||
];
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "prohibit-password";
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."authorized_keys/root" = {
|
||||
file = ../../../../secrets/authorized_keys/root.age;
|
||||
path = "/root/.ssh/authorized_keys";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."authorized_keys/charlotte" = {
|
||||
file = ../../../../secrets/authorized_keys/charlotte.age;
|
||||
owner = "charlotte";
|
||||
path = "/home/charlotte/.ssh/authorized_keys";
|
||||
symlink = false;
|
||||
};
|
||||
}
|
50
modules/nixos/base/telegraf/default.nix
Normal file
50
modules/nixos/base/telegraf/default.nix
Normal file
|
@ -0,0 +1,50 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.telegraf = {
|
||||
enable = true;
|
||||
extraConfig = {
|
||||
agent = {
|
||||
interval = "10s";
|
||||
round_interval = true;
|
||||
metric_batch_size = 1000;
|
||||
metric_buffer_limit = 10000;
|
||||
collection_jitter = "0s";
|
||||
flush_interval = "10s";
|
||||
flush_jitter = "0s";
|
||||
precision = "0s";
|
||||
omit_hostname = false;
|
||||
};
|
||||
outputs.influxdb_v2 = {
|
||||
urls = [ "https://stats.chvp.be:8086" ];
|
||||
token = "$TOKEN";
|
||||
organization = "default";
|
||||
bucket = "default";
|
||||
};
|
||||
inputs = {
|
||||
cpu = {
|
||||
percpu = true;
|
||||
totalcpu = true;
|
||||
collect_cpu_time = false;
|
||||
report_active = false;
|
||||
};
|
||||
diskio = { };
|
||||
exec = {
|
||||
commands = [ "${pkgs.zfs}/libexec/zfs/zpool_influxdb" ];
|
||||
timeout = "5s";
|
||||
data_format = "influx";
|
||||
};
|
||||
kernel = { };
|
||||
mem = { };
|
||||
processes = { };
|
||||
swap = { };
|
||||
system = { };
|
||||
};
|
||||
};
|
||||
environmentFiles = [ config.age.secrets."passwords/services/telegraf-env".path ];
|
||||
};
|
||||
age.secrets."passwords/services/telegraf-env" = {
|
||||
file = ../../../../secrets/passwords/services/telegraf-env.age;
|
||||
owner = "telegraf";
|
||||
};
|
||||
}
|
22
modules/nixos/base/tmux/default.nix
Normal file
22
modules/nixos/base/tmux/default.nix
Normal file
|
@ -0,0 +1,22 @@
|
|||
{ ... }:
|
||||
let
|
||||
base = {
|
||||
programs.tmux = {
|
||||
enable = true;
|
||||
clock24 = true;
|
||||
extraConfig = ''
|
||||
bind q kill-session
|
||||
bind v run-shell "tmux setw main-pane-width $(($(tmux display -p '#{window_width}') * 70 / 100)); tmux select-layout main-vertical"
|
||||
bind h run-shell "tmux setw main-pane-height $(($(tmux display -p '#{window_height}') * 70 / 100)); tmux select-layout main-horizontal"
|
||||
|
||||
set -g default-terminal "screen-256color"
|
||||
set -sg escape-time 10
|
||||
'';
|
||||
keyMode = "vi";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
home-manager.users.charlotte = { ... }: base;
|
||||
home-manager.users.root = { ... }: base;
|
||||
}
|
198
modules/nixos/base/zfs/default.nix
Normal file
198
modules/nixos/base/zfs/default.nix
Normal file
|
@ -0,0 +1,198 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.chvp.base.zfs = {
|
||||
encrypted = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
systemLinks = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [
|
||||
{ path = "/var/lib/docker"; type = "cache"; }
|
||||
{ path = "/var/lib/docker/volumes"; type = "data"; }
|
||||
];
|
||||
};
|
||||
homeLinks = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [
|
||||
{ path = ".config/syncthing"; type = "data"; }
|
||||
{ path = ".cache/nix-index"; type = "cache"; }
|
||||
];
|
||||
};
|
||||
ensureSystemExists = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [ "/data/etc/ssh" ];
|
||||
};
|
||||
ensureHomeExists = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [ ".ssh" ];
|
||||
};
|
||||
backups = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [{
|
||||
path = "rpool/safe/data";
|
||||
remotePath = "zdata/recv/<hostname>/safe/data";
|
||||
fast = false;
|
||||
location = "lasting-integrity.vanpetegem.me";
|
||||
}];
|
||||
};
|
||||
rootDataset = lib.mkOption {
|
||||
example = "rpool/local/root";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
chvp.dataPrefix = lib.mkDefault "/data";
|
||||
chvp.cachePrefix = lib.mkDefault "/cache";
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = [ "zfs" ];
|
||||
zfs.requestEncryptionCredentials = config.chvp.base.zfs.encrypted;
|
||||
initrd.postDeviceCommands = lib.mkAfter ''
|
||||
zfs rollback -r ${config.chvp.base.zfs.rootDataset}@blank
|
||||
'';
|
||||
};
|
||||
|
||||
services = {
|
||||
znapzend = {
|
||||
enable = config.chvp.base.zfs.backups != [ ];
|
||||
pure = true;
|
||||
autoCreation = true;
|
||||
zetup = builtins.listToAttrs
|
||||
(map
|
||||
(elem: {
|
||||
name = elem.path;
|
||||
value = {
|
||||
enable = true;
|
||||
plan =
|
||||
if elem.fast then
|
||||
"1hour=>15min,1day=>1hour,1week=>1day,4week=>1week" else
|
||||
"1day=>1hour,1week=>1day,4week=>1week,1year=>1month,10year=>6month";
|
||||
timestampFormat = "%Y-%m-%d--%H%M%SZ";
|
||||
destinations."${elem.location}" = {
|
||||
plan =
|
||||
if elem.fast then
|
||||
"1day=>1hour,1week=>1day,4week=>1week,1year=>4week,10year=>1year" else
|
||||
"1day=>1hour,1week=>1day,4week=>1week,1year=>1month,10year=>6month";
|
||||
host = "${elem.location}";
|
||||
dataset = elem.remotePath;
|
||||
};
|
||||
};
|
||||
})
|
||||
config.chvp.base.zfs.backups);
|
||||
|
||||
};
|
||||
zfs = {
|
||||
autoScrub.enable = true;
|
||||
trim.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
system.activationScripts =
|
||||
let
|
||||
ensureSystemExistsScript = lib.concatStringsSep "\n" (map (path: ''mkdir -p "${path}"'') config.chvp.base.zfs.ensureSystemExists);
|
||||
ensureHomeExistsScript = lib.concatStringsSep "\n" (map (path: ''mkdir -p "/home/charlotte/${path}"'') config.chvp.base.zfs.ensureHomeExists);
|
||||
ensureHomePermissionsScript = lib.concatStringsSep "\n" (map (path: ''chown charlotte:users /home/charlotte/${path}'') config.chvp.base.zfs.ensureHomeExists);
|
||||
in
|
||||
{
|
||||
ensureSystemPathsExist = {
|
||||
text = ensureSystemExistsScript;
|
||||
deps = [ "agenixNewGeneration" ];
|
||||
};
|
||||
ensureHomePathsExist = {
|
||||
text = ''
|
||||
mkdir -p /home/charlotte/
|
||||
${ensureHomeExistsScript}
|
||||
'';
|
||||
};
|
||||
agenixInstall.deps = [ "ensureSystemPathsExist" "ensureHomePathsExist" ];
|
||||
ensureHomePermissionsScript = {
|
||||
text = ''
|
||||
chown charlotte:users /home/charlotte
|
||||
${ensureHomePermissionsScript}
|
||||
'';
|
||||
deps = [ "agenixInstall" "users" "groups" ];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services =
|
||||
let
|
||||
makeLinkScript = config: lib.concatStringsSep "\n" (map (location: ''mkdir -p "${location.path}"'') config);
|
||||
systemLinksScript = makeLinkScript config.chvp.base.zfs.systemLinks;
|
||||
homeLinksScript = makeLinkScript config.chvp.base.zfs.homeLinks;
|
||||
in
|
||||
{
|
||||
make-system-links-destinations = {
|
||||
script = systemLinksScript;
|
||||
after = [ "local-fs.target" ];
|
||||
wants = [ "local-fs.target" ];
|
||||
before = [ "shutdown.target" "sysinit.target" ];
|
||||
conflicts = [ "shutdown.target" ];
|
||||
wantedBy = [ "sysinit.target" ];
|
||||
serviceConfig = {
|
||||
RemainAfterExit = "yes";
|
||||
Type = "oneshot";
|
||||
UMask = "0077";
|
||||
};
|
||||
unitConfig = {
|
||||
DefaultDependencies = "no";
|
||||
};
|
||||
};
|
||||
|
||||
make-home-links-destinations = {
|
||||
script = homeLinksScript;
|
||||
after = [ "local-fs.target" "make-system-links-destinations.service" ];
|
||||
wants = [ "local-fs.target" "make-system-links-destinations.service" ];
|
||||
before = [ "shutdown.target" "sysinit.target" ];
|
||||
conflicts = [ "shutdown.target" ];
|
||||
wantedBy = [ "sysinit.target" ];
|
||||
serviceConfig = {
|
||||
RemainAfterExit = "yes";
|
||||
Type = "oneshot";
|
||||
User = "charlotte";
|
||||
Group = "users";
|
||||
UMask = "0077";
|
||||
WorkingDirectory = "/home/charlotte";
|
||||
};
|
||||
unitConfig = {
|
||||
DefaultDependencies = "no";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.mounts =
|
||||
(map
|
||||
(location: {
|
||||
what = "/${location.type}${location.path}";
|
||||
where = "${location.path}";
|
||||
type = "none";
|
||||
options = "bind";
|
||||
after = [ "local-fs.target" "make-system-links-destinations.service" ];
|
||||
wants = [ "local-fs.target" "make-system-links-destinations.service" ];
|
||||
before = [ "umount.target" "sysinit.target" ];
|
||||
conflicts = [ "umount.target" ];
|
||||
wantedBy = [ "sysinit.target" ];
|
||||
unitConfig = {
|
||||
DefaultDependencies = "no";
|
||||
};
|
||||
})
|
||||
config.chvp.base.zfs.systemLinks) ++
|
||||
(map
|
||||
(location: {
|
||||
what = "/${location.type}/home/charlotte/${location.path}";
|
||||
where = "/home/charlotte/${location.path}";
|
||||
type = "none";
|
||||
options = "bind";
|
||||
after = [ "local-fs.target" "make-home-links-destinations.service" ];
|
||||
wants = [ "local-fs.target" "make-home-links-destinations.service" ];
|
||||
before = [ "umount.target" "sysinit.target" ];
|
||||
conflicts = [ "umount.target" ];
|
||||
wantedBy = [ "sysinit.target" ];
|
||||
unitConfig = {
|
||||
DefaultDependencies = "no";
|
||||
};
|
||||
})
|
||||
config.chvp.base.zfs.homeLinks);
|
||||
};
|
||||
}
|
127
modules/nixos/base/zsh/default.nix
Normal file
127
modules/nixos/base/zsh/default.nix
Normal file
|
@ -0,0 +1,127 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
base = (home: {
|
||||
home.packages = [ pkgs.autojump ];
|
||||
programs.zsh = {
|
||||
enable = true;
|
||||
autosuggestion.enable = true;
|
||||
syntaxHighlighting.enable = true;
|
||||
autocd = true;
|
||||
dotDir = ".config/zsh";
|
||||
history = {
|
||||
expireDuplicatesFirst = true;
|
||||
path = "${config.chvp.cachePrefix}${home}/.local/share/zsh/history";
|
||||
};
|
||||
initExtra = ''
|
||||
nshell() {
|
||||
local -a drvs
|
||||
for attr in "$@"; do
|
||||
drvs+=(nixpkgs#$attr)
|
||||
done
|
||||
local paths="$(nix build --no-link --print-out-paths $drvs)"
|
||||
for p in $paths; do
|
||||
export PATH="$p/bin:$PATH"
|
||||
done
|
||||
}
|
||||
|
||||
nrun() {
|
||||
local drv="$1"
|
||||
shift 1
|
||||
nix run nixpkgs#$drv $@
|
||||
}
|
||||
|
||||
nsrun() {
|
||||
local drv="$1"
|
||||
shift 1
|
||||
nix shell nixpkgs#$drv -c $@
|
||||
}
|
||||
|
||||
lightmode() {
|
||||
printf "\033]10;rgb:4c/4f/69\007"
|
||||
printf "\033]11;rgb:ef/f1/f5\007"
|
||||
printf "\033]17;rgb:cc/d0/da\007"
|
||||
printf "\033]19;rgb:4c/4f/69\007"
|
||||
printf "\033]4;0;rgb:5c/5f/77\007"
|
||||
printf "\033]4;1;rgb:d2/0f/39\007"
|
||||
printf "\033]4;2;rgb:40/a0/2b\007"
|
||||
printf "\033]4;3;rgb:df/8e/1d\007"
|
||||
printf "\033]4;4;rgb:1e/66/f5\007"
|
||||
printf "\033]4;5;rgb:ea/76/cb\007"
|
||||
printf "\033]4;6;rgb:17/92/99\007"
|
||||
printf "\033]4;7;rgb:ac/b0/be\007"
|
||||
printf "\033]4;8;rgb:6c/6f/85\007"
|
||||
printf "\033]4;9;rgb:d2/0f/39\007"
|
||||
printf "\033]4;10;rgb:40/a0/2b\007"
|
||||
printf "\033]4;11;rgb:df/8e/1d\007"
|
||||
printf "\033]4;12;rgb:1e/66/f5\007"
|
||||
printf "\033]4;13;rgb:ea/76/cb\007"
|
||||
printf "\033]4;14;rgb:17/92/99\007"
|
||||
printf "\033]4;15;rgb:bc/c0/cc\007"
|
||||
}
|
||||
|
||||
darkmode() {
|
||||
printf "\033]10;rgb:c6/d0/f5\007"
|
||||
printf "\033]11;rgb:30/34/46\007"
|
||||
printf "\033]17;rgb:41/45/59\007"
|
||||
printf "\033]19;rgb:c6/d0/f5\007"
|
||||
printf "\033]4;0;rgb:51/57/6d\007"
|
||||
printf "\033]4;1;rgb:e7/82/84\007"
|
||||
printf "\033]4;2;rgb:a6/d1/89\007"
|
||||
printf "\033]4;3;rgb:e5/c8/90\007"
|
||||
printf "\033]4;4;rgb:8c/aa/ee\007"
|
||||
printf "\033]4;5;rgb:f4/b8/e4\007"
|
||||
printf "\033]4;6;rgb:81/c8/be\007"
|
||||
printf "\033]4;7;rgb:b5/bf/e2\007"
|
||||
printf "\033]4;8;rgb:62/68/80\007"
|
||||
printf "\033]4;9;rgb:e7/82/84\007"
|
||||
printf "\033]4;10;rgb:a6/d1/89\007"
|
||||
printf "\033]4;11;rgb:e5/c8/90\007"
|
||||
printf "\033]4;12;rgb:8c/aa/ee\007"
|
||||
printf "\033]4;13;rgb:f4/b8/e4\007"
|
||||
printf "\033]4;14;rgb:81/c8/be\007"
|
||||
printf "\033]4;15;rgb:a5/ad/ce\007"
|
||||
}
|
||||
|
||||
TRAPUSR1() {
|
||||
lightmode
|
||||
}
|
||||
|
||||
TRAPUSR2() {
|
||||
darkmode
|
||||
}
|
||||
|
||||
if type darkman >/dev/null
|
||||
then
|
||||
if [ "$(darkman get)" = "dark" ]
|
||||
then
|
||||
darkmode
|
||||
else
|
||||
lightmode
|
||||
fi
|
||||
fi
|
||||
'';
|
||||
sessionVariables = { DEFAULT_USER = "charlotte"; };
|
||||
oh-my-zsh = {
|
||||
enable = true;
|
||||
plugins = [
|
||||
"autojump"
|
||||
"common-aliases"
|
||||
"extract"
|
||||
"history-substring-search"
|
||||
"git"
|
||||
"systemd"
|
||||
"tmux"
|
||||
];
|
||||
theme = "robbyrussell";
|
||||
};
|
||||
};
|
||||
});
|
||||
in
|
||||
{
|
||||
chvp.base.zfs.systemLinks = [{ path = "/root/.local/share/autojump"; type = "cache"; }];
|
||||
chvp.base.zfs.homeLinks = [{ path = ".local/share/autojump"; type = "cache"; }];
|
||||
home-manager.users.charlotte = { ... }: (base "/home/charlotte");
|
||||
home-manager.users.root = { ... }: (base "/root");
|
||||
programs.zsh.enable = true;
|
||||
}
|
12
modules/nixos/default.nix
Normal file
12
modules/nixos/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./base
|
||||
./development
|
||||
./games
|
||||
./graphical
|
||||
./programs
|
||||
./services
|
||||
];
|
||||
}
|
27
modules/nixos/development/android/default.nix
Normal file
27
modules/nixos/development/android/default.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.chvp.development.android.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.development.android.enable {
|
||||
chvp.base = {
|
||||
emacs.extraConfig = [
|
||||
''
|
||||
;; Groovy (gradle) language support
|
||||
(use-package groovy-mode
|
||||
:mode "\\.gradle\\'")
|
||||
|
||||
;; Kotlin language support
|
||||
(use-package kotlin-mode
|
||||
:mode "\\.kt\\'")
|
||||
''
|
||||
];
|
||||
zfs.homeLinks = [{ path = ".android"; type = "cache"; }];
|
||||
};
|
||||
programs.adb.enable = true;
|
||||
users.users.charlotte.extraGroups = [ "adbusers" ];
|
||||
};
|
||||
}
|
184
modules/nixos/development/default.nix
Normal file
184
modules/nixos/development/default.nix
Normal file
|
@ -0,0 +1,184 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./android
|
||||
./docker
|
||||
./git
|
||||
];
|
||||
|
||||
options.chvp.development.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.development.enable {
|
||||
chvp = {
|
||||
base.emacs.extraConfig = [
|
||||
''
|
||||
;; Editorconfig
|
||||
(use-package editorconfig
|
||||
:diminish (editorconfig-mode)
|
||||
:config
|
||||
(editorconfig-mode 1)
|
||||
)
|
||||
|
||||
;; R syntax support
|
||||
(use-package ess
|
||||
:init
|
||||
(load "ess-autoloads")
|
||||
:mode ("\\.r\\'" . ess-r-mode)
|
||||
:mode ("\\.R\\'" . ess-r-mode)
|
||||
)
|
||||
|
||||
;; Language server support
|
||||
(use-package eglot
|
||||
:demand t
|
||||
:general
|
||||
(lmap
|
||||
:keymaps '(prog-mode-map vue-mode-map)
|
||||
"SPC s" '(eglot :which-key "Add buffer to eglot")
|
||||
"SPC f" '(eglot-format :which-key "Format region")
|
||||
"SPC F" '(eglot-format :which-key "Format buffer")
|
||||
"SPC r" '(eglot-rename :which-key "Rename symbol")
|
||||
"SPC a" '(eglot-code-actions :which-key "Relevant local actions")
|
||||
"SPC n" '(flymake-goto-next-error :which-key "Next error")
|
||||
"SPC p" '(flymake-goto-prev-error :which-key "Previous error")
|
||||
)
|
||||
:hook (eglot-managed-mode . chvp--eglot-capf)
|
||||
:config
|
||||
(advice-add 'eglot-completion-at-point :around #'cape-wrap-buster)
|
||||
(defun chvp--eglot-capf ()
|
||||
(setq-local completion-at-point-functions
|
||||
(list (cape-super-capf
|
||||
#'eglot-completion-at-point
|
||||
#'tempel-complete)
|
||||
#'cape-file
|
||||
#'dabbrev-capf
|
||||
#'cape-line)))
|
||||
)
|
||||
|
||||
;; Forth syntax support
|
||||
(use-package forth-mode
|
||||
:mode ("\\.fs\\'" . forth-mode)
|
||||
:mode ("\\.fb\\'" . forth-block-mode)
|
||||
)
|
||||
|
||||
;; Markdown syntax support
|
||||
(use-package markdown-mode
|
||||
:commands (markdown-mode gfm-mode)
|
||||
:mode ("README\\.md\\'" . gfm-mode)
|
||||
:mode ("\\.md\\'" . markdown-mode)
|
||||
:mode ("\\.markdown\\'" . markdown-mode)
|
||||
)
|
||||
|
||||
;; Haskell language support
|
||||
(use-package haskell-mode
|
||||
:mode "\\.hs\\'"
|
||||
:config
|
||||
(require 'haskell-doc)
|
||||
)
|
||||
|
||||
;; Folding
|
||||
(use-package origami
|
||||
:hook (prog-mode . origami-mode)
|
||||
)
|
||||
|
||||
;; Python syntax support
|
||||
(use-package python-mode
|
||||
:mode "\\.py\\'"
|
||||
)
|
||||
|
||||
;; Ruby language support
|
||||
(use-package ruby-mode
|
||||
:ensure nil ;; Included with emacs
|
||||
:mode "\\.\\(?:cap\\|gemspec\\|irbrc\\|gemrc\\|rake\\|rb\\|ru\\|thor\\)\\'"
|
||||
:mode "\\(?:Brewfile\\|Capfile\\|Gemfile\\(?:\\.[a-zA-Z0-9._-]+\\)?\\|[rR]akefile\\)\\'"
|
||||
:custom
|
||||
(ruby-insert-encoding-magic-comment nil "Don't insert encoding magic comment")
|
||||
)
|
||||
|
||||
;; Rust language support
|
||||
(use-package rust-mode
|
||||
:mode "\\.rs\\'"
|
||||
)
|
||||
|
||||
;; TypeScript language support
|
||||
(use-package typescript-mode
|
||||
:mode "\\.ts\\'"
|
||||
)
|
||||
|
||||
;; Vue language support
|
||||
(use-package vue-mode
|
||||
:mode "\\.vue\\'"
|
||||
:custom
|
||||
(mmm-submode-decoration-level 0 "Don't color submodes differently")
|
||||
:config
|
||||
(defun vue-eglot-init-options ()
|
||||
(let ((tsdk-path "${pkgs.typescript}/lib/node_modules/typescript/lib"))
|
||||
`(:typescript (:tsdk ,tsdk-path
|
||||
:languageFeatures (:completion
|
||||
(:defaultTagNameCase "kebab"
|
||||
:defaultAttrNameCase "kebab"
|
||||
:getDocumentNameCasesRequest nil
|
||||
:getDocumentSelectionRequest nil)
|
||||
:diagnostics
|
||||
(:getDocumentVersionRequest nil))
|
||||
:documentFeatures (:documentFormatting
|
||||
(:defaultPrintWidth 100
|
||||
:getDocumentPrintWidthRequest nil)
|
||||
:documentSymbol t
|
||||
:documentColor t)))))
|
||||
(add-to-list 'eglot-server-programs `(vue-mode . ("${pkgs.vue-language-server}/bin/vue-language-server" "--stdio" :initializationOptions ,(vue-eglot-init-options))))
|
||||
(setq vue--front-tag-lang-regex
|
||||
(concat "<%s" ; The tag name
|
||||
"\\(?:" ; Zero of more of...
|
||||
"\\(?:\\s-+\\w+=[\"'].*?[\"']\\)" ; Any optional key-value pairs like type="foo/bar"
|
||||
"\\|\\(?:\\s-+scoped\\)" ; The optional "scoped" attribute
|
||||
"\\|\\(?:\\s-+module\\)" ; The optional "module" attribute
|
||||
"\\|\\(?:\\s-+setup\\)" ; The optional "setup" attribute
|
||||
"\\)*"
|
||||
"\\(?:\\s-+lang=[\"']%s[\"']\\)" ; The language specifier (required)
|
||||
"\\(?:" ; Zero of more of...
|
||||
"\\(?:\\s-+\\w+=[\"'].*?[\"']\\)" ; Any optional key-value pairs like type="foo/bar"
|
||||
"\\|\\(?:\\s-+scoped\\)" ; The optional "scoped" attribute
|
||||
"\\|\\(?:\\s-+module\\)" ; The optional "module" attribute
|
||||
"\\|\\(?:\\s-+setup\\)" ; The optional "setup" attribute
|
||||
"\\)*"
|
||||
" *>\n")) ; The end of the tag
|
||||
(setq vue--front-tag-regex
|
||||
(concat "<%s" ; The tag name
|
||||
"\\(?:" ; Zero of more of...
|
||||
"\\(?:\\s-+" vue--not-lang-key "[\"'][^\"']*?[\"']\\)" ; Any optional key-value pairs like type="foo/bar".
|
||||
;; ^ Disallow "lang" in k/v pairs to avoid matching regions with non-default languages
|
||||
"\\|\\(?:\\s-+scoped\\)" ; The optional "scoped" attribute
|
||||
"\\|\\(?:\\s-+module\\)" ; The optional "module" attribute
|
||||
"\\|\\(?:\\s-+setup\\)" ; The optional "setup" attribute
|
||||
"\\)*"
|
||||
"\\s-*>\n")) ; The end of the tag
|
||||
)
|
||||
|
||||
;; HTML (and HTML template) support
|
||||
(use-package web-mode
|
||||
:mode "\\.html\\'"
|
||||
:mode "\\.html\\.erb\\'"
|
||||
)
|
||||
|
||||
;; YAML syntax support
|
||||
(use-package yaml-mode
|
||||
:mode "\\.yml\\'"
|
||||
:mode "\\.yaml\\'"
|
||||
)
|
||||
''
|
||||
];
|
||||
development = {
|
||||
docker.enable = lib.mkDefault true;
|
||||
git.enable = lib.mkDefault true;
|
||||
};
|
||||
};
|
||||
|
||||
users.users.charlotte.extraGroups = [ "dialout" "uucp" ];
|
||||
|
||||
boot.kernel.sysctl."fs.inotify.max_user_watches" = 524288;
|
||||
};
|
||||
}
|
20
modules/nixos/development/docker/default.nix
Normal file
20
modules/nixos/development/docker/default.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.development.docker.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.development.docker.enable {
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
extraOptions = "--data-root ${config.chvp.dataPrefix}/var/lib/docker";
|
||||
storageDriver = "zfs";
|
||||
};
|
||||
|
||||
environment.systemPackages = [ pkgs.docker-compose ];
|
||||
|
||||
users.users.charlotte.extraGroups = [ "docker" ];
|
||||
};
|
||||
}
|
94
modules/nixos/development/git/default.nix
Normal file
94
modules/nixos/development/git/default.nix
Normal file
|
@ -0,0 +1,94 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.development.git = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
email = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "charlotte@vanpetegem.be";
|
||||
example = "charlotte@vanpetegem.be";
|
||||
description = ''
|
||||
Default email set in global git config.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
base = {
|
||||
programs.git = {
|
||||
enable = true;
|
||||
lfs.enable = true;
|
||||
extraConfig = {
|
||||
branch.autosetuprebase = "always";
|
||||
github.user = "chvp";
|
||||
merge.conflictStyle = "diff3";
|
||||
pull.rebase = true;
|
||||
rerere.enabled = true;
|
||||
tag.gpgSign = true;
|
||||
};
|
||||
ignores = [
|
||||
".data"
|
||||
".direnv"
|
||||
".envrc"
|
||||
".dir-locals.el"
|
||||
];
|
||||
signing = {
|
||||
key = "charlotte@vanpetegem.me";
|
||||
signByDefault = config.chvp.graphical.enable;
|
||||
};
|
||||
userEmail = config.chvp.development.git.email;
|
||||
userName = "Charlotte Van Petegem";
|
||||
};
|
||||
};
|
||||
in
|
||||
lib.mkIf config.chvp.development.git.enable {
|
||||
chvp.base.emacs.extraConfig = [
|
||||
''
|
||||
;; Magit GitHub/GitLab integration
|
||||
(use-package forge
|
||||
:after magit)
|
||||
|
||||
;; Git integration
|
||||
(use-package magit
|
||||
:init
|
||||
(setq forge-add-default-bindings nil)
|
||||
:general
|
||||
(lmap
|
||||
"g" '(:ignore t :which-key "git")
|
||||
"gs" '(magit-status :which-key "status")
|
||||
)
|
||||
)
|
||||
|
||||
;; Project management
|
||||
(use-package project
|
||||
:custom
|
||||
(project-switch-commands
|
||||
'(
|
||||
(project-find-file "find file")
|
||||
(consult-ripgrep "find regexp" ?r)
|
||||
(project-eshell "eshell")
|
||||
)
|
||||
"Change default actions when switching project"
|
||||
)
|
||||
:general
|
||||
(lmap
|
||||
"p" '(:ignore t :which-key "project")
|
||||
"pf" '(project-find-file :which-key "find")
|
||||
"pp" '(project-switch-project :which-key "switch")
|
||||
"pr" '(project-query-replace-regexp :which-key "replace")
|
||||
"ps" '(consult-ripgrep :search "incsearch")
|
||||
"pS" '(project-find-regexp :which-key "search")
|
||||
"p!" '(project-shell-command :which-key "command")
|
||||
"p&" '(project-async-shell-command :which-key "task")
|
||||
)
|
||||
)
|
||||
''
|
||||
];
|
||||
home-manager.users.charlotte = { ... }: base;
|
||||
home-manager.users.root = { ... }: base;
|
||||
};
|
||||
}
|
24
modules/nixos/games/default.nix
Normal file
24
modules/nixos/games/default.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./minecraft
|
||||
./mumble
|
||||
./particles
|
||||
./steam
|
||||
./tetris
|
||||
];
|
||||
|
||||
options.chvp.games.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.games.enable {
|
||||
chvp.games = {
|
||||
minecraft.client = lib.mkDefault false;
|
||||
mumble.enable = lib.mkDefault true;
|
||||
steam.enable = lib.mkDefault true;
|
||||
};
|
||||
};
|
||||
}
|
32
modules/nixos/games/minecraft/default.nix
Normal file
32
modules/nixos/games/minecraft/default.nix
Normal file
|
@ -0,0 +1,32 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.games.minecraft = {
|
||||
client = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
server = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (config.chvp.games.minecraft.client || config.chvp.games.minecraft.server) {
|
||||
home-manager.users.charlotte = lib.mkIf config.chvp.games.minecraft.client ({ ... }: {
|
||||
home.packages = [ pkgs.minecraft ];
|
||||
});
|
||||
chvp.base = {
|
||||
zfs.homeLinks = lib.optional config.chvp.games.minecraft.client { path = ".minecraft"; type = "cache"; };
|
||||
nix.unfreePackages =
|
||||
(lib.optional config.chvp.games.minecraft.client "minecraft-launcher") ++
|
||||
(lib.optional config.chvp.games.minecraft.server "minecraft-server");
|
||||
};
|
||||
services.minecraft-server = lib.mkIf config.chvp.games.minecraft.server {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/minecraft-server";
|
||||
eula = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
}
|
19
modules/nixos/games/mumble/default.nix
Normal file
19
modules/nixos/games/mumble/default.nix
Normal file
|
@ -0,0 +1,19 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.games.mumble.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.games.mumble.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".config/Mumble"; type = "data"; }
|
||||
{ path = ".local/share/Mumble"; type = "data"; }
|
||||
];
|
||||
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = with pkgs; [ mumble ];
|
||||
};
|
||||
};
|
||||
}
|
24
modules/nixos/games/particles/default.nix
Normal file
24
modules/nixos/games/particles/default.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
particles = pkgs.fetchgit {
|
||||
url = "https://git.zeus.gent/midgard/particles.git";
|
||||
sha256 = "0weSBjhSS0XuII5yZXWYUJpPOhetFJKbcsS8WWpodhs=";
|
||||
};
|
||||
in
|
||||
{
|
||||
options.chvp.games.particles.server = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.games.particles.server {
|
||||
chvp.services.nginx.hosts = [{
|
||||
fqdn = "particles.vanpetegem.me";
|
||||
options = {
|
||||
root = "${particles}/public";
|
||||
locations."/".index = "index.html";
|
||||
};
|
||||
}];
|
||||
};
|
||||
}
|
29
modules/nixos/games/steam/default.nix
Normal file
29
modules/nixos/games/steam/default.nix
Normal file
|
@ -0,0 +1,29 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.games.steam.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.games.steam.enable {
|
||||
hardware.graphics = {
|
||||
enable32Bit = true;
|
||||
extraPackages = with pkgs.pkgsi686Linux; [ libva ];
|
||||
};
|
||||
services.pipewire.alsa.support32Bit = true;
|
||||
chvp.base = {
|
||||
nix.unfreePackages = [ "steam" "steam-original" "steam-runtime" "steam-run" ];
|
||||
zfs.homeLinks = [
|
||||
{ path = ".paradoxlauncher"; type = "cache"; }
|
||||
{ path = ".steam"; type = "cache"; }
|
||||
{ path = ".local/share/Steam"; type = "cache"; }
|
||||
{ path = ".local/share/Paradox Interactive"; type = "cache"; }
|
||||
];
|
||||
};
|
||||
|
||||
home-manager.users.charlotte = { pkgs, ... }: {
|
||||
home.packages = [ pkgs.steam pkgs.protontricks pkgs.wine ];
|
||||
};
|
||||
};
|
||||
}
|
18
modules/nixos/games/tetris/default.nix
Normal file
18
modules/nixos/games/tetris/default.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.games.tetris.server = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.games.tetris.server {
|
||||
chvp.services.nginx.hosts = [{
|
||||
fqdn = "tetris.vanpetegem.me";
|
||||
options = {
|
||||
root = "${pkgs.tetris}";
|
||||
locations."/".index = "index.html";
|
||||
};
|
||||
}];
|
||||
};
|
||||
}
|
7
modules/nixos/graphical/compositor/color-picker.nix
Normal file
7
modules/nixos/graphical/compositor/color-picker.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{ pkgs }:
|
||||
|
||||
pkgs.writeShellScriptBin "color_picker" ''
|
||||
color=$(${pkgs.grim}/bin/grim -t png -g "$(${pkgs.slurp}/bin/slurp -p)" - | ${pkgs.imagemagick}/bin/convert png:- -unique-colors txt:- | grep -o '#[A-F0-9]\+')
|
||||
|
||||
${pkgs.sway}/bin/swaymsg exec -- "echo -n '$color' | ${pkgs.wl-clipboard}/bin/wl-copy --foreground"
|
||||
''
|
523
modules/nixos/graphical/compositor/default.nix
Normal file
523
modules/nixos/graphical/compositor/default.nix
Normal file
|
@ -0,0 +1,523 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
launcher = import ./launcher.nix { inherit pkgs; stdenv = pkgs.stdenv; };
|
||||
color-picker = import ./color-picker.nix { inherit pkgs; };
|
||||
screenshot = import ./screenshot.nix { inherit pkgs; };
|
||||
mail-status = pkgs.writeShellScript "mail-status" ''
|
||||
mails=$(${pkgs.mblaze}/bin/mlist -N ~/mail/*/INBOX | ${pkgs.coreutils}/bin/wc -l)
|
||||
if [ "$mails" -gt 0 ]
|
||||
then
|
||||
echo "{ \"class\": \"has-mail\", \"text\": \"📬 $mails\" }"
|
||||
else
|
||||
echo "{ \"text\": \"📭\" }"
|
||||
fi
|
||||
'';
|
||||
lock = pkgs.writeShellScript "lock" ''
|
||||
if [ "$(darkman get)" == "light" ]
|
||||
then
|
||||
${pkgs.swaylock}/bin/swaylock -fF -c eff1f5
|
||||
else
|
||||
${pkgs.swaylock}/bin/swaylock -fF -c 303446
|
||||
fi
|
||||
'';
|
||||
baseWrapper = pkgs.writeShellScriptBin "river" ''
|
||||
export XDG_SESSION_TYPE=wayland
|
||||
export XDG_CURRENT_DESKTOP=river
|
||||
export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
|
||||
export QT_AUTO_SCREEN_SCALE_FACTOR=0
|
||||
export QT_SCALE_FACTOR=1
|
||||
export GDK_SCALE=1
|
||||
export GDK_DPI_SCALE=1
|
||||
export MOZ_ENABLE_WAYLAND=1
|
||||
export XCURSOR_SIZE=24
|
||||
export _JAVA_AWT_WM_NONREPARENTING=1
|
||||
if [ "$DBUS_SESSION_BUS_ADDRESS" ]; then
|
||||
export DBUS_SESSION_BUS_ADDRESS
|
||||
exec ${pkgs.river}/bin/river
|
||||
else
|
||||
exec ${pkgs.dbus}/bin/dbus-run-session ${pkgs.river}/bin/river
|
||||
fi
|
||||
'';
|
||||
river = pkgs.symlinkJoin {
|
||||
name = "river-${pkgs.river.version}";
|
||||
paths = [ baseWrapper pkgs.river ];
|
||||
strictDeps = false;
|
||||
nativeBuildInputs = with pkgs; [ makeWrapper wrapGAppsHook ];
|
||||
buildInputs = with pkgs; [ gdk-pixbuf glib gtk3 ];
|
||||
dontWrapGApps = true;
|
||||
postBuild = ''
|
||||
gappsWrapperArgsHook
|
||||
|
||||
wrapProgram $out/bin/river "''${gappsWrapperArgs[@]}"
|
||||
'';
|
||||
};
|
||||
river-init = pkgs.writeShellScript "river-init" ''
|
||||
riverctl map normal Super Return spawn foot
|
||||
riverctl map normal Super D spawn 'foot --app-id launcher -- zsh -ic ${launcher}/bin/launcher'
|
||||
riverctl map normal None Menu spawn 'foot --app-id launcher -- zsh -ic ${launcher}/bin/launcher'
|
||||
|
||||
riverctl map normal Super C spawn ${lock}
|
||||
|
||||
riverctl map normal Super+Shift C close
|
||||
|
||||
riverctl map normal Super+Shift E exit
|
||||
|
||||
riverctl map normal Super J focus-view next
|
||||
riverctl map normal Super K focus-view previous
|
||||
|
||||
riverctl map normal Super+Shift J swap next
|
||||
riverctl map normal Super+Shift K swap previous
|
||||
|
||||
riverctl map normal Super H focus-output next
|
||||
riverctl map normal Super L focus-output previous
|
||||
|
||||
riverctl map normal Super+Shift H send-to-output -current-tags next
|
||||
riverctl map normal Super+Shift L send-to-output -current-tags previous
|
||||
|
||||
riverctl map normal Super F zoom
|
||||
riverctl map normal Super+Shift F toggle-fullscreen
|
||||
|
||||
riverctl map normal Super+Control H send-layout-cmd rivertile "main-ratio -0.05"
|
||||
riverctl map normal Super+Control L send-layout-cmd rivertile "main-ratio +0.05"
|
||||
|
||||
riverctl map normal Super+Control+Shift H send-layout-cmd rivertile "main-count +1"
|
||||
riverctl map normal Super+Control+Shift L send-layout-cmd rivertile "main-count -1"
|
||||
|
||||
riverctl map normal Super+Alt H move left 100
|
||||
riverctl map normal Super+Alt J move down 100
|
||||
riverctl map normal Super+Alt K move up 100
|
||||
riverctl map normal Super+Alt L move right 100
|
||||
|
||||
riverctl map normal Super+Alt+Control H snap left
|
||||
riverctl map normal Super+Alt+Control J snap down
|
||||
riverctl map normal Super+Alt+Control K snap up
|
||||
riverctl map normal Super+Alt+Control L snap right
|
||||
|
||||
riverctl map normal Super+Alt+Shift H resize horizontal -100
|
||||
riverctl map normal Super+Alt+Shift J resize vertical 100
|
||||
riverctl map normal Super+Alt+Shift K resize vertical -100
|
||||
riverctl map normal Super+Alt+Shift L resize horizontal 100
|
||||
|
||||
riverctl map normal Super Space toggle-float
|
||||
|
||||
riverctl map-pointer normal Super BTN_LEFT move-view
|
||||
riverctl map-pointer normal Super BTN_RIGHT resize-view
|
||||
|
||||
for i in $(seq 1 9)
|
||||
do
|
||||
tags=$((1 << ($i - 1)))
|
||||
riverctl map normal Super $i set-focused-tags $tags
|
||||
riverctl map normal Super+Shift $i set-view-tags $tags
|
||||
riverctl map normal Super+Control $i toggle-focused-tags $tags
|
||||
riverctl map normal Super+Shift+Control $i toggle-view-tags $tags
|
||||
done
|
||||
|
||||
all_tags=$(((1 << 32) - 1))
|
||||
riverctl map normal Super 0 set-focused-tags $all_tags
|
||||
riverctl map normal Super+Shift 0 set-view-tags $all_tags
|
||||
|
||||
riverctl map normal Super Up send-layout-cmd rivertile "main-location top"
|
||||
riverctl map normal Super Right send-layout-cmd rivertile "main-location right"
|
||||
riverctl map normal Super Down send-layout-cmd rivertile "main-location bottom"
|
||||
riverctl map normal Super Left send-layout-cmd rivertile "main-location left"
|
||||
|
||||
riverctl map normal None XF86AudioRaiseVolume spawn '${pkgs.pamixer}/bin/pamixer -i 5'
|
||||
riverctl map normal None XF86AudioLowerVolume spawn '${pkgs.pamixer}/bin/pamixer -d 5'
|
||||
riverctl map normal None XF86AudioMute spawn '${pkgs.pamixer}/bin/pamixer --toggle-mute'
|
||||
riverctl map normal None XF86MonBrightnessDown spawn '${pkgs.brightnessctl}/bin/brightnessctl s -- -5%'
|
||||
riverctl map normal None XF86MonBrightnessUp spawn '${pkgs.brightnessctl}/bin/brightnessctl s -- +5%'
|
||||
|
||||
riverctl map normal None Print spawn '${screenshot}/bin/screenshot'
|
||||
riverctl map normal Alt Print spawn '${screenshot}/bin/screenshot -d'
|
||||
riverctl map normal Shift Print spawn '${screenshot}/bin/screenshot -r'
|
||||
riverctl map normal Alt+Shift Print spawn '${screenshot}/bin/screenshot -r -d'
|
||||
|
||||
riverctl rule-add -app-id launcher float
|
||||
riverctl rule-add -app-id be.ugent.objprog.ugentopoly.Ugentopoly float
|
||||
riverctl rule-add -title "Quick Format Citation" float
|
||||
|
||||
riverctl rule-add ssd
|
||||
|
||||
riverctl default-layout rivertile
|
||||
rivertile -view-padding 0 -outer-padding 0 &
|
||||
|
||||
riverctl default-attach-mode bottom
|
||||
riverctl background-color 0xacb0be
|
||||
riverctl border-color-focused 0x04e5e5
|
||||
riverctl border-color-unfocused 0xdce0e8
|
||||
riverctl border-color-urgent 0xea76cb
|
||||
riverctl border-width 1
|
||||
riverctl focus-follows-cursor normal
|
||||
riverctl hide-cursor when-typing enabled
|
||||
riverctl set-cursor-warp on-output-change
|
||||
riverctl xcursor-theme Catppuccin-Latte-Light-Cursors 24
|
||||
|
||||
riverctl keyboard-layout -variant altgr-intl -options compose:caps us
|
||||
|
||||
configure_touchpads() {
|
||||
riverctl list-inputs | grep 'type: pointer' -B 1 | grep -vE 'type: pointer|^--$' | xargs -I '{}' riverctl input '{}' $@
|
||||
}
|
||||
|
||||
configure_touchpads drag enabled
|
||||
configure_touchpads tap enabled
|
||||
configure_touchpads scroll-method two-finger
|
||||
|
||||
${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE XCURSOR_SIZE QT_QPA_PLATFORM_THEME QT_STYLE_OVERRIDE QT_PLUGIN_PATH QTWEBKIT_PLUGIN_PATH GDK_PIXBUF_MODULE_FILE XDG_DATA_DIRS GIO_EXTRA_MODULES PATH
|
||||
systemctl --user start river-session.target
|
||||
systemctl --user start tray.target
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.chvp.graphical.compositor.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.compositor.enable {
|
||||
services = {
|
||||
dbus.packages = with pkgs; [ dconf ];
|
||||
greetd = {
|
||||
enable = true;
|
||||
settings =
|
||||
let
|
||||
river-run = pkgs.writeShellScript "river-run" ''
|
||||
exec zsh -c "systemd-cat -t river ${river}/bin/river"
|
||||
'';
|
||||
in
|
||||
{
|
||||
default_session = {
|
||||
command = "${pkgs.greetd.greetd}/bin/agreety --cmd ${river-run}";
|
||||
};
|
||||
initial_session = {
|
||||
command = "${river-run}";
|
||||
user = "charlotte";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
security.pam.services.swaylock = { };
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
extraPortals = [ pkgs.xdg-desktop-portal-gtk pkgs.xdg-desktop-portal-wlr ];
|
||||
config.preferred = {
|
||||
default = "gtk";
|
||||
"org.freedesktop.impl.portal.Screencast" = "wlr";
|
||||
};
|
||||
};
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = [
|
||||
river
|
||||
color-picker
|
||||
screenshot
|
||||
pkgs.wf-recorder
|
||||
pkgs.wl-clipboard
|
||||
pkgs.wl-mirror
|
||||
];
|
||||
programs = {
|
||||
waybar = {
|
||||
enable = true;
|
||||
settings = {
|
||||
mainBar = {
|
||||
spacing = 2;
|
||||
modules-left = [ "river/tags" ];
|
||||
modules-center = [ "river/window" ];
|
||||
modules-right = [ "idle_inhibitor" "network#wlp0s20f3" "network#enp0s13f0u2u2" "battery" "backlight" "mpris" "pulseaudio" "custom/mail-status" "clock" "tray" ];
|
||||
backlight = {
|
||||
format = "{percent}% {icon}";
|
||||
format-icons = [ "🌑" "🌒" "🌓" "🌔" "🌕" ];
|
||||
on-scroll-up = "${pkgs.brightnessctl}/bin/brightnessctl s -- +5%";
|
||||
on-scroll-down = "${pkgs.brightnessctl}/bin/brightnessctl s -- -5%";
|
||||
};
|
||||
battery = {
|
||||
states = {
|
||||
good = 90;
|
||||
warning = 30;
|
||||
critical = 15;
|
||||
};
|
||||
format = "{capacity}% {icon}";
|
||||
format-charging = "{capacity}% ";
|
||||
format-plugged = "";
|
||||
format-alt = "{time} {icon}";
|
||||
format-icons = [ "" "" "" "" "" ];
|
||||
};
|
||||
clock.format = " {:%a %d/%m %H:%M}";
|
||||
"custom/mail-status" = {
|
||||
exec = "${mail-status}";
|
||||
return-type = "json";
|
||||
interval = 1;
|
||||
on-click = "${pkgs.isync}/bin/mbsync -a && ${config.chvp.base.emacs.package}/bin/emacsclient --eval \"(mu4e-update-index)\"";
|
||||
};
|
||||
idle_inhibitor = {
|
||||
format = "{icon}";
|
||||
format-icons = {
|
||||
activated = "";
|
||||
deactivated = "";
|
||||
};
|
||||
};
|
||||
mpris = {
|
||||
player = "firefox";
|
||||
format = "{status_icon} {artist} - {title}";
|
||||
status-icons = {
|
||||
playing = "▶";
|
||||
paused = "";
|
||||
stopped = "";
|
||||
};
|
||||
};
|
||||
"network#wlp0s20f3" = {
|
||||
interface = "wlp0s20f3";
|
||||
format-wifi = "{essid} ";
|
||||
format-ethernet = "{ipaddr}/{cidr} ";
|
||||
tooltip-format = "{ifname} via {gwaddr} ";
|
||||
format-linked = "{ifname} (No IP) ";
|
||||
format-disconnected = "";
|
||||
format-alt = "{ifname}: {ipaddr}/{cidr}";
|
||||
};
|
||||
"network#enp0s13f0u2u2" = {
|
||||
interface = "enp0s13f0u2u2";
|
||||
format-wifi = "{essid} ";
|
||||
format-ethernet = "{ipaddr}/{cidr} ";
|
||||
tooltip-format = "{ifname} via {gwaddr} ";
|
||||
format-linked = "{ifname} (No IP) ";
|
||||
format-disconnected = "";
|
||||
format-alt = "{ifname}: {ipaddr}/{cidr}";
|
||||
};
|
||||
pulseaudio = {
|
||||
format = "{volume}% {icon} {format_source}";
|
||||
format-bluetooth = "{volume}% {icon} {format_source}";
|
||||
format-bluetooth-muted = " {icon} {format_source}";
|
||||
format-muted = " {format_source}";
|
||||
format-source = "{volume}% ";
|
||||
format-source-muted = "";
|
||||
format-icons = {
|
||||
headphone = "";
|
||||
hands-free = "";
|
||||
headset = "";
|
||||
phone = "";
|
||||
portable = "";
|
||||
car = "";
|
||||
default = [ "" "" "" ];
|
||||
};
|
||||
on-click = "${pkgs.pamixer}/bin/pamixer -t";
|
||||
on-click-right = "${pkgs.pamixer}/bin/pamixer --default-source -t";
|
||||
on-click-middle = "${pkgs.pavucontrol}/bin/pavucontrol";
|
||||
};
|
||||
tray.spacing = 2;
|
||||
};
|
||||
};
|
||||
style = ''
|
||||
@import "colors.css";
|
||||
|
||||
* {
|
||||
font-family: Hack, monospace;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#window, #idle_inhibitor, #network, #battery, #backlight, #mpris, #pulseaudio, #custom-mail-status, #clock, #tray {
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
background-color: @surface0;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
button:hover {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
background-color: @base;
|
||||
color: @text;
|
||||
}
|
||||
|
||||
#backlight {
|
||||
color: @sky;
|
||||
}
|
||||
|
||||
#battery {
|
||||
color: @green;
|
||||
}
|
||||
#battery.good {
|
||||
color: @sky;
|
||||
}
|
||||
#battery.warning {
|
||||
color: @yellow;
|
||||
}
|
||||
#battery.critical {
|
||||
color: @pink;
|
||||
}
|
||||
|
||||
#custom-mail-status.has-mail {
|
||||
color: @sky;
|
||||
}
|
||||
|
||||
#idle_inhibitor.activated {
|
||||
color: @sky;
|
||||
}
|
||||
|
||||
#pulseaudio {
|
||||
color: @yellow;
|
||||
}
|
||||
|
||||
#tags button {
|
||||
padding: 0;
|
||||
box-shadow: inset 0 -3px transparent
|
||||
color: @text;
|
||||
}
|
||||
#tags button.occupied {
|
||||
background-color: @surface1;
|
||||
}
|
||||
#tags button.focused {
|
||||
color: @sky;
|
||||
}
|
||||
#tags button.urgent {
|
||||
color: @pink;
|
||||
}
|
||||
#tags button:hover {
|
||||
box-shadow: inset 0 -3px @text;
|
||||
}
|
||||
'';
|
||||
systemd.enable = true;
|
||||
};
|
||||
zsh.initExtra = ''
|
||||
rs() {
|
||||
riverctl spawn "$*"
|
||||
}
|
||||
'';
|
||||
};
|
||||
services = {
|
||||
kanshi = {
|
||||
enable = true;
|
||||
systemdTarget = "river-session.target";
|
||||
settings = [
|
||||
{
|
||||
profile = {
|
||||
name = "home-undocked";
|
||||
outputs = [
|
||||
{ criteria = "AU Optronics 0x2036 Unknown"; position = "0,0"; mode = "2560x1440"; scale = 1.0; }
|
||||
];
|
||||
};
|
||||
}
|
||||
{
|
||||
profile = {
|
||||
name = "home-docked";
|
||||
outputs = [
|
||||
{ criteria = "AU Optronics 0x2036 Unknown"; position = "0,0"; mode = "2560x1440"; scale = 1.0; }
|
||||
{ criteria = "Dell Inc. DELL U2718Q FN84K01T095L"; position = "2560,0"; mode = "3840x2160"; scale = 1.0; }
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
mako = {
|
||||
enable = true;
|
||||
font = "Hack Regular 9";
|
||||
};
|
||||
swayidle = {
|
||||
enable = true;
|
||||
systemdTarget = "river-session.target";
|
||||
events = [{ event = "before-sleep"; command = "${lock}"; }];
|
||||
timeouts = [
|
||||
{ timeout = 150; command = "${pkgs.wlopm}/bin/wlopm --off '*'"; resumeCommand = "${pkgs.wlopm}/bin/wlopm --on '*'"; }
|
||||
{ timeout = 300; command = "${lock}"; }
|
||||
];
|
||||
};
|
||||
};
|
||||
systemd.user.targets = {
|
||||
river-session.Unit = {
|
||||
Description = "river compositor session";
|
||||
BindsTo = [ "graphical-session.target" ];
|
||||
Wants = [ "graphical-session-pre.target" ];
|
||||
After = [ "graphical-session-pre.target" ];
|
||||
};
|
||||
tray.Unit = {
|
||||
Description = "tray target";
|
||||
Wants = [ "graphical-session.target" ];
|
||||
After = [ "graphical-session.target" ];
|
||||
};
|
||||
};
|
||||
xdg.configFile = {
|
||||
"river/init" = {
|
||||
source = river-init;
|
||||
onChange = ''
|
||||
if [ -d /run/user/$UID ]
|
||||
then
|
||||
WAYLAND_DISPLAY="$(${pkgs.findutils}/bin/find /run/user/$UID -mindepth 1 -maxdepth 1 -type s -name wayland-\*)"
|
||||
if [ -S "WAYLAND_DISPLAY" ]
|
||||
then
|
||||
${river-init}
|
||||
fi
|
||||
fi
|
||||
'';
|
||||
};
|
||||
"waybar/frappe.css".text = ''
|
||||
@define-color base #303446;
|
||||
@define-color mantle #292c3c;
|
||||
@define-color crust #232634;
|
||||
|
||||
@define-color text #c6d0f5;
|
||||
@define-color subtext0 #a5adce;
|
||||
@define-color subtext1 #b5bfe2;
|
||||
|
||||
@define-color surface0 #414559;
|
||||
@define-color surface1 #51576d;
|
||||
@define-color surface2 #626880;
|
||||
|
||||
@define-color overlay0 #737994;
|
||||
@define-color overlay1 #838ba7;
|
||||
@define-color overlay2 #949cbb;
|
||||
|
||||
@define-color blue #8caaee;
|
||||
@define-color lavender #babbf1;
|
||||
@define-color sapphire #85c1dc;
|
||||
@define-color sky #99d1db;
|
||||
@define-color teal #81c8be;
|
||||
@define-color green #a6d189;
|
||||
@define-color yellow #e5c890;
|
||||
@define-color peach #ef9f76;
|
||||
@define-color maroon #ea999c;
|
||||
@define-color red #e78284;
|
||||
@define-color mauve #ca9ee6;
|
||||
@define-color pink #f4b8e4;
|
||||
@define-color flamingo #eebebe;
|
||||
@define-color rosewater #f2d5cf;
|
||||
'';
|
||||
"waybar/latte.css".text = ''
|
||||
@define-color base #eff1f5;
|
||||
@define-color mantle #e6e9ef;
|
||||
@define-color crust #dce0e8;
|
||||
|
||||
@define-color text #4c4f69;
|
||||
@define-color subtext0 #6c6f85;
|
||||
@define-color subtext1 #5c5f77;
|
||||
|
||||
@define-color surface0 #ccd0da;
|
||||
@define-color surface1 #bcc0cc;
|
||||
@define-color surface2 #acb0be;
|
||||
|
||||
@define-color overlay0 #9ca0b0;
|
||||
@define-color overlay1 #8c8fa1;
|
||||
@define-color overlay2 #7c7f93;
|
||||
|
||||
@define-color blue #1e66f5;
|
||||
@define-color lavender #7287fd;
|
||||
@define-color sapphire #209fb5;
|
||||
@define-color sky #04a5e5;
|
||||
@define-color teal #179299;
|
||||
@define-color green #40a02b;
|
||||
@define-color yellow #df8e1d;
|
||||
@define-color peach #fe640b;
|
||||
@define-color maroon #e64553;
|
||||
@define-color red #d20f39;
|
||||
@define-color mauve #8839ef;
|
||||
@define-color pink #ea76cb;
|
||||
@define-color flamingo #dd7878;
|
||||
@define-color rosewater #dc8a78;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
24
modules/nixos/graphical/compositor/launcher.nix
Normal file
24
modules/nixos/graphical/compositor/launcher.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{ pkgs, stdenv }:
|
||||
let
|
||||
script = pkgs.substituteAll {
|
||||
src = ./launcher.zsh;
|
||||
inherit (pkgs)
|
||||
fzy
|
||||
jq
|
||||
libqalculate
|
||||
nix
|
||||
pass
|
||||
slurp
|
||||
uni
|
||||
zsh
|
||||
;
|
||||
wfRecorder = pkgs.wf-recorder;
|
||||
wlClipboard = pkgs.wl-clipboard;
|
||||
xdgUserDirs = pkgs.xdg-user-dirs;
|
||||
};
|
||||
in
|
||||
pkgs.runCommand "launcher" { } ''
|
||||
mkdir -p $out/bin
|
||||
cp ${script} $out/bin/launcher
|
||||
chmod +x $out/bin/launcher
|
||||
''
|
61
modules/nixos/graphical/compositor/launcher.zsh
Normal file
61
modules/nixos/graphical/compositor/launcher.zsh
Normal file
|
@ -0,0 +1,61 @@
|
|||
#!@zsh@/bin/zsh
|
||||
|
||||
_sighandler() {
|
||||
kill -INT "$child" 2>/dev/null
|
||||
}
|
||||
|
||||
calc_options() {
|
||||
echo "calc "
|
||||
}
|
||||
|
||||
calc() {
|
||||
if [ -n "$1" ]
|
||||
then
|
||||
@libqalculate@/bin/qalc "$1"
|
||||
sleep 5
|
||||
else
|
||||
@libqalculate@/bin/qalc
|
||||
fi
|
||||
}
|
||||
|
||||
emoji_options() {
|
||||
@uni@/bin/uni emoji all | sed "s/^/emoji /"
|
||||
}
|
||||
|
||||
emoji() {
|
||||
char=$(echo -n "$1" | sed "s/^\([^ ]*\) .*/\1/")
|
||||
riverctl spawn "echo -n $char | @wlClipboard@/bin/wl-copy --foreground"
|
||||
}
|
||||
|
||||
nrun_options() {
|
||||
echo "nrun "
|
||||
}
|
||||
|
||||
nrun() {
|
||||
riverctl spawn "@nix@/bin/nix run nixpkgs\#$1"
|
||||
}
|
||||
|
||||
run_options() {
|
||||
print -rl -- ''${(ko)commands} | grep -v "^\\." | sed "s/^/run /"
|
||||
}
|
||||
|
||||
run() {
|
||||
riverctl spawn $1
|
||||
}
|
||||
|
||||
systemctl_options() {
|
||||
echo systemctl hibernate
|
||||
echo systemctl poweroff
|
||||
echo systemctl reboot
|
||||
echo systemctl suspend
|
||||
}
|
||||
|
||||
CHOSEN=$(cat <(systemctl_options) <(nrun_options) <(run_options) <(calc_options) <(emoji_options) | @fzy@/bin/fzy --lines 80 | tail -n1)
|
||||
|
||||
if [ -n "$CHOSEN" ]
|
||||
then
|
||||
PREFIX=$(echo $CHOSEN | sed "s/^\([^ ]*\) .*/\1/g")
|
||||
WORD=$(echo $CHOSEN | sed "s/^[^ ]* \(.*\)/\1/g")
|
||||
|
||||
$PREFIX $WORD
|
||||
fi
|
36
modules/nixos/graphical/compositor/screenshot.nix
Normal file
36
modules/nixos/graphical/compositor/screenshot.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
{ pkgs }:
|
||||
|
||||
pkgs.writeShellScriptBin "screenshot" ''
|
||||
while getopts ":rd" opt
|
||||
do
|
||||
case "''${opt}" in
|
||||
r)
|
||||
remote=true
|
||||
;;
|
||||
d)
|
||||
delay=true
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
dims="$(${pkgs.slurp}/bin/slurp)"
|
||||
|
||||
if [[ -n "$delay" ]]
|
||||
then
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
if [[ -n "$remote" ]]
|
||||
then
|
||||
name=$(${pkgs.util-linux}/bin/uuidgen).png
|
||||
${pkgs.grim}/bin/grim -t png -g "$dims" - | ${pkgs.openssh}/bin/ssh data "cat > data/public/$name"
|
||||
path="https://data.vanpetegem.me/public/$name"
|
||||
else
|
||||
name=$(date +'screenshot_%Y-%m-%d-%H%M%S.png')
|
||||
path="$(${pkgs.xdg-user-dirs}/bin/xdg-user-dir PICTURES)/$name"
|
||||
${pkgs.grim}/bin/grim -g "$dims" "$path"
|
||||
fi
|
||||
|
||||
${pkgs.sway}/bin/swaymsg exec -- "echo -n '$path' | ${pkgs.wl-clipboard}/bin/wl-copy --foreground"
|
||||
${pkgs.libnotify}/bin/notify-send "Screenshot taken" "$path"
|
||||
''
|
56
modules/nixos/graphical/default.nix
Normal file
56
modules/nixos/graphical/default.nix
Normal file
|
@ -0,0 +1,56 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./compositor
|
||||
./firefox
|
||||
./gnupg
|
||||
./mail
|
||||
./nextcloud-client
|
||||
./pass
|
||||
./sound
|
||||
./terminal
|
||||
./theme
|
||||
./xdg
|
||||
];
|
||||
|
||||
options.chvp.graphical.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.enable {
|
||||
users.users.charlotte.extraGroups = [ "input" "video" ];
|
||||
chvp = {
|
||||
base = {
|
||||
nix.unfreePackages = [ "google-chrome" ];
|
||||
};
|
||||
graphical = {
|
||||
compositor.enable = lib.mkDefault true;
|
||||
firefox.enable = lib.mkDefault true;
|
||||
gnupg = {
|
||||
enable = lib.mkDefault true;
|
||||
pinentryFlavor = "qt";
|
||||
};
|
||||
mail.enable = lib.mkDefault true;
|
||||
nextcloud-client.enable = lib.mkDefault true;
|
||||
pass.enable = lib.mkDefault true;
|
||||
sound.enable = lib.mkDefault true;
|
||||
terminal.enable = lib.mkDefault true;
|
||||
theme.enable = lib.mkDefault true;
|
||||
xdg.enable = lib.mkDefault true;
|
||||
};
|
||||
};
|
||||
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = with pkgs; [
|
||||
google-chrome
|
||||
mpv
|
||||
okular
|
||||
ranger
|
||||
uni
|
||||
wtype
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
108
modules/nixos/graphical/firefox/default.nix
Normal file
108
modules/nixos/graphical/firefox/default.nix
Normal file
|
@ -0,0 +1,108 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
ff2mpv-host = pkgs.stdenv.mkDerivation rec {
|
||||
pname = "ff2mpv";
|
||||
version = "4.0.0";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "woodruffw";
|
||||
repo = "ff2mpv";
|
||||
rev = "v${version}";
|
||||
sha256 = "sxUp/JlmnYW2sPDpIO2/q40cVJBVDveJvbQMT70yjP4=";
|
||||
};
|
||||
buildInputs = [ pkgs.python3 ];
|
||||
buildPhase = ''
|
||||
sed -i "s#/home/william/scripts/ff2mpv#$out/bin/ff2mpv.py#" ff2mpv.json
|
||||
sed -i 's#"mpv"#"${pkgs.mpv}/bin/umpv"#' ff2mpv.py
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp ff2mpv.py $out/bin
|
||||
mkdir -p $out/lib/mozilla/native-messaging-hosts
|
||||
cp ff2mpv.json $out/lib/mozilla/native-messaging-hosts
|
||||
'';
|
||||
};
|
||||
ffPackage = pkgs.firefox.override { pkcs11Modules = [ pkgs.eid-mw ]; };
|
||||
zotero-connector = pkgs.nur.repos.rycee.firefox-addons.buildFirefoxXpiAddon rec {
|
||||
pname = "zotero-connector";
|
||||
version = "5.0.119";
|
||||
addonId = "zotero@chnm.gmu.edu";
|
||||
url = "https://download.zotero.org/connector/firefox/release/Zotero_Connector-${version}.xpi";
|
||||
sha256 = "sha256-uRbhq0OSQ0Exgi5FEVFtdAGuLVla0aoGLmL0bMud0J8=";
|
||||
meta = with lib; {
|
||||
homepage = "https://www.zotero.org";
|
||||
description = "Save references to Zotero from your web browser";
|
||||
license = licenses.agpl3Plus;
|
||||
platforms = platforms.all;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.chvp.graphical.firefox = {
|
||||
enable = lib.mkEnableOption "firefox";
|
||||
package = lib.mkOption {
|
||||
description = "Final used firefox package";
|
||||
default = ffPackage;
|
||||
readOnly = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.firefox.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".mozilla"; type = "data"; }
|
||||
{ path = ".cache/mozilla"; type = "cache"; }
|
||||
];
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
programs.firefox = {
|
||||
enable = true;
|
||||
package = ffPackage;
|
||||
nativeMessagingHosts = [
|
||||
pkgs.keepassxc
|
||||
ff2mpv-host
|
||||
];
|
||||
policies = {
|
||||
DisableFirefoxStudies = true;
|
||||
DisablePocket = true;
|
||||
DisableTelemetry = true;
|
||||
DisableFirefoxAccounts = true;
|
||||
FirefoxHome = { Pocket = false; Snippets = false; };
|
||||
OfferToSaveLogins = false;
|
||||
UserMessaging = { SkipOnboarding = true; ExtensionRecommendations = false; };
|
||||
};
|
||||
profiles.default = {
|
||||
extensions = with pkgs.nur.repos.rycee.firefox-addons; [
|
||||
belgium-eid
|
||||
consent-o-matic
|
||||
cookie-autodelete
|
||||
darkreader
|
||||
decentraleyes
|
||||
ff2mpv
|
||||
keepassxc-browser
|
||||
multi-account-containers
|
||||
stylus
|
||||
ublock-origin
|
||||
vue-js-devtools
|
||||
zotero-connector
|
||||
];
|
||||
settings = {
|
||||
"browser.aboutConfig.showWarning" = false;
|
||||
"browser.contentblocking.category" = "custom";
|
||||
"browser.download.dir" = "/home/charlotte/downloads";
|
||||
"browser.newtabpage.enabled" = false;
|
||||
"browser.safebrowsing.malware.enabled" = false;
|
||||
"browser.safebrowsing.phishing.enabled" = false;
|
||||
"browser.shell.checkDefaultBrowser" = false;
|
||||
"browser.startup.homepage" = "about:blank";
|
||||
"browser.startup.page" = 3;
|
||||
"dom.security.https_only_mode" = true;
|
||||
"network.cookie.cookieBehavior" = 1;
|
||||
"privacy.annotate_channels.strict_list.enabled" = true;
|
||||
"privacy.trackingprotection.enabled" = true;
|
||||
"privacy.trackingprotection.socialtracking.enabled" = true;
|
||||
"security.identityblock.show_extended_validation" = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
41
modules/nixos/graphical/gnupg/default.nix
Normal file
41
modules/nixos/graphical/gnupg/default.nix
Normal file
|
@ -0,0 +1,41 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.graphical.gnupg = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
pinentryFlavor = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "curses";
|
||||
example = "qt";
|
||||
description = ''
|
||||
Pinentry flavor for gnupg.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.gnupg.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".gnupg"; type = "data"; }
|
||||
];
|
||||
programs.gnupg.agent = {
|
||||
enable = true;
|
||||
pinentryPackage = pkgs."pinentry-${config.chvp.graphical.gnupg.pinentryFlavor}";
|
||||
};
|
||||
home-manager.users.charlotte = { lib, ... }: {
|
||||
home.activation.fixPermissionsCommands = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
mkdir -p /home/charlotte/.gnupg
|
||||
chmod u=rwX,go= /home/charlotte/.gnupg
|
||||
'';
|
||||
programs.gpg.enable = true;
|
||||
services.gpg-agent = {
|
||||
enable = true;
|
||||
defaultCacheTtl = 7200;
|
||||
maxCacheTtl = 99999;
|
||||
pinentryPackage = pkgs."pinentry-${config.chvp.graphical.gnupg.pinentryFlavor}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
315
modules/nixos/graphical/mail/default.nix
Normal file
315
modules/nixos/graphical/mail/default.nix
Normal file
|
@ -0,0 +1,315 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
passwordScript = pkgs.writeShellScript "get_mail_password" ''${pkgs.libsecret}/bin/secret-tool lookup secret-tool-id $1 | ${pkgs.coreutils}/bin/tr -d "\n"'';
|
||||
notifyScript = name: pkgs.writeShellScript "notify_${name}_mail" ''
|
||||
unseen_count=$(${pkgs.mblaze}/bin/mlist -N ~/mail/*/INBOX | ${pkgs.coreutils}/bin/wc -l)
|
||||
|
||||
if [ "$unseen_count" = "1" ]
|
||||
then
|
||||
${pkgs.libnotify}/bin/notify-send -t 5000 'New ${name} mail arrived' "1 unseen mail"
|
||||
elif [ "$unseen_count" != "0" ]
|
||||
then
|
||||
${pkgs.libnotify}/bin/notify-send -t 5000 'New ${name} mail arrived' "$unseen_count unseen mails"
|
||||
fi
|
||||
'';
|
||||
makeAccount = { name, address, host ? "", imapHost ? host, smtpHost ? host, useStartTls ? false, secretToolId, extraConfig ? { }, oauth ? false }: (lib.recursiveUpdate
|
||||
{
|
||||
inherit address;
|
||||
gpg = {
|
||||
key = "charlotte@vanpetegem.me";
|
||||
signByDefault = true;
|
||||
};
|
||||
imap = {
|
||||
host = imapHost;
|
||||
port = 993;
|
||||
tls.enable = true;
|
||||
};
|
||||
imapnotify = {
|
||||
enable = true;
|
||||
boxes = [ "INBOX" ];
|
||||
onNotify = "${pkgs.isync}/bin/mbsync ${name}:INBOX";
|
||||
onNotifyPost = "${config.chvp.base.emacs.package}/bin/emacsclient --eval \"(mu4e-update-index)\" && ${notifyScript name}";
|
||||
extraConfig = lib.mkIf oauth { xoauth2 = true; };
|
||||
};
|
||||
mbsync = {
|
||||
enable = true;
|
||||
create = "both";
|
||||
expunge = "both";
|
||||
flatten = ".";
|
||||
remove = "both";
|
||||
extraConfig.account.AuthMechs = if (oauth) then "XOAUTH2" else "LOGIN";
|
||||
};
|
||||
msmtp = {
|
||||
enable = true;
|
||||
extraConfig = lib.mkIf oauth { auth = "xoauth2"; };
|
||||
};
|
||||
mu.enable = true;
|
||||
passwordCommand = if oauth then "${pkgs.mfauth}/bin/mfauth access ${name}" else "${passwordScript} ${secretToolId}";
|
||||
realName = "Charlotte Van Petegem";
|
||||
signature = {
|
||||
showSignature = "none";
|
||||
};
|
||||
smtp = {
|
||||
host = smtpHost;
|
||||
port = if useStartTls then 587 else 465;
|
||||
tls = {
|
||||
enable = true;
|
||||
inherit useStartTls;
|
||||
};
|
||||
};
|
||||
userName = address;
|
||||
}
|
||||
extraConfig);
|
||||
toRecursiveINI = with lib.strings; with lib.attrsets; with lib.generators; with lib.lists; let
|
||||
repeat = count: char: concatStrings (genList (_: char) count);
|
||||
mkHeader = depth: name: concatStrings [ (repeat depth "[") (escape [ "[" ] name) (repeat depth "]") ];
|
||||
simpleAttrs = filterAttrs (n: v: !(isAttrs v));
|
||||
complexAttrs = filterAttrs (n: v: isAttrs v);
|
||||
removeEmpty = filter (v: v != "");
|
||||
toRecursiveINIBase = depth: data: (concatStringsSep "\n" (
|
||||
mapAttrsToList
|
||||
(name: values: concatStringsSep "\n" (removeEmpty [
|
||||
(mkHeader depth name)
|
||||
(toKeyValue { } (simpleAttrs values))
|
||||
(toRecursiveINIBase (depth + 1) (complexAttrs values))
|
||||
]))
|
||||
data
|
||||
));
|
||||
in
|
||||
toRecursiveINIBase 1;
|
||||
in
|
||||
{
|
||||
options.chvp.graphical.mail.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.mail.enable {
|
||||
nixpkgs.overlays = [
|
||||
(self: super: rec {
|
||||
isync = super.isync.override { withCyrusSaslXoauth2 = true; };
|
||||
})
|
||||
];
|
||||
chvp = {
|
||||
base = {
|
||||
emacs.extraConfig =
|
||||
let
|
||||
mkAccountConfig = account: ''
|
||||
(make-mu4e-context
|
||||
:name "${account.name}"
|
||||
:match-func (lambda (msg) (when msg (string-prefix-p "/${account.maildir.path}/" (mu4e-message-field msg :maildir))))
|
||||
:vars '(
|
||||
(user-mail-address . "${account.address}")
|
||||
(user-full-name . "${account.realName}")
|
||||
(mu4e-drafts-folder . "/${account.maildir.path}/${account.folders.drafts}")
|
||||
(mu4e-sent-folder . "/${account.maildir.path}/${account.folders.sent}")
|
||||
(mu4e-refile-folder . "/${account.maildir.path}/${account.folders.trash}")
|
||||
(mu4e-trash-folder . "/${account.maildir.path}/${account.folders.trash}")
|
||||
(message-sendmail-extra-arguments . ("--read-envelope-from" "--account" "${account.name}"))
|
||||
)
|
||||
)
|
||||
'';
|
||||
hmConfig = config.home-manager.users.charlotte;
|
||||
in
|
||||
[
|
||||
''
|
||||
(use-package mu4e
|
||||
;; Use mu4e included in the mu package, see emacs/default.nix
|
||||
:ensure nil
|
||||
:demand t
|
||||
:after (vertico)
|
||||
:hook
|
||||
(mu4e-view-mode . display-line-numbers-mode)
|
||||
(mu4e-view-mode . visual-line-mode)
|
||||
(mu4e-compose-mode . chvp--mu4e-auto-dodona-cc-reply-to)
|
||||
(mu4e-compose-mode . visual-line-mode)
|
||||
(mu4e-compose-mode . (lambda () (setq use-hard-newlines nil)))
|
||||
:custom
|
||||
(mu4e-read-option-use-builtin nil "Don't use builtin autocomplete in mu4e")
|
||||
(mu4e-completing-read-function 'completing-read "Use default completing read function")
|
||||
(mu4e-maildir-initial-input "" "Don't have initial input when completing a maildir")
|
||||
(mu4e-change-filenames-when-moving t "Avoid sync issues with mbsync")
|
||||
(mu4e-maildir "${hmConfig.accounts.email.maildirBasePath}" "Root of the maildir hierarchy")
|
||||
(mu4e-context-policy 'pick-first "Use the first mail context in the list")
|
||||
(mu4e-attachment-dir "/home/charlotte/downloads/" "Save attachments to downloads folder")
|
||||
(mu4e-compose-dont-reply-to-self t "Don't reply to myself on reply to all")
|
||||
(mu4e-compose-format-flowed t "Send format=flowed mails when use-hard-newlines gets enabled")
|
||||
(fill-flowed-display-column 1000000000000 "Dont fill when decoding flowed messages, let visual-line-mode handle it")
|
||||
(gnus-treat-fill-long-lines nil "Let visual-line-mode handle filling")
|
||||
(mu4e-confirm-quit nil "Don't confirm when quitting")
|
||||
(mu4e-headers-include-related nil "Don't show related messages by default")
|
||||
(mu4e-headers-skip-duplicates nil "Show duplicate emails")
|
||||
(message-kill-buffer-on-exit t "Close buffer when finished with email")
|
||||
(mm-verify-option 'known "Always verify PGP signatures (known protocols)")
|
||||
(mm-discouraged-alternatives '("text/html" "text/richtext") "Discourage showing HTML views")
|
||||
(gnus-buttonized-mime-types '("multipart/signed") "Make sure signature verification is always shown")
|
||||
(mml-secure-openpgp-sign-with-sender t "Sign mails with the sender")
|
||||
(sendmail-program "msmtp" "Use msmtp to send email")
|
||||
(message-sendmail-f-is-evil t "Remove username from the emacs message")
|
||||
(message-send-mail-function 'message-send-mail-with-sendmail "Use sendmail to send mail instead internal smtp")
|
||||
(message-cite-reply-position 'below "Bottom posting is the correct way to reply to email")
|
||||
:config
|
||||
;; mu4e should just open in the currently focused window instead of taking up the whole frame
|
||||
(add-to-list 'display-buffer-alist
|
||||
`(,(regexp-quote mu4e-main-buffer-name)
|
||||
display-buffer-same-window))
|
||||
(setq mu4e-contexts (list ${lib.concatStringsSep "\n" (map mkAccountConfig (lib.attrValues hmConfig.accounts.email.accounts))}))
|
||||
(add-to-list
|
||||
'mu4e-bookmarks
|
||||
'(:name "Combined inbox" :query "maildir:/personal/INBOX or maildir:/posteo/INBOX or maildir:/rodekruis-eerstehulp/INBOX" :key ?i :favorite t)
|
||||
)
|
||||
(defun chvp--mu4e-dodona-cc-reply-to ()
|
||||
"Add dodona@ugent.be in cc and reply-to headers."
|
||||
(interactive)
|
||||
(save-excursion (message-add-header "Cc: dodona@ugent.be\nReply-To: dodona@ugent.be\n"))
|
||||
)
|
||||
(defun chvp--mu4e-auto-dodona-cc-reply-to ()
|
||||
"Set dodona@ugent.be in CC and Reply-To headers when message was directed to dodona@ugent.be"
|
||||
(let ((msg mu4e-compose-parent-message))
|
||||
(when (and msg (mu4e-message-contact-field-matches msg :to "dodona@ugent.be")) (chvp--mu4e-dodona-cc-reply-to))
|
||||
)
|
||||
)
|
||||
;; Never actually quit mu4e, just close the current buffer (making sure the modeline is still visible)
|
||||
(defalias 'mu4e-quit 'chvp--kill-current-buffer)
|
||||
(define-advice mu4e--context-ask-user
|
||||
(:around (orig-fun &rest args) mu4e--context-ask-user-completing-read)
|
||||
"Replace `mu4e-read-option` by general-purpose completing-read"
|
||||
(cl-letf (((symbol-function 'mu4e-read-option)
|
||||
(lambda (prompt options)
|
||||
(let* ((prompt (mu4e-format "%s" prompt))
|
||||
(choice (completing-read prompt (cl-mapcar #'car options) nil t))
|
||||
(chosen-el (cl-find-if (lambda (option) (equal choice (car option))) options)))
|
||||
(if chosen-el
|
||||
(cdr chosen-el)
|
||||
(mu4e-warn "Unknown option: '%s'" choice))))))
|
||||
(apply orig-fun args)))
|
||||
(mu4e 'background)
|
||||
:general
|
||||
(lmap "m" '(mu4e :which-key "mail"))
|
||||
;; Unmap SPC in the mail view so we can still use the leader.
|
||||
(lmap mu4e-view-mode-map "" nil)
|
||||
(lmap mu4e-compose-mode-map
|
||||
"SPC s" '(mml-secure-message-sign-pgpmime :which-key "Sign")
|
||||
"SPC c" '(mml-secure-message-encrypt-pgpmime :which-key "Encrypt")
|
||||
"SPC d" '(chvp--mu4e-dodona-cc-reply-to :which-key "Dodona support headers")
|
||||
"SPC f" '(mu4e-toggle-use-hard-newlines :which-key "Toggle format=flowed/hard newlines")
|
||||
)
|
||||
)
|
||||
|
||||
(use-package visual-fill-column
|
||||
:custom (visual-fill-column-enable-sensible-window-split t "Sensibly split windows in visual-fill-column-mode")
|
||||
:hook (visual-line-mode . visual-fill-column-mode)
|
||||
)
|
||||
|
||||
(use-package adaptive-wrap
|
||||
:hook (visual-fill-column-mode . adaptive-wrap-prefix-mode)
|
||||
)
|
||||
''
|
||||
];
|
||||
zfs.homeLinks = [
|
||||
{ path = "mail"; type = "data"; }
|
||||
{ path = ".cache/mu"; type = "cache"; }
|
||||
{ path = ".cache/mfauth"; type = "cache"; }
|
||||
];
|
||||
};
|
||||
};
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
accounts.email = {
|
||||
maildirBasePath = "/home/charlotte/mail";
|
||||
accounts = {
|
||||
personal = makeAccount {
|
||||
name = "personal";
|
||||
address = "charlotte@vanpetegem.be";
|
||||
host = "mail.vanpetegem.me";
|
||||
secretToolId = "personal-mail";
|
||||
extraConfig = {
|
||||
folders = { drafts = "Drafts"; inbox = "INBOX"; sent = "INBOX"; trash = "Trash"; };
|
||||
primary = true;
|
||||
};
|
||||
};
|
||||
posteo = makeAccount {
|
||||
name = "posteo";
|
||||
address = "chvp@posteo.net";
|
||||
host = "posteo.de";
|
||||
secretToolId = "posteo";
|
||||
extraConfig = {
|
||||
folders = { drafts = "Drafts"; inbox = "INBOX"; sent = "INBOX"; trash = "Trash"; };
|
||||
};
|
||||
};
|
||||
postbot = makeAccount {
|
||||
name = "postbot";
|
||||
address = "postbot@vanpetegem.be";
|
||||
host = "mail.vanpetegem.me";
|
||||
secretToolId = "postbot";
|
||||
extraConfig = {
|
||||
folders = { drafts = "Drafts"; inbox = "INBOX"; sent = "INBOX"; trash = "Trash"; };
|
||||
};
|
||||
};
|
||||
rodekruis-eerstehulp = makeAccount {
|
||||
name = "rodekruis-eerstehulp";
|
||||
address = "eerstehulp@gent.rodekruis.be";
|
||||
imapHost = "imap.gmail.com";
|
||||
smtpHost = "smtp.gmail.com";
|
||||
useStartTls = true;
|
||||
secretToolId = "eerstehulp-mail";
|
||||
extraConfig = {
|
||||
folders = { drafts = "[Gmail].Concepten"; inbox = "INBOX"; sent = "INBOX"; trash = "[Gmail].Prullenbak"; };
|
||||
flavor = "gmail.com";
|
||||
};
|
||||
};
|
||||
webmaster = makeAccount {
|
||||
name = "webmaster";
|
||||
address = "webmaster@vanpetegem.be";
|
||||
host = "mail.vanpetegem.me";
|
||||
secretToolId = "webmaster";
|
||||
extraConfig = {
|
||||
folders = { drafts = "Drafts"; inbox = "INBOX"; sent = "INBOX"; trash = "Trash"; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
programs = {
|
||||
mbsync.enable = true;
|
||||
msmtp.enable = true;
|
||||
mu.enable = true;
|
||||
};
|
||||
services = {
|
||||
imapnotify.enable = true;
|
||||
};
|
||||
systemd.user = {
|
||||
services = {
|
||||
mbsync = {
|
||||
Unit = {
|
||||
Description = "MBSync email fetcher";
|
||||
After = "network-online.target";
|
||||
Wants = "network-online.target";
|
||||
};
|
||||
Service = {
|
||||
Type = "oneshot";
|
||||
ExecStart = [ "${pkgs.isync}/bin/mbsync -a" "${config.chvp.base.emacs.package}/bin/emacsclient --eval \"(mu4e-update-index)\"" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
timers = {
|
||||
mbsync = {
|
||||
Unit = { Description = "MBSync email fetcher"; };
|
||||
Timer = {
|
||||
OnCalendar = "*:0/5";
|
||||
Unit = "mbsync.service";
|
||||
};
|
||||
Install = { WantedBy = [ "timers.target" ]; };
|
||||
};
|
||||
vdirsyncer = {
|
||||
Unit = { Description = "VDirSyncer WebDAV syncer"; };
|
||||
Timer = {
|
||||
OnCalendar = "*:0/5";
|
||||
Unit = "vdirsyncer.service";
|
||||
};
|
||||
Install = { WantedBy = [ "timers.target" ]; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
22
modules/nixos/graphical/nextcloud-client/default.nix
Normal file
22
modules/nixos/graphical/nextcloud-client/default.nix
Normal file
|
@ -0,0 +1,22 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.graphical.nextcloud-client.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.nextcloud-client.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".config/Nextcloud"; type = "cache"; }
|
||||
{ path = ".local/share/Nextcloud"; type = "cache"; }
|
||||
{ path = "sync"; type = "cache"; }
|
||||
];
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
services.nextcloud-client = {
|
||||
enable = true;
|
||||
startInBackground = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
42
modules/nixos/graphical/pass/default.nix
Normal file
42
modules/nixos/graphical/pass/default.nix
Normal file
|
@ -0,0 +1,42 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.graphical.pass.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.pass.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".config/keepassxc"; type = "data"; }
|
||||
{ path = ".cache/keepassxc"; type = "cache"; }
|
||||
];
|
||||
|
||||
chvp.base.emacs.extraConfig = [
|
||||
''
|
||||
(use-package secrets
|
||||
:ensure nil
|
||||
:custom
|
||||
(auth-sources '(default))
|
||||
)
|
||||
''
|
||||
];
|
||||
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = [ pkgs.keepassxc ];
|
||||
systemd.user.services.keepassxc = {
|
||||
Unit = {
|
||||
Description = "KeepassXC startup";
|
||||
PartOf = [ "river-session.target" ];
|
||||
Wants = [ "waybar.service" ];
|
||||
After = [ "river-session.target" "waybar.service" ];
|
||||
};
|
||||
Service = {
|
||||
ExecStart = "${pkgs.keepassxc}/bin/keepassxc";
|
||||
Restart = "always";
|
||||
};
|
||||
Install.WantedBy = [ "river-session.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
30
modules/nixos/graphical/sound/default.nix
Normal file
30
modules/nixos/graphical/sound/default.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.graphical.sound.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.sound.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".local/state/wireplumber"; type = "cache"; }
|
||||
];
|
||||
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = with pkgs; [
|
||||
pavucontrol
|
||||
qjackctl
|
||||
];
|
||||
};
|
||||
|
||||
services = {
|
||||
pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
jack.enable = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
50
modules/nixos/graphical/terminal/default.nix
Normal file
50
modules/nixos/graphical/terminal/default.nix
Normal file
|
@ -0,0 +1,50 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.graphical.terminal.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.terminal.enable {
|
||||
home-manager.users.charlotte = { pkgs, ... }: {
|
||||
home.packages = [ pkgs.foot ];
|
||||
programs.foot = {
|
||||
enable = true;
|
||||
settings = {
|
||||
main = {
|
||||
font = "Hack:size=9";
|
||||
dpi-aware = "no";
|
||||
};
|
||||
bell = {
|
||||
urgent = true;
|
||||
notify = true;
|
||||
};
|
||||
scrollback.lines = 10000;
|
||||
cursor.blink = true;
|
||||
mouse.hide-when-typing = true;
|
||||
colors = {
|
||||
foreground = "4c4f69";
|
||||
background = "eff1f5";
|
||||
regular0 = "5c5f77";
|
||||
regular1 = "d20f39";
|
||||
regular2 = "40a02b";
|
||||
regular3 = "df8e1d";
|
||||
regular4 = "1e66f5";
|
||||
regular5 = "ea76cb";
|
||||
regular6 = "179299";
|
||||
regular7 = "acb0be";
|
||||
bright0 = "6c6f85";
|
||||
bright1 = "d20f39";
|
||||
bright2 = "40a02b";
|
||||
bright3 = "df8e1d";
|
||||
bright4 = "1e66f5";
|
||||
bright5 = "ea76cb";
|
||||
bright6 = "179299";
|
||||
bright7 = "bcc0cc";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
198
modules/nixos/graphical/theme/default.nix
Normal file
198
modules/nixos/graphical/theme/default.nix
Normal file
|
@ -0,0 +1,198 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.graphical.theme.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.theme.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".config/qt5ct"; type = "cache"; }
|
||||
{ path = ".config/qt6ct"; type = "cache"; }
|
||||
];
|
||||
fonts = {
|
||||
fontDir.enable = true;
|
||||
fontconfig = {
|
||||
enable = true;
|
||||
defaultFonts = {
|
||||
emoji = [ "Noto Color Emoji" ];
|
||||
# The Tinos and Amiro fonts overlap with Font Awesome's codepoints, so make sure we give Font Awesome a higher priority.
|
||||
monospace = [ "Hack" "Font Awesome 6 Free" ];
|
||||
sansSerif = [ "Noto Sans" "Font Awesome 6 Free" ];
|
||||
serif = [ "Noto Serif" "Font Awesome 6 Free" ];
|
||||
};
|
||||
};
|
||||
packages = with pkgs; [
|
||||
hack-font
|
||||
font-awesome
|
||||
noto-fonts
|
||||
noto-fonts-cjk
|
||||
noto-fonts-emoji
|
||||
noto-fonts-extra
|
||||
roboto
|
||||
];
|
||||
};
|
||||
|
||||
programs.dconf.enable = true;
|
||||
home-manager.users.charlotte = { pkgs, lib, ... }: {
|
||||
home.packages = [
|
||||
pkgs.catppuccin-cursors.latteLight
|
||||
# Also install dark mode to profile for darkman
|
||||
(pkgs.catppuccin-gtk.override { size = "compact"; variant = "frappe"; })
|
||||
];
|
||||
home.file = {
|
||||
".icons/default/index.theme".text = ''
|
||||
[Icon Theme]
|
||||
Name=Default
|
||||
Comment=Default Cursor Theme
|
||||
Inherits=catppuccin-latte-light-cursors
|
||||
'';
|
||||
};
|
||||
dconf.settings."org/gnome/desktop/wm/preferences".button-layout = "";
|
||||
gtk = {
|
||||
enable = true;
|
||||
font = {
|
||||
package = pkgs.noto-fonts;
|
||||
name = "Noto Sans";
|
||||
size = 10;
|
||||
};
|
||||
gtk2.extraConfig = ''
|
||||
gtk-cursor-theme-name = "catppuccin-latte-light-cursors"
|
||||
gtk-cursor-theme-size = 24
|
||||
'';
|
||||
gtk3 = {
|
||||
extraConfig = {
|
||||
gtk-cursor-theme-name = "catppuccin-latte-light-cursors";
|
||||
gtk-cursor-theme-size = 24;
|
||||
};
|
||||
extraCss = ''
|
||||
/* No (default) titlebar on wayland */
|
||||
headerbar.titlebar.default-decoration {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
margin: 0 0 -17px 0;
|
||||
border: 0;
|
||||
min-height: 0;
|
||||
font-size: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* rm -rf window shadows */
|
||||
window.csd, /* gtk4? */
|
||||
window.csd decoration { /* gtk3 */
|
||||
box-shadow: none;
|
||||
}
|
||||
'';
|
||||
};
|
||||
gtk4 = {
|
||||
extraConfig = {
|
||||
gtk-cursor-theme-name = "catppuccin-latte-light-cursors";
|
||||
gtk-cursor-theme-size = 24;
|
||||
};
|
||||
extraCss = ''
|
||||
/* No (default) titlebar on wayland */
|
||||
headerbar.titlebar.default-decoration {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
margin: 0 0 -17px 0;
|
||||
border: 0;
|
||||
min-height: 0;
|
||||
font-size: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* rm -rf window shadows */
|
||||
window.csd, /* gtk4? */
|
||||
window.csd decoration { /* gtk3 */
|
||||
box-shadow: none;
|
||||
}
|
||||
'';
|
||||
};
|
||||
iconTheme = {
|
||||
package = pkgs.libsForQt5.breeze-icons;
|
||||
name = "breeze";
|
||||
};
|
||||
theme = {
|
||||
package = pkgs.catppuccin-gtk.override { size = "compact"; variant = "latte"; };
|
||||
name = "Catppuccin-Latte-Compact-Blue-Light";
|
||||
};
|
||||
};
|
||||
qt = {
|
||||
enable = true;
|
||||
platformTheme.name = "qtct";
|
||||
style = {
|
||||
name = "lightly";
|
||||
package = pkgs.lightly-qt;
|
||||
};
|
||||
};
|
||||
services.darkman = {
|
||||
enable = true;
|
||||
settings = {
|
||||
lat = 51.0;
|
||||
lng = 3.7;
|
||||
usegeoclue = false;
|
||||
dbusserver = true;
|
||||
portal = true;
|
||||
};
|
||||
darkModeScripts = {
|
||||
emacs = ''
|
||||
emacsclient --eval "(setq catppuccin-flavor 'frappe)"
|
||||
emacsclient --eval "(load-theme 'catppuccin :no-confirm)"
|
||||
'';
|
||||
gtk = ''
|
||||
${pkgs.glib}/bin/gsettings set org.gnome.desktop.interface gtk-theme Catppuccin-Frappe-Compact-Blue-Dark
|
||||
'';
|
||||
river = ''
|
||||
riverctl background-color 0x626880
|
||||
riverctl border-color-focused 0x99d1db
|
||||
riverctl border-color-unfocused 0x232634
|
||||
riverctl border-color-urgent 0xf4b8e4
|
||||
'';
|
||||
qt = ''
|
||||
sed -i "s/Latte/Frappe/" ~/.config/qt5ct/qt5ct.conf
|
||||
sed -i "s/Latte/Frappe/" ~/.config/qt6ct/qt6ct.conf
|
||||
'';
|
||||
terminal = ''
|
||||
pkill -SIGUSR2 zsh
|
||||
'';
|
||||
waybar = ''
|
||||
ln -sf ~/.config/waybar/frappe.css ~/.config/waybar/colors.css
|
||||
systemctl --user restart waybar.service
|
||||
'';
|
||||
};
|
||||
lightModeScripts = {
|
||||
emacs = ''
|
||||
emacsclient --eval "(setq catppuccin-flavor 'latte)"
|
||||
emacsclient --eval "(load-theme 'catppuccin :no-confirm)"
|
||||
'';
|
||||
gtk = ''
|
||||
${pkgs.glib}/bin/gsettings set org.gnome.desktop.interface gtk-theme Catppuccin-Latte-Compact-Blue-Light
|
||||
'';
|
||||
river = ''
|
||||
riverctl background-color 0xacb0be
|
||||
riverctl border-color-focused 0x04e5e5
|
||||
riverctl border-color-unfocused 0xdce0e8
|
||||
riverctl border-color-urgent 0xea76cb
|
||||
'';
|
||||
qt = ''
|
||||
sed -i "s/Frappe/Latte/" ~/.config/qt5ct/qt5ct.conf
|
||||
sed -i "s/Frappe/Latte/" ~/.config/qt6ct/qt6ct.conf
|
||||
'';
|
||||
terminal = ''
|
||||
pkill -SIGUSR1 zsh
|
||||
'';
|
||||
waybar = ''
|
||||
ln -sf ~/.config/waybar/latte.css ~/.config/waybar/colors.css
|
||||
systemctl --user restart waybar.service
|
||||
'';
|
||||
};
|
||||
};
|
||||
home.activation = {
|
||||
linkWaybarCssColors = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
$DRY_RUN_CMD ln -sf $VERBOSE_ARG ~/.config/waybar/latte.css ~/.config/waybar/colors.css
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
58
modules/nixos/graphical/xdg/default.nix
Normal file
58
modules/nixos/graphical/xdg/default.nix
Normal file
|
@ -0,0 +1,58 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.graphical.xdg.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.graphical.xdg.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = "desktop"; type = "data"; }
|
||||
{ path = "documents"; type = "data"; }
|
||||
{ path = "downloads"; type = "cache"; }
|
||||
{ path = "music"; type = "data"; }
|
||||
{ path = "pictures"; type = "cache"; }
|
||||
{ path = "repos"; type = "cache"; }
|
||||
{ path = "templates"; type = "data"; }
|
||||
{ path = "videos"; type = "data"; }
|
||||
];
|
||||
|
||||
home-manager.users.charlotte = { pkgs, ... }: {
|
||||
home.packages = with pkgs; [ xdg-user-dirs xdg-utils ];
|
||||
xdg = {
|
||||
enable = true;
|
||||
# Some applications overwrite mimeapps.list with an identical file
|
||||
configFile."mimeapps.list".force = true;
|
||||
mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
"image/png" = [ "org.kde.okular.desktop" ];
|
||||
"image/jpg" = [ "org.kde.okular.desktop" ];
|
||||
"image/jpeg" = [ "org.kde.okular.desktop" ];
|
||||
"application/pdf" = [ "org.kde.okular.desktop" ];
|
||||
|
||||
"text/html" = [ "firefox.desktop" ];
|
||||
"x-scheme-handler/about" = [ "firefox.desktop" ];
|
||||
"x-scheme-handler/http" = [ "firefox.desktop" ];
|
||||
"x-scheme-handler/https" = [ "firefox.desktop" ];
|
||||
"x-scheme-handler/unknown" = [ "firefox.desktop" ];
|
||||
|
||||
"x-scheme-handler/msteams" = [ "teams.desktop" ];
|
||||
};
|
||||
};
|
||||
userDirs = {
|
||||
enable = true;
|
||||
desktop = "\$HOME/desktop";
|
||||
documents = "\$HOME/documents";
|
||||
download = "\$HOME/downloads";
|
||||
music = "\$HOME/music";
|
||||
pictures = "\$HOME/pictures";
|
||||
publicShare = "\$HOME/desktop";
|
||||
templates = "\$HOME/templates";
|
||||
videos = "\$HOME/videos";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
18
modules/nixos/programs/calibre/default.nix
Normal file
18
modules/nixos/programs/calibre/default.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.programs.calibre.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.programs.calibre.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".config/calibre"; type = "cache"; }
|
||||
];
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = [ pkgs.calibre ];
|
||||
};
|
||||
services.udisks2.enable = true;
|
||||
};
|
||||
}
|
20
modules/nixos/programs/default.nix
Normal file
20
modules/nixos/programs/default.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./calibre
|
||||
./eid
|
||||
./element
|
||||
./hledger
|
||||
./obs
|
||||
./torrents
|
||||
];
|
||||
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = with pkgs; [
|
||||
jq
|
||||
xsv
|
||||
yt-dlp
|
||||
];
|
||||
};
|
||||
}
|
16
modules/nixos/programs/eid/default.nix
Normal file
16
modules/nixos/programs/eid/default.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.programs.eid.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.programs.eid.enable {
|
||||
environment.systemPackages = [ pkgs.eid-mw ];
|
||||
services.pcscd = {
|
||||
enable = true;
|
||||
plugins = [ pkgs.ccid ];
|
||||
};
|
||||
};
|
||||
}
|
19
modules/nixos/programs/element/default.nix
Normal file
19
modules/nixos/programs/element/default.nix
Normal file
|
@ -0,0 +1,19 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.programs.element.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.programs.element.enable {
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".config/nheko"; type = "data"; }
|
||||
{ path = ".local/share/nheko"; type = "data"; }
|
||||
{ path = ".cache/nheko"; type = "cache"; }
|
||||
];
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = [ pkgs.nheko ];
|
||||
};
|
||||
};
|
||||
}
|
33
modules/nixos/programs/hledger/default.nix
Normal file
33
modules/nixos/programs/hledger/default.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.programs.hledger.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.programs.hledger.enable {
|
||||
chvp.base.emacs.extraConfig = [
|
||||
''
|
||||
;; Ledger syntax support
|
||||
(use-package ledger-mode
|
||||
:mode "\\.journal\\'"
|
||||
:custom
|
||||
(ledger-binary-path "hledger" "Use hledger instead of ledger")
|
||||
(ledger-highlight-xact-under-point nil "Remove distracting highlight")
|
||||
(ledger-mode-should-check-version nil "Remove version check, since it doesn't work with hledger anyway")
|
||||
(ledger-post-account-alignment-column 4 "Indent postings with 4 spaces")
|
||||
(ledger-post-amount-alignment-at :decimal "Align on the decimal")
|
||||
(ledger-post-amount-alignment-column 69 "Align on column 70")
|
||||
(ledger-post-auto-align t "Align when moving to the next line")
|
||||
:config
|
||||
(advice-add 'ledger-complete-at-point :around #'cape-wrap-nonexclusive)
|
||||
)
|
||||
''
|
||||
];
|
||||
|
||||
home-manager.users.charlotte = { ... }: {
|
||||
home.packages = [ pkgs.hledger ];
|
||||
};
|
||||
};
|
||||
}
|
27
modules/nixos/programs/obs/default.nix
Normal file
27
modules/nixos/programs/obs/default.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.programs.obs.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.programs.obs.enable {
|
||||
boot.kernelModules = [ "v4l2loopback" ];
|
||||
boot.extraModulePackages = [ pkgs.linuxPackages.v4l2loopback ];
|
||||
boot.extraModprobeConfig = ''
|
||||
options v4l2loopback video_nr=9 card_label="obs"
|
||||
'';
|
||||
|
||||
chvp.base.zfs.homeLinks = [
|
||||
{ path = ".config/obs-studio"; type = "data"; }
|
||||
];
|
||||
|
||||
home-manager.users.charlotte = { pkgs, ... }: {
|
||||
programs.obs-studio = {
|
||||
enable = true;
|
||||
plugins = [ pkgs.obs-studio-plugins.wlrobs ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
16
modules/nixos/programs/torrents/default.nix
Normal file
16
modules/nixos/programs/torrents/default.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.programs.torrents.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.programs.torrents.enable {
|
||||
chvp.base.zfs.homeLinks = [{ path = ".config/transmission-remote-gtk"; type = "data"; }];
|
||||
|
||||
home-manager.users.charlotte = { pkgs, ... }: {
|
||||
home.packages = with pkgs; [ transmission-remote-gtk ];
|
||||
};
|
||||
};
|
||||
}
|
42
modules/nixos/services/accentor/default.nix
Normal file
42
modules/nixos/services/accentor/default.nix
Normal file
|
@ -0,0 +1,42 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.accentor.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.accentor.enable {
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
};
|
||||
|
||||
services.accentor = {
|
||||
enable = true;
|
||||
home = "${config.chvp.dataPrefix}/var/lib/accentor";
|
||||
hostname = "accentor.vanpetegem.me";
|
||||
environmentFile = config.age.secrets."passwords/services/accentor".path;
|
||||
rescanTimer = {
|
||||
enable = true;
|
||||
dates = "00:00";
|
||||
};
|
||||
nginx = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "vanpetegem.me";
|
||||
};
|
||||
};
|
||||
|
||||
security.doas.extraRules = [{
|
||||
users = [ "charlotte" ];
|
||||
noPass = true;
|
||||
cmd = "accentor-console";
|
||||
runAs = "accentor";
|
||||
}];
|
||||
|
||||
age.secrets."passwords/services/accentor" = {
|
||||
file = ../../../../secrets/passwords/services/accentor.age;
|
||||
owner = "accentor";
|
||||
};
|
||||
};
|
||||
}
|
21
modules/nixos/services/containers/default.nix
Normal file
21
modules/nixos/services/containers/default.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.containers = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
externalInterface = lib.mkOption {
|
||||
example = "eno3";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
networking.nat = lib.mkIf config.chvp.services.containers.enable {
|
||||
enable = true;
|
||||
enableIPv6 = true;
|
||||
internalInterfaces = [ "ve-+" ];
|
||||
externalInterface = config.chvp.services.containers.externalInterface;
|
||||
};
|
||||
};
|
||||
}
|
46
modules/nixos/services/data-access/config.nix
Normal file
46
modules/nixos/services/data-access/config.nix
Normal file
|
@ -0,0 +1,46 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
users.users.data = {
|
||||
isNormalUser = true;
|
||||
home = "/home/data";
|
||||
description = "Data Access";
|
||||
uid = 1000;
|
||||
group = "users";
|
||||
hashedPasswordFile = "/run/secrets/password_file";
|
||||
};
|
||||
users.users.readonly = {
|
||||
isNormalUser = true;
|
||||
home = "/home/readonly";
|
||||
description = "Readonly data access";
|
||||
uid = 1001;
|
||||
group = "sftponly";
|
||||
hashedPasswordFile = "/run/secrets/readonly_password_file";
|
||||
};
|
||||
users.groups.sftponly = { gid = 10000; };
|
||||
environment.systemPackages = [ pkgs.rsync pkgs.mktorrent (pkgs.writeShellScriptBin "create_torrent" ". /run/secrets/create_torrent") ];
|
||||
security.sudo.enable = false;
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
hostKeys = [
|
||||
{ bits = 4096; path = "/run/secrets/ssh_host_rsa_key"; type = "rsa"; }
|
||||
{ path = "/run/secrets/ssh_host_ed25519_key"; type = "ed25519"; }
|
||||
];
|
||||
settings = {
|
||||
HostKeyAlgorithms = "+ssh-rsa";
|
||||
Macs = [ "hmac-sha2-512-etm@openssh.com" "hmac-sha2-256-etm@openssh.com" "umac-128-etm@openssh.com" "hmac-sha2-512" ];
|
||||
PermitRootLogin = "no";
|
||||
};
|
||||
extraConfig = ''
|
||||
Match group sftponly
|
||||
X11Forwarding no
|
||||
AllowTcpForwarding no
|
||||
AllowAgentForwarding no
|
||||
ForceCommand internal-sftp
|
||||
Match user data
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
'';
|
||||
authorizedKeysFiles = [ "/run/secrets/%u_authorized_keys" ];
|
||||
};
|
||||
}
|
122
modules/nixos/services/data-access/default.nix
Normal file
122
modules/nixos/services/data-access/default.nix
Normal file
|
@ -0,0 +1,122 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.data-access.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.data-access.enable {
|
||||
chvp.services = {
|
||||
containers.enable = true;
|
||||
nginx.hosts = [
|
||||
{
|
||||
fqdn = "data.vanpetegem.me";
|
||||
options = {
|
||||
default = true;
|
||||
basicAuthFile = config.age.secrets."passwords/services/data-basic-auth".path;
|
||||
root = "/srv/data";
|
||||
locations = {
|
||||
"/".extraConfig = ''
|
||||
autoindex on;
|
||||
'';
|
||||
"/public".extraConfig = ''
|
||||
autoindex on;
|
||||
auth_basic off;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 2002 ];
|
||||
|
||||
containers.data-access = {
|
||||
ephemeral = true;
|
||||
autoStart = true;
|
||||
bindMounts = {
|
||||
"/home/data/data" = {
|
||||
hostPath = "/srv/data";
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/home/readonly/data" = {
|
||||
hostPath = "/srv/data";
|
||||
isReadOnly = true;
|
||||
};
|
||||
"/run/secrets" = {
|
||||
hostPath = "/run/data-access";
|
||||
isReadOnly = true;
|
||||
};
|
||||
};
|
||||
forwardPorts = [{
|
||||
containerPort = 22;
|
||||
hostPort = 2002;
|
||||
protocol = "tcp";
|
||||
}];
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.10";
|
||||
hostAddress6 = "fc00::1";
|
||||
localAddress = "192.168.100.11";
|
||||
localAddress6 = "fc00::2";
|
||||
config = { ... }: {
|
||||
system.stateVersion = config.chvp.stateVersion;
|
||||
imports = [ ./config.nix ];
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."data-access/ssh_host_rsa_key" = {
|
||||
file = ../../../../secrets/data-access/ssh_host_rsa_key.age;
|
||||
path = "/run/data-access/ssh_host_rsa_key";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/ssh_host_rsa_key.pub" = {
|
||||
file = ../../../../secrets/data-access/ssh_host_rsa_key.pub.age;
|
||||
path = "/run/data-access/ssh_host_rsa_key.pub";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/ssh_host_ed25519_key" = {
|
||||
file = ../../../../secrets/data-access/ssh_host_ed25519_key.age;
|
||||
path = "/run/data-access/ssh_host_ed25519_key";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/ssh_host_ed25519_key.pub" = {
|
||||
file = ../../../../secrets/data-access/ssh_host_ed25519_key.pub.age;
|
||||
path = "/run/data-access/ssh_host_ed25519_key.pub";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/password_file" = {
|
||||
file = ../../../../secrets/data-access/password_file.age;
|
||||
path = "/run/data-access/password_file";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/readonly_password_file" = {
|
||||
file = ../../../../secrets/data-access/readonly_password_file.age;
|
||||
path = "/run/data-access/readonly_password_file";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/authorized_keys" = {
|
||||
file = ../../../../secrets/data-access/authorized_keys.age;
|
||||
owner = "charlotte";
|
||||
path = "/run/data-access/data_authorized_keys";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/readonly_authorized_keys" = {
|
||||
file = ../../../../secrets/data-access/readonly_authorized_keys.age;
|
||||
owner = "1001";
|
||||
group = "65534";
|
||||
path = "/run/data-access/readonly_authorized_keys";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/create_torrent" = {
|
||||
file = ../../../../secrets/data-access/create_torrent.age;
|
||||
owner = "charlotte";
|
||||
path = "/run/data-access/create_torrent";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."passwords/services/data-basic-auth" = {
|
||||
file = ../../../../secrets/passwords/services/data-basic-auth.age;
|
||||
owner = "nginx";
|
||||
};
|
||||
};
|
||||
}
|
20
modules/nixos/services/default.nix
Normal file
20
modules/nixos/services/default.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./accentor
|
||||
./containers
|
||||
./data-access
|
||||
./garmin-scraper
|
||||
./git
|
||||
./grafana
|
||||
./mail
|
||||
./mastodon
|
||||
./matrix
|
||||
./nextcloud
|
||||
./nginx
|
||||
./torrents
|
||||
];
|
||||
|
||||
services.postgresql.package = pkgs.postgresql_15;
|
||||
}
|
39
modules/nixos/services/garmin-scraper/default.nix
Normal file
39
modules/nixos/services/garmin-scraper/default.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
garmin2influx = pkgs.writers.writePython3Bin "garmin2influx"
|
||||
{
|
||||
libraries = with pkgs.python3Packages; [ garminconnect influxdb-client ];
|
||||
}
|
||||
(builtins.readFile ./garmin2influx.py);
|
||||
in
|
||||
{
|
||||
options.chvp.services.garmin-scraper.enable = lib.mkEnableOption "garmin scraper";
|
||||
|
||||
config = lib.mkIf config.chvp.services.garmin-scraper.enable {
|
||||
# Install in environment to allow manual data collection
|
||||
environment.systemPackages = [ garmin2influx ];
|
||||
systemd = {
|
||||
services.garmin2influx = {
|
||||
description = "Garmin health data importer";
|
||||
restartIfChanged = false;
|
||||
unitConfig.X-StopOnRemoval = false;
|
||||
serviceConfig = {
|
||||
EnvironmentFile = config.age.secrets."passwords/services/garmin2influx-env".path;
|
||||
Type = "oneshot";
|
||||
User = "charlotte";
|
||||
Group = "users";
|
||||
ExecStart = "${garmin2influx}/bin/garmin2influx";
|
||||
RestartSec = "5s";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
startAt = "02/4:00";
|
||||
};
|
||||
timers.garmin2influx.timerConfig.RandomizedDelaySec = "30min";
|
||||
};
|
||||
age.secrets."passwords/services/garmin2influx-env" = {
|
||||
file = ../../../../secrets/passwords/services/garmin2influx-env.age;
|
||||
owner = "charlotte";
|
||||
};
|
||||
};
|
||||
}
|
88
modules/nixos/services/garmin-scraper/garmin2influx.py
Normal file
88
modules/nixos/services/garmin-scraper/garmin2influx.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
import os
|
||||
import sys
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
from garminconnect import (
|
||||
Garmin,
|
||||
GarminConnectConnectionError,
|
||||
GarminConnectTooManyRequestsError,
|
||||
GarminConnectAuthenticationError,
|
||||
)
|
||||
from influxdb_client import InfluxDBClient, Point, WritePrecision
|
||||
from influxdb_client.client.write_api import SYNCHRONOUS
|
||||
|
||||
email = os.getenv('EMAIL')
|
||||
password = os.getenv('PASSWORD')
|
||||
token = os.getenv('TOKEN')
|
||||
org = 'default'
|
||||
bucket = 'default'
|
||||
|
||||
|
||||
def hr2point(time, val):
|
||||
return Point("health") \
|
||||
.field("heart_rate", val) \
|
||||
.time(
|
||||
datetime.fromtimestamp(time / 1000, timezone.utc),
|
||||
WritePrecision.S
|
||||
)
|
||||
|
||||
|
||||
def stress2point(time, val):
|
||||
return Point("health") \
|
||||
.field("stress", max(val, 0)) \
|
||||
.time(
|
||||
datetime.fromtimestamp(time / 1000, timezone.utc),
|
||||
WritePrecision.S
|
||||
)
|
||||
|
||||
|
||||
def hr_for_date(api, date_to_fetch):
|
||||
return api.get_heart_rates(date_to_fetch.isoformat())['heartRateValues']
|
||||
|
||||
|
||||
def stress_for_date(api, date_to_fetch):
|
||||
return api.get_stress_data(date_to_fetch.isoformat())['stressValuesArray']
|
||||
|
||||
|
||||
date_to_fetch = date.today().isoformat()
|
||||
if len(sys.argv) > 1:
|
||||
date_to_fetch = sys.argv[1]
|
||||
|
||||
date_to_fetch = date.fromisoformat(date_to_fetch)
|
||||
|
||||
try:
|
||||
api = Garmin(email, password)
|
||||
api.login()
|
||||
hr_points = list(map(
|
||||
lambda p: hr2point(*p),
|
||||
hr_for_date(api, date_to_fetch - timedelta(days=1))
|
||||
))
|
||||
stress_points = list(map(
|
||||
lambda p: stress2point(*p),
|
||||
stress_for_date(api, date_to_fetch - timedelta(days=1))
|
||||
))
|
||||
hr_points += list(map(
|
||||
lambda p: hr2point(*p),
|
||||
hr_for_date(api, date_to_fetch)
|
||||
))
|
||||
stress_points += list(map(
|
||||
lambda p: stress2point(*p),
|
||||
stress_for_date(api, date_to_fetch)
|
||||
))
|
||||
with InfluxDBClient(
|
||||
url="https://stats.chvp.be:8086",
|
||||
token=token,
|
||||
org=org
|
||||
) as client:
|
||||
write_api = client.write_api(write_options=SYNCHRONOUS)
|
||||
write_api.write(bucket, org, hr_points)
|
||||
write_api.write(bucket, org, stress_points)
|
||||
except (
|
||||
GarminConnectConnectionError,
|
||||
GarminConnectAuthenticationError,
|
||||
GarminConnectTooManyRequestsError,
|
||||
) as err:
|
||||
print(
|
||||
f'Error occured during Garmin Connect communication: {err}',
|
||||
file=sys.stderr
|
||||
)
|
||||
sys.exit(1)
|
85
modules/nixos/services/git/default.nix
Normal file
85
modules/nixos/services/git/default.nix
Normal file
|
@ -0,0 +1,85 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./runner.nix ];
|
||||
|
||||
options.chvp.services.git.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.git.enable {
|
||||
chvp.services.nginx.hosts = [{
|
||||
fqdn = "git.chvp.be";
|
||||
options = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
|
||||
extraConfig = ''
|
||||
client_max_body_size 50M;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}];
|
||||
users = {
|
||||
users = {
|
||||
git = {
|
||||
uid = lib.mkForce 963;
|
||||
group = "git";
|
||||
isSystemUser = true;
|
||||
useDefaultShell = true;
|
||||
};
|
||||
nginx.extraGroups = [ "git" ];
|
||||
};
|
||||
groups.git.gid = lib.mkForce 963;
|
||||
};
|
||||
services.openssh.settings.AcceptEnv = "GIT_PROTOCOL";
|
||||
services.gitlab = {
|
||||
enable = true;
|
||||
statePath = "/var/lib/git/state";
|
||||
backup.path = "/var/lib/git/backup";
|
||||
databaseCreateLocally = true;
|
||||
databaseUsername = "git";
|
||||
databaseName = "git";
|
||||
user = "git";
|
||||
group = "git";
|
||||
host = "git.chvp.be";
|
||||
port = 443;
|
||||
https = true;
|
||||
initialRootEmail = "charlotte@vanpetegem.be";
|
||||
initialRootPasswordFile = config.age.secrets."passwords/services/git/initial-root-password".path;
|
||||
# Hack, https://github.com/NixOS/nixpkgs/pull/135926 broke stuff
|
||||
pages.settings.pages-domain = "not.actually.enabled";
|
||||
secrets = {
|
||||
dbFile = config.age.secrets."passwords/services/git/db".path;
|
||||
jwsFile = config.age.secrets."passwords/services/git/jws".path;
|
||||
otpFile = config.age.secrets."passwords/services/git/otp".path;
|
||||
secretFile = config.age.secrets."passwords/services/git/secret".path;
|
||||
};
|
||||
smtp = {
|
||||
enable = true;
|
||||
enableStartTLSAuto = false;
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."passwords/services/git/initial-root-password" = {
|
||||
file = ../../../../secrets/passwords/services/git/initial-root-password.age;
|
||||
owner = "git";
|
||||
};
|
||||
age.secrets."passwords/services/git/db" = {
|
||||
file = ../../../../secrets/passwords/services/git/db.age;
|
||||
owner = "git";
|
||||
};
|
||||
age.secrets."passwords/services/git/jws" = {
|
||||
file = ../../../../secrets/passwords/services/git/jws.age;
|
||||
owner = "git";
|
||||
};
|
||||
age.secrets."passwords/services/git/otp" = {
|
||||
file = ../../../../secrets/passwords/services/git/otp.age;
|
||||
owner = "git";
|
||||
};
|
||||
age.secrets."passwords/services/git/secret" = {
|
||||
file = ../../../../secrets/passwords/services/git/secret.age;
|
||||
owner = "git";
|
||||
};
|
||||
};
|
||||
}
|
57
modules/nixos/services/git/runner.nix
Normal file
57
modules/nixos/services/git/runner.nix
Normal file
|
@ -0,0 +1,57 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.git.runner.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.git.runner.enable {
|
||||
services.gitlab-runner = {
|
||||
enable = true;
|
||||
settings.concurrent = 8;
|
||||
services = {
|
||||
nix = {
|
||||
authenticationTokenConfigFile = config.age.secrets."passwords/services/gitlab-runner/registration".path;
|
||||
dockerImage = "alpine";
|
||||
dockerVolumes = [
|
||||
"/nix/store:/nix/store:ro"
|
||||
"/nix/var/nix/db:/nix/var/nix/db:ro"
|
||||
"/nix/var/nix/daemon-socket:/nix/var/nix/daemon-socket:ro"
|
||||
"/etc/nix/nix.conf:/etc/nix/nix.conf:ro"
|
||||
];
|
||||
preBuildScript = pkgs.writeScript "setup-container" ''
|
||||
mkdir -p -m 0755 /nix/var/log/nix/drvs
|
||||
mkdir -p -m 0755 /nix/var/nix/gcroots
|
||||
mkdir -p -m 0755 /nix/var/nix/profiles
|
||||
mkdir -p -m 0755 /nix/var/nix/temproots
|
||||
mkdir -p -m 0755 /nix/var/nix/userpool
|
||||
mkdir -p -m 1777 /nix/var/nix/gcroots/per-user
|
||||
mkdir -p -m 1777 /nix/var/nix/profiles/per-user
|
||||
mkdir -p -m 0755 /nix/var/nix/profiles/per-user/root
|
||||
mkdir -p -m 0700 "$HOME/.nix-defexpr"
|
||||
|
||||
. ${pkgs.nix}/etc/profile.d/nix.sh
|
||||
|
||||
${pkgs.nix}/bin/nix-env -i ${lib.concatStringsSep " " (with pkgs; [ nix cacert git openssh ])}
|
||||
'';
|
||||
environmentVariables = {
|
||||
ENV = "/etc/profile";
|
||||
USER = "root";
|
||||
NIX_REMOTE = "daemon";
|
||||
PATH = "/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin";
|
||||
NIX_SSL_CERT_FILE = "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt";
|
||||
};
|
||||
requestConcurrency = 4;
|
||||
};
|
||||
};
|
||||
};
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
storageDriver = "zfs";
|
||||
};
|
||||
age.secrets."passwords/services/gitlab-runner/registration" = {
|
||||
file = ../../../../secrets/passwords/services/gitlab-runner/registration.age;
|
||||
};
|
||||
};
|
||||
}
|
97
modules/nixos/services/grafana/default.nix
Normal file
97
modules/nixos/services/grafana/default.nix
Normal file
|
@ -0,0 +1,97 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.grafana.enable = lib.mkEnableOption "grafana";
|
||||
|
||||
config = lib.mkIf config.chvp.services.grafana.enable {
|
||||
chvp.services.nginx.hosts = [{
|
||||
fqdn = "stats.chvp.be";
|
||||
options.locations."/" = {
|
||||
proxyPass = "http://grafana";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
}];
|
||||
users.users = {
|
||||
influxdb2.extraGroups = [ "acme" ];
|
||||
nginx.extraGroups = [ "grafana" ];
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 8086 ];
|
||||
services = {
|
||||
nginx.upstreams.grafana.servers = { "unix:/run/grafana/grafana.sock" = { }; };
|
||||
influxdb2 = {
|
||||
enable = true;
|
||||
settings = {
|
||||
reporting-disabled = true;
|
||||
tls-cert = "${config.security.acme.certs."vanpetegem.me".directory}/fullchain.pem";
|
||||
tls-key = "${config.security.acme.certs."vanpetegem.me".directory}/key.pem";
|
||||
};
|
||||
};
|
||||
grafana = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/grafana";
|
||||
settings = {
|
||||
analytics.reporting_enabled = false;
|
||||
"auth.anonymous" = {
|
||||
enabled = "true";
|
||||
org_name = "Van Petegem";
|
||||
};
|
||||
database = {
|
||||
user = "grafana";
|
||||
type = "postgres";
|
||||
host = "/run/postgresql/";
|
||||
name = "grafana";
|
||||
};
|
||||
security = {
|
||||
admin_user = "chvp";
|
||||
admin_password = "$__file{${config.age.secrets."passwords/services/grafana/admin-password".path}}";
|
||||
secret_key = "$__file{${config.age.secrets."passwords/services/grafana/secret-key".path}}";
|
||||
};
|
||||
server = {
|
||||
domain = "stats.chvp.be";
|
||||
http_port = 3000;
|
||||
protocol = "socket";
|
||||
root_url = "https://stats.chvp.be";
|
||||
socket = "/run/grafana/grafana.sock";
|
||||
};
|
||||
smtp = {
|
||||
enabled = true;
|
||||
host = "mail.vanpetegem.me:25";
|
||||
user = "noreply@vanpetegem.me";
|
||||
from_address = "noreply@vanpetegem.me";
|
||||
password = "$__file{${config.age.secrets."passwords/services/grafana/smtp".path}}";
|
||||
};
|
||||
users = {
|
||||
default_theme = "light";
|
||||
allow_sign_up = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
grafana-image-renderer = {
|
||||
enable = true;
|
||||
provisionGrafana = true;
|
||||
chromium = pkgs.ungoogled-chromium;
|
||||
};
|
||||
postgresql = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
ensureDatabases = [ "grafana" ];
|
||||
ensureUsers = [{
|
||||
name = "grafana";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
};
|
||||
age.secrets."passwords/services/grafana/smtp" = {
|
||||
file = ../../../../secrets/passwords/services/grafana/smtp.age;
|
||||
owner = "grafana";
|
||||
};
|
||||
age.secrets."passwords/services/grafana/admin-password" = {
|
||||
file = ../../../../secrets/passwords/services/grafana/admin-password.age;
|
||||
owner = "grafana";
|
||||
};
|
||||
age.secrets."passwords/services/grafana/secret-key" = {
|
||||
file = ../../../../secrets/passwords/services/grafana/secret-key.age;
|
||||
owner = "grafana";
|
||||
};
|
||||
};
|
||||
}
|
166
modules/nixos/services/mail/default.nix
Normal file
166
modules/nixos/services/mail/default.nix
Normal file
|
@ -0,0 +1,166 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
keyFile = "${config.security.acme.certs."vanpetegem.me".directory}/key.pem";
|
||||
certFile = "${config.security.acme.certs."vanpetegem.me".directory}/fullchain.pem";
|
||||
in
|
||||
{
|
||||
options.chvp.services.mail.enable = lib.mkEnableOption "mail";
|
||||
|
||||
config = lib.mkIf config.chvp.services.mail.enable {
|
||||
chvp.base.zfs.systemLinks = [
|
||||
{ path = "/var/lib/dhparams"; type = "cache"; }
|
||||
{ path = "/var/lib/dovecot"; type = "cache"; }
|
||||
{ path = "/var/lib/opendkim"; type = "cache"; }
|
||||
{ path = "/var/lib/postfix"; type = "cache"; }
|
||||
{ path = "/var/lib/redis-rspamd"; type = "cache"; }
|
||||
{ path = "/var/lib/rspamd"; type = "cache"; }
|
||||
{ path = "/var/sieve"; type = "data"; }
|
||||
];
|
||||
mailserver = {
|
||||
enable = true;
|
||||
enableManageSieve = true;
|
||||
fqdn = "mail.vanpetegem.me";
|
||||
domains = [
|
||||
"accentor.tech"
|
||||
"chvp.be"
|
||||
"cvpetegem.be"
|
||||
"robbe.be"
|
||||
"robbevanpetegem.be"
|
||||
"robbevp.be"
|
||||
"toekomstlabo.be"
|
||||
"vanpetegem.be"
|
||||
"vanpetegem.me"
|
||||
];
|
||||
localDnsResolver = false;
|
||||
loginAccounts = {
|
||||
"charlotte@vanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/charlotte@vanpetegem.be".path;
|
||||
aliases = [ "@chvp.be" "@cvpetegem.be" "charlotte@vanpetegem.me" ];
|
||||
};
|
||||
"huis@vanpetegem.me".hashedPasswordFile = config.age.secrets."passwords/services/mail/huis@vanpetegem.me".path;
|
||||
"noreply@vanpetegem.me" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/noreply@vanpetegem.me".path;
|
||||
sendOnly = true;
|
||||
};
|
||||
"peter@vanpetegem.me".hashedPasswordFile = config.age.secrets."passwords/services/mail/peter@vanpetegem.me".path;
|
||||
"postbot@vanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/postbot@vanpetegem.be".path;
|
||||
aliases = [ "@vanpetegem.me" "@vanpetegem.be" ];
|
||||
};
|
||||
"robbe@vanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/robbe@vanpetegem.be".path;
|
||||
aliases = [ "robbe.nb@vanpetegem.me" "robbe@vanpetegem.me" ];
|
||||
};
|
||||
"robbe@robbevanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/robbe@robbevanpetegem.be".path;
|
||||
aliases = [ "@robbevanpetegem.be" ];
|
||||
};
|
||||
"hallo@robbe.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/hallo@robbe.be".path;
|
||||
aliases = [ "@robbe.be" "@robbevp.be" ];
|
||||
};
|
||||
"webmaster@vanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/webmaster@vanpetegem.be".path;
|
||||
aliases = [ "webmaster@vanpetegem.me" ];
|
||||
};
|
||||
};
|
||||
indexDir = "${config.chvp.cachePrefix}/var/lib/dovecot/indices";
|
||||
fullTextSearch = {
|
||||
enable = false;
|
||||
memoryLimit = 4000;
|
||||
};
|
||||
lmtpSaveToDetailMailbox = "no";
|
||||
mailboxes = {
|
||||
Trash = {
|
||||
auto = "no";
|
||||
specialUse = "Trash";
|
||||
autoexpunge = "60d";
|
||||
};
|
||||
Junk = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Junk";
|
||||
autoexpunge = "60d";
|
||||
};
|
||||
Drafts = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Drafts";
|
||||
};
|
||||
Sent = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Sent";
|
||||
};
|
||||
};
|
||||
extraVirtualAliases = {
|
||||
"team@accentor.tech" = [ "charlotte@vanpetegem.be" "robbe@vanpetegem.be" ];
|
||||
};
|
||||
forwards = {
|
||||
"info@toekomstlabo.be" = "robbe+toekomstlabo@robbevanpetegem.be";
|
||||
};
|
||||
rejectRecipients = [
|
||||
"cindy@vanpetegem.be"
|
||||
"contact@vanpetegem.be"
|
||||
"info@vanpetegem.be"
|
||||
"isabelle@vanpetegem.be"
|
||||
"marierose@vanpetegem.be"
|
||||
"rudy@vanpetegem.be"
|
||||
"sarina@vanpetegem.be"
|
||||
"sabrina@vanpetegem.be"
|
||||
];
|
||||
rejectSender = [
|
||||
"junjunggaming07@gmail.com"
|
||||
"censysnetbackup@gmail.com"
|
||||
"vitor.carvalheiro@escola.pr.gov.br"
|
||||
"spam@vuztc.ru"
|
||||
"mofos@theportalnetworks.com" # Someone registered my f-droid contact address on a porn site :(
|
||||
];
|
||||
mailDirectory = "${config.chvp.dataPrefix}/var/vmail";
|
||||
useFsLayout = false;
|
||||
certificateScheme = "manual";
|
||||
certificateFile = certFile;
|
||||
keyFile = keyFile;
|
||||
dkimKeyDirectory = "${config.chvp.dataPrefix}/var/dkim";
|
||||
};
|
||||
|
||||
services.dovecot2.sieve = {
|
||||
extensions = [ "editheader" ];
|
||||
scripts.after2 = pkgs.writeText "custom-spam.sieve" ''
|
||||
require ["fileinto", "regex"];
|
||||
|
||||
if anyof(
|
||||
# Freshdesk is often used to sent spam from emails like `support@info5813.freshdesk.com`
|
||||
address :regex "From" "[a-z\d]+@[a-z\d]+\.freshdesk\.com",
|
||||
header :contains "From" ["jakubbielec", "Jakub Bielec"],
|
||||
# Stop any mail pretending to be from itsme not from their official domains
|
||||
allof(
|
||||
address :contains "From" "itsme",
|
||||
not address :matches :domain "from" ["*itsme.be", "*itsme-id.com"]
|
||||
)
|
||||
) {
|
||||
fileinto "Junk";
|
||||
stop;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
services.rspamd.extraConfig = ''
|
||||
actions {
|
||||
reject = null;
|
||||
add_header = 6;
|
||||
greylist = 4;
|
||||
}
|
||||
'';
|
||||
|
||||
age.secrets = {
|
||||
"passwords/services/mail/charlotte@vanpetegem.be".file = ../../../../secrets/passwords/services/mail/charlotte_at_vanpetegem.be.age;
|
||||
"passwords/services/mail/hallo@robbe.be".file = ../../../../secrets/passwords/services/mail/hallo_at_robbe.be.age;
|
||||
"passwords/services/mail/huis@vanpetegem.me".file = ../../../../secrets/passwords/services/mail/huis_at_vanpetegem.me.age;
|
||||
"passwords/services/mail/noreply@vanpetegem.me".file = ../../../../secrets/passwords/services/mail/noreply_at_vanpetegem.me.age;
|
||||
"passwords/services/mail/peter@vanpetegem.me".file = ../../../../secrets/passwords/services/mail/peter_at_vanpetegem.me.age;
|
||||
"passwords/services/mail/postbot@vanpetegem.be".file = ../../../../secrets/passwords/services/mail/postbot_at_vanpetegem.be.age;
|
||||
"passwords/services/mail/robbe@robbevanpetegem.be".file = ../../../../secrets/passwords/services/mail/robbe_at_robbevanpetegem.be.age;
|
||||
"passwords/services/mail/robbe@vanpetegem.be".file = ../../../../secrets/passwords/services/mail/robbe_at_vanpetegem.be.age;
|
||||
"passwords/services/mail/webmaster@vanpetegem.be".file = ../../../../secrets/passwords/services/mail/webmaster_at_vanpetegem.be.age;
|
||||
};
|
||||
};
|
||||
}
|
75
modules/nixos/services/mastodon/default.nix
Normal file
75
modules/nixos/services/mastodon/default.nix
Normal file
|
@ -0,0 +1,75 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.mastodon.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.mastodon.enable {
|
||||
chvp.services.nginx.hosts = [{
|
||||
fqdn = "social.chvp.be";
|
||||
options = {
|
||||
root = "${pkgs.mastodon}/public/";
|
||||
locations = {
|
||||
"/system/".alias = "/var/lib/mastodon/public-system/";
|
||||
"/".tryFiles = "$uri @proxy";
|
||||
"@proxy" = {
|
||||
proxyPass = "http://unix:/run/mastodon-web/web.socket";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
"/api/v1/streaming" = {
|
||||
proxyPass = "http://unix:/run/mastodon-streaming/streaming.socket";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}];
|
||||
users = {
|
||||
users = {
|
||||
mastodon.uid = 989;
|
||||
nginx.extraGroups = [ "mastodon" ];
|
||||
};
|
||||
groups.mastodon.gid = 985;
|
||||
};
|
||||
services.mastodon = {
|
||||
enable = true;
|
||||
configureNginx = false;
|
||||
localDomain = "social.chvp.be";
|
||||
enableUnixSocket = true;
|
||||
streamingProcesses = 4;
|
||||
|
||||
database.createLocally = true;
|
||||
redis.createLocally = true;
|
||||
smtp = {
|
||||
fromAddress = "social@chvp.be";
|
||||
createLocally = false;
|
||||
};
|
||||
extraConfig = {
|
||||
SMTP_OPENSSL_VERIFY_MODE = "none";
|
||||
};
|
||||
|
||||
otpSecretFile = config.age.secrets."passwords/services/mastodon/otp".path;
|
||||
secretKeyBaseFile = config.age.secrets."passwords/services/mastodon/key".path;
|
||||
vapidPublicKeyFile = config.age.secrets."passwords/services/mastodon/vapid-public".path;
|
||||
vapidPrivateKeyFile = config.age.secrets."passwords/services/mastodon/vapid-private".path;
|
||||
};
|
||||
|
||||
age.secrets."passwords/services/mastodon/vapid-public" = {
|
||||
file = ../../../../secrets/passwords/services/mastodon/vapid-public.age;
|
||||
owner = "mastodon";
|
||||
};
|
||||
age.secrets."passwords/services/mastodon/vapid-private" = {
|
||||
file = ../../../../secrets/passwords/services/mastodon/vapid-private.age;
|
||||
owner = "mastodon";
|
||||
};
|
||||
age.secrets."passwords/services/mastodon/key" = {
|
||||
file = ../../../../secrets/passwords/services/mastodon/key.age;
|
||||
owner = "mastodon";
|
||||
};
|
||||
age.secrets."passwords/services/mastodon/otp" = {
|
||||
file = ../../../../secrets/passwords/services/mastodon/otp.age;
|
||||
owner = "mastodon";
|
||||
};
|
||||
};
|
||||
}
|
229
modules/nixos/services/matrix/default.nix
Normal file
229
modules/nixos/services/matrix/default.nix
Normal file
|
@ -0,0 +1,229 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.matrix.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.matrix.enable {
|
||||
chvp.base.zfs.systemLinks = [{ path = "/var/lib/matrix-hookshot"; type = "data"; }];
|
||||
chvp.services.nginx.hosts = [
|
||||
{
|
||||
fqdn = "matrix.vanpetegem.me";
|
||||
options.locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://127.0.0.1:8448";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_read_timeout 600;
|
||||
client_max_body_size 10M;
|
||||
'';
|
||||
};
|
||||
"/_slack" = {
|
||||
proxyPass = "http://127.0.0.1:9898";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
'';
|
||||
};
|
||||
"~ ^/_hookshot/(.*)" = {
|
||||
proxyPass = "http://127.0.0.1:9000/$1";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
fqdn = "matrix-sync.vanpetegem.me";
|
||||
basicProxy = "http://localhost:8009";
|
||||
}
|
||||
];
|
||||
|
||||
services = {
|
||||
matrix-synapse = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server_name = "vanpetegem.me";
|
||||
public_baseurl = "https://matrix.vanpetegem.me";
|
||||
listeners = [{
|
||||
port = 8448;
|
||||
bind_addresses = [ "::1" "127.0.0.1" ];
|
||||
type = "http";
|
||||
tls = false;
|
||||
x_forwarded = true;
|
||||
resources = [
|
||||
{ names = [ "client" ]; compress = true; }
|
||||
{ names = [ "federation" ]; compress = false; }
|
||||
];
|
||||
}];
|
||||
url_preview_enabled = true;
|
||||
enable_metrics = false;
|
||||
enable_registration = false;
|
||||
report_stats = false;
|
||||
allow_guest_access = false;
|
||||
suppress_key_server_warning = true;
|
||||
app_service_config_files = [
|
||||
config.age.secrets."files/services/matrix-synapse/whatsapp-registration.yml".path
|
||||
config.age.secrets."files/services/matrix-synapse/slack-registration.yml".path
|
||||
config.age.secrets."files/services/matrix-synapse/hookshot-registration.yml".path
|
||||
];
|
||||
};
|
||||
extraConfigFiles = [
|
||||
config.age.secrets."files/services/matrix-synapse/config.yml".path
|
||||
];
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/matrix-synapse";
|
||||
};
|
||||
postgresql = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
ensureDatabases = [
|
||||
"matrix-synapse"
|
||||
"matrix_appservice_slack"
|
||||
"mautrix_whatsapp"
|
||||
];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "matrix_appservice_slack";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "mautrix_whatsapp";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "matrix-synapse";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
matrix-sliding-sync = {
|
||||
enable = true;
|
||||
settings = {
|
||||
SYNCV3_SERVER = "https://matrix.vanpetegem.me";
|
||||
};
|
||||
environmentFile = config.age.secrets."files/servers/matrix-sliding-sync/env".path;
|
||||
createDatabase = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
matrix-appservice-slack = {
|
||||
description = "Matrix <-> Slack bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "postgresql.service" "matrix-synapse.service" ];
|
||||
requires = [ "postgresql.service" "matrix-synapse.service" ];
|
||||
script = "${pkgs.matrix-appservice-slack}/bin/matrix-appservice-slack --config ${config.age.secrets."files/services/matrix-appservice-slack/config.yml".path} --file ${config.age.secrets."files/services/matrix-appservice-slack/registration.yml".path}";
|
||||
serviceConfig = {
|
||||
User = "matrix_appservice_slack";
|
||||
Group = "matrix_appservice_slack";
|
||||
};
|
||||
};
|
||||
matrix-synapse = {
|
||||
requires = [ "postgresql.service" ];
|
||||
};
|
||||
mautrix-whatsapp = {
|
||||
description = "Matrix <-> WhatsApp bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "postgresql.service" "matrix-synapse.service" ];
|
||||
requires = [ "postgresql.service" "matrix-synapse.service" ];
|
||||
script = "${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp --config ${config.age.secrets."files/services/mautrix-whatsapp/config.yml".path}";
|
||||
serviceConfig = {
|
||||
User = "mautrix_whatsapp";
|
||||
Group = "mautrix_whatsapp";
|
||||
};
|
||||
};
|
||||
matrix-hookshot = {
|
||||
description = "Matrix <-> Services bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "matrix-synapse.service" ];
|
||||
requires = [ "matrix-synapse.service" ];
|
||||
script = "${pkgs.matrix-hookshot}/bin/matrix-hookshot ${config.age.secrets."files/services/matrix-hookshot/config.yml".path} ${config.age.secrets."files/services/matrix-hookshot/registration.yml".path}";
|
||||
serviceConfig = {
|
||||
User = "matrix_hookshot";
|
||||
Group = "matrix_hookshot";
|
||||
WorkingDirectory = "/var/lib/matrix-hookshot";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users = {
|
||||
users = {
|
||||
matrix_appservice_slack = {
|
||||
uid = 998;
|
||||
group = "matrix_appservice_slack";
|
||||
isSystemUser = true;
|
||||
};
|
||||
mautrix_whatsapp = {
|
||||
uid = 997;
|
||||
group = "mautrix_whatsapp";
|
||||
isSystemUser = true;
|
||||
};
|
||||
matrix_hookshot = {
|
||||
uid = 979;
|
||||
group = "matrix_hookshot";
|
||||
home = "/var/lib/matrix-hookshot";
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
groups = {
|
||||
matrix_appservice_slack = {
|
||||
gid = 998;
|
||||
};
|
||||
mautrix_whatsapp = {
|
||||
gid = 997;
|
||||
};
|
||||
matrix_hookshot = {
|
||||
gid = 979;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."files/services/matrix-appservice-slack/config.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-appservice-slack/config.yml.age;
|
||||
owner = "matrix_appservice_slack";
|
||||
};
|
||||
age.secrets."files/services/matrix-appservice-slack/registration.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-appservice-slack/registration.yml.age;
|
||||
owner = "matrix_appservice_slack";
|
||||
};
|
||||
age.secrets."files/services/matrix-hookshot/config.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-hookshot/config.yml.age;
|
||||
owner = "matrix_hookshot";
|
||||
};
|
||||
age.secrets."files/services/matrix-hookshot/registration.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-hookshot/registration.yml.age;
|
||||
owner = "matrix_hookshot";
|
||||
};
|
||||
age.secrets."files/services/matrix-hookshot/passkey.pem" = {
|
||||
path = "/var/lib/matrix-hookshot/passkey.pem";
|
||||
file = ../../../../secrets/files/services/matrix-hookshot/passkey.pem.age;
|
||||
owner = "matrix_hookshot";
|
||||
};
|
||||
age.secrets."files/services/mautrix-whatsapp/config.yml" = {
|
||||
file = ../../../../secrets/files/services/mautrix-whatsapp/config.yml.age;
|
||||
owner = "mautrix_whatsapp";
|
||||
};
|
||||
age.secrets."files/services/mautrix-whatsapp/registration.yml" = {
|
||||
file = ../../../../secrets/files/services/mautrix-whatsapp/registration.yml.age;
|
||||
owner = "mautrix_whatsapp";
|
||||
};
|
||||
age.secrets."files/services/matrix-synapse/config.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-synapse/config.yml.age;
|
||||
owner = "matrix-synapse";
|
||||
};
|
||||
age.secrets."files/services/matrix-synapse/slack-registration.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-appservice-slack/registration.yml.age;
|
||||
owner = "matrix-synapse";
|
||||
};
|
||||
age.secrets."files/services/matrix-synapse/whatsapp-registration.yml" = {
|
||||
file = ../../../../secrets/files/services/mautrix-whatsapp/registration.yml.age;
|
||||
owner = "matrix-synapse";
|
||||
};
|
||||
age.secrets."files/services/matrix-synapse/hookshot-registration.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-hookshot/registration.yml.age;
|
||||
owner = "matrix-synapse";
|
||||
};
|
||||
age.secrets."files/servers/matrix-sliding-sync/env".file = ../../../../secrets/files/services/matrix-sliding-sync/env.age;
|
||||
};
|
||||
}
|
68
modules/nixos/services/nextcloud/default.nix
Normal file
68
modules/nixos/services/nextcloud/default.nix
Normal file
|
@ -0,0 +1,68 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.nextcloud.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
config = lib.mkIf config.chvp.services.nextcloud.enable {
|
||||
services = {
|
||||
nextcloud = {
|
||||
home = "${config.chvp.dataPrefix}/var/lib/nextcloud";
|
||||
https = true;
|
||||
hostName = "nextcloud.vanpetegem.me";
|
||||
enable = true;
|
||||
autoUpdateApps.enable = true;
|
||||
package = pkgs.nextcloud29;
|
||||
caching.redis = true;
|
||||
config = {
|
||||
dbuser = "nextcloud";
|
||||
dbname = "nextcloud";
|
||||
dbtype = "pgsql";
|
||||
dbhost = "/run/postgresql";
|
||||
adminuser = "admin";
|
||||
adminpassFile = config.age.secrets."passwords/services/nextcloud-admin".path;
|
||||
};
|
||||
settings.redis = {
|
||||
host = "127.0.0.1";
|
||||
port = 31638;
|
||||
dbindex = 0;
|
||||
timeout = 1.5;
|
||||
};
|
||||
};
|
||||
nginx.virtualHosts."nextcloud.vanpetegem.me" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "vanpetegem.me";
|
||||
extraConfig = ''
|
||||
fastcgi_connect_timeout 10m;
|
||||
fastcgi_read_timeout 10m;
|
||||
fastcgi_send_timeout 10m;
|
||||
'';
|
||||
};
|
||||
postgresql = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
ensureDatabases = [ "nextcloud" ];
|
||||
ensureUsers = [{
|
||||
name = "nextcloud";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
redis.servers.nextcloud = {
|
||||
enable = true;
|
||||
port = 31638;
|
||||
bind = "127.0.0.1";
|
||||
};
|
||||
};
|
||||
age.secrets."passwords/services/nextcloud-admin" = {
|
||||
file = ../../../../secrets/passwords/services/nextcloud-admin.age;
|
||||
owner = "nextcloud";
|
||||
};
|
||||
systemd.services."nextcloud-setup" = {
|
||||
requires = [ "postgresql.service" ];
|
||||
after = [ "postgresql.service" ];
|
||||
};
|
||||
users.users.nextcloud.uid = 996;
|
||||
users.groups.nextcloud.gid = 996;
|
||||
};
|
||||
}
|
88
modules/nixos/services/nginx/default.nix
Normal file
88
modules/nixos/services/nginx/default.nix
Normal file
|
@ -0,0 +1,88 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.nginx = {
|
||||
enable = lib.mkOption {
|
||||
readOnly = true;
|
||||
default = (builtins.length config.chvp.services.nginx.hosts) > 0;
|
||||
};
|
||||
hosts = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [
|
||||
{
|
||||
fqdn = "data.vanpetegem.me";
|
||||
options = {
|
||||
default = true;
|
||||
root = "/srv/data";
|
||||
locations = {
|
||||
"/".extraConfig = ''
|
||||
autoindex on;
|
||||
'';
|
||||
"/public".extraConfig = ''
|
||||
autoindex on;
|
||||
auth_basic off;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.nginx.enable {
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
security.acme = {
|
||||
certs."vanpetegem.me" = {
|
||||
dnsProvider = "cloudflare";
|
||||
credentialsFile = config.age.secrets."passwords/services/acme".path;
|
||||
extraDomainNames = [
|
||||
"*.vanpetegem.me"
|
||||
"cvpetegem.be"
|
||||
"*.cvpetegem.be"
|
||||
"chvp.be"
|
||||
"*.chvp.be"
|
||||
"vanpetegem.be"
|
||||
"*.vanpetegem.be"
|
||||
];
|
||||
};
|
||||
defaults.email = "webmaster@vanpetegem.me";
|
||||
acceptTerms = true;
|
||||
preliminarySelfsigned = false;
|
||||
};
|
||||
age.secrets."passwords/services/acme" = {
|
||||
file = ../../../../secrets/passwords/services/acme.age;
|
||||
owner = "acme";
|
||||
};
|
||||
chvp.base.zfs.systemLinks = [
|
||||
{ type = "data"; path = "/var/lib/acme"; }
|
||||
];
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedTlsSettings = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts = builtins.listToAttrs
|
||||
(map
|
||||
(elem: {
|
||||
name = elem.fqdn;
|
||||
value = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "vanpetegem.me";
|
||||
locations."/" = lib.mkIf (builtins.hasAttr "basicProxy" elem) {
|
||||
proxyPass = elem.basicProxy;
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
'' + (elem.extraProxySettings or "");
|
||||
};
|
||||
} // (elem.options or { });
|
||||
})
|
||||
config.chvp.services.nginx.hosts);
|
||||
};
|
||||
users.users = {
|
||||
nginx.extraGroups = [ "acme" ];
|
||||
acme.uid = 999;
|
||||
};
|
||||
users.groups.acme.gid = 999;
|
||||
};
|
||||
}
|
41
modules/nixos/services/torrents/default.nix
Normal file
41
modules/nixos/services/torrents/default.nix
Normal file
|
@ -0,0 +1,41 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.torrents = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.torrents.enable {
|
||||
chvp.services.nginx.hosts = [{ fqdn = "transmission.vanpetegem.me"; basicProxy = "http://localhost:9091"; }];
|
||||
|
||||
services.transmission = {
|
||||
enable = true;
|
||||
package = pkgs.transmission_4;
|
||||
user = "charlotte";
|
||||
group = "users";
|
||||
home = "/data/var/lib/transmission";
|
||||
openRPCPort = false;
|
||||
openPeerPorts = true;
|
||||
credentialsFile = config.age.secrets."files/programs/transmission/config.json".path;
|
||||
settings = {
|
||||
umask = 18;
|
||||
download-dir = "/srv/data";
|
||||
incomplete-dir = "/srv/data/.incomplete";
|
||||
rpc-authentication-required = true;
|
||||
rpc-bind-address = "0.0.0.0";
|
||||
rpc-enabled = true;
|
||||
rpc-host-whitelist-enabled = false;
|
||||
rpc-whitelist-enabled = false;
|
||||
speed-limit-down = 51200;
|
||||
speed-limit-down-enabled = true;
|
||||
};
|
||||
};
|
||||
age.secrets."files/programs/transmission/config.json" = {
|
||||
file = ../../../../secrets/files/programs/transmission/config.json.age;
|
||||
owner = "charlotte";
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue