streamLayeredImage: Allow customizing ownership

This opens the way towards building images where Nix can be used as an
unprivileged user (in single-user mode).
This commit is contained in:
WxNzEMof 2024-01-22 11:48:36 +00:00
parent fcea2b6260
commit 0ec13cdb90
2 changed files with 32 additions and 12 deletions

View File

@ -907,6 +907,11 @@ rec {
, # Time of creation of the image. Passing "now" will make the
# created date be the time of building.
created ? "1970-01-01T00:00:01Z"
, # Credentials for file ownership.
uid ? 0
, gid ? 0
, uname ? "root"
, gname ? "root"
, # Optional bash script to run on the files prior to fixturizing the layer.
extraCommands ? ""
, # Optional bash script to run inside fakeroot environment.
@ -1007,7 +1012,7 @@ rec {
conf = runCommand "${baseName}-conf.json"
{
inherit fromImage maxLayers created;
inherit fromImage maxLayers created uid gid uname gname;
imageName = lib.toLower name;
preferLocalBuild = true;
passthru.imageTag =
@ -1086,14 +1091,22 @@ rec {
"store_layers": $store_layers[0],
"customisation_layer", $customisation_layer,
"repo_tag": $repo_tag,
"created": $created
"created": $created,
"uid": $uid,
"gid": $gid,
"uname": $uname,
"gname": $gname
}
' --arg store_dir "${storeDir}" \
--argjson from_image ${if fromImage == null then "null" else "'\"${fromImage}\"'"} \
--slurpfile store_layers store_layers.json \
--arg customisation_layer ${customisationLayer} \
--arg repo_tag "$imageName:$imageTag" \
--arg created "$created" |
--arg created "$created" \
--arg uid "$uid" \
--arg gid "$gid" \
--arg uname "$uname" \
--arg gname "$gname" |
tee $out
'';

View File

@ -9,6 +9,8 @@ image as an uncompressed tarball to stdout:
the fields with the same name on the image spec [2].
* "created" can be "now".
* "created" is also used as mtime for files added to the image.
* "uid", "gid", "uname", "gname" is the file ownership, for example,
0, 0, "root", "root".
* "store_layers" is a list of layers in ascending order, where each
layer is the list of store paths to include in that layer.
@ -45,7 +47,7 @@ from datetime import datetime, timezone
from collections import namedtuple
def archive_paths_to(obj, paths, mtime):
def archive_paths_to(obj, paths, mtime, uid, gid, uname, gname):
"""
Writes the given store paths as a tar file to the given stream.
@ -61,10 +63,10 @@ def archive_paths_to(obj, paths, mtime):
def apply_filters(ti):
ti.mtime = mtime
ti.uid = 0
ti.gid = 0
ti.uname = "root"
ti.gname = "root"
ti.uid = uid
ti.gid = gid
ti.uname = uname
ti.gname = gname
return ti
def nix_root(ti):
@ -208,7 +210,7 @@ def overlay_base_config(from_image, final_config):
return final_config
def add_layer_dir(tar, paths, store_dir, mtime):
def add_layer_dir(tar, paths, store_dir, mtime, uid, gid, uname, gname):
"""
Appends given store paths to a TarFile object as a new layer.
@ -231,7 +233,7 @@ def add_layer_dir(tar, paths, store_dir, mtime):
archive_paths_to(
extract_checksum,
paths,
mtime=mtime,
mtime, uid, gid, uname, gname
)
(checksum, size) = extract_checksum.extract()
@ -247,7 +249,7 @@ def add_layer_dir(tar, paths, store_dir, mtime):
archive_paths_to(
write,
paths,
mtime=mtime,
mtime, uid, gid, uname, gname
)
write.close()
@ -324,6 +326,10 @@ def main():
else datetime.fromisoformat(conf["created"])
)
mtime = int(created.timestamp())
uid = int(conf["uid"])
gid = int(conf["gid"])
uname = conf["uname"]
gname = conf["gname"]
store_dir = conf["store_dir"]
from_image = load_from_image(conf["from_image"])
@ -336,7 +342,8 @@ def main():
for num, store_layer in enumerate(conf["store_layers"], start=start):
print("Creating layer", num, "from paths:", store_layer,
file=sys.stderr)
info = add_layer_dir(tar, store_layer, store_dir, mtime=mtime)
info = add_layer_dir(tar, store_layer, store_dir,
mtime, uid, gid, uname, gname)
layers.append(info)
print("Creating layer", len(layers) + 1, "with customisation...",