Repository: containers/ramalama

Issue:
ramalama unecessarily expects /usr/bin/nvidia-container-runtime on Fedora 42
### Issue Description

I setup ramalama on Fedora 42 according to the instructions. `podman run --rm --device=nvidia.com/gpu=all fedora nvidia-smi` shows the nvidia device.

`ramalama run granite` fails with: `Error: no valid executable found for OCI runtime /usr/bin/nvidia-container-runtime: invalid argument`

I am using golang-github-nvidia-container-toolkit-1.17.3-1.fc42 and python3-ramalama-0.7.2-1.fc42. The file`/usr/bin/nvidia-container-runtime` does not exist on my system with these packages installed.

I noticed that removing https://github.com/containers/ramalama/blob/main/ramalama/model.py#L322 makes ramalama work as expected.

### Steps to reproduce the issue

Steps to reproduce the issue
1. dnf install  nvidia-container-toolkit python3-ramalama
2. nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
3. nvidia-ctk config --in-place --set nvidia-container-runtime.mode=cdi # not sure if this is needed
4. ramalama run granite



### Describe the results you received

Error: no valid executable found for OCI runtime /usr/bin/nvidia-container-runtime: invalid argument

### Describe the results you expected

ramalama prompt

### ramalama info output

```yaml
{
    "Accelerator": "cuda",
    "Engine": {
        "Info": {
            "host": {
                "arch": "amd64",
                "buildahVersion": "1.39.4",
                "cgroupControllers": [
                    "cpu",
                    "io",
                    "memory",
                    "pids"
                ],
                "cgroupManager": "systemd",
                "cgroupVersion": "v2",
                "conmon": {
                    "package": "conmon-2.1.13-1.fc42.x86_64",
                    "path": "/usr/bin/conmon",
                    "version": "conmon version 2.1.13, commit: "
                },
                "cpuUtilization": {
                    "idlePercent": 97.5,
                    "systemPercent": 0.45,
                    "userPercent": 2.05
                },
                "cpus": 24,
                "databaseBackend": "sqlite",
                "distribution": {
                    "distribution": "fedora",
                    "variant": "workstation",
                    "version": "42"
                },
                "eventLogger": "journald",
                "freeLocks": 2041,
                "hostname": "genius",
                "idMappings": {
                    "gidmap": [
                        {
                            "container_id": 0,
                            "host_id": 1000,
                            "size": 1
                        },
                        {
                            "container_id": 1,
                            "host_id": 524288,
                            "size": 65536
                        }
                    ],
                    "uidmap": [
                        {
                            "container_id": 0,
                            "host_id": 1000,
                            "size": 1
                        },
                        {
                            "container_id": 1,
                            "host_id": 524288,
                            "size": 65536
                        }
                    ]
                },
                "kernel": "6.14.2-300.fc42.x86_64",
                "linkmode": "dynamic",
                "logDriver": "journald",
                "memFree": 106652884992,
                "memTotal": 134821318656,
                "networkBackend": "netavark",
                "networkBackendInfo": {
                    "backend": "netavark",
                    "dns": {
                        "package": "aardvark-dns-1.14.0-1.fc42.x86_64",
                        "path": "/usr/libexec/podman/aardvark-dns",
                        "version": "aardvark-dns 1.14.0"
                    },
                    "package": "netavark-1.14.1-1.fc42.x86_64",
                    "path": "/usr/libexec/podman/netavark",
                    "version": "netavark 1.14.1"
                },
                "ociRuntime": {
                    "name": "crun",
                    "package": "crun-1.21-1.fc42.x86_64",
                    "path": "/usr/bin/crun",
                    "version": "crun version 1.21\ncommit: 10269840aa07fb7e6b7e1acff6198692d8ff5c88\nrundir: /run/user/1000/crun\nspec: 1.0.0\n+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +LIBKRUN +WASM:wasmedge +YAJL"
                },
                "os": "linux",
                "pasta": {
                    "executable": "/usr/bin/pasta",
                    "package": "passt-0^20250320.g32f6212-2.fc42.x86_64",
                    "version": ""
                },
                "remoteSocket": {
                    "exists": true,
                    "path": "/run/user/1000/podman/podman.sock"
                },
                "rootlessNetworkCmd": "pasta",
                "security": {
                    "apparmorEnabled": false,
                    "capabilities": "CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT",
                    "rootless": true,
                    "seccompEnabled": true,
                    "seccompProfilePath": "/usr/share/containers/seccomp.json",
                    "selinuxEnabled": true
                },
                "serviceIsRemote": false,
                "slirp4netns": {
                    "executable": "/usr/bin/slirp4netns",
                    "package": "slirp4netns-1.3.1-2.fc42.x86_64",
                    "version": "slirp4netns version 1.3.1\ncommit: e5e368c4f5db6ae75c2fce786e31eef9da6bf236\nlibslirp: 4.8.0\nSLIRP_CONFIG_VERSION_MAX: 5\nlibseccomp: 2.5.5"
                },
                "swapFree": 8589930496,
                "swapTotal": 8589930496,
                "uptime": "1h 6m 27.00s (Approximately 0.04 days)",
                "variant": ""
            },
            "plugins": {
                "authorization": null,
                "log": [
                    "k8s-file",
                    "none",
                    "passthrough",
                    "journald"
                ],
                "network": [
                    "bridge",
                    "macvlan",
                    "ipvlan"
                ],
                "volume": [
                    "local"
                ]
            },
            "registries": {
                "search": [
                    "registry.fedoraproject.org",
                    "registry.access.redhat.com",
                    "docker.io"
                ]
            },
            "store": {
                "configFile": "/home/till/.config/containers/storage.conf",
                "containerStore": {
                    "number": 6,
                    "paused": 0,
                    "running": 1,
                    "stopped": 5
                },
                "graphDriverName": "overlay",
                "graphOptions": {},
                "graphRoot": "/home/till/.local/share/containers/storage",
                "graphRootAllocated": 536608768000,
                "graphRootUsed": 109001195520,
                "graphStatus": {
                    "Backing Filesystem": "xfs",
                    "Native Overlay Diff": "true",
                    "Supports d_type": "true",
                    "Supports shifting": "false",
                    "Supports volatile": "true",
                    "Using metacopy": "false"
                },
                "imageCopyTmpDir": "/var/tmp",
                "imageStore": {
                    "number": 24
                },
                "runRoot": "/run/user/1000/containers",
                "transientStore": false,
                "volumePath": "/home/till/.local/share/containers/storage/volumes"
            },
            "version": {
                "APIVersion": "5.4.2",
                "BuildOrigin": "Fedora Project",
                "Built": 1743552000,
                "BuiltTime": "Wed Apr  2 02:00:00 2025",
                "GitCommit": "be85287fcf4590961614ee37be65eeb315e5d9ff",
                "GoVersion": "go1.24.1",
                "Os": "linux",
                "OsArch": "linux/amd64",
                "Version": "5.4.2"
            }
        },
        "Name": "podman"
    },
    "Image": "quay.io/ramalama/ramalama",
    "Runtime": "llama.cpp",
    "Store": "/home/till/.local/share/ramalama",
    "UseContainer": true,
    "Version": "0.7.2"
}
```

### Upstream Latest Release

No

### Additional environment details

_No response_

### Additional information

_No response_

Discussion:
@rhatdan: On my machine without it I get:

./bin/ramalama run granite
Error: crun: cannot stat `/usr/lib64/libEGL_nvidia.so.570.124.06`: No such file or directory: OCI runtime attempted to invoke a command that was not found

I can do an access check on it, and not include it if it is not installed.@tyll: How did you get the file? The RPM does not contain it for me. `/usr/lib64/libEGL_nvidia.so.570.124.0` does not exist for me, either. I have /usr/lib64/libEGL_nvidia.so.570.133.07. I use the nvidia drivers from rpmfusion: /etc/yum.repos.d/rpmfusion-nonfree-nvidia-driver.repo - maybe it is related to the newer Nvidia drivers?@rhatdan: I am on Fedora 42 and get the drivers from the same place.@ericcurtin: There's Fedora install steps here:

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html

it is better if we always install nvidia-container-runtime , the Container can change at any point. nvidia-container-runtime ensures guest container and host OS stay on compatible versions of drivers.
@tyll: I installed the nvidia-container-toolkit as it was described in https://github.com/containers/ramalama/blob/main/docs/ramalama-cuda.7.md with a plain

`dnf install -y nvidia-container-toolkit` - this installs golang-github-nvidia-container-toolkit-1.17.3-1.fc42.x86_64 on Fedora 42 from the official Fedora repositories. The NVIDIA install guide seems to install it from an NVIDIA repository. Nevertheless, it seems to work fine with the Fedora toolkit except for ramalama not handling this correctly.@tyll: FYI, the Fedora package does not build the binary: https://src.fedoraproject.org/rpms/golang-github-nvidia-container-toolkit/blob/rawhide/f/golang-github-nvidia-container-toolkit.spec#_89@tyll: I pinged @debarshiray about this, he is the maintainer of the package in Fedora.@rhatdan: I merged https://github.com/containers/ramalama/pull/1211 which would allow your scenario to work.

dnf install -y nvidia-container-toolkit-base 

$ rpm -qf /usr/bin/nvidia-container-runtime 
nvidia-container-toolkit-base-1.17.5-1.x86_64
@Iolaum: I also had this issue because I thought running

```
rpm-ostree install nvidia-container-toolkit
```

was enough. I was even able to successfully run the `nvidia-smi` test in the docs with it.

Ending up solving it by uninstalling the package in the default fedora repos and activating the [`@ai-ml/nvidia-container-toolkit`](https://copr.fedorainfracloud.org/coprs/g/ai-ml/nvidia-container-toolkit/) copr and installing the package (and its selinux counterpart) from there.

Ideally (imo)  the docs should be updated to not cause confusion for people who think the package in the fedora repos is enough.@antbbn: I think this might be necessary as well:
```diff
--- ramalama/engine.py	2025-05-10 11:41:07.925184949 +0200
+++ ramalama/engine.py	2025-05-10 11:42:05.230404305 +0200
@@ -73,7 +73,7 @@
         if check_nvidia() == "cuda":
             if self.use_docker:
                 self.exec_args += ["--runtime", "nvidia"]
-            else:
+            elif os.access("/usr/bin/nvidia-container-runtime", os.X_OK):
                 self.exec_args += ["--runtime", "/usr/bin/nvidia-container-runtime"]
 
     def add_privileged_options(self):
```@ericcurtin: @antbbn feel free to open a PR, I'd probably go for an even simpler os.path.exists personally@antbbn: Done, I left the executable access only for consistency with the same check that happens in `model.py` from the other PR. 
But yeah, i agree,  if it's in `/usr/bin` i would be very surprised if it's not an executable :)

Solution patch:
diff --git a/.github/workflows/latest.yml b/.github/workflows/latest.yml
index 0e4ccb1..8072739 100644
--- a/.github/workflows/latest.yml
+++ b/.github/workflows/latest.yml
@@ -9,7 +9,9 @@ jobs:
   linux:
     runs-on: ubuntu-24.04
     steps:
-      - uses: actions/checkout@v4
+      - name: Checkout ramalama
+        uses: actions/checkout@v4
+
       - name: Free Disk Space Linux
         shell: bash
         run: |
@@ -52,31 +54,40 @@ jobs:
       - name: Build a container for CPU inferencing
         run: ./container_build.sh build ramalama
 
-      - name: Run a one-line script
+      - name: Install end-to-end test requirements
         run: |
+          sudo apt-get install bats
           make install-requirements
-          make end-to-end-tests
+
+      - name: Run end-to-end tests
+        run: make end-to-end-tests
 
   macos:
     runs-on: macos-14
     steps:
-      - uses: actions/checkout@v4
-      - name: install golang
+      - name: Checkout ramalama
+        uses: actions/checkout@v4
+
+      - name: Install golang
         shell: bash
         run: brew install go
-      - name: Run a one-line script
+
+      - name: Install end-to-end test requirements
         shell: bash
         run: |
+          brew install shellcheck
           make install-requirements
-          make end-to-end-tests
+
+      - name: Run end-to-end tests
+        shell: bash
+        run: make end-to-end-tests
 
   build:
     runs-on: ubuntu-24.04
     needs: [linux, macos]
     steps:
-        - uses: actions/checkout@v4
-          with:
-            ref: 'main'
+        - name: Checkout ramalama
+          uses: actions/checkout@v4
 
         - name: Upgrade to podman 5
           run: |
@@ -117,19 +128,19 @@ jobs:
           run: |
              df -h
 
-        - name: install qemu-user-static
+        - name: Install qemu-user-static
           run: |
             sudo apt-get update
             sudo apt-get install qemu-user-static
 
-        - name: Login to Registry
+        - name: Login to quay
           uses: redhat-actions/podman-login@v1.7
           with:
             registry: quay.io
             username: ${{ secrets.USERNAME }}
             password: ${{ secrets.PASSWORD }}
 
-        - name: use buildah to build images for amd and aarch64
+        - name: Build images for amd64 and aarch64
           uses: redhat-actions/buildah-build@v2
           id: build_image
           with:
@@ -139,7 +150,7 @@ jobs:
               container-images/ramalama/Containerfile
             platforms: linux/amd64, linux/arm64
 
-        - name: push images to registry
+        - name: Push images to quay
           uses: redhat-actions/push-to-registry@v2.8
           with:
             image: ramalama/ramalama
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index ae426c8..df7655d 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -8,7 +8,9 @@ jobs:
   linux:
     runs-on: ubuntu-24.04
     steps:
-      - uses: actions/checkout@v4
+      - name: Checkout ramalama
+        uses: actions/checkout@v4
+
       - name: Free Disk Space Linux
         shell: bash
         run: |
@@ -51,31 +53,40 @@ jobs:
       - name: Build a container for CPU inferencing
         run: ./container_build.sh build ramalama
 
-      - name: Run a one-line script
+      - name: Install end-to-end test requirements
         run: |
+          sudo apt-get install bats
           make install-requirements
-          make end-to-end-tests
+
+      - name: Run end-to-end tests
+        run: make end-to-end-tests
 
   macos:
     runs-on: macos-14
     steps:
-      - uses: actions/checkout@v4
-      - name: install golang
+      - name: Checkout ramalama
+        uses: actions/checkout@v4
+
+      - name: Install golang
         shell: bash
         run: brew install go
-      - name: Run a one-line script
+
+      - name: Install end-to-end test requirements
         shell: bash
         run: |
+          brew install shellcheck
           make install-requirements
-          make end-to-end-tests
+
+      - name: Run end-to-end tests
+        shell: bash
+        run: make end-to-end-tests
 
   build:
     runs-on: ubuntu-24.04
     needs: [linux, macos]
     steps:
-        - uses: actions/checkout@v4
-          with:
-            ref: 'main'
+        - name: Checkout ramalama
+          uses: actions/checkout@v4
 
         - name: Upgrade to podman 5
           run: |
@@ -93,14 +104,14 @@ jobs:
             sudo apt-get update
             sudo apt-get install qemu-user-static
 
-        - name: Login to Registry
+        - name: Login to quay
           uses: redhat-actions/podman-login@v1.7
           with:
             registry: quay.io
             username: ${{ secrets.USERNAME }}
             password: ${{ secrets.PASSWORD }}
 
-        - name: use buildah to build images for amd and aarch64
+        - name: Build images for amd64 and arm64
           uses: redhat-actions/buildah-build@v2
           id: build_image
           with:
@@ -110,7 +121,7 @@ jobs:
               container-images/ramalama/Containerfile
             platforms: linux/amd64, linux/arm64
 
-        - name: push images to registry
+        - name: Push images to quay
           uses: redhat-actions/push-to-registry@v2.8
           with:
             image: ramalama/ramalama
diff --git a/ramalama/engine.py b/ramalama/engine.py
index 126270a..fc53a57 100644
--- a/ramalama/engine.py
+++ b/ramalama/engine.py
@@ -74,7 +74,7 @@ class Engine:
         if check_nvidia() == "cuda":
             if self.use_docker:
                 self.exec_args += ["--runtime", "nvidia"]
-            else:
+            elif os.access("/usr/bin/nvidia-container-runtime", os.X_OK):
                 self.exec_args += ["--runtime", "/usr/bin/nvidia-container-runtime"]
 
     def add_privileged_options(self):


Test patch:
diff --git a/test/unit/test_engine.py b/test/unit/test_engine.py
index 599ea93..b84bfa9 100644
--- a/test/unit/test_engine.py
+++ b/test/unit/test_engine.py
@@ -26,15 +26,24 @@ class TestEngine(unittest.TestCase):
         self.assertIn("ai.ramalama.port=8080", exec_args)
         self.assertIn("ai.ramalama.command=run", exec_args)
 
+    @patch('os.access')
     @patch('ramalama.engine.check_nvidia')
-    def test_add_oci_runtime_nvidia(self, mock_check_nvidia):
+    def test_add_oci_runtime_nvidia(self, mock_check_nvidia, mock_os_access):
         mock_check_nvidia.return_value = "cuda"
+        mock_os_access.return_value = True
 
         # Test Podman
         podman_engine = Engine(self.base_args)
         self.assertIn("--runtime", podman_engine.exec_args)
         self.assertIn("/usr/bin/nvidia-container-runtime", podman_engine.exec_args)
 
+        # Test Podman wehn nvidia-container-runtime executable is missing
+        # This is expected with the official package
+        mock_os_access.return_value = False
+        podman_engine = Engine(self.base_args)
+        self.assertNotIn("--runtime", podman_engine.exec_args)
+        self.assertNotIn("/usr/bin/nvidia-container-runtime", podman_engine.exec_args)
+
         # Test Docker
         args = self.base_args
         args.engine = "docker"