From 0bdcd9a2e1ec1b0c11736ec2b18469ee142729c8 Mon Sep 17 00:00:00 2001 From: nite Date: Fri, 3 Apr 2026 20:09:42 +1100 Subject: [PATCH] init --- .github/ISSUE_TEMPLATE/bug_report.md | 24 + .github/ISSUE_TEMPLATE/rule_improvement.md | 24 + .github/pull_request_template.md | 14 + .gitignore | 14 + LICENSE | 21 + README.md | 44 + README.zh-CN.md | 44 + SKILL.md | 284 +++ references/compose-mapping.md | 177 ++ references/deployment-notes.md | 55 + references/env-strategy.md | 165 ++ references/github-repo-intake.md | 57 + references/podman-systemd.unit.5.md | 2556 ++++++++++++++++++++ references/validation.md | 70 + 14 files changed, 3549 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/rule_improvement.md create mode 100644 .github/pull_request_template.md create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 README.zh-CN.md create mode 100644 SKILL.md create mode 100644 references/compose-mapping.md create mode 100644 references/deployment-notes.md create mode 100644 references/env-strategy.md create mode 100644 references/github-repo-intake.md create mode 100644 references/podman-systemd.unit.5.md create mode 100644 references/validation.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..3a1fd01 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: Report a problem, ambiguity, or incorrect migration rule +--- + +## Summary + +Describe the issue. + +## Input + +Provide the relevant `docker run`, Compose snippet, or repository context. + +## Expected behavior + +Describe what the skill should have done. + +## Actual behavior + +Describe what happened instead. + +## Additional context + +Add any references, screenshots, or Podman / Quadlet version details. diff --git a/.github/ISSUE_TEMPLATE/rule_improvement.md b/.github/ISSUE_TEMPLATE/rule_improvement.md new file mode 100644 index 0000000..70ef204 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/rule_improvement.md @@ -0,0 +1,24 @@ +--- +name: Rule improvement +about: Propose an improvement to mapping rules, env strategy, or workflow +--- + +## Area + +- [ ] workflow +- [ ] compose mapping +- [ ] env strategy +- [ ] repo intake +- [ ] deployment / validation + +## Proposal + +Describe the rule change. + +## Why + +Explain the concrete problem this would solve. + +## Example + +Add a minimal input and the expected outcome if possible. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..39e5a27 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,14 @@ +## Summary + +- describe the change +- explain any skill behavior or rule updates + +## Test / validation + +- [ ] reviewed `SKILL.md` +- [ ] reviewed affected files under `references/` +- [ ] considered impact on topology, env handling, and finalize flow + +## Notes + +Add any migration edge cases or trade-offs here. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8b46a20 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# OS / editor +.DS_Store +Thumbs.db +*.swp +*.swo +*~ + +# Claude / local tooling +.claude/ + +# Build or temp outputs +*.log +*.tmp +*.bak diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e4c577d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 nite + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..adfba81 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Quadlet Migrator + +[English](./README.md) | [简体中文](./README.zh-CN.md) + +A skill for migrating `docker run` commands and Docker Compose-style deployments into maintainable Podman Quadlet units. + +## What it does + +- translates `docker run` and Compose-style inputs into Quadlet-oriented designs +- helps decide between `.container`, `.pod`, `.network`, `.volume`, and `.build` +- preserves `.env` / `env_file` workflows when appropriate +- reduces large env templates into a small set of high-impact deployment questions +- explains rootless vs rootful placement, deployment notes, and validation steps + +## Design principles + +- prefer the lightest operating mode that matches the request +- separate planning, review, and generation into explicit phases +- do not invent deployment-specific values +- make lossy mappings explicit +- prefer maintainable output over mechanical one-to-one translation + +## Operating modes + +- `advice`: explain mappings or review source inputs without writing final artifacts +- `design`: perform planning and finalize review, then stop before runnable artifact generation +- `generate`: produce approved runnable artifacts after planning and finalize review + +## References + +- `SKILL.md` contains the operating modes, workflow, and high-level rules +- `references/compose-mapping.md` covers field mapping and topology decisions +- `references/env-strategy.md` covers env handling and secret defaults +- `references/github-repo-intake.md` covers repository discovery and canonical input selection +- `references/deployment-notes.md` covers deployment guidance +- `references/validation.md` covers validation and troubleshooting + +## Limitations + +This skill does not claim perfect equivalence between Docker Compose semantics and Podman Quadlet semantics. + +## License + +MIT diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..580b486 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,44 @@ +# Quadlet Migrator + +[English](./README.md) | [简体中文](./README.zh-CN.md) + +一个 skill,用来将 `docker run` 命令和 Docker Compose 风格部署迁移为可维护的 Podman Quadlet 单元。 + +## 功能概览 + +- 将 `docker run` 和 Compose 风格输入转换为面向 Quadlet 的设计 +- 帮助在 `.container`、`.pod`、`.network`、`.volume`、`.build` 之间做选择 +- 在合适时保留 `.env` / `env_file` 工作流 +- 将大型 env 模板归纳为少量高影响部署问题 +- 说明 rootless / rootful 放置路径、部署说明与验证步骤 + +## 设计原则 + +- 优先选择满足需求的最轻运行模式 +- 将规划、审阅、生成拆成明确阶段 +- 不虚构部署相关取值 +- 对有损映射保持显式说明 +- 优先输出可维护的结果,而不是机械一比一转换 + +## 运行模式 + +- `advice`:解释映射方式或审查输入,不写最终产物 +- `design`:执行 planning 和 finalize 审阅,但在生成可运行产物前停止 +- `generate`:在 planning 和 finalize 审阅通过后,生成已批准的可运行产物 + +## 文档说明 + +- `SKILL.md`:运行模式、工作流和高层规则 +- `references/compose-mapping.md`:Compose 字段映射与拓扑决策 +- `references/env-strategy.md`:env 处理与 secret 默认策略 +- `references/github-repo-intake.md`:仓库发现与 canonical 输入选择 +- `references/deployment-notes.md`:部署说明 +- `references/validation.md`:验证与排障 + +## 限制 + +本 skill 不保证 Docker Compose 语义与 Podman Quadlet 语义完全等价。 + +## 许可证 + +MIT diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..47eea95 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,284 @@ +--- +name: quadlet-migrator +description: Convert docker run commands or Docker Compose configurations into maintainable Podman Quadlet files, help users map env/env_file/.env usage into Environment or EnvironmentFile, and explain rootless or rootful deployment details and migration risks. +--- + +# Quadlet Migrator + +Use this skill when the user wants to migrate `docker run`, `docker compose`, or Compose-like service definitions into Podman Quadlet units, especially when environment variables, `env_file`, `.env`, rootless deployment, or systemd layout need to be planned or generated. + +Do not rely on `podlet` as an execution dependency. You may use it only as prior-art knowledge, not as part of the runtime workflow. + +## What this skill does + +This skill helps you: + +- discover Docker deployment entry points from a GitHub repository URL +- translate `docker run` flags and Compose service fields into Quadlet units +- choose between `.container`, `.pod`, `.network`, `.volume`, and `.build` +- decide whether values belong in `Environment=` or `EnvironmentFile=` +- work closely with the user to confirm deployment-specific environment values and operational choices +- identify missing variables, unsafe inline secrets, and unsupported Compose semantics +- produce deployment notes for rootless or rootful systemd setups + +## Operating modes + +Choose the lightest mode that satisfies the user's request. + +- `advice`: explain mappings, review source inputs, answer targeted migration questions, or sketch a recommended structure without writing final artifacts +- `design`: perform `Planning` and `Finalize`, produce `QUADLET-FINALIZE.md`, but stop before writing runnable artifacts +- `generate`: perform `Planning`, `Finalize`, and `Execution`, then write the approved runnable artifacts + +Do not force `generate` mode when the user only wants explanation, review, or a partial conversion. + +## Workflow + +The full workflow has three explicit phases: `Planning`, `Finalize`, and `Execution`. + +- `advice` usually stays in `Planning` or gives a targeted answer without entering all phases +- `design` uses `Planning` and `Finalize` +- `generate` uses all three phases + +Do not skip phase boundaries when you are using them. The skill should not jump directly from discovery into writing files. + +### Planning phase + +Goal: gather inputs, understand the project, and work with the user to make the key decisions. + +Tasks in this phase: + +1. Classify the input. + - `docker run` or `podman run` style command + - single-file Compose configuration + - Compose plus `.env` and optional `env_file` + - GitHub repository URL that likely contains self-hosting assets + - already partially converted Quadlet files that need cleanup + +2. If the input is a GitHub repository, discover the deployment entry points first. + - start from the repository README and deployment subdirectory READMEs + - follow explicit links or references from documentation before making assumptions about file locations + - search the repository tree for `docker-compose.yaml`, `docker-compose.yml`, `compose.yaml`, `compose.yml` + - inspect common deployment-oriented subdirectories such as `docker/`, `deploy/`, `ops/`, `infra/`, `.devcontainer/`, and `examples/`, but do not assume the right entry point must live there + - look for `.env.example`, `.env.sample`, `env.example`, `middleware.env.example`, or similar templates + - inspect whether the project uses Compose profiles, multiple compose files, generated compose files, or helper scripts + - identify the canonical self-hosting entry point rather than assuming the repo root file is authoritative + +3. Build a semantic model before writing Quadlet. + - services + - images or builds + - ports + - volumes and bind mounts + - networks + - environment variables and env files + - restart policy + - health checks + - startup dependencies + +4. Identify which values and decisions must be confirmed with the user. + - external URLs, domains, and ports + - database hostnames, passwords, and database names + - storage backend selection and credentials + - profile selection or optional service selection + - pod grouping when the project has many services or optional containers + - volume mode selection: named volume, bind mount, or anonymous volume + - rootless vs rootful deployment mode + - whether secrets should stay in env files or be moved elsewhere + +Do not silently invent deployment-specific values. If the repository or compose file provides placeholders, defaults, or examples, read the surrounding documentation and comments yourself, infer the intended meaning, and only ask the user to confirm the values that materially affect deployment. + +When many variables exist, do not hand the raw `.env.example` back to the user for manual review. Your job is to digest it, reduce it, and produce a concise checklist of high-impact decisions. Prioritize the variables that are required to produce a safe and runnable output. + +At the end of planning, summarize what you learned and what you intend to generate, then explicitly ask the user whether anything should be changed or added before you move to the next phase. + +Planning is also the phase where you must actively ask the user for the unresolved high-impact decisions you identified. + +Do not defer first-time decision gathering into `QUADLET-FINALIZE.md`. + +If decisions are still unresolved, stop in planning and ask the user directly. Do not write `QUADLET-FINALIZE.md` yet. + +### Finalize phase + +Goal: consolidate the decisions already made in planning into one internally consistent design snapshot and ask the user to review it. + +The output of this phase must be written to a Markdown file named `QUADLET-FINALIZE.md`. + +This filename is fixed. Do not rename it per project. + +This phase starts only after planning-phase questions have been asked and the user has had a chance to answer or explicitly say there is nothing more to add. + +Finalize is not a second discovery pass. Do not use it to introduce new major design choices, gather first-time requirements, or expand the scope of analysis. If execution reveals a new material decision or conflict, return to planning rather than stretching finalize into another analysis phase. + +Tasks in this phase: + +1. Freeze the chosen service set and runtime grouping. + - prefer putting the whole project in a single pod when practical + - if the project is a simple single-container deployment, a standalone `.container` is acceptable + - if shared networking, shared published ports, or tighter lifecycle coupling make pod semantics useful, prefer one or more `.pod` units + - containers in the same `.pod` can communicate over `127.0.0.1` / `localhost` because they share a network namespace + - containers in different pods must not be treated as reachable via `127.0.0.1` / `localhost`; if you split the topology across multiple pods, use container networking and service addressing, or publish ports across the host boundary when that better matches the deployment + - if one pod is not practical because of port conflicts or clearly incompatible groupings, split the result into a small number of pods rather than forcing an awkward topology + +2. Freeze the storage strategy. + - named volume, bind mount, or anonymous volume per storage use case + - bind mounts must end up as absolute host paths + +3. Freeze the image strategy. + - prefer upstream prebuilt registry images when they already exist and local build is not required for correctness + - create `.build` only when local build is actually required, or when the user explicitly wants a declarative local-build workflow + - prefer fully qualified image names in generated output + - if the source image omits a registry and is intended for Docker Hub, expand it explicitly instead of relying on short-name resolution + - for images of the form `name[:tag]` with no namespace, normalize to `docker.io/library/name[:tag]` + - for images of the form `namespace/name[:tag]` with no registry, normalize to `docker.io/namespace/name[:tag]` + - if the source clearly points to another registry such as `ghcr.io`, `quay.io`, or a private registry, preserve that registry explicitly + +4. Freeze the environment strategy. + - use `Environment=` for a small number of stable non-sensitive values + - use `EnvironmentFile=` for bulk variables, secrets, or values already sourced from `.env` / `env_file` + - if Compose interpolation references variables that are missing, report them explicitly and prepare a candidate env file with placeholders or suggested defaults instead of delegating the entire review back to the user + - treat variable names containing `PASSWORD`, `TOKEN`, `SECRET`, `KEY`, `PRIVATE`, or `PASS` as sensitive by default and avoid inlining unless the user explicitly wants that + +5. Summarize already-known conflicts and their chosen resolution. + - port collisions + - incompatible grouping decisions + - storage mode inconsistencies + - unresolved required variables + - mismatch between requested deployment mode and selected file locations + +At the end of finalize, write `QUADLET-FINALIZE.md` and ask the user to review it before you start writing the final artifacts. + +`QUADLET-FINALIZE.md` is a review artifact, not a questionnaire. It should summarize decisions that were already discussed in planning. + +If `QUADLET-FINALIZE.md` already exists, read it first and update it intentionally. Do not blindly overwrite it without checking whether it reflects a prior review round that should be preserved or revised. + +When the design has materially changed, replace outdated sections so the file remains a single current review snapshot rather than an append-only log. + +`QUADLET-FINALIZE.md` should include: + +- source inputs you chose and why +- selected services and omitted optional services +- pod layout +- naming prefix +- image strategy +- volume strategy +- env strategy +- only the minimal placeholders that still cannot be resolved without user secrets or environment-specific values +- detected conflicts and how they were resolved +- the list of files that will be created in execution phase + +Do not start execution until the user has reviewed and confirmed `QUADLET-FINALIZE.md` or provided requested edits. + +Do not use `QUADLET-FINALIZE.md` as the first place where the user sees important choices. Those choices should already have been raised in planning. + +### Execution phase + +Goal: write the approved runnable artifacts. + +Tasks in this phase: + +1. Generate the Quadlet files. +2. Generate the env file or env delta only when needed for runnable output. +3. Generate deployment notes or validation guidance only when they materially help the user operate the result. +4. Generate a README only when the user explicitly wants a self-contained handoff artifact or a packaged deliverable. + +Execution should follow the approved contents of `QUADLET-FINALIZE.md`. If the implementation reveals a material conflict with the finalized design, stop and return to planning rather than silently diverging. + +If you generate a README or operational notes, use the same language as the user unless the user explicitly asks for another language. + +## Decision priority + +When rules or signals conflict, use this priority order: + +1. the user's explicit request +2. the source project's documented canonical deployment path +3. runnable and safe output +4. maintainable output +5. default style rules in this skill and its references + +If a lower-priority default conflicts with a higher-priority source of truth, follow the higher-priority source and say so briefly. + +## Hard stops + +Stop and ask the user before finalizing or generating runnable output when any of these remain unresolved: + +- required secrets, external URLs, host paths, or other deployment-specific values are missing +- multiple plausible source inputs exist and the canonical deployment entry point cannot be determined confidently +- image strategy versus local build strategy is materially ambiguous +- a lossy mapping would change runtime behavior in a way that matters +- the requested deployment mode conflicts with the intended output location or operator model + +Do not keep moving forward by guessing through these gaps. + +## Rootless vs rootful + +Decide early whether the deployment is rootless or rootful, because this changes the output path and some operational guidance. + +- For rootless deployments, use `~/.config/containers/systemd/` unless the user has a reason to use another supported path. +- For rootful deployments, use `/etc/containers/systemd/` unless the user asks for a different placement. +- For rootless long-running services, remind the user about lingering if relevant. See `references/deployment-notes.md`. + +When you need authoritative details about supported search paths, unit semantics, option names, or debugging, read `references/podman-systemd.unit.5.md`. + +## Reference routing + +Use the reference files for detailed rules instead of restating them here: + +- `references/compose-mapping.md` for Compose field mapping, topology choices, and naming conventions +- `references/env-strategy.md` for `.env`, `env_file`, interpolation, and secret-handling defaults +- `references/github-repo-intake.md` for GitHub repository discovery and canonical input selection +- `references/deployment-notes.md` for deployment guidance and rootless or rootful operational notes +- `references/validation.md` for post-generation validation and troubleshooting steps + +## User collaboration + +This skill is not a blind converter. For runnable output, collaborate tightly with the user. + +- Confirm any environment value that controls external connectivity, credentials, storage, or deployment topology. +- If the source contains a large env template, summarize the required variables into a small decision list and ask the user to confirm only those values. +- Do not ask the user to read upstream docs or manually audit a large `.env.example` unless they explicitly want to do that themselves. +- Read the docs, comments, and example values yourself, then present the user with a reduced set of concrete decisions and a candidate env result. +- Ask the user to choose optional services and pod grouping early when the source project offers many containers or feature profiles. +- Ask the user which volume mode they want before finalizing storage mappings. +- Ask these questions before writing `QUADLET-FINALIZE.md`, not inside it. +- Preserve placeholders when the user has not provided final values yet. +- Distinguish between upstream example values and user-confirmed production values. + +You should still make reasonable structural decisions yourself, but do not pretend unknown deployment inputs are settled facts. + +## Deployment and validation + +When the user wants runnable output, provide the relevant deployment notes from `references/deployment-notes.md` and the validation steps from `references/validation.md` as needed. + +At minimum, mention the need to: + +- place files in a valid Quadlet directory +- run `systemctl daemon-reload` or `systemctl --user daemon-reload` +- create required bind-mount directories before first start +- verify generator output or systemd unit validity when startup fails + +## Examples + +- `docker run` for a single web service -> often `advice` or `generate` with one `.container` +- small Compose app with api and db -> usually `design` or `generate`, often one `.pod` plus child containers +- GitHub repo with `.env.example` and multiple profiles -> start in `Planning`, reduce the env questions, then move to `Finalize` + +## Anti-examples + +- do not dump a large `.env.example` back to the user as the primary review artifact +- do not introduce first-time critical decisions inside `QUADLET-FINALIZE.md` +- do not force pod topology when a standalone `.container` is the simpler correct result +- do not keep generating through unresolved deployment-critical unknowns + +## Boundaries + +Do not claim perfect equivalence where Podman or Quadlet semantics differ from Docker Compose. + +Be especially careful with: + +- Compose interpolation and default syntax +- `depends_on` readiness assumptions +- complex `deploy` blocks +- multi-file Compose merges +- secrets and credentials +- permission behavior on rootless bind mounts + +If a mapping is lossy, say so directly and explain the concrete risk. diff --git a/references/compose-mapping.md b/references/compose-mapping.md new file mode 100644 index 0000000..a9cc026 --- /dev/null +++ b/references/compose-mapping.md @@ -0,0 +1,177 @@ +# Compose Mapping + +Use this file when converting `docker-compose.yml` or `compose.yaml` into Quadlet units. + +## General approach + +- Model each service first, then decide how to group all resulting containers into one or more `.pod` units. +- Prefer maintainable Quadlet output over mechanical one-to-one translation. +- Keep names stable and predictable. Generated filenames should use a shared project prefix. + +## Field strategy + +### `name` + +- Use as an application prefix when it improves unit naming clarity. +- Do not force a top-level project name into every filename if the user prefers shorter units. + +### `services..image` + +- Map to `Image=` in `[Container]`. +- Prefer fully qualified image names when normalizing output. +- If the source omits a registry and is using Docker Hub semantics, normalize it explicitly for Podman. +- Use these rules when filling in Docker Hub references: + - `redis:7` -> `docker.io/library/redis:7` + - `nginx` -> `docker.io/library/nginx` + - `langgenius/dify-api:latest` -> `docker.io/langgenius/dify-api:latest` +- Do not guess `docker.io/library/...` for images that already include a namespace. + +### `services..build` + +- Prefer upstream published images over local builds when the project already documents supported registry images. +- If the user wants declarative builds, create a `.build` unit and reference it from `Image=`. +- If the build semantics are too custom, or if an equivalent upstream image is clearly available, keep this as a manual follow-up item instead of guessing. + +### `container_name` + +- Drop it. +- Do not generate `ContainerName=`. Let Podman and systemd derive the runtime name. + +### `ports` + +- For a standalone service, map to `PublishPort=` on the `.container`. +- For a pod-based topology, prefer `PublishPort=` on the `.pod` when the published ports belong to the pod boundary rather than one child container. + +### `volumes` + +- Bind mounts become `Volume=HOST:CONTAINER[:OPTIONS]`. +- Normalize relative host paths against the Compose file directory and emit absolute paths in the final Quadlet output. +- Named volumes can remain referenced by name, but when the user wants explicit infrastructure-as-code, create matching `.volume` units. +- Ask the user which volume mode they want when the source does not make the intended persistence model obvious. + +### `networks` + +- If the source uses a default network only, you often do not need a `.network` unit. +- If a custom network is intentional and needs to be managed declaratively, create a `.network` unit and reference it explicitly. +- Containers in the same `.pod` can communicate over `127.0.0.1` / `localhost` because they share a network namespace. +- Containers in different pods must not be treated as reachable via `127.0.0.1` / `localhost`. +- When splitting services across multiple pods, use container networking and service-level addressing, or publish ports to the host boundary when that is the intended access pattern. + +### `environment` + +- Small stable values can become one or more `Environment=` lines. +- Sensitive values should be moved to `EnvironmentFile=` unless the user explicitly wants them inline. + +### `env_file` + +- Prefer `EnvironmentFile=`. +- If there are multiple env files, preserve order and explain precedence if the user asks. + +### `.env` interpolation + +- Resolve only when you have the actual source values. +- If variables are missing, surface a missing-variable list. +- Never silently replace unknown values with blanks. + +### `profiles` + +- Decide first which profiles are actually part of the desired deployment. +- Do not try to preserve Compose profiles as a direct Quadlet concept. +- Treat profiles as source selection inputs that decide which services become units. + +### `depends_on` + +- Translate to `Requires=` and `After=` when that reflects intent. +- State clearly that this controls startup ordering, not application readiness. + +### `restart` + +- Map common cases to `[Service] Restart=`. +- If the source policy has no direct systemd equivalent, choose the nearest safe mapping and explain it. + +### `healthcheck` + +- Prefer dedicated Quadlet health fields such as `HealthCmd=`, `HealthInterval=`, `HealthTimeout=`, `HealthRetries=` when representable. +- If the Compose healthcheck is only partially representable, preserve the command intent and call out missing knobs. + +### `command` and `entrypoint` + +- `entrypoint` typically maps to `Entrypoint=`. +- `command` typically maps to `Exec=`. + +### `user` + +- Map to `User=` and `Group=` in `[Container]` only when it is a container runtime user mapping, not a systemd service user. +- Do not use systemd `User=` to try to make a rootless Quadlet run as another login user. + +### unsupported or risky fields + +Handle these conservatively and usually as migration notes: + +- `deploy` +- `profiles` +- `extends` +- advanced Compose merge behavior +- readiness semantics hidden behind `depends_on` + +## Minimal examples + +### Single service to standalone container + +Source intent: + +```yaml +services: + web: + image: nginx:latest + ports: + - "8080:80" +``` + +Reasonable result shape: + +```ini +[Container] +Image=docker.io/library/nginx:latest +PublishPort=8080:80 +``` + +Use this when the deployment is truly a simple single-service case and pod semantics add little value. + +### Small multi-service app to one pod + +Source intent: + +```yaml +services: + api: + image: ghcr.io/example/api:1.0 + depends_on: + - db + db: + image: postgres:16 +``` + +Reasonable result shape: + +- one `.pod` for the application boundary +- one container unit for `api` +- one container unit for `db` +- `api` may reach `db` over `127.0.0.1` / `localhost` because both containers share the pod network namespace +- ordering hints for startup, while explicitly noting that `depends_on` does not guarantee readiness + +Use this when shared networking and a grouped lifecycle make the deployment easier to operate. + +## Pod decision rule + +Choose the simplest topology that preserves the source deployment intent. + +Prefer a single `.pod` for multi-container applications when practical. + +If the project is a simple single-container deployment with no real need for pod semantics, a standalone `.container` is acceptable. + +If shared networking, shared published ports, or tightly coupled service lifecycle make pod semantics useful, prefer one or more `.pod` units. + +If one pod is not practical because of port conflicts or clearly incompatible groupings, split the result into a small number of pods rather than forcing an awkward topology. + +For large application stacks with optional services, ask the user to choose the desired service set before generating a minimized result. diff --git a/references/deployment-notes.md b/references/deployment-notes.md new file mode 100644 index 0000000..315e830 --- /dev/null +++ b/references/deployment-notes.md @@ -0,0 +1,55 @@ +# Deployment Notes + +Use this file when the user wants deployment-ready instructions alongside generated Quadlet units. + +## Directory choice + +### Rootless + +- primary default: `~/.config/containers/systemd/` +- user-scoped management commands use `systemctl --user` + +### Rootful + +- primary default: `/etc/containers/systemd/` +- system-scoped management commands use `systemctl` + +See `podman-systemd.unit.5.md` for the full search-path matrix. + +## Rootless operational notes + +- Bind mounts may hit UID/GID mismatches. +- For pod-based deployments that should preserve host ownership semantics, consider `UserNS=keep-id` on `[Pod]` when appropriate. +- If the service must survive logout, mention lingering: + +```bash +sudo loginctl enable-linger +``` + +## Paths and bind mounts + +- Ensure bind-mount source directories exist before first start. +- Normalize relative source paths against the source Compose file directory or the directory the user specifies. +- Emit absolute host paths in generated Quadlet files when using bind mounts. +- Explain the resolved absolute path if the source used `./...`. + +## Recommended service defaults + +Depending on the workload, consider adding: + +```ini +[Service] +Restart=always +TimeoutStartSec=900 +``` + +Use the timeout especially when first start may need to pull large images or build locally. + +## Useful optional enhancements + +- `AutoUpdate=registry` for opt-in automatic image refresh workflows +- explicit `.volume` or `.network` units when the user wants declarative infrastructure instead of implicit Podman objects + +## Output language + +If you generate a README, deployment note, or operator-facing document as part of the migration, write it in the user's language unless the user explicitly asks for another language. diff --git a/references/env-strategy.md b/references/env-strategy.md new file mode 100644 index 0000000..84857f0 --- /dev/null +++ b/references/env-strategy.md @@ -0,0 +1,165 @@ +# Environment Strategy + +Use this file whenever the migration includes `.env`, `env_file`, Compose interpolation, or inline `-e` flags. + +## Goals + +- preserve source-of-truth for variables +- avoid leaking secrets into generated Quadlet files by default +- keep resulting units readable +- report missing variables explicitly +- reduce large upstream env templates into a small set of user decisions + +## Default rules + +The agent should actively interpret the env template and its comments. Do not offload the entire env review back to the user. + +### Prefer `Environment=` when + +- there are only a few variables +- values are stable and not sensitive +- keeping everything in one file materially improves readability + +### Prefer `EnvironmentFile=` when + +- the source already uses `.env` or `env_file` +- variables are numerous +- variables contain secrets or deployment-specific values +- the same env file is shared by multiple services + +## Sensitive-value heuristic + +Treat names containing these substrings as sensitive unless the user tells you otherwise: + +- `PASSWORD` +- `TOKEN` +- `SECRET` +- `KEY` +- `PRIVATE` +- `PASS` + +Default behavior: + +- do not inline them in `Environment=` +- keep them in `EnvironmentFile=` or generate a placeholder sample file instead + +## Compose interpolation + +Common forms: + +- `${VAR}` +- `${VAR:-default}` +- `${VAR-default}` + +Strategy: + +- if the actual value source is present, resolve it and document where it came from +- if only a default is available, note that the value is default-derived +- if the variable is missing, list it as unresolved + +Do not fabricate values. + +## Agent responsibility + +When the source project ships a large `.env.example` or multiple env templates: + +- read the comments and deployment docs yourself +- determine which values can safely stay at documented defaults +- determine which values are true deployment decisions and must be confirmed with the user +- prepare a candidate `.env` or env delta instead of asking the user to read the whole template manually + +The user should only need to answer the small number of high-impact questions that cannot be discovered locally. + +## Minimal examples + +### Inline stable values + +Source intent: + +```yaml +environment: + APP_ENV: production + APP_PORT: "8080" +``` + +Reasonable result shape: + +```ini +[Container] +Environment=APP_ENV=production +Environment=APP_PORT=8080 +``` + +Use this when there are only a few non-sensitive structural values. + +### Preserve env-file workflow + +Source intent: + +```yaml +env_file: + - .env +``` + +Reasonable result shape: + +```ini +[Container] +EnvironmentFile=/opt/myapp/.env +``` + +Use this when the source already relies on an env file, especially for secrets or many variables. + +### Large template reduced to a candidate env + +Source intent: + +- upstream ships `.env.example` +- only a few values are true deployment decisions + +Recommended behavior: + +- keep documented defaults that are safe to preserve +- ask the user only for high-impact values such as domain, storage path, or database password +- generate a candidate `.env` or env delta with clear placeholders for the unresolved items + +## Output patterns + +### Small inline set + +```ini +[Container] +Environment=APP_ENV=production +Environment=APP_PORT=8080 +``` + +### External env file + +```ini +[Container] +EnvironmentFile=/opt/myapp/myapp.env +``` + +### Mixed pattern + +Use this when a few values are structural and the rest are secret or deployment-specific. + +```ini +[Container] +Environment=APP_ENV=production +EnvironmentFile=/opt/myapp/myapp.env +``` + +## Missing-variable reporting + +When variables cannot be resolved, report them as a concrete checklist. + +Example: + +- missing `DB_PASSWORD` +- missing `IMMICH_VERSION` +- missing `UPLOAD_LOCATION` + +If the user asks for scaffolding, generate a sample env file with obvious placeholders. + +Even when the user does not explicitly ask for scaffolding, produce a candidate env result when that materially advances the migration. diff --git a/references/github-repo-intake.md b/references/github-repo-intake.md new file mode 100644 index 0000000..f001dfb --- /dev/null +++ b/references/github-repo-intake.md @@ -0,0 +1,57 @@ +# GitHub Repository Intake + +Use this file when the user provides a GitHub repository URL and expects you to find the deployment inputs yourself. + +## Goal + +Discover the canonical self-hosting assets before attempting any Quadlet conversion. + +## Discovery order + +1. Read the repository `README.md`. +2. Look for self-hosting instructions and explicit references to Compose files. +3. If documentation names a path, follow that path first. +4. Search the repository tree for likely deployment files: + - `docker-compose.yaml` + - `docker-compose.yml` + - `compose.yaml` + - `compose.yml` + - `.env.example` + - `.env.sample` + - `env.example` + - `middleware.env.example` +5. Inspect likely deployment directories when needed: + - `docker/` + - `deploy/` + - `ops/` + - `infra/` + - `examples/` + - `.devcontainer/` +6. Read deployment-specific README files in those directories. +7. Identify helper scripts that generate or sync compose files. + +## What to extract + +- canonical compose file path +- companion env template path +- additional compose files used for middleware or optional services +- whether the compose file is generated +- whether the source relies on profiles +- whether startup requires preparatory steps such as copying `.env.example` to `.env` + +## Heuristics + +- Prefer the path explicitly linked from the main README over a randomly discovered file. +- Do not hardcode assumptions like "the deployment entry point is always under `docker/`". +- If the repo has both a template and a generated compose file, treat the generated file as the runnable source and the template as explanatory context. +- If profiles control optional databases or vector stores, decide which profile set the user actually wants before generating Quadlet. +- If env management is mandatory, preserve that pattern rather than flattening hundreds of variables into inline `Environment=` values. +- If several candidate compose files exist, explain which one you selected and why. + +## Migration posture for GitHub-sourced projects + +When converting a GitHub-hosted project, report: + +- which files you chose as source of truth +- which optional files or profiles you ignored +- which variables still require user decisions diff --git a/references/podman-systemd.unit.5.md b/references/podman-systemd.unit.5.md new file mode 100644 index 0000000..b500cdd --- /dev/null +++ b/references/podman-systemd.unit.5.md @@ -0,0 +1,2556 @@ +% podman-systemd.unit 5 + +## NAME + +podman\-systemd.unit - systemd units using Podman Quadlet + +## SYNOPSIS + +*name*.container, *name*.volume, *name*.network, *name*.kube *name*.image, *name*.build *name*.pod, *name*.artifact + +### Podman rootful unit search path + +Quadlet files for the root user can be placed in the following directories ordered in precedence. Meaning duplicate named quadlets found under /run take precedence over ones in /etc, as well as those in /usr: + +Temporary quadlets, usually used for testing: + +* /run/containers/systemd/ + +System administrator's defined quadlets: + +* /etc/containers/systemd/ + +Distribution defined quadlets: + +* /usr/share/containers/systemd/ + +### Podman rootless unit search path + +Quadlet files for non-root users can be placed in the following directories: + + * $XDG_RUNTIME_DIR/containers/systemd/ + * $XDG_CONFIG_HOME/containers/systemd/ or ~/.config/containers/systemd/ + * /etc/containers/systemd/users/${UID} + * /etc/containers/systemd/users/ + * /usr/share/containers/systemd/users/${UID} + * /usr/share/containers/systemd/users/ + +### Using symbolic links + +Quadlet supports using symbolic links for the base of the search paths and inside them. + +## DESCRIPTION + +Podman supports building and starting containers (and creating volumes) via systemd by using a +[systemd generator](https://www.freedesktop.org/software/systemd/man/systemd.generator.html). +These files are read during boot (and when `systemctl daemon-reload` is run) and generate +corresponding regular systemd service unit files. Both system and user systemd units are supported. +All options and tables available in standard systemd unit files are supported. For example, options defined in +the [Service] table and [Install] tables pass directly to systemd and are handled by it. +See systemd.unit(5) man page for more information. + +The Podman generator reads the search paths above and reads files with the extensions `.container` +`.volume`, `.network`, `.build`, `.pod`, `.kube`, and `.artifact`, and for each file generates a similarly named `.service` file. Be aware that +existing vendor services (i.e., in `/usr/`) are replaced if they have the same name. The generated unit files can +be started and managed with `systemctl` like any other systemd service. `systemctl {--user} list-unit-files` +lists existing unit files on the system. To list unit files of a user who has `/sbin/nologin` as a login shell, +run `sudo systemctl --machine username@ --user list-unit-files`. + +The Podman files use the same format as [regular systemd unit files](https://www.freedesktop.org/software/systemd/man/systemd.syntax.html). +Each file type has a custom section (for example, `[Container]`) that is handled by Podman, and all +other sections are passed on untouched, allowing the use of any normal systemd configuration options +like dependencies or cgroup limits. + +The source files also support drop-ins in the same [way systemd does](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html). +For a given source file (`foo.container`), the corresponding `.d` directory (`foo.container.d`) will +be scanned for files with a `.conf` extension, which are then merged into the base file in alphabetical +order. Top-level type drop-ins (`container.d`) will also be included. If the unit contains dashes ("-") +in the name (`foo-bar-baz.container`), then the drop-in directories generated by truncating the name after +the dash are searched as well (`foo-.container.d` and `foo-bar-.container.d`). Drop-in files with the same name +further down the hierarchy override those further up (`foo-bar-baz.container.d/10-override.conf` overrides +`foo-bar-.container.d/10-override.conf`, which overrides `foo-.service.d/10-override.conf`, which overrides +`container.d/10-override.conf`). The format of these drop-in files is the same as the base file. This is useful +to alter or add configuration settings for a unit, without having to modify unit files. + +For rootless containers, when administrators place Quadlet files in the +/etc/containers/systemd/users or /usr/share/containers/users directories, +all users' sessions execute the Quadlet when the login session begins. +If the administrator places a Quadlet file in the +/etc/containers/systemd/users/${UID}/ or /usr/share/containers/users/${UID} +directory, then only the user with the matching UID executes the Quadlet +when the login session gets started. For unit files placed in subdirectories within +/etc/containers/systemd/user/${UID}/, /usr/share/containers/users/${UID} and +the other user unit search paths, Quadlet will recursively search and run the +unit files present in these subdirectories. + +Note that Quadlet units do not support running as a non-root user by defining the +[User, Group](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#User=), +or [DynamicUser](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#DynamicUser=) +systemd options. If you want to run a rootless Quadlet, you will need to create the user +and add the unit file to one of the above rootless unit search paths. + +When a Quadlet unit starts, Podman may need to pull or build container images, which can take significantly longer +than systemd's default 90-second service startup limit. If this causes the unit to fail, you can either pre-pull the +required images or increase the service's startup timeout using the *TimeoutStartSec* option. Keep in mind, however, +that for units that specify `Type=oneshot`, the startup timeout is disabled by default (set to infinity), so +*TimeoutStartSec* must be explicitly configured if a timeout is desired. For further details on *TimeoutStartSec*, see `systemd.service(5)`. + +Adding the following snippet to a Quadlet file extends the startup timeout to 15 minutes. + +``` +[Service] +TimeoutStartSec=900 +``` + +Quadlet requires the use of cgroup v2, use `podman info --format {{.Host.CgroupsVersion}}` to check on the system. + +### Service Type + +By default, the `Type` field of the `Service` section of the Quadlet file does not need to be set. +Quadlet will set it to `notify` for `.container` and `.kube` files, +`forking` for `.pod` files, and `oneshot` for `.volume`, `.network`, `.build`, `.image`, and `.artifact` files. + +However, `Type` may be explicitly set to `oneshot` for `.container` and `.kube` files when no containers are expected +to run once `podman` exits. + +When setting `Type=oneshot`, it is recommended to also set `RemainAfterExit=yes` to prevent the service state +from becoming `inactive (dead)`. However, when activating a service via a timer unit, having `RemainAfterExit=yes` +leaves the job in a "started" state which prevents subsequent activations by the timer. For more information, see the +`systemd.service(5)` man page. + +Examples for such cases: +- `.container` file with an image that exits after their entrypoint has finished + +- `.kube` file pointing to a Kubernetes Yaml file that does not define any containers. E.g. PVCs only + +### Enabling unit files + +The services created by Podman are considered transient by systemd, which means they don't have the same +persistence rules as regular units. In particular, it is not possible to `systemctl enable` them +in order for them to become automatically enabled on the next boot. + +To compensate for this, the generator manually applies the `[Install]` section of the container definition +unit files during generation, in the same way `systemctl enable` does when run later. + +For example, to start a container on boot, add something like this to the file: + +``` +[Install] +WantedBy=default.target +``` + +Currently, only the `Alias`, `WantedBy`, `RequiredBy`, and `UpheldBy` keys are supported. + +The Install section can be part of the main file, or it can be in a +separate drop-in file as described above. The latter allows you to +install an non-enabled unit and then later enabling it by installing +the drop-in. + +### Template files + +Systemd supports a concept of [template files](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#Service%20Templates). +They are units with names of the form "basename@instancename.service" +when they are running, but that can be instantiated multiple times +from a single "basename@.service" file. The individual instances can +also be different by using drop-in files with the full instance name. + +Quadlets support these in two ways. First of all, a quadlet unit with +a template form will generate a systemd service with a template form, +and the template systemd service can be used as a regular template. +For example, "foo@.container" will generate "foo@.service" and you can +then "systemctl start foo@bar.service". + +Secondly, if you make a symlink like "foo@instance.container", that +will generate an instantiated template file. When generating this file +quadlet will read drop-in files both from the instanced directory +(foo@instance.container.d) and the template directory +(foo@.container.d). This allows customization of individual instances. + +Instanced template files (like `foo@bar.container`) can be enabled +just like non-templated ones. However, templated ones +(`foo@.container`) are different, because they need to be +instantiated. If the `[Install]` section contains a `DefaultInstance=` +key, then that instance will be enabled, but if not, nothing will +happen and the options will only be used as the default for units +that are instantiated using symlinks. + +An example template file `sleep@.container` might look like this: + +``` +[Unit] +Description=A templated sleepy container + +[Container] +Image=quay.io/fedora/fedora +Exec=sleep %i + +[Service] +# Restart service when sleep finishes +Restart=always + +[Install] +WantedBy=multi-user.target +DefaultInstance=100 +``` + +If this is installed, then on boot there will be a `sleep@100.service` +running that sleeps for 100 seconds. You can then do something like +`systemctl start sleep@50.service` to start another instance that +sleeps 50 seconds, or alternatively another service can start it via a +dependency like `Wants=sleep@50.service`. + +In addition, if you do `ln -s sleep@.container sleep@10.container` you +will also have a 10 second sleep running at boot. And, if you want +that particular instance to be running with another image, you can +create a drop-in file like `sleep@10.container.d/10-image.conf`: +``` +[Container] +Image=quay.io/centos/centos +``` + +#### Referencing other template Quadlets + +It often occurs that you may want to reference another template Quadlet +from your Quadlet. For example, you may want each instance of `foo@.container` +to mount a distinct volume. In this case you can create a template Quadlet +`foo-data@.volume` (the name is arbitrary) and reference it in `foo@.container`: + +`foo-data@.volume`: +``` +[Volume] +# Optional: without an explicit VolumeName, Quadlet auto-generates one with a +# "systemd-" prefix (e.g. systemd-foo-data-%i for foo-data@.volume). +# This does not affect how you reference this Quadlet from other Quadlets. +VolumeName=my-name-%i +``` + +`foo@.container`: +``` +[Container] +Volume=foo-data@.volume:/mnt/path +``` + +Note that we reference the template name `foo-data@.volume` instead of +the instance name `foo-data@%i.volume`. Quadlet will read the template file +and determine the correct volume name (with the systemd specifier) for +the `podman run` command in the generated `.service` file. In this example, +the `ExecStart` generated by Quadlet would look something like this: + +``` +ExecStart=/usr/bin/podman run ... -v my-name-%i:/mnt/path ... +``` + +### Relative paths + +In order to support Systemd specifiers, Quadlet does not resolve relative paths that start with `%`. +To resolve such a path, prepend it with `./`. + +For example, instead of `EnvironmentFile=%n/env` use `EnvironmentFile=./%n/env` + +### Debugging unit files + +After placing the unit file in one of the unit search paths (mentioned +above), you can start it with `systemctl start {--user}`. If it fails +with "Failed to start example.service: Unit example.service not +found.", then it is possible that you used incorrect syntax or you +used an option from a newer version of Podman Quadlet and the +generator failed to create a service file. + +View the generated files and/or error messages with: +``` +/usr/lib/systemd/system-generators/podman-system-generator {--user} --dryrun +``` + +Alternatively, show only the errors with: +``` +systemd-analyze {--user} --generators=true verify example.service +``` + +That command also performs additional checks on the generated service unit. +For details, see systemd-analyze(1) man page. + +#### Debugging a limited set of unit files + +If you would like to debug a limited set of unit files, you can copy them to a separate directory and set the +`QUADLET_UNIT_DIRS` environment variable to this directory when running the command below: + +``` +QUADLET_UNIT_DIRS= /usr/lib/systemd/system-generators/podman-system-generator {--user} --dryrun +``` + +This will instruct Quadlet to look for units in this directory instead of the common ones and by +that limit the output to only the units you are debugging. + +### Implicit network dependencies + +Quadlet will add dependencies on `network-online.target` (as root) or `podman-user-wait-network-online.service` +(as user) by adding `After=` and `Wants=` properties to the unit. This is to ensure that the network is reachable +if an image needs to be pulled and by the time the container is started. + +The special case `podman-user-wait-network-online.service` unit is needed as user because user units are unable to wait +for system (root) units so `network-online.target` doesn't do anything there and is instead ignored. As this caused +a significant amount of issues we decided to work around this with our own special purpose unit that simply checks if +the `network-online.target` unit is active with `systemctl is-active network-online.target`. + +This behavior can be disabled by adding `DefaultDependencies=false` in the `Quadlet` section. +Note, the _systemd_ `[Unit]` section has an option with the same name but a different meaning. + +### Dependency between Quadlet units + +Quadlet will automatically translate dependencies, specified in the keys +`Wants`, `Requires`, `Requisite`, `BindsTo`, `PartOf`, `Upholds`, `Conflicts`, `Before` and `After` +of the `[Unit]` section, between different Quadlet units. + +For example the `fedora.container` unit below specifies a dependency on the `basic.container` unit. +``` +[Unit] +After=basic.container +Requires=basic.container + +[Container] +Image=registry.fedoraproject.org/fedora:41 +``` + +### Setting resource names + +Quadlet units allow setting the names of the created resources +(e.g. `VolumeName` for `.volume` units or `PodName` for `.pod` units). + +Note that using systemd specifiers that reference the generated service unit (e.g. `$N`) +breaks Quadlet's ability to link between resources as they are translated differently in each service + +## Container units [Container] + +Container units are named with a `.container` extension and contain a `[Container]` section describing +the container that is run as a service. The resulting service file contains a line like +`ExecStart=podman run … image-name`, and most of the keys in this section control the command-line +options passed to Podman. However, some options also affect the details of how systemd is set up to run and +interact with the container. + +By default, the Podman container has the same name as the unit, but with a `systemd-` prefix, i.e. +a `$name.container` file creates a `$name.service` unit and a `systemd-$name` Podman container. The +`ContainerName` option allows for overriding this default name with a user-provided one. + +There is only one required key, `Image`, which defines the container image the service runs. + +Valid options for `[Container]` are listed below: + +| **[Container] options** | **podman run equivalent** | +|--------------------------------------|------------------------------------------------------| +| AddCapability=CAP | --cap-add CAP | +| AddDevice=/dev/foo | --device /dev/foo | +| AddHost=example\.com:192.168.10.11 | --add-host example.com:192.168.10.11 | +| Annotation="XYZ" | --annotation "XYZ" | +| AppArmor="alternate-profile" | --security-opt apparmor=alternate-profile | +| AutoUpdate=registry | --label "io.containers.autoupdate=registry" | +| CgroupsMode=no-conmon | --cgroups=no-conmon | +| ContainerName=name | --name name | +| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | +| DNS=192.168.55.1 | --dns=192.168.55.1 | +| DNSOption=ndots:1 | --dns-option=ndots:1 | +| DNSSearch=example.com | --dns-search example.com | +| DropCapability=CAP | --cap-drop=CAP | +| Entrypoint=/foo.sh | --entrypoint=/foo.sh | +| Environment=foo=bar | --env foo=bar | +| EnvironmentFile=/tmp/env | --env-file /tmp/env | +| EnvironmentHost=true | --env-host | +| Exec=/usr/bin/command | Command after image specification - /usr/bin/command | +| ExposeHostPort=50-59 | --expose 50-59 | +| GIDMap=0:10000:10 | --gidmap=0:10000:10 | +| GlobalArgs=--log-level=debug | --log-level=debug | +| Group=1234 | --user UID:1234 | +| GroupAdd=keep-groups | --group-add=keep-groups | +| HealthCmd=/usr/bin/command | --health-cmd=/usr/bin/command | +| HealthInterval=2m | --health-interval=2m | +| HealthLogDestination=/foo/log | --health-log-destination=/foo/log | +| HealthMaxLogCount=5 | --health-max-log-count=5 | +| HealthMaxLogSize=500 | --health-max-log-size=500 | +| HealthOnFailure=kill | --health-on-failure=kill | +| HealthRetries=5 | --health-retries=5 | +| HealthStartPeriod=1m | --health-start-period=1m | +| HealthStartupCmd=command | --health-startup-cmd=command | +| HealthStartupInterval=1m | --health-startup-interval=1m | +| HealthStartupRetries=8 | --health-startup-retries=8 | +| HealthStartupSuccess=2 | --health-startup-success=2 | +| HealthStartupTimeout=1m33s | --health-startup-timeout=1m33s | +| HealthTimeout=20s | --health-timeout=20s | +| HostName=example.com | --hostname example.com | +| HttpProxy=true | --http-proxy=true | +| Image=ubi8 | Image specification - ubi8 | +| IP=192.5.0.1 | --ip 192.5.0.1 | +| IP6=2001:db8::1 | --ip6 2001:db8::1 | +| Label="XYZ" | --label "XYZ" | +| LogDriver=journald | --log-driver journald | +| LogOpt=path=/var/log/mykube\.json | --log-opt path=/var/log/mykube\.json | +| Mask=/proc/sys/foo\:/proc/sys/bar | --security-opt mask=/proc/sys/foo:/proc/sys/bar | +| Memory=20g | --memory 20g | +| Mount=type=... | --mount type=... | +| Network=host | --network host | +| NetworkAlias=name | --network-alias name | +| NoNewPrivileges=true | --security-opt no-new-privileges | +| Notify=true | --sdnotify container | +| PidsLimit=10000 | --pids-limit 10000 | +| Pod=pod-name | --pod=pod-name | +| PodmanArgs=--publish 8080:80 | --publish 8080:80 | +| PublishPort=8080:80 | --publish 8080:80 | +| Pull=never | --pull never | +| ReadOnly=true | --read-only | +| ReadOnlyTmpfs=true | --read-only-tmpfs | +| ReloadCmd=/usr/bin/command | Add ExecReload and run exec with the value | +| ReloadSignal=SIGHUP | Add ExecReload and run kill with the signal | +| Retry=5 | --retry=5 | +| RetryDelay=5s | --retry-delay=5s | +| Rootfs=/var/lib/rootfs | --rootfs /var/lib/rootfs | +| RunInit=true | --init | +| SeccompProfile=/tmp/s.json | --security-opt seccomp=/tmp/s.json | +| Secret=secret | --secret=secret[,opt=opt ...] | +| SecurityLabelDisable=true | --security-opt label=disable | +| SecurityLabelFileType=usr_t | --security-opt label=filetype:usr_t | +| SecurityLabelLevel=s0:c1,c2 | --security-opt label=level:s0:c1,c2 | +| SecurityLabelNested=true | --security-opt label=nested | +| SecurityLabelType=spc_t | --security-opt label=type:spc_t | +| ServiceName=name | Name the systemd unit `name.service` | +| ShmSize=100m | --shm-size=100m | +| StartWithPod=true | If Pod= is defined, container is started by pod | +| StopSignal=SIGINT | --stop-signal=SIGINT | +| StopTimeout=20 | --stop-timeout=20 | +| SubGIDMap=gtest | --subgidname=gtest | +| SubUIDMap=utest | --subuidname=utest | +| Sysctl=name=value | --sysctl=name=value | +| Timezone=local | --tz local | +| Tmpfs=/work | --tmpfs /work | +| UIDMap=0:10000:10 | --uidmap=0:10000:10 | +| Ulimit=nofile=1000:10000 | --ulimit nofile=1000:10000 | +| Unmask=ALL | --security-opt unmask=ALL | +| User=bin | --user bin | +| UserNS=keep-id:uid=200,gid=210 | --userns keep-id:uid=200,gid=210 | +| Volume=/source:/dest | --volume /source:/dest | +| WorkingDir=$HOME | --workdir $HOME | + +Description of `[Container]` section are: + +### `AddCapability=` + +Add these capabilities, in addition to the default Podman capability set, to the container. + +This is a space separated list of capabilities. This key can be listed multiple times. + +For example: +``` +AddCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER +``` + +### `AddDevice=` + +Adds a device node from the host into the container. The format of this is +`HOST-DEVICE[:CONTAINER-DEVICE][:PERMISSIONS]`, where `HOST-DEVICE` is the path of +the device node on the host, `CONTAINER-DEVICE` is the path of the device node in +the container, and `PERMISSIONS` is a list of permissions combining 'r' for read, +'w' for write, and 'm' for mknod(2). The `-` prefix tells Quadlet to add the device +only if it exists on the host. + +This key can be listed multiple times. + +### `AddHost=` + +Add host-to-IP mapping to /etc/hosts. +The format is `hostname:ip`. + +Equivalent to the Podman `--add-host` option. +This key can be listed multiple times. + +### `Annotation=` + +Set one or more OCI annotations on the container. The format is a list of `key=value` items, +similar to `Environment`. + +This key can be listed multiple times. + +### `AppArmor=` + +Sets the apparmor confinement profile for the container. A value of `unconfined` turns off apparmor confinement. + +### `AutoUpdate=` + +Indicates whether the container will be auto-updated ([podman-auto-update(1)](podman-auto-update.1.md)). The following values are supported: + +* `registry`: Requires a fully-qualified image reference (e.g., quay.io/podman/stable:latest) to be used to create the container. This enforcement is necessary to know which image to actually check and pull. If an image ID was used, Podman does not know which image to check/pull anymore. + +* `local`: Tells Podman to compare the image a container is using to the image with its raw name in local storage. If an image is updated locally, Podman simply restarts the systemd unit executing the container. + +### `CgroupsMode=` + +The cgroups mode of the Podman container. Equivalent to the Podman `--cgroups` option. + +By default, the cgroups mode of the container created by Quadlet is `split`, +which differs from the default (`enabled`) used by the Podman CLI. + +If the container joins a pod (i.e. `Pod=` is specified), you may want to change this to +`no-conmon` or `enabled` so that pod level cgroup resource limits can take effect. + +### `ContainerName=` + +The (optional) name of the Podman container. If this is not specified, the default value +of `systemd-%N` is used, which is the same as the service name but with a `systemd-` +prefix to avoid conflicts with user-managed containers. + +### `ContainersConfModule=` + +Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option. + +This key can be listed multiple times. + +### `DNS=` + +Set network-scoped DNS resolver/nameserver for containers in this network. + +This key can be listed multiple times. + +### `DNSOption=` + +Set custom DNS options. + +This key can be listed multiple times. + +### `DNSSearch=` + +Set custom DNS search domains. Use **DNSSearch=.** to remove the search domain. + +This key can be listed multiple times. + +### `DropCapability=` + +Drop these capabilities from the default podman capability set, or `all` to drop all capabilities. + +This is a space separated list of capabilities. This key can be listed multiple times. + +For example: +``` +DropCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER +``` + +### `Entrypoint=` + +Override the default ENTRYPOINT from the image. +Equivalent to the Podman `--entrypoint` option. +Specify multi option commands in the form of a JSON string. + +### `Environment=` + +Set an environment variable in the container. This uses the same format as +[services in systemd](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Environment=) +and can be listed multiple times. + +### `EnvironmentFile=` + +Use a line-delimited file to set environment variables in the container. +The path may be absolute or relative to the location of the unit file. +This key may be used multiple times, and the order persists when passed to `podman run`. + +### `EnvironmentHost=` + +Use the host environment inside of the container. + +### `Exec=` + +Additional arguments for the container; this has exactly the same effect as passing +more arguments after a `podman run ` invocation. + +The format is the same as for [systemd command lines](https://www.freedesktop.org/software/systemd/man/systemd.service.html#Command%20lines), +However, unlike the usage scenario for similarly-named systemd `ExecStart=` verb +which operates on the ambient root filesystem, it is very common for container +images to have their own `ENTRYPOINT` or `CMD` metadata which this interacts with. + +The default expectation for many images is that the image will include an `ENTRYPOINT` +with a default binary, and this field will add arguments to that entrypoint. + +Another way to describe this is that it works the same way as the [args field in a Kubernetes pod](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell). + +### `ExposeHostPort=` + +Exposes a port, or a range of ports (e.g. `50-59`), from the host to the container. Equivalent +to the Podman `--expose` option. + +This key can be listed multiple times. + +### `GIDMap=` + +Run the container in a new user namespace using the supplied GID mapping. +Equivalent to the Podman `--gidmap` option. + +This key can be listed multiple times. + +### `GlobalArgs=` + +This key contains a list of arguments passed directly between `podman` and `run` +in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `Group=` + +The (numeric) GID to run as inside the container. This does not need to match the GID on the host, +which can be modified with `UserNS`, but if that is not specified, this GID is also used on the host. + +Note: when both `User=` and `Group=` are specified, they are combined into a single `--user USER:GROUP` +argument passed to Podman. Using `Group=` without `User=` will result in an error. + +### `GroupAdd=` + +Assign additional groups to the primary user running within the container process. Also supports the `keep-groups` special flag. +Equivalent to the Podman `--group-add` option. + +### `HealthCmd=` + +Set or alter a healthcheck command for a container. A value of none disables existing healthchecks. +Equivalent to the Podman `--health-cmd` option. + +### `HealthInterval=` + +Set an interval for the healthchecks. An interval of disable results in no automatic timer setup. +Equivalent to the Podman `--health-interval` option. + +### `HealthLogDestination=` + +Set the destination of the HealthCheck log. Directory path, local or events_logger (local use container state file) +(Default: local) +Equivalent to the Podman `--health-log-destination` option. + +* `local`: (default) HealthCheck logs are stored in overlay containers. (For example: `$runroot/healthcheck.log`) +* `directory`: creates a log file named `-healthcheck.log` with HealthCheck logs in the specified directory. +* `events_logger`: The log will be written with logging mechanism set by events_logger. It also saves the log to a default directory, for performance on a system with a large number of logs. + +### `HealthMaxLogCount=` + +Set maximum number of attempts in the HealthCheck log file. ('0' value means an infinite number of attempts in the log file) +(Default: 5 attempts) +Equivalent to the Podman `--Health-max-log-count` option. + +### `HealthMaxLogSize=` + +Set maximum length in characters of stored HealthCheck log. ("0" value means an infinite log length) +(Default: 500 characters) +Equivalent to the Podman `--Health-max-log-size` option. + +### `HealthOnFailure=` + +Action to take once the container transitions to an unhealthy state. +The "kill" action in combination integrates best with systemd. Once +the container turns unhealthy, it gets killed, and systemd restarts the +service. +Equivalent to the Podman `--health-on-failure` option. + +### `HealthRetries=` + +The number of retries allowed before a healthcheck is considered to be unhealthy. +Equivalent to the Podman `--health-retries` option. + +### `HealthStartPeriod=` + +The initialization time needed for a container to bootstrap. +Equivalent to the Podman `--health-start-period` option. + +### `HealthStartupCmd=` + +Set a startup healthcheck command for a container. +Equivalent to the Podman `--health-startup-cmd` option. + +### `HealthStartupInterval=` + +Set an interval for the startup healthcheck. An interval of disable results in no automatic timer setup. +Equivalent to the Podman `--health-startup-interval` option. + +### `HealthStartupRetries=` + +The number of attempts allowed before the startup healthcheck restarts the container. +Equivalent to the Podman `--health-startup-retries` option. + +### `HealthStartupSuccess=` + +The number of successful runs required before the startup healthcheck succeeds and the regular healthcheck begins. +Equivalent to the Podman `--health-startup-success` option. + +### `HealthStartupTimeout=` + +The maximum time a startup healthcheck command has to complete before it is marked as failed. +Equivalent to the Podman `--health-startup-timeout` option. + +### `HealthTimeout=` + +The maximum time allowed to complete the healthcheck before an interval is considered failed. +Equivalent to the Podman `--health-timeout` option. + +### `HostName=` + +Sets the host name that is available inside the container. +Equivalent to the Podman `--hostname` option. + +### `HttpProxy=` + +Controls whether proxy environment variables (http_proxy, https_proxy, ftp_proxy, no_proxy) are passed from the Podman process into the container during image pulls and builds. + +Set to `true` to enable proxy inheritance (default Podman behavior) or `false` to disable it. +This option is particularly useful on systems that require proxy configuration for internet access but don't want proxy settings passed to the container runtime. + +Equivalent to the Podman `--http-proxy` option. + +### `Image=` + +The image to run in the container. +It is recommended to use a fully qualified image name rather than a short name, both for +performance and robustness reasons. + +The format of the name is the same as when passed to `podman pull`. So, it supports using +`:tag` or digests to guarantee the specific image version. + +Special Cases: + +* If the `name` of the image ends with `.image`, Quadlet will use the image pulled by the corresponding `.image` file, and the generated systemd service contains a dependency on the `$name-image.service` (or the service name set in the .image file). Note that the corresponding `.image` file must exist. +* If the `name` of the image ends with `.build`, Quadlet will use the image built by the corresponding `.build` file, and the generated systemd service contains a dependency on the `$name-build.service`. Note: the corresponding `.build` file must exist. + +### `IP=` + +Specify a static IPv4 address for the container, for example **10.88.64.128**. +Equivalent to the Podman `--ip` option. + +### `IP6=` + +Specify a static IPv6 address for the container, for example **fd46:db93:aa76:ac37::10**. +Equivalent to the Podman `--ip6` option. + +### `Label=` + +Set one or more OCI labels on the container. The format is a list of `key=value` items, +similar to `Environment`. + +This key can be listed multiple times. + +### `LogDriver=` + +Set the log-driver used by Podman when running the container. +Equivalent to the Podman `--log-driver` option. + +### `LogOpt=` + +Set the log-opt (logging options) used by Podman when running the container. +Equivalent to the Podman `--log-opt` option. +This key can be listed multiple times. + +### `Mask=` + +Specify the paths to mask separated by a colon. `Mask=/path/1:/path/2`. A masked path cannot be accessed inside the container. + +### `Memory=` + +Specify the amount of memory for the container. + +### `Mount=` + +Attach a filesystem mount to the container. +This is equivalent to the Podman `--mount` option, and +generally has the form `type=TYPE,TYPE-SPECIFIC-OPTION[,...]`. + +Special cases: + +* For `type=volume`, if `source` ends with `.volume`, the Podman named volume generated by the corresponding `.volume` file is used. +* For `type=image`, if `source` ends with `.image`, the image generated by the corresponding `.image` file is used. + +In both cases, the generated systemd service will contain a dependency on the service generated for the corresponding unit. Note: the corresponding `.volume` or `.image` file must exist. + +This key can be listed multiple times. + +### `Network=` + +Specify a custom network for the container. This has the same format as the `--network` option +to `podman run`. For example, use `host` to use the host network in the container, or `none` to +not set up networking in the container. + +Special cases: + +* If the `name` of the network ends with `.network`, a Podman network called +`systemd-$name` is used, and the generated systemd service contains +a dependency on the `$name-network.service`. Such a network can be automatically +created by using a `$name.network` Quadlet file. Note: the corresponding `.network` file must exist. + +* If the `name` ends with `.container`, +the container will reuse the network stack of another container created by `$name.container`. +The generated systemd service contains a dependency on `$name.service`. Note: the corresponding `.container` file must exist. + +This key can be listed multiple times. + +### `NetworkAlias=` + +Add a network-scoped alias for the container. This has the same format as the `--network-alias` +option to `podman run`. Aliases can be used to group containers together in DNS resolution: for +example, setting `NetworkAlias=web` on multiple containers will make a DNS query for `web` resolve +to all the containers with that alias. + +This key can be listed multiple times. + +### `NoNewPrivileges=` (defaults to `false`) + +If enabled, this disables the container processes from gaining additional privileges via things like +setuid and file capabilities. + +### `Notify=` (defaults to `false`) + +By default, Podman is run in such a way that the systemd startup notify command is handled by +the container runtime. In other words, the service is deemed started when the container runtime +starts the child in the container. However, if the container application supports +[sd_notify](https://www.freedesktop.org/software/systemd/man/sd_notify.html), then setting +`Notify` to true passes the notification details to the container allowing it to notify +of startup on its own. + +In addition, setting `Notify` to `healthy` will postpone startup notifications until such time as +the container is marked healthy, as determined by Podman healthchecks. Note that this requires +setting up a container healthcheck, see the `HealthCmd` option for more. + +### `PidsLimit=` + +Tune the container's pids limit. +This is equivalent to the Podman `--pids-limit` option. + +### `Pod=` + +Specify a Quadlet `.pod` unit to link the container to. +The value must take the form of `.pod` and the `.pod` unit must exist. + +Quadlet will add all the necessary parameters to link between the container and the pod and between their corresponding services. + + +### `PodmanArgs=` + +This key contains a list of arguments passed directly to the end of the `podman run` command +in the generated file (right before the image name in the command line). It can be used to +access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `PublishPort=` + +Exposes a port, or a range of ports (e.g. `50-59`), from the container to the host. Equivalent +to the Podman `--publish` option. The format is similar to the Podman options, which is of +the form `ip:hostPort:containerPort`, `ip::containerPort`, `hostPort:containerPort` or +`containerPort`, where the number of host and container ports must be the same (in the case +of a range). The protocol can be provided at the end, e.g., `hostPort:containerPort/tcp`. +Valid protocols are `tcp` and `udp`; the `sctp` protocol is supported only for rootful containers. + +If the IP is set to 0.0.0.0 or not set at all, the port is bound on all IPv4 addresses on +the host; use [::] for IPv6. + +Note that not listing a host port means that Podman automatically selects one, and it +may be different for each invocation of service. This makes that a less useful option. The +allocated port can be found with the `podman port` command. + +This key can be listed multiple times. + +### `Pull=` + +Set the image pull policy. +This is equivalent to the Podman `--pull` option + +### `ReadOnly=` (defaults to `false`) + +If enabled, makes the image read-only. + +### `ReadOnlyTmpfs=` (defaults to `true`) + +If ReadOnly is set to `true`, mount a read-write tmpfs on /dev, /dev/shm, /run, /tmp, and /var/tmp. + +### `ReloadCmd=` + +Add `ExecReload` line to the `Service` that runs ` podman exec` with this command in this container. + +In order to execute the reload run `systemctl reload ` + +Mutually exclusive with `ReloadSignal` + +### `ReloadSignal=` + +Add `ExecReload` line to the `Service` that runs `podman kill` with this signal which sends the signal to the main container process. + +In order to execute the reload run `systemctl reload ` + +Mutually exclusive with `ReloadCmd` + +### `Retry=` + +Number of times to retry the image pull when a HTTP error occurs. Equivalent to the Podman `--retry` option. + +### `RetryDelay=` + +Delay between retries. Equivalent to the Podman `--retry-delay` option. + +### `Rootfs=` + +The rootfs to use for the container. Rootfs points to a directory on the system that contains the content to be run within the container. This option conflicts with the `Image` option. + +The format of the rootfs is the same as when passed to `podman run --rootfs`, so it supports overlay mounts as well. + +Note: On SELinux systems, the rootfs needs the correct label, which is by default unconfined_u:object_r:container_file_t:s0. + +### `RunInit=` (defaults to `false`) + +If enabled, the container has a minimal init process inside the +container that forwards signals and reaps processes. + +### `SeccompProfile=` + +Set the seccomp profile to use in the container. If unset, the default podman profile is used. +Set to either the pathname of a JSON file, or `unconfined` to disable the seccomp filters. + +### `Secret=` + +Use a Podman secret in the container either as a file or an environment variable. +This is equivalent to the Podman `--secret` option and generally has the form `secret[,opt=opt ...]` + +### `SecurityLabelDisable=` + +Turn off label separation for the container. + +### `SecurityLabelFileType=` + +Set the label file type for the container files. + +### `SecurityLabelLevel=` + +Set the label process level for the container processes. + +### `SecurityLabelNested=` + +Allow SecurityLabels to function within the container. This allows separation of containers created within the container. + +### `SecurityLabelType=` + +Set the label process type for the container processes. + +### `ServiceName=` + +By default, Quadlet will name the systemd service unit using the name of the Quadlet. +Setting this key overrides this behavior by instructing Quadlet to use the provided name. + +Note, the name should not include the `.service` file extension + +### `ShmSize=` + +Size of /dev/shm. + +This is equivalent to the Podman `--shm-size` option and generally has the form `number[unit]` + +### `StartWithPod=` + +Start the container after the associated pod is created. Default to **true**. + +If `true`, container will be started/stopped/restarted alongside the pod. + +If `false`, the container will not be started when the pod starts. The container will be stopped with the pod. Restarting the pod will also restart the container as long as the container was also running before. + +Note, the container can still be started manually or through a target by configuring the `[Install]` section. The pod will be started as needed in any case. + +### `StopSignal=` + +Signal to stop a container. Default is **SIGTERM**. + +This is equivalent to the Podman `--stop-signal` option + +### `StopTimeout=` + +Seconds to wait before forcibly stopping the container. + +Note, this value should be lower than the actual systemd unit timeout to make sure the podman rm command is not killed by systemd. + +This is equivalent to the Podman `--stop-timeout` option + +### `SubGIDMap=` + +Run the container in a new user namespace using the map with name in the /etc/subgid file. +Equivalent to the Podman `--subgidname` option. + +### `SubUIDMap=` + +Run the container in a new user namespace using the map with name in the /etc/subuid file. +Equivalent to the Podman `--subuidname` option. + +### `Sysctl=` + +Configures namespaced kernel parameters for the container. The format is `Sysctl=name=value`. + +This is a space separated list of kernel parameters. This key can be listed multiple times. + +For example: +``` +Sysctl=net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.all.use_tempaddr=1 +``` + +### `Timezone=` (if unset uses system-configured default) + +The timezone to run the container in. + +### `Tmpfs=` + +Mount a tmpfs in the container. This is equivalent to the Podman `--tmpfs` option, and +generally has the form `CONTAINER-DIR[:OPTIONS]`. + +This key can be listed multiple times. + +### `UIDMap=` + +Run the container in a new user namespace using the supplied UID mapping. +Equivalent to the Podman `--uidmap` option. + +This key can be listed multiple times. + +### `Ulimit=` + +Ulimit options. Sets the ulimits values inside of the container. + +This key can be listed multiple times. + +### `Unmask=` + +Specify the paths to unmask separated by a colon. unmask=ALL or /path/1:/path/2, or shell expanded paths (/proc/*): + +If set to `ALL`, Podman will unmask all the paths that are masked or made read-only by default. + +The default masked paths are /proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux. + +The default paths that are read-only are /proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup. + +### `User=` + +The (numeric) UID to run as inside the container. This does not need to match the UID on the host, +which can be modified with `UserNS`, but if that is not specified, this UID is also used on the host. + +Note: when both `User=` and `Group=` are specified, they are combined into a single `--user USER:GROUP` +argument passed to Podman. + +### `UserNS=` + +Set the user namespace mode for the container. This is equivalent to the Podman `--userns` option and +generally has the form `MODE[:OPTIONS,...]`. + +### `Volume=` + +Mount a volume in the container. This is equivalent to the Podman `--volume` option, and +generally has the form `[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]`. + +If `SOURCE-VOLUME` starts with `.`, Quadlet resolves the path relative to the location of the unit file. + +Special case: + +* If `SOURCE-VOLUME` ends with `.volume`, a Podman named volume called `systemd-$name` is used as the source, and the generated systemd service contains a dependency on the `$name-volume.service`. Note that the corresponding `.volume` file must exist. + +This key can be listed multiple times. + +### `WorkingDir=` + +Working directory inside the container. + +The default working directory for running binaries within a container is the root directory (/). The image developer can set a different default with the WORKDIR instruction. This option overrides the working directory by using the -w option. + +## Pod units [Pod] + +Pod units are named with a `.pod` extension and contain a `[Pod]` section describing +the pod that is created and run as a service. The resulting service file contains a line like +`ExecStartPre=podman pod create …`, and most of the keys in this section control the command-line +options passed to Podman. + +By default, the Podman pod has the same name as the unit, but with a `systemd-` prefix, i.e. +a `$name.pod` file creates a `$name-pod.service` unit and a `systemd-$name` Podman pod. The +`PodName` option allows for overriding this default name with a user-provided one. + +The generated service defaults to `Restart=on-failure`. Note that with `ExitPolicy=stop` (the +default for Quadlet pods), the pod exits cleanly (exit code 0) when all its containers stop, so +`on-failure` will **not** trigger a restart in that case. To have the pod automatically restart +when containers exit, set `Restart=always` in the `[Service]` section of the `.pod` file. + +Valid options for `[Pod]` are listed below: + +| **[Pod] options** | **podman pod create equivalent** | +|-------------------------------------|----------------------------------------| +| AddHost=example\.com:192.168.10.11 | --add-host example.com:192.168.10.11 | +| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | +| DNS=192.168.55.1 | --dns=192.168.55.1 | +| DNSOption=ndots:1 | --dns-option=ndots:1 | +| DNSSearch=example.com | --dns-search example.com | +| ExitPolicy=stop | --exit-policy stop | +| GIDMap=0:10000:10 | --gidmap=0:10000:10 | +| GlobalArgs=--log-level=debug | --log-level=debug | +| HostName=name | --hostname=name | +| IP=192.5.0.1 | --ip 192.5.0.1 | +| IP6=2001:db8::1 | --ip6 2001:db8::1 | +| Label="XYZ" | --label "XYZ" | +| Network=host | --network host | +| NetworkAlias=name | --network-alias name | +| PodmanArgs=\-\-cpus=2 | --cpus=2 | +| PodName=name | --name=name | +| PublishPort=8080:80 | --publish 8080:80 | +| ServiceName=name | Name the systemd unit `name.service` | +| ShmSize=100m | --shm-size=100m | +| StopTimeout=20 | --time=20 | +| SubGIDMap=gtest | --subgidname=gtest | +| SubUIDMap=utest | --subuidname=utest | +| UIDMap=0:10000:10 | --uidmap=0:10000:10 | +| UserNS=keep-id:uid=200,gid=210 | --userns keep-id:uid=200,gid=210 | +| Volume=/source:/dest | --volume /source:/dest | + +Supported keys in the `[Pod]` section are: + +### `AddHost=` + +Add host-to-IP mapping to /etc/hosts. +The format is `hostname:ip`. + +Equivalent to the Podman `--add-host` option. +This key can be listed multiple times. + +### `ContainersConfModule=` + +Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option. + +This key can be listed multiple times. + +### `DNS=` + +Set network-scoped DNS resolver/nameserver for containers in this pod. + +This key can be listed multiple times. + +### `DNSOption=` + +Set custom DNS options. + +This key can be listed multiple times. + +### `DNSSearch=` + +Set custom DNS search domains. Use **DNSSearch=.** to remove the search domain. + +This key can be listed multiple times. + +### `ExitPolicy=` + +Set the exit policy of the pod when the last container exits. Default for quadlets is **stop**. + +To keep the pod active, set `ExitPolicy=continue`. + +### `GIDMap=` + +Create the pod in a new user namespace using the supplied GID mapping. +Equivalent to the Podman `--gidmap` option. + +This key can be listed multiple times. + +### `GlobalArgs=` + +This key contains a list of arguments passed directly between `podman` and `pod` +in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `HostName=` + +Set the pod’s hostname inside all containers. + +The given hostname is also added to the /etc/hosts file using the container’s primary IP address (also see the `--add-host` option). + +Equivalent to the Podman `--hostname` option. + +### `IP=` + +Specify a static IPv4 address for the pod, for example **10.88.64.128**. +Equivalent to the Podman `--ip` option. + +### `IP6=` + +Specify a static IPv6 address for the pod, for example **fd46:db93:aa76:ac37::10**. +Equivalent to the Podman `--ip6` option. + +### `Label=` + +Set one or more OCI labels on the pod. The format is a list of +`key=value` items, similar to `Environment`. + +This key can be listed multiple times. + +### `Network=` + +Specify a custom network for the pod. +This has the same format as the `--network` option to `podman pod create`. +For example, use `host` to use the host network in the pod, or `none` to not set up networking in the pod. + +Special case: + +* If the `name` of the network ends with `.network`, Quadlet will look for the corresponding `.network` Quadlet unit. If found, Quadlet will use the name of the Network set in the Unit, otherwise, `systemd-$name` is used. + +The generated systemd service contains a dependency on the service unit generated for that `.network` unit. Note: the corresponding `.network` file must exist. + +This key can be listed multiple times. + +### `NetworkAlias=` + +Add a network-scoped alias for the pod. This has the same format as the `--network-alias` option to +`podman pod create`. Aliases can be used to group containers together in DNS resolution: for +example, setting `NetworkAlias=web` on multiple containers will make a DNS query for `web` resolve +to all the containers with that alias. + +This key can be listed multiple times. + +### `PodmanArgs=` + +This key contains a list of arguments passed directly to the end of the `podman pod create` command +in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `PodName=` + +The (optional) name of the Podman pod. +If this is not specified, the default value is the same name as the unit, but with a `systemd-` prefix, +i.e. a `$name.pod` file creates a `systemd-$name` Podman pod to avoid conflicts with user-managed pods. + +Please note that pods and containers cannot have the same name. +So, if PodName is set, it must not conflict with any container. + +### `PublishPort=` + +Exposes a port, or a range of ports (e.g. `50-59`), from the pod to the host. Equivalent +to the Podman `--publish` option. The format is similar to the Podman options, which is of +the form `ip:hostPort:containerPort`, `ip::containerPort`, `hostPort:containerPort` or +`containerPort`, where the number of host and container ports must be the same (in the case +of a range). The protocol can be provided at the end, e.g., `hostPort:containerPort/tcp`. +Valid protocols are `tcp` and `udp`; the `sctp` protocol is supported only for rootful containers. + +If the IP is set to 0.0.0.0 or not set at all, the port is bound on all IPv4 addresses on +the host; use [::] for IPv6. + +Note that not listing a host port means that Podman automatically selects one, and it +may be different for each invocation of service. This makes that a less useful option. The +allocated port can be found with the `podman port` command. + +When using `host` networking via `Network=host`, the `PublishPort=` option cannot be used. + +This key can be listed multiple times. + + +### `ServiceName=` + +By default, Quadlet will name the systemd service unit by appending `-pod` to the name of the Quadlet. +Setting this key overrides this behavior by instructing Quadlet to use the provided name. + +Note, the name should not include the `.service` file extension + +### `ShmSize=` + +Size of /dev/shm. + +This is equivalent to the Podman `--shm-size` option and generally has the form `number[unit]` + +### `StopTimeout=` + +Sets the time in seconds to wait for the pod to gracefully stop. +This value is equivalent to the `--time` argument in the podman `pod stop` command when the service is stopped. +After this period expires, any running containers in the pod are forcibly killed. + +### `SubGIDMap=` + +Create the pod in a new user namespace using the map with name in the /etc/subgid file. +Equivalent to the Podman `--subgidname` option. + +### `SubUIDMap=` + +Create the pod in a new user namespace using the map with name in the /etc/subuid file. +Equivalent to the Podman `--subuidname` option. + +### `UIDMap=` + +Create the pod in a new user namespace using the supplied UID mapping. +Equivalent to the Podman `--uidmap` option. + +This key can be listed multiple times. + +### `UserNS=` + +Set the user namespace mode for the pod. This is equivalent to the Podman `--userns` option and +generally has the form `MODE[:OPTIONS,...]`. + +### `Volume=` + +Mount a volume in the pod. This is equivalent to the Podman `--volume` option, and +generally has the form `[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]`. + +If `SOURCE-VOLUME` starts with `.`, Quadlet resolves the path relative to the location of the unit file. + +Special case: + +* If `SOURCE-VOLUME` ends with `.volume`, Quadlet will look for the corresponding `.volume` Quadlet unit. If found, Quadlet will use the name of the Volume set in the Unit, otherwise, `systemd-$name` is used. Note: the corresponding `.volume` file must exist. + +The generated systemd service contains a dependency on the service unit generated for that `.volume` unit, +or on `$name-volume.service` if the `.volume` unit is not found. + +This key can be listed multiple times. + +## Kube units [Kube] + +Kube units are named with a `.kube` extension and contain a `[Kube]` section describing +how `podman kube play` runs as a service. The resulting service file contains a line like +`ExecStart=podman kube play … file.yml`, and most of the keys in this section control the command-line +options passed to Podman. However, some options also affect the details of how systemd is set up to run and +interact with the container. + +There is only one required key, `Yaml`, which defines the path to the Kubernetes YAML file. + +Valid options for `[Kube]` are listed below: + +| **[Kube] options** | **podman kube play equivalent** | +| ------------------------------------| -----------------------------------------------------------------| +| AutoUpdate=registry | --annotation "io.containers.autoupdate=registry" | +| ConfigMap=/tmp/config.map | --config-map /tmp/config.map | +| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | +| ExitCodePropagation=how | How to propagate container error status | +| GlobalArgs=--log-level=debug | --log-level=debug | +| KubeDownForce=true | --force (for `podman kube down`) | +| LogDriver=journald | --log-driver journald | +| Network=host | --network host | +| PodmanArgs=\-\-annotation=key=value | --annotation=key=value | +| PublishPort=8080:80 | --publish 8080:80 | +| ServiceName=name | Name the systemd unit `name.service` | +| SetWorkingDirectory=yaml | Set `WorkingDirectory` of unit file to location of the YAML file | +| UserNS=keep-id:uid=200,gid=210 | --userns keep-id:uid=200,gid=210 | +| Yaml=/tmp/kube.yaml | podman kube play /tmp/kube.yaml | + +Supported keys in the `[Kube]` section are: + +### `AutoUpdate=` + +Indicates whether containers will be auto-updated ([podman-auto-update(1)](podman-auto-update.1.md)). AutoUpdate can be specified multiple times. The following values are supported: + +* `registry`: Requires a fully-qualified image reference (e.g., quay.io/podman/stable:latest) to be used to create the container. This enforcement is necessary to know which images to actually check and pull. If an image ID was used, Podman does not know which image to check/pull anymore. + +* `local`: Tells Podman to compare the image a container is using to the image with its raw name in local storage. If an image is updated locally, Podman simply restarts the systemd unit executing the Kubernetes Quadlet. + +* `name/(local|registry)`: Tells Podman to perform the `local` or `registry` autoupdate on the specified container name. + +### `ConfigMap=` + +Pass the Kubernetes ConfigMap YAML path to `podman kube play` via the `--configmap` argument. +Unlike the `configmap` argument, the value may contain only one path but +it may be absolute or relative to the location of the unit file. + +This key may be used multiple times + +### `ContainersConfModule=` + +Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option. + +This key can be listed multiple times. + +### `ExitCodePropagation=` + +Control how the main PID of the systemd service should exit. The following values are supported: +- `all`: exit non-zero if all containers have failed (i.e., exited non-zero) +- `any`: exit non-zero if any container has failed +- `none`: exit zero and ignore failed containers + +The current default value is `none`. + +### `GlobalArgs=` + +This key contains a list of arguments passed directly between `podman` and `kube` +in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `KubeDownForce=` + +Remove all resources, including volumes, when calling `podman kube down`. +Equivalent to the Podman `--force` option. + +### `LogDriver=` + +Set the log-driver Podman uses when running the container. +Equivalent to the Podman `--log-driver` option. + +### `Network=` + +Specify a custom network for the container. This has the same format as the `--network` option +to `podman kube play`. For example, use `host` to use the host network in the container, or `none` to +not set up networking in the container. + +Special case: + +* If the `name` of the network ends with `.network`, a Podman network called `systemd-$name` is used, and the generated systemd service contains a dependency on the `$name-network.service`. Such a network can be automatically created by using a `$name.network` Quadlet file. Note: the corresponding `.network` file must exist. + +This key can be listed multiple times. + +### `PodmanArgs=` + +This key contains a list of arguments passed directly to the end of the `podman kube play` command +in the generated file (right before the path to the yaml file in the command line). It can be used to +access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `PublishPort=` + +Exposes a port, or a range of ports (e.g. `50-59`), from the container to the host. Equivalent +to the `podman kube play`'s `--publish` option. The format is similar to the Podman options, which is of +the form `ip:hostPort:containerPort`, `ip::containerPort`, `hostPort:containerPort` or +`containerPort`, where the number of host and container ports must be the same (in the case +of a range). The protocol can be provided at the end, e.g., `hostPort:containerPort/tcp`. +Valid protocols are `tcp` and `udp`; the `sctp` protocol is supported only for rootful containers. + +If the IP is set to 0.0.0.0 or not set at all, the port is bound on all IPv4 addresses on +the host; use [::] for IPv6. + +The list of published ports specified in the unit file is merged with the list of ports specified +in the Kubernetes YAML file. If the same container port and protocol is specified in both, the +entry from the unit file takes precedence + +This key can be listed multiple times. + +### `ServiceName=` + +By default, Quadlet will name the systemd service unit using the name of the Quadlet. +Setting this key overrides this behavior by instructing Quadlet to use the provided name. + +Note, the name should not include the `.service` file extension + +### `SetWorkingDirectory=` + +Set the `WorkingDirectory` field of the `Service` group of the Systemd service unit file. +Used to allow `podman kube play` to correctly resolve relative paths. +Supported values are `yaml` and `unit` to set the working directory to that of the YAML or Quadlet Unit file respectively. + +Alternatively, users can explicitly set the `WorkingDirectory` field of the `Service` group in the `.kube` file. +Please note that if the `WorkingDirectory` field of the `Service` group is set, +Quadlet will not set it even if `SetWorkingDirectory` is set + +Special case: +* If multiple `Yaml` path are provided only `unit` is supported. + +### `UserNS=` + +Set the user namespace mode for the container. This is equivalent to the Podman `--userns` option and +generally has the form `MODE[:OPTIONS,...]`. + +### `Yaml=` + +The path, absolute or relative to the location of the unit file, to the Kubernetes YAML file to use. + +This key can be listed multiple times. + +## Network units [Network] + +Network files are named with a `.network` extension and contain a section `[Network]` describing the +named Podman network. The generated service is a one-time command that ensures that the network +exists on the host, creating it if needed. + +By default, the Podman network has the same name as the unit, but with a `systemd-` prefix, i.e. for +a network file named `$NAME.network`, the generated Podman network is called `systemd-$NAME`, and +the generated service file is `$NAME-network.service`. The `NetworkName` option allows for +overriding this default name with a user-provided one. + +In order to update the network parameters you will first need to manually remove the podman network and then restart the service. +Set `NetworkDeleteOnStop=true` to override the behavior and delete the network when the device is stopped. + +Using network units allows containers to depend on networks being automatically pre-created. This is +particularly interesting when using special options to control network creation, as Podman otherwise creates networks with the default options. + +Valid options for `[Network]` are listed below: + +| **[Network] options** | **podman network create equivalent** | +|-------------------------------------|-----------------------------------------------------------------| +| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | +| DisableDNS=true | --disable-dns | +| DNS=192.168.55.1 | --dns=192.168.55.1 | +| Driver=bridge | --driver bridge | +| Gateway=192.168.55.3 | --gateway 192.168.55.3 | +| GlobalArgs=--log-level=debug | --log-level=debug | +| InterfaceName=enp1 | --interface-name enp1 | +| Internal=true | --internal | +| IPAMDriver=dhcp | --ipam-driver dhcp | +| IPRange=192.168.55.128/25 | --ip-range 192.168.55.128/25 | +| IPv6=true | --ipv6 | +| Label="XYZ" | --label "XYZ" | +| NetworkDeleteOnStop=true | Add ExecStopPost to delete the network when the unit is stopped | +| NetworkName=foo | podman network create foo | +| Options=isolate=true | --opt isolate=true | +| PodmanArgs=--dns=192.168.55.1 | --dns=192.168.55.1 | +| ServiceName=name | Name the systemd unit `name.service` | +| Subnet=192.5.0.0/16 | --subnet 192.5.0.0/16 | + +Supported keys in `[Network]` section are: + +### `ContainersConfModule=` + +Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option. + +This key can be listed multiple times. + +### `DisableDNS=` (defaults to `false`) + +If enabled, disables the DNS plugin for this network. + +This is equivalent to the Podman `--disable-dns` option + +### `DNS=` + +Set network-scoped DNS resolver/nameserver for containers in this network. + +This key can be listed multiple times. + +### `Driver=` (defaults to `bridge`) + +Driver to manage the network. Currently `bridge`, `macvlan` and `ipvlan` are supported. + +This is equivalent to the Podman `--driver` option + +### `Gateway=` + +Define a gateway for the subnet. If you want to provide a gateway address, you must also provide a subnet option. + +This is equivalent to the Podman `--gateway` option + +This key can be listed multiple times. + +### `GlobalArgs=` + +This key contains a list of arguments passed directly between `podman` and `network` +in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `InterfaceName=` + +This option maps the *network_interface* option in the network config, see **podman network inspect**. +Depending on the driver, this can have different effects; for `bridge`, it uses the bridge interface name. +For `macvlan` and `ipvlan`, it is the parent device on the host. It is the same as `--opt parent=...`. + +This is equivalent to the Podman `--interface-name` option. + +### `Internal=` (defaults to `false`) + +Restrict external access of this network. + +This is equivalent to the Podman `--internal` option + +### `IPAMDriver=` + +Set the ipam driver (IP Address Management Driver) for the network. Currently `host-local`, `dhcp` and `none` are supported. + +This is equivalent to the Podman `--ipam-driver` option + +### `IPRange=` + +Allocate container IP from a range. The range must be a either a complete subnet in CIDR notation or be +in the `-` syntax which allows for a more flexible range compared to the CIDR subnet. +The ip-range option must be used with a subnet option. + +This is equivalent to the Podman `--ip-range` option + +This key can be listed multiple times. + +### `IPv6=` + +Enable IPv6 (Dual Stack) networking. + +This is equivalent to the Podman `--ipv6` option + +### `Label=` + +Set one or more OCI labels on the network. The format is a list of +`key=value` items, similar to `Environment`. + +This key can be listed multiple times. + +### `NetworkDeleteOnStop=` (defaults to `false`) + +When set to `true` the network is deleted when the service is stopped + +### `NetworkName=` + +The (optional) name of the Podman network. +If this is not specified, the default value is the same name as the unit, but with a `systemd-` prefix, +i.e. a `$name.network` file creates a `systemd-$name` Podman network to avoid +conflicts with user-managed network. + +### `Options=` + +Set driver specific options. + +This is equivalent to the Podman `--opt` option + +### `PodmanArgs=` + +This key contains a list of arguments passed directly to the end of the `podman network create` command +in the generated file (right before the name of the network in the command line). It can be used to +access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `ServiceName=` + +By default, Quadlet will name the systemd service unit by appending `-network` to the name of the Quadlet. +Setting this key overrides this behavior by instructing Quadlet to use the provided name. + +Note, the name should not include the `.service` file extension + +### `Subnet=` + +The subnet in CIDR notation. + +This is equivalent to the Podman `--subnet` option + +This key can be listed multiple times. + +## Volume units [Volume] + +Volume files are named with a `.volume` extension and contain a section `[Volume]` describing the +named Podman volume. The generated service is a one-time command that ensures that the volume +exists on the host, creating it if needed. + +By default, the Podman volume has the same name as the unit, but with a `systemd-` prefix, i.e. for +a volume file named `$NAME.volume`, the generated Podman volume is called `systemd-$NAME`, and the +generated service file is `$NAME-volume.service`. The `VolumeName` option allows for overriding this +default name with a user-provided one. + +Using volume units allows containers to depend on volumes being automatically pre-created. This is +particularly interesting when using special options to control volume creation, +as Podman otherwise creates volumes with the default options. + +Valid options for `[Volume]` are listed below: + +| **[Volume] options** | **podman volume create equivalent** | +|-------------------------------------|-------------------------------------------| +| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | +| Copy=true | --opt copy | +| Device=tmpfs | --opt device=tmpfs | +| Driver=image | --driver=image | +| GID=5678 | --gid 5678 | +| GlobalArgs=--log-level=debug | --log-level=debug | +| Group=192 | --opt "o=group=192" | +| Image=quay.io/centos/centos\:latest | --opt image=quay.io/centos/centos\:latest | +| Label="foo=bar" | --label "foo=bar" | +| Options=XYZ | --opt "o=XYZ" | +| PodmanArgs=--driver=image | --driver=image | +| ServiceName=name | Name the systemd unit `name.service` | +| Type=type | Filesystem type of Device | +| UID=1234 | --uid 1234 | +| User=123 | --opt "o=uid=123" | +| VolumeName=foo | podman volume create foo | + +Supported keys in `[Volume]` section are: + +### `ContainersConfModule=` + +Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option. + +This key can be listed multiple times. + +### `Copy=` (default to `true`) + +If enabled, the content of the image located at the mountpoint of the volume is copied into the +volume on the first run. + +### `Device=` + +The path of a device which is mounted for the volume. + +### `Driver=` + +Specify the volume driver name. When set to `image`, the `Image` key must also be set. + +This is equivalent to the Podman `--driver` option. + +### `GID=` + +The GID that the volume will be created as. Differently than `Group=`, the specified value is not passed to the mount operation. The specified GID will own the volume's mount point directory and affects the volume chown operation. + +### `GlobalArgs=` + +This key contains a list of arguments passed directly between `podman` and `volume` +in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `Group=` + +The host (numeric) GID, or group name to use as the group for the volume. Differently than `GID`, the specified value is passed to the mount operation. + +### `Image=` + +Specifies the image the volume is based on when `Driver` is set to the `image`. +It is recommended to use a fully qualified image name rather than a short name, both for +performance and robustness reasons. + +The format of the name is the same as when passed to `podman pull`. So, it supports using +`:tag` or digests to guarantee the specific image version. + +Special case: + +* If the `name` of the image ends with `.image`, Quadlet will use the image +pulled by the corresponding `.image` file, and the generated systemd service contains a dependency on the `$name-image.service` (or the service name set in the .image file). Note: the corresponding `.image` file must exist. + +### `Label=` + +Set one or more OCI labels on the volume. The format is a list of +`key=value` items, similar to `Environment`. + +This key can be listed multiple times. + +### `Options=` + +The mount options to use for a filesystem as used by the **mount(8)** command `-o` option. + +### `PodmanArgs=` + +This key contains a list of arguments passed directly to the end of the `podman volume create` command +in the generated file (right before the name of the volume in the command line). It can be used to +access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `ServiceName=` + +By default, Quadlet will name the systemd service unit by appending `-volume` to the name of the Quadlet. +Setting this key overrides this behavior by instructing Quadlet to use the provided name. + +Note, the name should not include the `.service` file extension + +### `Type=` + +The filesystem type of `Device` as used by the **mount(8)** commands `-t` option. + +### `UID=` + +The UID that the volume will be created as. Differently than `User`, the specified value is not passed to the mount operation. The specified UID will own the volume's mount point directory and affects the volume chown operation. + +### `User=` + +The host (numeric) UID, or user name to use as the owner for the volume. Differently than `UID`, the specified value is passed to the mount operation. + +### `VolumeName=` + +The (optional) name of the Podman volume. +If this is not specified, the default value is the same name as the unit, but with a `systemd-` prefix, +i.e. a `$name.volume` file creates a `systemd-$name` Podman volume to avoid +conflicts with user-managed volumes. + +## Build units [Build] + +Build files are named with a `.build` extension and contain a section `[Build]` describing the image +build command. The generated service is a one-time command that ensures that the image is built on +the host from a supplied Containerfile and context directory. Subsequent (re-)starts of the +generated built service will usually finish quickly, as image layer caching will skip unchanged +build steps. + +A minimal `.build` unit needs at least the `ImageTag=` key, and either of `File=` or +`SetWorkingDirectory=` keys. + +Using build units allows containers and volumes to depend on images being built locally. This can be +interesting for creating container images not available on container registries, or for local +testing and development. + +Valid options for `[Build]` are listed below: + +| **[Build] options** | **podman build equivalent** | +|-------------------------------------|---------------------------------------------| +| Annotation=annotation=value | --annotation=annotation=value | +| Arch=aarch64 | --arch=aarch64 | +| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json | +| BuildArg=foo=bar | --build-arg foo=bar | +| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | +| DNS=192.168.55.1 | --dns=192.168.55.1 | +| DNSOption=ndots:1 | --dns-option=ndots:1 | +| DNSSearch=example.com | --dns-search example.com | +| Environment=foo=bar | --env foo=bar | +| File=/path/to/Containerfile | --file=/path/to/Containerfile | +| ForceRM=false | --force-rm=false | +| GlobalArgs=--log-level=debug | --log-level=debug | +| GroupAdd=keep-groups | --group-add=keep-groups | +| IgnoreFile=/path/to/\.customignore | --ignorefile=/path/to/\.customignore | +| ImageTag=localhost/imagename | --tag=localhost/imagename | +| Label=label | --label=label | +| Network=host | --network=host | +| PodmanArgs=--pull never | --pull never | +| Pull=never | --pull never | +| Retry=5 | --retry=5 | +| RetryDelay=10s | --retry-delay=10s | +| Secret=secret | --secret=id=mysecret,src=path | +| ServiceName=name | Name the systemd unit `name.service` | +| SetWorkingDirectory=unit | Set `WorkingDirectory` of systemd unit file | +| Target=my-app | --target=my-app | +| TLSVerify=false | --tls-verify=false | +| Variant=arm/v7 | --variant=arm/v7 | +| Volume=/source:/dest | --volume /source:/dest | + +### `Annotation=` + +Add an image *annotation* (e.g. annotation=*value*) to the image metadata. Can be used multiple +times. + +This is equivalent to the `--annotation` option of `podman build`. + +### `Arch=` + +Override the architecture, defaults to hosts', of the image to be built. + +This is equivalent to the `--arch` option of `podman build`. + +### `AuthFile=` + +Path of the authentication file. + +This is equivalent to the `--authfile` option of `podman build`. + +### `BuildArg=` + +Specifies a build argument and its value in the same way environment variables are +(e.g., env=*value*), but it is not added to the environment variable list in the +resulting image's configuration. Can be listed multiple times. + +This is equivalent to the `--build-arg` option of `podman build`. + +### `ContainersConfModule=` + +Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option. + +This key can be listed multiple times. + +### `DNS=` + +Set network-scoped DNS resolver/nameserver for the build container. + +This key can be listed multiple times. + +This is equivalent to the `--dns` option of `podman build`. + +### `DNSOption=` + +Set custom DNS options. + +This key can be listed multiple times. + +This is equivalent to the `--dns-option` option of `podman build`. + +### `DNSSearch=` + +Set custom DNS search domains. Use **DNSSearch=.** to remove the search domain. + +This key can be listed multiple times. + +This is equivalent to the `--dns-search` option of `podman build`. + +### `Environment=` + +Add a value (e.g. env=*value*) to the built image. This uses the same format as [services in +systemd](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Environment=) and can be +listed multiple times. + +### `File=` + +Specifies a Containerfile which contains instructions for building the image. A URL starting with +`http(s)://` allows you to specify a remote Containerfile to be downloaded. Note that for a given +relative path to a Containerfile, or when using a `http(s)://` URL, you also must set +`SetWorkingDirectory=` in order for `podman build` to find a valid context directory for the +resources specified in the Containerfile. + +Note that setting a `File=` field is mandatory for a `.build` file, unless `SetWorkingDirectory` (or +a `WorkingDirectory` in the `Service` group) has also been set. + +This is equivalent to the `--file` option of `podman build`. + +### `ForceRM=` + +Always remove intermediate containers after a build, even if the build fails (default true). + +This is equivalent to the `--force-rm` option of `podman build`. + +### `GlobalArgs=` + +This key contains a list of arguments passed directly between `podman` and `build` in the generated +file. It can be used to access Podman features otherwise unsupported by the generator. Since the +generator is unaware of what unexpected interactions can be caused by these arguments, it is not +recommended to use this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `GroupAdd=` + +Assign additional groups to the primary user running within the container process. Also supports the +`keep-groups` special flag. + +This is equivalent to the `--group-add` option of `podman build`. + +### `IgnoreFile=` + +Path to an alternate .containerignore file to use when building the image. +Note that when using a relative path you should also set `SetWorkingDirectory=` + +This is equivalent to the `--ignorefile` option of `podman build`. + +### `ImageTag=` + +Specifies the name which is assigned to the resulting image if the build process completes +successfully. + +This is equivalent to the `--tag` option of `podman build`. + +This key can be listed multiple times. The first instance will be used as the name of the created artifact when the `.build` file is referenced by another Quadlet unit. + +### `Label=` + +Add an image *label* (e.g. label=*value*) to the image metadata. Can be used multiple times. + +This is equivalent to the `--label` option of `podman build`. + +### `Network=` + +Sets the configuration for network namespaces when handling RUN instructions. This has the same +format as the `--network` option to `podman build`. For example, use `host` to use the host network, +or `none` to not set up networking. + +Special case: + +* If the `name` of the network ends with `.network`, Quadlet will look for the corresponding `.network` Quadlet unit. If found, Quadlet will use the name of the Network set in the Unit, otherwise, `systemd-$name` is used. The generated systemd service contains a dependency on the service unit generated for that `.network` unit, or on `$name-network.service` if the `.network` unit is not found. Note: the corresponding `.network` file must exist. + +This key can be listed multiple times. + +### `PodmanArgs=` + +This key contains a list of arguments passed directly to the end of the `podman build` command +in the generated file (right before the image name in the command line). It can be used to +access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `Pull=` + +Set the image pull policy. + +This is equivalent to the `--pull` option of `podman build`. + +### `Retry=` + +Number of times to retry the image pull when a HTTP error occurs. Equivalent to the Podman `--retry` option. + +### `RetryDelay=` + +Delay between retries. Equivalent to the Podman `--retry-delay` option. + +### `Secret=` + +Pass secret information used in Containerfile build stages in a safe way. + +This is equivalent to the `--secret` option of `podman build` and generally has the form +`secret[,opt=opt ...]`. + +### `ServiceName=` + +By default, Quadlet will name the systemd service unit by appending `-build` to the name of the Quadlet. +Setting this key overrides this behavior by instructing Quadlet to use the provided name. + +Note, the name should not include the `.service` file extension + +### `SetWorkingDirectory=` + +Provide context (a working directory) to `podman build`. Supported values are a path, a URL, or the +special keys `file` or `unit` to set the context directory to the parent directory of the file from +the `File=` key or to that of the Quadlet `.build` unit file, respectively. This allows Quadlet to +resolve relative paths. + +When using one of the special keys (`file` or `unit`), the `WorkingDirectory` field of the `Service` +group of the Systemd service unit will also be set to accordingly. Alternatively, users can +explicitly set the `WorkingDirectory` field of the `Service` group in the `.build` file. Please note +that if the `WorkingDirectory` field of the `Service` group is set by the user, Quadlet will not +overwrite it even if `SetWorkingDirectory` is set to `file` or `unit`. + +By providing a URL to `SetWorkingDirectory=` you can instruct `podman build` to clone a Git +repository or download an archive file extracted to a temporary location by `podman build` as build +context. Note that in this case, the `WorkingDirectory` of the Systemd service unit is left +untouched by Quadlet. + +Note that providing context directory is mandatory for a `.build` file, unless a `File=` key has +also been provided. + +### `Target=` + +Set the target build stage to build. Commands in the Containerfile after the target stage are +skipped. + +This is equivalent to the `--target` option of `podman build`. + +### `TLSVerify=` + +Require HTTPS and verification of certificates when contacting registries. + +This is equivalent to the `--tls-verify` option of `podman build`. + +### `Variant=` + +Override the default architecture variant of the container image to be built. + +This is equivalent to the `--variant` option of `podman build`. + +### `Volume=` + +Mount a volume to containers when executing RUN instructions during the build. This is equivalent to +the `--volume` option of `podman build`, and generally has the form +`[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]`. + +If `SOURCE-VOLUME` starts with `.`, Quadlet resolves the path relative to the location of the unit file. + +Special case: + +* If `SOURCE-VOLUME` ends with `.volume`, Quadlet will look for the corresponding `.volume` Quadlet unit. If found, Quadlet will use the name of the Volume set in the Unit, otherwise, `systemd-$name` is used. The generated systemd service contains a dependency on the service unit generated for that `.volume` unit, or on `$name-volume.service` if the `.volume` unit is not found. Note: the corresponding `.volume` file must exist. + +This key can be listed multiple times. + +## Image units [Image] + +Image files are named with a `.image` extension and contain a section `[Image]` describing the +container image pull command. The generated service is a one-time command that ensures that the image +exists on the host, pulling it if needed. + +Using image units allows containers and volumes to depend on images being automatically pulled. This is +particularly interesting when using special options to control image pulls. + +Valid options for `[Image]` are listed below: + +| **[Image] options** | **podman image pull equivalent** | +|----------------------------------------|--------------------------------------------------| +| AllTags=true | --all-tags | +| Arch=aarch64 | --arch=aarch64 | +| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json | +| CertDir=/etc/registry/certs | --cert-dir=/etc/registry/certs | +| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | +| Creds=myname\:mypassword | --creds=myname\:mypassword | +| DecryptionKey=/etc/registry\.key | --decryption-key=/etc/registry\.key | +| GlobalArgs=--log-level=debug | --log-level=debug | +| Image=quay\.io/centos/centos:latest | podman image pull quay.io/centos/centos\:latest | +| ImageTag=quay\.io/centos/centos:latest | Use this name when resolving `.image` references | +| OS=windows | --os=windows | +| PodmanArgs=--os=linux | --os=linux | +| Policy=always | --policy=always | +| Retry=5 | --retry=5 | +| RetryDelay=10s | --retry-delay=10s | +| ServiceName=name | Name the systemd unit `name.service` | +| TLSVerify=false | --tls-verify=false | +| Variant=arm/v7 | --variant=arm/v7 | + +### `AllTags=` + +All tagged images in the repository are pulled. + +This is equivalent to the Podman `--all-tags` option. + +### `Arch=` + +Override the architecture, defaults to hosts, of the image to be pulled. + +This is equivalent to the Podman `--arch` option. + +### `AuthFile=` + +Path of the authentication file. + +This is equivalent to the Podman `--authfile` option. + +### `CertDir=` + +Use certificates at path (*.crt, *.cert, *.key) to connect to the registry. + +This is equivalent to the Podman `--cert-dir` option. + +### `ContainersConfModule=` + +Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option. + +This key can be listed multiple times. + +### `Creds=` + +The `[username[:password]]` to use to authenticate with the registry, if required. + +This is equivalent to the Podman `--creds` option. + +### `DecryptionKey=` + +The `[key[:passphrase]]` to be used for decryption of images. + +This is equivalent to the Podman `--decryption-key` option. + +### `GlobalArgs=` + +This key contains a list of arguments passed directly between `podman` and `image` +in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `Image=` + +The image to pull. +It is recommended to use a fully qualified image name rather than a short name, both for +performance and robustness reasons. + +The format of the name is the same as when passed to `podman pull`. So, it supports using +`:tag` or digests to guarantee the specific image version. + +### `ImageTag=` + +Actual FQIN of the referenced `Image`. +Only meaningful when source is a file or directory archive. + +For example, an image saved into a `docker-archive` with the following Podman command: + +`podman image save --format docker-archive --output /tmp/archive-file.tar quay.io/podman/stable:latest` + +requires setting +- `Image=docker-archive:/tmp/archive-file.tar` +- `ImageTag=quay.io/podman/stable:latest` + +### `OS=` + +Override the OS, defaults to hosts, of the image to be pulled. + +This is equivalent to the Podman `--os` option. + +### `PodmanArgs=` + +This key contains a list of arguments passed directly to the end of the `podman image pull` command +in the generated file (right before the image name in the command line). It can be used to +access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `Policy=` + +The pull policy to use when pulling the image. + +This is equivalent to the Podman `--policy` option. + +### `Retry=` + +Number of times to retry the image pull when a HTTP error occurs. Equivalent to the Podman `--retry` option. + +### `RetryDelay=` + +Delay between retries. Equivalent to the Podman `--retry-delay` option. + +### `ServiceName=` + +By default, Quadlet will name the systemd service unit by appending `-image` to the name of the Quadlet. +Setting this key overrides this behavior by instructing Quadlet to use the provided name. + +Note, the name should not include the `.service` file extension + +### `TLSVerify=` + +Require HTTPS and verification of certificates when contacting registries. + +This is equivalent to the Podman `--tls-verify` option. + +### `Variant=` + +Override the default architecture variant of the container image. + +This is equivalent to the Podman `--variant` option. + +## Artifact units [Artifact] + +### WARNING: Experimental Unit + +This unit is considered experimental and still in development. Inputs, options, and outputs are all subject to change. + +Artifact units are named with a `.artifact` extension and contain a `[Artifact]` section describing +the container artifact pull command. The generated service is a one-time command that ensures that the artifact +exists on the host, pulling it if needed. + +Using artifact units allows containers to depend on artifacts being automatically pulled. This is +particularly useful for managing artifacts that containers need to mount or access, the **Artifact** key is mandatory inside of the [Artifact] unit. + +Valid options for `[Artifact]` are listed below: + +| **[Artifact] options** | **podman artifact pull equivalent** | +|---------------------------------------------|--------------------------------------------------------| +| Artifact=quay\.io/foobar/artifact:special | podman artifact pull quay\.io/foobar/artifact:special | +| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json | +| CertDir=/etc/registry/certs | --cert-dir=/etc/registry/certs | +| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | +| Creds=username:password | --creds=username:password | +| DecryptionKey=/etc/registry\.key | --decryption-key=/etc/registry\.key | +| GlobalArgs=--log-level=debug | --log-level=debug | +| PodmanArgs=--pull never | --pull never | +| Quiet=true | --quiet | +| Retry=5 | --retry=5 | +| RetryDelay=10s | --retry-delay=10s | +| ServiceName=my-artifact | Set the systemd service name to my-artifact.service | +| TLSVerify=false | --tls-verify=false | + +### `Artifact=` + +The artifact to pull from a registry onto the local machine. This is the only required key for artifact units. + +It is required to use a fully qualified artifact name rather than a short name, both for +performance and robustness reasons. + +### `AuthFile=` + +Path of the authentication file. + +This is equivalent to the Podman `--authfile` option. + +### `CertDir=` + +Use certificates at path (*.crt, *.cert, *.key) to connect to the registry. + +This is equivalent to the Podman `--cert-dir` option. + +### `ContainersConfModule=` + +Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option. + +This key can be listed multiple times. + +### `Creds=` + +The credentials to use when contacting the registry in the format `[username[:password]]`. + +This is equivalent to the Podman `--creds` option. + +### `DecryptionKey=` + +The `[key[:passphrase]]` to be used for decryption of artifacts. + +This is equivalent to the Podman `--decryption-key` option. + +### `GlobalArgs=` + +This key contains a list of arguments passed directly between `podman` and `artifact` +in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `PodmanArgs=` + +This key contains a list of arguments passed directly to the end of the `podman artifact pull` command +in the generated file (right before the artifact name in the command line). It can be used to +access Podman features otherwise unsupported by the generator. Since the generator is unaware +of what unexpected interactions can be caused by these arguments, it is not recommended to use +this option. + +The format of this is a space separated list of arguments, which can optionally be individually +escaped to allow inclusion of whitespace and other control characters. + +This key can be listed multiple times. + +### `Quiet=` + +Suppress output information when pulling artifacts. + +This is equivalent to the Podman `--quiet` option. + +### `Retry=` + +Number of times to retry the artifact pull when a HTTP error occurs. Equivalent to the Podman `--retry` option. + +### `RetryDelay=` + +Delay between retries. Equivalent to the Podman `--retry-delay` option. + +### `ServiceName=` + +The (optional) name of the systemd service. If this is not specified, the default value is the same name as the unit, but with a `-artifact` suffix, i.e. a `$name.artifact` file creates a `$name-artifact.service` systemd service. + +### `TLSVerify=` + +Require HTTPS and verification of certificates when contacting registries. + +This is equivalent to the Podman `--tls-verify` option. + +## Quadlet section [Quadlet] +Some quadlet specific configuration is shared between different unit types. Those settings +can be configured in the `[Quadlet]` section. + +Valid options for `[Quadlet]` are listed below: + +| **[Quadlet] options** | **Description** | +|----------------------------|---------------------------------------------------| +| DefaultDependencies=false | Disable implicit network dependencies to the unit | + +### `DefaultDependencies=` + +Add Quadlet's default network dependencies to the unit (default is `true`). + +When set to false, Quadlet will **not** add a dependency (After=, Wants=) to +`network-online.target`/`podman-user-wait-network-online.service` to the generated unit. + +Note, this option is set in the `[Quadlet]` section. The _systemd_ `[Unit]` section +has an option with the same name but a different meaning. + +## EXAMPLES + +Example `test.container`: + +``` +[Unit] +Description=A minimal container + +[Container] +# Use the centos image +Image=quay.io/centos/centos:latest + +# Use volume and network defined below +Volume=test.volume:/data +Network=test.network + +# In the container we just run sleep +Exec=sleep 60 + +[Service] +# Restart service when sleep finishes +Restart=always +# Extend Timeout to allow time to pull the image +TimeoutStartSec=900 +# ExecStartPre flag and other systemd commands can go here, see systemd.unit(5) man page. +ExecStartPre=/usr/share/mincontainer/setup.sh + +[Install] +# Start by default on boot +WantedBy=multi-user.target default.target +``` + +Example `test.kube`: +``` +[Unit] +Description=A kubernetes yaml based service +Before=local-fs.target + +[Kube] +Yaml=/opt/k8s/deployment.yml + +[Install] +# Start by default on boot +WantedBy=multi-user.target default.target +``` + +Example for locally built image to be used in a container with build-specific arguments: + +`test.build` +``` +[Build] +# Tag the image to be built +ImageTag=localhost/imagename + +# Set the working directory to the path of the unit file, +# expecting to find a Containerfile/Dockerfile +# + other files needed to build the image +SetWorkingDirectory=unit +# Set build arguments VERSION and DEBUG +BuildArg=VERSION=1.0 \ + DEBUG=false +``` + +`test.container` +``` +[Container] +Image=test.build +``` + +Example `test.volume`: + +``` +[Volume] +User=root +Group=root +Label=org.test.Key=value +``` + +Example `test.network`: +``` +[Network] +Subnet=172.16.0.0/24 +Gateway=172.16.0.1 +IPRange=172.16.0.0/28 +Label=org.test.Key=value +``` + +Example `test.artifact` to only pull the artifact using one auth file: +``` +[Artifact] +Artifact=quay.io/example/my-artifact:latest +AuthFile=/etc/registry/auth.json +TLSVerify=false +``` + +Example usage where a container depends on an artifact: + +`my-artifact.artifact`: +``` +[Artifact] +Artifact=quay.io/example/my-config:latest +``` + +`my-app.container`: +``` +[Container] +Image=quay.io/example/my-app:latest +Mount=type=artifact,source=my-artifact.artifact,destination=/etc/config +``` + +Example for a container in a Pod: + +`test.pod` +``` +[Pod] +PodName=test +``` + +`centos.container` +``` +[Container] +Image=quay.io/centos/centos:latest +Exec=sh -c "sleep inf" +Pod=test.pod +``` + +Example for a Pod with a one-shot startup task: + +`test.pod` +``` +[Pod] +PodName=test +ExitPolicy=continue +``` + +`startup-task.container` +``` +[Service] +Type=oneshot +RemainAfterExit=yes + +[Container] +Pod=test.pod +Image=quay.io/centos/centos:latest +Exec=sh -c "echo 'setup starting'; sleep 2; echo 'setup complete'" +``` + +`app.container` +``` +[Unit] +Requires=startup-task.container +After=startup-task.container + +[Container] +Pod=test.pod +Image=quay.io/centos/centos:latest +Exec=sh -c "echo 'app running.'; sleep 30" +``` + +Example `s3fs.volume`: + +For further details, please see the [s3fs-fuse](https://github.com/s3fs-fuse/s3fs-fuse) project. +Remember to read the [FAQ](https://github.com/s3fs-fuse/s3fs-fuse/wiki/FAQ) + +> NOTE: Enabling the cache massively speeds up access and write times on static files/objects. + +> However, `use_cache` is [UNBOUNDED](https://github.com/s3fs-fuse/s3fs-fuse/wiki/FAQ#q-how-does-the-local-file-cache-work)! + +> Be careful, it will fill up with any files accessed on the s3 bucket through the file system. + +Please remember to set `S3_BUCKET`, `PATH`, `AWS_REGION`. `CACHE_DIRECTORY` should be set up by [systemd](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#RuntimeDirectory=) + +``` +[Service] +CacheDirectory=s3fs +ExecStartPre=/usr/local/bin/aws s3api put-object --bucket ${S3_BUCKET} --key ${PATH}/ + +[Volume] +Device=${S3_BUCKET}:/${PATH} +Type=fuse.s3fs +VolumeName=s3fs-volume +Options=iam_role,endpoint=${AWS_REGION},use_xattr,listobjectsv2,del_cache,use_cache=${CACHE_DIRECTORY} +# `iam_role` assumes inside EC2, if not, Use `profile=` instead +``` + +## SEE ALSO +**[systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html)**, +**[systemd.service(5)](https://www.freedesktop.org/software/systemd/man/systemd.service.html)**, +**[systemd-analyze(1)](https://www.freedesktop.org/software/systemd/man/latest/systemd-analyze.html)**, +**[podman-run(1)](podman-run.1.md)**, +**[podman-network-create(1)](podman-network-create.1.md)**, +**[podman-auto-update(1)](podman-auto-update.1.md)** \ No newline at end of file diff --git a/references/validation.md b/references/validation.md new file mode 100644 index 0000000..9db8026 --- /dev/null +++ b/references/validation.md @@ -0,0 +1,70 @@ +# Validation + +Use this file when the user asks how to verify or troubleshoot generated Quadlet units. + +## Basic deployment flow + +### Rootless + +```bash +systemctl --user daemon-reload +systemctl --user start +systemctl --user status +``` + +### Rootful + +```bash +systemctl daemon-reload +systemctl start +systemctl status +``` + +## Generator debugging + +Use the Podman systemd generator dry run when units fail to appear or options look unsupported. + +```bash +/usr/lib/systemd/system-generators/podman-system-generator --dryrun +``` + +For rootless debugging: + +```bash +/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun +``` + +## Systemd verification + +```bash +systemd-analyze verify .service +``` + +For user units: + +```bash +systemd-analyze --user verify .service +``` + +## Common failure causes + +- unsupported Quadlet option for the installed Podman version +- bind-mount source directory missing +- wrong rootless or rootful unit directory +- unresolved env file path +- permissions on rootless bind mounts +- readiness assumptions hidden behind `depends_on` + +## Troubleshooting posture + +When validation fails, report: + +- what generated successfully +- what failed to generate or start +- whether the issue is syntax, unsupported feature, path resolution, or permissions + +## Relationship to execution phase + +Validation belongs after the files are written in the execution phase. + +Before execution, the skill should already have completed planning and finalize review with the user. Do not treat validation as a substitute for design review.