|
| 1 | +# Change Request |
| 2 | + |
| 3 | +<!-- |
| 4 | +This template is used to propose and discuss major new features to be added to Podman, Buildah, Skopeo, Netavark, and associated libraries. |
| 5 | +The creation of a design document prior to feature implementation is not mandatory, but is encouraged. |
| 6 | +Before major features are implemented, a pull request should be opened against the Podman repository with a completed version of this template. |
| 7 | +Discussion on the feature will occur in the pull request. |
| 8 | +Merging the pull request will constitute approval by project maintainers to proceed with implementation work. |
| 9 | +When the feature is completed and merged, this document should be removed to avoid cluttering the repository. |
| 10 | +It will remain in the Git history for future retrieval if necessary. |
| 11 | +--> |
| 12 | + |
| 13 | +## **Short Summary** |
| 14 | + |
| 15 | +Unify (and rework) our config file parsing logic to make the various config files all behave |
| 16 | +the same parsing wise so users can better understand how it works. |
| 17 | + |
| 18 | +## **Objective** |
| 19 | + |
| 20 | +We have several config files such a containers.conf, storage.conf, registries.conf and more that |
| 21 | +get all implement their own parsing logic and have a different feature set. The goal is to |
| 22 | +consolidate the parsing into a separate package and then port all files to use that package |
| 23 | +instead making them behave consistently. |
| 24 | + |
| 25 | +## **Detailed Description:** |
| 26 | + |
| 27 | +### General |
| 28 | + |
| 29 | +Add new package to the storage library (`go.podman.io/storage/pkg/configfile`) which implements |
| 30 | +the core logic of how to read config files. The goal of the package is to define with config paths |
| 31 | +to use and in what order. |
| 32 | + |
| 33 | +It will however not define the structs and fields used for the actual content in each file, these |
| 34 | +stay where there are defined currently and the plan is to have the code there call into the `configfile` |
| 35 | +package to read the files in the same way. |
| 36 | + |
| 37 | +#### Search locations: |
| 38 | + |
| 39 | +Linux: |
| 40 | + |
| 41 | +- `/usr/share/containers/<name>.conf` |
| 42 | +- `/usr/share/containers/<name>.conf.d/` |
| 43 | +- `/usr/share/containers/<name>.rootful.conf.d/` (only when UID == 0) |
| 44 | +- `/usr/share/containers/<name>.rootless.conf.d/` (only when UID > 0) |
| 45 | +- `/usr/share/containers/<name>.rootless.conf.d/<UID>/` (only when UID > 0) |
| 46 | + |
| 47 | +- `/etc/containers/<name>.conf` |
| 48 | +- `/etc/containers/<name>.conf.d/` |
| 49 | +- `/etc/containers/<name>.rootful.conf.d/` (only when UID == 0) |
| 50 | +- `/etc/containers/<name>.rootless.conf.d/` (only when UID > 0) |
| 51 | +- `/etc/containers/<name>.rootless.conf.d/<UID>/` (only when UID > 0) |
| 52 | + |
| 53 | +- `$XDG_CONFIG_HOME/containers/<name>.conf` |
| 54 | +- `$XDG_CONFIG_HOME/containers/<name>.conf.d/` |
| 55 | + (if $XDG_CONFIG_HOME is empty then it uses $HOME/.config) |
| 56 | + This homedir lookup will also be done by root [1]. |
| 57 | + |
| 58 | +Where `<name>` is `containers`, `storage` or `registries` for each config file. |
| 59 | + |
| 60 | +The `<name>.rootless.conf.d/<UID>/` is a directory named by the user id. Only the user with this |
| 61 | +exact uid match will read the config files in this directory. |
| 62 | +The use case is for admin to be able to set a default for a specific user without having to write |
| 63 | +into their home directory. Note this is not intended as security mechanism, the user home directory |
| 64 | +config files will still have higher priority. |
| 65 | + |
| 66 | +FreeBSD: |
| 67 | + |
| 68 | +Same as Linux except `/usr/share` is `/usr/local/share` and `/etc` is `/usr/local/etc`. |
| 69 | + |
| 70 | +Windows: |
| 71 | + |
| 72 | +There is no `/usr` equivalent, for `/etc` we instead lookup `ProgramData` env and use that one. |
| 73 | +And instead of `XDG_CONFIG_HOME` which isn't used on windows we use `APPDATA`. |
| 74 | + |
| 75 | +MacOS: |
| 76 | + |
| 77 | +Same as Linux. |
| 78 | + |
| 79 | +#### Load order |
| 80 | + |
| 81 | +I propose adopting the UAPI config file specification for loading config files (version 1.0): |
| 82 | +https://uapi-group.org/specifications/specs/configuration_files_specification/ |
| 83 | + |
| 84 | +Based on that the files must be loaded in this order: |
| 85 | + |
| 86 | +Read `$XDG_CONFIG_HOME/containers/<name>.conf`, only if this file doesn't exists read |
| 87 | +`/etc/containers/<name>.conf`, and if that doesn't exists read `/usr/share/containers/<name>.conf` |
| 88 | +As such setting an empty file on `$XDG_CONFIG_HOME/containers/<name>.conf` would cause us to ignore |
| 89 | +all possible options there were set in the other files. |
| 90 | +Note: This is different from the current containers.conf loading where we would have read all files. |
| 91 | + |
| 92 | +Regardless of which file has been loaded above it then must read the drop-in locations in the following order: |
| 93 | + |
| 94 | +- `/usr/share/containers/<name>.conf.d/` |
| 95 | +- `/usr/share/containers/<name>.rootful.conf.d/` (UID == 0) |
| 96 | +- `/usr/share/containers/<name>.rootless.conf.d/` (UID > 0) |
| 97 | +- `/usr/share/containers/containers.rootless.conf.d/<UID>/` (UID > 0) |
| 98 | + |
| 99 | +- `/etc/containers/<name>.conf.d/` |
| 100 | +- `/etc/containers/<name>.rootful.conf.d/` (UID == 0) |
| 101 | +- `/etc/containers/<name>.rootless.conf.d/` (UID > 0) |
| 102 | +- `/etc/containers/containers.rootless.conf.d/<UID>/` (UID > 0) |
| 103 | + |
| 104 | +- `$XDG_CONFIG_HOME/containers/<name>.conf.d/` |
| 105 | + |
| 106 | +Only files read with the `.conf` file extension are read. |
| 107 | + |
| 108 | +If there is a drop-in file with the same filename as in a prior location it will replace |
| 109 | +the prior one and only the latest match is read. Once we have the list of all drop-in files |
| 110 | +they get sorted lexicographic. The later files have a higher priority so they can overwrite |
| 111 | +options set in a prior file. |
| 112 | + |
| 113 | +##### Example |
| 114 | + |
| 115 | +Consider the following files: |
| 116 | + |
| 117 | +`/usr/share/containers/containers.conf` (overridden by `/etc/containers/containers.conf`): |
| 118 | +``` |
| 119 | +field_1 = a |
| 120 | +``` |
| 121 | + |
| 122 | +`/etc/containers/containers.conf`: |
| 123 | +``` |
| 124 | +field_2 = b |
| 125 | +``` |
| 126 | + |
| 127 | +`/usr/share/containers/containers.conf.d/10-vendor.conf` (overridden by `$XDG_CONFIG_HOME/containers/containers.conf.d/10-vendor.conf`): |
| 128 | +``` |
| 129 | +field_3 = c |
| 130 | +``` |
| 131 | + |
| 132 | +`/usr/share/containers/containers.conf.d/99-important.conf`: |
| 133 | +``` |
| 134 | +field_4 = d |
| 135 | +``` |
| 136 | + |
| 137 | +`/usr/share/containers/containers.rootless.conf.d/50-my.conf`: |
| 138 | +``` |
| 139 | +field_5 = e |
| 140 | +``` |
| 141 | + |
| 142 | +`$XDG_CONFIG_HOME/containers/containers.conf.d/10-vendor.conf`: |
| 143 | +``` |
| 144 | +# empty |
| 145 | +``` |
| 146 | + |
| 147 | +`$XDG_CONFIG_HOME/containers/containers.conf.d/33-opt.conf` (this is read but field_4 is overridden by `/usr/share/containers/containers.conf.d/99-important.conf` as `99-important.conf` is sorted later): |
| 148 | +``` |
| 149 | +field_4 = user |
| 150 | +field_6 = f |
| 151 | +``` |
| 152 | + |
| 153 | +Now parsing this as user with UID 1000 results in this final config: |
| 154 | + |
| 155 | +``` |
| 156 | +field_2 = b |
| 157 | +field_4 = d |
| 158 | +field_5 = e |
| 159 | +field_6 = f |
| 160 | +``` |
| 161 | + |
| 162 | +#### Environment Variables |
| 163 | + |
| 164 | +The following two envs should be defined for each config file: |
| 165 | + |
| 166 | +`CONTAINERS_<name>_CONF`: If set only read the given file in this env and nothing else. |
| 167 | +`CONTAINERS_<name>_CONF_OVERRIDE`: If set append the given file as last file after parsing |
| 168 | +all other files as normal. Useful to overwrite a single field for testing without overwriting |
| 169 | +the rest of the system configuration. |
| 170 | + |
| 171 | +As special case for containers.conf the name of the vars is `CONTAINERS_CONF` and `CONTAINERS_CONF_OVERRIDE`. |
| 172 | + |
| 173 | +The handling of these should be part of the `configfile` package. |
| 174 | + |
| 175 | +#### Appending arrays |
| 176 | + |
| 177 | +The toml parser by default replaces arrays in each file which makes it impossible to append values in drop-ins, etc... |
| 178 | + |
| 179 | +containers.conf already has a work for that with a custom syntax to trigger appending: |
| 180 | +``` |
| 181 | +field = ["val", {append=true}] |
| 182 | +``` |
| 183 | +I propose we adapt the same universally for the other config files. |
| 184 | + |
| 185 | +https://github.com/containers/container-libs/blob/main/common/docs/containers.conf.5.md#appending-to-string-arrays |
| 186 | + |
| 187 | +This means moving the `common/internal/attributedstring` into the new configfile package so all callers can use it. |
| 188 | + |
| 189 | +#### Scope |
| 190 | + |
| 191 | +##### containers.conf |
| 192 | + |
| 193 | +No changes except `/etc/containers/containers.rootless.conf` search location has been removed. It has just been added |
| 194 | +in 5.7 so I don't think it would cause major concerns to drop it again. |
| 195 | + |
| 196 | +The reason to not support the main file with rootless/rootful now is that it is not obvious how this should interact |
| 197 | +with the parsing, should it replace the main config file or act like a drop in? As such I think it is better to not |
| 198 | +support this and we should generally push all users to use a drop instead of editing the main file. |
| 199 | + |
| 200 | +Also there was/is some discussion of splitting containers.conf in two files as currently there are fields in there |
| 201 | +that are only read on the server side while others only get used on the client side which makes using it in a remote |
| 202 | +context such as podman machine confusing. For now this is not part of this design doc, we may make another design docs |
| 203 | +just for this in case we like to move forward on it. |
| 204 | + |
| 205 | +containers.conf also supports "Modules", i.e. `podman --module name.conf ...` which adds additional drop-in files at |
| 206 | +the end after the regular config files. This functionality should be preserved but don't expand module support to the |
| 207 | +other files. |
| 208 | + |
| 209 | +##### storage.conf |
| 210 | + |
| 211 | +Deprecate `rootless_storage_path` option. With the `rootless/rootful` config location and admin could just use |
| 212 | +`graphroot` in the location in the rootless file location. As such there is no need to special case these fields |
| 213 | +in the parser. |
| 214 | + |
| 215 | +String arrays in the config will need to get switched to the attributedstring type, as described under Appending arrays. |
| 216 | + |
| 217 | +##### registries.conf |
| 218 | + |
| 219 | +Remove V1 config layout to simplify the parsing logic. If we do major config changes we might as well take the |
| 220 | +chance and remove this old format. |
| 221 | +Currently the V1 format is already rejected for drop-in files so this just effects the main config file. |
| 222 | + |
| 223 | +Additionally there might be a few challenges here, c/image uses the SystemContext struct which allows |
| 224 | +users to set `RootForImplicitAbsolutePaths`, `SystemRegistriesConfPath`, `SystemRegistriesConfDirPath`. |
| 225 | +We must continue to support them as they are used by various tools. |
| 226 | +For `RootForImplicitAbsolutePaths` we update it to check bot the `/usr` and `/etc` locations. |
| 227 | +When `SystemRegistriesConfPath` or `SystemRegistriesConfDirPath` are used don't do the normal parsing |
| 228 | +and just read the file/directory specified there. |
| 229 | + |
| 230 | +As described under the Environment Variables section the handling for `CONTAINERS_REGISTRIES_CONF` is moved |
| 231 | +out of Podman, and common/libimage into the actual `configfile` package. As such all users of c/image will |
| 232 | +be able to use this without having each caller specify their own env. |
| 233 | +As part of this I propose removing support for the old `REGISTRIES_CONFIG_PATH` env which was never documented |
| 234 | +and replaced by `CONTAINERS_REGISTRIES_CONF` in commit c9ef2607104a0b17e5146b3ee01852edb7d3d688 (over 4 years ago). |
| 235 | +Currently there is an issue because Buildah doesn't support it [4]. |
| 236 | + |
| 237 | +String arrays in the config will need to get switched to the attributedstring type, as described under Appending arrays. |
| 238 | + |
| 239 | +#### Maybe in scope? |
| 240 | + |
| 241 | +##### registries.d |
| 242 | + |
| 243 | +Note registries.d is confusingly a completely different config file format from registries.conf.d. |
| 244 | + |
| 245 | +It is unclear to me what we should do with this. Do we want to adopt the drop in logic as explained above? |
| 246 | +Right now it only uses `$HOME/.config/containers/registries.d` or `/etc/containers/registries.d` |
| 247 | + |
| 248 | +I think for consistency it would be best if it uses all drop in paths like shown above. |
| 249 | +At least we should add `/usr/share/containers` lookup locations. |
| 250 | + |
| 251 | +Additionally there seems to exit code duplication in `podman/pkg/trust`. We should find a way to |
| 252 | +not duplicate this logic at all. |
| 253 | + |
| 254 | +##### certs.d |
| 255 | + |
| 256 | +Same point as for registries.d. Should we make it also use all paths? |
| 257 | +There is also an open issue for proper XDG_CONFIG_HOME support [2]. |
| 258 | + |
| 259 | +##### policy.json |
| 260 | + |
| 261 | +This is a json file so I don't think the normal drop-in logic would be particular useful here. Though |
| 262 | +I think it should read at least also `/usr/share/containers/policy.json`. |
| 263 | + |
| 264 | +It is also missing the XDG_CONFIG_HOME support [3]. |
| 265 | + |
| 266 | +## **Use cases** |
| 267 | + |
| 268 | +A better way to configure podman and a better understanding for users how to do it without having |
| 269 | +to worry that each config file behaves differently. |
| 270 | +Since we then have only once place that defines the load order we can have a single man page |
| 271 | +documenting the load order as described above. All the config files man pages can then just |
| 272 | +refer to that and we don't have to duplicate so much docs. |
| 273 | + |
| 274 | +By adding `/usr/share/containers` locations for all config files vendors can properly ship default |
| 275 | +configurations there without causing package/user conflicts in `/etc` when admins also want to set |
| 276 | +a default config. |
| 277 | +This helps "Image Mode" or "Atomic" distributions which tend to prefer using /usr for configuration |
| 278 | +when possible, i.e. |
| 279 | +https://bootc-dev.github.io/bootc/building/guidance.html#configuration-in-usr-vs-etc |
| 280 | +Given the increased importance of podman on such distributions it makes sense to support /usr configs |
| 281 | +universally. |
| 282 | + |
| 283 | +## **Target Podman Release** |
| 284 | + |
| 285 | +6.0 (Because this is a breaking change a major release is required and this work must be finished in time) |
| 286 | + |
| 287 | +## **Link(s)** |
| 288 | + |
| 289 | + |
| 290 | +- [1] https://github.com/containers/podman/issues/27227 |
| 291 | +- [2] https://github.com/containers/container-libs/issues/183 |
| 292 | +- [3] https://github.com/containers/container-libs/issues/202 |
| 293 | +- [4] https://github.com/containers/buildah/issues/6468 |
| 294 | +- https://github.com/containers/container-libs/issues/164 |
| 295 | +- https://github.com/containers/container-libs/issues/476 |
| 296 | + |
| 297 | +- https://github.com/containers/container-libs/issues/234 |
| 298 | + |
| 299 | + |
| 300 | +## **Stakeholders** |
| 301 | + |
| 302 | + |
| 303 | +- [x] Podman Users |
| 304 | +- [x] Podman Developers |
| 305 | +- [x] Buildah Users |
| 306 | +- [x] Buildah Developers |
| 307 | +- [x] Skopeo Users |
| 308 | +- [x] Skopeo Developers |
| 309 | +- [x] Podman Desktop |
| 310 | +- [x] CRI-O |
| 311 | +- [x] Storage library |
| 312 | +- [x] Image library |
| 313 | +- [x] Common library |
| 314 | +- [ ] Netavark and aardvark-dns |
| 315 | + |
| 316 | +## ** Assignee(s) ** |
| 317 | + |
| 318 | +- Paul Holzinger (@Luap99) |
| 319 | + |
| 320 | +## **Impacts** |
| 321 | + |
| 322 | +### **CLI** |
| 323 | + |
| 324 | +The cli should not change based on this. |
| 325 | + |
| 326 | +### **Libpod** |
| 327 | + |
| 328 | +No changes to libpod. |
| 329 | + |
| 330 | +### **Others** |
| 331 | + |
| 332 | +The major work will happen in the container-libs monorepo as this contains the file parsing logic for all. |
| 333 | + |
| 334 | +## **Further Description (Optional):** |
| 335 | + |
| 336 | +<!-- |
| 337 | +Is there anything not covered above that needs to be mentioned? |
| 338 | +--> |
| 339 | + |
| 340 | +## **Test Descriptions (Optional):** |
| 341 | + |
| 342 | +The code should be designed in a way to be unit testable and that they get parsed in the right order. |
0 commit comments