From fe96211bb8dc81fde57bf6900b840e69f2b218fc Mon Sep 17 00:00:00 2001 From: Kleidi Bujari Date: Fri, 12 Sep 2025 20:57:59 -0700 Subject: move packages to overlay and expose certain packages --- .github/workflows/blog.yaml | 2 +- flake.nix | 60 +++- lib/depot-tools.nix | 4 +- packages/cses/default.nix | 13 - packages/cses/problems/1068.cpp | 17 -- packages/cses/problems/1069.cpp | 23 -- packages/cses/problems/1070.cpp | 15 - packages/cses/problems/1071.cpp | 19 -- packages/cses/problems/1083.cpp | 20 -- packages/cses/problems/1094.cpp | 27 -- packages/cv/cv.typ | 177 ----------- packages/cv/default.nix | 4 - packages/misc/cv/cv.typ | 162 ++++++++++ packages/misc/cv/package.nix | 3 + packages/partitioner.nix | 82 ----- packages/perf-flamegraph.nix | 22 +- packages/resistors/default.nix | 7 - packages/resistors/index.html | 339 --------------------- packages/resistors/styles.css | 127 -------- packages/web/resistors/default.nix | 7 + packages/web/resistors/index.html | 339 +++++++++++++++++++++ packages/web/resistors/styles.css | 127 ++++++++ packages/web/site/.gitignore | 1 + packages/web/site/config.toml | 8 + packages/web/site/content/about/index.md | 38 +++ packages/web/site/content/paper-reviews/_index.md | 7 + packages/web/site/content/posts/_index.md | 7 + .../site/content/posts/deterministic-hostnames.md | 80 +++++ packages/web/site/content/posts/nohup.md | 26 ++ .../site/content/posts/overusing-emacs-modes.md | 39 +++ .../content/posts/stateless-compute-networks.md | 41 +++ packages/web/site/content/posts/vim-compilers.md | 20 ++ packages/web/site/package.nix | 36 +++ packages/web/site/static/atom.svg | 7 + packages/web/site/static/theme.css | 71 +++++ packages/web/site/templates/404.html | 9 + packages/web/site/templates/base.html | 31 ++ packages/web/site/templates/index.html | 28 ++ packages/web/site/templates/page.html | 17 ++ packages/web/site/templates/section.html | 28 ++ 40 files changed, 1192 insertions(+), 898 deletions(-) delete mode 100644 packages/cses/default.nix delete mode 100644 packages/cses/problems/1068.cpp delete mode 100644 packages/cses/problems/1069.cpp delete mode 100644 packages/cses/problems/1070.cpp delete mode 100644 packages/cses/problems/1071.cpp delete mode 100644 packages/cses/problems/1083.cpp delete mode 100644 packages/cses/problems/1094.cpp delete mode 100644 packages/cv/cv.typ delete mode 100644 packages/cv/default.nix create mode 100644 packages/misc/cv/cv.typ create mode 100644 packages/misc/cv/package.nix delete mode 100644 packages/partitioner.nix delete mode 100644 packages/resistors/default.nix delete mode 100644 packages/resistors/index.html delete mode 100644 packages/resistors/styles.css create mode 100644 packages/web/resistors/default.nix create mode 100644 packages/web/resistors/index.html create mode 100644 packages/web/resistors/styles.css create mode 100644 packages/web/site/.gitignore create mode 100644 packages/web/site/config.toml create mode 100644 packages/web/site/content/about/index.md create mode 100644 packages/web/site/content/paper-reviews/_index.md create mode 100644 packages/web/site/content/posts/_index.md create mode 100644 packages/web/site/content/posts/deterministic-hostnames.md create mode 100644 packages/web/site/content/posts/nohup.md create mode 100644 packages/web/site/content/posts/overusing-emacs-modes.md create mode 100644 packages/web/site/content/posts/stateless-compute-networks.md create mode 100644 packages/web/site/content/posts/vim-compilers.md create mode 100644 packages/web/site/package.nix create mode 100644 packages/web/site/static/atom.svg create mode 100644 packages/web/site/static/theme.css create mode 100644 packages/web/site/templates/404.html create mode 100644 packages/web/site/templates/base.html create mode 100644 packages/web/site/templates/index.html create mode 100644 packages/web/site/templates/page.html create mode 100644 packages/web/site/templates/section.html diff --git a/.github/workflows/blog.yaml b/.github/workflows/blog.yaml index faaa50e..2d5556b 100644 --- a/.github/workflows/blog.yaml +++ b/.github/workflows/blog.yaml @@ -24,7 +24,7 @@ jobs: uses: DeterminateSystems/nix-installer-action@main - name: Build blog - run: nix build .#blog + run: nix build .#site - name: Setup Pages uses: actions/configure-pages@v4 diff --git a/flake.nix b/flake.nix index a87c3f6..7f53a57 100644 --- a/flake.nix +++ b/flake.nix @@ -9,35 +9,48 @@ nixos-hardware.url = "github:nixos/nixos-hardware/master"; }; - outputs = { self, nixpkgs, ... } @ inputs: + outputs = + { self, nixpkgs, ... }@inputs: let - inherit (builtins) mapAttrs; - inherit (nixpkgs) lib; - systems = [ "x86_64-linux" "aarch64-linux" ]; + systems = lib.intersectLists lib.systems.flakeExposed lib.platforms.linux; + + forAllSystems = lib.genAttrs systems; + nixpkgsFor = forAllSystems ( + system: + import inputs.nixpkgs { + inherit system; + overlays = [ overlays.default ]; + } + ); inherit (import ./lib/depot-tools.nix { inherit inputs systems lib; }) importDir - eachSystem systemArgs ; - packages = eachSystem ( - { newScope, ... }: - mapAttrs (pname: { path, ... }: newScope { inherit pname; } path { }) - (importDir ./packages lib.id) - ); + overlays.default = + final: _: + let + depot = lib.filesystem.packagesFromDirectoryRecursive { + callPackage = lib.callPackageWith (final // { inherit depot; }); + directory = ./packages; + }; + in + { + inherit depot; + }; - nixosModules = importDir ./modules - (mapAttrs (_: { path, ... }: path)); + nixosModules = importDir ./modules (builtins.mapAttrs (_: { path, ... }: path)); nixosConfigurations = importDir ./machines ( entries: let flake = self; - defaultModule = { config, ... }: + defaultModule = + { config, ... }: let perSystemArg = system: { _module.args.perSystem = systemArgs.${system}.perSystem; @@ -47,7 +60,8 @@ imports = [ (perSystemArg config.nixpkgs.hostPlatform.system) ]; }; - buildNixOS = hostName: entry: + buildNixOS = + hostName: entry: lib.nixosSystem { modules = [ defaultModule @@ -57,8 +71,22 @@ specialArgs = { inherit inputs flake hostName; }; }; in - mapAttrs buildNixOS entries + builtins.mapAttrs buildNixOS entries ); in - { inherit packages nixosModules nixosConfigurations; }; + { + inherit nixosModules nixosConfigurations; + + formatter = forAllSystems (system: nixpkgsFor.${system}.nixfmt-rfc-style); + packages = forAllSystems ( + system: + let + inherit (nixpkgsFor.${system}) depot; + in + { + inherit (depot.misc) cv; + inherit (depot.web) site; + } + ); + }; } diff --git a/lib/depot-tools.nix b/lib/depot-tools.nix index 1a16df9..7c2fc6b 100644 --- a/lib/depot-tools.nix +++ b/lib/depot-tools.nix @@ -80,7 +80,5 @@ let in makeScope callPackageWith (_: { inherit inputs perSystem flake pkgs system; }) ); - - eachSystem = f: genAttrs systems (system: f systemArgs.${system}); in -{ inherit importDir systemArgs eachSystem; } +{ inherit importDir systemArgs; } diff --git a/packages/cses/default.nix b/packages/cses/default.nix deleted file mode 100644 index 6538eb8..0000000 --- a/packages/cses/default.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ pkgs ? import { }, ... }: - -pkgs.mkShell { - packages = with pkgs; [ - clang-tools - (writeShellScriptBin "cpprun" '' - TEMP=".tmp.cpp" - g++ -std=c++20 -O3 ./problems/"$1.cpp" -o $TEMP - ./$TEMP - rm $TEMP - '') - ]; -} diff --git a/packages/cses/problems/1068.cpp b/packages/cses/problems/1068.cpp deleted file mode 100644 index 8d05936..0000000 --- a/packages/cses/problems/1068.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include - -int main(int argc, char *argv[]) { - unsigned long long n; - std::cin >> n; - - while (n != 1) { - std::cout << n << " "; - - if (n % 2 == 0) - n /= 2; - else - n = (n * 3) + 1; - } - - std::cout << 1; -} diff --git a/packages/cses/problems/1069.cpp b/packages/cses/problems/1069.cpp deleted file mode 100644 index 232d2f7..0000000 --- a/packages/cses/problems/1069.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include - -int main() { - std::string input; - std::cin >> input; - - auto max = 0; - auto curr = '-'; - auto count = 0; - - for (auto const ch : input) { - if (curr != ch) { - curr = ch; - count = 0; - } - - count += 1; - max = std::max(max, count); - } - - std::cout << max; - return 0; -} diff --git a/packages/cses/problems/1070.cpp b/packages/cses/problems/1070.cpp deleted file mode 100644 index 131a644..0000000 --- a/packages/cses/problems/1070.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include - -int main() { - int n; - std::cin >> n; - - if (n == 1) - std::cout << 1; - else if (n < 4) - std::cout << "NO SOLUTION"; - else { - for (auto i = 2; i <= n; i += 2) std::cout << i << " "; - for (auto i = 1; i <= n; i += 2) std::cout << i << " "; - } -} diff --git a/packages/cses/problems/1071.cpp b/packages/cses/problems/1071.cpp deleted file mode 100644 index 778cc86..0000000 --- a/packages/cses/problems/1071.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include - -using ull = unsigned long long; - -int main() { - int n; - std::cin >> n; - - while (n--) { - ull x, y; - std::cin >> y >> x; - - auto area = y * y; - auto perimeter = y + y + 1; - auto max = area + perimeter; - } -} diff --git a/packages/cses/problems/1083.cpp b/packages/cses/problems/1083.cpp deleted file mode 100644 index a3cd253..0000000 --- a/packages/cses/problems/1083.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -using ull = unsigned long long; - -int main(int argc, char *argv[]) { - ull n; - std::cin >> n; - - auto set = std::set{}; - - std::string numstr; - while (std::getline(std::cin, numstr, ' ')) set.insert(std::stoi(numstr)); - - for (auto i = 1; i <= n; i++) { - if (set.contains(i)) continue; - std::cout << i; - break; - } -} diff --git a/packages/cses/problems/1094.cpp b/packages/cses/problems/1094.cpp deleted file mode 100644 index 56f3886..0000000 --- a/packages/cses/problems/1094.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -using ull = unsigned long long; - -int main() { - ull n; - auto arr = std::vector{}; - - std::cin >> n; - - std::string type; - while (std::cin >> type) arr.push_back(std::stoi(type)); - - ull count = 0; - auto last = arr[0]; - - for (auto const num : arr) { - if (num > last) { - last = num; - continue; - } - count += last - num; - } - - std::cout << count; -} diff --git a/packages/cv/cv.typ b/packages/cv/cv.typ deleted file mode 100644 index 8e839b2..0000000 --- a/packages/cv/cv.typ +++ /dev/null @@ -1,177 +0,0 @@ -#set document(author: "Kleidi Bujari", title: "Kleidi's Resume!") -#set text(size: 10pt, lang: "en", ligatures: false) -#set page(margin: 0.5in, paper: "us-letter") - -#show link: underline -#set par(justify: true) - -#show heading.where(level: 1): it => [ - #set text(weight: 700, size: 20pt) - #pad(it.body) -] - -#show heading.where(level: 2): it => [ - #pad(top: 0pt, bottom: -10pt, [#smallcaps(it.body)]) - #line(length: 100%, stroke: 1pt) -] - -#let generic-two-by-two( - top-left: "", - top-right: "", - bottom-left: "", - bottom-right: "", -) = [ - #strong(top-left) #h(1fr) #top-right \ - #bottom-left #h(1fr) #bottom-right -] - -#let dates-helper(from: "", to: "") = from + " " + $dash.em$ + " " + to - -#let edu( - institution: "", - dates: "", - degree: "", - location: "", -) = generic-two-by-two( - top-left: institution, - top-right: dates, - bottom-left: degree, - bottom-right: location, -) - -#let work( - title: "", - dates: "", - company: "", - location: "", -) = generic-two-by-two( - top-left: title, - top-right: dates, - bottom-left: company, - bottom-right: location, -) - -= Kleidi Bujari - -#( - link("mailto:mail@4kb.net"), - link("https://github.com/kbujari")[github.com/kbujari], - link("http://kleidi.ca")[kleidi.ca], -).join(" | ") - -== Experience - -#work( - company: "Meta", - title: "Production Engineer", - dates: dates-helper(from: "Aug 2025", to: "Present"), - location: "Menlo Park", -) - -#v(5em) - -#work( - company: "Toronto Metropolitan University", - title: "Graduate Research Assistant", - dates: dates-helper(from: "May 2024", to: "Sep 2024"), - location: "Toronto", -) - -- Organized webhosting and analytics for a large film release, - leading design of web presence for thousands of concurrent visitors. -- Automated transformations for hundreds of media files, - using ffmpeg and unix primitives to parallelize workload. -- Published frontend with AstroJS to generate only static HTML, - ensuring compatibility with many hosting providers. - -#work( - company: "Canadian Broadcasting Corporation", - title: "Network Engineering Intern", - dates: dates-helper(from: "May 2023", to: "Apr 2024"), - location: "Toronto", -) - -- Designed custom PXE based provisioning for hundreds of devices on existing network, - eliminating manual configuration. -- Architected hyper-converged Proxmox cluster for 2024 Olympics, - saving \$250k+ with reused hardware and open software. -- Mentored junior application developers in modern C++ programming, - aiding in memory safety and performance design. - -#work( - company: "WSP Canada", - title: "Student Engineer", - dates: dates-helper(from: "May", to: "Aug") + ", 2021, 2022", - location: "Toronto", -) - -- Modernized subway control systems with modern C++, - replacing legacy code with newer STL functions and safer standards. -- Validated large-scale electrical designs for power consumption, - cost efficiency, and viability with existing systems. -- Extended internal distributed databases with compression and deduplication, - reclaiming terabytes of storage across entire org. - -== Projects - -*Custom Linux Distribution* --- -Designed entire Linux distribution used for hosting production servers, -daily desktop use, and embedded programming on a Raspberry Pi. -Using NixOS, it supports enabling only required functionality at build time. -Features systemd, -an in-memory root filesystem, -ZFS persistent storage with backups, -and extremely hardened networking. - -*Distributed Compute Cluster* --- -Bare-metal Kubernetes cluster managed with GitOps to be completely reproducible. -Uses Cilium CNI for fast eBPF networking and BGP load balancing, -FluxCD for cluster management, -and CEPH distributed storage for stateful workloads. -Air-gapped, automated cluster provisioning with custom PXEBOOT images. - -*ICER Compressor* --- -Image compression library written in Rust, -designed for deep-space communication. -Hand tuned for speed and portability by using only integer arithmetic, -no heap allocations, and no standard library by default. -Achieves practically instant compressions, even on microprocessors. - -*Mirrorlist Generator* --- -Fetches Arch Linux package mirrors, -filtering them based on user parameters. -Sorts and outputs formatted data compliant with the pacman package manager. -Heavily outperforms default Python implementation. - -== Education - -#edu( - institution: "Toronto Metropolitan University", - dates: dates-helper(from: "Sep 2020", to: "Apr 2025"), - location: "Canada", - degree: "Bachelor's of Engineering, Computer Engineering", -) - -- *Relevant Coursework*: - Data Structures, FPGA Programming, Compilers & Interpreters, Digital Systems, Computer Networks -- *Extracurriculars*: - Member of student robotics design team, - teaching assistant for micro-processor courses. - -== Skills - -- *Languages*: #( - "Rust", - "Scheme", - "Haskell", - "Nix", - "C++", - ).join(", ") -- *Technologies*: #( - "Linux", - "Distributed Systems", - "Compilers", - "Virtualisation", - "Reproducible Infrastructure", - "Build Systems", - ).join(", ") diff --git a/packages/cv/default.nix b/packages/cv/default.nix deleted file mode 100644 index 01485a6..0000000 --- a/packages/cv/default.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ pkgs, ... }: - -pkgs.runCommand "cv" { } - "${pkgs.typst}/bin/typst compile --format pdf ${./cv.typ} $out" diff --git a/packages/misc/cv/cv.typ b/packages/misc/cv/cv.typ new file mode 100644 index 0000000..bad635d --- /dev/null +++ b/packages/misc/cv/cv.typ @@ -0,0 +1,162 @@ +#set document(author: "Kleidi Bujari", title: "Kleidi's Resume!") +#set text(size: 10pt, lang: "en", ligatures: false) +#set page(margin: 0.5in, paper: "us-letter") + +#show link: underline +#set par(justify: true) + +#show heading.where(level: 1): it => [ + #set text(weight: 700, size: 20pt) + #pad(it.body) +] + +#show heading.where(level: 2): it => [ + #pad(top: 0pt, bottom: -10pt, [#smallcaps(it.body)]) + #line(length: 100%, stroke: 1pt) +] + +#let generic-headline( + left: "", + right: "", + description: "", +) = [#strong(left) #h(1fr) #description `::` #right] + +#let dates-helper(from: "", to: "") = from + " " + $dash.em$ + " " + to + +#let edu( + institution: "", + dates: "", + degree: "", +) = generic-headline( + left: institution, + description: degree, + right: dates, +) + +#let work( + title: "", + dates: "", + company: "", +) = generic-headline( + left: company, + description: title, + right: dates, +) + += Kleidi Bujari + +#( + link("mailto:mail@4kb.net"), + link("https://github.com/kbujari")[github.com/kbujari], + link("http://kleidi.ca")[kleidi.ca], +).join(" | ") + +== Experience + +#work( + company: "Meta", + title: "Production Engineer", + dates: dates-helper(from: "Aug 2025", to: "Present"), +) + +- Probably working on really cool things. + +#work( + company: "Toronto Metropolitan University", + title: "Graduate Research Assistant", + dates: dates-helper(from: "May 2024", to: "Sep 2024"), +) + +- Organized webhosting and analytics for a large film release, + leading design of web presence for thousands of concurrent visitors. +- Automated transformations for hundreds of media files, + using ffmpeg and unix primitives to parallelize workload. +- Published frontend with AstroJS to generate only static HTML, + ensuring compatibility with many hosting providers. + +#work( + company: "Canadian Broadcasting Corporation", + title: "Network Engineering Intern", + dates: dates-helper(from: "May 2023", to: "Apr 2024"), +) + +- Designed custom PXE based provisioning for hundreds of devices on existing network, + eliminating manual configuration. +- Architected hyper-converged Proxmox cluster for 2024 Olympics, + saving \$250k+ with reused hardware and open software. +- Mentored junior application developers in modern C++ programming, + aiding in memory safety and performance design. + +#work( + company: "WSP Canada", + title: "Student Engineer", + dates: dates-helper(from: "May", to: "Aug") + ", 2021, 2022", +) + +- Validated large-scale electrical designs for power consumption, + cost efficiency, and viability with existing systems. +- Extended internal distributed databases with compression and deduplication, + reclaiming terabytes of storage across entire org. + +== Projects + +*Custom Linux Distribution* --- +Designed entire Linux distribution used for hosting production servers, +daily desktop use, and embedded programming on a Raspberry Pi. +Using NixOS, it supports enabling only required functionality at build time. +Features systemd, +an in-memory root filesystem, +ZFS persistent storage with backups, +and extremely hardened networking. + +*Distributed Compute Cluster* --- +Bare-metal Kubernetes cluster managed with GitOps to be completely reproducible. +Uses Cilium CNI for fast eBPF networking and BGP load balancing, +FluxCD for cluster management, +and CEPH distributed storage for stateful workloads. +Air-gapped, automated cluster provisioning with custom PXEBOOT images. + +*ICER Compressor* --- +Image compression library written in Rust, +designed for deep-space communication. +Hand tuned for speed and portability by using only integer arithmetic, +no heap allocations, and no standard library by default. +Achieves practically instant compressions, even on microprocessors. + +*Mirrorlist Generator* --- +Fetches Arch Linux package mirrors, +filtering them based on user parameters. +Sorts and outputs formatted data compliant with the pacman package manager. +Heavily outperforms default Python implementation. + +== Education + +#edu( + institution: "Toronto Metropolitan University", + dates: dates-helper(from: "Sep 2020", to: "Apr 2025"), + degree: "Bachelor's of Engineering, Computer Engineering", +) + +- *Relevant Coursework*: + Data Structures, FPGA Programming, Compilers & Interpreters, Digital Systems, Computer Networks +- *Extracurriculars*: + Member of student robotics design team, + teaching assistant for micro-processor courses. + +== Skills + +- *Languages*: #( + "Rust", + "Scheme", + "Haskell", + "Nix", + "C++", + ).join(", ") +- *Technologies*: #( + "Linux", + "Distributed Systems", + "Compilers", + "Virtualisation", + "Reproducible Infrastructure", + "Build Systems", + ).join(", ") diff --git a/packages/misc/cv/package.nix b/packages/misc/cv/package.nix new file mode 100644 index 0000000..fe51328 --- /dev/null +++ b/packages/misc/cv/package.nix @@ -0,0 +1,3 @@ +{ runCommandNoCC, typst, ... }: + +runCommandNoCC "cv" { } "${typst}/bin/typst compile --format pdf ${./cv.typ} $out" diff --git a/packages/partitioner.nix b/packages/partitioner.nix deleted file mode 100644 index df9f37d..0000000 --- a/packages/partitioner.nix +++ /dev/null @@ -1,82 +0,0 @@ -# Apply standard partition layout to a disk device. -{ pkgs, ... }: - -pkgs.writeShellApplication { - name = "partitioner"; - - runtimeInputs = with pkgs; [ - gptfdisk - dosfstools - zfs - coreutils - util-linux - ]; - - text = '' - set -euo pipefail - - if [ $# -ne 1 ]; then - echo "Usage: $0 " - echo "Example: $0 /dev/sda or /dev/nvme0n1" - exit 1 - fi - - DISK="$1" - - if [ ! -b "$DISK" ]; then - echo "Error: $DISK is not a valid block device" - exit 1 - fi - - echo "creating partition table on $DISK" - # create gpt partition table - sgdisk --zap-all "$DISK" - - echo "creating efi partition" - sgdisk --new=1:0:+1G --typecode=1:EF00 --change-name=1:ESP "$DISK" - - echo "creating zfs partition with remaining space" - sgdisk --new=2:0:0 --typecode=2:BF00 --change-name=2:ZROOT "$DISK" - - if [[ "$DISK" == *"nvme"* ]]; then - EFI_PART="''${DISK}p1" - ZFS_PART="''${DISK}p2" - else - EFI_PART="''${DISK}1" - ZFS_PART="''${DISK}2" - fi - - sleep 1 - - echo "formatting rfi partition ($EFI_PART)" - mkfs.fat -F32 -n ESP "$EFI_PART" - - echo "creating pool on $ZFS_PART" - zpool create -f \ - -o ashift=12 \ - -o autotrim=on \ - -O acltype=posixacl \ - -O canmount=off \ - -O compression=on \ - -O mountpoint=none \ - -O normalization=formD \ - -O relatime=off \ - -O xattr=sa \ - zroot "$ZFS_PART" - - # create ZFS datasets - echo "Creating datasets" - - zfs create \ - -o refreservation=10G \ - -o mountpoint=none \ - zroot/reserved - - zfs create -o mountpoint=legacy zroot/nix - zfs create -o mountpoint=legacy zroot/home - zfs create -o mountpoint=legacy zroot/persist - - echo "---" - echo "done" - ''; -} diff --git a/packages/perf-flamegraph.nix b/packages/perf-flamegraph.nix index b472b74..780a280 100644 --- a/packages/perf-flamegraph.nix +++ b/packages/perf-flamegraph.nix @@ -1,12 +1,18 @@ -# Script that collects perf timing for the execution of a command and writes a -# flamegraph to stdout -{ pkgs, ... }: +# Script that collects perf timing for the execution of a command and +# writes a flamegraph to stdout -pkgs.writeShellScriptBin "perf-flamegraph" '' +{ + writeShellScriptBin, + linuxPackages, + flamegraph, + ... +}: + +writeShellScriptBin "perf-flamegraph" '' set -euo pipefail - ${pkgs.linuxPackages.perf}/bin/perf record -g --call-graph dwarf -F max "$@" - ${pkgs.linuxPackages.perf}/bin/perf script \ - | ${pkgs.flamegraph}/bin/stackcollapse-perf.pl \ - | ${pkgs.flamegraph}/bin/flamegraph.pl + ${linuxPackages.perf}/bin/perf record -g --call-graph dwarf -F max "$@" + ${linuxPackages.perf}/bin/perf script \ + | ${flamegraph}/bin/stackcollapse-perf.pl \ + | ${flamegraph}/bin/flamegraph.pl '' diff --git a/packages/resistors/default.nix b/packages/resistors/default.nix deleted file mode 100644 index 6a038ea..0000000 --- a/packages/resistors/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ pkgs, ... }: - -pkgs.runCommandNoCC "resisto-rs" { } '' - mkdir -p $out - cp ${./index.html} $out/index.html - cp ${./styles.css} $out/styles.css -'' diff --git a/packages/resistors/index.html b/packages/resistors/index.html deleted file mode 100644 index 0683f49..0000000 --- a/packages/resistors/index.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - rs-calc - - - - - -

rs-calc

- - - - - - -
-

- forked from - this, with removed analytics, cleaned up code. - my github -

-
- - - - diff --git a/packages/resistors/styles.css b/packages/resistors/styles.css deleted file mode 100644 index e2823e4..0000000 --- a/packages/resistors/styles.css +++ /dev/null @@ -1,127 +0,0 @@ -* { - /*font-family: 'firacode';*/ - text-rendering: optimizeLegibility; -} - -body { - margin: 10px 20px; - color: #cccccc; - background: #252525; - background-attachment: fixed !important; -} - -h1 { - font-weight: normal; - font-size: 50px; - margin: -10px 0 10px 0; -} - -h2 { - font-weight: normal; - font-size: 15px; -} - -strong { - font-weight: normal; -} - -footer { - position: absolute; - font-size: 12px; - color: #555; - bottom: 0; - left: 0; - right: 0; - padding: 20px; -} - -a { - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -footer a { - color: #775; -} - -#resistor-query { - font-size: 20px; - border: 1px solid #999; - color: #fff; - background-color: #444; - outline: none; - width: 180px; -} - -.resistor-stripe { - width: 80px; - height: 150px; - display: inline-block; - padding: 4px 4px; -} - -.resistor-smt { - display: inline-block; - padding: 0px 10px; - font-size: 35px; - background-color: #000; - border-left: 15px solid silver; - border-right: 15px solid silver; - border-top: 1px solid silver; - border-bottom: 1px solid silver; - margin-right: 10px; -} - -@media print, screen and (max-width: 520px) { - .resistor-stripe { - width: 55px; - font-size: 80%; - height: 100px; - } - .resistor-smt { - font-size: 25px; - border-left: 12px solid silver; - border-right: 12px solid silver; - } -} - -@media print, screen and (max-width: 410px) { - .resistor-stripe { - width: 35px; - font-size: 55%; - height: 70px; - } - .resistor-smt { - font-size: 18px; - border-left: 8px solid silver; - border-right: 8px solid silver; - } -} - -@media print, screen and (max-width: 300px) { - .resistor-stripe { - width: 25px; - font-size: 50%; - height: 60px; - padding: 2px; - } - .resistor-smt { - font-size: 13px; - border-left: 6px solid silver; - border-right: 6px solid silver; - padding: 2px 4px; - } -} - -@media print, screen and (max-height: 660px) { - .resistor-stripe { - height: 55px; - } - footer { - position: inherit; - padding: 10px 0; - } -} diff --git a/packages/web/resistors/default.nix b/packages/web/resistors/default.nix new file mode 100644 index 0000000..cb32c2f --- /dev/null +++ b/packages/web/resistors/default.nix @@ -0,0 +1,7 @@ +{ runCommandNoCC, ... }: + +runCommandNoCC "resisto-rs" { } '' + mkdir -p $out + cp ${./index.html} $out/index.html + cp ${./styles.css} $out/styles.css +'' diff --git a/packages/web/resistors/index.html b/packages/web/resistors/index.html new file mode 100644 index 0000000..0683f49 --- /dev/null +++ b/packages/web/resistors/index.html @@ -0,0 +1,339 @@ + + + + rs-calc + + + + + +

rs-calc

+ + + + + + +
+

+ forked from + this, with removed analytics, cleaned up code. + my github +

+
+ + + + diff --git a/packages/web/resistors/styles.css b/packages/web/resistors/styles.css new file mode 100644 index 0000000..e2823e4 --- /dev/null +++ b/packages/web/resistors/styles.css @@ -0,0 +1,127 @@ +* { + /*font-family: 'firacode';*/ + text-rendering: optimizeLegibility; +} + +body { + margin: 10px 20px; + color: #cccccc; + background: #252525; + background-attachment: fixed !important; +} + +h1 { + font-weight: normal; + font-size: 50px; + margin: -10px 0 10px 0; +} + +h2 { + font-weight: normal; + font-size: 15px; +} + +strong { + font-weight: normal; +} + +footer { + position: absolute; + font-size: 12px; + color: #555; + bottom: 0; + left: 0; + right: 0; + padding: 20px; +} + +a { + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +footer a { + color: #775; +} + +#resistor-query { + font-size: 20px; + border: 1px solid #999; + color: #fff; + background-color: #444; + outline: none; + width: 180px; +} + +.resistor-stripe { + width: 80px; + height: 150px; + display: inline-block; + padding: 4px 4px; +} + +.resistor-smt { + display: inline-block; + padding: 0px 10px; + font-size: 35px; + background-color: #000; + border-left: 15px solid silver; + border-right: 15px solid silver; + border-top: 1px solid silver; + border-bottom: 1px solid silver; + margin-right: 10px; +} + +@media print, screen and (max-width: 520px) { + .resistor-stripe { + width: 55px; + font-size: 80%; + height: 100px; + } + .resistor-smt { + font-size: 25px; + border-left: 12px solid silver; + border-right: 12px solid silver; + } +} + +@media print, screen and (max-width: 410px) { + .resistor-stripe { + width: 35px; + font-size: 55%; + height: 70px; + } + .resistor-smt { + font-size: 18px; + border-left: 8px solid silver; + border-right: 8px solid silver; + } +} + +@media print, screen and (max-width: 300px) { + .resistor-stripe { + width: 25px; + font-size: 50%; + height: 60px; + padding: 2px; + } + .resistor-smt { + font-size: 13px; + border-left: 6px solid silver; + border-right: 6px solid silver; + padding: 2px 4px; + } +} + +@media print, screen and (max-height: 660px) { + .resistor-stripe { + height: 55px; + } + footer { + position: inherit; + padding: 10px 0; + } +} diff --git a/packages/web/site/.gitignore b/packages/web/site/.gitignore new file mode 100644 index 0000000..d298be1 --- /dev/null +++ b/packages/web/site/.gitignore @@ -0,0 +1 @@ +public/ \ No newline at end of file diff --git a/packages/web/site/config.toml b/packages/web/site/config.toml new file mode 100644 index 0000000..6762a97 --- /dev/null +++ b/packages/web/site/config.toml @@ -0,0 +1,8 @@ +base_url = "https://kleidi.ca" +build_search_index = false +generate_feeds = true +minify_html = true +author = "Kleidi Bujari" + +[markdown] +highlight_code = false diff --git a/packages/web/site/content/about/index.md b/packages/web/site/content/about/index.md new file mode 100644 index 0000000..65c4556 --- /dev/null +++ b/packages/web/site/content/about/index.md @@ -0,0 +1,38 @@ +--- +title: "" +--- + +I'm a programmer working on Linux stuff, +distributed systems, +and compilers/runtimes. + +## Uses + +I run NixOS on all my computers and servers, +and prefer to use simple unixy workflows. + +### Editors + +I use Emacs as my text editor, +although its slowly taking over my workflow as I grow proficient. +Rather than use a premade distribution, +I decided early on to go vanilla and build a config myself. +Part of the reasoning was to get a better understanding of the core emacs philosophy before adding plugins, +the other part being that I didn't know what most plugins even did. + +In the past I enjoyed using neovim but left to try out the emacs hype. +I didn't think they were too different until I tried using neovim again after ~6 months, +and immediately missed all the functionality from emacs, +maybe I'll elaborate in a post one day. +Sure, neovim is a lot more minimal as an editor, +but emacs aims to be a computing platorm with a text editor bolted on. +They are ultimately trying to do different things, +and lisp is just better than lua. + +I've played around with Helix and Kakoune but haven't dedicated serious time yet. + +## Meta + +This site is built mostly using [zola](http://getzola.org), +with other projects built with nix sprinkled in afterwards. +The entire site is then generated as a nix derivation and served from there. diff --git a/packages/web/site/content/paper-reviews/_index.md b/packages/web/site/content/paper-reviews/_index.md new file mode 100644 index 0000000..33c9820 --- /dev/null +++ b/packages/web/site/content/paper-reviews/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Paper Reviews" +sort_by = "date" +generate_feeds = true ++++ + +Once in a while I take some notes. \ No newline at end of file diff --git a/packages/web/site/content/posts/_index.md b/packages/web/site/content/posts/_index.md new file mode 100644 index 0000000..c7c63df --- /dev/null +++ b/packages/web/site/content/posts/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Posts" +sort_by = "date" +generate_feeds = true ++++ + +Writings and musings. \ No newline at end of file diff --git a/packages/web/site/content/posts/deterministic-hostnames.md b/packages/web/site/content/posts/deterministic-hostnames.md new file mode 100644 index 0000000..43dc7d8 --- /dev/null +++ b/packages/web/site/content/posts/deterministic-hostnames.md @@ -0,0 +1,80 @@ +--- +title: "Deterministic and unique network hostnames" +date: "2024-11-10" +--- + +As part of building out a Kubernetes cluster, I wanted to build and distribute a +single OS image to create stateless worker nodes. Using network booting, and +some clever tricks to differentiate nodes, we can create a scaleable and +efficient farm of workers for a cluster that don't even need disks. + +The idea came from a plan to build a cluster using the +[compute blade](https://computeblade.com/), and a few Raspberry Pi SBCs I +already own. Running the cluster from an SD card is not recommended due to the +not-so-great reliability of the flash used by most manufacturers, so I wanted to +try PXE booting each Pi to save money rather than purchasing an SSD for each +one. The compute blades do support an NVMe disk, but I plan to use those for a +storage cluster later, so they need to remain empty. + +## Base image + +Alpine Linux has been my preferred server OS for a long time. It provides a very +lightweight base system, and bundles an excellent bootstrapping system, +[apkovl](https://wiki.alpinelinux.org/wiki/Alpine_local_backup), that allows the +user to save a set of customisations to an system as an overlay to a stock +Alpine live image. In other words, we can create our image once, save the +changes as an `apkovl.tar.gz` file, and apply the same changes to a base system +on boot. This file can even be provided as a +[kernel parameter](https://wiki.alpinelinux.org/wiki/PXE_boot#Guide_to_options) +and will be fetched from a remote webserver automatically! + +Since the image and configuration will be shipped to the node via the network, +an added benefit of using Alpine is its tiny space consumption. I'm not using +enough nodes for this to really matter, but it's a cool optimization regardless. + +## Differentiating the nodes + +One of the main goals of this project is that there should be no persistent +storage required outside the boot image itself. Since every node will download +and generate the same root file-system on startup, the first problem that arises +is how the nodes will identify themselves both on the network and the cluster, +given that it's not possible to name them ahead of time. In other words, any +given node has to generate a unique hostname that won't collide with other +workers, and that will be the same each time that node boots. + +Since these nodes will not have a predefined name, we have to rely on +characteristics of the hardware to differentiate each one. The hardware MAC +address is perfect for this, since it's unique to to each node and will not be +wiped away after the node reboots. On a system like Linux that exposes its +hardware through a _sysfs_, we can find a file containing the address at +`/sys/class/net/eth0/address`. I don't really like the idea of attaching the +literal MAC address of the node to its network hostname, since it's a security +risk, and a bit too verbose. Instead, we can transform it into something safer +using a `sha1sum`, which is already present on our Alpine base system: + +```console +sha1sum /sys/class/net/eth0/address | head -c 6 | awk '{print "worker-" $0}' +``` + +### Applying the new name + +Ideally, the node should apply its generated hostname before reaching out for an +address over DHCP or joining the cluster. We can make sure it happens before any +traffic is sent out by adding a `pre-up` command to the right interface in +`/etc/network/interfaces`: + +``` + +... + +auto eth0 +iface eth0 inet dhcp + pre-up sha1sum /sys/class/net/eth0/address | head -c 6 | awk '{print "worker-" $0}' > /etc/hostname + +... +``` + +The VM I tested with looks outputs `worker-e2fae8`. Pretty clean result, and if +you want to know the physical node that maps to each hostname, you can take note +of the MAC address beforehand and generate the same hash on another computer to +match them up. diff --git a/packages/web/site/content/posts/nohup.md b/packages/web/site/content/posts/nohup.md new file mode 100644 index 0000000..64f7983 --- /dev/null +++ b/packages/web/site/content/posts/nohup.md @@ -0,0 +1,26 @@ +--- +title: "Spawning background processes" +date: "2024-11-17" +--- + +Working in a terminal, +I often pair my editor with a background process watching files. +Before reaching for terminal multiplexers, +see if you can get away with simple tty job control. +Spawn the background process, +still attached to the terminal instance: + +``` +program args & +``` + +Also redirect its output to a file, +for when the process writes to the tty from the background: + +``` +nohup program args & +``` + +Extra reading: + +- diff --git a/packages/web/site/content/posts/overusing-emacs-modes.md b/packages/web/site/content/posts/overusing-emacs-modes.md new file mode 100644 index 0000000..1ea1654 --- /dev/null +++ b/packages/web/site/content/posts/overusing-emacs-modes.md @@ -0,0 +1,39 @@ +--- +title: On editors and plugins +date: 2025-08-14 +draft: true +--- + +The healthy package ecosystems that extensible editors have is a standout feature. + +After setting up my first neovim package manager, +I never hesitated testdriving cool plugins from the community. +I installed a terminal plugin that without really having problems with `:term`, +or using a file manager without ever trying `:netrw`. +After a while, I found neovim overloaded with more features than I understood, +and frequently hit problems that encouraged yet another plugin to fix. +The issue wasn't that I had too many plugins per se, +it was that I didn't really understand what they did. +I promptly declared config bankruptcy. + +Going forward I strictly used plugins that were worth their weight. +That is, how they affect performance as well as any cognitive slowdown. +I quickly found that when a plugin strays too far from core neovim, +like not hooking into builtin functionality or not reusing normal keybinds, +it wouldn't make the cut. +It is simply not worth learning if it doesn't enrich the editor as a whole. + +Using this philosophy for a few years, +the only external plugins that survived were +LSP completion, a proper code formatter, and fzf for search. +Some plugins ended up in core neovim, +like language aware commenting and better compile commands. +Most were deleted. + +This meant my editor was really good at editing text and code projects, +and not much more. +It was fine that it didn't have a UI for viewing GitHub stars or whatever. +I could live without + +## Enter emacs +Modes reshape emacs to better fit certain work. diff --git a/packages/web/site/content/posts/stateless-compute-networks.md b/packages/web/site/content/posts/stateless-compute-networks.md new file mode 100644 index 0000000..bac9e5d --- /dev/null +++ b/packages/web/site/content/posts/stateless-compute-networks.md @@ -0,0 +1,41 @@ +--- +title: "On stateless compute networks" +date: "2024-11-10" +draft: true +--- + +On the topic of distributed systems and clustering, +I am quite invested in the idea of compute nodes that rely entirely on the network for configuration. +Arbitrary nodes can join a pre-existing cluster, +offering their CPU time and memory for computation without relying on any pre-existing configuration on the node itself. +In other words, any computer could pick up work, +only needing power and a network connection to the cluster. + +Perhaps this eventually leads into a "self-healing" cluster where only one node is manually bootstrapped, +which then serves a _configuration endpoint_ for other stateless nodes to reach out to for their instructions, +which they will then also serve once they are themselves ready. + +Early revisions of these notes mention Kubernetes, +but I am also trying to achieve similar results with NixOS on a custom project. +In any case, these are my ever-updating notes towards a general implementation of a stateless distributed systems architecture. + +## Self healing cluster + +Assuming control of an external DHCP server, +a self healing Kubernetes cluster would be feasible, +with the PXE boot artifacts supplied by the cluster itself. +That is, as long as one node is running the pod hosting the artifacts on a given endpoint, +other nodes can boot those artifacts and join the cluster, +thereby being able to host the artifacts as well. + +## Configuration endpoint + +The nodes shouldn't require a disk installed to be able to join the network. +Rather, the lofty goal of zero-configuration compute nodes passes the job of node initialization to the supporting network. +This is accomplished with PXE boot instructions supplied over DHCP. + +I delegate the following tasks to a single node in the subnet: + +- Gateway: Optional outbound connections if required +- DHCP server: Cluster IPAM +- TFTP and HTTP server: Serves iPXE firmware and kernel/initrd artifacts diff --git a/packages/web/site/content/posts/vim-compilers.md b/packages/web/site/content/posts/vim-compilers.md new file mode 100644 index 0000000..f735228 --- /dev/null +++ b/packages/web/site/content/posts/vim-compilers.md @@ -0,0 +1,20 @@ +--- +title: "Neovim's built-in compilers" +date: "2025-01-17" +--- + +Today I learned that neovim's `:make` comes with many +[backends](https://neovim.io/doc/user/quickfix.html#_6.-selecting-a-compiler) +already configured. +This works for checking c/cpp and python files, among other, but I was +most interested to see [Typst] and [Pandoc] listed as well. + +I was looking to add this functionality with a plugin or implementing it +manually, +where a document can be compiled on the fly from the editor. +After setting `:compiler pandoc`, +generating a pdf is done with `:make pdf`, +with other pandoc options just appended afterwards if needed. + +[typst]: https://typst.app +[pandoc]: https://github.com/jgm/pandoc diff --git a/packages/web/site/package.nix b/packages/web/site/package.nix new file mode 100644 index 0000000..aed7567 --- /dev/null +++ b/packages/web/site/package.nix @@ -0,0 +1,36 @@ +{ + lib, + zola, + depot, + stdenvNoCC, + ... +}: + +let + inherit (lib) fileset; +in +stdenvNoCC.mkDerivation { + name = "megasite"; + src = fileset.toSource { + root = ./.; + fileset = fileset.unions [ + ./config.toml + ./content + ./static + ./templates + ]; + }; + + nativeBuildInputs = [ zola ]; + buildPhase = "zola build"; + + installPhase = '' + mkdir -p $out/share + + # output site + cp -rv public/* $out/ + + # copy cv + cp -v ${depot.misc.cv} $out/share/cv.pdf + ''; +} diff --git a/packages/web/site/static/atom.svg b/packages/web/site/static/atom.svg new file mode 100644 index 0000000..22a8b23 --- /dev/null +++ b/packages/web/site/static/atom.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/web/site/static/theme.css b/packages/web/site/static/theme.css new file mode 100644 index 0000000..873a6ca --- /dev/null +++ b/packages/web/site/static/theme.css @@ -0,0 +1,71 @@ +/* Global Reset */ + +* { + margin: 0; + padding: 0; +} + +h1, h2, h3, h4, h5, h6 { + font-size: 110%; + margin: 0.50em 0; +} + +h1 { font-size: 120%; } + +:root { + --bg: #181616; + --fg: #c5c9c5; + --link: #76946a; + --linkhover: #98bb6c; +} + +html { + scroll-behavior: smooth; + color-scheme: dark; +} + +body { + font-size: 1em; + font-family: system-ui, sans-serif; + padding: 0 0.75em; + max-width: 42em; + margin: auto; + background: var(--bg); + color: var(--fg); +} + +p { + line-height: 1.3em; + margin: 1em 0; +} + +th, td { + padding: 0.2em 0.4em; + border: thin solid; +} + +table { + border: thin solid; + border-collapse: collapse; +} + +a, a:link { + color: var(--link); +} + +a:hover { + color: var(--linkhover); +} + +article img { + display: block; + margin: 0 auto; + max-width: 80%; + height: auto; + object-fit: contain; +} + +pre { + padding: 1em; + overflow-x: scroll; +} diff --git a/packages/web/site/templates/404.html b/packages/web/site/templates/404.html new file mode 100644 index 0000000..a4669df --- /dev/null +++ b/packages/web/site/templates/404.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} + +{% block content %} + + Error 404! + + +404! +{% endblock content %} diff --git a/packages/web/site/templates/base.html b/packages/web/site/templates/base.html new file mode 100644 index 0000000..8f49bb2 --- /dev/null +++ b/packages/web/site/templates/base.html @@ -0,0 +1,31 @@ + + + + + + {% block title %}kleidi.ca{% endblock title %} + + {% block head%}{% endblock head %} + + +
+ + Kleidi Bujari <mail@4kb.net> + + +
+
{% block content %} {% endblock %}
+ + diff --git a/packages/web/site/templates/index.html b/packages/web/site/templates/index.html new file mode 100644 index 0000000..bc2994a --- /dev/null +++ b/packages/web/site/templates/index.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} +{% block content %} + +{% for name in ["posts", "paper-reviews"] %} +{% set section = get_section(path=name ~ "/_index.md") %} +{%- if section.pages | length > 0 %} +
+

{{ section.title }}

+
    + {% for page in section.pages | slice(end=3) %} +
  • + {{ page.title }} +
    + +
  • + {% endfor %} +
+ + {%- if section.pages | length > 2 %} + see more ↗ + {% endif %} +
+{% endif %} +{% endfor %} + +{% endblock content %} diff --git a/packages/web/site/templates/page.html b/packages/web/site/templates/page.html new file mode 100644 index 0000000..8189fe6 --- /dev/null +++ b/packages/web/site/templates/page.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% if page.title %} +{% block title%} +{{ page.title }} :: {{ super() }} +{% endblock title %} +{% endif %} + +{% block content %} + +
+

{{ page.title }}

+ + {{ page.content | safe}} +
+ +{% endblock content %} diff --git a/packages/web/site/templates/section.html b/packages/web/site/templates/section.html new file mode 100644 index 0000000..9bd8956 --- /dev/null +++ b/packages/web/site/templates/section.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} + +{% block title %} +{{ section.title | lower }} :: {{ super() }} {% endblock title %} +{% block content %} + +{% block head %} + +{% endblock head%} + +

{{ section.title }}

+

{{ section.content | safe }}

+ +
+
    + {% for page in section.pages %} +
  • + {{ page.title }} +
    + {{ page.date | date(format="%B %d, %Y") }} +
  • + {% endfor %} +
+{% endblock content %} -- cgit v1.3.1