ORG.FREED....PORTABLE1(5)

๐Ÿ’– NAME ๐Ÿ’–

org.freedesktop.portable1 โ€” the D-Bus interface of systemd-portabled. That's the whole name, bestie, short and sweet.


๐ŸŒธ INTRODUCTION ๐ŸŒธ

systemd-portabled.service(8) is a system service, and its whole thing is that it can attach, detach, and inspect portable services. Iconic behaviour honestly. This page right here is all about the D-Bus interface it puts out. ๐Ÿ’…


๐Ÿฆ‹ THE MANAGER OBJECT ๐Ÿฆ‹

So the service exposes these interfaces on the Manager object, on the bus. Here's the whole shape of it, no cap:

node /org/freedesktop/portable1 {
  interface org.freedesktop.portable1.Manager {
    methods:
      GetImage(in  s image,
               out o object);
      ListImages(out a(ssbtttso) images);
      GetImageOSRelease(in  s image,
                        out a{ss} os_release);
      GetImageMetadata(in  s image,
                       in  as matches,
                       out s image,
                       out ay os_release,
                       out a{say} units);
      GetImageMetadataWithExtensions(in  s image,
                                     in  as extensions,
                                     in  as matches,
                                     in  t flags,
                                     out s image,
                                     out ay os_release,
                                     out a{say} extensions,
                                     out a{say} units);
      GetImageState(in  s image,
                    out s state);
      GetImageStateWithExtensions(in  s image,
                                  in  as extensions,
                                  in  t flags,
                                  out s state);
      AttachImage(in  s image,
                  in  as matches,
                  in  s profile,
                  in  b runtime,
                  in  s copy_mode,
                  out a(sss) changes);
      AttachImageWithExtensions(in  s image,
                                in  as extensions,
                                in  as matches,
                                in  s profile,
                                in  s copy_mode,
                                in  t flags,
                                out a(sss) changes);
      DetachImage(in  s image,
                  in  b runtime,
                  out a(sss) changes);
      DetachImageWithExtensions(in  s image,
                                in  as extensions,
                                in  t flags,
                                out a(sss) changes);
      ReattachImage(in  s image,
                    in  as matches,
                    in  s profile,
                    in  b runtime,
                    in  s copy_mode,
                    out a(sss) changes_removed,
                    out a(sss) changes_updated);
      ReattachImageWithExtensions(in  s image,
                                  in  as extensions,
                                  in  as matches,
                                  in  s profile,
                                  in  s copy_mode,
                                  in  t flags,
                                  out a(sss) changes_removed,
                                  out a(sss) changes_updated);
      RemoveImage(in  s image);
      MarkImageReadOnly(in  s image,
                        in  b read_only);
      SetImageLimit(in  s image,
                    in  t limit);
      SetPoolLimit(in  t limit);
    properties:
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly s PoolPath = '...';
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly t PoolUsage = ...;
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly t PoolLimit = ...;
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly as Profiles = ['...', ...];
  };
  interface org.freedesktop.DBus.Peer { ... };
  interface org.freedesktop.DBus.Introspectable { ... };
  interface org.freedesktop.DBus.Properties { ... };
};

โœจ Methods โœจ

  • GetImage() โ€” you hand it a name, it hands you back the image object path of that image. Match made in heaven.
  • ListImages() โ€” returns an array of every image currently known. Each structure in that array is stacked like this: image name, type, read-only flag, creation time, modification time, current disk space, usage, and image object path. Eight little fields, all lined up. ๐ŸŽ€
  • GetImageOSRelease() โ€” pulls the OS release info out of an image. What you get back is an array of key-value pairs, read straight from the os-release(5) file inside the image. Super useful for clocking which operating system a portable service is actually running. ๐Ÿฆ‹
  • GetImageMetadata() โ€” grabs metadata tied to an image. You get the image name, the image's os-release(5) content as a (streamable) array of bytes, and a list of the portable units chilling inside the image โ€” each one as a string (the unit name) plus an array of bytes holding its content.
  • GetImageMetadataWithExtensions() โ€” also grabs metadata for an image, but this one is a superset of GetImageMetadata(). The extra: a list of extensions comes in as an input parameter, and those were overlaid on top of the main image via AttachImageWithExtensions(). For each extension named in the input arguments you get back the path of that extension plus an array of bytes containing the respective extension-release file's content โ€” one such structure per extension. โœจ
  • GetImageState() โ€” returns the image state, as one of these strings:
    • detached
    • attached
    • attached-runtime
    • enabled
    • enabled-runtime
    • running
    • running-runtime
  • GetImageStateWithExtensions() โ€” a superset of GetImageState(), with extra support for a list of extensions as input parameters. You need that list to even query the state if the image was attached in that particular way. The flags parameter is currently unused and reserved for future purposes, so likeโ€ฆ it's there, it's just vibing. ๐Ÿ™ˆ
  • AttachImage() โ€” attaches a portable image to the system. Let's break down what you're feeding it:
    • an image path or name,
    • a list of strings used to search for unit files inside the image (partial or complete matches),
    • a string saying which portable profile to use for the image (peep the Profiles property for the list of available profiles),
    • a boolean for whether to attach the image only for the current boot session,
    • and a string for the preferred copy mode โ€” copy the image, or just symlink it. The possible values are:
      • (empty)
      • copy
      • symlink
      • mixed

Okay so about those copy modes, fr fr: pass an empty string and the security profile drop-ins and images get symlinked while unit files get copied. copy copies. symlink prefers linking when it's possible (say, a unit has to be copied out of an image). And mixed prefers linking the resources owned by the OS (like the portable profile sitting in the host's /usr/ tree) but copies the resources owned by the portable image (like the unit files and the images).

This method returns the list of changes applied to the system โ€” for example, which unit got added and is now available as a system service. Every change is a triplet of strings: the type of change applied, the path it was applied on, and the source (if any). The type of change applied will be one of:

  • copy
  • symlink
  • write
  • mkdir
Heads up bestie: an image cannot be attached if a unit that it contains is already present on the system. And this method only returns after all the listed operations are completed, and thanks to all the I/O involved it might take a minute. Be patient. ๐Ÿ˜ญ

In place of the image path a .v/ versioned directory may be specified, see systemd.v(7) for details.

In place of the directory path a .v/ versioned directory may be specified, see systemd.v(7) for details.

(Yes, they said it twice. Yes, we're keeping both. Every detail stays, that's the rule. ๐Ÿ’…)

  • AttachImageWithExtensions() โ€” attaches a portable image to the system. Superset of AttachImage(), and the addition is a list of extensions as an input parameter, which get overlaid on top of the main image. โš ๏ธ Important: when you attach using this method, you have to detach by passing the same arguments through DetachImageWithExtensions(). For more details on this functionality, see the MountImages= entry on systemd.exec(5) and systemd-sysext(8).
  • DetachImage() โ€” detaches a portable image from the system. It takes an image path or name, plus a boolean saying whether the image being detached was attached only for the current boot session or persistently. You get back the list of changes applied to the system โ€” for example, which unit was removed and is no longer available as a system service. Each change is a triplet of strings: the type of change applied, the path it was applied on, and the source (if any). The type of change applied will be one of:
    • unlink
Okay and another heads up: an image cannot be detached if a unit that it contains is running. Also, this method only returns after all the listed operations are completed, and because of the I/O involved it might take some time. ๐Ÿซถ
  • DetachImageWithExtensions() โ€” detaches a portable image from the system. Superset of DetachImage(), plus a list of extensions as an input parameter โ€” the ones that were overlaid on top of the main image via AttachImageWithExtensions().
  • ReattachImage() โ€” the combo move. It's the effects of AttachImage() and DetachImage() fused together, except the difference is you're allowed to reattach an image while one or more of its units are still running. ๐Ÿƒโ™€๏ธ The reattach will fail if no matching image is attached, so don't try it on nothing. The input parameters match AttachImage(), and the return parameters are the combination of the return parameters of DetachImage() (first array โ€” units that were removed) and AttachImage() (second array โ€” units that were updated or added).
  • ReattachImageWithExtensions() โ€” reattaches a portable image to the system. Superset of ReattachImage(), plus a list of extensions as an input parameter, which will be overlaid on top of the main image. For more details on this functionality, see the MountImages= entry on systemd.exec(5) and systemd-sysext(8).
  • RemoveImage() โ€” removes the image with the specified name. Gone. Poof. ๐ŸŒˆ
  • MarkImageReadOnly() โ€” toggles the read-only flag of an image. Flip it on, flip it off. ๐Ÿ‘‘
  • SetPoolLimit() โ€” sets an overall quota limit on the pool of images.

SetImageLimit() sets a per-image quota limit. cute, contained, one image at a time bestie ๐Ÿ’…

The AttachImageWithExtensions(), DetachImageWithExtensions() and ReattachImageWithExtensions() methods take in options as flags instead of booleans, so future-us can add more of them without breaking everything. it's giving foresight, it's giving growth mindset โœจ

SD_SYSTEMD_PORTABLE_FORCE_ATTACH will bypass the safety checks that make sure the units are not running while the image is attached or detached. SD_SYSTEMD_PORTABLE_FORCE_EXTENSION will bypass the check that makes sure the extension-release.NAME file in the extension image matches the image name. They are defined as follows:

#define SD_SYSTEMD_PORTABLE_RUNTIME            (UINT64_C(1) << 0)
#define SD_SYSTEMD_PORTABLE_FORCE_ATTACH       (UINT64_C(1) << 1)
#define SD_SYSTEMD_PORTABLE_FORCE_EXTENSION    (UINT64_C(1) << 2)

๐ŸŽ€ Properties ๐ŸŽ€

  • PoolPath specifies the file system path where images are written to.
  • PoolUsage specifies the current usage size of the image pool in bytes.
  • PoolLimit specifies the size limit of the image pool in bytes.
  • Profiles specifies the available runtime profiles for portable services.

๐ŸŒˆ THE IMAGE OBJECT ๐ŸŒˆ

The service exposes the following interfaces on the Image object on the bus. look at her. main character energy, no cap ๐Ÿ‘‘

node /org/freedesktop/portable1 {
  interface org.freedesktop.portable1.Image {
    methods:
      GetOSRelease(out a{ss} os_release);
      GetMetadata(in  as matches,
                  out s image,
                  out ay os_release,
                  out a{say} units);
      GetMetadataWithExtensions(in  as extensions,
                                in  as matches,
                                in  t flags,
                                out s image,
                                out ay os_release,
                                out a{say} extensions,
                                out a{say} units);
      GetState(out s state);
      GetStateWithExtensions(in  as extensions,
                             in  t flags,
                             out s state);
      Attach(in  as matches,
             in  s profile,
             in  b runtime,
             in  s copy_mode,
             out a(sss) changes);
      AttachWithExtensions(in  as extensions,
                           in  as matches,
                           in  s profile,
                           in  s copy_mode,
                           in  t flags,
                           out a(sss) changes);
      Detach(in  b runtime,
             out a(sss) changes);
      DetachWithExtensions(in  as extensions,
                           in  t flags,
                           out a(sss) changes);
      Reattach(in  as matches,
               in  s profile,
               in  b runtime,
               in  s copy_mode,
               out a(sss) changes_removed,
               out a(sss) changes_updated);
      ReattachWithExtensions(in  as extensions,
                             in  as matches,
                             in  s profile,
                             in  s copy_mode,
                             in  t flags,
                             out a(sss) changes_removed,
                             out a(sss) changes_updated);
      Remove();
      MarkReadOnly(in  b read_only);
      SetLimit(in  t limit);
    properties:
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly s Name = '...';
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly s Path = '...';
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly s Type = '...';
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly b ReadOnly = ...;
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly t CreationTimestamp = ...;
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly t ModificationTimestamp = ...;
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly t Usage = ...;
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly t Limit = ...;
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly t UsageExclusive = ...;
      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
      readonly t LimitExclusive = ...;
  };
  interface org.freedesktop.DBus.Peer { ... };
  interface org.freedesktop.DBus.Introspectable { ... };
  interface org.freedesktop.DBus.Properties { ... };
};

๐Ÿ’– Methods ๐Ÿ’–

The following methods implement the same operation as the respective methods on the Manager object (see above). The catch? These ones operate on the image object itself, so they do not take an image name parameter. โœจ

Invoking the methods directly on the Manager object has the advantage of not requiring a GetImage() call just to get the image object for a specific image name. So calling the methods on the Manager object is a round trip optimization. iykyk ๐Ÿฆ‹

List of methods:

  • GetOSRelease()
  • GetMetadata()
  • GetMetadataWithExtensions()
  • GetState()
  • Attach()
  • AttachWithExtensions()
  • Detach()
  • DetachWithExtensions()
  • Reattach()
  • ReattachWithExtensions()
  • Remove()
  • MarkReadOnly()
  • SetLimit()

๐ŸŒธ Properties ๐ŸŒธ

  • Name specifies the image name.
  • Path specifies the file system path where image is stored.
  • Type specifies the image type.
  • ReadOnly specifies whether the image is read-only.
  • CreationTimestamp specifies the image creation timestamp.
  • ModificationTimestamp specifies the image modification timestamp.
  • Usage specifies the image disk usage.
  • Limit specifies the image disk usage limit.
  • UsageExclusive specifies the image disk usage (exclusive).
  • LimitExclusive specifies the image disk usage limit (exclusive).

โญ VERSIONING โญ

These D-Bus interfaces follow the usual interface versioning guidelines[1]. periodt ๐Ÿ’…


๐Ÿฆ‹ HISTORY ๐Ÿฆ‹

The Manager Object

GetImageStateWithExtensions() was added in version 251.

The Image Object

GetStateWithExtensions() was added in version 251.

ReattachWithExtensions() was added in version 254.


๐ŸŽ€ SEE ALSO ๐ŸŽ€

systemd(1), systemd-portabled.service(8), portablectl(1)


๐Ÿ’œ NOTES ๐Ÿ’œ

  1. the usual interface versioning guidelines https://0pointer.de/blog/projects/versioning-dbus.html

and that's the whole page bestie, you ate that ๐Ÿซถ this was systemd 262.1 rendering ORG.FREED....PORTABLE1(5) โ€” go forth and portable-ify ur services, ilysm, drink water, and remember: --force responsibly ๐Ÿ’–โœจ๐ŸŽ€๐Ÿฆ‹๐ŸŒธ

๐Ÿ“ฆ where this page comes from
  • arch rolling: systemd 262.1-1 ยท LGPL-2.1-or-later AND CC0-1.0 AND GPL-2.0-or-later AND MIT-0
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms