From 9a1e9e0c31e3497c7a0560996ae9a9878cf8bec6 Mon Sep 17 00:00:00 2001 From: Clayton Hickey Date: Tue, 18 Nov 2025 17:14:20 -0500 Subject: [PATCH] add nixnas config --- bikeability.nix | 114 +++++++++++++++ clhickey-nixos/configuration.nix | 2 + cos.nix | 1 + flake.nix | 6 + gnupg.nix | 16 ++- nixnas/hardware-configuration.nix | 53 +++++++ nixnas/nixnas.nix | 222 ++++++++++++++++++++++++++++++ 7 files changed, 411 insertions(+), 3 deletions(-) create mode 100755 bikeability.nix create mode 100644 nixnas/hardware-configuration.nix create mode 100644 nixnas/nixnas.nix diff --git a/bikeability.nix b/bikeability.nix new file mode 100755 index 0000000..367878a --- /dev/null +++ b/bikeability.nix @@ -0,0 +1,114 @@ +{ lib, pkgs, config, ... }: +let + cfg = config.cos.bikeability; +in +{ + imports = []; + + options.cos.bikeability = { + enable = lib.mkEnableOption "Bikeability server"; + dataDir = lib.mkOption { + type = lib.types.path; + }; + tileserverHost = lib.mkOption { + type = lib.types.str; + default = "0.0.0.0"; + }; + tileserverPort = lib.mkOption { + type = lib.types.port; + default = 8000; + }; + clientHost = lib.mkOption { + type = lib.types.str; + default = "0.0.0.0"; + }; + clientPort = lib.mkOption { + type = lib.types.port; + default = 8000; + }; + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + }; + firewallInterface = lib.mkOption { + type = lib.types.str; + default = ""; + }; + fetchAndRenderTimerConfig = lib.mkOption { + type = lib.types.attrs; + default = { + OnCalendar = "daily"; + Persistent = true; + }; + }; + }; + + config = lib.mkIf cfg.enable { + + systemd.services.bikeability-tileserver = { + description = "bikeability-tileserver.claytonhickey.me"; + wantedBy = [ "default.target" ]; + script = ''#!/bin/sh + cd ${cfg.dataDir} && + ${pkgs.mbtileserver}/bin/mbtileserver --host ${cfg.tileserverHost} --port ${builtins.toString cfg.tileserverPort} --enable-fs-watch + ''; + serviceConfig = { + Restart = "on-failure"; + }; + }; + + virtualisation.oci-containers.containers.tileserver-gl = { + image = "maptiler/tileserver-gl:latest"; + volumes = [ + "${cfg.dataDir}/tileserver-gl-data:/data" + ]; + ports = [ + "${cfg.clientHost}:9000:8080" + ]; + }; + + systemd.services.bikeability-fetch-and-render = { + script = '' + set -eu + cd ${cfg.dataDir}/bikeability-tilemaker + ls + PATH="${pkgs.wget}/bin:${pkgs.osmium-tool}/bin:$PATH" ./fetch-data.sh + ${pkgs.tilemaker}/bin/tilemaker --config ${cfg.dataDir}/bikeability-tilemaker/tilemaker-config.json --process ${cfg.dataDir}/bikeability-tilemaker/tilemaker-process.lua --output ${cfg.dataDir}/bikeability-new.mbtiles --input ${cfg.dataDir}/bikeability-tilemaker/data.osm.pbf + mv ${cfg.dataDir}/bikeability-new.mbtiles ${cfg.dataDir}/tilesets/bikeability.mbtiles + cp ${cfg.dataDir}/tilesets/bikeability.mbtiles ${cfg.dataDir}/tileserver-gl-data/bikeability.mbtiles + ''; + serviceConfig = { + Type = "oneshot"; + User = "clhickey"; + }; + }; + + systemd.timers.bikeability-fetch-and-render = { + wantedBy = [ "timers.target" ]; + timerConfig = cfg.fetchAndRenderTimerConfig // { + Unit = "bikeability-fetch-and-render.service"; + }; + }; + + services.nginx = { + enable = true; + virtualHosts."bikeability-client" = { + listen = [ { addr = cfg.clientHost; port = cfg.clientPort; } ]; + locations."/" = { + root = "${cfg.dataDir}/bikeability-client/"; + }; + }; + }; + + networking.firewall.allowedTCPPorts = lib.mkIf (cfg.openFirewall && cfg.firewallInterface == "") [ + cfg.tileserverPort + cfg.clientPort + ]; + + networking.firewall.interfaces.${cfg.firewallInterface}.allowedTCPPorts = lib.mkIf (cfg.openFirewall && cfg.firewallInterface != "") [ + cfg.tileserverPort + cfg.clientPort + ]; + + }; +} diff --git a/clhickey-nixos/configuration.nix b/clhickey-nixos/configuration.nix index 566f8e3..2fd9332 100644 --- a/clhickey-nixos/configuration.nix +++ b/clhickey-nixos/configuration.nix @@ -14,6 +14,8 @@ cos.remoteBuild.enable = false; + cos.gnupg.enable = true; + boot = { loader = { systemd-boot.enable = true; diff --git a/cos.nix b/cos.nix index b4f9d6c..f1cff87 100644 --- a/cos.nix +++ b/cos.nix @@ -7,6 +7,7 @@ ./docker.nix ./remoteBuild.nix ./gnupg.nix + ./bikeability.nix "${inputs.home-manager}/nixos" ]; diff --git a/flake.nix b/flake.nix index fed5653..f1fddf9 100644 --- a/flake.nix +++ b/flake.nix @@ -25,6 +25,12 @@ ./clhickey-nixos/configuration.nix ]; }; + nixosConfigurations.nixnas = nixpkgs.lib.nixosSystem { + specialArgs = { inherit inputs; }; + modules = [ + ./nixnas/nixnas.nix + ]; + }; }; } diff --git a/gnupg.nix b/gnupg.nix index b573183..dc8f4f9 100644 --- a/gnupg.nix +++ b/gnupg.nix @@ -1,4 +1,14 @@ -{pkgs, ...}: { - programs.gnupg.agent.enable = true; - programs.gnupg.agent.pinentryPackage = pkgs.pinentry-curses; +{pkgs, config, lib, ...}: +let + cfg = config.cos.gnupg; +in +{ + options.cos.gnupg = { + enable = lib.mkEnableOption "Bikeability server"; + }; + + config = lib.mkIf cfg.enable { + programs.gnupg.agent.enable = true; + programs.gnupg.agent.pinentryPackage = pkgs.pinentry-curses; + }; } diff --git a/nixnas/hardware-configuration.nix b/nixnas/hardware-configuration.nix new file mode 100644 index 0000000..f3621e0 --- /dev/null +++ b/nixnas/hardware-configuration.nix @@ -0,0 +1,53 @@ +# 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 = [ "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/29a93135-31be-4ede-b726-f687a9ecdac2"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/3711-B4A2"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + fileSystems."/Block" = { + device = "/dev/disk/by-uuid/97676339-b0c3-49df-9299-0fa382d1a1a7"; + fsType = "ext4"; + }; + + + swapDevices = + [ { device = "/dev/disk/by-uuid/1043f4d8-dc9d-4255-bcdc-ae09f05e08e7"; } + ]; + + # 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..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp3s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp0s26u1u1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + + hardware.graphics.enable = true; + services.xserver.videoDrivers = [ "nvidia" ]; + hardware.nvidia.open = false; + hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_390; + nixpkgs.config.nvidia.acceptLicense = true; +} diff --git a/nixnas/nixnas.nix b/nixnas/nixnas.nix new file mode 100644 index 0000000..012f91c --- /dev/null +++ b/nixnas/nixnas.nix @@ -0,0 +1,222 @@ +{ config, pkgs, inputs, ... }: +let + wireguardIP = config.cos.wireguard.clientInternalIP; + wireguardInterface = config.cos.wireguard.interface; + sshPort = 22; + jellyfinDataDir = "/Block/jellyfin/jellyfin-data"; + jellyfinCacheDir = "/Block/jellyfin/jellyfin-cache"; + jellyfinPort = 8096; + hydraPort = 7839; + nextcloudPort = 8120; +in +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ../cos.nix + ]; + + cos.username = "clhickey"; + cos.hostName = "nixnas"; + + cos.wireguard = { + enable = true; + privateKeyFile = "/Block/wireguard-keys/private"; + }; + + cos.bikeability = { + enable = true; + dataDir = "/Block/bikeability"; + tileserverHost = wireguardIP; + tileserverPort = 8000; + clientHost = wireguardIP; + clientPort = 8001; + openFirewall = true; + firewallInterface = wireguardInterface; + }; + + networking = { + firewall = { + interfaces = { + ${wireguardInterface} = { + allowedTCPPorts = [ + 80 + 443 + sshPort + jellyfinPort + hydraPort + nextcloudPort + ]; + allowedUDPPorts = [ + config.networking.wireguard.interfaces.${wireguardInterface}.listenPort + ]; + }; + }; + }; + }; + + services.openssh = { + enable = true; + openFirewall = false; + listenAddresses = [ + { + addr = wireguardIP; + port = sshPort; + } + ]; + }; + + nixpkgs = { + overlays = [ + (final: prev: { + jellyfin-ffmpeg = prev.jellyfin-ffmpeg.override { + ffmpeg_7-full = prev.ffmpeg_7-full.override { + withUnfree = true; + }; + }; + }) + ]; + config.allowUnfree = true; + }; + + environment.systemPackages = with pkgs; [ + inputs.cnvim.packages.x86_64-linux.default + wget + tilemaker + osmium-tool + osmctools + mbtileserver + git + gh + htop + wireguard-tools + fastfetch + ]; + + services.jellyfin = { + enable = true; + cacheDir = jellyfinCacheDir; + dataDir = jellyfinDataDir; + }; + + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; + + services.postgresql.dataDir = "/Block/postgresql"; + + services.hydra = { + enable = true; + hydraURL = "http://hydra.claytonhickey.me"; + notificationSender = "hydra@claytonhickey.me"; + buildMachinesFiles = []; + useSubstitutes = true; + listenHost = "127.0.0.1"; + port = hydraPort; + }; + + nix.buildMachines = [ + { + hostName = "localhost"; + protocol = null; + system = "x86_64-linux"; + supportedFeatures = [ "kvm" "nixos-test" "big-parallel" "benchmark" ]; + maxJobs = 4; + } + ]; + + services.nextcloud = { + enable = true; + package = pkgs.nextcloud32; + extraApps = let apps = config.services.nextcloud.package.packages.apps; in { + contacts = apps.contacts; + calendar = apps.calendar; + #tasks = apps.tasks; + news = apps.news; + notes = apps.notes; + forms = apps.forms; + richdocuments = apps.richdocuments; + #onlyoffice = apps.onlyoffice; + }; + extraAppsEnable = true; + hostName = "nextcloud.claytondoesthings.xyz"; + https = true; + maxUploadSize = "1G"; + config = { + adminpassFile = "${pkgs.writeText "adminpass" "@n2XuojRT9*&e5"}"; + adminuser = "clay53"; + dbtype = "sqlite"; + }; + home = "/Block/nextcloud"; + settings = { + log_type = "file"; + loglevel = 0; + trusted_proxies = [ + "10.100.0.1" + ]; + trusted_domains = [ + "${wireguardIP}:${builtins.toString nextcloudPort}" + ]; + }; + }; + + services.nginx.recommendedProxySettings = true; + services.nginx.virtualHosts."hydra.claytonhickey.me" = { + locations."/".proxyPass = "http://127.0.0.1:${builtins.toString hydraPort}"; + }; + + services.nginx.virtualHosts."${config.services.nextcloud.hostName}" = { + listen = [ { addr=wireguardIP; port=nextcloudPort; } ]; + }; + + services.onlyoffice = { + enable = false; + hostname = "localhost"; + jwtSecretFile = "/Block/onlyoffice.jwt.secret"; + }; + + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + networking.hostName = "nixnas"; + + networking.networkmanager.enable = true; + + time.timeZone = "America/New_York"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + + # Configure keymap in X11 + services.xserver.xkb = { + layout = "us"; + variant = ""; + }; + + users.users.clhickey = { + isNormalUser = true; + description = "Clayton Lopez Hickey"; + extraGroups = [ "networkmanager" "wheel" ]; + packages = with pkgs; []; + }; + + services.getty.autologinUser = "clhickey"; + + nix.settings.secret-key-files = "/Block/keys/nix/cache-priv-key.pem"; + + system.stateVersion = "25.05"; # Did you read the comment? + +}