aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--home-manager/browser/default.nix75
-rw-r--r--home-manager/default.nix61
-rw-r--r--home-manager/dotfiles/default.nix32
-rw-r--r--home-manager/git/default.nix15
-rw-r--r--home-manager/gnupg/default.nix9
-rw-r--r--home-manager/gtk/default.nix33
-rw-r--r--home-manager/kanshi/default.nix6
-rw-r--r--home-manager/ssh-agent/default.nix34
-rw-r--r--home-manager/waybar/default.nix6
-rw-r--r--home-manager/xdg/default.nix42
-rw-r--r--home-manager/zsh/default.nix125
-rw-r--r--hosts/pad/boot.nix16
-rw-r--r--hosts/pad/default.nix34
-rw-r--r--hosts/pad/hardware-configuration.nix43
-rw-r--r--hosts/pad/hardware.nix5
-rw-r--r--hosts/pad/network.nix53
-rw-r--r--hosts/station/boot.nix20
-rw-r--r--hosts/station/default.nix34
-rw-r--r--hosts/station/hardware-configuration.nix43
-rw-r--r--hosts/station/hardware.nix11
-rw-r--r--hosts/station/network.nix55
-rw-r--r--modules/client/1password/default.nix22
-rw-r--r--modules/client/default.nix8
-rw-r--r--modules/client/flatpak/default.nix49
-rw-r--r--modules/client/labwc/default.nix40
-rw-r--r--modules/client/thunar/default.nix24
-rw-r--r--modules/common/adguard/default.nix106
-rw-r--r--modules/common/default.nix45
-rw-r--r--modules/common/fonts/default.nix12
-rw-r--r--modules/common/gnupg/default.nix5
-rw-r--r--modules/common/i18n/default.nix20
-rw-r--r--modules/common/nh/default.nix9
-rw-r--r--modules/common/pipewire/default.nix12
-rw-r--r--modules/common/searx/default.nix115
-rw-r--r--modules/common/ssh/default.nix5
-rw-r--r--modules/common/users/default.nix20
-rw-r--r--modules/common/xserver/default.nix9
-rw-r--r--modules/server/calibre/default.nix39
-rw-r--r--modules/server/cgit/default.nix76
-rw-r--r--modules/server/cgit/static/cgit.css1346
-rwxr-xr-xmodules/server/cgit/static/favicon.pngbin0 -> 2535629 bytes
-rwxr-xr-xmodules/server/cgit/static/logo.pngbin0 -> 2535629 bytes
-rw-r--r--modules/server/default.nix53
-rw-r--r--modules/server/forgejo/default.nix42
-rw-r--r--modules/server/gemini/default.nix57
-rw-r--r--modules/server/grafana/default.nix23
-rw-r--r--modules/server/immich/default.nix28
-rw-r--r--modules/server/jellyfin/default.nix27
-rw-r--r--modules/server/ollama/default.nix69
49 files changed, 3013 insertions, 0 deletions
diff --git a/home-manager/browser/default.nix b/home-manager/browser/default.nix
new file mode 100644
index 0000000..ab8278a
--- /dev/null
+++ b/home-manager/browser/default.nix
@@ -0,0 +1,75 @@
+{ config, pkgs, inputs, ... }:
+{
+ imports = [
+ inputs.zen-browser.homeModules.beta
+ ];
+
+ programs.zen-browser = {
+ enable = true;
+
+ nativeMessagingHosts = [pkgs.firefoxpwa];
+ policies = {
+ # find more options here: https://mozilla.github.io/policy-templates/
+ AutofillAddressEnabled = false;
+ AutofillCreditCardEnabled = false;
+
+ Cookies = {
+ Locked = true;
+ Behavior = "reject-foreign";
+ BehaviorPrivateBrowsing = "reject";
+ };
+
+ DisablePocket = true;
+ DisableAppUpdate = true;
+ DisableFirefoxStudies = true;
+ DisableFirefoxAccounts = true;
+ DisableFeedbackCommands = true;
+ DisableTelemetry = true;
+
+ DontCheckDefaultBrowser = true;
+
+ DownloadDirectory = "${config.home.homeDirectory}/downloads";
+
+ EnableTrackingProtection = {
+ Value = true;
+ Locked = true;
+ Cryptomining = true;
+ Fingerprinting = true;
+ };
+
+ HardwareAcceleration = true;
+
+ HttpsOnlyMode = "force_enabled";
+
+ NoDefaultBookmarks = true;
+
+ OfferToSaveLogins = false;
+
+ PasswordManagerEnabled = false;
+
+ PopupBlocking = {
+ Default = false;
+ Locked = true;
+ };
+
+ PostQuantumKeyAgreementEnabled = false;
+
+ SanitizeOnShutdown = {
+ Cache = true;
+ Cookies = false;
+ FormData = true;
+ History = false;
+ Sessions = false;
+ SiteSettings = true;
+ };
+
+ SearchEngines = {
+ Default = "Startpage";
+ Remove = [
+ "Google"
+ "Bing"
+ ];
+ };
+ };
+ };
+}
diff --git a/home-manager/default.nix b/home-manager/default.nix
new file mode 100644
index 0000000..78d085f
--- /dev/null
+++ b/home-manager/default.nix
@@ -0,0 +1,61 @@
+{ pkgs, system, inputs, ...}:
+{
+ imports = [
+ ./browser
+ ./dotfiles
+ ./git
+ ./gnupg
+ ./gtk
+ ./kanshi
+ ./ssh-agent
+ # ./waybar
+ ./xdg
+ ./zsh
+ ];
+
+ home = {
+ username = "aethrvmn";
+ homeDirectory = "/home/aethrvmn";
+
+ # DO NOT TOUCH THIS
+ stateVersion = "24.11";
+
+ packages = with pkgs; [
+ bat
+ bemenu
+ btop
+ chayang
+ electrum
+ eza
+ faircamp
+ fastfetch
+ featherpad
+ feishin
+ ghostty
+ gitui
+ grim
+ hugo
+ imv
+ j4-dmenu-desktop
+ mako
+ marksman
+ monero-gui
+ mpv
+ pavucontrol
+ slurp
+ swappy
+ wbg
+ wlr-randr
+
+ inputs.waybar.packages."${system}".default
+ ];
+
+ pointerCursor = {
+ gtk.enable = true;
+ x11.enable = true;
+ name = "Qogir";
+ package = pkgs.qogir-icon-theme;
+ size = 24;
+ };
+ };
+}
diff --git a/home-manager/dotfiles/default.nix b/home-manager/dotfiles/default.nix
new file mode 100644
index 0000000..875c110
--- /dev/null
+++ b/home-manager/dotfiles/default.nix
@@ -0,0 +1,32 @@
+{ config, pkgs, ... }:
+ let
+ ghosttyPath = "${config.home.homeDirectory}/.nix/dotfiles/ghostty";
+ helixPath = "${config.home.homeDirectory}/.nix/dotfiles/helix";
+ labwcPath = "${config.home.homeDirectory}/.nix/dotfiles/labwc";
+ makoPath = "${config.home.homeDirectory}/.nix/dotfiles/mako";
+ swappyPath = "${config.home.homeDirectory}/.nix/dotfiles/swappy";
+ waybarPath = "${config.home.homeDirectory}/.nix/dotfiles/waybar";
+
+ # theming
+ themesPath = "${config.home.homeDirectory}/.nix/dotfiles/themes";
+ fontPath = "${config.home.homeDirectory}/.nix/dotfiles/fonts";
+ in {
+ xdg = {
+ configFile = {
+ # configFile points to ~/.config
+ "ghostty".source = config.lib.file.mkOutOfStoreSymlink ghosttyPath;
+ "helix".source = config.lib.file.mkOutOfStoreSymlink helixPath;
+ "labwc".source = config.lib.file.mkOutOfStoreSymlink labwcPath;
+ "mako".source = config.lib.file.mkOutOfStoreSymlink makoPath;
+ "swappy".source = config.lib.file.mkOutOfStoreSymlink swappyPath;
+ "waybar".source = config.lib.file.mkOutOfStoreSymlink waybarPath;
+ };
+
+ dataFile = {
+ # dataFile points to ~/.local/share
+ "themes".source = config.lib.file.mkOutOfStoreSymlink themesPath;
+ "fonts".source = config.lib.file.mkOutOfStoreSymlink fontPath;
+ };
+ };
+ }
+
diff --git a/home-manager/git/default.nix b/home-manager/git/default.nix
new file mode 100644
index 0000000..dac2b35
--- /dev/null
+++ b/home-manager/git/default.nix
@@ -0,0 +1,15 @@
+{ config, pkgs, ... }:
+
+{
+ programs.git = {
+ enable = true;
+
+ userName = "aethrvmn";
+ userEmail = "me@aethrvmn.gr";
+
+ signing = {
+ key = "2DEC 190B 26C6 188E 5951 66AA 0F0C D756 AA91 0DB6";
+ signByDefault = true;
+ };
+ };
+}
diff --git a/home-manager/gnupg/default.nix b/home-manager/gnupg/default.nix
new file mode 100644
index 0000000..c415bca
--- /dev/null
+++ b/home-manager/gnupg/default.nix
@@ -0,0 +1,9 @@
+{
+ programs.gpg = {
+ enable = true;
+
+ settings = {
+ default-key = "2DEC 190B 26C6 188E 5951 66AA 0F0C D756 AA91 0DB6";
+ };
+ };
+}
diff --git a/home-manager/gtk/default.nix b/home-manager/gtk/default.nix
new file mode 100644
index 0000000..fceae3f
--- /dev/null
+++ b/home-manager/gtk/default.nix
@@ -0,0 +1,33 @@
+{ config, pkgs, ... }:
+{
+ dconf = {
+ enable = true;
+ settings = {
+ "org/gnome/desktop/interface" = {
+ color-scheme = "prefer-dark";
+ };
+ };
+ };
+
+ gtk = {
+ enable = true;
+
+ theme = {
+ name = "Qogir";
+ package = pkgs.qogir-theme;
+ };
+
+ iconTheme = {
+ name = "Qogir";
+ package = pkgs.qogir-icon-theme;
+ };
+
+ gtk3.extraConfig = {
+ gtk-application-prefer-dark-theme = 1;
+ };
+
+ gtk4.extraConfig = {
+ gtk-application-prefer-dark-theme = 1;
+ };
+ };
+}
diff --git a/home-manager/kanshi/default.nix b/home-manager/kanshi/default.nix
new file mode 100644
index 0000000..a6ffb0d
--- /dev/null
+++ b/home-manager/kanshi/default.nix
@@ -0,0 +1,6 @@
+{
+ services.kanshi = {
+ enable = true;
+ };
+}
+
diff --git a/home-manager/ssh-agent/default.nix b/home-manager/ssh-agent/default.nix
new file mode 100644
index 0000000..ae22c8f
--- /dev/null
+++ b/home-manager/ssh-agent/default.nix
@@ -0,0 +1,34 @@
+{
+ programs.ssh = {
+ enable = true;
+ addKeysToAgent = "yes";
+
+ extraConfig = ''
+ IdentitiesOnly yes
+ '';
+
+ matchBlocks = {
+ "aethrvmn.gr" = {
+ hostname = "aethrvmn.gr";
+ identityFile = "~/.ssh/connections";
+ };
+
+ "apo.theke.ml" = {
+ hostname = "apo.theke.ml";
+ user = "git";
+ port = 222;
+ identityFile = "~/.ssh/theke";
+ };
+
+ "code.aethrvmn.gr" = {
+ hostname = "code.aethrvmn.gr";
+ identityFile = "~/.ssh/commits";
+ };
+
+ "velor.gr" = {
+ hostname = "velor.gr";
+ identityFile = "~/.ssh/velor";
+ };
+ };
+ };
+}
diff --git a/home-manager/waybar/default.nix b/home-manager/waybar/default.nix
new file mode 100644
index 0000000..9457d06
--- /dev/null
+++ b/home-manager/waybar/default.nix
@@ -0,0 +1,6 @@
+{ config, pkgs, ...}:
+# {
+# programs.waybar = {
+# enable = true;
+# };
+# }
diff --git a/home-manager/xdg/default.nix b/home-manager/xdg/default.nix
new file mode 100644
index 0000000..55dde61
--- /dev/null
+++ b/home-manager/xdg/default.nix
@@ -0,0 +1,42 @@
+{
+ xdg = {
+ enable = true;
+ mimeApps = {
+ enable = true; # manage ~/.config/mimeapps.list
+
+ defaultApplications = {
+ "application/pdf" = [ "zen" ];
+ "x-scheme-handler/http" = [ "zen" ];
+ "x-scheme-handler/https" = [ "zen" ];
+ "x-scheme-handler/chrome" = [ "zen" ];
+
+ "text/html" = [ "featherpad.desktop" ];
+
+ "x-scheme-handler/discord" = [ "io.github.equicord.equibop.desktop" ];
+
+ "x-scheme-handler/tg" = [ "org.telegram.desktop.desktop" ];
+ "x-scheme-handler/tonsite" = [ "org.telegram.desktop.desktop" ];
+
+ "message/rfc822" = [ "eu.betterbird.Betterbird.desktop" ];
+ "x-scheme-handler/mailto" = [ "eu.betterbird.Betterbird.desktop" ];
+ "x-scheme-handler/mid" = [ "eu.betterbird.Betterbird.desktop" ];
+ "x-scheme-handler/feed" = [ "eu.betterbird.Betterbird.desktop" ];
+ "x-scheme-handler/webcal" = [ "eu.betterbird.Betterbird.desktop" ];
+ "x-scheme-handler/webcals" = [ "eu.betterbird.Betterbird.desktop" ];
+
+ "image/png" = [ "imv-dir.desktop" ];
+ "image/jpeg" = [ "imv-dir.desktop" ];
+ "image/svg+xml" = [ "featherpad.desktop" ];
+
+ "application/pgp-keys" = [ "com.bktus.gpgfrontend" ];
+ "application/octet-stream" = [ "org.gnome.FileRoller.desktop" ];
+ };
+
+ # Optional extra handlers that *don’t* become default
+ associations.added = {
+ "text/html" = [ "zen" ];
+ "application/pdf" = [ "zen" ];
+ };
+ };
+ };
+}
diff --git a/home-manager/zsh/default.nix b/home-manager/zsh/default.nix
new file mode 100644
index 0000000..d713873
--- /dev/null
+++ b/home-manager/zsh/default.nix
@@ -0,0 +1,125 @@
+{ config, pkgs, lib, ... }: let
+ nixosScript = ''
+ nixos() {
+ case $1 in
+ update | up)
+ if [ "$#" -gt 1 ]; then
+ echo "Error: 'nixos update' takes no additional arguments."
+ return 1
+ fi
+ nh os switch $HOME/.nix --ask
+ ;;
+ upgrade)
+ if [ "$#" -gt 1 ]; then
+ echo "Error: 'nixos upgrade' takes no additional arguments."
+ return 1
+ fi
+ nh os switch $HOME/.nix -u --ask
+ ;;
+ clean)
+ nh clean all --verbose
+ ;;
+ config)
+ hx ~/.nix/"$2"
+ ;;
+ *)
+ echo "Usage: nixos update | up || nixos upgrade || nixos config <path>"
+ ;;
+ esac
+ }
+
+ nix() {
+ if [[ $1 == "develop" ]]; then
+ shift
+ local flake
+ case $1 in
+ python)
+ flake="$HOME/.nix#python"
+ shift
+ ;;
+ nim)
+ flake="$HOME/.nix#nim"
+ shift
+ ;;
+ js)
+ flake="$HOME/.nix#js"
+ shift
+ ;;
+ *)
+ flake="$1"
+ shift
+ ;;
+ esac
+ command nix develop "$flake" -c zsh
+ else
+ command nix "$@"
+ fi
+ }
+
+ _nixos_autocomplete() {
+ _arguments \
+ '1: :->subcmd' \
+ '2: :->files'
+
+ case $state in
+ subcmd)
+ local -a commands
+ commands=("update" "config")
+ _describe 'command' commands
+ ;;
+ files)
+ # Check if the subcommand is config.
+ if [[ $words[2] == "config" ]]; then
+ _files -W "$HOME/.nix" -g '*'
+ fi
+ ;;
+ esac
+ }
+
+ compdef _nixos_autocomplete nixos
+ '';
+in {
+ programs.zsh = {
+ enable = true;
+
+ autosuggestion.enable = true;
+ enableCompletion = true;
+ syntaxHighlighting.enable = true;
+
+ shellAliases = {
+ ls = "eza --icons=always --color=always";
+ ll = "eza -a --long --icons=always --color=always --no-time";
+ lt = "eza -a --long --tree --icons=always --color=always --no-time";
+
+ cat = "bat";
+ mk = "(){ mkdir -p $1 && cd $1 }";
+
+ grep = "grep --color=auto";
+
+ mv = "mv -i";
+ cp = "cp -i";
+ rm = "rm -i";
+
+ fetch = "fastfetch -c examples/7";
+
+ nix-shell = "nix-shell --run $SHELL";
+ };
+
+ initContent = ''
+ ${nixosScript};
+ eval "$(atuin init zsh)"
+ eval "$(starship init zsh)"
+ '';
+ };
+
+ programs = {
+ starship = {
+ enable = true;
+ };
+
+ atuin = {
+ enable = true;
+ enableZshIntegration = true;
+ };
+ };
+}
diff --git a/hosts/pad/boot.nix b/hosts/pad/boot.nix
new file mode 100644
index 0000000..a6108d6
--- /dev/null
+++ b/hosts/pad/boot.nix
@@ -0,0 +1,16 @@
+{ config, pkgs, ...}:
+
+{
+ boot = {
+ loader = {
+ systemd-boot = {
+ enable = true;
+ # Only keep the last 10 configurations
+ configurationLimit = 10;
+ };
+ efi.canTouchEfiVariables = true;
+ };
+
+ initrd.luks.devices."luks-11563c8c-1bf7-471f-a173-918f47aa31ed".device = "/dev/disk/by-uuid/11563c8c-1bf7-471f-a173-918f47aa31ed";
+ };
+}
diff --git a/hosts/pad/default.nix b/hosts/pad/default.nix
new file mode 100644
index 0000000..738e407
--- /dev/null
+++ b/hosts/pad/default.nix
@@ -0,0 +1,34 @@
+# Edit this configuration file to define what should be installed on
+# your system. Help is available in the configuration.nix(5) man page
+# and in the NixOS manual (accessible by running ‘nixos-help’).
+{ config, lib, pkgs, ... }:
+
+{
+ imports = [
+ # Include the results of the hardware scan.
+ ./hardware-configuration.nix
+
+ # Base modules
+ ./boot.nix
+ ./hardware.nix
+ ./network.nix
+ ];
+
+ system = {
+ autoUpgrade = {
+ enable = true;
+ flake = "/home/aethrvmn/.nix#pad";
+ };
+
+ # This value determines the NixOS release from which the default
+ # settings for stateful data, like file locations and database versions
+ # on your system were taken. It‘s perfectly fine and recommended to leave
+ # this value at the release version of the first install of this system.
+ # Before changing this value read the documentation for this option
+ # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
+ stateVersion = "24.11"; # Did you read the comment?
+ };
+
+ # Set time zone.
+ time.timeZone = "Europe/Brussels";
+}
diff --git a/hosts/pad/hardware-configuration.nix b/hosts/pad/hardware-configuration.nix
new file mode 100644
index 0000000..4345851
--- /dev/null
+++ b/hosts/pad/hardware-configuration.nix
@@ -0,0 +1,43 @@
+# Do not modify this file! It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations. Please make changes
+# to /etc/nixos/configuration.nix instead.
+{ config, lib, pkgs, modulesPath, ... }:
+
+{
+ imports =
+ [ (modulesPath + "/installer/scan/not-detected.nix")
+ ];
+
+ boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ata_piix" "usb_storage" "sd_mod" "sr_mod" "sdhci_pci" ];
+ boot.initrd.kernelModules = [ ];
+ boot.kernelModules = [ ];
+ boot.extraModulePackages = [ ];
+
+ fileSystems."/" =
+ { device = "/dev/disk/by-uuid/fe8e7c2d-ae75-4617-b26c-650377ce813e";
+ fsType = "ext4";
+ };
+
+ boot.initrd.luks.devices."luks-3462560d-86f8-4ddd-9f37-4d3f92846e1e".device = "/dev/disk/by-uuid/3462560d-86f8-4ddd-9f37-4d3f92846e1e";
+
+ fileSystems."/boot" =
+ { device = "/dev/disk/by-uuid/B370-4AFC";
+ fsType = "vfat";
+ options = [ "fmask=0077" "dmask=0077" ];
+ };
+
+ swapDevices =
+ [ { device = "/dev/disk/by-uuid/1d8ca4a9-b5aa-46d1-96f9-6be57c8a6fc6"; }
+ ];
+
+ # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+ # (the default) this is the recommended approach. When using systemd-networkd it's
+ # still possible to use this option, but it's recommended to use it in conjunction
+ # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+ networking.useDHCP = lib.mkDefault true;
+ # networking.interfaces.enp0s25.useDHCP = lib.mkDefault true;
+ # networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true;
+
+ nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+ hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
+}
diff --git a/hosts/pad/hardware.nix b/hosts/pad/hardware.nix
new file mode 100644
index 0000000..4c63dba
--- /dev/null
+++ b/hosts/pad/hardware.nix
@@ -0,0 +1,5 @@
+{
+ hardware.graphics = {
+ enable = true;
+ };
+}
diff --git a/hosts/pad/network.nix b/hosts/pad/network.nix
new file mode 100644
index 0000000..6831f92
--- /dev/null
+++ b/hosts/pad/network.nix
@@ -0,0 +1,53 @@
+{ config, pkgs, ... }:
+
+{
+ networking = {
+ hostName = "pad"; # Define your hostname.
+
+ # Enables wireless support via wpa_supplicant.
+ # wireless.enable = true;
+
+ # Configure network proxy if necessary
+ # proxy.default = "http://user:password@proxy:port/";
+ # proxy.noProxy = "127.0.0.1,localhost,internal.domain";
+
+ # Enable networking
+ networkmanager.enable = true;
+
+ wireguard = {
+ enable = true;
+
+ interfaces = {
+ rousi = {
+ ips = [
+ "10.0.0.4/24"
+ ];
+ listenPort = 51820;
+ privateKeyFile = "/home/aethrvmn/.creds/rousikey";
+
+ peers = [
+ {
+ allowedIPs = [
+ "192.168.10.0/24"
+ "172.16.0.0/24"
+ ];
+ publicKey = "LEeO3Qy6c3W0qoR1xFhl7Fx29Oppq8tKE72HPoA831I=";
+ endpoint = "vpn.valatsos.gr:51820";
+ persistentKeepalive = 25;
+ }
+ ];
+ };
+ };
+ };
+
+ # Open ports in the firewall.
+ firewall = {
+ ## 1313 is for HUGO
+ allowedTCPPorts = [ 1313 ];
+ ## 51820 is wg 53317 is localsend
+ allowedUDPPorts = [ 51820 53317 ];
+ };
+ # Or disable the firewall altogether.
+ # firewall.enable = false;
+ };
+}
diff --git a/hosts/station/boot.nix b/hosts/station/boot.nix
new file mode 100644
index 0000000..603ebf7
--- /dev/null
+++ b/hosts/station/boot.nix
@@ -0,0 +1,20 @@
+{ config, pkgs, ...}:
+
+{
+ boot = {
+ loader = {
+ systemd-boot = {
+ enable = true;
+ # Only keep the last 10 configurations
+ configurationLimit = 10;
+ };
+ efi.canTouchEfiVariables = true;
+ };
+
+ initrd = {
+ luks.devices."luks-4d8ffefc-fb74-4628-9779-abc535146374".device = "/dev/disk/by-uuid/4d8ffefc-fb74-4628-9779-abc535146374";
+
+ kernelModules = ["amdgpu"];
+ };
+ };
+}
diff --git a/hosts/station/default.nix b/hosts/station/default.nix
new file mode 100644
index 0000000..b57bcb1
--- /dev/null
+++ b/hosts/station/default.nix
@@ -0,0 +1,34 @@
+# Edit this configuration file to define what should be installed on
+# your system. Help is available in the configuration.nix(5) man page
+# and in the NixOS manual (accessible by running ‘nixos-help’).
+{ config, lib, pkgs, ... }:
+
+{
+ imports = [
+ # Include the results of the hardware scan.
+ ./hardware-configuration.nix
+
+ # Base modules
+ ./boot.nix
+ ./hardware.nix
+ ./network.nix
+ ];
+
+ system = {
+ autoUpgrade = {
+ enable = true;
+ flake = "/home/aethrvmn/.nix#nixstation";
+ };
+
+ # This value determines the NixOS release from which the default
+ # settings for stateful data, like file locations and database versions
+ # on your system were taken. It‘s perfectly fine and recommended to leave
+ # this value at the release version of the first install of this system.
+ # Before changing this value read the documentation for this option
+ # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
+ stateVersion = "24.11"; # Did you read the comment?
+ };
+
+ # Set time zone.
+ time.timeZone = "Europe/Brussels";
+}
diff --git a/hosts/station/hardware-configuration.nix b/hosts/station/hardware-configuration.nix
new file mode 100644
index 0000000..8c60298
--- /dev/null
+++ b/hosts/station/hardware-configuration.nix
@@ -0,0 +1,43 @@
+# Do not modify this file! It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations. Please make changes
+# to /etc/nixos/configuration.nix instead.
+{ config, lib, pkgs, modulesPath, ... }:
+
+{
+ imports =
+ [ (modulesPath + "/installer/scan/not-detected.nix")
+ ];
+
+ boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
+ boot.initrd.kernelModules = [ ];
+ boot.kernelModules = [ "kvm-amd" ];
+ boot.extraModulePackages = [ ];
+
+ fileSystems."/" =
+ { device = "/dev/disk/by-uuid/48ee999d-df45-49da-96dd-7bbb7682677d";
+ fsType = "ext4";
+ };
+
+ boot.initrd.luks.devices."luks-38168e30-5417-440d-b521-faaaf4ef9360".device = "/dev/disk/by-uuid/38168e30-5417-440d-b521-faaaf4ef9360";
+
+ fileSystems."/boot" =
+ { device = "/dev/disk/by-uuid/EDF1-9467";
+ fsType = "vfat";
+ options = [ "fmask=0077" "dmask=0077" ];
+ };
+
+ swapDevices =
+ [ { device = "/dev/disk/by-uuid/6b838eef-e44d-4aac-b29e-9c91e10b015b"; }
+ ];
+
+ # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+ # (the default) this is the recommended approach. When using systemd-networkd it's
+ # still possible to use this option, but it's recommended to use it in conjunction
+ # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+ networking.useDHCP = lib.mkDefault true;
+ # networking.interfaces.enp42s0.useDHCP = lib.mkDefault true;
+ # networking.interfaces.wlo1.useDHCP = lib.mkDefault true;
+
+ nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+ hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
+}
diff --git a/hosts/station/hardware.nix b/hosts/station/hardware.nix
new file mode 100644
index 0000000..8f84745
--- /dev/null
+++ b/hosts/station/hardware.nix
@@ -0,0 +1,11 @@
+{ config, pkgs, ... }:
+{
+ hardware = {
+ graphics = {
+ enable = true;
+ extraPackages = with pkgs; [
+ rocmPackages.clr
+ ];
+ };
+ };
+}
diff --git a/hosts/station/network.nix b/hosts/station/network.nix
new file mode 100644
index 0000000..c1b08ea
--- /dev/null
+++ b/hosts/station/network.nix
@@ -0,0 +1,55 @@
+{ config, pkgs, ... }:
+
+{
+ networking = {
+ hostName = "station"; # Define your hostname.
+
+ # Enables wireless support via wpa_supplicant.
+ # wireless.enable = true;
+
+ # Configure network proxy if necessary
+ # proxy.default = "http://user:password@proxy:port/";
+ # proxy.noProxy = "127.0.0.1,localhost,internal.domain";
+
+ # Enable networking
+ networkmanager.enable = true;
+
+ wireguard = {
+ enable = true;
+
+ interfaces = {
+ rousi = {
+ ips = [
+ "10.0.0.5/24"
+ ];
+ listenPort = 51820;
+ privateKeyFile = "/home/aethrvmn/.creds/rousikey";
+
+ peers = [
+ {
+ allowedIPs = [
+ "192.168.10.0/24"
+ "172.16.0.0/24"
+ ];
+ publicKey = "LEeO3Qy6c3W0qoR1xFhl7Fx29Oppq8tKE72HPoA831I=";
+ endpoint = "vpn.valatsos.gr:51820";
+ persistentKeepalive = 25;
+ }
+ ];
+ };
+ };
+ };
+
+ # Open ports in the firewall.
+ firewall ={
+ ## 1313 is HUGO
+ ## 2234 is nicotine
+ allowedTCPPorts = [ 1313 2234 ];
+ ## 51820 is wg
+ ## 53317 is localsend
+ allowedUDPPorts = [ 51820 53317 ];
+ };
+ # Or disable the firewall altogether.
+ # firewall.enable = false;
+ };
+}
diff --git a/modules/client/1password/default.nix b/modules/client/1password/default.nix
new file mode 100644
index 0000000..1d137d1
--- /dev/null
+++ b/modules/client/1password/default.nix
@@ -0,0 +1,22 @@
+{ config, pkgs, ... }:
+
+{
+ programs = {
+ _1password.enable = true;
+ _1password-gui = {
+ enable = true;
+ polkitPolicyOwners = [ "aethrvmn" ];
+ };
+ };
+
+ environment.etc ={
+ "1password/custom_allowed_browsers" = {
+ text = ''
+ firefox
+ zen
+ '';
+ mode = "0755";
+ };
+ };
+}
+
diff --git a/modules/client/default.nix b/modules/client/default.nix
new file mode 100644
index 0000000..0f189b1
--- /dev/null
+++ b/modules/client/default.nix
@@ -0,0 +1,8 @@
+{
+ imports = [
+ ./1password
+ ./flatpak
+ ./labwc
+ ./thunar
+ ];
+}
diff --git a/modules/client/flatpak/default.nix b/modules/client/flatpak/default.nix
new file mode 100644
index 0000000..63d5669
--- /dev/null
+++ b/modules/client/flatpak/default.nix
@@ -0,0 +1,49 @@
+{ pkgs, lib, ...}:
+{
+ # imports = [
+ # inputs.nix-flatpak.nixosModules.nix-flatpak
+ # ];
+
+ services.flatpak = {
+ enable = true;
+
+ remotes = [
+ {
+ name = "flathub";
+ location = "https://flathub.org/repo/flathub.flatpakrepo";
+ }
+ ];
+
+ packages = [
+ "eu.betterbird.Betterbird"
+ "io.github.equicord.equibop"
+ "com.github.tchx84.Flatseal"
+ "app.grayjay.Grayjay"
+ "fi.skyjake.Lagrange"
+ "org.localsend.localsend_app"
+ "net.lutris.Lutris"
+ "org.nicotine_plus.Nicotine"
+ "org.musicbrainz.Picard"
+ "com.obsproject.Studio"
+ "org.telegram.desktop"
+ "com.rtosta.zapzap"
+ ];
+
+ update.auto = {
+ enable = true;
+ onCalendar = "weekly"; # Default value
+ };
+
+ overrides = {
+ global = {
+ # Force Wayland by default
+ Context.sockets = [ "wayland" "!x11" "!fallback-x11" ];
+
+ Environment = {
+ # Fix un-themed cursor in some Wayland apps
+ XCURSOR_PATH = "/run/host/user-share/icons:/run/host/share/icons";
+ };
+ };
+ };
+ };
+}
diff --git a/modules/client/labwc/default.nix b/modules/client/labwc/default.nix
new file mode 100644
index 0000000..e0350f4
--- /dev/null
+++ b/modules/client/labwc/default.nix
@@ -0,0 +1,40 @@
+{ config, pkgs, ... }:
+# Set up a complete labwc instance system-side
+{
+ # Enable labwc
+ programs.labwc.enable = true;
+
+ # Enable XDG portals for wl-roots
+ xdg.portal = {
+ wlr.enable = true;
+ extraPortals = with pkgs; [
+ xdg-desktop-portal-gtk
+ ];
+ enable = true;
+ };
+
+ # Enable tuigreet
+ services = {
+ greetd = {
+ enable = true;
+ settings = {
+ default_session = {
+ command = "${pkgs.tuigreet}/bin/tuigreet --user-menu -rti --asterisks --cmd labwc";
+ user = "greeter";
+ };
+ };
+ };
+ };
+
+ # Hide stderror and bootlogs from filling tuigreet
+ systemd.services.greetd.serviceConfig = {
+ Type = "idle";
+ StandardInput = "tty";
+ StandardOutput = "ttu";
+ StandardError = "journal"; # logs erros to journal, preventing spam on tuigreet
+
+ TTYReset = true;
+ TTYVHangup = true;
+ TTYVTDisallocate = true;
+ };
+}
diff --git a/modules/client/thunar/default.nix b/modules/client/thunar/default.nix
new file mode 100644
index 0000000..0caaabf
--- /dev/null
+++ b/modules/client/thunar/default.nix
@@ -0,0 +1,24 @@
+{ config, pkgs, ... }:
+{
+ services = {
+ gvfs.enable = true;
+ # TODO: Check if I need these
+ # udisks2.enable = true;
+ # devmon.enable = true;
+ tumbler.enable = true;
+ };
+
+ programs = {
+ thunar = {
+ enable = true;
+
+ plugins = with pkgs.xfce; [
+ thunar-archive-plugin
+ thunar-media-tags-plugin
+ thunar-volman
+ ];
+ };
+
+ file-roller.enable = true;
+ };
+}
diff --git a/modules/common/adguard/default.nix b/modules/common/adguard/default.nix
new file mode 100644
index 0000000..9929bc1
--- /dev/null
+++ b/modules/common/adguard/default.nix
@@ -0,0 +1,106 @@
+{ config, lib, ... }:
+{
+ services = {
+ adguardhome = {
+ enable = false;
+ openFirewall = false;
+ mutableSettings = false;
+
+ settings = {
+ http = {
+ address = "127.0.0.1:3000";
+ };
+
+ dns = {
+ bind_hosts = [ "10.0.0.5" "127.0.0.1" ];
+ port = 53;
+
+ upstream_dns = [
+ "9.9.9.9"
+ "149.112.112.112"
+ ];
+ fallback_dns = [
+ "1.1.1.1"
+ "1.0.0.1"
+ ];
+ bootstrap_dns = [
+ "9.9.9.9"
+ "149.112.112.112"
+ ];
+ };
+
+ filtering = {
+ rewrites = [
+ # jellyfin
+ {
+ domain = "media.internal";
+ answer = "10.0.0.5";
+ }
+ # immich
+ {
+ domain = "photos.internal";
+ answer = "10.0.0.5";
+ }
+ # calibre-web
+ {
+ domain = "library.internal";
+ answer = "10.0.0.5";
+ }
+ # searxng
+ {
+ domain = "search.internal";
+ answer = "10.0.0.5";
+ }
+ # ollama api
+ {
+ domain = "ollama.internal";
+ answer = "10.0.0.5";
+ }
+ # open-webui
+ {
+ domain = "chat.internal";
+ answer = "10.0.0.5";
+ }
+ # forgejo
+ {
+ domain = "forge.internal";
+ answer = "10.0.0.5";
+ }
+ # cgit
+ {
+ domain = "code.internal";
+ answer = "10.0.0.5";
+ }
+ # adguard
+ {
+ domain = "dns.internal";
+ answer = "10.0.0.5";
+ }
+ # grafana
+ {
+ domain = "monitor.internal";
+ answer = "10.0.0.5";
+ }
+ ];
+ };
+ };
+ };
+
+ nginx.virtualHosts = {
+ "dns.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:3000";
+ proxyWebsockets = true;
+ };
+ };
+ };
+ };
+
+ # networking = {
+ # nameservers = [
+ # "9.9.9.9"
+ # "127.0.0.1"
+ # "10.0.0.5"
+ # ];
+ # };
+}
diff --git a/modules/common/default.nix b/modules/common/default.nix
new file mode 100644
index 0000000..f34cd8f
--- /dev/null
+++ b/modules/common/default.nix
@@ -0,0 +1,45 @@
+{ config, pkgs, ... }:
+{
+ imports =[
+ # names are self explanatory
+ ./adguard
+ ./fonts
+ ./gnupg
+ ./i18n
+ ./nh
+ ./pipewire
+ ./searx
+ ./ssh
+ ./users
+ ./xserver
+ ];
+
+ nix = {
+ settings = {
+ # Enable flakes
+ experimental-features = [ "nix-command" "flakes" ];
+
+ # Optimize storage
+ auto-optimise-store = true;
+ };
+ };
+
+ # Allow unfree packages
+ nixpkgs = {
+ config.allowUnfree = true;
+ };
+
+ # List packages installed in system profile.
+ # These should be tools in case user tools brake.
+ # To search, run:
+ # $ nix search <pkgname>
+ # or
+ # $ nh search <pkgname>
+ environment.systemPackages = with pkgs; [
+ alacritty
+ git
+ helix
+ xdg-utils
+ ];
+}
+
diff --git a/modules/common/fonts/default.nix b/modules/common/fonts/default.nix
new file mode 100644
index 0000000..bf1c91d
--- /dev/null
+++ b/modules/common/fonts/default.nix
@@ -0,0 +1,12 @@
+{ config, pkgs, ... }:
+{
+ fonts.packages = with pkgs; [
+ corefonts
+ font-awesome
+ font-awesome_5
+ maple-mono.NF-CN
+ noto-fonts
+ noto-fonts-cjk-sans
+ noto-fonts-emoji
+ ];
+}
diff --git a/modules/common/gnupg/default.nix b/modules/common/gnupg/default.nix
new file mode 100644
index 0000000..fc6e537
--- /dev/null
+++ b/modules/common/gnupg/default.nix
@@ -0,0 +1,5 @@
+{
+ programs.gnupg.agent = {
+ enable = true;
+ };
+}
diff --git a/modules/common/i18n/default.nix b/modules/common/i18n/default.nix
new file mode 100644
index 0000000..786332c
--- /dev/null
+++ b/modules/common/i18n/default.nix
@@ -0,0 +1,20 @@
+{ config, ... }:
+
+# Locale generation
+{
+ i18n = {
+ defaultLocale = "en_US.UTF-8";
+
+ extraLocaleSettings = {
+ LC_ADDRESS = "el_GR.UTF-8";
+ LC_IDENTIFICATION = "el_GR.UTF-8";
+ LC_MEASUREMENT = "el_GR.UTF-8";
+ LC_MONETARY = "el_GR.UTF-8";
+ LC_NAME = "el_GR.UTF-8";
+ LC_NUMERIC = "el_GR.UTF-8";
+ LC_PAPER = "el_GR.UTF-8";
+ LC_TELEPHONE = "el_GR.UTF-8";
+ LC_TIME = "el_GR.UTF-8";
+ };
+ };
+}
diff --git a/modules/common/nh/default.nix b/modules/common/nh/default.nix
new file mode 100644
index 0000000..a5e09ac
--- /dev/null
+++ b/modules/common/nh/default.nix
@@ -0,0 +1,9 @@
+{ config, pkgs, ... }:
+{
+ programs.nh = {
+ enable = true;
+ clean.enable = true;
+
+ flake = "/home/aethrvmn/.nix/";
+ };
+}
diff --git a/modules/common/pipewire/default.nix b/modules/common/pipewire/default.nix
new file mode 100644
index 0000000..311cf94
--- /dev/null
+++ b/modules/common/pipewire/default.nix
@@ -0,0 +1,12 @@
+{
+ security.rtkit.enable = true;
+
+ services.pipewire = {
+ enable = true;
+
+ audio.enable = true;
+ pulse.enable = true;
+ alsa.enable = true;
+ jack.enable = true;
+ };
+}
diff --git a/modules/common/searx/default.nix b/modules/common/searx/default.nix
new file mode 100644
index 0000000..659c700
--- /dev/null
+++ b/modules/common/searx/default.nix
@@ -0,0 +1,115 @@
+{ config, pkgs, lib, ... }:
+{
+ services = {
+ searx = {
+ enable = true;
+ package = pkgs.searxng;
+
+ settings = {
+ server = {
+ port = 3040;
+ bind_address = "127.0.0.1";
+ secret_key = "secret_key";
+ };
+
+ general = {
+ debug = false;
+ instance_name = "SearXNG Instance";
+ donation_url = false;
+ contact_url = false;
+ privacypolicy_url = false;
+ enable_metrics = false;
+ autocomplete = "startpage";
+ };
+
+ # Search engines
+ engines = lib.mapAttrsToList (name: value: { inherit name; } // value) {
+ # main boys
+ "brave" = {
+ disabled = false;
+ weight = 0.8;
+ };
+ "duckduckgo" = {
+ disabled = false;
+ weight = 0.8;
+ };
+ "ecosia" = {
+ disabled = false;
+ weight = 0.7;
+ };
+ "mojeek" = {
+ disabled = true;
+ weight = 0.4;
+ };
+ "qwant" = {
+ disabled = false;
+ weight = 0.4;
+ };
+ "startpage" = {
+ disabled = false;
+ weight = 1;
+ };
+ "wiby" = {
+ disabled = false;
+ weight = 0.4;
+ };
+
+ #
+ "openverse".disabled = false;
+
+ # repos
+ "bitbucket".disabled = false;
+ "codeberg".disabled = false;
+ "gitea.com".disabled = false;
+ "github".disabled = false;
+ "gitlab".disabled = false;
+ "huggingface".disabled = false;
+ "huggingface datasets".disabled = false;
+ "huggingface spaces".disabled = false;
+ "ollama".disabled = false;
+ "sourcehut".disabled = false;
+
+ # software wikis
+ "gentoo".disabled = false;
+ "nixos wiki".disabled = false;
+ "arch linux wiki".disabled = false;
+ "free software directory".disabled = false;
+
+ # IT etc
+ "mankier".disabled = false;
+ "searchcode code".disabled = false;
+
+ # wikimedia
+ "wikidata".disabled = false;
+ "wikibooks".disabled = false;
+ "wikiquote".disabled = false;
+ "wikisource".disabled = false;
+ "wikivoyage".disabled = false;
+ "wikispecies".disabled = false;
+ "wikiversity".disabled = false;
+ "wikicommons".disabled = false;
+
+ # translate
+ "mozhi".disabled = false;
+ "lingva".disabled = false;
+ "dictzone".disabled = false;
+ "libretranslate".disabled = false;
+
+ # # scams/don't trusts
+ "bing".disabled = true;
+ "yahoo".disabled = true;
+ "google".disabled = true;
+ };
+ };
+ };
+
+ nginx.virtualHosts = {
+ "search.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:3040";
+ proxyWebsockets = true;
+ };
+ };
+ };
+ };
+}
diff --git a/modules/common/ssh/default.nix b/modules/common/ssh/default.nix
new file mode 100644
index 0000000..70b67e2
--- /dev/null
+++ b/modules/common/ssh/default.nix
@@ -0,0 +1,5 @@
+{
+ programs.ssh = {
+ startAgent = true;
+ };
+}
diff --git a/modules/common/users/default.nix b/modules/common/users/default.nix
new file mode 100644
index 0000000..6f086c7
--- /dev/null
+++ b/modules/common/users/default.nix
@@ -0,0 +1,20 @@
+{ config, pkgs, ... }:
+
+# User configuration
+{
+ users = {
+ defaultUserShell = pkgs.zsh;
+
+ users.aethrvmn = {
+ isNormalUser = true;
+ extraGroups = [ "networkmanager" "video" "wheel" ];
+ password = "gg";
+
+ openssh.authorizedKeys.keys = [
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFTRmMBlTFJbOWQBLI9XS2HMdUSlsAcaQ6vWjLpfweEo aethrvmn@apotheke.earth"
+ ];
+ };
+ };
+
+ programs.zsh.enable = true;
+}
diff --git a/modules/common/xserver/default.nix b/modules/common/xserver/default.nix
new file mode 100644
index 0000000..7249ae2
--- /dev/null
+++ b/modules/common/xserver/default.nix
@@ -0,0 +1,9 @@
+{ config, pkgs, ... }:
+
+# XServer
+{
+ services.xserver.xkb = {
+ layout = "us, gr";
+ options = "grp:alt_shift_toggle";
+ };
+}
diff --git a/modules/server/calibre/default.nix b/modules/server/calibre/default.nix
new file mode 100644
index 0000000..d177ac1
--- /dev/null
+++ b/modules/server/calibre/default.nix
@@ -0,0 +1,39 @@
+{ config, pkgs, ... }:
+let
+ libDir = "/var/lib/calibre-web/library";
+in {
+ services = {
+ calibre-web = {
+ enable = true;
+
+ listen = {
+ ip = "127.0.0.1";
+ port = 3020;
+ };
+
+ options = {
+ calibreLibrary = libDir;
+ enableBookUploading = true;
+ };
+ };
+
+ nginx = {
+ virtualHosts."library.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:3020";
+ proxyWebsockets = true;
+ };
+ };
+ };
+ };
+
+ systemd.services.calibre-web = {
+ preStart = ''
+ if [ ! -f "${libDir}/metadata.db" ]; then
+ mkdir -p "${libDir}"
+ ${pkgs.calibre}/bin/calibredb add --empty \
+ --with-library "${libDir}"
+ fi
+ '';
+ };
+}
diff --git a/modules/server/cgit/default.nix b/modules/server/cgit/default.nix
new file mode 100644
index 0000000..08784fe
--- /dev/null
+++ b/modules/server/cgit/default.nix
@@ -0,0 +1,76 @@
+{ config, pkgs, lib, ... }:
+let
+ cgitWithAssets = pkgs.cgit.overrideAttrs (old: {
+ pname = "cgit-with-assets";
+
+ postInstall = (old.postInstall or "") + ''
+ # overwrite the stock files that the module aliases
+ install -Dm444 ${./static/cgit.css} $out/cgit/cgit.css
+ install -Dm444 ${./static/logo.png} $out/cgit/cgit.png # keep the name!
+ install -Dm444 ${./static/favicon.png} $out/cgit/favicon.ico
+ '';
+ });
+in {
+ services = {
+ cgit."code" = {
+ enable = true;
+ scanPath = "/srv/git";
+ package = cgitWithAssets;
+
+ settings = {
+ cache-size = 0;
+ cache-scanrc-ttl = 0;
+ enable-log-filecount = 1;
+ enable-log-linecount = 1;
+ enable-git-config = 1;
+
+ localtime = 1;
+
+ noplainemail = 1;
+
+ root-title = "code.aethrvmn.gr";
+ root-desc = "αpothēke of aethrvmn";
+ clone-url = "https://code.aethrvmn.gr/$CGIT_REPO_URL";
+
+ logo-link = "https://aethrvmn.gr/";
+
+ about-filter = "${pkgs.cgit}/lib/cgit/filters/about-formatting.sh";
+ source-filter = "${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py";
+ };
+
+ nginx.virtualHost = "code.internal";
+ };
+ };
+
+ users = {
+ groups.git = { };
+
+ users = {
+ git = {
+ isSystemUser = true;
+ description = "aethrvmn";
+ group = "git";
+ home = "/srv/git";
+ homeMode = "0755";
+ createHome = true;
+ shell = "${pkgs.git}/bin/git-shell";
+
+ openssh.authorizedKeys.keys = [
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFTRmMBlTFJbOWQBLI9XS2HMdUSlsAcaQ6vWjLpfweEo aethrvmn@apotheke.earth"
+ ];
+ };
+
+ cgit = {
+ isSystemUser = true;
+ extraGroups = [ "git" ];
+ };
+ };
+ };
+
+ systemd = {
+ tmpfiles.rules = [
+ # type path mode uid gid age target
+ "L /srv/git/static - git git - /home/aethrvmn/.nix/modules/server/cgit/static"
+ ];
+ };
+}
diff --git a/modules/server/cgit/static/cgit.css b/modules/server/cgit/static/cgit.css
new file mode 100644
index 0000000..d2ee006
--- /dev/null
+++ b/modules/server/cgit/static/cgit.css
@@ -0,0 +1,1346 @@
+@import url(source-code-pro/source-code-pro.css);
+
+div#cgit {
+ padding: 0em;
+ margin: 0em;
+ font-family: sans-serif;
+ font-size: 10pt;
+ color: #333;
+ background: white;
+ padding: 4px;
+}
+
+div#cgit a {
+ color: blue;
+ text-decoration: none;
+}
+
+div#cgit a:hover {
+ text-decoration: underline;
+}
+
+div#cgit table {
+ border-collapse: collapse;
+}
+
+div#cgit table#header {
+ width: 100%;
+ margin-bottom: 1em;
+}
+
+div#cgit table#header td.logo {
+ width: 96px;
+ vertical-align: top;
+
+ img {
+ width: 96px;
+ }
+}
+
+div#cgit table#header td.main {
+ font-size: 250%;
+ padding-left: 10px;
+ white-space: nowrap;
+}
+
+div#cgit table#header td.main a {
+ color: #000;
+}
+
+div#cgit table#header td.form {
+ text-align: right;
+ vertical-align: bottom;
+ padding-right: 1em;
+ padding-bottom: 2px;
+ white-space: nowrap;
+}
+
+div#cgit table#header td.form form,
+div#cgit table#header td.form input,
+div#cgit table#header td.form select {
+ font-size: 90%;
+}
+
+div#cgit table#header td.sub {
+ color: #777;
+ border-top: solid 1px #ccc;
+ padding-left: 10px;
+}
+
+div#cgit table.tabs {
+ border-bottom: solid 3px #ccc;
+ border-collapse: collapse;
+ margin-top: 2em;
+ margin-bottom: 0px;
+ width: 100%;
+}
+
+div#cgit table.tabs td {
+ padding: 0px 1em;
+ vertical-align: bottom;
+}
+
+div#cgit table.tabs td a {
+ padding: 2px 0.75em;
+ color: #777;
+ font-size: 110%;
+}
+
+div#cgit table.tabs td a.active {
+ color: #000;
+ background-color: #ccc;
+}
+
+div#cgit table.tabs a[href^="http://"]:after, div#cgit table.tabs a[href^="https://"]:after
+{
+ content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfgAhcJDQY+gm2TAAAAHWlUWHRDb21tZW50AAAAAABDcmVhdGVkIHdpdGggR0lNUGQuZQcAAABbSURBVAhbY2BABs4MU4CwhYHBh2Erww4wrGFQZHjI8B8IgUIscJWyDHcggltQhI4zGDCcRwhChPggHIggP1QoAVmQkSETrGoHsiAEsACtBYN0oDAMbgU6EBcAAL2eHUt4XUU4AAAAAElFTkSuQmCC);
+ opacity: 0.5;
+ margin: 0 0 0 5px;
+}
+
+div#cgit table.tabs td.form {
+ text-align: right;
+}
+
+div#cgit table.tabs td.form form {
+ padding-bottom: 2px;
+ font-size: 90%;
+ white-space: nowrap;
+}
+
+div#cgit table.tabs td.form input,
+div#cgit table.tabs td.form select {
+ font-size: 90%;
+}
+
+div#cgit div.path {
+ margin: 0px;
+ padding: 5px 2em 2px 2em;
+ color: #000;
+ background-color: #eee;
+}
+
+div#cgit div.content {
+ margin: 0px;
+ padding: 2em;
+ border-bottom: solid 3px #ccc;
+}
+
+div#cgit table.list {
+ width: 100%;
+ border: none;
+ border-collapse: collapse;
+}
+
+div#cgit table.list tr {
+ background: white;
+}
+
+div#cgit table.list tr.logheader {
+ background: #eee;
+}
+
+div#cgit table.list tr:nth-child(even) {
+ background: #f7f7f7;
+}
+
+div#cgit table.list tr:nth-child(odd) {
+ background: white;
+}
+
+div#cgit table.list tr:hover {
+ background: #eee;
+}
+
+div#cgit table.list tr.nohover {
+ background: white;
+}
+
+div#cgit table.list tr.nohover:hover {
+ background: white;
+}
+
+div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
+ background: #f7f7f7;
+}
+
+div#cgit table.list tr.nohover-highlight:hover:nth-child(odd) {
+ background: white;
+}
+
+div#cgit table.list th {
+ font-weight: bold;
+ /* color: #888;
+ border-top: dashed 1px #888;
+ border-bottom: dashed 1px #888;
+ */
+ padding: 0.1em 0.5em 0.05em 0.5em;
+ vertical-align: baseline;
+}
+
+div#cgit table.list td {
+ border: none;
+ padding: 0.1em 0.5em 0.1em 0.5em;
+}
+
+div#cgit table.list td.commitgraph {
+ font-family: "Source Code Pro", "Courier New", monospace;
+ white-space: pre;
+}
+div#cgit pre {
+ font-family: "Source Code Pro", "Courier New", monospace;
+}
+
+div#cgit table.list td.commitgraph .column1 {
+ color: #a00;
+}
+
+div#cgit table.list td.commitgraph .column2 {
+ color: #0a0;
+}
+
+div#cgit table.list td.commitgraph .column3 {
+ color: #aa0;
+}
+
+div#cgit table.list td.commitgraph .column4 {
+ color: #00a;
+}
+
+div#cgit table.list td.commitgraph .column5 {
+ color: #a0a;
+}
+
+div#cgit table.list td.commitgraph .column6 {
+ color: #0aa;
+}
+
+div#cgit table.list td.logsubject {
+ font-family: "Source Code Pro", "Courier New", monospace;
+ font-weight: bold;
+}
+
+div#cgit table.list td.logmsg {
+ font-family: "Source Code Pro", "Courier New", monospace;
+ white-space: pre;
+ padding: 0 0.5em;
+}
+
+div#cgit table.list td a {
+ color: black;
+}
+
+div#cgit table.list td a.ls-dir {
+ font-weight: bold;
+ color: #00f;
+}
+
+div#cgit table.list td a:hover {
+ color: #00f;
+}
+
+div#cgit img {
+ border: none;
+}
+
+div#cgit input#switch-btn {
+ margin: 2px 0px 0px 0px;
+}
+
+div#cgit td#sidebar input.txt {
+ width: 100%;
+ margin: 2px 0px 0px 0px;
+}
+
+div#cgit table#grid {
+ margin: 0px;
+}
+
+div#cgit td#content {
+ vertical-align: top;
+ padding: 1em 2em 1em 1em;
+ border: none;
+}
+
+div#cgit div#summary {
+ vertical-align: top;
+ margin-bottom: 1em;
+}
+
+div#cgit table#downloads {
+ float: right;
+ border-collapse: collapse;
+ border: solid 1px #777;
+ margin-left: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+div#cgit table#downloads th {
+ background-color: #ccc;
+}
+
+div#cgit div#blob {
+ border: solid 1px black;
+}
+
+div#cgit div.error {
+ color: red;
+ font-weight: bold;
+ margin: 1em 2em;
+}
+
+div#cgit a.ls-blob,
+div#cgit a.ls-dir,
+div#cgit .ls-mod {
+ font-family: "Source Code Pro", "Courier New", monospace;
+}
+
+div#cgit td.ls-size {
+ text-align: right;
+ font-family: "Source Code Pro", "Courier New", monospace;
+ width: 10em;
+}
+
+div#cgit td.ls-mode {
+ font-family: "Source Code Pro", "Courier New", monospace;
+ width: 10em;
+}
+
+div#cgit table.blob {
+ margin-top: 0.5em;
+ border-top: solid 1px black;
+}
+
+div#cgit table.blob td.hashes,
+div#cgit table.blob td.lines {
+ margin: 0;
+ padding: 0 0 0 0.5em;
+ vertical-align: top;
+ color: black;
+}
+
+div#cgit table.blob td.linenumbers {
+ margin: 0;
+ padding: 0 0.5em 0 0.5em;
+ vertical-align: top;
+ text-align: right;
+ border-right: 1px solid gray;
+}
+
+div#cgit table.blob pre {
+ padding: 0;
+ margin: 0;
+}
+
+div#cgit table.blob td.linenumbers a,
+div#cgit table.ssdiff td.lineno a {
+ color: gray;
+ text-align: right;
+ text-decoration: none;
+}
+
+div#cgit table.blob td.linenumbers a:hover,
+div#cgit table.ssdiff td.lineno a:hover {
+ color: black;
+}
+
+div#cgit table.blame td.hashes,
+div#cgit table.blame td.lines,
+div#cgit table.blame td.linenumbers {
+ padding: 0;
+}
+
+div#cgit table.blame td.hashes div.alt,
+div#cgit table.blame td.lines div.alt {
+ padding: 0 0.5em 0 0.5em;
+}
+
+div#cgit table.blame td.linenumbers div.alt {
+ padding: 0 0.5em 0 0;
+}
+
+div#cgit table.blame div.alt:nth-child(even) {
+ background: #eee;
+}
+
+div#cgit table.blame div.alt:nth-child(odd) {
+ background: white;
+}
+
+div#cgit table.blame td.lines > div {
+ position: relative;
+}
+
+div#cgit table.blame td.lines > div > pre {
+ padding: 0 0 0 0.5em;
+ position: absolute;
+ top: 0;
+}
+
+div#cgit table.blame .oid {
+ font-size: 100%;
+}
+
+div#cgit table.bin-blob {
+ margin-top: 0.5em;
+ border: solid 1px black;
+}
+
+div#cgit table.bin-blob th {
+ font-family: "Source Code Pro", "Courier New", monospace;
+ white-space: pre;
+ border: solid 1px #777;
+ padding: 0.5em 1em;
+}
+
+div#cgit table.bin-blob td {
+ font-family: "Source Code Pro", "Courier New", monospace;
+ white-space: pre;
+ border-left: solid 1px #777;
+ padding: 0em 1em;
+}
+
+div#cgit table.nowrap td {
+ white-space: nowrap;
+}
+
+div#cgit table.commit-info {
+ border-collapse: collapse;
+ margin-top: 1.5em;
+}
+
+div#cgit div.cgit-panel {
+ float: right;
+ margin-top: 1.5em;
+}
+
+div#cgit div.cgit-panel table {
+ border-collapse: collapse;
+ border: solid 1px #aaa;
+ background-color: #eee;
+}
+
+div#cgit div.cgit-panel th {
+ text-align: center;
+}
+
+div#cgit div.cgit-panel td {
+ padding: 0.25em 0.5em;
+}
+
+div#cgit div.cgit-panel td.label {
+ padding-right: 0.5em;
+}
+
+div#cgit div.cgit-panel td.ctrl {
+ padding-left: 0.5em;
+}
+
+div#cgit table.commit-info th {
+ text-align: left;
+ font-weight: normal;
+ padding: 0.1em 1em 0.1em 0.1em;
+ vertical-align: top;
+}
+
+div#cgit table.commit-info td {
+ font-weight: normal;
+ padding: 0.1em 1em 0.1em 0.1em;
+}
+
+div#cgit div.commit-subject {
+ font-weight: bold;
+ font-size: 125%;
+ margin: 1.5em 0em 0.5em 0em;
+ padding: 0em;
+}
+
+div#cgit div.commit-msg {
+ white-space: pre;
+ font-family: "Source Code Pro", "Courier New", monospace;
+}
+
+div#cgit div.notes-header {
+ font-weight: bold;
+ padding-top: 1.5em;
+}
+
+div#cgit div.notes {
+ white-space: pre;
+ font-family: "Source Code Pro", "Courier New", monospace;
+ border: solid 1px #ee9;
+ background-color: #ffd;
+ padding: 0.3em 2em 0.3em 1em;
+ float: left;
+}
+
+div#cgit div.notes-footer {
+ clear: left;
+}
+
+div#cgit div.diffstat-header {
+ font-weight: bold;
+ padding-top: 1.5em;
+}
+
+div#cgit table.diffstat {
+ border-collapse: collapse;
+ border: solid 1px #aaa;
+ background-color: #eee;
+}
+
+div#cgit table.diffstat th {
+ font-weight: normal;
+ text-align: left;
+ text-decoration: underline;
+ padding: 0.1em 1em 0.1em 0.1em;
+ font-size: 100%;
+}
+
+div#cgit table.diffstat td {
+ padding: 0.2em 0.2em 0.1em 0.1em;
+ font-size: 100%;
+ border: none;
+}
+
+div#cgit table.diffstat td.mode {
+ white-space: nowrap;
+}
+
+div#cgit table.diffstat td span.modechange {
+ padding-left: 1em;
+ color: red;
+}
+
+div#cgit table.diffstat td.add a {
+ color: green;
+}
+
+div#cgit table.diffstat td.del a {
+ color: red;
+}
+
+div#cgit table.diffstat td.upd a {
+ color: blue;
+}
+
+div#cgit table.diffstat td.graph {
+ width: 500px;
+ vertical-align: middle;
+}
+
+div#cgit table.diffstat td.graph table {
+ border: none;
+}
+
+div#cgit table.diffstat td.graph td {
+ padding: 0px;
+ border: 0px;
+ height: 7pt;
+}
+
+div#cgit table.diffstat td.graph td.add {
+ background-color: #5c5;
+}
+
+div#cgit table.diffstat td.graph td.rem {
+ background-color: #c55;
+}
+
+div#cgit div.diffstat-summary {
+ color: #888;
+ padding-top: 0.5em;
+}
+
+div#cgit table.diff {
+ width: 100%;
+}
+
+div#cgit table.diff td {
+ font-family: "Source Code Pro", "Courier New", monospace;
+ white-space: pre;
+}
+
+div#cgit table.diff td div.head {
+ font-weight: bold;
+ margin-top: 1em;
+ color: black;
+}
+
+div#cgit table.diff td div.hunk {
+ color: #009;
+}
+
+div#cgit table.diff td div.add {
+ color: green;
+}
+
+div#cgit table.diff td div.del {
+ color: red;
+}
+
+div#cgit .oid {
+ font-family: "Source Code Pro", "Courier New", monospace;
+ font-size: 90%;
+}
+
+div#cgit .left {
+ text-align: left;
+}
+
+div#cgit .right {
+ text-align: right;
+}
+
+div#cgit table.list td.reposection {
+ font-style: italic;
+ color: #888;
+}
+
+div#cgit a.button {
+ font-size: 80%;
+ padding: 0em 0.5em;
+}
+
+div#cgit a.primary {
+ font-size: 100%;
+}
+
+div#cgit a.secondary {
+ font-size: 90%;
+}
+
+div#cgit td.toplevel-repo {
+}
+
+div#cgit table.list td.sublevel-repo {
+ padding-left: 1.5em;
+}
+
+div#cgit ul.pager {
+ list-style-type: none;
+ text-align: center;
+ margin: 1em 0em 0em 0em;
+ padding: 0;
+}
+
+div#cgit ul.pager li {
+ display: inline-block;
+ margin: 0.25em 0.5em;
+}
+
+div#cgit ul.pager a {
+ color: #777;
+}
+
+div#cgit ul.pager .current {
+ font-weight: bold;
+}
+
+div#cgit span.age-mins {
+ font-weight: bold;
+ color: #080;
+}
+
+div#cgit span.age-hours {
+ color: #080;
+}
+
+div#cgit span.age-days {
+ color: #040;
+}
+
+div#cgit span.age-weeks {
+ color: #444;
+}
+
+div#cgit span.age-months {
+ color: #888;
+}
+
+div#cgit span.age-years {
+ color: #bbb;
+}
+
+div#cgit span.insertions {
+ color: #080;
+}
+
+div#cgit span.deletions {
+ color: #800;
+}
+
+div#cgit div.footer {
+ margin-top: 0.5em;
+ text-align: center;
+ font-size: 80%;
+ color: #ccc;
+}
+
+div#cgit div.footer a {
+ color: #ccc;
+ text-decoration: none;
+}
+
+div#cgit div.footer a:hover {
+ text-decoration: underline;
+}
+
+div#cgit a.branch-deco {
+ color: #000;
+ margin: 0px 0.5em;
+ padding: 0px 0.25em;
+ background-color: #88ff88;
+ border: solid 1px #007700;
+}
+
+div#cgit a.tag-deco {
+ color: #000;
+ margin: 0px 0.5em;
+ padding: 0px 0.25em;
+ background-color: #ffff88;
+ border: solid 1px #777700;
+}
+
+div#cgit a.tag-annotated-deco {
+ color: #000;
+ margin: 0px 0.5em;
+ padding: 0px 0.25em;
+ background-color: #ffcc88;
+ border: solid 1px #777700;
+}
+
+div#cgit a.remote-deco {
+ color: #000;
+ margin: 0px 0.5em;
+ padding: 0px 0.25em;
+ background-color: #ccccff;
+ border: solid 1px #000077;
+}
+
+div#cgit a.deco {
+ color: #000;
+ margin: 0px 0.5em;
+ padding: 0px 0.25em;
+ background-color: #ff8888;
+ border: solid 1px #770000;
+}
+
+div#cgit div.commit-subject a.branch-deco,
+div#cgit div.commit-subject a.tag-deco,
+div#cgit div.commit-subject a.tag-annotated-deco,
+div#cgit div.commit-subject a.remote-deco,
+div#cgit div.commit-subject a.deco {
+ margin-left: 1em;
+ font-size: 75%;
+}
+
+div#cgit table.stats {
+ border: solid 1px black;
+ border-collapse: collapse;
+}
+
+div#cgit table.stats th {
+ text-align: left;
+ padding: 1px 0.5em;
+ background-color: #eee;
+ border: solid 1px black;
+}
+
+div#cgit table.stats td {
+ text-align: right;
+ padding: 1px 0.5em;
+ border: solid 1px black;
+}
+
+div#cgit table.stats td.total {
+ font-weight: bold;
+ text-align: left;
+}
+
+div#cgit table.stats td.sum {
+ color: #c00;
+ font-weight: bold;
+ /* background-color: #eee; */
+}
+
+div#cgit table.stats td.left {
+ text-align: left;
+}
+
+div#cgit table.vgraph {
+ border-collapse: separate;
+ border: solid 1px black;
+ height: 200px;
+}
+
+div#cgit table.vgraph th {
+ background-color: #eee;
+ font-weight: bold;
+ border: solid 1px white;
+ padding: 1px 0.5em;
+}
+
+div#cgit table.vgraph td {
+ vertical-align: bottom;
+ padding: 0px 10px;
+}
+
+div#cgit table.vgraph div.bar {
+ background-color: #eee;
+}
+
+div#cgit table.hgraph {
+ border: solid 1px black;
+ width: 800px;
+}
+
+div#cgit table.hgraph th {
+ background-color: #eee;
+ font-weight: bold;
+ border: solid 1px black;
+ padding: 1px 0.5em;
+}
+
+div#cgit table.hgraph td {
+ vertical-align: middle;
+ padding: 2px 2px;
+}
+
+div#cgit table.hgraph div.bar {
+ background-color: #eee;
+ height: 1em;
+}
+
+div#cgit table.ssdiff {
+ width: 100%;
+}
+
+div#cgit table.ssdiff td {
+ font-size: 75%;
+ font-family: "Source Code Pro", "Courier New", monospace;
+ white-space: pre;
+ padding: 1px 4px 1px 4px;
+ border-left: solid 1px #aaa;
+ border-right: solid 1px #aaa;
+}
+
+div#cgit table.ssdiff td.add {
+ color: black;
+ background: #cfc;
+ min-width: 50%;
+}
+
+div#cgit table.ssdiff td.add_dark {
+ color: black;
+ background: #aca;
+ min-width: 50%;
+}
+
+div#cgit table.ssdiff span.add {
+ background: #cfc;
+ font-weight: bold;
+}
+
+div#cgit table.ssdiff td.del {
+ color: black;
+ background: #fcc;
+ min-width: 50%;
+}
+
+div#cgit table.ssdiff td.del_dark {
+ color: black;
+ background: #caa;
+ min-width: 50%;
+}
+
+div#cgit table.ssdiff span.del {
+ background: #fcc;
+ font-weight: bold;
+}
+
+div#cgit table.ssdiff td.changed {
+ color: black;
+ background: #ffc;
+ min-width: 50%;
+}
+
+div#cgit table.ssdiff td.changed_dark {
+ color: black;
+ background: #cca;
+ min-width: 50%;
+}
+
+div#cgit table.ssdiff td.lineno {
+ color: black;
+ background: #eee;
+ text-align: right;
+ width: 3em;
+ min-width: 3em;
+}
+
+div#cgit table.ssdiff td.hunk {
+ color: black;
+ background: #ccf;
+ border-top: solid 1px #aaa;
+ border-bottom: solid 1px #aaa;
+}
+
+div#cgit table.ssdiff td.head {
+ border-top: solid 1px #aaa;
+ border-bottom: solid 1px #aaa;
+}
+
+div#cgit table.ssdiff td.head div.head {
+ font-weight: bold;
+ color: black;
+}
+
+div#cgit table.ssdiff td.foot {
+ border-top: solid 1px #aaa;
+ border-left: none;
+ border-right: none;
+ border-bottom: none;
+}
+
+div#cgit table.ssdiff td.space {
+ border: none;
+}
+
+div#cgit table.ssdiff td.space div {
+ min-height: 3em;
+}
+div#cgit span.libravatar img.onhover {
+ display: none;
+ border: 1px solid gray;
+ padding: 0px;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ width: 128px;
+ height: 128px;
+}
+
+div#cgit span.libravatar img.inline {
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ width: 13px;
+ height: 13px;
+ margin-right: 0.2em;
+ opacity: 0.6;
+}
+
+div#cgit span.libravatar:hover > img.onhover {
+ display: block;
+ position: absolute;
+ margin-left: 1.5em;
+ background-color: #eeeeee;
+ box-shadow: 2px 2px 7px rgba(100, 100, 100, 0.75);
+}
+
+/*
+ Color overrides for browsers running in dark mode.
+ "only all and ..." forces very old browsers to ignore the media query:
+ https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries#improving_compatibility_with_older_browsers
+*/
+:root {
+ color-scheme: light dark;
+}
+@media only all and (prefers-color-scheme: dark) {
+ html,
+ div#cgit {
+ color: #eee;
+ background: #171717;
+ }
+ div#cgit a {
+ color: #3af;
+ }
+ div#cgit .diffstat-header a {
+ color: #28d;
+ }
+ div#cgit table#header td.main a {
+ color: #eee;
+ }
+ div#cgit table#header td.sub {
+ color: #999;
+ }
+ div#cgit table.tabs {
+ border-bottom-color: #444;
+ }
+ div#cgit table.tabs td a {
+ color: #888;
+ }
+ div#cgit table.tabs td a.active {
+ color: #fff;
+ background-color: #444;
+ }
+ div#cgit div.path {
+ color: #eee;
+ background-color: #333;
+ }
+ div#cgit div.content {
+ border-bottom-color: #bbb;
+ }
+ div#cgit table.list tr {
+ background: #171717;
+ }
+ div#cgit table.list tr.logheader {
+ background: #171717;
+ }
+ div#cgit table.list tr:nth-child(even) {
+ background: #171717;
+ }
+ div#cgit table.list tr:nth-child(odd) {
+ background: #1f1f1f;
+ }
+ div#cgit table.list tr:hover {
+ background: #333;
+ }
+ div#cgit table.list tr.nohover {
+ background: #171717;
+ }
+ div#cgit table.list tr.nohover:hover {
+ background: #171717;
+ }
+ div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
+ background: #171717;
+ }
+ div#cgit table.list tr.nohover-highlight:hover:nth-child(odd) {
+ background: #1f1f1f;
+ }
+ div#cgit table.list td.commitgraph .column1 {
+ color: #f55;
+ }
+ div#cgit table.list td.commitgraph .column2 {
+ color: #5f5;
+ }
+ div#cgit table.list td.commitgraph .column3 {
+ color: #ff5;
+ }
+ div#cgit table.list td.commitgraph .column4 {
+ color: #55f;
+ }
+ div#cgit table.list td.commitgraph .column5 {
+ color: #f5f;
+ }
+ div#cgit table.list td.commitgraph .column6 {
+ color: #5ff;
+ }
+ div#cgit table.list td a {
+ color: #eee;
+ }
+ div#cgit table.list td a.ls-dir {
+ color: #28d;
+ }
+ div#cgit table.list td a:hover {
+ color: #3af;
+ }
+ div#cgit table#downloads {
+ border-color: #888;
+ }
+ div#cgit table#downloads th {
+ background-color: #333;
+ }
+ div#cgit div#blob {
+ border-color: #eee;
+ }
+ div#cgit table.blob {
+ border-top-color: #eee;
+ }
+ div#cgit table.blob td.hashes,
+ div#cgit table.blob td.lines {
+ color: #eee;
+ }
+ div#cgit table.blob td.linenumbers {
+ border-right-color: gray;
+ }
+ div#cgit table.blob td.linenumbers a,
+ div#cgit table.ssdiff td.lineno a {
+ color: gray;
+ }
+ div#cgit table.blob td.linenumbers a:hover,
+ div#cgit table.ssdiff td.lineno a:hover {
+ color: #eee;
+ }
+ div#cgit table.blame div.alt:nth-child(even) {
+ background: #171717;
+ }
+ div#cgit table.blame div.alt:nth-child(odd) {
+ background: #1f1f1f;
+ }
+ div#cgit table.bin-blob {
+ border-color: #eee;
+ }
+ div#cgit table.bin-blob th {
+ border-color: #888;
+ }
+ div#cgit table.bin-blob td {
+ border-left-color: #888;
+ }
+ div#cgit div.cgit-panel table {
+ border-color: #555;
+ background-color: #282828;
+ }
+ div#cgit div.notes {
+ border-color: #661;
+ background-color: #220;
+ }
+ div#cgit table.diffstat {
+ border-color: #555;
+ background-color: #282828;
+ }
+ div#cgit table.diffstat td span.modechange {
+ color: #c66;
+ }
+ div#cgit table.diffstat td.add a {
+ color: #6c6;
+ }
+ div#cgit table.diffstat td.del a {
+ color: #c66;
+ }
+ div#cgit table.diffstat td.upd a {
+ color: #3af;
+ }
+ div#cgit table.diffstat td.graph td.add {
+ background-color: #3a3;
+ }
+ div#cgit table.diffstat td.graph td.rem {
+ background-color: #a33;
+ }
+ div#cgit div.diffstat-summary {
+ color: #777;
+ }
+ div#cgit table.diff td div.head {
+ color: #eee;
+ }
+ div#cgit table.diff td div.hunk {
+ color: #28d;
+ }
+ div#cgit table.diff td div.add {
+ color: #6c6;
+ }
+ div#cgit table.diff td div.del {
+ color: #c66;
+ }
+ div#cgit table.list td.reposection {
+ color: #777;
+ }
+ div#cgit ul.pager a {
+ color: #888;
+ }
+ div#cgit span.age-mins {
+ color: #7f7;
+ }
+ div#cgit span.age-hours {
+ color: #7f7;
+ }
+ div#cgit span.age-days {
+ color: #9d9;
+ }
+ div#cgit span.age-weeks {
+ color: #bbb;
+ }
+ div#cgit span.age-months {
+ color: #888;
+ }
+ div#cgit span.age-years {
+ color: #666;
+ }
+ div#cgit span.insertions {
+ color: #7f7;
+ }
+ div#cgit span.deletions {
+ color: #e33;
+ }
+ div#cgit div.footer {
+ color: #555;
+ }
+ div#cgit div.footer a {
+ color: #555;
+ }
+ div#cgit a.branch-deco {
+ color: #fff;
+ background-color: #361;
+ border-color: #3b2;
+ }
+ div#cgit a.tag-deco {
+ color: #fff;
+ background-color: #650;
+ border-color: #ba3;
+ }
+ div#cgit a.tag-annotated-deco {
+ color: #fff;
+ background-color: #840;
+ border-color: #b96;
+ }
+ div#cgit a.remote-deco {
+ color: #fff;
+ background-color: #348;
+ border-color: #67c;
+ }
+ div#cgit a.deco {
+ color: #fff;
+ background-color: #922;
+ border-color: #d55;
+ }
+ div#cgit a.branch-deco:hover,
+ div#cgit table.list td a.branch-deco:hover,
+ div#cgit a.tag-deco:hover,
+ div#cgit table.list td a.tag-deco:hover,
+ div#cgit a.tag-annotated-deco:hover,
+ div#cgit table.list td a.tag-annotated-deco:hover,
+ div#cgit a.remote-deco:hover,
+ div#cgit table.list td a.remote-deco:hover,
+ div#cgit a.deco:hover,
+ div#cgit table.list td a.deco:hover {
+ color: #fff;
+ }
+ div#cgit table.stats {
+ border-color: #555;
+ }
+ div#cgit table.stats th {
+ background-color: #333;
+ border-color: #555;
+ }
+ div#cgit table.stats td {
+ border-color: #555;
+ }
+ div#cgit table.stats td.sum {
+ color: #5c7e9b;
+ }
+ div#cgit table.vgraph {
+ border-color: #eee;
+ }
+ div#cgit table.vgraph th {
+ background-color: #1f1f1f;
+ border-color: black;
+ }
+ div#cgit table.vgraph div.bar {
+ background-color: #1f1f1f;
+ }
+ div#cgit table.hgraph {
+ border-color: #eee;
+ }
+ div#cgit table.hgraph th {
+ background-color: #1f1f1f;
+ border-color: #eee;
+ }
+ div#cgit table.hgraph div.bar {
+ background-color: #1f1f1f;
+ }
+ div#cgit table.ssdiff td {
+ border-left-color: #555;
+ border-right-color: #555;
+ }
+ div#cgit table.ssdiff td.add {
+ color: #eee;
+ background: #353;
+ }
+ div#cgit table.ssdiff td.add_dark {
+ color: #eee;
+ background: #030;
+ }
+ div#cgit table.ssdiff span.add {
+ background: #030;
+ }
+ div#cgit table.ssdiff td.del {
+ color: #eee;
+ background: #533;
+ }
+ div#cgit table.ssdiff td.del_dark {
+ color: #eee;
+ background: #411;
+ }
+ div#cgit table.ssdiff span.del {
+ background: #300;
+ }
+ div#cgit table.ssdiff td.changed {
+ color: #eee;
+ background: #553;
+ }
+ div#cgit table.ssdiff td.changed_dark {
+ color: #eee;
+ background: #330;
+ }
+ div#cgit table.ssdiff td.lineno {
+ color: #eee;
+ background: #1f1f1f;
+ }
+ div#cgit table.ssdiff td.hunk {
+ color: #eee;
+ background: #0d3d64;
+ border-top-color: #555;
+ border-bottom-color: #555;
+ }
+ div#cgit table.ssdiff td.head {
+ border-top-color: #555;
+ border-bottom-color: #555;
+ }
+ div#cgit table.ssdiff td.head div.head {
+ color: #eee;
+ }
+ div#cgit table.ssdiff td.foot {
+ border-top-color: #555;
+ }
+}
+/* Style definition file generated by highlight 3.13, http://www.andre-simon.de/ */
+
+/* Highlighting theme: Kwrite Editor */
+
+body.hl {
+ background-color: #e0eaee;
+}
+pre.hl {
+ color: #000000;
+ background-color: #e0eaee;
+ font-size: 10pt;
+ font-family: "Courier New", monospace;
+}
+.hl.num {
+ color: #b07e00;
+}
+.hl.esc {
+ color: #ff00ff;
+}
+.hl.str {
+ color: #bf0303;
+}
+.hl.pps {
+ color: #818100;
+}
+.hl.slc {
+ color: #838183;
+ font-style: italic;
+}
+.hl.com {
+ color: #838183;
+ font-style: italic;
+}
+.hl.ppc {
+ color: #008200;
+}
+.hl.opt {
+ color: #000000;
+}
+.hl.ipl {
+ color: #0057ae;
+}
+.hl.lin {
+ color: #555555;
+}
+.hl.kwa {
+ color: #000000;
+ font-weight: bold;
+}
+.hl.kwb {
+ color: #0057ae;
+}
+.hl.kwc {
+ color: #000000;
+ font-weight: bold;
+}
+.hl.kwd {
+ color: #010181;
+}
+
diff --git a/modules/server/cgit/static/favicon.png b/modules/server/cgit/static/favicon.png
new file mode 100755
index 0000000..a9c1396
--- /dev/null
+++ b/modules/server/cgit/static/favicon.png
Binary files differ
diff --git a/modules/server/cgit/static/logo.png b/modules/server/cgit/static/logo.png
new file mode 100755
index 0000000..a9c1396
--- /dev/null
+++ b/modules/server/cgit/static/logo.png
Binary files differ
diff --git a/modules/server/default.nix b/modules/server/default.nix
new file mode 100644
index 0000000..60b7681
--- /dev/null
+++ b/modules/server/default.nix
@@ -0,0 +1,53 @@
+{
+ imports = [
+ ./adguard
+ ./calibre
+ ./cgit
+ ./forgejo
+ ./gemini
+ ./grafana
+ ./immich
+ ./jellyfin
+ ./ollama
+ ./searx
+ ];
+
+ services = {
+ nginx = {
+ enable = true;
+ recommendedGzipSettings = true;
+ recommendedOptimisation = true;
+ recommendedProxySettings = true;
+ };
+
+ sshguard.enable = true;
+
+ openssh = {
+ enable = false;
+ settings = {
+ PermitRootLogin = false;
+ PasswordAuthentication = false;
+ AllowTcpForwarding = false;
+ X11Forwarding = false;
+ };
+ };
+ };
+
+ networking = {
+ firewall.allowedTCPPorts = [ 80 ];
+
+ hosts = {
+ "127.0.0.1" = [
+ "library.internal"
+ "media.internal"
+ "photos.internal"
+ "chat.internal"
+ "ollama.internal"
+ "code.internal"
+ "forge.internal"
+ "search.internal"
+ "monitor.internal"
+ ];
+ };
+ };
+}
diff --git a/modules/server/forgejo/default.nix b/modules/server/forgejo/default.nix
new file mode 100644
index 0000000..cf611ce
--- /dev/null
+++ b/modules/server/forgejo/default.nix
@@ -0,0 +1,42 @@
+{
+ services = {
+ forgejo = {
+ enable = true;
+
+ dump.enable = true;
+
+ settings = {
+ DEFAULT = {
+ APP_NAME = "apothēke";
+ RUN_MODE = "prod";
+ APP_SLOGAN = "a place for storing objects.";
+ RUN_USER = "forgejo";
+ };
+
+ server = {
+ HTTP_ADDR = "forge.internal";
+ HTTP_PORT = 3000;
+ DISABLE_SSH = true;
+ };
+
+ service = {
+ DISABLE_REGISTRATION = false;
+ DEFAULT_KEEP_EMAIL_PRIVATE = true;
+ };
+
+ lfs = {
+ enable = true;
+ };
+ };
+ };
+
+ nginx = {
+ virtualHosts."forge.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:3000";
+ proxyWebsockets = true;
+ };
+ };
+ };
+ };
+}
diff --git a/modules/server/gemini/default.nix b/modules/server/gemini/default.nix
new file mode 100644
index 0000000..d59f65f
--- /dev/null
+++ b/modules/server/gemini/default.nix
@@ -0,0 +1,57 @@
+{ config, pkgs, lib, ... }:
+{
+ services.agate = {
+ enable = true;
+
+ hostnames = [ "aethrvmn.gr" ];
+ addresses = [ "0.0.0.0:1965" ];
+ language = "en";
+ contentDir = "/srv/gemini";
+ };
+
+ networking.firewall.allowedTCPPorts = [ 1965 ];
+
+ users = {
+ groups.agate = { };
+ users = {
+ agate = {
+ isSystemUser = true;
+ description = "gemini user";
+ group = "agate";
+ home = "/srv/gemini";
+ createHome = true;
+ shell = "${pkgs.git}/bin/git-shell";
+ };
+ };
+ };
+
+ systemd = {
+ # set service
+ services."gemini" = {
+ description = "Update Gemini site from repo";
+
+ script = ''
+ if [ -d /srv/gemini/.git ]; then
+ ${pkgs.git}/bin/git -C /srv/gemini pull
+ else
+ ${pkgs.git}/bin/git clone https://apo.theke.ml/aethrvmn/gemini.git /srv/gemini
+ fi
+ '';
+
+ serviceConfig = {
+ Type = "oneshot";
+ User = "agate";
+ };
+ };
+
+ timers."gemini" = {
+ description = "Hourly Gemini-site update";
+ wantedBy = [ "timers.target" ];
+
+ timerConfig = {
+ OnCalendar = "hourly";
+ Persistent = true;
+ };
+ };
+ };
+}
diff --git a/modules/server/grafana/default.nix b/modules/server/grafana/default.nix
new file mode 100644
index 0000000..056221a
--- /dev/null
+++ b/modules/server/grafana/default.nix
@@ -0,0 +1,23 @@
+{ config, pkgs, ... }:
+{
+ services = {
+ grafana = {
+ enable = false;
+ settings.server = {
+ domain = "monitor.internal";
+ http_port = 3050;
+ http_addr = "127.0.0.1";
+ };
+ };
+
+ nginx = {
+ virtualHosts."monitor.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:3050";
+ proxyWebsockets = true;
+ };
+ };
+ };
+ };
+}
+
diff --git a/modules/server/immich/default.nix b/modules/server/immich/default.nix
new file mode 100644
index 0000000..fac75f9
--- /dev/null
+++ b/modules/server/immich/default.nix
@@ -0,0 +1,28 @@
+{ config, lib, ... }:
+{
+ services = {
+ # Immich setup
+ immich = {
+ enable = true;
+ openFirewall = false;
+
+ host = "127.0.0.1";
+ port = 3010;
+ };
+
+ nginx = {
+ virtualHosts."photos.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:3010";
+ proxyWebsockets = true;
+ };
+ };
+ };
+ };
+
+ hardware.graphics.enable = lib.mkForce true;
+
+ users.users.immich = {
+ extraGroups = [ "video" "render" ];
+ };
+}
diff --git a/modules/server/jellyfin/default.nix b/modules/server/jellyfin/default.nix
new file mode 100644
index 0000000..424b4d8
--- /dev/null
+++ b/modules/server/jellyfin/default.nix
@@ -0,0 +1,27 @@
+{ config, pkgs, lib, ...}:
+{
+ environment.systemPackages = with pkgs; [
+ jellyfin
+ jellyfin-web
+ jellyfin-ffmpeg
+ logrotate
+ ];
+
+ services = {
+ jellyfin = {
+ enable = true;
+ openFirewall = false;
+ };
+
+ logrotate.enable = true;
+
+ nginx = {
+ virtualHosts."media.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:8096";
+ proxyWebsockets = true;
+ };
+ };
+ };
+ };
+}
diff --git a/modules/server/ollama/default.nix b/modules/server/ollama/default.nix
new file mode 100644
index 0000000..3b99daf
--- /dev/null
+++ b/modules/server/ollama/default.nix
@@ -0,0 +1,69 @@
+{ config, pkgs, lib, ... }:
+{
+ services = {
+ ollama = {
+ enable = true;
+ loadModels = [
+ "qwen3:14b"
+ "gemma3:12b"
+ "gpt-oss:20b"
+ "deepseek-r1:14b"
+ "phi4-reasoning:14b"
+ ];
+
+ acceleration = "rocm";
+ environmentVariables = {
+ HCC_AMDGPU_TARGET = "gfx1031";
+ };
+ rocmOverrideGfx = "10.3.0";
+ };
+
+ open-webui = {
+ enable = true;
+ port = 3030;
+ environment = {
+ ANONYMIZED_TELEMETRY = "False";
+ DO_NOT_TRACK = "True";
+ SCARF_NO_ANALYTICS = "True";
+ WEBUI_AUTH = "False";
+ OLLAMA_API_BASE_URL = "http://localhost:11434";
+
+ #dir stuff
+ STATIC_DIR = "${config.services.open-webui.stateDir}/static";
+ DATA_DIR = "${config.services.open-webui.stateDir}/data";
+ HF_HOME = "${config.services.open-webui.stateDir}/hf_home";
+ SENTENCE_TRANSFORMERS_HOME = "${config.services.open-webui.stateDir}/transformers_home";
+ };
+ };
+
+ xserver.videoDrivers = [ "amdgpu" ];
+
+ nginx.virtualHosts = {
+ "chat.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:3030";
+ proxyWebsockets = true;
+ };
+ };
+
+ "ollama.internal" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:11434";
+ proxyWebsockets = true;
+ };
+ };
+ };
+ };
+
+ nixpkgs.config = {
+ allowUnfree = lib.mkForce true;
+ rocmSupport = lib.mkForce true;
+ rocmTargets = [ "gfx1031" ];
+ };
+
+ environment.systemPackages = with pkgs; [
+ rocmPackages.rocminfo
+ rocmPackages.rocm-smi
+ rocmPackages.hipcc
+ ];
+}
Directive (EU) 2019/790, Article 4(3); all rights regarding Text and Data Mining (TDM) are reserved.