diff --git a/lib/examples/file-utils.nix b/lib/examples/file-utils.nix index ccd8ee4..c3005c2 100644 --- a/lib/examples/file-utils.nix +++ b/lib/examples/file-utils.nix @@ -44,7 +44,7 @@ in # Example of using these functions together nixosConfigurations = lib.mapAttrs' ( - name: + _name: { system, hostname, ... }: { name = hostname; diff --git a/lib/examples/reverseproxy.nix b/lib/examples/reverseproxy.nix index 1b6e0c1..d38d6d9 100644 --- a/lib/examples/reverseproxy.nix +++ b/lib/examples/reverseproxy.nix @@ -1,5 +1,5 @@ # Example usage of the reverse proxy utilities -{ inputs, lib, ... }: +{ lib, ... }: let inherit (lib.mjallen-lib.reverseproxy) mkReverseProxy @@ -89,11 +89,15 @@ in domain = "example.com"; priority = 20; rule = "Host(`custom.example.com`) && PathPrefix(`/api`)"; - middlewares = [ "crowdsec" "whitelist-geoblock" "rate-limit" ]; + middlewares = [ + "crowdsec" + "whitelist-geoblock" + "rate-limit" + ]; }; # Example usage in a Traefik configuration: - # + # # mjallen.services.traefik = { # enable = true; # extraServices = multipleProxies.extraServices; diff --git a/lib/examples/system-utils.nix b/lib/examples/system-utils.nix index 0679ba0..9bd668b 100644 --- a/lib/examples/system-utils.nix +++ b/lib/examples/system-utils.nix @@ -19,7 +19,7 @@ in nixosSystems = inputs.self.mjallen-lib.file.filterNixOSSystems allSystems; in inputs.nixpkgs.lib.mapAttrs' ( - name: + _name: { system, hostname, ... }: let # Create extended lib with mjallen-lib @@ -86,7 +86,7 @@ in allHomes = inputs.self.mjallen-lib.file.scanHomes ../homes; in inputs.nixpkgs.lib.mapAttrs' ( - name: + _name: { system, username, diff --git a/lib/reverseproxy/default.nix b/lib/reverseproxy/default.nix index 25ae814..0170150 100644 --- a/lib/reverseproxy/default.nix +++ b/lib/reverseproxy/default.nix @@ -1,77 +1,112 @@ { inputs }: let inherit (inputs.nixpkgs.lib) - mkOption - types listToAttrs nameValuePair ; in rec { # Create a service configuration for Traefik - mkService = { - name, - url, - loadBalancer ? { }, - }: { - inherit name url; - config = { - loadBalancer = { - servers = [{ inherit url; }]; - } // loadBalancer; + mkService = + { + name, + url, + loadBalancer ? { }, + }: + { + inherit name url; + config = { + loadBalancer = { + servers = [ { inherit url; } ]; + } + // loadBalancer; + }; }; - }; # Create a router configuration for Traefik - mkRouter = { - subdomain, - domain ? "mjallen.dev", - service, - entryPoints ? [ "websecure" ], - middlewares ? [ "crowdsec" "whitelist-geoblock" ], - priority ? null, - rule ? null, - tls ? { certResolver = "letsencrypt"; }, - }: { - inherit subdomain service entryPoints middlewares; - config = { - inherit entryPoints service middlewares tls; - rule = if rule != null then rule else "Host(`${subdomain}.${domain}`)"; - } // (if priority != null then { inherit priority; } else { }); - }; + mkRouter = + { + subdomain, + domain ? "mjallen.dev", + service, + entryPoints ? [ "websecure" ], + middlewares ? [ + "crowdsec" + "whitelist-geoblock" + ], + priority ? null, + rule ? null, + tls ? { + certResolver = "letsencrypt"; + }, + }: + { + inherit + subdomain + service + entryPoints + middlewares + ; + config = { + inherit + entryPoints + service + middlewares + tls + ; + rule = if rule != null then rule else "Host(`${subdomain}.${domain}`)"; + } + // (if priority != null then { inherit priority; } else { }); + }; # Create both service and router for a simple reverse proxy setup - mkReverseProxy = { - name, - subdomain, - url, - domain ? "mjallen.dev", - entryPoints ? [ "websecure" ], - middlewares ? [ "crowdsec" "whitelist-geoblock" ], - priority ? null, - rule ? null, - tls ? { certResolver = "letsencrypt"; }, - loadBalancer ? { }, - }: { - service = mkService { - inherit name url loadBalancer; + mkReverseProxy = + { + name, + subdomain, + url, + domain ? "mjallen.dev", + entryPoints ? [ "websecure" ], + middlewares ? [ + "crowdsec" + "whitelist-geoblock" + ], + priority ? null, + rule ? null, + tls ? { + certResolver = "letsencrypt"; + }, + loadBalancer ? { }, + }: + { + service = mkService { + inherit name url loadBalancer; + }; + router = mkRouter { + inherit + subdomain + domain + entryPoints + middlewares + priority + rule + tls + ; + service = name; + }; }; - router = mkRouter { - inherit subdomain domain entryPoints middlewares priority rule tls; - service = name; - }; - }; # Convert a list of services to the format expected by Traefik module - servicesToConfig = services: - listToAttrs (map (service: nameValuePair service.name service.config) services); + servicesToConfig = + services: listToAttrs (map (service: nameValuePair service.name service.config) services); # Convert a list of routers to the format expected by Traefik module - routersToConfig = routers: - listToAttrs (map (router: nameValuePair router.subdomain router.config) routers); + routersToConfig = + routers: listToAttrs (map (router: nameValuePair router.subdomain router.config) routers); # Helper to create multiple reverse proxies at once - mkReverseProxies = proxies: + mkReverseProxies = + proxies: let results = map mkReverseProxy proxies; services = map (result: result.service) results; @@ -91,31 +126,47 @@ rec { middlewares = { # Authentication middleware auth = [ "authentik" ]; - + # Basic security (default) - basic = [ "crowdsec" "whitelist-geoblock" ]; - + basic = [ + "crowdsec" + "whitelist-geoblock" + ]; + # Internal only access - internal = [ "crowdsec" "whitelist-geoblock" "internal-ipallowlist" ]; - + internal = [ + "crowdsec" + "whitelist-geoblock" + "internal-ipallowlist" + ]; + # WebSocket support - websocket = [ "crowdsec" "whitelist-geoblock" "onlyoffice-websocket" ]; - + websocket = [ + "crowdsec" + "whitelist-geoblock" + "onlyoffice-websocket" + ]; + # Authenticated with basic security - authBasic = [ "crowdsec" "whitelist-geoblock" "authentik" ]; + authBasic = [ + "crowdsec" + "whitelist-geoblock" + "authentik" + ]; }; # Common service URL builders urls = { # Local container service - container = containerName: port: "http://\${config.containers.${containerName}.localAddress}:${toString port}"; - + container = + containerName: port: "http://\${config.containers.${containerName}.localAddress}:${toString port}"; + # Local host service localhost = port: "http://127.0.0.1:${toString port}"; - + # Network service network = ip: port: "http://${ip}:${toString port}"; - + # Server IP service (using your server IP pattern) server = port: "http://\${serverIp}:${toString port}"; }; @@ -123,31 +174,47 @@ rec { # Pre-configured reverse proxy templates templates = { # Standard web application - webapp = { name, subdomain, port, ... }@args: - mkReverseProxy ({ - url = urls.localhost port; - middlewares = middlewares.basic; - } // args); + webapp = + { port, ... }@args: + mkReverseProxy ( + { + url = urls.localhost port; + middlewares = middlewares.basic; + } + // args + ); - # Authenticated web application - authWebapp = { name, subdomain, port, ... }@args: - mkReverseProxy ({ - url = urls.localhost port; - middlewares = middlewares.authBasic; - } // args); + # Authenticated web application + authWebapp = + { port, ... }@args: + mkReverseProxy ( + { + url = urls.localhost port; + middlewares = middlewares.authBasic; + } + // args + ); # Container-based service - containerService = { name, subdomain, containerName, port, ... }@args: - mkReverseProxy ({ - url = urls.container containerName port; - middlewares = middlewares.basic; - } // args); + containerService = + { containerName, port, ... }@args: + mkReverseProxy ( + { + url = urls.container containerName port; + middlewares = middlewares.basic; + } + // args + ); # Internal-only service - internalService = { name, subdomain, port, ... }@args: - mkReverseProxy ({ - url = urls.localhost port; - middlewares = middlewares.internal; - } // args); + internalService = + { port, ... }@args: + mkReverseProxy ( + { + url = urls.localhost port; + middlewares = middlewares.internal; + } + // args + ); }; } diff --git a/modules/home/programs/hyprland/default.nix b/modules/home/programs/hyprland/default.nix index b7e7c3e..27415a0 100644 --- a/modules/home/programs/hyprland/default.nix +++ b/modules/home/programs/hyprland/default.nix @@ -498,30 +498,30 @@ in # send_cancel = "0"; # }; - # hyprgrass-bind = [ - # # swipe left from right edge - # ", edge:r:l, workspace, +1" + # hyprgrass-bind = [ + # # swipe left from right edge + # ", edge:r:l, workspace, +1" - # # swipe up from bottom edge - # ", edge:d:u, exec, ${cfg.defaultApps.browser.pname}" + # # swipe up from bottom edge + # ", edge:d:u, exec, ${cfg.defaultApps.browser.pname}" - # # swipe down from left edge - # ", edge:l:d, exec, pactl set-sink-volume @DEFAULT_SINK@ -4%" + # # swipe down from left edge + # ", edge:l:d, exec, pactl set-sink-volume @DEFAULT_SINK@ -4%" - # # swipe down with 4 fingers - # ", swipe:4:d, killactive" + # # swipe down with 4 fingers + # ", swipe:4:d, killactive" - # # swipe diagonally left and down with 3 fingers - # # l (or r) must come before d and u - # ", swipe:3:ld, exec, foot" + # # swipe diagonally left and down with 3 fingers + # # l (or r) must come before d and u + # ", swipe:3:ld, exec, foot" - # # tap with 3 fingers - # ", tap:3, exec, foot" + # # tap with 3 fingers + # ", tap:3, exec, foot" - # # longpress can trigger mouse binds: - # ", longpress:2, movewindow" - # ", longpress:3, resizewindow" - # ]; + # # longpress can trigger mouse binds: + # ", longpress:2, movewindow" + # ", longpress:3, resizewindow" + # ]; # }; }; diff --git a/modules/nixos/disko/aarch64-linux/default.nix b/modules/nixos/disko/aarch64-linux/default.nix.ori similarity index 100% rename from modules/nixos/disko/aarch64-linux/default.nix rename to modules/nixos/disko/aarch64-linux/default.nix.ori diff --git a/modules/nixos/disko/default.nix b/modules/nixos/disko/default.nix new file mode 100644 index 0000000..5e5a84c --- /dev/null +++ b/modules/nixos/disko/default.nix @@ -0,0 +1,160 @@ +{ + config, + lib, + namespace, + ... +}: +with lib; +let + cfg = config.${namespace}.hardware.disko; + + defaultBtrfsMountOptions = [ + "compress=${cfg.compression}" + "noatime" + ]; + defaultBcachefsMountOptions = [ + "noatime" + ]; + + subvolumes = + let + make = + name: subvolume: + nameValuePair "${name}" { + mountOptions = + if subvolume.mountOptions == null then + if cfg.filesystem == "btrfs" then defaultBtrfsMountOptions else defaultBcachefsMountOptions + else + subvolume.mountOptions; + mountpoint = if subvolume.mountPoint == null then "/${name}" else subvolume.mountPoint; + }; + in + mapAttrs' make cfg.subvolumes; + + # BTRFS root partition configuration + root = { + name = "${cfg.filesystem}-root"; + size = "100%"; + content = { + type = cfg.filesystem; + # Subvolumes must set a mountpoint in order to be mounted, + # unless their parent is mounted + subvolumes = subvolumes; + } + // ( + if cfg.filesystem == "btrfs" then + { + extraArgs = [ "-f" ]; # Override existing partition + } + else + { + # This refers to a filesystem in the `bcachefs_filesystems` attrset below. + filesystem = "mounted_subvolumes_in_multi"; + label = "ssd.ssd1"; + extraFormatArgs = [ + "--discard" + ]; + } + ); + }; + + # Luks root partition configuration + luksRoot = { + name = "cryptroot"; + size = "100%"; + content = { + type = "luks"; + name = "cryptroot"; + extraOpenArgs = [ + "--allow-discards" + "--perf-no_read_workqueue" + "--perf-no_write_workqueue" + ]; + settings = { + crypttabExtraOpts = [ + "fido2-device=auto" + "token-timeout=10" + ]; + }; + content = { + type = cfg.filesystem; + # Subvolumes must set a mountpoint in order to be mounted, + # unless their parent is mounted + subvolumes = subvolumes; + } + // ( + if cfg.filesystem == "btrfs" then + { + extraArgs = [ "-f" ]; # Override existing partition + } + else + { + # This refers to a filesystem in the `bcachefs_filesystems` attrset below. + filesystem = "mounted_subvolumes_in_multi"; + label = "ssd.ssd1"; + extraFormatArgs = [ + "--discard" + ]; + } + ); + }; + }; +in +{ + imports = [ ./options.nix ]; + config = lib.mkIf cfg.enable { + disko.devices = lib.mkMerge [ + { + nodev."/" = { + fsType = "tmpfs"; + mountOptions = [ + "mode=755" + "defaults" + "size=25%" + ]; + }; + disk = { + main = { + device = cfg.rootDisk; + type = "disk"; + imageSize = "32G"; + content = { + type = "gpt"; + partitions = { + ESP = { + type = "EF00"; + size = "500M"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + }; + }; + + swap = lib.mkIf cfg.enableSwap { + type = "8200"; + size = cfg.swapSize; + }; + + root = if cfg.enableLuks then luksRoot else root; + }; + }; + }; + }; + + # configure Bcachefs + bcachefs_filesystems = lib.mkIf (cfg.filesystem == "bcachefs") { + mounted_subvolumes_in_multi = { + type = "bcachefs_filesystem"; + # passwordFile = "/etc/nixos/pool.jwe"; + extraFormatArgs = [ + "--compression=${cfg.compression}" + ]; + subvolumes = subvolumes; + }; + }; + } + ]; + }; +} diff --git a/modules/nixos/disko/options.nix b/modules/nixos/disko/options.nix index 948291d..9939636 100644 --- a/modules/nixos/disko/options.nix +++ b/modules/nixos/disko/options.nix @@ -20,5 +20,30 @@ in enableLuks = mkBoolOpt false "Enable Luks"; swapSize = mkOpt types.str "16G" "size of swap part"; + + rootDisk = mkOpt types.str "/dev/nvme0n1" "Root disk"; + + compression = mkOpt types.str "zstd" "Type of compression to enable"; + + subvolumes = + mkOpt + (types.attrsOf ( + types.submodule { + options = { + mountPoint = mkOpt (types.nullOr types.path) null "Mountpoint of the subvolume"; + mountOptions = mkOpt (types.nullOr (types.listOf types.str)) null "Extra mount options"; + }; + } + )) + { + "home" = { }; + "etc" = { }; + "nix" = { }; + "root" = { }; + "log" = { + mountPoint = "/var/log"; + }; + } + "Subvolumes on root disk"; }; } diff --git a/modules/nixos/disko/x86_64-linux/default.nix b/modules/nixos/disko/x86_64-linux/default.nix.ori similarity index 100% rename from modules/nixos/disko/x86_64-linux/default.nix rename to modules/nixos/disko/x86_64-linux/default.nix.ori diff --git a/modules/nixos/homeassistant/services/homeassistant/default.nix b/modules/nixos/homeassistant/services/homeassistant/default.nix index 2d3610c..0e0442d 100644 --- a/modules/nixos/homeassistant/services/homeassistant/default.nix +++ b/modules/nixos/homeassistant/services/homeassistant/default.nix @@ -264,102 +264,102 @@ in ps: with ps; [ # pkgs.${namespace}.python-roborock # pkgs.${namespace}.pyvesync - # # Core functionality - # aiohttp - # aiodns - # paho-mqtt - # pillow - # pytz - # pyyaml - # sqlalchemy + # # Core functionality + # aiohttp + # aiodns + # paho-mqtt + # pillow + # pytz + # pyyaml + # sqlalchemy - # # Discovery & networking - # zeroconf - # netdisco - # ifaddr - # ssdp + # # Discovery & networking + # zeroconf + # netdisco + # ifaddr + # ssdp - # # Device protocols - # pyserial # Serial communications - # bluepy # Bluetooth LE + # # Device protocols + # pyserial # Serial communications + # bluepy # Bluetooth LE - # # Smart home ecosystems - # mutagen # Media file metadata - # pysonos # Sonos - # pywemo # Belkin WeMo - # python-miio # Xiaomi devices - # python-kasa # TP-Link + # # Smart home ecosystems + # mutagen # Media file metadata + # pysonos # Sonos + # pywemo # Belkin WeMo + # python-miio # Xiaomi devices + # python-kasa # TP-Link - # # Sensors & monitoring - # meteocalc # Weather calculations - # speedtest-cli # Internet speed + # # Sensors & monitoring + # meteocalc # Weather calculations + # speedtest-cli # Internet speed - # # Visualization & UI - # matplotlib # Graphing + # # Visualization & UI + # matplotlib # Graphing - # # Security - # bcrypt - # cryptography - # pyjwt + # # Security + # bcrypt + # cryptography + # pyjwt - # # Media - # ha-ffmpeg # Camera streams + # # Media + # ha-ffmpeg # Camera streams - # # Specialized integrations - # python-matter-server # Matter protocol + # # Specialized integrations + # python-matter-server # Matter protocol - # # System integrations - # psutil # System monitoring + # # System integrations + # psutil # System monitoring psycopg2 - # numpy - # hassil - # pyturbojpeg - # paho-mqtt - # pychromecast - # pyatv - # python-otbr-api - # brother - # pyipp - # govee-ble - # adguardhome - # nextcord - # aiogithubapi - # jellyfin-apiclient-python - # pylitterbot - # dateparser - # aionut - # nextcloudmonitor - # ollama - # pynecil - # aiopyarr - # pysabnzbd - # getmac - # zigpy - # bellows # For Zigbee EmberZNet-based adapters - # zigpy-xbee # For XBee adapters - # zigpy-deconz # For ConBee/RaspBee adapters - # pyicloud # iCloud - # pyatv # Apple TV - # opencv-python - # face-recognition - # ibeacon-ble - # gehomesdk - # onedrive-personal-sdk - # pkgs.${namespace}.python-steam - # apple-weatherkit + # numpy + # hassil + # pyturbojpeg + # paho-mqtt + # pychromecast + # pyatv + # python-otbr-api + # brother + # pyipp + # govee-ble + # adguardhome + # nextcord + # aiogithubapi + # jellyfin-apiclient-python + # pylitterbot + # dateparser + # aionut + # nextcloudmonitor + # ollama + # pynecil + # aiopyarr + # pysabnzbd + # getmac + # zigpy + # bellows # For Zigbee EmberZNet-based adapters + # zigpy-xbee # For XBee adapters + # zigpy-deconz # For ConBee/RaspBee adapters + # pyicloud # iCloud + # pyatv # Apple TV + # opencv-python + # face-recognition + # ibeacon-ble + # gehomesdk + # onedrive-personal-sdk + # pkgs.${namespace}.python-steam + # apple-weatherkit - # samsungctl - # samsungtvws + # samsungctl + # samsungtvws - # aiohomekit + # aiohomekit - # icmplib - # aioelectricitymaps - # wyoming - # pysmartthings - # wakeonlan - # ephem + # icmplib + # aioelectricitymaps + # wyoming + # pysmartthings + # wakeonlan + # ephem ]; config = { diff --git a/modules/nixos/services/actual/default.nix b/modules/nixos/services/actual/default.nix index e363480..f3b0232 100644 --- a/modules/nixos/services/actual/default.nix +++ b/modules/nixos/services/actual/default.nix @@ -12,7 +12,7 @@ let hostAddress = "10.0.1.3"; actualUserId = config.users.users.nix-apps.uid; actualGroupId = config.users.groups.jallen-nas.gid; - + actualConfig = { lib, ... }: { @@ -80,12 +80,12 @@ let system.stateVersion = "23.11"; }; - bindMounts = { - ${dataDir} = { - hostPath = cfg.dataDir; - isReadOnly = false; - }; + bindMounts = { + ${dataDir} = { + hostPath = cfg.dataDir; + isReadOnly = false; }; + }; # Create reverse proxy configuration using mkReverseProxy reverseProxyConfig = lib.${namespace}.mkReverseProxy { @@ -95,23 +95,25 @@ let middlewares = cfg.reverseProxy.middlewares; }; - actualContainer = (lib.${namespace}.mkContainer { - name = "actual"; - localAddress = cfg.localAddress; - port = cfg.port; - bindMounts = bindMounts; - config = actualConfig; - }) { inherit lib; }; + actualContainer = + (lib.${namespace}.mkContainer { + name = "actual"; + localAddress = cfg.localAddress; + port = cfg.port; + bindMounts = bindMounts; + config = actualConfig; + }) + { inherit lib; }; fullConfig = { ${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable { reverseProxies = [ reverseProxyConfig ]; }; - } // actualContainer; + } + // actualContainer; in { imports = [ ./options.nix ]; - + config = mkIf cfg.enable fullConfig; } - diff --git a/modules/nixos/services/crowdsec/default.nix b/modules/nixos/services/crowdsec/default.nix index 03105eb..89bcbb4 100755 --- a/modules/nixos/services/crowdsec/default.nix +++ b/modules/nixos/services/crowdsec/default.nix @@ -1,11 +1,9 @@ { config, lib, - pkgs, namespace, ... }: -with lib; let cfg = config.${namespace}.services.crowdsec; in @@ -71,6 +69,7 @@ in ]; }; settings = { + # general.api.server.enable = true; capi.credentialsFile = cfg.apiKey; }; }; diff --git a/modules/nixos/services/gitea/default.nix b/modules/nixos/services/gitea/default.nix index 78bc6eb..f6e5b6b 100644 --- a/modules/nixos/services/gitea/default.nix +++ b/modules/nixos/services/gitea/default.nix @@ -13,7 +13,7 @@ let mailerPasswordFile = config.sops.secrets."jallen-nas/gitea/mail-key".path; metricsTokenFile = config.sops.secrets."jallen-nas/gitea/metrics-key".path; - serviceConfig = + serviceConfig = { lib, ... }: { services.gitea = { @@ -74,7 +74,7 @@ let services.resolved.enable = true; system.stateVersion = "23.11"; }; - + bindMounts = { ${dataDir} = { hostPath = cfg.dataDir; @@ -95,19 +95,22 @@ let middlewares = cfg.reverseProxy.middlewares; }; - containerConfig = (lib.${namespace}.mkContainer { - name = "gitea"; - localAddress = cfg.localAddress; - port = cfg.httpPort; - bindMounts = bindMounts; - config = serviceConfig; - }) { inherit lib; }; + containerConfig = + (lib.${namespace}.mkContainer { + name = "gitea"; + localAddress = cfg.localAddress; + port = cfg.httpPort; + bindMounts = bindMounts; + config = serviceConfig; + }) + { inherit lib; }; giteaConfig = { ${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable { reverseProxies = [ reverseProxyConfig ]; }; - } // containerConfig; + } + // containerConfig; in { imports = [ ./options.nix ]; diff --git a/modules/nixos/services/glance/default.nix b/modules/nixos/services/glance/default.nix index 71325ce..c0e05da 100644 --- a/modules/nixos/services/glance/default.nix +++ b/modules/nixos/services/glance/default.nix @@ -1,4 +1,9 @@ -{ config, lib, namespace, ... }: +{ + config, + lib, + namespace, + ... +}: let inherit (lib.${namespace}) mkOpt mkReverseProxyOpt; cfg = config.${namespace}.services.glance; @@ -16,7 +21,7 @@ with lib; reverseProxy = mkReverseProxyOpt; }; - + config = lib.mkIf cfg.enable { services.glance = { enable = true; diff --git a/modules/nixos/services/matrix/default.nix b/modules/nixos/services/matrix/default.nix index 82f688d..4bbee3e 100644 --- a/modules/nixos/services/matrix/default.nix +++ b/modules/nixos/services/matrix/default.nix @@ -1,4 +1,9 @@ -{ config, lib, namespace, ... }: +{ + config, + lib, + namespace, + ... +}: let inherit (lib.${namespace}) mkOpt mkReverseProxyOpt; cfg = config.${namespace}.services.matrix; @@ -19,10 +24,16 @@ let port = cfg.port; tls = false; x_forwarded = true; - bind_addresses = [ "::1" "0.0.0.0" ]; + bind_addresses = [ + "::1" + "0.0.0.0" + ]; resources = [ { - names = [ "client" "federation" ]; + names = [ + "client" + "federation" + ]; compress = false; } ]; @@ -37,7 +48,7 @@ let issuer = "https://authentik.mjallen.dev/application/o/matrix/"; client_id = "KiChwyQn2kMtXU6LU0x3dlCb0jO6VB6e9xsN9NPs"; # TO BE FILLED client_secret = "6XRfNCUayZqnyaMv0QSEeFz98x2y8BkXnDyylmvAbg71YkQVtpEybP6jmPzncpJsx4k5evtziicgu8p9dOa2oADHL6Ao13643VMTsI4BSel1sbIICA2TH755BpB9J39A"; # TO BE FILLED - scopes =[ + scopes = [ "openid" "profile" "email" @@ -64,31 +75,31 @@ let cp_max = 10; }; }; - + # Registration settings - enable_registration = false; # Set to true initially to create admin user + enable_registration = false; # Set to true initially to create admin user enable_registration_without_verification = false; # registration_shared_secret = "BogieDudie1"; - + # Media settings max_upload_size = "50M"; media_store_path = "/var/lib/matrix-synapse/media"; - + # Logging # log_config = "/var/lib/matrix-synapse/log_config.yaml"; trusted_key_servers = [ { - server_name = "matrix.org"; + server_name = "matrix.org"; } ]; }; }; - + users.users.matrix-synapse = { isSystemUser = true; group = "matrix-synapse"; }; - users.groups.matrix-synapse = {}; + users.groups.matrix-synapse = { }; services.postgresql = { enable = lib.mkDefault true; @@ -135,19 +146,22 @@ let middlewares = cfg.reverseProxy.middlewares; }; - matrixContainer = (lib.${namespace}.mkContainer { - name = "matrix-synapse"; - localAddress = cfg.localAddress; - port = cfg.port; - bindMounts = bindMounts; - config = matrixConfig; - }) { inherit lib; }; + matrixContainer = + (lib.${namespace}.mkContainer { + name = "matrix-synapse"; + localAddress = cfg.localAddress; + port = cfg.port; + bindMounts = bindMounts; + config = matrixConfig; + }) + { inherit lib; }; fullConfig = { ${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable { reverseProxies = [ reverseProxyConfig ]; }; - } // matrixContainer; + } + // matrixContainer; in with lib; { @@ -164,4 +178,4 @@ with lib; }; config = lib.mkIf cfg.enable fullConfig; -} \ No newline at end of file +} diff --git a/modules/nixos/services/nextcloud/default.nix b/modules/nixos/services/nextcloud/default.nix index 7baa306..0c4ac44 100755 --- a/modules/nixos/services/nextcloud/default.nix +++ b/modules/nixos/services/nextcloud/default.nix @@ -96,24 +96,28 @@ in secretFile = secretsFile; extraApps = { - inherit (pkgs.nextcloud31Packages.apps) app_api - bookmarks - mail - calendar - contacts - integration_openai - integration_paperless - maps - oidc_login - onlyoffice - previewgenerator - recognize - richdocuments - user_oidc; + inherit (pkgs.nextcloud31Packages.apps) + app_api + bookmarks + mail + calendar + contacts + integration_openai + integration_paperless + maps + oidc_login + onlyoffice + previewgenerator + recognize + richdocuments + user_oidc + ; - inherit nextcloudPhotos - nextcloudPdfViewer - nextcloudAssist; + inherit + nextcloudPhotos + nextcloudPdfViewer + nextcloudAssist + ; }; config = { diff --git a/modules/nixos/services/ntfy/default.nix b/modules/nixos/services/ntfy/default.nix index e88f7fb..8d3dbb3 100644 --- a/modules/nixos/services/ntfy/default.nix +++ b/modules/nixos/services/ntfy/default.nix @@ -1,4 +1,9 @@ -{ config, lib, namespace, ... }: +{ + config, + lib, + namespace, + ... +}: let inherit (lib.${namespace}) mkOpt mkReverseProxyOpt; cfg = config.${namespace}.services.ntfy; @@ -66,19 +71,22 @@ let middlewares = cfg.reverseProxy.middlewares; }; - ntfyContainer = (lib.${namespace}.mkContainer { - name = "ntfy"; - localAddress = cfg.localAddress; - port = cfg.port; - bindMounts = bindMounts; - config = ntfyConfig; - }) { inherit lib; }; + ntfyContainer = + (lib.${namespace}.mkContainer { + name = "ntfy"; + localAddress = cfg.localAddress; + port = cfg.port; + bindMounts = bindMounts; + config = ntfyConfig; + }) + { inherit lib; }; fullConfig = { ${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable { reverseProxies = [ reverseProxyConfig ]; }; - } // ntfyContainer; + } + // ntfyContainer; in with lib; { diff --git a/modules/nixos/services/tabby-web/README.md b/modules/nixos/services/tabby-web/README.md deleted file mode 100644 index 143d2b7..0000000 --- a/modules/nixos/services/tabby-web/README.md +++ /dev/null @@ -1,196 +0,0 @@ -# Tabby Web Service Module - -This module provides a NixOS service for running the Tabby Web terminal application server. - -## Features - -- Systemd service with automatic startup -- User and group management -- Database migration on startup -- Configurable environment variables -- Security hardening -- Firewall integration -- Support for PostgreSQL and SQLite databases -- Social authentication configuration - -## Basic Usage - -```nix -{ - mjallen.services.tabby-web = { - enable = true; - port = 9000; - openFirewall = true; - }; -} -``` - -## Advanced Configuration - -```nix -{ - mjallen.services.tabby-web = { - enable = true; - port = 8080; - openFirewall = true; - - # Use PostgreSQL instead of SQLite - databaseUrl = "postgresql://tabby:password@localhost:5432/tabby"; - - # Use S3 for app distribution storage - appDistStorage = "s3://my-bucket/tabby-dist"; - - # Configure social authentication - socialAuth = { - github = { - key = "your-github-oauth-key"; - secret = "your-github-oauth-secret"; - }; - gitlab = { - key = "your-gitlab-oauth-key"; - secret = "your-gitlab-oauth-secret"; - }; - }; - - # Performance tuning - workers = 8; - timeout = 300; - - # Additional environment variables - extraEnvironment = { - DEBUG = "0"; - LOG_LEVEL = "info"; - }; - }; -} -``` - -## Configuration Options - -### Basic Options - -- `enable`: Enable the tabby-web service -- `port`: Port to run the server on (default: 9000) -- `openFirewall`: Whether to open the firewall port (default: false) -- `user`: User to run the service as (default: "tabby-web") -- `group`: Group to run the service as (default: "tabby-web") -- `dataDir`: Data directory (default: "/var/lib/tabby-web") - -### Database Configuration - -- `databaseUrl`: Database connection URL - - SQLite: `"sqlite:///var/lib/tabby-web/tabby.db"` (default) - - PostgreSQL: `"postgresql://user:password@host:port/database"` - -### Storage Configuration - -- `appDistStorage`: Storage URL for app distributions - - Local: `"file:///var/lib/tabby-web/dist"` (default) - - S3: `"s3://bucket-name/path"` - - GCS: `"gcs://bucket-name/path"` - -### Social Authentication - -Configure OAuth providers: - -```nix -socialAuth = { - github = { - key = "oauth-key"; - secret = "oauth-secret"; - }; - gitlab = { - key = "oauth-key"; - secret = "oauth-secret"; - }; - microsoftGraph = { - key = "oauth-key"; - secret = "oauth-secret"; - }; - googleOauth2 = { - key = "oauth-key"; - secret = "oauth-secret"; - }; -}; -``` - -### Performance Options - -- `workers`: Number of gunicorn worker processes (default: 4) -- `timeout`: Worker timeout in seconds (default: 120) - -### Additional Configuration - -- `extraEnvironment`: Additional environment variables as an attribute set - -## Service Management - -```bash -# Start the service -sudo systemctl start tabby-web - -# Enable automatic startup -sudo systemctl enable tabby-web - -# Check service status -sudo systemctl status tabby-web - -# View logs -sudo journalctl -u tabby-web -f - -# Run management commands -sudo -u tabby-web tabby-web-manage migrate -sudo -u tabby-web tabby-web-manage add_version 1.0.156-nightly.2 -``` - -## Security - -The service runs with extensive security hardening: - -- Dedicated user and group -- Restricted filesystem access -- No new privileges -- Protected system directories -- Private temporary directory -- Memory execution protection -- Namespace restrictions - -## Database Setup - -### PostgreSQL - -If using PostgreSQL, ensure the database and user exist: - -```sql -CREATE USER tabby WITH PASSWORD 'your-password'; -CREATE DATABASE tabby OWNER tabby; -``` - -### SQLite - -SQLite databases are created automatically in the data directory. - -## Troubleshooting - -1. **Service fails to start**: Check logs with `journalctl -u tabby-web` -2. **Database connection issues**: Verify database URL and credentials -3. **Permission errors**: Ensure data directory has correct ownership -4. **Port conflicts**: Check if another service is using the configured port - -## Integration with Reverse Proxy - -Example Nginx configuration: - -```nginx -server { - listen 80; - server_name tabby.example.com; - - location / { - proxy_pass http://localhost:9000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } -} diff --git a/modules/nixos/services/tabby-web/default.nix b/modules/nixos/services/tabby-web/default.nix deleted file mode 100644 index 622e0ac..0000000 --- a/modules/nixos/services/tabby-web/default.nix +++ /dev/null @@ -1,121 +0,0 @@ -{ - config, - lib, - pkgs, - namespace, - ... -}: -with lib; -let - cfg = config.${namespace}.services.tabby-web; - - # Build environment variables from configuration - environmentVars = { - DATABASE_URL = cfg.databaseUrl; - APP_DIST_STORAGE = cfg.appDistStorage; - PORT = toString cfg.port; - } - // optionalAttrs (cfg.socialAuth.github.key != null) { - SOCIAL_AUTH_GITHUB_KEY = cfg.socialAuth.github.key; - } - // optionalAttrs (cfg.socialAuth.github.secret != null) { - SOCIAL_AUTH_GITHUB_SECRET = cfg.socialAuth.github.secret; - } - // optionalAttrs (cfg.socialAuth.gitlab.key != null) { - SOCIAL_AUTH_GITLAB_KEY = cfg.socialAuth.gitlab.key; - } - // optionalAttrs (cfg.socialAuth.gitlab.secret != null) { - SOCIAL_AUTH_GITLAB_SECRET = cfg.socialAuth.gitlab.secret; - } - // optionalAttrs (cfg.socialAuth.microsoftGraph.key != null) { - SOCIAL_AUTH_MICROSOFT_GRAPH_KEY = cfg.socialAuth.microsoftGraph.key; - } - // optionalAttrs (cfg.socialAuth.microsoftGraph.secret != null) { - SOCIAL_AUTH_MICROSOFT_GRAPH_SECRET = cfg.socialAuth.microsoftGraph.secret; - } - // optionalAttrs (cfg.socialAuth.googleOauth2.key != null) { - SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = cfg.socialAuth.googleOauth2.key; - } - // optionalAttrs (cfg.socialAuth.googleOauth2.secret != null) { - SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = cfg.socialAuth.googleOauth2.secret; - } - // cfg.extraEnvironment; - -in -{ - imports = [ ./options.nix ]; - - config = mkIf cfg.enable { - # Create user and group - users.users.${cfg.user} = { - isSystemUser = true; - group = cfg.group; - home = cfg.dataDir; - createHome = true; - description = "Tabby Web service user"; - }; - - users.groups.${cfg.group} = { }; - - # Ensure data directory exists with correct permissions - systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' 0750 ${cfg.user} ${cfg.group} - -" - "d '${cfg.dataDir}/dist' 0750 ${cfg.user} ${cfg.group} - -" - ]; - - # Create the systemd service - systemd.services.tabby-web = { - description = "Tabby Web Terminal Application Server"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ] ++ optional (hasPrefix "postgresql://" cfg.databaseUrl) "postgresql.service"; - - environment = environmentVars; - - serviceConfig = { - Type = "exec"; - User = cfg.user; - Group = cfg.group; - WorkingDirectory = cfg.dataDir; - - # Use the tabby-web package from our custom packages - ExecStart = "${pkgs.${namespace}.tabby-web}/bin/tabby-web --workers ${toString cfg.workers} --timeout ${toString cfg.timeout}"; - - # Run database migrations before starting the service - ExecStartPre = "${pkgs.${namespace}.tabby-web}/bin/tabby-web-manage migrate"; - - # Security settings - NoNewPrivileges = true; - ProtectSystem = "strict"; - ProtectHome = true; - ReadWritePaths = [ cfg.dataDir ]; - PrivateTmp = true; - ProtectKernelTunables = true; - ProtectKernelModules = true; - ProtectControlGroups = true; - RestrictSUIDSGID = true; - RestrictRealtime = true; - RestrictNamespaces = true; - LockPersonality = true; - MemoryDenyWriteExecute = true; - - # Restart policy - Restart = "always"; - RestartSec = "10s"; - - # Resource limits - LimitNOFILE = "65536"; - }; - - # Ensure the service starts after database if using PostgreSQL - requisite = mkIf (hasPrefix "postgresql://" cfg.databaseUrl) [ "postgresql.service" ]; - }; - - # Open firewall if requested - networking.firewall = mkIf cfg.openFirewall { - allowedTCPPorts = [ cfg.port ]; - }; - - # Add the tabby-web package to system packages - environment.systemPackages = [ pkgs.${namespace}.tabby-web ]; - }; -} diff --git a/modules/nixos/services/tabby-web/example.nix b/modules/nixos/services/tabby-web/example.nix deleted file mode 100644 index b15b81e..0000000 --- a/modules/nixos/services/tabby-web/example.nix +++ /dev/null @@ -1,45 +0,0 @@ -# Example configuration for Tabby Web service -# Add this to your NixOS configuration to enable tabby-web - -{ - # Basic configuration - SQLite database, local storage - mjallen.services.tabby-web = { - enable = true; - port = 9000; - openFirewall = true; - }; - - # Advanced configuration example (commented out) - /* - mjallen.services.tabby-web = { - enable = true; - port = 8080; - openFirewall = true; - - # Use PostgreSQL database - databaseUrl = "postgresql://tabby:password@localhost:5432/tabby"; - - # Use S3 for app distribution storage - appDistStorage = "s3://my-bucket/tabby-dist"; - - # Configure GitHub OAuth - socialAuth.github = { - key = "your-github-oauth-key"; - secret = "your-github-oauth-secret"; - }; - - # Performance tuning - workers = 8; - timeout = 300; - - # Custom data directory - dataDir = "/srv/tabby-web"; - - # Additional environment variables - extraEnvironment = { - DEBUG = "0"; - LOG_LEVEL = "info"; - }; - }; - */ -} diff --git a/modules/nixos/services/tabby-web/options.nix b/modules/nixos/services/tabby-web/options.nix deleted file mode 100644 index 1a62974..0000000 --- a/modules/nixos/services/tabby-web/options.nix +++ /dev/null @@ -1,127 +0,0 @@ -{ lib, namespace, ... }: -with lib; -{ - options.${namespace}.services.tabby-web = { - enable = mkEnableOption "Tabby Web terminal application server"; - - port = mkOption { - type = types.port; - default = 9000; - description = "Port for tabby-web server"; - }; - - openFirewall = mkOption { - type = types.bool; - default = false; - description = "Whether to open firewall for tabby-web"; - }; - - user = mkOption { - type = types.str; - default = "tabby-web"; - description = "User to run tabby-web as"; - }; - - group = mkOption { - type = types.str; - default = "tabby-web"; - description = "Group to run tabby-web as"; - }; - - dataDir = mkOption { - type = types.path; - default = "/var/lib/tabby-web"; - description = "Directory to store tabby-web data"; - }; - - databaseUrl = mkOption { - type = types.str; - default = "sqlite:///var/lib/tabby-web/tabby.db"; - description = "Database connection URL"; - example = "postgresql://user:password@localhost:5432/tabby"; - }; - - appDistStorage = mkOption { - type = types.str; - default = "file:///var/lib/tabby-web/dist"; - description = "Storage URL for app distributions"; - example = "s3://my-bucket/tabby-dist"; - }; - - socialAuth = { - github = { - key = mkOption { - type = types.nullOr types.str; - default = null; - description = "GitHub OAuth key"; - }; - secret = mkOption { - type = types.nullOr types.str; - default = null; - description = "GitHub OAuth secret"; - }; - }; - - gitlab = { - key = mkOption { - type = types.nullOr types.str; - default = null; - description = "GitLab OAuth key"; - }; - secret = mkOption { - type = types.nullOr types.str; - default = null; - description = "GitLab OAuth secret"; - }; - }; - - microsoftGraph = { - key = mkOption { - type = types.nullOr types.str; - default = null; - description = "Microsoft Graph OAuth key"; - }; - secret = mkOption { - type = types.nullOr types.str; - default = null; - description = "Microsoft Graph OAuth secret"; - }; - }; - - googleOauth2 = { - key = mkOption { - type = types.nullOr types.str; - default = null; - description = "Google OAuth2 key"; - }; - secret = mkOption { - type = types.nullOr types.str; - default = null; - description = "Google OAuth2 secret"; - }; - }; - }; - - extraEnvironment = mkOption { - type = types.attrsOf types.str; - default = { }; - description = "Extra environment variables for tabby-web"; - example = { - DEBUG = "1"; - LOG_LEVEL = "info"; - }; - }; - - workers = mkOption { - type = types.ints.positive; - default = 4; - description = "Number of gunicorn worker processes"; - }; - - timeout = mkOption { - type = types.ints.positive; - default = 120; - description = "Worker timeout in seconds"; - }; - }; -} diff --git a/modules/nixos/services/traefik/default.nix b/modules/nixos/services/traefik/default.nix index 6f79a97..c33e089 100755 --- a/modules/nixos/services/traefik/default.nix +++ b/modules/nixos/services/traefik/default.nix @@ -9,42 +9,46 @@ let cfg = config.${namespace}.services.traefik; # Process extraServices into service configurations - extraServiceConfigs = + extraServiceConfigs = let - makeService = service: nameValuePair service.name { - loadBalancer.servers = [ - { - url = service.url; - } - ]; - }; + makeService = + service: + nameValuePair service.name { + loadBalancer.servers = [ + { + url = service.url; + } + ]; + }; in listToAttrs (map makeService cfg.extraServices); # Process extraRouters into router configurations - extraRouterConfigs = + extraRouterConfigs = let - makeRouter = router: nameValuePair router.subdomain { - entryPoints = router.entryPoints; - rule = "Host(`${router.subdomain}.${domain}`)"; - service = router.service; - middlewares = router.middlewares ++ [ - "crowdsec" - "whitelist-geoblock" - ]; - tls.certResolver = "letsencrypt"; - }; + makeRouter = + router: + nameValuePair router.subdomain { + entryPoints = router.entryPoints; + rule = "Host(`${router.subdomain}.${domain}`)"; + service = router.service; + middlewares = router.middlewares ++ [ + "crowdsec" + "whitelist-geoblock" + ]; + tls.certResolver = "letsencrypt"; + }; in listToAttrs (map makeRouter cfg.extraRouters); # Process reverseProxies into service and router configurations - reverseProxyServiceConfigs = + reverseProxyServiceConfigs = let makeService = reverseProxy: nameValuePair reverseProxy.service.name reverseProxy.service.config; in listToAttrs (map makeService cfg.reverseProxies); - reverseProxyRouterConfigs = + reverseProxyRouterConfigs = let makeRouter = reverseProxy: nameValuePair reverseProxy.router.subdomain reverseProxy.router.config; in @@ -292,7 +296,7 @@ in url = authUrl; } ]; - + authentik.loadBalancer.servers = [ { url = authentikUrl; @@ -348,7 +352,9 @@ in url = paperlessUrl; } ]; - } // extraServiceConfigs // reverseProxyServiceConfigs; + } + // extraServiceConfigs + // reverseProxyServiceConfigs; routers = { auth = { @@ -457,7 +463,9 @@ in ]; tls.certResolver = "letsencrypt"; }; - } // extraRouterConfigs // reverseProxyRouterConfigs; + } + // extraRouterConfigs + // reverseProxyRouterConfigs; }; }; }; diff --git a/modules/nixos/services/traefik/options.nix b/modules/nixos/services/traefik/options.nix index 7b163e0..2bf323b 100644 --- a/modules/nixos/services/traefik/options.nix +++ b/modules/nixos/services/traefik/options.nix @@ -1,34 +1,42 @@ { lib, namespace, ... }: with lib; let - inherit (lib.${namespace}) mkOpt mkBoolOpt; + inherit (lib.${namespace}) mkOpt; in { options.${namespace}.services.traefik = { enable = mkEnableOption "enable traefik"; - extraServices = mkOpt (types.listOf (types.submodule { - options = { - name = mkOpt types.str "" "Name of the service"; - url = mkOpt types.str "http://localhost:8080" "Url of the service"; - }; - })) [ ] "List of extra services to forward"; + extraServices = mkOpt (types.listOf ( + types.submodule { + options = { + name = mkOpt types.str "" "Name of the service"; + url = mkOpt types.str "http://localhost:8080" "Url of the service"; + }; + } + )) [ ] "List of extra services to forward"; - extraRouters = mkOpt (types.listOf (types.submodule { - options = { - entryPoints = mkOpt (types.listOf types.str) [ "websecure" ] "Entrypoint"; - subdomain = mkOpt types.str "" "subdomain of the service"; - service = mkOpt types.str "" "name of the service"; - middlewares = mkOpt (types.listOf (types.enum [ - "authentik" - "onlyoffice-websocket" - "crowdsec" - "whitelist-geoblock" - "internal-ipallowlist" - ])) [ ] "List of middlewares to enable"; - }; - })) [ ] "List of extra services to forward"; + extraRouters = mkOpt (types.listOf ( + types.submodule { + options = { + entryPoints = mkOpt (types.listOf types.str) [ "websecure" ] "Entrypoint"; + subdomain = mkOpt types.str "" "subdomain of the service"; + service = mkOpt types.str "" "name of the service"; + middlewares = mkOpt (types.listOf ( + types.enum [ + "authentik" + "onlyoffice-websocket" + "crowdsec" + "whitelist-geoblock" + "internal-ipallowlist" + ] + )) [ ] "List of middlewares to enable"; + }; + } + )) [ ] "List of extra services to forward"; - reverseProxies = mkOpt (types.listOf types.attrs) [ ] "List of reverse proxy configurations from mkReverseProxy"; + reverseProxies = + mkOpt (types.listOf types.attrs) [ ] + "List of reverse proxy configurations from mkReverseProxy"; }; } diff --git a/modules/nixos/services/wyoming/default.nix b/modules/nixos/services/wyoming/default.nix index a305714..d419c49 100755 --- a/modules/nixos/services/wyoming/default.nix +++ b/modules/nixos/services/wyoming/default.nix @@ -23,14 +23,14 @@ in uri = "tcp://0.0.0.0:10300"; }; - piper = { - package = pkgs.stable.wyoming-piper; - servers.hass-piper = { - enable = true; - voice = "en-us-ryan-high"; - uri = "tcp://0.0.0.0:10200"; - }; - }; + # piper = { + # package = pkgs.stable.wyoming-piper; + # servers.hass-piper = { + # enable = true; + # voice = "en-us-ryan-high"; + # uri = "tcp://0.0.0.0:10200"; + # }; + # }; }; }; } diff --git a/packages/bolt-launcher/default.nix b/packages/bolt-launcher/default.nix index cc23eac..44374a8 100644 --- a/packages/bolt-launcher/default.nix +++ b/packages/bolt-launcher/default.nix @@ -1,44 +1,45 @@ -{ lib -, stdenv -, fetchzip -, autoPatchelfHook -, makeWrapper -# Core dependencies -, alsa-lib -, at-spi2-core -, cairo -, cups -, dbus -, expat -, fontconfig -, freetype -, gdk-pixbuf -, glib -, gtk3 -, libarchive -, libdrm -, libGL -, libx11 -, libxcb -, libxext -, libxkbcommon -, mesa -, nspr -, nss -, pango -, systemd -, xorg -, zlib -# Additional CEF/Chromium dependencies -, libnotify -, libpulseaudio -, libuuid -, libva -, pipewire -, udev -, wayland -, jdk17 # for RuneLite/HDOS -, gtk2 ? null # for RS3 +{ + lib, + stdenv, + fetchzip, + autoPatchelfHook, + makeWrapper, + # Core dependencies + alsa-lib, + at-spi2-core, + cairo, + cups, + dbus, + expat, + fontconfig, + freetype, + gdk-pixbuf, + glib, + gtk3, + libarchive, + libdrm, + libGL, + libx11, + libxcb, + libxext, + libxkbcommon, + mesa, + nspr, + nss, + pango, + systemd, + xorg, + zlib, + # Additional CEF/Chromium dependencies + libnotify, + libpulseaudio, + libuuid, + libva, + pipewire, + udev, + wayland, + jdk17 # for RuneLite/HDOS + , # for RS3 }: stdenv.mkDerivation rec { @@ -79,7 +80,7 @@ stdenv.mkDerivation rec { nspr nss pango - stdenv.cc.cc.lib # for libstdc++.so.6 + stdenv.cc.cc.lib # for libstdc++.so.6 systemd zlib # Additional CEF/Chromium deps @@ -90,7 +91,8 @@ stdenv.mkDerivation rec { pipewire udev wayland - ] ++ (with xorg; [ + ] + ++ (with xorg; [ libXcomposite libXcursor libXdamage @@ -119,10 +121,10 @@ stdenv.mkDerivation rec { # Copy all files to lib directory cp -r ./bolt-launcher/* $out/lib/bolt-launcher/ - + # The main executable is 'bolt' (lowercase) chmod +x $out/lib/bolt-launcher/bolt - + # Also make chrome-sandbox executable (needed for CEF) if [ -f $out/lib/bolt-launcher/chrome-sandbox ]; then chmod +x $out/lib/bolt-launcher/chrome-sandbox @@ -155,7 +157,7 @@ stdenv.mkDerivation rec { # Make sure they can find each other patchelf --set-rpath "$out/lib/bolt-launcher:${lib.makeLibraryPath buildInputs}" \ $out/lib/bolt-launcher/bolt || true - + # Patch the CEF libraries for lib in $out/lib/bolt-launcher/*.so*; do if [ -f "$lib" ]; then @@ -168,8 +170,11 @@ stdenv.mkDerivation rec { description = "Free open-source third-party implementation of the Jagex Launcher"; homepage = "https://bolt.adamcake.com/"; license = licenses.agpl3Only; - platforms = [ "x86_64-linux" "aarch64-linux" ]; + platforms = [ + "x86_64-linux" + "aarch64-linux" + ]; maintainers = with maintainers; [ ]; sourceProvenance = with sourceTypes; [ binaryNativeCode ]; }; -} \ No newline at end of file +} diff --git a/packages/homeassistant/ha-bedjet/default.nix b/packages/homeassistant/ha-bedjet/default.nix index 115812a..5e886c7 100644 --- a/packages/homeassistant/ha-bedjet/default.nix +++ b/packages/homeassistant/ha-bedjet/default.nix @@ -20,7 +20,7 @@ buildHomeAssistantComponent rec { beautifulsoup4 ]; - meta = { + meta = { changelog = "https://github.com/natekspencer/ha-bedjet/releases/tag/${version}"; description = "This project provides various entities to allow control of a BedJet device."; homepage = "https://github.com/natekspencer/ha-bedjet"; diff --git a/packages/nextcloud/nextcloud-app-photos/default.nix b/packages/nextcloud/nextcloud-app-photos/default.nix index 32c4ac4..b0eb3ca 100644 --- a/packages/nextcloud/nextcloud-app-photos/default.nix +++ b/packages/nextcloud/nextcloud-app-photos/default.nix @@ -7,4 +7,4 @@ fetchNextcloudApp { sha256 = "sha256-F2hh/0RlLG2zcEatfd4fejRV0i2hMkwONM4P7nhdh18="; url = "https://github.com/nextcloud/photos/archive/refs/tags/v31.0.8.tar.gz"; license = "agpl3Only"; -} \ No newline at end of file +} diff --git a/packages/python/python-roborock/default.nix b/packages/python/python-roborock/default.nix index 8e5faa4..dbe1225 100644 --- a/packages/python/python-roborock/default.nix +++ b/packages/python/python-roborock/default.nix @@ -29,20 +29,22 @@ python3Packages.buildPythonPackage rec { build-system = with python3Packages; [ poetry-core ]; - dependencies = with python3Packages; [ - aiohttp - aiomqtt - async-timeout - click - construct - dacite - paho-mqtt - pycryptodome - pyrate-limiter - vacuum-map-parser-roborock - pyshark - ] - ++ lib.optionals stdenv.hostPlatform.isDarwin [ pycryptodomex ]; + dependencies = + with python3Packages; + [ + aiohttp + aiomqtt + async-timeout + click + construct + dacite + paho-mqtt + pycryptodome + pyrate-limiter + vacuum-map-parser-roborock + pyshark + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ pycryptodomex ]; nativeCheckInputs = with python3Packages; [ aioresponses @@ -61,4 +63,4 @@ python3Packages.buildPythonPackage rec { maintainers = with maintainers; [ fab ]; mainProgram = "roborock"; }; -} \ No newline at end of file +} diff --git a/packages/python/pyvesync/default.nix b/packages/python/pyvesync/default.nix index b4bc6ce..e640ea5 100644 --- a/packages/python/pyvesync/default.nix +++ b/packages/python/pyvesync/default.nix @@ -35,4 +35,4 @@ python3Packages.buildPythonPackage rec { license = with licenses; [ mit ]; maintainers = with maintainers; [ fab ]; }; -} \ No newline at end of file +} diff --git a/packages/tabby-web/default.nix b/packages/tabby-web/default.nix index 8bfa033..5f7ff1e 100644 --- a/packages/tabby-web/default.nix +++ b/packages/tabby-web/default.nix @@ -53,7 +53,7 @@ stdenv.mkDerivation rec { # Set up yarn export HOME=$TMPDIR cd frontend - + # Fix up yarn.lock and set up offline cache fixup-yarn-lock yarn.lock yarn config --offline set yarn-offline-mirror ${yarnDeps} @@ -82,98 +82,107 @@ stdenv.mkDerivation rec { ''; installPhase = '' - runHook preInstall + runHook preInstall - # Create output directories - mkdir -p $out/lib/tabby-web - mkdir -p $out/bin - mkdir -p $out/share/tabby-web + # Create output directories + mkdir -p $out/lib/tabby-web + mkdir -p $out/bin + mkdir -p $out/share/tabby-web - # Install backend - cp -r backend/* $out/lib/tabby-web/ - - # Install frontend build output - if [ -d frontend/dist ]; then - cp -r frontend/dist/* $out/share/tabby-web/ - elif [ -d frontend/build ]; then - cp -r frontend/build/* $out/share/tabby-web/ - fi + # Install backend + cp -r backend/* $out/lib/tabby-web/ + + # Install frontend build output + if [ -d frontend/dist ]; then + cp -r frontend/dist/* $out/share/tabby-web/ + elif [ -d frontend/build ]; then + cp -r frontend/build/* $out/share/tabby-web/ + fi - # Create main executable wrapper - makeWrapper ${python3.withPackages (ps: with ps; [ gunicorn django ])}/bin/python $out/bin/tabby-web \ - --add-flags "-m gunicorn tabby_web.wsgi:application" \ - --set PYTHONPATH "$out/lib/tabby-web" \ - --set DJANGO_SETTINGS_MODULE "tabby_web.settings" \ - --set STATIC_ROOT "$out/share/tabby-web" \ - --run "cd $out/lib/tabby-web" \ - --run 'export DATABASE_URL="''${DATABASE_URL:-sqlite:///tmp/tabby-web.db}"' \ - --run 'export APP_DIST_STORAGE="''${APP_DIST_STORAGE:-file:///tmp/tabby-web-dist}"' \ - --run 'export PORT="''${PORT:-9000}"' \ - --add-flags '--bind "0.0.0.0:$PORT"' \ - --add-flags "--workers 4" \ - --add-flags "--timeout 120" + # Create main executable wrapper + makeWrapper ${ + python3.withPackages ( + ps: with ps; [ + gunicorn + django + ] + ) + }/bin/python $out/bin/tabby-web \ + --add-flags "-m gunicorn tabby_web.wsgi:application" \ + --set PYTHONPATH "$out/lib/tabby-web" \ + --set DJANGO_SETTINGS_MODULE "tabby_web.settings" \ + --set STATIC_ROOT "$out/share/tabby-web" \ + --run "cd $out/lib/tabby-web" \ + --run 'export DATABASE_URL="''${DATABASE_URL:-sqlite:///tmp/tabby-web.db}"' \ + --run 'export APP_DIST_STORAGE="''${APP_DIST_STORAGE:-file:///tmp/tabby-web-dist}"' \ + --run 'export PORT="''${PORT:-9000}"' \ + --add-flags '--bind "0.0.0.0:$PORT"' \ + --add-flags "--workers 4" \ + --add-flags "--timeout 120" - # Create Django management wrapper - makeWrapper ${python3.withPackages (ps: with ps; [ django ])}/bin/python $out/bin/tabby-web-manage \ - --add-flags "manage.py" \ - --set PYTHONPATH "$out/lib/tabby-web" \ - --set DJANGO_SETTINGS_MODULE "tabby_web.settings" \ - --set STATIC_ROOT "$out/share/tabby-web" \ - --run "cd $out/lib/tabby-web" \ - --run 'export DATABASE_URL="''${DATABASE_URL:-sqlite:///tmp/tabby-web.db}"' \ - --run 'export APP_DIST_STORAGE="''${APP_DIST_STORAGE:-file:///tmp/tabby-web-dist}"' + # Create Django management wrapper + makeWrapper ${ + python3.withPackages (ps: with ps; [ django ]) + }/bin/python $out/bin/tabby-web-manage \ + --add-flags "manage.py" \ + --set PYTHONPATH "$out/lib/tabby-web" \ + --set DJANGO_SETTINGS_MODULE "tabby_web.settings" \ + --set STATIC_ROOT "$out/share/tabby-web" \ + --run "cd $out/lib/tabby-web" \ + --run 'export DATABASE_URL="''${DATABASE_URL:-sqlite:///tmp/tabby-web.db}"' \ + --run 'export APP_DIST_STORAGE="''${APP_DIST_STORAGE:-file:///tmp/tabby-web-dist}"' - # Create a help script - cat > $out/bin/tabby-web-help << 'HELP_EOF' -#!/bin/bash -cat << 'HELP' -Tabby Web - Terminal application server + # Create a help script + cat > $out/bin/tabby-web-help << 'HELP_EOF' + #!/bin/bash + cat << 'HELP' + Tabby Web - Terminal application server -Usage: - tabby-web Start the server - tabby-web-manage Run Django management commands - tabby-web-help Show this help + Usage: + tabby-web Start the server + tabby-web-manage Run Django management commands + tabby-web-help Show this help -Environment Variables: - DATABASE_URL Database connection URL - Examples: sqlite:///path/to/db.sqlite - postgresql://user:pass@host:5432/dbname - - APP_DIST_STORAGE Storage URL for app distributions - Examples: file:///path/to/storage - s3://bucket-name/path - gcs://bucket-name/path - - PORT Server port (default: 9000) - - Social Authentication (optional): - SOCIAL_AUTH_GITHUB_KEY GitHub OAuth key - SOCIAL_AUTH_GITHUB_SECRET GitHub OAuth secret - SOCIAL_AUTH_GITLAB_KEY GitLab OAuth key - SOCIAL_AUTH_GITLAB_SECRET GitLab OAuth secret - SOCIAL_AUTH_MICROSOFT_GRAPH_KEY Microsoft Graph OAuth key - SOCIAL_AUTH_MICROSOFT_GRAPH_SECRET Microsoft Graph OAuth secret - SOCIAL_AUTH_GOOGLE_OAUTH2_KEY Google OAuth2 key - SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET Google OAuth2 secret + Environment Variables: + DATABASE_URL Database connection URL + Examples: sqlite:///path/to/db.sqlite + postgresql://user:pass@host:5432/dbname + + APP_DIST_STORAGE Storage URL for app distributions + Examples: file:///path/to/storage + s3://bucket-name/path + gcs://bucket-name/path + + PORT Server port (default: 9000) + + Social Authentication (optional): + SOCIAL_AUTH_GITHUB_KEY GitHub OAuth key + SOCIAL_AUTH_GITHUB_SECRET GitHub OAuth secret + SOCIAL_AUTH_GITLAB_KEY GitLab OAuth key + SOCIAL_AUTH_GITLAB_SECRET GitLab OAuth secret + SOCIAL_AUTH_MICROSOFT_GRAPH_KEY Microsoft Graph OAuth key + SOCIAL_AUTH_MICROSOFT_GRAPH_SECRET Microsoft Graph OAuth secret + SOCIAL_AUTH_GOOGLE_OAUTH2_KEY Google OAuth2 key + SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET Google OAuth2 secret -Examples: - # Development with defaults - tabby-web - - # Production with PostgreSQL - DATABASE_URL="postgresql://user:pass@localhost:5432/tabby" tabby-web - - # Run migrations - tabby-web-manage migrate - - # Add app version - tabby-web-manage add_version 1.0.156-nightly.2 -HELP -HELP_EOF + Examples: + # Development with defaults + tabby-web + + # Production with PostgreSQL + DATABASE_URL="postgresql://user:pass@localhost:5432/tabby" tabby-web + + # Run migrations + tabby-web-manage migrate + + # Add app version + tabby-web-manage add_version 1.0.156-nightly.2 + HELP + HELP_EOF - chmod +x $out/bin/tabby-web-help + chmod +x $out/bin/tabby-web-help - runHook postInstall + runHook postInstall ''; meta = with lib; { diff --git a/secrets/nas-secrets.yaml b/secrets/nas-secrets.yaml index d646ee1..6152612 100644 --- a/secrets/nas-secrets.yaml +++ b/secrets/nas-secrets.yaml @@ -9,6 +9,7 @@ jallen-nas: cloudflare-zone-api-token: ENC[AES256_GCM,data:N02jcaPLYVzOmo5omGvOKUw2MZg8/cVolRcw/pu+sFnV8IsrUFOjmA==,iv:NZ+OaNR5lmsXicYQ7QL9CBMhlm397VbqmIcmr6GGBWw=,tag:FOT0EzDDuJ/kKOArn8e/rA==,type:str] cloudflare-api-key: ENC[AES256_GCM,data:SWCsa1YzUpl5aQmeVBzKjfkZdAfduX8pl5RKd+EP6pgyMCCc6Q==,iv:ccIzA1OzGyRnq8gxXAg4B3HHtKcvXhXKMWVuTs/PHLI=,tag:R9KrYDrAluTAyuv7DfYVWQ==,type:str] cloudflare-email: ENC[AES256_GCM,data:WCe6JlTQnv2PXYcySZNbZ5Lv,iv:qc+o+GEqdRm3U5qBqvH23HOah3Sa63QzqZyDXWozcqo=,tag:v8YY3jCoVC8h12wHTFjkIg==,type:str] + crowdsec-capi: ENC[AES256_GCM,data:9T3e6CzJZOT1KAXlpG323oPmk9xsoVVWI/WYnhdmzyymj61LgNJKvA==,iv:NywJk/tkmIGR5jIgxpvheRBCrK64QytXAkr+40nn62M=,tag:XFeafjL/84r0fLa8UpjyjQ==,type:str] collabora: ENC[AES256_GCM,data:tFbbm16DFMsxT0I1ogXTRwyTgkE=,iv:yzembXvJ9+DroplBUDiMPa/jn9pjpAI7f5oHSTaZedA=,tag:yprIBtaRIjaHW6nplLYYzQ==,type:str] mariadb: root_pass: ENC[AES256_GCM,data:AmZ3lU/GM9lMAjchF4kvjkIZlYX0KZV7ov0dxtnDmg==,iv:9JQuHWcb3/lCR3gw4PFtzMKxk85GXzFV35NguJydUkk=,tag:MEvmiYhAYa1LUGTN9wm/3w==,type:str] @@ -173,8 +174,8 @@ sops: NXZkbVZyV0VtTzArOE1uU1JwMXZZN0EKLDU1x+rIWecDD9x//huoM2BM9NRSa4g1 L5nodU/J0XsfB9z3kr7eY5LYSwsqGkAxI1cXJYZGHF+bozJjweyXTQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-09-17T02:00:58Z" - mac: ENC[AES256_GCM,data:l1J7omMlj1orONfmsgvGG+DZvdv5GmsdvQmUqPml9EfE7gF0ZoioEaGfcWDLBfutH9VU/9cWLclNbDinqL63m7/tAvv/8LGVvJ0s1T8xbAbu7d95+hXH7rMVU6C15h+maXLV4wNlFJFlNp1cFmZzmJmG3scXPZQ1aJM33ol/hV0=,iv:67MnPLlTh1WO6c15hB4LkeKc91r8epS5MZWT6LCOVRk=,tag:msZ3iBU+poU3BRDtV6G5zg==,type:str] + lastmodified: "2025-09-30T23:04:02Z" + mac: ENC[AES256_GCM,data:rDWyDZSXNGs2q4epxCQBI5Mj8E5Dpen6F6cUU7NxTVlOI933Gi12bdpuFghrjEf2S1Lk0u/duOM07q2NJrsMOgVPws2f/jzcCzcpPeaUsrD1vkQUpCr2hUKNjSIEbrrtwanm2vbr0LMV0noxFluf68fpeph+/ZMe8eqJjxXWK+A=,iv:DvmxVM7m76trz5aXx/Llsrqmk53uTipo4SHaOdc2YUM=,tag:cIC5iF7+iaIjwLiYR22exg==,type:str] pgp: - created_at: "2025-08-24T02:21:34Z" enc: |- diff --git a/systems/aarch64-darwin/macbook-pro/trampoline-apps/default.nix b/systems/aarch64-darwin/macbook-pro/trampoline-apps/default.nix index 3f7b5c4..01226c1 100755 --- a/systems/aarch64-darwin/macbook-pro/trampoline-apps/default.nix +++ b/systems/aarch64-darwin/macbook-pro/trampoline-apps/default.nix @@ -1,7 +1,6 @@ # Hook home-manager to make a trampoline for each app we install # from: https://github.com/nix-community/home-manager/issues/1341#issuecomment-1870352014 { - config, lib, pkgs, ... diff --git a/systems/aarch64-linux/pi4/default.nix b/systems/aarch64-linux/pi4/default.nix index c305eee..f2bc65c 100755 --- a/systems/aarch64-linux/pi4/default.nix +++ b/systems/aarch64-linux/pi4/default.nix @@ -77,7 +77,7 @@ } ]; }; - + virtualisation = { docker.enable = false; podman.enable = false; diff --git a/systems/aarch64-linux/pi5/default.nix b/systems/aarch64-linux/pi5/default.nix index 5859eaf..8a4893f 100644 --- a/systems/aarch64-linux/pi5/default.nix +++ b/systems/aarch64-linux/pi5/default.nix @@ -8,7 +8,7 @@ }: { imports = [ -# ./adguard.nix + # ./adguard.nix ./boot.nix ./sops.nix ]; @@ -93,7 +93,7 @@ device = "/dev/disk/bu-uuid/a85420cc-a026-4100-80d2-a999081d792a"; fsType = "bcachefs"; options = [ - "nofail" + "nofail" ]; }; } diff --git a/systems/x86_64-linux/jallen-nas/apps.nix b/systems/x86_64-linux/jallen-nas/apps.nix index 52304f8..2864c9c 100755 --- a/systems/x86_64-linux/jallen-nas/apps.nix +++ b/systems/x86_64-linux/jallen-nas/apps.nix @@ -1,4 +1,4 @@ -{ namespace, ... }: +{ config, namespace, ... }: { ${namespace} = { services = { @@ -67,7 +67,7 @@ enable = true; port = 9898; apiAddress = "10.0.1.3"; - apiKey = "1daH89qmJ41r2Lpd9hvDw4sxtOAtBzaj3aKFOFqE"; + apiKey = config.sops.secrets."jallen-nas/crowdsec-capi".path; dataDir = "/media/nas/main/nix-app-data/crowdsec"; }; diff --git a/systems/x86_64-linux/jallen-nas/default.nix b/systems/x86_64-linux/jallen-nas/default.nix index fb6df51..a5eb38f 100755 --- a/systems/x86_64-linux/jallen-nas/default.nix +++ b/systems/x86_64-linux/jallen-nas/default.nix @@ -249,9 +249,9 @@ in mountPoint = "/media/nas/main"; options = [ "noauto" - "nofail" - # "x-systemd.mount-timeout=0" - # "x-systemd.device-timeout=0" + "nofail" + # "x-systemd.mount-timeout=0" + # "x-systemd.device-timeout=0" ]; }; diff --git a/systems/x86_64-linux/jallen-nas/sops.nix b/systems/x86_64-linux/jallen-nas/sops.nix index 79f7f58..0b1f590 100755 --- a/systems/x86_64-linux/jallen-nas/sops.nix +++ b/systems/x86_64-linux/jallen-nas/sops.nix @@ -94,6 +94,15 @@ in restartUnits = [ "podman-collabora.service" ]; }; + # ------------------------------ + # crowdsec + # ------------------------------ + + "jallen-nas/crowdsec-capi" = { + sopsFile = defaultSops; + restartUnits = [ "crowdsec.service" ]; + }; + # ------------------------------ # mariadb # TODO # ------------------------------