Skip to content

feat(dcm_deploy): add optional rootless Podman deployment support#3

Open
chadcrum wants to merge 4 commits into
dcm-project:mainfrom
chadcrum:flpath-4169-rootless-podman-deploy
Open

feat(dcm_deploy): add optional rootless Podman deployment support#3
chadcrum wants to merge 4 commits into
dcm-project:mainfrom
chadcrum:flpath-4169-rootless-podman-deploy

Conversation

@chadcrum
Copy link
Copy Markdown
Contributor

@chadcrum chadcrum commented May 14, 2026

Summary

  • Add dcm_rootless boolean (default false) for optional rootless Podman deployment — rootful remains the default with zero behavior change
  • A resolve_rootless_vars phase runs first, creating a dedicated user with lingering, subuid/subgid ranges, and setting internal facts that redirect paths, ownership, and systemd scope
  • All 13 quadlet templates use {{ _dcm_wanted_by }} instead of hardcoded multi-user.target
  • Every task file updated with become_user, scope, and environment directives for user-scoped systemd/podman operations
  • Preflight assertions block rootless on hosts with existing rootful deployments (mutually exclusive)
  • New molecule/rootless/ scenario validates template rendering with rootless paths and targets
  • CI bumped to ansible-core>=2.16 (required for systemd_service scope parameter)

Tested on

RHEL 9.6 (sealusa12) with all providers enabled — 11/12 containers running under user-scoped systemd. ACM provider not started (dummy pull secret, not a deployment defect). Full QE validation: systemd units, file ownership, port publishing, container DNS, health checks, namespace isolation, cgroup hierarchy, SELinux contexts, idempotency, and service restart resilience — all pass.

Jira

FLPATH-4169

Test plan

  • molecule test — default (rootful) scenario passes
  • molecule test -s rootless — rootless scenario passes
  • ansible-playbook verify_compose_alignment.yml — compose alignment
  • yamllint -s . + ansible-lint — clean
  • Deploy rootless on RHEL 9 host with dcm_rootless: true
  • Verify all containers run under user-scoped systemd
  • Verify no rootful artifacts in /etc/containers/systemd/

🤖 Generated with Claude Code

@chadcrum chadcrum force-pushed the flpath-4169-rootless-podman-deploy branch from 7d5ccdf to 4b514ef Compare May 14, 2026 19:52
@chadcrum chadcrum force-pushed the flpath-4169-rootless-podman-deploy branch from 4b514ef to f3f837b Compare May 26, 2026 18:02
Ansible role that deploys DCM as Podman quadlet containers managed by
systemd on RHEL 9. Includes optional rootless deployment mode, CI
pipeline with Molecule tests, and compose alignment verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Chad Crum <chadcrum@users.noreply.github.com>
@testetson22
Copy link
Copy Markdown

🤖 AI Code Review

PR Review: #3 — feat(dcm_deploy): add optional rootless Podman deployment support
Repo: dcm-project/quadlet-deploy
Author: chadcrum
Verdict:APPROVE
Files changed: 31 (+584, -21)


Gate Checks

Gate Status
PR Description Quality ✅ Comprehensive summary, tested-on section, Jira link, detailed test plan
CI Status ✅ All 7 checks passing
Single Concern ✅ All changes relate to rootless Podman deployment support
Reasonable Scope ✅ 584 lines is moderate; most additions are systematic become/scope updates
No Secrets in Diff ✅ No credentials found
Draft Status ✅ Not a draft

Findings Summary

Severity Count
Critical 0
High 0
Medium 1
Low 2

Medium Issues

  • roles/dcm_deploy/tasks/resolve_rootless_vars.yml:47-53 — The subordinate UID/GID range 231072:65536 is hardcoded. On systems with existing subuid allocations, this could conflict with other rootless users or services. Fix: Consider making the starting UID configurable via dcm_rootless_subuid_start with a sensible default, or document that administrators should verify no conflicts exist before deployment.

Low Issues

  • roles/dcm_deploy/tasks/resolve_rootless_vars.yml:68-72 — The lingering check uses stat then conditional command, but loginctl enable-linger is idempotent. Could simplify, but current implementation is correct and explicit.

  • PR description test plan — One unchecked item: "`[ ] Verify all containers run under user-scoped systemd"". The "Tested on" section describes this verification was done; appears to be a checklist cosmetic oversight.


Positive Observations

Architecture: Clean separation via internal facts (_dcm_* prefix convention) allows existing templates and tasks to work unchanged. The resolve_rootless_vars phase is elegant.

Security: Proper service user setup with system: true, /sbin/nologin shell, and 0700 home directory permissions. Environment file at 0600.

Error Handling: Preflight assertions catch mixed rootful/rootless deployments early with clear error messages. Proper wait_for on XDG_RUNTIME_DIR.

Testing: New molecule/rootless/ scenario with comprehensive assertions on paths, ownership, and systemd targets. Existing default scenario updated to assert rootful behavior.

Documentation: Excellent updates to README.md and CLAUDE.md explaining the feature, path differences, requirements, and limitations.

Ansible Best Practices: All modules use FQCN, proper become_user/scope/environment directives, appropriate handler conditionals.


Recommendation

Ready to merge. The rootless implementation is well-designed, thoroughly tested, and properly documented. The medium-severity finding about hardcoded subuid ranges is a hardening suggestion rather than a blocker — the chosen range (231072) is unlikely to conflict in practice and follows common conventions.


ℹ️ Auto-merge: Skipped — repo not on auto-merge allowlist.

Copy link
Copy Markdown

@testetson22 testetson22 left a comment

Choose a reason for hiding this comment

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

well, I got the bot to work directly from my local repo using my creds without any effort.

@hardengl
Copy link
Copy Markdown

@testetson22 nice!

@chadcrum
Copy link
Copy Markdown
Contributor Author

Good catch on the subuid range. 231072:65536 is the conventional second allocation slot for rootless podman — collision is unlikely on single-purpose DCM hosts, and any system with custom subuid allocations would need to review these values regardless of whether they're in a variable or hardcoded.

The linger check is intentional — avoids a changed report on every run, which keeps idempotency clean.

I'll fix the test plan checkbox.

Comment thread roles/dcm_deploy/tasks/resolve_rootless_vars.yml
Comment thread roles/dcm_deploy/tasks/resolve_rootless_vars.yml
Comment thread README.md

## Deployment Phases

The `dcm_deploy` role executes in six phases:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think resolve_rootless_vars is missing in the list

Comment thread README.md

The DCM UI's `APP_BASE_URL` defaults to `http://<ansible_host>:<dcm_ui_port>`. If the UI is accessed via a different hostname, domain, or behind a reverse proxy, override `ansible_host` in your inventory or set `APP_BASE_URL` directly in a custom vars file.

### Paths
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is related to my previous comment

Comment thread README.md
Comment on lines 283 to 284
# All systemd units active
systemctl status dcm-*.service
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do you also need to document the --user for rootless

Comment thread molecule/rootless/converge.yml
Comment thread molecule/rootless/molecule.yml
Comment thread molecule/rootless/verify.yml
Comment thread molecule/rootless/verify.yml
Comment thread molecule/rootless/converge.yml
chadcrum and others added 3 commits May 27, 2026 10:02
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Chad Crum <chadcrum@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Chad Crum <chadcrum@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Chad Crum <chadcrum@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants