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
2 changes: 1 addition & 1 deletion .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,6 @@ jobs:
--copy conformance-input/openshell-conformance:/tmp/openshell-conformance \
--copy nix/test-guest/conformance-plans/gateway-upgrade-restart.toml:/tmp/conformance-plan.toml \
--provision openshell-rpm-latest-release \
--provision gateway-rootless-podman \
--provision gateway-podman \
--provision openshell-rpm-gateway-upgrade \
-- /tmp/openshell-conformance run --plan /tmp/conformance-plan.toml
45 changes: 29 additions & 16 deletions nix/test-guest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ nix/test-guest/
│ └── rocky.nix
└── configuration/
├── docker.yml
├── podman-rootful.yml
├── podman-rootless.yml
├── tasks/
│ ├── podman-common.yml
Expand All @@ -50,7 +51,7 @@ nix/test-guest/
└── selinux.yml
└── provisioners/
└── roles/
├── gateway-rootless-podman/
├── gateway-podman/
├── openshell-development/
├── openshell-rpm/
└── openshell-rpm-gateway-upgrade/
Expand All @@ -70,13 +71,13 @@ The root [`flake.nix`](../../flake.nix) exposes this directory as the `test-gues

## Supported configurations

| Distro | Docker | Rootless Podman | SELinux | Package format |
| --- | --- | --- | --- | --- |
| Ubuntu 24.04 | Yes | No | No | `.deb` |
| Ubuntu 26.04 | Yes | Yes | No | `.deb` |
| CentOS Stream 10 | No | No | Yes | `.rpm` |
| Fedora 44 | No | Yes | Yes | `.rpm` |
| Rocky Linux 9 | Yes | No | Yes | `.rpm` |
| Distro | Docker | Rootful Podman | Rootless Podman | SELinux | Package format |
| --- | --- | --- | --- | --- | --- |
| Ubuntu 24.04 | Yes | Yes | No | No | `.deb` |
| Ubuntu 26.04 | Yes | Yes | Yes | No | `.deb` |
| CentOS Stream 10 | No | Yes | No | Yes | `.rpm` |
| Fedora 44 | No | Yes | Yes | Yes | `.rpm` |
| Rocky Linux 9 | Yes | Yes | No | Yes | `.rpm` |

The `snapd` configuration is available for Ubuntu and prepares snapd for
local Snap lifecycle experiments. It does not install Docker, because the Snap
Expand All @@ -91,6 +92,13 @@ Both configurations verify rootless mode and the `pasta` network helper
required by OpenShell sandbox callbacks. Ubuntu 24.04 ships Podman 4, which
does not provide that helper.

`podman-rootful` installs Podman, enables its system API socket, and records
the selected mode for the `gateway-podman` provisioner. The provisioner then
starts the selected OpenShell installation as root. It does not write a
rootful-specific gateway setting; the gateway discovers the Podman socket
available to its service account. The rootless configuration records its mode
the same way and runs the gateway as the `openshell` user.

List the available distros and configurations:

```shell
Expand All @@ -115,6 +123,7 @@ Other combinations use the same interface:

```shell
nix run .#test-guest -- --distro rocky --with docker
nix run .#test-guest -- --distro fedora --with podman-rootful
nix run .#test-guest -- --distro ubuntu-26-04 --with podman-rootless
nix run .#test-guest -- --distro fedora --with podman-rootless
```
Expand Down Expand Up @@ -189,8 +198,11 @@ EOF
- `/usr/local/bin/openshell-gateway`
- `/usr/local/lib/openshell-sandbox.tar`

Compose it with `gateway-rootless-podman` to configure a rootless Podman
gateway. For example, run conformance after the provisioners complete:
Compose it with `gateway-podman` after either Podman configuration. The role
uses the recorded mode to select the corresponding service account. It
generates configuration only for development artifacts; RPM installations
retain their packaged service and first-start configuration. For example, run
conformance after the rootless provisioners complete:

```shell
nix run .#test-guest -- \
Expand All @@ -200,7 +212,7 @@ nix run .#test-guest -- \
--copy ./openshell-gateway:/usr/local/bin/openshell-gateway \
--copy ./openshell-sandbox.tar:/usr/local/lib/openshell-sandbox.tar \
--provision openshell-development \
--provision gateway-rootless-podman \
--provision gateway-podman \
-- /usr/local/bin/openshell-conformance run --plan - <<'EOF'
version = 1

Expand All @@ -218,13 +230,14 @@ EOF
`openshell-rpm` expects OpenShell to have been installed with `--install`. It
uses the RPM-owned `/usr/bin` binaries and `openshell-gateway` user service,
without copied development artifacts or a supervisor archive. Compose it with
`gateway-rootless-podman` before an RPM action such as
`gateway-podman` to start the installed version. The existing upgrade flow uses
the same role with the rootless configuration before
`openshell-rpm-gateway-upgrade`.

`openshell-rpm-latest-release` downloads and installs the latest stable
OpenShell GitHub release for the guest architecture, then publishes the same
RPM installation contract. Compose it with `gateway-rootless-podman` and an
RPM gateway action when testing an upgrade from the current release.
RPM installation contract. Compose it with `gateway-podman` and an RPM gateway
action when testing an upgrade from the current release.

Versioned plans under `nix/test-guest/conformance-plans/` bind conformance
scenarios to the stable action-command contracts installed by provisioners.
Expand Down Expand Up @@ -284,7 +297,7 @@ Cache command options:

```text
--distro NAME Base distro: ubuntu-24-04, ubuntu-26-04, centos, fedora, or rocky
--with NAME Apply docker, podman-rootless, selinux, or snapd; repeatable
--with NAME Apply docker, podman-rootful, podman-rootless, selinux, or snapd; repeatable
--repository REF OCI repository without a tag
--digest DIGEST Trusted OCI manifest digest required for pulls
--cache-dir PATH Override the local prepared-disk cache directory
Expand Down Expand Up @@ -361,7 +374,7 @@ from `000` through `777` for explicit modes.

```text
--distro NAME Base distro: ubuntu-24-04, ubuntu-26-04, centos, fedora, or rocky
--with NAME Apply docker, podman-rootless, selinux, or snapd; repeatable
--with NAME Apply docker, podman-rootful, podman-rootless, selinux, or snapd; repeatable
--install PATH Install a .deb or .rpm package; repeatable
--copy SRC:DEST[:MODE]
Copy a regular file into the guest; use MODE when provided,
Expand Down
5 changes: 3 additions & 2 deletions nix/test-guest/cache.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Usage:

Options:
--distro NAME Base distro: ubuntu-24-04, ubuntu-26-04, centos, fedora, or rocky
--with NAME Apply a configuration; repeatable (docker, podman-rootless, selinux, snapd)
--with NAME Apply a configuration; repeatable (docker, podman-rootful, podman-rootless, selinux, snapd)
--repository REF OCI repository without a tag
--digest DIGEST Trusted OCI manifest digest required for pulls
--cache-dir PATH Override the local prepared-disk cache directory
Expand Down Expand Up @@ -380,7 +380,8 @@ build_local() {
for configuration in "${configurations[@]}"; do
case "${configuration}" in
docker) validation+='; docker info >/dev/null' ;;
podman-rootless) validation+='; podman info >/dev/null' ;;
podman-rootful) validation+='; sudo podman --url unix:///run/podman/podman.sock info >/dev/null; test "$(cat /etc/openshell-test-guest/podman-mode)" = rootful' ;;
podman-rootless) validation+='; podman info >/dev/null; test "$(cat /etc/openshell-test-guest/podman-mode)" = rootless' ;;
selinux) validation+='; test "$(getenforce)" = Enforcing' ;;
esac
done
Expand Down
36 changes: 36 additions & 0 deletions nix/test-guest/configuration/podman-rootful.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

- name: Configure rootful Podman
hosts: test_vm
become: true
gather_facts: true
tasks:
- name: Install common Podman prerequisites
ansible.builtin.import_tasks: tasks/podman-common.yml

- name: Enable the rootful Podman API socket
ansible.builtin.systemd_service:
name: podman.socket
enabled: true
state: started

- name: Verify rootful Podman mode
ansible.builtin.command:
argv:
- podman
- --url
- unix:///run/podman/podman.sock
- info
- --format
- "{% raw %}{{.Host.Security.Rootless}}{% endraw %}"
changed_when: false
register: podman_rootful_info
failed_when: podman_rootful_info.stdout != "false"

- name: Record rootful Podman mode
ansible.builtin.copy:
dest: /etc/openshell-test-guest/podman-mode
content: "rootful\n"
mode: "0644"
6 changes: 6 additions & 0 deletions nix/test-guest/configuration/podman-rootless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@

- name: Configure shared rootless Podman settings
ansible.builtin.import_tasks: tasks/podman-rootless/shared.yml

- name: Record rootless Podman mode
ansible.builtin.copy:
dest: /etc/openshell-test-guest/podman-mode
content: "rootless\n"
mode: "0644"
6 changes: 6 additions & 0 deletions nix/test-guest/configuration/tasks/podman-common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@
ansible.builtin.package:
name: podman
state: present

- name: Create test-guest state directory
ansible.builtin.file:
path: /etc/openshell-test-guest
state: directory
mode: "0755"
3 changes: 2 additions & 1 deletion nix/test-guest/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ let

configurations = {
docker = ./configuration/docker.yml;
podman-rootful = ./configuration/podman-rootful.yml;
podman-rootless = ./configuration/podman-rootless.yml;
selinux = ./configuration/selinux.yml;
snapd = ./configuration/snapd.yml;
Expand All @@ -43,7 +44,7 @@ let
"openshell-development"
"openshell-rpm"
"openshell-rpm-latest-release"
"gateway-rootless-podman"
"gateway-podman"
"openshell-rpm-gateway-reinstall"
"openshell-rpm-gateway-upgrade"
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

openshell_gateway_service_command: /home/openshell/.local/bin/openshell-test-guest-as-gateway-user
openshell_gateway_restart_command: /home/openshell/.local/bin/openshell-test-guest-gateway-restart
openshell_gateway_diagnostics_command: /home/openshell/.local/bin/openshell-test-guest-diagnostics
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,40 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

- name: Create development gateway state directories
- name: Publish development gateway paths
ansible.builtin.set_fact:
openshell_gateway_state_root: "{{ openshell_gateway_service_home }}/.local/share/openshell-test-guest"
openshell_gateway_config_home: "{{ openshell_gateway_service_home }}/.config"

- name: Create development gateway directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0700"
owner: "{{ openshell_gateway_service_user }}"
group: "{{ openshell_gateway_service_user }}"
loop:
- "{{ openshell_gateway_state_root }}"
- "{{ openshell_gateway_state_root }}/xdg/config"
- "{{ openshell_gateway_state_root }}/xdg/cache"
- "{{ openshell_gateway_state_root }}/xdg/data"
- "{{ openshell_gateway_state_root }}/xdg/state"
- /home/openshell/.config/systemd/user
- "{{ openshell_gateway_config_home }}/systemd/user"
become: true

- name: Generate development gateway certificates
- name: Generate development gateway credentials
ansible.builtin.command:
cmd: "{{ openshell_gateway_bin }} generate-certs --output-dir {{ openshell_gateway_state_root }}/pki"
creates: "{{ openshell_gateway_state_root }}/pki/jwt/signing.pem"
become: true
become_user: "{{ openshell_gateway_service_user }}"

- name: Write rootless Podman gateway configuration
- name: Write development Podman gateway configuration
ansible.builtin.copy:
dest: "{{ openshell_gateway_state_root }}/gateway.toml"
mode: "0600"
owner: "{{ openshell_gateway_service_user }}"
group: "{{ openshell_gateway_service_user }}"
content: |
[openshell]
version = 1
Expand All @@ -50,25 +62,32 @@
image_pull_policy = "always"
network_name = "openshell-test-guest"
grpc_endpoint = "http://host.containers.internal:8080"
become: true

- name: Check for the development supervisor image
ansible.builtin.command:
cmd: "podman image exists {{ openshell_supervisor_image }}"
register: openshell_supervisor_image_exists
changed_when: false
failed_when: false
become: true
become_user: "{{ openshell_gateway_service_user }}"

- name: Import the development supervisor image
ansible.builtin.command:
cmd: >-
podman import --change 'ENTRYPOINT ["/openshell-sandbox"]'
{{ openshell_supervisor_archive }} {{ openshell_supervisor_image }}
when: openshell_supervisor_image_exists.rc != 0
become: true
become_user: "{{ openshell_gateway_service_user }}"

- name: Install the development gateway user service
ansible.builtin.copy:
dest: "/home/openshell/.config/systemd/user/{{ openshell_gateway_service }}"
dest: "{{ openshell_gateway_config_home }}/systemd/user/{{ openshell_gateway_service }}"
mode: "0600"
owner: "{{ openshell_gateway_service_user }}"
group: "{{ openshell_gateway_service_user }}"
content: |
[Unit]
Description=OpenShell development test guest gateway
Expand All @@ -84,3 +103,4 @@

[Install]
WantedBy=default.target
become: true
Loading
Loading