Re: [meta-virtualization][PATCH 5/7] recipes-containers/images: add app-container-nginx

Tim Orling <[email protected]> Fri, 03 Jul 2026 08:28:19 -0700
Newsgroups org.yoctoproject.lists.meta-virtualization
Message-ID <178309249987.29524.16274527706941065904.b4-reply@b4>
On 2026-06-12 11:15:22-07:00, Bruce Ashfield wrote:
> Hi Tim,
> 
> Most complex recipe in the series, and I like the the runtime-dir
> handling
> 
> A few nginx-specific things, that came up when I was searching up
> the runtime parts.
> 
> On Fri, May 29, 2026 at 18:31 -0700, Tim Orling wrote:
> 
> > Add OCI container image recipe for the NGINX web server. The image
> > uses multi-layer mode with separate base, nginx packages, nginx
> > runtime directories, and nginx log file layers.
> 
> [...]
> 
> > +NONROOT_USER = "nginx"
> 
> The biggest open question here. The nginx recipe in meta-webserver
> creates its own 'nginx' user (via useradd in inherit useradd or a
> postinst), with a uid the package picks. Now we have two paths trying
> to create user 'nginx':
> 
>   a) container-nonroot-user.bbclass adds it via extrausers as uid
>      65532 / gid 65532 (whatever NONROOT_UID/GID are set to).
> 
>   b) The nginx package's own user-creation step adds it with the
>      package's chosen uid.
> 
> Last one to run wins in /etc/passwd, but RPM/dpkg may also refuse a
> duplicate-uid useradd outright. Did you see any "user already exists"
> or uid-mismatch noise in do_rootfs? If not, the order happens to be
> fine in your build but it's fragile.
> 
> Are these options for v2 ?
> 
>   1) Override NONROOT_UID to whatever the nginx package picks for the
>      nginx user. Looks up the package's uid, set NONROOT_UID to match.
> 
>   2) Use NONROOT_USER = "nginxapp" or similar — a name that doesn't
>      collide with the package's own — and tell nginx to run as that
>      user via the conf file (`user nginxapp;`) instead of relying on
>      the implicit uid match.
> 
> Not blocking but worth a note in the recipe about which approach you
> chose and why, so we won't get cut and paste propagation without
> a reason.

Previously, our container was not even running as 'nonroot' user because of
inheritance order of image-oci and container-nonroot-user, this has been fixed.

Now, in container-nonroot-user, the UID:GID of the 'nginx' user is
changed to the 65532 'nonroot' user values in the layer which provides
/etc/passwd. The reason for keeping the 'nginx' user name is that there
are a number of places where upstream nginx uses the 'nginx' user name
explicitly. This is why the dhi.io/nginx:1.30 container sets the
'nonroot' user to have the 'nginx' user name. See for instance:
https://github.com/docker-hardened-images/catalog/blob/main/image/nginx/debian-13/stable.yaml#L81

One other issue that presented itself once we are running as uid 65532
was directory ownership. This has been fixed with the introduction of the
NONROOT_OWNED_DIRS list variable which fixes the ownership in the same
'raw' layer as the '/home/<nonroot_username>' was being fixed.

> 
> > +OCI_LAYERS = "\
> > +    base:packages:base-files+base-passwd+netbase \
> > +    nginx:packages:nginx \
> > +    nginx-dirs:directories:${localstatedir}/log/nginx+/run/nginx+${localstatedir}/volatile/tmp+${localstatedir}/volatile/log \
> > +    nginx-files:files:${localstatedir}/log/nginx/access.log+${localstatedir}/log/nginx/error.log \
> > +"
> 
> Nice mix of packages + directories + files layer types in a single
> recipe — this is exactly the scenario the multi-layer support was
> built for, glad to see it landing in a real recipe.
> 
> > +    # nginx opens the compiled-in error_log path before reading -c config.
> > +    # /var/log is typically a symlink to /var/volatile/log in a Yocto rootfs,
> > +    # so create the target path explicitly to guarantee the directory lands in
> > +    # the container layer regardless of symlink resolution order.
> > +    install -m 755 -d ${IMAGE_ROOTFS}/${localstatedir}/log
> > +    install -m 755 -d ${IMAGE_ROOTFS}/${localstatedir}/log/nginx
> > +
> > +    # nginx's compiled-in temp paths (client_body_temp, proxy_temp, etc.) all
> > +    # live under /run/nginx, which is not created by any package.
> > +    install -m 755 -d ${IMAGE_ROOTFS}/run/nginx
> 
> The /run/nginx catch is great — that's the kind of thing that bites
> you at first-request time and you can't reproduce without the right
> URL hitting the right module. Good comment too.
> 
> > +OCI_IMAGE_APP_RECIPE = "nginx"
> 
> Glad to see this in use. It's been sitting in image-oci.bbclass as
> documentation-only / hook-point, and this is the first recipe that
> actually sets it. Once we wire it up to auto-extract SRCREV/branch
> for OCI labels (the "future versions may auto-extract" hook comment
> in the bbclass), recipes that set it correctly will get the
> provenance labels for free.
> 
> Bruce