{ inputs = { utils.url = "github:numtide/flake-utils"; gokill.url = "github:k4lipso/gokill"; nixos-hardware = { url = "github:NixOS/nixos-hardware/master"; inputs.nixpkgs.follows = "nixpkgs"; }; nixos-raspberrypi = { url = "github:nvmd/nixos-raspberrypi/main"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { self, nixpkgs, utils, ... } @ inputs: utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; gokillPackage = inputs.gokill.packages.${system}.gokill; in { devShell = pkgs.mkShell { buildInputs = with pkgs; [ ]; }; packages.showGokillStatus = let watchGokillStatus = pkgs.writeShellScriptBin "watch-gokill-status" '' ${pkgs.procps}/bin/watch -c -t "sudo ${gokillPackage}/bin/gokillctl --db=/etc/gokill status; # sudo ${gokillPackage}/bin/gokillctl --db=/etc/gokill remote status" ''; in pkgs.writeShellScriptBin "show-gokill-status" '' TERMINAL="${pkgs.xterm}/bin/xterm -bg black -fg white" APP_COMMAND="${watchGokillStatus}/bin/watch-gokill-status" TARGET_WORKSPACE="1" #env DISPLAY=:0 ${pkgs.sudo}/bin/sudo su -c "${pkgs.i3}/bin/i3-msg \"exec $TERMINAL -T 'Status' -e $APP_COMMAND;\"" rpi ${pkgs.i3}/bin/i3-msg "exec $TERMINAL -T 'Status' -e $APP_COMMAND; layout tabbed" ''; packages.alarmSound = pkgs.writeShellScriptBin "alarm-sound" '' # 533 == pin 21 # use cat /sys/kernel/debug/gpio to get assignments exportPin() { if [ ! -e $BASE_GPIO_PATH/gpio$1 ]; then echo "$1" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio$1/direction fi } setState() { echo $2 > /sys/class/gpio/gpio$1/value } # GPIO 26 - Use as VCC exportPin "538" setState "538" "1" # GPIO 19 - Use as Signal exportPin "531" echo "Starting Alert sound!" for i in {1..5}; do echo "Alert Iteration $i of 5" setState "531" "1" sleep 1 setState "531" "0" sleep 1 done echo "Finished Alert sound!" ''; packages.showAlert = pkgs.writeShellScriptBin "show-alert" '' echo "show alert" export DISPLAY=:0 echo "call xset" ${pkgs.xorg.xset}/bin/xset dpms force on echo "call alert" ${self.packages.${system}.alertTest}/bin/alert #env DISPLAY=:0 sudo su -c "${pkgs.xorg.xset}/bin/xset dpms force on" rpi #env DISPLAY=:0 sudo su -c "${self.packages.${system}.alertTest}/bin/alert" rpi ''; packages.alertTest = pkgs.buildGoModule { pname = "alertTest"; version = "0.5"; vendorHash = "sha256-VNhegIXNH4rNdLaH8fALtA6iMu5ejX3gqXQRw9TWDU8="; src = ./scripts/alert; nativeBuildInputs = [ pkgs.pkg-config ]; buildInputs = [ pkgs.gcc pkgs.mesa pkgs.freeglut pkgs.libGL pkgs.xorg.libX11 pkgs.xorg.libXcursor pkgs.xorg.libXrandr pkgs.xorg.libXinerama pkgs.xorg.xinput pkgs.xorg.libXi pkgs.libxxf86vm ]; PKG_CONFIG_PATH = "${pkgs.libGL}/lib/pkgconfig/"; }; } ) // { nixosConfigurations = let pkgs = nixpkgs.legacyPackages."aarch64-linux"; Keys = { Kalipso = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCfDz5teTvRorVtpMj7i3pffD8W4Dn3Aiqre5L4WZq8Wc4bh2OjabGnIcDWpeToKf38n5m0d95OkIbARJwFN7KlbuQbmnIJ5n6pUj/zzRQ3dQTeSsUjkvdbSXVvTcDczMWwLixc/UKP1DMbiLHz5ZSywPTSH2l40lg74q7tSFGBwMy8uy4tsdp2d2sUIDfpvgGj3Pq+zkQHWyFR5BYyCLDfJMTQvGO0bEsbRIDOjkH8YVni46ds6sQKMgc+L2vPo8S3neFZBQRlERVRvIAzdLiBWqGkiw4YgWQA8ocTfWp9DVzW+BZiatc34+AX3KtLEF1Oz76YsKjBttSQL4myUucuskz2Bs7UYvAsDFlWyiJ43ayZNzvG63m1UVsAoq84IhNYsdkPhd+G1rtnG0KxPVAtn7RkAGt8t7ObU+6xWayHcpSteNeE+QyH9nNmJcXNNKfoOeP4vHUBrBTeURafw527yuZDOYknJmg3O+nkeGseIgBYgq/As4+dD6vhp03Y5chjU4/FC6nEjsGPRdfe2RZx+0cqJkLgdd1paGByUfPfaUKykw4TsCUAiDucRwBjU32MLslUbyzeEkjzOJzOD5Frif3jZZLxaNP2QcHRbTiiKkdn+WFJmjr3BdC60pm7hqvmDxl0UZcz9hDv3wZUALUc92TQXnWc8GicKdpQgRYDRQ== kalipso@c3d2.de" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCxgcjNOYbza3+RfANFDXy7HXNRFlkpDOAcGyB7MKshiVlbPByWRSjfZa0BeRNjpeCd8QkIodKUzqYOCOrc8ad3kiNbdLRcDz57A5xSLD3ynakoWJo0AmJjT3Ta1JJj8inNwwykR0ig5//SrtsZb9HkWJDAF017MokM2r8AWPE1QzcQdh93kojXcgTHrJHzEqgKbEGDEk37f1RvZG4umEFeqdK2FvS5isPa7P9X7hyyoDC8bvEy7xfaDrToJAoXon6r79taxH8UWIvy//xsU0NBLYK2eE4RQe2AjF6Ri+CybI6y1SsHOvyh4nNKWlfUOEL6UnIulRn/LXFOKCJi7xuoTeJXS0+w1DNEuiGosVNXPSKbUm/eDBVnb8Iyep9wmygSZayN82xL5lRlG3Mn45ttecqfm2SJkmduBA5qXcTdDPe/lXTZaVO9tbiIcJfUgd3ttEu2+6YjLn74D965PlovzvR6EhbVUZ8IkOAt4VmuTkXIdm8SCS7jzhsiKeUXoZ4rfa375zi79SIPuIkoMasj6d16wcYOeFIUIMFFccfQ9jQjr9NTSXC2dd7sfbI9I9mF7eRQSsUdSwpP8WH1b+M1MxTbdhEUdPwpOLviTTIuk8E8K8DQDZIcOOh38mCDpyoh02nwfRxlyoYVsKAHIQH02dHTvYEa3/pMsRwGc9W1Ow== kalipso@desktop" ]; }; in { rpi = nixpkgs.lib.nixosSystem { system = "aarch64-linux"; specialArgs.inputs = inputs; modules = [ "${nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix" inputs.nixos-hardware.nixosModules.raspberry-pi-3 inputs.gokill.nixosModules.gokill ({ pkgs, ... }: { nix.nixPath = [ "nixpkgs=${pkgs.path}" ]; nix.extraOptions = '' experimental-features = nix-command flakes ''; nix.settings = { trusted-users = [ "root" "@wheel" ]; }; }) ( { config, ... }: { environment.systemPackages = with pkgs; [ libraspberrypi raspberrypi-eeprom unclutter self.packages.aarch64-linux.alertTest ]; sdImage = pkgs.lib.mkForce { compressImage = false; populateFirmwareCommands = let configTxt = pkgs.writeText "config.txt" '' [pi3] kernel=u-boot-rpi3.bin hdmi_force_hotplug=1 [pi02] kernel=u-boot-rpi3.bin [pi4] kernel=u-boot-rpi4.bin enable_gic=1 armstub=armstub8-gic.bin # Otherwise the resolution will be weird in most cases, compared to # what the pi3 firmware does by default. disable_overscan=1 # Supported in newer board revisions arm_boost=1 [cm4] # Enable host mode on the 2711 built-in XHCI USB controller. # This line should be removed if the legacy DWC2 controller is required # (e.g. for USB device mode) or if USB support is not required. otg_mode=1 [all] # Boot in 64-bit mode. arm_64bit=1 # U-Boot needs this to work, regardless of whether UART is actually used or not. # Look in arch/arm/mach-bcm283x/Kconfig in the U-Boot tree to see if this is still # a requirement in the future. enable_uart=1 # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel # when attempting to show low-voltage or overtemperature warnings. # avoid_warnings=1 # PiScreen: # For more options and information see # http://rptl.io/configtxt # Some settings may impact device functionality. See link above for details # Automatically load overlays for detected DSI displays display_auto_detect=1 # Automatically load initramfs files, if found auto_initramfs=1 # Enable DRM VC4 V3D driver dtoverlay=vc4-kms-v3d max_framebuffers=2 # Don't have the firmware create an initial video= setting in cmdline.txt. # Use the kernel's default instead. disable_fw_kms_setup=1 # Run as fast as firmware / board allows arm_boost=1 [cm5] dtoverlay=dwc2,dr_mode=host [all] enable_uart=1 dtoverlay=piscreen,drm,rotate=0,speed=18000000s ''; in '' (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/firmware/) # Add the config cp ${configTxt} firmware/config.txt # Add pi3 specific files cp ${pkgs.ubootRaspberryPi3_64bit}/u-boot.bin firmware/u-boot-rpi3.bin cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-2-b.dtb firmware/ cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-3-b.dtb firmware/ cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-3-b-plus.dtb firmware/ cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-cm3.dtb firmware/ cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-zero-2.dtb firmware/ cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-zero-2-w.dtb firmware/ cp -r ${pkgs.device-tree_rpi.passthru.overlays} firmware/ # Add pi4 specific files cp ${pkgs.ubootRaspberryPi4_64bit}/u-boot.bin firmware/u-boot-rpi4.bin cp ${pkgs.raspberrypi-armstubs}/armstub8-gic.bin firmware/armstub8-gic.bin cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-4-b.dtb firmware/ cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-400.dtb firmware/ cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4.dtb firmware/ cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4s.dtb firmware/ ''; populateRootCommands = '' mkdir -p ./files/boot ${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot ''; }; security.sudo = { extraRules = [ { users = [ "rpi" ]; commands = [ { command = "ALL"; options = [ "NOPASSWD" ]; } { command = "${inputs.gokill.packages.aarch64-linux.gokill}/bin/gokillctl"; options = [ "NOPASSWD" ]; } ]; } ]; }; systemd.services.gokill-status = { enable = true; description = "Open gokill status view at boot"; after = [ "graphical.target" ]; wantedBy = [ "gokill.service" ]; environment = { DISPLAY = ":0"; XAUTHORITY = "/home/rpi/.Xauthority"; }; #preStart = "${pkgs.coreutils-full}/bin/sleep 30"; serviceConfig = { ExecStart = "${self.packages.aarch64-linux.showGokillStatus}/bin/show-gokill-status"; }; }; systemd.services.gokill = { environment = { DISPLAY = ":0"; XAUTHORITY = "/home/rpi/.Xauthority"; }; }; services.gokill = { enable = true; triggers = [ { type = "Timeout"; name = "custom timeout"; options = { duration = 120; }; actions = [ { type = "ShellScript"; options = { path = "${inputs.self.packages.aarch64-linux.showAlert}/bin/show-alert"; }; stage = 1; } #{ # type = "ShellScript"; # options = { # path = "${self.packages.aarch64-linux.alarmSound}/bin/alarm-sound"; # }; # stage = 1; #} ]; } ]; }; services.displayManager = { autoLogin.enable = true; autoLogin.user = "rpi"; }; services.xserver = { videoDrivers = [ "fbdev" ]; enable = true; windowManager.i3 = { enable = true; extraPackages = with pkgs; [ dmenu #application launcher most people use i3status # gives you the default i3 status bar i3lock #default i3 screen locker ]; }; # Hide mouse cursor displayManager.startx.extraCommands = '' ${pkgs.unclutter}/bin/unclutter & ''; }; services.openssh.enable = true; services.openssh.ports = [ 22 ]; services.openssh.settings.PasswordAuthentication = false; users.users.root.openssh.authorizedKeys.keys = Keys.Kalipso; users.users.rpi = { isNormalUser = true; extraGroups = [ "wheel" ]; openssh.authorizedKeys.keys = Keys.Kalipso; initialPassword = "test"; }; boot.supportedFilesystems = pkgs.lib.mkForce [ "ext4" "vfat" ]; boot.kernelPackages = pkgs.linuxKernel.packages.linux_rpi3; boot.tmp.cleanOnBoot = true; boot.tmp.useTmpfs = true; boot = { growPartition = true; kernelParams = [ "console=tty0" ]; loader.grub.enable = false; loader.efi.canTouchEfiVariables = true; }; hardware = { bluetooth.enable = false; deviceTree = { enable = true; filter = "bcm2710-rpi-3-b.dtb"; overlays = [ { name = "piscreen-overlay"; dtboFile = "${config.boot.kernelPackages.kernel}/dtbs/overlays/piscreen.dtbo"; } ]; }; }; nixpkgs.hostPlatform = pkgs.lib.mkDefault "aarch64-linux"; networking.hostName = "rpi"; time.timeZone = "Europe/Berlin"; system.stateVersion = "25.11"; }) ]; }; }; }; }