about summary refs log tree commit diff
path: root/nix/hosts
diff options
context:
space:
mode:
Diffstat (limited to 'nix/hosts')
-rw-r--r--nix/hosts/caladan/aliases.nix1
-rw-r--r--nix/hosts/caladan/darwin-configuration.nix28
-rw-r--r--nix/hosts/caladan/emacs_config.el203
-rw-r--r--nix/hosts/caladan/home_emile.nix341
-rw-r--r--nix/hosts/caladan/nvim_plugins.nix21
-rw-r--r--nix/hosts/caladan/overlay.nix63
-rw-r--r--nix/hosts/chusuk/configuration.nix4
-rw-r--r--nix/hosts/corrino/configuration.nix230
-rw-r--r--nix/hosts/corrino/ports.nix14
-rw-r--r--nix/hosts/corrino/secrets/garage_admin_metrics_secret.age7
-rw-r--r--nix/hosts/corrino/secrets/garage_admin_token_secret.age7
-rw-r--r--nix/hosts/corrino/secrets/garage_env.agebin0 -> 602 bytes
-rw-r--r--nix/hosts/corrino/secrets/garage_rpc_secret.agebin387 -> 387 bytes
-rw-r--r--nix/hosts/corrino/secrets/goapp_oidc_client_secret.age7
-rw-r--r--nix/hosts/corrino/secrets/goapp_oidc_secret.agebin0 -> 395 bytes
-rw-r--r--nix/hosts/corrino/secrets/goapp_oidc_session_key.age8
-rw-r--r--nix/hosts/corrino/secrets/gotosocial_environment_file.agebin765 -> 765 bytes
-rw-r--r--nix/hosts/corrino/secrets/gotosocial_oidc_client_secret.age7
-rw-r--r--nix/hosts/corrino/secrets/grafana_env_vars.agebin431 -> 431 bytes
-rw-r--r--nix/hosts/corrino/secrets/grafana_oidc_client_secret.age7
-rw-r--r--nix/hosts/corrino/secrets/hedgedoc_environment_variables.agebin907 -> 911 bytes
-rw-r--r--nix/hosts/corrino/secrets/hedgedoc_oidc_client_secret.agebin0 -> 454 bytes
-rw-r--r--nix/hosts/corrino/secrets/immich_oidc_client_secret.agebin0 -> 454 bytes
-rw-r--r--nix/hosts/corrino/secrets/miniflux_admin_file.age7
-rw-r--r--nix/hosts/corrino/secrets/miniflux_oidc_client_secret.agebin0 -> 454 bytes
-rw-r--r--nix/hosts/corrino/secrets/miniflux_oidc_secret.age8
-rw-r--r--nix/hosts/corrino/secrets/tailscale-corrino-cert.agebin0 -> 3210 bytes
-rw-r--r--nix/hosts/corrino/secrets/tailscale-corrino-key.agebin0 -> 549 bytes
-rw-r--r--nix/hosts/corrino/vm.nix55
-rw-r--r--nix/hosts/corrino/www/cs.emile.space.nix23
-rw-r--r--nix/hosts/corrino/www/ctf.emile.space.nix21
-rw-r--r--nix/hosts/corrino/www/git/cgit.nix6
-rw-r--r--nix/hosts/corrino/www/git/git.nix106
-rw-r--r--nix/hosts/corrino/www/goapp.emile.space.nix93
-rw-r--r--nix/hosts/corrino/www/grafana.emile.space.nix245
-rw-r--r--nix/hosts/corrino/www/hydra.emile.space.nix9
-rw-r--r--nix/hosts/corrino/www/irc.emile.space.nix345
-rw-r--r--nix/hosts/corrino/www/loki.emile.space.nix64
-rw-r--r--nix/hosts/corrino/www/mc.emile.space.nix153
-rw-r--r--nix/hosts/corrino/www/md.emile.space.nix49
-rw-r--r--nix/hosts/corrino/www/miniflux.emile.space.nix81
-rw-r--r--nix/hosts/corrino/www/photo/immich.nix39
-rw-r--r--nix/hosts/corrino/www/prometheus.emile.space.nix36
-rw-r--r--nix/hosts/corrino/www/promtail.emile.space.nix114
-rw-r--r--nix/hosts/corrino/www/s3.emile.space.nix105
-rw-r--r--nix/hosts/corrino/www/social.emile.space.nix25
-rw-r--r--nix/hosts/corrino/www/sso.emile.space.nix35
-rw-r--r--nix/hosts/corrino/www/tickets.emile.space.nix2
-rw-r--r--nix/hosts/hacknix/burpsuitepro/default.nix4
-rw-r--r--nix/hosts/hacknix/configuration.nix15
-rw-r--r--nix/hosts/lampadas/configuration.nix76
-rw-r--r--nix/hosts/lernaeus/configuration.nix14
-rw-r--r--nix/hosts/mail/mail.nix31
53 files changed, 1579 insertions, 1130 deletions
diff --git a/nix/hosts/caladan/aliases.nix b/nix/hosts/caladan/aliases.nix
index d65bc14..6738589 100644
--- a/nix/hosts/caladan/aliases.nix
+++ b/nix/hosts/caladan/aliases.nix
@@ -4,6 +4,7 @@
 
   # short forms
   tf = "terraform";
+  m = "multipass";
 
   r2help = ''r2 -qq -c "?*~..." --'';
   mosh = "mosh --no-init";
diff --git a/nix/hosts/caladan/darwin-configuration.nix b/nix/hosts/caladan/darwin-configuration.nix
index ef18642..e581cb8 100644
--- a/nix/hosts/caladan/darwin-configuration.nix
+++ b/nix/hosts/caladan/darwin-configuration.nix
@@ -1,7 +1,9 @@
 { pkgs, lib, ... }:
 
 {
-  imports = [ ./overlay.nix ];
+  imports = [
+    ./overlay.nix
+  ];
 
   system.stateVersion = 5;
 
@@ -27,9 +29,17 @@
   # users.users."_nixbld3".uid = 307;
   # users.users."_nixbld4".uid = 308;
   # users.users."_nixbld5".uid = 309;
+  
+  # virtualisation.multipass = {
+  #   enable = true;
+  #   package = pkgs.multipass;
+  #   logLevel = "debug";
+  # };
+
+  ids.gids.nixbld = 30000;
 
   nix = {
-    useDaemon = true;
+    # useDaemon = true;
     # package = pkgs.nixFlakes;
     extraOptions =
       ''
@@ -85,10 +95,10 @@
       {
         hostName = "corrino.emile.space";
         system = "x86_64-linux";
-        maxJobs = 16;
+        maxJobs = 10;
         speedFactor = 2;
 
-        # Feature	      | Derivations requiring it
+        # Feature	        | Derivations requiring it
         # ----------------|-----------------------------------------------------
         # kvm	            | Everything which builds inside a vm, like NixOS tests
         # nixos-test	    | Machine can run NixOS tests
@@ -110,14 +120,16 @@
     ];
   };
 
-  nixpkgs = {
-    config.allowUnfree = true;
+  nixpkgs.config = {
+    allowUnfree = true;
+    allowUnsupportedSystem = true;
   };
 
-  services.nix-daemon.enable = true;
+  # services.nix-daemon.enable = true;
 
   # <3
-  security.pam.enableSudoTouchIdAuth = true;
+  # security.pam.enableSudoTouchIdAuth = true;
+  security.pam.services.sudo_local.touchIdAuth = true;
 
   environment = {
     systemPackages = [ ]; # set via home-manager
diff --git a/nix/hosts/caladan/emacs_config.el b/nix/hosts/caladan/emacs_config.el
new file mode 100644
index 0000000..01cf5bd
--- /dev/null
+++ b/nix/hosts/caladan/emacs_config.el
@@ -0,0 +1,203 @@
+;;; emacs-config --- My emacs config
+
+;;; Commentary:
+;;; This is my (currently often changing) Emacs config
+
+;;; Code:
+
+(require 'package)
+(package-initialize)
+(add-to-list 'package-archives
+             '("melpa" . "https://melpa.org/packages/") t)
+
+(unless package-archive-contents
+  (package-refresh-contents))
+
+(dolist (package '(use-package sly corfu org))
+  (unless (package-installed-p package)
+    (package-install package)))
+
+(scroll-bar-mode -1)
+(load-theme 'leuven) ;; light theme
+(setq pixel-scroll-precision-mode 1)
+(xterm-mouse-mode 1)
+
+(setq standard-indent 2)
+(setq create-lockfiles nil)
+(setq delete-old-versions -1)
+(setq make-backup-files nil) ; stop creating ~ files
+(setq version-control t)
+(setq coding-system-for-write 'utf-8)
+(setq-default indent-tabs-mode nil) ;; use spaces, not tabs
+(setq show-paren-delay 0)
+(show-paren-mode)
+
+(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
+
+(add-to-list 'display-buffer-alist
+             '("\\`\\*\\(Warnings\\|Compile-Log\\)\\*\\'"
+               (display-buffer-no-window)
+               (allow-no-window . t)))
+
+;; general purpose emacs settings
+(use-package emacs
+  :init
+
+  ;; do not allow cursor in the minibuffer prompt
+  (setq minibuffer-prompt-properties
+        '(read-only t cursor-intangible t face minibuffer-prompt))
+  (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
+
+  ;; support opening new minibuffers from inside existing minibuffers
+  (setq enable-recursive-minibuffers t)
+
+  ;; Emacs 28 and newer: Hide commands in M-x which do not work in the current
+  ;; mode. Vertico commands are hidden in normal buffers. This setting is
+  ;; useful beyond Vertico.
+  (setq read-extended-command-predicate #'command-completion-default-include-p))
+
+;; org-mode
+(use-package org)
+(define-key global-map "\C-cl" 'org-store-link)
+(define-key global-map "\C-ca" 'org-agenda)
+(setq org-log-done t)
+
+;; =============== plugins ==================
+
+;; Corfu - COmpletion in Region FUnction
+;; https://github.com/minad/corfu
+(declare-function global-corfu-mode "proced")
+(declare-function corfu-history-mode "proced")
+(declare-function corfu-mode "proced")
+(defvar corfu-map)
+(use-package corfu
+  :custom
+  (corfu-cycle-tab t)
+  (corfu-auto t)
+  (corfu-auto-prefix 2)
+  (corfu-auto-delay 0.0)
+  (corfu-quit-at-boundary 'separator)
+  (corfu-echo-documentation 0.5)
+  (corfu-preview-current 'insert)
+  (corfu-preselect 'prompt)
+  :bind (:map corfu-map
+              ("M-SPC" . corfu-insert-separator)
+              ("RET" . nil)
+              ("TAB" . corfu-next)
+              ([tab] . corfu-next)
+              ("S-TAB" . corfu-previous)
+              ([backtab] . corfu-previous)
+              ("S-<return>" . corfu-insert))
+  :init
+  (global-corfu-mode)
+  (corfu-history-mode)
+
+  :config
+  (add-hook 'eshell-mode-hook
+            (lambda ()
+              (setq-local corfu-quit-at-boundary t
+                          corfu-quit-no-match t
+                          corfu-auto nil)
+              (corfu-mode))))
+
+;; Marginalia - Marginalia in the minibuffer
+;; https://github.com/minad/marginalia
+(declare-function marginalia-mode "proced")
+(use-package marginalia
+  :custom
+  (marginalia-max-relative-age 0)
+  (marginalia-align 'right)
+  :init
+  (marginalia-mode))
+
+;; == Fancy icons ==
+;; all-the-icons
+;; https://github.com/domtronn/all-the-icons.el
+(use-package all-the-icons
+  :if (display-graphic-p))
+
+;; ... also in completions
+(declare-function all-the-icons-completion-mode "proced")
+(use-package all-the-icons-completion
+  :after (marginalia all-the-icons)
+  :hook (marginalia . all-the-icons-completion-marginalia-setup)
+  :init (all-the-icons-completion-mode))
+
+;; vectico.el - VERTical Interactive COmpletion
+;; https://github.com/minad/vertico
+(declare-function vertico-mode "proced")
+(use-package vertico
+  :init (vertico-mode)
+  :custom (vertico-count 13)
+  (vertico-resize t)
+  (vertico-cycle nil)
+  :config (vertico-mode))
+
+;; orderless - completion
+;; This allows searching for space separated terms in any order
+;; https://github.com/oantolin/orderless
+(use-package orderless
+  :init (setq completion-styles '(orderless basic)
+              completion-category-defaults nil
+              completion-category-overrides '((file (styles partial-completion)))))
+              
+
+;; markdown mode
+;; https://jblevins.org/projects/markdown-mode/
+(defvar markdown-command)
+(use-package markdown-mode
+  :ensure t
+  :mode ("README\\.md\\'" . gfm-mode)
+  :init (setq markdown-command "multimarkdown"))
+
+;; Minibuffer with help when waiting too long
+;; In emacs per default with Emacs v30
+(declare-function which-key-mode "proced")
+(defvar which-key-idle-delay)
+(defvar which-key-idle-secondary-delay)
+(use-package which-key
+  :ensure t
+  :config
+  (setq which-key-idle-delay 0.1)
+  (setq which-key-idle-secondary-delay 0.1)
+  (which-key-mode))
+
+;; flycheck - Syntax checking for GNU Emacs¶
+;; https://www.flycheck.org/en/latest/
+(declare-function global-flycheck-mode "proced")
+(use-package flycheck
+  :ensure t
+  :init (global-flycheck-mode))
+
+;; allow the deletion of selected text (don't know why this isn't implemented by default)
+(use-package delsel
+  :ensure nil ; no need to install it as it is built-in, but needs to be activated
+  :hook (after-init . delete-selection-mode))
+
+;; Configure the Lisp program for SLY
+(add-to-list 'exec-path "/Users/emile/.nix-profile/bin")
+(defvar inferior-lisp-program "sbcl")
+
+;; configure parinfer to be enabled as a mode when the major lisp mode is enabled
+(add-to-list 'load-path "/Users/emile/parinfer-rust")
+(add-hook 'emacs-lisp-mode 'parinfer-rust-mode)
+(declare-function lispy-mode "proced")
+(add-hook 'emacs-lisp-mods (lambda () (lispy-mode 1)))
+
+;; pixel perfect ultra precise low latency scrolling
+(declare-function ultra-scroll-mode "proced")
+(use-package ultra-scroll
+     ; if you git clone'd instead of package-vc-install
+     ;:load-path "~/code/emacs/ultra-scroll"
+
+     :init
+     (setq scroll-conservatively 101 ; important!
+         scroll-margin 0)
+     :config
+     (ultra-scroll-mode 1))
+
+(use-package breadcrumb
+     :ensure t)
+
+(provide '.emacs)
+;;; emacs_config.el ends here
diff --git a/nix/hosts/caladan/home_emile.nix b/nix/hosts/caladan/home_emile.nix
index 2a52db9..704b73b 100644
--- a/nix/hosts/caladan/home_emile.nix
+++ b/nix/hosts/caladan/home_emile.nix
@@ -1,4 +1,4 @@
-{ pkgs, ... }:
+{ pkgs, lib, ... }:
 
 {
   home = {
@@ -50,7 +50,7 @@
         fi
       '';
 
-      initExtraBeforeCompInit = ''
+      initContent = lib.mkOrder 550 ''
         ${builtins.readFile ./session_variables.zsh}
         ${builtins.readFile ./functions.zsh}
 
@@ -60,6 +60,18 @@
       '';
     };
 
+    neovim = let
+      custom_plugins = pkgs.callPackage ./nvim_plugins.nix { };
+    in {
+      enable = true;
+      plugins = with pkgs.vimPlugins // custom_plugins; [
+        neovim-ayu
+        lisp.vlime
+      ];
+      extraConfig = ''
+      '';
+    };
+
     emacs = {
       enable = true;
       package = pkgs.emacs;
@@ -69,308 +81,15 @@
           magit # Git
           parinfer-rust-mode # Lisp Parens
           tuareg # OCaml
-          howm # Notes
         ];
-      extraConfig = ''
-        (require 'package)
-        (package-initialize)
-        (add-to-list 'package-archives
-          '("melpa" . "https://melpa.org/packages/") t)
-        (unless package-archive-contents
-          (package-refresh-contents))
-
-        (dolist (package '(use-package sly corfu org))
-          (unless (package-installed-p package)
-            (package-install package)))
-
-        (when (display-graphic-p)
-          (tool-bar-mode 0)
-          (scroll-bar-mode 'left))
-
-        (load-theme 'leuven) ;; light theme
-        (setq pixel-scroll-precision-mode 1)
-
-        (setq standard-indent 2)
-        (setq create-lockfiles nil)
-        (setq delete-old-versions -1)
-        (setq make-backup-files nil) ; stop creating ~ files
-        (setq version-control t)
-        (setq coding-system-for-write 'utf-8)
-        (setq-default indent-tabs-mode nil) ;; use spaces, not tabs
-        (setq show-paren-delay 0)
-        (show-paren-mode)
-
-        (setq custom-file (expand-file-name "custom.el" user-emacs-directory))
-
-        (add-to-list 'display-buffer-alist
-                     '("\\`\\*\\(Warnings\\|Compile-Log\\)\\*\\'"
-                       (display-buffer-no-window)
-                       (allow-no-window . t)))
-
-        ;; general purpose emacs settings
-        (use-package emacs
-          :init
-
-          ;; do not allow cursor in the minibuffer prompt
-          (setq minibuffer-prompt-properties
-                '(read-only t cursor-intangible t face minibuffer-prompt))
-          (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
-
-          ;; support opening new minibuffers from inside existing minibuffers
-          (setq enable-recursive-minibuffers t)
-
-          ;; Emacs 28 and newer: Hide commands in M-x which do not work in the current
-          ;; mode. Vertico commands are hidden in normal buffers. This setting is
-          ;; useful beyond Vertico.
-          (setq read-extended-command-predicate #'command-completion-default-include-p))
-
-        ;; Add "lisp" to the list of languages babel is allowed to eval
-        ;(setq-default org-babel-lisp-eval-fn #'sly-eval)
-        (org-babel-do-load-languages
-         'org-babel-load-languages
-         '((lisp . t)))
-
-        ;; org-mode
-        (use-package org)
-        (define-key global-map "\C-cl" 'org-store-link)
-        (define-key global-map "\C-ca" 'org-agenda)
-        (setq org-log-done t)
-
-        ;; =============== plugins ==================
-
-        ;; Corfu - COmpletion in Region FUnction
-        ;; https://github.com/minad/corfu
-        (use-package corfu
-          :custom
-          (corfu-cycle-tab t)
-          (corfu-auto t)
-          (corfu-auto-prefix 2)
-          (corfu-auto-delay 0.0)
-          (corfu-quit-at-boundary 'separator)
-          (corfu-echo-documentation 0.5)
-          (corfu-preview-current 'insert)
-          (corfu-preselect 'prompt)
-          :bind (:map corfu-map
-                      ("M-SPC" . corfu-insert-separator)
-                      ("RET" . nil)
-                      ("TAB" . corfu-next)
-                      ([tab] . corfu-next)
-                      ("S-TAB" . corfu-previous)
-                      ([backtab] . corfu-previous)
-                      ("S-<return>" . corfu-insert))
-          :init
-          (global-corfu-mode)
-          (corfu-history-mode)
-
-          :config
-          (add-hook 'eshell-mode-hook
-                    (lambda ()
-                      (setq-local corfu-quit-at-boundary t
-                                  corfu-quit-no-match t
-                                  corfu-auto nil)
-                      (corfu-mode))))
-
-        ;; Marginalia - Marginalia in the minibuffer
-        ;; https://github.com/minad/marginalia
-        (use-package marginalia
-          :custom
-          (marginalia-max-relative-age 0)
-          (marginalia-align 'right)
-          :init
-          (marginalia-mode))
-
-        ;; == Fancy icons ==
-        ;; all-the-icons
-        ;; https://github.com/domtronn/all-the-icons.el
-        (use-package all-the-icons
-          :if (display-graphic-p))
-
-        ;; ... also in completions 
-        (use-package all-the-icons-completion
-          :after (marginalia all-the-icons)
-          :hook (marginalia . all-the-icons-completion-marginalia-setup)
-          :init (all-the-icons-completion-mode))
-
-        ;; vectico.el - VERTical Interactive COmpletion
-        ;; https://github.com/minad/vertico
-        (use-package vertico
-          :init (vertico-mode)
-          :custom (vertico-count 13)
-          (vertico-resize t)
-          (vertico-cycle nil)
-          :config (vertico-mode))
-
-        ;; orderless - completion
-        ;; This allows searching for space separated terms in any order
-        ;; https://github.com/oantolin/orderless
-        (use-package orderless
-          :init (setq completion-styles '(orderless basic)
-                      completion-category-defaults nil
-                      completion-category-overrides '((file (styles partial-completion)))
-                      ))
-
-
-        ;; markdown mode
-        ;; https://jblevins.org/projects/markdown-mode/
-        (use-package markdown-mode
-          :ensure t
-          :mode ("README\\.md\\'" . gfm-mode)
-          :init (setq markdown-command "multimarkdown"))
-
-        ;; Minibuffer with help when waiting too long
-        ;; In emacs per default with Emacs v30
-        (use-package which-key
-          :ensure t
-          :config
-          (setq which-key-idle-delay 0.1)
-          (setq which-key-idle-secondary-delay 0.1)
-          (which-key-mode))
-
-        ;; imenu-list - Display imenu (symbols) in a separate buffer
-        ;; https://github.com/bmag/imenu-list
-        (use-package imenu-list :ensure t
-          :init
-          (setq imenu-list-auto-resize t)
-          (setq imenu-list-focus-after-activation t))
-
-        ;; flycheck - Syntax checking for GNU Emacs¶
-        ;; https://www.flycheck.org/en/latest/
-        (use-package flycheck
-          :ensure t
-          :init (global-flycheck-mode))
-
-        ;; allow the deletion of selected text (don't know why this isn't implemented by default)
-        (use-package delsel
-          :ensure nil ; no need to install it as it is built-in, but needs to be activated
-          :hook (after-init . delete-selection-mode))
-
-        ; howm mode
-        ; (require 'howm)
-        (use-package howm
-          :ensure t
-          :init
-          ;; Where to store the files?
-          (setq howm-file-name-format "%Y/%m/%Y-%m-%d-%H%M%S.md")
-          (setq howm-view-title-header "#") ; markdown mode!
-          (setq howm-directory "~/Notes")
-          (setq howm-home-directory howm-directory)
-          (setq howm-keyword-file (expand-file-name ".howm-keys" howm-home-directory))
-          (setq howm-history-file (expand-file-name ".howm-history" howm-home-directory))
-
-          ;; Use ripgrep as grep
-          (setq howm-view-use-grep t)
-          (setq howm-view-grep-command "rg")
-          (setq howm-view-grep-option "-nH --no-heading --color never")
-          (setq howm-view-grep-extended-option nil)
-          (setq howm-view-grep-fixed-option "-F")
-          (setq howm-view-grep-expr-option nil)
-          (setq howm-view-grep-file-stdin-option nil))
-
-
-        ;; Rename buffers to their title
-        (add-hook 'howm-mode-hook 'howm-mode-set-buffer-name)
-        (add-hook 'after-save-hook 'howm-mode-set-buffer-name)
-
-        ; OCaml mode
-        (use-package tuareg)
-        (setq tuareg-indent-align-with-first-arg t)
-
-        (defun insert-date ()
-          "Insert today's date at point"
-          (interactive "*")
-          (insert (format-time-string "%F")))
-        (global-set-key (kbd "C-c C-.") #'insert-date)
-
-
-        ;; Configure the Lisp program for SLIME
-        (add-to-list 'exec-path "/Users/emile/.nix-profile/bin")
-        (defvar inferior-lisp-program "sbcl")
-
-        ;; configure parinfer to be enabled as a mode when the major lisp mode is enabled
-        (add-to-list 'load-path "/Users/emile/parinfer-rust")
-        (add-hook 'emacs-lisp-mode 'parinfer-rust-mode)
-        (add-hook 'emacs-lisp-mods (lambda () (lispy-mode 1)))
-
-        ;; erc (emacs irc) settings
-        (use-package erc
-            :config
-            (setopt erc-modules
-                (seq-union '(sals nicks bufbar nickbar scrolltobottom)
-                           etc-modules))
-            (setopt erc-sasl-mechanism 'external)
-
-
-            :custom
-            (erc-prompt-for-nickserv-password nil)
-            (erc-inhibit-multiline-input t)
-            (erc-send-whitespace-lines t)
-            (erc-ask-about-multiline-input t)
-            (erc-server-reconnect-timeout 30)
-            (erc-interactive-display 'buffer)
-
-            (erc-autojoin-timing 'ident)
-            (erc-autojoin-channels-alist '((Libera.Chat "#r2wars")))
-
-            :bind
-            ;; Insert \n when hitting <RET> and send messages using C-c C-c
-            (:map erc-mode-map
-                  ("RET" . nil)
-                  ("C-c C-c" . #'erc-send-current-line)))
-
-        (use-package ultra-scroll
-             ; if you git clone'd instead of package-vc-install
-             ;:load-path "~/code/emacs/ultra-scroll"
-
-             :init
-             (setq scroll-conservatively 101 ; important!
-                 scroll-margin 0) 
-             :config
-                 (ultra-scroll-mode 1))
-        
-        (global-set-key (kbd "C-c e l") (lambda ()
-            (interactive)
-            (if (get-buffer "irc.libera.chat")
-                (erc-track-switch-buffer 1)
-                (when (y-or-n-p "Start ERC? ")
-                  (erc-tls :server "irc.libera.chat"
-                           :port 6697
-                           :nick "hanemile"
-                           :client-certificate
-                             '(,(expand-file-name "~/libera.key")
-                               ,(expand-file-name "~/libera.crt")))))))
-
-        (use-package org-roam
-          :ensure t
-          :custom
-          (org-roam-directory (file-truename "/Users/emile/notes"))
-          :bind (("C-c n l" . org-roam-buffer-toggle)
-                 ("C-c n f" . org-roam-node-find)
-                 ("C-c n g" . org-roam-graph)
-                 ("C-c n i" . org-roam-node-insert)
-                 ("C-c n c" . org-roam-capture)
-                 ;; Dailies
-                 ("C-c n j" . org-roam-dailies-capture-today))
-          :config
-
-          ;; If you're using a vertical completion framework, you might want a more informative completion interface
-          (setq org-roam-node-display-template
-            (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
-          (org-roam-db-autosync-mode)
-
-          ;; If using org-roam-protocol
-          (require 'org-roam-protocol))
-
-        (provide '.emacs)                       ; makes flycheck happy
-      '';
+      extraConfig = builtins.readFile ./emacs_config.el;
     };
 
     kitty = {
       enable = true;
 
-      # package = pkgs.kitty;
-
       font = {
-        name = "Iosevka Nerd Font";
+        name = "Berkeley Mono";
         size = 13;
       };
 
@@ -383,9 +102,6 @@
         tab_bar_edge = "top";
         tab_bar_style = "slant";
         tab_bar_min_tabs = 1;
-
-        # tab_title_template = "{index}[{layout_name[0:2]}]: {title.replace('emile', 'e')[title.rfind('/')+1:]}";
-        # tab_title_template = "{index}[{layout_name[0:2]}]: {title.replace('emile', 'e')}";
         tab_title_template = "{index} {title.replace('emile', 'e')}";
 
         editor = "/Users/emile/.cargo/bin/hx";
@@ -473,9 +189,9 @@
     ## language server
     # nodePackages_latest.typescript-language-server # js / typescript
     nil # nix 
-    nodePackages.yaml-language-server # yaml
+    # nodePackages.yaml-language-server # yaml
     python312Packages.python-lsp-server # python
-    gopls # golang
+    # gopls # golang
 
     # binary foo
     radare2
@@ -490,7 +206,8 @@
 
     # go foo
     go
-    delve
+    # delve
+    # gotools
 
     # c foo
     cmake
@@ -538,7 +255,23 @@
 
     taskwarrior3
 
-    drawio
+    # drawio
+
+    # cargo rustup
+    cargo
+
+    utm
+
+    #nmap ffuf
+    #typst
+    #age
+    #ffmpeg
+    #exiftool
+
+    # custom
+    # libc-database
+
+    # unstable.duckdb
 
     # blender
 
diff --git a/nix/hosts/caladan/nvim_plugins.nix b/nix/hosts/caladan/nvim_plugins.nix
new file mode 100644
index 0000000..7f07816
--- /dev/null
+++ b/nix/hosts/caladan/nvim_plugins.nix
@@ -0,0 +1,21 @@
+{ vimUtils, fetchgit, ... }:
+
+let
+  build = ({name, owner, rev, sha256}: vimUtils.buildVimPlugin {
+    inherit name;
+    src = fetchgit {
+      inherit rev sha256;
+      url = "https://github.com/${owner}/${name}";
+    };
+    dependencies = [];
+  });
+in {
+  lisp = {
+    vlime = build {
+      name = "vlime";
+      owner = "l04m33";
+      rev = "065b95f3ac7a455314c2bdefeb2b792f290034df";
+      sha256 = "1bmmskdwvbl6lvbnjp9lls86rz0vzmk73y644bjb9ix9ygmjbia4";
+    };
+  };
+}
diff --git a/nix/hosts/caladan/overlay.nix b/nix/hosts/caladan/overlay.nix
index c9bdd79..8295339 100644
--- a/nix/hosts/caladan/overlay.nix
+++ b/nix/hosts/caladan/overlay.nix
@@ -3,42 +3,37 @@
 {
   nixpkgs = {
     overlays = [
-      (self: super: {
-        kitty = super.kitty.overrideAttrs (old: {
-          preCheck = ''
-            # skip failing tests due to darwin sandbox
-            substituteInPlace kitty_tests/file_transmission.py \
-              --replace test_file_get dont_test_file_get \
-              --replace test_path_mapping_receive dont_test_path_mapping_receive \
-              --replace test_transfer_send dont_test_transfer_send
-            substituteInPlace kitty_tests/shell_integration.py \
-              --replace test_fish_integration dont_test_fish_integration
-            substituteInPlace kitty_tests/shell_integration.py \
-              --replace test_bash_integration dont_test_bash_integration
-            substituteInPlace kitty_tests/open_actions.py \
-              --replace test_parsing_of_open_actions dont_test_parsing_of_open_actions
-            substituteInPlace kitty_tests/ssh.py \
-              --replace test_ssh_connection_data dont_test_ssh_connection_data
-            substituteInPlace kitty_tests/fonts.py \
-              --replace 'class Rendering(BaseTest)' 'class Rendering'
+      #(self: super: {
+      #  kitty = super.kitty.overrideAttrs (old: {
+      #    preCheck = ''
+      #      # skip failing tests due to darwin sandbox
+      #      substituteInPlace kitty_tests/file_transmission.py \
+      #        --replace test_file_get dont_test_file_get \
+      #        --replace test_path_mapping_receive dont_test_path_mapping_receive \
+      #        --replace test_transfer_send dont_test_transfer_send
+      #      substituteInPlace kitty_tests/shell_integration.py \
+      #        --replace test_fish_integration dont_test_fish_integration
+      #      substituteInPlace kitty_tests/shell_integration.py \
+      #        --replace test_bash_integration dont_test_bash_integration
+      #      substituteInPlace kitty_tests/open_actions.py \
+      #        --replace test_parsing_of_open_actions dont_test_parsing_of_open_actions
+      #      substituteInPlace kitty_tests/ssh.py \
+      #        --replace test_ssh_connection_data dont_test_ssh_connection_data
+      #      substituteInPlace kitty_tests/fonts.py \
+      #        --replace 'class Rendering(BaseTest)' 'class Rendering'
 
-            # TODO(emile): figure out why this test is failing and activate it
-            # again.
-            substituteInPlace kittens/hyperlinked_grep/main_test.go \
-              --replace TestRgArgParsing DontTestRgArgParsing \
+      #      # TODO(emile): figure out why this test is failing and activate it
+      #      # again.
+      #      substituteInPlace kittens/hyperlinked_grep/main_test.go \
+      #        --replace TestRgArgParsing DontTestRgArgParsing \
 
-            # theme collection test starts an http server
-            rm tools/themes/collection_test.go
-            # passwd_test tries to exec /usr/bin/dscl
-            rm tools/utils/passwd_test.go
-          '';
-        });
-
-        # helix-2303 = self.callPackage ../../pkgs/helix-2303 { };
-        # r2 = self.callPackage ../../pkgs/radare2-5.8.4 { };
-        # ansel = self.callPackage ../../pkgs/ansel { };
-        # typst = self.callPackage ../pkgs/radare2-5.8.4 { };
-      })
+      #      # theme collection test starts an http server
+      #      rm tools/themes/collection_test.go
+      #      # passwd_test tries to exec /usr/bin/dscl
+      #      rm tools/utils/passwd_test.go
+      #    '';
+      #  });
+      #})
     ];
     config = {
       allowUnfree = true;
diff --git a/nix/hosts/chusuk/configuration.nix b/nix/hosts/chusuk/configuration.nix
index 5ec116f..364a1c6 100644
--- a/nix/hosts/chusuk/configuration.nix
+++ b/nix/hosts/chusuk/configuration.nix
@@ -116,15 +116,13 @@
   services = {
     openssh.enable = true;
     tailscale.enable = true;
+    displayManager.defaultSession = "none+i3";
     xserver = {
       enable = true;
       desktopManager = {
         xterm.enable = false;
       };
 
-      displayManager = {
-        defaultSession = "none+i3";
-      };
 
       windowManager.i3 = {
         enable = true;
diff --git a/nix/hosts/corrino/configuration.nix b/nix/hosts/corrino/configuration.nix
index eed5076..7683630 100644
--- a/nix/hosts/corrino/configuration.nix
+++ b/nix/hosts/corrino/configuration.nix
@@ -22,46 +22,53 @@ in
     ./hardware-configuration.nix
 
     ./ports.nix
+    # ./vm.nix
 
     ./www/git
-    ./www/nix-cache
+    #./www/nix-cache
+
+    # doesn't find the goapp-frontend package, some issue with the overlay being applied, at least
+    # thats what I think the problem is
+    # ./www/goapp.emile.space.nix
 
     # screego
 
     # web
     ./www/emile.space.nix
     ./www/tmp.emile.space.nix
-    # ./www/hydra.emile.space.nix
-    ./www/netbox.emile.space.nix
+    ./www/hydra.emile.space.nix
+    # ./www/netbox.emile.space.nix
     ./www/stats.emile.space.nix
-    # ./www/grafana.emile.space.nix
+    ./www/grafana.emile.space.nix
     # ./www/prometheus.emile.space.nix
-    # ./www/loki.emile.space.nix
-    # ./www/promtail.emile.space.nix
 
     ./www/photo
 
-    # ./www/tickets.emile.space.nix
-    ./www/talks.emile.space.nix
+    ./www/tickets.emile.space.nix
+    # ./www/talks.emile.space.nix
+    ./www/miniflux.emile.space.nix
     # ./www/stream.emile.space.nix
     ./www/md.emile.space.nix
     ./www/social.emile.space.nix
     ./www/sso.emile.space.nix
-    ./www/s3.emile.space.nix
-    ./www/cs.emile.space.nix
-    ./www/irc.emile.space.nix
+    # ./www/s3.emile.space.nix
+    # ./www/cs.emile.space.nix
+    # ./www/irc.emile.space.nix
+    # ./www/cl.emile.space.nix
     # ./www/db.emile.space.nix
 
-    # ./www/ctf.emile.space.nix
+    #./www/ctf.emile.space.nix
     # ./www/magic-hash.emile.space.nix
 
+    # ./www/mc.emile.space.nix
+
     # gemini
-    ./gemini/emile.space.nix
+    # ./gemini/emile.space.nix
 
     # general purpose modules
 
     # r2wars
-    ./www/r2wa.rs.nix
+    # ./www/r2wa.rs.nix
 
     # milliways
     # ./remarvin.nix
@@ -156,9 +163,7 @@ in
       '';
     };
 
-    supportedFilesystems = {
-      "cifs" = true;
-    };
+    supportedFilesystems = [ "cifs" ];
   };
 
   time.timeZone = "Europe/Berlin";
@@ -217,40 +222,40 @@ in
   };
 
   # create a oneshot job to authenticate to Tailscale
-  systemd.services.tailscale-autoconnect = {
-    description = "Automatic connection to Tailscale";
-
-    # make sure tailscale is running before trying to connect to tailscale
-    after = [
-      "network-pre.target"
-      "tailscale.service"
-    ];
-    wants = [
-      "network-pre.target"
-      "tailscale.service"
-    ];
-    wantedBy = [ "multi-user.target" ];
-
-    # set this service as a oneshot job
-    serviceConfig.Type = "oneshot";
-
-    # have the job run this shell script
-    script = with pkgs; ''
-      # wait for tailscaled to settle
-      sleep 2
-
-      # check if we are already authenticated to tailscale
-      status="$(${tailscale}/bin/tailscale status -json | ${jq}/bin/jq -r .BackendState)"
-      if [ $status = "Running" ]; then # if so, then do nothing
-        exit 0
-      fi
-
-      # otherwise authenticate with tailscale
-      ${tailscale}/bin/tailscale up \
-        --advertise-exit-node --exit-node
-    '';
-    # -authkey ${config.age.secrets.tailscale_authkey}
-  };
+  # systemd.services.tailscale-autoconnect = {
+  #   description = "Automatic connection to Tailscale";
+
+  #   # make sure tailscale is running before trying to connect to tailscale
+  #   after = [
+  #     "network-pre.target"
+  #     "tailscale.service"
+  #   ];
+  #   wants = [
+  #     "network-pre.target"
+  #     "tailscale.service"
+  #   ];
+  #   wantedBy = [ "multi-user.target" ];
+
+  #   # set this service as a oneshot job
+  #   serviceConfig.Type = "oneshot";
+
+  #   # have the job run this shell script
+  #   script = with pkgs; ''
+  #     # wait for tailscaled to settle
+  #     sleep 2
+
+  #     # check if we are already authenticated to tailscale
+  #     status="$(${tailscale}/bin/tailscale status -json | ${jq}/bin/jq -r .BackendState)"
+  #     if [ $status = "Running" ]; then # if so, then do nothing
+  #       exit 0
+  #     fi
+
+  #     # otherwise authenticate with tailscale
+  #     ${tailscale}/bin/tailscale up \
+  #       --advertise-exit-node --exit-node
+  #   '';
+  #   # -authkey ${config.age.secrets.tailscale_authkey}
+  # };
 
   networking = {
     hostName = "corrino";
@@ -311,6 +316,7 @@ in
         80
         443 # normal web
         config.emile.ports.gitDaemon
+        8085
       ];
       allowedUDPPorts = [
         # 51820 # wireguard
@@ -402,6 +408,9 @@ in
         "docker"
         "libvirtd"
       ];
+      packages = with pkgs; [
+        docker
+      ];
     };
 
     tmpuser1 = {
@@ -437,6 +446,27 @@ in
       # use corrino as a subnet router and an exit node
       useRoutingFeatures = "both";
     };
+
+    restic.backups."corrino" = {
+      repository = "/mnt/storagebox-bx11/corrino";
+      passwordFile = config.age.secrets.restic_password.path;
+      initialize = true;
+      pruneOpts = [
+        "--keep-daily 7"
+        "--keep-weekly 5"
+        "--keep-monthly 12"
+        "--keep-yearly 75"
+      ];
+    };
+    # restic.server = {
+    #   enable = true;
+    #   prometheus = true;
+    #   package = pkgs.restic-rest-server;
+    #   extraFlags = [ "--no-auth" ];
+    #   listenAddress = "127.0.0.1:${toString config.emile.ports.restic}";
+    #   dataDir = "/var/lib/restic";
+    #   appendOnly = true;
+    # };
   };
 
   nix = {
@@ -466,36 +496,38 @@ in
       allowed-uris = https://github.com/ https://git.emile.space/ git+https://github.com/
     '';
 
-    buildMachines = [
-      {
-        hostName = "localhost";
-        system = "x86_64-linux";
-        protocol = "ssh-ng";
-        maxJobs = 8;
-        supportedFeatures = [
-          "nixos-test"
-          "benchmark"
-          "big-parallel"
-          "kvm"
-        ];
-      }
-      # {
-      #   hostName = "caladan.pinto-pike.ts.net";
-      #   system = "aarch64-darwin";
-      #   protocol = "ssh-ng";
-      #   maxJobs = 1;
-      #   speedFactor = 2;
-      #   supportedFeatures = [
-      #     "nixos-test"
-      #     "benchmark"
-      #     "big-parallel"
-      #     "kvm"
-      #   ];
-      #   mandatoryFeatures = [ ];
-      # }
-    ];
+    # buildMachines = [
+    #   {
+    #     hostName = "localhost";
+    #     system = "x86_64-linux";
+    #     protocol = "ssh-ng";
+    #     maxJobs = 8;
+    #     supportedFeatures = [
+    #       "nixos-test"
+    #       "benchmark"
+    #       "big-parallel"
+    #       "kvm"
+    #     ];
+    #   }
+    #   {
+    #     hostName = "caladan.pinto-pike.ts.net";
+    #     sshUser = "hydra";
+    #     sshKey = "/var/lib/hydra/.ssh/id_ed25519";
+    #     system = "aarch64-darwin";
+    #     protocol = "ssh-ng";
+    #     maxJobs = 1;
+    #     speedFactor = 2;
+    #     supportedFeatures = [
+    #       "nixos-test"
+    #       "benchmark"
+    #       "big-parallel"
+    #       "kvm"
+    #     ];
+    #     mandatoryFeatures = [ ];
+    #   }
+    # ];
 
-    distributedBuilds = true;
+    # distributedBuilds = true;
   };
 
   nixpkgs.config = {
@@ -513,7 +545,7 @@ in
   };
 
   virtualisation = {
-    # docker.enable = true;
+    docker.enable = true;
     libvirtd = {
       enable = true;
       qemu = {
@@ -521,12 +553,14 @@ in
         runAsRoot = true;
         swtpm.enable = true;
         ovmf = {
-          enable = true;
-          packages = [
-            (pkgs.unstable.OVMF.override {
+        enable = true;
+        packages = [
+          (
+            pkgs.OVMF.override {
               secureBoot = true;
               tpmSupport = true;
-            }).fd
+            }
+          ).fd
           ];
         };
       };
@@ -551,13 +585,25 @@ in
     };
 
     "/mnt/storagebox-bx11" = {
-      device = "//u331921.your-storagebox.de/backup";
-      fsType = "cifs";
-      options =
-        let
-          automount_opts = "_netdev,x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
-        in
-        [ "${automount_opts},credentials=${config.age.secrets.storage_box_bx11_password.path}" ];
+      device = "u331921@u331921.your-storagebox.de:/home/backup";
+      fsType = "sshfs";
+      options = [ # Filesystem options
+        "allow_other"          # for non-root access
+        "_netdev"              # this is a network fs
+
+        # We don't mount on demand, as that will cause services like navidrome to fail
+        # as the share doesn't yet exist.
+        #"x-systemd.automount" # mount on demand, rather than boot
+
+        #"debug"               # print debug logging
+                               # warning: this causes the one-shot service to never exit
+
+        # SSH options
+        "StrictHostKeyChecking=no"  # prevent the connection from failing if the host's key hasn't been trusted yet
+        "ServerAliveInterval=15" # keep connections alive
+        "Port=23"
+        "IdentityFile=/root/.ssh/id_ed25519"
+      ];
     };
   };
 
diff --git a/nix/hosts/corrino/ports.nix b/nix/hosts/corrino/ports.nix
index 10ae593..483ab7f 100644
--- a/nix/hosts/corrino/ports.nix
+++ b/nix/hosts/corrino/ports.nix
@@ -5,16 +5,24 @@
     photo = {
       photoprism = 2342;
       immich = 2343;
+      immich-public-proxy = 2344;
     };
     git = 3000;
     hydra = 3001;
     grafana = 3002;
     md = 3003;
     gotosocial = 3004;
-    immich = 3005;
     monica = 3006;
+    miniflux = 3007;
     harmonia = 5000;
+    garage = {
+      s3 = 6001;
+      web = 6002;
+      rpc = 6003;
+      admin = 6004;
+    };
     irc = {
+      bouncer = 6666;
       clear = 6667;
       ssl = 6697;
     };
@@ -24,6 +32,7 @@
     restic = 8002;
     nocodb = 8003;
     goatcounter = 8004;
+    goapp = 8005;
     r2wars-web = 8089;
     ctf = 8338;
     magic-hash = 8339;
@@ -33,8 +42,6 @@
       s3 = 9000;
       web = 9001;
     };
-    promtail = 9033;
-    loki = 9034;
     authelia = 9091;
     gitDaemon = 9418;
     prometheus = {
@@ -44,6 +51,7 @@
         nginx = 9913;
         systemd = 9558;
         smartctl = 9633;
+        restic = 9634;
       };
     };
   };
diff --git a/nix/hosts/corrino/secrets/garage_admin_metrics_secret.age b/nix/hosts/corrino/secrets/garage_admin_metrics_secret.age
new file mode 100644
index 0000000..e1af7da
--- /dev/null
+++ b/nix/hosts/corrino/secrets/garage_admin_metrics_secret.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q 7QkcpYGeeMsbW0GcXzNGPTc0jUf4ydpMiTO6ZxEIKGY
+OOxq2hMORsmUzBuoqOIPNJeLqJB0seve9PhorS6PKNs
+-> ssh-ed25519 m8VklA pF7mWG6tviFC6qD88dxoQRnXGfR0AuanVyY+bh8XgV0
+mrk4HgEs3i8y5P+BSGM1psweXpY/xO+8vK/DsXyhyiY
+--- zqEl/ZN/3jEgMZ/IbPbyTHGZJDDENLOnoQezaACeoSs
+l,±W`\6yh.
oV(?Em,;(@0dVA=4v
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/garage_admin_token_secret.age b/nix/hosts/corrino/secrets/garage_admin_token_secret.age
new file mode 100644
index 0000000..2a18a6b
--- /dev/null
+++ b/nix/hosts/corrino/secrets/garage_admin_token_secret.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q hcMMVkZSsObrOFjetml2z4eH+EfnuSsna+GaXEeMUA4
+y6lFBj49cMhOGuJBpILHsykpBMpKDHZpFXR4E4zZEbg
+-> ssh-ed25519 m8VklA Z6zLilTWlGWG17Q6jBx13m3KYs3gE93TPLq0CidHeTA
+eqMN5mDMasi/Nw2y5Kgwy2COna+3zbbFTTUrD/O26ls
+--- QdVyqrTLmEcGSB37Ft3Ur0Ry9Jk9DyHFI6fo88tnsgI
+X`wY,<A$XeDGe	;െ>1nsNr_Y\`)F#{<
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/garage_env.age b/nix/hosts/corrino/secrets/garage_env.age
new file mode 100644
index 0000000..becb511
--- /dev/null
+++ b/nix/hosts/corrino/secrets/garage_env.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/garage_rpc_secret.age b/nix/hosts/corrino/secrets/garage_rpc_secret.age
index e228d0d..ce8a65a 100644
--- a/nix/hosts/corrino/secrets/garage_rpc_secret.age
+++ b/nix/hosts/corrino/secrets/garage_rpc_secret.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/goapp_oidc_client_secret.age b/nix/hosts/corrino/secrets/goapp_oidc_client_secret.age
new file mode 100644
index 0000000..1477d56
--- /dev/null
+++ b/nix/hosts/corrino/secrets/goapp_oidc_client_secret.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q wi3/W2UnB/8kCTeJ8shGpBQ21uvSQlbtZBAbocbQ+zY
+6RQGQss6B6uvq4yFXGVQtbHgDKGzMVO2xDgUDlBV5Es
+-> ssh-ed25519 m8VklA oFBut6nQ5Er9YQWpCb+2j3JKsNIjBRjwuQ7ERVekVyM
+ccR/5J5g1D11iNieF/BXtzxcusF1Zaq04iifOFk6Q/U
+--- r2E/KdtXa9/j5ecWhjzLsztBG8W+if2MeOPya6KJDxY
+C7p}Vj4|EW].k~Xe:(r2:$}~w0ƻP`+Xg@PFX/i%;!$	"Ii_#*|Od;ZtwDFldF6дJa4q2y
8T
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/goapp_oidc_secret.age b/nix/hosts/corrino/secrets/goapp_oidc_secret.age
new file mode 100644
index 0000000..4ca657b
--- /dev/null
+++ b/nix/hosts/corrino/secrets/goapp_oidc_secret.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/goapp_oidc_session_key.age b/nix/hosts/corrino/secrets/goapp_oidc_session_key.age
new file mode 100644
index 0000000..938f97f
--- /dev/null
+++ b/nix/hosts/corrino/secrets/goapp_oidc_session_key.age
@@ -0,0 +1,8 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q BAvDdIEUEgmo963+9Wd5VLJgrp3MBISvWR3+27bfJW8
+NOEj2ObYe/cM2CaqzmbgexSEUNZIEo1ZmvlamJaSOjo
+-> ssh-ed25519 m8VklA d/hwd3rGkPD3GDdlOP2XUsi687VH+tfKrAsKnImk+kI
+gFAyyMZT5DK7da7YXOf/5gUd4Bi9cEe3ddMKUMuctMU
+--- 9tVE+AAvptrlMZe5+UGJGzH9usnxa+ZICbikcRT0PYI
+g!X+/0P	;*{Vp!4sa	I+/\IԖ,op웘DP7";pPp
+%cUڜ8
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/gotosocial_environment_file.age b/nix/hosts/corrino/secrets/gotosocial_environment_file.age
index 7211c12..d2b6b90 100644
--- a/nix/hosts/corrino/secrets/gotosocial_environment_file.age
+++ b/nix/hosts/corrino/secrets/gotosocial_environment_file.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/gotosocial_oidc_client_secret.age b/nix/hosts/corrino/secrets/gotosocial_oidc_client_secret.age
new file mode 100644
index 0000000..bd6a14a
--- /dev/null
+++ b/nix/hosts/corrino/secrets/gotosocial_oidc_client_secret.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q PoCUbJ4Pg2ZCYy3HCI4w7J/vu5gh6d257Q/PlOBEEG4
+Hisdtymy8i3cN0LVuXpY8duCBMLlTT8QoOEYVmLy+n8
+-> ssh-ed25519 m8VklA i01UwKFor55UM6dL7glsMP6PQM9fcoa9EV3RRXPwRnE
+9fJ9nWhhwyEXclzaYAszUTLTNH/xkM3u9uw0BgY8FOg
+--- 8MUr5xLS5Rt1yXNPfIQwfF6ZGJwNOe/RVtlX0MaGMZ8
+Y^h#2NtغBFXƭo.eCv%1/O%.G×Ϥ%f]_2eo~p {bݚSH݆Rnkcjm<?k%n:FBJ#&
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/grafana_env_vars.age b/nix/hosts/corrino/secrets/grafana_env_vars.age
index 0365676..7ad889e 100644
--- a/nix/hosts/corrino/secrets/grafana_env_vars.age
+++ b/nix/hosts/corrino/secrets/grafana_env_vars.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/grafana_oidc_client_secret.age b/nix/hosts/corrino/secrets/grafana_oidc_client_secret.age
new file mode 100644
index 0000000..91d87e8
--- /dev/null
+++ b/nix/hosts/corrino/secrets/grafana_oidc_client_secret.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q YdFGe2zYgdQDdW9tZG/VPlV6ZnWCv1u2hIg3AiBVwU0
+7PXZNJR5HszD2IqVJX3Rw2VfI1Anf3fuOQTFNq58raU
+-> ssh-ed25519 m8VklA LP+D7xz1SbSPT+6lEfaRjxNPSsBfyN7pE2LAe7ErVCA
+wQeekB+chF01SCX8+BNcKk7o6jN8sT5uic+Oe/od9yc
+--- ZG36Lj4tUALxjMb1+86Y3tdH1KMEw+Teeks0UbB2Zvk
+. i0.XN)`uP&4pHTDBaC>}qQQ㓴>T<ه+'ze{S؃
Ix$mO֨yčPvyAUgf4$oWg
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/hedgedoc_environment_variables.age b/nix/hosts/corrino/secrets/hedgedoc_environment_variables.age
index cf3cac2..a5fe67e 100644
--- a/nix/hosts/corrino/secrets/hedgedoc_environment_variables.age
+++ b/nix/hosts/corrino/secrets/hedgedoc_environment_variables.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/hedgedoc_oidc_client_secret.age b/nix/hosts/corrino/secrets/hedgedoc_oidc_client_secret.age
new file mode 100644
index 0000000..46d39fd
--- /dev/null
+++ b/nix/hosts/corrino/secrets/hedgedoc_oidc_client_secret.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/immich_oidc_client_secret.age b/nix/hosts/corrino/secrets/immich_oidc_client_secret.age
new file mode 100644
index 0000000..be7429d
--- /dev/null
+++ b/nix/hosts/corrino/secrets/immich_oidc_client_secret.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/miniflux_admin_file.age b/nix/hosts/corrino/secrets/miniflux_admin_file.age
new file mode 100644
index 0000000..3e00b9b
--- /dev/null
+++ b/nix/hosts/corrino/secrets/miniflux_admin_file.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q OGds4NLmRiMmVjPTORP3jLe3iEkqrDyTqW4V7ceFfRk
+FFdZcsT9ZruNhpY5cb674qpQpK0qzHNwRPCfHvYaKcE
+-> ssh-ed25519 m8VklA 84XSPja8dzJEUVR5olwNONVzNn5QrsX+R+WeBHqxXDo
+5CVpnTDcO0EG3NsHdFsSABWNBIe3Xe16me13JIOlfos
+--- rlIUU/0gYwxIXmpRI5/3mmZXJ+JrG/tE/3IBtpo4uT4
+-9JNVG.l.e?&r;V#ahSJWjhvѳt;3ϫk(^QU	*czFbwPZuqĉ
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/miniflux_oidc_client_secret.age b/nix/hosts/corrino/secrets/miniflux_oidc_client_secret.age
new file mode 100644
index 0000000..85879a9
--- /dev/null
+++ b/nix/hosts/corrino/secrets/miniflux_oidc_client_secret.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/miniflux_oidc_secret.age b/nix/hosts/corrino/secrets/miniflux_oidc_secret.age
new file mode 100644
index 0000000..668c429
--- /dev/null
+++ b/nix/hosts/corrino/secrets/miniflux_oidc_secret.age
@@ -0,0 +1,8 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q Xjrf8ip0AwW6b77m4XJupjfszP3echG2XQULubcQO14
+A2RZ+dWnrbS83yw5krGr3QuHzdxUo8RLbqstO7PqdzY
+-> ssh-ed25519 m8VklA RHSeMlhwrnG433aw1Hggck8kaVlSL94TVvn68PIS3W8
+ymqenUy96rBZnCaLzrgcAW67s4WkHUv/xRPLw3Viy9g
+--- iJRJrTP0vx6h7/uHO09JlKmq5Z/IfcrYxlIe+ZGFFlI
+-SJ%1dZ"5xZ5gs%{}un/pw€J(3!1nE2QQMJs[Ao{tr/
+vK`rD
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/tailscale-corrino-cert.age b/nix/hosts/corrino/secrets/tailscale-corrino-cert.age
new file mode 100644
index 0000000..ecb9e6e
--- /dev/null
+++ b/nix/hosts/corrino/secrets/tailscale-corrino-cert.age
Binary files differdiff --git a/nix/hosts/corrino/secrets/tailscale-corrino-key.age b/nix/hosts/corrino/secrets/tailscale-corrino-key.age
new file mode 100644
index 0000000..5226883
--- /dev/null
+++ b/nix/hosts/corrino/secrets/tailscale-corrino-key.age
Binary files differdiff --git a/nix/hosts/corrino/vm.nix b/nix/hosts/corrino/vm.nix
new file mode 100644
index 0000000..78d818f
--- /dev/null
+++ b/nix/hosts/corrino/vm.nix
@@ -0,0 +1,55 @@
+{  pkgs, ... }:
+
+{
+  services.emile.libvirtnix = {
+    enable = true;
+    instances = {
+
+      vm1 = {
+        domain = {
+          name = "VM1";
+          title = "vm one";
+          description = "The first VM";
+          id = 1;
+
+          uuid = "E34DE478-1402-45BB-B3FD-FC960549258E";
+          genid = "CA1E2462-1E9D-404C-8DDB-19EEF9D9651B";
+
+          os = {
+            nvram = {
+              type = "network";
+              source = {
+                mirror = {
+                  abi = "copy";
+                  ready = "yes";
+                  type = "network";
+                };
+              };
+            };
+          };
+
+          packages = {
+            libvirt = pkgs.libvirt;
+            qemu = pkgs.qemu;
+          };
+          memory = 1024;
+        };
+      };
+
+      vm2 = {
+        domain = {
+          name = "VM2";
+          title = "vm one";
+          description = "The second VM";
+          id = 2;
+
+          uuid = "E34DE478-1402-45BB-B3FD-FC960549258E";
+          genid = "002D0D8F-B21A-4001-92BF-2313707EED9D";
+
+          memory = 2048;
+        };
+      };
+
+    };
+  };
+}
diff --git a/nix/hosts/corrino/www/cs.emile.space.nix b/nix/hosts/corrino/www/cs.emile.space.nix
index d07d9b2..e182f9c 100644
--- a/nix/hosts/corrino/www/cs.emile.space.nix
+++ b/nix/hosts/corrino/www/cs.emile.space.nix
@@ -44,18 +44,17 @@ in
   services.hound = {
     enable = true;
 
-    config = ''
-      			{
-      			  "dbpath": "/var/lib/hound/data",
-      			  "max-concurrent-indexers" : 6,
-      		    "vcs-config" : {
-      	        "git" : {
-                  "detect-ref" : true
-      	        }
-      		    },
-      			  "repos" : ${repos}
-      			}
-      		'';
+    settings = {
+              title = "cs.emile.space";
+      			  dbpath = "/var/lib/hound/data";
+      			  max-concurrent-indexers = 6;
+      		    vcs-config = {
+      	        git = {
+                  detect-ref = true;
+      	        };
+      		    };
+      			  repos = repos;
+      			};
 
     listen = "127.0.0.1:${toString config.emile.ports.hound}";
   };
diff --git a/nix/hosts/corrino/www/ctf.emile.space.nix b/nix/hosts/corrino/www/ctf.emile.space.nix
index 28c9419..a6ebd05 100644
--- a/nix/hosts/corrino/www/ctf.emile.space.nix
+++ b/nix/hosts/corrino/www/ctf.emile.space.nix
@@ -7,18 +7,19 @@
 
     locations = {
       "/" = {
-        proxyPass = "http://127.0.0.1:${toString config.emile.ports.ctf}";
+        # proxyPass = "http://127.0.0.1:${toString config.emile.ports.ctf}";
+        proxyPass = "http://138.199.213.51";
       };
     };
   };
 
-  virtualisation.oci-containers = {
-    # backend = "docker";
-    containers = {
-      "ctfd" = {
-        image = "ctfd/ctfd";
-        ports = [ "${toString config.emile.ports.ctf}:8000" ];
-      };
-    };
-  };
+  # virtualisation.oci-containers = {
+  #   # backend = "docker";
+  #   containers = {
+  #     "ctfd" = {
+  #       image = "ctfd/ctfd";
+  #       ports = [ "${toString config.emile.ports.ctf}:8000" ];
+  #     };
+  #   };
+  # };
 }
diff --git a/nix/hosts/corrino/www/git/cgit.nix b/nix/hosts/corrino/www/git/cgit.nix
index 68304db..44f5996 100644
--- a/nix/hosts/corrino/www/git/cgit.nix
+++ b/nix/hosts/corrino/www/git/cgit.nix
@@ -630,7 +630,13 @@ in
     extraGroups = [ "gitea" ];
     home = "/var/lib/git";
     uid = lib.mkForce 127;
+    # shell = "${pkgs.git}/bin/git-shell";
+    #   openssh.authorizedKeys.keys = [
+    #     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPZi43zHEsoWaQomLGaftPE5k0RqVrZyiTtGqZlpWsew emile@caladan
+    # "
+    # ];
   };
+  
   users.groups.git = {
     gid = lib.mkForce 127;
   };
diff --git a/nix/hosts/corrino/www/git/git.nix b/nix/hosts/corrino/www/git/git.nix
deleted file mode 100644
index 3a2b9da..0000000
--- a/nix/hosts/corrino/www/git/git.nix
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-  lib,
-  pkgs,
-  config,
-  ...
-}:
-
-let
-  cfg = config.services.gitea;
-in
-{
-  services.nginx.virtualHosts."git.emile.space" = {
-    forceSSL = true;
-    enableACME = true;
-
-    # TODO(emile): figure out why this doesn't work when enabled, has to do with authelia
-    # extraConfig = authelia-location;
-
-    locations = {
-      "/" = {
-        # proxyPass = "http://127.0.0.1:3000";
-        proxyPass = "http://127.0.0.1:${toString config.services.gitea.settings.server.HTTP_PORT}";
-
-        # TODO(emile): figure out why this doesn't work when enabled, has to do with authelia
-        # extraConfig = authelia-authrequest;
-      };
-    };
-  };
-
-  # auth via authelia
-  services.authelia.instances.main.settings.identity_providers.oidc.clients = [
-    {
-      id = "git";
-
-      # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
-      secret = "$pbkdf2-sha512$310000$4bi9wRkfcqnjbdmgt7rU.g$pQ2mC6GW4.BQwanGKKFhFyIx6Y.WY80xd/YpmlYOPnlnGBWpp0dSOTv6a/2yqSA5D.EuRkGCyeexSE5FdCK2TA";
-      public = false;
-      authorization_policy = "two_factor";
-      redirect_uris = [ "https://git.emile.space/user/oauth2/authelia/callback" ];
-      scopes = [
-        "openid"
-        "email"
-        "profile"
-      ];
-    }
-  ];
-
-  services.gitea = rec {
-    enable = true;
-
-    appName = "git.emile.space";
-
-    # unstable in order to use the 1.20... version
-    #package = pkgs.forgejo;
-    package = pkgs.unstable.forgejo;
-
-    stateDir = "/var/lib/gitea";
-    repositoryRoot = "${stateDir}/repositories";
-
-    settings = {
-      service.DISABLE_REGISTRATION = true;
-
-      DEFAULT = {
-        WORK_PATH = "/var/lib/gitea";
-      };
-
-      server = {
-        DOMAIN = pkgs.lib.mkForce "git.emile.space";
-        ROOT_URL = pkgs.lib.mkForce "https://git.emile.space";
-        HTTP_PORT = config.emile.ports.git;
-
-        #START_SSH_SERVER = true;
-        BUILTIN_SSH_SERVER_USER = "git";
-        SSH_USER = "gitea";
-        SSH_DOMAIN = "git.emile.space";
-
-        REPO_INDEXER_ENABLED = true;
-      };
-
-      indexer = {
-        REPO_INDEXER_ENABLED = true;
-        ISSUE_INDEXER_PATH = "${stateDir}/indexers/issues.bleve";
-        REPO_INDEXER_PATH = "${stateDir}/indexers/repos.bleve";
-        MAX_FILE_SIZE = 1048576;
-        REPO_INDEXER_INCLUDE = "";
-        REPO_INDEXER_EXCLUDE = "resources/bin/**";
-      };
-
-      #federation = {
-      #  enable = true;
-      #  share_user_statistics = true;
-      #  max_size = 4;
-      #};
-    };
-  };
-
-  users.users.git = {
-    isSystemUser = true;
-    useDefaultShell = true;
-    group = "git";
-    extraGroups = [ "gitea" ];
-    home = cfg.stateDir;
-    uid = 127;
-  };
-  users.groups.git = { };
-}
diff --git a/nix/hosts/corrino/www/goapp.emile.space.nix b/nix/hosts/corrino/www/goapp.emile.space.nix
new file mode 100644
index 0000000..e31079e
--- /dev/null
+++ b/nix/hosts/corrino/www/goapp.emile.space.nix
@@ -0,0 +1,93 @@
+{ config, pkgs, ... }:
+
+{
+  services.nginx.virtualHosts."goapp.emile.space" = {
+    forceSSL = true;
+    enableACME = true;
+
+    locations = {
+      "/" = {
+        proxyPass = "http://${config.services.emile.goapp-frontend.host}:${toString config.services.emile.goapp-frontend.port}";
+      };
+    };
+  };
+
+  age.secrets.goapp_oidc_client_secret.owner = "authelia-main";
+  age.secrets.goapp_oidc_client_secret.group = "authelia-main";
+  
+  services.authelia.instances.main.settings.identity_providers.oidc.clients = [
+    {
+      client_id = "goapp";
+
+      # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
+      client_secret = "{{ secret \"${config.age.secrets.goapp_oidc_client_secret.path}\" }}";
+
+      public = false;
+      authorization_policy = "two_factor";
+      redirect_uris = [
+        "https://goapp.emile.space/oauth2/callback"
+      ];
+      scopes = [
+        "openid"
+        "email"
+        "profile"
+        "groups"
+      ];
+      grant_types = [
+        "refresh_token"
+        "authorization_code"
+      ];
+      response_types = [ "code" ];
+      response_modes = [
+        "form_post"
+        "query"
+        "fragment"
+      ];
+      token_endpoint_auth_method = "client_secret_post";
+    }
+  ];
+
+  environment.systemPackages = with pkgs; [ goapp-frontend ];
+
+  # deploy:
+  # - push code
+  # - build in order to get the new hash (nix build .#goapp-frontend-pkg)
+  # - update hash in the package (//nix/templates/goapp/frontent/default.nix)
+  # - deploy
+  #
+  # https://goapp.emile.space/oauth2/callback?code=authelia_ac_iZKCXtRMnj2yjUAmiSkg_LBWjiME2-ghE6KMkxdb6Zw.nDLgCVpu9ctH1llEKUml5rr8szd3bkZYaGa_MAOtNLI&iss=https%3A%2F%2Fsso.emile.space&scope=openid+profile+email+groups&state=random-string-here
+  #
+  # Unable to exchange authorization code for tokens
+  #
+  # unable to exchange authorization code for tokens: oauth2: "invalid_client" "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)."
+
+  services.emile.goapp-frontend = {
+    enable = true;
+    package = pkgs.goapp-frontend;
+
+    host = "127.0.0.1";
+    port = config.emile.ports.goapp;
+    public-url = "https://goapp.emile.space/";
+
+    oidc = {
+      id = "goapp";
+      issuer = "https://sso.emile.space";
+      cookie-name = "oidc-client";
+      scopes = [
+        "openid"
+        "profile"
+        "email"
+        "groups"
+      ];
+      # secret-path = "/run/goapp-frontend_oidc_secret";
+      secret-path = config.age.secrets.goapp_oidc_secret.path;
+    };
+
+    # TODO(emile): change these when going live
+    session-key-path = config.age.secrets.goapp_oidc_secret.path;
+
+    logfile-path = "/var/log/goapp-frontend.log";
+    database-path = "/var/lib/goapp-frontend/main.db";
+    sessiondb-path = "/var/lib/goapp-frontend/session.db";
+  };
+}
diff --git a/nix/hosts/corrino/www/grafana.emile.space.nix b/nix/hosts/corrino/www/grafana.emile.space.nix
index 22b444f..2caa4d4 100644
--- a/nix/hosts/corrino/www/grafana.emile.space.nix
+++ b/nix/hosts/corrino/www/grafana.emile.space.nix
@@ -3,134 +3,143 @@
 {
   systemd.services.grafana.serviceConfig.EnvironmentFile = config.age.secrets.grafana_env_vars.path;
 
-  services = {
-    nginx.virtualHosts = {
-      "grafana.emile.space" = {
-        addSSL = true;
-        enableACME = true;
-        locations."/" = {
-          proxyPass = "http://${toString config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}/";
-          proxyWebsockets = true;
-        };
+  
+  services.nginx.virtualHosts = {
+    "grafana.emile.space" = {
+      addSSL = true;
+      enableACME = true;
+      locations."/" = {
+        proxyPass = "http://${toString config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}/";
+        proxyWebsockets = true;
       };
     };
+  };
 
-    authelia.instances.main.settings.identity_providers.oidc.clients = [
-      {
-        id = "Grafana";
-
-        # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
-        secret = "$pbkdf2-sha512$310000$S.RE0jcmr7Sn/tjJDNxV/A$1tsYhQ/YEcVfE4JyzszHemrcUqy.84Fb6xVSmz87if5C9N46Mz2lRWB5l8s4EIrLsiumPnt4HQMkYZ4MoovJzA";
-        public = false;
-        authorization_policy = "two_factor";
-        redirect_uris = [ "https://grafana.emile.space/login/generic_oauth" ];
-        scopes = [
-          "openid"
-          "email"
-          "profile"
-          "groups"
-        ];
-        grant_types = [
-          "refresh_token"
-          "authorization_code"
-        ];
-        response_types = [ "code" ];
-        response_modes = [
-          "form_post"
-          "query"
-          "fragment"
-        ];
-      }
-    ];
-
-    grafana = {
-      enable = true;
-      settings = {
-        server = {
-          http_addr = "127.0.0.1";
-          http_port = config.emile.ports.grafana;
-          domain = "grafana.emile.space";
-          root_url = "https://grafana.emile.space/";
-        };
+  age.secrets.grafana_oidc_client_secret.owner = "authelia-main";
+  age.secrets.grafana_oidc_client_secret.group = "authelia-main";
 
-        "auth.generic_oauth" =
-          let
-            sso = "https://sso.emile.space/api/oidc";
-          in
-          {
-            enabled = true;
-            client_id = "Grafana";
-
-            # [auth.generic_oauth]
-            # client_secret = ... 
-            #   set in env var as 
-            #   GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET 
-            client_secret = "set in env var this is just a placeholder";
-
-            use_refresh_token = true;
-            token_url = "${sso}/token";
-            auth_url = "${sso}/authorization";
-            api_url = "${sso}/userinfo";
-
-            scopes = [
-              "openid"
-              "email"
-              "profile"
-              "groups"
-            ];
-
-            email_attribute_path = "email";
-            login_attribute_path = "preferred_username";
-            name_attribute_path = "name";
-
-            role_attribute_path = "contains(groups[*], 'grafana_server_admin') && 'GrafanaAdmin' || contains(groups[*], 'grafana_admin') && 'Admin' || contains(groups[*], 'grafana_editor') && 'Editor' || 'Viewer'";
-
-          };
+  services.authelia.instances.main.settings.identity_providers.oidc.clients = [
+    {
+      client_id = "Grafana";
+
+      # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
+      client_secret = "{{ secret \"${config.age.secrets.grafana_oidc_client_secret.path}\" }}";
+
+      public = false;
+      authorization_policy = "two_factor";
+      redirect_uris = [ "https://grafana.emile.space/login/generic_oauth" ];
+      scopes = [
+        "openid"
+        "email"
+        "profile"
+        "groups"
+      ];
+      grant_types = [
+        "refresh_token"
+        "authorization_code"
+      ];
+      response_types = [ "code" ];
+      response_modes = [
+        "form_post"
+        "query"
+        "fragment"
+      ];
+    }
+  ];
+
+  services.grafana = {
+    enable = true;
+    settings = {
+      server = {
+        http_addr = "127.0.0.1";
+        http_port = config.emile.ports.grafana;
+        domain = "grafana.emile.space";
+        root_url = "https://grafana.emile.space/";
       };
 
-      provision = {
-        dashboards.settings = { };
-        datasources.settings = {
-          datasources = [
-            {
-              url = "http://localhost:${toString config.services.prometheus.port}";
-              type = "prometheus";
-              name = "Prometheus";
-              editable = false;
-              access = "proxy"; # server = "proxy", browser = "direct"
-            }
-            {
-              name = "loki";
-              url = "http://${config.services.loki.configuration.common.instance_addr}:${toString config.services.loki.configuration.server.http_listen_port}";
-              type = "loki";
-            }
+      "auth.generic_oauth" =
+        let
+          sso = "https://sso.emile.space/api/oidc";
+        in
+        {
+          enabled = true;
+          client_id = "Grafana";
+
+          # [auth.generic_oauth]
+          # client_secret = ... 
+          #   set in env var as 
+          #   GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET 
+          client_secret = "set in env var this is just a placeholder";
+
+          use_refresh_token = true;
+          token_url = "${sso}/token";
+          auth_url = "${sso}/authorization";
+          api_url = "${sso}/userinfo";
+
+          scopes = [
+            "openid"
+            "email"
+            "profile"
+            "groups"
           ];
+
+          email_attribute_path = "email";
+          login_attribute_path = "preferred_username";
+          name_attribute_path = "name";
+
+          role_attribute_path = "contains(groups[*], 'grafana_server_admin') && 'GrafanaAdmin' || contains(groups[*], 'grafana_admin') && 'Admin' || contains(groups[*], 'grafana_editor') && 'Editor' || 'Viewer'";
+
         };
+    };
 
-        # TODO(emile): finish setting up the grafana notifier filling out the settings section
-        # notifiers = [
-        #   {
-        #     uid = "2ad1c1d1-bcd9-4cb8-8897-c89c5820ffb1";
-        #     type = "email";
-        #     settings = {};
-        #     org_name = "Main Org.";
-        #     org_id = 1;
-        #     name = "email";
-        #     id_default = true;
-        #     frequency = "5m";
-        #     disable_resolve_message = false;
-        #   }
-        # ];
-
-        # TODO(emile): finish setting up the alerting stuff within here
-        # alerting = {
-        #   templates.settings = { };
-        #   rules.settings = {};
-        #   policies.settings = {};
-        #   muteTimings.settings = {};
-        #   contactPoints.settings = {};
-        # };
+    provision = {
+      dashboards.settings = { };
+      datasources.settings = {
+        deleteDatasources = [
+          { name = "Prometheus"; orgId = 1; }  
+          { name = "Lampadas"; orgId = 1; }  
+        ];
+        datasources = [
+          {
+            url = "http://localhost:${toString config.services.prometheus.port}";
+            type = "prometheus";
+            name = "Prometheus Corrino";
+            editable = false;
+            access = "proxy"; # server = "proxy", browser = "direct"
+          }
+          {
+            url = "http://lampadas:9009";
+            type = "prometheus";
+            name = "Prometheus Lampadas";
+            editable = false;
+            access = "proxy"; # server = "proxy", browser = "direct"
+          }
+        ];
       };
+
+      # TODO(emile): finish setting up the grafana notifier filling out the settings section
+      # notifiers = [
+      #   {
+      #     uid = "2ad1c1d1-bcd9-4cb8-8897-c89c5820ffb1";
+      #     type = "email";
+      #     settings = {};
+      #     org_name = "Main Org.";
+      #     org_id = 1;
+      #     name = "email";
+      #     id_default = true;
+      #     frequency = "5m";
+      #     disable_resolve_message = false;
+      #   }
+      # ];
+
+      # TODO(emile): finish setting up the alerting stuff within here
+      # alerting = {
+      #   templates.settings = { };
+      #   rules.settings = {};
+      #   policies.settings = {};
+      #   muteTimings.settings = {};
+      #   contactPoints.settings = {};
+      # };
     };
   };
 }
diff --git a/nix/hosts/corrino/www/hydra.emile.space.nix b/nix/hosts/corrino/www/hydra.emile.space.nix
index 941ad5b..fe70bf4 100644
--- a/nix/hosts/corrino/www/hydra.emile.space.nix
+++ b/nix/hosts/corrino/www/hydra.emile.space.nix
@@ -21,9 +21,10 @@
   services.hydra = {
     enable = true;
 
-    package = pkgs.hydra_unstable.overrideAttrs (old: {
-      patches = (if old ? patches then old.patches else [ ]) ++ [ ./hydra.patch ];
-    });
+    #package = pkgs.hydra_unstable.overrideAttrs (old: {
+    #  patches = (if old ? patches then old.patches else [ ]) ++ [ ./hydra.patch ];
+    #});
+    package = pkgs.hydra;
 
     listenHost = "*";
     port = config.emile.ports.hydra;
@@ -32,8 +33,6 @@
     # Directory that holds Hydra garbage collector roots.
     gcRootsDir = "/nix/var/nix/gcroots/hydra";
 
-    # a standalone hydra will require you to unset the buildMachinesFiles list to avoid using a nonexistant /etc/nix/hosts
-    buildMachinesFiles = [ ];
     # you will probably also want, otherwise *everything* will be built from scratch
     useSubstitutes = true;
 
diff --git a/nix/hosts/corrino/www/irc.emile.space.nix b/nix/hosts/corrino/www/irc.emile.space.nix
index ac00445..7653cb4 100644
--- a/nix/hosts/corrino/www/irc.emile.space.nix
+++ b/nix/hosts/corrino/www/irc.emile.space.nix
@@ -1,155 +1,198 @@
-{ config, ... }:
+{ config, pkgs, ... }:
 
 {
+  ##############################################################################
+  # Client
+  ##############################################################################
+  # gamja web client
+  # https://codeberg.org/emersion/gamja
+  #
+  # nah, let's just use the commaond line "senpai" client, from the same person
+
+  ##############################################################################
+  # Bouncer
+  ##############################################################################
+  # soju bouncer
+  # https://soju.im
+
+  # services.soju = {
+  #   enable = true;
+  #   listen = [ "127.0.0.1:${toString config.emile.ports.irc.bouncer}" ];
+
+  #   hostName = "irc.emile.space";
+  #   httpOrigins = [ "127.0.0.1" "irc.emile.space" ];
+
+  #   # tlsCertificateKey = "/var/lib/acme/irc.emile.space/key.pem";
+  #   # tlsCertificate = "/var/lib/acme/irc.emile.space/cert.pem";
+  # };
+
+  # services.soju = {
+  #   enable = true;
+  #   package = pkgs.soju;
+  #   listen = [ "127.0.0.1:${toString config.emile.ports.irc.bouncer}" ];
+  #   adminSocket.enable = true;
+  #   # tlsCertificateKey = "/var/lib/acme/irc.emile.space/key.pem";
+  #   # tlsCertificate = "/var/lib/acme/irc.emile.space/cert.pem";
+  #   httpOrigins = [ "127.0.0.1" "irc.emile.space" ];
+  #   hostName = "irc.emile.space";
+  #   extraConfig = "";
+  #   enableMessageLogging = true;
+  #   acceptProxyIP = [];
+  # };
+
+  ##############################################################################
+  # Server
+  ##############################################################################
+
   # Create a tls cert for the irc server
-  security.acme.certs = {
-    "irc.emile.space" = {
-      webroot = "/var/lib/acme/acme-challenge/";
-      email = "acme@emile.space";
-      postRun = "cp fullchain.pem /home/ergo/ && cp key.pem /home/ergo && chown ergo:ergo /home/ergo/*.pem && systemctl reload ergo.service";
-    };
-  };
-
-  # Allow ergo to access the created cert
-  # The systemd server runs using a dynamic user, so the below inserts the .pem files
-  #   into "/run/credentials/ergochat.service/key.pem"
-  systemd.services.ergochat.serviceConfig = {
-    LoadCredential = [
-      "fullchain.pem:/var/lib/acme/irc.emile.space/fullchain.pem"
-      "key.pem:/var/lib/acme/irc.emile.space/key.pem"
-    ];
-  };
-
-  # allow connections to the port from the "outside"
-  networking.firewall.allowedTCPPorts = [ config.emile.ports.irc.ssl ];
-
-  services.ergochat = {
-    enable = true;
-
-    # https://raw.githubusercontent.com/ergochat/ergo/master/default.yaml
-    settings = {
-      accounts = {
-        authentication-enabled = true;
-        multiclient = {
-          allowed-by-default = true;
-          always-on = "opt-out";
-          auto-away = "opt-out";
-          enabled = true;
-        };
-        registration = {
-          enabled = true;
-          allow-before-connect = true;
-          bcrypt-cost = 4;
-          email-verification = {
-            enabled = false;
-          };
-          throttling = {
-            duration = "10m";
-            enabled = true;
-            max-attempts = 30;
-          };
-        };
-      };
-      channels = {
-        default-modes = "+ntC";
-        registration = {
-          enabled = true;
-        };
-      };
-      datastore = {
-        autoupgrade = true;
-        path = "/var/lib/ergo/ircd.db";
-      };
-      history = {
-        enabled = true;
-        autoreplay-on-join = 0;
-        autoresize-window = "3d";
-        channel-length = 2048;
-        chathistory-maxmessages = 100;
-        client-length = 256;
-        restrictions = {
-          expire-time = "1w";
-          grace-period = "1h";
-          query-cutoff = "none";
-        };
-        retention = {
-          allow-individual-delete = false;
-          enable-account-indexing = false;
-        };
-        tagmsg-storage = {
-          default = false;
-          whitelist = [
-            "+draft/react"
-            "+react"
-          ];
-        };
-        znc-maxmessages = 2048;
-      };
-      limits = {
-        awaylen = 390;
-        channellen = 64;
-        identlen = 20;
-        kicklen = 390;
-        nicklen = 32;
-        topiclen = 390;
-      };
-      network = {
-        name = "emilespace";
-      };
-      server = {
-        casemapping = "permissive";
-        check-ident = false;
-        enforce-utf = true;
-        forward-confirm-hostnames = false;
-        ip-cloaking = {
-          enabled = false;
-        };
-        ip-limits = {
-          count = false;
-          throttle = false;
-        };
-        listeners = {
-          # sts only port
-          ":6667".sts-only = true;
-
-          # loopback listeners
-          # "127.0.0.1:6668" = {};
-          # "[::]:6668" = {};
-
-          ":${toString config.emile.ports.irc.ssl}" = {
-            tls = {
-              cert = "/run/credentials/ergochat.service/fullchain.pem";
-              key = "/run/credentials/ergochat.service/key.pem";
-            };
-
-            # for cloud load balancers setting a PROXY header, NOT reverse proxies...
-            proxy = false;
-
-            min-tls-version = 1.2;
-          };
-        };
-        lookup-hostnames = false;
-        max-sendq = "1M";
-        name = "emile.space";
-        relaymsg = {
-          enabled = false;
-        };
-        sts = {
-          enabled = true; # redirect from plain to tls if supported
-
-          # how long clients should be forced to use TLS for.
-          # (Emile): no clue why, can I set something like \infty here?
-          duration = "12m";
-
-        };
-      };
-      logging = [
-        {
-          method = "stderr";
-          type = "* -userinput -useroutput";
-          level = "debug";
-        }
-      ];
-    };
-  };
+  # security.acme.certs = {
+  #   "irc.emile.space" = {
+  #     webroot = "/var/lib/acme/acme-challenge/";
+  #     email = "acme@emile.space";
+  #     # postRun = "cp fullchain.pem /home/ergo/ && cp key.pem /home/ergo && chown ergo:ergo /home/ergo/*.pem && systemctl reload ergo.service";
+  #   };
+  # };
+
+  # # Allow ergo to access the created cert
+  # # The systemd server runs using a dynamic user, so the below inserts the .pem files
+  # #   into "/run/credentials/ergochat.service/key.pem"
+  # systemd.services.ergochat.serviceConfig = {
+  #   LoadCredential = [
+  #     "fullchain.pem:/var/lib/acme/irc.emile.space/fullchain.pem"
+  #     "key.pem:/var/lib/acme/irc.emile.space/key.pem"
+  #   ];
+  # };
+
+  # # allow connections to the port from the "outside"
+  # networking.firewall.allowedTCPPorts = [ config.emile.ports.irc.ssl ];
+
+  # services.ergochat = {
+  #   enable = true;
+
+  #   # https://raw.githubusercontent.com/ergochat/ergo/master/default.yaml
+  #   settings = {
+  #     accounts = {
+  #       authentication-enabled = true;
+  #       multiclient = {
+  #         allowed-by-default = true;
+  #         always-on = "opt-out";
+  #         auto-away = "opt-out";
+  #         enabled = true;
+  #       };
+  #       registration = {
+  #         enabled = true;
+  #         allow-before-connect = true;
+  #         bcrypt-cost = 4;
+  #         email-verification = {
+  #           enabled = false;
+  #         };
+  #         throttling = {
+  #           duration = "10m";
+  #           enabled = true;
+  #           max-attempts = 30;
+  #         };
+  #       };
+  #     };
+  #     channels = {
+  #       default-modes = "+ntC";
+  #       registration = {
+  #         enabled = true;
+  #       };
+  #     };
+  #     datastore = {
+  #       autoupgrade = true;
+  #       path = "/var/lib/ergo/ircd.db";
+  #     };
+  #     history = {
+  #       enabled = true;
+  #       autoreplay-on-join = 0;
+  #       autoresize-window = "3d";
+  #       channel-length = 2048;
+  #       chathistory-maxmessages = 100;
+  #       client-length = 256;
+  #       restrictions = {
+  #         expire-time = "1w";
+  #         grace-period = "1h";
+  #         query-cutoff = "none";
+  #       };
+  #       retention = {
+  #         allow-individual-delete = false;
+  #         enable-account-indexing = false;
+  #       };
+  #       tagmsg-storage = {
+  #         default = false;
+  #         whitelist = [
+  #           "+draft/react"
+  #           "+react"
+  #         ];
+  #       };
+  #       znc-maxmessages = 2048;
+  #     };
+  #     limits = {
+  #       awaylen = 390;
+  #       channellen = 64;
+  #       identlen = 20;
+  #       kicklen = 390;
+  #       nicklen = 32;
+  #       topiclen = 390;
+  #     };
+  #     network = {
+  #       name = "emilespace";
+  #     };
+  #     server = {
+  #       casemapping = "permissive";
+  #       check-ident = false;
+  #       enforce-utf = true;
+  #       forward-confirm-hostnames = false;
+  #       ip-cloaking = {
+  #         enabled = false;
+  #       };
+  #       ip-limits = {
+  #         count = false;
+  #         throttle = false;
+  #       };
+  #       listeners = {
+  #         # sts only port
+  #         ":6667".sts-only = true;
+
+  #         # loopback listeners
+  #         # "127.0.0.1:6668" = {};
+  #         # "[::]:6668" = {};
+
+  #         ":${toString config.emile.ports.irc.ssl}" = {
+  #           tls = {
+  #             cert = "/run/credentials/ergochat.service/fullchain.pem";
+  #             key = "/run/credentials/ergochat.service/key.pem";
+  #           };
+
+  #           # for cloud load balancers setting a PROXY header, NOT reverse proxies...
+  #           proxy = false;
+
+  #           min-tls-version = 1.2;
+  #         };
+  #       };
+  #       lookup-hostnames = false;
+  #       max-sendq = "1M";
+  #       name = "emile.space";
+  #       relaymsg = {
+  #         enabled = false;
+  #       };
+  #       sts = {
+  #         enabled = true; # redirect from plain to tls if supported
+
+  #         # how long clients should be forced to use TLS for.
+  #         # (Emile): no clue why, can I set something like \infty here?
+  #         duration = "12m";
+
+  #       };
+  #     };
+  #     logging = [
+  #       {
+  #         method = "stderr";
+  #         type = "* -userinput -useroutput";
+  #         level = "debug";
+  #       }
+  #     ];
+  #   };
+  # };
 }
diff --git a/nix/hosts/corrino/www/loki.emile.space.nix b/nix/hosts/corrino/www/loki.emile.space.nix
deleted file mode 100644
index e5bfe24..0000000
--- a/nix/hosts/corrino/www/loki.emile.space.nix
+++ /dev/null
@@ -1,64 +0,0 @@
-{ config, ... }:
-
-{
-  services = {
-    loki = {
-      enable = false;
-      configuration = {
-        auth_enabled = false;
-        server = {
-          http_listen_port = config.emile.ports.loki;
-        };
-
-        limits_config = {
-          reject_old_samples = false;
-          reject_old_samples_max_age = "7d";
-          max_global_streams_per_user = 100000;
-          max_streams_per_user = 100000;
-
-          retention_period = "10m";
-        };
-
-        compactor = {
-          retention_enabled = true;
-          delete_request_store = "tsdb";
-        };
-
-        common = {
-          instance_addr = "127.0.0.1";
-          ring = {
-            instance_addr = "127.0.0.1";
-            kvstore.store = "inmemory";
-          };
-          replication_factor = 1;
-          path_prefix = "/tmp/loki";
-        };
-
-        # limits_config.allow_structured_metadata = false;
-
-        schema_config.configs = [
-          {
-            from = "2023-05-09";
-            store = "tsdb";
-            object_store = "filesystem";
-            schema = "v13";
-            index = {
-              prefix = "index_";
-              period = "24h";
-            };
-          }
-          {
-            from = "2024-10-18";
-            store = "tsdb";
-            object_store = "filesystem";
-            schema = "v13";
-            index = {
-              prefix = "index_";
-              period = "24h";
-            };
-          }
-        ];
-      };
-    };
-  };
-}
diff --git a/nix/hosts/corrino/www/mc.emile.space.nix b/nix/hosts/corrino/www/mc.emile.space.nix
new file mode 100644
index 0000000..1a081bc
--- /dev/null
+++ b/nix/hosts/corrino/www/mc.emile.space.nix
@@ -0,0 +1,153 @@
+{ config, pkgs, ... }:
+
+{
+  services.minecraft-server = {
+    package = pkgs.minecraft-server;
+    serverProperties = {
+      server-port = 43000;
+
+      # 0 peaceful
+      # 1 easy
+      # 2 normal
+      # 3 hard
+      difficulty = 1;
+
+      # 0 survival
+      # 1 creative
+      # 2 adventure
+      # 5 default
+      # "spectator" spectator
+      # gamemode = "survival";
+      gamemode = 0;
+
+      max-players = 10;
+      motd = "Neurodivergenter Hexenzirkel";
+      enable-rcon = true;
+      "rcon.password" = "hunter2";
+      enable-command-block = false;
+      enable-query = false;
+      spawn-protection = 0;
+
+      white-list = true;
+    };
+    openFirewall = true;
+
+    whitelist = {
+      "emileemail" = "a7614a53-b8b8-47b7-91cf-860e7c7f325f";
+      "dodonator23" = "f93506b6-76e8-437d-927d-dceeb833a33f";
+      "ChaosAyumi" = "223040ec-ca30-4238-8b58-c81597c30426";
+      "xerunala" = "962e41c8-1da8-4592-9a2f-e36cdb20d5a6";
+      "rappet" = "588377a5-362f-4ea1-8195-9cf97dd7a884";
+    };
+
+    jvmOpts = "-Xms4092M -Xmx4092M";
+    eula = true;
+    enable = true;
+    declarative = true;
+    dataDir = "/var/lib/minecraft";
+  };
+
+  services.nginx.virtualHosts."mc.emile.space" = {
+    forceSSL = true;
+    enableACME = true;
+  };
+
+  services.bluemap = {
+    enable = true;
+
+    enableNginx = true;
+    host = "mc.emile.space";
+
+    webappSettings = {
+      enabled = true;
+      webroot = config.services.bluemap.webRoot;
+    };
+
+    # webserverSettings = {};
+    webserverSettings.enabled = false; # using nginx;
+    webRoot = "/var/lib/bluemap/web";
+
+    # coreSettings = {};
+    coreSettings.data = "/var/lib/bluemap";
+    coreSettings.metrics = false; # don't send data to the devs
+
+    storage = {
+      "file" = {
+        root = "${config.services.bluemap.webRoot}/maps";
+      };
+    };
+    # storage.<name>.storage-type
+
+    maps = let
+      worldpath = "/var/lib/minecraft/world";
+    in {
+      "overworld" = {
+        world = "${worldpath}";
+        ambient-light = 0.1;
+        cave-detection-ocean-floor = -5;
+        dimension = "minecraft:overworld";
+      };
+
+      "nether" = {
+        world = "${worldpath}/DIM-1";
+        sorting = 100;
+        sky-color = "#290000";
+        void-color = "#150000";
+        ambient-light = 0.6;
+        world-sky-light = 0;
+        remove-caves-below-y = -10000;
+        cave-detection-ocean-floor = -5;
+        cave-detection-uses-block-light = true;
+        max-y = 90;
+        dimension = "minecraft:the_nether";
+      };
+
+      "end" = {
+        world = "${worldpath}/DIM1";
+        sorting = 200;
+        sky-color = "#080010";
+        void-color = "#080010";
+        ambient-light = 0.6;
+        world-sky-light = 0;
+        remove-caves-below-y = -10000;
+        cave-detection-ocean-floor = -5;
+        dimension = "minecraft:the_end";
+      };
+    };
+
+    # A set of resourcepacks, datapacks, and mods to extract resources from, loaded in alphabetical order.
+    packs = {};
+
+    # How often to trigger rendering the map, in the format of a systemd timer onCalendar configuration. See systemd.timer(5).
+    #
+    # This one means "every three hours":
+    # *-*-* */3:00:00
+    onCalendar = "*-*-* *:00:00";
+
+    eula = true;
+
+    enableRender = true;
+
+    # The world used by the default map ruleset. If you configure your own maps you do not need to set this.
+    # defaultWorld = "${config.services.minecraft.dataDir}/world";
+     
+    addons = {};
+  };
+
+  services.restic.backups."corrino" = {
+    paths = [ "/var/lib/minecraft" ];
+  };
+
+  services.restic.backups."minecraft" = {
+    repository = "/mnt/storagebox-bx11/minecraft";
+    paths = [ "/var/lib/minecraft" ];
+    passwordFile = config.age.secrets.restic_password.path;
+    initialize = true;
+    pruneOpts = [
+      "--keep-daily 7"
+      "--keep-weekly 5"
+      "--keep-monthly 12"
+      "--keep-yearly 75"
+    ];
+  };
+}
diff --git a/nix/hosts/corrino/www/md.emile.space.nix b/nix/hosts/corrino/www/md.emile.space.nix
index 6088ea0..1ee46fd 100644
--- a/nix/hosts/corrino/www/md.emile.space.nix
+++ b/nix/hosts/corrino/www/md.emile.space.nix
@@ -6,18 +6,21 @@
     enableACME = true;
     locations = {
       "/" = {
-        proxyPass = "http://127.0.0.1:${toString config.services.hedgedoc.settings.port}";
+        proxyPass = "http://[${config.services.hedgedoc.settings.host}]:${toString config.services.hedgedoc.settings.port}";
       };
     };
   };
 
+  age.secrets.hedgedoc_oidc_client_secret.owner = "authelia-main";
+  age.secrets.hedgedoc_oidc_client_secret.group = "authelia-main";
+  
   # auth via authelia
   services.authelia.instances.main.settings.identity_providers.oidc.clients = [
     {
-      id = "HedgeDoc";
+      client_id = "HedgeDoc";
 
       # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
-      secret = "$pbkdf2-sha512$310000$l4Kyec7Q9oY2GAhWA/xMig$P/MYFmulfgsDNyyiclUzd6le0oSiOvqCIvl4op5DkXtVTxLWlMA3ZwhJ6Z7u.OfIREuEM2htH6asxWPhBhkpNQ";
+      client_secret = "{{ secret \"${config.age.secrets.hedgedoc_oidc_client_secret.path}\" }}";
       public = false;
       authorization_policy = "two_factor";
       redirect_uris = [ "https://md.emile.space/auth/oauth2/callback" ];
@@ -47,7 +50,7 @@
     environmentFile = config.age.secrets.hedgedoc_environment_variables.path;
 
     settings = {
-      host = "127.0.0.1";
+      host = "::1";
       port = config.emile.ports.md;
 
       domain = "md.emile.space";
@@ -85,28 +88,20 @@
     };
   };
 
-  # backups
-  # services.restic.backups."hedgedoc" = {
-  #   user = "u331921";
-  #   timerConfig = {
-  #     OnCalendar = "daily";
-  #     Persistent = true;
-  #   };
-  #   # repository = "stfp:u331921@u331921.your-storagebox-de:23/restic";
-  #   repository = "/mnt/storagebox-bx11/backup/hedgedoc";
-  #   initialize = true; # initializes the repo, don't set if you want manual control
-  #   passwordFile = config.age.secrets.restic_password.path;
-  #   paths = [ "/var/lib/hedgedoc/" ];
-  #   pruneOpts = [
-  #     "--keep-daily 7"
-  #     "--keep-weekly 5"
-  #     "--keep-monthly 12"
-  #     "--keep-yearly 75"
-  #   ];
-
-  #   # extraOpts = [
-  #   #   "sftp.command='ssh backup@192.168.1.100 -i /home/user/.ssh/id_rsa -s sftp'"
-  #   # ];
-  # };
+  services.restic.backups."corrino" = {
+    paths = [ "/var/lib/hedgedoc" ];
+  };
 
+  services.restic.backups."hedgedoc" = {
+    repository = "/mnt/storagebox-bx11/hedgedoc";
+    paths = [ "/var/lib/hedgedoc" ];
+    passwordFile = config.age.secrets.restic_password.path;
+    initialize = true;
+    pruneOpts = [
+      "--keep-daily 7"
+      "--keep-weekly 5"
+      "--keep-monthly 12"
+      "--keep-yearly 75"
+    ];
+  };
 }
diff --git a/nix/hosts/corrino/www/miniflux.emile.space.nix b/nix/hosts/corrino/www/miniflux.emile.space.nix
new file mode 100644
index 0000000..90cb8f2
--- /dev/null
+++ b/nix/hosts/corrino/www/miniflux.emile.space.nix
@@ -0,0 +1,81 @@
+{ config, pkgs, ... }:
+
+{
+	services.nginx.virtualHosts."miniflux.emile.space" = {
+		forceSSL = true;
+		enableACME = true;
+		locations = {
+			"/" = {
+				proxyPass = "http://${config.services.miniflux.config.LISTEN_ADDR}";
+			};
+		};
+	};
+
+	# oidc not working and I can't bother to continue debugging it now
+	# 
+	# Apr 12 15:37:38 corrino authelia[3693799]: {"level":"error","method":"POST","msg":"Access Request failed with error: Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method). The request was determined to be using 'token_endpoint_auth_method' method 'none', however the OAuth 2.0 client registration does not allow this method. The registered client with id 'miniflux' is configured to only support 'token_endpoint_auth_method' method 'client_secret_basic'. Either the Authorization Server client registration will need to have the 'token_endpoint_auth_method' updated to 'none' or the Relying Party will need to be configured to use 'client_secret_basic'.
+	#
+  # age.secrets.miniflux_oidc_client_secret.owner = "authelia-main";
+  # age.secrets.miniflux_oidc_client_secret.group = "authelia-main";
+	# 
+  # auth via authelia
+  # services.authelia.instances.main.settings.identity_providers.oidc.clients = [
+  #   {
+  #     client_id = "miniflux";
+
+  #     # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
+	#     client_secret = "{{ secret \"${config.age.secrets.miniflux_oidc_client_secret.path}\" }}";
+  #     public = false;
+  #     authorization_policy = "two_factor";
+  #     redirect_uris = [ "https://miniflux.emile.space/oauth2/oidc/callback" ];
+  #     scopes = [
+  #       "openid"
+  #       "email"
+  #       "profile"
+  #     ];
+  #     # grant_types = [
+  #     #   "refresh_token"
+  #     #   "authorization_code"
+  #     # ];
+  #     # response_types = [ "code" ];
+  #     # response_modes = [
+  #     #   "form_post"
+  #     #   "query"
+  #     #   "fragment"
+  #     # ];
+  #     # token_endpoint_auth_method = "client_secret_post";
+  #     # token_endpoint_auth_method = "none";
+  #   }
+  # ];
+
+	services.miniflux = {
+		enable = true;
+		package = pkgs.miniflux;
+		config = {
+		  LISTEN_ADDR = "[::1]:${toString config.emile.ports.miniflux}";
+			BASE_URL = "https://miniflux.emile.space";
+
+			# Cleanup job frequency to remove old sessions and archive entries.
+		  CLEANUP_FREQUENCY = 48;
+
+			# Set to 1 to enable maintenance mode. Maintenance mode disables the web ui and show a text message to the users.
+			# MAINTENANCE_MODE = 1;
+			# MAINTENANCE_MESSAGE = "updating foo";
+			
+			# DISABLE_LOCAL_AUTH = "true";
+			# OAUTH2_CLIENT_ID = "miniflux";
+			# OAUTH2_USER_CREATION = 1;
+			# OAUTH2_CLIENT_SECRET_FILE = config.age.secrets.miniflux_oidc_secret.path;
+			# OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://sso.emile.space";
+			# OAUTH2_OIDC_PROVIDER_NAME = "authelia";
+			# OAUTH2_PROVIDER = "oidc";
+			# OAUTH2_REDIRECT_URL = "https://miniflux.emile.space/oauth2/oidc/callback";
+			
+			LOG_LEVEL = "debug";
+		};
+		createDatabaseLocally = true;
+
+		# File containing the ADMIN_USERNAME and ADMIN_PASSWORD (length >= 6) in the format of an EnvironmentFile=, as described by systemd.exec(5).
+		adminCredentialsFile = config.age.secrets.miniflux_admin_file.path;
+	};
+}
diff --git a/nix/hosts/corrino/www/photo/immich.nix b/nix/hosts/corrino/www/photo/immich.nix
index 92a3a64..3e1bf48 100644
--- a/nix/hosts/corrino/www/photo/immich.nix
+++ b/nix/hosts/corrino/www/photo/immich.nix
@@ -6,6 +6,15 @@
     forceSSL = true;
     enableACME = true;
     locations = {
+      # # immich private proxy
+      # "/share" = {
+      #   proxyPass = "http://${config.services.immich.host}:${toString config.services.immich-public-proxy.port}";
+      # };
+      # "/share/*" = {
+      #   proxyPass = "http://${config.services.immich.host}:${toString config.services.immich-public-proxy.port}";
+      # };
+
+      # immich
       "/" = {
         proxyPass = "http://${config.services.immich.host}:${toString config.services.immich.port}";
         proxyWebsockets = true;
@@ -13,13 +22,17 @@
     };
   };
 
+  age.secrets.immich_oidc_client_secret.owner = "authelia-main";
+  age.secrets.immich_oidc_client_secret.group = "authelia-main";
+
   # auth via authelia
   services.authelia.instances.main.settings.identity_providers.oidc.clients = [
     {
-      id = "Immich";
+      client_id = "Immich";
 
       # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
-      secret = "$pbkdf2-sha512$310000$iCgyAKjoYH9UKADProvbgw$LjrYkX1MjjtSXWDkxDjyp3NkLLuLVvKVwy3o8/Rw.8Z8b6yCkPWdBCothuCMlaGcgfG/zLWM6lRV4BrXVZpkig";
+      client_secret = "{{ secret \"${config.age.secrets.immich_oidc_client_secret.path}\" }}";
+
       public = false;
       authorization_policy = "two_factor";
       redirect_uris = [
@@ -43,15 +56,14 @@
       #  "fragment"
       #];
 
-      token_endpoint_auth_method = "client_secret_basic";
+      # token_endpoint_auth_method = "client_secret_basic";
 
       # might be needed since the upgrade to nixos-24.11 and the resulting
       # 4.37.5 -> 4.38.17 upgrade
-      # token_endpoint_auth_method = "client_secret_post";
+      token_endpoint_auth_method = "client_secret_post";
     }
   ];
 
-
   services.immich = {
     enable = true;
     package = pkgs.immich;
@@ -59,7 +71,7 @@
     secretsFile = config.age.secrets.immich_secrets_file.path;
 
     host = "127.0.0.1";
-    port = config.emile.ports.immich;
+    port = config.emile.ports.photo.immich;
 
     machine-learning = {
       enable = false;
@@ -68,4 +80,19 @@
       };
     };
   };
+
+  # services.immich-public-proxy = {
+  #   enable = true;
+  #   package = pkgs.immich-public-proxy;
+  #   settings = {
+  #     downloadOriginalPhoto = true;
+  #     showGalleryTitle = true;
+  #     allowDownloadAll = 1;
+  #     showHomePage = true;
+  #     showMetadata = true;
+  #   };
+  #   port = config.emile.ports.photo.immich-public-proxy;
+  #   openFirewall = false;
+  #   immichUrl = "photo.emile.space";
+  # };
 }
diff --git a/nix/hosts/corrino/www/prometheus.emile.space.nix b/nix/hosts/corrino/www/prometheus.emile.space.nix
index 898f3b2..ec13dfa 100644
--- a/nix/hosts/corrino/www/prometheus.emile.space.nix
+++ b/nix/hosts/corrino/www/prometheus.emile.space.nix
@@ -38,15 +38,43 @@
           enable = true;
           port = config.emile.ports.prometheus.exporter.nginx;
         };
+        restic = {
+          enable = true;
+          # repository = "sftp:u331921@u331921.your-storagebox.de:/home/backup";
+          repository = "/mnt/storagebox-bx11/corrino";
+          port = config.emile.ports.prometheus.exporter.restic;
+          passwordFile = config.age.secrets.restic_password.path;
+        };
       };
       scrapeConfigs = [
         {
           job_name = "corrino";
           static_configs = [
-            { targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" ]; }
-            { targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.systemd.port}" ]; }
-            { targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.smartctl.port}" ]; }
-            { targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.nginx.port}" ]; }
+            {
+              targets = [
+                "127.0.0.1:${toString config.services.prometheus.exporters.node.port}"
+              ];
+            }
+            {
+              targets = [
+                "127.0.0.1:${toString config.services.prometheus.exporters.systemd.port}"
+              ];
+            }
+            {
+              targets = [
+                "127.0.0.1:${toString config.services.prometheus.exporters.smartctl.port}"
+              ];
+            }
+            {
+              targets = [
+                "127.0.0.1:${toString config.services.prometheus.exporters.nginx.port}"
+              ];
+            }
+            {
+              targets = [
+                "127.0.0.1:${toString config.services.prometheus.exporters.restic.port}"
+              ];
+            }
           ];
         }
         {
diff --git a/nix/hosts/corrino/www/promtail.emile.space.nix b/nix/hosts/corrino/www/promtail.emile.space.nix
deleted file mode 100644
index 654414c..0000000
--- a/nix/hosts/corrino/www/promtail.emile.space.nix
+++ /dev/null
@@ -1,114 +0,0 @@
-{ config, ... }:
-
-{
-  # allow the promtail user to read the nginx access files
-  users.users.promtail.extraGroups = [ "nginx" ];
-
-  services = {
-    promtail = {
-      enable = true;
-      configuration = {
-        server = {
-          http_listen_port = config.emile.ports.promtail;
-          grpc_listen_port = 0;
-        };
-        positions.filename = "/tmp/positions.yml";
-        clients = [{
-          url = "http://localhost:${toString config.services.loki.configuration.server.http_listen_port}/loki/api/v1/push";
-        }];
-        scrape_configs = [
-
-          # systemd
-          {
-            job_name = "journal";
-            journal = {
-              max_age = "12h";
-              labels = {
-                job = "systemd-journal";
-                host = config.networking.hostName;
-              };
-            };
-            relabel_configs = [
-              {
-                source_labels = [ "__journal__systemd_unit" ];
-                target_label = "unit";
-              }
-            ];
-          }
-
-          # nginx error log
-          {
-            job_name = "nginx-error-logs";
-            static_configs = [{
-              targets = [ "localhost" ];
-              labels = {
-                job = "nginx-error-logs";
-                host = "corrino";
-                __path__ = "/var/log/nginx/*error.log";
-              };
-            }];
-          }
-
-          # nginx
-          {
-            job_name = "nginx";
-            static_configs = [
-              {
-                targets = [ "localhost" ];
-                labels = {
-                  job = "nginx";
-                  host = "corrino";
-                  __path__ = "/var/log/nginx/*access.log";
-                };   
-              }
-            ];
-            pipeline_stages = [
-              # {
-              #   regex = {
-              #     expression = "(?:[0-9]{1,3}\.){3}([0-9]{1,3})";
-              #     replace = "***";
-              #   };
-              # }
-              {
-                regex = {
-                  expression = ''(?P<remote_addr>.+) - - \[(?P<time_local>.+)\] "(?P<method>.+) (?P<url>.+) (HTTP\/(?P<version>\d.\d))" (?P<status>\d{3}) (?P<body_bytes_sent>\d+) (["](?P<http_referer>(\-)|(.+))["]) (["](?P<http_user_agent>.+)["])'';
-                };
-              }
-              {
-                labels = {
-                  remote_addr = null;
-                  time_local = null;
-                  method = null;
-                  url = null;
-                  status = null;
-                  body_bytes_sent = null;
-                  http_referer = null;
-                  http_user_agent = null;
-                };
-              }
-              {
-                timestamp = {
-                  source = "time_local";
-                  format = "02/Jan/2006:15:04:05 -0700";
-                };
-              }
-              {
-                drop = {
-                  source = "url";
-                  expression = ''/(_matrix|.well-known|notifications|api|identity).*'';
-                };
-              }
-              {
-                drop = {
-                  source = "url";
-                  expression = ''grafana.*'';
-                };
-              }
-            ];
-          }
-
-        ];
-      };
-    };
-  };
-}
diff --git a/nix/hosts/corrino/www/s3.emile.space.nix b/nix/hosts/corrino/www/s3.emile.space.nix
index b4646ad..ae33542 100644
--- a/nix/hosts/corrino/www/s3.emile.space.nix
+++ b/nix/hosts/corrino/www/s3.emile.space.nix
@@ -1,12 +1,21 @@
-{ config, ... }:
+{ config, pkgs, ... }:
 
 {
+  security.acme.certs."s3.emile.space" = {
+    group = "nginx";
+    domain = "s3.emile.space";
+    extraDomainNames = [
+      "*.s3.emile.space"
+      "*.s3-web.emile.space"
+    ];
+  };
+
   services.nginx.virtualHosts."s3.emile.space" = {
     forceSSL = true;
     enableACME = true;
     locations = {
       "/" = {
-        proxyPass = "http://[::1]:${toString config.emile.ports.minio.s3}";
+        proxyPass = "http://[::1]:${toString config.emile.ports.garage.s3}";
       };
     };
   };
@@ -16,24 +25,96 @@
     enableACME = true;
     locations = {
       "/" = {
-        proxyPass = "http://[::1]:${toString config.emile.ports.minio.web}";
+        proxyPass = "http://[::1]:${toString config.emile.ports.garage.web}";
       };
     };
   };
 
-  services.minio = {
+  services.garage = {
     enable = true;
-    region = "eu-north-1-hel-1a"; # corrino is in the helsinki hetzner dc
+    package = pkgs.garage_1_x;
+    settings = {
+      data_dir = [
+        { capacity = "50G"; path = "/var/lib/garage/data"; }
+      ];
 
-    listenAddress = "[::1]:${toString config.emile.ports.minio.s3}";
+      db_engine = "sqlite";
+      replication_factor = 3;
 
-    browser = true;
-    consoleAddress = "[::1]:${toString config.emile.ports.minio.web}";
+      s3_api = {
+        s3_region = "garage";
+        api_bind_addr = "[::]:${toString config.emile.ports.garage.s3}";
+        root_domain = "s3.emile.space";
+      };
+      s3_web = {
+        bind_addr = "[::]:${toString config.emile.ports.garage.web}";
+        root_domain = "s3-web.emile.space";
+        index = "index.html";
+      };
+      admin = {
+        api_bind_addr = "[::]:${toString config.emile.ports.garage.admin}";
+        # metrics_token = config.age.secrets.garage_admin_metrics_secret.path;
+        # admin_token = config.age.secrets.garage_admin_token_secret.path;
+      };
 
-    dataDir = [ "/minio/data" ];
-    configDir = "/minio/config";
+      # rpc_secret_file = config.age.secrets.garage_rpc_secret.path;
+      rpc_bind_addr = "[::]:${toString config.emile.ports.garage.rpc}";
+      rpc_bind_outgoing = false;
+      rpc_public_addr = "[fc00:1::1]:${toString config.emile.ports.garage.rpc}";
+    };
 
-    rootCredentialsFile = config.age.secrets.minio_root_credz.path;
-    # accessKey
+    environmentFile = config.age.secrets.garage_env.path;
   };
+#         metrics_token = config.age.secrets.garage_admin_metrics_secret.path;
+#         admin_token = config.age.secrets.garage_admin_token_secret.path;
+#       rpc_secret_file = config.age.secrets.garage_rpc_secret.path;
+
+# nix/hosts/corrino/secrets/garage_admin_metrics_secret.age
+# nix/hosts/corrino/secrets/garage_admin_token_secret.age  
+# nix/hosts/corrino/secrets/garage_admin_token.age         
+# nix/hosts/corrino/secrets/garage_metrics_token.age       
+# nix/hosts/corrino/secrets/garage_rpc_secret.age
+  
+  # services.garage = {
+  #   enable = true;
+  #   package = pkgs.garage_1_x;
+  #   settings = {
+  #     db_engine = "sqlite";
+  #     replication_factor = 2;
+
+  #     data_dir = [
+  #       { capacity = "50G"; path = dataDir; }
+  #     ];
+
+  #     compression_level = 1;
+
+  #     rpc_secret_file = config.age.secrets.garage_rpc_secret.path;
+  #     rpc_bind_addr = "[::]:${toString config.emile.ports.garage.rpc}";
+  #     rpc_bind_outgoing = false;
+  #     rpc_public_addr = "[fc00:1::1]:${toString config.emile.ports.garage.rpc}";
+
+  #     allow_world_readable_secrets = false;
+
+  #     s3_api = {
+  #       api_bind_addr = "[::]:${toString config.emile.ports.garage.s3}";
+  #       s3_region = "garage";
+  #       root_domain = "s3.emile.space";
+  #     };
+
+  #     s3_web = {
+  #       bind_addr = "[::]:${toString config.emile.ports.garage.web}";
+  #       root_domain = "s3-web.emile.space";
+  #       add_host_to_metrics = true;
+  #     };
+
+  #     admin = {
+  #       api_bind_addr = "[::]:${toString config.emile.ports.garage.admin}";
+  #       metrics_token = config.age.secrets.garage_admin_metrics_secret.path;
+  #       admin_token = config.age.secrets.garage_admin_token_secret.path;
+  #       trace_sink = "http://localhost:4317";
+  #     };
+
+  #   };
+  #   logLevel = "trace"; # info
+  # };
 }
diff --git a/nix/hosts/corrino/www/social.emile.space.nix b/nix/hosts/corrino/www/social.emile.space.nix
index 210f0be..d9d30f7 100644
--- a/nix/hosts/corrino/www/social.emile.space.nix
+++ b/nix/hosts/corrino/www/social.emile.space.nix
@@ -38,13 +38,17 @@
     };
   };
 
+  age.secrets.gotosocial_oidc_client_secret.owner = "authelia-main";
+  age.secrets.gotosocial_oidc_client_secret.group = "authelia-main";
+  
   # auth via authelia
   services.authelia.instances.main.settings.identity_providers.oidc.clients = [
     {
-      id = "gotosocial";
+      client_id = "gotosocial";
 
       # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
-      secret = "$pbkdf2-sha512$310000$oDpZ5FuO965TbjPoophJXw$dbkAwWFvLN1h1Zh9US2ZOE5ilPRdEHMdGF/x0uorou2UqURrXF0KQmXxsV38F2yYMS7u/ecramKlvfMwsqHOcg";
+      client_secret = "{{ secret \"${config.age.secrets.gotosocial_oidc_client_secret.path}\" }}";
+
       public = false;
       authorization_policy = "two_factor";
       redirect_uris = [ "https://social.emile.space/auth/callback" ];
@@ -93,4 +97,21 @@
       Restart = "on-failure";
     };
   };
+
+  services.restic.backups."corrino" = {
+    paths = [ "/var/lib/gotosocial" ];
+  };
+
+  services.restic.backups."gotosocial" = {
+    repository = "/mnt/storagebox-bx11/gotosocial";
+    paths = [ "/var/lib/gotosocial" ];
+    passwordFile = config.age.secrets.restic_password.path;
+    initialize = true;
+    pruneOpts = [
+      "--keep-daily 7"
+      "--keep-weekly 5"
+      "--keep-monthly 12"
+      "--keep-yearly 75"
+    ];
+  };
 }
diff --git a/nix/hosts/corrino/www/sso.emile.space.nix b/nix/hosts/corrino/www/sso.emile.space.nix
index 2596bbe..6ffff80 100644
--- a/nix/hosts/corrino/www/sso.emile.space.nix
+++ b/nix/hosts/corrino/www/sso.emile.space.nix
@@ -116,9 +116,9 @@ in
         theme = "dark";
 
         server = {
-          # address = "127.0.0.1:${toString config.emile.ports.authelia}";
-          host = "127.0.0.1";
-          port = config.emile.ports.authelia;
+          address = "127.0.0.1:${toString config.emile.ports.authelia}";
+          # host = "127.0.0.1";
+          # port = config.emile.ports.authelia;
         };
 
         # we're using a file to store the user information
@@ -141,9 +141,22 @@ in
         storage.local.path = "/var/lib/authelia-main/db.sqlite";
 
         session = {
-          domain = "sso.emile.space";
-          expiration = 3600; # 1 hour
-          inactivity = 300; # 5 minutes
+          # domain = "sso.emile.space";
+          # expiration = 3600; # 1 hour
+          # inactivity = 300; # 5 minutes
+
+          cookies = [
+            {
+              domain = "emile.space";
+              authelia_url = "https://sso.emile.space";
+              # The period of time the user can be inactive for until the session is destroyed. Useful if you want long session timers but don’t want unused devices to be vulnerable.
+              inactivity = "1h";
+              # The period of time before the cookie expires and the session is destroyed. This is overridden by remember_me when the remember me box is checked.
+              expiration = "1d";
+              # The period of time before the cookie expires and the session is destroyed when the remember me box is checked. Setting this to -1 disables this feature entirely for this session cookie domain
+              remember_me = "3M";
+            }
+          ];
         };
 
         notifier = {
@@ -196,6 +209,16 @@ in
           default_policy = "deny";
           rules = [
             {
+              # silverbullet needs access to these without auth
+              domain = "sb.emile.space";
+              policy = "bypass";
+              resources = [
+                "/.client/manifest.json$"
+                "/.client/[a-zA-Z0-9_-]+.png$"
+                "/service_worker.js$"
+              ];
+            }
+            {
               domain = "*.emile.space";
               policy = "two_factor";
             }
diff --git a/nix/hosts/corrino/www/tickets.emile.space.nix b/nix/hosts/corrino/www/tickets.emile.space.nix
index fb12961..08f23d3 100644
--- a/nix/hosts/corrino/www/tickets.emile.space.nix
+++ b/nix/hosts/corrino/www/tickets.emile.space.nix
@@ -18,7 +18,7 @@
       enable = true;
       package = pkgs.pretix;
       plugins = with config.services.pretix.package.plugins; [
-        passbook
+        # passbook
         pages
       ];
       user = "pretix";
diff --git a/nix/hosts/hacknix/burpsuitepro/default.nix b/nix/hosts/hacknix/burpsuitepro/default.nix
index 8c9605d..a2b76b7 100644
--- a/nix/hosts/hacknix/burpsuitepro/default.nix
+++ b/nix/hosts/hacknix/burpsuitepro/default.nix
@@ -19,7 +19,7 @@ pkgs.stdenvNoCC.mkDerivation rec {
     eval "$(${pkgs.unzip}/bin/unzip -p ${src} chromium.properties)"
     mkdir -p "$HOME/.BurpSuite/burpbrowser/$linux64"
     ln -sf "${pkgs.chromium}/bin/chromium" "$HOME/.BurpSuite/burpbrowser/$linux64/chrome"
-    exec ${pkgs.jdk19}/bin/java -jar ${src} "$@"' > $out/bin/burpsuitepro
+    exec ${pkgs.jdk23}/bin/java -jar ${src} "$@"' > $out/bin/burpsuitepro
     chmod +x $out/bin/${pname}
     runHook postInstall
   '';
@@ -38,7 +38,7 @@ pkgs.stdenvNoCC.mkDerivation rec {
     downloadPage = "https://portswigger.net/burp/freedownload";
     sourceProvenance = with sourceTypes; [ binaryBytecode ];
     #license = licenses.unfree;
-    platforms = pkgs.jdk19.meta.platforms;
+    platforms = pkgs.jdk23.meta.platforms;
     hydraPlatforms = [ ];
     maintainers = with maintainers; [ hanemile ];
   };
diff --git a/nix/hosts/hacknix/configuration.nix b/nix/hosts/hacknix/configuration.nix
index 388626c..85a93af 100644
--- a/nix/hosts/hacknix/configuration.nix
+++ b/nix/hosts/hacknix/configuration.nix
@@ -47,12 +47,15 @@ in
 
   services = {
     dbus.enable = true;
+
+    displayManager.defaultSession = "xfce+i3";
+
     xserver = {
       enable = true;
 
       # Keyboard settings
-      layout = "us";
-      xkbOptions = "caps:compose";
+      xkb.layout = "us";
+      xkb.options = "caps:compose";
 
       desktopManager = {
         xterm.enable = false;
@@ -68,7 +71,6 @@ in
 
       # default display manager when logging in
       displayManager = {
-        defaultSession = "xfce+i3";
         sessionCommands = '''';
       };
 
@@ -92,7 +94,7 @@ in
   # Enable sound.
   # sound.enable = true;
   # hardware.pulseaudio.enable = true;
-  hardware.opengl.enable = true;
+  hardware.graphics.enable = true;
 
   # Enable touchpad support (enabled default in most desktopManager).
   # services.xserver.libinput.enable = true;
@@ -252,7 +254,10 @@ in
   # started in user sessions.
   programs = {
 
-    vim.defaultEditor = true;
+    vim = {
+      enable = true;
+      defaultEditor = true;
+    };
 
     htop = {
       enable = true;
diff --git a/nix/hosts/lampadas/configuration.nix b/nix/hosts/lampadas/configuration.nix
index cc829d8..d2630a8 100644
--- a/nix/hosts/lampadas/configuration.nix
+++ b/nix/hosts/lampadas/configuration.nix
@@ -2,7 +2,7 @@
 # your system. Help is available in the configuration.nix(5) man page, on
 # https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
 
-{ pkgs, lib, ... }:
+{ config, pkgs, lib, ... }:
 
 let
   emile_keys = [
@@ -17,12 +17,34 @@ in
     ./hardware-configuration.nix
   ];
 
+  hardware.fancontrol = {
+    enable = true;
+    config = ''
+      # Configuration file generated by pwmconfig, changes will be lost
+      INTERVAL=10
+      DEVPATH=hwmon0=devices/platform/coretemp.0 hwmon1=devices/platform/nct6775.672
+      DEVNAME=hwmon0=coretemp hwmon1=nct6798
+      FCTEMPS=hwmon1/pwm3=hwmon0/temp2_input hwmon1/pwm2=hwmon1/temp2_input
+      FCFANS=hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm2=hwmon1/fan2_input
+      MINTEMP=hwmon1/pwm3=35 hwmon1/pwm2=35
+      MAXTEMP=hwmon1/pwm3=75 hwmon1/pwm2=75
+      MINSTART=hwmon1/pwm3=255 hwmon1/pwm2=255
+      MINSTOP=hwmon1/pwm3=30 hwmon1/pwm2=30
+      MINPWM=hwmon1/pwm3=30 hwmon1/pwm2=30
+      MAXPWM=hwmon1/pwm3=255 hwmon1/pwm2=255
+    '';
+  };
+
   boot = {
     loader = {
       systemd-boot.enable = true;
       efi.canTouchEfiVariables = true;
     };
     kernelParams = [ "ip=dhcp" ];
+    kernelModules = [
+      # fan speed modules, detected using `sensors-detect`
+      "coretemp" "nct6775"
+    ];
     initrd = {
       availableKernelModules = [ "r8169" ];
       systemd.users.root.shell = "/bin/cryptsetup-askpass";
@@ -159,10 +181,41 @@ in
     };
 
     # metric exporters
-    prometheus.exporters = {
-      node.enable = true; # port 9100
-      systemd.enable = true; # port 9558
-      smartctl.enable = true; # port 9633
+    prometheus = {
+      enable = true;
+      port = 9090;
+      listenAddress = "100.87.209.97";
+      scrapeConfigs = [
+        {
+          job_name = "node";
+          static_configs = [{
+            targets = [
+              "localhost:${toString config.services.prometheus.exporters.node.port}"
+            ];
+          }];
+        }  
+        {
+          job_name = "systemd";
+          static_configs = [{
+            targets = [
+              "localhost:${toString config.services.prometheus.exporters.systemd.port}"
+            ];
+          }];
+        }  
+        {
+          job_name = "smartctl";
+          static_configs = [{
+            targets = [
+              "localhost:${toString config.services.prometheus.exporters.smartctl.port}"
+            ];
+          }];
+        }  
+      ];
+      exporters = {
+        node.enable = true; # port 9100
+        systemd.enable = true; # port 9558
+        smartctl.enable = true; # port 9633
+      };
     };
 
     # shares
@@ -177,7 +230,6 @@ in
       openFirewall = true;
       settings = {
         global = {
-
           ## Browsing/Identification ###
           "workgroup" = "Pacific";
           "server string" = "lampadas";
@@ -269,18 +321,6 @@ in
           "force user" = "emile";
           "guest ok" = "no";
           "read only" = "no";
-
-          # "fruit:aapl" = "yes";
-          # "fruit:copyfile" = "yes";
-          # "fruit:delete_empty_adfiles" = "yes";
-          # "fruit:metadata" = "stream";
-          # "fruit:posix_rename" = "yes";
-          # "fruit:time machine" = "yes";
-          # "fruit:veto_appledouble" = "no";
-          # "fruit:wipe_intentionally_left_blank_rfork" = "yes";
-          # "fruit:nfs_aces" = "no";
-          # "fruit:zero_file_id" = "yes";
-          # "fruit:encoding" = "native";
         };
 
         public = {
diff --git a/nix/hosts/lernaeus/configuration.nix b/nix/hosts/lernaeus/configuration.nix
index 57cacb9..43297a2 100644
--- a/nix/hosts/lernaeus/configuration.nix
+++ b/nix/hosts/lernaeus/configuration.nix
@@ -20,13 +20,6 @@ in
     ./hardware-configuration.nix
   ];
 
-  ##################
-  # sound
-
-  sound.enable = true;
-
-  hardware.pulseaudio.enable = true;
-  hardware.pulseaudio.support32Bit = true;    ## If compatibility with 32-bit applications is desired.
 
   users.extraUsers.emile.extraGroups = [ "audio" ];
 
@@ -39,11 +32,8 @@ in
   };
 
   # Enable OpenGL
-  hardware.opengl = {
-    enable = true;
-    driSupport = true;
-    driSupport32Bit = true;
-  };
+  hardware.graphics.enable = true;
+  hardware.graphics.enable32Bit = true;
 
   # Load nvidia driver for Xorg and Wayland
   services.xserver.videoDrivers = [ "nvidia" ];
diff --git a/nix/hosts/mail/mail.nix b/nix/hosts/mail/mail.nix
index 9c15e66..2dbfc35 100644
--- a/nix/hosts/mail/mail.nix
+++ b/nix/hosts/mail/mail.nix
@@ -1,17 +1,27 @@
-{ ... }:
+{ config, pkgs, ... }:
 let
-  release = "nixos-23.05";
-in
-{
+  #release = "nixos-21.11";
+  # release = "nixos-23.05";
+  # release = "nixos-24.05";
+  release = "nixos-24.11";
+in {
   imports = [
     (builtins.fetchTarball {
       # Pick a commit from the branch you are interested in
       url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz";
       # And set its hash
-      sha256 = "1ngil2shzkf61qxiqw11awyl81cr7ks2kv3r3k243zz7v2xakm5c";
+      #sha256 = "1i56llz037x416bw698v8j6arvv622qc0vsycd20lx3yx8n77n44";
+      #sha256 = "1ngil2shzkf61qxiqw11awyl81cr7ks2kv3r3k243zz7v2xakm5c";
+      #sha256 = "0000000000000000000000000000000000000000000000000000";
+      sha256 = "05k4nj2cqz1c5zgqa0c6b8sp3807ps385qca74fgs6cdc415y3qw";
     })
   ];
 
+  # temporary fix for the issue linked below that showed up after updating to
+  # nixos-24.05 and the nixos-24.05 release
+  # https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/275
+  services.dovecot2.sieve.extensions = [ "fileinto" ];
+
   mailserver = {
     enable = true;
     fqdn = "mail.emile.space";
@@ -20,10 +30,10 @@ in
     # A list of all login accounts. To create the password hashes, use
     # nix run nixpkgs.apacheHttpd -c htpasswd -nbB "" "super secret password" | cut -d: -f2
     loginAccounts = {
-      "mail@emile.space" = {
-        hashedPasswordFile = "/etc/nixos/keys/mail";
-        aliases = [ "@emile.space" ];
-      };
+        "mail@emile.space" = {
+            hashedPasswordFile = "/etc/nixos/keys/mail";
+            aliases = ["@emile.space"];
+        };
     };
 
     localDnsResolver = false;
@@ -33,12 +43,12 @@ in
     #certificateScheme = 3;
     certificateScheme = "acme-nginx";
 
+
     # Enable IMAP and POP3
     enableImap = true;
     enablePop3 = true;
     enableSubmission = true;
 
-    # as well with ssl
     enableImapSsl = true;
     enablePop3Ssl = true;
     enableSubmissionSsl = true;
@@ -46,6 +56,5 @@ in
     enableManageSieve = true;
 
     virusScanning = false;
-
   };
 }