[systemd-devel] Best practice for prepopulating the CacheDirectory of dynamic users

aleivag aleivag at gmail.com
Wed Feb 28 16:13:36 UTC 2018


Hi Antoine:

2 disclosure before reading this:

1) i'm not part of systemd-devel team, and
2) this is also a shameless plug because i'm talking about a lib i created.

with that out of the way, here is my advice/solution.

do everything in python and use `pystemd` (pip install pystemd, just have
libsystemd installed and you should be fine), and also ditch the
cachedirectory in favor of PrivateTmp, that is always new when you start
your unit, and always goes away with your unit.

pystemd is  apython wrapper around a few libsystemd-dev, and it has a nice
module name pystemd.run, here is a example

import sys
import pystemd.run

pscript = """
import os
import shutil
print(shutil.copytree('/var/cache/dnf', '/tmp/dnf'))
print(os.listdir('/tmp/dnf'))
"""

pystemd.run(
    ['/usr/bin/python3', '-c', pscript],
    stdout=sys.stdout, stderr=sys.stderr, wait=True,
    env={'PYTHONUSERBASE': '/dev/null'},
    extra={'DynamicUser': True, 'PrivateTmp': True},
)

this would output: something like
/tmp/dnf
['last_makecache', '.gpgkeyschecked.yum', 'rawhide-2d95c80a1fa0a67d',
'google-chrome-filenames.solvx', 'tempfiles.json',
'rawhide-filenames.solvx', 'google-chrome.solv', 'expired_repos.json',
'rawhide.solv', 'packages.db', 'google-chrome-eb0d6f10ccbdafba']


so my recommendation, create a custom script with your build process and
call it using pystemd.run. Now, you could also use systemd-run to run your
script, but then it would not have been a shameless plug, right?

hope it helps


Alvaro Leiva

On Wed, Feb 28, 2018 at 7:03 AM, Antoine Pietri <antoine.pietri1 at gmail.com>
wrote:

> On Tue, Feb 27, 2018 at 2:37 PM, Antoine Pietri
> <antoine.pietri1 at gmail.com> wrote:
> > - My current workaround is to shell-out to `systemd-run -p
> > DynamicUser=yes ...` first to do a mkdir -p, then for a cp -R. This
> > solution requires a lot of boilerplate from the Python wrapper and
> > takes more time for no good reason, so I think it's not ideal.
> >
> > - I believe another solution would be to modify /var/cache/private
> > directly, but I'm not sure it's a good practice to do so because I
> > don't know if this path is reliable or just an implementation detail.
> > Plus, it requires a weird special case compared to when I don't run
> > makepkg with systemd-run, as I have to insert something in the middle
> > of the copy destination path.
> >
> > - Maybe there's something else I'm missing that would allow me to do
> > this more cleanly?
>
> We came up with a third option, which looks a bit weird at first but
> should work:
>
> 1) systemd-run -P \
>   -p DynamicUser=yes \
>   -p CacheDirectory=mywrapper \
>   sh -c read
>
> 2) do the file operations in the Python code
> 3) send a "\n" or just kill() the systemd-run process when the setup is
> done.
>
> I am still not satisfied with any of the three options, so I would
> love to know what you think would be best. :-)
>
> --
> Antoine Pietri
>
> On Tue, Feb 27, 2018 at 2:37 PM, Antoine Pietri
> <antoine.pietri1 at gmail.com> wrote:
> > Hi!
> >
> > To experiment with systemd dynamic users, I started working on a
> > wrapper around a program that builds user packages (Archlinux makepkg)
> > and that refuses to be launched as root (for very good reasons). The
> > idea is that the wrapper just calls:
> >
> > systemd-run --pipe \
> >   -p DynamicUser=yes \
> >   -p CacheDirectory=mywrapper \
> >   -p WorkingDirectory=/var/cache/mywrapper/build/repo \
> >   makepkg
> >
> > However, to be able to run makepkg, its cache directory has to be
> > pre-populated with a clone of the package to build. So, from my
> > wrapper, I just did:
> >
> >   os.makedirs(os.path.dirname(build_dir), exist_ok=True)
> >   shutil.copytree(repo_path, build_dir)
> >
> > to copy the content of the repo to the build directory. But it fails
> with:
> >
> >   run-u63.service: Failed to set up special execution directory in
> > /var/cache: File exists
> >
> > This makes sense, because of the symbolic link shenanigans to
> > /var/cache/private that systemd uses to keep the filesystem readonly.
> > So, now I'm wondering what would be the best practice to prepopulate
> > this directory:
> >
> > - My current workaround is to shell-out to `systemd-run -p
> > DynamicUser=yes ...` first to do a mkdir -p, then for a cp -R. This
> > solution requires a lot of boilerplate from the Python wrapper and
> > takes more time for no good reason, so I think it's not ideal.
> >
> > - I believe another solution would be to modify /var/cache/private
> > directly, but I'm not sure it's a good practice to do so because I
> > don't know if this path is reliable or just an implementation detail.
> > Plus, it requires a weird special case compared to when I don't run
> > makepkg with systemd-run, as I have to insert something in the middle
> > of the copy destination path.
> >
> > - Maybe there's something else I'm missing that would allow me to do
> > this more cleanly?
> >
> > Thanks,
> >
> > --
> > Antoine Pietri
>
>
>
> --
> Antoine Pietri
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/systemd-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/systemd-devel/attachments/20180228/e72fecda/attachment.html>


More information about the systemd-devel mailing list