Compare commits

...
Sign in to create a new pull request.

11 commits

Author SHA1 Message Date
7ecbd46b53 Merge pull request 'chore: rootfs pkg' (#18) from lsjostro/push-ptznrypypruv into main
Some checks are pending
ci/woodpecker/push/ci Pipeline is pending
Reviewed-on: #18
2025-02-21 18:48:36 +01:00
a689fa9925
chore: rootfs pkg
Some checks are pending
ci/woodpecker/pr/ci Pipeline is pending
2025-02-21 18:44:46 +01:00
6dc82ee21f Merge pull request 'chore: add dbus-broker' (#17) from lsjostro/push-tsrlsoumoytp into main
Some checks are pending
ci/woodpecker/push/ci Pipeline is pending
Reviewed-on: #17
2025-02-21 10:44:36 +01:00
0dfda7560f
chore: add dbus-broker
Some checks are pending
ci/woodpecker/pr/ci Pipeline is pending
2025-02-21 10:40:09 +01:00
0f7958b596 Merge pull request 'Build image from scratch / without NixOS.' (#14) from dln/push-wxvqmqvrsxzv into main
Some checks are pending
ci/woodpecker/push/ci Pipeline is pending
Reviewed-on: #14
2025-02-19 15:24:42 +01:00
2ad53505eb Merge pull request 'silly uki image with the systemd-ukify tooling' (#16) from lsjostro/push-mzqkykluxntr into dln/push-wxvqmqvrsxzv
Some checks are pending
ci/woodpecker/pr/ci Pipeline is pending
Reviewed-on: #16
2025-02-19 15:23:36 +01:00
dbd4e729de
silly uki image with the systemd-ukify tooling
Some checks are pending
ci/woodpecker/pr/ci Pipeline is pending
2025-02-19 15:20:28 +01:00
52986e7e70 Merge pull request 'chore(systemd): remove nix store ref and disable some features' (#15) from lsjostro/push-tpqplksttywz into dln/push-wxvqmqvrsxzv
Some checks are pending
ci/woodpecker/pr/ci Pipeline is pending
Reviewed-on: #15
2025-02-17 11:34:40 +01:00
faf5fce8a4
chore(systemd): remove nix store ref and disable some features
Some checks are pending
ci/woodpecker/pr/ci Pipeline is pending
2025-02-17 10:45:01 +01:00
b784c94d42
WIP: Build image from scratch / without NixOS.
Some checks are pending
ci/woodpecker/pr/ci Pipeline is pending
An experiment to see if we can minimize the PatOS project even further,
and not have to adapt NixOS packages and config for our needs.
2025-02-14 13:07:01 +01:00
4702e0dddb
feat(systemd): enabled sysupdated
Some checks are pending
ci/woodpecker/push/ci Pipeline is pending
2025-02-12 15:06:07 +01:00
35 changed files with 3398 additions and 1165 deletions

View file

@ -1 +1,3 @@
nix_direnv_manual_reload
use flake
dotenv_if_exists

2
.gitignore vendored
View file

@ -4,6 +4,8 @@
.task
/result
/target
/out
/initrd.gz
.*.swp
.*.swo
.nixos-test-history

165
dbus-broker/default.nix Normal file
View file

@ -0,0 +1,165 @@
{
lib,
stdenv,
fetchFromGitHub,
pkgs,
...
}:
let
meta = {
maintainers = with lib.maintainers; [ peterhoeg ];
platforms = lib.platforms.linux;
};
dep =
{
pname,
version,
hash,
rev ? "v${version}",
buildInputs ? [ ],
}:
stdenv.mkDerivation {
inherit pname version;
src = fetchFromGitHub {
owner = "c-util";
repo = pname;
inherit hash rev;
};
nativeBuildInputs = with pkgs; [
meson
ninja
pkg-config
];
inherit buildInputs;
meta = meta // {
description = "The C-Util Project is a collection of utility libraries for the C11 language.";
homepage = "https://c-util.github.io/";
license = [
lib.licenses.asl20
lib.licenses.lgpl21Plus
];
};
};
# These libraries are not used outside of dbus-broker.
#
# If that changes, we can always break them out, but they are essentially
# part of the dbus-broker project, just in separate repositories.
c-dvar = dep {
pname = "c-dvar";
version = "1.1.0";
hash = "sha256-p/C+BktclVseCtZJ1Q/YK03vP2ClnYRLB1Vmj2OQJD4=";
buildInputs = [
c-stdaux
c-utf8
];
};
c-ini = dep {
pname = "c-ini";
version = "1.1.0";
hash = "sha256-wa7aNl20hkb/83c4AkQ/0YFDdmBs4XGW+WLUtBWIC98=";
buildInputs = [
c-list
c-rbtree
c-stdaux
c-utf8
];
};
c-list = dep {
pname = "c-list";
version = "3.1.0";
hash = "sha256-fp3EAqcbFCLaT2EstLSzwP2X13pi2EFpFAullhoCtpw=";
};
c-rbtree = dep {
pname = "c-rbtree";
version = "3.2.0";
hash = "sha256-dTMeawhPLRtHvMXfXCrT5iCdoh7qS3v+raC6c+t+X38=";
buildInputs = [ c-stdaux ];
};
c-shquote = dep {
pname = "c-shquote";
version = "1.1.0";
hash = "sha256-z6hpQ/kpCYAngMNfxLkfsxaGtvP4yBMigX1lGpIIzMQ=";
buildInputs = [ c-stdaux ];
};
c-stdaux = dep {
pname = "c-stdaux";
version = "1.5.0";
hash = "sha256-MsnuEyVCmOIr/q6I1qyPsNXp48jxIEcXoYLHbOAZtW0=";
};
c-utf8 = dep {
pname = "c-utf8";
version = "1.1.0";
hash = "sha256-9vBYylbt1ypJwIAQJd/oiAueh+4VYcn/KzofQuhUea0=";
buildInputs = [ c-stdaux ];
};
in
stdenv.mkDerivation (finalAttrs: {
pname = "dbus-broker";
version = "36";
src = fetchFromGitHub {
owner = "bus1";
repo = "dbus-broker";
rev = "v${finalAttrs.version}";
hash = "sha256-5dAMKjybqrHG57vArbtWEPR/svSj2ION75JrjvnnpVM=";
};
nativeBuildInputs = with pkgs; [
docutils
meson
ninja
pkg-config
];
buildInputs = [
c-dvar
c-ini
c-list
c-rbtree
c-shquote
c-stdaux
c-utf8
pkgs.dbus
pkgs.linuxHeaders
pkgs.systemd
];
mesonFlags = [
# while we technically support 4.9 and 4.14, the NixOS module will throw an
# error when using a kernel that's too old
"--prefix=/"
"--bindir=/usr/bin"
"-D=linux-4-17=true"
"-D=system-console-users=gdm,sddm,lightdm"
];
PKG_CONFIG_SYSTEMD_SYSTEMDSYSTEMUNITDIR = "/usr/lib/systemd/system";
PKG_CONFIG_SYSTEMD_SYSTEMDUSERUNITDIR = "/usr/lib/systemd/user";
PKG_CONFIG_SYSTEMD_CATALOGDIR = "/usr/lib/systemd/catalog";
preInstall = ''
export DESTDIR=${placeholder "out"}
'';
postInstall = ''
mkdir -p $out/usr/share
cp -Pr ${pkgs.dbus.out}/share/* $out/usr/share/
cp ${pkgs.dbus.out}/etc/systemd/system/dbus.socket $out/usr/lib/systemd/system/
find $out/usr/share/ -type d -exec chmod 755 {} \;
sed -i 's#/nix/store.*/share#/usr/share#' $out/usr/share/xml/dbus-1/catalog.xml
sed -i 's#/nix/store.*/libexec#/usr/bin#' $out/usr/share/dbus-1/system.conf
'';
doCheck = false;
meta = meta // {
description = "Linux D-Bus Message Broker";
homepage = "https://github.com/bus1/dbus-broker/wiki";
license = lib.licenses.asl20;
};
})

40
flake.lock generated
View file

@ -1,12 +1,30 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1737469691,
"narHash": "sha256-nmKOgAU48S41dTPIXAq0AHZSehWUn6ZPrUKijHAMmIk=",
"lastModified": 1739020877,
"narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9e4d5190a9482a1fb9d18adf0bdb83c6e506eaab",
"rev": "a79cfe0ebd24952b580b1cf08cd906354996d547",
"type": "github"
},
"original": {
@ -18,8 +36,24 @@
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",

126
flake.nix
View file

@ -2,90 +2,68 @@
description = "PatOS is a minimal, immutable Linux distribution specialized for the Patagia Platform.";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ self, nixpkgs }:
let
releaseVersion = "0.0.1";
system = "x86_64-linux";
updateUrl = "https://images.dl.patagia.dev/patos/";
pkgs = import nixpkgs { inherit system; };
in
{
nixosModules.devel.imports = [
./modules/profiles/devel.nix
];
self,
flake-utils,
nixpkgs,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs { inherit system; };
patosPkgs = self.packages.${system};
in
{
packages = {
default = self.packages.${system}.image;
image = pkgs.writeShellScriptBin "image" ''
set -ex
echo "make UKI..."
nixosModules.server.imports = [
./modules/profiles/server.nix
];
mkdir -p patos/efi/boot
${self.packages.${system}.systemd.out}/usr/bin/ukify build \
--linux ${self.packages.${system}.kernel.kernel}/bzImage \
--initrd ./initrd.gz \
--cmdline "console=ttyS0" \
-o patos/efi/boot/bootx64.efi
'';
nixosModules.image.imports = [
./modules
./modules/profiles/base.nix
./modules/image
];
kernel = pkgs.callPackage ./kernel { };
glibc = pkgs.callPackage ./glibc { };
systemd = pkgs.callPackage ./systemd { };
dbus-broker = pkgs.callPackage ./dbus-broker { };
rootfs = pkgs.callPackage ./rootfs { inherit patosPkgs; };
packages.${system} = {
devel =
(nixpkgs.lib.nixosSystem {
modules = [
(
{ ... }:
{
nixpkgs.hostPlatform = system;
system.stateVersion = "25.05";
}
)
{
system.image.updates.url = "${updateUrl}";
system.image.id = "patos";
system.image.version = releaseVersion;
image.compress = false;
}
self.nixosModules.image
self.nixosModules.devel
];
}).config.system.build.updatePackage;
mkinitrd = pkgs.callPackage ./utils/mkinitrd.nix { inherit patosPkgs; };
qemu-uefi-tpm = pkgs.callPackage ./utils/qemu-uefi-tpm.nix { };
};
patos =
(nixpkgs.lib.nixosSystem {
modules = [
(
{ ... }:
{
nixpkgs.hostPlatform = system;
system.stateVersion = "25.05";
}
)
{
system.image.updates.url = "${updateUrl}";
system.image.id = "patos";
system.image.version = releaseVersion;
}
self.nixosModules.image
self.nixosModules.server
];
}).config.system.build.updatePackage;
checks = {
simple-test = pkgs.runCommand "simple-test" { } ''
${self.packages.${system}.default}/bin/my-program
touch $out
'';
};
qemu-uefi-tpm = pkgs.callPackage ./utils/qemu-uefi-tpm.nix { inherit pkgs; };
};
formatter = pkgs.nixpkgs-fmt;
checks.${system} = {
podman = import ./tests/podman.nix { inherit pkgs self; };
system-update = import ./tests/system-update.nix { inherit pkgs self; };
};
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
erofs-utils
just
nixd
nixfmt-rfc-style
squashfs-tools-ng
self.packages.${system}.qemu-uefi-tpm
self.packages.${system}.mkinitrd
];
};
devShells.${system}.default = pkgs.mkShell {
buildInputs = with pkgs; [
erofs-utils
just
self.packages.${system}.qemu-uefi-tpm
squashfs-tools-ng
];
};
};
}
);
}

53
glibc/default.nix Normal file
View file

@ -0,0 +1,53 @@
{
pkgs,
stdenv,
...
}:
let
version = pkgs.glibc.version;
src = pkgs.glibc.src;
pname = "glibcPatos";
in
stdenv.mkDerivation (finalAttrs: {
inherit version;
inherit src;
inherit pname;
enableParallelBuilding = true;
dontPatchShebangs = true;
configureFlags = [
"--prefix=/"
"--libdir=/lib"
"--bindir=/bin"
"--sysconfdir=/etc"
];
preConfigure =
''
export PWD_P=$(type -tP pwd)
for i in configure io/ftwtest-sh; do
sed -i "$i" -e "s^/bin/pwd^$PWD_P^g"
done
mkdir ../build
cd ../build
configureScript="`pwd`/../$sourceRoot/configure"
'';
nativeBuildInputs = with pkgs; [
bison
python3Minimal
];
outputs = [
"out"
];
preInstall = ''
export DESTDIR=${placeholder "out"}
'';
})

16
kernel/default.nix Normal file
View file

@ -0,0 +1,16 @@
{ pkgs, ... }:
let
version = "6.13.2";
in
pkgs.linuxPackagesFor (
pkgs.linuxManualConfig {
version = "${version}-patos1";
modDirVersion = version;
src = pkgs.fetchurl {
url = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${version}.tar.xz";
hash = "sha256-zfYpgZBru+lwGutzxPn8yAegmEbCiHMWY9YnF+0a5wU=";
};
configfile = ./generic.config;
allowImportFromDerivation = true;
}
)

2513
kernel/generic.config Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,15 +0,0 @@
{ config, ... }:
{
boot = {
bootspec.enable = false;
initrd.kernelModules = config.boot.kernelModules;
kernel.enable = false; # No kernel or modules in the rootfs
modprobeConfig.enable = false;
};
system.build = {
inherit (config.boot.kernelPackages) kernel;
};
system.modulesTree = [ config.boot.kernelPackages.kernel ] ++ config.boot.extraModulePackages;
}

View file

@ -1,26 +0,0 @@
{ ... }:
{
nixpkgs.overlays = [
(final: prev: {
composefs = final.callPackage ../../pkgs/composefs.nix { inherit prev; };
qemu_tiny = final.callPackage ../../pkgs/qemu.nix { inherit prev; };
systemdUkify = final.callPackage ../../pkgs/systemd-ukify.nix { inherit prev; };
# # FIXME: Revisit + refine these below in a future image minimization effort
#
# util-linux = prev.util-linux.override {
# ncursesSupport = false;
# nlsSupport = false;
# };
#
# dbus = prev.dbus.override {
# enableSystemd = false;
# x11Support = false;
# };
})
];
}

View file

@ -1,6 +0,0 @@
{
imports = [
./config/minimal-modules.nix
./config/minimal-system.nix
];
}

View file

@ -1,196 +0,0 @@
{
config,
lib,
options,
pkgs,
...
}:
let
inherit (pkgs.stdenv.hostPlatform) efiArch;
initialPartitions = {
"10-root" = {
storePaths = [ config.system.build.toplevel ];
repartConfig = {
Type = "root";
Minimize = "best";
Format = "erofs";
MakeDirectories = "/home /root /etc /dev /sys /bin /var /proc /run /usr /usr/bin /srv /tmp /mnt /lib /boot";
Verity = "data";
VerityMatchKey = "root";
SplitName = "root";
};
};
"20-root-verity" = {
repartConfig = {
Type = "root-verity";
Minimize = "best";
Verity = "hash";
VerityMatchKey = "root";
SplitName = "verity";
};
};
};
# TODO: We don't need a combined image here - add dry-run flag to repart invocation
verityRepart = import (pkgs.path + "/nixos/lib/eval-config.nix") {
inherit lib pkgs;
system = null;
modules = [
(
{ modulesPath, ... }:
{
imports = [ (modulesPath + "/image/repart.nix") ];
image.repart = {
name = "verity";
split = true;
mkfsOptions = lib.mkIf config.image.compress {
erofs = [
"-zlz4hc,level=12"
"-Efragments,dedupe,ztailpacking"
];
};
partitions = initialPartitions;
};
}
)
];
};
rootPart = "${verityRepart.config.system.build.image}/${verityRepart.config.image.repart.imageFileBasename}.root.raw";
verityPart = "${verityRepart.config.system.build.image}/${verityRepart.config.image.repart.imageFileBasename}.verity.raw";
verityImgAttrs = builtins.fromJSON (
builtins.readFile "${verityRepart.config.system.build.image}/repart-output.json"
);
rootAttrs = builtins.elemAt verityImgAttrs 0;
verityAttrs = builtins.elemAt verityImgAttrs 1;
rootUuid = rootAttrs.uuid;
verityUuid = verityAttrs.uuid;
verityRootHash = rootAttrs.roothash;
finalPartitions = {
"10-esp" = {
contents = {
"/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source = "${pkgs.systemdUkify}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";
"/EFI/Linux/${config.system.boot.loader.ukiFile}".source = "${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
"/EFI/memtest86/memtest86.efi".source = "${pkgs.memtest86plus}/memtest.efi";
"/loader/entries/patos-factory-reset.conf".source = pkgs.writeText "patos-factory-reset.conf" ''
title Patos Factory Reset
efi /EFI/Linux/${config.system.boot.loader.ukiFile}
options ${toString config.boot.kernelParams} systemd.factory_reset=yes
sort-key z_factory_reset
'';
"/loader/entries/memtest86.conf".source = pkgs.writeText "memtest86.conf" ''
title Memtest86+
efi /EFI/memtest86/memtest86.efi
options console=ttyS0
sort-key z_memtest
'';
"/loader/loader.conf".source = pkgs.writeText "loader.conf" ''
timeout 2
'';
};
repartConfig = {
Type = "esp";
Format = "vfat";
SizeMinBytes = "96M";
SizeMaxBytes = "96M";
SplitName = "-";
};
};
"20-root-verity-a" = {
repartConfig = {
Type = "root-verity";
Label = "verity-${config.system.image.version}";
CopyBlocks = "${verityPart}";
SplitName = "-";
SizeMinBytes = "64M";
SizeMaxBytes = "64M";
UUID = "${verityUuid}";
ReadOnly = 1;
};
};
# TODO: Add signature partition for systemd-nspawn
"22-root-a" = {
repartConfig = {
Type = "root";
Label = "root-${config.system.image.version}";
CopyBlocks = "${rootPart}";
SplitName = "-";
UUID = "${rootUuid}";
ReadOnly = 1;
};
};
};
finalRepart = import (pkgs.path + "/nixos/lib/eval-config.nix") {
inherit lib pkgs;
system = null;
modules = [
(
{ modulesPath, ... }:
{
imports = [ (modulesPath + "/image/repart.nix") ];
image.repart = {
name = "${config.system.image.id}";
partitions = finalPartitions;
};
}
)
];
};
in
{
# This fields is immutable by default, but can be overridden.
options.system.nixos.codeName = lib.mkOption { readOnly = false; };
options.system.nixos.release = lib.mkOption { readOnly = false; };
# FIXME: Should be configured somehow
config.system.nixos = {
codeName = "Finn";
distroId = "patos";
distroName = "PatOS";
release = "2024-11";
variant_id = "server";
variantName = "Server";
vendorName = "PatOS";
};
options.image.compress = lib.mkEnableOption "image compression" // {
default = true;
};
config.system.build = {
inherit verityRootHash;
image =
(pkgs.linkFarm "image-release" [
{
name = "${config.system.image.id}_${config.system.image.version}.efi";
path = "${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
}
{
name = "${config.system.image.id}_${config.system.image.version}_${verityUuid}.verity";
path = "${verityRepart.config.system.build.image}/${verityRepart.config.image.repart.imageFileBasename}.verity.raw";
}
{
name = "${config.system.image.id}_${config.system.image.version}_${rootUuid}.root";
path = "${verityRepart.config.system.build.image}/${verityRepart.config.image.repart.imageFileBasename}.root.raw";
}
{
name = "${config.system.image.id}_${config.system.image.version}.img";
path = "${finalRepart.config.system.build.image}/${finalRepart.config.image.repart.imageFileBasename}.raw";
}
])
// {
imageFile = "${config.system.image.id}_${config.system.image.version}.img";
};
};
}

View file

@ -1,137 +0,0 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [
./updater.nix
./builder.nix
./veritysetup.nix
];
system.build.updatePackage = pkgs.runCommand "update-package" { } ''
mkdir "$out"
cd "$out"
cp "${config.system.build.image}"/* .
${pkgs.coreutils}/bin/sha256sum * > SHA256SUMS
'';
systemd.repart.partitions = {
"10-esp" = {
Type = "esp";
UUID = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"; # Well known
Format = "vfat";
SizeMinBytes = "96M";
SizeMaxBytes = "96M";
};
"20-root-verity-a" = {
Type = "root-verity";
SizeMinBytes = "64M";
SizeMaxBytes = "64M";
};
"22-root-a" = {
Type = "root";
SizeMinBytes = "512M";
SizeMaxBytes = "512M";
};
"30-root-verity-b" = {
Type = "root-verity";
SizeMinBytes = "64M";
SizeMaxBytes = "64M";
Label = "_empty";
ReadOnly = 1;
};
"32-root-b" = {
Type = "root";
SizeMinBytes = "512M";
SizeMaxBytes = "512M";
Label = "_empty";
ReadOnly = 1;
};
"40-var" = {
Type = "var";
UUID = "4d21b016-b534-45c2-a9fb-5c16e091fd2d"; # Well known
Format = "btrfs";
Label = "patos-state";
Minimize = "off";
FactoryReset = "yes";
Encrypt = "tpm2";
SizeMinBytes = "2G";
SplitName = "-";
};
};
boot.loader.grub.enable = false;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.systemd-boot.enable = true;
boot.uki.name = "patos";
boot.initrd = {
compressor = "zstd";
compressorArgs = [ "-8" ];
luks.forceLuksSupportInInitrd = true;
kernelModules = [
"dm_mod"
"dm_crypt"
] ++ config.boot.initrd.luks.cryptoModules;
supportedFilesystems = {
btrfs = true;
erofs = true;
};
systemd.enable = true;
systemd.repart.enable = true;
systemd.services.systemd-repart = {
after = lib.mkForce [ "sysroot.mount" ];
requires = [ "sysroot.mount" ];
serviceConfig.Environment = [
"SYSTEMD_REPART_MKFS_OPTIONS_BTRFS=--nodiscard"
];
};
};
system.etc.overlay.mutable = false;
users.mutableUsers = false;
boot.kernelParams = [
"rootfstype=erofs"
"rootflags=ro"
"roothash=${config.system.build.verityRootHash}"
];
fileSystems =
let
parts = config.systemd.repart.partitions;
in
{
"/var" = {
fsType = parts."40-var".Format;
device = "/dev/mapper/var";
encrypted = {
enable = true;
blkDev = "/dev/disk/by-partuuid/${parts."40-var".UUID}";
label = "var";
};
};
};
# Required to mount the efi partition
boot.kernelModules = [
"vfat"
"nls_cp437"
"nls_iso8859-1"
];
environment.etc."machine-id" = {
text = "";
mode = "0755";
};
# Refuse to boot on mount failure
systemd.targets."sysinit".requires = [ "local-fs.target" ];
}

View file

@ -1,87 +0,0 @@
{ config, lib, ... }:
{
options.system.image.updates = {
enable = lib.mkEnableOption "system updates via systemd-sysupdate" // {
default = config.system.image.updates.url != null;
};
url = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
};
config = lib.mkIf config.system.image.updates.enable {
assertions = [
{ assertion = config.system.image.updates.url != null; }
];
systemd.sysupdate.enable = true;
systemd.sysupdate.reboot.enable = lib.mkDefault true;
systemd.sysupdate.transfers = {
"10-uki" = {
Transfer = {
Verify = "no";
};
Source = {
Type = "url-file";
Path = "${config.system.image.updates.url}";
MatchPattern = "${config.boot.uki.name}_@v.efi";
};
Target = {
Type = "regular-file";
Path = "/EFI/Linux";
PathRelativeTo = "esp";
MatchPattern = "${config.boot.uki.name}_@v+@l-@d.efi ${config.boot.uki.name}_@v+@l.efi ${config.boot.uki.name}_@v.efi";
Mode = "0444";
TriesLeft = 3;
TriesDone = 0;
InstancesMax = 2;
};
};
"20-root-verity" = {
Transfer = {
Verify = "no";
};
Source = {
Type = "url-file";
Path = "${config.system.image.updates.url}";
MatchPattern = "${config.system.image.id}_@v_@u.verity";
};
Target = {
Type = "partition";
Path = "auto";
MatchPattern = "verity-@v";
MatchPartitionType = "root-verity";
ReadOnly = 1;
};
};
"22-root" = {
Transfer = {
Verify = "no";
};
Source = {
Type = "url-file";
Path = "${config.system.image.updates.url}";
MatchPattern = "${config.system.image.id}_@v_@u.root";
};
Target = {
Type = "partition";
Path = "auto";
MatchPattern = "root-@v";
MatchPartitionType = "root";
ReadOnly = 1;
};
};
};
systemd.additionalUpstreamSystemUnits = [
"systemd-bless-boot.service"
"boot-complete.target"
];
};
}

View file

@ -1,39 +0,0 @@
{ config, lib, ... }:
{
options.boot.initrd.systemd.root = lib.mkOption {
type = lib.types.enum [
"fstab"
"gpt-auto"
""
];
};
config.boot.initrd = {
kernelModules = [
"dm_mod"
"dm_verity"
];
systemd = {
# Required to activate systemd-fstab-generator
root = "";
additionalUpstreamUnits = [
"veritysetup-pre.target"
"veritysetup.target"
"remote-veritysetup.target"
];
storePaths = [
"${config.boot.initrd.systemd.package}/lib/systemd/systemd-veritysetup"
"${config.boot.initrd.systemd.package}/lib/systemd/system-generators/systemd-veritysetup-generator"
];
};
};
}

View file

@ -1,97 +0,0 @@
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/image-based-appliance.nix")
(modulesPath + "/profiles/perlless.nix")
(modulesPath + "/profiles/qemu-guest.nix")
];
# system.forbiddenDependenciesRegexes = lib.mkForce [ ];
nixpkgs.flake.setNixPath = false;
nixpkgs.flake.setFlakeRegistry = false;
boot.enableContainers = false;
boot.kernelModules = [
"zram"
"usb_storage"
"uas"
"sd_mod"
"r8169"
"ehci-hcd"
"ehci-pci"
"xhci-hcd"
"xhci-pci"
"xhci-pci-renesas"
"nvme"
"virtio_net"
"9p"
"9pnet_virtio"
];
system.etc.overlay.mutable = lib.mkDefault false;
systemd.watchdog = lib.mkDefault {
runtimeTime = "10s";
rebootTime = "30s";
};
zramSwap.enable = true;
# FIXME: fstrim should only be enabled for virtual machine images?
services.fstrim.enable = true;
users.allowNoPasswordLogin = true;
users.users.root.home = lib.mkForce "/";
security.sudo.enable = lib.mkDefault false;
security.polkit = {
enable = true;
extraConfig = ''
polkit.addRule(function(action, subject) {
if (subject.isInGroup("wheel")) {
return polkit.Result.YES;
}
});
'';
};
i18n.supportedLocales = [ "en_US.UTF-8/UTF-8" ];
# Console
systemd.enableEmergencyMode = false;
boot.consoleLogLevel = lib.mkDefault 1;
boot.kernelParams = [
"panic=1"
"boot.panic_on_fail"
# "nomodeset"
"console=ttyS0,115200n8"
"earlyprintk=ttyS0,115200n8"
"systemd.mask=systemd-vconsole-setup.service" # FIXME: Figure out why vconsole-setup fails when loading keymap
];
# This is vi country
programs.nano.enable = false;
programs.vim.enable = true;
programs.vim.defaultEditor = lib.mkDefault true;
# Temporary file
boot.tmp.useTmpfs = true;
# Logging
services.journald = {
storage = "volatile";
extraConfig = ''
SystemMaxUse=10M
'';
};
}

View file

@ -1,39 +0,0 @@
{
modulesPath,
...
}:
{
imports = [ ./server.nix ];
boot.kernel.sysctl = {
"net.ipv4.ip_unprivileged_port_start" = 0;
};
boot.kernelParams = [
"systemd.log_level=info"
"systemd.log_target=console"
"systemd.journald.forward_to_console"
];
users.users."admin" = {
isNormalUser = true;
linger = true;
extraGroups = [ "wheel" ];
home = "/var/home/admin";
};
environment.etc = {
subuid = {
text = "admin:100000:65536";
mode = "0644";
};
subgid = {
text = "admin:100000:65536";
mode = "0644";
};
};
services.getty.autologinUser = "admin";
}

View file

@ -1,65 +0,0 @@
{ lib, ... }:
{
# Use networkd
networking.useNetworkd = true;
systemd.network.wait-online.enable = true;
# Firewall
networking.firewall.enable = false;
networking.nftables.enable = lib.mkDefault true;
# DNS
services.resolved = {
fallbackDns = [ ]; # Disable fallback DNS. DNS will fail if resolvers are unconfigured
extraConfig = ''
DNSStubListener=no
'';
};
# Configuration
networking.hostName = "";
# Kernel
boot.kernel.sysctl = {
"net.core.default_qdisc" = "fq"; # FIXME: manage these with networkd?
"net.ipv4.tcp_congestion_control" = "bbr";
};
# Modules
boot.kernelModules = [
"ip_tables"
"x_tables"
"nf_tables"
"nft_ct"
"nft_log"
"nf_log_syslog"
"nft_fib"
"nft_fib_inet"
"nft_compat"
"nft_nat"
"nft_chain_nat"
"nft_masq"
"nfnetlink"
"xt_conntrack"
"nf_conntrack"
"nf_log_syslog"
"nf_nat"
"af_packet"
"bridge"
"veth"
"tcp_bbr"
"sch_fq_codel"
"ipt_rpfilter"
"ip6t_rpfilter"
"sch_fq"
"tun"
"tap"
"xt_MASQUERADE"
"xt_mark"
"xt_comment"
"xt_multiport"
"xt_addrtype"
];
}

View file

@ -1,18 +0,0 @@
{
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/minimal.nix")
./network.nix
./sysext.nix
];
boot.kernelParams = [
"quiet"
];
virtualisation.podman.enable = true;
}

View file

@ -1,23 +0,0 @@
{ ... }:
{
system.activationScripts.sysext = ''
mkdir -p /var/lib/confexts
mkdir -p /var/lib/extensions
mkdir -p /etc/systemd/extensions
'';
systemd.additionalUpstreamSystemUnits = [
"systemd-confext.service"
"systemd-sysext.service"
];
# systemd.services."systemd-confext" = {
# enable = true;
# wantedBy = [ "multi-user.target" ];
# };
# systemd.services."systemd-sysext.service" = {
# enable = true;
# wantedBy = [ "multi-user.target" ];
# };
}

View file

@ -1,5 +0,0 @@
{ prev, ... }:
prev.composefs.overrideAttrs (final: prev: {
doCheck = false;
})

View file

@ -1,12 +0,0 @@
{ stdenv, lib
, linux-firmware
, fwDirs
}: stdenv.mkDerivation {
pname = "linux-firmware-minimal";
version = linux-firmware.version;
buildCommand = lib.concatStringsSep "\n" (
[''mkdir -p "$out/lib/firmware"'']
++ (map (name: ''
cp -r "${linux-firmware}/lib/firmware/${name}" "$out/lib/firmware/${name}"
'') fwDirs));
}

View file

@ -1,30 +0,0 @@
{ prev, pkgs, ... }:
(prev.qemu_test.override {
enableDocs = false;
capstoneSupport = false;
guestAgentSupport = false;
tpmSupport = false;
libiscsiSupport = false;
usbredirSupport = false;
canokeySupport = false;
hostCpuTargets = [ "x86_64-softmmu" ];
}).overrideDerivation (old: {
postFixup = ''
rm -r "$out/share/icons"
cp "${pkgs.OVMF.fd + "/FV/OVMF.fd"}" "$out/share/qemu/"
'';
configureFlags = old.configureFlags ++ [
"--disable-tcg"
"--disable-tcg-interpreter"
"--disable-docs"
"--disable-install-blobs"
"--disable-slirp"
"--disable-virtfs"
"--disable-virtfs-proxy-helper"
"--disable-vhost-user-blk-server"
"--without-default-features"
"--enable-kvm"
"--disable-tools"
];
})

View file

@ -1,48 +0,0 @@
{ prev, ... }:
prev.systemd.override {
withAcl = false;
withAnalyze = false;
withApparmor = false;
withAudit = false;
withEfi = true;
withCompression = false;
withCoredump = false;
withCryptsetup = false;
withRepart = false;
withDocumentation = false;
withFido2 = false;
withFirstboot = false;
withHomed = false;
withHostnamed = false;
withHwdb = false;
withImportd = false;
withIptables = false;
withKmod = false;
withLibBPF = false;
withLibidn2 = false;
withLocaled = false;
withLogind = false;
withMachined = false;
withNetworkd = false;
withNss = false;
withOomd = false;
withPam = false;
withPasswordQuality = false;
withPCRE2 = false;
withPolkit = false;
withPortabled = false;
withQrencode = false;
withRemote = false;
withResolved = false;
withShellCompletions = false;
withSysusers = false;
withSysupdate = false;
withTimedated = false;
withTimesyncd = false;
withTpm2Tss = false;
withUkify = true;
withUserDb = false;
withUtmp = false;
withVmspawn = false;
}

View file

@ -1,10 +0,0 @@
{ prev, ... }:
prev.systemd.override {
withAcl = false;
withApparmor = false;
withDocumentation = false;
withRemote = false;
withShellCompletions = false;
withVmspawn = false;
}

30
rootfs/default.nix Normal file
View file

@ -0,0 +1,30 @@
{
pkgs,
stdenvNoCC,
patosPkgs,
...
}:
let
version = "0.0.1";
pname = "patos-rootfs";
in
stdenvNoCC.mkDerivation (finalAttrs: {
inherit version;
inherit pname;
buildInputs = with pkgs; [
glibc
binutils
];
glibcPatos = patosPkgs.glibc.out;
systemd = patosPkgs.systemd.out;
dbusBroker = patosPkgs.dbus-broker.out;
kernel = patosPkgs.kernel.kernel;
busybox = pkgs.busybox.out;
kmodLibs = pkgs.kmod.lib;
kmodBin = pkgs.kmod.out;
libbpf = pkgs.libbpf.out;
builder = ./mkrootfs.sh;
})

54
rootfs/mkrootfs.sh Normal file
View file

@ -0,0 +1,54 @@
set -ex -o pipefail
mkdir -p $out
mkdir -p $out/etc $out/dev $out/proc $out/sys $out/tmp $out/root
ln -sf ../usr/bin $out/bin
ln -sf ../usr/bin $out/sbin
ln -sf ../usr/lib $out/lib
ln -sf ../usr/lib $out/lib64
ln -sf ../proc/self/mounts $out/etc/mtab
### install systemd
echo "Installing systemd"
cp -Pr $systemd/* $out/
find $out -type d -exec chmod 755 {} \;
rm -rf $out/usr/include
rm -rf $out/usr/sbin
rm -f $out/usr/lib/systemd/system/sysinit.target.wants/systemd-firstboot.service
# remove vconsole setup
rm -f $out/usr/lib/udev/rules.d/90-vconsole.rules
### install PatOS glibc
cp -P $glibcPatos/lib/*.so* $out/usr/lib/
### install kernel modules
cp -r $kernel/lib/modules $out/usr/lib/
find $out/usr/lib/modules -type d -exec chmod 755 {} \;
### install busybox
cp $busybox/bin/busybox $out/usr/bin/
$out/usr/bin/busybox --list | xargs -I {} ln -sf busybox $out/usr/bin/{}
### install dbus broker
cp -r $dbusBroker/* $out/
### install lib kmod
cp -P $kmodLibs/lib/* $out/usr/lib
cp -P $kmodBin/bin/* $out/usr/bin
### install libbpf
cp -P $libbpf/lib/libbpf* $out/usr/lib
### Find and install all shared libs
find $out -type f -executable -exec ldd {} \; | awk '{print $3}' | grep -v systemd | grep -v glibc | sort -u | xargs cp -t $out/usr/lib
find $out -type f -executable -exec chmod 755 {} \;
# FIXME: ELF patching. Is there a better way?
find $out -type f -executable -exec patchelf --set-rpath /lib:/usr/lib:/usr/lib/systemd {} \;
find $out -type f -executable -exec patchelf --set-interpreter /lib/ld-linux-x86-64.so.2 {} \;
patchelf --remove-rpath $out/usr/lib/ld-linux-x86-64.so.2
# strip binaries
find $out -type f -executable -exec strip {} \;
find $out -type d -exec chmod 755 {} \;

View file

@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: nikstur <nikstur@outlook.com>
Date: Mon, 6 Nov 2023 22:51:38 +0100
Subject: [PATCH] meson.build: do not create systemdstatedir
---
meson.build | 1 -
1 file changed, 1 deletion(-)
diff --git a/meson.build b/meson.build
index bffda86845..cb5dcec0f9 100644
--- a/meson.build
+++ b/meson.build
@@ -2781,7 +2781,6 @@ install_data('LICENSE.GPL2',
install_subdir('LICENSES',
install_dir : docdir)
-install_emptydir(systemdstatedir)
#####################################################################

324
systemd/default.nix Normal file
View file

@ -0,0 +1,324 @@
{
fetchFromGitHub,
lib,
pkgs,
stdenv,
targetPackages,
...
}:
let
version = "257.3";
# Use the command below to update `releaseTimestamp` on every (major) version
# change. More details in the commentary at mesonFlags.
# command:
# $ curl -s https://api.github.com/repos/systemd/systemd/releases/latest | \
# jq '.created_at|strptime("%Y-%m-%dT%H:%M:%SZ")|mktime'
releaseTimestamp = "1734643670";
pname = "systemd";
in
stdenv.mkDerivation (finalAttrs: {
inherit version;
pname = pname;
src = fetchFromGitHub {
owner = "systemd";
repo = "systemd";
rev = "v${version}";
hash = "sha256-GvRn55grHWR6M+tA86RMzqinuXNpPZzRB4ApuGN/ZvU=";
};
dontCheckForBrokenSymlinks = true;
patches = [
./0017-meson.build-do-not-create-systemdstatedir.patch
];
nativeBuildInputs = with pkgs; [
bash
pkg-config
makeBinaryWrapper
gperf
ninja
meson
glibcLocales
getent
m4
autoPatchelfHook
intltool
gettext
libxslt
docbook_xsl
docbook_xml_dtd_42
docbook_xml_dtd_45
bash
(buildPackages.python3Packages.python.withPackages (
ps: with ps; [
lxml
jinja2
ps.pyelftools
]
))
bpftools
buildPackages.llvmPackages.clang
buildPackages.llvmPackages.libllvm
];
outputs = [
"out"
"dev"
];
separateDebugInfo = true;
autoPatchelfFlags = [ "--keep-libc" ];
hardeningDisable = [
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111523
"trivialautovarinit"
# breaks clang -target bpf; should be fixed to filter target?
"zerocallusedregs"
"shadowstack"
];
buildInputs = with pkgs; [
libxcrypt
libcap
libuuid
linuxHeaders
bashInteractive # for patch shebangs
libgcrypt
libgpg-error
openssl
acl
libapparmor
audit
zlib
bzip2
lz4
xz
zstd
elfutils
kexec-tools
kmod
libidn2
libseccomp
libselinux
iptables
p11-kit
libfido2
pam
pcre2
libbpf
tpm2-tss
qrencode
libarchive
(lib.getDev curl)
(lib.getDev cryptsetup.dev)
(python3Packages.python.withPackages (ps: with ps; [ pefile ]))
(llvmPackages.compiler-rt.override {
doFakeLibgcc = true;
})
];
mesonBuildType = "release";
doCheck = false; # fails a bunch of tests
preConfigure = ''
mesonFlagsArray+=(-Dntp-servers="0.europe.pool.ntp.org 1.europe.pool.ntp.org 2.europe.pool.ntp.org 3.europe.pool.ntp.org")
export LC_ALL="en_US.UTF-8";
'';
postPatch =
''
substituteInPlace meson.build \
--replace "find_program('clang'" "find_program('${stdenv.cc.targetPrefix}clang'"
''
+ ''
substituteInPlace src/ukify/ukify.py \
--replace \
"'readelf'" \
"'${targetPackages.stdenv.cc.bintools.targetPrefix}readelf'" \
--replace \
"/usr/lib/systemd/boot/efi" \
"$out/usr/lib/systemd/boot/efi"
''
# Finally, patch shebangs in scripts used at build time. This must not patch
# scripts that will end up in the output, to avoid build platform references
# when cross-compiling.
+ ''
shopt -s extglob
patchShebangs tools test src/!(rpm|kernel-install|ukify) src/kernel-install/test-kernel-install.sh
'';
# trigger the test -n "$DESTDIR" || mutate in upstreams build system
preInstall = ''
export DESTDIR=${placeholder "out"}
'';
mesonFlags = [
"--prefix=/usr"
"--sysconfdir=/etc"
"--localstatedir=/var"
"--libdir=/usr/lib"
"--bindir=/usr/bin"
"--includedir=/usr/include"
"--localedir=/usr/share/locale"
# Options
# We bump this attribute on every (major) version change to ensure that we
# have known-good value for a timestamp that is in the (not so distant)
# past. This serves as a lower bound for valid system timestamps during
# startup. Systemd will reset the system timestamp if this date is +- 15
# years from the system time.
# See the systemd v250 release notes for further details:
# https://github.com/systemd/systemd/blob/60e930fc3e6eb8a36fbc184773119eb8d2f30364/NEWS#L258-L266
(lib.mesonOption "time-epoch" releaseTimestamp)
(lib.mesonOption "version-tag" version)
(lib.mesonOption "mode" "release")
(lib.mesonOption "tty-gid" "3") # tty in NixOS has gid 3
(lib.mesonOption "kmod-path" "/usr/bin/kmod")
(lib.mesonOption "debug-shell" "/usr/bin/sh")
(lib.mesonOption "pamconfdir" "/etc/pam.d")
(lib.mesonOption "shellprofiledir" "/etc/profile.d")
(lib.mesonOption "dbuspolicydir" "/usr/share/dbus-1/system.d")
(lib.mesonOption "dbussessionservicedir" "/usr/share/dbus-1/services")
(lib.mesonOption "dbussystemservicedir" "/usr/share/dbus-1/system-services")
(lib.mesonOption "setfont-path" "/usr/bin/setfont")
(lib.mesonOption "loadkeys-path" "/usr/bin/loadkeys")
(lib.mesonOption "sulogin-path" "/usr/bin/sulogin")
(lib.mesonOption "nologin-path" "/usr/bin/nologin")
(lib.mesonOption "mount-path" "/usr/bin/mount")
(lib.mesonOption "umount-path" "/usr/bin/umount")
# SBAT
(lib.mesonOption "sbat-distro" "patos")
(lib.mesonOption "sbat-distro-summary" "PatOS")
(lib.mesonOption "sbat-distro-url" "https://patagia.io/")
(lib.mesonOption "sbat-distro-pkgname" pname)
(lib.mesonOption "sbat-distro-version" version)
# Users
(lib.mesonOption "system-uid-max" "999")
(lib.mesonOption "system-gid-max" "999")
# SysVinit
(lib.mesonOption "sysvinit-path" "")
(lib.mesonOption "sysvrcnd-path" "")
# SSH
# Disabled for now until someone makes this work.
(lib.mesonOption "sshconfdir" "no")
(lib.mesonOption "sshdconfdir" "no")
# Features
# Tests
(lib.mesonBool "tests" false)
(lib.mesonEnable "glib" false)
(lib.mesonEnable "dbus" false)
# Compression
(lib.mesonEnable "bzip2" true)
(lib.mesonEnable "lz4" true)
(lib.mesonEnable "xz" true)
(lib.mesonEnable "zstd" true)
(lib.mesonEnable "zlib" true)
# NSS
(lib.mesonEnable "nss-resolve" true)
(lib.mesonBool "nss-myhostname" true)
(lib.mesonBool "nss-systemd" true)
# Cryptsetup
(lib.mesonEnable "libcryptsetup" true)
(lib.mesonEnable "libcryptsetup-plugins" true)
(lib.mesonEnable "p11kit" true)
# FIDO2
(lib.mesonEnable "libfido2" true)
(lib.mesonEnable "openssl" true)
# Password Quality
(lib.mesonEnable "pwquality" false)
(lib.mesonEnable "passwdqc" false)
# Remote
(lib.mesonEnable "remote" false)
(lib.mesonEnable "microhttpd" false)
(lib.mesonEnable "pam" false)
(lib.mesonEnable "acl" true)
(lib.mesonEnable "audit" true)
(lib.mesonEnable "apparmor" true)
(lib.mesonEnable "gcrypt" true)
(lib.mesonEnable "importd" true)
(lib.mesonEnable "homed" false)
(lib.mesonEnable "polkit" true)
(lib.mesonEnable "elfutils" true)
(lib.mesonEnable "libcurl" true)
(lib.mesonEnable "libidn" false)
(lib.mesonEnable "libidn2" true)
(lib.mesonEnable "libiptc" true)
(lib.mesonEnable "repart" true)
(lib.mesonEnable "sysupdate" true)
(lib.mesonEnable "sysupdated" true)
(lib.mesonEnable "seccomp" true)
(lib.mesonEnable "selinux" true)
(lib.mesonEnable "tpm2" true)
(lib.mesonEnable "pcre2" true)
(lib.mesonEnable "bpf-framework" true)
(lib.mesonEnable "bootloader" true)
(lib.mesonEnable "ukify" true)
(lib.mesonEnable "kmod" true)
(lib.mesonEnable "qrencode" true)
(lib.mesonEnable "vmspawn" false)
(lib.mesonEnable "libarchive" true)
(lib.mesonEnable "xenctrl" false)
(lib.mesonEnable "gnutls" false)
(lib.mesonEnable "xkbcommon" false)
(lib.mesonEnable "man" false)
(lib.mesonBool "analyze" true)
(lib.mesonBool "logind" true)
(lib.mesonBool "localed" false)
(lib.mesonBool "hostnamed" true)
(lib.mesonBool "machined" true)
(lib.mesonBool "networkd" true)
(lib.mesonBool "oomd" true)
(lib.mesonBool "portabled" true)
(lib.mesonBool "hwdb" true)
(lib.mesonBool "timedated" true)
(lib.mesonBool "timesyncd" true)
(lib.mesonBool "userdb" false)
(lib.mesonBool "coredump" true)
(lib.mesonBool "firstboot" true)
(lib.mesonBool "resolve" true)
(lib.mesonBool "sysusers" true)
(lib.mesonBool "efi" true)
(lib.mesonBool "utmp" true)
(lib.mesonBool "log-trace" true)
(lib.mesonBool "kernel-install" true)
(lib.mesonBool "quotacheck" false)
(lib.mesonBool "ldconfig" false)
(lib.mesonBool "install-sysconfdir" true)
(lib.mesonBool "create-log-dirs" true)
(lib.mesonBool "smack" true)
(lib.mesonBool "b_pie" true)
(lib.mesonOption "bashcompletiondir" "no")
(lib.mesonOption "zshcompletiondir" "no")
];
})

View file

@ -1,155 +0,0 @@
{
self,
lib,
pkgs,
...
}:
with import (pkgs.path + "/nixos/lib/testing-python.nix") {
inherit pkgs;
inherit (pkgs.hostPlatform) system;
};
let
qemu-common = import (pkgs.path + "/nixos/lib/qemu-common.nix") { inherit lib pkgs; };
in
rec {
makeSystem =
extraConfig:
(import (pkgs.path + "/nixos/lib/eval-config.nix")) {
inherit pkgs lib;
system = null;
modules = [
{
nixpkgs.hostPlatform = pkgs.hostPlatform;
}
{
users.allowNoPasswordLogin = true;
system.stateVersion = lib.versions.majorMinor lib.version;
system.image.id = lib.mkDefault "test";
system.image.version = lib.mkDefault "1";
networking.hosts."10.0.2.1" = [ "server.test" ];
}
{
boot.kernelParams = [
"console=ttyS0,115200n8"
"systemd.journald.forward_to_console=1"
];
image.compress = false;
boot.uki.name = lib.mkForce "test";
boot.initrd.compressor = lib.mkForce "zstd";
boot.initrd.compressorArgs = lib.mkForce [ "-8" ];
}
(pkgs.path + "/nixos/modules/testing/test-instrumentation.nix")
self.nixosModules.devel
self.nixosModules.image
extraConfig
];
};
makeImage =
extraConfig:
let
system = makeSystem extraConfig;
in
"${system.config.system.build.image}/${system.config.system.build.image.imageFile}";
makeUpdatePackage =
extraConfig:
let
system = makeSystem extraConfig;
in
"${system.config.system.build.updatePackage}";
makeImageTest =
{
name,
image,
script,
httpRoot ? null,
}:
let
qemu = qemu-common.qemuBinary pkgs.qemu_test;
flags = [
"-m"
"512M"
"-drive"
"if=pflash,format=raw,unit=0,readonly=on,file=${pkgs.OVMF.firmware}"
"-drive"
"if=pflash,format=raw,unit=1,readonly=on,file=${pkgs.OVMF.variables}"
"-drive"
"if=virtio,file=${mutableImage}"
"-chardev"
"socket,id=chrtpm,path=${tpmFolder}/swtpm-sock"
"-tpmdev"
"emulator,id=tpm0,chardev=chrtpm"
"-device"
"tpm-tis,tpmdev=tpm0"
"-netdev"
(
"'user,id=net0"
+ (lib.optionalString (
httpRoot != null
) ",guestfwd=tcp:10.0.2.1:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${httpRoot}")
+ "'"
)
"-device"
"virtio-net-pci,netdev=net0"
];
flagsStr = lib.concatStringsSep " " flags;
startCommand = "${qemu} ${flagsStr}";
mutableImage = "/tmp/linked-image.qcow2";
tpmFolder = "/tmp/emulated_tpm";
indentLines = str: lib.concatLines (map (s: " " + s) (lib.splitString "\n" str));
in
makeTest {
inherit name;
nodes = { };
testScript =
''
import os
import subprocess
subprocess.check_call(
[
"qemu-img",
"create",
"-f",
"qcow2",
"-F",
"raw",
"-b",
"${image}",
"${mutableImage}",
]
)
subprocess.check_call(["qemu-img", "resize", "${mutableImage}", "4G"])
os.mkdir("${tpmFolder}")
os.mkdir("${tpmFolder}/swtpm")
def start_tpm():
subprocess.Popen(
[
"${pkgs.swtpm}/bin/swtpm",
"socket",
"--tpmstate", "dir=${tpmFolder}/swtpm",
"--ctrl", "type=unixio,path=${tpmFolder}/swtpm-sock",
"--tpm2"
]
)
machine = create_machine("${startCommand}")
try:
''
+ indentLines script
+ ''
finally:
machine.shutdown()
'';
};
}

View file

@ -1,9 +0,0 @@
test:
{ pkgs, self }:
let nixos-lib = import (pkgs.path + "/nixos/lib") {};
in (nixos-lib.runTest {
hostPkgs = pkgs;
defaults.documentation.enable = false;
node.specialArgs = { inherit self; };
imports = [ test ];
}).config.result

View file

@ -1,22 +0,0 @@
{ pkgs, self }: let
lib = pkgs.lib;
test-common = import ./common.nix { inherit self lib pkgs; };
image = test-common.makeImage { };
in test-common.makeImageTest {
name = "podman";
inherit image;
script = ''
start_tpm()
machine.start()
machine.wait_for_unit("multi-user.target")
machine.wait_for_unit("network-online.target")
machine.succeed("tar cv --files-from /dev/null | su admin -l -c 'podman import - scratchimg'")
machine.succeed("su admin -l -c 'podman run --rm -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg true'")
'';
}

View file

@ -1,45 +0,0 @@
{ pkgs, self }: let
lib = pkgs.lib;
test-common = import ./common.nix { inherit self lib pkgs; };
initialImage = test-common.makeImage {
system.image.version = "1";
system.image.updates.url = "http://server.test/";
# The default root-b is too small for uncompressed test images
systemd.repart.partitions."32-root-b" = {
SizeMinBytes = lib.mkForce "1G";
SizeMaxBytes = lib.mkForce "1G";
};
};
updatePackage = test-common.makeUpdatePackage {
system.image.version = "2";
system.image.updates.url = "http://server.test/";
};
in test-common.makeImageTest {
name = "system-update";
image = initialImage;
httpRoot = updatePackage;
script = ''
start_tpm()
machine.start()
machine.wait_for_unit("multi-user.target")
machine.wait_for_unit("network-online.target")
machine.succeed("/run/current-system/sw/lib/systemd/systemd-sysupdate update")
machine.shutdown()
start_tpm()
machine.start()
machine.wait_for_unit("multi-user.target")
machine.succeed('. /etc/os-release; [ "$IMAGE_VERSION" == "2" ]')
machine.wait_for_unit("systemd-bless-boot.service")
'';
}

125
utils/mkinitrd.nix Normal file
View file

@ -0,0 +1,125 @@
{
pkgs,
patosPkgs,
...
}:
pkgs.writeShellApplication {
name = "mkinitrd";
runtimeInputs = with pkgs; [
cpio
gzip
];
text = ''
echo "Building initram disk"
mkdir -p root
pushd root
### copy rootfs
cp -prP ${patosPkgs.rootfs}/* .
find . -type d -exec chmod 755 {} \;
### create directories
ln -sf ../usr/lib/systemd/systemd init
# set default target to basic
mkdir usr/lib/systemd/system/basic.target.wants
ln -sf basic.target usr/lib/systemd/system/default.target
# enable dbus broker
ln -sf ../dbus-broker.service usr/lib/systemd/system/basic.target.wants/dbus.service
ln -sf ../dbus.socket usr/lib/systemd/system/sockets.target.wants/dbus.socket
### Create needed files
echo patos > ./etc/hostname
cat <<EOF > ./etc/os-release
NAME="PatOS"
PRETTY_NAME="PatOS Platform"
ID=patos
EOF
cat <<EOF > ./etc/passwd
root::0:0:root:/root:/bin/sh
bin:x:1:1:bin:/bin:/usr/bin/nologin
daemon:x:2:2:daemon:/:/usr/bin/nologin
mail:x:8:12:mail:/var/spool/mail:/usr/bin/nologin
ftp:x:14:11:ftp:/srv/ftp:/usr/bin/nologin
http:x:33:33:http:/srv/http:/usr/bin/nologin
uuidd:x:68:68:uuidd:/:/usr/bin/nologin
messagebus:x:81:81:messagebus:/:/usr/bin/nologin
nobody:x:99:99:nobody:/:/usr/bin/nologin
EOF
chmod 644 ./etc/passwd
cat <<EOF > ./etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin
adm:x:4:root,daemon
tty:x:5:
disk:x:6:root
lp:x:7:daemon
mem:x:8:
kmem:x:9:
wheel:x:10:root
ftp:x:11:
mail:x:12:
uucp:x:14:
log:x:19:root
utmp:x:20:
locate:x:21:
rfkill:x:24:
smmsp:x:25:
proc:x:26:
http:x:33:
games:x:50:
lock:x:54:
uuidd:x:68:
messagebus:x:81:
network:x:90:
video:x:91:
audio:x:92:
optical:x:93:
floppy:x:94:
storage:x:95:
scanner:x:96:
input:x:97:
power:x:98:
nobody:x:99:
EOF
chmod 644 ./etc/group
# FIXME: remove this later (just to get a shell in the initramfs)
cat <<EOF > usr/lib/systemd/system/demo.service
[Unit]
Description=Debug Shell (/bin/sulogin)
Conflicts=shutdown.target
Before=shutdown.target
[Service]
Environment=HOME=/root
WorkingDirectory=/root
ExecStart=/bin/sulogin
Type=idle
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes
Restart=always
[Install]
WantedBy=basic.target
EOF
ln -sf ../demo.service usr/lib/systemd/system/basic.target.wants/demo.service
# gen initrd
find . -print0 | cpio --null --owner=root:root -o --format=newc | gzip -9 > ../initrd.gz
popd
rm -rf root
'';
}

View file

@ -1,5 +1,4 @@
{
config,
pkgs,
...
}:
@ -20,7 +19,7 @@ pkgs.writeShellApplication {
state="/tmp/patos-qemu-$USER"
rm -rf "$state"
mkdir -m 700 "$state"
qemu-img create -f qcow2 -F raw -b "$(readlink -e "$1")" "$state/disk.qcow2" 10G
truncate -s 1G "$state/disk.raw"
swtpm socket -d --tpmstate dir="$state" \
--ctrl type=unixio,path="$state/swtpm-sock" \
@ -34,7 +33,7 @@ pkgs.writeShellApplication {
-smp 8 \
-m 4G \
-display none \
-virtfs "local,path=/tmp,security_model=mapped,mount_tag=shared" \
-nographic \
-chardev "stdio,id=char0,mux=on,logfile=$state/console.log,signal=off" \
-serial chardev:char0 \
-mon chardev=char0 \
@ -45,6 +44,7 @@ pkgs.writeShellApplication {
-device tpm-tis,tpmdev=tpm0 \
-netdev id=net00,type=user,hostfwd=tcp::2222-:22 \
-device virtio-net-pci,netdev=net00 \
-drive "format=qcow2,file=$state/disk.qcow2"
-drive "file=fat:rw:patos/,format=raw" \
-drive "format=raw,file=$state/disk.raw"
'';
}