Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/actions/release_artifacts/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ runs:
CONTAINER_REGISTRY: ${{ inputs.container_registry }}
SET: base
run: |
coordinatorImg=$(nix run ".#${SET}.containers.push-coordinator" -- "${CONTAINER_REGISTRY}/contrast/coordinator")
nodeInstallerKataImg=$(nix run ".#${SET}.containers.push-node-installer-kata" -- "${CONTAINER_REGISTRY}/contrast/node-installer-kata")
nodeInstallerKataGPUImg=$(nix run ".#${SET}.containers.push-node-installer-kata-gpu" -- "${CONTAINER_REGISTRY}/contrast/node-installer-kata-gpu")
initializerImg=$(nix run ".#${SET}.containers.push-initializer" -- "${CONTAINER_REGISTRY}/contrast/initializer")
serviceMeshImg=$(nix run ".#${SET}.containers.push-service-mesh-proxy" -- "${CONTAINER_REGISTRY}/contrast/service-mesh-proxy")
debugShellImg=$(nix run ".#${SET}.containers.push-debugshell" -- "${CONTAINER_REGISTRY}/contrast/debugshell")
coordinatorImg=$(nix run ".#${SET}.container-scripts.push-coordinator" -- "${CONTAINER_REGISTRY}/contrast/coordinator")
nodeInstallerKataImg=$(nix run ".#${SET}.container-scripts.push-node-installer-kata" -- "${CONTAINER_REGISTRY}/contrast/node-installer-kata")
nodeInstallerKataGPUImg=$(nix run ".#${SET}.container-scripts.push-node-installer-kata-gpu" -- "${CONTAINER_REGISTRY}/contrast/node-installer-kata-gpu")
initializerImg=$(nix run ".#${SET}.container-scripts.push-initializer" -- "${CONTAINER_REGISTRY}/contrast/initializer")
serviceMeshImg=$(nix run ".#${SET}.container-scripts.push-service-mesh-proxy" -- "${CONTAINER_REGISTRY}/contrast/service-mesh-proxy")
debugShellImg=$(nix run ".#${SET}.container-scripts.push-debugshell" -- "${CONTAINER_REGISTRY}/contrast/debugshell")
echo "coordinatorImg=$coordinatorImg" | tee -a "$GITHUB_OUTPUT"
echo "nodeInstallerMsftImg=$nodeInstallerMsftImg" | tee -a "$GITHUB_OUTPUT"
echo "nodeInstallerKataImg=$nodeInstallerKataImg" | tee -a "$GITHUB_OUTPUT"
Expand Down
4 changes: 3 additions & 1 deletion .github/actions/setup_nix/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ runs:
using: "composite"
steps:
- name: Allow unrestricted user namespaces
if: runner.os == 'Linux'
# Ubuntu 24.04 ships strict apparmor defaults, so we have to disable them to be able to call
# unshare in the Nix sansbox without beeing root.
shell: bash
run: |
sudo sysctl --ignore --write kernel.apparmor_restrict_unprivileged_unconfined=0
sudo sysctl --ignore --write kernel.apparmor_restrict_unprivileged_userns=0
- name: use btrfs for nix builds
if: runner.os == 'Linux'
shell: bash
run: |
echo "Setting up btrfs /nix volume..."
Expand All @@ -33,7 +35,7 @@ runs:
- uses: cachix/install-nix-action@2126ae7fc54c9df00dd18f7f18754393182c73cd # v31.9.1
with:
github_access_token: ${{ inputs.githubToken }}
extra_nix_config: "build-dir = /nix/bld"
extra_nix_config: ${{ runner.os == 'Linux' && 'build-dir = /nix/bld' || '' }}
- uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
with:
name: edgelesssys
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,26 @@ jobs:
- name: Build CLI
run: |
nix build ".#${SET}.contrast.cli"

darwin-cli-build:
needs: cli-build
runs-on: macos-latest
timeout-minutes: 60
permissions:
contents: read
env:
SET: base
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: ./.github/actions/setup_nix
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
cachixToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build darwin formatter
run: |
nix build .#formatter.aarch64-darwin
- name: Build darwin CLI
run: |
nix build ".#${SET}.contrast.cli"
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ If you are struggling with your git history during the review process, please as

### Development setup

> [!NOTE]
> If you are developing on macOS/Darwin, you have to first follow the **experimental** [developer documentation for macOS](./dev-docs/macos.md), and then proceed with the rest of the setup.

1. [Install Nix](https://nixos.org/download/#multi-user-installation-recommended)

Enable the experimental features `nix-command` and `flakes` in your Nix configuration.
Expand Down
70 changes: 70 additions & 0 deletions dev-docs/macos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Development setup for macOS (experimental)

Contrast uses `just` and Nix as its build system. Several packages Contrast needs to build, such as container images (`nix build .#base.containers.*`), need to be built for `x86_64-linux` so when building from a different architecture such as `aarch64-darwin`, those builds need to be delegated to a builder that can build for `x86_64-linux`.

## Canonical setup

1. Install Nix. You have several options such the [Lix installer](https://lix.systems/install/) (recommended), the [Determinate Nix installer](https://docs.determinate.systems/) or by following the [official instructions](https://nixos.org/download/). It's recommended to use one of the automated installers as they also make the uninstall on macOS easy.

2. Setup a `x86_64-linux` builder. There are 2 options:

- setup a remote builder by following Nix's [distributed builds tutorial](https://nix.dev/tutorials/nixos/distributed-builds-setup.html). If you are working for Edgeless Systems, you can use one of our office machines by following the instructions in https://github.com/edgelesssys/nix-remote-builders.
- setup a local VM-based builder that emulates x86, by installing [nix-rosetta-builder](https://github.com/cpick/nix-rosetta-builder). Not that the performance of this option might not be great but it's helpful if you need to work offline.

It's recommended to setup both. Nix will automatically offload packages that need to be built for `x86_64-linux` to any builder available for that architecture. So if one of the remote machines isn't available, builds will use the VM-based builder.

## Alternative setup using a Linux VM

Alternatively you can setup a VM with Nix which you can use to build contrast. Since this option will be also using emulation, the performance might not be great.

1. Follow the instructions on [nixos-lima](https://github.com/nixos-lima/nixos-lima) and [nixos-lima-config-sample](https://github.com/nixos-lima/nixos-lima-config-sample) to create a `x86_64-linux` VM.

2. To avoid having to authenticate twice either with your container registry or kubectl, you can forward the local credentials to the VM by adding the following in the VM configuration:

```yaml
- location: "~/.docker"
mountPoint: "/home/lima.linux/.docker"
writable: true
9p:
cache: "mmap"
- location: "~/.kube"
mountPoint: "/home/lima.linux/.kube"
writable: true
```

3. Forward contrast project path as well:

```yaml
- location: "~/contrast"
writable: true
9p:
cache: "mmap"
```

4. Add the lima user to trusted-users by adding the following in the VM's NixOS configuration (`configuration.nix`):

```nix
nix.settings.trusted-users = [ "root" "@wheel" ];
```

5. (Optional) You might have to add the hosts you are deploying to in the VM's NixOS configuration:

```nix
networking.hosts = {
"XXX.YYY.ZZZ.XXX" = [ "<SOME HOSTNAME>" ];
};
```

6. Start a `x86_64` VM with:

```bash
limactl start --yes --set '.user.name = "lima"' nixos.yaml --arch=x86_64
```

7. Connect to the VM with:

```
cd ~/contrast
limactl shell nixos
nix develop .#
```
8 changes: 5 additions & 3 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
setsFromDirectory =
dir:
builtins.listToAttrs (
map (file: {
map (file: rec {
name = builtins.substring 0 (builtins.stringLength file - 4) (baseNameOf file);
value = mkSet (defaultOverlays ++ [ (import (dir + "/${file}")) ]);
value = mkSet ((defaultOverlays name) ++ [ (import (dir + "/${file}")) ]);
}) (builtins.attrNames (builtins.readDir dir))
);

Expand All @@ -65,10 +65,12 @@
];
};

defaultOverlays = [
defaultOverlays = set: [
(final: _prev: { fenix = self.inputs.fenix.packages.${final.stdenv.hostPlatform.system}; })
(_final: _prev: { runtimePkgs = self.legacyPackages.x86_64-linux.${set}; })
(import ./overlays/nixpkgs.nix)
(import ./overlays/contrast.nix)
(import ./overlays/runtimepkgs.nix)
];

sets = setsFromDirectory ./overlays/sets;
Expand Down
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ push target set=default_set:
set -euo pipefail
mkdir -p {{ workspace_dir }}
echo "Pushing container $container_registry/contrast/{{ target }}"
nix run -L .#{{ set }}.containers.push-{{ target }} -- "$container_registry/contrast/{{ target }}" "{{ workspace_dir }}/just.containerlookup" "{{ workspace_dir }}/layers-cache.json"
nix run -L .#{{ set }}.container-scripts.push-{{ target }} -- "$container_registry/contrast/{{ target }}" "{{ workspace_dir }}/just.containerlookup" "{{ workspace_dir }}/layers-cache.json"

coordinator: (push "coordinator")

Expand Down
62 changes: 62 additions & 0 deletions overlays/runtimepkgs.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Copyright 2026 Edgeless Systems GmbH
# SPDX-License-Identifier: BUSL-1.1

final: prev:

if prev.stdenv.hostPlatform.system == "x86_64-linux" then
{ }
else
{
contrastPkgs = prev.contrastPkgs.overrideScope (
_cFinal: cPrev: {
kata = cPrev.kata.overrideScope (
_: _: {
inherit (final.runtimePkgs.kata)
contrast-node-installer-image
agent
image
kernel-uvm
calculateSnpLaunchDigest
calculateTdxLaunchDigests
;
}
);

contrast = cPrev.contrast.overrideScope (
_: _: {
inherit (final.runtimePkgs.contrast)
coordinator
initializer
node-installer-image
nodeinstaller
;
}
);

inherit (final.runtimePkgs)
debugshell
service-mesh
k8s-log-collector
boot-image
boot-microvm
qemu-cc
pause-bundle
OVMF-TDX
calculateSnpIDBlock
;

scripts = cPrev.scripts.overrideScope (
_: _: {
inherit (final.runtimePkgs.scripts)
cleanup-bare-metal
cleanup-images
cleanup-containerd
nix-gc
;
}
);

inherit (final.runtimePkgs) containers;
}
);
}
10 changes: 9 additions & 1 deletion packages/by-name/contrast/cli/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

{
lib,
stdenv,
buildGoModule,
contrast,
kata,
Expand Down Expand Up @@ -54,7 +55,14 @@ buildGoModule (finalAttrs: {
nativeBuildInputs = [ installShellFiles ];

prePatch = ''
install -D ${lib.getExe contrastPkgsStatic.kata.genpolicy} cli/genpolicy/assets/genpolicy-kata
# On linux, use the statically linked genpolicy (portable across distros).
# On darwin, use the native build (macOS doesn't support static binaries
# and system libraries are always present).
install -D ${
lib.getExe (
if stdenv.hostPlatform.isDarwin then kata.genpolicy else contrastPkgsStatic.kata.genpolicy
)
} cli/genpolicy/assets/genpolicy-kata
Comment on lines +58 to +65
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhhh I get now what you meant in the other comment. Did the "old" version, i.e. overriding contrastStaticPkgs in the runtimepkgs overlay work? If so, that approach + a comment would be preferable, otherwise we are already starting to handle darwin-specifics in different places...

install -D ${kata.genpolicy.rules}/genpolicy-rules.rego cli/genpolicy/assets/genpolicy-rules-kata.rego
install -D ${reference-values} internal/manifest/assets/reference-values.json
install -D ${snp-id-blocks} cli/cmd/assets/snp-id-blocks.json
Expand Down
2 changes: 2 additions & 0 deletions packages/by-name/kata/genpolicy/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ rustPlatform.buildRustPackage rec {
};

env.OPENSSL_NO_VENDOR = 1;
env.OPENSSL_DIR = "${openssl.dev}";
env.OPENSSL_LIB_DIR = "${lib.getLib openssl}/lib";

nativeBuildInputs = [
cmake
Expand Down
41 changes: 41 additions & 0 deletions packages/container-scripts.nix
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than a new scope, could we nest this in scripts? You can just move this file to packages/by-name/scripts/.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright 2026 Edgeless Systems GmbH
# SPDX-License-Identifier: BUSL-1.1

{
lib,
pkgs,
contrastPkgs,
writeShellApplication,
}:

let
pushOCIDir =
name: dir: tag:
writeShellApplication {
name = "push-${name}";
runtimeInputs = with pkgs; [ crane ];
text = ''
imageName="$1"
containerlookup="''${2:-/dev/null}"
layersCache="''${3:-$(mktemp)}"
hash=$(crane push "${dir}" "$imageName:${tag}")
printf "ghcr.io/edgelesssys/contrast/%s:latest=%s\n" "${name}" "$hash" >> "$containerlookup"
if [ ! -f "$layersCache" ]; then
echo -n "[]" > "$layersCache"
fi
jq -s 'add' "$layersCache" "${dir}/layers-cache.json" > tmp.json && mv tmp.json "$layersCache"
echo "$hash"
'';
};
in
{
push-node-installer-kata =
pushOCIDir "node-installer-kata" contrastPkgs.contrast.node-installer-image
"v${contrastPkgs.contrast.nodeinstaller.version}";
push-node-installer-kata-gpu =
pushOCIDir "node-installer-kata-gpu" contrastPkgs.contrast.node-installer-image.gpu
"v${contrastPkgs.contrast.nodeinstaller.version}";
}
// (lib.concatMapAttrs (name: container: {
"push-${name}" = pushOCIDir name container.outPath container.meta.tag;
}) contrastPkgs.containers)
Loading
Loading