1
0
mirror of https://github.com/bestnite/quadlet-migrator-skill.git synced 2026-04-26 17:41:53 +00:00

Add helper script templates and align reference guidance.

Point helper-script generation at shared templates, tighten prefix-based Quadlet handling, and refresh the bundled Quadlet reference formatting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-04 17:55:30 +11:00
parent e2372f1b3d
commit 62704d3a2d
13 changed files with 349 additions and 197 deletions
+1
View File
@@ -56,6 +56,7 @@ Execution starts only after the user approves that review.
- `references/github-repo-intake.md` covers how the skill finds the right repository entry point - `references/github-repo-intake.md` covers how the skill finds the right repository entry point
- `references/deployment-notes.md` covers deployment guidance - `references/deployment-notes.md` covers deployment guidance
- `references/validation.md` covers validation and troubleshooting - `references/validation.md` covers validation and troubleshooting
- `references/template/` contains simple helper-script templates for stable prefix-based Quadlet file handling and lifecycle management
## Limitations ## Limitations
+1
View File
@@ -56,6 +56,7 @@ Finalize 是在这些问题讨论清楚之后进行的对话式审阅。
- `references/github-repo-intake.md`:说明 skill 如何找到正确的仓库入口 - `references/github-repo-intake.md`:说明 skill 如何找到正确的仓库入口
- `references/deployment-notes.md`:部署说明 - `references/deployment-notes.md`:部署说明
- `references/validation.md`:验证与排障 - `references/validation.md`:验证与排障
- `references/template/`:用于稳定处理 Quadlet 文件与 lifecycle 管理的简洁 helper script 模板目录
## 限制 ## 限制
+3 -2
View File
@@ -18,7 +18,7 @@ This skill helps you:
- choose between `.container`, `.pod`, `.network`, `.volume`, and `.build`, with a pod-first bias for multi-container services - choose between `.container`, `.pod`, `.network`, `.volume`, and `.build`, with a pod-first bias for multi-container services
- decide whether values belong in `Environment=` or `EnvironmentFile=` - decide whether values belong in `Environment=` or `EnvironmentFile=`
- write reviewable output to the current directory by default, unless the user requested another output directory or an existing-file conflict requires a decision before writing - write reviewable output to the current directory by default, unless the user requested another output directory or an existing-file conflict requires a decision before writing
- generate helper scripts with `install.sh` as the canonical apply script name, plus `uninstall.sh`, `reload.sh`, `start.sh`, `stop.sh`, and `restart.sh` when producing runnable artifacts - generate helper scripts with `install.sh` as the canonical apply script name, plus `uninstall.sh`, `reload.sh`, `start.sh`, `stop.sh`, and `restart.sh` when producing runnable artifacts, using the reviewed shell templates under `references/template/` as the default source
- identify required repo-local companion files such as config files, templates, seed data, or initialization assets that must be shipped alongside Quadlet output for the deployment to run correctly - identify required repo-local companion files such as config files, templates, seed data, or initialization assets that must be shipped alongside Quadlet output for the deployment to run correctly
- validate env completeness before claiming runnable output, including missing required keys and suspicious env-key mismatches - validate env completeness before claiming runnable output, including missing required keys and suspicious env-key mismatches
- work closely with the user to confirm deployment-specific environment values and operational choices - work closely with the user to confirm deployment-specific environment values and operational choices
@@ -202,9 +202,11 @@ Tasks in this phase:
1. Generate the Quadlet files in the current working directory by default so the user can review them before applying them. 1. Generate the Quadlet files in the current working directory by default so the user can review them before applying them.
2. Generate the env file or env delta only when needed for runnable output. 2. Generate the env file or env delta only when needed for runnable output.
3. Generate helper scripts such as `install.sh`, `uninstall.sh`, `reload.sh`, `start.sh`, `stop.sh`, and `restart.sh` when they materially help the user apply and operate the result. 3. Generate helper scripts such as `install.sh`, `uninstall.sh`, `reload.sh`, `start.sh`, `stop.sh`, and `restart.sh` when they materially help the user apply and operate the result.
- Generate these shell scripts by adapting the reviewed templates under `references/template/`.
- Use `install.sh` as the default and canonical script name for applying the reviewed artifact set. - Use `install.sh` as the default and canonical script name for applying the reviewed artifact set.
- Do not also generate `apply.sh` unless the user explicitly asks for that alternate name. - Do not also generate `apply.sh` unless the user explicitly asks for that alternate name.
- `install.sh` should copy only Quadlet unit files into the chosen Quadlet target directory. Required env files, mounted config, scripts, and other runtime support files should remain in the reviewed current-directory deliverable set and be referenced from Quadlet via absolute host paths. - `install.sh` should copy only Quadlet unit files into the chosen Quadlet target directory. Required env files, mounted config, scripts, and other runtime support files should remain in the reviewed current-directory deliverable set and be referenced from Quadlet via absolute host paths.
- helper shell scripts must not hardcode exact Quadlet filenames or assume a fixed number of Quadlet files. They should operate on the reviewed Quadlet set via the shared generated prefix, using shared-prefix glob matching such as `<prefix>*`.
- `install.sh` should not start, stop, restart, or reload services as a side effect. - `install.sh` should not start, stop, restart, or reload services as a side effect.
- `uninstall.sh` should remove only the previously installed reviewed Quadlet unit files from the chosen Quadlet target directory. - `uninstall.sh` should remove only the previously installed reviewed Quadlet unit files from the chosen Quadlet target directory.
- `uninstall.sh` should stop affected services before removing their installed unit files, and should not delete support files from the current-directory deliverable set, unrelated files, shared directories, named volumes, images, or Podman objects unless the user explicitly asks for that broader cleanup. - `uninstall.sh` should stop affected services before removing their installed unit files, and should not delete support files from the current-directory deliverable set, unrelated files, shared directories, named volumes, images, or Podman objects unless the user explicitly asks for that broader cleanup.
@@ -235,7 +237,6 @@ Use this execution checklist template:
- [ ] helper scripts operate on the same reviewed artifact set that finalize approved - [ ] helper scripts operate on the same reviewed artifact set that finalize approved
- [ ] chosen output directory still matches the approved plan and no new file conflicts appeared before writing - [ ] chosen output directory still matches the approved plan and no new file conflicts appeared before writing
If you generate a README or operational notes, use the same language as the user unless the user explicitly asks for another language. 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 ## Decision priority
+1 -1
View File
@@ -7,6 +7,7 @@ Use this file when converting `docker-compose.yml` or `compose.yaml` into Quadle
- Model each service first, then decide how to group all resulting containers into one or more `.pod` units. - 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. - Prefer maintainable Quadlet output over mechanical one-to-one translation.
- Keep names stable and predictable. Generated filenames should use a shared project prefix. - Keep names stable and predictable. Generated filenames should use a shared project prefix.
- When one deliverable set includes multiple Quadlet files, keep that shared prefix consistent so helper shell scripts can match them by shared-prefix globbing such as `<prefix>*`, instead of hardcoding exact filenames or assuming a fixed file count.
## Field strategy ## Field strategy
@@ -187,4 +188,3 @@ When services are split across multiple pods, do not rely on `127.0.0.1` / `loca
Avoid preserving bridge networks by default when pod grouping already expresses the intended communication pattern well. Avoid preserving bridge networks by default when pod grouping already expresses the intended communication pattern well.
For large application stacks with optional services, ask the user to choose the desired service set before generating a minimized result. For large application stacks with optional services, ask the user to choose the desired service set before generating a minimized result.
+1
View File
@@ -35,6 +35,7 @@ See `podman-systemd.unit.5.md` for the full search-path matrix.
- `install.sh`: canonical apply script; copy only reviewed Quadlet unit files into the selected Quadlet target directory - `install.sh`: canonical apply script; copy only reviewed Quadlet unit files into the selected Quadlet target directory
- do not generate a separate `apply.sh` by default; reserve that alternate name only when the user explicitly asks for it - do not generate a separate `apply.sh` by default; reserve that alternate name only when the user explicitly asks for it
- helper shell scripts must discover the reviewed Quadlet files through their shared generated prefix, using shared-prefix glob matching such as `<prefix>*` instead of hardcoding exact filenames or assuming a fixed file count
- `install.sh` must not start, stop, restart, or reload services as a side effect - `install.sh` must not start, stop, restart, or reload services as a side effect
- `uninstall.sh`: remove the installed reviewed Quadlet unit files from the selected Quadlet target directory - `uninstall.sh`: remove the installed reviewed Quadlet unit files from the selected Quadlet target directory
- `uninstall.sh` should stop affected services before removing their installed unit files, and should not delete support files from the current-directory deliverable set, unrelated files, shared directories, named volumes, images, or Podman objects unless the user explicitly asks for broader cleanup - `uninstall.sh` should stop affected services before removing their installed unit files, and should not delete support files from the current-directory deliverable set, unrelated files, shared directories, named volumes, images, or Podman objects unless the user explicitly asks for broader cleanup
+78 -53
View File
@@ -6,7 +6,7 @@ podman\-systemd.unit - systemd units using Podman Quadlet
## SYNOPSIS ## SYNOPSIS
*name*.container, *name*.volume, *name*.network, *name*.kube *name*.image, *name*.build *name*.pod, *name*.artifact _name_.container, _name_.volume, _name_.network, _name_.kube _name_.image, _name_.build _name_.pod, _name_.artifact
### Podman rootful unit search path ### Podman rootful unit search path
@@ -14,26 +14,26 @@ Quadlet files for the root user can be placed in the following directories order
Temporary quadlets, usually used for testing: Temporary quadlets, usually used for testing:
* /run/containers/systemd/ - /run/containers/systemd/
System administrator's defined quadlets: System administrator's defined quadlets:
* /etc/containers/systemd/ - /etc/containers/systemd/
Distribution defined quadlets: Distribution defined quadlets:
* /usr/share/containers/systemd/ - /usr/share/containers/systemd/
### Podman rootless unit search path ### Podman rootless unit search path
Quadlet files for non-root users can be placed in the following directories: Quadlet files for non-root users can be placed in the following directories:
* $XDG_RUNTIME_DIR/containers/systemd/ - $XDG_RUNTIME_DIR/containers/systemd/
* $XDG_CONFIG_HOME/containers/systemd/ or ~/.config/containers/systemd/ - $XDG_CONFIG_HOME/containers/systemd/ or ~/.config/containers/systemd/
* /etc/containers/systemd/users/${UID} - /etc/containers/systemd/users/${UID}
* /etc/containers/systemd/users/ - /etc/containers/systemd/users/
* /usr/share/containers/systemd/users/${UID} - /usr/share/containers/systemd/users/${UID}
* /usr/share/containers/systemd/users/ - /usr/share/containers/systemd/users/
### Using symbolic links ### Using symbolic links
@@ -91,9 +91,9 @@ 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 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 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, 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 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)`. _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. Adding the following snippet to a Quadlet file extends the startup timeout to 15 minutes.
@@ -119,6 +119,7 @@ leaves the job in a "started" state which prevents subsequent activations by the
`systemd.service(5)` man page. `systemd.service(5)` man page.
Examples for such cases: Examples for such cases:
- `.container` file with an image that exits after their entrypoint has finished - `.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 - `.kube` file pointing to a Kubernetes Yaml file that does not define any containers. E.g. PVCs only
@@ -203,6 +204,7 @@ 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 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 that particular instance to be running with another image, you can
create a drop-in file like `sleep@10.container.d/10-image.conf`: create a drop-in file like `sleep@10.container.d/10-image.conf`:
``` ```
[Container] [Container]
Image=quay.io/centos/centos Image=quay.io/centos/centos
@@ -216,6 +218,7 @@ 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` (the name is arbitrary) and reference it in `foo@.container`:
`foo-data@.volume`: `foo-data@.volume`:
``` ```
[Volume] [Volume]
# Optional: without an explicit VolumeName, Quadlet auto-generates one with a # Optional: without an explicit VolumeName, Quadlet auto-generates one with a
@@ -225,6 +228,7 @@ VolumeName=my-name-%i
``` ```
`foo@.container`: `foo@.container`:
``` ```
[Container] [Container]
Volume=foo-data@.volume:/mnt/path Volume=foo-data@.volume:/mnt/path
@@ -257,11 +261,13 @@ used an option from a newer version of Podman Quadlet and the
generator failed to create a service file. generator failed to create a service file.
View the generated files and/or error messages with: View the generated files and/or error messages with:
``` ```
/usr/lib/systemd/system-generators/podman-system-generator {--user} --dryrun /usr/lib/systemd/system-generators/podman-system-generator {--user} --dryrun
``` ```
Alternatively, show only the errors with: Alternatively, show only the errors with:
``` ```
systemd-analyze {--user} --generators=true verify example.service systemd-analyze {--user} --generators=true verify example.service
``` ```
@@ -302,6 +308,7 @@ Quadlet will automatically translate dependencies, specified in the keys
of the `[Unit]` section, between different Quadlet units. of the `[Unit]` section, between different Quadlet units.
For example the `fedora.container` unit below specifies a dependency on the `basic.container` unit. For example the `fedora.container` unit below specifies a dependency on the `basic.container` unit.
``` ```
[Unit] [Unit]
After=basic.container After=basic.container
@@ -336,7 +343,7 @@ There is only one required key, `Image`, which defines the container image the s
Valid options for `[Container]` are listed below: Valid options for `[Container]` are listed below:
| **[Container] options** | **podman run equivalent** | | **[Container] options** | **podman run equivalent** |
|--------------------------------------|------------------------------------------------------| | ----------------------------------- | ---------------------------------------------------- |
| AddCapability=CAP | --cap-add CAP | | AddCapability=CAP | --cap-add CAP |
| AddDevice=/dev/foo | --device /dev/foo | | AddDevice=/dev/foo | --device /dev/foo |
| AddHost=example\.com:192.168.10.11 | --add-host example.com:192.168.10.11 | | AddHost=example\.com:192.168.10.11 | --add-host example.com:192.168.10.11 |
@@ -436,6 +443,7 @@ Add these capabilities, in addition to the default Podman capability set, to the
This is a space separated list of capabilities. This key can be listed multiple times. This is a space separated list of capabilities. This key can be listed multiple times.
For example: For example:
``` ```
AddCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER AddCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER
``` ```
@@ -474,9 +482,9 @@ Sets the apparmor confinement profile for the container. A value of `unconfined`
Indicates whether the container will be auto-updated ([podman-auto-update(1)](podman-auto-update.1.md)). The following values are supported: 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. - `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. - `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=` ### `CgroupsMode=`
@@ -525,6 +533,7 @@ Drop these capabilities from the default podman capability set, or `all` to drop
This is a space separated list of capabilities. This key can be listed multiple times. This is a space separated list of capabilities. This key can be listed multiple times.
For example: For example:
``` ```
DropCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER DropCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER
``` ```
@@ -621,9 +630,9 @@ Set the destination of the HealthCheck log. Directory path, local or events_logg
(Default: local) (Default: local)
Equivalent to the Podman `--health-log-destination` option. Equivalent to the Podman `--health-log-destination` option.
* `local`: (default) HealthCheck logs are stored in overlay containers. (For example: `$runroot/healthcheck.log`) - `local`: (default) HealthCheck logs are stored in overlay containers. (For example: `$runroot/healthcheck.log`)
* `directory`: creates a log file named `<container-ID>-healthcheck.log` with HealthCheck logs in the specified directory. - `directory`: creates a log file named `<container-ID>-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. - `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=` ### `HealthMaxLogCount=`
@@ -710,8 +719,8 @@ The format of the name is the same as when passed to `podman pull`. So, it suppo
Special Cases: 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 `.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. - 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=` ### `IP=`
@@ -757,8 +766,8 @@ generally has the form `type=TYPE,TYPE-SPECIFIC-OPTION[,...]`.
Special cases: Special cases:
* For `type=volume`, if `source` ends with `.volume`, the Podman named volume generated by the corresponding `.volume` file is used. - 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. - 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. 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.
@@ -772,12 +781,12 @@ not set up networking in the container.
Special cases: Special cases:
* If the `name` of the network ends with `.network`, a Podman network called - If the `name` of the network ends with `.network`, a Podman network called
`systemd-$name` is used, and the generated systemd service contains `systemd-$name` is used, and the generated systemd service contains
a dependency on the `$name-network.service`. Such a network can be automatically 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. created by using a `$name.network` Quadlet file. Note: the corresponding `.network` file must exist.
* If the `name` ends with `.container`, - If the `name` ends with `.container`,
the container will reuse the network stack of another container created by `$name.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. The generated systemd service contains a dependency on `$name.service`. Note: the corresponding `.container` file must exist.
@@ -822,7 +831,6 @@ The value must take the form of `<name>.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. Quadlet will add all the necessary parameters to link between the container and the pod and between their corresponding services.
### `PodmanArgs=` ### `PodmanArgs=`
This key contains a list of arguments passed directly to the end of the `podman run` command This key contains a list of arguments passed directly to the end of the `podman run` command
@@ -988,6 +996,7 @@ Configures namespaced kernel parameters for the container. The format is `Sysctl
This is a space separated list of kernel parameters. This key can be listed multiple times. This is a space separated list of kernel parameters. This key can be listed multiple times.
For example: For example:
``` ```
Sysctl=net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.all.use_tempaddr=1 Sysctl=net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.all.use_tempaddr=1
``` ```
@@ -1018,7 +1027,7 @@ This key can be listed multiple times.
### `Unmask=` ### `Unmask=`
Specify the paths to unmask separated by a colon. unmask=ALL or /path/1:/path/2, or shell expanded paths (/proc/*): 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. If set to `ALL`, Podman will unmask all the paths that are masked or made read-only by default.
@@ -1048,7 +1057,7 @@ If `SOURCE-VOLUME` starts with `.`, Quadlet resolves the path relative to the lo
Special case: 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. - 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. This key can be listed multiple times.
@@ -1077,7 +1086,7 @@ when containers exit, set `Restart=always` in the `[Service]` section of the `.p
Valid options for `[Pod]` are listed below: Valid options for `[Pod]` are listed below:
| **[Pod] options** | **podman pod create equivalent** | | **[Pod] options** | **podman pod create equivalent** |
|-------------------------------------|----------------------------------------| | ----------------------------------- | ------------------------------------ |
| AddHost=example\.com:192.168.10.11 | --add-host example.com:192.168.10.11 | | AddHost=example\.com:192.168.10.11 | --add-host example.com:192.168.10.11 |
| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | | ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf |
| DNS=192.168.55.1 | --dns=192.168.55.1 | | DNS=192.168.55.1 | --dns=192.168.55.1 |
@@ -1196,7 +1205,7 @@ For example, use `host` to use the host network in the pod, or `none` to not set
Special case: 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. - 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. The generated systemd service contains a dependency on the service unit generated for that `.network` unit. Note: the corresponding `.network` file must exist.
@@ -1252,7 +1261,6 @@ When using `host` networking via `Network=host`, the `PublishPort=` option canno
This key can be listed multiple times. This key can be listed multiple times.
### `ServiceName=` ### `ServiceName=`
By default, Quadlet will name the systemd service unit by appending `-pod` to the name of the Quadlet. By default, Quadlet will name the systemd service unit by appending `-pod` to the name of the Quadlet.
@@ -1303,7 +1311,7 @@ If `SOURCE-VOLUME` starts with `.`, Quadlet resolves the path relative to the lo
Special case: 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. - 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, 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. or on `$name-volume.service` if the `.volume` unit is not found.
@@ -1323,7 +1331,7 @@ There is only one required key, `Yaml`, which defines the path to the Kubernetes
Valid options for `[Kube]` are listed below: Valid options for `[Kube]` are listed below:
| **[Kube] options** | **podman kube play equivalent** | | **[Kube] options** | **podman kube play equivalent** |
| ------------------------------------| -----------------------------------------------------------------| | ----------------------------------- | ---------------------------------------------------------------- |
| AutoUpdate=registry | --annotation "io.containers.autoupdate=registry" | | AutoUpdate=registry | --annotation "io.containers.autoupdate=registry" |
| ConfigMap=/tmp/config.map | --config-map /tmp/config.map | | ConfigMap=/tmp/config.map | --config-map /tmp/config.map |
| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | | ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf |
@@ -1345,11 +1353,11 @@ Supported keys in the `[Kube]` section are:
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: 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. - `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. - `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. - `name/(local|registry)`: Tells Podman to perform the `local` or `registry` autoupdate on the specified container name.
### `ConfigMap=` ### `ConfigMap=`
@@ -1368,6 +1376,7 @@ This key can be listed multiple times.
### `ExitCodePropagation=` ### `ExitCodePropagation=`
Control how the main PID of the systemd service should exit. The following values are supported: 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) - `all`: exit non-zero if all containers have failed (i.e., exited non-zero)
- `any`: exit non-zero if any container has failed - `any`: exit non-zero if any container has failed
- `none`: exit zero and ignore failed containers - `none`: exit zero and ignore failed containers
@@ -1404,7 +1413,7 @@ not set up networking in the container.
Special case: 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. - 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. This key can be listed multiple times.
@@ -1457,7 +1466,8 @@ Please note that if the `WorkingDirectory` field of the `Service` group is set,
Quadlet will not set it even if `SetWorkingDirectory` is set Quadlet will not set it even if `SetWorkingDirectory` is set
Special case: Special case:
* If multiple `Yaml` path are provided only `unit` is supported.
- If multiple `Yaml` path are provided only `unit` is supported.
### `UserNS=` ### `UserNS=`
@@ -1490,7 +1500,7 @@ particularly interesting when using special options to control network creation,
Valid options for `[Network]` are listed below: Valid options for `[Network]` are listed below:
| **[Network] options** | **podman network create equivalent** | | **[Network] options** | **podman network create equivalent** |
|-------------------------------------|-----------------------------------------------------------------| | ----------------------------------- | --------------------------------------------------------------- |
| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | | ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf |
| DisableDNS=true | --disable-dns | | DisableDNS=true | --disable-dns |
| DNS=192.168.55.1 | --dns=192.168.55.1 | | DNS=192.168.55.1 | --dns=192.168.55.1 |
@@ -1558,7 +1568,7 @@ This key can be listed multiple times.
### `InterfaceName=` ### `InterfaceName=`
This option maps the *network_interface* option in the network config, see **podman network inspect**. 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. 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=...`. For `macvlan` and `ipvlan`, it is the parent device on the host. It is the same as `--opt parent=...`.
@@ -1662,7 +1672,7 @@ as Podman otherwise creates volumes with the default options.
Valid options for `[Volume]` are listed below: Valid options for `[Volume]` are listed below:
| **[Volume] options** | **podman volume create equivalent** | | **[Volume] options** | **podman volume create equivalent** |
|-------------------------------------|-------------------------------------------| | ----------------------------------- | ----------------------------------------- |
| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | | ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf |
| Copy=true | --opt copy | | Copy=true | --opt copy |
| Device=tmpfs | --opt device=tmpfs | | Device=tmpfs | --opt device=tmpfs |
@@ -1734,7 +1744,7 @@ The format of the name is the same as when passed to `podman pull`. So, it suppo
Special case: Special case:
* If the `name` of the image ends with `.image`, Quadlet will use the image - 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. 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=` ### `Label=`
@@ -1805,7 +1815,7 @@ testing and development.
Valid options for `[Build]` are listed below: Valid options for `[Build]` are listed below:
| **[Build] options** | **podman build equivalent** | | **[Build] options** | **podman build equivalent** |
|-------------------------------------|---------------------------------------------| | ----------------------------------- | ------------------------------------------- |
| Annotation=annotation=value | --annotation=annotation=value | | Annotation=annotation=value | --annotation=annotation=value |
| Arch=aarch64 | --arch=aarch64 | | Arch=aarch64 | --arch=aarch64 |
| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json | | AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json |
@@ -1837,7 +1847,7 @@ Valid options for `[Build]` are listed below:
### `Annotation=` ### `Annotation=`
Add an image *annotation* (e.g. annotation=*value*) to the image metadata. Can be used multiple Add an image _annotation_ (e.g. annotation=_value_) to the image metadata. Can be used multiple
times. times.
This is equivalent to the `--annotation` option of `podman build`. This is equivalent to the `--annotation` option of `podman build`.
@@ -1857,7 +1867,7 @@ This is equivalent to the `--authfile` option of `podman build`.
### `BuildArg=` ### `BuildArg=`
Specifies a build argument and its value in the same way environment variables are 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 (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. resulting image's configuration. Can be listed multiple times.
This is equivalent to the `--build-arg` option of `podman build`. This is equivalent to the `--build-arg` option of `podman build`.
@@ -1894,7 +1904,7 @@ This is equivalent to the `--dns-search` option of `podman build`.
### `Environment=` ### `Environment=`
Add a value (e.g. env=*value*) to the built image. This uses the same format as [services in 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 systemd](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Environment=) and can be
listed multiple times. listed multiple times.
@@ -1954,7 +1964,7 @@ This key can be listed multiple times. The first instance will be used as the na
### `Label=` ### `Label=`
Add an image *label* (e.g. label=*value*) to the image metadata. Can be used multiple times. 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`. This is equivalent to the `--label` option of `podman build`.
@@ -1966,7 +1976,7 @@ or `none` to not set up networking.
Special case: 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. - 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. This key can be listed multiple times.
@@ -2061,7 +2071,7 @@ If `SOURCE-VOLUME` starts with `.`, Quadlet resolves the path relative to the lo
Special case: 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. - 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. This key can be listed multiple times.
@@ -2077,7 +2087,7 @@ particularly interesting when using special options to control image pulls.
Valid options for `[Image]` are listed below: Valid options for `[Image]` are listed below:
| **[Image] options** | **podman image pull equivalent** | | **[Image] options** | **podman image pull equivalent** |
|----------------------------------------|--------------------------------------------------| | -------------------------------------- | ------------------------------------------------ |
| AllTags=true | --all-tags | | AllTags=true | --all-tags |
| Arch=aarch64 | --arch=aarch64 | | Arch=aarch64 | --arch=aarch64 |
| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json | | AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json |
@@ -2117,7 +2127,7 @@ This is equivalent to the Podman `--authfile` option.
### `CertDir=` ### `CertDir=`
Use certificates at path (*.crt, *.cert, *.key) to connect to the registry. Use certificates at path (_.crt, _.cert, \*.key) to connect to the registry.
This is equivalent to the Podman `--cert-dir` option. This is equivalent to the Podman `--cert-dir` option.
@@ -2170,6 +2180,7 @@ For example, an image saved into a `docker-archive` with the following Podman co
`podman image save --format docker-archive --output /tmp/archive-file.tar quay.io/podman/stable:latest` `podman image save --format docker-archive --output /tmp/archive-file.tar quay.io/podman/stable:latest`
requires setting requires setting
- `Image=docker-archive:/tmp/archive-file.tar` - `Image=docker-archive:/tmp/archive-file.tar`
- `ImageTag=quay.io/podman/stable:latest` - `ImageTag=quay.io/podman/stable:latest`
@@ -2241,7 +2252,7 @@ particularly useful for managing artifacts that containers need to mount or acce
Valid options for `[Artifact]` are listed below: Valid options for `[Artifact]` are listed below:
| **[Artifact] options** | **podman artifact pull equivalent** | | **[Artifact] options** | **podman artifact pull equivalent** |
|---------------------------------------------|--------------------------------------------------------| | ----------------------------------------- | ----------------------------------------------------- |
| Artifact=quay\.io/foobar/artifact:special | podman artifact pull quay\.io/foobar/artifact:special | | Artifact=quay\.io/foobar/artifact:special | podman artifact pull quay\.io/foobar/artifact:special |
| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json | | AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json |
| CertDir=/etc/registry/certs | --cert-dir=/etc/registry/certs | | CertDir=/etc/registry/certs | --cert-dir=/etc/registry/certs |
@@ -2271,7 +2282,7 @@ This is equivalent to the Podman `--authfile` option.
### `CertDir=` ### `CertDir=`
Use certificates at path (*.crt, *.cert, *.key) to connect to the registry. Use certificates at path (_.crt, _.cert, \*.key) to connect to the registry.
This is equivalent to the Podman `--cert-dir` option. This is equivalent to the Podman `--cert-dir` option.
@@ -2343,13 +2354,14 @@ Require HTTPS and verification of certificates when contacting registries.
This is equivalent to the Podman `--tls-verify` option. This is equivalent to the Podman `--tls-verify` option.
## Quadlet section [Quadlet] ## Quadlet section [Quadlet]
Some quadlet specific configuration is shared between different unit types. Those settings Some quadlet specific configuration is shared between different unit types. Those settings
can be configured in the `[Quadlet]` section. can be configured in the `[Quadlet]` section.
Valid options for `[Quadlet]` are listed below: Valid options for `[Quadlet]` are listed below:
| **[Quadlet] options** | **Description** | | **[Quadlet] options** | **Description** |
|----------------------------|---------------------------------------------------| | ------------------------- | ------------------------------------------------- |
| DefaultDependencies=false | Disable implicit network dependencies to the unit | | DefaultDependencies=false | Disable implicit network dependencies to the unit |
### `DefaultDependencies=` ### `DefaultDependencies=`
@@ -2395,6 +2407,7 @@ WantedBy=multi-user.target default.target
``` ```
Example `test.kube`: Example `test.kube`:
``` ```
[Unit] [Unit]
Description=A kubernetes yaml based service Description=A kubernetes yaml based service
@@ -2411,6 +2424,7 @@ WantedBy=multi-user.target default.target
Example for locally built image to be used in a container with build-specific arguments: Example for locally built image to be used in a container with build-specific arguments:
`test.build` `test.build`
``` ```
[Build] [Build]
# Tag the image to be built # Tag the image to be built
@@ -2426,6 +2440,7 @@ BuildArg=VERSION=1.0 \
``` ```
`test.container` `test.container`
``` ```
[Container] [Container]
Image=test.build Image=test.build
@@ -2441,6 +2456,7 @@ Label=org.test.Key=value
``` ```
Example `test.network`: Example `test.network`:
``` ```
[Network] [Network]
Subnet=172.16.0.0/24 Subnet=172.16.0.0/24
@@ -2450,6 +2466,7 @@ Label=org.test.Key=value
``` ```
Example `test.artifact` to only pull the artifact using one auth file: Example `test.artifact` to only pull the artifact using one auth file:
``` ```
[Artifact] [Artifact]
Artifact=quay.io/example/my-artifact:latest Artifact=quay.io/example/my-artifact:latest
@@ -2460,12 +2477,14 @@ TLSVerify=false
Example usage where a container depends on an artifact: Example usage where a container depends on an artifact:
`my-artifact.artifact`: `my-artifact.artifact`:
``` ```
[Artifact] [Artifact]
Artifact=quay.io/example/my-config:latest Artifact=quay.io/example/my-config:latest
``` ```
`my-app.container`: `my-app.container`:
``` ```
[Container] [Container]
Image=quay.io/example/my-app:latest Image=quay.io/example/my-app:latest
@@ -2475,12 +2494,14 @@ Mount=type=artifact,source=my-artifact.artifact,destination=/etc/config
Example for a container in a Pod: Example for a container in a Pod:
`test.pod` `test.pod`
``` ```
[Pod] [Pod]
PodName=test PodName=test
``` ```
`centos.container` `centos.container`
``` ```
[Container] [Container]
Image=quay.io/centos/centos:latest Image=quay.io/centos/centos:latest
@@ -2491,6 +2512,7 @@ Pod=test.pod
Example for a Pod with a one-shot startup task: Example for a Pod with a one-shot startup task:
`test.pod` `test.pod`
``` ```
[Pod] [Pod]
PodName=test PodName=test
@@ -2498,6 +2520,7 @@ ExitPolicy=continue
``` ```
`startup-task.container` `startup-task.container`
``` ```
[Service] [Service]
Type=oneshot Type=oneshot
@@ -2510,6 +2533,7 @@ Exec=sh -c "echo 'setup starting'; sleep 2; echo 'setup complete'"
``` ```
`app.container` `app.container`
``` ```
[Unit] [Unit]
Requires=startup-task.container Requires=startup-task.container
@@ -2548,6 +2572,7 @@ Options=iam_role,endpoint=${AWS_REGION},use_xattr,listobjectsv2,del_cache,use_ca
``` ```
## SEE ALSO ## SEE ALSO
**[systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html)**, **[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.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)**, **[systemd-analyze(1)](https://www.freedesktop.org/software/systemd/man/latest/systemd-analyze.html)**,
+29
View File
@@ -0,0 +1,29 @@
#!/bin/sh
set -eu
# Copy reviewed Quadlet unit files into the target Quadlet directory.
# Update the variables below before using this template.
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
QUADLET_PREFIX='app-'
QUADLET_TARGET_DIR="${HOME}/.config/containers/systemd"
list_quadlet_files() {
for ext in container pod network volume build image kube; do
for file in "$SCRIPT_DIR"/"$QUADLET_PREFIX"*."$ext"; do
[ -e "$file" ] || continue
printf '%s\n' "$file"
done
done | LC_ALL=C sort -u
}
files=$(list_quadlet_files)
[ -n "$files" ] || {
printf 'No Quadlet files found for prefix %s\n' "$QUADLET_PREFIX" >&2
exit 1
}
mkdir -p -- "$QUADLET_TARGET_DIR"
printf '%s\n' "$files" | while IFS= read -r file; do
install -m 0644 -- "$file" "$QUADLET_TARGET_DIR/$(basename -- "$file")"
done
+11
View File
@@ -0,0 +1,11 @@
#!/bin/sh
set -eu
# Reload systemd after reviewed Quadlet unit changes.
# Update the systemctl_cmd() function below before using this template.
systemctl_cmd() {
systemctl --user "$@"
}
systemctl_cmd daemon-reload
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
set -eu
# Restart the reviewed lifecycle unit(s).
# Update the variables and systemctl_cmd() function below before using this template.
LIFECYCLE_UNITS='app-pod.service'
systemctl_cmd() {
systemctl --user "$@"
}
for unit in $LIFECYCLE_UNITS; do
systemctl_cmd restart "$unit"
done
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
set -eu
# Start the reviewed lifecycle unit(s).
# Update the variables and systemctl_cmd() function below before using this template.
LIFECYCLE_UNITS='app-pod.service'
systemctl_cmd() {
systemctl --user "$@"
}
for unit in $LIFECYCLE_UNITS; do
systemctl_cmd start "$unit"
done
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
set -eu
# Stop the reviewed lifecycle unit(s).
# Update the variables and systemctl_cmd() function below before using this template.
LIFECYCLE_UNITS='app-pod.service'
systemctl_cmd() {
systemctl --user "$@"
}
for unit in $LIFECYCLE_UNITS; do
systemctl_cmd stop "$unit"
done
+37
View File
@@ -0,0 +1,37 @@
#!/bin/sh
set -eu
# Stop the reviewed lifecycle unit(s), then remove installed Quadlet unit files.
# Update the variables and systemctl_cmd() function below before using this template.
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
QUADLET_PREFIX='app-'
QUADLET_TARGET_DIR="${HOME}/.config/containers/systemd"
LIFECYCLE_UNITS='app-pod.service'
systemctl_cmd() {
systemctl --user "$@"
}
list_quadlet_files() {
for ext in container pod network volume build image kube; do
for file in "$SCRIPT_DIR"/"$QUADLET_PREFIX"*."$ext"; do
[ -e "$file" ] || continue
printf '%s\n' "$file"
done
done | LC_ALL=C sort -u
}
files=$(list_quadlet_files)
[ -n "$files" ] || {
printf 'No Quadlet files found for prefix %s\n' "$QUADLET_PREFIX" >&2
exit 1
}
for unit in $LIFECYCLE_UNITS; do
systemctl_cmd stop "$unit" || true
done
printf '%s\n' "$files" | while IFS= read -r file; do
rm -f -- "$QUADLET_TARGET_DIR/$(basename -- "$file")"
done
+1
View File
@@ -68,6 +68,7 @@ Before calling the result runnable, verify that:
- repo-local entrypoint or helper scripts referenced by the container exist and are executable when needed - repo-local entrypoint or helper scripts referenced by the container exist and are executable when needed
- initialization assets such as `init.sql`, seeds, bootstrap files, or config templates are present where the deployment expects them - initialization assets such as `init.sql`, seeds, bootstrap files, or config templates are present where the deployment expects them
- service-management scripts operate on the same reviewed artifact set that finalize approved - service-management scripts operate on the same reviewed artifact set that finalize approved
- helper shell scripts match reviewed Quadlet files by their shared generated prefix with globbing such as `<prefix>*`, not hardcoded filenames or assumed file counts
Runnable-output gate checklist template: Runnable-output gate checklist template: