diff --git a/machines/agb01/_configuration.nix b/machines/agb01/_configuration.nix new file mode 100644 index 0000000..2f20fd7 --- /dev/null +++ b/machines/agb01/_configuration.nix @@ -0,0 +1,50 @@ +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + { + imports = [ + (modulesPath + "/installer/sd-card/sd-image-aarch64.nix") # this holds the hardware-config + ./bootloader.nix + ./secrets + ./networking.nix + ./users.nix + ]; + + nix.settings.substituters = lib.mkForce []; + + networking.hostName = "agb01"; # Define your hostname. + + environment.systemPackages = [ + (pkgs.writeShellApplication { + name = "run-gw"; + runtimeInputs = [ + pkgs.curl + (pkgs.python3.withPackages (ps: [ + ps.pyjecteur + ps.colour + ps.requests + ])) + ]; + text = "curl -s -n https://agb.hackens.org/api/sse | python ${./script.py}"; + }) + ]; + + services.openssh.enable = true; + + # Set your time zone. + time.timeZone = "Europe/Paris"; + + fonts.enableDefaultPackages = true; + + # 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). + system.stateVersion = "unstable"; # Did you read the comment? +} diff --git a/machines/agb01/bootloader.nix b/machines/agb01/bootloader.nix new file mode 100644 index 0000000..df2338f --- /dev/null +++ b/machines/agb01/bootloader.nix @@ -0,0 +1,4 @@ +{pkgs, ...}: { + boot.loader.grub.enable = false; + boot.loader.generic-extlinux-compatible.enable = true; +} diff --git a/machines/agb01/networking.nix b/machines/agb01/networking.nix new file mode 100644 index 0000000..ff36ff9 --- /dev/null +++ b/machines/agb01/networking.nix @@ -0,0 +1,68 @@ +{ + config, + lib, + pkgs, + ... +}: { + networking.useDHCP = false; + + networking.wireless.userControlled.enable = true; + networking.wireless.enable = true; + + systemd.network = { + enable = true; + + networks = { + "10-uplink" = { + name = "enu1u1"; + DHCP = "yes"; + }; + "50-wg0" = { + name = "wg0"; + address = [ + "10.10.10.5/24" + ]; + }; + "10-wifi" = { + name = "wlan0"; + DHCP = "yes"; + networkConfig = { + }; + dhcpV4Config = { + RouteMetric = 2000; + }; + }; + }; + netdevs = { + "50-wg0" = { + netdevConfig = { + Name = "wg0"; + Kind = "wireguard"; + }; + wireguardConfig = { + PrivateKeyFile = config.age.secrets."wg".path; + }; + + wireguardPeers = [ + { + wireguardPeerConfig = { + AllowedIPs = [ + "10.10.10.1/24" + ]; + PublicKey = "CzUK0RPHsoG9N1NisOG0u7xwyGhTZnjhl7Cus3X76Es="; + Endpoint="129.199.129.76:1194"; + PersistentKeepalive = 5; + }; + } + ]; + }; + }; + }; + networking.nameservers = [ + "2620:fe::fe" + "2620:fe::9" + "9.9.9.9" + "149.112.112.112" + ]; + +} diff --git a/machines/agb01/script.py b/machines/agb01/script.py new file mode 100644 index 0000000..bb77dfa --- /dev/null +++ b/machines/agb01/script.py @@ -0,0 +1,84 @@ +#!/nix/store/z46wvcd15152qnsry80p8ricxya2n2lr-python3-3.11.7-env/bin/python +import json +import logging +import sys + +import requests +from colour import Color +from pyjecteur.fixtures import Blinder, LedBar48Ch, Tradi +from pyjecteur.lights import Universe +from pyjecteur.widget import Widget + +if False: # True: # True: + logging.basicConfig(level=logging.DEBUG) +else: + logging.basicConfig(level=logging.INFO) + +w = Widget("/dev/ttyUSB0") + +DIM = { + "blinder": 1.0, + "led_tub": 1.0, + "spot": 1.0, +} + +u = Universe(w) + + +def strToProj(s): + match s: + case "spot": + return Tradi() + case "led_tub": + return LedBar48Ch() + case "blinder": + return Blinder() + + +r = requests.get("https://agb.hackens.org/api-docs/patch.json") +patch = r.json() + +lights = {} + +update = {} + +current_addr = 0 + +for k, v in patch["lights"].items(): + lights[k] = strToProj(v["kind"]) + u.register(lights[k], current_addr) + # update dmx since some params are set before + lights[k].update_dmx() + logging.info( + f"Light {k} of kind {v['kind']} is at DMX{v['channels'][0]*3+1} (PLS convention)" + ) + for i, chan in enumerate(v["channels"]): + update[chan] = (k, i) # put the light name + current_addr += lights[k].address_size + + +def update_light(address, red, green, blue): + light, chan = update[address] + kind = patch["lights"][light]["kind"] + r, g, b = red * DIM[kind] / 255, (green * DIM[kind]) / 255, (blue * DIM[kind]) / 255 + match kind: + case "blinder": + lights[light].colors[chan] = Color(rgb=(r, g, b)) + case "led_tub": + lights[light].colors[chan] = Color(rgb=(r, g, b)) + case "spot": + lights[light].color = Color(rgb=(r, g, b)) + + +def run(): + logging.info("Started") + for line in sys.stdin: + logging.debug(line) + if line.startswith("data:"): + dataStr = line[5:] + logging.debug(f"Received: {dataStr}") + data = json.loads(dataStr) + update_light(data["address"], **data["value"]) + + +run() diff --git a/machines/agb01/secrets/default.nix b/machines/agb01/secrets/default.nix new file mode 100644 index 0000000..14efc4b --- /dev/null +++ b/machines/agb01/secrets/default.nix @@ -0,0 +1,11 @@ +{ + pkgs, + config, + lib, + ... +}: { + age.secrets."wg" = { + file = ./wg.age; + owner = "systemd-network"; + }; +} diff --git a/machines/agb01/secrets/secrets.nix b/machines/agb01/secrets/secrets.nix new file mode 100644 index 0000000..c5105fe --- /dev/null +++ b/machines/agb01/secrets/secrets.nix @@ -0,0 +1,9 @@ +let + lib = (import {}).lib; + readPubkeys = user: + builtins.filter (k: k != "") (lib.splitString "\n" + (builtins.readFile (../../../shared/pubkeys + "/${user}.keys"))); +in { + "wg.age".publicKeys = (readPubkeys "maurice") ++ (readPubkeys "bakham"); + +} diff --git a/machines/agb01/secrets/wg.age b/machines/agb01/secrets/wg.age new file mode 100644 index 0000000..db4fdf6 --- /dev/null +++ b/machines/agb01/secrets/wg.age @@ -0,0 +1,10 @@ +age-encryption.org/v1 +-> ssh-ed25519 JGx7Ng HtaAERSKhcnVlwgXFSeoBxgvyMD6LLS2FS2hVJHj5GE +++aPZYrVrMRKkMqhTAdTXRuJ0gDTxTaF7lw3ETB3jkA +-> ssh-ed25519 Ih+Lhw J4sYJKFXL8GY2EfpJLvDecXSjEM9OUv2v0GROxUMGXM +vsJCO+hWC7s/0fFPkIcZxsT6dhuVqalRNtCe5BkX3+U +-> ssh-ed25519 wS9Cng 1t3BDvGC5asaG6fZnNuxxuYKm3EKOPGDmFwRA5okiD8 +ABEvfYlQB1LJjQl6XJ40sqEgdnrrCHci+c09UUbCfCk +--- 6/mVEZIYh6VgkIdgMAFwBdFcTBiiahJI5kShcVuXOCc +ųʬ`Gw;}tm}~^hA0|2jX^õj +.tLN?9?n^SH> \ No newline at end of file diff --git a/machines/agb01/users.nix b/machines/agb01/users.nix new file mode 100644 index 0000000..4fb1722 --- /dev/null +++ b/machines/agb01/users.nix @@ -0,0 +1,13 @@ +{ ... }: +{ + users = { + mutableUsers = false; + users = { + root.openssh.authorizedKeys.keyFiles = [ + ../../pubkeys/sinavir.keys + ../../pubkeys/catvayor.keys + ../../pubkeys/soyouzpanda.keys + ]; + }; + }; +} diff --git a/meta.nix b/meta.nix index 7721dae..b20ff80 100644 --- a/meta.nix +++ b/meta.nix @@ -15,6 +15,13 @@ let }; imports = [ agenix ]; }; + agb01 = { + deployment = { + targetHost = "10.10.10.5"; + }; + arch = "aarch64-linux"; + imports = [ agenix ]; + }; rigel = { deployment = { targetHost = "10.1.1.1"; diff --git a/pkgs/overlays.nix b/pkgs/overlays.nix index 569d0f9..6bb89cd 100644 --- a/pkgs/overlays.nix +++ b/pkgs/overlays.nix @@ -1,14 +1,13 @@ [ (final: prev: { - python3 = prev.python3.override { - packageOverrides = self: _: { + pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [(self: _: { loadcredential = self.callPackage ./loadcredential { }; authens = self.callPackage ./authens { }; python-cas = self.callPackage ./python-cas { }; + pyjecteur = self.callPackage ./pyjecteur.nix { }; django-autoslug = self.callPackage ./django-autoslug { }; markdown-icons = self.callPackage ./markdown-icons { }; - }; - }; + })]; }) ] diff --git a/pkgs/pyjecteur.nix b/pkgs/pyjecteur.nix new file mode 100644 index 0000000..b4b74e6 --- /dev/null +++ b/pkgs/pyjecteur.nix @@ -0,0 +1,23 @@ +{ lib , pkgs, fetchgit, stdenv, setuptoolsBuildHook, buildPythonPackage, pythonPackages , fetchFromGitHub }: +let + attrs = { + name = "pyjecteur"; + version = "2.0"; + doCheck = false; + src = fetchgit { + url = "https://git.dgnum.eu/HackENS/pyjecteur.git"; + rev = "28759972328c2774b3ab571440051bd97ca35bcc"; + hash = "sha256-xlLS7Hrh1FrBnW7ASfYz42+pguHCbn3Z1k7X3uQseHQ="; + } ; + passthru = { + wheel = buildPythonPackage (attrs // { + name = "pyjecteur-py3.whl"; + installPhase = "mv dist/pyjecteur-2.0-py3-none-any.whl $out"; + dontFixup = true; + doInstallCheck = false; + }); + }; + propagatedBuildInputs = [ pythonPackages.pyserial pythonPackages.colour ]; + }; +in +buildPythonPackage attrs