summaryrefslogtreecommitdiffstats
path: root/doc/spec/rootless-builds.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/spec/rootless-builds.txt')
-rw-r--r--doc/spec/rootless-builds.txt177
1 files changed, 177 insertions, 0 deletions
diff --git a/doc/spec/rootless-builds.txt b/doc/spec/rootless-builds.txt
new file mode 100644
index 0000000..5a5af83
--- /dev/null
+++ b/doc/spec/rootless-builds.txt
@@ -0,0 +1,177 @@
+Supporting rootless builds
+==========================
+
+Status: recommendation, stable
+Version: 1.0
+
+Background
+----------
+
+Traditionally, Debian packages have required (fake)root privileges for some
+of the "debian/rules" targets. This has required also a split between build
+and binary targets; making the builds slower, due to the increased amount
+of invocations of "debian/rules" and the overhead of using fakeroot(1) or
+equivalent fake environments, or less secure due to the increased dangers
+of running under real root via sudo or equivalent.
+
+On this document when talking about "(fake)root" privileges, it will refer
+to any mechanism, supported by the dpkg-buildpackage "-r/--root-command"
+option, that can provide either a real or faked root user environment.
+
+Specification
+-------------
+
+We add a new field to the "Source" stanza of debian/control:
+
+ Rules-Requires-Root: no | binary-targets | <implementations-keywords>
+
+The case sensitive values are defined as:
+
+ * If "no", then "debian/rules binary" will not require root at all (not even
+ fakeroot). This is the default in dpkg-build-api level >= 1.
+ - If the "no" keyword is used, it MUST be the only keyword in that field
+ and MUST appear exactly once.
+
+ * If "binary-targets", then "debian/rules binary" (etc.) must always be run
+ under (fake)root. This is the status quo, default in dpkg-build-api level 0.
+
+ * <implementations-keywords> will be a space separated list of keywords which
+ define when root is required.
+
+ - Keywords consists of <namespace>/<cases>. The "namespace" part cannot
+ contain "/" or whitespace. The "cases" part cannot contain whitespace.
+ Furthermore, both parts MUST consist entirely of printable ASCII
+ characters.
+
+ - Each tool/package will define a namespace named after itself and provide
+ a number of cases where (fake)root is required.
+ (See also "Implementation provided keywords".)
+
+ - When "Rules-Requires-Root" is set to <implementations-keywords>, the
+ builder (i.e. whatever is executing debian/rules) will expose an
+ interface that is used to run a command under (fake)root via the
+ "Gain Root API". If the builder cannot provide such a command, it
+ MUST behave like "Rules-Requires-Root" was set to "binary-targets",
+ i.e. run "debian/rules binary" under (fake)root.
+
+When the builder supports this specification, it MUST notify this fact to
+the rules file via the "DEB_RULES_REQUIRES_ROOT" environment variable, with
+the value it has obtained from the Rules-Requires-Root field or some builder
+specific override mechanism, which will denote the level of support the
+builder has chosen to commit to take effect during the build. When set,
+it MUST be a valid value for the Rules-Requires-Root field. If unset,
+the build system SHOULD assume that the builder does not recognize the
+Rules-Requires-Root field at all.
+
+It is always permissible for a builder to ignore this field and fall back to
+running the binary targets under (fake)root. This is to ensure backwards
+compatibility when builds are performed by legacy builders or older versions
+of the tooling.
+
+Tools called from the rules file MUST cope gracefully with being called under
+(fake)root even when Rules-Requires-Root is set to a value that implies they
+should not be (e.g. "no"). However, they MUST NOT attempt to run processes
+under (fake)root when run as a regular user when Rules-Requires-Root does
+not list any keywords they respond to.
+
+Tools MUST gracefully ignore valid unknown keywords outside their namespace.
+They MAY warn about unknown keywords inside their namespace.
+
+The value of this field MUST NOT change the content of the package in any
+way. Notably, packages that are bit-for-bit reproducible MUST still provide
+bit-for-bit identical results even when the field is ignored.
+
+Implementation provided keywords
+--------------------------------
+
+Keywords provided by various implementations:
+
+ * dpkg/target-subcommand: When the package needs to run a given command
+ under (fake)root within the "debian/rules" files directly, this MUST be
+ declared via this keyword.
+
+ * dpkg/target/<target-name>: When a specific "debian/rules" unofficial
+ target (none of the root-requiring "binary-indep", "binary-arch", "binary",
+ "clean", nor the non-root-requiring "build-indep", "build-arch", "build")
+ needs to be run under (fake)root, this MUST be declared via this dynamic
+ keyword, where <target-name> is the name of the "debian/rules" target.
+
+ * debhelper/upstream-make-install: The dh_auto_install command will run
+ the "install" target from the upstream's Makefile under (fake)root (for
+ the "makefile" build system or one derived from it).
+
+Gain Root API
+-------------
+
+The builder will provide a command to promote a given command to (fake)root
+by exposing it in the environment variable "DEB_GAIN_ROOT_CMD". Tools that
+need this promotion will then use it like the following:
+
+ $DEB_GAIN_ROOT_CMD cmd-that-needs-root ...
+
+This command is subject to the same requirements as the "gain-root-command"
+that dpkg-buildpackage accepts via its "-r/--root-command" option, which
+means that it can contain space-separated parameters. If dpkg-buildpackage is
+called with "-r/--root-command", then dpkg-buildpackage shall use that value
+as the value for "DEB_GAIN_ROOT_CMD". The command SHOULD preserve all the
+environment variables, unmodified.
+
+The variable SHOULD only be provided when there is a need for it. Notably
+when "Rules-Requires-Root" is either "no" or "binary-targets" the variable
+SHOULD NOT be defined.
+
+(The "DEB_GAIN_ROOT_CMD" variable used to be named "DPKG_GAIN_ROOT_CMD"
+starting with dpkg 1.19.0 and before dpkg 1.19.1 when this specification
+got released as stable. The old name MUST not be used.)
+
+Common cases
+------------
+
+ * Upstream installation insists on "sudo make install"-like behavior.
+ => Use dpkg/target-subcommand or debhelper/upstream-make-install.
+
+ * Files shipped in the package must be owned by another user than root.
+ => Not covered; use "binary-targets" for now until dpkg+debhelper
+ provides the required interface.
+
+Prototyping/preparation
+=======================
+
+dpkg side
+---------
+
+dpkg-deb --build provides the --root-owner-group option so that dh_builddeb
+or direct calls can control the owner/group file values w/o requiring
+(fake)root.
+
+dpkg-buildpackage must export DEB_GAIN_ROOT_CMD when necessary (for
+prototyping, doing this unconditionally would be fine).
+
+
+debhelper side
+--------------
+
+When the field is present:
+
+ * dh_testroot will behave as usual when Rules-Requires-Root is not present
+ or set to "binary-targets".
+
+ * dh_testroot will be a no-op when Rules-Requires-Root is set to "no".
+
+ * Otherwise, dh_testroot will either verify that it is run under (fake)root
+ (as usual) OR assert that DEB_GAIN_ROOT_CMD is defined.
+
+ * debhelper build systems will be patched to check for the
+ "debhelper/upstream-make-install" keyword and use the "Gain Root API"
+ accordingly.
+
+ * All other (src:)debhelper commands will skip their calls to chown
+ (currently they just reset them to "0:0" anyway).
+
+With the above, a default "dh $@" will no longer require (fake)root when
+built (and Rules-Requires-Root is "no").
+
+Prototyping:
+
+ * During prototyping, dh_builddeb can wrap the dpkg-deb --build call with
+ fakeroot (when not already root).