├── .gitignore ├── LICENSE ├── README.md ├── default.nix ├── flake.lock ├── flake.nix ├── modules ├── declarative-vms │ ├── default.nix │ ├── iso.nix │ └── options.nix ├── default.nix ├── proxmox-backup │ └── default.nix └── proxmox-ve │ ├── ceph.nix │ ├── cluster.nix │ ├── container.nix │ ├── default.nix │ ├── firewall.nix │ ├── ha-manager.nix │ ├── linstor.nix │ ├── manager.nix │ ├── qemu-server.nix │ ├── rrdcached.nix │ └── vms.nix ├── pkgs ├── cstream │ └── default.nix ├── default.nix ├── extjs │ └── default.nix ├── fonts-font-logos │ └── default.nix ├── linstor-api-py │ └── default.nix ├── linstor-client │ └── default.nix ├── linstor-proxmox │ └── default.nix ├── linstor-server │ ├── build.patch │ ├── default.nix │ └── deps.json ├── mappings.json ├── markedjs │ └── default.nix ├── nixmoxer │ ├── default.nix │ ├── main.py │ └── pyproject.toml ├── perl-modules │ ├── authenpam │ │ └── default.nix │ ├── datadumper │ │ └── default.nix │ ├── digest-sha │ │ └── default.nix │ ├── find-bin │ │ └── default.nix │ ├── iosocketip │ │ └── default.nix │ ├── mimebase32 │ │ └── default.nix │ ├── mimebase64 │ │ └── default.nix │ ├── posixstrptime │ │ └── default.nix │ ├── socket │ │ └── default.nix │ ├── termreadline │ │ └── default.nix │ ├── testharness │ │ └── default.nix │ ├── update.pl │ └── uuid │ │ └── default.nix ├── perlmod │ ├── Cargo.lock │ ├── default.nix │ └── remove_safe_putenv.patch ├── proxmox-acme │ └── default.nix ├── proxmox-backup-qemu │ ├── Cargo.lock │ ├── backup-toml.patch │ ├── default.nix │ └── sources.nix ├── proxmox-registry │ ├── default.nix │ └── remove_workspace_deps.py ├── proxmox-ve │ └── default.nix ├── proxmox-widget-toolkit │ └── default.nix ├── pve-access-control │ └── default.nix ├── pve-apiclient │ └── default.nix ├── pve-cluster │ └── default.nix ├── pve-common │ ├── 0001-ss_fix_path.patch │ ├── 0002-mknod-mknodat.patch │ ├── 0003-pci-id-path.patch │ └── default.nix ├── pve-container │ └── default.nix ├── pve-docs │ └── default.nix ├── pve-edk2-firmware │ └── default.nix ├── pve-firewall │ └── default.nix ├── pve-guest-common │ └── default.nix ├── pve-ha-manager │ └── default.nix ├── pve-http-server │ └── default.nix ├── pve-manager │ ├── 0001-no-apt-update.patch │ ├── 0002-no-repo-status.patch │ └── default.nix ├── pve-novnc │ └── default.nix ├── pve-qemu-server │ └── default.nix ├── pve-qemu │ └── default.nix ├── pve-rados2 │ └── default.nix ├── pve-rs │ ├── Cargo.lock │ ├── default.nix │ └── sources.nix ├── pve-storage │ └── default.nix ├── pve-xtermjs │ └── default.nix ├── sencha-touch │ └── default.nix ├── termproxy │ ├── Cargo.lock │ ├── default.nix │ └── sources.nix ├── unifont │ └── default.nix ├── update.py └── vncterm │ └── default.nix ├── proxmox-nixos.png ├── tasks ├── README.md ├── generate-registry.py ├── update.nix └── update.py └── tests ├── basic.nix ├── ceph.nix ├── cluster.nix ├── default.nix ├── linstor.nix └── vm.nix /.gitignore: -------------------------------------------------------------------------------- 1 | .direnv 2 | result* 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Proxmox on NixOS 2 | 3 | ![Proxmox on NixOS](proxmox-nixos.png) 4 | 5 | This project is a port of the [Proxmox Hypervisor](https://www.proxmox.com/) on NixOS. 6 | 7 | ⚠️ Proxmox-NixOS is still **experimental** and we do not advise running it on production machines. Do it at your own risk and only if you are ready to fix issues by yourself. 8 | 9 | ## 🚦 Supported features 10 | 11 | Proxmox-NixOS has been tested on real hardware with most basic features of Proxmox (booting VMs, user management, etc), more involved setups (clusters, HA, etc) are still under development and testing. 12 | 13 | While we export other architectures for convenience of the user, we only support `x86_64-linux` for now; 14 | 15 | ## 🗃️ Cache 16 | 17 | Some Proxmox packages have a quite power intensive build process. We make a cache available to download directly the artifacts: 18 | 19 | - address: `https://cache.saumon.network/proxmox-nixos` 20 | - public key: `proxmox-nixos:nveXDuVVhFDRFx8Dn19f1WDEaNRJjPrF2CPD2D+m1ys=` 21 | 22 | ## 🚀 Quick start 23 | 24 | ### With [`npins`](https://github.com/andir/npins) 25 | 26 | Add `proxmox-nixos` as a dependency of your npins project. 27 | 28 | ```console 29 | $ npins add github SaumonNet proxmox-nixos -b main 30 | [INFO ] Adding 'proxmox-nixos' … 31 | repository: https://github.com/SaumonNet/proxmox-nixos.git 32 | branch: main 33 | revision: ... 34 | url: https://github.com/saumonnet/proxmox-nixos/archive/$revision.tar.gz 35 | hash: ... 36 | ``` 37 | 38 | Below is a fragment of a NixOS configuration that enables Proxmox VE. 39 | 40 | ```nix 41 | # file: configuration.nix 42 | { pkgs, lib, ... }: 43 | let 44 | sources = import ./npins; 45 | proxmox-nixos = import sources.proxmox-nixos; 46 | in 47 | { 48 | imports = [ proxmox-nixos.nixosModules.proxmox-ve ]; 49 | 50 | services.proxmox-ve = { 51 | enable = true; 52 | ipAddress = "192.168.0.1"; 53 | }; 54 | 55 | nixpkgs.overlays = [ 56 | proxmox-nixos.overlays.x86_64-linux 57 | ]; 58 | 59 | # The rest of your configuration... 60 | } 61 | ``` 62 | 63 | ### With Flakes 64 | 65 | Below is a fragment of a NixOS configuration that enables Proxmox VE. 66 | 67 | ```nix 68 | { 69 | description = "A flake with Proxmox VE enabled"; 70 | 71 | inputs = { 72 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 73 | proxmox-nixos.url = "github:SaumonNet/proxmox-nixos"; 74 | }; 75 | 76 | outputs = { self, nixpkgs, proxmox-nixos, ...}: { 77 | nixosConfigurations = { 78 | yourHost = nixpkgs.lib.nixosSystem rec { 79 | system = "x86_64-linux"; 80 | modules = [ 81 | 82 | proxmox-nixos.nixosModules.proxmox-ve 83 | 84 | ({ pkgs, lib, ... }: { 85 | services.proxmox-ve = { 86 | enable = true; 87 | ipAddress = "192.168.0.1"; 88 | }; 89 | 90 | nixpkgs.overlays = [ 91 | proxmox-nixos.overlays.${system} 92 | ]; 93 | 94 | # The rest of your configuration... 95 | }) 96 | ]; 97 | }; 98 | }; 99 | }; 100 | } 101 | ``` 102 | 103 | Do not override the `nixpkgs-stable` input of the flake, as the only tested and supported version of Proxmox-NixOS is with the upstream stable NixOS release. 104 | 105 | ## 💾 Using with Impermanence 106 | 107 | If you're using [impermanence](https://github.com/nix-community/impermanence) for your NixOS system, you'll need to make certain Proxmox directories persistent to maintain your configuration across reboots. 108 | 109 | Add the following directories to your persistence configuration: 110 | 111 | ```nix 112 | environment.persistence."/persistent".directories = [ 113 | "/var/lib/pve-cluster" 114 | ]; 115 | ``` 116 | 117 | ## 🌐 Networking 118 | 119 | To get internet in your VMs, you need to add a network device to the VM, connected to a bridge. To get this working, follow this 2 steps: 120 | 121 | 1. Create the bridge in `System->Network->Create->Linux Bridge`. This operation has no effect on your system and is just a quirk for Proxmox to know the existence of your bridge. 122 | 2. Configure your networking through NixOS configuration so that the bridge you created in the Proxmox web interface actually exists! 123 | 124 | ### Example NixOS networking configurations 125 | 126 | Any kind of advanced networking configuration is possible through the usual NixOS options, but here are basic examples that can get you started: 127 | 128 | #### With `systemd-networkd` 129 | 130 | ```nix 131 | systemd.network.networks."10-lan" = { 132 | matchConfig.Name = [ "ens18" ]; 133 | networkConfig = { 134 | Bridge = "vmbr0"; 135 | }; 136 | }; 137 | 138 | systemd.network.netdevs."vmbr0" = { 139 | netdevConfig = { 140 | Name = "vmbr0"; 141 | Kind = "bridge"; 142 | }; 143 | }; 144 | 145 | systemd.network.networks."10-lan-bridge" = { 146 | matchConfig.Name = "vmbr0"; 147 | networkConfig = { 148 | IPv6AcceptRA = true; 149 | DHCP = "ipv4"; 150 | }; 151 | linkConfig.RequiredForOnline = "routable"; 152 | }; 153 | ``` 154 | 155 | ### With scripted networking 156 | 157 | ```nix 158 | networking.bridges.vmbr0.interfaces = [ "ens18" ]; 159 | networking.interfaces.vmbr0.useDHCP = lib.mkDefault true; 160 | ``` 161 | 162 | ## 🧱 Declarative VMs 163 | 164 | ### Using the module [`virtualisation.proxmox`](modules/declarative-vms) 165 | 166 | _This solution is available even for the admin of a particular VM with only 167 | a restricted API access to the Proxmox Hypervisor._ 168 | 169 | The utility `nixmoxer` allows one to bootstrap NixOS virtual machines on an 170 | existing Proxmox hypervisor, using the API. 171 | 172 | First, configure the virtual machine settings using the options of the NixOS module 173 | `virtualisation.proxmox` of your `nixosConfigurations.myvm`: 174 | 175 | ```nix 176 | # myvm.nix 177 | { config, ... }: 178 | 179 | { 180 | imports = [ ./disko.nix ]; 181 | 182 | networking.hostName = "myvm"; 183 | 184 | virtualisation.proxmox = { 185 | node = "myproxmoxnode"; 186 | iso = ; 187 | vmid = 101; 188 | memory = 4096; 189 | cores = 4; 190 | sockets = 2; 191 | net = [ 192 | { 193 | model = "virtio"; 194 | bridge = "vmbr0"; 195 | } 196 | ]; 197 | scsi = [ { file = "local:16"; } ]; # This will create a 16GB volume in 'local' 198 | }; 199 | 200 | # The rest of your configuration... 201 | } 202 | ``` 203 | 204 | You can find an exhaustive list of options in [modules/declarative-vms/options.nix](modules/declarative-vms/options.nix), 205 | or in the official [documentation](https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/qemu) of the Proxmox API. 206 | 207 | Then configure the access to the Proxmox API: 208 | 209 | ```sh 210 | # nixmoxer.conf 211 | host=192.168.0.3:8006 212 | user=root 213 | password= 214 | verify_ssl=0 215 | ``` 216 | 217 | Now you can bootstrap `myvm` using `nixmoxer`: 218 | 219 | ```console 220 | $ nix run github:SaumonNet/proxmox-nixos#nixmoxer -- [--flake] myvm 221 | ``` 222 | 223 | `nixmoxer` will setup the VM on the Proxmox node and attach the specified iso. Instead of specified an iso, setting `autoInstall = true;` will automatically generate an iso that will automatically install the configuration to the VM being bootstrapped. 224 | 225 | ⚠️ `nixmoxer` shall only be used for the initial bootstraping of a VM, the NixOS VM can be rebuilt with usual tools like `nixos-rebuild`, `colmena`, etc. Changes to the `virtualisation.proxmox` options after the boostraping have no impact. 226 | 227 | ### Using the module [`services.proxmox-ve.vms`](modules/proxmox-ve/vms.nix) 228 | 229 | _This solution is only available for the admin of a Proxmox Hypervisor on NixOS_. 230 | 231 | This configuration will create two VMs on a Proxmox-NixOS Hypervisor. Then you can attach an 232 | iso and configure your VMs as usual. 233 | 234 | ```nix 235 | # configuration.nix 236 | { 237 | services.proxmox-ve = { 238 | enable = true; 239 | ipAddress = "192.168.0.1"; 240 | 241 | vms = { 242 | myvm1 = { 243 | vmid = 100; 244 | memory = 4096; 245 | cores = 4; 246 | sockets = 2; 247 | kvm = false; 248 | net = [ 249 | { 250 | model = "virtio"; 251 | bridge = "vmbr0"; 252 | } 253 | ]; 254 | scsi = [ { file = "local:16"; } ]; 255 | }; 256 | myvm2 = { 257 | vmid = 101; 258 | memory = 8192; 259 | cores = 2; 260 | sockets = 2; 261 | scsi = [ { file = "local:32"; } ]; 262 | }; 263 | }; 264 | }; 265 | 266 | # The rest of your configuration... 267 | } 268 | ``` 269 | 270 | You can find an exhaustive list of options in [modules/declarative-vms/options.nix](modules/declarative-vms/options.nix), 271 | or in the official [documentation](https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/qemu) of the Proxmox API. 272 | 273 | ⚠️ The current limitation is that if for instance VM `myvm1` has already been initialised, 274 | subsequent changes to the configuration in `services.proxmox-ve.vms.myvm1` will have no impact. 275 | 276 | ### Note 277 | 278 | Truly declarative configuration of virtual machines is very difficult with Proxmox-NixOS because there is essentially 2 sources of truth (the NixOS configuration and the Proxmox web interface) that have to be reconciliated. If you want truly declarative VMs configurations we recommend the amazing project [microvms.nix](https://github.com/astro/microvm.nix). 279 | 280 | ## 🚧 Roadmap 281 | 282 | - Support for clusters / HA with Ceph 283 | - More coverage of NixOS tests 284 | - Proxmox backup server 285 | 286 | ## 🔧 Maintainance 287 | 288 | Most packages are regularly and automatically updated thanks to [a modified version](https://github.com/SaumonNet/proxmox-nixos-update) of the [`nixpkgs-update`](https://github.com/nix-community/nixpkgs-update) bot, whose logs are available [here](https://proxmox-nixos-update-logs.saumon.network/). 289 | 290 | ## 📬 Help / Discussions 291 | 292 | There is [a matrix room](https://matrix.to/#/#proxmox-nixos:matrix.org) for discussions about Proxmox-NixOS. 293 | 294 | ## Thanks 295 | 296 | This project has received support from [NLNet](https://nlnet.nl/). 297 | 298 |
Logo of NLnet Foundation     Logo of NGI Assure
299 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | (import ( 2 | let 3 | lock = builtins.fromJSON (builtins.readFile ./flake.lock); 4 | in 5 | fetchTarball { 6 | url = 7 | lock.nodes.flake-compat.locked.url 8 | or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 9 | sha256 = lock.nodes.flake-compat.locked.narHash; 10 | } 11 | ) { src = ./.; }).defaultNix 12 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-compat": { 4 | "locked": { 5 | "lastModified": 1696426674, 6 | "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", 7 | "owner": "edolstra", 8 | "repo": "flake-compat", 9 | "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "edolstra", 14 | "repo": "flake-compat", 15 | "type": "github" 16 | } 17 | }, 18 | "nixpkgs-stable": { 19 | "locked": { 20 | "lastModified": 1748437600, 21 | "narHash": "sha256-hYKMs3ilp09anGO7xzfGs3JqEgUqFMnZ8GMAqI6/k04=", 22 | "owner": "NixOS", 23 | "repo": "nixpkgs", 24 | "rev": "7282cb574e0607e65224d33be8241eae7cfe0979", 25 | "type": "github" 26 | }, 27 | "original": { 28 | "id": "nixpkgs", 29 | "ref": "nixos-25.05", 30 | "type": "indirect" 31 | } 32 | }, 33 | "nixpkgs-unstable": { 34 | "locked": { 35 | "lastModified": 1723637854, 36 | "narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=", 37 | "owner": "NixOS", 38 | "repo": "nixpkgs", 39 | "rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9", 40 | "type": "github" 41 | }, 42 | "original": { 43 | "id": "nixpkgs", 44 | "ref": "nixos-unstable", 45 | "type": "indirect" 46 | } 47 | }, 48 | "root": { 49 | "inputs": { 50 | "flake-compat": "flake-compat", 51 | "nixpkgs-stable": "nixpkgs-stable", 52 | "nixpkgs-unstable": "nixpkgs-unstable", 53 | "utils": "utils" 54 | } 55 | }, 56 | "systems": { 57 | "locked": { 58 | "lastModified": 1681028828, 59 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 60 | "owner": "nix-systems", 61 | "repo": "default", 62 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 63 | "type": "github" 64 | }, 65 | "original": { 66 | "owner": "nix-systems", 67 | "repo": "default", 68 | "type": "github" 69 | } 70 | }, 71 | "utils": { 72 | "inputs": { 73 | "systems": "systems" 74 | }, 75 | "locked": { 76 | "lastModified": 1710146030, 77 | "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", 78 | "owner": "numtide", 79 | "repo": "flake-utils", 80 | "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", 81 | "type": "github" 82 | }, 83 | "original": { 84 | "owner": "numtide", 85 | "repo": "flake-utils", 86 | "type": "github" 87 | } 88 | } 89 | }, 90 | "root": "root", 91 | "version": 7 92 | } 93 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs-stable.url = "nixpkgs/nixos-25.05"; 4 | nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; 5 | utils.url = "github:numtide/flake-utils"; 6 | flake-compat.url = "github:edolstra/flake-compat"; 7 | }; 8 | 9 | nixConfig.extra-substituters = "https://cache.saumon.network/proxmox-nixos"; 10 | nixConfig.extra-trusted-public-keys = "proxmox-nixos:nveXDuVVhFDRFx8Dn19f1WDEaNRJjPrF2CPD2D+m1ys="; 11 | 12 | description = "Proxmox on NixOS"; 13 | 14 | outputs = 15 | { 16 | self, 17 | nixpkgs-stable, 18 | nixpkgs-unstable, 19 | utils, 20 | ... 21 | }: 22 | let 23 | inherit (nixpkgs-stable) lib; 24 | in 25 | { 26 | nixosModules = import ./modules; 27 | } 28 | // 29 | utils.lib.eachSystem 30 | [ 31 | "x86_64-linux" 32 | "aarch64-linux" 33 | "x86_64-darwin" 34 | "aarch64-darwin" 35 | ] 36 | ( 37 | system: 38 | let 39 | pkgs = import nixpkgs-stable { 40 | inherit system; 41 | overlays = [ self.overlays.${system} ]; 42 | }; 43 | pkgs-unstable = import nixpkgs-unstable { 44 | inherit system; 45 | overlays = [ 46 | (_: prev: { 47 | pacemaker = prev.pacemaker.overrideAttrs (_: { 48 | env.NIX_CFLAGS_COMPILE = toString ( 49 | [ "-Wno-error=deprecated-declarations" ] 50 | ++ lib.optionals prev.stdenv.cc.isGNU [ "-Wno-error=strict-prototypes" ] 51 | ); 52 | }); 53 | 54 | }) 55 | ]; 56 | }; 57 | in 58 | { 59 | overlays = _: _: (import ./pkgs { inherit pkgs pkgs-unstable; }); 60 | 61 | packages = utils.lib.filterPackages system (import ./pkgs { inherit pkgs pkgs-unstable; }); 62 | 63 | checks = 64 | if (system == "x86_64-linux") then 65 | ( 66 | self.packages.${system} 67 | // (import ./tests { 68 | inherit pkgs; 69 | extraBaseModules = self.nixosModules; 70 | }) 71 | ) 72 | else 73 | { }; 74 | } 75 | ); 76 | } 77 | -------------------------------------------------------------------------------- /modules/declarative-vms/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.virtualisation.proxmox; 10 | in 11 | with lib; 12 | 13 | { 14 | meta.maintainers = with maintainers; [ 15 | julienmalka 16 | camillemndn 17 | ]; 18 | 19 | options.virtualisation.proxmox = (import ./options.nix { inherit config lib; }).options // { 20 | node = mkOption { 21 | type = types.str; 22 | description = "The cluster node name."; 23 | }; 24 | 25 | name = mkOption { 26 | type = types.str; 27 | default = config.networking.hostName; 28 | description = "Set a name for the VM. Only used on the configuration web interface."; 29 | }; 30 | 31 | autoInstall = mkEnableOption "Automatically install the NixOS configuration on the VM"; 32 | 33 | iso = mkOption { 34 | default = null; 35 | type = types.package; 36 | description = "Iso that will be inserted into the VM. Not compatible with the autoInstall option"; 37 | }; 38 | 39 | }; 40 | 41 | config = lib.mkIf cfg.autoInstall { 42 | virtualisation.proxmox.iso = 43 | let 44 | isoConfig = import ./iso.nix config.system.build; 45 | in 46 | (pkgs.nixos isoConfig).config.system.build.isoImage; 47 | }; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /modules/declarative-vms/iso.nix: -------------------------------------------------------------------------------- 1 | installBuild: 2 | { 3 | config, 4 | pkgs, 5 | lib, 6 | modulesPath, 7 | ... 8 | }: 9 | 10 | { 11 | imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" ]; 12 | 13 | boot.kernelModules = [ "kvm-intel" ]; 14 | 15 | environment.systemPackages = with pkgs; [ git ]; 16 | 17 | isoImage.compressImage = false; 18 | isoImage.squashfsCompression = null; 19 | isoImage.isoBaseName = lib.mkForce "nixos-offline-installer"; 20 | isoImage.isoName = lib.mkForce "${config.isoImage.isoBaseName}-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.iso"; 21 | isoImage.makeEfiBootable = true; 22 | isoImage.makeUsbBootable = true; 23 | isoImage.volumeID = "NIXOS_ISO"; 24 | isoImage.storeContents = [ installBuild.toplevel ]; 25 | 26 | nix.extraOptions = '' 27 | experimental-features = nix-command flakes 28 | ''; 29 | 30 | systemd.services.installer = { 31 | description = "Unattended NixOS installer"; 32 | wantedBy = [ "multi-user.target" ]; 33 | after = [ 34 | "getty.target" 35 | "nscd.service" 36 | ]; 37 | conflicts = [ "getty@tty1.service" ]; 38 | serviceConfig = { 39 | Type = "oneshot"; 40 | RemainAfterExit = "yes"; 41 | StandardInput = "tty-force"; 42 | StandardOutput = "inherit"; 43 | StandardError = "inherit"; 44 | TTYReset = "yes"; 45 | TTYVHangup = "yes"; 46 | }; 47 | path = [ "/run/current-system/sw" ]; 48 | environment = config.nix.envVars // { 49 | inherit (config.environment.sessionVariables) NIX_PATH; 50 | HOME = "/root"; 51 | }; 52 | script = '' 53 | set -euxo pipefail 54 | ${installBuild.diskoScript} 55 | 56 | # nixos-install will run "nix build --store /mnt ..." which won't be able 57 | # to see what we have in the installer nix store, so copy everything 58 | # needed over. 59 | nix copy --no-check-sigs --to local?root=/mnt ${installBuild.toplevel} 60 | ${installBuild.nixos-install}/bin/nixos-install --no-channel-copy --no-root-passwd --system ${installBuild.toplevel} 61 | 62 | reboot 63 | ''; 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /modules/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | declarative-vms = import ./declarative-vms; 3 | proxmox-ve = import ./proxmox-ve; 4 | proxmox-backup = import ./proxmox-backup; 5 | } 6 | -------------------------------------------------------------------------------- /modules/proxmox-backup/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | with lib; 9 | let 10 | cfg = config.services.proxmox-backup; 11 | in 12 | 13 | { 14 | meta.maintainers = with maintainers; [ 15 | julienmalka 16 | camillemndn 17 | ]; 18 | 19 | options.services.proxmox-backup = { 20 | enable = mkEnableOption (mdDoc ''Proxmox VE''); 21 | localIP = mkOption { 22 | description = mdDoc ''Local IP''; 23 | type = types.str; 24 | example = "192.168.0.2"; 25 | }; 26 | }; 27 | 28 | config = mkIf cfg.enable { 29 | systemd.services = { 30 | proxmox-backup-banner = { 31 | description = "Proxmox Backup Server Login Banner"; 32 | unitConfig = { 33 | DefaultDependencies = "no"; 34 | After = "local-fs.target"; 35 | Before = "console-getty.service"; 36 | }; 37 | serviceConfig = { 38 | ExecStart = "${pkgs.proxmox-backup}/bin/proxmox-backup-banner"; 39 | Type = "oneshot"; 40 | RemainAfterExit = "yes"; 41 | }; 42 | wantedBy = [ "getty.target" ]; 43 | }; 44 | proxmox-backup-proxy = { 45 | description = "Proxmox Backup API Proxy Server"; 46 | unitConfig = { 47 | Wants = [ 48 | "network-online.target" 49 | "proxmox-backup.service" 50 | ]; 51 | After = [ 52 | "network.target" 53 | "proxmox-backup.service" 54 | ]; 55 | }; 56 | serviceConfig = { 57 | Type = "notify"; 58 | ExecStart = "${pkgs.proxmox-backup}/bin/proxmox-backup-proxy"; 59 | ExecReload = "/bin/kill -HUP $MAINPID"; 60 | PIDFile = "/run/proxmox-backup/proxy.pid"; 61 | Restart = "on-failure"; 62 | User = "backup"; 63 | Group = "backup"; 64 | }; 65 | 66 | wantedBy = [ "multi-user.target" ]; 67 | }; 68 | proxmox-backup = { 69 | description = "Proxmox Backup API Server"; 70 | unitConfig = { 71 | Wants = [ "network-online.target" ]; 72 | After = [ "network.target" ]; 73 | }; 74 | serviceConfig = { 75 | Type = "notify"; 76 | ExecStart = "${pkgs.proxmox-backup}/bin/proxmox-backup-api"; 77 | ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 78 | PIDFile = "/run/proxmox-backup/api.pid"; 79 | Restart = "on-failure"; 80 | }; 81 | wantedBy = [ "multi-user.target" ]; 82 | }; 83 | }; 84 | 85 | users.users.backup = { 86 | isSystemUser = true; 87 | group = "backup"; 88 | }; 89 | users.groups.backup = { }; 90 | 91 | environment.systemPackages = [ pkgs.proxmox-backup ]; 92 | environment.etc.issue.enable = false; 93 | 94 | networking.firewall.allowedTCPPorts = [ 95 | 8007 96 | 111 97 | 80 98 | 443 99 | ]; 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /modules/proxmox-ve/ceph.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.services.proxmox-ve.ceph; 10 | 11 | makeServices = 12 | daemonType: daemonIds: 13 | lib.mkMerge ( 14 | map (daemonId: { 15 | "ceph-${daemonType}-${daemonId}" = makeService daemonType daemonId "ceph" cfg.${daemonType}.package; 16 | }) daemonIds 17 | ); 18 | 19 | makeService = 20 | daemonType: daemonId: clusterName: ceph: 21 | let 22 | stateDirectory = "ceph/${ 23 | if daemonType == "rgw" then "radosgw" else daemonType 24 | }/${clusterName}-${daemonId}"; 25 | in 26 | { 27 | enable = true; 28 | description = "Ceph ${ 29 | builtins.replaceStrings lib.lowerChars lib.upperChars daemonType 30 | } daemon ${daemonId}"; 31 | after = [ 32 | "network-online.target" 33 | "time-sync.target" 34 | "pve-cluster.service" 35 | ] ++ lib.optional (daemonType == "osd") "ceph-mon.target"; 36 | wants = [ 37 | "network-online.target" 38 | "time-sync.target" 39 | ]; 40 | partOf = [ "ceph-${daemonType}.target" ]; 41 | wantedBy = [ "ceph-${daemonType}.target" ]; 42 | 43 | path = [ pkgs.getopt ]; 44 | 45 | # Don't start services that are not yet initialized 46 | unitConfig.ConditionPathExists = "/var/lib/${stateDirectory}/keyring"; 47 | startLimitBurst = 48 | if daemonType == "osd" then 49 | 30 50 | else if 51 | lib.elem daemonType [ 52 | "mgr" 53 | "mds" 54 | ] 55 | then 56 | 3 57 | else 58 | 5; 59 | startLimitIntervalSec = 60 * 30; # 30 mins 60 | 61 | serviceConfig = 62 | { 63 | LimitNOFILE = 1048576; 64 | LimitNPROC = 1048576; 65 | Environment = "CLUSTER=${clusterName}"; 66 | ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 67 | PrivateDevices = "yes"; 68 | PrivateTmp = "true"; 69 | ProtectHome = "true"; 70 | ProtectSystem = "full"; 71 | Restart = "on-failure"; 72 | ExecStart = '' 73 | ${ceph.out}/bin/${if daemonType == "rgw" then "radosgw" else "ceph-${daemonType}"} \ 74 | -f --cluster ${clusterName} --id ${daemonId} --setuser ceph --setgroup ceph''; 75 | } 76 | // lib.optionalAttrs (daemonType == "osd") { 77 | ExecStartPre = "${ceph.lib}/libexec/ceph/ceph-osd-prestart.sh --id ${daemonId} --cluster ${clusterName}"; 78 | RestartSec = "20s"; 79 | PrivateDevices = "no"; # osd needs disk access 80 | } 81 | // lib.optionalAttrs (daemonType == "mon") { 82 | RestartSec = "10"; 83 | }; 84 | }; 85 | 86 | makeTarget = daemonType: { 87 | "ceph-${daemonType}" = { 88 | description = "Ceph target allowing to start/stop all ceph-${daemonType} services at once"; 89 | partOf = [ "ceph.target" ]; 90 | wantedBy = [ "ceph.target" ]; 91 | before = [ "ceph.target" ]; 92 | unitConfig.StopWhenUnneeded = true; 93 | }; 94 | }; 95 | in 96 | 97 | { 98 | options.services.proxmox-ve.ceph = { 99 | enable = lib.mkEnableOption "Ceph global configuration"; 100 | 101 | mgr = { 102 | enable = lib.mkEnableOption "Ceph MGR daemon"; 103 | package = lib.mkPackageOption pkgs "ceph" { }; 104 | daemons = lib.mkOption { 105 | type = with lib.types; listOf str; 106 | default = [ config.networking.hostName ]; 107 | example = [ 108 | "name1" 109 | "name2" 110 | ]; 111 | description = '' 112 | A list of names for manager daemons that should have a service created. The names correspond 113 | to the id part in ceph i.e. [ "name1" ] would result in mgr.name1 114 | ''; 115 | }; 116 | }; 117 | 118 | mon = { 119 | enable = lib.mkEnableOption "Ceph MON daemon"; 120 | package = lib.mkPackageOption pkgs "ceph" { }; 121 | daemons = lib.mkOption { 122 | type = with lib.types; listOf str; 123 | default = [ config.networking.hostName ]; 124 | example = [ 125 | "name1" 126 | "name2" 127 | ]; 128 | description = '' 129 | A list of monitor daemons that should have a service created. The names correspond 130 | to the id part in ceph i.e. [ "name1" ] would result in mon.name1 131 | ''; 132 | }; 133 | }; 134 | 135 | osd = { 136 | enable = lib.mkEnableOption "Ceph OSD daemon"; 137 | package = lib.mkPackageOption pkgs "ceph" { }; 138 | daemons = lib.mkOption { 139 | type = with lib.types; listOf str; 140 | default = [ ]; 141 | example = [ 142 | "1" 143 | "2" 144 | ]; 145 | description = '' 146 | A list of OSD daemons that should have a service created. The names correspond 147 | to the id part in ceph i.e. [ "1" ] would result in osd.1 148 | ''; 149 | }; 150 | }; 151 | 152 | mds = { 153 | enable = lib.mkEnableOption "Ceph MDS daemon"; 154 | package = lib.mkPackageOption pkgs "ceph" { }; 155 | daemons = lib.mkOption { 156 | type = with lib.types; listOf str; 157 | default = [ ]; 158 | example = [ 159 | "name1" 160 | "name2" 161 | ]; 162 | description = '' 163 | A list of metadata service daemons that should have a service created. The names correspond 164 | to the id part in ceph i.e. [ "name1" ] would result in mds.name1 165 | ''; 166 | }; 167 | }; 168 | 169 | rgw = { 170 | enable = lib.mkEnableOption "Ceph RadosGW daemon"; 171 | package = lib.mkPackageOption pkgs "ceph" { }; 172 | daemons = lib.mkOption { 173 | type = with lib.types; listOf str; 174 | default = [ ]; 175 | example = [ 176 | "name1" 177 | "name2" 178 | ]; 179 | description = '' 180 | A list of rados gateway daemons that should have a service created. The names correspond 181 | to the id part in ceph i.e. [ "name1" ] would result in client.name1, radosgw daemons 182 | aren't daemons to cluster in the sense that OSD, MGR or MON daemons are. They are simply 183 | daemons, from ceph, that uses the cluster as a backend. 184 | ''; 185 | }; 186 | }; 187 | }; 188 | 189 | config = lib.mkIf config.services.proxmox-ve.ceph.enable { 190 | assertions = [ 191 | { 192 | assertion = cfg.enable -> !config.services.ceph.enable; 193 | message = "Ceph for Proxmox VE is not compatible with the Ceph module for NixOS"; 194 | } 195 | { 196 | assertion = cfg.mon.enable -> cfg.mon.daemons != [ ]; 197 | message = "have to set id of atleast one MON if you're going to enable Monitor"; 198 | } 199 | { 200 | assertion = cfg.mds.enable -> cfg.mds.daemons != [ ]; 201 | message = "have to set id of atleast one MDS if you're going to enable Metadata Service"; 202 | } 203 | { 204 | assertion = cfg.osd.enable -> cfg.osd.daemons != [ ]; 205 | message = "have to set id of atleast one OSD if you're going to enable OSD"; 206 | } 207 | { 208 | assertion = cfg.mgr.enable -> cfg.mgr.daemons != [ ]; 209 | message = "have to set id of atleast one MGR if you're going to enable MGR"; 210 | } 211 | ]; 212 | 213 | networking.firewall = lib.mkIf config.services.proxmox-ve.openFirewall { 214 | allowedTCPPorts = lib.optionals cfg.mon.enable [ 215 | 3300 216 | 6789 217 | ]; 218 | allowedTCPPortRanges = lib.optionals (cfg.osd.enable || cfg.msd.enable || cfg.mgr.enable) [ 219 | { 220 | from = 6800; 221 | to = 7300; 222 | } 223 | ]; 224 | }; 225 | 226 | users.users.ceph = { 227 | uid = config.ids.uids.ceph; 228 | description = "Ceph daemon user"; 229 | group = "ceph"; 230 | extraGroups = [ "disk" ]; 231 | }; 232 | 233 | users.groups.ceph = { 234 | gid = config.ids.gids.ceph; 235 | }; 236 | 237 | systemd.services = 238 | let 239 | services = 240 | lib.optional cfg.mon.enable (makeServices "mon" cfg.mon.daemons) 241 | ++ lib.optional cfg.mds.enable (makeServices "mds" cfg.mds.daemons) 242 | ++ lib.optional cfg.osd.enable (makeServices "osd" cfg.osd.daemons) 243 | ++ lib.optional cfg.rgw.enable (makeServices "rgw" cfg.rgw.daemons) 244 | ++ lib.optional cfg.mgr.enable (makeServices "mgr" cfg.mgr.daemons); 245 | in 246 | lib.mkMerge services; 247 | 248 | systemd.targets = 249 | let 250 | targets = 251 | [ 252 | { 253 | ceph = { 254 | description = "Ceph target allowing to start/stop all ceph service instances at once"; 255 | wantedBy = [ "multi-user.target" ]; 256 | unitConfig.StopWhenUnneeded = true; 257 | }; 258 | } 259 | ] 260 | ++ lib.optional cfg.mon.enable (makeTarget "mon") 261 | ++ lib.optional cfg.mds.enable (makeTarget "mds") 262 | ++ lib.optional cfg.osd.enable (makeTarget "osd") 263 | ++ lib.optional cfg.rgw.enable (makeTarget "rgw") 264 | ++ lib.optional cfg.mgr.enable (makeTarget "mgr"); 265 | in 266 | lib.mkMerge targets; 267 | 268 | systemd.tmpfiles.settings."10-ceph" = 269 | let 270 | defaultConfig = { 271 | user = "ceph"; 272 | group = "ceph"; 273 | }; 274 | in 275 | { 276 | "/etc/ceph".d = defaultConfig; 277 | "/run/ceph".d = defaultConfig // { 278 | mode = "0770"; 279 | }; 280 | "/var/lib/ceph".d = defaultConfig; 281 | "/var/lib/ceph/mgr".d = lib.mkIf cfg.mgr.enable defaultConfig; 282 | "/var/lib/ceph/mon".d = lib.mkIf cfg.mon.enable defaultConfig; 283 | "/var/lib/ceph/osd".d = lib.mkIf cfg.osd.enable defaultConfig; 284 | "/var/lib/ceph/bootstrap-mgr".d = lib.mkIf cfg.mgr.enable defaultConfig; 285 | "/var/lib/ceph/bootstrap-mon".d = lib.mkIf cfg.mon.enable defaultConfig; 286 | "/var/lib/ceph/bootstrap-osd".d = lib.mkIf cfg.osd.enable defaultConfig; 287 | "/var/lib/ceph/bootstrap-rgw".d = lib.mkIf cfg.rgw.enable defaultConfig; 288 | "/var/lib/ceph/bootstrap-mds".d = lib.mkIf cfg.mds.enable defaultConfig; 289 | }; 290 | }; 291 | } 292 | -------------------------------------------------------------------------------- /modules/proxmox-ve/cluster.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.services.proxmox-ve; 10 | in 11 | 12 | lib.mkIf cfg.enable { 13 | systemd.services = { 14 | pve-cluster = { 15 | description = "The Proxmox VE cluster filesystem"; 16 | wants = [ 17 | "corosync.service" 18 | #"rrdcached.service" 19 | #"shutdown.target" 20 | ]; 21 | after = [ 22 | "network.target" 23 | "sys-fs-fuse-connections.mount" 24 | "time-sync.target" 25 | #"rrdcached.service" 26 | ]; 27 | before = [ 28 | "corosync.service" 29 | "cron.service" 30 | ]; 31 | #unitConfig = { 32 | # DefaultDependencies = false; 33 | # Conflicts = [ "shutdown.target" ]; 34 | #}; 35 | serviceConfig = { 36 | ExecStart = "${cfg.package}/bin/pmxcfs"; 37 | KillMode = "mixed"; 38 | Restart = "on-failure"; 39 | TimeoutStopSec = 10; 40 | Type = "forking"; 41 | PIDFile = "/run/pve-cluster.pid"; 42 | }; 43 | }; 44 | 45 | corosync = { 46 | description = "Corosync Cluster Engine"; 47 | requires = [ "network-online.target" ]; 48 | after = [ "network-online.target" ]; 49 | wantedBy = [ "multi-user.target" ]; 50 | unitConfig = { 51 | ConditionKernelCommandLine = "!nocluster"; 52 | ConditionPathExists = "/etc/corosync/corosync.conf"; 53 | }; 54 | serviceConfig = { 55 | ExecStart = "${pkgs.corosync}/bin/corosync -f $COROSYNC_OPTIONS"; 56 | ExecStop = "${pkgs.corosync}/bin/corosync-cfgtool -H --force"; 57 | Type = "notify"; 58 | StateDirectory = "corosync"; 59 | 60 | # In typical systemd deployments, both standard outputs are forwarded to 61 | # journal (stderr is what's relevant in the pristine corosync configuration), 62 | # which hazards a message redundancy since the syslog stream usually ends there 63 | # as well; before editing this line, you may want to check DefaultStandardError 64 | # in systemd-system.conf(5) and whether /dev/log is a systemd related symlink. 65 | StandardError = "null"; 66 | 67 | # The following config is for corosync with enabled watchdog service. 68 | # 69 | # When corosync watchdog service is being enabled and using with 70 | # pacemaker.service, and if you want to exert the watchdog when a 71 | # corosync process is terminated abnormally, 72 | # uncomment the line of the following Restart= and RestartSec=. 73 | #Restart=on-failure 74 | # Specify a period longer than soft_margin as RestartSec. 75 | #RestartSec=70 76 | # rewrite according to environment. 77 | #ExecStartPre=/sbin/modprobe softdog 78 | PrivateTmp = "yes"; 79 | }; 80 | }; 81 | }; 82 | 83 | systemd.tmpfiles.rules = [ "d /etc/corosync 0755 root root -" ]; 84 | } 85 | -------------------------------------------------------------------------------- /modules/proxmox-ve/container.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | lib.mkIf config.services.proxmox-ve.enable { 9 | systemd.services = { 10 | pve-lxc-syscalld = { 11 | description = "Proxmox VE LXC Syscall Daemon"; 12 | wantedBy = [ "multi-user.target" ]; 13 | before = [ "pve-guests.service" ]; 14 | serviceConfig = { 15 | Type = "notify"; 16 | ExecStart = "/usr/lib/x86_64-linux-gnu/pve-lxc-syscalld/pve-lxc-syscalld --system /run/pve/lxc-syscalld.sock"; 17 | RuntimeDirectory = "pve"; 18 | Restart = "on-failure"; 19 | }; 20 | }; 21 | 22 | "pve-container-debug@" = { 23 | # based on lxc@.service, but without an install section because 24 | # starting and stopping should be initiated by PVE code, not 25 | # systemd. 26 | description = "PVE LXC Container: %i"; 27 | after = [ "lxc.service" ]; 28 | wants = [ "lxc.service" ]; 29 | unitConfig = { 30 | DefaultDependencies = false; 31 | Documentation = "man:lxc-start man:lxc man:pct"; 32 | serviceConfig = { 33 | Type = "simple"; 34 | Delegate = true; 35 | KillMode = "mixed"; 36 | TimeoutStopSec = 120; 37 | ExecStart = "${pkgs.lxc}/bin/lxc-start -F -n %i -o /dev/stderr -l DEBUG"; 38 | ExecStop = "${pkgs.pve-container}/share/lxc/pve-container-stop-wrapper %i"; 39 | # Environment=BOOTUP=serial 40 | # Environment=CONSOLETYPE=serial 41 | # Prevent container init from putting all its output into the journal 42 | StandardOutput = null; 43 | StandardError = "file:/run/pve/ct-%i.stderr"; 44 | }; 45 | }; 46 | 47 | "pve-container@" = { 48 | # based on lxc@.service, but without an install section because 49 | # starting and stopping should be initiated by PVE code, not 50 | # systemd. 51 | description = "PVE LXC Container: %i"; 52 | after = [ "lxc.service" ]; 53 | wants = [ "lxc.service" ]; 54 | unitConfig = { 55 | DefaultDependencies = false; 56 | Documentation = "man:lxc-start man:lxc man:pct"; 57 | }; 58 | serviceConfig = { 59 | Type = "simple"; 60 | Delegate = true; 61 | KillMode = "mixed"; 62 | TimeoutStopSec = 120; 63 | ExecStart = "${pkgs.lxc}/bin/lxc-start -F -n %i"; 64 | ExecStop = "${pkgs.pve-container}/share/lxc/pve-container-stop-wrapper %i"; 65 | # Environment=BOOTUP=serial 66 | # Environment=CONSOLETYPE=serial 67 | # Prevent container init from putting all its output into the journal 68 | StandardOutput = null; 69 | StandardError = "file:/run/pve/ct-%i.stderr"; 70 | }; 71 | }; 72 | }; 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /modules/proxmox-ve/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | with lib; 9 | let 10 | cfg = config.services.proxmox-ve; 11 | in 12 | 13 | { 14 | meta.maintainers = with maintainers; [ 15 | julienmalka 16 | camillemndn 17 | ]; 18 | 19 | imports = [ 20 | ./ceph.nix 21 | ./cluster.nix 22 | # ./firewall.nix 23 | # ./ha-manager.nix 24 | ./linstor.nix 25 | ./manager.nix 26 | ./qemu-server.nix 27 | ./rrdcached.nix 28 | ./vms.nix 29 | ]; 30 | 31 | options.services.proxmox-ve = { 32 | enable = mkEnableOption "Proxmox VE"; 33 | 34 | package = mkPackageOption pkgs "proxmox-ve" { }; 35 | 36 | ipAddress = lib.mkOption { 37 | type = lib.types.str; 38 | description = '' 39 | The IP address used to reach this Proxmox node from outside, added to "/etc/hosts" file. 40 | ''; 41 | }; 42 | 43 | openFirewall = lib.mkOption { 44 | type = lib.types.bool; 45 | default = true; 46 | description = '' 47 | Open port in firewall for proxmox-admin (8006), rpcbind (111) and http(s) (80,443) 48 | ''; 49 | }; 50 | }; 51 | 52 | config = mkIf cfg.enable (mkMerge [ 53 | { 54 | boot.supportedFilesystems = [ 55 | "fuse" 56 | "glusterfs" 57 | ]; 58 | 59 | networking.hosts = { 60 | "127.0.0.2" = lib.mkForce [ ]; 61 | "::1" = lib.mkForce [ ]; 62 | "${cfg.ipAddress}" = [ config.networking.hostName ]; 63 | }; 64 | 65 | # create the /etc/network/interfaces file for proxmox 66 | systemd.tmpfiles.rules = [ 67 | "d /etc/network 0755 root root -" 68 | "f /etc/network/interfaces 0755 root root -" 69 | ]; 70 | 71 | services.openssh = { 72 | enable = true; 73 | settings.AcceptEnv = "LANG LC_*"; 74 | }; 75 | programs.ssh.extraConfig = '' 76 | Host * 77 | SendEnv LANG LC_* 78 | ''; 79 | 80 | security.pam.services."proxmox-ve-auth" = { 81 | logFailures = true; 82 | nodelay = true; 83 | }; 84 | 85 | services.rpcbind.enable = true; 86 | services.rrdcached.enable = true; 87 | 88 | users.users.www-data = { 89 | isSystemUser = true; 90 | group = "www-data"; 91 | }; 92 | users.groups.www-data = { }; 93 | 94 | environment.systemPackages = [ cfg.package ]; 95 | environment.etc.issue.enable = false; 96 | 97 | networking.firewall = mkIf cfg.openFirewall { 98 | allowedTCPPorts = [ 99 | 80 100 | 111 101 | 443 102 | 8006 103 | ]; 104 | allowedUDPPorts = [ 111 ]; 105 | allowedUDPPortRanges = [ 106 | { 107 | from = 5405; 108 | to = 5412; 109 | } 110 | ]; 111 | }; 112 | } 113 | ]); 114 | } 115 | -------------------------------------------------------------------------------- /modules/proxmox-ve/firewall.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | lib.mkIf config.services.proxmox-ve.enable { 9 | systemd.services = { 10 | pve-firewall = { 11 | description = "Proxmox VE firewall"; 12 | unitConfig = { 13 | Wants = [ 14 | "pve-cluster.service" 15 | "pvefw-logger.service" 16 | ]; 17 | After = [ 18 | "pvefw-logger.service" 19 | "pve-cluster.service" 20 | "network.target" 21 | "systemd-modules-load.service" 22 | ]; 23 | DefaultDependencies = "no"; 24 | Before = [ "shutdown.target" ]; 25 | Conflicts = [ "shutdown.target" ]; 26 | }; 27 | serviceConfig = { 28 | ExecStart = "${pkgs.pve-firewall}/bin/pve-firewall start"; 29 | ExecStop = "${pkgs.pve-firewall}/bin/pve-firewall stop"; 30 | ExecReload = "${pkgs.pve-firewall}/bin/pve-firewall restart"; 31 | PIDFile = "/run/pve-firewall.pid"; 32 | Type = "forking"; 33 | }; 34 | }; 35 | 36 | pvefw-logger = { 37 | description = "Proxmox VE firewall logger"; 38 | unitConfig = { 39 | DefaultDependencies = "no"; 40 | Before = [ "shutdown.target" ]; 41 | After = [ "local-fs.target" ]; 42 | Conflicts = [ "shutdown.target" ]; 43 | }; 44 | serviceConfig = { 45 | ExecStart = "${pkgs.pve-firewall}/bin/pvefw-logger"; 46 | PIDFile = "/run/pvefw-logger.pid"; 47 | TimeoutStopSec = 5; 48 | Type = "forking"; 49 | }; 50 | }; 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /modules/proxmox-ve/ha-manager.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | lib.mkIf config.services.proxmox-ve.enable { 9 | systemd.services = { 10 | pve-ha-lrm = { 11 | description = "PVE Local HA Resource Manager Daemon"; 12 | wantedBy = [ "multi-user.target" ]; 13 | wants = [ 14 | "pve-cluster.service" 15 | "watchdog-mux.service" 16 | "pvedaemon.service" 17 | "pve-ha-crm.service" 18 | "lxc.service" 19 | "pve-storage.target" 20 | ]; 21 | after = [ 22 | "corosync.service" 23 | "lxc.service" 24 | "pve-cluster.service" 25 | "pve-ha-crm.service" 26 | "pve-storage.target" 27 | "pvedaemon.service" 28 | "pveproxy.service" 29 | "sshd.service" 30 | "syslog.service" 31 | "watchdog-mux.service" 32 | ]; 33 | serviceConfig = { 34 | ExecStart = "${pkgs.pve-ha-manager}/bin/pve-ha-lrm start"; 35 | ExecStop = "${pkgs.pve-ha-manager}/bin/pve-ha-lrm stop"; 36 | PIDFile = "/run/pve-ha-lrm.pid"; 37 | #TimeoutStopSec = "infinity"; 38 | KillMode = "process"; 39 | Type = "forking"; 40 | }; 41 | }; 42 | 43 | pve-ha-crm = { 44 | description = "PVE Cluster HA Resource Manager Daemon"; 45 | wants = [ 46 | "pve-cluster.service" 47 | "watchdog-mux.service" 48 | "pvedaemon.service" 49 | ]; 50 | after = [ 51 | "pve-cluster.service" 52 | "corosync.service" 53 | "pvedaemon.service" 54 | "watchdog-mux.service" 55 | "syslog.service" 56 | ]; 57 | serviceConfig = { 58 | ExecStart = "${pkgs.pve-ha-manager}/bin/pve-ha-crm start"; 59 | ExecStop = "${pkgs.pve-ha-manager}/bin/pve-ha-crm stop"; 60 | PIDFile = "/run/pve-ha-crm.pid"; 61 | TimeoutStopSec = 65; 62 | Type = "forking"; 63 | }; 64 | }; 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /modules/proxmox-ve/linstor.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | with lib; 9 | let 10 | cfg = config.services.proxmox-ve.linstor; 11 | in 12 | 13 | { 14 | meta.maintainers = with maintainers; [ 15 | julienmalka 16 | camillemndn 17 | ]; 18 | 19 | options.services.proxmox-ve.linstor = { 20 | enable = mkEnableOption "Linstor for Proxmox VE"; 21 | openFirewall = mkEnableOption "opening the default ports in the firewall for Linstor Satellite"; 22 | }; 23 | 24 | config = mkIf cfg.enable { 25 | boot.extraModulePackages = with config.boot.kernelPackages; [ drbd ]; 26 | boot.kernelModules = [ 27 | "dm_thin_pool" 28 | "drbd" 29 | ]; 30 | 31 | services.drbd = { 32 | enable = true; 33 | config = '' 34 | global { 35 | usage-count yes; 36 | 37 | # Decide what kind of udev symlinks you want for "implicit" volumes 38 | # (those without explicit volume {} block, implied vnr=0): 39 | # /dev/drbd/by-resource// (explicit volumes) 40 | # /dev/drbd/by-resource/ (default for implict) 41 | udev-always-use-vnr; # treat implicit the same as explicit volumes 42 | 43 | # minor-count dialog-refresh disable-ip-verification 44 | # cmd-timeout-short 5; cmd-timeout-medium 121; cmd-timeout-long 600; 45 | } 46 | include "/var/lib/linstor.d/*.res"; 47 | ''; 48 | }; 49 | 50 | networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ 51 | 3366 52 | 3367 53 | ]; 54 | 55 | services.proxmox-ve.package = pkgs.proxmox-ve.override { enableLinstor = true; }; 56 | 57 | systemd.services = { 58 | linstor-controller = { 59 | description = "Linstor Controller"; 60 | wantedBy = [ "multi-user.target" ]; 61 | wants = [ "network-online.target" ]; 62 | after = [ "network-online.target" ]; 63 | before = [ "pvedaemon.service" ]; 64 | serviceConfig = { 65 | Type = "notify"; 66 | ExecStart = "${pkgs.linstor-server}/bin/linstor-controller"; 67 | Restart = "on-failure"; 68 | # if killed by signal 143 -> SIGTERM, 129 -> SIGHUP 69 | SuccessExitStatus = "0 143 129"; 70 | PrivateTmp = true; 71 | }; 72 | }; 73 | 74 | linstor-satellite = { 75 | description = "LINSTOR Satellite Service"; 76 | wantedBy = [ "multi-user.target" ]; 77 | wants = [ "network-online.target" ]; 78 | after = [ "network-online.target" ]; 79 | before = [ "pvedaemon.service" ]; 80 | 81 | serviceConfig = { 82 | Type = "simple"; 83 | ExecStart = "${pkgs.linstor-server}/bin/linstor-satellite --logs=/var/log/linstor-satellite --config-directory=/etc/linstor"; 84 | SuccessExitStatus = "0 143 129"; 85 | PrivateTmp = true; 86 | }; 87 | }; 88 | }; 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /modules/proxmox-ve/manager.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.services.proxmox-ve; 10 | in 11 | 12 | lib.mkIf cfg.enable { 13 | systemd.services = { 14 | pvedaemon = { 15 | description = "PVE API Daemon"; 16 | wants = [ 17 | "corosync.service" 18 | "pve-cluster.service" 19 | ]; 20 | after = [ 21 | "corosync.service" 22 | "pve-cluster.service" 23 | ]; 24 | path = with pkgs; [ btrfs-progs zfs bashInteractive cdrkit swtpm ]; 25 | serviceConfig = { 26 | ExecStart = "${cfg.package}/bin/pvedaemon start"; 27 | ExecStop = "${cfg.package}/bin/pvedaemon stop"; 28 | ExecReload = "${cfg.package}/bin/pvedaemon restart"; 29 | PIDFile = "/run/pvedaemon.pid"; 30 | Type = "forking"; 31 | Restart = "on-failure"; 32 | CacheDirectory = "linstor-proxmox"; 33 | }; 34 | }; 35 | 36 | pveproxy = { 37 | description = "PVE API Proxy Server"; 38 | wants = [ 39 | "pve-cluster.service" 40 | "pvedaemon.service" 41 | "sshd.service" 42 | "pve-storage.target" 43 | ]; 44 | after = [ 45 | "pve-storage.target" 46 | "pve-cluster.service" 47 | "pvedaemon.service" 48 | "sshd.service" 49 | ]; 50 | serviceConfig = { 51 | ExecStartPre = [ 52 | "${cfg.package}/bin/pvecm updatecerts -silent" 53 | "${pkgs.coreutils}/bin/touch /var/lock/pveproxy.lck" 54 | "${pkgs.coreutils}/bin/chown -R www-data:www-data /var/lock/pveproxy.lck" 55 | ]; 56 | ExecStart = "${cfg.package}/bin/pveproxy start"; 57 | ExecStop = "${cfg.package}/bin/pveproxy stop"; 58 | ExecReload = "${cfg.package}/bin/pveproxy restart"; 59 | PIDFile = "/run/pveproxy/pveproxy.pid"; 60 | Type = "forking"; 61 | StateDirectory = "pve-manager"; 62 | Restart = "on-failure"; 63 | }; 64 | }; 65 | 66 | pve-guests = { 67 | description = "PVE guests"; 68 | environment.PVE_LOG_ID = "pve-guests"; 69 | wantedBy = [ "multi-user.target" ]; 70 | wants = [ 71 | "pvestatd.service" 72 | "pveproxy.service" 73 | "spiceproxy.service" 74 | "pve-firewall.service" 75 | "lxc.service" 76 | ]; 77 | after = [ 78 | "pveproxy.service" 79 | "pvestatd.service" 80 | "spiceproxy.service" 81 | "pve-firewall.service" 82 | "lxc.service" 83 | "pve-ha-crm.service" 84 | "pve-ha-lrm.service" 85 | ]; 86 | path = with pkgs; [ swtpm ]; 87 | unitConfig = { 88 | RefuseManualStart = true; 89 | RefuseManualStop = true; 90 | }; 91 | serviceConfig = { 92 | #ExecStartPre = "${cfg.package}/share/pve-manager/helpers/pve-startall-delay"; 93 | ExecStart = "${cfg.package}/bin/pvesh --nooutput create /nodes/localhost/startall"; 94 | ExecStop = pkgs.writeShellScript "pve-guests-stop" '' 95 | -${cfg.package}/bin/vzdump -stop 96 | ${cfg.package}/bin/pvesh --nooutput create /nodes/localhost/stopall 97 | ''; 98 | Type = "oneshot"; 99 | RemainAfterExit = true; 100 | #TimeoutSec = "infinity"; 101 | }; 102 | }; 103 | 104 | pvebanner = { 105 | description = "Proxmox VE Login Banner"; 106 | wantedBy = [ "multi-user.target" ]; 107 | unitConfig = { 108 | DefaultDependencies = false; 109 | After = [ "local-fs.target" ]; 110 | Before = [ "console-getty.service" ]; 111 | }; 112 | serviceConfig = { 113 | ExecStart = "${cfg.package}/bin/pvebanner"; 114 | Type = "oneshot"; 115 | RemainAfterExit = true; 116 | }; 117 | }; 118 | 119 | pvescheduler = { 120 | description = "Proxmox VE scheduler"; 121 | wantedBy = [ "multi-user.target" ]; 122 | wants = [ "pve-cluster.service" ]; 123 | after = [ 124 | "pve-cluster.service" 125 | "pve-guests.service" 126 | "pve-storage.target" 127 | ]; 128 | path = with pkgs; [ btrfs-progs zfs ]; 129 | serviceConfig = { 130 | ExecStartPre = [ 131 | "${pkgs.coreutils}/bin/touch /var/lib/pve-manager/pve-replication-state.lck" 132 | "${pkgs.coreutils}/bin/chown -R www-data:www-data /var/lib/pve-manager/pve-replication-state.lck" 133 | ]; 134 | ExecStart = "${cfg.package}/bin/pvescheduler start"; 135 | ExecStop = "${cfg.package}/bin/pvescheduler stop"; 136 | ExecReload = "${cfg.package}/bin/pvescheduler restart"; 137 | PIDFile = "/var/run/pvescheduler.pid"; 138 | KillMode = "process"; 139 | Type = "forking"; 140 | }; 141 | }; 142 | 143 | pvestatd = { 144 | description = "PVE Status Daemon"; 145 | wants = [ "pve-cluster.service" ]; 146 | after = [ "pve-cluster.service" ]; 147 | path = with pkgs; [ btrfs-progs zfs ]; 148 | serviceConfig = { 149 | ExecStart = "${cfg.package}/bin/pvestatd start"; 150 | ExecStop = "${cfg.package}/bin/pvestatd stop"; 151 | ExecReload = "${cfg.package}/bin/pvestatd restart"; 152 | PIDFile = "/run/pvestatd.pid"; 153 | Type = "forking"; 154 | }; 155 | }; 156 | 157 | # pvenetcommit = { 158 | # description = "Commit Proxmox VE network changes"; 159 | # wantedBy = [ "multi-user.target" ]; 160 | # environment.FN = "/etc/network/interfaces"; 161 | # unitConfig = { 162 | # DefaultDependencies = false; 163 | # After = "local-fs.target"; 164 | # Before = "sysinit.target"; 165 | # }; 166 | # serviceConfig = { 167 | # ExecStartPre = "${pkgs.coreutils}/bin/rm -f /etc/openvswitch/conf.db"; 168 | # ExecStart = "${pkgs.bash}/bin/sh -c 'if [ -f $FN.new ]; then ${pkgs.coreutils}/bin/mv $FN.new $FN; fi'"; 169 | # Type = "oneshot"; 170 | # RemainAfterExit = true; 171 | # }; 172 | # }; 173 | 174 | spiceproxy = { 175 | description = "PVE SPICE Proxy Server"; 176 | wantedBy = [ "multi-user.target" ]; 177 | after = [ "pveproxy.service" ]; 178 | wants = [ "pveproxy.service" ]; 179 | serviceConfig = { 180 | ExecStartPre = [ 181 | "${pkgs.coreutils}/bin/touch /var/lock/spiceproxy.lck" 182 | "${pkgs.coreutils}/bin/chown www-data:www-data /var/lock/spiceproxy.lck" 183 | ]; 184 | ExecStart = "${pkgs.proxmox-ve}/bin/spiceproxy start"; 185 | ExecStop = [ 186 | "${pkgs.coreutils}/bin/rm -f /var/lock/spiceproxy.lck" 187 | "${pkgs.proxmox-ve}/bin/spiceproxy stop" 188 | ]; 189 | ExecReload = "${pkgs.proxmox-ve}/bin/spiceproxy restart"; 190 | PIDFile = "/run/pveproxy/spiceproxy.pid"; # the code puts it here, not in /run/spiceproxy/ 191 | Type = "forking"; 192 | Restart = "on-failure"; 193 | }; 194 | }; 195 | }; 196 | 197 | systemd.tmpfiles.rules = [ "d /var/log/pveproxy 0755 www-data www-data -" ]; 198 | 199 | systemd.targets = { 200 | pve-storage = { 201 | description = "PVE Storage Target"; 202 | unitConfig = { 203 | Wants = [ "remote-fs.target" ]; 204 | After = [ 205 | "remote-fs.target" 206 | "ceph.target" 207 | "ceph-mon.target" 208 | "ceph-osd.target" 209 | "ceph-mds.target" 210 | "ceph-mgr.target" 211 | "glusterd.service" 212 | "open-iscsi.service" 213 | ]; 214 | }; 215 | }; 216 | }; 217 | } 218 | -------------------------------------------------------------------------------- /modules/proxmox-ve/qemu-server.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | lib.mkIf config.services.proxmox-ve.enable { 9 | systemd.services.qmeventd = { 10 | description = "PVE Qemu Event Daemon"; 11 | unitConfig.RequiresMountsFor = [ "/var/run" ]; 12 | wantedBy = [ "multi-user.target" ]; 13 | before = [ 14 | "pve-ha-lrm.service" 15 | "pve-guests.service" 16 | ]; 17 | serviceConfig = { 18 | ExecStart = "${pkgs.pve-ha-manager}/bin/qmeventd /var/run/qmeventd.sock"; 19 | Type = "forking"; 20 | }; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /modules/proxmox-ve/rrdcached.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | with lib; 9 | let 10 | cfg = config.services.rrdcached; 11 | in 12 | 13 | { 14 | meta.maintainers = with maintainers; [ 15 | julienmalka 16 | camillemndn 17 | ]; 18 | 19 | options.services.rrdcached = { 20 | enable = mkEnableOption (mdDoc ''RRD Cache Daemon''); 21 | }; 22 | 23 | config = mkIf cfg.enable { 24 | systemd.services.rrdcached = { 25 | description = "LSB: start or stop rrdcached"; 26 | before = [ 27 | "multi-user.target" 28 | "graphical.target" 29 | ]; 30 | after = [ 31 | "remote-fs.target" 32 | "nss-lookup.target" 33 | "time-sync.target" 34 | "network-online.target" 35 | ]; 36 | wants = [ "network-online.target" ]; 37 | wantedBy = [ "multi-user.target" ]; 38 | unitConfig = { 39 | Documentation = "man:systemd-sysv-generator(8)"; 40 | SourcePath = "${pkgs.rrdtool}/bin/rrdcached"; 41 | }; 42 | serviceConfig = { 43 | Type = "forking"; 44 | Restart = "no"; 45 | TimeoutSec = "5min"; 46 | IgnoreSIGPIPE = false; 47 | KillMode = "process"; 48 | GuessMainPID = false; 49 | RemainAfterExit = true; 50 | SuccessExitStatus = "5 6"; 51 | ExecStart = "${pkgs.rrdtool}/bin/rrdcached start -b /var/lib/rrdcached/db/ -j /var/lib/rrdcached/journal/ -l /var/run/rrdcached.sock -p /var/run/rrdcached.pid"; 52 | ExecStop = "${pkgs.rrdtool}/bin/rrdcached stop"; 53 | }; 54 | }; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /modules/proxmox-ve/vms.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | with lib; 9 | let 10 | cfg = config.services.proxmox-ve; 11 | 12 | # Fix toString to return "0" for false 13 | toString' = x: if isBool x && (!x) then "0" else toString x; 14 | filterAttrsNonEmpty = filterAttrsRecursive ( 15 | _: v: 16 | v != null 17 | && (!(isList v) || any (x: x != null) v) 18 | && (!(isAttrs v) || any (x: x != null) (attrValues v)) 19 | ); 20 | 21 | configToParams = 22 | config: 23 | processTopLevelAttrs ( 24 | mapAttrs ( 25 | name: value: 26 | if isAttrs value then 27 | processAttrs value 28 | else if isList value then 29 | (if all isAttrs value then processListOfAttrs name value else processList value) 30 | else 31 | toString' value 32 | ) (filterAttrsNonEmpty config) 33 | ); 34 | 35 | processAttrs = 36 | attrs: 37 | concatStringsSep "," ( 38 | mapAttrsToList ( 39 | name: value: "${name}=${if isList value then concatStringsSep ";" value else toString' value}" 40 | ) (filterAttrsNonEmpty attrs) 41 | ); 42 | processListOfAttrs = name: l: imap0 (i: x: "-${name}${toString' i} ${processAttrs x}") l; 43 | processList = concatStringsSep ","; 44 | processTopLevelAttrs = 45 | attrs: 46 | toString' ( 47 | mapAttrsToList ( 48 | name: value: if isString value then "-${name} ${value}" else concatStringsSep " " value 49 | ) attrs 50 | ); 51 | in 52 | 53 | { 54 | options.services.proxmox-ve.vms = mkOption { 55 | type = types.attrsOf ( 56 | types.submodule { inherit (import ../declarative-vms/options.nix { inherit config lib; }) options; } 57 | ); 58 | default = { }; 59 | example = literalExpression '' 60 | { 61 | myvm1 = { 62 | vmid = 100; 63 | memory = 4096; 64 | cores = 4; 65 | sockets = 2; 66 | kvm = false; 67 | net = [ 68 | { 69 | model = "virtio"; 70 | bridge = "vmbr0"; 71 | } 72 | ]; 73 | scsi = [ { file = "local:16"; } ]; 74 | }; 75 | myvm2 = { 76 | vmid = 101; 77 | memory = 8192; 78 | cores = 2; 79 | sockets = 2; 80 | scsi = [ { file = "local:32"; } ]; 81 | }; 82 | }; 83 | ''; 84 | description = "Declarative configuration of Proxmox VMs."; 85 | }; 86 | 87 | config = mkIf cfg.enable { 88 | systemd.services = mapAttrs' ( 89 | name: conf: 90 | let 91 | vmid = toString conf.vmid; 92 | in 93 | nameValuePair "pve-generate-vm-${vmid}" { 94 | description = "PVE VM ${vmid} creation from configuration."; 95 | wants = [ "pveproxy.service" ]; 96 | after = [ "pveproxy.service" ]; 97 | wantedBy = [ "multi-user.target" ]; 98 | script = '' 99 | if ${pkgs.proxmox-ve}/bin/pvesh get /cluster/resources --type vm --output-format json | ${pkgs.jq}/bin/jq -r '.[].vmid' | grep -qw "${vmid}"; then 100 | echo "VM ID ${vmid} is already in use. Skipping creation." 101 | else 102 | echo "VM ID ${vmid} is available. Creating the VM..." 103 | ${pkgs.proxmox-ve}/bin/pvesh create /nodes/${config.networking.hostName}/qemu -name ${name} ${configToParams conf} 104 | echo "VM ID ${vmid} has been successfully created." 105 | fi 106 | ''; 107 | } 108 | ) cfg.vms; 109 | }; 110 | } 111 | -------------------------------------------------------------------------------- /pkgs/cstream/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchurl, 5 | ... 6 | }: 7 | 8 | stdenv.mkDerivation rec { 9 | pname = "cstream"; 10 | version = "4.0.0"; 11 | 12 | src = fetchurl { 13 | url = "https://www.cons.org/cracauer/download/cstream-${version}.tar.gz"; 14 | sha256 = "sha256-a8BtfEOG+5jTqRcTQ0wxXZ5tQlyRyIYoG+qiVMDgluM="; 15 | }; 16 | 17 | meta = { 18 | description = "A general-purpose stream-handling tool like dd"; 19 | homepage = "https://www.cons.org/cracauer/cstream.html"; 20 | maintainers = with lib.maintainers; [ ]; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /pkgs/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | pkgs-unstable, 4 | ... 5 | }: 6 | let 7 | callPackage = pkgs.lib.callPackageWith (pkgs // ours); 8 | 9 | ours = { 10 | authenpam = callPackage ./perl-modules/authenpam { }; 11 | datadumper = callPackage ./perl-modules/datadumper { }; 12 | digestsha = callPackage ./perl-modules/digest-sha { }; 13 | findbin = callPackage ./perl-modules/find-bin { }; 14 | iosocketip = callPackage ./perl-modules/iosocketip { }; 15 | mimebase32 = callPackage ./perl-modules/mimebase32 { }; 16 | mimebase64 = callPackage ./perl-modules/mimebase64 { }; 17 | posixstrptime = callPackage ./perl-modules/posixstrptime { }; 18 | socket = callPackage ./perl-modules/socket { }; 19 | termreadline = callPackage ./perl-modules/termreadline { }; 20 | testharness = callPackage ./perl-modules/testharness { }; 21 | uuid = callPackage ./perl-modules/uuid { }; 22 | 23 | extjs = callPackage ./extjs { }; 24 | fonts-font-logos = callPackage ./fonts-font-logos { }; 25 | sencha-touch = callPackage ./sencha-touch { }; 26 | markedjs = callPackage ./markedjs { }; 27 | perlmod = callPackage ./perlmod { }; 28 | termproxy = callPackage ./termproxy { }; 29 | unifont_hex = callPackage ./unifont { }; 30 | vncterm = callPackage ./vncterm { }; 31 | cstream = callPackage ./cstream { }; 32 | 33 | mkRegistry = callPackage ./proxmox-registry { }; 34 | 35 | proxmox-acme = callPackage ./proxmox-acme { }; 36 | proxmox-backup-qemu = callPackage ./proxmox-backup-qemu { }; 37 | proxmox-ve = callPackage ./proxmox-ve { }; 38 | proxmox-widget-toolkit = callPackage ./proxmox-widget-toolkit { }; 39 | 40 | pve-access-control = callPackage ./pve-access-control { }; 41 | pve-apiclient = callPackage ./pve-apiclient { }; 42 | pve-cluster = callPackage ./pve-cluster { }; 43 | pve-common = callPackage ./pve-common { }; 44 | pve-container = callPackage ./pve-container { }; 45 | pve-docs = callPackage ./pve-docs { }; 46 | pve-edk2-firmware = callPackage ./pve-edk2-firmware { }; 47 | pve-firewall = callPackage ./pve-firewall { }; 48 | pve-guest-common = callPackage ./pve-guest-common { }; 49 | pve-ha-manager = callPackage ./pve-ha-manager { }; 50 | pve-http-server = callPackage ./pve-http-server { }; 51 | pve-manager = callPackage ./pve-manager { }; 52 | pve-novnc = callPackage ./pve-novnc { }; 53 | pve-qemu = callPackage ./pve-qemu { }; 54 | pve-qemu-server = callPackage ./pve-qemu-server { }; 55 | pve-rados2 = callPackage ./pve-rados2 { }; 56 | pve-rs = callPackage ./pve-rs { }; 57 | pve-storage = callPackage ./pve-storage { }; 58 | pve-xtermjs = callPackage ./pve-xtermjs { }; 59 | 60 | linstor-api-py = callPackage ./linstor-api-py { }; 61 | linstor-client = callPackage ./linstor-client { }; 62 | linstor-proxmox = callPackage ./linstor-proxmox { }; 63 | linstor-server = pkgs-unstable.callPackage ./linstor-server { 64 | protobuf = pkgs-unstable.protobuf_24; 65 | jre = pkgs.jdk11_headless; 66 | }; 67 | nixmoxer = callPackage ./nixmoxer { }; 68 | }; 69 | in 70 | ours 71 | -------------------------------------------------------------------------------- /pkgs/extjs/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | }: 6 | 7 | stdenv.mkDerivation rec { 8 | pname = "extjs"; 9 | version = "7.0.0-5"; 10 | 11 | src = fetchgit { 12 | url = "git://git.proxmox.com/git/extjs.git"; 13 | rev = "18909118c3d316f0bb48846920b8c94a4efc31f5"; 14 | hash = "sha256-AaV2DY5DG7tnqDFmfM3yIvJiyQYpR3pX9geH64JG4Ik="; 15 | }; 16 | 17 | sourceRoot = "${src.name}/extjs/build"; 18 | 19 | installPhase = '' 20 | mkdir -p $out/share/javascript/extjs 21 | cp -r classic/locale $out/share/javascript/extjs 22 | cp -r classic/theme-crisp $out/share/javascript/extjs 23 | cp ext-all-debug.js $out/share/javascript/extjs 24 | cp ext-all.js $out/share/javascript/extjs 25 | cp packages/charts/classic/charts-debug.js $out/share/javascript/extjs 26 | cp packages/charts/classic/charts.js $out/share/javascript/extjs 27 | cp -r packages/charts/classic/crisp $out/share/javascript/extjs 28 | ''; 29 | 30 | passthru.updateScript = [ 31 | ../update.py 32 | pname 33 | "--url" 34 | src.url 35 | ]; 36 | 37 | meta = with lib; { 38 | description = ""; 39 | homepage = "git://git.proxmox.com/?p=extjs.git"; 40 | license = [ ]; 41 | maintainers = with maintainers; [ 42 | camillemndn 43 | julienmalka 44 | ]; 45 | mainProgram = "extjs"; 46 | platforms = platforms.all; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /pkgs/fonts-font-logos/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | }: 6 | 7 | stdenv.mkDerivation rec { 8 | pname = "fonts-font-logos"; 9 | version = "1.0.1-3"; 10 | 11 | src = fetchgit { 12 | url = "git://git.proxmox.com/git/fonts-font-logos.git"; 13 | rev = "063091d1a7ea70eba36c5684d20428ba215cb769"; 14 | hash = "sha256-eSlnOqbXFLLlomFCb6IWdgzHAqqHn4sSTG5rEC4Tasg="; 15 | }; 16 | 17 | sourceRoot = "${src.name}/src"; 18 | 19 | installPhase = '' 20 | mkdir -p $out/share/fonts-font-logos/css 21 | cp -r font-logos/assets $out/share/fonts-font-logos/fonts 22 | cp font-logos.css $out/share/fonts-font-logos/css 23 | ''; 24 | 25 | passthru.updateScript = [ 26 | ../update.py 27 | pname 28 | "--url" 29 | src.url 30 | ]; 31 | 32 | meta = with lib; { 33 | description = ""; 34 | homepage = "git://git.proxmox.com/?p=fonts-font-logos.git"; 35 | license = [ ]; 36 | maintainers = with maintainers; [ 37 | camillemndn 38 | julienmalka 39 | ]; 40 | mainProgram = "fonts-font-logos"; 41 | platforms = platforms.all; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /pkgs/linstor-api-py/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | python310, 4 | fetchFromGitHub, 5 | }: 6 | 7 | python310.pkgs.buildPythonPackage rec { 8 | pname = "linstor-api-py"; 9 | version = "1.23.0"; 10 | pyproject = true; 11 | 12 | src = fetchFromGitHub { 13 | owner = "LINBIT"; 14 | repo = "linstor-api-py"; 15 | rev = "v${version}"; 16 | hash = "sha256-+nv1Lp14X7a5BVHYGWFEESO95MsTa6NLPJSRJvIJc3w="; 17 | fetchSubmodules = true; 18 | }; 19 | 20 | nativeBuildInputs = [ 21 | python310.pkgs.setuptools 22 | python310.pkgs.wheel 23 | python310.pkgs.distutils 24 | ]; 25 | 26 | pythonImportsCheck = [ "linstor" ]; 27 | 28 | meta = with lib; { 29 | description = "LINSTOR Python API"; 30 | homepage = "https://github.com/LINBIT/linstor-api-py"; 31 | changelog = "https://github.com/LINBIT/linstor-api-py/blob/${src.rev}/CHANGELOG.md"; 32 | license = [ ]; 33 | maintainers = with maintainers; [ 34 | camillemndn 35 | julienmalka 36 | ]; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /pkgs/linstor-client/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | python310, 4 | fetchFromGitHub, 5 | linstor-api-py, 6 | nix-update-script, 7 | }: 8 | 9 | python310.pkgs.buildPythonApplication rec { 10 | pname = "linstor-client"; 11 | version = "1.23.0"; 12 | pyproject = true; 13 | 14 | src = fetchFromGitHub { 15 | owner = "LINBIT"; 16 | repo = "linstor-client"; 17 | rev = "v${version}"; 18 | hash = "sha256-DxYtqJr8ZOlwQdX4s4UF1BnzQsJQaYQOYOupbN3kD5k="; 19 | }; 20 | 21 | nativeBuildInputs = [ 22 | python310.pkgs.setuptools 23 | python310.pkgs.wheel 24 | ]; 25 | 26 | propagatedBuildInputs = [ linstor-api-py ]; 27 | 28 | pythonImportsCheck = [ "linstor_client" ]; 29 | 30 | passthru.updateScript = nix-update-script { extraArgs = [ "--flake" ]; }; 31 | 32 | meta = with lib; { 33 | description = "Python client for LINSTOR"; 34 | homepage = "https://github.com/LINBIT/linstor-client"; 35 | changelog = "https://github.com/LINBIT/linstor-client/blob/${src.rev}/CHANGELOG.md"; 36 | license = licenses.gpl3Only; 37 | maintainers = with maintainers; [ 38 | camillemndn 39 | julienmalka 40 | ]; 41 | mainProgram = "linstor"; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /pkgs/linstor-proxmox/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchFromGitHub, 5 | perl538, 6 | nix-update-script, 7 | }: 8 | 9 | let 10 | perlDeps = with perl538.pkgs; [ 11 | JSONXS 12 | RESTClient 13 | TypesSerialiser 14 | ]; 15 | 16 | perlEnv = perl538.withPackages (_: perlDeps); 17 | in 18 | 19 | perl538.pkgs.toPerlModule ( 20 | stdenv.mkDerivation rec { 21 | pname = "linstor-proxmox"; 22 | version = "8.1.1"; 23 | 24 | src = fetchFromGitHub { 25 | owner = "LINBIT"; 26 | repo = "linstor-proxmox"; 27 | rev = "v${version}"; 28 | hash = "sha256-O50dqs6XPiU58mr65h+Juj9hxalUL6UcgTcXnyCEwBY="; 29 | }; 30 | 31 | makeFlags = [ 32 | "DESTDIR=$(out)" 33 | "PERLDIR=/${perl538.libPrefix}/${perl538.version}" 34 | ]; 35 | 36 | buildInputs = [ perlEnv ]; 37 | propagatedBuildInputs = perlDeps; 38 | 39 | passthru.updateScript = nix-update-script { extraArgs = [ "--flake" ]; }; 40 | 41 | meta = with lib; { 42 | description = "Integration pluging bridging LINSTOR to Proxmox VE"; 43 | homepage = "https://github.com/LINBIT/linstor-proxmox"; 44 | changelog = "https://github.com/LINBIT/linstor-proxmox/blob/${src.rev}/CHANGELOG.md"; 45 | license = licenses.agpl3Plus; 46 | maintainers = with maintainers; [ 47 | camillemndn 48 | julienmalka 49 | ]; 50 | platforms = platforms.linux; 51 | }; 52 | } 53 | ) 54 | -------------------------------------------------------------------------------- /pkgs/linstor-server/build.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Makefile b/Makefile 2 | index 0646cedd7..6d932bae3 100644 3 | --- a/Makefile 4 | +++ b/Makefile 5 | @@ -16,7 +16,7 @@ GENSRC=./server/generated-src 6 | VERSINFO=$(GENRES)/version-info.properties 7 | 8 | # echo v0.1 to get it started 9 | -VERSION ?= $(shell echo $(shell git describe --tags || echo "v0.1") | sed -e 's/^v//;s/^[^0-9]*//;s/\(.*\)-g/\1-/') 10 | +VERSION ?= $(shell echo $(shell git describe --tags ) | sed -e 's/^v//;s/^[^0-9]*//;s/\(.*\)-g/\1-/') 11 | GITHASH := $(shell git rev-parse HEAD) 12 | DEBVERSION = $(shell echo $(VERSION) | sed -e 's/-/~/g') 13 | 14 | diff --git a/build.gradle b/build.gradle 15 | index 846bc752b..053a33c46 100644 16 | --- a/build.gradle 17 | +++ b/build.gradle 18 | @@ -173,13 +173,8 @@ project(':server') { 19 | * tarball, and it is then skipped when the package is finally built. 20 | */ 21 | tasks.register('generateProto', Exec) { 22 | - doFirst { 23 | - if (!protoc.exists()) { 24 | - throw new GradleException("'protoc' binary not found; run the task 'getProtoc' to download the binary") 25 | - } 26 | - } 27 | 28 | - commandLine 'make', '-C', "${projectDir}/proto", "PROTOC=" + protoc, 'proto' 29 | + commandLine 'make', '-C', "${projectDir}/proto", "PROTOC=protoc", 'proto' 30 | 31 | inputs.files(fileTree("${projectDir}/proto")) 32 | outputs.dir(file("${projectDir}/generated-src")) 33 | -------------------------------------------------------------------------------- /pkgs/linstor-server/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchFromGitHub, 5 | gradle, 6 | protobuf, 7 | git, 8 | python3, 9 | makeWrapper, 10 | jre, 11 | bashInteractive, 12 | bcache-tools, 13 | coreutils, 14 | cryptsetup, 15 | drbd, 16 | gnugrep, 17 | kmod, 18 | lsscsi, 19 | lvm2, 20 | mount, 21 | nvme-cli, 22 | systemdMinimal, 23 | thin-provisioning-tools, 24 | util-linux, 25 | zfs, 26 | }: 27 | 28 | let 29 | self = stdenv.mkDerivation (finalAttrs: { 30 | pname = "linstor-server"; 31 | version = "1.29.0"; 32 | 33 | src = fetchFromGitHub { 34 | owner = "LINBIT"; 35 | repo = "linstor-server"; 36 | rev = "v${finalAttrs.version}"; 37 | hash = "sha256-+rtvc6FrBQ9YjLiuJpVy/xzSpXp9AgIRNScRd4BPmYw="; 38 | fetchSubmodules = true; 39 | leaveDotGit = true; 40 | }; 41 | 42 | patches = [ ./build.patch ]; 43 | postPatch = '' 44 | find . -type f -name "*.java" -exec sed -i {} -e "s|/bin/bash|${bashInteractive}/bin/bash|g" \; 45 | ''; 46 | 47 | nativeBuildInputs = [ 48 | gradle 49 | protobuf 50 | git 51 | python3 52 | makeWrapper 53 | ]; 54 | 55 | buildInputs = [ protobuf ]; 56 | 57 | gradleBuildTask = "installDist"; 58 | 59 | preBuild = '' 60 | VERSION="${finalAttrs.version}" make versioninfo 61 | ''; 62 | 63 | mitmCache = gradle.fetchDeps { 64 | pkg = self; 65 | data = ./deps.json; 66 | }; 67 | 68 | gradleFlags = [ "-Dfile.encoding=utf-8" ]; 69 | 70 | doCheck = false; 71 | 72 | installPhase = '' 73 | mkdir -p $out/bin 74 | mkdir -p $out/lib/conf 75 | cp -r build/install/linstor-server/lib/* $out/lib/ 76 | cp server/logback.xml $out/lib/conf/ 77 | makeWrapper ${jre}/bin/java $out/bin/linstor-controller \ 78 | --add-flags "-Xms32M -classpath $out/lib/conf:$out/lib/* com.linbit.linstor.core.Controller" \ 79 | --prefix PATH : ${ 80 | lib.makeBinPath [ 81 | bcache-tools 82 | coreutils 83 | cryptsetup 84 | drbd 85 | gnugrep 86 | kmod 87 | lsscsi 88 | lvm2 89 | mount 90 | nvme-cli 91 | systemdMinimal 92 | thin-provisioning-tools 93 | util-linux 94 | zfs 95 | ] 96 | } 97 | 98 | makeWrapper ${jre}/bin/java $out/bin/linstor-satellite \ 99 | --add-flags "-Xms32M -classpath $out/lib/conf:$out/lib/* com.linbit.linstor.core.Satellite" \ 100 | --prefix PATH : ${ 101 | lib.makeBinPath [ 102 | bcache-tools 103 | coreutils 104 | cryptsetup 105 | drbd 106 | gnugrep 107 | kmod 108 | lsscsi 109 | lvm2 110 | mount 111 | nvme-cli 112 | systemdMinimal 113 | thin-provisioning-tools 114 | util-linux 115 | zfs 116 | ] 117 | } 118 | ''; 119 | }); 120 | 121 | in 122 | self 123 | -------------------------------------------------------------------------------- /pkgs/markedjs/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | buildNpmPackage, 4 | fetchFromGitHub, 5 | nix-update-script, 6 | }: 7 | 8 | buildNpmPackage rec { 9 | pname = "markedjs"; 10 | version = "15.0.12"; 11 | 12 | src = fetchFromGitHub { 13 | owner = "markedjs"; 14 | repo = "marked"; 15 | rev = "v${version}"; 16 | hash = "sha256-GwKL1EsxiYijPAMNM9bO0RQ/aQBcQSUlOy6O73igH6U="; 17 | }; 18 | 19 | npmDepsHash = "sha256-tUE8GWlwXmHpCeWyI0ipvSO2PvJ2YB0uCX7gugzscF0="; 20 | 21 | passthru.updateScript = nix-update-script { extraArgs = [ "--flake" ]; }; 22 | 23 | meta = with lib; { 24 | description = "A markdown parser and compiler. Built for speed"; 25 | homepage = "https://marked.js.org/"; 26 | license = licenses.mit; 27 | maintainers = with maintainers; [ 28 | camillemndn 29 | julienmalka 30 | ]; 31 | platforms = platforms.linux; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /pkgs/nixmoxer/default.nix: -------------------------------------------------------------------------------- 1 | { python3Packages }: 2 | 3 | python3Packages.buildPythonApplication rec { 4 | pname = "nixmoxer"; 5 | version = "1.0.0"; 6 | pyproject = true; 7 | 8 | src = ./.; 9 | 10 | build-system = with python3Packages; [ setuptools ]; 11 | 12 | dependencies = with python3Packages; [ 13 | proxmoxer 14 | click 15 | requests_toolbelt 16 | ]; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /pkgs/nixmoxer/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "nixmoxer" 7 | version = "1.0.0" 8 | description = "Declarative proxmox VM bootstrap" 9 | authors = [ 10 | {name = "Julien Malka"}, 11 | {name = "Camille Mondon"} 12 | ] 13 | readme = "README.md" 14 | requires-python = ">=3.7" 15 | license = {text = "MIT"} # You can specify your preferred license here 16 | dependencies = [ 17 | "proxmoxer", 18 | "requests_toolbelt" 19 | ] 20 | [project.scripts] 21 | nixmoxer = "main:run_main" 22 | -------------------------------------------------------------------------------- /pkgs/perl-modules/authenpam/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | linux-pam, 5 | perl538, 6 | }: 7 | 8 | perl538.pkgs.buildPerlPackage rec { 9 | pname = "AuthenPAM"; 10 | version = "0.16"; 11 | 12 | src = fetchurl { 13 | url = "mirror://cpan/authors/id/N/NI/NIKIP/Authen-PAM-${version}.tar.gz"; 14 | hash = "sha256-DpSb2aKp3w+CmXEDD+kWnLr2zseLkvryL1R/9sYVXJs="; 15 | }; 16 | 17 | buildInputs = [ linux-pam ]; 18 | setOutputFlags = false; 19 | doCheck = false; 20 | 21 | passthru.updateScript = [ 22 | ../update.pl 23 | "Authen::PAM" 24 | ]; 25 | 26 | meta = with lib; { 27 | description = "Perl interface to PAM library"; 28 | license = with licenses; [ 29 | artistic1 30 | gpl1Plus 31 | ]; 32 | maintainers = with maintainers; [ 33 | camillemndn 34 | julienmalka 35 | ]; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /pkgs/perl-modules/datadumper/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlPackage rec { 8 | pname = "DataDumper"; 9 | version = "2.183"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/N/NW/NWCLARK/Data-Dumper-${version}.tar.gz"; 13 | hash = "sha256-5Cc2iQt9rhs3gY2cXvofH9xS3sBPRGozpIGb8dSrWtM="; 14 | }; 15 | 16 | passthru.updateScript = [ 17 | ../update.pl 18 | "Data::Dumper" 19 | ]; 20 | 21 | meta = with lib; { 22 | description = "stringified perl data structures, suitable for both printing and eval"; 23 | license = with licenses; [ 24 | artistic1 25 | gpl1Plus 26 | ]; 27 | maintainers = with maintainers; [ 28 | camillemndn 29 | julienmalka 30 | ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /pkgs/perl-modules/digest-sha/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlPackage rec { 8 | pname = "DigestSHA"; 9 | version = "6.04"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/M/MS/MSHELOR/Digest-SHA-${version}.tar.gz"; 13 | hash = "sha256-7pH499uJTufG7gA9qsEKmQVsSUimdO9GrNu2PIGkq+s="; 14 | }; 15 | 16 | passthru.updateScript = [ 17 | ../update.pl 18 | "Digest::SHA" 19 | ]; 20 | 21 | meta = with lib; { 22 | description = "Perl extension for SHA-1/224/256/384/512"; 23 | license = with licenses; [ 24 | artistic1 25 | gpl1Plus 26 | ]; 27 | maintainers = with maintainers; [ 28 | camillemndn 29 | julienmalka 30 | ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /pkgs/perl-modules/find-bin/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | perl538.pkgs.buildPerlPackage rec { 7 | pname = "FindBin"; 8 | version = "1.54"; 9 | src = fetchurl { 10 | url = "mirror://cpan/authors/id/T/TO/TODDR/FindBin-${version}.tar.gz"; 11 | hash = "sha256-ascyln5Sn+N2lZre7uJ2Dmli16nYXnlti2peHNjykV0="; 12 | }; 13 | 14 | passthru.updateScript = [ 15 | ../update.pl 16 | "FindBin" 17 | ]; 18 | 19 | meta = with lib; { 20 | description = "Base32 encoder and decoder"; 21 | license = with licenses; [ 22 | artistic1 23 | gpl1Plus 24 | ]; 25 | maintainers = with maintainers; [ 26 | camillemndn 27 | julienmalka 28 | ]; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /pkgs/perl-modules/iosocketip/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlModule rec { 8 | pname = "IOSocketIP"; 9 | version = "0.42"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/P/PE/PEVANS/IO-Socket-IP-${version}.tar.gz"; 13 | hash = "sha256-+Xo4RsUKTgZYzhciznzCrK2UcucEeL++nHlPsdtqaxM="; 14 | }; 15 | 16 | passthru.updateScript = [ 17 | ../update.pl 18 | "IO::Socket::IP" 19 | ]; 20 | 21 | meta = with lib; { 22 | description = "Base32 encoder and decoder"; 23 | license = with licenses; [ 24 | artistic1 25 | gpl1Plus 26 | ]; 27 | maintainers = with maintainers; [ 28 | camillemndn 29 | julienmalka 30 | ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /pkgs/perl-modules/mimebase32/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlPackage rec { 8 | pname = "MIMEBase32"; 9 | version = "1.303"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/R/RE/REHSACK/MIME-Base32-${version}.tar.gz"; 13 | hash = "sha256-qyH6mRMOM6Cv9s21lvZH5eVl0gfWNLou8Gvb71BCTpk="; 14 | }; 15 | 16 | propagatedBuildInputs = [ perl538.pkgs.Exporter ]; 17 | 18 | passthru.updateScript = [ 19 | ../update.pl 20 | "MIME::Base32" 21 | ]; 22 | 23 | meta = with lib; { 24 | description = "Base32 encoder and decoder"; 25 | license = with licenses; [ 26 | artistic1 27 | gpl1Plus 28 | ]; 29 | maintainers = with maintainers; [ 30 | camillemndn 31 | julienmalka 32 | ]; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /pkgs/perl-modules/mimebase64/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlPackage rec { 8 | pname = "MIMEBase64"; 9 | version = "3.16"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/C/CA/CAPOEIRAB/MIME-Base64-${version}.tar.gz"; 13 | hash = "sha256-d/c9b3rrjTO+CLDYwmF/m2x3+3/EVCLVB8qLr+QkYBc="; 14 | }; 15 | 16 | passthru.updateScript = [ 17 | ../update.pl 18 | "MIME::Base64" 19 | ]; 20 | 21 | meta = with lib; { 22 | description = "Base32 encoder and decoder"; 23 | license = with licenses; [ 24 | artistic1 25 | gpl1Plus 26 | ]; 27 | maintainers = with maintainers; [ 28 | camillemndn 29 | julienmalka 30 | ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /pkgs/perl-modules/posixstrptime/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlPackage rec { 8 | pname = "POSIXstrptime"; 9 | version = "0.13"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/G/GO/GOZER/POSIX-strptime-${version}.tar.gz"; 13 | hash = "sha256-qBgQmCnjWkrHlnfWgGOGX0DIfJnKfzogiQF3qPjlwnc="; 14 | }; 15 | 16 | passthru.updateScript = [ 17 | ../update.pl 18 | "POSIX::strptime" 19 | ]; 20 | 21 | meta = with lib; { 22 | description = "Base32 encoder and decoder"; 23 | license = with licenses; [ 24 | artistic1 25 | gpl1Plus 26 | ]; 27 | maintainers = with maintainers; [ 28 | camillemndn 29 | julienmalka 30 | ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /pkgs/perl-modules/socket/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlPackage rec { 8 | pname = "Socket"; 9 | version = "2.038"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/P/PE/PEVANS/Socket-${version}.tar.gz"; 13 | hash = "sha256-Vj0Rcx/0Qwf6J3mmlY/S0vZkP72aMXTL81AiixWWgfg="; 14 | }; 15 | 16 | passthru.updateScript = [ 17 | ../update.pl 18 | "Socket" 19 | ]; 20 | 21 | meta = with lib; { 22 | description = "Base32 encoder and decoder"; 23 | license = with licenses; [ 24 | artistic1 25 | gpl1Plus 26 | ]; 27 | maintainers = with maintainers; [ 28 | camillemndn 29 | julienmalka 30 | ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /pkgs/perl-modules/termreadline/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlPackage rec { 8 | pname = "TermReadLine"; 9 | version = "1.14"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/F/FL/FLORA/Term-ReadLine-${version}.tar.gz"; 13 | hash = "sha256-VFI8crJqBGCBcISQE6QzukAPZrT5sFJCAb/Tf/bjxHc="; 14 | }; 15 | 16 | passthru.updateScript = [ 17 | ../update.pl 18 | "Term::ReadLine" 19 | ]; 20 | 21 | meta = with lib; { 22 | description = "Perl interface to various readline packages"; 23 | license = with licenses; [ 24 | artistic1 25 | gpl1Plus 26 | ]; 27 | maintainers = with maintainers; [ 28 | camillemndn 29 | julienmalka 30 | ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /pkgs/perl-modules/testharness/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | }: 6 | 7 | perl538.pkgs.buildPerlPackage rec { 8 | pname = "TestHarness"; 9 | version = "3.52"; 10 | 11 | src = fetchurl { 12 | url = "mirror://cpan/authors/id/L/LE/LEONT/Test-Harness-${version}.tar.gz"; 13 | hash = "sha256-j+Zc/AJh7TyKQ5XwUkKG9XGWaf4wX5sDsWzzaE1izXA="; 14 | }; 15 | 16 | doCheck = false; 17 | 18 | passthru.updateScript = [ 19 | ../update.pl 20 | "Test::Harness" 21 | ]; 22 | 23 | meta = with lib; { 24 | description = "Run test scripts with statistics"; 25 | license = with licenses; [ 26 | artistic1 27 | gpl1Plus 28 | ]; 29 | maintainers = with maintainers; [ 30 | camillemndn 31 | julienmalka 32 | ]; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /pkgs/perl-modules/update.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix-shell 2 | #!nix-shell -i perl -p common-updater-scripts 3 | 4 | use strict; 5 | use warnings; 6 | use CPAN; 7 | 8 | # Suppress CPAN output by redirecting STDOUT and STDERR to /dev/null 9 | open my $old_stdout, '>&', \*STDOUT; 10 | open my $old_stderr, '>&', \*STDERR; 11 | open STDOUT, '>', '/dev/null'; 12 | open STDERR, '>', '/dev/null'; 13 | 14 | # Check if the package name is provided as an argument 15 | if (@ARGV != 1) { 16 | open STDOUT, '>&', $old_stdout; 17 | open STDERR, '>&', $old_stderr; 18 | die "Usage: $0 \n"; 19 | } 20 | 21 | my $package_name = $ARGV[0]; 22 | 23 | # Initialize CPAN and reload index silently 24 | CPAN::HandleConfig->load; 25 | CPAN::Shell::setup_output; 26 | CPAN::Index->reload; 27 | 28 | # Find the latest version of the package 29 | my $module = CPAN::Shell->expand('Module', $package_name); 30 | 31 | unless ($module) { 32 | open STDOUT, '>&', $old_stdout; 33 | open STDERR, '>&', $old_stderr; 34 | die "Package $package_name not found on CPAN.\n"; 35 | } 36 | 37 | # Get the latest version of the package 38 | my $latest_version = $module->cpan_version; 39 | 40 | # Restore STDOUT and STDERR 41 | open STDOUT, '>&', $old_stdout; 42 | open STDERR, '>&', $old_stderr; 43 | 44 | # Print the latest version 45 | print "Latest version: $latest_version"; 46 | 47 | # Run the update-source-version command with the package name and version 48 | (my $modified_package_name = $package_name) =~ s/:://g; 49 | $modified_package_name = lc($modified_package_name); 50 | 51 | my $command = "update-source-version $modified_package_name $latest_version"; 52 | system($command) == 0 53 | or die "Failed to run command: $command\n"; 54 | -------------------------------------------------------------------------------- /pkgs/perl-modules/uuid/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchurl, 4 | perl538, 5 | libuuid, 6 | }: 7 | 8 | perl538.pkgs.buildPerlPackage rec { 9 | pname = "UUID"; 10 | version = "0.37"; 11 | 12 | src = fetchurl { 13 | url = "mirror://cpan/authors/id/J/JR/JRM/UUID-${version}.tar.gz"; 14 | hash = "sha256-AvWv4rQ4bgm2yzo5taECt054mj4pcimUogqOMoXFYcc="; 15 | }; 16 | 17 | buildInputs = [ 18 | perl538.pkgs.DevelChecklib 19 | libuuid.dev 20 | ]; 21 | 22 | NIX_CFLAGS_LINK = "-luuid"; 23 | doCheck = false; 24 | 25 | passthru.updateScript = [ 26 | ../update.pl 27 | "UUID" 28 | ]; 29 | 30 | meta = with lib; { 31 | description = "DCE compatible Universally Unique Identifier library"; 32 | license = with licenses; [ 33 | artistic1 34 | gpl1Plus 35 | ]; 36 | maintainers = with maintainers; [ 37 | camillemndn 38 | julienmalka 39 | ]; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /pkgs/perlmod/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "anyhow" 7 | version = "1.0.98" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 16 | 17 | [[package]] 18 | name = "cc" 19 | version = "1.2.25" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" 22 | dependencies = [ 23 | "shlex", 24 | ] 25 | 26 | [[package]] 27 | name = "libc" 28 | version = "0.2.172" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 31 | 32 | [[package]] 33 | name = "perlmod" 34 | version = "0.13.6" 35 | dependencies = [ 36 | "bitflags", 37 | "cc", 38 | "libc", 39 | "perlmod-macro", 40 | "serde", 41 | ] 42 | 43 | [[package]] 44 | name = "perlmod-macro" 45 | version = "0.9.0" 46 | dependencies = [ 47 | "perlmod", 48 | "proc-macro2", 49 | "quote", 50 | "syn", 51 | ] 52 | 53 | [[package]] 54 | name = "perlmod-test" 55 | version = "0.1.0" 56 | dependencies = [ 57 | "anyhow", 58 | "perlmod", 59 | "serde", 60 | ] 61 | 62 | [[package]] 63 | name = "proc-macro2" 64 | version = "1.0.95" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 67 | dependencies = [ 68 | "unicode-ident", 69 | ] 70 | 71 | [[package]] 72 | name = "quote" 73 | version = "1.0.40" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 76 | dependencies = [ 77 | "proc-macro2", 78 | ] 79 | 80 | [[package]] 81 | name = "serde" 82 | version = "1.0.219" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 85 | dependencies = [ 86 | "serde_derive", 87 | ] 88 | 89 | [[package]] 90 | name = "serde_derive" 91 | version = "1.0.219" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 94 | dependencies = [ 95 | "proc-macro2", 96 | "quote", 97 | "syn", 98 | ] 99 | 100 | [[package]] 101 | name = "shlex" 102 | version = "1.3.0" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 105 | 106 | [[package]] 107 | name = "syn" 108 | version = "2.0.101" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 111 | dependencies = [ 112 | "proc-macro2", 113 | "quote", 114 | "unicode-ident", 115 | ] 116 | 117 | [[package]] 118 | name = "unicode-ident" 119 | version = "1.0.18" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 122 | -------------------------------------------------------------------------------- /pkgs/perlmod/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | rustPlatform, 4 | fetchgit, 5 | perl538, 6 | libxcrypt, 7 | }: 8 | 9 | rustPlatform.buildRustPackage rec { 10 | pname = "perlmod"; 11 | version = "0.2.0-3"; 12 | 13 | src = fetchgit { 14 | url = "git://git.proxmox.com/git/perlmod.git"; 15 | rev = "1544fc13d7196152409467db416f1791ed121fc3"; 16 | hash = "sha256-/HsItWYgSMkqaXHsvsRR3seuHkzWJfBnAR2DDwcvpw4="; 17 | }; 18 | 19 | patches = [ ./remove_safe_putenv.patch ]; 20 | 21 | cargoLock.lockFile = ./Cargo.lock; 22 | 23 | postPatch = '' 24 | rm .cargo/config.toml 25 | patchShebangs perlmod-bin/genpackage.pl 26 | ln -s ${./Cargo.lock} Cargo.lock 27 | ''; 28 | 29 | nativeBuildInputs = [ perl538 ]; 30 | buildInputs = [ libxcrypt ]; 31 | 32 | postInstall = '' 33 | mkdir $out/lib/perlmod 34 | cp perlmod-bin/genpackage.pl $out/lib/perlmod 35 | ''; 36 | 37 | passthru.updateScript = [ 38 | ../update.py 39 | pname 40 | "--url" 41 | src.url 42 | "--prefix" 43 | "bump perlmod-bin to" 44 | "--root" 45 | pname 46 | ]; 47 | 48 | meta = with lib; { 49 | description = "Alternative to Perl XS for Rust"; 50 | homepage = "git://git.proxmox.com/?p=perlmod.git"; 51 | license = with licenses; [ ]; 52 | maintainers = with maintainers; [ 53 | camillemndn 54 | julienmalka 55 | ]; 56 | platforms = platforms.linux; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /pkgs/perlmod/remove_safe_putenv.patch: -------------------------------------------------------------------------------- 1 | diff --git a/perlmod/src/glue.c b/perlmod/src/glue.c 2 | index 6e05684..189362e 100644 3 | --- a/perlmod/src/glue.c 4 | +++ b/perlmod/src/glue.c 5 | @@ -455,7 +455,7 @@ extern HV* RSPL_defstash() { 6 | } 7 | 8 | extern void RSPL_set_use_safe_putenv(int on) { 9 | - PL_use_safe_putenv = on ? TRUE : FALSE; 10 | + // Do nothing 11 | } 12 | 13 | /* 14 | -------------------------------------------------------------------------------- /pkgs/proxmox-acme/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | acme-sh, 7 | bash, 8 | curl, 9 | }: 10 | 11 | let 12 | perlDeps = with perl538.pkgs; [ 13 | HTTPDaemon 14 | HTTPMessage 15 | ]; 16 | in 17 | 18 | perl538.pkgs.toPerlModule ( 19 | stdenv.mkDerivation rec { 20 | pname = "proxmox-acme"; 21 | version = "1.5.1"; 22 | 23 | src = fetchgit { 24 | url = "git://git.proxmox.com/git/${pname}.git"; 25 | rev = "bb6df0b8185829b5c1757330c12f977e196ed2b8"; 26 | hash = "sha256-yVgOOE7vAEc9PFeAUuqnctdkWdXLYnDD/gra8YDGhq0="; 27 | }; 28 | 29 | sourceRoot = "${src.name}/src"; 30 | 31 | postPatch = '' 32 | # Remove --reset-env so basic coreutils tools could be found 33 | substituteInPlace PVE/ACME/DNSChallenge.pm \ 34 | --replace-fail ', "--reset-env"' "" \ 35 | --replace-fail '/bin/bash' '${lib.getExe bash}' 36 | substituteInPlace proxmox-acme \ 37 | --replace-fail '_CURL="curl' '_CURL="${lib.getExe curl}' 38 | 39 | sed -i Makefile -e "s,acme.sh,${acme-sh}/libexec," 40 | ''; 41 | 42 | makeFlags = [ 43 | "PREFIX=$(out)" 44 | "PERLDIR=$(out)/${perl538.libPrefix}/${perl538.version}" 45 | ]; 46 | 47 | propagatedBuildInputs = perlDeps; 48 | 49 | postFixup = '' 50 | find $out -type f | xargs sed -i -e "s|/usr/share/proxmox-acme|$out/share/proxmox-acme|" 51 | ''; 52 | 53 | passthru.updateScript = [ 54 | ../update.py 55 | pname 56 | "--url" 57 | src.url 58 | ]; 59 | 60 | meta = with lib; { 61 | description = "ACME library and helpers for perl-based Proxmox projects"; 62 | homepage = "git://git.proxmox.com/?p=proxmox-acme.git"; 63 | license = with licenses; [ ]; 64 | maintainers = with maintainers; [ 65 | camillemndn 66 | julienmalka 67 | ]; 68 | platforms = platforms.linux; 69 | }; 70 | } 71 | ) 72 | -------------------------------------------------------------------------------- /pkgs/proxmox-backup-qemu/backup-toml.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Cargo.toml b/Cargo.toml 2 | index 62f91553..7fdfc65c 100644 3 | --- a/Cargo.toml 4 | +++ b/Cargo.toml 5 | @@ -124,7 +124,7 @@ env_logger = "0.10" 6 | flate2 = "1.0" 7 | foreign-types = "0.3" 8 | futures = "0.3" 9 | -h2 = { version = "0.4", features = [ "stream" ] } 10 | +h2 = { version = "0.3", features = [ "stream" ] } 11 | handlebars = "3.0" 12 | hex = "0.4.3" 13 | http = "0.2" 14 | -------------------------------------------------------------------------------- /pkgs/proxmox-backup-qemu/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | fetchgit, 3 | pkg-config, 4 | clang, 5 | zstd, 6 | apt, 7 | sg3_utils, 8 | libclang, 9 | openssl, 10 | libxcrypt, 11 | acl, 12 | linux-pam, 13 | libuuid, 14 | rustPlatform, 15 | git, 16 | mkRegistry, 17 | }: 18 | let 19 | sources = import ./sources.nix; 20 | registry = mkRegistry sources; 21 | in 22 | rustPlatform.buildRustPackage rec { 23 | pname = "proxmox-backup-qemu"; 24 | version = "1.5.1"; 25 | 26 | src = fetchgit { 27 | url = "git://git.proxmox.com/git/${pname}.git"; 28 | rev = "c3cbcae289d04b4454a70fc59dc58a19d5edb681"; 29 | hash = "sha256-qynY7bt+lOzpg4YxeUnRk7/xoSbtk+tWGbuNMmAdzHY="; 30 | fetchSubmodules = true; 31 | }; 32 | 33 | patches = [ ./backup-toml.patch ]; 34 | patchFlags = [ 35 | "-p1" 36 | "-d" 37 | "submodules/proxmox-backup/" 38 | ]; 39 | 40 | cargoLock.lockFile = ./Cargo.lock; 41 | 42 | postPatch = '' 43 | rm -rf .cargo 44 | cat ${registry}/cargo-patches.toml >> Cargo.toml 45 | ln -s ${./Cargo.lock} Cargo.lock 46 | ''; 47 | 48 | nativeBuildInputs = [ 49 | acl 50 | pkg-config 51 | clang 52 | zstd 53 | zstd.dev 54 | apt 55 | sg3_utils 56 | openssl 57 | sg3_utils 58 | libxcrypt 59 | acl 60 | linux-pam 61 | git 62 | ]; 63 | 64 | buildInputs = [ 65 | acl 66 | libxcrypt 67 | libuuid 68 | zstd 69 | clang 70 | zstd.dev 71 | registry 72 | git 73 | openssl 74 | ]; 75 | 76 | passthru.registry = registry; 77 | 78 | postInstall = '' 79 | cp proxmox-backup-qemu.h $out/lib 80 | cp target/*/release/libproxmox_backup_qemu.so $out/lib/libproxmox_backup_qemu.so.0 81 | ''; 82 | 83 | LIBCLANG_PATH = "${libclang.lib}/lib"; 84 | 85 | cargoTestExtraArgs = "-- --skip=test_get_current_release_codename rrd::tests::load_and_save_rrd_v2 rrd::tests::upgrade_from_rrd_v1"; 86 | } 87 | -------------------------------------------------------------------------------- /pkgs/proxmox-registry/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | fetchgit, 3 | stdenv, 4 | runCommand, 5 | writeText, 6 | lib, 7 | python3, 8 | }: 9 | sources: 10 | let 11 | workspace-remove = ( 12 | python3.withPackages (python-pkgs: [ 13 | python-pkgs.toml 14 | ]) 15 | ); 16 | 17 | processed = map ( 18 | source: 19 | let 20 | fetched = fetchgit { 21 | url = source.url; 22 | rev = source.rev; 23 | sha256 = source.sha256; 24 | }; 25 | 26 | patched = 27 | if (source ? patches && source.patches != [ ]) then 28 | stdenv.mkDerivation { 29 | name = "${source.name}-patched"; 30 | src = fetched; 31 | patches = source.patches; 32 | phases = [ 33 | "unpackPhase" 34 | "patchPhase" 35 | "installPhase" 36 | ]; 37 | installPhase = '' 38 | mkdir -p $out 39 | ${lib.concatStringsSep "\n" ( 40 | map ( 41 | crate: 42 | "${workspace-remove}/bin/python3 ${./remove_workspace_deps.py} --workspace-root . ${crate.path} -o ${crate.path}/Cargo.toml" 43 | ) source.crates 44 | )} 45 | cp -r . $out/ 46 | ''; 47 | } 48 | else 49 | stdenv.mkDerivation { 50 | name = "${source.name}-filtered"; 51 | src = fetched; 52 | phases = [ 53 | "unpackPhase" 54 | "installPhase" 55 | ]; 56 | installPhase = '' 57 | mkdir -p $out 58 | ${lib.concatStringsSep "\n" ( 59 | map ( 60 | crate: 61 | "${workspace-remove}/bin/python3 ${./remove_workspace_deps.py} --workspace-root . ${crate.path} -o ${crate.path}/Cargo.toml" 62 | ) source.crates 63 | )} 64 | cp -r . $out/ 65 | 66 | ''; 67 | }; 68 | in 69 | { 70 | inherit (source) name crates; 71 | path = patched; 72 | } 73 | ) sources; 74 | 75 | tomlEntries = lib.concatStringsSep "\n" ( 76 | lib.flatten ( 77 | map ( 78 | s: 79 | map ( 80 | crate: 81 | let 82 | fullPath = "${s.path}/${crate.path}"; 83 | in 84 | "${crate.name} = { path = \"${fullPath}\" }" 85 | ) s.crates 86 | ) processed 87 | ) 88 | ); 89 | 90 | cargoPatchesToml = writeText "cargo-patches.toml" '' 91 | 92 | 93 | [patch.crates-io] 94 | ${tomlEntries} 95 | ''; 96 | 97 | in 98 | runCommand "patched-sources" { } '' 99 | mkdir -p $out 100 | ${lib.concatStringsSep "\n" ( 101 | map (s: '' 102 | ln -s ${s.path} $out/${s.name} 103 | '') processed 104 | )} 105 | cp ${cargoPatchesToml} $out/cargo-patches.toml 106 | '' 107 | -------------------------------------------------------------------------------- /pkgs/proxmox-ve/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | buildEnv, 4 | linstor-client, 5 | pve-access-control, 6 | pve-cluster, 7 | pve-container, 8 | pve-firewall, 9 | pve-ha-manager, 10 | pve-manager, 11 | pve-qemu-server, 12 | pve-storage, 13 | termproxy, 14 | vncterm, 15 | wget, 16 | util-linux, 17 | enableLinstor ? false, 18 | }: 19 | 20 | buildEnv rec { 21 | name = "proxmox-ve-${pve-manager.version}"; 22 | 23 | paths = [ 24 | pve-access-control 25 | pve-cluster 26 | pve-container 27 | pve-firewall 28 | (pve-ha-manager.override { inherit enableLinstor; }) 29 | (pve-manager.override { inherit enableLinstor; }) 30 | pve-qemu-server 31 | (pve-storage.override { inherit enableLinstor; }) 32 | termproxy 33 | vncterm 34 | wget 35 | util-linux 36 | ] ++ lib.optionals enableLinstor [ linstor-client ]; 37 | 38 | meta = with lib; { 39 | description = "A complete, open-source server management platform for enterprise virtualization"; 40 | homepage = "https://proxmox.com/proxmox-virtual-environment/"; 41 | license = concatMap (pkg: toList pkg.meta.license) paths; 42 | maintainers = with maintainers; [ 43 | camillemndn 44 | julienmalka 45 | ]; 46 | platforms = platforms.linux; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /pkgs/proxmox-widget-toolkit/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | markedjs, 6 | nodePackages, 7 | sassc, 8 | }: 9 | 10 | stdenv.mkDerivation rec { 11 | pname = "proxmox-widget-toolkit"; 12 | version = "4.3.3"; 13 | 14 | src = fetchgit { 15 | url = "git://git.proxmox.com/git/proxmox-widget-toolkit.git"; 16 | rev = "a5fb3afcf9f9865baf379f8840d411e30f07625d"; 17 | hash = "sha256-wJe8TW5mP6g+JdmAoe4GZ6Wj3grkzgOAJhEYf2N7Gis="; 18 | }; 19 | 20 | sourceRoot = "${src.name}/src"; 21 | 22 | postPatch = '' 23 | sed -i defines.mk -e "s,/usr,," 24 | sed -i Makefile -e "/BUILD_VERSION=/d" -e "/ESLINT/d" 25 | ''; 26 | 27 | buildInputs = [ 28 | nodePackages.uglify-js 29 | sassc 30 | ]; 31 | 32 | makeFlags = [ 33 | "DESTDIR=$(out)" 34 | "MARKEDJS=${markedjs}/lib/node_modules/marked/marked.min.js" 35 | ]; 36 | 37 | postInstall = '' 38 | cp api-viewer/APIViewer.js $out/share/javascript/proxmox-widget-toolkit 39 | ''; 40 | 41 | passthru.updateScript = [ 42 | ../update.py 43 | pname 44 | "--url" 45 | src.url 46 | ]; 47 | 48 | meta = with lib; { 49 | description = ""; 50 | homepage = "git://git.proxmox.com/?p=proxmox-widget-toolkit.git"; 51 | license = with licenses; [ ]; 52 | maintainers = with maintainers; [ 53 | camillemndn 54 | julienmalka 55 | ]; 56 | platforms = platforms.linux; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /pkgs/pve-access-control/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | pve-common, 7 | authenpam, 8 | }: 9 | 10 | let 11 | perlDeps = with perl538.pkgs; [ 12 | authenpam 13 | pve-common 14 | ]; 15 | 16 | perlEnv = perl538.withPackages (_: perlDeps); 17 | in 18 | 19 | perl538.pkgs.toPerlModule ( 20 | stdenv.mkDerivation rec { 21 | pname = "pve-access-control"; 22 | version = "8.2.0"; 23 | 24 | src = fetchgit { 25 | url = "git://git.proxmox.com/git/${pname}.git"; 26 | rev = "de84a7894b61de8fce49539a853c3dd7d5154028"; 27 | hash = "sha256-jnq/VDRRN5l+D94FDGUdwEcmT8v7ZPVru3RvuWGHeP0="; 28 | }; 29 | 30 | sourceRoot = "${src.name}/src"; 31 | 32 | postPatch = '' 33 | sed -i Makefile \ 34 | -e "s/pveum.1 oathkeygen pveum.bash-completion pveum.zsh-completion/oathkeygen/" \ 35 | -e "/pveum.1/,+2d" 36 | ''; 37 | 38 | buildInputs = [ perlEnv ]; 39 | propagatedBuildInputs = perlDeps; 40 | dontPatchShebangs = true; 41 | 42 | makeFlags = [ 43 | "DESTDIR=$(out)" 44 | "PREFIX=" 45 | "SBINDIR=/.bin" 46 | "BINDIR=/.bin" 47 | "PERLDIR=/${perl538.libPrefix}/${perl538.version}" 48 | ]; 49 | 50 | passthru.updateScript = [ 51 | ../update.py 52 | pname 53 | "--url" 54 | src.url 55 | ]; 56 | 57 | meta = with lib; { 58 | description = "Proxmox VE Access control framework"; 59 | homepage = "git://git.proxmox.com/?p=pve-access-control.git"; 60 | license = licenses.agpl3Plus; 61 | maintainers = with maintainers; [ 62 | camillemndn 63 | julienmalka 64 | ]; 65 | platforms = platforms.linux; 66 | }; 67 | } 68 | ) 69 | -------------------------------------------------------------------------------- /pkgs/pve-apiclient/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | }: 7 | 8 | let 9 | perlDeps = with perl538.pkgs; [ IOSocketSSL ]; 10 | in 11 | 12 | perl538.pkgs.toPerlModule ( 13 | stdenv.mkDerivation rec { 14 | pname = "pve-apiclient"; 15 | version = "3.3.2"; 16 | 17 | src = fetchgit { 18 | url = "git://git.proxmox.com/git/${pname}.git"; 19 | rev = "94d38f0aba67ad04bf20159f605d5f7380cf7b58"; 20 | hash = "sha256-wCPCEx8SpGpcuYDV2InobN9bcBu0RUlzcpD6sgmm/Wg="; 21 | }; 22 | 23 | sourceRoot = "${src.name}/src"; 24 | 25 | makeFlags = [ 26 | "PERL5DIR=$(out)/${perl538.libPrefix}/${perl538.version}" 27 | "DOCDIR=$(out)/share/doc" 28 | ]; 29 | 30 | propagatedBuildInputs = perlDeps; 31 | 32 | passthru.updateScript = [ 33 | ../update.py 34 | pname 35 | "--url" 36 | src.url 37 | ]; 38 | 39 | meta = with lib; { 40 | description = "Perl API client library"; 41 | homepage = "git://git.proxmox.com/?p=pve-apiclient.git"; 42 | license = licenses.agpl3Plus; 43 | maintainers = with maintainers; [ 44 | camillemndn 45 | julienmalka 46 | ]; 47 | platforms = platforms.linux; 48 | }; 49 | } 50 | ) 51 | -------------------------------------------------------------------------------- /pkgs/pve-cluster/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | pve-access-control, 7 | pve-apiclient, 8 | pve-rs, 9 | bash, 10 | check, 11 | corosync, 12 | fuse, 13 | glib, 14 | gzip, 15 | libfaketime, 16 | libqb, 17 | libxcrypt, 18 | makeWrapper, 19 | openssh, 20 | openssl, 21 | pkg-config, 22 | rrdtool, 23 | sqlite, 24 | systemd, 25 | uuid, 26 | }: 27 | 28 | let 29 | perlDeps = with perl538.pkgs; [ 30 | DigestHMAC 31 | uuid 32 | (rrdtool.override { perl = perl538; }) 33 | pve-access-control 34 | pve-apiclient 35 | pve-rs 36 | ]; 37 | 38 | perlEnv = perl538.withPackages (_: perlDeps); 39 | in 40 | 41 | perl538.pkgs.toPerlModule ( 42 | stdenv.mkDerivation rec { 43 | pname = "pve-cluster"; 44 | version = "8.0.10"; 45 | 46 | src = fetchgit { 47 | url = "git://git.proxmox.com/git/${pname}.git"; 48 | rev = "3749d370ac2e1e73d2558f8dbe5d7f001651157c"; 49 | hash = "sha256-/DQ59CGlK8UDQFpnXnE8rrJ0sgtG4G5J6BpsBV2gHPg="; 50 | }; 51 | 52 | sourceRoot = "${src.name}/src"; 53 | 54 | postPatch = '' 55 | find . -type f -name Makefile | xargs sed -i "s|/usr||g" 56 | sed -i PVE/Makefile \ 57 | -e "/install -D pvecm.1/,+3d" \ 58 | -e "s/pvecm.1 pvecm.bash-completion pvecm.zsh-completion datacenter.cfg.5//" 59 | sed -i pmxcfs/Makefile \ 60 | -e "s/ pmxcfs.8//" \ 61 | -e "/CFLAGS += -std/,+3d" \ 62 | -e "s/-MMD.*//" \ 63 | -e "s/-Wl,-z,relro //" \ 64 | -e "/pmxcfs.8/d" 65 | ''; 66 | 67 | buildInputs = [ 68 | check 69 | corosync 70 | fuse 71 | glib 72 | libqb 73 | libxcrypt 74 | makeWrapper 75 | pkg-config 76 | rrdtool 77 | sqlite 78 | perlEnv 79 | ]; 80 | 81 | propagatedBuildInputs = perlDeps; 82 | 83 | makeFlags = [ 84 | "DESTDIR=$(out)" 85 | "PERL_VENDORARCH=${perl538.libPrefix}/${perl538.version}" 86 | "PVEDIR=$(out)/${perl538.libPrefix}/${perl538.version}/PVE" 87 | ]; 88 | 89 | postInstall = '' 90 | cp ${pve-access-control}/.bin/* $out/bin 91 | ''; 92 | 93 | postFixup = '' 94 | find $out/lib -type f | xargs sed -i -re "s|(/usr)?/s?bin/||" 95 | 96 | for bin in $out/bin/*; do 97 | wrapProgram $bin \ 98 | --prefix PATH : ${ 99 | lib.makeBinPath [ 100 | openssh 101 | openssl 102 | bash 103 | systemd 104 | sqlite 105 | gzip 106 | corosync 107 | libfaketime 108 | ] 109 | } \ 110 | --prefix PERL5LIB : $out/${perl538.libPrefix}/${perl538.version} 111 | done 112 | ''; 113 | 114 | passthru.updateScript = [ 115 | ../update.py 116 | pname 117 | "--url" 118 | src.url 119 | ]; 120 | 121 | meta = with lib; { 122 | description = "Proxmox VE Cluster FS and Tools"; 123 | homepage = "git://git.proxmox.com/?p=pve-cluster.git"; 124 | license = licenses.agpl3Plus; 125 | maintainers = with maintainers; [ 126 | camillemndn 127 | julienmalka 128 | ]; 129 | platforms = platforms.linux; 130 | }; 131 | } 132 | ) 133 | -------------------------------------------------------------------------------- /pkgs/pve-common/0001-ss_fix_path.patch: -------------------------------------------------------------------------------- 1 | diff --git a/PVE/Tools.pm b/src/PVE/Tools.pm 2 | index 9ffac12..639b178 100644 3 | --- a/PVE/Tools.pm 4 | +++ b/PVE/Tools.pm 5 | @@ -851,7 +851,7 @@ sub wait_for_vnc_port { 6 | my $starttime = [gettimeofday]; 7 | my $elapsed; 8 | 9 | - my $cmd = ['/bin/ss', '-Htln', "sport = :$port"]; 10 | + my $cmd = ['@sspath@/bin/ss', '-Htln', "sport = :$port"]; 11 | push @$cmd, $family == AF_INET6 ? '-6' : '-4' if defined($family); 12 | 13 | my $found; 14 | -------------------------------------------------------------------------------- /pkgs/pve-common/0002-mknod-mknodat.patch: -------------------------------------------------------------------------------- 1 | diff --git a/PVE/Syscall.pm b/PVE/Syscall.pm 2 | index 9ef3d5d..dca8b4f 100644 3 | --- a/PVE/Syscall.pm 4 | +++ b/PVE/Syscall.pm 5 | @@ -16,7 +16,7 @@ BEGIN { 6 | openat => &SYS_openat, 7 | close => &SYS_close, 8 | mkdirat => &SYS_mkdirat, 9 | - mknod => &SYS_mknod, 10 | + mknodat => &SYS_mknodat, 11 | faccessat => &SYS_faccessat, 12 | setresuid => &SYS_setresuid, 13 | fchownat => &SYS_fchownat, 14 | diff --git a/PVE/Tools.pm b/PVE/Tools.pm 15 | index 766c809..643a05d 100644 16 | --- a/PVE/Tools.pm 17 | +++ b/PVE/Tools.pm 18 | @@ -1753,7 +1753,7 @@ sub mkdirat($$$) { 19 | 20 | sub mknod($$$) { 21 | my ($filename, $mode, $dev) = @_; 22 | - return syscall(PVE::Syscall::SYS_mknod, $filename, int($mode), int($dev)) == 0; 23 | + return syscall(PVE::Syscall::SYS_mknodat, 'AT_FDCWD', $filename, int($mode), int($dev)) == 0; 24 | } 25 | 26 | sub fchownat($$$$$) { 27 | -------------------------------------------------------------------------------- /pkgs/pve-common/0003-pci-id-path.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/PVE/SysFSTools.pm b/src/PVE/SysFSTools.pm 2 | index 57f0ac8..13d0bdf 100644 3 | --- a/PVE/SysFSTools.pm 4 | +++ b/PVE/SysFSTools.pm 5 | @@ -14,7 +14,7 @@ my $pciregex = "($domainregex):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])"; 6 | my $parse_pci_ids = sub { 7 | my $ids = {}; 8 | 9 | - open(my $fh, '<', "/usr/share/misc/pci.ids") 10 | + open(my $fh, '<', "@pciutils@/share/pci.ids") 11 | or return $ids; 12 | 13 | my $curvendor; 14 | -------------------------------------------------------------------------------- /pkgs/pve-common/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | bash, 6 | coreutils, 7 | diffutils, 8 | iproute2, 9 | perl538, 10 | glibc, 11 | openvswitch, 12 | pciutils, 13 | proxmox-backup-client, 14 | systemd, 15 | tzdata, 16 | usbutils, 17 | mimebase32, 18 | mimebase64, 19 | replaceVars, 20 | }: 21 | 22 | let 23 | perlDeps = with perl538.pkgs; [ 24 | AnyEvent 25 | Carp 26 | Clone 27 | CryptOpenSSLRSA 28 | CryptOpenSSLRandom 29 | PathTools 30 | DataDumper 31 | TimeDate 32 | DevelCycle 33 | #DigestMD5 34 | DigestSHA 35 | Encode 36 | EncodeLocale 37 | #Exporter 38 | FilePath 39 | #FileTemp 40 | FilesysDf 41 | GetoptLong 42 | HTTPMessage 43 | IOStringy 44 | IO 45 | IOSocketIP 46 | JSON 47 | #libwwwperl 48 | LinuxInotify2 49 | LWPProtocolHttps 50 | ScalarListUtils 51 | mimebase32 52 | mimebase64 53 | NetDBus 54 | NetIP 55 | perlldap 56 | NetSSLeay 57 | NetAddrIP 58 | Socket 59 | #Storable 60 | StringShellQuote 61 | SysSyslog 62 | TextParsewords 63 | #TextTabsWrap 64 | TimeHiRes 65 | TimeLocal 66 | URI 67 | YAMLLibYAML 68 | ]; 69 | in 70 | 71 | perl538.pkgs.toPerlModule ( 72 | stdenv.mkDerivation rec { 73 | pname = "pve-common"; 74 | version = "8.2.1"; 75 | 76 | src = fetchgit { 77 | url = "git://git.proxmox.com/git/${pname}.git"; 78 | rev = "1a6005ad2377b6586e084b3840ac622752b666b8"; 79 | hash = "sha256-fMgkeaOoaJDk9yf3O4uZSTs0p7H4uUYyy1Ii3J02uNw="; 80 | }; 81 | 82 | sourceRoot = "${src.name}/src"; 83 | 84 | patches = [ 85 | (replaceVars ./0001-ss_fix_path.patch { 86 | sspath = "${iproute2}/bin/"; 87 | }) 88 | 89 | ./0002-mknod-mknodat.patch 90 | 91 | (replaceVars ./0003-pci-id-path.patch { 92 | pciutils = "${pciutils}"; 93 | }) 94 | ]; 95 | 96 | propagatedBuildInputs = [ 97 | bash 98 | coreutils 99 | diffutils 100 | iproute2 101 | openvswitch 102 | proxmox-backup-client 103 | systemd 104 | usbutils 105 | ] ++ perlDeps; 106 | 107 | makeFlags = [ 108 | "PREFIX=$(out)" 109 | "PERLDIR=$(out)/${perl538.libPrefix}/${perl538.version}" 110 | ]; 111 | 112 | postInstall = 113 | let 114 | includeHeaders = 115 | "{sys,bits,}/syscall.h " 116 | + ( 117 | if (stdenv.buildPlatform.system == "x86_64-linux") then 118 | "asm/unistd{,_64}.h" 119 | else 120 | "asm{,-generic}/{unistd,bitsperlong}.h" 121 | ); 122 | in 123 | '' 124 | for h in ${includeHeaders}; do 125 | ${perl538}/bin/h2ph -d $out ${glibc.dev}/include/$h 126 | mkdir -p $out/include/$(dirname $h) 127 | mv $out${glibc.dev}/include/''${h%.h}.ph $out/include/$(dirname $h) 128 | done 129 | mv $out/_h2ph_pre.ph $out/include 130 | cp -r $out/include/* $out/${perl538.libPrefix}/${perl538.version} 131 | rm -r $out/{nix,include} 132 | ''; 133 | 134 | postFixup = '' 135 | find $out/lib -type f | xargs sed -i \ 136 | -e "/ENV{'PATH'}/d" \ 137 | -e "s|/usr/share/zoneinfo|${tzdata}/share/zoneinfo|" \ 138 | -Ee "s|(/usr)?/s?bin/||" 139 | ''; 140 | 141 | passthru.updateScript = [ 142 | ../update.py 143 | pname 144 | "--url" 145 | src.url 146 | ]; 147 | 148 | meta = with lib; { 149 | description = "Proxmox Project's Common Perl Code"; 150 | homepage = "git://git.proxmox.com/?p=pve-common.git"; 151 | license = licenses.agpl3Plus; 152 | maintainers = with maintainers; [ 153 | camillemndn 154 | julienmalka 155 | ]; 156 | platforms = platforms.linux; 157 | }; 158 | } 159 | ) 160 | -------------------------------------------------------------------------------- /pkgs/pve-container/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | dtach, 7 | lxc, 8 | openssh, 9 | tzdata, 10 | }: 11 | 12 | let 13 | perlDeps = [ ]; 14 | perlEnv = perl538.withPackages (_: perlDeps); 15 | in 16 | 17 | perl538.pkgs.toPerlModule ( 18 | stdenv.mkDerivation rec { 19 | pname = "pve-container"; 20 | version = "5.2.6"; 21 | 22 | src = fetchgit { 23 | url = "git://git.proxmox.com/git/${pname}.git"; 24 | rev = "a0a7cec91c6f57c4ca3b6317ff12a15d2c528177"; 25 | hash = "sha256-n0LR/DCziTYX7hvyptcyoKoZ9GtLncczLUXYeo4pZjQ="; 26 | }; 27 | 28 | sourceRoot = "${src.name}/src"; 29 | 30 | postPatch = '' 31 | sed -i Makefile \ 32 | -e "s/pct.1 pct.conf.5 pct.bash-completion pct.zsh-completion //" \ 33 | -e "s,/usr/share/lxc,$NIX_BUILD_TOP/lxc," \ 34 | -e "/pve-doc-generator/d" \ 35 | -e "/PVE_GENERATING_DOCS/d" \ 36 | -e "/SERVICEDIR/d" \ 37 | -e "/BASHCOMPLDIR/d" \ 38 | -e "/ZSHCOMPLDIR/d" \ 39 | -e "/MAN1DIR/d" \ 40 | -e "/MAN5DIR/d" 41 | ''; 42 | 43 | buildInputs = [ perlEnv ]; 44 | propagatedBuildInputs = perlDeps; 45 | dontPatchShebangs = true; 46 | 47 | postConfigure = '' 48 | cp -r ${lxc}/share/lxc $NIX_BUILD_TOP/ 49 | chmod -R +w $NIX_BUILD_TOP/lxc 50 | ''; 51 | 52 | makeFlags = [ 53 | "DESTDIR=$(out)" 54 | "PREFIX=$(out)" 55 | "SBINDIR=$(out)/.bin" 56 | "PERLDIR=$(out)/${perl538.libPrefix}/${perl538.version}" 57 | ]; 58 | 59 | postFixup = '' 60 | find $out -type f | xargs sed -i \ 61 | -e "s|/usr/bin/dtach|${dtach}/bin/dtach|" \ 62 | -e "s|/usr/bin/ssh|${openssh}/bin/ssh|" \ 63 | -e "s|/usr/bin/vncterm||" \ 64 | -e "s|/usr/bin/termproxy||" \ 65 | -e "s|/usr/bin/lxc|${lxc}/bin/lxc|" \ 66 | -e "s|/usr/share/lxc|$out/share/lxc|" \ 67 | -e "s|/usr/share/zoneinfo|${tzdata}/share/zoneinfo|" 68 | ''; 69 | 70 | passthru.updateScript = [ 71 | ../update.py 72 | pname 73 | "--url" 74 | src.url 75 | ]; 76 | 77 | meta = with lib; { 78 | description = "Proxmox VE container manager & runtime"; 79 | homepage = "git://git.proxmox.com/?p=pve-container.git"; 80 | license = licenses.agpl3Plus; 81 | maintainers = with maintainers; [ 82 | camillemndn 83 | julienmalka 84 | ]; 85 | platforms = platforms.linux; 86 | }; 87 | } 88 | ) 89 | -------------------------------------------------------------------------------- /pkgs/pve-docs/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | proxmox-widget-toolkit, 7 | asciidoc, 8 | librsvg, 9 | }: 10 | 11 | let 12 | perlDeps = with perl538.pkgs; [ JSON ]; 13 | 14 | perlEnv = perl538.withPackages (_: perlDeps); 15 | in 16 | 17 | stdenv.mkDerivation rec { 18 | pname = "pve-docs"; 19 | version = "8.3.1"; 20 | 21 | src = fetchgit { 22 | url = "git://git.proxmox.com/git/${pname}.git"; 23 | rev = "a89cb75f36a1c3a5c7ba7d9ca113ee5af7a88e17"; 24 | hash = "sha256-9vgGDgRXKC9cIVhNOf9RLgCMVqf4lC9Ik97/18zLXys="; 25 | }; 26 | 27 | postPatch = '' 28 | patchShebangs scan-adoc-refs 29 | sed -i Makefile \ 30 | -e '/GITVERSION/d' \ 31 | -e '/pkg-info/d' \ 32 | -e "s|/usr/share/javascript/proxmox-widget-toolkit-dev|${proxmox-widget-toolkit}/share/javascript/proxmox-widget-toolkit|" \ 33 | -e 's|/usr||' \ 34 | -e "s/gen-install doc-install mediawiki-install/gen-install mediawiki-install/" \ 35 | -e 's|\./asciidoc-pve|$out/bin/asciidoc-pve|' 36 | #find . -type f | xargs sed -i -e "s|/usr|$out|" 37 | ''; 38 | 39 | buildInputs = [ 40 | asciidoc 41 | librsvg 42 | perlEnv 43 | ]; 44 | propagatedBuildInputs = perlDeps; 45 | 46 | makeFlags = [ 47 | "GITVERSION=${src.rev}" 48 | "INDEX_INCLUDES=" 49 | "DESTDIR=$(out)" 50 | ]; 51 | 52 | passthru.updateScript = [ 53 | ../update.py 54 | pname 55 | "--url" 56 | src.url 57 | ]; 58 | 59 | meta = with lib; { 60 | description = "Proxmox VE Documentation"; 61 | homepage = "git://git.proxmox.com/?p=pve-docs.git"; 62 | license = licenses.agpl3Plus; 63 | maintainers = with maintainers; [ 64 | camillemndn 65 | julienmalka 66 | ]; 67 | platforms = platforms.linux; 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /pkgs/pve-edk2-firmware/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | python3, 4 | pkgs, 5 | pkgsCross, 6 | stdenv, 7 | fetchgit, 8 | writeShellScriptBin, 9 | ... 10 | }: 11 | 12 | stdenv.mkDerivation rec { 13 | pname = "pve-edk2-firmware"; 14 | version = "4.2025.02-3"; 15 | 16 | src = fetchgit { 17 | url = "git://git.proxmox.com/git/${pname}.git"; 18 | rev = "d6146dd6dfc084215dfaa59b95bcf6177e988cb5"; 19 | sha256 = "sha256-6zh9nTdR5+1zZODJ1JBtWkJyo+ioeZoxk7yWtmLBekc="; 20 | 21 | # FIXME: remove manual fetch submodule if 22 | # https://git.proxmox.com/?p=mirror_edk2.git is accessible again 23 | fetchSubmodules = false; 24 | leaveDotGit = true; 25 | 26 | postFetch = '' 27 | pushd $out 28 | git reset 29 | 30 | # Switch to official edk2 git repo 31 | substituteInPlace ./.gitmodules \ 32 | --replace-fail 'url = ../mirror_edk2' 'url = https://github.com/tianocore/edk2.git' 33 | 34 | git submodule update --init --recursive -j ''${NIX_BUILD_CORES:-1} --depth 1 35 | 36 | # Remove .git dirs 37 | find . -name .git -type f -exec rm -rf {} + 38 | rm -rf .git/ 39 | popd 40 | ''; 41 | }; 42 | 43 | buildInputs = [ ]; 44 | 45 | hardeningDisable = [ 46 | "format" 47 | "fortify" 48 | "trivialautovarinit" 49 | ]; 50 | 51 | nativeBuildInputs = with pkgs; [ 52 | dpkg 53 | fakeroot 54 | qemu 55 | bc 56 | dosfstools 57 | acpica-tools 58 | mtools 59 | nasm 60 | libuuid 61 | qemu-utils 62 | libisoburn 63 | python3 64 | # Mock debhelper 65 | (writeShellScriptBin "dh" "true") 66 | ] ++ (lib.optional (stdenv.hostPlatform.system != "aarch64-linux") pkgsCross.aarch64-multiplatform.stdenv.cc) 67 | ++ (lib.optional (stdenv.hostPlatform.system != "x86_64-linux") pkgsCross.gnu64.stdenv.cc) 68 | ++ (lib.optional (stdenv.hostPlatform.system != "riscv64-linux") pkgsCross.riscv64.stdenv.cc); 69 | 70 | depsBuildBuild = [ stdenv.cc ]; 71 | 72 | postPatch = 73 | let 74 | pythonPath = python3.pkgs.makePythonPath (with python3.pkgs; [ pexpect ]); 75 | in 76 | '' 77 | patchShebangs . 78 | substituteInPlace ./debian/rules \ 79 | --replace-warn /bin/bash ${pkgs.bash}/bin/bash 80 | substituteInPlace ./Makefile ./debian/rules \ 81 | --replace-warn /usr/share/dpkg ${pkgs.dpkg}/share/dpkg 82 | substituteInPlace ./debian/rules \ 83 | --replace-warn 'PYTHONPATH=$(CURDIR)/debian/python' 'PYTHONPATH=$(CURDIR)/debian/python:${pythonPath}' 84 | 85 | # Patch cross compiler paths 86 | substituteInPlace ./debian/rules ./**/CMakeLists.txt \ 87 | --replace-warn 'aarch64-linux-gnu-' '${pkgsCross.aarch64-multiplatform.stdenv.cc.targetPrefix}' 88 | substituteInPlace ./debian/rules ./**/CMakeLists.txt \ 89 | --replace-warn 'riscv64-linux-gnu-' '${pkgsCross.riscv64.stdenv.cc.targetPrefix}' 90 | sed -i '/^EDK2_TOOLCHAIN *=/a export $(EDK2_TOOLCHAIN)_BIN=${pkgsCross.gnu64.stdenv.cc.targetPrefix}' ./debian/rules 91 | ''; 92 | 93 | buildPhase = '' 94 | mv ./debian ./edk2 95 | pushd ./edk2 96 | make -f ./debian/rules override_dh_auto_build 97 | ''; 98 | 99 | installPhase = '' 100 | # Copy files as mentioned in *.install files 101 | for f in ./debian/*.install; do 102 | while IFS= read -r line; do 103 | read -ra paths <<< "$line" 104 | dest="$out/''${paths[-1]}" 105 | mkdir -p "$dest" 106 | for src in "''${paths[@]::''${#paths[@]}-1}"; do 107 | cp $src "$dest" 108 | done 109 | done < "$f" 110 | done 111 | 112 | # Create symlinks as mentioned in *.links files 113 | for f in ./debian/*.links; do 114 | while IFS= read -r line; do 115 | read -ra paths <<< "$line" 116 | dest="$out/''${paths[-1]}" 117 | for src in "''${paths[@]::''${#paths[@]}-1}"; do 118 | ln -s "$out/$src" "$dest" 119 | done 120 | done < "$f" 121 | done 122 | ''; 123 | 124 | passthru.updateScript = [ 125 | ../update.py 126 | pname 127 | "--url" 128 | src.url 129 | ]; 130 | 131 | meta = { 132 | description = "edk2 based UEFI firmware modules for virtual machines"; 133 | homepage = "git://git.proxmox.com/git/${pname}.git"; 134 | maintainers = with lib.maintainers; [ codgician julienmalka ]; 135 | }; 136 | } 137 | -------------------------------------------------------------------------------- /pkgs/pve-firewall/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | makeWrapper, 6 | perl538, 7 | pve-cluster, 8 | glib, 9 | ipset, 10 | iptables, 11 | libnetfilter_conntrack, 12 | libnetfilter_log, 13 | libnfnetlink, 14 | pkg-config, 15 | }: 16 | 17 | let 18 | perlDeps = [ pve-cluster ]; 19 | perlEnv = perl538.withPackages (_: perlDeps); 20 | in 21 | 22 | perl538.pkgs.toPerlModule ( 23 | stdenv.mkDerivation rec { 24 | pname = "pve-firewall"; 25 | version = "5.0.7"; 26 | 27 | src = fetchgit { 28 | url = "git://git.proxmox.com/git/${pname}.git"; 29 | rev = "4339ef1526fd482f800438fbdeec2f6b50133be2"; 30 | hash = "sha256-bAbObcdrxTY6VVwpP3fH8+7TBudlViQHNTVPjZdm8c8="; 31 | }; 32 | 33 | sourceRoot = "${src.name}/src"; 34 | 35 | postPatch = '' 36 | sed -i Makefile \ 37 | -e "s/pve-firewall.8 pve-firewall.bash-completion pve-firewall.zsh-completion//" \ 38 | -e "/install -m 0644 pve-firewall.8/,+4d" \ 39 | -e "s/pve-firewall.8//" \ 40 | -e "/dpkg-buildflags/d" 41 | ''; 42 | 43 | buildInputs = [ 44 | glib 45 | libnetfilter_conntrack 46 | libnetfilter_log 47 | libnfnetlink 48 | pkg-config 49 | perlEnv 50 | makeWrapper 51 | ]; 52 | 53 | makeFlags = [ 54 | "DESTDIR=$(out)" 55 | "PREFIX=" 56 | "SBINDIR=$(out)/bin" 57 | "PERLDIR=$(out)/${perl538.libPrefix}/${perl538.version}" 58 | ]; 59 | 60 | postFixup = '' 61 | wrapProgram $out/bin/pve-firewall \ 62 | --prefix PATH : ${ 63 | lib.makeBinPath [ 64 | ipset 65 | iptables 66 | ] 67 | } \ 68 | --prefix PERL5LIB : $out/${perl538.libPrefix}/${perl538.version} 69 | ''; 70 | 71 | passthru.updateScript = [ 72 | ../update.py 73 | pname 74 | "--url" 75 | src.url 76 | ]; 77 | 78 | meta = with lib; { 79 | description = "Firewall test scripts"; 80 | homepage = "git://git.proxmox.com/?p=pve-firewall.git"; 81 | license = with licenses; [ ]; 82 | maintainers = with maintainers; [ 83 | camillemndn 84 | julienmalka 85 | ]; 86 | platforms = platforms.linux; 87 | }; 88 | } 89 | ) 90 | -------------------------------------------------------------------------------- /pkgs/pve-guest-common/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | }: 7 | 8 | perl538.pkgs.toPerlModule ( 9 | stdenv.mkDerivation rec { 10 | pname = "pve-guest-common"; 11 | version = "5.1.6"; 12 | 13 | src = fetchgit { 14 | url = "git://git.proxmox.com/git/${pname}.git"; 15 | rev = "4c2dd7c226ee3268bc144bbb9b639637f0981ff2"; 16 | hash = "sha256-NbJBKb4az62esyb8D3iMw+3I5U+XnfEyaK0XQxu5hv8="; 17 | }; 18 | 19 | sourceRoot = "${src.name}/src"; 20 | 21 | makeFlags = [ 22 | "PERL5DIR=$(out)/${perl538.libPrefix}/${perl538.version}" 23 | "DOCDIR=$(out)/share/doc/${pname}" 24 | ]; 25 | 26 | passthru.updateScript = [ 27 | ../update.py 28 | pname 29 | "--url" 30 | src.url 31 | ]; 32 | 33 | meta = with lib; { 34 | description = "Proxmox VE guest-related modules"; 35 | homepage = "git://git.proxmox.com/?p=pve-guest-common.git"; 36 | license = with licenses; [ ]; 37 | maintainers = with maintainers; [ 38 | camillemndn 39 | julienmalka 40 | ]; 41 | platforms = platforms.linux; 42 | }; 43 | } 44 | ) 45 | -------------------------------------------------------------------------------- /pkgs/pve-ha-manager/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | makeWrapper, 6 | perl538, 7 | pve-container, 8 | pve-firewall, 9 | pve-guest-common, 10 | pve-qemu-server, 11 | pve-storage, 12 | pve-qemu, 13 | enableLinstor ? false, 14 | }: 15 | 16 | let 17 | perlDeps = [ 18 | pve-container 19 | pve-firewall 20 | pve-guest-common 21 | pve-qemu-server 22 | (pve-storage.override { inherit enableLinstor; }) 23 | ]; 24 | perlEnv = perl538.withPackages (_: perlDeps); 25 | in 26 | 27 | perl538.pkgs.toPerlModule ( 28 | stdenv.mkDerivation rec { 29 | pname = "pve-ha-manager"; 30 | version = "4.0.7"; 31 | 32 | src = fetchgit { 33 | url = "git://git.proxmox.com/git/${pname}.git"; 34 | rev = "53d8e4892147a063c215bdd9b0c1224d14dad898"; 35 | hash = "sha256-n/Lj12k2h81ZPNYKaiVJ2U3H+TPs/ijwqF8IwJP4Q2o="; 36 | }; 37 | 38 | sourceRoot = "${src.name}/src"; 39 | 40 | postPatch = '' 41 | sed -i Makefile \ 42 | -e "s/ha-manager.1 pve-ha-crm.8 pve-ha-lrm.8 ha-manager.bash-completion pve-ha-lrm.bash-completion //" \ 43 | -e "s/pve-ha-crm.bash-completion ha-manager.zsh-completion pve-ha-lrm.zsh-completion pve-ha-crm.zsh-completion //" \ 44 | -e "/install -m 0644 -D pve-ha-crm.bash-completion/,+5d" \ 45 | -e "/install -m 0644 pve-ha-crm.8/,+6d" \ 46 | -e "s/Werror/Wno-error/" \ 47 | -e "/PVE_GENERATING_DOCS/d" \ 48 | -e "/shell /d" 49 | ''; 50 | 51 | makeFlags = [ 52 | "DESTDIR=$(out)" 53 | "PREFIX=" 54 | "SBINDIR=/bin" 55 | "PERLDIR=/${perl538.libPrefix}/${perl538.version}" 56 | ]; 57 | 58 | buildInputs = [ 59 | perlEnv 60 | makeWrapper 61 | ]; 62 | propagatedBuildInputs = perlDeps; 63 | 64 | postInstall = '' 65 | cp ${pve-container}/.bin/pct $out/bin 66 | cp ${pve-qemu-server}/.bin/* $out/bin 67 | rm $out/bin/pve-ha-simulator 68 | ''; 69 | 70 | postFixup = '' 71 | for bin in $out/bin/*; do 72 | wrapProgram $bin \ 73 | --prefix PATH : ${lib.makeBinPath [ pve-qemu ]} \ 74 | --prefix PERL5LIB : $out/${perl538.libPrefix}/${perl538.version} 75 | done 76 | ''; 77 | 78 | passthru.updateScript = [ 79 | ../update.py 80 | pname 81 | "--url" 82 | src.url 83 | ]; 84 | 85 | meta = with lib; { 86 | description = "Proxmox VE High Availabillity Manager"; 87 | homepage = "git://git.proxmox.com/?p=pve-ha-manager.git"; 88 | license = with licenses; [ ]; 89 | maintainers = with maintainers; [ 90 | camillemndn 91 | julienmalka 92 | ]; 93 | platforms = platforms.linux; 94 | }; 95 | } 96 | ) 97 | -------------------------------------------------------------------------------- /pkgs/pve-http-server/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | proxmox-widget-toolkit, 7 | extjs, 8 | font-awesome_4, 9 | fonts-font-logos, 10 | sencha-touch, 11 | }: 12 | 13 | let 14 | perlDeps = with perl538.pkgs; [ AnyEventHTTP ]; 15 | fonts-font-awesome = font-awesome_4.overrideAttrs ( 16 | _: _: { 17 | installPhase = '' 18 | mkdir -p $out/share/fonts-font-awesome 19 | cp -r css $out/share/fonts-font-awesome 20 | cp -r fonts $out/share/fonts-font-awesome 21 | cp -r less $out/share/fonts-font-awesome 22 | ''; 23 | } 24 | ); 25 | in 26 | 27 | perl538.pkgs.toPerlModule ( 28 | stdenv.mkDerivation rec { 29 | pname = "pve-http-server"; 30 | version = "5.2.2"; 31 | 32 | src = fetchgit { 33 | url = "git://git.proxmox.com/git/${pname}.git"; 34 | rev = "444a9e19f616b49b02238c76d3e5530a9fa27383"; 35 | hash = "sha256-RxUNSva6yyrNbPZFA4q7ndse6HZnLy8eDZ6//skxfJg="; 36 | }; 37 | 38 | sourceRoot = "${src.name}/src"; 39 | propagatedBuildInputs = perlDeps; 40 | makeFlags = [ "PERL5DIR=$(out)/${perl538.libPrefix}/${perl538.version}" ]; 41 | 42 | postFixup = '' 43 | find $out -type f | xargs sed -i \ 44 | -e "s|/usr/share/javascript|$out/share/javascript|" 45 | mkdir -p $out/share/javascript 46 | ln -s ${proxmox-widget-toolkit}/share/javascript/proxmox-widget-toolkit $out/share/javascript 47 | ln -s ${extjs}/share/javascript/extjs $out/share/javascript 48 | ln -s ${sencha-touch}/share/javascript/sencha-touch $out/share/javascript 49 | ln -s ${fonts-font-awesome}/share/fonts-font-awesome $out/share 50 | ln -s ${fonts-font-logos}/share/fonts-font-logos $out/share 51 | ''; 52 | 53 | passthru.updateScript = [ 54 | ../update.py 55 | pname 56 | "--url" 57 | src.url 58 | ]; 59 | 60 | meta = with lib; { 61 | description = "Proxmox VE HTTP Server"; 62 | homepage = "git://git.proxmox.com/?p=pve-http-server.git"; 63 | license = with licenses; [ ]; 64 | maintainers = with maintainers; [ 65 | camillemndn 66 | julienmalka 67 | ]; 68 | platforms = platforms.linux; 69 | }; 70 | } 71 | ) 72 | -------------------------------------------------------------------------------- /pkgs/pve-manager/0001-no-apt-update.patch: -------------------------------------------------------------------------------- 1 | diff --git a/www/manager6/node/Config.js b/www/manager6/node/Config.js 2 | index d27592ce..34c52a5d 100644 3 | --- a/www/manager6/node/Config.js 4 | +++ b/www/manager6/node/Config.js 5 | @@ -253,33 +253,6 @@ Ext.define('PVE.node.Config', { 6 | }); 7 | 8 | if (caps.nodes['Sys.Modify']) { 9 | - me.items.push({ 10 | - xtype: 'proxmoxNodeAPT', 11 | - title: gettext('Updates'), 12 | - iconCls: 'fa fa-refresh', 13 | - expandedOnInit: true, 14 | - disabled: !caps.nodes['Sys.Console'], 15 | - // do we want to link to system updates instead? 16 | - itemId: 'apt', 17 | - upgradeBtn: { 18 | - xtype: 'pveConsoleButton', 19 | - disabled: Proxmox.UserName !== 'root@pam', 20 | - text: gettext('Upgrade'), 21 | - consoleType: 'upgrade', 22 | - nodename: nodename, 23 | - }, 24 | - nodename: nodename, 25 | - }); 26 | - 27 | - me.items.push({ 28 | - xtype: 'proxmoxNodeAPTRepositories', 29 | - title: gettext('Repositories'), 30 | - iconCls: 'fa fa-files-o', 31 | - itemId: 'aptrepositories', 32 | - nodename: nodename, 33 | - onlineHelp: 'sysadmin_package_repositories', 34 | - groups: ['apt'], 35 | - }); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /pkgs/pve-manager/0002-no-repo-status.patch: -------------------------------------------------------------------------------- 1 | diff --git a/www/manager6/node/StatusView.js b/www/manager6/node/StatusView.js 2 | index 0ac200c7..7b64bab9 100644 3 | --- a/www/manager6/node/StatusView.js 4 | +++ b/www/manager6/node/StatusView.js 5 | @@ -156,13 +156,6 @@ Ext.define('PVE.node.StatusView', { 6 | nodetab: "aptrepositories", 7 | }); 8 | 9 | - me.items.push({ 10 | - xtype: 'pmxNodeInfoRepoStatus', 11 | - itemId: 'repositoryStatus', 12 | - product: 'Proxmox VE', 13 | - repoLink: `#${repoLink}`, 14 | - }); 15 | - 16 | me.callParent(); 17 | }, 18 | }); 19 | diff --git a/www/manager6/node/Summary.js b/www/manager6/node/Summary.js 20 | index c2dca0df..d2cac94e 100644 21 | --- a/www/manager6/node/Summary.js 22 | +++ b/www/manager6/node/Summary.js 23 | @@ -207,8 +207,6 @@ Ext.define('PVE.node.Summary', { 24 | }, 25 | }); 26 | 27 | - me.updateRepositoryStatus(); 28 | - 29 | me.callParent(); 30 | 31 | let sp = Ext.state.Manager.getProvider(); 32 | -------------------------------------------------------------------------------- /pkgs/pve-manager/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | makeWrapper, 6 | perl538, 7 | proxmox-widget-toolkit, 8 | proxmox-acme, 9 | pve-docs, 10 | pve-ha-manager, 11 | pve-http-server, 12 | cdrkit, 13 | enableLinstor ? false, 14 | ceph, 15 | gnupg, 16 | graphviz, 17 | gzip, 18 | nodePackages, 19 | openvswitch, 20 | openssh, 21 | pve-qemu, 22 | tzdata, 23 | pve-novnc, 24 | pve-xtermjs, 25 | iproute2, 26 | termproxy, 27 | shadow, 28 | sqlite, 29 | wget, 30 | bash, 31 | zstd, 32 | util-linux, 33 | system-sendmail, 34 | rsync, 35 | busybox, 36 | cstream, 37 | lvm2, 38 | lxc, 39 | libfaketime, 40 | corosync, 41 | openssl, 42 | systemd, 43 | }: 44 | 45 | let 46 | perlDeps = with perl538.pkgs; [ 47 | CryptOpenSSLBignum 48 | FileReadBackwards 49 | NetDNS 50 | PodParser 51 | TemplateToolkit 52 | proxmox-acme 53 | (pve-ha-manager.override { inherit enableLinstor; }) 54 | pve-http-server 55 | ]; 56 | 57 | perlEnv = perl538.withPackages (_: perlDeps); 58 | in 59 | 60 | perl538.pkgs.toPerlModule ( 61 | stdenv.mkDerivation rec { 62 | pname = "pve-manager"; 63 | version = "8.2.4"; 64 | 65 | src = fetchgit { 66 | url = "git://git.proxmox.com/git/${pname}.git"; 67 | rev = "faa83925c96413258b9a02c4de89442adeff9215"; 68 | hash = "sha256-onNnxvQ7YrdnrFpl+z7Z+xUyEZsMcU6Qxn/kjYLan+8="; 69 | }; 70 | 71 | patches = [ 72 | ./0001-no-apt-update.patch 73 | ./0002-no-repo-status.patch 74 | ]; 75 | 76 | postPatch = '' 77 | sed -i {defines.mk,configs/Makefile} -e "s,/usr,," 78 | sed -i Makefile \ 79 | -e '/GITVERSION/d' \ 80 | -e "/default.mk/d" \ 81 | -e '/pkg-info/d' \ 82 | -e '/log/d' \ 83 | -e '/architecture/d' \ 84 | -e 's/aplinfo PVE bin www services configs network-hooks test/PVE bin www configs test/' 85 | sed -i bin/Makefile -e '/pod2man/,+1d' -e '/install -d \$(MAN1DIR)/,+7d' 86 | patchShebangs configs/country.pl 87 | sed -i configs/country.pl -e "s|/usr|${tzdata}|" 88 | #cp PVE/pvecfg.pm{.in,} 89 | sed -i www/manager6/Makefile -e "/ESLINT/d" -e "s|/usr/bin/asciidoc-pve|${pve-docs}/bin/asciidoc-pve|" 90 | ''; 91 | 92 | buildInputs = [ 93 | perlEnv 94 | nodePackages.eslint 95 | graphviz 96 | makeWrapper 97 | ]; 98 | propagatedBuildInputs = perlDeps; 99 | 100 | makeFlags = [ 101 | "DESTDIR=$(out)" 102 | "PVERELEASE=8.0" 103 | "VERSION=${version}" 104 | "REPOID=nixos" 105 | "PERLLIBDIR=$(out)/${perl538.libPrefix}/${perl538.version}" 106 | "WIDGETKIT=${proxmox-widget-toolkit}/share/javascript/proxmox-widget-toolkit/proxmoxlib.js" 107 | "BASH_COMPLETIONS=" 108 | "ZSH_COMPLETIONS=" 109 | "CLI_MANS=" 110 | "SERVICE_MANS=" 111 | ]; 112 | 113 | postInstall = '' 114 | rm -r $out/var $out/bin/pve{upgrade,update,version,7to8} 115 | sed -i $out/{bin/*,share/pve-manager/helpers/pve-startall-delay} -e "s/-T//" 116 | ''; 117 | 118 | postFixup = '' 119 | find $out/lib -type f | xargs sed -i \ 120 | -e "/API2::APT/d" \ 121 | -e "/ENV{'PATH'}/d" \ 122 | -e "s|/usr/share/javascript|${pve-http-server}/share/javascript|" \ 123 | -e "s|/usr/share/fonts-font-awesome|${pve-http-server}/share/fonts-font-awesome|" \ 124 | -e "s|/usr/share/pve-manager|$out/share/pve-manager|" \ 125 | -e "s|/usr/share/zoneinfo|${tzdata}/share/zoneinfo|" \ 126 | -e "s|/usr/share/pve-xtermjs|${pve-xtermjs}/share/pve-xtermjs|" \ 127 | -Ee "s|(/usr)?/s?bin/||" \ 128 | -e "s|/usr/share/novnc-pve|${pve-novnc}/share/webapps/novnc|" \ 129 | -e "s/Ceph Nautilus required/Ceph Nautilus required - PATH: \$ENV{PATH}\\\n/" \ 130 | -e "s|/usr/share/perl5/\\\$plug|/run/current-system/sw/${perl538.libPrefix}/${perl538.version}/\$plug|" 131 | 132 | # Ceph systemd units in NixOS do not use templates 133 | find $out/lib -type f -wholename "*Ceph*" | xargs sed -i -e "s/\\\@/-/g" 134 | 135 | sed -i $out/${perl538.libPrefix}/${perl538.version}/PVE/Ceph/Tools.pm \ 136 | -e 's|=> "ceph|=> "${ceph}/bin/ceph|' \ 137 | -e "s|=> 'ceph|=> '${ceph}/bin/ceph|" \ 138 | -e "s|ceph-authtool|${ceph}/bin/ceph-authtool|" 139 | 140 | find $out/bin -type f | xargs sed -i \ 141 | -e "/ENV{'PATH'}/d" 142 | 143 | for bin in $out/{bin/*,share/pve-manager/helpers/pve-startall-delay}; do 144 | wrapProgram $bin \ 145 | --prefix PATH : ${ 146 | lib.makeBinPath [ 147 | ceph 148 | cdrkit # cloud-init 149 | corosync 150 | gnupg 151 | gzip 152 | iproute2 153 | libfaketime 154 | openssh 155 | openssl 156 | openvswitch 157 | (pve-ha-manager.override { inherit enableLinstor; }) 158 | pve-qemu 159 | shadow 160 | sqlite 161 | systemd 162 | termproxy 163 | util-linux 164 | wget 165 | 166 | ## dependencies of backup and restore 167 | bash 168 | busybox 169 | cstream 170 | lvm2 171 | lxc 172 | rsync 173 | system-sendmail 174 | zstd 175 | ] 176 | } \ 177 | --prefix PERL5LIB : $out/${perl538.libPrefix}/${perl538.version} 178 | done 179 | ''; 180 | 181 | passthru.updateScript = [ 182 | ../update.py 183 | pname 184 | "--url" 185 | src.url 186 | ]; 187 | 188 | meta = with lib; { 189 | description = "The Proxmox VE Manager API and Web UI repository"; 190 | homepage = "git://git.proxmox.com/?p=pve-manager.git"; 191 | license = licenses.agpl3Plus; 192 | maintainers = with maintainers; [ 193 | camillemndn 194 | julienmalka 195 | ]; 196 | platforms = platforms.linux; 197 | }; 198 | } 199 | ) 200 | -------------------------------------------------------------------------------- /pkgs/pve-novnc/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | novnc, 4 | esbuild, 5 | fetchgit, 6 | }: 7 | 8 | novnc.overrideAttrs (old: rec { 9 | pname = "pve-novnc"; 10 | version = "1.5.0-1"; 11 | 12 | src = fetchgit { 13 | url = "git://git.proxmox.com/git/novnc-pve.git"; 14 | rev = "2de2bef9737032c14edf0862261e34da74adb76d"; 15 | hash = "sha256-5pybuOkvNVcP+In03ZokNpqgmGwB4DQEO4jmefV7W9Y="; 16 | fetchSubmodules = true; 17 | }; 18 | 19 | patches = 20 | let 21 | series = builtins.readFile "${src}/debian/patches/series"; 22 | patchList = builtins.filter (patch: builtins.isString patch && patch != "") ( 23 | builtins.split "\n" series 24 | ); 25 | patchPathsList = map (patch: "${src}/debian/patches/${patch}") patchList; 26 | in 27 | old.patches ++ patchPathsList; 28 | 29 | sourceRoot = "${src.name}/novnc"; 30 | 31 | buildInputs = [ esbuild ]; 32 | 33 | installPhase = 34 | '' 35 | esbuild --bundle app/ui.js > app.js 36 | '' 37 | + old.installPhase 38 | + '' 39 | cp app.js $out/share/webapps/novnc/ 40 | mv $out/share/webapps/novnc/{vnc.html,index.html.tpl} 41 | ''; 42 | 43 | passthru.updateScript = [ 44 | ../update.py 45 | pname 46 | "--url" 47 | src.url 48 | "--version-prefix" 49 | (lib.versions.majorMinor old.version) 50 | ]; 51 | 52 | meta.position = builtins.dirOf ./.; 53 | }) 54 | -------------------------------------------------------------------------------- /pkgs/pve-qemu-server/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | glib, 7 | json_c, 8 | pkg-config, 9 | proxmox-backup-client, 10 | pve-edk2-firmware, 11 | pve-qemu, 12 | util-linux, 13 | uuid, 14 | findbin, 15 | termreadline, 16 | socat, 17 | vncterm, 18 | swtpm, 19 | libglvnd, 20 | }: 21 | 22 | let 23 | perlDeps = with perl538.pkgs; [ 24 | CryptOpenSSLRandom 25 | DataDumper 26 | DigestSHA 27 | FilePath 28 | findbin 29 | HTTPMessage 30 | GetoptLong 31 | IO 32 | IOMultiplex 33 | IOSocketIP 34 | JSON 35 | MIMEBase64 36 | NetSSLeay 37 | PathTools 38 | ScalarListUtils 39 | Socket 40 | Storable 41 | termreadline 42 | TestHarness 43 | TestMockModule 44 | TestMore 45 | TimeHiRes 46 | uuid 47 | XMLLibXML 48 | ]; 49 | 50 | perlEnv = perl538.withPackages (_: perlDeps); 51 | in 52 | 53 | perl538.pkgs.toPerlModule ( 54 | stdenv.mkDerivation rec { 55 | pname = "pve-qemu-server"; 56 | version = "8.3.8"; 57 | 58 | src = fetchgit { 59 | url = "git://git.proxmox.com/git/qemu-server.git"; 60 | rev = "78a0c43e7c6b844d1c4f7ce037ce32c9ed6857cd"; 61 | hash = "sha256-YktRlURya0pPg5mu+LVlJcBDhDW5Kd7tduZv0hgGyJo="; 62 | }; 63 | 64 | postPatch = '' 65 | sed -i {qmeventd/,}Makefile \ 66 | -e "/GITVERSION/d" \ 67 | -e "/default.mk/d" \ 68 | -e "/pve-doc-generator/d" \ 69 | -e "/install -m 0644 -D qm.bash-completion/,+3d" \ 70 | -e "/install -m 0644 qm.1/,+4d" \ 71 | -e "s/qmeventd docs/qmeventd/" \ 72 | -e "/qmeventd.8/d" \ 73 | -e "/modules-load.conf/d" \ 74 | -e "s,usr/,,g" 75 | 76 | # Fix QEMU version check 77 | sed -i PVE/QemuServer/Helpers.pm -e "s/\[,\\\s\]//" 78 | 79 | # Fix libGL and libEGL detection 80 | sed -i PVE/QemuServer.pm -e "s|/usr/lib/x86_64-linux-gnu/lib|${libglvnd}/lib/lib|" 81 | ''; 82 | 83 | buildInputs = [ 84 | glib 85 | json_c 86 | pkg-config 87 | perlEnv 88 | ]; 89 | propagatedBuildInputs = perlDeps; 90 | dontPatchShebangs = true; 91 | 92 | makeFlags = [ 93 | "PKGSOURCES=qm qmrestore qmextract" 94 | "DESTDIR=$(out)" 95 | "PREFIX=" 96 | "SBINDIR=/.bin" 97 | "USRSHAREDIR=$(out)/share/qemu-server" 98 | "VARLIBDIR=$(out)/lib/qemu-server" 99 | "PERLDIR=/${perl538.libPrefix}/${perl538.version}" 100 | ]; 101 | 102 | # Create missing SERVICEDIR 103 | preInstall = '' 104 | mkdir -p $out/lib/systemd/system 105 | ''; 106 | 107 | postFixup = '' 108 | find $out/lib -type f | xargs sed -i \ 109 | -e "/ENV{'PATH'}/d" \ 110 | -e "s|/usr/lib/qemu-server|$out/lib/qemu-server|" \ 111 | -e "s|/usr/share/qemu-server|$out/share/qemu-server|" \ 112 | -e "s|/usr/share/kvm|${pve-qemu}/share/qemu|" \ 113 | -Ee "s|(/usr)?/s?bin/kvm|qemu-kvm|" \ 114 | -Ee "s|(/usr)?/s?bin/||" \ 115 | -e "s|socat|${socat}/bin/socat|" \ 116 | -e "s|vncterm|${vncterm}/bin/vncterm|" \ 117 | -e "s|qemu-kvm|${pve-qemu}/bin/qemu-kvm|" \ 118 | -e "s|qemu-system|${pve-qemu}/bin/qemu-system|" \ 119 | -e "s|/var/lib/qemu-server|$out/lib/qemu-server|" \ 120 | -e "s|/usr/share/pve-edk2-firmware|${pve-edk2-firmware}/usr/share/pve-edk2-firmware|" \ 121 | -e 's|/etc/swtpm_setup.conf|${swtpm}/etc/swtpm_setup.conf|' \ 122 | #-e "s|/usr/bin/proxmox-backup-client|${proxmox-backup-client}/bin/proxmox-backup-client|" \ 123 | #-e "s|/usr/sbin/qm|$out/bin/qm|" \ 124 | #-e "s|/usr/bin/qemu|${pve-qemu}/bin/qemu|" \ 125 | #-e "s|/usr/bin/taskset|${util-linux}/bin/taskset|" \ 126 | #-e "s|/usr/bin/vncterm||" \ 127 | #-e "s|/usr/bin/termproxy||" \ 128 | #-e "s|/usr/bin/vma||" \ 129 | #-e "s|/usr/bin/pbs-restore||" \ 130 | patchShebangs $out/lib/qemu-server/pve-bridge 131 | patchShebangs $out/lib/qemu-server/pve-bridgedown 132 | patchShebangs $out/lib/qemu-server/pve-bridge-hotplug 133 | patchShebangs $out/lib/qemu-server/qmextract 134 | ''; 135 | 136 | passthru.updateScript = [ 137 | ../update.py 138 | pname 139 | "--url" 140 | src.url 141 | ]; 142 | 143 | meta = with lib; { 144 | description = "Proxmox VE's Virtual Machine Manager"; 145 | homepage = "git://git.proxmox.com/?p=qemu-server.git"; 146 | license = licenses.agpl3Plus; 147 | maintainers = with maintainers; [ 148 | camillemndn 149 | julienmalka 150 | ]; 151 | platforms = platforms.linux; 152 | }; 153 | } 154 | ) 155 | -------------------------------------------------------------------------------- /pkgs/pve-qemu/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | qemu, 4 | fetchgit, 5 | proxmox-backup-qemu, 6 | perl538, 7 | pkg-config, 8 | meson, 9 | cacert 10 | }: 11 | 12 | ( 13 | (qemu.overrideAttrs (old: rec { 14 | pname = "pve-qemu"; 15 | version = "9.2.0-5"; 16 | 17 | src = fetchgit { 18 | url = "git://git.proxmox.com/git/pve-qemu.git"; 19 | rev = "e0969989ac8ba252891a1a178b71e068c8ed4995"; 20 | hash = "sha256-wIrvaSjatyQq3a897ScljxmivUIM80rvc0F0y2tIZWo="; 21 | fetchSubmodules = true; 22 | 23 | # Download subprojects managed by meson 24 | postFetch = '' 25 | cd "$out/qemu" 26 | export NIX_SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt 27 | for prj in subprojects/*.wrap; do 28 | ${lib.getExe meson} subprojects download "$(basename "$prj" .wrap)" 29 | done 30 | find subprojects -type d -name .git -prune -execdir rm -r {} + 31 | rm -rf subprojects/packagecache/tmp* 32 | ''; 33 | }; 34 | 35 | patches = 36 | let 37 | series = builtins.readFile "${src}/debian/patches/series"; 38 | patchList = builtins.filter (patch: builtins.isString patch && patch != "") ( 39 | builtins.split "\n" series 40 | ); 41 | patchPathsList = map (patch: "${src}/debian/patches/${patch}") patchList; 42 | in 43 | old.patches ++ patchPathsList; 44 | 45 | sourceRoot = "${src.name}/qemu"; 46 | 47 | buildInputs = old.buildInputs ++ [ proxmox-backup-qemu ]; 48 | propagatedBuildInputs = [ proxmox-backup-qemu ]; 49 | 50 | preBuild = 51 | '' 52 | cp ${proxmox-backup-qemu}/lib/proxmox-backup-qemu.h . 53 | '' 54 | + old.preBuild; 55 | 56 | nativeBuildInputs = old.nativeBuildInputs ++ [ 57 | proxmox-backup-qemu 58 | perl538 59 | pkg-config 60 | ]; 61 | 62 | passthru.updateScript = [ 63 | ../update.py 64 | pname 65 | "--url" 66 | src.url 67 | "--version-prefix" 68 | (lib.versions.majorMinor old.version) 69 | ]; 70 | })).override 71 | { 72 | glusterfsSupport = true; 73 | enableDocs = false; 74 | cephSupport = true; 75 | } 76 | ) 77 | -------------------------------------------------------------------------------- /pkgs/pve-rados2/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | ceph, 7 | }: 8 | 9 | perl538.pkgs.toPerlModule ( 10 | stdenv.mkDerivation rec { 11 | pname = "pve-rados2"; 12 | version = "1.4.1"; 13 | 14 | src = fetchgit { 15 | url = "git://git.proxmox.com/git/librados2-perl.git"; 16 | rev = "b2017399cac82628e15ec14e95551c14fdfbf14f"; 17 | hash = "sha256-rHBM4xVwxAO0ZOU9YVw/n98JBzyRDwm0sOEAOhzUARc="; 18 | }; 19 | 20 | postPatch = '' 21 | sed -i Makefile \ 22 | -e '/GITVERSION/d' \ 23 | -e '/pkg-info/d' \ 24 | -e '/architecture/d' 25 | ''; 26 | 27 | buildInputs = [ 28 | perl538 29 | ceph.dev 30 | ]; 31 | 32 | makeFlags = [ 33 | "DESTDIR=$(out)" 34 | "PREFIX=" 35 | "SBINDIR=/bin" 36 | "PERLDIR=/${perl538.libPrefix}/${perl538.version}" 37 | "PERLSODIR=/${perl538.libPrefix}/auto" 38 | ]; 39 | 40 | passthru.updateScript = [ 41 | ../update.py 42 | pname 43 | "--url" 44 | src.url 45 | ]; 46 | 47 | meta = with lib; { 48 | description = "Perl bindings for librados"; 49 | homepage = "git://git.proxmox.com/?p=librados2-perl.git"; 50 | license = licenses.agpl3Plus; 51 | maintainers = with maintainers; [ 52 | camillemndn 53 | julienmalka 54 | ]; 55 | platforms = platforms.linux; 56 | }; 57 | } 58 | ) 59 | -------------------------------------------------------------------------------- /pkgs/pve-rs/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | rustPlatform, 5 | cargo, 6 | rustc, 7 | libuuid, 8 | pkg-config, 9 | openssl, 10 | fetchgit, 11 | perl538, 12 | perlmod, 13 | apt, 14 | mkRegistry, 15 | }: 16 | let 17 | sources = import ./sources.nix; 18 | registry = mkRegistry sources; 19 | in 20 | 21 | perl538.pkgs.toPerlModule ( 22 | stdenv.mkDerivation rec { 23 | pname = "pve-rs"; 24 | version = "0.9.1"; 25 | 26 | src = fetchgit { 27 | url = "git://git.proxmox.com/git/proxmox-perl-rs.git"; 28 | rev = "82bfbbf6c64b3749e3e982d933b9156e638386b2"; 29 | hash = "sha256-NetS/dDi5PT1TWZbI0pSqc57C4SSgBzbPmeSpquSuTA="; 30 | }; 31 | 32 | cargoDeps = rustPlatform.importCargoLock { 33 | lockFile = ./Cargo.lock; 34 | allowBuiltinFetchGit = true; 35 | }; 36 | 37 | postPatch = '' 38 | for i in {common/pkg/,pve-rs/}Makefile; do 39 | sed -i "$i" \ 40 | -e '/GITVERSION/d' \ 41 | -e '/dpkg-architecture/d' \ 42 | -e '/pkg-info/d' \ 43 | -e '/MConfig/d' \ 44 | -e 's,/usr/lib/perlmod/genpackage.pl,${perlmod}/lib/perlmod/genpackage.pl,' 45 | done 46 | cd pve-rs 47 | rm .cargo/config.toml 48 | cat ${registry}/cargo-patches.toml >> Cargo.toml 49 | ln -s ${./Cargo.lock} Cargo.lock 50 | ''; 51 | 52 | nativeBuildInputs = [ 53 | rustPlatform.cargoSetupHook 54 | cargo 55 | rustc 56 | perl538 57 | apt 58 | ]; 59 | 60 | buildInputs = [ 61 | libuuid 62 | pkg-config 63 | openssl 64 | registry 65 | apt 66 | ]; 67 | 68 | makeFlags = [ 69 | "BUILDIR=$NIX_BUILD_TOP" 70 | "BUILD_MODE=release" 71 | "DESTDIR=$(out)" 72 | "GITVERSION:=${src.rev}" 73 | "PERL_INSTALLVENDORARCH=/${perl538.libPrefix}/${perl538.version}" 74 | "PERL_INSTALLVENDORLIB=/${perl538.libPrefix}/${perl538.version}" 75 | ]; 76 | 77 | postInstall = '' 78 | ( 79 | cd common/pkg 80 | PERL_INSTALLVENDORLIB=$out/${perl538.libPrefix}/${perl538.version} make install 81 | ) 82 | ''; 83 | 84 | passthru.updateScript = [ 85 | ../update.py 86 | pname 87 | "--url" 88 | src.url 89 | "--prefix" 90 | "pve: bump version to" 91 | "--root" 92 | pname 93 | ]; 94 | 95 | passthru.registry = registry; 96 | 97 | meta = with lib; { 98 | description = "Proxmox Rust interface for Perl"; 99 | homepage = "git://git.proxmox.com/?p=proxmox-perl-rs.git"; 100 | license = licenses.agpl3Plus; 101 | maintainers = with maintainers; [ 102 | camillemndn 103 | julienmalka 104 | ]; 105 | platforms = platforms.linux; 106 | }; 107 | } 108 | ) 109 | -------------------------------------------------------------------------------- /pkgs/pve-storage/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | perl538, 6 | pve-cluster, 7 | pve-rados2, 8 | enableLinstor ? false, 9 | linstor-proxmox, 10 | ceph, 11 | coreutils, 12 | e2fsprogs, 13 | file, 14 | glusterfs, 15 | gptfdisk, 16 | gzip, 17 | libiscsi, 18 | lvm2, 19 | nfs-utils, 20 | openiscsi, 21 | openssh, 22 | proxmox-backup-client, 23 | pve-qemu, 24 | rpcbind, 25 | samba, 26 | smartmontools, 27 | targetcli, 28 | util-linux, 29 | zfs, 30 | posixstrptime, 31 | }: 32 | 33 | let 34 | perlDeps = 35 | with perl538.pkgs; 36 | [ 37 | Filechdir 38 | XMLLibXML 39 | posixstrptime 40 | pve-cluster 41 | pve-rados2 42 | ] 43 | ++ lib.optional enableLinstor linstor-proxmox; 44 | 45 | perlEnv = perl538.withPackages (_: perlDeps); 46 | in 47 | 48 | perl538.pkgs.toPerlModule ( 49 | stdenv.mkDerivation rec { 50 | pname = "pve-storage"; 51 | version = "8.3.2"; 52 | 53 | src = fetchgit { 54 | url = "git://git.proxmox.com/git/${pname}.git"; 55 | rev = "edb18d638697c08a52343ad8664a92e618bb7841"; 56 | hash = "sha256-nNsa8F8b7HNA/p39GaY5PNxXhlvr0/g1/69cUdUSjag="; 57 | }; 58 | 59 | sourceRoot = "${src.name}/src"; 60 | 61 | postPatch = '' 62 | sed -i bin/Makefile \ 63 | -e "s/pvesm.1 pvesm.bash-completion pvesm.zsh-completion//" \ 64 | -e "/pvesm.1/,+3d" 65 | ''; 66 | 67 | buildInputs = [ perlEnv ]; 68 | propagatedBuildInputs = perlDeps; 69 | 70 | makeFlags = [ 71 | "DESTDIR=$(out)" 72 | "PREFIX=" 73 | "SBINDIR=/bin" 74 | "PERLDIR=/${perl538.libPrefix}/${perl538.version}" 75 | ]; 76 | 77 | postInstall = 78 | '' 79 | sed -i $out/bin/* \ 80 | -e "s/-T//" \ 81 | -e "1s|$| -I$out/${perl538.libPrefix}/${perl538.version}|" 82 | '' 83 | + lib.optionalString enableLinstor '' 84 | cp -rs ${linstor-proxmox}/lib $out 85 | ''; 86 | 87 | postFixup = '' 88 | find $out -type f | xargs sed -i \ 89 | -e "s|/bin/lsblk|${util-linux}/bin/lsblk|" \ 90 | -e "s|/bin/mkdir|${coreutils}/bin/mkdir|" \ 91 | -e "s|/bin/mount|${util-linux}/bin/mount|" \ 92 | -e "s|/bin/umount|${util-linux}/bin/umount|" \ 93 | -e "s|/sbin/blkid|${util-linux}/bin/blkid|" \ 94 | -e "s|/sbin/blockdev|${util-linux}/bin/blockdev|" \ 95 | -e "s|/sbin/lv|${lvm2.bin}/bin/lv|" \ 96 | -e "s|/sbin/mkfs|${util-linux}/bin/mkfs|" \ 97 | -e "s|/sbin/pv|${lvm2.bin}/bin/vg|" \ 98 | -e "s|/sbin/sgdisk|${gptfdisk}/bin/sgdisk|" \ 99 | -e "s|/sbin/showmount|${nfs-utils}/bin/showmount|" \ 100 | -e "s|/sbin/vg|${lvm2.bin}/bin/vg|" \ 101 | -e "s|/sbin/zfs|${zfs}/bin/zfs|" \ 102 | -e "s|/sbin/zpool|${zfs}/bin/zpool|" \ 103 | -e "s|/usr/bin/chattr|${e2fsprogs}/bin/chattr|" \ 104 | -e "s|/usr/bin/cstream||" \ 105 | -e "s|/usr/bin/file|${file}/bin/file|" \ 106 | -e "s|/usr/bin/iscsi-ls|${libiscsi}/bin/iscsi-ls|" \ 107 | -e "s|/usr/bin/iscsiadm|${openiscsi}/bin/iscsiadm|" \ 108 | -e "s|/usr/bin/proxmox-backup-client|${proxmox-backup-client}/bin/proxmox-backup-client|" \ 109 | -e "s|/usr/bin/qemu|${pve-qemu}/bin/qemu|" \ 110 | -e "s|/usr/bin/rados|${ceph}/bin/rados|" \ 111 | -e "s|/usr/bin/rbd|${ceph}/bin/rbd|" \ 112 | -e "s|/usr/bin/scp|${openssh}/bin/scp|" \ 113 | -e "s|/usr/bin/smbclient|${samba}/bin/smbclient|" \ 114 | -e "s|/usr/bin/ssh|${openssh}/bin/ssh|" \ 115 | -e "s|/usr/bin/targetcli|${targetcli}/bin/targetcli|" \ 116 | -e "s|/usr/bin/vma|${pve-qemu}/bin/vma|" \ 117 | -e "s|/usr/bin/zcat|${gzip}/bin/zcat|" \ 118 | -e "s|/usr/libexec/ceph|$out/libexec/ceph|" \ 119 | -re "s|/usr/s?bin/ceph|${ceph}/bin/ceph|" \ 120 | -e "s|/usr/sbin/gluster|${glusterfs}/bin/gluster|" \ 121 | -e "s|/usr/sbin/ietadm||" \ 122 | -e "s|/usr/sbin/pvesm|$out/bin/pvesm|" \ 123 | -e "s|/usr/sbin/rpcinfo|${rpcbind}/bin/rpcinfo|" \ 124 | -e "s|/usr/sbin/sbdadm||" \ 125 | -e "s|/usr/sbin/smartctl|${smartmontools}/bin/smartctl|" \ 126 | -e "s|/usr/sbin/stmfadm||" \ 127 | -e "s|/usr/share/perl5|$out/${perl538.libPrefix}/${perl538.version}|" 128 | ''; 129 | 130 | passthru.updateScript = [ 131 | ../update.py 132 | pname 133 | "--url" 134 | src.url 135 | ]; 136 | 137 | meta = with lib; { 138 | description = "Proxmox VE Storage Library"; 139 | homepage = "git://git.proxmox.com/?p=pve-storage.git"; 140 | license = licenses.agpl3Plus; 141 | maintainers = with maintainers; [ 142 | camillemndn 143 | julienmalka 144 | ]; 145 | platforms = platforms.linux; 146 | }; 147 | } 148 | ) 149 | -------------------------------------------------------------------------------- /pkgs/pve-xtermjs/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | }: 6 | 7 | stdenv.mkDerivation rec { 8 | pname = "pve-xtermjs"; 9 | version = "5.3.0-3"; 10 | 11 | src = fetchgit { 12 | url = "git://git.proxmox.com/git/pve-xtermjs.git"; 13 | rev = "9e209b042bad4f3cf524654c1484ec8061a9edfb"; 14 | hash = "sha256-Ifnv0sYC9nNHuHPpXwTn+2vKSFHpnFn1Gwc59s5kzOE="; 15 | }; 16 | 17 | dontBuild = true; 18 | 19 | installPhase = '' 20 | mkdir -p $out/share/pve-xtermjs 21 | cp -r $src/xterm.js/src/* $out/share/pve-xtermjs/ 22 | cd $out/share/pve-xtermjs 23 | mv index.html.hbs.in index.html.hbs 24 | mv index.html.tpl.in index.html.tpl 25 | ''; 26 | 27 | passthru.updateScript = [ 28 | ../update.py 29 | pname 30 | "--url" 31 | src.url 32 | "--prefix" 33 | "xtermjs: bump version to" 34 | "--root" 35 | "xterm.js" 36 | ]; 37 | 38 | meta = with lib; { 39 | description = "xterm.js webclient"; 40 | homepage = "git://git.proxmox.com/?p=pve-xtermjs.git"; 41 | license = licenses.agpl3Plus; 42 | maintainers = with maintainers; [ 43 | camillemndn 44 | julienmalka 45 | ]; 46 | platforms = platforms.linux; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /pkgs/sencha-touch/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | }: 6 | 7 | stdenv.mkDerivation rec { 8 | pname = "sencha-touch"; 9 | version = "2.4.2"; 10 | 11 | src = fetchgit { 12 | url = "git://git.proxmox.com/git/sencha-touch.git"; 13 | rev = "c4685c8425cee430dd9c3b496a14fcc35c550a62"; 14 | hash = "sha256-ZlUXcszZbi9kSXxF39wLf7PBhJlGBSVN6NS+WACuXmM="; 15 | }; 16 | 17 | sourceRoot = "${src.name}/src"; 18 | dontBuild = true; 19 | 20 | installPhase = '' 21 | mkdir -p $out/share/javascript/sencha-touch 22 | cp sencha-touch-all.js $out/share/javascript/sencha-touch 23 | cp sencha-touch-all-debug.js $out/share/javascript/sencha-touch 24 | 25 | mkdir -p $out/share/javascript/sencha-touch/resources/css 26 | cp -r resources/css/*.css $out/share/javascript/sencha-touch/resources/css 27 | 28 | mkdir -p $out/share/javascript/sencha-touch/resources/themes/images 29 | cp -r resources/themes/images/default/* $out/share/javascript/sencha-touch/resources/themes/images 30 | ''; 31 | 32 | passthru.updateScript = [ 33 | ../update.py 34 | pname 35 | "--url" 36 | src.url 37 | ]; 38 | 39 | meta = with lib; { 40 | description = ""; 41 | homepage = "git://git.proxmox.com/?p=sencha-touch.git"; 42 | license = [ ]; 43 | maintainers = with maintainers; [ 44 | camillemndn 45 | julienmalka 46 | ]; 47 | platforms = platforms.all; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /pkgs/termproxy/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "anyhow" 7 | version = "1.0.98" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 10 | 11 | [[package]] 12 | name = "autocfg" 13 | version = "1.4.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 16 | 17 | [[package]] 18 | name = "bitflags" 19 | version = "1.3.2" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 22 | 23 | [[package]] 24 | name = "cfg-if" 25 | version = "1.0.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 28 | 29 | [[package]] 30 | name = "endian_trait" 31 | version = "0.6.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "77c844962d33db56fe7024846eeb8db92c79ccb68d3752a0ee37c261ac79fd46" 34 | dependencies = [ 35 | "endian_trait_derive", 36 | ] 37 | 38 | [[package]] 39 | name = "endian_trait_derive" 40 | version = "0.6.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "a03aff727e0a6b907127d45940d06dec1ca6c0c3df1fdfa647780c32d2b61ca0" 43 | dependencies = [ 44 | "quote", 45 | "syn", 46 | ] 47 | 48 | [[package]] 49 | name = "form_urlencoded" 50 | version = "1.2.1" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 53 | dependencies = [ 54 | "percent-encoding", 55 | ] 56 | 57 | [[package]] 58 | name = "libc" 59 | version = "0.2.172" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 62 | 63 | [[package]] 64 | name = "log" 65 | version = "0.4.27" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 68 | 69 | [[package]] 70 | name = "memoffset" 71 | version = "0.7.1" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" 74 | dependencies = [ 75 | "autocfg", 76 | ] 77 | 78 | [[package]] 79 | name = "mio" 80 | version = "0.8.11" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 83 | dependencies = [ 84 | "libc", 85 | "log", 86 | "wasi", 87 | "windows-sys", 88 | ] 89 | 90 | [[package]] 91 | name = "nix" 92 | version = "0.26.4" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" 95 | dependencies = [ 96 | "bitflags", 97 | "cfg-if", 98 | "libc", 99 | "memoffset", 100 | "pin-utils", 101 | ] 102 | 103 | [[package]] 104 | name = "percent-encoding" 105 | version = "2.3.1" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 108 | 109 | [[package]] 110 | name = "pico-args" 111 | version = "0.4.2" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" 114 | 115 | [[package]] 116 | name = "pin-utils" 117 | version = "0.1.0" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 120 | 121 | [[package]] 122 | name = "proc-macro2" 123 | version = "0.2.3" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" 126 | dependencies = [ 127 | "unicode-xid", 128 | ] 129 | 130 | [[package]] 131 | name = "proxmox-io" 132 | version = "1.1.0" 133 | dependencies = [ 134 | "endian_trait", 135 | ] 136 | 137 | [[package]] 138 | name = "proxmox-lang" 139 | version = "1.3.0" 140 | 141 | [[package]] 142 | name = "proxmox-termproxy" 143 | version = "1.1.0" 144 | dependencies = [ 145 | "anyhow", 146 | "form_urlencoded", 147 | "libc", 148 | "mio", 149 | "nix", 150 | "pico-args", 151 | "proxmox-io", 152 | "proxmox-lang", 153 | ] 154 | 155 | [[package]] 156 | name = "quote" 157 | version = "0.4.2" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" 160 | dependencies = [ 161 | "proc-macro2", 162 | ] 163 | 164 | [[package]] 165 | name = "syn" 166 | version = "0.12.15" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" 169 | dependencies = [ 170 | "proc-macro2", 171 | "quote", 172 | "unicode-xid", 173 | ] 174 | 175 | [[package]] 176 | name = "unicode-xid" 177 | version = "0.1.0" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 180 | 181 | [[package]] 182 | name = "wasi" 183 | version = "0.11.0+wasi-snapshot-preview1" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 186 | 187 | [[package]] 188 | name = "windows-sys" 189 | version = "0.48.0" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 192 | dependencies = [ 193 | "windows-targets", 194 | ] 195 | 196 | [[package]] 197 | name = "windows-targets" 198 | version = "0.48.5" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 201 | dependencies = [ 202 | "windows_aarch64_gnullvm", 203 | "windows_aarch64_msvc", 204 | "windows_i686_gnu", 205 | "windows_i686_msvc", 206 | "windows_x86_64_gnu", 207 | "windows_x86_64_gnullvm", 208 | "windows_x86_64_msvc", 209 | ] 210 | 211 | [[package]] 212 | name = "windows_aarch64_gnullvm" 213 | version = "0.48.5" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 216 | 217 | [[package]] 218 | name = "windows_aarch64_msvc" 219 | version = "0.48.5" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 222 | 223 | [[package]] 224 | name = "windows_i686_gnu" 225 | version = "0.48.5" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 228 | 229 | [[package]] 230 | name = "windows_i686_msvc" 231 | version = "0.48.5" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 234 | 235 | [[package]] 236 | name = "windows_x86_64_gnu" 237 | version = "0.48.5" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 240 | 241 | [[package]] 242 | name = "windows_x86_64_gnullvm" 243 | version = "0.48.5" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 246 | 247 | [[package]] 248 | name = "windows_x86_64_msvc" 249 | version = "0.48.5" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 252 | -------------------------------------------------------------------------------- /pkgs/termproxy/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchgit, 4 | rustPlatform, 5 | mkRegistry, 6 | }: 7 | 8 | let 9 | sources = import ./sources.nix; 10 | registry = mkRegistry sources; 11 | in 12 | rustPlatform.buildRustPackage rec { 13 | pname = "termproxy"; 14 | version = "1.1.0"; 15 | 16 | src = fetchgit { 17 | url = "git://git.proxmox.com/git/pve-xtermjs.git"; 18 | rev = "9bf8b31e8daac4fa9f464bff9e864a7b10179609"; 19 | hash = "sha256-OmL57wuLQGqfm1089hy2q40gHyti2PHzkizfWYRXQaU="; 20 | }; 21 | 22 | cargoLock = { 23 | lockFile = ./Cargo.lock; 24 | allowBuiltinFetchGit = true; 25 | }; 26 | 27 | prePatch = '' 28 | rm .cargo/config.toml 29 | cd termproxy 30 | cat ${registry}/cargo-patches.toml >> Cargo.toml 31 | cp ${./Cargo.lock} Cargo.lock 32 | ''; 33 | 34 | buildInputs = [ registry ]; 35 | 36 | postInstall = '' 37 | mv $out/bin/{proxmox-,}termproxy 38 | ''; 39 | 40 | passthru.registry = registry; 41 | 42 | passthru.updateScript = [ 43 | ../update.py 44 | pname 45 | "--url" 46 | src.url 47 | "--prefix" 48 | "termproxy: bump version to" 49 | "--root" 50 | pname 51 | ]; 52 | 53 | meta = with lib; { 54 | description = "xterm.js helper utility"; 55 | homepage = "git://git.proxmox.com/?p=pve-xtermjs.git"; 56 | license = with licenses; [ ]; 57 | maintainers = with maintainers; [ 58 | camillemndn 59 | julienmalka 60 | ]; 61 | platforms = platforms.linux; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /pkgs/termproxy/sources.nix: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | name = "librust-proxmox-io-dev"; 4 | url = "git://git.proxmox.com/git/proxmox.git"; 5 | rev = "c336cb9ab78b2bc3ebd9ab6a94e9e6f202de3ee6"; 6 | 7 | sha256 = "1b8zl8by8rpz1bv6drq3pzpfqf98rj2yl91ldg1mgig3dmbck4db"; 8 | crates = [ 9 | { 10 | name = "proxmox-io"; 11 | path = "proxmox-io"; 12 | } 13 | ]; 14 | } 15 | { 16 | name = "librust-proxmox-lang-dev"; 17 | url = "git://git.proxmox.com/git/proxmox.git"; 18 | rev = "d8eb6d1bde70a308190e14270b025d6c7270198d"; 19 | 20 | sha256 = "sha256-LnBMxRY3ELf5ktP2in2fM9rXlqS7s2Xm+nhPktfSvhI="; 21 | crates = [ 22 | { 23 | name = "proxmox-lang"; 24 | path = "proxmox-lang"; 25 | } 26 | ]; 27 | } 28 | 29 | ] 30 | -------------------------------------------------------------------------------- /pkgs/unifont/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchurl, 5 | }: 6 | 7 | stdenv.mkDerivation rec { 8 | pname = "unifont"; 9 | version = "15.1.05"; 10 | 11 | src = fetchurl { 12 | url = "mirror://gnu/unifont/unifont-${version}/unifont-${version}.tar.gz"; 13 | hash = "sha256-0nX1X0NYdQ4PhjBbkuh7iOszCqRsFfVT0u3wR/scI/o="; 14 | }; 15 | 16 | makeFlags = [ 17 | "USRDIR=." 18 | "DESTDIR=$(out)" 19 | ]; 20 | 21 | meta = with lib; { 22 | description = ""; 23 | homepage = "https://unifoundry.com/unifont/"; 24 | license = [ ]; 25 | maintainers = with maintainers; [ 26 | camillemndn 27 | julienmalka 28 | ]; 29 | platforms = platforms.all; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /pkgs/update.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix-shell 2 | #!nix-shell -i python3 -p git common-updater-scripts cargo toml-cli jq 3 | 4 | import argparse 5 | import os 6 | import subprocess 7 | import shutil 8 | import re 9 | 10 | 11 | def run_command(command): 12 | result = subprocess.run(command, shell=True, 13 | text=True, capture_output=True) 14 | if result.returncode != 0: 15 | error_message = f"Command '{command}' failed with error: {result.stderr.strip()}" 16 | raise RuntimeError(error_message) 17 | return result.stdout.strip() 18 | 19 | 20 | def main(): 21 | parser = argparse.ArgumentParser( 22 | description='Update a package to a new version.') 23 | parser.add_argument('pkg_name', help='Name of the package to update') 24 | parser.add_argument('--url', help='URL of the Git source', default=None) 25 | parser.add_argument('--version', help='Specify the version to update to') 26 | parser.add_argument('--version-prefix', default=None, 27 | help='Specify the prefix of targeted update version') 28 | parser.add_argument('--prefix', default='bump version to', 29 | help='Prefix for the commit message') 30 | parser.add_argument('--root', default='.', 31 | help='Root directory of the source') 32 | 33 | args = parser.parse_args() 34 | 35 | base_dir = os.getcwd() 36 | pkg_name = args.pkg_name 37 | repo_url = args.url if args.url else f'git://git.proxmox.com/git/{pkg_name}.git' 38 | old_version = run_command(f'nix eval .#{pkg_name}.version').strip('"') 39 | 40 | repo_name = os.path.basename(repo_url).replace('.git', '') 41 | 42 | temp_dir = '/tmp' 43 | os.chdir(temp_dir) 44 | 45 | if not os.path.isdir(repo_name): 46 | print(f'Cloning the {pkg_name} repository...') 47 | run_command(f'git clone {repo_url}') 48 | else: 49 | print('Repository already cloned.') 50 | 51 | os.chdir(repo_name) 52 | run_command('git fetch origin && git reset --hard @{u} && git clean -fd') 53 | 54 | if args.version: 55 | version = args.version 56 | else: 57 | print('Finding latest version') 58 | grep_prefix = f'{args.prefix} {args.version_prefix}' if args.version_prefix else args.prefix 59 | 60 | log_output = run_command( 61 | f'git log --grep="{grep_prefix}" -n 1 --pretty=format:"%s"') 62 | version_match = re.search(f'{re.escape(args.prefix)} (.*)', log_output) 63 | version = version_match.group(1) if version_match else None 64 | 65 | if not version: 66 | print('No version found in the commit messages.') 67 | return 68 | 69 | rev = run_command( 70 | f'git log --grep="{args.prefix} {version}" -n 1 --pretty=format:"%H"') 71 | if len(rev) == 0: 72 | print("Error: Version was not found in the Git repository.") 73 | return 74 | 75 | if old_version == version: 76 | print('New version same as old version, nothing to do.') 77 | else: 78 | os.chdir(temp_dir) 79 | os.chdir(repo_name) 80 | print(f'Resetting to {rev}') 81 | run_command(f'git reset --hard {rev}') 82 | 83 | # Remove debian registry 84 | for root, _, files in os.walk('.'): 85 | for file in files: 86 | if file == 'config' and '.cargo' in root: 87 | os.remove(os.path.join(root, file)) 88 | 89 | os.chdir(args.root) 90 | 91 | cargo_toml_files = [os.path.join(dp, f) for dp, dn, filenames in os.walk( 92 | '.') for f in filenames if f == 'Cargo.toml'] 93 | 94 | if len(cargo_toml_files) > 1: 95 | print('Error: There should be at most 1 Cargo.toml file.') 96 | return 97 | 98 | if len(cargo_toml_files) == 1: 99 | cargo_toml = cargo_toml_files[0] 100 | cargo_dir = os.path.dirname(cargo_toml) 101 | print(f'Found a Cargo.toml file in directory: {cargo_dir}') 102 | 103 | os.chdir(cargo_dir) 104 | 105 | def transform_git_deps(): 106 | deps = run_command( 107 | 'toml get Cargo.toml dependencies | jq -r "keys[]"').splitlines() 108 | with open('Cargo.toml', 'r') as f: 109 | lines = f.readlines() 110 | 111 | with open('Cargo.toml', 'w') as f: 112 | for line in lines: 113 | if not line.strip(): 114 | continue 115 | f.write(line) 116 | 117 | for dep in deps: 118 | if dep.startswith('proxmox-') or dep.startswith('pbs-'): 119 | print(f"Patching Cargo dependency '{dep}' to use Git.") 120 | if dep == 'perlmod': 121 | run_command( 122 | f'toml set Cargo.toml dependencies.{dep}.git git://git.proxmox.com/git/perlmod.git > Cargo.toml.tmp && mv Cargo.toml.tmp Cargo.toml') 123 | elif dep == 'proxmox-resource-scheduling': 124 | run_command( 125 | f'toml set Cargo.toml dependencies.{dep}.git git://git.proxmox.com/git/proxmox-resource-scheduling.git > Cargo.toml.tmp && mv Cargo.toml.tmp Cargo.toml') 126 | elif dep.startswith('proxmox-'): 127 | run_command( 128 | f'toml set Cargo.toml dependencies.{dep}.git git://git.proxmox.com/git/proxmox.git > Cargo.toml.tmp && mv Cargo.toml.tmp Cargo.toml') 129 | elif dep.startswith('pbs-'): 130 | run_command( 131 | f'toml set Cargo.toml dependencies.{dep}.git git://git.proxmox.com/git/proxmox-backup.git > Cargo.toml.tmp && mv Cargo.toml.tmp Cargo.toml') 132 | print("Finished patching Git dependencies.") 133 | 134 | transform_git_deps() 135 | run_command('cargo generate-lockfile') 136 | shutil.copy('Cargo.toml', os.path.join( 137 | base_dir, f'pkgs/{pkg_name}/')) 138 | 139 | cargo_lock_files = [os.path.join(dp, f) for dp, dn, filenames in os.walk( 140 | temp_dir) for f in filenames if f == 'Cargo.lock'] 141 | if len(cargo_lock_files) != 1: 142 | print( 143 | f'Error: Found {len(cargo_lock_files)} Cargo.lock file(s).') 144 | return 145 | 146 | cargo_lock = cargo_lock_files[0] 147 | print(f'Found one Cargo.lock file: {cargo_lock}') 148 | shutil.copy(cargo_lock, os.path.join( 149 | base_dir, f'pkgs/{pkg_name}/')) 150 | 151 | os.chdir(base_dir) 152 | print(f'Updating {pkg_name} with hash: {rev}') 153 | run_command(f'update-source-version {pkg_name} {version} --rev={rev}') 154 | 155 | 156 | if __name__ == '__main__': 157 | main() 158 | -------------------------------------------------------------------------------- /pkgs/vncterm/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | unifont_hex, 6 | libvncserver, 7 | gnutls, 8 | libjpeg, 9 | libnsl, 10 | libpng, 11 | bashInteractive, 12 | }: 13 | 14 | stdenv.mkDerivation rec { 15 | pname = "vncterm"; 16 | version = "1.8.0"; 17 | 18 | src = fetchgit { 19 | url = "git://git.proxmox.com/git/vncterm.git"; 20 | rev = "6ceee68be1ffb58db99b2027bd6d7cb408b4cabc"; 21 | hash = "sha256-HD6d6uEzG5u0EgrcmHg5N/mxofG0i1ZwpOB5E1G3In0="; 22 | }; 23 | 24 | postPatch = '' 25 | sed -i Makefile \ 26 | -e "/architecture.mk/d" \ 27 | -e "/pkg-info/d" \ 28 | -e "s|/usr/share/unifont/unifont.hex|${unifont_hex}/share/unifont/unifont.hex|" \ 29 | -e "s|usr/||g" \ 30 | -e "s/Werror/Wno-error/" \ 31 | -e "s|wchardata.c|${unifont_hex}/share/unifont/wchardata.c|g" \ 32 | -e "/^\$(VNCLIB)/,5d" \ 33 | -e "/pod2man/d" \ 34 | -e "/man1/d" 35 | 36 | sed -i vncterm.c -e "s|/usr|$out|" 37 | sed "s|/bin/bash|${bashInteractive}/bin/bash|g" -i vncterm.c 38 | ''; 39 | 40 | makeFlags = 41 | let 42 | libvncserver-patched = libvncserver.overrideAttrs ( 43 | _: _: { patches = [ "${src}/vncpatches/tls-auth-pluging.patch" ]; } 44 | ); 45 | in 46 | [ 47 | "VNCLIB=${libvncserver-patched}/lib/libvncserver.so" 48 | "VNCDIR=${libvncserver-patched.dev}/include" 49 | "DESTDIR=$(out)" 50 | ]; 51 | 52 | buildInputs = [ 53 | gnutls 54 | libjpeg 55 | libnsl 56 | libpng 57 | ]; 58 | 59 | passthru.updateScript = [ 60 | ../update.py 61 | pname 62 | "--url" 63 | src.url 64 | ]; 65 | 66 | meta = with lib; { 67 | description = ""; 68 | homepage = "git://git.proxmox.com/?p=vncterm.git"; 69 | license = with licenses; [ ]; 70 | maintainers = with maintainers; [ 71 | camillemndn 72 | julienmalka 73 | ]; 74 | mainProgram = "vncterm"; 75 | platforms = platforms.all; 76 | }; 77 | } 78 | -------------------------------------------------------------------------------- /proxmox-nixos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaumonNet/proxmox-nixos/89a8387839864f3a7ec9fa3556d8dd3da8ef89aa/proxmox-nixos.png -------------------------------------------------------------------------------- /tasks/README.md: -------------------------------------------------------------------------------- 1 | To update, run: 2 | 3 | ```bash 4 | # All and commit: 5 | nix-shell tasks/update.nix --arg predicate '_: _: true' --argstr commit true 6 | 7 | # Only Proxmox packages: 8 | nix-shell tasks/update.nix --arg predicate '_: pkg: builtins.match ".*proxmox.*" pkg.src.url == []' 9 | 10 | # Only Perl packages: 11 | nix-shell tasks/update.nix --arg predicate '_: pkg: builtins.match ".*cpan.*" pkg.src.url == []' 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /tasks/update.nix: -------------------------------------------------------------------------------- 1 | /* 2 | To run: 3 | 4 | nix-shell maintainers/scripts/update.nix 5 | 6 | See https://nixos.org/manual/nixpkgs/unstable/#var-passthru-updateScript 7 | */ 8 | { 9 | package ? null, 10 | maintainer ? null, 11 | predicate ? null, 12 | path ? null, 13 | max-workers ? null, 14 | include-overlays ? false, 15 | keep-going ? null, 16 | commit ? null, 17 | }: 18 | 19 | let 20 | pkgs = 21 | import 22 | ( 23 | let 24 | lock = builtins.fromJSON (builtins.readFile ../flake.lock); 25 | nixpkgsName = lock.nodes.root.inputs.nixpkgs-stable; 26 | in 27 | fetchTarball { 28 | url = "https://github.com/NixOS/nixpkgs/archive/${lock.nodes.${nixpkgsName}.locked.rev}.tar.gz"; 29 | sha256 = lock.nodes.${nixpkgsName}.locked.narHash; 30 | } 31 | ) 32 | ( 33 | if !include-overlays then 34 | { overlays = [ ]; } 35 | else if include-overlays then 36 | { } # Let Nixpkgs include overlays impurely. 37 | else 38 | { overlays = include-overlays; } 39 | ); 40 | 41 | pkgs-unstable = 42 | import 43 | ( 44 | let 45 | lock = builtins.fromJSON (builtins.readFile ../flake.lock); 46 | nixpkgsName = lock.nodes.root.inputs.nixpkgs-unstable; 47 | in 48 | fetchTarball { 49 | url = "https://github.com/NixOS/nixpkgs/archive/${lock.nodes.${nixpkgsName}.locked.rev}.tar.gz"; 50 | sha256 = lock.nodes.${nixpkgsName}.locked.narHash; 51 | } 52 | ) 53 | ( 54 | if !include-overlays then 55 | { overlays = [ ]; } 56 | else if include-overlays then 57 | { } # Let Nixpkgs include overlays impurely. 58 | else 59 | { overlays = include-overlays; } 60 | ); 61 | 62 | lock = builtins.fromJSON (builtins.readFile ../flake.lock); 63 | crane = fetchTarball { 64 | url = "https://github.com/ipetkov/crane/${lock.nodes.crane.locked.rev}.tar.gz"; 65 | sha256 = lock.nodes.crane.locked.narHash; 66 | }; 67 | craneLib = import crane { inherit pkgs; }; 68 | 69 | ourpkgs = import ../pkgs { inherit pkgs pkgs-unstable craneLib; }; 70 | inherit (pkgs) lib; 71 | 72 | # Remove duplicate elements from the list based on some extracted value. O(n^2) complexity. 73 | nubOn = 74 | f: list: 75 | if list == [ ] then 76 | [ ] 77 | else 78 | let 79 | x = lib.head list; 80 | xs = lib.filter (p: f x != f p) (lib.drop 1 list); 81 | in 82 | [ x ] ++ nubOn f xs; 83 | 84 | /* 85 | Recursively find all packages (derivations) in `pkgs` matching `cond` predicate. 86 | 87 | Type: packagesWithPath :: AttrPath → (AttrPath → derivation → bool) → AttrSet → List 88 | AttrPath :: [str] 89 | 90 | The packages will be returned as a list of named pairs comprising of: 91 | - attrPath: stringified attribute path (based on `rootPath`) 92 | - package: corresponding derivation 93 | */ 94 | packagesWithPath = 95 | rootPath: cond: _pkgs: 96 | let 97 | packagesWithPathInner = 98 | path: pathContent: 99 | let 100 | result = builtins.tryEval pathContent; 101 | 102 | somewhatUniqueRepresentant = 103 | { package, attrPath }: 104 | { 105 | inherit (package) updateScript; 106 | # Some updaters use the same `updateScript` value for all packages. 107 | # Also compare `meta.description`. 108 | position = package.meta.position or null; 109 | # We cannot always use `meta.position` since it might not be available 110 | # or it might be shared among multiple packages. 111 | }; 112 | 113 | dedupResults = lst: nubOn somewhatUniqueRepresentant (lib.concatLists lst); 114 | in 115 | if result.success then 116 | let 117 | evaluatedPathContent = result.value; 118 | in 119 | if lib.isDerivation evaluatedPathContent then 120 | lib.optional (cond path evaluatedPathContent) { 121 | attrPath = lib.concatStringsSep "." path; 122 | package = evaluatedPathContent; 123 | } 124 | else if lib.isAttrs evaluatedPathContent then 125 | # If user explicitly points to an attrSet or it is marked for recursion, we recur. 126 | if 127 | path == rootPath 128 | || evaluatedPathContent.recurseForDerivations or false 129 | || evaluatedPathContent.recurseForRelease or false 130 | then 131 | dedupResults ( 132 | lib.mapAttrsToList (name: elem: packagesWithPathInner (path ++ [ name ]) elem) evaluatedPathContent 133 | ) 134 | else 135 | [ ] 136 | else 137 | [ ] 138 | else 139 | [ ]; 140 | in 141 | packagesWithPathInner rootPath ourpkgs; 142 | 143 | # Recursively find all packages (derivations) in `pkgs` matching `cond` predicate. 144 | packagesWith = packagesWithPath [ ]; 145 | 146 | # Recursively find all packages in `pkgs` with updateScript matching given predicate. 147 | packagesWithUpdateScriptMatchingPredicate = 148 | cond: packagesWith (path: pkg: builtins.hasAttr "updateScript" pkg && cond path pkg); 149 | 150 | # Recursively find all packages in `pkgs` with updateScript by given maintainer. 151 | packagesWithUpdateScriptAndMaintainer = 152 | maintainer': 153 | let 154 | maintainer = 155 | if !builtins.hasAttr maintainer' lib.maintainers then 156 | builtins.throw "Maintainer with name `${maintainer'} does not exist in `maintainers/maintainer-list.nix`." 157 | else 158 | builtins.getAttr maintainer' lib.maintainers; 159 | in 160 | packagesWithUpdateScriptMatchingPredicate ( 161 | _path: pkg: 162 | ( 163 | if builtins.hasAttr "maintainers" pkg.meta then 164 | ( 165 | if builtins.isList pkg.meta.maintainers then 166 | builtins.elem maintainer pkg.meta.maintainers 167 | else 168 | maintainer == pkg.meta.maintainers 169 | ) 170 | else 171 | false 172 | ) 173 | ); 174 | 175 | # Recursively find all packages under `path` in `pkgs` with updateScript. 176 | packagesWithUpdateScript = 177 | path: _pkgs: 178 | let 179 | prefix = lib.splitString "." path; 180 | pathContent = lib.attrByPath prefix null ourpkgs; 181 | in 182 | if pathContent == null then 183 | builtins.throw "Attribute path `${path}` does not exist." 184 | else 185 | packagesWithPath prefix (_path: pkg: builtins.hasAttr "updateScript" pkg) pathContent; 186 | 187 | # Find a package under `path` in `pkgs` and require that it has an updateScript. 188 | packageByName = 189 | path: _pkgs: 190 | let 191 | package = lib.attrByPath (lib.splitString "." path) null ourpkgs; 192 | in 193 | if package == null then 194 | builtins.throw "Package with an attribute name `${path}` does not exist." 195 | else if !builtins.hasAttr "updateScript" package then 196 | builtins.throw "Package with an attribute name `${path}` does not have a `passthru.updateScript` attribute defined." 197 | else 198 | { 199 | attrPath = path; 200 | inherit package; 201 | }; 202 | 203 | # List of packages matched based on the CLI arguments. 204 | packages = 205 | if package != null then 206 | [ (packageByName package ourpkgs) ] 207 | else if predicate != null then 208 | packagesWithUpdateScriptMatchingPredicate predicate ourpkgs 209 | else if maintainer != null then 210 | packagesWithUpdateScriptAndMaintainer maintainer ourpkgs 211 | else if path != null then 212 | packagesWithUpdateScript path ourpkgs 213 | else 214 | builtins.throw "No arguments provided.\n\n${helpText}"; 215 | 216 | helpText = '' 217 | Please run: 218 | 219 | % nix-shell maintainers/scripts/update.nix --argstr maintainer garbas 220 | 221 | to run all update scripts for all packages that lists \`garbas\` as a maintainer 222 | and have \`updateScript\` defined, or: 223 | 224 | % nix-shell maintainers/scripts/update.nix --argstr package gnome.nautilus 225 | 226 | to run update script for specific package, or 227 | 228 | % nix-shell maintainers/scripts/update.nix --arg predicate '(path: pkg: pkg.updateScript.name or null == "gnome-update-script")' 229 | 230 | to run update script for all packages matching given predicate, or 231 | 232 | % nix-shell maintainers/scripts/update.nix --argstr path gnome 233 | 234 | to run update script for all package under an attribute path. 235 | 236 | You can also add 237 | 238 | --argstr max-workers 8 239 | 240 | to increase the number of jobs in parallel, or 241 | 242 | --argstr keep-going true 243 | 244 | to continue running when a single update fails. 245 | 246 | You can also make the updater automatically commit on your behalf from updateScripts 247 | that support it by adding 248 | 249 | --argstr commit true 250 | ''; 251 | 252 | # Transform a matched package into an object for update.py. 253 | packageData = 254 | { package, attrPath }: 255 | { 256 | inherit (package) name; 257 | pname = lib.getName package; 258 | oldVersion = lib.getVersion package; 259 | updateScript = map builtins.toString ( 260 | lib.toList (package.updateScript.command or package.updateScript) 261 | ); 262 | supportedFeatures = package.updateScript.supportedFeatures or [ ]; 263 | attrPath = package.updateScript.attrPath or attrPath; 264 | }; 265 | 266 | # JSON file with data for update.py. 267 | packagesJson = pkgs.writeText "packages.json" (builtins.toJSON (map packageData packages)); 268 | 269 | optionalArgs = 270 | lib.optional (max-workers != null) "--max-workers=${max-workers}" 271 | ++ lib.optional (keep-going == "true") "--keep-going" 272 | ++ lib.optional (commit == "true") "--commit"; 273 | 274 | args = [ packagesJson ] ++ optionalArgs; 275 | in 276 | pkgs.stdenv.mkDerivation { 277 | name = "nixpkgs-update-script"; 278 | buildCommand = '' 279 | echo "" 280 | echo "----------------------------------------------------------------" 281 | echo "" 282 | echo "Not possible to update packages using \`nix-build\`" 283 | echo "" 284 | echo "${helpText}" 285 | echo "----------------------------------------------------------------" 286 | exit 1 287 | ''; 288 | shellHook = '' 289 | unset shellHook # do not contaminate nested shells 290 | exec ${pkgs.python3.interpreter} ${./update.py} ${builtins.concatStringsSep " " args} 291 | ''; 292 | } 293 | -------------------------------------------------------------------------------- /tasks/update.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from typing import Dict, Generator, List, Optional, Tuple 3 | import argparse 4 | import asyncio 5 | import contextlib 6 | import json 7 | import os 8 | import re 9 | import subprocess 10 | import sys 11 | import tempfile 12 | 13 | class CalledProcessError(Exception): 14 | process: asyncio.subprocess.Process 15 | 16 | class UpdateFailedException(Exception): 17 | pass 18 | 19 | def eprint(*args, **kwargs): 20 | print(*args, file=sys.stderr, **kwargs) 21 | 22 | async def check_subprocess(*args, **kwargs): 23 | """ 24 | Emulate check argument of subprocess.run function. 25 | """ 26 | process = await asyncio.create_subprocess_exec(*args, **kwargs) 27 | returncode = await process.wait() 28 | 29 | if returncode != 0: 30 | error = CalledProcessError() 31 | error.process = process 32 | 33 | raise error 34 | 35 | return process 36 | 37 | async def run_update_script(nixpkgs_root: str, merge_lock: asyncio.Lock, temp_dir: Optional[Tuple[str, str]], package: Dict, keep_going: bool): 38 | worktree: Optional[str] = None 39 | 40 | update_script_command = package['updateScript'] 41 | 42 | if temp_dir is not None: 43 | worktree, _branch = temp_dir 44 | 45 | # Ensure the worktree is clean before update. 46 | await check_subprocess('git', 'reset', '--hard', '--quiet', 'HEAD', cwd=worktree) 47 | 48 | # Update scripts can use $(dirname $0) to get their location but we want to run 49 | # their clones in the git worktree, not in the main nixpkgs repo. 50 | update_script_command = map(lambda arg: re.sub(r'^{0}'.format(re.escape(nixpkgs_root)), worktree, arg), update_script_command) 51 | 52 | eprint(f" - {package['name']}: UPDATING ...") 53 | 54 | try: 55 | update_process = await check_subprocess( 56 | 'env', 57 | f"UPDATE_NIX_NAME={package['name']}", 58 | f"UPDATE_NIX_PNAME={package['pname']}", 59 | f"UPDATE_NIX_OLD_VERSION={package['oldVersion']}", 60 | f"UPDATE_NIX_ATTR_PATH={package['attrPath']}", 61 | *update_script_command, 62 | stdout=asyncio.subprocess.PIPE, 63 | stderr=asyncio.subprocess.PIPE, 64 | cwd=worktree, 65 | ) 66 | update_info = await update_process.stdout.read() 67 | 68 | await merge_changes(merge_lock, package, update_info, temp_dir) 69 | except KeyboardInterrupt as e: 70 | eprint('Cancelling…') 71 | raise asyncio.exceptions.CancelledError() 72 | except CalledProcessError as e: 73 | eprint(f" - {package['name']}: ERROR") 74 | eprint() 75 | eprint(f"--- SHOWING ERROR LOG FOR {package['name']} ----------------------") 76 | eprint() 77 | stderr = await e.process.stderr.read() 78 | eprint(stderr.decode('utf-8')) 79 | with open(f"{package['pname']}.log", 'wb') as logfile: 80 | logfile.write(stderr) 81 | eprint() 82 | eprint(f"--- SHOWING ERROR LOG FOR {package['name']} ----------------------") 83 | 84 | if not keep_going: 85 | raise UpdateFailedException(f"The update script for {package['name']} failed with exit code {e.process.returncode}") 86 | 87 | @contextlib.contextmanager 88 | def make_worktree() -> Generator[Tuple[str, str], None, None]: 89 | with tempfile.TemporaryDirectory() as wt: 90 | branch_name = f'update-{os.path.basename(wt)}' 91 | target_directory = f'{wt}/nixpkgs' 92 | 93 | subprocess.run(['git', 'worktree', 'add', '-b', branch_name, target_directory]) 94 | yield (target_directory, branch_name) 95 | subprocess.run(['git', 'worktree', 'remove', '--force', target_directory]) 96 | subprocess.run(['git', 'branch', '-D', branch_name]) 97 | 98 | async def commit_changes(name: str, merge_lock: asyncio.Lock, worktree: str, branch: str, changes: List[Dict]) -> None: 99 | for change in changes: 100 | # Git can only handle a single index operation at a time 101 | async with merge_lock: 102 | await check_subprocess('git', 'add', *change['files'], cwd=worktree) 103 | commit_message = '{attrPath}: {oldVersion} -> {newVersion}'.format(**change) 104 | if 'commitMessage' in change: 105 | commit_message = change['commitMessage'] 106 | elif 'commitBody' in change: 107 | commit_message = commit_message + '\n\n' + change['commitBody'] 108 | await check_subprocess('git', 'commit', '--quiet', '-m', commit_message, cwd=worktree) 109 | await check_subprocess('git', 'cherry-pick', branch) 110 | 111 | async def check_changes(package: Dict, worktree: str, update_info: str): 112 | if 'commit' in package['supportedFeatures']: 113 | changes = json.loads(update_info) 114 | else: 115 | changes = [{}] 116 | 117 | # Try to fill in missing attributes when there is just a single change. 118 | if len(changes) == 1: 119 | # Dynamic data from updater take precedence over static data from passthru.updateScript. 120 | if 'attrPath' not in changes[0]: 121 | # update.nix is always passing attrPath 122 | changes[0]['attrPath'] = package['attrPath'] 123 | 124 | if 'oldVersion' not in changes[0]: 125 | # update.nix is always passing oldVersion 126 | changes[0]['oldVersion'] = package['oldVersion'] 127 | 128 | if 'newVersion' not in changes[0]: 129 | attr_path = changes[0]['attrPath'] 130 | obtain_new_version_process = await check_subprocess('nix', 'eval', f'.#{attr_path}.version', stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, cwd=worktree) 131 | changes[0]['newVersion'] = json.loads((await obtain_new_version_process.stdout.read()).decode('utf-8')) 132 | 133 | if 'files' not in changes[0]: 134 | changed_files_process = await check_subprocess('git', 'diff', '--name-only', 'HEAD', stdout=asyncio.subprocess.PIPE, cwd=worktree) 135 | changed_files = (await changed_files_process.stdout.read()).splitlines() 136 | changes[0]['files'] = changed_files 137 | 138 | if len(changed_files) == 0: 139 | return [] 140 | 141 | return changes 142 | 143 | async def merge_changes(merge_lock: asyncio.Lock, package: Dict, update_info: str, temp_dir: Optional[Tuple[str, str]]) -> None: 144 | if temp_dir is not None: 145 | worktree, branch = temp_dir 146 | changes = await check_changes(package, worktree, update_info) 147 | 148 | if len(changes) > 0: 149 | await commit_changes(package['name'], merge_lock, worktree, branch, changes) 150 | else: 151 | eprint(f" - {package['name']}: DONE, no changes.") 152 | else: 153 | eprint(f" - {package['name']}: DONE.") 154 | 155 | async def updater(nixpkgs_root: str, temp_dir: Optional[Tuple[str, str]], merge_lock: asyncio.Lock, packages_to_update: asyncio.Queue[Optional[Dict]], keep_going: bool, commit: bool): 156 | while True: 157 | package = await packages_to_update.get() 158 | if package is None: 159 | # A sentinel received, we are done. 160 | return 161 | 162 | if not ('commit' in package['supportedFeatures'] or 'attrPath' in package): 163 | temp_dir = None 164 | 165 | await run_update_script(nixpkgs_root, merge_lock, temp_dir, package, keep_going) 166 | 167 | async def start_updates(max_workers: int, keep_going: bool, commit: bool, packages: List[Dict]): 168 | merge_lock = asyncio.Lock() 169 | packages_to_update: asyncio.Queue[Optional[Dict]] = asyncio.Queue() 170 | 171 | with contextlib.ExitStack() as stack: 172 | temp_dirs: List[Optional[Tuple[str, str]]] = [] 173 | 174 | # Do not create more workers than there are packages. 175 | num_workers = min(max_workers, len(packages)) 176 | 177 | nixpkgs_root_process = await check_subprocess('git', 'rev-parse', '--show-toplevel', stdout=asyncio.subprocess.PIPE) 178 | nixpkgs_root = (await nixpkgs_root_process.stdout.read()).decode('utf-8').strip() 179 | 180 | # Set up temporary directories when using auto-commit. 181 | for i in range(num_workers): 182 | temp_dir = stack.enter_context(make_worktree()) if commit else None 183 | temp_dirs.append(temp_dir) 184 | 185 | # Fill up an update queue, 186 | for package in packages: 187 | await packages_to_update.put(package) 188 | 189 | # Add sentinels, one for each worker. 190 | # A workers will terminate when it gets sentinel from the queue. 191 | for i in range(num_workers): 192 | await packages_to_update.put(None) 193 | 194 | # Prepare updater workers for each temp_dir directory. 195 | # At most `num_workers` instances of `run_update_script` will be running at one time. 196 | updaters = asyncio.gather(*[updater(nixpkgs_root, temp_dir, merge_lock, packages_to_update, keep_going, commit) for temp_dir in temp_dirs]) 197 | 198 | try: 199 | # Start updater workers. 200 | await updaters 201 | except asyncio.exceptions.CancelledError: 202 | # When one worker is cancelled, cancel the others too. 203 | updaters.cancel() 204 | except UpdateFailedException as e: 205 | # When one worker fails, cancel the others, as this exception is only thrown when keep_going is false. 206 | updaters.cancel() 207 | eprint(e) 208 | sys.exit(1) 209 | 210 | def main(max_workers: int, keep_going: bool, commit: bool, packages_path: str) -> None: 211 | with open(packages_path) as f: 212 | packages = json.load(f) 213 | 214 | eprint() 215 | eprint('Going to be running update for following packages:') 216 | for package in packages: 217 | eprint(f" - {package['name']}") 218 | eprint() 219 | 220 | confirm = input('Press Enter key to continue...') 221 | if confirm == '': 222 | eprint() 223 | eprint('Running update for:') 224 | 225 | asyncio.run(start_updates(max_workers, keep_going, commit, packages)) 226 | 227 | eprint() 228 | eprint('Packages updated!') 229 | sys.exit() 230 | else: 231 | eprint('Aborting!') 232 | sys.exit(130) 233 | 234 | parser = argparse.ArgumentParser(description='Update packages') 235 | parser.add_argument('--max-workers', '-j', dest='max_workers', type=int, help='Number of updates to run concurrently', nargs='?', default=4) 236 | parser.add_argument('--keep-going', '-k', dest='keep_going', action='store_true', help='Do not stop after first failure') 237 | parser.add_argument('--commit', '-c', dest='commit', action='store_true', help='Commit the changes') 238 | parser.add_argument('packages', help='JSON file containing the list of package names and their update scripts') 239 | 240 | if __name__ == '__main__': 241 | args = parser.parse_args() 242 | 243 | try: 244 | main(args.max_workers, args.keep_going, args.commit, args.packages) 245 | except KeyboardInterrupt as e: 246 | # Let’s cancel outside of the main loop too. 247 | sys.exit(130) 248 | -------------------------------------------------------------------------------- /tests/basic.nix: -------------------------------------------------------------------------------- 1 | { 2 | name = "pve-basic"; 3 | 4 | nodes.mypve = { 5 | services.proxmox-ve = { 6 | enable = true; 7 | ipAddress = "192.168.1.1"; 8 | }; 9 | }; 10 | 11 | testScript = '' 12 | machine.start() 13 | machine.wait_for_unit("pveproxy.service") 14 | assert "running" in machine.succeed("pveproxy status") 15 | assert "Proxmox" in machine.succeed("curl -k https://localhost:8006") 16 | machine.succeed("pvecm create mycluster") 17 | machine.wait_for_unit("corosync.service") 18 | ''; 19 | } 20 | -------------------------------------------------------------------------------- /tests/ceph.nix: -------------------------------------------------------------------------------- 1 | { 2 | name = "pve-cluster"; 3 | 4 | nodes = { 5 | pve1 = 6 | { pkgs, ... }: 7 | { 8 | services.proxmox-ve = { 9 | enable = true; 10 | ipAddress = "192.168.1.1"; 11 | ceph = { 12 | enable = true; 13 | mgr.enable = true; 14 | mon.enable = true; 15 | osd = { 16 | enable = true; 17 | daemons = [ "1" ]; 18 | }; 19 | }; 20 | }; 21 | 22 | environment.systemPackages = [ pkgs.openssl ]; 23 | 24 | users.users.root = { 25 | password = "mypassword"; 26 | initialPassword = null; 27 | hashedPassword = null; 28 | hashedPasswordFile = null; 29 | }; 30 | 31 | virtualisation.emptyDiskImages = [ 1024 ]; 32 | }; 33 | 34 | pve2 = { 35 | services.proxmox-ve = { 36 | enable = true; 37 | ipAddress = "192.168.1.2"; 38 | ceph = { 39 | enable = true; 40 | mon.enable = true; 41 | osd = { 42 | enable = true; 43 | daemons = [ "2" ]; 44 | }; 45 | }; 46 | }; 47 | 48 | virtualisation.emptyDiskImages = [ 1024 ]; 49 | }; 50 | 51 | pve3 = { 52 | services.proxmox-ve = { 53 | enable = true; 54 | ipAddress = "192.168.1.3"; 55 | ceph = { 56 | enable = true; 57 | mon.enable = true; 58 | osd = { 59 | enable = true; 60 | daemons = [ "3" ]; 61 | }; 62 | }; 63 | }; 64 | 65 | virtualisation.emptyDiskImages = [ 1024 ]; 66 | }; 67 | }; 68 | 69 | testScript = '' 70 | import time 71 | start_all() 72 | 73 | pve1.wait_for_unit("pveproxy.service") 74 | pve1.wait_for_unit("sshd.service") 75 | pve2.wait_for_unit("sshd.service") 76 | pve3.wait_for_unit("sshd.service") 77 | 78 | assert "running" in pve1.succeed("pveproxy status") 79 | assert "Proxmox" in pve1.succeed("curl -k https://localhost:8006") 80 | 81 | pve1.succeed("pvecm create mycluster") 82 | pve1.wait_for_unit("corosync.service") 83 | 84 | fingerprint = pve1.succeed("openssl x509 -noout -fingerprint -sha256 -in /etc/pve/local/pve-ssl.pem | cut -d= -f2") 85 | 86 | pve2.wait_for_unit("multi-user.target") 87 | time.sleep(10) 88 | pve2.succeed(f"pvesh create /cluster/config/join --hostname 192.168.1.1 --fingerprint {fingerprint.strip()} --password 'mypassword'") 89 | 90 | pve1.succeed( 91 | "pveceph init", 92 | "pveceph mon create", 93 | "pveceph mgr create", 94 | "ceph-volume lvm create --osd-id 1 --data /dev/vdb --no-systemd" 95 | ) 96 | 97 | pve2.succeed( 98 | "pveceph init", 99 | "pveceph mon create", 100 | "ceph-volume lvm create --osd-id 2 --data /dev/vdb --no-systemd" 101 | ) 102 | 103 | pve3.succeed( 104 | "pveceph init", 105 | "pveceph mon create", 106 | "ceph-volume lvm create --osd-id 3 --data /dev/vdb --no-systemd" 107 | ) 108 | ''; 109 | } 110 | -------------------------------------------------------------------------------- /tests/cluster.nix: -------------------------------------------------------------------------------- 1 | { 2 | name = "pve-cluster"; 3 | 4 | nodes = { 5 | pve1 = 6 | { pkgs, ... }: 7 | { 8 | services.proxmox-ve = { 9 | enable = true; 10 | ipAddress = "192.168.1.1"; 11 | }; 12 | 13 | environment.systemPackages = [ pkgs.openssl ]; 14 | 15 | users.users.root = { 16 | password = "mypassword"; 17 | initialPassword = null; 18 | hashedPassword = null; 19 | hashedPasswordFile = null; 20 | }; 21 | 22 | virtualisation.memorySize = 2048; 23 | }; 24 | 25 | pve2 = { 26 | services.proxmox-ve = { 27 | enable = true; 28 | ipAddress = "192.168.1.2"; 29 | }; 30 | 31 | virtualisation.memorySize = 2048; 32 | }; 33 | }; 34 | 35 | testScript = '' 36 | import time 37 | pve1.start() 38 | pve2.start() 39 | pve1.wait_for_unit("pveproxy.service") 40 | pve1.wait_for_unit("sshd.service") 41 | pve2.wait_for_unit("sshd.service") 42 | assert "running" in pve1.succeed("pveproxy status") 43 | assert "Proxmox" in pve1.succeed("curl -k https://localhost:8006") 44 | 45 | pve1.succeed("pvecm create mycluster") 46 | pve1.wait_for_unit("corosync.service") 47 | 48 | pve2.wait_for_unit("multi-user.target") 49 | time.sleep(10) 50 | 51 | fingerprint = pve1.succeed("openssl x509 -noout -fingerprint -sha256 -in /etc/pve/local/pve-ssl.pem | cut -d= -f2") 52 | pve2.succeed(f"pvesh create /cluster/config/join --hostname 192.168.1.1 --fingerprint {fingerprint.strip()} --password 'mypassword'") 53 | 54 | assert "Yes" in pve2.succeed("pvecm status | grep Quorate") 55 | assert "pve2" in pve1.succeed("pvecm nodes") 56 | ''; 57 | } 58 | -------------------------------------------------------------------------------- /tests/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, extraBaseModules }: 2 | 3 | let 4 | runTest = 5 | module: 6 | pkgs.testers.runNixOSTest { 7 | imports = [ module ]; 8 | globalTimeout = 5 * 60; 9 | extraBaseModules = { 10 | imports = builtins.attrValues extraBaseModules; 11 | }; 12 | }; 13 | in 14 | { 15 | test-pve-basic = runTest ./basic.nix; 16 | test-pve-ceph = runTest ./vm.nix; 17 | test-pve-cluster = runTest ./cluster.nix; 18 | # Disable this test until drdb gets unbroken in 24.11 19 | test-pve-linstor = runTest ./linstor.nix; 20 | test-pve-vm = runTest ./vm.nix; 21 | } 22 | -------------------------------------------------------------------------------- /tests/linstor.nix: -------------------------------------------------------------------------------- 1 | { 2 | name = "pve-linstor"; 3 | 4 | nodes = { 5 | pve1 = { 6 | services = { 7 | proxmox-ve = { 8 | enable = true; 9 | ipAddress = "192.168.1.1"; 10 | linstor.enable = true; 11 | }; 12 | 13 | lvm = { 14 | enable = true; 15 | dmeventd.enable = true; 16 | }; 17 | }; 18 | 19 | virtualisation = { 20 | emptyDiskImages = [ 10000 ]; 21 | memorySize = 2048; 22 | }; 23 | }; 24 | }; 25 | 26 | testScript = '' 27 | start_all() 28 | 29 | pve1.wait_for_unit("pveproxy.service") 30 | assert "running" in pve1.succeed("pveproxy status") 31 | assert "Proxmox" in pve1.succeed("curl -k https://localhost:8006") 32 | 33 | pve1.wait_for_unit("multi-user.target") 34 | 35 | pve1.wait_for_unit("linstor-satellite.service") 36 | pve1.wait_for_unit("linstor-controller.service") 37 | pve1.succeed("pvcreate /dev/vdb >&2") 38 | pve1.succeed("vgcreate linstor_vg /dev/vdb >&2") 39 | pve1.succeed("lvcreate -l 80%FREE -T linstor_vg/thinpool >&2") 40 | 41 | pve1.succeed("linstor node list >&2") 42 | pve1.succeed("linstor node create pve1 127.0.0.1 >&2") 43 | pve1.succeed("linstor node info >&2") 44 | pve1.succeed("linstor storage-pool create lvmthin pve1 pve-storage linstor_vg/thinpool >&2") 45 | pve1.succeed("linstor resource-group create test --storage-pool pve-storage --place-count 1 >&2") 46 | pve1.succeed("linstor volume-group create test") 47 | pve1.succeed("linstor resource-group spawn-resources test test_res 1G >&2") 48 | pve1.succeed("linstor resource list >&2") 49 | 50 | ''; 51 | } 52 | -------------------------------------------------------------------------------- /tests/vm.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | 3 | let 4 | minimalIso = pkgs.fetchurl { 5 | url = "https://releases.nixos.org/nixos/24.05/nixos-24.05.7139.bcba2fbf6963/nixos-minimal-24.05.7139.bcba2fbf6963-x86_64-linux.iso"; 6 | hash = "sha256-plre/mIHdIgU4xWU+9xErP+L4i460ZbcKq8iy2n4HT8="; 7 | }; 8 | in 9 | 10 | { 11 | name = "pve-vm"; 12 | 13 | nodes.mypve = { 14 | services.proxmox-ve = { 15 | enable = true; 16 | ipAddress = "192.168.1.1"; 17 | 18 | vms = { 19 | myvm1 = { 20 | vmid = 100; 21 | memory = 1024; 22 | cores = 1; 23 | sockets = 1; 24 | kvm = true; 25 | scsi = [ { file = "local:16"; } ]; 26 | cdrom = "local:iso/minimal.iso"; 27 | }; 28 | }; 29 | }; 30 | 31 | virtualisation = { 32 | additionalPaths = [ minimalIso ]; 33 | diskSize = 4096; 34 | memorySize = 2048; 35 | }; 36 | }; 37 | 38 | testScript = '' 39 | machine.start() 40 | machine.wait_for_unit("pveproxy.service") 41 | assert "running" in machine.succeed("pveproxy status") 42 | 43 | # Copy Iso 44 | machine.succeed("mkdir -p /var/lib/vz/template/iso/") 45 | machine.succeed("cp ${minimalIso} /var/lib/vz/template/iso/minimal.iso") 46 | 47 | # Declarative VM creation 48 | machine.wait_for_unit("multi-user.target") 49 | machine.succeed("qm stop 100 --timeout 0") 50 | 51 | # Seabios VM creation 52 | machine.succeed( 53 | "qm create 101 --kvm 0 --bios seabios -cdrom local:iso/minimal.iso", 54 | "qm start 101", 55 | "qm stop 101 --timeout 0" 56 | ) 57 | 58 | # Legacy ovmf vm creation 59 | machine.succeed( 60 | "qm create 102 --kvm 0 --bios ovmf -cdrom local:iso/minimal.iso", 61 | "qm start 102", 62 | "qm stop 102 --timeout 0" 63 | ) 64 | 65 | # UEFI ovmf vm creation 66 | machine.succeed( 67 | "qm create 103 --kvm 0 --bios ovmf --efidisk0 local:4,efitype=4m -cdrom local:iso/minimal.iso", 68 | "qm start 103", 69 | "qm stop 103 --timeout 0" 70 | ) 71 | 72 | # UEFI ovmf vm creation with secure boot 73 | machine.succeed( 74 | "qm create 104 --kvm 0 --bios ovmf --efidisk0 local:4,efitype=4m,pre-enrolled-keys=1 -cdrom local:iso/minimal.iso", 75 | "qm start 104", 76 | "qm stop 104 --timeout 0" 77 | ) 78 | ''; 79 | } 80 | --------------------------------------------------------------------------------