Subsections of Guides
Checking OpenShift Certificates
This guide covers methods for checking the expiration dates of critical OpenShift certificates, including the API server and Ingress controller. While OpenShift typically auto-rotates most internal certificates, manually verifying them can be useful for troubleshooting and custom monitoring.
Key Certificate Locations
Critical certificates are stored as Kubernetes Secrets across different namespaces:
| Component | Namespace | Secret Name |
|---|---|---|
| API Server | openshift-kube-apiserver | kube-apiserver-cert-key-pair |
| Ingress (default) | openshift-ingress | router-certs-default |
| Controller Manager | openshift-kube-controller-manager | Various cert secrets |
| Scheduler | openshift-kube-scheduler | Various cert secrets |
Quick Checks
Use these one-liners to manually inspect specific certificates.
API Server Certificate
To check the expiration date directly:
To view full certificate details including the validity period:
Default Ingress Controller Certificate
To check the expiration date:
Automated Expiration Checks
When dealing with many certificates, automation is necessary. Here are several approaches for scripting certificate checks.
Option 1: Multi-Namespace Checking
This script iterates over key namespaces and extracts the end date for all TLS secrets:
Option 2: Comprehensive Warning Script (Recommended)
This script calculates the remaining days for each certificate in a namespace and provides warnings if they are close to expiring. It handles epoch time conversion for robust comparison.
Note: Save as check-certs.sh, run chmod +x check-certs.sh, and configure it as a cron job for regular monitoring.
Option 3: Quick One-Liners
If you prefer one-liners over a script, you can use jq to loop through secrets:
Built-In Monitoring
While scripts are helpful for point-in-time checks, OpenShift provides built-in mechanisms for monitoring:
- Prometheus Alerts: OpenShift’s default monitoring stack includes Prometheus alerts for certificate expiration.
- Web Console: Check Observe β Alerting in the OpenShift web console for active certificate expiration warnings.
- CSR Approval: For pending Certificate Signing Requests (often relevant during node addition or cert rotation), check status with
oc get csr -wand approve manually if necessary usingoc adm certificate approve <csr-name>.
Chaining GitHub Actions Workflows Without a PAT or GitHub App
How to trigger one workflow from another when you can’t (or don’t want to) use Personal Access Tokens or GitHub Apps.
The Problem
You have two workflows:
- Workflow A β Detects branches and auto-creates PRs against main
- Workflow B β Runs tests on PRs opened against main
Manual PRs trigger Workflow B. But when Workflow A creates a PR, Workflow B never runs.
Why This Happens
GitHub Actions has a deliberate security feature:
Actions performed using the default
GITHUB_TOKENdo not trigger other workflows.
This prevents accidental infinite loops (Workflow A triggers B triggers A triggers B…). When Workflow A creates a PR using GITHUB_TOKEN, GitHub suppresses the pull_request event that Workflow B listens for.
Mitigation Options
| Option | How It Works | Pros | Cons |
|---|---|---|---|
| Personal Access Token | Use a PAT instead of GITHUB_TOKEN | Simple | Tied to user account, expires, requires secret management |
| GitHub App | Create app, use its token | Not tied to user, fine-grained permissions | Requires app creation/management, may need org admin access |
workflow_run trigger | Workflow B triggers on Workflow A completion | No extra tokens, works within default permissions | Slightly more complex logic |
Why Not PAT or GitHub App?
In enterprise environments, engineers often:
- Don’t have permission to create GitHub Apps at the org level
- Can’t or shouldn’t create PATs tied to personal accounts for shared workflows
- Face security policies that restrict token creation
- Need solutions that work within the default
GITHUB_TOKENpermissions
The workflow_run approach works entirely within GitHub’s default permission model.
Solution: Using workflow_run Trigger
Instead of Workflow B listening for pull_request events (which won’t fire), have it listen for Workflow A’s completion.
Architecture
βββββββββββββββββββ βββββββββββββββββββ
β Workflow A β β Workflow B β
β (Auto-Create PR)β β (Run Tests) β
ββββββββββ¬βββββββββ ββββββββββ²βββββββββ
β β
β completes β triggers on
β β workflow_run
βΌ β
ββββββββββββββ β
β PR βββββββββββββββββββββ
β Created β (B finds PR from A's run)
ββββββββββββββImplementation
Workflow A: Auto-Create PR
Workflow B: Run Tests on Workflow A Completion
Key Points
Dual triggers: Workflow B responds to both
pull_request(manual PRs) andworkflow_run(auto PRs)Conditional logic: The
ifcondition ensures we only run on successful Workflow A completionsPR discovery: Since
workflow_rundoesn’t have PR context, we query the API to find the PR by branch nameStatus reporting: We manually create commit statuses so the PR shows test results
Caveats
Check Runs and PR Status
When triggered via workflow_run, the workflow runs in the context of the default branch, not the PR. This means:
- PR checks list won’t automatically show the workflow
- You need to manually create commit statuses (shown above)
- Or use the Checks API to create check runs
Race Conditions
If Workflow A completes before the PR is fully created (rare but possible), the PR lookup might fail. Add a short delay or retry logic if needed:
Branch Name Matching
The PR lookup uses the head branch. Ensure Workflow A’s branch naming is predictable so Workflow B can find the right PR.
Verification
After implementing:
- Push a branch matching your pattern (e.g.,
feature/test-chain) - Confirm Workflow A runs and creates the PR
- Confirm Workflow B triggers on Workflow A completion
- Confirm tests run and status appears on the PR
Summary
The workflow_run trigger lets you chain workflows without PATs or GitHub Apps. It’s slightly more complex than the token-based approaches, but works entirely within GitHub’s default permission model β making it ideal for enterprise environments where token creation is restricted.
Fixing Podman Start issues with Krunkit on MacOS
Podman on macOS can run its Linux VM through libkrun via the krunkit binary (installed from Homebrew). When required shared libraries are missing, krunkit crashes immediately and Podman reports an unhelpful abort-trap error instead of the underlying dyld failure.
This guide documents the symptoms, troubleshooting steps, fix, and prevention for that failure mode.
Symptoms
Starting a libkrun-backed Podman machine fails:
Example output:
Related indicators:
podman machine listshows the machine in stopped state with Never under Last Uppodman versionfails with a socket/SSH connection error because the VM never started- The machine was created with VM type libkrun (default when
krunkitis installed)
Root Cause
krunkit depends on a chain of Homebrew libraries (libkrun-efi, virglrenderer, and others). If any link in that chain is missing, macOS dynamic linker (dyld) aborts the process before Podman can surface a clear error.
In this case, two libraries were not installed:
| Missing library | Required by | Symptom when running krunkit --version |
|---|---|---|
libepoxy | libkrun-efi | Library not loaded: .../libepoxy.0.dylib |
molten-vk | virglrenderer | Library not loaded: .../libMoltenVK.dylib |
Podman only reported the generic abort trap because krunkit exited before the VM could boot.
Troubleshooting
Work through these steps to isolate the failure.
1. Confirm machine state and provider
Look for VM TYPE: libkrun and State: stopped.
2. Run krunkit directly
This usually reveals the real dyld error:
If krunkit crashes with Library not loaded, note the missing .dylib path.
3. Check Homebrew dependency tree
Compare installed deps against what krunkit --version reports as missing.
4. Inspect linked libraries (optional)
Follow the chain into /opt/homebrew/Cellar/ if multiple libraries are missing.
Resolution
Install the missing libraries reported by krunkit --version, then start the machine.
For the missing libepoxy and molten-vk libraries:
Verify krunkit runs:
Start the Podman machine:
If dependencies are still broken or versions are mismatched, reinstall the krunkit stack so Homebrew relinks everything:
Verification
Confirm clientβserver connectivity:
Run a test container:
Expected: image pulls successfully and prints the Podman hello-world banner.
Prevention
Install krunkit from the maintained tap so Homebrew tracks dependencies:
Avoid orphaning dependencies β if you run
brew cleanupor manually remove packages, check thatkrunkit --versionstill works before starting Podman.After major macOS or Homebrew upgrades, verify the stack:
Rootless vs rootful β the default machine runs rootless. If you need ports below 1024 or hit Docker-client compatibility issues:
Environment (reference)
This issue was diagnosed on:
| Item | Value |
|---|---|
| OS | macOS 26.5.1 (arm64) |
| Podman | 5.8.2 (Homebrew) |
| krunkit | 1.1.1 |
| Machine provider | libkrun |
References
- containers/krunkit β libkrun VM launcher for macOS; Homebrew install instructions
- krunkit usage docs β VM configuration and device options
HCL BigFix Agent Architecture Guide
Overview
HCL BigFix is a multi-platform endpoint management platform that enables IT operations and security teams to discover, manage, patch, and secure global IT estates. Whether operating on-premises, in the cloud, or in hybrid environments, BigFix uses a unique single-agent, hierarchical architecture to manage thousands of devices efficiently with minimal bandwidth overhead.
This guide is designed for technical consultants planning a new BigFix deployment with a client. It outlines the core architectural components, infrastructure decisions, prerequisite checklists, deployment flows, and discovery questions necessary to align with a client’s requirements.
BigFix Core Architecture & Components
BigFix does not rely on active scanning or heavy database polling. Instead, it operates on a pull-based, “Relevance” evaluation model.
+-------------------+
| Windows Console |
+---------+---------+
|
| (HTTPS - TCP 52311)
v
+-------------------+ +-------------------+ +-------------------+
| Web Reports |<----------| Root Server |---------->| HCL License / |
+-------------------+ (TCP) +---------+---------+ (HTTPS) | Content Servers |
| +-------------------+
| (TCP/UDP 52311)
v
+-------------------+
| Top-Level |
| Relay |
+---------+---------+
|
+----------------------+----------------------+
| (TCP/UDP 52311) | (TCP/UDP 52311)
v v
+-------------------+ +-------------------+
| Branch Relay | | Branch Relay |
| (Location A) | | (Location B) |
+---------+---------+ +---------+---------+
| |
+---------+---------+ +---------+---------+
| | | |
v v v v
+-----------+ +-----------+ +-----------+ +-----------+
| Client | | Client | | Client | | Client |
+-----------+ +-----------+ +-----------+ +-----------+1. The Root Server
The central brain of the deployment. It:
- Collects and aggregates reports from agents.
- Downloads patch feeds and fixlets from the HCL Content Servers.
- Manages and distributes action payloads.
- Runs the core database services.
2. BigFix Relays
Relays are intermediate staging points. Instead of 10,000 agents downloading a 100MB patch over a WAN link from the Root Server, the local Relay downloads it once, and the local agents fetch it from that Relay over the local LAN.
- Relays are standard endpoints running a lightweight relay service.
- Hierarchical layering: Relays can report to other parent relays (Top-Level Relays), shielding the Root Server from direct load.
3. BigFix Client (Agent)
A lightweight agent (~10-20MB RAM, <2% CPU) running as a system service on every managed machine.
- It continuously evaluates the endpoint state using Relevance Language (a declarative query language).
- If an agent determines a patch or configuration is “relevant”, it flags itself in the Console.
- It executes Action Scripts when instructed by the operator.
4. BigFix Console
The primary administrative interface used by operators to view inventory, author actions, and deploy patches.
- Constraint: The Console is strictly a Windows-only desktop application.
- It connects directly to the Root Server via HTTP/HTTPS.
5. Web Reports
A web-based interface for secondary reporting, viewing historical trends, and sharing read-only compliance dashboards with executive stakeholders.
Infrastructure Sizing & Database Choices
Selecting the right OS and Database backend is the most critical decision during the initial phase.
Supported Operating Systems for Root Server
- Windows Server: 2016, 2019, 2022 (Standard and Datacenter editions).
- Red Hat Enterprise Linux (RHEL): 8.x, 9.x (64-bit).
Database Backends & Constraints
- Microsoft SQL Server (for Windows Server deployments):
- SQL Server Enterprise & Standard: Supported for versions 2014 through 2022.
- SQL Server Express: Supported only for proof-of-concept (POC) environments or environments with fewer than 500 endpoints due to the 10GB database size limit.
- IBM DB2 (for Linux deployments):
- DB2 v11.5 is the standard for Linux deployments.
- An evaluation/bundled version of DB2 is typically included in the Linux server installer.
Hardware Sizing Guidelines
Note: Sizing depends on endpoint counts and active modules (e.g., Lifecycle, Compliance, Inventory).
| Endpoint Count | Role | CPU Cores | RAM | Storage Type | Recommended Disk IOPS |
|---|---|---|---|---|---|
| < 1,000 | All-in-One Server | 4 Cores | 16 GB | SSD (SAS/SATA) | 500+ |
| 1,000 - 10,000 | Root Server + DB | 8 Cores | 32 GB | High-Speed NVMe/SSD | 2,000+ |
| 10,000 - 50,000 | Split Root & DB Server | 16 Cores | 64 GB+ | Dedicated Enterprise SAN | 5,000+ |
Prerequisites
1. Network & Firewall Port Requirements
The BigFix platform uses TCP/UDP port 52311 as its default communication channel.
| Source | Destination | Port / Protocol | Direction | Purpose |
|---|---|---|---|---|
| Windows Console | Root Server | TCP 52311 | Inbound | Console-to-Server connection |
| Root Server | Internet (HCL) | TCP 80 / 443 | Outbound | Gathering sync feeds and downloads |
| Relays | Root Server | TCP 52311 | Inbound | Reporting parent-upstream status |
| Clients (Agents) | Local Relay | TCP 52311 | Inbound | Client report uploads & payloads |
| Relays / Server | Clients (Agents) | UDP 52311 | Outbound | “Ping” notification to trigger fast checks |
| Web Reports Server | Root Server / DB | TCP 1433 or 50000 | Inbound | SQL Server (1433) or DB2 (50000) access |
Note on UDP 52311: If UDP is blocked across subnets, agents will still check in via TCP on a polling interval (defaulting to every 4 hours), but real-time “gather now” command execution will be delayed.
2. DNS & Name Resolution
- The Root Server must be reachable via a fully qualified domain name (FQDN) or a dedicated IP.
- It is highly recommended to use a CNAME alias (e.g.,
bigfix.clientdomain.com) during installation rather than a specific server host name. This allows easy migration of the hardware/VM in the future without redeploying agents.
Configuration & Installation Sequence
The general deployment path follows these distinct phases:
Phase 1: License Authorization & Masthead Creation
- Run the BigFix Installation Generator on a Windows staging machine.
- Submit your HCL license authorization file (
.BesLicenseRequest) to the HCL License server. - HCL returns a Signed License file.
- Generate the Masthead file (
actionsite.afxm). This file acts as the anchor of trust. It contains the server FQDN, configuration parameters, and the public key used by agents to verify that actions sent to them are authentically signed.
Phase 2: Installing the Root Server
- On Windows: Run
setup.exeand choose “Install Server”. Configure your connection to MS SQL Server and select your generated masthead. - On Linux: Extract the tarball, ensure database (DB2/external) is ready, and run:Select Option
[1] All Componentsor[2] Server and Client Onlywhen prompted.
Phase 3: Deploying the Console
- Run the console installer on a Windows administrator workstation.
- Connect to the Root Server using the operator account created during server installation.
Phase 4: Deploying Relays
- Install the standard BigFix Agent on dedicated relay VMs or branch office hosts.
- In the BigFix Console, right-click the designated computers and select “Install BigFix Relay”.
- Configure the relay settings (e.g., maximum cache size, parent relays).
Phase 5: Agent Rollout
- Use the Client Deploy Tool (CDT) built into the Console to push agents over SSH or WMI.
- For large scale deployments, deploy the agent MSI/RPM package via GPO, SCCM, or Ansible, bundled with the generated
actionsite.afxmmasthead.
Consultant’s Discovery Checklist
Use these specific discovery questions during your initial meeting with the client to gather architectural requirements:
- How many total endpoints (workstations, servers, VMs, containers) are in scope?
- Why: Determines whether SQL Server Express is acceptable (< 500) and sets hardware specifications.
- What is the current distribution of Operating Systems across these endpoints?
- Why: Identifies if they need specific OS agents and helps plan the deployment method.
- What is the network topology? Do you have remote branch offices or bandwidth-constrained links?
- Why: Drives the relay placement strategy and WAN bandwidth throttle planning.
- Do you have a preferred Operating System for the central BigFix server (Windows Server vs RHEL)?
- Why: Dictates database licensing requirements (MS SQL Server vs DB2) and administrative skillsets.
- How are endpoints currently patched or managed? Do we need to plan co-existence or a migration from tools like WSUS, SCCM, or Ansible?
- Why: Highlights potential software conflicts or open firewall port struggles.
- Will endpoints reporting from outside the corporate firewall (remote/WFH workers) need management?
- Why: Determines if we need to deploy an Internet-Facing Relay (DMZ Relay) with public DNS records.
Common Pitfalls & Anti-Patterns
- Hardcoding Server Names: Installing with a specific server name (e.g.,
srv-bf-prod-01) instead of a DNS CNAME alias (bigfix.company.com). If the server hardware dies, migrating the system requires manually updating the masthead on every single agent. - Neglecting Relay Cache Limits: Leaving relay cache limits at default values. In environments deploying heavy OS patches or major software rollouts, relays will run out of cache space, causing them to fetch payloads repeatedly across WAN links.
- Ignoring UDP 52311: Assuming TCP is sufficient. Without UDP 52311 inbound to clients, operators cannot trigger “Instant” actions, severely impacting incident response speeds.
- Insufficient Space in Temporary Directories: Installing without verifying disk space in
/var/tmp(Linux) orC:\Windows\Temp(Windows). BigFix client downloads are staged here, and major patch actions will fail if these directories are constrained.
References
- HCL BigFix Enterprise Support Portal - Central knowledge base and product updates.
- BigFix Developer Reference - Authoring guides, Relevance query guides, and REST API references.
Installing Podman on MacOS
Podman Desktop is the graphical front end for Podman on macOS. Containers do not run natively on macOS β Podman launches a lightweight Linux VM (a Podman machine) and runs containers inside it. The desktop app handles onboarding, machine management, and optional Docker compatibility so existing Docker workflows keep working.
This guide covers installation, first-run setup, Docker compatibility, rootless vs rootful mode, and common gotchas β including the krunkit abort trap failure on Homebrew installs.
Prerequisites
| Requirement | Notes |
|---|---|
| macOS 14+ | Required for libkrun/krunkit on Apple Silicon |
| Apple Silicon or Intel | Universal .dmg works on both |
| Admin password | Needed during first-run Podman engine install |
| ~4 GB RAM minimum | Default machine uses 2 GiB; increase for heavier workloads |
Optional but useful:
- Homebrew β alternative install path (see gotchas below)
- Docker CLI β not required; Podman can serve the Docker API. Install via onboarding or
brew install dockerif you want thedockercommand
Choose an Install Path (Important)
Podman Desktop and the Podman CLI can be installed two ways. Pick one and stay on it.
| Method | Command / source | Official stance |
|---|---|---|
| DMG installer (recommended) | podman-desktop.io/downloads/macos | Most stable; bundles Podman, krunkit, and CLIs |
| Homebrew | brew install --cask podman-desktop | Supported but not recommended by upstream |
Do not mix install methods
If Podman is already installed via Homebrew, either:
- Uninstall Homebrew Podman before using the
.dmginstaller, or - Use Homebrew only β do not also install the
.dmg
Mixing paths causes duplicate binaries, conflicting machine configs, and hard-to-debug startup failures.
Installation
Option A: DMG installer (recommended)
- Download the Universal
.dmgfrom Podman Desktop macOS downloads. - Open the
.dmgand drag Podman Desktop to Applications. - Launch from Applications or Spotlight (
Cmd+Spaceβ “Podman Desktop”). - Complete onboarding (see First-run setup below).
The installer bundles krunkit and avoids the Homebrew dependency-chain issues described in Podman Machine krunkit Abort Trap.
Option B: Homebrew
Homebrew installs Podman Desktop and the Podman engine if not already present. Open the app from /Applications.
If you use libkrun (krunkit is on your PATH), install krunkit from the maintained tap so dependencies are tracked:
After any Homebrew install, verify krunkit before creating a machine:
If this crashes, see the krunkit abort trap guide before proceeding.
First-run setup
Podman Desktop onboarding walks through engine install, machine creation, and optional CLIs. You can also finish setup later from Settings β Resources or the Dashboard notification.
Onboarding checklist
- Install Podman engine β enter your macOS password when prompted.
- Create a Podman machine β default name is
podman-machine-default. - Install optional CLIs β
kubectlandcompose(Podman Compose). - Open Dashboard β confirm the machine shows Running under Settings β Resources.
CLI equivalent
If you prefer the terminal (or need to script setup):
Customize resources before or after init:
Machine providers
On Apple Silicon with krunkit installed, new machines default to libkrun (GPU-capable, uses Apple’s Hypervisor framework). Without krunkit, Podman falls back to applehv.
Rootless vs rootful
Every Podman machine runs containers in one of two modes. Rootless is the default.
| Rootless (default) | Rootful | |
|---|---|---|
| Container UID mapping | Runs as your user inside the VM | Runs as root inside the VM |
| Security | Smaller blast radius | Broader privileges in the VM |
| Privileged ports (< 1024) | Cannot bind (e.g. port 80, 443) | Can bind |
| Some Docker tools | May need extra socket/config | Better compatibility |
| Editing VM system files | Requires podman machine ssh as user | Easier access to /etc/containers/ |
When to stay rootless
- General development and learning
- Running apps on high ports (3000, 8080, etc.)
- You want the safer default
When to switch to rootful
- Binding ports below 1024
- Tools that assume root-owned containers or the root Podman socket
- Permission errors editing registries or storage inside the VM
How to switch
Podman Desktop: Settings β Resources β select your machine β toggle rootful mode, then restart the machine.
CLI:
To revert:
Podman maintains separate connection endpoints for each mode:
Switch the active connection if needed:
Docker compatibility
Podman exposes a Docker-compatible API so tools and scripts written for Docker can talk to Podman instead. On macOS, Podman Desktop enables Third-Party Docker Tool Compatibility by default.
What gets mapped
When the machine is running, macOS exposes a system socket symlink:
Podman Desktop reports socket status under Settings β Docker Compatibility.
Using the Docker CLI with Podman
- Ensure the Podman machine is running.
- Enable Docker compatibility in Podman Desktop (on by default on macOS).
- Install the Docker CLI if you do not have it (onboarding or
brew install docker). - Verify:
DOCKER_HOST (explicit configuration)
Some tools (Gradle, Testcontainers, CI scripts) need an explicit socket path instead of relying on /var/run/docker.sock:
Or create a Docker context:
Compose
- Podman Compose β installed during onboarding; invoke as
podman compose(preferred on Podman). - Docker Compose β works against the Docker-compatible socket when compatibility is enabled.
Compose project naming and networking differ slightly from Docker Compose in edge cases; prefer podman compose for Podman-native behavior.
Coexistence with Docker Desktop
Do not run Docker Desktop and Podman Desktop socket forwarding at the same time β both compete for /var/run/docker.sock. Quit Docker Desktop (or disable its socket) before enabling Podman Docker compatibility.
Gotchas
1. krunkit abort trap (Homebrew + libkrun)
Symptom: podman machine start fails with krunkit was terminated by signal: abort trap.
Cause: Missing Homebrew libraries in the krunkit dependency chain (libepoxy, molten-vk, etc.).
Fix: See Podman Machine krunkit Abort Trap.
Quick check:
2. Mixed Homebrew and DMG installs
Installing Podman via Homebrew and Podman Desktop via .dmg (or vice versa) leaves duplicate podman/krunkit binaries and conflicting machine state. Uninstall one path completely before adopting the other.
3. krunkit not found
Podman Desktop onboarding or podman machine init may report that krunkit is missing when using a partial Homebrew install.
The official .dmg bundles krunkit and avoids this.
4. Rootless privileged ports
Binding host port 80 in rootless mode fails silently or with permission errors. Switch to rootful or use a high port (8080) with a reverse proxy.
5. ARM64 image platform
On Apple Silicon, prefer multi-arch images or specify the platform:
Running x86-only images requires emulation and is slower.
6. Docker CLI still talks to Docker Desktop
If docker info shows Docker Desktop after switching to Podman:
- Quit Docker Desktop
- Confirm Podman machine is running
- Check Settings β Docker Compatibility in Podman Desktop
- Run
docker context lsand switch away fromdesktop-linux
7. Machine resource defaults
The default 2 GiB RAM is tight for multiple containers or image builds. Increase before heavy use:
Changes apply on next start.
8. Registries and VM config edits
Files like /etc/containers/registries.conf live inside the VM, not on macOS. Edit from the host:
Verification
Run this checklist after setup:
In Podman Desktop: Settings β Resources shows the machine as Running; Settings β Docker Compatibility shows the socket as reachable.
Quick reference
| Task | Command / location |
|---|---|
| Start machine | podman machine start or Podman Desktop Dashboard |
| Stop machine | podman machine stop |
| SSH into VM | podman machine ssh |
| Enable rootful | podman machine set --rootful |
| Docker compatibility | Settings β Docker Compatibility |
| Fix krunkit crash | krunkit abort trap guide |
| Increase RAM/CPUs | podman machine set --memory 8192 --cpus 4 |
References
- Podman Desktop macOS install β official install and onboarding
- Managing Docker compatibility β socket mapping and CLI setup
- Podman installation (macOS) β CLI and machine overview
- containers/krunkit β libkrun VM backend for Apple Silicon
NVIDIA Container Toolkit & CDI Setup on Proxmox GPU Passthrough VMs
Overview
NVIDIA Container Toolkit with CDI (Container Device Interface) enables Docker containers to access physical GPUs. On Proxmox VMs with GPU PCI passthrough, CDI specs must be explicitly generated and Docker must be configured to use them.
Prerequisites
- Proxmox VM with NVIDIA GPU PCI passthrough configured (IOMMU, vfio-pci)
- NVIDIA driver installed and
nvidia-smiworking on the host - Docker installed
Step-by-Step
1. Install NVIDIA Container Toolkit
2. Generate CDI Specs
Verify the spec was created:
3. (If Needed) Create AMD CDI Stub
On Proxmox GPU passthrough VMs, Docker’s CDI resolution may also require an amd.yaml spec. If NemoClaw or other GPU-passthrough tools fail with “AMD CDI spec not found”, create a minimal stub:
4. Configure Docker for CDI
5. Verify GPU Access
You should see the GPU listed with driver version and CUDA capabilities.
Common Pitfalls
| Pitfall | Resolution |
|---|---|
| “AMD CDI spec not found” | Create stub /etc/cdi/amd.yaml as described above |
CDI specs in /run/cdi/ conflict with /etc/cdi/ | Clean both directories and regenerate |
| GPU works on host but not in containers | Verify CDI specs exist and Docker was restarted |
Container starts but nvidia-smi fails inside | Check container runtime is docker (not containerd directly) |
References
NVIDIA vGPU Manager: build, integrated registry, and ClusterPolicy (OpenShift Virtualization)
This note validates a common on-cluster workflow against NVIDIAβs published steps, then records that workflow when Quay (or another external registry) is not used and images land in the integrated OpenShift image registry instead.
Primary NVIDIA reference: NVIDIA GPU Operator with OpenShift Virtualization β Building the vGPU Manager image and Creating a ClusterPolicy.
Related workspace guide: Using the integrated OpenShift container image registry.
End-to-end workflow (integrated registry)
1. Download the vGPU Manager .run
- NVIDIA Licensing Portal β Software Downloads β Driver downloads β Linux KVM complete vGPU package for the Product Version you intend to support.
- Unzip and locate
NVIDIA-Linux-x86_64-*-vgpu-kvm.run(or the AIE variant renamed per NVIDIA).
2. Clone NVIDIAβs build context and copy the installer
Change into the vgpu-manager subdirectory for your OS line (NVIDIAβs OpenShift example historically used vgpu-manager/rhel8; confirm the right path for your OCP / RHCOS generation):
3. Point the build at the integrated registry and RHCOS
Set VERSION to the vGPU software / driver version from the portal (NVIDIAβs examples look like 510.73.06; use your shipped version string).
Set OS_TAG to rhcos4.<minor> matching your OpenShift workers (NVIDIA documents this pattern).
Set PRIVATE_REGISTRY to the registry host and namespace prefix you will push to. For the integrated registry, that is commonly the external route hostname (for pushes from your workstation) plus project path, for example:
default-route-openshift-image-registry.apps.<cluster-base>/<project>
β¦where <project> is often nvidia-gpu-operator or a dedicated images project. See using-integrated-openshift-registry.md for login and push mechanics.
Example (illustrative only β adjust host, project, and versions):
Build and push using podman or docker as in NVIDIAβs doc:
Use a meaningful tag (here ${VERSION}-${OS_TAG}) so ClusterPolicy and support tickets stay unambiguous.
4. Reference the image from in-cluster pulls
Operands pull using the in-cluster registry DNS (typically image-registry.openshift-image-registry.svc:5000/<project>/vgpu-manager:<tag>). Your ClusterPolicy vgpuManager.repository / image / version (or equivalent fields) must match how your installed GPU Operator version assembles the pull spec. Always confirm with:
Conceptually you are wiring repository + image + version so they resolve to the same image you pushed (often image: vgpu-manager, version: tag string like 510.73.06-rhcos4.15 if that is what you pushed).
5. Update ClusterPolicy (operator already installed)
Generate or export the example ClusterPolicy, then merge at least:
spec.sandboxWorkloads.enabled: truespec.sandboxDevicePlugin.enabled: truespec.vgpuManager.enabled: truewithrepository,image,version, andimagePullSecretsif your registry requires themspec.vgpuDeviceManager.enabled: true
NVIDIAβs JSON-oriented example is in Creating a ClusterPolicy for the GPU Operator using the CLI. If a ClusterPolicy already exists, prefer oc get clusterpolicy -o yaml, edit, and oc apply.
6. Verify
When the vGPU Manager and sandbox operands are healthy and nodes are labeled, continue with NVIDIAβs HyperConverged mediated device steps and VM attachment.
Common pitfalls
- Wrong
vgpu-managersubdirectory orOS_TAGfor your RHCOS line β build succeeds but driver mismatches the node OS. ClusterPolicyfields do not match the pushed tag βImagePullBackOffon daemonsets or operator-managed pods.- Image in project A, operands in
nvidia-gpu-operatorwithoutsystem:image-puller(or a pull secret) β pull forbidden across namespaces. - Enabling
vgpuManagerbefore the image exists β transient failures; enable or point after push.
References
Using the integrated OpenShift container image registry
OpenShift ships with a cluster-internal container registry (the Image Registry Operator, namespace openshift-image-registry). You can push images there instead of an external registry (for example Quay.io), as long as workloads that need the image can pull from the namespace where the image lives.
This is the same pattern NVIDIA documents for hosting built images (for example vGPU Manager) on the clusterβs own registry.
What you get
In-cluster pull hostname (from any pod on the cluster):
image-registry.openshift-image-registry.svc:5000Full image reference:
image-registry.openshift-image-registry.svc:5000/<project>/<image>:<tag>Example:
image-registry.openshift-image-registry.svc:5000/nvidia-gpu-operator/vgpu-manager:9.0.0.0Private by default: images are not public on the internet; access is via Kubernetes RBAC and image pull credentials where needed.
Prerequisites
Registry is running β
ManagementStateshould beManaged:Storage β the registry needs a PVC or other supported backend (install-time or day-2 configuration). If the registry is not ready, pushes fail until storage is fixed.
Pushing from your laptop β you need a route (or port-forward) and authentication. Check for the default route:
If there is no route, an admin can enable the default route or you can push from a Job or Build inside the cluster that uses the internal service DNS and a service account token.
Basic workflow: push an image to the integrated registry
Create or pick a project (namespace) to hold the image, for example
nvidia-gpu-operatoror a dedicatedgpu-imagesproject.Log in to the registry from your workstation (using the external route host Red Hat documents for your version), with an OpenShift user token:
Use
dockerinstead ofpodmanif that is what you use.Tag and push using the external host for the push client (OpenShift documents the exact hostname pattern; it is often
default-route-openshift-image-registry.apps.<cluster-domain>).Reference the image from manifests using the in-cluster form (
*.svc:5000/...) so nodes and pods resolve it without depending on the apps route from inside the cluster.
Use explicit tags (for example 9.0.0.0 or a driver version string), not only latest, so rollbacks and support questions stay clear.
Pulling from another namespace (for example GPU Operator operands)
If the image lives in project gpu-images but pods run in nvidia-gpu-operator, those pods need permission to pull. Typical approaches:
- Grant the
nvidia-gpu-operatordefault service account (or the operand SA) access to pull from the other namespace (for exampleoc policy add-role-to-user system:image-puller system:serviceaccount:nvidia-gpu-operator:default -n gpu-images), or - Copy/mirror the image into
nvidia-gpu-operatorand reference it there, or - Use an image pull secret in
nvidia-gpu-operatorthat can authenticate to the registry (often unnecessary for same-cluster internal pulls when RBAC is set correctly).
Exact policy depends on your orgβs security model; the important part is: internal registry does not remove the need for RBAC across namespaces.
Wiring operators (example: NVIDIA ClusterPolicy / vgpuManager)
Point repository, image, and version (and imagePullSecrets if you use them) at the integrated registry path the same way you would for Quay. The operator concatenates fields according to its CRD; confirm with:
Conceptually you want the operands to pull something equivalent to:
image-registry.openshift-image-registry.svc:5000/<project>/<image>:<tag>
Verification
Further reading
- Red Hat: Accessing the registry (push/pull, routes, and authentication for your OCP version).
See also: NVIDIA vGPU Manager: build, integrated registry, and ClusterPolicy β end-to-end flow when hosting the vGPU Manager image on the integrated registry.
VSCode Setup for Enterprise Development
This guide covers setting up Visual Studio Code (VSCode) as your primary development environment on enterprise devices for working with OpenShift, Ansible, Python, YAML, and Bash.
Prerequisites
Before configuring VSCode, ensure the following core tools are installed on your system. While VSCode is assumed to be installed, these underlying dependencies are required for functionality.
1. Git (git-scm)
Download and install Git from the official git-scm.com site.
- Windows: Use the Git for Windows installer. Ensure “Git from the command line and also from 3rd-party software” is selected during installation.
- macOS: Install via Homebrew (
brew install git) or by installing Xcode Command Line Tools (xcode-select --install).
2. Python 3
Install Python 3.x from python.org or your system’s package manager.
- Ensure
pipis included in the installation. - Add Python to your system PATH.
3. Ansible Lint
Once Python is installed, install ansible-lint to enable playbook validation in VSCode:
Authentication: Personal Access Tokens (PAT)
In an enterprise environment, you will typically use a Personal Access Token (PAT) instead of your account password for Git operations over HTTPS.
Generating a PAT (GitHub Example)
- Log in to your GitHub account.
- Go to Settings > Developer settings > Personal access tokens > Fine-grained tokens (or Tokens classic).
- Click Generate new token.
- Give it a descriptive name (e.g., “VSCode Enterprise Desktop”).
- Select the required scopes (typically
repofor full control of private repositories). - Copy the token immediately. You will not be able to see it again.
Using the PAT
When you clone a repository or push changes for the first time, Git will prompt for your credentials.
- Username: Your GitHub username.
- Password: Paste your PAT here.
Note: On Windows and macOS, the system credential manager will securely store this token for future use.
Recommended Extensions
To get the best experience, install the following extensions from the VSCode Marketplace.
Core Languages & Tools
| Technology | Extension Name | Publisher | Description |
|---|---|---|---|
| Python | Python | Microsoft | Rich support for Python (IntelliSense, linting, debugging). |
| YAML | YAML | Red Hat | YAML Language Support with built-in Kubernetes/OpenShift syntax. |
| Ansible | Ansible | Red Hat | Language support, linting, and integration for Ansible playbooks. |
| Bash | Bash IDE | mads-hartmann | Bash language server for better autocomplete and linting. |
| OpenShift | OpenShift Connector | Red Hat | Interact with OpenShift clusters directly from VSCode. |
Version Control & Collaboration
| Extension Name | Publisher | Description |
|---|---|---|
| GitLens | GitKraken | Supercharge Git capabilities, view line history, and repository heatmaps. |
| GitHub PRs & Issues | GitHub | Create, review, and manage GitHub Pull Requests and Issues within VSCode. |
| Git Graph | mhutchie | View a Git Graph of your repository and perform Git actions from the graph. |
Utilities
- Error Lens: Highlights errors and warnings inline in your code.
- Path Intellisense: Autocompletes filenames.
- Dotenv: Support for
.envfile syntax highlighting.
Installing Extensions
To install any of the recommended extensions:
- Click the Extensions icon in the Activity Bar on the side of VSCode (or press
Ctrl + Shift + X). - Type the name of the extension in the search bar.
- Click Install.
Recommended Settings
Add these to your user settings.json (Ctrl + Shift + P > “Open User Settings (JSON)”) for a smoother experience:
Setting Up Your Workspace
1. Pulling Repositories
Use the integrated terminal (Ctrl + \``) or the Command Palette (Ctrl + Shift + P`) to clone your repositories.
2. Creating a Workspace
If you work across multiple repositories (e.g., one for Ansible playbooks, one for Python tools), use Multi-root Workspaces:
- Open your first repository folder.
- Go to File > Add Folder to Workspace…
- Select your second repository folder.
- Save the workspace: File > Save Workspace As…
3. Version Control Workflow
Basic Git Usage
- Stage Changes: Click the
+icon next to files in the Source Control tab. - Commit: Enter a message in the text box and click Commit.
- Push/Pull: Use the sync icon in the status bar or the
...menu in Source Control.
Creating Pull Requests (PRs)
With the GitHub Pull Requests and Issues extension:
- Push your branch to the remote repository.
- Click the GitHub icon in the Activity Bar.
- Click the + (Create Pull Request) icon.
- Follow the prompts to select base/head branches and enter a title/description.
Plugin Configuration Tips
Ansible & YAML
To ensure the YAML extension recognizes OpenShift/Kubernetes schemas:
- Open Settings (
Ctrl + ,). - Search for
yaml.schemas. - Add entries for your Kubernetes/OpenShift manifest patterns.
Python
Ensure you select the correct Python interpreter:
- Press
Ctrl + Shift + P. - Type
Python: Select Interpreter. - Choose the version or virtual environment (
.venv) relevant to your project.
Related Ideas & Next Steps
- Dev Containers: Use the Remote - Containers extension to define your development environment in a
Dockerfileordocker-compose.yamlwithin the repo. - Snippets: Create custom snippets for common Ansible tasks or OpenShift manifest headers.
- Tasks: Define VSCode Tasks (
tasks.json) to run your playbooks or tests with a single shortcut.