From 9a0f035528df449983ef2c2418f6eb849f14cc61 Mon Sep 17 00:00:00 2001 From: gziv Date: Sun, 31 May 2026 12:17:11 +0300 Subject: [PATCH 1/2] feat: add rhel-deploy ASE evaluation submission --- submissions/rhel-deploy/evals/evals.json | 18 + submissions/rhel-deploy/metadata.yaml | 5 + submissions/rhel-deploy/skills/SKILL.md | 486 +++++++++++++++ .../skills/references/builder-images.md | 308 ++++++++++ .../skills/references/debugging-patterns.md | 478 +++++++++++++++ .../skills/references/dynamic-validation.md | 259 ++++++++ .../skills/references/human-in-the-loop.md | 98 +++ .../references/image-selection-criteria.md | 221 +++++++ .../skills/references/prerequisites.md | 212 +++++++ .../references/python-s2i-entrypoints.md | 70 +++ .../skills/references/rhel-deployment.md | 580 ++++++++++++++++++ .../references/selinux-troubleshooting.md | 387 ++++++++++++ 12 files changed, 3122 insertions(+) create mode 100644 submissions/rhel-deploy/evals/evals.json create mode 100644 submissions/rhel-deploy/metadata.yaml create mode 100644 submissions/rhel-deploy/skills/SKILL.md create mode 100644 submissions/rhel-deploy/skills/references/builder-images.md create mode 100644 submissions/rhel-deploy/skills/references/debugging-patterns.md create mode 100644 submissions/rhel-deploy/skills/references/dynamic-validation.md create mode 100644 submissions/rhel-deploy/skills/references/human-in-the-loop.md create mode 100644 submissions/rhel-deploy/skills/references/image-selection-criteria.md create mode 100644 submissions/rhel-deploy/skills/references/prerequisites.md create mode 100644 submissions/rhel-deploy/skills/references/python-s2i-entrypoints.md create mode 100644 submissions/rhel-deploy/skills/references/rhel-deployment.md create mode 100644 submissions/rhel-deploy/skills/references/selinux-troubleshooting.md diff --git a/submissions/rhel-deploy/evals/evals.json b/submissions/rhel-deploy/evals/evals.json new file mode 100644 index 0000000..e81e1b3 --- /dev/null +++ b/submissions/rhel-deploy/evals/evals.json @@ -0,0 +1,18 @@ +{ + "skill_name": "rhel-deploy", + "evals": [ + { + "id": "rhel-deploy-eval", + "name": "RHEL Deployment Methodology", + "prompt": "You need to deploy a Python web application to a standalone RHEL 9 host via SSH, not to OpenShift. The host has Podman installed. The application needs persistent data stored at /var/data/myapp.\n\nDescribe your complete deployment methodology: how you analyze the target host capabilities, the two deployment strategies available and when to choose each, how you handle Podman container volume mounts with SELinux labels, the difference between rootful and rootless Podman systemd units, and what pre-deploy checks you would perform if Red Hat Insights is available.", + "expected_output": "A RHEL deployment methodology covering host analysis (OS version, Podman availability, SELinux status, firewall), two strategies (Container with Podman + systemd vs Native with dnf + systemd), SELinux volume labels :z (shared) vs :Z (private) for Podman mounts, rootful vs rootless systemd unit paths and linger, and optional Insights checks for RHEL lifecycle and CVEs.", + "assertions": [ + "The output describes two distinct deployment strategies: container-based (Podman with systemd) and native (direct installation with systemd), and provides guidance on when each is appropriate.", + "The output describes SELinux volume labeling for Podman container mounts using :z for shared volumes and :Z for private (exclusive) volumes to avoid SELinux denials on bind mounts.", + "The output distinguishes between rootful and rootless Podman deployments, noting different systemd unit file locations (/etc/systemd/system/ for rootful vs ~/.config/systemd/user/ for rootless) and that rootless requires loginctl enable-linger.", + "The output describes analyzing the target RHEL host capabilities before deployment, including checking RHEL version, Podman availability, SELinux enforcement status, and firewall state.", + "The output describes optionally checking Red Hat Insights before deployment for the RHEL version lifecycle status (active support vs end of life) and known critical CVEs on the target system." + ] + } + ] +} diff --git a/submissions/rhel-deploy/metadata.yaml b/submissions/rhel-deploy/metadata.yaml new file mode 100644 index 0000000..fcb1ec8 --- /dev/null +++ b/submissions/rhel-deploy/metadata.yaml @@ -0,0 +1,5 @@ +name: rhel-deploy +description: "CRITICAL: When user types /rhel-deploy, use THIS skill immediately." +persona: ocp-admin +version: "1.0.0" +eval_engine: ase diff --git a/submissions/rhel-deploy/skills/SKILL.md b/submissions/rhel-deploy/skills/SKILL.md new file mode 100644 index 0000000..fa9eb53 --- /dev/null +++ b/submissions/rhel-deploy/skills/SKILL.md @@ -0,0 +1,486 @@ +--- +name: rhel-deploy +description: 'CRITICAL: When user types /rhel-deploy, use THIS skill immediately. + This skill deploys applications to standalone RHEL/Fedora/CentOS systems (NOT OpenShift) + using Podman containers with systemd, or native dnf builds. Handles SSH connectivity, + SELinux, firewall-cmd, and systemd unit creation. Triggers: /rhel-deploy command, + ''deploy to RHEL'', ''deploy to Fedora'', ''deploy to my server via SSH''. + + ' +license: Apache-2.0 +metadata: + user_invocable: 'true' +--- + +# /rhel-deploy Skill + +**IMPORTANT:** This skill is for deploying to standalone RHEL/Fedora/CentOS systems via SSH. If user invoked `/rhel-deploy`, skip any OpenShift-related steps and proceed directly with SSH-based deployment. + +Deploy applications to standalone RHEL systems using Podman containers or native builds with systemd service management. + +## Overview + +``` +[Intro] → [SSH Connect] → [Analyze] → [Strategy] ──┬─→ [Container Path] ──→ [Complete] + │ (Podman + systemd) + │ + └─→ [Native Path] ─────→ [Complete] + (dnf + systemd) +``` + +**Deployment Strategies (user chooses one):** +- **Container** - Build/pull container image, run with Podman, manage with systemd +- **Native** - Install dependencies with dnf, run application directly, manage with systemd + +## Prerequisites + +1. SSH access to target RHEL host with sudo privileges +2. RHEL 8+, CentOS Stream, Rocky Linux, or Fedora +3. For container deployments: Podman installed on target +4. For native deployments: Required development tools available via dnf + +## When to Use This Skill + +Use `/rhel-deploy` when deploying applications to standalone RHEL, Fedora, or CentOS systems via SSH. This skill handles Podman container or native dnf deployments with systemd service management, SELinux, and firewall configuration. + +## Critical: Human-in-the-Loop Requirements + +See [Human-in-the-Loop Requirements](../../docs/human-in-the-loop.md) for mandatory checkpoint behavior. + +## Workflow + +### Phase 0: Introduction + +Present the workflow overview: Connect → Analyze → Strategy → Build/Deploy → Verify. Describe Container (Podman + systemd) vs Native (dnf + systemd) strategies. Ask: **Ready to begin?** (yes/no) + +**WAIT for user confirmation before proceeding.** + +### Phase 1: SSH Connection + +```markdown +## Phase 1: Connecting to RHEL Host + +**SSH Target Configuration:** + +Please provide your RHEL host details: + +| Setting | Value | Default | +|---------|-------|---------| +| Host | [required] | - | +| User | [current user] | $USER | +| Port | 22 | 22 | + +Example: `user@192.168.1.100` or `deploy@myserver.example.com` + +**Enter your SSH target:** +``` + +**Connection verification:** + +```bash +ssh -o BatchMode=yes -o ConnectTimeout=10 [user]@[host] "echo 'Connection successful'" +``` + +If connection fails, troubleshoot: host reachability, SSH key configuration, firewall port 22. + +Store `RHEL_HOST`, `RHEL_USER`, `RHEL_PORT` in session state. + +### Phase 2: Target Host Analysis + +```markdown +## Phase 2: Analyzing Target Host + +Checking capabilities of [host]... + +| Setting | Value | +|---------|-------| +| OS | [cat /etc/redhat-release] | +| Kernel | [uname -r] | +| Architecture | [uname -m] | +| Podman | [Installed v4.x / Not installed] | +| SELinux | [Enforcing / Permissive / Disabled] | +| Firewall | [Active / Inactive] | + +Is this the correct target host? (yes/no) +``` + +**WAIT for user confirmation before proceeding.** + +**Commands to gather information:** + +```bash +ssh [target] "cat /etc/redhat-release" +ssh [target] "podman --version 2>/dev/null || echo 'Not installed'" +ssh [target] "getenforce" +ssh [target] "firewall-cmd --state 2>/dev/null || echo 'Not running'" +``` + +Store `RHEL_VERSION`, `PODMAN_AVAILABLE`, `SELINUX_STATUS`, `FIREWALL_STATUS` in session state. + +### Phase 2b: Red Hat Insights Pre-Deploy Check (Optional) + +**This phase runs only if the `lightspeed-mcp` server is available.** Use `ToolSearch` to check for Lightspeed MCP tools. If not available, skip silently and proceed to Phase 3. + +**Step 1:** Use `find_host_by_name` with the target hostname to look up the system in Red Hat Insights. + +**Step 2:** If found, use `get_system_cves` to check for critical/important CVEs on the target. + +**Step 3:** Use `get_rhel_lifecycle` to verify the target RHEL version is still supported. + +Append to Phase 2 output: + +```markdown +**Red Hat Insights (Optional):** +| Check | Status | Details | +|-------|--------|---------| +| Registered in Insights | [Yes/No] | [system-id or "Not found"] | +| RHEL Lifecycle | [Active/Maintenance/EOL] | [end date] | +| Critical/Important CVEs | [count] | [top 3 CVE IDs] | + +[If critical CVEs found:] +**WARNING:** Target system has [N] critical/important CVEs. Consider remediating before deploying. + +[If RHEL version is EOL:] +**WARNING:** RHEL [version] has reached End of Life ([date]). Consider upgrading before deploying. +``` + +These are informational warnings only — they do not block deployment. + +### Phase 3: Strategy Selection + +```markdown +## Deployment Strategy + +Based on your project ([language]/[framework]) and target capabilities: + +| Strategy | Description | Requirements | +|----------|-------------|--------------| +| **Container** | Build image, run with Podman + systemd | Podman installed | +| **Native** | Install with dnf, run directly + systemd | Runtime packages available | + +**Recommendation:** [Container/Native] because [reason] + +**Which deployment strategy would you like to use?** +1. Container - Deploy using Podman +2. Native - Deploy directly on host +``` + +**WAIT for user confirmation before proceeding.** + +**If Podman not installed and user selects Container:** +```markdown +Podman is not installed on the target. Would you like me to install it? + +```bash +sudo dnf install -y podman +``` + +Proceed with Podman installation? (yes/no) +``` + +**WAIT for user confirmation before proceeding.** + +Store `DEPLOYMENT_STRATEGY` in session state. + +--- + +## CONTAINER PATH (If DEPLOYMENT_STRATEGY is "Container") + +### Phase 4a-1: Image Selection + +```markdown +## Container Image + +**Options:** + +1. **Build on target** - Transfer source, build with Podman on RHEL host +2. **Build locally and transfer** - Build here, push to registry or transfer +3. **Use existing image** - Pull from registry (e.g., quay.io, docker.io) + +Which approach would you prefer? +``` + +**WAIT for user confirmation before proceeding.** + +**For options 1 and 2 (building an image):** + +If no Containerfile/Dockerfile exists in the project, delegate to `/recommend-image`: + +```markdown +## Selecting Base Image + +To build your container, I need to select an appropriate base image. + +Invoking `/recommend-image` to get the optimal UBI image for your [language]/[framework] project... +``` + +Use the `BUILDER_IMAGE` output from `/recommend-image` as the base image in the Containerfile. + +**For build on target:** +```bash +# Transfer source and build +rsync -avz --exclude node_modules --exclude .git ./ [target]:/tmp/[app-name]-build/ +# If no Containerfile exists, generate one using BUILDER_IMAGE from /recommend-image +ssh [target] "cd /tmp/[app-name]-build && podman build -t [app-name]:latest ." +``` + +**For existing image:** +```bash +ssh [target] "podman pull [image-reference]" +``` + +### Phase 4a-2: Container Configuration + +```markdown +## Container Configuration + +**Container Settings:** +| Setting | Value | +|---------|-------| +| Name | [app-name] | +| Image | [image-ref] | +| Port Mapping | [host-port]:[container-port] | +| Volume Mounts | [list any persistent data paths] | +| Environment | [list env vars] | +| Run Mode | [rootless / rootful] | + +**SELinux Volume Labels:** Use `:z` for shared volumes, `:Z` for private volumes. See [docs/rhel-deployment.md](../../docs/rhel-deployment.md) for SELinux configuration details. + +Proceed with this configuration? (yes/modify/cancel) +``` + +**WAIT for user confirmation before proceeding.** + +### Phase 4a-3: Systemd Unit Creation + +```markdown +## Systemd Service Configuration + +Creating systemd unit for Podman container. + +**Template to use:** +- Rootful: `templates/systemd/systemd-container-rootful.service` +- Rootless: `templates/systemd/systemd-container-rootless.service` + +**Variables to substitute:** +| Variable | Value | +|----------|-------| +| `${APP_NAME}` | [app-name] | +| `${PORT}` | [container-port] | +| `${IMAGE}` | [container-image] | + +**Target locations:** +- Rootful: `/etc/systemd/system/[app-name].service` +- Rootless: `~/.config/systemd/user/[app-name].service` + +Proceed with creating this service? (yes/no) +``` + +**WAIT for user confirmation before proceeding.** + +**Steps to execute:** + +1. Read the appropriate template from `templates/systemd/` +2. Substitute `${APP_NAME}`, `${PORT}`, `${IMAGE}` with session state values +3. Transfer the generated unit file to the target host +4. Enable and start the service + +```bash +# Rootful: transfer to /etc/systemd/system/, daemon-reload, enable --now +# Rootless: transfer to ~/.config/systemd/user/, daemon-reload, enable --now, enable-linger +ssh [target] "sudo systemctl daemon-reload && sudo systemctl enable --now [app-name]" +``` + +### Phase 4a-4: Firewall Configuration + +```markdown +## Firewall Configuration + +Opening port [port] for application access. + +**Commands to execute:** +```bash +# Open port permanently +sudo firewall-cmd --permanent --add-port=[port]/tcp + +# Reload firewall +sudo firewall-cmd --reload + +# Verify +sudo firewall-cmd --list-ports +``` + +Proceed with firewall configuration? (yes/skip) +``` + +**WAIT for user confirmation before proceeding.** + +--- + +## NATIVE PATH (If DEPLOYMENT_STRATEGY is "Native") + +### Phase 4b-1: Dependency Installation + +```markdown +## Installing Dependencies + +**Runtime packages for [language]:** + +See [docs/rhel-deployment.md](../../docs/rhel-deployment.md) for the complete runtime package mapping by language and RHEL version (Node.js, Python, Java, Go, Ruby, PHP). + +**Commands to execute:** +```bash +ssh [target] "sudo dnf install -y [packages]" +``` + +Proceed with installation? (yes/no) +``` + +**WAIT for user confirmation before proceeding.** + +### Phase 4b-2: Application Deployment + +```markdown +## Deploying Application + +**Deployment location:** `/opt/[app-name]` + +**Steps:** +1. Create application directory +2. Transfer source code via rsync +3. Install application dependencies +4. Set ownership and permissions +5. Configure SELinux context + +```bash +ssh [target] "sudo mkdir -p /opt/[app-name]" +rsync -avz --exclude node_modules --exclude .git --exclude __pycache__ ./ [target]:/tmp/[app-name]-deploy/ +ssh [target] "sudo cp -r /tmp/[app-name]-deploy/* /opt/[app-name]/" +ssh [target] "cd /opt/[app-name] && npm install --production" # language-specific +ssh [target] "sudo chown -R [service-user]:[service-user] /opt/[app-name]" +ssh [target] "sudo semanage fcontext -a -t bin_t '/opt/[app-name](/.*)?'" +ssh [target] "sudo restorecon -Rv /opt/[app-name]" +``` + +Proceed with deployment? (yes/no) +``` + +**WAIT for user confirmation before proceeding.** + +### Phase 4b-3: Native Systemd Unit + +```markdown +## Systemd Service Configuration + +**Template to use:** `templates/systemd/systemd-native.service` + +**Variables to substitute:** +| Variable | Value | Notes | +|----------|-------|-------| +| `${APP_NAME}` | [app-name] | Application name | +| `${SERVICE_USER}` | [service-user] | User to run the service as | +| `${APP_PATH}` | /opt/[app-name] | Application install path | +| `${PORT}` | [container-port] | Application listen port | +| `${START_COMMAND}` | [see below] | Language-specific start command | + +**Start commands by language:** See [docs/rhel-deployment.md](../../docs/rhel-deployment.md) for language-specific systemd unit templates (Node.js, Python, Java, Go). + +**Target location:** `/etc/systemd/system/[app-name].service` + +**Note:** The template includes security hardening (NoNewPrivileges, ProtectSystem, ProtectHome, PrivateTmp). + +Proceed with creating this service? (yes/no) +``` + +**WAIT for user confirmation before proceeding.** + +**Steps to execute:** + +1. Read the template from `templates/systemd/systemd-native.service` +2. Substitute all variables with session state values +3. Transfer the generated unit file to the target host +4. Enable and start the service + +### Phase 4b-4: Firewall Configuration + +Same as container path - open required port with firewall-cmd. + +--- + +## COMPLETION (Both paths converge here) + +### Phase 5: Completion + +```markdown +## Deployment Complete! + +Your application is now running on [host]. + +**Application Summary:** +| Setting | Value | +|---------|-------| +| Name | [app-name] | +| Host | [host] | +| Strategy | [Container/Native] | +| Service | [app-name].service | + +**Access URLs:** +| Type | URL | +|------|-----| +| HTTP | http://[host]:[port] | +| SSH | ssh [user]@[host] | + +**Service Status:** [systemctl status output] + +**Quick Commands:** + +Show quick commands for: view logs (journalctl), restart/stop/status (systemctl), container logs (if container), and removal steps. +``` + +### Phase 5a: Handle Deployment Failure + +If the service fails to start or is not accessible: + +```markdown +## Deployment Failed + +The service did not start successfully. + +**Service Status:** [systemctl status output showing failure] + +**Recent Errors:** +| Time | Error | +|------|-------| +| [time] | [error from journalctl] | + +**Would you like me to diagnose the issue?** +1. **Debug RHEL** (`/debug-rhel`) - Full system diagnosis (systemd, journal, SELinux, firewall) +2. **Debug Container** (`/debug-container`) - Container state, logs, exit codes +3. **View full logs** - Complete journalctl output +4. **Check SELinux** - Quick SELinux denial check +5. **Check firewall** - Quick firewall port check +6. **Stop and clean up** + +Select an option: +``` + +**WAIT for user to select an option.** + +- If user selects "Debug RHEL" → Invoke `/debug-rhel` skill +- If user selects "Debug Container" → Invoke `/debug-container` skill +- After debugging → Offer to retry deployment + +## Dependencies + +### Required MCP Servers +- `lightspeed-mcp` (optional) - Red Hat Insights pre-deploy checks + +### Related Skills +- `/debug-rhel` - systemd failures, SELinux denials, firewall blocking +- `/debug-container` - Container startup issues on RHEL host + +### Reference Documentation +- [docs/rhel-deployment.md](../../docs/rhel-deployment.md) - Systemd templates, SELinux, firewall, runtime packages +- [docs/selinux-troubleshooting.md](../../docs/selinux-troubleshooting.md) - SELinux denial analysis and fixes +- [docs/debugging-patterns.md](../../docs/debugging-patterns.md) - Common error patterns and troubleshooting +- [docs/prerequisites.md](../../docs/prerequisites.md) - Required tools (ssh, podman) diff --git a/submissions/rhel-deploy/skills/references/builder-images.md b/submissions/rhel-deploy/skills/references/builder-images.md new file mode 100644 index 0000000..6561c5c --- /dev/null +++ b/submissions/rhel-deploy/skills/references/builder-images.md @@ -0,0 +1,308 @@ +--- +title: S2I Builder Image Reference +category: containers +sources: + - title: Red Hat Container Catalog + url: https://catalog.redhat.com/software/containers/search + sections: UBI images, S2I builders + date_accessed: 2026-02-08 + - title: OpenShift Source-to-Image (S2I) + url: https://docs.openshift.com/container-platform/latest/openshift_images/using_images/using-s21-images.html + sections: S2I builder images, Language detection + date_accessed: 2026-02-08 + - title: Red Hat Universal Base Images + url: https://developers.redhat.com/products/rhel/ubi + sections: UBI9 images, Language runtimes + date_accessed: 2026-02-08 +--- + +# S2I Builder Image Reference + +Use this reference when recommending S2I builder images to users. + +> **Note:** Versions marked "Recommended" may change. Always verify with `skopeo inspect` before use. Prefer matching the project's version requirements over these defaults. + +For use-case-aware image selection, use the `/recommend-image` skill. + +--- + +## Dynamic Lookup and Verification + +**This reference may be outdated.** Always verify image availability before recommending. + +### Verify with Skopeo (Recommended) + +```bash +# Check if an image exists and get metadata +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 + +# Get specific fields +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 --format '{{.Created}}' +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 --format '{{.Architecture}}' + +# List all available tags +skopeo list-tags docker://registry.access.redhat.com/ubi9/nodejs-20 +``` + +**If skopeo is not installed**, prompt the user: +``` +Install with: sudo dnf install skopeo (Fedora/RHEL) + sudo apt install skopeo (Ubuntu/Debian) + brew install skopeo (macOS) +``` + +### Check Security Status (Red Hat Security Data API) + +Query CVE information (no authentication required): + +```bash +# Check for critical CVEs affecting UBI9 +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209&severity=critical" | jq 'length' + +# Get CVE details +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209&severity=critical" | jq '.[] | {cve: .CVE, severity: .severity}' +``` + +### Verify with Red Hat Catalog API (Alternative) + +```bash +# Search for available Node.js images +curl -s "https://catalog.redhat.com/api/containers/v1/repositories?filter=repository=like=ubi9/nodejs" | jq '.data[].repository' + +# Search for available Python images +curl -s "https://catalog.redhat.com/api/containers/v1/repositories?filter=repository=like=ubi9/python" | jq '.data[].repository' +``` + +--- + +## Project Detection and Version Mapping + +### Extract Version from Project Files + +Before recommending an image, check the project's version requirements: + +| Project File | How to Extract Version | +|--------------|------------------------| +| `package.json` | `.engines.node` field | +| `requirements.txt` | `python_requires` or comments | +| `pyproject.toml` | `[project].requires-python` | +| `pom.xml` | `` or `` | +| `go.mod` | `go` directive (e.g., `go 1.21`) | +| `*.csproj` | `` (e.g., `net8.0`) | + +### Detect Language from Files + +| Indicator File(s) | Language | Framework | Version Source | +|-------------------|----------|-----------|----------------| +| `package.json` | Node.js | - | `.engines.node` | +| `package.json` + `next.config.js` | Node.js | Next.js | `.engines.node` | +| `package.json` + `angular.json` | Node.js | Angular | `.engines.node` | +| `pom.xml` | Java | Maven | `` or `` | +| `pom.xml` + quarkus dep | Java | Quarkus | `` (prefer 21+) | +| `pom.xml` + spring-boot dep | Java | Spring Boot | `` | +| `build.gradle` / `build.gradle.kts` | Java | Gradle | `sourceCompatibility` or `java.toolchain` | +| `requirements.txt` | Python | - | `python_requires` or shebang | +| `Pipfile` | Python | Pipenv | `[requires].python_version` | +| `pyproject.toml` | Python | Poetry/Modern | `[project].requires-python` | +| `go.mod` | Go | - | `go` directive line | +| `Gemfile` | Ruby | - | `ruby` directive or `.ruby-version` | +| `*.csproj` / `*.sln` | .NET | - | `` (e.g., net8.0 → 80) | +| `composer.json` | PHP | - | `require.php` field | +| `Cargo.toml` | Rust | - | Custom (no official S2I) | + +### Map Version to Image + +**Quick lookup pattern:** `ubi9/{language}-{version}` (e.g., `ubi9/nodejs-20`, `ubi9/python-311`) + +| Language | Version Mapping | Image Pattern | +|----------|-----------------|---------------| +| Node.js | 18.x → 18, 20.x → 20, 22.x → 22 | `ubi9/nodejs-{major}` | +| Python | 3.9 → 39, 3.11 → 311, 3.12 → 312 | `ubi9/python-{majmin}` | +| Java | 11, 17, 21 (use nearest LTS) | `ubi9/openjdk-{version}` | +| Go | 1.21 → 1.21, 1.22 → 1.22 | `ubi9/go-toolset:{version}` | +| Ruby | 3.1 → 31, 3.3 → 33 | `ubi9/ruby-{majmin}` | +| .NET | net6.0 → 60, net8.0 → 80 | `ubi9/dotnet-{version}` | +| PHP | 8.0 → 80, 8.1 → 81 | `ubi9/php-{majmin}` | + +### Verify and Fallback + +1. **Verify image exists**: `skopeo inspect docker://registry.access.redhat.com/ubi9/{image}` +2. **If version not found**: Use nearest available LTS version +3. **If no version in project**: Use current LTS (check catalog API) + +--- + +## Red Hat UBI-based Images + +### Node.js + +| Version | Full Image | Minimal Image | Use Case | +|---------|------------|---------------|----------| +| 18 LTS | `registry.access.redhat.com/ubi9/nodejs-18` | `registry.access.redhat.com/ubi9/nodejs-18-minimal` | Long-term support | +| 20 LTS | `registry.access.redhat.com/ubi9/nodejs-20` | `registry.access.redhat.com/ubi9/nodejs-20-minimal` | **Recommended** | +| 22 | `registry.access.redhat.com/ubi9/nodejs-22` | `registry.access.redhat.com/ubi9/nodejs-22-minimal` | Current | + +**Choose minimal for:** Production, security-focused, smaller image size +**Choose full for:** Development, native module compilation + +### Python + +| Version | Image | Notes | +|---------|-------|-------| +| 3.9 | `registry.access.redhat.com/ubi9/python-39` | | +| 3.11 | `registry.access.redhat.com/ubi9/python-311` | **Recommended** | +| 3.12 | `registry.access.redhat.com/ubi9/python-312` | Latest | + +### Java / OpenJDK + +| Version | Build Image | Runtime Image | Notes | +|---------|-------------|---------------|-------| +| 11 LTS | `registry.access.redhat.com/ubi8/openjdk-11` | `registry.access.redhat.com/ubi8/openjdk-11-runtime` | LTS | +| 17 LTS | `registry.access.redhat.com/ubi9/openjdk-17` | `registry.access.redhat.com/ubi9/openjdk-17-runtime` | **Recommended** | +| 21 LTS | `registry.access.redhat.com/ubi9/openjdk-21` | `registry.access.redhat.com/ubi9/openjdk-21-runtime` | Latest LTS | + +**Choose runtime for:** Production with pre-built JARs, smallest footprint +**Choose build for:** S2I builds, Maven/Gradle compilation needed + +### Go + +| Version | Image | Notes | +|---------|-------|-------| +| 1.20 | `registry.access.redhat.com/ubi9/go-toolset:1.20` | | +| 1.21 | `registry.access.redhat.com/ubi9/go-toolset:1.21` | **Recommended** | + +### Ruby + +| Version | Image | Notes | +|---------|-------|-------| +| 3.1 | `registry.access.redhat.com/ubi9/ruby-31` | | +| 3.3 | `registry.access.redhat.com/ubi9/ruby-33` | **Recommended** | + +### .NET + +| Version | Build Image | Runtime Image | Notes | +|---------|-------------|---------------|-------| +| 6.0 LTS | `registry.access.redhat.com/ubi8/dotnet-60` | `registry.access.redhat.com/ubi8/dotnet-60-runtime` | LTS | +| 7.0 | `registry.access.redhat.com/ubi8/dotnet-70` | `registry.access.redhat.com/ubi8/dotnet-70-runtime` | | +| 8.0 LTS | `registry.access.redhat.com/ubi9/dotnet-80` | `registry.access.redhat.com/ubi9/dotnet-80-runtime` | **Recommended** | + +**Choose runtime for:** Production with pre-built assemblies +**Choose build for:** S2I builds, dotnet build/publish needed + +### PHP + +| Version | Image | Notes | +|---------|-------|-------| +| 8.0 | `registry.access.redhat.com/ubi9/php-80` | | +| 8.1 | `registry.access.redhat.com/ubi9/php-81` | **Recommended** | + +### Perl + +| Version | Image | Notes | +|---------|-------|-------| +| 5.32 | `registry.access.redhat.com/ubi9/perl-532` | | + +--- + +## Image Variants and Use-Case Selection + +### Quick Use-Case Matrix + +| Use Case | Variant | Priority | Example | +|----------|---------|----------|---------| +| Production | Minimal/Runtime | Security, Size | `nodejs-20-minimal` | +| Development | Full | Tools, Debug | `nodejs-20` | +| Serverless | Minimal | Startup Time | `openjdk-21-runtime` | +| Edge/IoT | Minimal | Size | `nodejs-20-minimal` | + +### Image Variants + +| Variant | Description | Has Build Tools | Size | +|---------|-------------|-----------------|------| +| Full | Complete development environment | Yes | Largest | +| Minimal | Essential packages only | Limited | Medium | +| Runtime | Runtime only, no build tools | No | Smallest | + +**Availability by language:** + +| Language | Full | Minimal | Runtime | +|----------|------|---------|---------| +| Node.js | `nodejs-{ver}` | `nodejs-{ver}-minimal` | - | +| Python | `python-{ver}` | - | - | +| Java | `openjdk-{ver}` | - | `openjdk-{ver}-runtime` | +| Go | `go-toolset:{ver}` | - | (produces static binary) | +| .NET | `dotnet-{ver}` | - | `dotnet-{ver}-runtime` | +| Ruby | `ruby-{ver}` | - | - | +| PHP | `php-{ver}` | - | - | + +### When to Recommend Each Variant + +**Full variant:** +- User needs to compile native extensions +- Development/debugging environment +- CI/CD build stages + +**Minimal variant:** +- Production deployments +- Security-focused environments +- When size matters but some tools needed + +**Runtime variant:** +- Pre-compiled applications (JARs, .NET assemblies) +- Maximum security posture +- Smallest possible footprint + +--- + +## OpenShift Built-in ImageStreams + +These are often pre-configured in OpenShift clusters under the `openshift` namespace: + +| ImageStream | Usage | +|-------------|-------| +| `nodejs:20-ubi9` | Node.js 20 on UBI 9 | +| `python:3.11-ubi9` | Python 3.11 on UBI 9 | +| `openjdk-17-ubi8` | Java 17 on UBI 8 | +| `ruby:3.1-ubi9` | Ruby 3.1 on UBI 9 | +| `php:8.0-ubi9` | PHP 8.0 on UBI 9 | + +When using OpenShift ImageStreams, reference them as: +```yaml +from: + kind: ImageStreamTag + namespace: openshift + name: nodejs:20-ubi9 +``` + +--- + +## Framework-Specific Recommendations + +### Quarkus (Java) +- **Native build**: `quay.io/quarkus/ubi-quarkus-mandrel-builder-image:jdk-21` +- **JVM build**: `registry.access.redhat.com/ubi9/openjdk-21` + +### Spring Boot (Java) +- Use: `registry.access.redhat.com/ubi9/openjdk-17` or `openjdk-21` +- Ensure `spring-boot-maven-plugin` is configured for packaging + +### Next.js / React (Node.js) +- Use: `registry.access.redhat.com/ubi9/nodejs-20` +- Ensure build outputs to `build/` or `.next/` + +### Django / Flask (Python) +- Use: `registry.access.redhat.com/ubi9/python-311` +- Ensure `requirements.txt` or `Pipfile` exists at root + +### Express.js (Node.js) +- Use: `registry.access.redhat.com/ubi9/nodejs-18` or higher +- Ensure `npm start` script is defined in `package.json` + +--- + +## Python S2I Entry Point Requirements + +**Quick reference:** +- Default entry point: `app.py` (works without configuration) +- Custom entry points require: `gunicorn` + `APP_MODULE` environment variable +- Format: `APP_MODULE=module:variable` (e.g., `main:app`) diff --git a/submissions/rhel-deploy/skills/references/debugging-patterns.md b/submissions/rhel-deploy/skills/references/debugging-patterns.md new file mode 100644 index 0000000..2863d55 --- /dev/null +++ b/submissions/rhel-deploy/skills/references/debugging-patterns.md @@ -0,0 +1,478 @@ +--- +title: Debugging Patterns +category: references +sources: + - title: Kubernetes Debugging Pods + url: https://kubernetes.io/docs/tasks/debug/debug-application/debug-pods/ + sections: Debugging Pods, Common Errors + date_accessed: 2026-02-16 + - title: OpenShift Troubleshooting Guide + url: https://docs.openshift.com/container-platform/latest/support/troubleshooting/troubleshooting-operator-issues.html + sections: Pod issues, Build issues + date_accessed: 2026-02-16 + - title: OpenShift Pipelines Troubleshooting + url: https://docs.openshift.com/pipelines/latest/about/about-openshift-pipelines.html + sections: Troubleshooting, PipelineRun status, TaskRun status + date_accessed: 2026-02-25 + - title: Podman Troubleshooting + url: https://github.com/containers/podman/blob/main/troubleshooting.md + sections: Common Issues + date_accessed: 2026-02-16 +--- + +# Debugging Patterns + +This document provides common error patterns, exit codes, and troubleshooting decision trees for the debugging skills. + +## Exit Code Reference + +### Container/Process Exit Codes + +| Exit Code | Signal | Meaning | Common Cause | +|-----------|--------|---------|--------------| +| 0 | - | Success | Normal termination | +| 1 | - | General error | Application error, unhandled exception | +| 2 | - | Misuse of shell | Invalid arguments, syntax error | +| 126 | - | Permission denied | Cannot execute command | +| 127 | - | Command not found | Binary/script missing in PATH | +| 128 | - | Invalid exit argument | Exit called with non-integer | +| 128+N | Signal N | Killed by signal | See signal table below | +| 137 | SIGKILL (9) | Force killed | OOM kill, manual kill, timeout | +| 139 | SIGSEGV (11) | Segmentation fault | Memory corruption, null pointer | +| 143 | SIGTERM (15) | Terminated | Graceful shutdown request | + +### Signal Reference (128+N) + +| Signal | Number | Exit Code | Typical Cause | +|--------|--------|-----------|---------------| +| SIGHUP | 1 | 129 | Terminal closed | +| SIGINT | 2 | 130 | Ctrl+C | +| SIGQUIT | 3 | 131 | Ctrl+\ | +| SIGKILL | 9 | 137 | OOM, forced termination | +| SIGSEGV | 11 | 139 | Segmentation fault | +| SIGTERM | 15 | 143 | Graceful stop request | + +## Pod Failure Patterns + +### CrashLoopBackOff + +**Symptom:** Pod repeatedly crashes and restarts + +**Diagnosis Flow:** +``` +CrashLoopBackOff +├─ Check exit code +│ ├─ 0 → Application exits normally (missing loop/server?) +│ ├─ 1 → Application error (check logs) +│ ├─ 127 → Command not found (check entrypoint) +│ └─ 137 → OOM killed (check memory limits) +├─ Check logs (current + previous) +│ ├─ Import errors → Missing dependencies +│ ├─ Connection errors → External service down +│ └─ Config errors → Missing env vars/secrets +└─ Check events + └─ FailedMount → Missing secrets/configmaps +``` + +**Common Causes:** +1. Application crashes on startup (dependency errors) +2. Memory limit too low (OOMKilled) +3. Missing environment variables or secrets +4. Database/service connection failures +5. Health probe failing immediately + +### ImagePullBackOff + +**Symptom:** Cannot pull container image + +**Diagnosis Flow:** +``` +ImagePullBackOff +├─ Check event message +│ ├─ "unauthorized" → Registry authentication +│ │ └─ Check imagePullSecrets +│ ├─ "not found" → Wrong image name/tag +│ │ └─ Verify image exists in registry +│ ├─ "timeout" → Network/registry issue +│ │ └─ Check cluster network egress +│ └─ "manifest unknown" → Tag doesn't exist +│ └─ Verify tag in registry +└─ Check image reference + ├─ Missing registry prefix? + ├─ Typo in image name? + └─ Tag exists? +``` + +**Common Causes:** +1. Private registry without imagePullSecret +2. Image tag doesn't exist +3. Registry URL typo +4. Network policy blocking egress +5. Registry rate limiting + +### Pending Pod + +**Symptom:** Pod stuck in Pending state + +**Diagnosis Flow:** +``` +Pending +├─ Check events +│ ├─ "FailedScheduling" +│ │ ├─ "Insufficient cpu/memory" → Scale cluster or reduce requests +│ │ ├─ "node selector" → No matching nodes +│ │ ├─ "taints" → Need tolerations +│ │ └─ "PVC not bound" → Storage issue +│ └─ No events → Check resourceQuota +└─ Check node status + └─ All nodes NotReady? → Node issue +``` + +**Common Causes:** +1. Insufficient cluster resources +2. Node selector doesn't match any nodes +3. PersistentVolumeClaim not bound +4. Resource quota exceeded +5. Affinity/anti-affinity rules too strict + +### OOMKilled + +**Symptom:** Container terminated with exit code 137 + +**Diagnosis Flow:** +``` +OOMKilled (exit 137) +├─ Check container state +│ └─ OOMKilled: true → Memory exhaustion confirmed +├─ Compare memory usage vs limit +│ ├─ Limit too low → Increase memory limit +│ └─ Memory leak → Profile application +└─ Check for: + ├─ Java → Heap size (-Xmx) exceeds limit + ├─ Node.js → --max-old-space-size too high + └─ Python → Large data structures in memory +``` + +**Common Causes:** +1. Memory limit set too low for application +2. Memory leak in application +3. Java heap size exceeds container limit +4. Processing large files/datasets in memory + +## Build Failure Patterns + +### S2I Build Phases + +| Phase | What Happens | Common Failures | +|-------|--------------|-----------------| +| **fetch-source** | Clone git repository | Auth failure, repo not found | +| **pull-builder** | Pull S2I builder image | Image not found, auth | +| **assemble** | Run S2I assemble script | Dependency install, build errors | +| **commit** | Create image layer | Disk space | +| **push** | Push to internal registry | Auth, quota | + +### Assemble Phase Failures + +**Node.js:** +``` +npm ERR! 404 Not Found +└─ Package doesn't exist in registry + → Check package.json for typos + +npm ERR! code ERESOLVE +└─ Dependency conflict + → Run npm install --legacy-peer-deps + +npm ERR! code ENOENT +└─ File not found + → Check paths in package.json +``` + +**Python:** +``` +ERROR: Could not find a version that satisfies the requirement +└─ Package not found + → Check requirements.txt spelling + +ModuleNotFoundError: No module named 'X' +└─ APP_MODULE misconfigured + → See docs/python-s2i-entrypoints.md + +gunicorn: command not found +└─ gunicorn not in requirements + → Add gunicorn to requirements.txt +``` + +**Java:** +``` +[ERROR] Failed to execute goal +└─ Maven/Gradle build failure + → Check pom.xml or build.gradle + +java.lang.OutOfMemoryError: Java heap space +└─ Build needs more memory + → Add MAVEN_OPTS=-Xmx512m +``` + +## Pipeline/Tekton Failure Patterns + +### PipelineRun Failure Decision Tree + +``` +PipelineRun Failed +├─ Check PipelineRun status conditions +│ ├─ "PipelineRunTimeout" → Increase spec.timeouts.pipeline +│ ├─ "CouldntGetPipeline" → Pipeline reference invalid, check name/namespace +│ ├─ "PipelineRunCancelled" → Check if timeout or manual cancellation +│ └─ "Failed" → Check which TaskRun failed (see below) +├─ Check failed TaskRun +│ ├─ Step failure (non-zero exit) +│ │ ├─ git-clone step → Auth/URL issue (check SA secrets) +│ │ ├─ build step → Compilation/dependency error +│ │ ├─ push step → Registry auth (check SA dockerconfigjson secret) +│ │ └─ test step → Test failures +│ ├─ Pod scheduling failure → Resource constraints (FailedScheduling event) +│ ├─ Workspace issue → PVC not bound or permission denied +│ └─ Step image pull failure → ImagePullBackOff on step container +└─ Pipeline stuck (Running too long) + ├─ TaskRun pending → Pod can't be scheduled + ├─ Step running indefinitely → Check logs for hang/deadlock + └─ Custom task waiting → Check custom task controller +``` + +### TaskRun Failure Analysis + +``` +TaskRun Failed +├─ Pod not created → Check ServiceAccount exists, resource quotas +├─ Pod pending → Scheduling issue (see Pod Failure Patterns) +├─ Pod terminated → Check step statuses +│ ├─ Exit 1 → Script/application error (check step logs) +│ ├─ Exit 125-127 → Entrypoint/command issue in step image +│ └─ Exit 137 → OOM killed (increase step resources) +└─ Workspace binding failure + ├─ PVC not found → Create PVC or fix workspace binding + ├─ RWO blocks parallel tasks → Use RWX or separate workspaces + └─ Permission denied → Check fsGroup, runAsUser in pod security context +``` + +### Common Tekton Error Messages + +| Error Message | Fix | +|--------------|-----| +| `task "X" not found` | Verify Task name, kind (Task vs ClusterTask), namespace | +| `could not read Username for...` | Add git-credentials secret (annotated with `tekton.dev/git-0`) to ServiceAccount | +| `unauthorized: access denied` (push) | Add dockerconfigjson secret (annotated with `tekton.dev/docker-0`) to ServiceAccount | +| `persistentvolumeclaim "X" not found` | Create PVC or change workspace binding to emptyDir | +| `exceeded timeout` | Increase timeouts in PipelineRun spec (`spec.timeouts.pipeline` / `spec.timeouts.tasks`) | +| `missing required parameter "X"` | Add parameter value to PipelineRun spec | +| `couldn't find remote ref` | Fix git `revision` parameter (branch/tag name) | +| `unable to open Containerfile/Dockerfile` | Fix `DOCKERFILE` param path relative to workspace root | + +## Network Troubleshooting + +### Service Has No Endpoints + +**Diagnosis Flow:** +``` +No endpoints +├─ Check service selector +│ └─ Compare with pod labels +│ ├─ Labels don't match → Fix selector or pod labels +│ └─ Labels match → Check pod readiness +├─ Check pod status +│ ├─ Pods not running → Debug pods first +│ └─ Pods running but not ready → Check readiness probe +└─ Check readiness probe + ├─ HTTP probe failing → Application not listening + └─ TCP probe failing → Wrong port +``` + +### Route Returning 503 + +**Diagnosis Flow:** +``` +503 Service Unavailable +├─ Check endpoints +│ └─ No endpoints → Pods not ready +├─ Check backend pods +│ ├─ All pods failing readiness → Application issue +│ └─ Some pods ready → Load balancer issue +└─ Check route configuration + └─ Wrong service or port → Fix route spec +``` + +### Connection Refused + +**Diagnosis Flow:** +``` +Connection refused +├─ Is service created? → oc get svc +├─ Does service have endpoints? → oc get endpoints +├─ Is pod running? → oc get pods +├─ Is application listening? → Check container port +└─ Is port correct? → Compare service port vs container port +``` + +## RHEL System Patterns + +### systemd Service Failures + +| Exit Code | Meaning | Common Fix | +|-----------|---------|------------| +| 1 | General error | Check application logs | +| 126 | Permission | Check ExecStart permissions | +| 127 | Not found | Check binary path in ExecStart | +| 203 | EXEC | Wrong architecture or format | +| 217 | USER | Service user doesn't exist | + +### SELinux Denial Patterns + +| Denial Type | Example | Typical Fix | +|-------------|---------|-------------| +| Port binding | `httpd_t` bind `port_t` | `semanage port -a -t http_port_t -p tcp [port]` | +| File read | `httpd_t` read `user_home_t` | `semanage fcontext` + `restorecon` | +| Network connect | `httpd_t` connect | `setsebool -P httpd_can_network_connect on` | +| Container | `container_t` manage | `setsebool -P container_manage_cgroup on` | + +See [selinux-troubleshooting.md](selinux-troubleshooting.md) for detailed SELinux guidance. + +## Troubleshooting Decision Tree + +### Application Not Accessible + +``` +Cannot access application +├─ Internal (from cluster)? +│ ├─ Yes, works internally → Route/Ingress issue +│ │ ├─ Check route admitted +│ │ ├─ Check route host/path +│ │ └─ Check TLS configuration +│ └─ No, fails internally too → Service/Pod issue +│ ├─ Check service endpoints +│ ├─ Check pod status +│ └─ Check pod readiness +└─ Neither works? + └─ Debug pod first (/debug-pod) +``` + +### Build Keeps Failing + +``` +Build failures +├─ Which phase? +│ ├─ fetch-source → Git access issue +│ │ ├─ Check source secret +│ │ └─ Verify git URL +│ ├─ pull-builder → Builder image issue +│ │ ├─ Check image reference +│ │ └─ Import ImageStream +│ ├─ assemble → Build script issue +│ │ ├─ Check dependencies +│ │ └─ Check language-specific config +│ └─ push → Registry issue +│ └─ Check push secret +└─ Same failure pattern? + └─ Compare with last successful build +``` + +### Pipeline Keeps Failing + +``` +Pipeline failures +├─ Same task always fails? +│ ├─ git-clone → Check ServiceAccount secrets, git URL, revision +│ ├─ build step → Check source code, Containerfile path, build context +│ └─ push step → Check ServiceAccount imagePullSecrets, registry URL +├─ Different tasks fail? +│ ├─ Resource exhaustion → Reduce parallel tasks or increase quotas +│ └─ Workspace contention → Use RWX PVC or separate workspaces +├─ Pipeline hangs? +│ ├─ TaskRun pending → Pod can't be scheduled +│ └─ Step running indefinitely → Check step logs +└─ Pipeline never triggers? + ├─ EventListener pod not running → Check EL deployment/logs + ├─ Webhook misconfigured → Verify webhook URL and secret + └─ TriggerBinding wrong → Check CEL expression param extraction +``` + +## Quick Reference Commands + +### OpenShift Debugging + +```bash +# Pod status and events +oc describe pod [pod-name] + +# Pod logs (current) +oc logs [pod-name] + +# Pod logs (previous container) +oc logs [pod-name] --previous + +# All events in namespace +oc get events --sort-by='.lastTimestamp' + +# Check endpoints +oc get endpoints [service-name] + +# Build logs +oc logs build/[build-name] +``` + +### Pipeline/Tekton Debugging + +```bash +# List PipelineRuns (oldest first) +oc get pipelinerun --sort-by='.metadata.creationTimestamp' + +# Get PipelineRun details +oc get pipelinerun [name] -o yaml + +# List TaskRuns for a PipelineRun +oc get taskrun -l tekton.dev/pipelineRun=[pipelinerun-name] + +# Get TaskRun pod logs for a specific step +oc logs [taskrun-name]-pod -c step-[step-name] + +# Get events for pipeline resources +oc get events --field-selector involvedObject.kind=PipelineRun + +# Describe EventListener +oc get eventlistener [name] -o yaml +``` + +### RHEL Debugging + +```bash +# Service status +systemctl status [service] + +# Journal logs +journalctl -u [service] -n 100 + +# SELinux denials +ausearch -m AVC -ts recent + +# Firewall rules +firewall-cmd --list-all + +# SELinux context +ls -lZ [path] +``` + +### Container Debugging + +```bash +# List all containers +podman ps -a + +# Container inspect +podman inspect [container] + +# Container logs +podman logs [container] + +# Run interactively for debugging +podman run -it --entrypoint /bin/sh [image] +``` diff --git a/submissions/rhel-deploy/skills/references/dynamic-validation.md b/submissions/rhel-deploy/skills/references/dynamic-validation.md new file mode 100644 index 0000000..a027f0c --- /dev/null +++ b/submissions/rhel-deploy/skills/references/dynamic-validation.md @@ -0,0 +1,259 @@ +--- +title: Dynamic Image Validation Reference +category: containers +sources: + - title: Skopeo Documentation + url: https://github.com/containers/skopeo + sections: Inspecting images, Copying images + date_accessed: 2026-02-08 + - title: Red Hat Security Data API + url: https://access.redhat.com/documentation/en-us/red_hat_security_data_api/1.0 + sections: CVE queries, Product filtering + date_accessed: 2026-02-08 +--- + +# Dynamic Image Validation Reference + +This document provides detailed patterns for validating container images using Skopeo and the Red Hat Security Data API. + +## Skopeo Commands + +Skopeo inspects container images without downloading them, providing real-time metadata. + +### Prerequisites + +**Check if skopeo is installed:** +```bash +which skopeo +# or +skopeo --version +``` + +**Installation:** +| OS | Command | +|----|---------| +| Fedora/RHEL/CentOS | `sudo dnf install skopeo` | +| Ubuntu/Debian | `sudo apt install skopeo` | +| macOS (Homebrew) | `brew install skopeo` | + +### Basic Inspection + +```bash +# Inspect an image (full JSON output) +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 + +# The docker:// transport is OCI-standard and works with all registries +# (Docker Hub, Red Hat, Quay, Podman registries, etc.) +``` + +### Extracting Specific Fields + +```bash +# Get creation date +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 --format '{{.Created}}' + +# Get architecture +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 --format '{{.Architecture}}' + +# Get all labels +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 --format '{{.Labels}}' + +# Get specific label (e.g., version) +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 --format '{{index .Labels "version"}}' + +# Get layer count +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 --format '{{len .Layers}}' +``` + +### Listing Available Tags + +```bash +# List all tags for an image +skopeo list-tags docker://registry.access.redhat.com/ubi9/nodejs-20 + +# Output includes all available versions/tags +``` + +### Image Transport Options + +```bash +# Remote registry (most common) +skopeo inspect docker://registry.access.redhat.com/ubi9/nodejs-20 + +# Local Podman storage +skopeo inspect containers-storage:localhost/myimage:latest + +# OCI layout directory +skopeo inspect oci:/path/to/oci-layout:tag + +# Docker archive +skopeo inspect docker-archive:/path/to/image.tar +``` + +### Useful Metadata Fields + +| Field | Description | Use Case | +|-------|-------------|----------| +| `Created` | Image build timestamp | Freshness indicator | +| `Architecture` | CPU architecture | Verify ARM64/x86_64 support | +| `Os` | Operating system | Should be "linux" for UBI | +| `Labels` | Image labels (version, maintainer, etc.) | Verify language version | +| `Layers` | Layer digests | Calculate approximate size | +| `Digest` | Immutable image hash | Pin exact version | + +### Error Handling + +**Image not found:** +``` +Error: Error reading manifest: ... 404 Not Found +``` +→ Image does not exist at specified tag + +**Authentication required:** +``` +Error: Error reading manifest: unauthorized +``` +→ Private registry, need `skopeo login` first + +**Network error:** +``` +Error: Error initializing source: pinging container registry +``` +→ Network connectivity issue + +--- + +## Red Hat Security Data API + +The Security Data API provides CVE information without authentication. + +### Base Endpoint + +``` +https://access.redhat.com/hydra/rest/securitydata/ +``` + +### Query CVEs + +```bash +# Get all CVEs for UBI 9 (may return many results) +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209" + +# Filter by severity (critical, important, moderate, low) +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209&severity=critical" + +# Filter by date (CVEs after a specific date) +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209&after=2025-01-01" + +# Count critical CVEs +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209&severity=critical" | jq 'length' +``` + +### Product Names for Queries + +| Image Base | Product Name (URL-encoded) | +|------------|---------------------------| +| UBI 9 | `Red%20Hat%20Universal%20Base%20Image%209` | +| UBI 8 | `Red%20Hat%20Universal%20Base%20Image%208` | +| RHEL 9 | `Red%20Hat%20Enterprise%20Linux%209` | +| RHEL 8 | `Red%20Hat%20Enterprise%20Linux%208` | + +### Response Fields + +Each CVE object contains: + +| Field | Description | +|-------|-------------| +| `CVE` | CVE identifier (e.g., CVE-2024-1234) | +| `severity` | critical, important, moderate, low | +| `public_date` | When CVE was disclosed | +| `advisories` | Related Red Hat advisories | +| `bugzilla` | Bugzilla tracking URL | +| `affected_packages` | Packages affected by CVE | + +### Parsing Examples + +```bash +# Get CVE IDs and severities +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209&severity=critical" | jq '.[] | {cve: .CVE, severity: .severity}' + +# Get most recent CVE date +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209&severity=critical" | jq '.[0].public_date' + +# Check if any critical CVEs exist +CRITICAL_COUNT=$(curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?product=Red%20Hat%20Universal%20Base%20Image%209&severity=critical" | jq 'length') +if [ "$CRITICAL_COUNT" -gt 0 ]; then + echo "Warning: $CRITICAL_COUNT critical CVEs found" +fi +``` + +--- + +## Validation Workflow + +### Complete Validation Sequence + +``` +1. Check if skopeo is installed + ├── Yes → Continue to step 2 + └── No → Prompt user to install, offer to continue with static data + +2. For each candidate image: + a. Run: skopeo inspect docker://registry.access.redhat.com/ubi9/[image] + b. If fails → Remove from candidates, try next + c. If succeeds → Extract: Created, Architecture, Labels + +3. Query Security Data API for UBI base: + a. Run: curl CVE query for critical severity + b. Parse count of critical CVEs + c. If count > 0 → Add warning to recommendation + +4. Compile results: + - Image metadata (from skopeo) + - Security status (from API) + - Static scoring data (from reference tables) + +5. Present recommendation with sources indicated +``` + +### Fallback Behavior + +| Scenario | Action | +|----------|--------| +| Skopeo not installed | Prompt installation, offer static-only mode | +| Skopeo command fails | Note "unable to verify", use static data | +| Security API unavailable | Note "security not verified", proceed | +| Image not found | Remove from candidates, suggest alternatives | +| Network offline | Use static data only, note limitations | + +--- + +## Integration with Recommendation Output + +### When Dynamic Data Available + +```markdown +| Property | Value | Source | +|----------|-------|--------| +| Size | 147 MB | Skopeo | +| Built | 2026-01-28 | Skopeo | +| Architecture | amd64, arm64 | Skopeo | + +**Security Status:** No critical CVEs +- Last checked: 2026-02-03 +- Source: Red Hat Security Data API +``` + +### When Dynamic Data Unavailable + +```markdown +| Property | Value | Source | +|----------|-------|--------| +| Size | ~150 MB (estimate) | Static | +| Built | Unknown | - | +| Architecture | Assumed amd64 | Static | + +**Security Status:** Not verified (warning) +- Skopeo not installed - install for accurate metadata +- Run: `sudo dnf install skopeo` +``` diff --git a/submissions/rhel-deploy/skills/references/human-in-the-loop.md b/submissions/rhel-deploy/skills/references/human-in-the-loop.md new file mode 100644 index 0000000..696fccf --- /dev/null +++ b/submissions/rhel-deploy/skills/references/human-in-the-loop.md @@ -0,0 +1,98 @@ +# Human-in-the-Loop Requirements + +This document defines mandatory checkpoint behavior for all rh-developer skills. + +## Critical Requirements + +**IMPORTANT:** All skills require explicit user confirmation at each step. You MUST: + +1. **Wait for user confirmation** before executing any actions +2. **Do NOT proceed** to the next step until the user explicitly approves +3. **Present options clearly** (yes/no/modify) and wait for response +4. **Never auto-execute** resource creation, builds, or deployments +5. **Never skip configuration questions** even if user seems to know what they want + +If the user says "no" or wants modifications, address their concerns before proceeding. + +## Anti-Patterns to Avoid + +**CRITICAL - DO NOT DO THIS:** + +| Anti-Pattern | Why It's Wrong | +|--------------|----------------| +| User says "yes do X to namespace Y" → Skip config questions | Strategy ≠ Configuration. User chose WHAT, not HOW | +| User seems experienced → Assume they've considered all options | Even experts benefit from checklists | +| User provides multiple answers at once → Skip individual confirmations | Each checkpoint exists for a reason | +| User is in a hurry → Rush through phases | Speed causes mistakes in production | + +## When User Provides Multiple Answers + +If user says: "yes do helm deployment to test-app namespace" + +**DO NOT** skip phases. Instead: + +1. Acknowledge: "Great, you've chosen Helm strategy and test-app namespace." +2. Continue: "Let me confirm the configuration details..." +3. Still ask: Environment type, config approach, resources, etc. +4. Get explicit confirmation for each phase + +**The user specifying WHAT to deploy does not mean they've decided HOW to configure it.** + +## Standard Checkpoint Language + +Use this exact pattern after EVERY step/phase: + +```markdown +**WAIT for user confirmation before proceeding.** Do NOT continue to the next phase until user explicitly confirms. + +- If user says "yes" → Proceed to next phase +- If user says "no" → Ask what they would like to change +- If user says "modify" → Update configuration and show again for confirmation +- If user gives multiple answers at once → Still confirm each remaining checkpoint individually +``` + +## Mandatory Configuration Questions + +Before ANY resource creation, these questions should be asked: + +| Question | Why It Matters | +|----------|----------------| +| Environment type (dev/staging/prod) | Affects image tags, resources, replicas | +| Runtime vs build-time config | Affects flexibility and rebuild frequency | +| Resource limits | Prevents OOM, ensures fair scheduling | +| Replicas | Affects availability and cost | + +## Include in Your Skill + +Add this section after Prerequisites in your SKILL.md: + +```markdown +## Critical: Human-in-the-Loop Requirements + +See [Human-in-the-Loop Requirements](../docs/human-in-the-loop.md) for mandatory checkpoint behavior. + +**Key Rules:** +1. WAIT for explicit user confirmation at each phase +2. Never skip configuration questions, even if user specifies strategy upfront +3. Strategy choice ≠ Configuration approval +``` + +## Phase Execution Rules + +**MANDATORY:** Execute phases in order. Each phase MUST: + +1. Display the phase information to the user +2. Ask the specific question for that phase +3. Wait for user response +4. Only then proceed to next phase + +**Even if user provides information for multiple phases at once:** +- Acknowledge what they said +- But still display each phase's confirmation prompt +- Get explicit "yes" for each phase before executing + +Example: +- User: "yes do helm to test-app namespace" +- AI: "Great, you've chosen Helm strategy and test-app namespace. Let me confirm the configuration details..." +- [Still show Configuration Review phase] +- [Still ask environment type, config approach, etc.] diff --git a/submissions/rhel-deploy/skills/references/image-selection-criteria.md b/submissions/rhel-deploy/skills/references/image-selection-criteria.md new file mode 100644 index 0000000..184b7f5 --- /dev/null +++ b/submissions/rhel-deploy/skills/references/image-selection-criteria.md @@ -0,0 +1,221 @@ +--- +title: Image Selection Criteria Reference +category: containers +sources: + - title: Red Hat Container Best Practices + url: https://developers.redhat.com/articles/2023/02/14/best-practices-building-images-pass-red-hat-container-certification + sections: Image sizing, Security considerations + date_accessed: 2026-02-08 + - title: OpenShift Image Guidelines + url: https://docs.openshift.com/container-platform/latest/openshift_images/create-images.html + sections: Image creation, Optimization + date_accessed: 2026-02-08 +--- + +# Image Selection Criteria Reference + +This document provides detailed criteria for selecting the optimal container image based on use case requirements. + +## Scoring Matrix + +Use this matrix to score image options based on user requirements. + +### Criteria Weights by Environment + +| Criteria | Production | Development | Edge/IoT | Serverless | +|----------|------------|-------------|----------|------------| +| Image Size | 3 | 1 | 5 | 4 | +| Security Posture | 5 | 2 | 4 | 3 | +| Build Tools | 1 | 5 | 1 | 1 | +| Startup Time | 3 | 1 | 3 | 5 | +| LTS Status | 5 | 2 | 4 | 3 | +| Debug Tools | 1 | 5 | 1 | 1 | + +**Scale:** 1 (low importance) to 5 (high importance) + +### Image Variant Scores + +| Variant | Size | Security | Build Tools | Startup | Debug | +|---------|------|----------|-------------|---------|-------| +| Full | 2 | 2 | 5 | 2 | 5 | +| Minimal | 4 | 4 | 2 | 4 | 2 | +| Runtime | 5 | 5 | 1 | 5 | 1 | + +**Scale:** 1 (poor) to 5 (excellent) + +## Image Size Reference + +Approximate compressed image sizes: + +### Node.js +| Image | Size | +|-------|------| +| `ubi9/nodejs-20` | ~250MB | +| `ubi9/nodejs-20-minimal` | ~150MB | + +### Python +| Image | Size | +|-------|------| +| `ubi9/python-311` | ~280MB | + +### Java +| Image | Size | +|-------|------| +| `ubi9/openjdk-17` | ~400MB | +| `ubi9/openjdk-17-runtime` | ~200MB | + +### Go +| Image | Size | +|-------|------| +| `ubi9/go-toolset:1.21` | ~500MB | +| Final binary | ~10-50MB | + +### .NET +| Image | Size | +|-------|------| +| `ubi9/dotnet-80` | ~350MB | +| `ubi9/dotnet-80-runtime` | ~150MB | + +## LTS Support Timeline + +### Node.js +| Version | Status | End of Life | +|---------|--------|-------------| +| 18 LTS | Active | April 2025 | +| 20 LTS | Active | April 2026 | +| 22 LTS | Active | April 2027 | + +### Python +| Version | Status | End of Life | +|---------|--------|-------------| +| 3.9 | Security | October 2025 | +| 3.11 | Active | October 2027 | +| 3.12 | Active | October 2028 | + +### Java (OpenJDK) +| Version | Status | Extended Support | +|---------|--------|------------------| +| 11 LTS | Active | Red Hat until 2027 | +| 17 LTS | Active | Red Hat until 2029 | +| 21 LTS | Active | Red Hat until 2031 | + +### .NET +| Version | Status | End of Life | +|---------|--------|-------------| +| 6.0 LTS | Active | November 2024 | +| 8.0 LTS | Active | November 2026 | + +## Security Considerations + +### Minimal Images - When to Use +- Fewer installed packages = smaller attack surface +- Recommended for production workloads +- May lack debugging tools when issues occur + +### Full Images - When to Use +- Include development tools (gcc, make, etc.) +- Needed for native extensions (Python C extensions, Node native modules) +- Better for development and debugging + +### Runtime Images - When to Use +- No build tools at all +- Smallest possible footprint +- Requires pre-compiled application (JAR, static binary) + +## Framework-Specific Considerations + +### Quarkus (Java) +**For JVM mode:** +- Use `ubi9/openjdk-21` for build +- Use `ubi9/openjdk-21-runtime` for production + +**For Native mode:** +- Build: `quay.io/quarkus/ubi-quarkus-mandrel-builder-image:jdk-21` +- Run: `quay.io/quarkus/quarkus-micro-image:2.0` +- Dramatically faster startup (~50ms vs ~2s) + +### Spring Boot (Java) +**Standard:** +- Build and run: `ubi9/openjdk-17` + +**Optimized production:** +- Build with layered JAR: `spring-boot-maven-plugin` with layers +- Run on: `ubi9/openjdk-17-runtime` + +### Next.js (Node.js) +**Development:** +- Use `ubi9/nodejs-20` + +**Production (multi-stage recommended):** +1. Build stage: `ubi9/nodejs-20` +2. Run stage: `ubi9/nodejs-20-minimal` with `.next` output + +### Django/Flask (Python) +- Always use full image (may need compilation for dependencies) +- `ubi9/python-311` recommended +- Consider `gunicorn` for production + +## Decision Tree + +``` +START + | + v +Is this production? + | + +-- YES --> Need native compilation? + | | + | +-- YES --> Use FULL variant + | | + | +-- NO --> Is app pre-compiled? + | | + | +-- YES --> Use RUNTIME variant + | | + | +-- NO --> Use MINIMAL variant + | + +-- NO (Development) --> Use FULL variant +``` + +## Multi-Stage Build Recommendations + +For optimal production images, consider multi-stage builds: + +### Node.js Example +```dockerfile +# Build stage +FROM registry.access.redhat.com/ubi9/nodejs-20 AS builder +COPY . . +RUN npm ci && npm run build + +# Production stage +FROM registry.access.redhat.com/ubi9/nodejs-20-minimal +COPY --from=builder /app/dist /app +CMD ["node", "/app/index.js"] +``` + +### Java Example +```dockerfile +# Build stage +FROM registry.access.redhat.com/ubi9/openjdk-21 AS builder +COPY . . +RUN mvn package -DskipTests + +# Production stage +FROM registry.access.redhat.com/ubi9/openjdk-21-runtime +COPY --from=builder /app/target/*.jar /app/app.jar +CMD ["java", "-jar", "/app/app.jar"] +``` + +### Go Example +Go produces static binaries, so minimal base is ideal: +```dockerfile +# Build stage +FROM registry.access.redhat.com/ubi9/go-toolset:1.21 AS builder +COPY . . +RUN go build -o /app/server + +# Production stage +FROM registry.access.redhat.com/ubi9/ubi-micro +COPY --from=builder /app/server /server +CMD ["/server"] +``` diff --git a/submissions/rhel-deploy/skills/references/prerequisites.md b/submissions/rhel-deploy/skills/references/prerequisites.md new file mode 100644 index 0000000..d81a9b5 --- /dev/null +++ b/submissions/rhel-deploy/skills/references/prerequisites.md @@ -0,0 +1,212 @@ +--- +title: Prerequisites +category: setup +sources: + - title: OpenShift CLI (oc) Installation + url: https://docs.openshift.com/container-platform/latest/cli_reference/openshift_cli/getting-started-cli.html + sections: Installing the CLI, Logging in + date_accessed: 2026-02-08 + - title: Helm Installation Guide + url: https://helm.sh/docs/intro/install/ + sections: From script, From package managers + date_accessed: 2026-02-08 + - title: Podman Installation + url: https://podman.io/docs/installation + sections: Linux, macOS, Windows + date_accessed: 2026-02-08 + - title: Skopeo Installation + url: https://github.com/containers/skopeo/blob/main/install.md + sections: Distribution packages, Building from source + date_accessed: 2026-02-08 +--- + +# Prerequisites + +This document lists all tools required by the rh-developer agentic collection. + +## Required Tools by Skill + +| Skill | Required Tools | Optional Tools | +|-------|----------------|----------------| +| `/detect-project` | `git` | - | +| `/s2i-build` | `oc` | `git` | +| `/deploy` | `oc` | - | +| `/helm-deploy` | `oc`, `helm` | - | +| `/containerize-deploy` | `oc` | `git`, `helm` | +| `/rhel-deploy` | `ssh`, `podman` or `docker` | `git`, `dnf` | +| `/recommend-image` | - | `skopeo`, `curl`, `jq` | +| `/debug-pod` | `oc` | - | +| `/debug-build` | `oc` | - | +| `/debug-network` | `oc` | - | +| `/debug-rhel` | `ssh` | `ausearch`, `journalctl` | +| `/debug-container` | `podman` or `docker` | - | + +## Tool Reference + +### OpenShift CLI (oc) + +**Required for:** Cluster operations, S2I builds, deployments + +```bash +# Check installation +oc version + +# Installation +# Download from: https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/ +# Or via package manager: +sudo dnf install openshift-clients # Fedora/RHEL +brew install openshift-cli # macOS +``` + +### Helm + +**Required for:** Helm chart deployments + +```bash +# Check installation +helm version + +# Installation +curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash +# Or via package manager: +sudo dnf install helm # Fedora/RHEL +brew install helm # macOS +``` + +### Podman + +**Required for:** Container builds, RHEL container deployments + +```bash +# Check installation +podman --version + +# Installation +sudo dnf install podman # Fedora/RHEL/CentOS +sudo apt install podman # Ubuntu/Debian +brew install podman # macOS +``` + +### Docker (alternative to Podman) + +**Required for:** Container builds (if Podman not available) + +```bash +# Check installation +docker --version + +# Installation +# See: https://docs.docker.com/engine/install/ +``` + +### Skopeo + +**Required for:** Image inspection, tag verification + +```bash +# Check installation +skopeo --version + +# Installation +sudo dnf install skopeo # Fedora/RHEL/CentOS +sudo apt install skopeo # Ubuntu/Debian +brew install skopeo # macOS +``` + +### Git + +**Required for:** Repository cloning + +```bash +# Check installation +git --version + +# Installation +sudo dnf install git # Fedora/RHEL/CentOS +sudo apt install git # Ubuntu/Debian +brew install git # macOS (or Xcode Command Line Tools) +``` + +### SSH + +**Required for:** RHEL remote deployments + +```bash +# Check installation +ssh -V + +# Usually pre-installed on Linux/macOS +# Windows: Use OpenSSH or WSL +``` + +### curl and jq + +**Required for:** API calls and JSON parsing + +```bash +# Check installation +curl --version +jq --version + +# Installation +sudo dnf install curl jq # Fedora/RHEL/CentOS +sudo apt install curl jq # Ubuntu/Debian +brew install curl jq # macOS +``` + +## Cluster Requirements + +### OpenShift Cluster Access + +For S2I builds and deployments, you need: + +1. **Logged in to cluster:** + ```bash + oc login + # or + oc login --token= --server= + ``` + +2. **Namespace with edit permissions:** + ```bash + # Verify access + oc auth can-i create deployments + oc auth can-i create buildconfigs + ``` + +3. **Image registry accessible:** + ```bash + # Verify internal registry + oc get route -n openshift-image-registry + ``` + +### RHEL/Fedora Host Access + +For RHEL deployments, you need: + +1. **SSH access to target host:** + ```bash + ssh user@target-host + ``` + +2. **sudo privileges on target** (for systemd services) + +3. **Firewall ports open** (for application access) + +## Quick Validation + +Run these commands to check your environment: + +```bash +# Core tools +which oc helm podman git ssh curl jq skopeo + +# Cluster connection (if using OpenShift) +oc whoami +oc project + +# Container runtime +podman info || docker info +``` + +Use the `/validate-environment` skill for automated checking. diff --git a/submissions/rhel-deploy/skills/references/python-s2i-entrypoints.md b/submissions/rhel-deploy/skills/references/python-s2i-entrypoints.md new file mode 100644 index 0000000..bb29398 --- /dev/null +++ b/submissions/rhel-deploy/skills/references/python-s2i-entrypoints.md @@ -0,0 +1,70 @@ +--- +title: Python S2I Entry Point Requirements +category: containers +sources: + - title: UBI Python S2I Builder + url: https://github.com/sclorg/s2i-python-container + sections: Run script logic, APP_MODULE configuration + date_accessed: 2026-02-08 + - title: Red Hat Python S2I Documentation + url: https://catalog.redhat.com/software/containers/ubi9/python-311 + sections: Environment variables, Startup behavior + date_accessed: 2026-02-08 +--- + +# Python S2I Entry Point Requirements + +The UBI Python S2I builder has specific startup logic that must be understood to avoid deployment failures. + +## How the S2I Python Run Script Works + +The S2I Python builder uses this startup logic (in order): + +1. If `app.sh` exists → Execute it directly +2. If `gunicorn` is installed AND `APP_MODULE` is set → Start with gunicorn +3. If `app.py` exists → Run with Python directly +4. Otherwise → **ERROR: No start command found** + +## Entry Point Configuration Matrix + +| Entry Point File | gunicorn in requirements | Configuration Needed | Result | +|------------------|--------------------------|----------------------|--------| +| `app.py` | No | None | Works (Python direct) | +| `app.py` | Yes | None (optional APP_MODULE) | Works | +| `main.py` | **No** | - | **FAILS** | +| `main.py` | Yes | `APP_MODULE=main:app` | Works | +| `wsgi.py` | Yes | `APP_MODULE=wsgi` or `APP_MODULE=wsgi:application` | Works | +| Custom file | Yes | `APP_MODULE=[module]:[variable]` | Works | + +## APP_MODULE Format + +- **Format:** `[python_module]:[flask_app_variable]` +- **Example:** `main:app` → imports `app` from `main.py` +- **Requires:** `gunicorn` in `requirements.txt` + +### Common Patterns + +| File | Typical APP_MODULE | +|------|-------------------| +| `main.py` with `app = Flask(__name__)` | `main:app` | +| `main.py` with `application = Flask(__name__)` | `main:application` | +| `wsgi.py` with `application` | `wsgi:application` or just `wsgi` | +| `src/app.py` with `app` | `src.app:app` | + +## Alternative: APP_FILE + +- Set `APP_FILE=main.py` to run with Python directly (development mode) +- **Not recommended for production** (no WSGI server, no worker management) +- Use only if gunicorn is not an option + +## Critical Warning + +**If the entry point is NOT `app.py` and `gunicorn` is NOT installed:** +- The S2I build will succeed (dependencies install) +- The container will **fail to start** with "No start command found" +- This is a **runtime failure**, not a build failure + +**Always verify:** +1. Entry point file name +2. `gunicorn` in requirements.txt +3. `APP_MODULE` environment variable in BuildConfig diff --git a/submissions/rhel-deploy/skills/references/rhel-deployment.md b/submissions/rhel-deploy/skills/references/rhel-deployment.md new file mode 100644 index 0000000..06eda27 --- /dev/null +++ b/submissions/rhel-deploy/skills/references/rhel-deployment.md @@ -0,0 +1,580 @@ +--- +title: RHEL Deployment Reference +category: deployment +sources: + - title: RHEL System Administrator's Guide - systemd + url: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_basic_system_settings/managing-system-services-with-systemctl_configuring-basic-system-settings + sections: Managing services, Unit files + date_accessed: 2026-02-08 + - title: RHEL SELinux Guide + url: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/using_selinux + sections: Contexts, Port labeling + date_accessed: 2026-02-08 + - title: RHEL Firewall Configuration + url: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_firewalls_and_packet_filters + sections: firewalld, Opening ports + date_accessed: 2026-02-08 +--- + +# RHEL Deployment Reference + +Reference material for deploying applications to standalone RHEL systems. + +## Table of Contents + +1. [RHEL Version Compatibility](#rhel-version-compatibility) +2. [Systemd Unit Templates](#systemd-unit-templates) +3. [SELinux Configuration](#selinux-configuration) +4. [Firewall Commands](#firewall-commands) +5. [SSH Connection Patterns](#ssh-connection-patterns) +6. [Runtime Package Mapping](#runtime-package-mapping) + +--- + +## RHEL Version Compatibility + +| Distribution | Version | Podman | Recommended | +|--------------|---------|--------|-------------| +| RHEL | 8.x | 4.0+ | Production ready | +| RHEL | 9.x | 4.4+ | **Recommended** | +| CentOS Stream | 8 | 4.0+ | Development | +| CentOS Stream | 9 | 4.4+ | Development | +| Rocky Linux | 8.x | 4.0+ | Production ready | +| Rocky Linux | 9.x | 4.4+ | Production ready | +| AlmaLinux | 8.x | 4.0+ | Production ready | +| AlmaLinux | 9.x | 4.4+ | Production ready | +| Fedora | 38+ | 4.6+ | Latest features | + +### Version Detection Commands + +```bash +# Get RHEL/CentOS version +cat /etc/redhat-release + +# Get detailed OS info +cat /etc/os-release + +# Check architecture +uname -m + +# Check kernel version +uname -r +``` + +--- + +## Systemd Unit Templates + +### Podman Container Service (Rootful) + +```ini +[Unit] +Description=${APP_NAME} Container +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +Restart=always +RestartSec=5 +TimeoutStartSec=300 +TimeoutStopSec=70 + +# Pre-start: ensure clean state +ExecStartPre=-/usr/bin/podman stop -t 10 ${APP_NAME} +ExecStartPre=-/usr/bin/podman rm ${APP_NAME} + +# Main container run +ExecStart=/usr/bin/podman run \ + --name ${APP_NAME} \ + -p ${HOST_PORT}:${CONTAINER_PORT} \ + --rm \ + ${IMAGE} + +# Stop container gracefully +ExecStop=/usr/bin/podman stop -t 10 ${APP_NAME} + +[Install] +WantedBy=multi-user.target +``` + +### Podman Container Service (Rootless) + +```ini +[Unit] +Description=${APP_NAME} Container (Rootless) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +Restart=always +RestartSec=5 +TimeoutStartSec=300 +TimeoutStopSec=70 + +ExecStartPre=-/usr/bin/podman stop -t 10 ${APP_NAME} +ExecStartPre=-/usr/bin/podman rm ${APP_NAME} +ExecStart=/usr/bin/podman run \ + --name ${APP_NAME} \ + -p ${HOST_PORT}:${CONTAINER_PORT} \ + --rm \ + ${IMAGE} +ExecStop=/usr/bin/podman stop -t 10 ${APP_NAME} + +[Install] +WantedBy=default.target +``` + +**Rootless setup commands:** +```bash +# Create user systemd directory +mkdir -p ~/.config/systemd/user + +# Place unit file +cp ${APP_NAME}.service ~/.config/systemd/user/ + +# Reload and enable +systemctl --user daemon-reload +systemctl --user enable --now ${APP_NAME} + +# Keep services running after logout +loginctl enable-linger ${USER} +``` + +### Podman Container with Volumes + +```ini +[Unit] +Description=${APP_NAME} Container with Persistent Data +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +Restart=always +RestartSec=5 + +ExecStartPre=-/usr/bin/podman stop -t 10 ${APP_NAME} +ExecStartPre=-/usr/bin/podman rm ${APP_NAME} +ExecStart=/usr/bin/podman run \ + --name ${APP_NAME} \ + -p ${HOST_PORT}:${CONTAINER_PORT} \ + -v /var/lib/${APP_NAME}/data:/app/data:z \ + -e DATABASE_URL=${DATABASE_URL} \ + --rm \ + ${IMAGE} +ExecStop=/usr/bin/podman stop -t 10 ${APP_NAME} + +[Install] +WantedBy=multi-user.target +``` + +### Native Node.js Application + +```ini +[Unit] +Description=${APP_NAME} Node.js Service +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=${SERVICE_USER} +WorkingDirectory=/opt/${APP_NAME} +Environment=NODE_ENV=production +Environment=PORT=${PORT} +ExecStart=/usr/bin/node /opt/${APP_NAME}/server.js +Restart=always +RestartSec=5 + +# Security hardening +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true +ReadWritePaths=/opt/${APP_NAME} + +[Install] +WantedBy=multi-user.target +``` + +### Native Python Application + +```ini +[Unit] +Description=${APP_NAME} Python Service +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=${SERVICE_USER} +WorkingDirectory=/opt/${APP_NAME} +Environment=PYTHONUNBUFFERED=1 +Environment=PORT=${PORT} +ExecStart=/usr/bin/python3 /opt/${APP_NAME}/app.py +Restart=always +RestartSec=5 + +# Security hardening +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true +ReadWritePaths=/opt/${APP_NAME} + +[Install] +WantedBy=multi-user.target +``` + +### Native Java Application + +```ini +[Unit] +Description=${APP_NAME} Java Service +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=${SERVICE_USER} +WorkingDirectory=/opt/${APP_NAME} +Environment=JAVA_OPTS=-Xmx512m +ExecStart=/usr/bin/java -jar /opt/${APP_NAME}/app.jar --server.port=${PORT} +Restart=always +RestartSec=5 +SuccessExitStatus=143 + +# Security hardening +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true +ReadWritePaths=/opt/${APP_NAME} + +[Install] +WantedBy=multi-user.target +``` + +### Native Go Application + +```ini +[Unit] +Description=${APP_NAME} Go Service +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=${SERVICE_USER} +WorkingDirectory=/opt/${APP_NAME} +Environment=PORT=${PORT} +ExecStart=/opt/${APP_NAME}/${BINARY_NAME} +Restart=always +RestartSec=5 + +# Security hardening +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true + +[Install] +WantedBy=multi-user.target +``` + +--- + +## SELinux Configuration + +### Common SELinux Contexts + +| Context Type | Use Case | +|--------------|----------| +| `container_t` | Standard Podman container processes | +| `container_file_t` | Container data files | +| `bin_t` | Executable binaries | +| `httpd_sys_content_t` | Web application content (read-only) | +| `httpd_sys_rw_content_t` | Web application content (read-write) | +| `var_lib_t` | Application data in /var/lib | + +### Volume Label Options for Podman + +| Option | Description | Use Case | +|--------|-------------|----------| +| `:z` | Shared volume label | Volume accessed by multiple containers | +| `:Z` | Private volume label | Volume accessed by single container only | + +Example: +```bash +podman run -v /data/shared:/app/shared:z myimage # Shared +podman run -v /data/private:/app/data:Z myimage # Private +``` + +### SELinux Commands + +```bash +# Check current SELinux mode +getenforce + +# View file context +ls -Z /path/to/file + +# Set context for application directory +sudo semanage fcontext -a -t bin_t "/opt/myapp(/.*)?" +sudo restorecon -Rv /opt/myapp + +# Set context for web content +sudo semanage fcontext -a -t httpd_sys_content_t "/opt/myapp/public(/.*)?" +sudo restorecon -Rv /opt/myapp/public + +# Allow non-standard port for HTTP +sudo semanage port -a -t http_port_t -p tcp 8080 + +# View port contexts +sudo semanage port -l | grep http + +# Check for SELinux denials +sudo ausearch -m AVC -ts recent + +# Generate policy from denials (troubleshooting) +sudo ausearch -m AVC -ts recent | audit2allow -M mypolicy +sudo semodule -i mypolicy.pp + +# Temporarily set permissive (for debugging only) +sudo setenforce 0 +``` + +### Common SELinux Booleans + +```bash +# Allow HTTP to connect to network (for proxy/API calls) +sudo setsebool -P httpd_can_network_connect 1 + +# Allow HTTP to connect to databases +sudo setsebool -P httpd_can_network_connect_db 1 + +# List all HTTP-related booleans +getsebool -a | grep httpd +``` + +--- + +## Firewall Commands + +### Basic Port Management + +```bash +# Check firewall status +sudo firewall-cmd --state + +# List all open ports +sudo firewall-cmd --list-ports + +# List all services +sudo firewall-cmd --list-services + +# Open port permanently +sudo firewall-cmd --permanent --add-port=8080/tcp + +# Open port temporarily (until reload) +sudo firewall-cmd --add-port=8080/tcp + +# Reload firewall to apply permanent changes +sudo firewall-cmd --reload + +# Remove port +sudo firewall-cmd --permanent --remove-port=8080/tcp +sudo firewall-cmd --reload +``` + +### Service-Based Management + +```bash +# Add HTTP service +sudo firewall-cmd --permanent --add-service=http + +# Add HTTPS service +sudo firewall-cmd --permanent --add-service=https + +# Remove service +sudo firewall-cmd --permanent --remove-service=http + +# Apply changes +sudo firewall-cmd --reload +``` + +### Zone Management + +```bash +# List zones +sudo firewall-cmd --get-zones + +# Get active zone +sudo firewall-cmd --get-active-zones + +# Add port to specific zone +sudo firewall-cmd --zone=public --permanent --add-port=8080/tcp + +# Set default zone +sudo firewall-cmd --set-default-zone=public +``` + +### Rich Rules (Advanced) + +```bash +# Allow specific IP to access port +sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="8080" accept' + +# Rate limiting +sudo firewall-cmd --permanent --add-rich-rule='rule service name="http" limit value="10/m" accept' + +# Apply changes +sudo firewall-cmd --reload +``` + +--- + +## SSH Connection Patterns + +### Test Connection + +```bash +# Basic connection test +ssh -o BatchMode=yes -o ConnectTimeout=10 user@host "echo 'OK'" + +# Verbose output for debugging +ssh -v user@host + +# Test with specific key +ssh -i ~/.ssh/mykey user@host "echo 'OK'" +``` + +### Execute Remote Commands + +```bash +# Single command +ssh user@host "command" + +# Multiple commands +ssh user@host "cmd1 && cmd2 && cmd3" + +# With sudo +ssh user@host "sudo command" + +# Preserve environment +ssh user@host 'bash -l -c "command"' +``` + +### File Transfer + +```bash +# Copy file to remote +scp local_file user@host:/remote/path/ + +# Copy directory recursively +scp -r local_dir user@host:/remote/path/ + +# Using rsync (preferred for large transfers) +rsync -avz --progress local_dir/ user@host:/remote/path/ + +# Exclude patterns +rsync -avz --exclude 'node_modules' --exclude '.git' ./ user@host:/remote/path/ +``` + +### SSH Config for Convenience + +``` +# ~/.ssh/config +Host myrhel + HostName 192.168.1.100 + User deploy + Port 22 + IdentityFile ~/.ssh/id_rsa + StrictHostKeyChecking accept-new +``` + +Usage: `ssh myrhel "command"` + +--- + +## Runtime Package Mapping + +### Node.js + +| Version | RHEL 8 | RHEL 9 | +|---------|--------|--------| +| 18 | `dnf module enable nodejs:18 && dnf install -y nodejs npm` | `dnf install -y nodejs npm` | +| 20 | `dnf module enable nodejs:20 && dnf install -y nodejs npm` | `dnf module enable nodejs:20 && dnf install -y nodejs npm` | + +### Python + +| Version | RHEL 8 | RHEL 9 | +|---------|--------|--------| +| 3.8 | `dnf install -y python38 python38-pip` | N/A | +| 3.9 | `dnf install -y python39 python39-pip` | `dnf install -y python3 python3-pip` | +| 3.11 | N/A | `dnf install -y python3.11 python3.11-pip` | +| 3.12 | N/A | `dnf install -y python3.12 python3.12-pip` | + +### Java + +| Version | RHEL 8 | RHEL 9 | +|---------|--------|--------| +| 11 | `dnf install -y java-11-openjdk java-11-openjdk-devel` | `dnf install -y java-11-openjdk java-11-openjdk-devel` | +| 17 | `dnf install -y java-17-openjdk java-17-openjdk-devel` | `dnf install -y java-17-openjdk java-17-openjdk-devel` | +| 21 | N/A | `dnf install -y java-21-openjdk java-21-openjdk-devel` | + +### Go + +| Version | RHEL 8 | RHEL 9 | +|---------|--------|--------| +| 1.20+ | `dnf install -y go-toolset` | `dnf install -y golang` | + +### Ruby + +| Version | RHEL 8 | RHEL 9 | +|---------|--------|--------| +| 3.0 | `dnf module enable ruby:3.0 && dnf install -y ruby ruby-devel` | `dnf install -y ruby ruby-devel` | +| 3.1 | `dnf module enable ruby:3.1 && dnf install -y ruby ruby-devel` | `dnf module enable ruby:3.1 && dnf install -y ruby ruby-devel` | + +### PHP + +| Version | RHEL 8 | RHEL 9 | +|---------|--------|--------| +| 7.4 | `dnf module enable php:7.4 && dnf install -y php php-cli php-fpm` | N/A | +| 8.0 | `dnf module enable php:8.0 && dnf install -y php php-cli php-fpm` | `dnf install -y php php-cli php-fpm` | +| 8.1 | N/A | `dnf module enable php:8.1 && dnf install -y php php-cli php-fpm` | + +### Module Stream Commands + +```bash +# List available streams for a module +dnf module list nodejs + +# Enable specific stream +sudo dnf module enable nodejs:20 + +# Reset module (to switch streams) +sudo dnf module reset nodejs + +# Install from enabled stream +sudo dnf install -y nodejs npm +``` + +--- + +## Service User Creation + +For running applications as non-root: + +```bash +# Create system user for the application +sudo useradd -r -s /sbin/nologin -d /opt/myapp myapp + +# Set ownership +sudo chown -R myapp:myapp /opt/myapp + +# Allow user to bind to privileged port (if needed) +sudo setcap 'cap_net_bind_service=+ep' /opt/myapp/binary +``` diff --git a/submissions/rhel-deploy/skills/references/selinux-troubleshooting.md b/submissions/rhel-deploy/skills/references/selinux-troubleshooting.md new file mode 100644 index 0000000..9942375 --- /dev/null +++ b/submissions/rhel-deploy/skills/references/selinux-troubleshooting.md @@ -0,0 +1,387 @@ +--- +title: SELinux Troubleshooting +category: references +sources: + - title: Red Hat SELinux User's and Administrator's Guide + url: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/using_selinux/index + sections: Troubleshooting, Managing confined services + date_accessed: 2026-02-16 + - title: SELinux Project Wiki + url: https://selinuxproject.org/page/Main_Page + sections: Troubleshooting + date_accessed: 2026-02-16 + - title: Fedora SELinux Guide + url: https://docs.fedoraproject.org/en-US/quick-docs/selinux-getting-started/ + sections: Troubleshooting + date_accessed: 2026-02-16 +--- + +# SELinux Troubleshooting + +This document provides guidance for diagnosing and resolving SELinux access denials on RHEL/Fedora/CentOS systems. + +## Understanding SELinux + +### SELinux Modes + +| Mode | Description | Use Case | +|------|-------------|----------| +| **Enforcing** | SELinux policy is enforced, denials are blocked and logged | Production | +| **Permissive** | SELinux policy is not enforced, denials are logged only | Debugging | +| **Disabled** | SELinux is completely disabled | Not recommended | + +```bash +# Check current mode +getenforce + +# Temporarily switch to permissive (until reboot) +sudo setenforce 0 + +# Switch back to enforcing +sudo setenforce 1 +``` + +### SELinux Contexts + +Every file, process, and port has an SELinux context: + +``` +user:role:type:level +``` + +Example: `system_u:object_r:httpd_sys_content_t:s0` + +- **user**: SELinux user (system_u, user_u, etc.) +- **role**: Role (object_r for files) +- **type**: Type label (most important for troubleshooting) +- **level**: MLS/MCS level (usually s0) + +```bash +# View file context +ls -lZ /path/to/file + +# View process context +ps auxZ | grep [process] + +# View port context +semanage port -l | grep [port] +``` + +## Finding SELinux Denials + +### Using ausearch + +```bash +# Recent denials (last 10 minutes) +sudo ausearch -m AVC -ts recent + +# Denials from today +sudo ausearch -m AVC -ts today + +# Denials for specific process +sudo ausearch -m AVC -c [command-name] + +# Denials involving specific file +sudo ausearch -m AVC -f /path/to/file +``` + +### Using journalctl + +```bash +# SELinux messages in journal +sudo journalctl -t setroubleshoot + +# AVC messages +sudo journalctl | grep "avc: denied" +``` + +### Using sealert + +```bash +# Install setroubleshoot (if not installed) +sudo dnf install setroubleshoot-server + +# Analyze all denials +sudo sealert -a /var/log/audit/audit.log + +# Interactive analysis +sudo sealert -b +``` + +## Reading AVC Denials + +Example AVC denial: + +``` +type=AVC msg=audit(1234567890.123:456): avc: denied { bind } for pid=1234 comm="httpd" src=8080 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0 +``` + +**Breakdown:** +| Field | Value | Meaning | +|-------|-------|---------| +| `denied { bind }` | bind | Denied action (bind to socket) | +| `pid=1234` | 1234 | Process ID | +| `comm="httpd"` | httpd | Command name | +| `src=8080` | 8080 | Port number | +| `scontext=...httpd_t...` | httpd_t | Source type (process) | +| `tcontext=...unreserved_port_t...` | unreserved_port_t | Target type (port) | +| `tclass=tcp_socket` | tcp_socket | Object class | + +**Translation:** Process `httpd` (type `httpd_t`) was denied permission to `bind` to port `8080` (type `unreserved_port_t`). + +## Common Denial Types and Fixes + +### Port Binding Denials + +**Symptom:** Application cannot bind to non-standard port + +**Example denial:** +``` +avc: denied { name_bind } for comm="nginx" src=8080 scontext=httpd_t tcontext=unreserved_port_t +``` + +**Fix:** +```bash +# Add port to allowed type +sudo semanage port -a -t http_port_t -p tcp 8080 + +# Verify +sudo semanage port -l | grep 8080 +``` + +**Common port types:** +| Port Type | Typical Ports | Used By | +|-----------|---------------|---------| +| `http_port_t` | 80, 443, 8080 | Web servers | +| `postgresql_port_t` | 5432 | PostgreSQL | +| `mysqld_port_t` | 3306 | MySQL/MariaDB | +| `redis_port_t` | 6379 | Redis | +| `mongod_port_t` | 27017 | MongoDB | + +### File Access Denials + +**Symptom:** Application cannot read/write files + +**Example denial:** +``` +avc: denied { read } for comm="httpd" name="config.yaml" scontext=httpd_t tcontext=user_home_t +``` + +**Fix - Change file context:** +```bash +# Set file context pattern +sudo semanage fcontext -a -t httpd_sys_content_t "/srv/myapp(/.*)?" + +# Apply the context +sudo restorecon -Rv /srv/myapp + +# Verify +ls -lZ /srv/myapp +``` + +**Common file types:** +| File Type | Access | Use Case | +|-----------|--------|----------| +| `httpd_sys_content_t` | Read | Web content | +| `httpd_sys_rw_content_t` | Read/Write | Web app data | +| `container_file_t` | Container access | Podman volumes | +| `var_log_t` | Log files | Application logs | + +### Network Connection Denials + +**Symptom:** Application cannot connect to external services + +**Example denial:** +``` +avc: denied { name_connect } for comm="httpd" dest=5432 scontext=httpd_t tcontext=postgresql_port_t +``` + +**Fix - Enable boolean:** +```bash +# Allow httpd to connect to network +sudo setsebool -P httpd_can_network_connect on + +# Or specifically to databases +sudo setsebool -P httpd_can_network_connect_db on + +# List all httpd booleans +sudo getsebool -a | grep httpd +``` + +**Common booleans:** +| Boolean | Purpose | +|---------|---------| +| `httpd_can_network_connect` | Allow outbound network connections | +| `httpd_can_network_connect_db` | Allow database connections | +| `httpd_can_sendmail` | Allow sending email | +| `httpd_use_nfs` | Allow NFS access | +| `container_manage_cgroup` | Allow container cgroup management | + +## Container-Specific Issues + +### Podman Volume Mounts + +When mounting host directories into containers, SELinux may block access. + +**Solutions:** + +1. **Shared label (:z)** - Multiple containers can access + ```bash + podman run -v /host/path:/container/path:z [image] + ``` + +2. **Private label (:Z)** - Only this container can access + ```bash + podman run -v /host/path:/container/path:Z [image] + ``` + +3. **Manual relabeling:** + ```bash + sudo semanage fcontext -a -t container_file_t "/data(/.*)?" + sudo restorecon -Rv /data + ``` + +### Container Booleans + +```bash +# Enable container to manage cgroups (for systemd in container) +sudo setsebool -P container_manage_cgroup on + +# Allow containers to connect to any port +sudo setsebool -P container_connect_any on + +# List all container booleans +sudo getsebool -a | grep container +``` + +## Troubleshooting Workflow + +### Step 1: Confirm SELinux is the Issue + +```bash +# Temporarily disable SELinux +sudo setenforce 0 + +# Test if application works +[test application] + +# Re-enable SELinux +sudo setenforce 1 +``` + +If application works with SELinux permissive, SELinux is blocking. + +### Step 2: Find the Denial + +```bash +# Get recent denials +sudo ausearch -m AVC -ts recent + +# Or use sealert for analysis +sudo sealert -a /var/log/audit/audit.log +``` + +### Step 3: Determine Fix Type + +| Denial Type | Fix Approach | +|-------------|--------------| +| Port binding | `semanage port` | +| File access | `semanage fcontext` + `restorecon` | +| Network connection | `setsebool` | +| Process capability | Custom policy or boolean | + +### Step 4: Apply Fix + +```bash +# For port: +sudo semanage port -a -t [type] -p [tcp/udp] [port] + +# For file: +sudo semanage fcontext -a -t [type] "[path](/.*)?" +sudo restorecon -Rv [path] + +# For boolean: +sudo setsebool -P [boolean] on +``` + +### Step 5: Verify + +```bash +# Test application +[restart and test] + +# Check for new denials +sudo ausearch -m AVC -ts recent +``` + +## Generating Custom Policies + +If no existing type or boolean works, generate a custom policy: + +```bash +# Generate policy from recent denials +sudo ausearch -m AVC -ts recent | audit2allow -M mypolicy + +# Review the policy +cat mypolicy.te + +# Install the policy +sudo semodule -i mypolicy.pp +``` + +**Warning:** Custom policies should be reviewed carefully. They grant permanent permissions. + +## Quick Reference + +### Common Commands + +```bash +# SELinux status +getenforce +sestatus + +# File context +ls -lZ [path] +restorecon -Rv [path] + +# Process context +ps auxZ | grep [process] + +# Port context +semanage port -l | grep [port] +semanage port -a -t [type] -p tcp [port] + +# Booleans +getsebool -a | grep [keyword] +setsebool -P [boolean] on + +# File context rules +semanage fcontext -l | grep [path] +semanage fcontext -a -t [type] "[path](/.*)?" + +# Audit logs +ausearch -m AVC -ts recent +sealert -a /var/log/audit/audit.log +``` + +### Common Types for Web Applications + +| Resource | Type | +|----------|------| +| Web content (read-only) | `httpd_sys_content_t` | +| Web content (read-write) | `httpd_sys_rw_content_t` | +| Web scripts | `httpd_sys_script_exec_t` | +| Application logs | `httpd_log_t` | +| HTTP ports | `http_port_t` | +| Container files | `container_file_t` | + +### Common Booleans for Applications + +| Application | Boolean | Purpose | +|-------------|---------|---------| +| Web server | `httpd_can_network_connect` | Outbound connections | +| Web server | `httpd_can_network_connect_db` | Database connections | +| Web server | `httpd_unified` | Unified handling | +| Container | `container_manage_cgroup` | cgroup management | +| Container | `container_connect_any` | Connect to any port | +| NFS | `use_nfs_home_dirs` | NFS home directories | From 9b6a1a983c326ed58c4a31cda85df6803068b39f Mon Sep 17 00:00:00 2001 From: gziv Date: Sun, 31 May 2026 14:53:55 +0300 Subject: [PATCH 2/2] retrigger: queue runner parallel