diff --git a/.envrc.example b/.envrc.example index b682864..b61ff84 100644 --- a/.envrc.example +++ b/.envrc.example @@ -1,4 +1,4 @@ -use_nix +use flake export TF_VAR_do_token= export TF_VAR_linode_token= diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..42d7b0d --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +secrets/*.yaml diff=sopsdiffer diff --git a/.gitignore b/.gitignore index bdeb823..37a95bf 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,7 @@ terraform.tfstate.* .direnv # End of https://www.toptal.com/developers/gitignore/api/direnv + +.pre-commit-config.yaml + +result diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..22f7061 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,11 @@ +keys: + - &r17x B0B63B776767DFAA669D06715CA1E57AFBF76F90 + - &komunix-dev age13rrpdnr7f9knpgdvafvjkp74ejacuhcvzhdw2j8h5xjwyrmrhv4s4tvr8j +creation_rules: + - path_regex: secrets/(?:[^/]+/)*[^/]+\.(yaml|json|env|ini)$ + key_groups: + - pgp: + - *r17x + age: + - *komunix-dev + diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..55917b9 --- /dev/null +++ b/flake.lock @@ -0,0 +1,179 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1726153070, + "narHash": "sha256-HO4zgY0ekfwO5bX0QH/3kJ/h4KvUDFZg8YpkNwIbg1U=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "bcef6817a8b2aa20a5a6dbb19b43e63c5bf8619a", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1725233747, + "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1731890469, + "narHash": "sha256-D1FNZ70NmQEwNxpSSdTXCSklBH1z2isPR84J6DQrJGs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5083ec887760adfe12af64830a66807423a859a7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1720386169, + "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "194846768975b7ad2c4988bdb82572c00222c0d7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1731890469, + "narHash": "sha256-D1FNZ70NmQEwNxpSSdTXCSklBH1z2isPR84J6DQrJGs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5083ec887760adfe12af64830a66807423a859a7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_2" + }, + "locked": { + "lastModified": 1726745158, + "narHash": "sha256-D5AegvGoEjt4rkKedmxlSEmC+nNLMBPWFxvmYnVLhjk=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "4e743a6920eab45e8ba0fbe49dc459f1423a4b74", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "nixpkgs-stable": "nixpkgs-stable", + "nixpkgs-unstable": "nixpkgs-unstable", + "pre-commit-hooks": "pre-commit-hooks", + "sops": "sops" + } + }, + "sops": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixpkgs-stable" + ] + }, + "locked": { + "lastModified": 1716400300, + "narHash": "sha256-0lMkIk9h3AzOHs1dCL9RXvvN4PM8VBKb+cyGsqOKa4c=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "b549832718b8946e875c016a4785d204fcfc2e53", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3ef2222 --- /dev/null +++ b/flake.nix @@ -0,0 +1,37 @@ +{ + description = "area13"; + + outputs = + inputs@{ flake-parts, pre-commit-hooks, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + systems = [ + "aarch64-darwin" + "aarch64-linux" + "x86_64-linux" + ]; + + imports = [ + pre-commit-hooks.flakeModule + ./nix + ]; + }; + + inputs = { + # utilities for Flake + flake-parts.url = "github:hercules-ci/flake-parts"; + + ## -- nixpkgs + nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs-stable.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs.follows = "nixpkgs-unstable"; + + # secret management + sops.url = "github:Mic92/sops-nix"; + sops.inputs.nixpkgs.follows = "nixpkgs"; + sops.inputs.nixpkgs-stable.follows = "nixpkgs-stable"; + + # utilities + pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; + pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs"; + }; +} diff --git a/nix/cache.html.tpl b/nix/cache.html.tpl new file mode 100644 index 0000000..ade0763 --- /dev/null +++ b/nix/cache.html.tpl @@ -0,0 +1,94 @@ + + +
+ + + ++ + + + + + + + + + + + + + __ __ + /\ \ /\ \ __ + ___ __ ___\ \ \___ __ \ \ \/'\ ___ ___ ___ __ __ ___ /\_\ __ _ ___ _ __ __ + /'___\ /'__`\ /'___\ \ _ `\ /'__`\ \ \ , < / __`\ /' __` __`\/\ \/\ \ /' _ `\/\ \ /\ \/'\ / __`\/\`'__\/'_ `\ + /\ \__//\ \L\.\_/\ \__/\ \ \ \ \/\ __/ __\ \ \\`\ /\ \L\ \/\ \/\ \/\ \ \ \_\ \/\ \/\ \ \ \\/> / __/\ \L\ \ \ \//\ \L\ \ + \ \____\ \__/.\_\ \____\\ \_\ \_\ \____\/\_\\ \_\ \_\ \____/\ \_\ \_\ \_\ \____/\ \_\ \_\ \_\/\_/\_\/\_\ \____/\ \_\\ \____ \ + \/____/\/__/\/_/\/____/ \/_/\/_/\/____/\/_/ \/_/\/_/\/___/ \/_/\/_/\/_/\/___/ \/_/\/_/\/_/\//\/_/\/_/\/___/ \/_/ \/___L\ \ + /\____/ + \_/__/ + + /nix/store milik bersama | tulung@komunix.org + + + + + + > NixOS + + # /etc/nixos/configuration.nix + + { nix.settings.substituters = [ https://cache.komunix.org/ ]; } + + > GNU/Linux + + # /etc/nix/nix.conf + + fallback = true + binary-caches = https://cache.komunix.org/ https://cache.nixos.org/ + + # OR + + fallback = true + substituters = https://cache.komunix.org + + + > Mac OS + + # $HOME/.nixpkgs/darwin-configuration.nix + + nix.settings.substituters = pkgs.lib.mkBefore [ "https://cache.komunix.org/" ]; + + > Flake + + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + nix.settings.trusted-substituters = [ "https://cache.komunix.org" ]; + + # Recomendation + nix.settings.fallback = true; + + + enjoy :^) + + --- + + # stats for nerds + + $> find /home/komunix/nfs/nix-cache -type f | wc -l + + $TOTAL_CACHE + + $> du -sh /home/komunix/nfs/nix-cache; echo; df -h /home/komunix/nfs/nix-cache; echo; date +%s + + $NICE + + Filesystem Size Used Avail Use% Mounted on + $USAGE + + $TIMESTAMP ++ + diff --git a/nix/default.nix b/nix/default.nix new file mode 100644 index 0000000..6c3f0c4 --- /dev/null +++ b/nix/default.nix @@ -0,0 +1,374 @@ +{ + self, + inputs, + ... +}: + +{ + perSystem = + { + pkgs, + config, + ... + }: + { + pre-commit.check.enable = true; + pre-commit.settings.hooks = { + actionlint.enable = true; + shellcheck.enable = true; + deadnix.enable = true; + deadnix.excludes = [ "nix/overlays/nodePackages/node2nix" ]; + nixfmt-rfc-style.enable = true; + }; + devShells.default = pkgs.mkShell { + shellHook = config.pre-commit.installationScript; + buildInputs = config.pre-commit.settings.enabledPackages; + }; + packages.cachex = pkgs.writeShellApplication { + name = "cachex"; + runtimeInputs = with pkgs; [ + coreutils + gnused + envsubst + ]; + text = '' + NFS_DIR="$1" + TIMESTAMP=$(date +%s) + USAGE=$(df -h "$NFS_DIR/nix-cache" | tail -n1 || echo "0") + TOTAL_CACHE=$(find "$NFS_DIR/nix-cache" -type f | wc -l || echo "0") + NICE=$(du -sh "$NFS_DIR/nix-cache" || echo "0") + + export TIMESTAMP + export USAGE + export TOTAL_CACHE + export NICE + envsubst < ${./cache.html.tpl} + ''; + }; + }; + + /** + Build image for Raspberry Pi: + `nix build .#nixosConfigurations.komunix-pi.config.system.build.sdImage` to build the sd card image, and + `nix build .#nixosConfigurations.komunix-pi.config.system.build.toplevel` to build (only) the system + */ + flake.nixosConfigurations.komunix-pi = inputs.nixpkgs.lib.nixosSystem { + system = "aarch64-linux"; + modules = inputs.nixpkgs.lib.attrValues self.nixosModules ++ [ + "${inputs.nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix" + ( + { config, ... }: + { + networking.hostName = "komunix-dev"; + services.traefik.enable = true; + services.tailscale.enable = true; + services.cachex.enable = true; + services.cachex.cachexPackage = self.packages.aarch64-linux.cachex; + services.cachex.settings.cron = true; + services.cachex.settings.workDir = config.users.users.komunix.home; + } + ) + ]; + }; + + flake.nixosConfigurations.komunix-dev = inputs.nixpkgs.lib.nixosSystem { + system = "aarch64-linux"; + modules = inputs.nixpkgs.lib.attrValues self.nixosModules ++ [ + "${inputs.nixpkgs}/nixos/modules/profiles/macos-builder.nix" + ( + { config, ... }: + { + networking.hostName = "komunix-dev"; + services.traefik.enable = true; + services.tailscale.enable = true; + services.cachex.enable = true; + services.cachex.cachexPackage = self.packages.aarch64-linux.cachex; + services.cachex.settings.cron = true; + services.cachex.settings.workDir = config.users.users.komunix.home; + } + ) + ]; + }; + + flake.nixosModules.common = { + system.stateVersion = "24.05"; + nix.settings.auto-optimise-store = true; + nix.settings.fallback = true; + nix.settings.experimental-features = [ + "flakes" + "nix-command" + ]; + }; + + flake.nixosModules.tailscale = + { config, ... }: + { + services.tailscale.extraUpFlags = [ "--ssh" ]; + services.tailscale.authKeyFile = config.sops.secrets.tailscale_auth_key.path; + sops.secrets.tailscale_auth_key = { }; + }; + + flake.nixosModules.sops = { + imports = [ + inputs.sops.nixosModules.sops + ]; + sops.defaultSopsFile = ../secrets/secret.yaml; + sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; + sops.age.keyFile = "/var/lib/sops-nix/key.txt"; + sops.age.generateKey = true; + }; + + flake.nixosModules.maintainers = + let + keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKvi3Co5fB1dSU2Qs1sR6LwdB1hM6HCyIWfXsC0wgz1pmeFlje24SzPCxDtsVMq28fDpEBsXPqKSZbUIyBtHRnpIc72Z8IV0KNtBjbKQTfHLTiDu43e+VLuAdFE7u2Wf5KPQIQ52r/jr9P7UKU2GKwV016OzrRiaZjm+gixmd8YRfidzG1bsL5fbKBjxCIUROdVpW5kNNtPZHpeuHCkZ7341USC6V2qnp1BNHIoHLjRYosV82apOxN/AWY/tMN2jlVQ/gKIUHbxXoILsG+XRFCen5TSSearx54KxifI1aIWbxVVmmYNuLXGWnVumaH6U7ARpz2cEXQB9z2lvJGYmod8qfloVdjXESu8OFe4RT+nj0JUQs7pMhiN6K1AsMQiyFc0ZmU2UNx4JcHre5STnSKUHUCx4zzoToFvIQRBTB3HePHy74FcXWaYDAN/6YF3JEA203nyYL4o5m/KhSXNkcT3H+r3IAqKnl7J7obsvNowwa1UB2NxVmq0VXXR8uZlT0=" + "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHnjecqMe2lrGzAvQ2VQRTXhjZ5q1tONgme+2/97Z3VSXdY0i2bEH3qGEIC7uMyWUfmLystXxqP0u6/Xspmm0Ck=" + ]; + in + { + # hosts aliases + networking.hosts = { + "100.121.185.1" = [ "synology" ]; + }; + + users.users.root.openssh.authorizedKeys.keys = keys; + users.users.komunix = { + home = "/home/komunix"; + createHome = true; + isNormalUser = true; + extraGroups = [ + "wheel" + "networkmanager" + ]; + openssh.authorizedKeys.keys = keys; + }; + }; + + flake.nixosModules.traefik = + { config, lib, ... }: + let + configCachex = config.services.cachex; + cachexListen = "${configCachex.settings.listenAddress}:${toString configCachex.settings.listenPort}"; + in + { + services.traefik.dynamicConfigOptions.http.middlewares = + { + raspi.headers.customResponseHeaders."X-Served-From" = "raspi"; + cachex_fallback.headers.customResponseHeaders."X-Komunix-Fallback-To" = "cache.nixos.org"; + nice.headers.customResponseHeaders."X-faultables" = "hayo mau cari apa .:monman"; + nice.headers.customResponseHeaders."X-Powered-By" = "PHP 69.42.0 (tapi boong)"; + } + // (lib.optionalAttrs configCachex.enable { + cachex_index.headers.customResponseHeaders.server = "komunix 0.66.6"; + + }); + + services.traefik.dynamicConfigOptions.http.services = + { + komunix_index = { + loadBalancer.servers = [ + { url = "http://127.0.0.1:2026"; } + ]; + }; + nice = { + loadBalancer.servers = [ + { url = "http://127.0.0.1:2025"; } + ]; + }; + cachex_fallback = { + loadBalancer = { + servers = [ + { url = "http://127.0.0.1:8080"; } + ]; + passHostHeader = false; + }; + }; + cachex = { + loadBalancer.servers = [ + { url = "http://127.0.0.1:8080"; } + ]; + }; + npm = { + loadBalancer.servers = [ + { url = "http://127.0.0.1:4873"; } + ]; + }; + npm_index = { + loadBalancer.servers = [ + { url = "http://127.0.0.1:2023"; } + ]; + }; + } + // (lib.optionalAttrs configCachex.enable { + index = { + loadBalancer.servers = [ + { url = "http://${cachexListen}"; } + ]; + }; + cachex_index = { + loadBalancer.servers = [ + { url = "http://${cachexListen}"; } + ]; + }; + }); + + services.traefik.dynamicConfigOptions.http.routers = + { + nice = { + rule = "Host(`raspi.faultables.net`)"; + service = "nice"; + middlewares = [ "nice" ]; + }; + index = { + rule = "Host(`komunix.org`)"; + service = "komunix_index"; + middlewares = [ "raspi" ]; + }; + cachex = { + rule = "Host(`cache.komunix.org`) && PathPrefix (`/`)"; + service = "cachex_fallback"; + priority = 1; + middlewares = [ + "cachex_index" + "cachex_fallback" + ]; + }; + npm = { + rule = "Host(`npm.komunix.org`) && PathPrefix (`/`)"; + service = "npm"; + }; + npm_index = { + rule = "Host(`npm.komunix.org`) && Path (`/`)"; + service = "npm_index"; + priority = 1337; + }; + } + // (lib.optionalAttrs configCachex.enable { + cachex_index = { + rule = "Host(`cache.komunix.org`) && Path (`/`)"; + service = "cachex_index"; + priority = 1337; + middlewares = [ "cachex_index" ]; + }; + }); + }; + + flake.nixosModules.services-cachex = + { + pkgs, + config, + lib, + ... + }: + let + cfg = config.services.cachex; + in + with lib; + { + options.services.cachex = { + enable = mkOption { + default = false; + type = with types; bool; + description = '' + Enable caddy for cachex + ''; + }; + cachexPackage = mkOption { + type = types.package; + description = '' + Cachex Package + ''; + }; + caddyPackage = mkOption { + default = pkgs.caddy; + type = types.package; + description = '' + Caddy package + ''; + example = literalExample "pkgs.caddy"; + }; + settings.cron = mkOption { + default = false; + type = with types; bool; + description = '' + Enable cachex in cron job + ''; + }; + settings.workDir = mkOption { + type = types.str; + example = literalExample "/home/komunix"; + }; + settings.listenAddress = mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + Listen Address + ''; + }; + settings.listenPort = mkOption { + type = types.port; + default = 2022; + description = '' + Listen Address + ''; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ + cfg.caddyPackage + pkgs.nfs-utils + ]; + system.activationScripts.createDir = + # bash + mkBefore '' + [[ -d ${cfg.settings.workDir}/cachex ]] || \ + (mkdir -p ${cfg.settings.workDir}/cachex && chown komunix:users ${cfg.settings.workDir}/cachex) + ''; + + services.cron.enable = cfg.settings.cron; + services.cron.systemCronJobs = [ + "* * * * * cachex ${getExe cfg.cachexPackage} ${cfg.settings.workDir}/nfs > ${cfg.settings.workDir}/cachex/index.html" + ]; + + services.rpcbind.enable = true; # needed for NFS + systemd.mounts = [ + { + type = "nfs"; + mountConfig = { + Options = "auto,nofail,noatime,nolock,tcp"; + }; + what = "synology:/volume2/komunix"; + where = "${cfg.settings.workDir}/nfs"; + } + ]; + systemd.automounts = [ + { + wantedBy = [ "multi-user.target" ]; + automountConfig = { + TimeoutIdleSec = "600"; + }; + where = "${cfg.settings.workDir}/nfs"; + } + ]; + + systemd.services.caddy = { + unitConfig.Description = "Caddy"; + serviceConfig.StartLimitInterval = 5; + serviceConfig.StartLimitBurst = 10; + serviceConfig.Restart = "always"; + serviceConfig.RestartSec = 10; + serviceConfig.StandardOutput = null; + serviceConfig.StandardError = "journal"; + serviceConfig.WorkingDirectory = cfg.settings.workDir; + serviceConfig.StateDirectory = "cachex"; + serviceConfig.RuntimeDirectory = "cachex"; + serviceConfig.ExecStart = # bash + '' + ${getExe cfg.caddyPackage} file-server --root ${cfg.settings.workDir}/cachex --listen ${cfg.settings.listenAddress}:${toString cfg.settings.listenPort} + ''; + wantedBy = [ "multi-user.target" ]; + }; + }; + }; +} diff --git a/secrets/secret.yaml b/secrets/secret.yaml new file mode 100644 index 0000000..e6947aa --- /dev/null +++ b/secrets/secret.yaml @@ -0,0 +1,41 @@ +tailscale_auth_key: ENC[AES256_GCM,data:dmYEr+eOf6UO2u7wBFWABERE5kt+3plKQOGQWR4HA+9gC0BGDgtW/AYNyoy4b1p50pQP9vo16X9UPXmTIg==,iv:hNS2NaAiQmzpYSv7A0hGooBPwDPBlvh+5cTURy0U280=,tag:r3zephEEu7KK77mt2ft9tQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age13rrpdnr7f9knpgdvafvjkp74ejacuhcvzhdw2j8h5xjwyrmrhv4s4tvr8j + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1UFhka0dZbkt6eGd2L2VB + RGx5eW9uMEkrbHJqM1FGcUU5N0l2MkJrdkNBClhvTWJ0Z0lWOFRRZzQ3NCsrZUox + amV0UVM4TU1hS0NFclQ5TVZEVnN1ZzQKLS0tIERmSmwralpLRzNIeWJYaG92VTVR + YlVNM3RidG56bHIvbHRkeWs3NlJMRDQKBO+jzjiIxg3u/6LuqWIjTTVimcukED0V + P+P8duF+keHnchpvD4Vi6EIcVK9Gb6MfODiUWqntsfL3R9Uc4DyutQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-11-10T08:13:27Z" + mac: ENC[AES256_GCM,data:cGaGo4y/NqHUOIWO82j6kIbJ1YQWZGdZO7CQFEDY+oyK5sPQR9m6KNVXyPLjgc9omiiF3BFyiPK7vmz2TV9xQx5hnSqYZn+KO8iM0d99LeBKQCYPzTVJA476oVhdnGxhuvNhVvMQ2k4OWuLufSB+NXXzTeiPVZmIRmfbz9jM6fY=,iv:DHYTN5hxqfzALIxaaqnvUCPi8q/5LqadOyHBIwMzrKw=,tag:j1dLRYSYxaW8mCWXoPXTEA==,type:str] + pgp: + - created_at: "2024-11-10T09:14:37Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA7z/T8UoYDaeARAAqg3MtNk7Y1T95qnEbWTw0OvO7GuPmiRO+cvctCbcvkRS + CpQ7rSfni+roJOI6uvny/MAFJtS/uybSVbgaaQj/rljWv+e/nCx/sYsg3vjIlL8l + MPEjjxcYn82CFkIOXJbsRuFMtKzE3wFugBojZIEql/byZ84fGQp3J53N6pYdSp04 + eK/nJnYoMj0bhyQIugn7F4hRDvl0rH1nSHFFdBiPuqa86DVyermnQtNoQhL2Xqk5 + QN3Ug4HWJ9h7qPofPIjVXn+bbMTwJaDZn4V9JKgJT79XQ+0oRz560N10XMMuqOUt + xpoUjakFW+GRToLu0zyG1hmXog0whxL1uK0RAdHxPQAADjy0fFJUR54fKVu0tmxX + 2O/TI8wOhxFM1xgAFOT+Ta8v5lwtQoVKGq7rCnsLRfU2UnSkpyH3QqygXD2Br1BV + YVzYzPND/H5uTKSp7sWVn/QMubTX96o/bXa1Pf0Lc3I6iGAOmwFq5ayKO6gRhd6P + G2IVW0rspg6qOPEBbTwbrbu1ZsEoNF4gkxtn9sAinLWSKyzQnrqJbWScVFd2NWSn + +4iy0ZjxExG5JyU3IgEknQ6wPnJjYGnKqQZSD5ZBtVFE4DBBt2FV5nSbVSK1YK0a + tl1EeVB5Tv/hRVdZRC/amoDUKO9iury7UlzVj7MYh8knf5Q5bUfrkEb+0vUJPUrS + XAHESNWRiS+wdetivov5wQV13sV99RBvO1HW1S6i0sb0lIeQHvUglbBiuGXSNNaN + qNlykGB2HHVsB6kIZfbT6XAjVY6zzTUb+qmV3IUTBLjTgTq6fXWY4TuDXgzR + =qffB + -----END PGP MESSAGE----- + fp: B0B63B776767DFAA669D06715CA1E57AFBF76F90 + unencrypted_suffix: _unencrypted + version: 3.9.0 diff --git a/shell.nix b/shell.nix deleted file mode 100644 index e95205e..0000000 --- a/shell.nix +++ /dev/null @@ -1,13 +0,0 @@ -with import