Merge pull request #32363 from CodethinkLabs/sysupdate-dbus

sysupdate: Implement dbus service
This commit is contained in:
Adrian Vovk
2024-08-21 15:35:34 -04:00
committed by GitHub
21 changed files with 4252 additions and 17 deletions
+487
View File
@@ -0,0 +1,487 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" >
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="org.freedesktop.sysupdate1" conditional='ENABLE_SYSUPDATE'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>org.freedesktop.sysupdate1</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>org.freedesktop.sysupdate1</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>org.freedesktop.sysupdate1</refname>
<refpurpose>The D-Bus interface of systemd-sysupdated</refpurpose>
</refnamediv>
<refsect1>
<title>Introduction</title>
<para>
<citerefentry><refentrytitle>systemd-sysupdated.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
is a system service that allows unprivileged clients to update the system. This page describes the D-Bus
interface.</para>
</refsect1>
<refsect1>
<title>The Manager Object</title>
<para>The service exposes the following interfaces on the Manager object on the bus:</para>
<programlisting executable="systemd-sysupdated" node="/org/freedesktop/sysupdate1" interface="org.freedesktop.sysupdate1.Manager">
node /org/freedesktop/sysupdate1 {
interface org.freedesktop.sysupdate1.Manager {
methods:
ListTargets(out a(sso) targets);
ListJobs(out a(tsuo) jobs);
ListAppStream(out as urls);
signals:
JobRemoved(t id,
o path,
i status);
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
};
</programlisting>
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.sysupdate1.Manager"/>
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.sysupdate1.Manager"/>
<variablelist class="dbus-method" generated="True" extra-ref="ListTargets()"/>
<variablelist class="dbus-method" generated="True" extra-ref="ListJobs()"/>
<variablelist class="dbus-method" generated="True" extra-ref="ListAppStream()"/>
<variablelist class="dbus-signal" generated="True" extra-ref="JobRemoved()"/>
<!--End of Autogenerated section-->
<refsect2>
<title>Methods</title>
<para><function>ListTargets()</function> returns a list all known update targets. It returns
an array of structures which consist of a string indicating the target's class (see Target's
<varname>Class</varname> property below for an explanation of the possible values), a string
with the name of the target, and the target object path.</para>
<para><function>ListJobs()</function> returns a list all ongoing jobs. It returns
an array of structures which consist of a numeric job ID, a string indicating the job type (see Job's
<varname>Type</varname> property below for an explanation of the possible values), the job's progress,
and the job's object path.</para>
<para><function>ListAppStream()</function> returns an array of all the appstream catalog URLs that this
service knows about. See Target's <varname>GetAppStream()</varname> method below for more
details.</para>
</refsect2>
<refsect2>
<title>Signals</title>
<para>The <function>JobRemoved()</function> signal is sent each time a job finishes,
is canceled or fails. It also carries the job ID and object path, followed by a numeric status
code. If the status is zero, the job has succeed. A positive status should be treated as an
exit code (i.e. <literal>EXIT_FAILURE</literal>), and a negative status should be treated as a
negative errno-style error code (i.e. <literal>-EINVAL</literal>).</para>
</refsect2>
</refsect1>
<refsect1>
<title>The Target Object</title>
<para>A target is a component of the system (i.e. the host itself, a sysext, a confext, etc.) that
can be updated by
<citerefentry><refentrytitle>systemd-sysupdate</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
</para>
<para>The service exposes the following interfaces on Target objects on the bus:</para>
<programlisting executable="systemd-sysupdated" node="/org/freedesktop/sysupdate1/target/host" interface="org.freedesktop.sysupdate1.Target">
node /org/freedesktop/sysupdate1/target/host {
interface org.freedesktop.sysupdate1.Target {
methods:
List(in t flags,
out as versions);
Describe(in s version,
in t flags,
out s json);
CheckNew(out s new_version);
Update(in s new_version,
in t flags,
out s new_version,
out t job_id,
out o job_path);
Vacuum(out u count);
GetAppStream(out as appstream);
GetVersion(out s version);
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Class = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Name = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Path = '...';
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
};
</programlisting>
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.sysupdate1.Target"/>
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.sysupdate1.Target"/>
<variablelist class="dbus-method" generated="True" extra-ref="List()"/>
<variablelist class="dbus-method" generated="True" extra-ref="Describe()"/>
<variablelist class="dbus-method" generated="True" extra-ref="CheckNew()"/>
<variablelist class="dbus-method" generated="True" extra-ref="Update()"/>
<variablelist class="dbus-method" generated="True" extra-ref="Vacuum()"/>
<variablelist class="dbus-method" generated="True" extra-ref="GetAppStream()"/>
<variablelist class="dbus-method" generated="True" extra-ref="GetVersion()"/>
<variablelist class="dbus-property" generated="True" extra-ref="Class"/>
<variablelist class="dbus-property" generated="True" extra-ref="Name"/>
<variablelist class="dbus-property" generated="True" extra-ref="Path"/>
<!--End of Autogenerated section-->
<refsect2>
<title>Methods</title>
<para><function>List()</function> returns a list of versions available for this target. The
<varname>flags</varname> argument can be used to pass additional options, with bit 0 mapping to
<option>offline</option>. When <option>offline</option> is true, this method returns only the versions
installed locally. Otherwise, this method pulls metadata from the network and returns all versions
available for this target. Use <function>Describe()</function> to query more information about each
version returned by this method.</para>
<para><function>Describe()</function> returns all known information about a given version as a JSON
object. The <varname>version</varname> argument is used to pass the version to be described. Additional
options may be passed through the <varname>flags</varname> argument. The only supported value currently
is <varname>SD_SYSTEMD_SYSUPDATE_OFFLINE</varname>, which prevents the call from accessing the network
and restricts results to locally installed versions. This flag is defined as follows:</para>
<programlisting>
#define SD_SYSTEMD_SYSUPDATE_OFFLINE (UINT64_C(1) &lt;&lt; 0)
</programlisting>
<para>The returned JSON object contains several known keys. More keys may be added in the future. The
currently known keys are as follows:</para>
<variablelist>
<varlistentry>
<term>version</term>
<listitem><para>A string containing the version number.</para></listitem>
</varlistentry>
<varlistentry>
<term>newest</term>
<listitem><para>A boolean indicating whether this version is the latest available for the target.</para></listitem>
</varlistentry>
<varlistentry>
<term>available</term>
<listitem><para>A boolean indicating whether this version is available for download.</para></listitem>
</varlistentry>
<varlistentry>
<term>installed</term>
<listitem><para>A boolean indicating whether this version is installed locally.</para></listitem>
</varlistentry>
<varlistentry>
<term>obsolete</term>
<listitem><para>A boolean indicating whether this version is considered obsolete by the service,
and is therefore disallowed from being installed.</para></listitem>
</varlistentry>
<varlistentry>
<term>protected</term>
<listitem><para>A boolean indicating whether this version is exempt from deletion by a
<function>Vacuum()</function> operation.</para></listitem>
</varlistentry>
<varlistentry>
<term>changelog_urls</term>
<listitem><para>A list of strings that contain user-presentable URLs to ChangeLogs associated with
this version.</para></listitem>
</varlistentry>
</variablelist>
<para><function>CheckNew()</function> checks if a newer version is available for this target. This
method pulls metadata from the network. If a newer version is found, this method returns the
version number. If no newer version is found, this method returns an empty string. Use
<function>Describe()</function> to query more information about the version returned by this method.
</para>
<para><function>Update()</function> installs an update for this target. If a
<varname>new_version</varname> is specified, that is the version that gets installed. Otherwise, the
latest version is installed. The <varname>flags</varname> argument is added for future
extensibility. No flags are currently defined, and the argument is required to be set to
<literal>0</literal>. Unlike all the other methods in this interface, <function>Update()</function>
does not wait for its job to complete. Instead, it returns the job's numeric ID and object path as soon
as the job begins, so that the caller can listen for progress updates or cancel the operation. This
method also returns the version the target will be updated to, for cases where no version was specified
by the caller. This method pulls both metadata and payload data from the network. Listen for the
Manager's <function>JobRemoved()</function> signal to detect when the job is complete.</para>
<para><function>Vacuum()</function> deletes old installed versions of this target to free up space.
It returns the number of instances that have been deleted.</para>
<para><function>GetAppStream()</function> returns a list of HTTP/HTTPS URLs to this target's
<ulink url="https://wwww.freedesktop.org/software/appstream/docs/chap-CatalogData.html">appstream catalog</ulink>
XML files. If this target has no appstream catalogs, the method will return an empty list. These
catalog files can be used by software centers (such as GNOME Software or KDE Discover) to present rich
metadata about the target, including a display name, changelog, icon, and more. The returned catalogs
will include <ulink url="https://systemd.io/APPSTREAM_BUNDLE">special metadata</ulink> to allow the
software center to correctly associate the catalogs with this target.</para>
<para><function>GetVersion()</function> returns the current version of this target, if any. The current
version is the newest version that is installed. Note that this isn't necessarily the same thing as the
booted or currently-in-use version of the target. For example, on the host system the booted version
is the current version most of the time, but if an update is installed and pending a reboot it will
become the current version instead. You can query the booted version of the host system via
<varname>IMAGE_VERSION</varname> in <filename>/etc/os-release</filename>. If the target has no current
version, the function will return an empty string.</para>
</refsect2>
<refsect2>
<title>Properties</title>
<para>The <varname>Class</varname> property exposes the class of this target, which describes
where it was enumerated. Possible values include: <literal>machine</literal> for containers and
virtual machines managed by
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<literal>portable</literal> for <ulink url="https://systemd.io/PORTABLE_SERVICES">portable services</ulink>,
<literal>sysext</literal> for system extensions managed by
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<literal>confext</literal> for configuration extensions managed by
<citerefentry><refentrytitle>systemd-confext</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<literal>component</literal> for components accepted by the <option>--component=</option> option of
<citerefentry><refentrytitle>systemd-sysupdate</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
and <literal>host</literal> for the host system itself. At most one target will have a class of
<literal>host</literal>.</para>
<para>The <varname>Path</varname> property exposes more detail about where this target was found.
For <literal>machine</literal>, <literal>portable</literal>, <literal>extension</literal>, and
<literal>confext</literal> targets, this is the file path to the image. For <literal>component</literal>
and <literal>host</literal> targets, this is the name of a
<citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
directory.</para>
<para>The <varname>Name</varname> property exposes the name of this target. Note that the name is
unique within a class but is not necessarily unique between classes. For instance, it is possible
to have both a <literal>portable</literal> target named <literal>foobar</literal> and an
<literal>extension</literal> target named <literal>foobar</literal>, but it is not possible to have
two <literal>portable</literal> targets named <literal>foobar</literal>.</para>
</refsect2>
<refsect2>
<title>Security</title>
<para>Method calls on this service are authenticated via
<ulink url="https://www.freedesktop.org/software/polkit/docs/latest/">polkit</ulink>.</para>
<para><function>List()</function>, <function>Describe()</function>, and <function>CheckNew()</function>
use the polkit action <interfacename>org.freedesktop.sysupdate1.check</interfacename>.
By default, this action is permitted without administrator authentication.</para>
<para><function>Update()</function> uses the polkit action
<interfacename>org.freedesktop.sysupdate1.update</interfacename> when no version is specified.
By default, this action is permitted without administrator authentication. When a version is
specified, <interfacename>org.freedesktop.sysupdate1.update-to-version</interfacename> is
used instead. By default, this alternate action requires administrator authentication.</para>
<para><function>Vacuum()</function> uses the polkit action
<interfacename>org.freedesktop.sysupdate1.vacuum</interfacename>. By default, this action requires
administrator authentication.</para>
<para><function>GetAppStream()</function> and <function>GetVersion()</function> are unauthenticated and
may be called by anybody.</para>
<para>All methods called on this interface expose additional variables to the polkit rules.
<literal>class</literal> contains the class of the Target being acted upon, and <literal>name</literal>
contains the name of the same Target. Additionally, each method exposes its arguments to the
rule. Arguments containing flags are unwrapped into a variable-per-flag; for example, the
<literal>SD_SYSTEMD_SYSUPDATE_OFFLINE</literal> flag is exposed as a variable named
<literal>offline</literal>.</para>
</refsect2>
</refsect1>
<refsect1>
<title>The Job Object</title>
<para>A job is an ongoing operation, started by one of the methods on a Target object.</para>
<para>The service exposes the following interfaces on Job objects on the bus:</para>
<programlisting executable="systemd-sysupdated" node="/org/freedesktop/sysupdate1/job/_1" interface="org.freedesktop.sysupdate1.Job">
node /org/freedesktop/sysupdate1/job/_1 {
interface org.freedesktop.sysupdate1.Job {
methods:
Cancel();
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t Id = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Type = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Offline = ...;
readonly u Progress = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
};
</programlisting>
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.sysupdate1.Job"/>
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.sysupdate1.Job"/>
<variablelist class="dbus-method" generated="True" extra-ref="Cancel()"/>
<variablelist class="dbus-property" generated="True" extra-ref="Id"/>
<variablelist class="dbus-property" generated="True" extra-ref="Type"/>
<variablelist class="dbus-property" generated="True" extra-ref="Offline"/>
<variablelist class="dbus-property" generated="True" extra-ref="Progress"/>
<!--End of Autogenerated section-->
<refsect2>
<title>Methods</title>
<para>The <function>Cancel()</function> method may be used to cancel the job. It takes no
parameters.</para>
</refsect2>
<refsect2>
<title>Properties</title>
<para>The <varname>Id</varname> property exposes the numeric job ID of the job object.</para>
<para>The <varname>Type</varname> property exposes the type of operation (one of: <literal>list</literal>,
<literal>describe</literal>, <literal>check-new</literal>, <literal>update</literal>, or <literal>vacuum</literal>).
</para>
<para>The <varname>Offline</varname> property exposes whether the job is permitted to access
the network or not.</para>
<para>The <varname>Progress</varname> property exposes the current progress of the job as a value
between 0 and 100. It is only available for <literal>update</literal> jobs; for all other jobs
it is always 0.</para>
</refsect2>
<refsect2>
<title>Security</title>
<para><function>Cancel()</function> uses the polkit action that corresponds to the method
that started this job. For instance, trying to cancel a <literal>list</literal> job will
require polkit to permit the <interfacename>org.freedesktop.sysupdate1.check</interfacename>
action.</para>
</refsect2>
</refsect1>
<refsect1>
<title>Examples</title>
<example>
<title>Introspect <interfacename>org.freedesktop.sysupdate1.Manager</interfacename> on the bus</title>
<programlisting>$ gdbus introspect --system \
--dest org.freedesktop.sysupdate1 \
--object-path /org/freedesktop/sysupdate1
</programlisting>
</example>
<example>
<title>Introspect <interfacename>org.freedesktop.sysupdate1.Target</interfacename> on the bus</title>
<programlisting>$ gdbus introspect --system \
--dest org.freedesktop.sysupdate1 \
--object-path /org/freedesktop/sysupdate1/target/host
</programlisting>
</example>
<example>
<title>Introspect <interfacename>org.freedesktop.sysupdate1.Job</interfacename> on the bus</title>
<programlisting>$ gdbus introspect --system \
--dest org.freedesktop.sysupdate1 \
--object-path /org/freedesktop/sysupdate1/job/_1
</programlisting>
</example>
</refsect1>
<xi:include href="org.freedesktop.locale1.xml" xpointer="versioning"/>
<refsect1>
<title>History</title>
<refsect2>
<title>The Manager Object</title>
<para><function>ListTargets()</function>,
<function>ListJobs()</function>,
<function>ListAppStream()</function>, and
<function>JobRemoved()</function> were added in version 257.</para>
</refsect2>
<refsect2>
<title>The Target Object</title>
<para><function>List()</function>,
<function>Describe()</function>,
<function>CheckNew()</function>,
<function>Update()</function>,
<function>Vacuum()</function>,
<function>GetAppStream()</function>,
<function>GetVersion()</function>,
<varname>Class</varname>,
<varname>Name</varname>, and
<varname>Path</varname> were added in version 257.</para>
</refsect2>
<refsect2>
<title>The Job Object</title>
<para><function>Cancel()</function>,
<varname>Id</varname>,
<varname>Type</varname>,
<varname>Offline</varname>, and
<varname>Progress</varname> were added in version 257.</para>
</refsect2>
</refsect1>
</refentry>
+6
View File
@@ -65,6 +65,7 @@ manpages = [
['org.freedesktop.portable1', '5', [], 'ENABLE_PORTABLED'],
['org.freedesktop.resolve1', '5', [], 'ENABLE_RESOLVE'],
['org.freedesktop.systemd1', '5', [], ''],
['org.freedesktop.sysupdate1', '5', [], 'ENABLE_SYSUPDATE'],
['org.freedesktop.timedate1', '5', [], 'ENABLE_TIMEDATED'],
['os-release', '5', ['extension-release', 'initrd-release'], ''],
['pam_systemd', '8', [], 'HAVE_PAM'],
@@ -1100,6 +1101,10 @@ manpages = [
'systemd-sysupdate.service',
'systemd-sysupdate.timer'],
'ENABLE_SYSUPDATE'],
['systemd-sysupdated.service',
'8',
['systemd-sysupdated'],
'ENABLE_SYSUPDATE'],
['systemd-sysusers', '8', ['systemd-sysusers.service'], ''],
['systemd-sysv-generator', '8', [], 'HAVE_SYSV_COMPAT'],
['systemd-time-wait-sync.service',
@@ -1277,6 +1282,7 @@ manpages = [
['udev_new', '3', ['udev_ref', 'udev_unref'], ''],
['udevadm', '8', [], ''],
['ukify', '1', [], 'ENABLE_UKIFY'],
['updatectl', '1', [], 'ENABLE_SYSUPDATE'],
['user@.service',
'5',
['systemd-user-runtime-dir', 'user-runtime-dir@.service'],
+1
View File
@@ -322,6 +322,7 @@
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemd-sysupdated.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
</simplelist></para>
</refsect1>
+55
View File
@@ -0,0 +1,55 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="systemd-sysupdated.service" conditional='ENABLE_SYSUPDATE'>
<refentryinfo>
<title>systemd-sysupdated.service</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-sysupdated.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-sysupdated.service</refname>
<refname>systemd-sysupdated</refname>
<refpurpose>System Update Service</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-sysupdated.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-sysupdated</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-sysupdated</command> is a system service that allows unprivileged
clients to update the system. It works by scanning the system for updateable "targets" (i.e.
portable services, sysexts, sysupdate components, etc.) and exposing them on the bus. Each
target then has methods that translate directly into invocations of
<citerefentry><refentrytitle>systemd-sysupdate</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
</para>
<para>See
<citerefentry><refentrytitle>org.freedesktop.sysupdate1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
and
<citerefentry><refentrytitle>org.freedesktop.LogControl1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for a description of the D-Bus API.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-sysupdate</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<citerefentry><refentrytitle>updatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>
+207
View File
@@ -0,0 +1,207 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="updatectl" conditional='ENABLE_SYSUPDATE'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>updatectl</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>updatectl</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>updatectl</refname>
<refpurpose>Control the system update service</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>updatectl</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="req">COMMAND</arg>
<arg choise="opt" rep="repeat">TARGET</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>updatectl</command> may be used to check for and install system updates managed by
<citerefentry><refentrytitle>systemd-sysupdated.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
</para>
</refsect1>
<refsect1>
<title>Commands</title>
<para>The following commands are understood:</para>
<variablelist>
<varlistentry>
<term><command>list</command> [<replaceable>TARGET</replaceable>[@<replaceable>VERSION</replaceable>]]</term>
<listitem><para>Show information about targets and their versions.</para>
<para>When no <replaceable>TARGET</replaceable> is specified, this command lists all
available targets. When a <replaceable>TARGET</replaceable> is specified without a
<replaceable>VERSION</replaceable>, this command lists all known versions of the
specified target. If a <replaceable>VERSION</replaceable> is specified, this command
lists all known information about the specific version.</para>
<para>See the example below for details of the output.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><command>check</command> [<replaceable>TARGET</replaceable>…]</term>
<listitem><para>Check if any updates are available for the specified targets. If no targets
are specified, all available targets will be checked for updates.</para>
<para>See the example below for details of the output.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><command>update</command> [<replaceable>TARGET</replaceable>[@<replaceable>VERSION</replaceable>]…]</term>
<listitem><para>Update the specified targets to the specified versions. If a target
is specified without a version, then it will be updated to the latest version. If no targets are
specified, then all available targets will be updated to the latest version.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><command>vacuum</command> [<replaceable>TARGET</replaceable>…]</term>
<listitem><para>Clean up old versions of the specified targets. If no targets are specified,
all available targets will be vacuumed.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following commands are understood:</para>
<variablelist>
<varlistentry>
<term><option>--reboot</option></term>
<listitem><para>When used with the <command>update</command> command, reboots the system
after updates finish applying. If any update fails, the system will not reboot.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--offline</option></term>
<listitem><para>When used with the <command>list</command> command, disables fetching
metadata from the network. This makes the <command>list</command> command only return
information that is available locally (i.e. about versions already installed on the system).
</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="no-legend" />
</variablelist>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>On success, 0 is returned, a non-zero failure code otherwise.</para>
</refsect1>
<xi:include href="common-variables.xml" />
<refsect1>
<title>Examples</title>
<para>Note that these examples are just here for demonstration purposes, and the output of these commands
is free to change. These commands are intended for display to a user. If you'd like machine-readable
output, use the
<citerefentry><refentrytitle>org.freedesktop.sysupdate1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
D-Bus API directly.</para>
<example>
<title>Output from <command>list</command></title>
<programlisting>$ <command>updatectl list</command>
TARGET VERSION PATH
host 48 sysupdate.d
machine:fedora 38 /var/lib/machines/fedora.raw
component:shim 15.7 sysupdate.shim.d
$ <command>updatectl list host</command>
VERSION STATUS
↻ 50 candidate
49 available
● 48 current
47 available
46 available
45 available
[...]
× 25 available+obsolete
× 24 available+obsolete
× 23 available+obsolete
[...]
$ <command>updatectl list host@49</command>
↻ Version: 50
State: candidate
ChangeLog: https://vendor.com/os/v50.html
TYPE PATH PTUUID PTFLAGS SHA256
url-file http://dl.vendor.com/os/uki_50 - - 90f6534282dd720f7a222fa781086990dc9c83e5c7499f085970a8e75e3ac349
url-file http://dl.vendor.com/os/usr_50_981a5b84-a301-c819-f681-3e575fe16f16 981a5b84-a301-c819-f681-3e575fe16f16 - c0596ab1095258ec6f16c7c281a50d71c419a9f587c1ef858cfbbb69fb0a16f3
url-file http://dl.vendor.com/os/verity_50_2f8d0f3b-f80a-6ddc-a556-3722bfbb5b79 2f8d0f3b-f80a-6ddc-a556-3722bfbb5b79 - e1e90a128e038b3a53455e55d1ca717c743aba31fe6b4b4624109df0243c6338
url-file http://dl.vendor.com/os/verity_sig_50 - - ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356
</programlisting>
</example>
<example>
<title>Checking for and installing updates</title>
<programlisting>$ <command>updatectl check</command>
TARGET UPDATE
host 48 → 50
machine:fedora 38 → 40
$ <command>updatectl update host machine:fedora@39</command>
[...]
✓ host@50
✓ machine:fedora@39</programlisting>
</example>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-sysupdate</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<citerefentry><refentrytitle>systemd-sysupdated.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
</para>
</refsect1>
</refentry>
+1
View File
@@ -277,6 +277,7 @@ conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP', pkgdatadir / 'lang
conf.set_quoted('SYSTEMD_MAKEFS_PATH', libexecdir / 'systemd-makefs')
conf.set_quoted('SYSTEMD_PULL_PATH', libexecdir / 'systemd-pull')
conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH', libexecdir / 'systemd-shutdown')
conf.set_quoted('SYSTEMD_SYSUPDATE_PATH', libexecdir / 'systemd-sysupdate')
conf.set_quoted('SYSTEMD_TEST_DATA', testdata_dir)
conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', bindir / 'systemd-tty-ask-password-agent')
conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH', libexecdir / 'systemd-update-helper')
+1
View File
@@ -11,5 +11,6 @@ src/machine/org.freedesktop.machine1.policy
src/network/org.freedesktop.network1.policy
src/portable/org.freedesktop.portable1.policy
src/resolve/org.freedesktop.resolve1.policy
src/sysupdate/org.freedesktop.sysupdate1.policy
src/timedate/org.freedesktop.timedate1.policy
src/core/dbus-unit.c
+6
View File
@@ -63,6 +63,12 @@ const BusLocator* const bus_systemd_mgr = &(BusLocator){
.interface = "org.freedesktop.systemd1.Manager"
};
const BusLocator* const bus_sysupdate_mgr = &(BusLocator){
.destination = "org.freedesktop.sysupdate1",
.path = "/org/freedesktop/sysupdate1",
.interface = "org.freedesktop.sysupdate1.Manager"
};
const BusLocator* const bus_timedate = &(BusLocator){
.destination = "org.freedesktop.timedate1",
.path = "/org/freedesktop/timedate1",
+1
View File
@@ -20,6 +20,7 @@ extern const BusLocator* const bus_oom_mgr;
extern const BusLocator* const bus_portable_mgr;
extern const BusLocator* const bus_resolve_mgr;
extern const BusLocator* const bus_systemd_mgr;
extern const BusLocator* const bus_sysupdate_mgr;
extern const BusLocator* const bus_timedate;
extern const BusLocator* const bus_timesync_mgr;
+28
View File
@@ -13,6 +13,12 @@ systemd_sysupdate_sources = files(
'sysupdate.c',
)
systemd_updatectl_sources = files(
'sysupdate-update-set-flags.c',
'sysupdate-util.c',
'updatectl.c',
)
executables += [
libexec_template + {
'name' : 'systemd-sysupdate',
@@ -30,4 +36,26 @@ executables += [
threads,
],
},
libexec_template + {
'name' : 'systemd-sysupdated',
'dbus' : true,
'conditions' : ['ENABLE_SYSUPDATE'],
'sources' : files('sysupdated.c'),
'dependencies' : threads,
},
executable_template + {
'name' : 'updatectl',
'public' : true,
'sources' : systemd_updatectl_sources,
'conditions' : ['ENABLE_SYSUPDATE'],
},
]
if conf.get('ENABLE_SYSUPDATE') == 1
install_data('org.freedesktop.sysupdate1.conf',
install_dir : dbuspolicydir)
install_data('org.freedesktop.sysupdate1.service',
install_dir : dbussystemservicedir)
install_data('org.freedesktop.sysupdate1.policy',
install_dir : polkitpolicydir)
endif
@@ -0,0 +1,88 @@
<?xml version="1.0"?> <!--*-nxml-*-->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"https://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1-or-later
This file is part of systemd.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
-->
<busconfig>
<policy user="root">
<allow own="org.freedesktop.sysupdate1"/>
<allow send_destination="org.freedesktop.sysupdate1"/>
<allow receive_sender="org.freedesktop.sysupdate1"/>
</policy>
<policy context="default">
<deny send_destination="org.freedesktop.sysupdate1"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.DBus.Peer"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.DBus.Properties"
send_member="Get"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.DBus.Properties"
send_member="GetAll"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Manager"
send_member="ListTargets"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Manager"
send_member="ListJobs"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Manager"
send_member="ListAppStream"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Target"
send_member="List"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Target"
send_member="Describe"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Target"
send_member="CheckNew"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Target"
send_member="Update"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Target"
send_member="Vacuum"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Target"
send_member="GetAppstream"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Target"
send_member="GetVersion"/>
<allow send_destination="org.freedesktop.sysupdate1"
send_interface="org.freedesktop.sysupdate1.Job"
send_member="Cancel"/>
<allow receive_sender="org.freedesktop.sysupdate1"/>
</policy>
</busconfig>
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"https://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1-or-later
This file is part of systemd.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
-->
<policyconfig>
<vendor>The systemd Project</vendor>
<vendor_url>https://systemd.io</vendor_url>
<!--
SECURITY: the default policy allows any user with an active session on the local console to check
for updates and update the system to the latest version without extra authentication.
Depending on the use case it might make sense to request authentication here, or add a polkit
rule to only allow access to these actions for members of a given group.
The default policy matches prior art in distributions and system update managers. To update a
system, for example: packagekit requires only a user with an active session, eos-updater needs
a user at the console, and rpm-ostree (generally) needs an "administrative user" at the computer.
Without this default, distributions hoping to use sysupdate as an update mechanism will have to
set the policy to it anyhow.
-->
<action id="org.freedesktop.sysupdate1.check">
<description gettext-domain="systemd">Check for system updates</description>
<message gettext-domain="systemd">Authentication is required to check for system updates</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.sysupdate1.update">
<description gettext-domain="systemd">Install system updates</description>
<message gettext-domain="systemd">Authentication is required to install system updates</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.sysupdate1.update-to-version">
<description gettext-domain="systemd">Install specific system version</description>
<message gettext-domain="systemd">Authentication is required to update the system to a specific (possibly old) version</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.freedesktop.sysupdate1.vacuum">
<description gettext-domain="systemd">Cleanup old system updates</description>
<message gettext-domain="systemd">Authentication is required to cleanup old system updates</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[D-BUS Service]
Name=org.freedesktop.sysupdate1
Exec=/bin/false
User=root
SystemdService=dbus-org.freedesktop.sysupdate1.service
+2
View File
@@ -3,3 +3,5 @@
#pragma once
int reboot_now(void);
#define SD_SYSTEMD_SYSUPDATE_OFFLINE (UINT64_C(1) << 0)
+1 -1
View File
@@ -1543,7 +1543,7 @@ static int run(int argc, char *argv[]) {
return r;
/* SIGCHLD signal must be blocked for sd_event_add_child to work */
BLOCK_SIGNALS(SIGCHLD);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
return sysupdate_main(argc, argv);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -3,5 +3,6 @@
integration_tests += [
integration_test_template + {
'name' : fs.name(meson.current_source_dir()),
'vm' : true,
},
]
+59 -16
View File
@@ -6,8 +6,10 @@ set -eux
set -o pipefail
SYSUPDATE=/lib/systemd/systemd-sysupdate
SYSUPDATED=/lib/systemd/systemd-sysupdated
SECTOR_SIZES=(512 4096)
WORKDIR="$(mktemp -d /var/tmp/test-72-XXXXXX)"
CONFIGDIR="/run/sysupdate.d"
BACKING_FILE="$WORKDIR/joined.raw"
export SYSTEMD_ESP_PATH="$WORKDIR/esp"
export SYSTEMD_XBOOTLDR_PATH="$WORKDIR/xbootldr"
@@ -28,6 +30,17 @@ if [[ ! -e /dev/loop-control ]]; then
SECTOR_SIZES=(512)
fi
# Set up sysupdated drop-in pointing at the correct definitions and setting
# no verification of images.
mkdir -p /run/systemd/system/systemd-sysupdated.service.d
cat >/run/systemd/system/systemd-sysupdated.service.d/override.conf<<EOF
[Service]
Environment=SYSTEMD_SYSUPDATE_NO_VERIFY=1
Environment=SYSTEMD_ESP_PATH=${SYSTEMD_ESP_PATH}
Environment=SYSTEMD_XBOOTLDR_PATH=${SYSTEMD_XBOOTLDR_PATH}
EOF
systemctl daemon-reload
at_exit() {
set +e
@@ -68,9 +81,9 @@ update_now() {
# Update to newest version. First there should be an update ready, then we
# do the update, and then there should not be any ready anymore
"$SYSUPDATE" --definitions="$WORKDIR/defs" --verify=no check-new
"$SYSUPDATE" --definitions="$WORKDIR/defs" --verify=no update
(! "$SYSUPDATE" --definitions="$WORKDIR/defs" --verify=no check-new)
"$SYSUPDATE" --verify=no check-new
"$SYSUPDATE" --verify=no update
(! "$SYSUPDATE" --verify=no check-new)
}
verify_version() {
@@ -127,12 +140,12 @@ size=2048, type=2c7357ed-ebd2-46d9-aec1-23d437ec2bf5, name=_empty
size=2048, type=2c7357ed-ebd2-46d9-aec1-23d437ec2bf5, name=_empty
EOF
for d in "dirs" "defs"; do
rm -rf "${WORKDIR:?}/$d"
mkdir -p "$WORKDIR/$d"
for d in "$WORKDIR/dirs" "$CONFIGDIR"; do
rm -rf "$d"
mkdir -p "$d"
done
cat >"$WORKDIR/defs/01-first.conf" <<EOF
cat >"$CONFIGDIR/01-first.conf" <<EOF
[Source]
Type=regular-file
Path=$WORKDIR/source
@@ -145,7 +158,7 @@ MatchPattern=part1-@v
MatchPartitionType=root-x86-64
EOF
cat >"$WORKDIR/defs/02-second.conf" <<EOF
cat >"$CONFIGDIR/02-second.conf" <<EOF
[Source]
Type=regular-file
Path=$WORKDIR/source
@@ -158,7 +171,7 @@ MatchPattern=part2-@v
MatchPartitionType=root-x86-64-verity
EOF
cat >"$WORKDIR/defs/03-third.conf" <<EOF
cat >"$CONFIGDIR/03-third.conf" <<EOF
[Source]
Type=directory
Path=$WORKDIR/source
@@ -172,7 +185,7 @@ MatchPattern=dir-@v
InstancesMax=3
EOF
cat >"$WORKDIR/defs/04-fourth.conf" <<EOF
cat >"$CONFIGDIR/04-fourth.conf" <<EOF
[Source]
Type=regular-file
Path=$WORKDIR/source
@@ -191,7 +204,7 @@ TriesDone=0
InstancesMax=2
EOF
cat >"$WORKDIR/defs/05-fifth.conf" <<EOF
cat >"$CONFIGDIR/05-fifth.conf" <<EOF
[Source]
Type=regular-file
Path=$WORKDIR/source
@@ -227,15 +240,45 @@ EOF
test ! -f "$WORKDIR/xbootldr/EFI/Linux/uki_v1.efi.extra.d/extra.addon.efi"
test ! -d "$WORKDIR/xbootldr/EFI/Linux/uki_v1.efi.extra.d"
# Create fourth version, and update through a file:// URL. This should be
# Create fourth version, update using updatectl and verify it replaced the
# second version
new_version "$sector_size" v4
if [[ -x "$SYSUPDATED" ]] && command -v updatectl; then
systemctl start systemd-sysupdated
"$SYSUPDATE" --verify=no check-new
updatectl update
else
# If no updatectl, gracefully fall back to systemd-sysupdate
update_now
fi
# User-facing updatectl returns 0 if there's no updates, so use the low-level
# utility to make sure we did upgrade
(! "$SYSUPDATE" --verify=no check-new )
verify_version "$blockdev" "$sector_size" v4 2 4
# Next, let's run updatectl's various inspection commands. We're not
# testing for specific output, but this will at least catch obvious crashes
# and allow updatectl to run under the various sanitizers. We create a
# component so that updatectl has multiple targets to list.
if [[ -x "$SYSUPDATED" ]] && command -v updatectl; then
mkdir -p /run/sysupdate.test.d/
cp "$CONFIGDIR/01-first.conf" /run/sysupdate.test.d/01-first.conf
updatectl list
updatectl list host
updatectl list host@v4
updatectl check
rm -r /run/sysupdate.test.d
fi
# Create fifth version, and update through a file:// URL. This should be
# almost as good as testing HTTP, but is simpler for us to set up. file:// is
# abstracted in curl for us, and since our main goal is to test our own code
# (and not curl) this test should be quite good even if not comprehensive. This
# will test the SHA256SUMS logic at least (we turn off GPG validation though,
# see above)
new_version "$sector_size" v4
new_version "$sector_size" v5
cat >"$WORKDIR/defs/02-second.conf" <<EOF
cat >"$CONFIGDIR/02-second.conf" <<EOF
[Source]
Type=url-file
Path=file://$WORKDIR/source
@@ -248,7 +291,7 @@ MatchPattern=part2-@v
MatchPartitionType=root-x86-64-verity
EOF
cat >"$WORKDIR/defs/03-third.conf" <<EOF
cat >"$CONFIGDIR/03-third.conf" <<EOF
[Source]
Type=url-tar
Path=file://$WORKDIR/source
@@ -263,7 +306,7 @@ InstancesMax=3
EOF
update_now
verify_version "$blockdev" "$sector_size" v4 2 4
verify_version "$blockdev" "$sector_size" v5 1 3
# Cleanup
[[ -b "$blockdev" ]] && losetup --detach "$blockdev"
+5
View File
@@ -640,6 +640,11 @@ units = [
'file' : 'systemd-sysupdate.service.in',
'conditions' : ['ENABLE_SYSUPDATE'],
},
{
'file' : 'systemd-sysupdated.service.in',
'conditions' : ['ENABLE_SYSUPDATE'],
'symlinks' : ['dbus-org.freedesktop.sysupdate1.service'],
},
{
'file' : 'systemd-sysupdate.timer',
'conditions' : ['ENABLE_SYSUPDATE'],
+30
View File
@@ -0,0 +1,30 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=System Update Service
Documentation=man:systemd-sysupdated.service(8)
Documentation=man:org.freedesktop.sysupdate1(5)
[Service]
ExecStart={{LIBEXECDIR}}/systemd-sysupdated
BusName=org.freedesktop.sysupdate1
KillMode=mixed
CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_SYS_ADMIN CAP_SETPCAP CAP_DAC_OVERRIDE CAP_LINUX_IMMUTABLE
NoNewPrivileges=yes
MemoryDenyWriteExecute=yes
ProtectHostname=yes
RestrictRealtime=yes
RestrictNamespaces=net
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
SystemCallFilter=@system-service @mount
SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
{{SERVICE_WATCHDOG}}