all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH container 0/2] oci create: honor `User` from OCI image config
@ 2025-12-15 17:41 Filip Schauer
  2025-12-15 17:41 ` [pve-devel] [PATCH container 1/2] config: add `lxc.init.uid`/`gid`/`groups` keys Filip Schauer
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Filip Schauer @ 2025-12-15 17:41 UTC (permalink / raw)
  To: pve-devel

Honor a custom user and group specified for the entrypoint via the OCI
image config `User` field instead of ignoring it.

This requires the following patch for LXC in order to work properly:
https://github.com/lxc/lxc/pull/4626

With these patches applied, docker.io/weblate/weblate starts with the
correct uid and groups instead of the default uid=0(root) gid=0(root)
groups=0(root).

Filip Schauer (2):
  config: add `lxc.init.uid`/`gid`/`groups` keys
  oci create: honor User from OCI image config

 src/PVE/LXC/Config.pm |  3 +++
 src/PVE/LXC/Create.pm | 59 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pve-devel] [PATCH container 1/2] config: add `lxc.init.uid`/`gid`/`groups` keys
  2025-12-15 17:41 [pve-devel] [PATCH container 0/2] oci create: honor `User` from OCI image config Filip Schauer
@ 2025-12-15 17:41 ` Filip Schauer
  2025-12-15 17:41 ` [pve-devel] [PATCH container 2/2] oci create: honor `User` from OCI image config Filip Schauer
  2025-12-16 12:03 ` [pve-devel] [PATCH container 0/2] " Maximiliano Sandoval
  2 siblings, 0 replies; 6+ messages in thread
From: Filip Schauer @ 2025-12-15 17:41 UTC (permalink / raw)
  To: pve-devel

These config keys allow one to specify the uid, gid and groups of the
init process. This is useful for application containers.

Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
 src/PVE/LXC/Config.pm | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index 6445528..6f54e9f 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -711,6 +711,9 @@ my $valid_lxc_conf_keys = {
     'lxc.signal.stop' => 1,
     'lxc.init.cmd' => 1,
     'lxc.init.cwd' => 1,
+    'lxc.init.uid' => 1,
+    'lxc.init.gid' => 1,
+    'lxc.init.groups' => 1,
     'lxc.pty.max' => 1,
     'lxc.console.logfile' => 1,
     'lxc.console.path' => 1,
-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pve-devel] [PATCH container 2/2] oci create: honor `User` from OCI image config
  2025-12-15 17:41 [pve-devel] [PATCH container 0/2] oci create: honor `User` from OCI image config Filip Schauer
  2025-12-15 17:41 ` [pve-devel] [PATCH container 1/2] config: add `lxc.init.uid`/`gid`/`groups` keys Filip Schauer
@ 2025-12-15 17:41 ` Filip Schauer
  2026-01-15 13:18   ` Wolfgang Bumiller
  2025-12-16 12:03 ` [pve-devel] [PATCH container 0/2] " Maximiliano Sandoval
  2 siblings, 1 reply; 6+ messages in thread
From: Filip Schauer @ 2025-12-15 17:41 UTC (permalink / raw)
  To: pve-devel

Honor a custom user and group specified for the entrypoint via the OCI
image config `User` field instead of ignoring it.

User and group name lookups, including supplementary groups, are
resolved from /etc/passwd and /etc/group in the container file system.
This behaviour matches the OCI image spec. [0]

[0] https://specs.opencontainers.org/image-spec/config/?v=v1.1.1#properties

Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
This requires the following patch for LXC in order to work properly:
https://github.com/lxc/lxc/pull/4626

 src/PVE/LXC/Create.pm | 59 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
index 9956cf9..08e0386 100644
--- a/src/PVE/LXC/Create.pm
+++ b/src/PVE/LXC/Create.pm
@@ -768,6 +768,65 @@ sub restore_oci_archive {
         }
     }
 
+    if (my $usercfg = $oci_config_get_checked_scalar->('User')) {
+        my ($user, $group) = $usercfg =~ /^([^:]+)(?::([^:]+))?$/
+            or die "OCI config value for 'User' has an invalid format\n";
+
+        my $etc_passwd = "$rootdir/etc/passwd";
+        my $etc_group = "$rootdir/etc/group";
+
+        # Scan file, match column $match_index against $match_val, return value at $ret_index
+        my $lookup_field = sub {
+            my ($file, $match_index, $match_val, $ret_index) = @_;
+
+            open(my $fh, '<', $file) or return undef;
+            while (my $line = <$fh>) {
+                my @fields = split(/:/, $line);
+                if (defined($fields[$match_index]) && $fields[$match_index] eq $match_val) {
+                    return $fields[$ret_index];
+                }
+            }
+            return undef;
+        };
+
+        my $get_supplementary_groups = sub {
+            my ($username) = @_;
+
+            my @groups;
+            open(my $fh, '<', $etc_group) or return undef;
+            while (defined(my $line = <$fh>)) {
+                push @groups, $1
+                    if ($line =~ m/^[^:]*:[^:]*:([^:]*):(?:[^,]*,)*$username(?:,|$)/);
+            }
+            return join(',', @groups);
+        };
+
+        my ($uid, $username, $gid, $groups);
+
+        if ($user =~ /^\d+$/) {
+            $uid = $user;
+            $username = $lookup_field->($etc_passwd, 2, $uid, 0);
+        } else {
+            $username = $user;
+            $uid = $lookup_field->($etc_passwd, 0, $username, 2);
+        }
+
+        if (defined($group)) {
+            if ($group =~ /^\d+$/) {
+                $gid = $group;
+            } else {
+                $gid = $lookup_field->($etc_group, 0, $group, 2);
+            }
+        } else {
+            $gid = $lookup_field->($etc_passwd, 2, $uid, 3) if defined($uid);
+            $groups = $get_supplementary_groups->($username) if defined($username);
+        }
+
+        push $conf->{lxc}->@*, ['lxc.init.uid', $uid] if defined($uid);
+        push $conf->{lxc}->@*, ['lxc.init.gid', $gid] if defined($gid);
+        push $conf->{lxc}->@*, ['lxc.init.groups', $groups] if defined($groups);
+    }
+
     if (my $working_dir = $oci_config_get_checked_scalar->('WorkingDir')) {
         push $conf->{lxc}->@*, ['lxc.init.cwd', $working_dir];
     }
-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [pve-devel] [PATCH container 0/2] oci create: honor `User` from OCI image config
  2025-12-15 17:41 [pve-devel] [PATCH container 0/2] oci create: honor `User` from OCI image config Filip Schauer
  2025-12-15 17:41 ` [pve-devel] [PATCH container 1/2] config: add `lxc.init.uid`/`gid`/`groups` keys Filip Schauer
  2025-12-15 17:41 ` [pve-devel] [PATCH container 2/2] oci create: honor `User` from OCI image config Filip Schauer
@ 2025-12-16 12:03 ` Maximiliano Sandoval
  2025-12-16 18:13   ` Filip Schauer
  2 siblings, 1 reply; 6+ messages in thread
From: Maximiliano Sandoval @ 2025-12-16 12:03 UTC (permalink / raw)
  To: Filip Schauer; +Cc: pve-devel

Filip Schauer <f.schauer@proxmox.com> writes:

> Honor a custom user and group specified for the entrypoint via the OCI
> image config `User` field instead of ignoring it.
>
> This requires the following patch for LXC in order to work properly:
> https://github.com/lxc/lxc/pull/4626
>
> With these patches applied, docker.io/weblate/weblate starts with the
> correct uid and groups instead of the default uid=0(root) gid=0(root)
> groups=0(root).

I tested this patch together with the patch for LXC and it allows to run
containers where the entry point is expected to run as a given user.

One thing is that came up during testing (that was already discussed
offlist) is that mount points should inherit the uid:gid if the
directory already exists in the container image.

Tested-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
-- 
Maximiliano


_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [pve-devel] [PATCH container 0/2] oci create: honor `User` from OCI image config
  2025-12-16 12:03 ` [pve-devel] [PATCH container 0/2] " Maximiliano Sandoval
@ 2025-12-16 18:13   ` Filip Schauer
  0 siblings, 0 replies; 6+ messages in thread
From: Filip Schauer @ 2025-12-16 18:13 UTC (permalink / raw)
  To: Maximiliano Sandoval; +Cc: pve-devel

On 16/12/2025 13:03, Maximiliano Sandoval wrote:
> One thing is that came up during testing (that was already discussed
> offlist) is that mount points should inherit the uid:gid if the
> directory already exists in the container image.

This is addressed in:
https://lore.proxmox.com/pve-devel/20251216180904.270167-1-f.schauer@proxmox.com/T



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [pve-devel] [PATCH container 2/2] oci create: honor `User` from OCI image config
  2025-12-15 17:41 ` [pve-devel] [PATCH container 2/2] oci create: honor `User` from OCI image config Filip Schauer
@ 2026-01-15 13:18   ` Wolfgang Bumiller
  0 siblings, 0 replies; 6+ messages in thread
From: Wolfgang Bumiller @ 2026-01-15 13:18 UTC (permalink / raw)
  To: Filip Schauer; +Cc: pve-devel

On Mon, Dec 15, 2025 at 06:41:59PM +0100, Filip Schauer wrote:
> Honor a custom user and group specified for the entrypoint via the OCI
> image config `User` field instead of ignoring it.
> 
> User and group name lookups, including supplementary groups, are
> resolved from /etc/passwd and /etc/group in the container file system.
> This behaviour matches the OCI image spec. [0]
> 
> [0] https://specs.opencontainers.org/image-spec/config/?v=v1.1.1#properties
> 
> Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
> ---
> This requires the following patch for LXC in order to work properly:
> https://github.com/lxc/lxc/pull/4626
> 
>  src/PVE/LXC/Create.pm | 59 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 59 insertions(+)
> 
> diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
> index 9956cf9..08e0386 100644
> --- a/src/PVE/LXC/Create.pm
> +++ b/src/PVE/LXC/Create.pm
> @@ -768,6 +768,65 @@ sub restore_oci_archive {
>          }
>      }
>  
> +    if (my $usercfg = $oci_config_get_checked_scalar->('User')) {

This code should be factored into a separate sub.

> +        my ($user, $group) = $usercfg =~ /^([^:]+)(?::([^:]+))?$/
> +            or die "OCI config value for 'User' has an invalid format\n";
> +
> +        my $etc_passwd = "$rootdir/etc/passwd";
> +        my $etc_group = "$rootdir/etc/group";
> +
> +        # Scan file, match column $match_index against $match_val, return value at $ret_index
> +        my $lookup_field = sub {
> +            my ($file, $match_index, $match_val, $ret_index) = @_;
> +
> +            open(my $fh, '<', $file) or return undef;
> +            while (my $line = <$fh>) {
> +                my @fields = split(/:/, $line);

A subtlety about this sub is that currently the last field also includes
the trailing `\n`. Should probably add a comment, or `chomp` it away,
even if we currently don't use the final field via `$ret_index`.

> +                if (defined($fields[$match_index]) && $fields[$match_index] eq $match_val) {
> +                    return $fields[$ret_index];
> +                }
> +            }
> +            return undef;
> +        };
> +
> +        my $get_supplementary_groups = sub {
> +            my ($username) = @_;
> +
> +            my @groups;
> +            open(my $fh, '<', $etc_group) or return undef;
> +            while (defined(my $line = <$fh>)) {
> +                push @groups, $1
> +                    if ($line =~ m/^[^:]*:[^:]*:([^:]*):(?:[^,]*,)*$username(?:,|$)/);

Username comes from the outside and is only limited to not containing a
colon. To use it inside a regex you'd have to quote it as
`\Q$username\E`.

Safer would be to do what you do in `$lookup_field` and just split on
`:` then `,` then grep with `eq`.

> +            }
> +            return join(',', @groups);
> +        };
> +
> +        my ($uid, $username, $gid, $groups);
> +
> +        if ($user =~ /^\d+$/) {
> +            $uid = $user;
> +            $username = $lookup_field->($etc_passwd, 2, $uid, 0);
> +        } else {
> +            $username = $user;
> +            $uid = $lookup_field->($etc_passwd, 0, $username, 2);
> +        }
> +
> +        if (defined($group)) {
> +            if ($group =~ /^\d+$/) {
> +                $gid = $group;
> +            } else {
> +                $gid = $lookup_field->($etc_group, 0, $group, 2);
> +            }
> +        } else {
> +            $gid = $lookup_field->($etc_passwd, 2, $uid, 3) if defined($uid);
> +            $groups = $get_supplementary_groups->($username) if defined($username);
> +        }
> +
> +        push $conf->{lxc}->@*, ['lxc.init.uid', $uid] if defined($uid);
> +        push $conf->{lxc}->@*, ['lxc.init.gid', $gid] if defined($gid);
> +        push $conf->{lxc}->@*, ['lxc.init.groups', $groups] if defined($groups);
> +    }
> +
>      if (my $working_dir = $oci_config_get_checked_scalar->('WorkingDir')) {
>          push $conf->{lxc}->@*, ['lxc.init.cwd', $working_dir];
>      }
> -- 
> 2.47.3


_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-01-15 13:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-15 17:41 [pve-devel] [PATCH container 0/2] oci create: honor `User` from OCI image config Filip Schauer
2025-12-15 17:41 ` [pve-devel] [PATCH container 1/2] config: add `lxc.init.uid`/`gid`/`groups` keys Filip Schauer
2025-12-15 17:41 ` [pve-devel] [PATCH container 2/2] oci create: honor `User` from OCI image config Filip Schauer
2026-01-15 13:18   ` Wolfgang Bumiller
2025-12-16 12:03 ` [pve-devel] [PATCH container 0/2] " Maximiliano Sandoval
2025-12-16 18:13   ` Filip Schauer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal