diff --git a/.forgejo/workflows/build-image.yml b/.forgejo/workflows/build-image.yml new file mode 100644 index 0000000..8b4871e --- /dev/null +++ b/.forgejo/workflows/build-image.yml @@ -0,0 +1,82 @@ +name: "Build & Upload NixOS Proxmox Image" + +on: + push: + tags: + - "v*" # triggers on v1.0.0, v1.2.3, etc. + workflow_dispatch: + +jobs: + build-upload: + runs-on: nixos-latest + env: + PROXMOX_HOST: 192.168.1.205 + PROXMOX_USER: forgejo-runner + TEMPLATE_VMID: 9001 + LATEST_TEMPLATE_VMID: 9000 + + steps: + - name: Install nodejs + run: nix-env -iA nixpkgs.nodejs + + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Set VERSION from tag or fallback + run: | + if [ -n "${CI_COMMIT_TAG}" ]; then + echo "VERSION=${CI_COMMIT_TAG}" >> $GITHUB_ENV + else + echo "VERSION=dev-$(date +%s)" >> $GITHUB_ENV + fi + + - name: Build NixOS image + run: nix build .#base --builders "ssh://root@nixos-builder.lab x86_64-linux" + + - name: Prepare SSH + env: + PROXMOX_SSH_KEY: ${{ secrets.PROXMOX_SSH_KEY }} + run: | + mkdir -p ~/.ssh + echo "$PROXMOX_SSH_KEY" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H $PROXMOX_HOST >> ~/.ssh/known_hosts + + # - name: Upload image to Proxmox and manage templates + # run: | + # set -e + # IMAGE="result/vm-image.vma.zst" + # REMOTE_NAME="nixos-base-image-${VERSION}.vma.zst" + # REMOTE_PATH="/var/lib/vz/template/images/$REMOTE_NAME" + + # echo "Uploading $IMAGE to Proxmox as $REMOTE_NAME" + # scp $IMAGE $PROXMOX_USER@$PROXMOX_HOST:$REMOTE_PATH + + # echo "Restoring as VMID $TEMPLATE_VMID" + # ssh $PROXMOX_USER@$PROXMOX_HOST " + # qm destroy $TEMPLATE_VMID --purge || true + # qmrestore $REMOTE_PATH $TEMPLATE_VMID --unique + # qm template $TEMPLATE_VMID + + # echo 'Cloning to $LATEST_TEMPLATE_VMID as latest' + # qm destroy $LATEST_TEMPLATE_VMID --purge || true + # qm clone $TEMPLATE_VMID $LATEST_TEMPLATE_VMID --name nixos-base-latest + # " + + # - name: Prune old templates + # run: | + # ssh $PROXMOX_USER@$PROXMOX_HOST " + # cd /var/lib/vz/template/images + # ls -tp nixos-base-image-*.vma.zst | grep -v '/$' | tail -n +6 | xargs -r rm -- + # " + + # - name: Create Forgejo Release (optional) + # if: ${{ github.ref_type == 'tag' }} + # uses: softprops/action-gh-release@v1 + # with: + # name: "NixOS Base Image ${{ env.VERSION }}" + # tag_name: ${{ env.VERSION }} + # body: | + # This release contains the NixOS base image for Proxmox labeled `${{ env.VERSION }}`. + # files: | + # result/vm-image.vma.zst diff --git a/README.md b/README.md index 4a23008..a69350e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,30 @@ -# nixos-base-image +# Nixs base image for promxox +This is the nixos base image to be used as a template in proxmox -Base image for NixOS VM building on proxmox \ No newline at end of file +## Using this base image + +Build the image on remote builder + +```bash +nix build .#base --builders "ssh://root@nixos-builder.lab x86_64-linux" +``` + +Copy to target proxmox storage + +```bash +scp ./result/vzdump-qemu-nixos-*.vma.zst jupiter:/mnt/pve/templates-nfs/dump/ +``` + +In proxmox UI + +* Go to datacenter->[node]->[storage]->backups +* Restore the image which was uploaded now +* Provide name, cpu, memory etc. Don't auto-start +* Open the new VM -> click on `more` -> convert to template + +## Testing the template manually + +* click on base image -> more -> clone +* Once cloned, provide cloud-init parameters as needed +* Adjust hard-disk size as needed. +* start and test diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..e69de29 diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..09cdf4c --- /dev/null +++ b/configuration.nix @@ -0,0 +1,81 @@ +{ config, pkgs, modulesPath, lib, ... }: + +{ + # We rely on the QEMU Guest Agent profile so that Proxmox can talk + # to the VM’s guest-agent. + imports = [ + # Enables QEMU Guest Agent support in the VM + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + config = { + # Provide a default hostname + networking.hostName = lib.mkDefault "base"; + # Allow unfree packages if you ever need them. + nixpkgs.config.allowUnfree = true; + + # QEMU Guest Agent (Proxmox integration) + # Ensure the qemu-guest-agent service is enabled so Proxmox can query + # the VM for IPs, etc. + services.qemuGuest.enable = lib.mkDefault true; + + # GRUB on the “boot drive” + # Both live and template should install a bootloader on /dev/disk/by-label/nixos. + boot.loader.grub.enable = lib.mkDefault true; + boot.loader.grub.devices = [ "nodev" ]; + + # Grow the root partition on first boot + boot.growPartition = lib.mkDefault true; + + # Sudo: Do not require a password for wheel group + security.sudo.wheelNeedsPassword = false; + + # OpenSSH: disable password‐based auth, only allow key‐based + services.openssh = { + enable = true; + settings.PermitRootLogin = "prohibit-password"; + settings.PasswordAuthentication = false; + settings.KbdInteractiveAuthentication = false; + }; + + programs.ssh.startAgent = true; + + # root SSH authorized_keys + users.users.root.openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUP7m8jZJiclZGfSje8CeBYFhX10SrdtjYziuChmj1X plasmagoat@macbook-air" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGlzZWik5bbH6/xjiCpwo1SQSJ/J/Cv7y4ZQ45P68GLB forgejo-runner" + ]; + + # Default filesystem on + fileSystems."/" = lib.mkDefault { + device = "/dev/disk/by-label/nixos"; + autoResize = true; # grow on first boot + fsType = "ext4"; + }; + + # Timezone & Keyboard + time.timeZone = "Europe/Copenhagen"; + console.keyMap = "dk-latin1"; + + # Default set of packages + environment.systemPackages = with pkgs; [ + vim # emergencies + git # pulling flakes, code + curl # downloading things + ]; + + # Nix settings (cache, experimental, gc) + nix.settings.trusted-users = [ "root" "@wheel" ]; + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + nix.extraOptions = '' + experimental-features = nix-command flakes + keep-outputs = true + keep-derivations = true + ''; + nix.gc.automatic = true; + nix.gc.dates = "weekly"; + nix.gc.options = "--delete-older-than 7d"; + + system.stateVersion = lib.mkDefault "25.05"; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..1349043 --- /dev/null +++ b/flake.lock @@ -0,0 +1,63 @@ +{ + "nodes": { + "nixlib": { + "locked": { + "lastModified": 1736643958, + "narHash": "sha256-tmpqTSWVRJVhpvfSN9KXBvKEXplrwKnSZNAoNPf/S/s=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "1418bc28a52126761c02dd3d89b2d8ca0f521181", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixos-generators": { + "inputs": { + "nixlib": "nixlib", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1747663185, + "narHash": "sha256-Obh50J+O9jhUM/FgXtI3he/QRNiV9+J53+l+RlKSaAk=", + "owner": "nix-community", + "repo": "nixos-generators", + "rev": "ee07ba0d36c38e9915c55d2ac5a8fb0f05f2afcc", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-generators", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1749324915, + "narHash": "sha256-aSpVf4BsMsXIlb5lUuF/N/nK1gbvwCKpRcyNEXoDb5k=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "0e9e520ad13e41b04e90db358f0bba0970c42180", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixos-generators": "nixos-generators", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..6b563ac --- /dev/null +++ b/flake.nix @@ -0,0 +1,33 @@ +{ + description = "NixOS Base Image"; + + inputs = { + # nixpkgs repo for system packages + nixpkgs.url = "github:nixos/nixpkgs"; + # nixos-generators lets us produce a "proxmox"-formatted image + nixos-generators = { + url = "github:nix-community/nixos-generators"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, nixos-generators,... }: + { + packages.x86_64-linux = { + base = nixos-generators.nixosGenerate { + system = "x86_64-linux"; + modules = [ + { + # Pin nixpkgs to the flake input, so that the packages installed + # come from the flake inputs.nixpkgs.url. + nix.registry.nixpkgs.flake = nixpkgs; + # set disk size to to 20G + # virtualisation.diskSize = 20 * 1024; + } + ./configuration.nix + ]; + format = "proxmox"; # outputs a .vma.zst suitable for qmrestore + }; + }; + }; +}