diff --git a/flake.nix b/flake.nix index a4a296e..7305b25 100644 --- a/flake.nix +++ b/flake.nix @@ -1,137 +1,273 @@ { - description = "CODE CRISPIES Workshop Infrastructure"; + description = "CODE CRISPIES Workshop Infrastructure"; - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - nixos-generators.url = "github:nix-community/nixos-generators"; - }; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixos-generators.url = "github:nix-community/nixos-generators"; + }; - outputs = { self, nixpkgs, nixos-generators }: - let - system = "x86_64-linux"; - pkgs = nixpkgs.legacyPackages.${system}; - # You can change the range here for local development (e.g., 1 2) - participantRange = nixpkgs.lib.range 1 2; - fullParticipantNames = [ - "hopper" "curie" "lovelace" "noether" "hamilton" - "franklin" "johnson" "clarke" "goldberg" "liskov" - "wing" "rosen" "shaw" "karp" "rich" - ]; - in - { - packages.${system} = { - live-iso = nixos-generators.nixosGenerate { - inherit system; - format = "iso"; - modules = [ - ({ pkgs, ... }: { - system.stateVersion = "25.05"; - networking.networkmanager.enable = true; - users.users.workshop = { - isNormalUser = true; - shell = pkgs.zsh; - extraGroups = [ "wheel" ]; - password = "workshop"; - }; - # Use generic autologin for the live ISO TTY - services.getty.autologinUser = "workshop"; - programs.zsh.enable = true; - environment.systemPackages = with pkgs; [ openssh curl git ]; - services.xserver = { - enable = true; - displayManager.lightdm.enable = true; - desktopManager.xfce.enable = true; - displayManager.sessionCommands = '' - ${pkgs.xfce.xfce4-terminal}/bin/xfce4-terminal -e "sudo -i" & - ''; - }; - }) - ]; - }; - local-vm = self.nixosConfigurations.workshop-local.config.system.build.vm; - }; + outputs = { self, nixpkgs, nixos-generators }: + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + participantRange = nixpkgs.lib.range 1 2; + fullParticipantNames = [ + "hopper" "curie" "lovelace" "noether" "hamilton" + "franklin" "johnson" "clarke" "goldberg" "liskov" + "wing" "rosen" "shaw" "karp" "rich" + ]; + in + { + packages.${system} = { + live-iso = nixos-generators.nixosGenerate { + inherit system; + format = "iso"; + modules = [ + ({ pkgs, ... }: { + system.stateVersion = "25.05"; + networking.networkmanager.enable = true; + users.users.workshop = { + isNormalUser = true; + shell = pkgs.zsh; + extraGroups = [ "wheel" ]; + password = "workshop"; + }; + services.getty.autologinUser = "workshop"; + programs.zsh.enable = true; + environment.systemPackages = with pkgs; [ openssh curl git ]; + services.xserver = { + enable = true; + displayManager.lightdm.enable = true; + desktopManager.xfce.enable = true; + }; + services.displayManager.autoLogin.enable = true; + services.displayManager.autoLogin.user = "workshop"; + }) + ]; + }; + local-vm = self.nixosConfigurations.workshop-local.config.system.build.vm; + }; - nixosConfigurations.workshop-local = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - ({ config, pkgs, ... }: { - system.stateVersion = "25.05"; - boot.loader.grub.enable = false; - boot.loader.generic-extlinux-compatible.enable = true; + nixosConfigurations.workshop-local = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + ({ config, pkgs, ... }: { + system.stateVersion = "25.05"; + boot.loader.grub.enable = false; + boot.loader.generic-extlinux-compatible.enable = true; + + # Enable IP forwarding for NAT + boot.kernel.sysctl."net.ipv4.ip_forward" = 1; + + # Host VM user setup + users.users.workshop = { + isNormalUser = true; + extraGroups = [ "wheel" ]; + password = ""; + shell = pkgs.bash; + }; + + # GUI setup + services.xserver = { + enable = true; + desktopManager.xfce.enable = true; + displayManager.lightdm.enable = true; + }; + services.displayManager.autoLogin.enable = true; + services.displayManager.autoLogin.user = "workshop"; + + # Auto-open root terminal + services.xserver.displayManager.sessionCommands = '' + ${pkgs.xfce.xfce4-terminal}/bin/xfce4-terminal -T "Workshop Root Shell" -e "sudo -i" & + ''; - users.users.workshop = { - isNormalUser = true; - extraGroups = [ "wheel" ]; # for sudo - password = ""; - }; - - # --- THIS IS THE CORRECTED SECTION --- - services.xserver = { - enable = true; - desktopManager.xfce.enable = true; - displayManager.lightdm.enable = true; - }; - # Use the generic, documented options for graphical autologin - services.displayManager.autoLogin.enable = true; - services.displayManager.autoLogin.user = "workshop"; + # Workshop user convenience + programs.bash = { + shellAliases = { + connect = "sudo nixos-container login"; + containers = "sudo nixos-container list"; + root = "sudo -i"; + }; + }; + environment.systemPackages = with pkgs; [ + gnumake nano nixos-container firefox git curl jq + ]; + security.pam.services.login.allowNullPassword = true; + security.sudo.wheelNeedsPassword = false; + networking.hostName = "workshop-vm"; - environment.systemPackages = with pkgs; [ gnumake nano nixos-container firefox ]; - security.pam.services.login.allowNullPassword = true; - security.sudo.wheelNeedsPassword = false; - networking.hostName = "workshop-vm"; + # FIXED: Proper NAT configuration + networking = { + nat = { + enable = true; + internalInterfaces = ["ve-+"]; + externalInterface = "eth0"; + # Ensure we have masquerading + extraCommands = '' + iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j MASQUERADE + ''; + }; + firewall = { + enable = true; + trustedInterfaces = [ "ve-+" ]; + # Allow forwarding from containers + extraCommands = '' + iptables -A FORWARD -i ve-+ -j ACCEPT + iptables -A FORWARD -o ve-+ -j ACCEPT + ''; + }; + }; - containers = builtins.listToAttrs (map (i: - let participant = builtins.elemAt fullParticipantNames (i - 1); - in { - name = "participant${toString i}"; - value = { - autoStart = true; - privateNetwork = true; - hostAddress = "192.168.100.1"; - localAddress = "192.168.100.${toString (10 + i)}"; - config = { - system.stateVersion = "25.05"; - services.openssh.enable = true; - networking.hostName = participant; - console.enable = true; - users.users.root.password = "root"; - virtualisation.docker.enable = true; - environment.systemPackages = with pkgs; [ docker git curl jq ]; - systemd.services.workshop-setup = { - wantedBy = [ "multi-user.target" ]; - after = [ "docker.service" ]; - script = '' - export HOME=/root; - ${pkgs.docker}/bin/docker swarm init --advertise-addr 192.168.100.${toString (10 + i)} || true; - ${pkgs.curl}/bin/curl -fsSL https://install.abra.coopcloud.tech | ${pkgs.bash}/bin/bash; - /root/.local/bin/abra server add ${participant}.local; - ''; - serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; - }; - }; - }; - } - ) participantRange); - - services.dnsmasq = { - enable = true; - settings.address = builtins.concatMap (i: - let participant = builtins.elemAt fullParticipantNames (i - 1); - in [ "/${participant}.local/192.168.100.${toString (10 + i)}" ] - ) participantRange; - }; - }) - ]; - }; - - devShells.${system}.default = pkgs.mkShell { - buildInputs = with pkgs; [ - terraform - nixos-rebuild - docker - openssh - ]; - }; - }; + # Container configurations + containers = builtins.listToAttrs (map (i: + let participant = builtins.elemAt fullParticipantNames (i - 1); + in { + name = participant; + value = { + autoStart = true; + privateNetwork = true; + hostAddress = "192.168.100.1"; + localAddress = "192.168.100.${toString (10 + i)}"; + config = { + system.stateVersion = "25.05"; + + users.users.root = { + password = "root"; + openssh.authorizedKeys.keys = []; + }; + users.users.workshop = { + isNormalUser = true; + password = "workshop"; + extraGroups = [ "wheel" "docker" ]; + }; + + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = true; + PermitRootLogin = "yes"; + }; + }; + + # FIXED: Proper network configuration + networking = { + hostName = participant; + nameservers = [ "8.8.8.8" "1.1.1.1" ]; + defaultGateway = { + address = "192.168.100.1"; + interface = "eth0"; + }; + firewall.enable = false; + useHostResolvConf = false; + # Ensure eth0 is configured properly + interfaces.eth0.ipv4.addresses = [{ + address = "192.168.100.${toString (10 + i)}"; + prefixLength = 24; + }]; + }; + + console.enable = true; + security.sudo.wheelNeedsPassword = false; + + virtualisation.docker.enable = true; + environment.systemPackages = with pkgs; [ + docker git curl jq wget gnutar gzip util-linux + ]; + + # FIXED: Better network initialization + systemd.services.container-network-setup = { + wantedBy = [ "network.target" ]; + before = [ "network-online.target" ]; + script = '' + # Ensure proper routing + ${pkgs.iproute2}/bin/ip route add default via 192.168.100.1 dev eth0 || true + # Set up DNS + echo "nameserver 8.8.8.8" > /etc/resolv.conf + echo "nameserver 1.1.1.1" >> /etc/resolv.conf + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + }; + + systemd.services.workshop-setup = { + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" "docker.service" "container-network-setup.service" ]; + wants = [ "network-online.target" ]; + script = '' + export HOME=/root + export PATH=/run/current-system/sw/bin:$PATH + + # Wait for network with better test + echo "Testing network connectivity..." + for attempt in {1..30}; do + if ${pkgs.curl}/bin/curl -s --max-time 10 --connect-timeout 5 https://install.abra.coopcloud.tech >/dev/null 2>&1; then + echo "Network is up!" + break + fi + echo "Attempt $attempt: Waiting for network..." + sleep 2 + done + + # Docker swarm init + ${pkgs.docker}/bin/docker swarm init --advertise-addr 192.168.100.${toString (10 + i)} || true + + # Install abra + if [ ! -f /root/.local/bin/abra ]; then + echo "Installing abra..." + ${pkgs.curl}/bin/curl -fsSL https://install.abra.coopcloud.tech | ${pkgs.bash}/bin/bash + fi + + # Make abra globally available + if [ -f /root/.local/bin/abra ]; then + ln -sf /root/.local/bin/abra /usr/local/bin/abra || true + fi + + # Add server + if command -v abra >/dev/null 2>&1; then + abra server add ${participant}.local || true + fi + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + StandardOutput = "journal"; + StandardError = "journal"; + }; + }; + + environment.sessionVariables = { + PATH = [ "/root/.local/bin" "$PATH" ]; + }; + }; + }; + } + ) participantRange); + + # DNS for .local domains + services.dnsmasq = { + enable = true; + settings = { + address = builtins.concatMap (i: + let participant = builtins.elemAt fullParticipantNames (i - 1); + in [ "/${participant}.local/192.168.100.${toString (10 + i)}" ] + ) participantRange; + server = [ "8.8.8.8" "1.1.1.1" ]; + }; + }; + }) + ]; + }; + + devShells.${system}.default = pkgs.mkShell { + buildInputs = with pkgs; [ + terraform + nixos-rebuild + docker + openssh + ]; + }; + }; }