photoncloud-monorepo/flake.nix

1427 lines
52 KiB
Nix

{
description = "PhotonCloud - Japanese Cloud Platform";
# ============================================================================
# INPUTS: External dependencies
# ============================================================================
inputs = {
# Use unstable nixpkgs for latest packages
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Rust overlay for managing Rust toolchains
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
# Flake utilities for multi-system support
flake-utils.url = "github:numtide/flake-utils";
# Disko for declarative disk partitioning
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
# Nix-NOS generic network operating system modules
nix-nos = {
url = "path:./nix-nos";
inputs.nixpkgs.follows = "nixpkgs";
};
};
# ============================================================================
# OUTPUTS: What this flake provides
# ============================================================================
outputs = { self, nixpkgs, rust-overlay, flake-utils, disko, nix-nos, systems ? null }:
flake-utils.lib.eachDefaultSystem (system:
let
# Apply rust-overlay to get rust-bin attribute
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
inherit system overlays;
};
# Rust toolchain configuration
# Using stable channel with rust-src (for rust-analyzer) and rust-analyzer
rustToolchain = pkgs.rust-bin.stable.latest.default.override {
extensions = [ "rust-src" "rust-analyzer" ];
};
# Common build inputs needed by all Rust packages
commonBuildInputs = with pkgs; [
rocksdb # RocksDB storage engine
openssl # TLS/SSL support
];
# Common native build inputs (build-time only)
commonNativeBuildInputs = with pkgs; [
pkg-config # For finding libraries
protobuf # Protocol Buffers compiler
rustToolchain
];
# Common environment variables for building
commonEnvVars = {
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
PROTOC = "${pkgs.protobuf}/bin/protoc";
ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib";
};
clusterPython = pkgs.python3.withPackages (ps: [ ps.python-snappy ]);
# Keep Rust package builds stable without invalidating every package on
# unrelated workspace changes.
workspaceSourceRoots = {
chainfire = [ "chainfire" ];
flaredb = [ "flaredb" ];
iam = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"flaredb"
"iam"
];
coronafs = [ "coronafs" ];
plasmavmc = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"flaredb"
"iam"
"lightningstor"
"plasmavmc"
"prismnet"
];
prismnet = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"flaredb"
"iam"
"prismnet"
];
flashdns = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"flashdns"
"flaredb"
"iam"
];
fiberlb = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"fiberlb"
"flaredb"
"iam"
];
lightningstor = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"flaredb"
"iam"
"lightningstor"
];
nightlight = [ "nightlight" ];
creditservice = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"flaredb"
"iam"
];
apigateway = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"flaredb"
"iam"
];
k8shost = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"fiberlb"
"flaredb"
"flashdns"
"iam"
"k8shost"
"lightningstor"
"plasmavmc"
"prismnet"
];
deployer = [
"apigateway"
"chainfire"
"creditservice"
"crates/photon-auth-client"
"crates/photon-config"
"crates/photon-runtime"
"crates/photon-state"
"deployer"
"fiberlb"
"flaredb"
"flashdns"
"iam"
];
};
mkWorkspaceSrc = workspaceSubdir:
let
sourceRoots = workspaceSourceRoots.${workspaceSubdir} or [ workspaceSubdir ];
in
pkgs.lib.cleanSourceWith {
src = ./.;
filter = path: type:
let
rel = pkgs.lib.removePrefix ((toString ./. ) + "/") (toString path);
in
rel == ""
|| builtins.elem rel [ "flake.nix" "flake.lock" ]
|| builtins.any (root:
rel == root
|| pkgs.lib.hasPrefix "${root}/" rel
|| pkgs.lib.hasPrefix "${rel}/" root
) sourceRoots;
};
flakeBundleSrc = pkgs.lib.cleanSourceWith {
src = ./.;
filter = path: type:
let
rel = pkgs.lib.removePrefix ((toString ./. ) + "/") (toString path);
topLevel = builtins.head (pkgs.lib.splitString "/" rel);
includedTopLevels = [
"apigateway"
"baremetal"
"chainfire"
"coronafs"
"crates"
"creditservice"
"deployer"
"fiberlb"
"flashdns"
"flaredb"
"iam"
"k8shost"
"lightningstor"
"mtls-agent"
"nightlight"
"nix"
"nix-nos"
"plasmavmc"
"prismnet"
];
isTargetDir = builtins.match "(.*/)?target(/.*)?" rel != null;
in
!isTargetDir
&& (
rel == ""
|| builtins.elem rel [ "flake.nix" "flake.lock" ]
|| builtins.elem topLevel includedTopLevels
);
};
flakeInputsBlock = ''
inputs = {
# Use unstable nixpkgs for latest packages
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Rust overlay for managing Rust toolchains
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
# Flake utilities for multi-system support
flake-utils.url = "github:numtide/flake-utils";
# Disko for declarative disk partitioning
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
# Nix-NOS generic network operating system modules
nix-nos = {
url = "path:./nix-nos";
inputs.nixpkgs.follows = "nixpkgs";
};
};
'';
bundledInputsBlock = ''
inputs = {
nixpkgs.url = "path:./.bundle-inputs/nixpkgs";
rust-overlay = {
url = "path:./.bundle-inputs/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-utils = {
url = "path:./.bundle-inputs/flake-utils";
inputs.systems.follows = "systems";
};
systems.url = "path:./.bundle-inputs/systems";
disko = {
url = "path:./.bundle-inputs/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-nos = {
url = "path:./nix-nos";
inputs.nixpkgs.follows = "nixpkgs";
};
};
'';
flakeHeaderBlock = ''
# ============================================================================
# INPUTS: External dependencies
# ============================================================================
inputs = {
# Use unstable nixpkgs for latest packages
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Rust overlay for managing Rust toolchains
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
# Flake utilities for multi-system support
flake-utils.url = "github:numtide/flake-utils";
# Disko for declarative disk partitioning
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
# Nix-NOS generic network operating system modules
nix-nos = {
url = "path:./nix-nos";
inputs.nixpkgs.follows = "nixpkgs";
};
};
# ============================================================================
# OUTPUTS: What this flake provides
# ============================================================================
outputs = { self, nixpkgs, rust-overlay, flake-utils, disko, nix-nos, systems ? null }:
'';
bundledHeaderBlock = ''
# ============================================================================
# INPUTS: External dependencies
# ============================================================================
inputs = {
nixpkgs.url = "path:./.bundle-inputs/nixpkgs";
rust-overlay = {
url = "path:./.bundle-inputs/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-utils = {
url = "path:./.bundle-inputs/flake-utils";
inputs.systems.follows = "systems";
};
systems.url = "path:./.bundle-inputs/systems";
disko = {
url = "path:./.bundle-inputs/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-nos = {
url = "path:./nix-nos";
inputs.nixpkgs.follows = "nixpkgs";
};
};
# ============================================================================
# OUTPUTS: What this flake provides
# ============================================================================
outputs = { self, nixpkgs, rust-overlay, flake-utils, disko, nix-nos, systems ? null }:
'';
bundledFlakeNix =
pkgs.writeText
"plasmacloud-bundled-flake.nix"
(
builtins.replaceStrings
[ flakeHeaderBlock ]
[ bundledHeaderBlock ]
(builtins.readFile ./flake.nix)
);
bundledFlakeHeaderFile =
pkgs.writeText "plasmacloud-bundled-flake-header" bundledHeaderBlock;
baseFlakeLock = builtins.fromJSON (builtins.readFile ./flake.lock);
bundleInputRelPaths = {
nixpkgs = "./.bundle-inputs/nixpkgs";
"rust-overlay" = "./.bundle-inputs/rust-overlay";
"flake-utils" = "./.bundle-inputs/flake-utils";
disko = "./.bundle-inputs/disko";
systems = "./.bundle-inputs/systems";
};
fetchLockedInput =
nodeName:
let
tree = builtins.fetchTree baseFlakeLock.nodes.${nodeName}.locked;
in
if builtins.isAttrs tree && tree ? outPath then tree.outPath else tree;
vendoredFlakeInputs = {
nixpkgs = fetchLockedInput "nixpkgs";
"rust-overlay" = fetchLockedInput "rust-overlay";
"flake-utils" = fetchLockedInput "flake-utils";
disko = fetchLockedInput "disko";
systems = fetchLockedInput "systems";
};
makeBundledLockNode =
nodeName: relPath:
let
node = baseFlakeLock.nodes.${nodeName};
in
node
// {
locked = {
type = "path";
path = relPath;
};
original = {
type = "path";
path = relPath;
};
};
bundledFlakeLock = baseFlakeLock // {
nodes =
baseFlakeLock.nodes
// {
root =
baseFlakeLock.nodes.root
// {
inputs =
baseFlakeLock.nodes.root.inputs
// {
systems = "systems";
};
};
nixpkgs = makeBundledLockNode "nixpkgs" bundleInputRelPaths.nixpkgs;
"rust-overlay" = makeBundledLockNode "rust-overlay" bundleInputRelPaths."rust-overlay";
"flake-utils" = makeBundledLockNode "flake-utils" bundleInputRelPaths."flake-utils";
disko = makeBundledLockNode "disko" bundleInputRelPaths.disko;
systems = makeBundledLockNode "systems" bundleInputRelPaths.systems;
};
};
bundledFlakeLockFile =
pkgs.writeText "plasmacloud-bundled-flake.lock" (builtins.toJSON bundledFlakeLock);
inBundledEval = builtins.pathExists ./.bundle-eval-marker;
bundledFlakeRootDrv = pkgs.runCommand "plasmacloud-bundled-flake-root" {
nativeBuildInputs = [
pkgs.coreutils
pkgs.python3
];
} ''
mkdir -p "$out"
cp -a ${flakeBundleSrc}/. "$out"/
chmod -R u+w "$out"
touch "$out/.bundle-eval-marker"
mkdir -p "$out/.bundle-inputs"
cp -a ${vendoredFlakeInputs.nixpkgs} "$out/.bundle-inputs/nixpkgs"
cp -a ${vendoredFlakeInputs."rust-overlay"} "$out/.bundle-inputs/rust-overlay"
cp -a ${vendoredFlakeInputs."flake-utils"} "$out/.bundle-inputs/flake-utils"
cp -a ${vendoredFlakeInputs.disko} "$out/.bundle-inputs/disko"
cp -a ${vendoredFlakeInputs.systems} "$out/.bundle-inputs/systems"
cp ${bundledFlakeLockFile} "$out/flake.lock"
python3 - <<'PY' "$out/flake.nix" ${bundledFlakeHeaderFile}
from pathlib import Path
import re
import sys
flake_path = Path(sys.argv[1])
header = Path(sys.argv[2]).read_text()
source = flake_path.read_text()
pattern = re.compile(
r" # ============================================================================\n"
r" # INPUTS: External dependencies\n"
r" # ============================================================================\n"
r" inputs = \{.*?\n"
r" # ============================================================================\n"
r" # OUTPUTS: What this flake provides\n"
r" # ============================================================================\n"
r" outputs = \{ self, nixpkgs, rust-overlay, flake-utils, disko, nix-nos, systems \? null \}:",
re.S,
)
rewritten, count = pattern.subn(header.rstrip("\n"), source, count=1)
if count != 1:
raise SystemExit(f"expected to rewrite 1 flake header, rewrote {count}")
flake_path.write_text(rewritten)
PY
'';
bundledFlakeRoot =
if inBundledEval then
null
else
builtins.path {
path = bundledFlakeRootDrv;
name = "plasmacloud-bundled-flake-root-src";
};
bundledFlakeRootNarHashFile =
if inBundledEval then
null
else
pkgs.runCommand "plasmacloud-bundled-flake-root-narhash" {
nativeBuildInputs = [ pkgs.nix ];
} ''
${pkgs.nix}/bin/nix \
--extra-experimental-features nix-command \
hash path --sri ${bundledFlakeRoot} \
| tr -d '\n' > "$out"
'';
bundledFlakeRootNarHash =
if inBundledEval then
null
else
builtins.readFile bundledFlakeRootNarHashFile;
bundledFlake =
if inBundledEval then
null
else
builtins.getFlake (
builtins.unsafeDiscardStringContext
"path:${toString bundledFlakeRoot}?narHash=${bundledFlakeRootNarHash}"
);
bundledVmSmokeTargetToplevel =
if inBundledEval then
null
else
bundledFlake.nixosConfigurations.vm-smoke-target.config.system.build.toplevel;
# Helper function to build a Rust workspace package
# Parameters:
# name: package name (e.g., "chainfire-server")
# workspaceSubdir: subdirectory containing Cargo.toml (e.g., "chainfire")
# mainCrate: optional main crate name if different from workspace
# description: package description for meta
# doCheck: whether to run tests during build (default: false)
buildRustWorkspace = { name, workspaceSubdir, mainCrate ? null, description ? "", doCheck ? false }:
pkgs.rustPlatform.buildRustPackage ({
pname = name;
version = "0.1.0";
src = mkWorkspaceSrc workspaceSubdir;
cargoLock = {
lockFile = ./${workspaceSubdir}/Cargo.lock;
};
# Build from the workspace subdirectory
buildAndTestSubdir = workspaceSubdir;
# Copy Cargo.lock to root for nix validation (expects it at src root)
postUnpack = ''
cp $sourceRoot/${workspaceSubdir}/Cargo.lock $sourceRoot/Cargo.lock
'';
nativeBuildInputs = commonNativeBuildInputs;
buildInputs = commonBuildInputs;
# Set environment variables for build
inherit (commonEnvVars) LIBCLANG_PATH PROTOC ROCKSDB_LIB_DIR;
# Enable cargo tests during build (can be overridden per-package)
inherit doCheck;
# Test flags: run tests for the main crate only
cargoTestFlags = pkgs.lib.optionals (mainCrate != null) [ "-p" mainCrate ];
# Metadata for the package
meta = with pkgs.lib; {
description = description;
homepage = "https://github.com/yourorg/plasmacloud";
license = licenses.asl20; # Apache 2.0
maintainers = [ ];
platforms = platforms.linux;
};
# Build only the server binary if mainCrate is specified
# This avoids building test binaries and examples
} // pkgs.lib.optionalAttrs (mainCrate != null) {
cargoBuildFlags = [ "-p" mainCrate ];
});
# Helper function to build multiple binaries from the same workspace in
# one cargo invocation. This is mainly used by the VM cluster builds so
# a single host build can satisfy several services from the same
# workspace.
buildRustWorkspaceBundle = { name, workspaceSubdir, crates, description ? "", doCheck ? false }:
pkgs.rustPlatform.buildRustPackage {
pname = name;
version = "0.1.0";
src = mkWorkspaceSrc workspaceSubdir;
cargoLock = {
lockFile = ./${workspaceSubdir}/Cargo.lock;
};
buildAndTestSubdir = workspaceSubdir;
postUnpack = ''
cp $sourceRoot/${workspaceSubdir}/Cargo.lock $sourceRoot/Cargo.lock
'';
nativeBuildInputs = commonNativeBuildInputs;
buildInputs = commonBuildInputs;
inherit (commonEnvVars) LIBCLANG_PATH PROTOC ROCKSDB_LIB_DIR;
inherit doCheck;
cargoBuildFlags = pkgs.lib.concatMap (crate: [ "-p" crate ]) crates;
meta = with pkgs.lib; {
description = description;
homepage = "https://github.com/yourorg/plasmacloud";
license = licenses.asl20;
maintainers = [ ];
platforms = platforms.linux;
};
};
in
{
# ======================================================================
# DEVELOPMENT SHELL: Drop-in replacement for shell.nix
# ======================================================================
devShells.default = pkgs.mkShell {
name = "cloud-dev";
buildInputs = with pkgs; [
# Rust toolchain (replaces rustup/cargo/rustc from shell.nix)
rustToolchain
# Protocol Buffers
protobuf
# LLVM/Clang (for bindgen/clang-sys)
llvmPackages.libclang
llvmPackages.clang
# Build essentials
pkg-config
openssl
# Development tools
git
curl
jq
grpcurl
openssh
sshpass
clusterPython
qemu
vde2
bind
# For RocksDB (chainfire dependency)
rocksdb
];
# Environment variables for clang-sys and other build tools
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
PROTOC = "${pkgs.protobuf}/bin/protoc";
ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib";
shellHook = ''
echo "Cloud Platform Development Environment"
echo "======================================="
echo "Rust: $(rustc --version)"
echo "Protoc: $(protoc --version)"
echo "Clang: $(clang --version | head -1)"
echo ""
echo "Environment variables set:"
echo " LIBCLANG_PATH=$LIBCLANG_PATH"
echo " PROTOC=$PROTOC"
echo " ROCKSDB_LIB_DIR=$ROCKSDB_LIB_DIR"
echo ""
echo "Available workspaces:"
echo " - chainfire (distributed cluster coordination store)"
echo " - flaredb (distributed SQL/KV database for metadata and tenant data)"
echo " - iam (identity & access management)"
echo " - plasmavmc (VM control plane)"
echo " - prismnet (SDN controller)"
echo " - flashdns (DNS server)"
echo " - fiberlb (load balancer)"
echo " - lightningstor (block storage)"
echo " - nightlight (metrics store)"
echo " - creditservice (quota & billing)"
echo " - k8shost (kubernetes hosting)"
'';
};
# ======================================================================
# PACKAGES: Buildable artifacts from each workspace
# ======================================================================
packages = {
# --------------------------------------------------------------------
# Chainfire: Distributed Cluster Coordination Store
# --------------------------------------------------------------------
chainfire-server = buildRustWorkspace {
name = "chainfire-server";
workspaceSubdir = "chainfire";
mainCrate = "chainfire-server";
description = "Distributed cluster coordination store with consensus, watches, and membership";
};
# --------------------------------------------------------------------
# FlareDB: Distributed SQL/KV Database
# --------------------------------------------------------------------
flaredb-server = buildRustWorkspace {
name = "flaredb-server";
workspaceSubdir = "flaredb";
mainCrate = "flaredb-server";
description = "Distributed Postgres-like SQL/KV database for service metadata, tenant data, and DBaaS";
};
# --------------------------------------------------------------------
# IAM: Identity and Access Management Service
# --------------------------------------------------------------------
iam-server = buildRustWorkspace {
name = "iam-server";
workspaceSubdir = "iam";
mainCrate = "iam-server";
description = "Identity and access management service with RBAC and multi-tenant support";
};
# --------------------------------------------------------------------
# CoronaFS: Shared Block Volume Service
# --------------------------------------------------------------------
coronafs-server = buildRustWorkspace {
name = "coronafs-server";
workspaceSubdir = "coronafs";
mainCrate = "coronafs-server";
description = "Shared block volume service exporting raw VM volumes over NBD";
};
# --------------------------------------------------------------------
# PlasmaVMC: Virtual Machine Control Plane
# --------------------------------------------------------------------
plasmavmc-server = buildRustWorkspace {
name = "plasmavmc-server";
workspaceSubdir = "plasmavmc";
mainCrate = "plasmavmc-server";
description = "Virtual machine control plane for managing compute instances";
};
# --------------------------------------------------------------------
# PrismNet: Software-Defined Networking Controller
# --------------------------------------------------------------------
prismnet-server = buildRustWorkspace {
name = "prismnet-server";
workspaceSubdir = "prismnet";
mainCrate = "prismnet-server";
description = "Software-defined networking controller with OVN integration";
};
# --------------------------------------------------------------------
# FlashDNS: High-Performance DNS Server
# --------------------------------------------------------------------
flashdns-server = buildRustWorkspace {
name = "flashdns-server";
workspaceSubdir = "flashdns";
mainCrate = "flashdns-server";
description = "High-performance DNS server with pattern-based reverse DNS";
};
# --------------------------------------------------------------------
# FiberLB: Layer 4/7 Load Balancer
# --------------------------------------------------------------------
fiberlb-server = buildRustWorkspace {
name = "fiberlb-server";
workspaceSubdir = "fiberlb";
mainCrate = "fiberlb-server";
description = "Layer 4/7 load balancer for distributing traffic across services";
};
# --------------------------------------------------------------------
# LightningStor: Block Storage Service
# --------------------------------------------------------------------
lightningstor-server = buildRustWorkspace {
name = "lightningstor-server";
workspaceSubdir = "lightningstor";
mainCrate = "lightningstor-server";
description = "Distributed block storage service for persistent volumes";
};
lightningstor-node = buildRustWorkspace {
name = "lightningstor-node";
workspaceSubdir = "lightningstor";
mainCrate = "lightningstor-node";
description = "LightningStor distributed storage node daemon";
};
lightningstor-workspace = buildRustWorkspaceBundle {
name = "lightningstor-workspace";
workspaceSubdir = "lightningstor";
crates = [
"lightningstor-server"
"lightningstor-node"
];
description = "Combined LightningStor server and node workspace build";
};
# --------------------------------------------------------------------
# NightLight: Prometheus-compatible Metrics Store
# --------------------------------------------------------------------
nightlight-server = buildRustWorkspace {
name = "nightlight-server";
workspaceSubdir = "nightlight";
mainCrate = "nightlight-server";
description = "Prometheus-compatible metrics storage (NightLight)";
};
# --------------------------------------------------------------------
# CreditService: Quota and Billing Controller
# --------------------------------------------------------------------
creditservice-server = buildRustWorkspace {
name = "creditservice-server";
workspaceSubdir = "creditservice";
mainCrate = "creditservice-server";
description = "Credit/quota management service with billing integration";
};
# --------------------------------------------------------------------
# APIGateway: API Gateway Service
# --------------------------------------------------------------------
apigateway-server = buildRustWorkspace {
name = "apigateway-server";
workspaceSubdir = "apigateway";
mainCrate = "apigateway-server";
description = "API Gateway for PlasmaCloud services";
};
# --------------------------------------------------------------------
# k8shost: Kubernetes Hosting Component
# --------------------------------------------------------------------
k8shost-server = buildRustWorkspace {
name = "k8shost-server";
workspaceSubdir = "k8shost";
mainCrate = "k8shost-server";
description = "Lightweight Kubernetes hosting with multi-tenant isolation";
};
# --------------------------------------------------------------------
# Deployer: Bare-metal bootstrap orchestration service
# --------------------------------------------------------------------
deployer-server = buildRustWorkspace {
name = "deployer-server";
workspaceSubdir = "deployer";
mainCrate = "deployer-server";
description = "Node bootstrap and phone-home orchestration service";
};
deployer-ctl = buildRustWorkspace {
name = "deployer-ctl";
workspaceSubdir = "deployer";
mainCrate = "deployer-ctl";
description = "Declarative control utility for PhotonCloud deployer state";
};
node-agent = buildRustWorkspace {
name = "node-agent";
workspaceSubdir = "deployer";
mainCrate = "node-agent";
description = "Node-local runtime agent for PhotonCloud scheduled services";
};
nix-agent = buildRustWorkspace {
name = "nix-agent";
workspaceSubdir = "deployer";
mainCrate = "nix-agent";
description = "Node-local NixOS reconciliation agent for PhotonCloud hosts";
};
plasmacloud-reconciler = buildRustWorkspace {
name = "plasmacloud-reconciler";
workspaceSubdir = "deployer";
mainCrate = "plasmacloud-reconciler";
description = "Declarative reconciler for host rollouts and published resources";
};
plasmacloudFlakeBundle = pkgs.runCommand "plasmacloud-flake-bundle.tar.gz" {
nativeBuildInputs = [
pkgs.coreutils
pkgs.gnutar
pkgs.gzip
];
} ''
bundle_root="$(mktemp -d)"
cp -a ${bundledFlakeRootDrv}/. "$bundle_root"/
chmod -R u+w "$bundle_root"
tar \
--sort=name \
--mtime='@1' \
--owner=0 \
--group=0 \
--numeric-owner \
-C "$bundle_root" \
-cf - . \
| gzip -n > "$out"
'';
# --------------------------------------------------------------------
# Fleet Scheduler: Non-Kubernetes service scheduler for bare-metal nodes
# --------------------------------------------------------------------
fleet-scheduler = buildRustWorkspace {
name = "fleet-scheduler";
workspaceSubdir = "deployer";
mainCrate = "fleet-scheduler";
description = "Label-aware service scheduler for PhotonCloud bare-metal fleets";
};
deployer-workspace = buildRustWorkspaceBundle {
name = "deployer-workspace";
workspaceSubdir = "deployer";
crates = [
"deployer-server"
"deployer-ctl"
"node-agent"
"nix-agent"
"plasmacloud-reconciler"
"fleet-scheduler"
];
description = "Combined deployer workspace build for cluster images and checks";
};
vmClusterDeployerState =
self.nixosConfigurations.node01.config.system.build.plasmacloudDeployerClusterState;
vmClusterFlakeBundle = self.packages.${system}.plasmacloudFlakeBundle;
vmSmokeBundledTargetToplevel = bundledVmSmokeTargetToplevel;
# --------------------------------------------------------------------
# Default package: Build all servers
# --------------------------------------------------------------------
default = pkgs.symlinkJoin {
name = "photoncloud-all";
paths = [
self.packages.${system}.chainfire-server
self.packages.${system}.flaredb-server
self.packages.${system}.iam-server
self.packages.${system}.plasmavmc-server
self.packages.${system}.prismnet-server
self.packages.${system}.flashdns-server
self.packages.${system}.fiberlb-server
self.packages.${system}.lightningstor-workspace
self.packages.${system}.nightlight-server
self.packages.${system}.creditservice-server
self.packages.${system}.apigateway-server
self.packages.${system}.k8shost-server
self.packages.${system}.deployer-workspace
self.packages.${system}.vmClusterDeployerState
];
};
};
# ======================================================================
# APPS: Runnable applications from packages
# ======================================================================
apps = {
chainfire-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.chainfire-server;
};
flaredb-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.flaredb-server;
};
iam-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.iam-server;
};
plasmavmc-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.plasmavmc-server;
};
prismnet-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.prismnet-server;
};
flashdns-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.flashdns-server;
};
fiberlb-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.fiberlb-server;
};
lightningstor-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.lightningstor-server;
};
lightningstor-node = flake-utils.lib.mkApp {
drv = self.packages.${system}.lightningstor-node;
};
nightlight-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.nightlight-server;
};
creditservice-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.creditservice-server;
};
apigateway-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.apigateway-server;
};
k8shost-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.k8shost-server;
};
deployer-server = flake-utils.lib.mkApp {
drv = self.packages.${system}.deployer-server;
};
deployer-ctl = flake-utils.lib.mkApp {
drv = self.packages.${system}.deployer-ctl;
};
plasmacloud-reconciler = flake-utils.lib.mkApp {
drv = self.packages.${system}.plasmacloud-reconciler;
};
nix-agent = flake-utils.lib.mkApp {
drv = self.packages.${system}.nix-agent;
};
node-agent = flake-utils.lib.mkApp {
drv = self.packages.${system}.node-agent;
};
fleet-scheduler = flake-utils.lib.mkApp {
drv = self.packages.${system}.fleet-scheduler;
};
};
checks = {
first-boot-topology-vm-smoke = pkgs.testers.runNixOSTest (
import ./nix/tests/first-boot-topology-vm-smoke.nix {
inherit pkgs;
photoncloudPackages = self.packages.${system};
photoncloudModule = self.nixosModules.default;
nixNosModule = nix-nos.nixosModules.default;
}
);
deployer-vm-smoke = pkgs.testers.runNixOSTest (
import ./nix/tests/deployer-vm-smoke.nix {
inherit pkgs;
photoncloudPackages = self.packages.${system};
smokeTargetToplevel = self.packages.${system}.vmSmokeBundledTargetToplevel;
}
);
deployer-vm-rollback = pkgs.testers.runNixOSTest (
import ./nix/tests/deployer-vm-smoke.nix {
inherit pkgs;
photoncloudPackages = self.packages.${system};
smokeTargetToplevel = self.packages.${system}.vmSmokeBundledTargetToplevel;
desiredSystemOverrides = {
health_check_command = [ "false" ];
rollback_on_failure = true;
};
expectedStatus = "rolled-back";
expectCurrentSystemMatchesTarget = false;
expectMarkerPresent = false;
}
);
fiberlb-native-bgp-vm-smoke = pkgs.testers.runNixOSTest (
import ./nix/tests/fiberlb-native-bgp-vm-smoke.nix {
inherit pkgs;
photoncloudPackages = self.packages.${system};
photoncloudModule = self.nixosModules.default;
nixNosModule = nix-nos.nixosModules.default;
}
);
fiberlb-native-bgp-multipath-vm-smoke = pkgs.testers.runNixOSTest (
import ./nix/tests/fiberlb-native-bgp-multipath-vm-smoke.nix {
inherit pkgs;
photoncloudPackages = self.packages.${system};
photoncloudModule = self.nixosModules.default;
nixNosModule = nix-nos.nixosModules.default;
}
);
fiberlb-native-bgp-interop-vm-smoke = pkgs.testers.runNixOSTest (
import ./nix/tests/fiberlb-native-bgp-interop-vm-smoke.nix {
inherit pkgs;
photoncloudPackages = self.packages.${system};
photoncloudModule = self.nixosModules.default;
nixNosModule = nix-nos.nixosModules.default;
}
);
fiberlb-native-bgp-ecmp-drain-vm-smoke = pkgs.testers.runNixOSTest (
import ./nix/tests/fiberlb-native-bgp-ecmp-drain-vm-smoke.nix {
inherit pkgs;
photoncloudPackages = self.packages.${system};
photoncloudModule = self.nixosModules.default;
nixNosModule = nix-nos.nixosModules.default;
}
);
deployer-bootstrap-e2e = pkgs.runCommand "deployer-bootstrap-e2e" {
nativeBuildInputs = with pkgs; [
bash
coreutils
curl
findutils
gawk
gnugrep
gnused
procps
python3
];
PHOTONCLOUD_E2E_IN_NIX = "1";
PHOTONCLOUD_CHAINFIRE_SERVER_BIN =
"${self.packages.${system}.chainfire-server}/bin/chainfire";
PHOTONCLOUD_DEPLOYER_SERVER_BIN =
"${self.packages.${system}.deployer-workspace}/bin/deployer-server";
PHOTONCLOUD_DEPLOYER_CTL_BIN =
"${self.packages.${system}.deployer-workspace}/bin/deployer-ctl";
} ''
export HOME="$TMPDIR/home"
mkdir -p "$HOME"
export PATH="${pkgs.lib.makeBinPath [
pkgs.bash
pkgs.coreutils
pkgs.curl
pkgs.findutils
pkgs.gawk
pkgs.gnugrep
pkgs.gnused
pkgs.procps
pkgs.python3
]}"
bash ${./deployer/scripts/verify-deployer-bootstrap-e2e.sh}
touch "$out"
'';
host-lifecycle-e2e = pkgs.runCommand "host-lifecycle-e2e" {
nativeBuildInputs = with pkgs; [
bash
coreutils
curl
findutils
gawk
gnugrep
gnused
procps
python3
];
PHOTONCLOUD_E2E_IN_NIX = "1";
PHOTONCLOUD_CHAINFIRE_SERVER_BIN =
"${self.packages.${system}.chainfire-server}/bin/chainfire";
PHOTONCLOUD_DEPLOYER_CTL_BIN =
"${self.packages.${system}.deployer-workspace}/bin/deployer-ctl";
PHOTONCLOUD_PLASMACLOUD_RECONCILER_BIN =
"${self.packages.${system}.deployer-workspace}/bin/plasmacloud-reconciler";
} ''
export HOME="$TMPDIR/home"
mkdir -p "$HOME"
export PATH="${pkgs.lib.makeBinPath [
pkgs.bash
pkgs.coreutils
pkgs.curl
pkgs.findutils
pkgs.gawk
pkgs.gnugrep
pkgs.gnused
pkgs.procps
pkgs.python3
]}"
bash ${./deployer/scripts/verify-host-lifecycle-e2e.sh}
touch "$out"
'';
fleet-scheduler-e2e = pkgs.runCommand "fleet-scheduler-e2e" {
nativeBuildInputs = with pkgs; [
bash
coreutils
curl
findutils
gawk
gnugrep
gnused
procps
python3
];
PHOTONCLOUD_E2E_IN_NIX = "1";
PHOTONCLOUD_CHAINFIRE_SERVER_BIN =
"${self.packages.${system}.chainfire-server}/bin/chainfire";
PHOTONCLOUD_DEPLOYER_CTL_BIN =
"${self.packages.${system}.deployer-workspace}/bin/deployer-ctl";
PHOTONCLOUD_NODE_AGENT_BIN =
"${self.packages.${system}.deployer-workspace}/bin/node-agent";
PHOTONCLOUD_FLEET_SCHEDULER_BIN =
"${self.packages.${system}.deployer-workspace}/bin/fleet-scheduler";
} ''
export HOME="$TMPDIR/home"
mkdir -p "$HOME"
export PATH="${pkgs.lib.makeBinPath [
pkgs.bash
pkgs.coreutils
pkgs.curl
pkgs.findutils
pkgs.gawk
pkgs.gnugrep
pkgs.gnused
pkgs.procps
pkgs.python3
]}"
bash ${./deployer/scripts/verify-fleet-scheduler-e2e.sh}
touch "$out"
'';
};
}
) // {
# ========================================================================
# NIXOS MODULES: System-level service modules (non-system-specific)
# ========================================================================
nixosModules.default = import ./nix/modules;
nixosModules.photoncloud = import ./nix/modules;
nixosModules.plasmacloud = import ./nix/modules; # backwards compatibility
# ========================================================================
# NIXOS CONFIGURATIONS: Netboot images for bare-metal provisioning
# ========================================================================
nixosConfigurations = {
# Control Plane netboot image (all 8 services)
netboot-control-plane = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./nix/images/netboot-control-plane.nix ];
};
# Worker netboot image (compute-focused services)
netboot-worker = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./nix/images/netboot-worker.nix ];
};
# All-in-One netboot image (single-node deployment)
netboot-all-in-one = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./nix/images/netboot-all-in-one.nix ];
};
# Base netboot image (minimal, for VM testing and provisioning)
netboot-base = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./nix/images/netboot-base.nix ];
};
# Offline-friendly target used by deployer VM smoke tests.
vm-smoke-target = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./nix/images/deployer-vm-smoke-target.nix ];
};
# PlasmaCloud ISO (T061.S5 - bootable ISO with cluster-config embedding)
plasmacloud-iso = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./nix/iso/plasmacloud-iso.nix
nix-nos.nixosModules.default
self.nixosModules.default
{ nixpkgs.overlays = [ self.overlays.default ]; }
];
};
# T036 VM Cluster Nodes (for nixos-anywhere deployment)
pxe-server = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
disko.nixosModules.disko
./baremetal/vm-cluster/pxe-server/configuration.nix
./baremetal/vm-cluster/pxe-server/disko.nix
self.nixosModules.default
{ nixpkgs.overlays = [ self.overlays.default ]; }
];
};
node01 = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
disko.nixosModules.disko
nix-nos.nixosModules.default
./nix/nodes/vm-cluster/node01/configuration.nix
self.nixosModules.default
({ pkgs, ... }: {
services.deployer = {
enable = true;
bindAddr = "0.0.0.0:8088";
chainfireEndpoints = [ "http://192.168.100.11:2379" ];
clusterId = "plasmacloud-vm-cluster";
requireChainfire = true;
allowUnknownNodes = false;
allowUnauthenticated = false;
bootstrapToken = "vm-cluster-bootstrap-token";
adminToken = "vm-cluster-admin-token";
bootstrapFlakeBundle = pkgs.plasmacloudFlakeBundle;
seedClusterState = true;
};
services.nix-agent = {
enable = true;
chainfireEndpoint = "http://192.168.100.11:2379";
clusterId = "plasmacloud-vm-cluster";
nodeId = "node01";
flakeRoot = self.outPath;
intervalSecs = 30;
apply = true;
};
})
{ nixpkgs.overlays = [ self.overlays.default ]; }
];
};
node02 = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
disko.nixosModules.disko
nix-nos.nixosModules.default
./nix/nodes/vm-cluster/node02/configuration.nix
self.nixosModules.default
{
services.nix-agent = {
enable = true;
chainfireEndpoint = "http://192.168.100.11:2379";
clusterId = "plasmacloud-vm-cluster";
nodeId = "node02";
flakeRoot = self.outPath;
intervalSecs = 30;
apply = true;
};
}
{ nixpkgs.overlays = [ self.overlays.default ]; }
];
};
node03 = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
disko.nixosModules.disko
nix-nos.nixosModules.default
./nix/nodes/vm-cluster/node03/configuration.nix
self.nixosModules.default
{
services.nix-agent = {
enable = true;
chainfireEndpoint = "http://192.168.100.11:2379";
clusterId = "plasmacloud-vm-cluster";
nodeId = "node03";
flakeRoot = self.outPath;
intervalSecs = 30;
apply = true;
};
}
{ nixpkgs.overlays = [ self.overlays.default ]; }
];
};
};
# ========================================================================
# OVERLAY: Provides PhotonCloud packages to nixpkgs
# ========================================================================
# Usage in NixOS configuration:
# nixpkgs.overlays = [ inputs.photoncloud.overlays.default ];
overlays.default = final: prev: {
chainfire-server = self.packages.${final.system}.chainfire-server;
flaredb-server = self.packages.${final.system}.flaredb-server;
iam-server = self.packages.${final.system}.iam-server;
coronafs-server = self.packages.${final.system}.coronafs-server;
plasmavmc-server = self.packages.${final.system}.plasmavmc-server;
prismnet-server = self.packages.${final.system}.prismnet-server;
flashdns-server = self.packages.${final.system}.flashdns-server;
fiberlb-server = self.packages.${final.system}.fiberlb-server;
lightningstor-workspace = self.packages.${final.system}.lightningstor-workspace;
lightningstor-server = self.packages.${final.system}.lightningstor-workspace;
lightningstor-node = self.packages.${final.system}.lightningstor-workspace;
nightlight-server = self.packages.${final.system}.nightlight-server;
creditservice-server = self.packages.${final.system}.creditservice-server;
apigateway-server = self.packages.${final.system}.apigateway-server;
k8shost-server = self.packages.${final.system}.k8shost-server;
deployer-workspace = self.packages.${final.system}.deployer-workspace;
deployer-server = self.packages.${final.system}.deployer-workspace;
deployer-ctl = self.packages.${final.system}.deployer-workspace;
plasmacloud-reconciler = self.packages.${final.system}.deployer-workspace;
plasmacloudFlakeBundle = self.packages.${final.system}.plasmacloudFlakeBundle;
nix-agent = self.packages.${final.system}.deployer-workspace;
node-agent = self.packages.${final.system}.deployer-workspace;
fleet-scheduler = self.packages.${final.system}.deployer-workspace;
};
};
}