add flake, copytoram boot image, wip pxe
This commit is contained in:
parent
4fb1bd90db
commit
aa168397b3
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
*~
|
||||
result
|
||||
*.qcow2
|
||||
|
||||
141
README.md
141
README.md
@ -104,11 +104,152 @@ python3 --version
|
||||
|
||||
---
|
||||
|
||||
## Nix-Based Setup (Alternative)
|
||||
|
||||
This workshop includes a Nix flake for reproducible environments. Use this if you have Nix installed or want a pre-configured bootable image.
|
||||
|
||||
### Quick Reference
|
||||
|
||||
| Goal | Command |
|
||||
|------|---------|
|
||||
| Dev shell with all tools | `nix develop` |
|
||||
| Apply tools to Ubuntu | `nix run github:numtide/system-manager -- switch --flake .` |
|
||||
| Build bootable USB ISO | `nix build .#iso` |
|
||||
| Build netboot files | `nix build .#netboot` |
|
||||
|
||||
### Development Shell
|
||||
|
||||
Get all workshop tools in your current shell without installing anything system-wide:
|
||||
|
||||
```bash
|
||||
cd perf-workshop
|
||||
nix develop
|
||||
|
||||
# Now you have: perf, strace, py-spy, bpftrace, hyperfine, valgrind, flamegraph, pyroscope
|
||||
perf --version
|
||||
py-spy --help
|
||||
```
|
||||
|
||||
### System-Manager (Ubuntu/Debian)
|
||||
|
||||
Install all workshop tools on an existing Ubuntu system using Nix:
|
||||
|
||||
```bash
|
||||
# Apply the configuration (installs tools via Nix)
|
||||
nix run 'github:numtide/system-manager' -- switch --flake .
|
||||
|
||||
# Configure perf permissions (system-manager can't do this)
|
||||
sudo /etc/perf-workshop-setup.sh
|
||||
```
|
||||
|
||||
This installs tools into `/nix/store` and adds them to your PATH without conflicting with apt packages.
|
||||
|
||||
### Bootable USB Image
|
||||
|
||||
Build a complete NixOS image with XFCE desktop, all tools pre-installed, and workshop materials:
|
||||
|
||||
```bash
|
||||
# Build the ISO (~4-5 GB)
|
||||
nix build .#iso
|
||||
|
||||
# Flash to USB (replace sdX with your device)
|
||||
sudo dd if=result/iso/*.iso of=/dev/sdX bs=4M status=progress conv=fsync
|
||||
```
|
||||
|
||||
**ISO Features:**
|
||||
- XFCE desktop with auto-login (user: `workshop`, password: `workshop`)
|
||||
- `copytoram` enabled — boots from USB, runs entirely from RAM (USB can be removed after boot)
|
||||
- `kernel.perf_event_paranoid=1` pre-configured
|
||||
- Workshop materials in `/home/workshop/perf-workshop`
|
||||
- Desktop shortcut to open terminal in workshop directory
|
||||
- SSH enabled for remote access
|
||||
|
||||
**Requirements:** 8+ GB RAM recommended (the system runs from RAM)
|
||||
|
||||
### Netboot over LAN
|
||||
|
||||
For workshops with many participants, netboot is more efficient than flashing multiple USBs.
|
||||
|
||||
```bash
|
||||
# Build netboot bundle
|
||||
nix build .#netboot
|
||||
cd result
|
||||
|
||||
# Contents:
|
||||
# - bzImage (kernel)
|
||||
# - initrd (initrd with full system, ~2-4 GB)
|
||||
# - netboot.ipxe (iPXE boot script)
|
||||
```
|
||||
|
||||
**Option 1: Pixiecore (easiest)**
|
||||
|
||||
Pixiecore is an all-in-one PXE server — just point it at the files:
|
||||
|
||||
```bash
|
||||
nix shell nixpkgs#pixiecore
|
||||
|
||||
# Serve on your LAN (requires root for DHCP proxy)
|
||||
sudo pixiecore boot bzImage initrd \
|
||||
--cmdline "$(grep -oP 'imgargs.*? \K.*' netboot.ipxe)"
|
||||
```
|
||||
|
||||
Participants set their BIOS to network boot and get the workshop environment automatically.
|
||||
|
||||
**Option 2: dnsmasq + HTTP server**
|
||||
|
||||
For more control or integration with existing infrastructure:
|
||||
|
||||
```bash
|
||||
# Terminal 1: Serve files over HTTP
|
||||
python3 -m http.server 8080
|
||||
```
|
||||
|
||||
Configure dnsmasq (`/etc/dnsmasq.d/workshop.conf`):
|
||||
```ini
|
||||
interface=eth0
|
||||
dhcp-range=192.168.1.100,192.168.1.200,12h
|
||||
enable-tftp
|
||||
tftp-root=/path/to/result
|
||||
dhcp-boot=netboot.ipxe
|
||||
```
|
||||
|
||||
**Option 3: Existing PXE infrastructure**
|
||||
|
||||
Copy files to your TFTP/HTTP server and configure your DHCP server to serve `netboot.ipxe`.
|
||||
|
||||
### Flake Outputs Reference
|
||||
|
||||
```bash
|
||||
# List all outputs
|
||||
nix flake show
|
||||
|
||||
# Available outputs:
|
||||
# - devShells.x86_64-linux.default # Development shell
|
||||
# - packages.x86_64-linux.iso # Bootable ISO image
|
||||
# - packages.x86_64-linux.netboot # Netboot bundle (kernel + initrd + ipxe)
|
||||
# - packages.x86_64-linux.netboot-kernel
|
||||
# - packages.x86_64-linux.netboot-initrd
|
||||
# - packages.x86_64-linux.netboot-ipxe
|
||||
# - nixosConfigurations.workshop-iso # NixOS config for ISO
|
||||
# - nixosConfigurations.workshop-netboot # NixOS config for netboot
|
||||
# - systemConfigs.default # system-manager config for Ubuntu
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
perf-workshop/
|
||||
├── README.md # This file
|
||||
├── flake.nix # Nix flake (dev shell, ISO, netboot)
|
||||
├── flake.lock # Locked dependencies
|
||||
├── nix/
|
||||
│ ├── packages.nix # Shared package list
|
||||
│ ├── common.nix # Common NixOS configuration
|
||||
│ ├── iso.nix # ISO-specific configuration
|
||||
│ ├── netboot.nix # Netboot-specific configuration
|
||||
│ └── system-manager.nix # Ubuntu system-manager module
|
||||
├── common/
|
||||
│ └── CHEATSHEET.md # Quick reference card
|
||||
├── scenario1-python-to-c/
|
||||
|
||||
82
flake.lock
generated
Normal file
82
flake.lock
generated
Normal file
@ -0,0 +1,82 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1767767207,
|
||||
"narHash": "sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5912c1772a44e31bf1c63c0390b90501e5026886",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"system-manager": "system-manager"
|
||||
}
|
||||
},
|
||||
"system-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767765652,
|
||||
"narHash": "sha256-brTUOSGRmUCU0xJZI/aD5jUYZJm4RhqMRfkzS4veohg=",
|
||||
"owner": "numtide",
|
||||
"repo": "system-manager",
|
||||
"rev": "85610060c48a0b9f1883d5b2525866fc6ddbbe03",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "system-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
144
flake.nix
Normal file
144
flake.nix
Normal file
@ -0,0 +1,144 @@
|
||||
{
|
||||
description = "Linux Performance Engineering Workshop";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
|
||||
system-manager = {
|
||||
url = "github:numtide/system-manager";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, system-manager, flake-utils }:
|
||||
let
|
||||
# Workshop source for embedding in ISO
|
||||
workshopSrc = builtins.path {
|
||||
path = ./.;
|
||||
name = "perf-workshop";
|
||||
filter = path: type:
|
||||
let
|
||||
baseName = baseNameOf path;
|
||||
in
|
||||
# Exclude nix build artifacts and git
|
||||
!(baseName == "result" ||
|
||||
baseName == ".git" ||
|
||||
baseName == "flake.lock" ||
|
||||
nixpkgs.lib.hasSuffix "~" baseName);
|
||||
};
|
||||
in
|
||||
flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
workshopPackages = import ./nix/packages.nix { inherit pkgs; };
|
||||
in
|
||||
{
|
||||
# Development shell with all workshop tools
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = workshopPackages;
|
||||
shellHook = ''
|
||||
echo "Linux Performance Workshop Development Environment"
|
||||
echo ""
|
||||
echo "Available tools: perf, strace, py-spy, hyperfine, bpftrace, ..."
|
||||
echo "Run 'make' in any scenario directory to build examples"
|
||||
'';
|
||||
};
|
||||
|
||||
# Package containing workshop materials
|
||||
packages.workshop-materials = pkgs.runCommand "workshop-materials" {} ''
|
||||
mkdir -p $out/share/perf-workshop
|
||||
cp -r ${workshopSrc}/* $out/share/perf-workshop/
|
||||
'';
|
||||
}
|
||||
) // {
|
||||
# System-manager configuration for Ubuntu
|
||||
systemConfigs.default = system-manager.lib.makeSystemConfig {
|
||||
modules = [
|
||||
./nix/system-manager.nix
|
||||
];
|
||||
};
|
||||
|
||||
# NixOS configuration for bootable workshop ISO
|
||||
nixosConfigurations.workshop-iso = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = { inherit workshopSrc; };
|
||||
modules = [
|
||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix"
|
||||
./nix/iso.nix
|
||||
];
|
||||
};
|
||||
|
||||
# NixOS configuration for netboot
|
||||
nixosConfigurations.workshop-netboot = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = { inherit workshopSrc; };
|
||||
modules = [
|
||||
"${nixpkgs}/nixos/modules/installer/netboot/netboot.nix"
|
||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix"
|
||||
./nix/netboot.nix
|
||||
];
|
||||
};
|
||||
|
||||
# Convenient alias for building the ISO
|
||||
packages.x86_64-linux.iso =
|
||||
self.nixosConfigurations.workshop-iso.config.system.build.isoImage;
|
||||
|
||||
# Netboot artifacts
|
||||
packages.x86_64-linux.netboot-kernel =
|
||||
self.nixosConfigurations.workshop-netboot.config.system.build.kernel;
|
||||
packages.x86_64-linux.netboot-initrd =
|
||||
self.nixosConfigurations.workshop-netboot.config.system.build.netbootRamdisk;
|
||||
packages.x86_64-linux.netboot-ipxe =
|
||||
self.nixosConfigurations.workshop-netboot.config.system.build.netbootIpxeScript;
|
||||
|
||||
# Bundle netboot files for easy serving
|
||||
packages.x86_64-linux.netboot = let
|
||||
pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||
cfg = self.nixosConfigurations.workshop-netboot.config;
|
||||
kernel = "${cfg.system.build.kernel}/bzImage";
|
||||
initrd = "${cfg.system.build.netbootRamdisk}/initrd";
|
||||
in pkgs.runCommand "workshop-netboot" {} ''
|
||||
mkdir -p $out
|
||||
ln -s ${kernel} $out/bzImage
|
||||
ln -s ${initrd} $out/initrd
|
||||
cp ${cfg.system.build.netbootIpxeScript} $out/netboot.ipxe
|
||||
|
||||
cat > $out/README.md << 'EOF'
|
||||
# Workshop Netboot Files
|
||||
|
||||
## Quick Start with Pixiecore (easiest)
|
||||
|
||||
```bash
|
||||
# Serve on your LAN (requires root for DHCP)
|
||||
sudo pixiecore boot bzImage initrd --cmdline "$(grep -oP 'imgargs.*? \K.*' netboot.ipxe)"
|
||||
```
|
||||
|
||||
## Using dnsmasq + HTTP server
|
||||
|
||||
1. Start HTTP server in this directory:
|
||||
```bash
|
||||
python3 -m http.server 8080
|
||||
```
|
||||
|
||||
2. Configure dnsmasq (adjust interface/IP):
|
||||
```
|
||||
interface=eth0
|
||||
dhcp-range=192.168.1.100,192.168.1.200,12h
|
||||
enable-tftp
|
||||
tftp-root=/path/to/this/dir
|
||||
dhcp-boot=netboot.ipxe
|
||||
```
|
||||
|
||||
3. For UEFI clients, you may need iPXE chainloading.
|
||||
|
||||
## Files
|
||||
|
||||
- bzImage: Linux kernel
|
||||
- initrd: Initial ramdisk (contains full system)
|
||||
- netboot.ipxe: iPXE boot script
|
||||
EOF
|
||||
'';
|
||||
};
|
||||
}
|
||||
100
nix/common.nix
Normal file
100
nix/common.nix
Normal file
@ -0,0 +1,100 @@
|
||||
# Common NixOS configuration shared between ISO and netboot
|
||||
{ config, lib, pkgs, workshopSrc, ... }:
|
||||
|
||||
let
|
||||
workshopPackages = import ./packages.nix {
|
||||
inherit pkgs;
|
||||
kernelPackages = config.boot.kernelPackages;
|
||||
};
|
||||
in
|
||||
{
|
||||
# System identification
|
||||
system.stateVersion = "24.11";
|
||||
|
||||
# Use a recent stable kernel
|
||||
boot.kernelPackages = pkgs.linuxPackages_6_12;
|
||||
|
||||
# Set perf permissions for non-root users
|
||||
boot.kernel.sysctl = {
|
||||
"kernel.perf_event_paranoid" = 1;
|
||||
"kernel.kptr_restrict" = 0; # Allow reading kernel symbols
|
||||
};
|
||||
|
||||
# Workshop packages
|
||||
environment.systemPackages = workshopPackages ++ (with pkgs; [
|
||||
# Additional GUI utilities
|
||||
firefox # for viewing flamegraphs
|
||||
xfce4-terminal
|
||||
]);
|
||||
|
||||
# Create workshop user with auto-login
|
||||
users.users.workshop = {
|
||||
isNormalUser = true;
|
||||
description = "Workshop User";
|
||||
extraGroups = [ "wheel" "video" "audio" "networkmanager" ];
|
||||
initialPassword = "workshop";
|
||||
home = "/home/workshop";
|
||||
};
|
||||
|
||||
# Auto-login to workshop user
|
||||
services.displayManager.autoLogin = {
|
||||
enable = true;
|
||||
user = "workshop";
|
||||
};
|
||||
|
||||
# Allow passwordless sudo for workshop user
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
|
||||
# XFCE desktop environment
|
||||
services.xserver.desktopManager.xfce.enable = true;
|
||||
services.displayManager.defaultSession = "xfce";
|
||||
|
||||
# Embed workshop materials into home directory
|
||||
system.activationScripts.workshopMaterials = ''
|
||||
mkdir -p /home/workshop/perf-workshop
|
||||
cp -rT ${workshopSrc} /home/workshop/perf-workshop
|
||||
chmod -R u+w /home/workshop/perf-workshop
|
||||
chown -R workshop:users /home/workshop/perf-workshop
|
||||
'';
|
||||
|
||||
# Desktop shortcut for workshop
|
||||
environment.etc."skel/Desktop/Workshop.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Performance Workshop
|
||||
Comment=Open terminal in workshop directory
|
||||
Exec=xfce4-terminal --working-directory=/home/workshop/perf-workshop
|
||||
Icon=utilities-terminal
|
||||
Terminal=false
|
||||
Categories=Development;
|
||||
'';
|
||||
|
||||
# Copy desktop shortcut for workshop user
|
||||
system.activationScripts.workshopDesktop = ''
|
||||
mkdir -p /home/workshop/Desktop
|
||||
cp /etc/skel/Desktop/Workshop.desktop /home/workshop/Desktop/
|
||||
chown -R workshop:users /home/workshop/Desktop
|
||||
chmod +x /home/workshop/Desktop/Workshop.desktop
|
||||
'';
|
||||
|
||||
# Networking
|
||||
networking = {
|
||||
hostName = "perf-workshop";
|
||||
networkmanager.enable = true;
|
||||
};
|
||||
|
||||
# Enable SSH for remote access (useful for debugging)
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PermitRootLogin = "no";
|
||||
PasswordAuthentication = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Timezone (can be changed by user)
|
||||
time.timeZone = "Asia/Kolkata";
|
||||
|
||||
# Locale
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
}
|
||||
17
nix/iso.nix
Normal file
17
nix/iso.nix
Normal file
@ -0,0 +1,17 @@
|
||||
# NixOS ISO-specific configuration
|
||||
{ config, lib, pkgs, workshopSrc, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
# Enable copytoram - boots from USB, runs entirely from RAM
|
||||
boot.kernelParams = [ "copytoram" ];
|
||||
|
||||
# ISO image customization
|
||||
isoImage = {
|
||||
volumeID = lib.mkForce "PERF_WORKSHOP";
|
||||
makeEfiBootable = true;
|
||||
makeUsbBootable = true;
|
||||
};
|
||||
image.fileName = lib.mkForce "perf-workshop-${config.system.nixos.label}-x86_64.iso";
|
||||
}
|
||||
8
nix/netboot.nix
Normal file
8
nix/netboot.nix
Normal file
@ -0,0 +1,8 @@
|
||||
# NixOS netboot-specific configuration
|
||||
{ config, lib, pkgs, workshopSrc, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
# Netboot runs entirely from RAM by default (initrd contains squashfs)
|
||||
}
|
||||
45
nix/packages.nix
Normal file
45
nix/packages.nix
Normal file
@ -0,0 +1,45 @@
|
||||
# Shared package list for the Linux Performance Workshop
|
||||
{ pkgs, kernelPackages ? pkgs.linuxPackages }:
|
||||
|
||||
with pkgs; [
|
||||
# Build essentials
|
||||
gcc
|
||||
gnumake
|
||||
binutils
|
||||
pkg-config
|
||||
|
||||
# Performance and tracing tools
|
||||
perf
|
||||
strace
|
||||
ltrace
|
||||
htop
|
||||
bpftrace
|
||||
|
||||
# Python ecosystem
|
||||
(python3.withPackages (ps: with ps; [
|
||||
pip
|
||||
flask # for scenario7 pyroscope demo
|
||||
]))
|
||||
py-spy
|
||||
|
||||
# Benchmarking and debugging
|
||||
hyperfine
|
||||
valgrind
|
||||
flamegraph
|
||||
|
||||
# USDT/SDT support (provides sys/sdt.h)
|
||||
libsystemtap
|
||||
|
||||
# Continuous profiling
|
||||
pyroscope
|
||||
|
||||
# Utilities
|
||||
curl
|
||||
wget
|
||||
git
|
||||
file
|
||||
which
|
||||
less
|
||||
vim
|
||||
nano
|
||||
]
|
||||
33
nix/system-manager.nix
Normal file
33
nix/system-manager.nix
Normal file
@ -0,0 +1,33 @@
|
||||
# System-manager module for Ubuntu systems
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
workshopPackages = import ./packages.nix { inherit pkgs; };
|
||||
in
|
||||
{
|
||||
config = {
|
||||
nixpkgs.hostPlatform = "x86_64-linux";
|
||||
|
||||
environment.systemPackages = workshopPackages;
|
||||
|
||||
# Create a script to configure perf permissions
|
||||
# (system-manager cannot set sysctl directly)
|
||||
environment.etc."perf-workshop-setup.sh" = {
|
||||
mode = "0755";
|
||||
text = ''
|
||||
#!/bin/sh
|
||||
# Run this script to enable perf for non-root users
|
||||
echo "Setting kernel.perf_event_paranoid=1..."
|
||||
sudo sysctl -w kernel.perf_event_paranoid=1
|
||||
|
||||
# Make it persistent
|
||||
if ! grep -q "kernel.perf_event_paranoid" /etc/sysctl.conf 2>/dev/null; then
|
||||
echo "kernel.perf_event_paranoid=1" | sudo tee -a /etc/sysctl.conf
|
||||
echo "Added to /etc/sysctl.conf for persistence"
|
||||
fi
|
||||
|
||||
echo "Done! You can now use perf as a regular user."
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user