Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions CLAUDE/ContainerEngines.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ This repo sets up three container technologies. They are not interchangeable —

## The role split

| Engine | Mode | Role | Installed by |
| ---------- | ------------ | ---------------------------------------------------------------- | ----------------------------------------------- |
| **Podman** | **rootless** | Default container engine for everything. Daily use. | `playbooks/imports/play-podman.yml` |
| **Docker** | **rootful** | Compatibility mode for tools that require full Docker semantics. | `playbooks/imports/play-docker.yml` |
| **LXC** | rootful | Full-system, VM-like containers with systemd inside. | `playbooks/imports/play-lxc-install-config.yml` |

All three are installed by `playbook-main.yml`. They coexist cleanly — different sockets, different storage, different networking stacks. See "Coexistence" below.
| Engine | Mode | Role | Installed by |
| ---------- | ------------ | ---------------------------------------------------------------- | -------------------------------------------------------------- |
| **Podman** | **rootless** | Default container engine for everything. Daily use. | `playbooks/imports/play-podman.yml` |
| **Docker** | **rootful** | Compatibility mode for tools that require full Docker semantics. | `playbooks/imports/optional/common/play-docker.yml` (optional) |
| **LXC** | rootful | Full-system, VM-like containers with systemd inside. | `playbooks/imports/play-lxc-install-config.yml` |

Podman and LXC are installed by `playbook-main.yml`. Docker is **optional** — consistent with
this document's own policy, a compatibility-only engine is not a core component: install it
explicitly (interactive optional menu, or `RUN_BASH_OPTIONAL_PLAYBOOKS` headless) only on hosts
that need it, e.g. for DDEV. A further reason it cannot be core: `docker-ce-cli` package-conflicts
with `podman-docker` (the `docker` CLI shim), so a core Docker import makes `playbook-main.yml`
unable to converge on a podman-only host that carries the shim. When installed, the engines
coexist cleanly — different sockets, different storage, different networking stacks. See
"Coexistence" below.

## Podman — the default, use this first

Expand Down Expand Up @@ -143,5 +150,5 @@ Yes — once, to pick up the new `docker` group membership. Log out and back in,
- `CLAUDE/Plan/Completed/033-ddev-installation/container-engine-strategy.md` — the decision-gate analysis that led to this split
- `vars/container-defaults.yml` — the `container_engine` default
- `playbooks/imports/play-podman.yml` — Podman setup
- `playbooks/imports/play-docker.yml` — Docker setup
- `playbooks/imports/optional/common/play-docker.yml` — Docker setup (optional)
- `playbooks/imports/play-lxc-install-config.yml` — LXC setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Plan 00091 — Journal 26-09-01

> **Append-only activity log** for plan 00091. One file per day
> (`00091-Journal-YY-MM-DD.md`). `PLAN.md` tracks the plan (what/why,
> current state, tasks); this journal tracks what actually *happened* —
> findings, decisions, dead-ends, hand-off state — the linear lifecycle a plan
> document structurally cannot carry.
>
> **Entry grammar** — append new entries at the BOTTOM; NEVER edit earlier
> entries (corrections are new entries):
>
> ```
> ## HH:MM · category · REF — optional short title
> ```
>
> - `HH:MM` local 24h (the date is in the filename); times increase down the file.
> - `category` ∈ `action` | `finding` | `decision` | `thought` | `blocker` | `handoff`
> - `REF` = optional task/phase ref (`T1.2`, `P1`) or `—`.
> - Bodies may embed fenced logs/diffs/snippets — no size limit — with a
> one-line takeaway above the fence.
> - End a working session with a `handoff` entry so the next agent's entry
> point is the last entry of the newest day-file.

## 14:02 · action · — — plan scaffolded

Plan 00091 created via `mkplan.bash`; `JOURNAL/` initialised. Next:
fill in `PLAN.md`, then log progress here as it happens.

## 14:03 · action · — — issue filed

Tracking issue created: https://github.com/LongTermSupport/fedora-desktop/issues/41
(rootful Docker core import vs podman-first hosts; docker-ce-cli conflicts with
podman-docker; remaining coexistence concerns tracked there).

## 14:06 · action · T1.1 T1.2 — demotion implemented

- `git mv playbooks/imports/play-docker.yml playbooks/imports/optional/common/play-docker.yml`;
import removed from `playbook-main.yml`.
- `play-lxc-install-config.yml`: replaced the hard "Docker must be installed first" assert
with a `/usr/bin/dockerd` presence probe (`docker_daemon_check`). Chose `dockerd`, not
`/usr/bin/docker`, because `podman-docker` also ships `/usr/bin/docker` — the probe must
detect the rootful engine, not the CLI shim. All five Docker-coexistence tasks
(DOCKER-USER assert, reconcile script deploy, immediate apply, systemd unit deploy,
unit enable) now condition on it. Fail-fast preserved: with dockerd on disk but no
DOCKER-USER chain the assert still aborts (half-configured Docker), pointing at the
optional play.
- Fixed a `partial-become` ansible-lint fatal on the lxc-bash block (`become_user`
without same-level `become`) — behaviourally a no-op (play is `become: true`).

## 14:07 · decision · — — server-recommended.bundle: no docker, no change

The bundle lists neither `play-docker.yml` nor `play-ddev.yml`, so podman-first is already
coherent there: DDEV users opt in explicitly to both. No bundle change.

## 14:08 · finding · T2.1 — menu discovery is automatic

Both the interactive optional menu and headless `RUN_BASH_OPTIONAL_PLAYBOOKS` discover plays
via `find playbooks/imports/optional…`, so the moved `play-docker.yml` appears with no
run.bash change. Docs/refs updated: play-ddev fix messages, playbooks.md (section moved to
optional catalog), architecture.md, README.md, installation.md, configuration.md, ddev.md,
containerization.md, ContainerEngines.md. `CLAUDE/PlanWorkflow.md`'s mention is an
illustrative example in a daemon-deployed doc — left untouched. QA: qa-ansible-syntax,
qa-ansible, qa-patterns, qa-discovery all pass; qa-docs fails only on pre-existing
`.claude/rules/*` links to a missing daemon doc (unrelated to this plan).

## 14:15 · handoff · T3.2 — PR open, awaiting review/merge

PR https://github.com/LongTermSupport/fedora-desktop/pull/42 open against F44 (commits
989457d + 67ee5a5). PR #40 closed as superseded (skip-docker-env branch left in place).
Plan stays In Progress until the PR merges; on merge, flip to Complete and archive.
66 changes: 66 additions & 0 deletions CLAUDE/Plan/00091-podman-first-docker-optional/PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Plan 00091: podman first docker optional

**Status**: In Progress
**Created**: 2026-09-01
**Owner**: joseph
**Priority**: Medium

## Overview

The repo's own container-engine policy (CLAUDE/ContainerEngines.md) is "Podman first, Docker
only for compatibility (e.g. DDEV)", yet `playbooks/playbook-main.yml` imports
`playbooks/imports/play-docker.yml` as a core, non-optional play. On a podman-first host that
carries `podman-docker` (the `docker` CLI shim — e.g. a headless podman-only CI host), the
`docker-ce-cli` package conflict makes the main playbook unable to converge at all.

This plan demotes rootful Docker from core to optional per the owner's direction: move
`play-docker.yml` to `playbooks/imports/optional/common/`, drop its import from
`playbook-main.yml`, and make `play-lxc-install-config.yml`'s Docker-coexistence handling
conditional on Docker actually being present (fail-fast is preserved for hosts with Docker
half-configured). The env-var opt-out of PR #40 (`RUN_BASH_SKIP_DOCKER`) is superseded and
that PR is closed. Remaining coexistence concerns are tracked in issue #41 (Refs #41).

## Goals

- `playbook-main.yml` converges on a podman-only host (no Docker CE install attempted).
- `play-docker.yml` remains fully functional as an optional play, discovered by both the
interactive menu and headless `RUN_BASH_OPTIONAL_PLAYBOOKS`.
- `play-lxc-install-config.yml` works on hosts with and without Docker, with no error hiding.
- Docs and CLAUDE topic files describe Docker as optional; no functional reference to the old
core path remains.

## Non-Goals

- Removing Docker support or the DDEV workflow (DDEV still requires rootful Docker).
- Adding `play-docker.yml` (or `play-ddev.yml`) to `server-recommended.bundle` — the bundle
stays podman-first; DDEV users opt in explicitly.
- Solving the wider coexistence problems (podman-docker assertion, docker-group containment)
— tracked in issue #41.

## Tasks

### Phase 1: Demotion

- [x] ✅ **Task 1.1**: `git mv playbooks/imports/play-docker.yml playbooks/imports/optional/common/play-docker.yml`; remove the import from `playbook-main.yml`.
- [x] ✅ **Task 1.2**: Make `play-lxc-install-config.yml` Docker-conditional: probe Docker presence; when present, keep the fail-fast DOCKER-USER assertion and reconcile tasks; when absent, skip the Docker-coexistence block (lxc-net's own FORWARD/MASQUERADE rules suffice without Docker).

### Phase 2: References

- [x] ✅ **Task 2.1**: Update all functional references to the old path (play-ddev.yml fix messages, docs/installation.md, docs/ddev.md, docs/playbooks.md, docs/architecture.md, docs/containerization.md, docs/configuration.md, docs/README.md, CLAUDE/ContainerEngines.md).

### Phase 3: QA and PR

- [x] ✅ **Task 3.1**: Run the repo QA (`scripts/qa-all.bash` relevant gates) and fix findings.
- [x] ✅ **Task 3.2**: Push branch, open PR (Refs #41), close PR #40 as superseded.

## Success Criteria

- [x] `ansible-playbook --syntax-check` passes for `playbook-main.yml` and the moved play.
- [x] No functional reference to `playbooks/imports/play-docker.yml` remains outside
historical plan folders.
- [x] PR open with rationale, migration notes, and bundle decision; PR #40 closed.

## Delivery & Milestones

- Demotion delivered on branch podman-first-docker-optional (989457d, 67ee5a5); PR: https://github.com/LongTermSupport/fedora-desktop/pull/42
- Issue: https://github.com/LongTermSupport/fedora-desktop/issues/41
2 changes: 2 additions & 0 deletions CLAUDE/Plan/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Use these Unicode icons in plan documents:

## Active Plans

- [00091-podman-first-docker-optional](00091-podman-first-docker-optional/) - Demote rootful Docker from core to optional (podman-first); Refs #41

- [004-comprehensive-feature-documentation](004-comprehensive-feature-documentation/) - Documentation for all major features (CCY, CCB, Nord, Speech-to-Text, etc.)

- [007-speech-to-text-resource-leak-fixes](007-speech-to-text-resource-leak-fixes/) - Fix microphone resource leak, transcription truncation, and browser paste failures
Expand Down
5 changes: 2 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,8 @@ ansible desktop -m setup | grep ansible_distribution
```bash
cd ~/Projects/fedora-desktop

# Docker is installed automatically by the main playbook (rootful, core)
# To re-run it manually:
ansible-playbook playbooks/imports/play-docker.yml
# Install rootful Docker (optional — needed for DDEV; Podman is the default engine)
ansible-playbook playbooks/imports/optional/common/play-docker.yml

# Install Distrobox
ansible-playbook playbooks/imports/optional/common/play-distrobox.yml
Expand Down
38 changes: 20 additions & 18 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,28 +106,30 @@ The bootstrap script:
14. **play-rpm-fusion.yml**: Third-party repository setup
15. **play-browsers.yml**: Additional browser setup
16. **play-toolbox-install.yml**: JetBrains Toolbox
17. **play-docker.yml**: Rootful Docker (compatibility engine for DDEV)
18. **play-lxc-install-config.yml**: LXC container support
- **Ordering constraint**: LXC runs _after_ Docker so the `DOCKER-USER`
iptables chain exists when LXC reconciles outbound connectivity.
See the "Reconcile iptables" block in `play-lxc-install-config.yml`.
19. **play-podman.yml**: Rootless Podman (default container engine)
20. **play-python.yml**: Python/pyenv setup
21. **play-claude-yolo.yml**: CCY (Claude container wrapper) installation
17. **play-lxc-install-config.yml**: LXC container support
- Rootful Docker is optional (`imports/optional/common/play-docker.yml`,
podman-first policy). On Docker hosts, run Docker _before_ this play so
the `DOCKER-USER` iptables chain exists when LXC reconciles outbound
connectivity; on podman-only hosts the Docker-coexistence block is
skipped. See the "Reconcile iptables" block in
`play-lxc-install-config.yml`.
18. **play-podman.yml**: Rootless Podman (default container engine)
19. **play-python.yml**: Python/pyenv setup
20. **play-claude-yolo.yml**: CCY (Claude container wrapper) installation
- **Ordering constraint**: CCY must run _before_ `play-claude-code.yml`
because the `cc` wrapper sources CCY lib files at runtime, and
`play-claude-code.yml` asserts the lib is present before deploying it.
See `CLAUDE/Plan/00048-cc-token-source-parity`.
22. **play-claude-code.yml**: Claude Code CLI and `cc` wrapper
23. **play-comms.yml**: Communication applications
24. **play-gnome-shell.yml**: GNOME Shell configuration
25. **play-gnome-shell-extensions.yml**: GNOME Shell extensions
26. **play-markless.yml**: Markless tool setup
27. **play-terminal-emulators.yml**: Terminal emulator configuration
28. **play-vscode.yml**: Visual Studio Code
29. **play-vpn.yml**: VPN configuration
30. **play-gsettings.yml**: GNOME settings
31. **play-ZZ-repo-cleanup.yml**: Post-run repository cleanup
21. **play-claude-code.yml**: Claude Code CLI and `cc` wrapper
22. **play-comms.yml**: Communication applications
23. **play-gnome-shell.yml**: GNOME Shell configuration
24. **play-gnome-shell-extensions.yml**: GNOME Shell extensions
25. **play-markless.yml**: Markless tool setup
26. **play-terminal-emulators.yml**: Terminal emulator configuration
27. **play-vscode.yml**: Visual Studio Code
28. **play-vpn.yml**: VPN configuration
29. **play-gsettings.yml**: GNOME settings
30. **play-ZZ-repo-cleanup.yml**: Post-run repository cleanup

### Desktop or server — the `provisioning_profile` / `scope` pair

Expand Down
7 changes: 4 additions & 3 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ Bash Git Prompt with Solarized theme in:
These plays are imported by `playbook-main.yml` and run automatically on every
provisioning run — there is nothing to enable.

### Docker
### Docker (optional — not imported by the main playbook)

`play-docker.yml` installs Docker as a **rootful** compatibility engine (Podman remains
the rootless default — see [Container Engines](../CLAUDE/ContainerEngines.md)):
`playbooks/imports/optional/common/play-docker.yml` installs Docker as a **rootful**
compatibility engine when a tool needs it (e.g. DDEV). Podman remains the rootless
default — see [Container Engines](../CLAUDE/ContainerEngines.md):

- User added to the `docker` group
- Systemd service enabled
Expand Down
5 changes: 3 additions & 2 deletions docs/containerization.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,11 @@ Docker is an application containerization platform designed for packaging, distr

### Installation

Installed automatically by the main playbook (`playbooks/imports/play-docker.yml` is a core import of `playbook-main.yml`). To run it standalone:
**Optional** — not imported by `playbook-main.yml` (podman-first policy; Docker is a
compatibility engine, e.g. for DDEV). Install it via the optional play:

```bash
ansible-playbook playbooks/imports/play-docker.yml
ansible-playbook playbooks/imports/optional/common/play-docker.yml
```

Configuration details:
Expand Down
5 changes: 3 additions & 2 deletions docs/ddev.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ This installs:
- **mkcert** — local HTTPS certificate authority (bundled with the DDEV RPM; Fedora's standalone `mkcert` package is removed first because it conflicts file-for-file)
- **DDEV** — via the official yum repository at `pkg.ddev.com`

**Prerequisite:** Rootful Docker must be installed first:
**Prerequisite:** Rootful Docker must be installed first (it is an optional play —
podman-first policy):

```bash
ansible-playbook playbooks/imports/play-docker.yml
ansible-playbook playbooks/imports/optional/common/play-docker.yml
```

This installs Docker CE as a system-wide daemon and adds your user to the `docker` group. After the first run you must **log out and back in** (or run `newgrp docker` in your shell) before `docker` commands work without `sudo`.
Expand Down
8 changes: 6 additions & 2 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,19 @@ The main playbook installs and configures:

Must be run manually after main playbook. See [Playbooks Reference](playbooks.md#optional-playbooks) for the complete catalog.

**Note:** Docker (rootful) is installed automatically by the main playbook via
`playbooks/imports/play-docker.yml` — it is a core component, not optional. See
**Note:** Docker (rootful) is **optional** — the main playbook does not install it.
Podman is the default container engine; install Docker only when a tool needs it for
compatibility (e.g. DDEV) via `playbooks/imports/optional/common/play-docker.yml`. See
`CLAUDE/ContainerEngines.md` for the Podman-first / Docker-for-compatibility policy.

Popular optional components:

```bash
cd ~/Projects/fedora-desktop

# Docker (rootful compatibility engine — required for DDEV)
ansible-playbook playbooks/imports/optional/common/play-docker.yml

# Distrobox
ansible-playbook playbooks/imports/optional/common/play-distrobox.yml

Expand Down
Loading
Loading