systemd: support systemd.tmpfiles.settings
Signed-off-by: phanirithvij <phanirithvij2000@gmail.com>
This commit is contained in:
parent
a79e02428d
commit
91323fb350
4 changed files with 205 additions and 14 deletions
|
|
@ -1,6 +1,139 @@
|
|||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) types;
|
||||
inherit (lib)
|
||||
concatStrings
|
||||
concatStringsSep
|
||||
getLib
|
||||
literalExpression
|
||||
mapAttrsToList
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
# copied from nixos/modules/system/boot/systemd/tmpfiles.nix
|
||||
settingsOption = {
|
||||
description = ''
|
||||
Declare systemd-tmpfiles rules to create, delete, and clean up volatile
|
||||
and temporary files and directories.
|
||||
|
||||
Even though the service is called `*tmp*files` you can also create
|
||||
persistent files.
|
||||
'';
|
||||
example = {
|
||||
"10-mypackage" = {
|
||||
"/var/lib/my-service/statefolder".d = {
|
||||
mode = "0755";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
type = types.attrsOf (
|
||||
types.attrsOf (
|
||||
types.attrsOf (
|
||||
types.submodule (
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
type = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
example = "d";
|
||||
description = ''
|
||||
The type of operation to perform on the file.
|
||||
|
||||
The type consists of a single letter and optionally one or more
|
||||
modifier characters.
|
||||
|
||||
Please see the upstream documentation for the available types and
|
||||
more details:
|
||||
<https://www.freedesktop.org/software/systemd/man/tmpfiles.d>
|
||||
'';
|
||||
};
|
||||
mode = mkOption {
|
||||
type = types.str;
|
||||
default = "-";
|
||||
example = "0755";
|
||||
description = ''
|
||||
The file access mode to use when creating this file or directory.
|
||||
'';
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "-";
|
||||
example = "root";
|
||||
description = ''
|
||||
The user of the file.
|
||||
|
||||
This may either be a numeric ID or a user/group name.
|
||||
|
||||
If omitted or when set to `"-"`, the user and group of the user who
|
||||
invokes systemd-tmpfiles is used.
|
||||
'';
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "-";
|
||||
example = "root";
|
||||
description = ''
|
||||
The group of the file.
|
||||
|
||||
This may either be a numeric ID or a user/group name.
|
||||
|
||||
If omitted or when set to `"-"`, the user and group of the user who
|
||||
invokes systemd-tmpfiles is used.
|
||||
'';
|
||||
};
|
||||
age = mkOption {
|
||||
type = types.str;
|
||||
default = "-";
|
||||
example = "10d";
|
||||
description = ''
|
||||
Delete a file when it reaches a certain age.
|
||||
|
||||
If a file or directory is older than the current time minus the age
|
||||
field, it is deleted.
|
||||
|
||||
If set to `"-"` no automatic clean-up is done.
|
||||
'';
|
||||
};
|
||||
argument = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "";
|
||||
description = ''
|
||||
An argument whose meaning depends on the type of operation.
|
||||
|
||||
Please see the upstream documentation for the meaning of this
|
||||
parameter in different situations:
|
||||
<https://www.freedesktop.org/software/systemd/man/tmpfiles.d>
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
# generates a single entry for a tmpfiles.d rule
|
||||
settingsEntryToRule = path: entry: ''
|
||||
'${entry.type}' '${path}' '${entry.mode}' '${entry.user}' '${entry.group}' '${entry.age}' ${entry.argument}
|
||||
'';
|
||||
|
||||
# generates a list of tmpfiles.d rules from the attrs (paths) under tmpfiles.settings.<name>
|
||||
pathsToRules = mapAttrsToList (
|
||||
path: types: concatStrings (mapAttrsToList (_type: settingsEntryToRule path) types)
|
||||
);
|
||||
|
||||
mkRuleFileContent = paths: concatStrings (pathsToRules paths);
|
||||
|
||||
in
|
||||
{
|
||||
options = {
|
||||
|
|
@ -15,13 +148,60 @@ in
|
|||
for the exact format.
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.tmpfiles.settings = lib.mkOption settingsOption;
|
||||
|
||||
systemd.tmpfiles.packages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [ ];
|
||||
example = literalExpression "[ pkgs.lvm2 ]";
|
||||
apply = map getLib;
|
||||
description = ''
|
||||
List of packages containing {command}`systemd-tmpfiles` rules.
|
||||
|
||||
All files ending in .conf found in
|
||||
{file}`«pkg»/lib/tmpfiles.d`
|
||||
will be included.
|
||||
If this folder does not exist or does not contain any files an error will be returned instead.
|
||||
|
||||
If a {file}`lib` output is available, rules are searched there and only there.
|
||||
If there is no {file}`lib` output it will fall back to {file}`out`
|
||||
and if that does not exist either, the default output will be used.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = {
|
||||
environment.etc."tmpfiles.d/00-system-manager.conf".text = ''
|
||||
# This file is created automatically and should not be modified.
|
||||
# Please change the option ‘systemd.tmpfiles.rules’ instead.
|
||||
${lib.concatStringsSep "\n" config.systemd.tmpfiles.rules}
|
||||
environment.etc = {
|
||||
"tmpfiles.d".source = pkgs.symlinkJoin {
|
||||
name = "tmpfiles.d";
|
||||
paths = map (p: p + "/lib/tmpfiles.d") config.systemd.tmpfiles.packages;
|
||||
postBuild = ''
|
||||
for i in $(cat $pathsPath); do
|
||||
(test -d "$i" && test $(ls "$i"/*.conf | wc -l) -ge 1) || (
|
||||
echo "ERROR: The path '$i' from systemd.tmpfiles.packages contains no *.conf files."
|
||||
exit 1
|
||||
)
|
||||
done
|
||||
'';
|
||||
};
|
||||
};
|
||||
systemd.tmpfiles.packages =
|
||||
[
|
||||
(pkgs.writeTextFile {
|
||||
name = "system-manager-tmpfiles.d";
|
||||
destination = "/lib/tmpfiles.d/00-system-manager.conf";
|
||||
text = ''
|
||||
# This file is created automatically and should not be modified.
|
||||
# Please change the option ‘systemd.tmpfiles.rules’ instead.
|
||||
|
||||
${concatStringsSep "\n" config.systemd.tmpfiles.rules}
|
||||
'';
|
||||
})
|
||||
]
|
||||
++ (mapAttrsToList (
|
||||
name: paths: pkgs.writeTextDir "lib/tmpfiles.d/${name}.conf" (mkRuleFileContent paths)
|
||||
) config.systemd.tmpfiles.settings);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ pub fn activate(store_path: &StorePath, ephemeral: bool) -> Result<()> {
|
|||
match etc_files::activate(store_path, old_state.file_tree, ephemeral) {
|
||||
Ok(etc_tree) => {
|
||||
log::info!("Activating tmp files...");
|
||||
match tmp_files::activate() {
|
||||
match tmp_files::activate(&etc_tree) {
|
||||
Ok(_) => {
|
||||
log::debug!("Successfully created tmp files");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ impl FileStatus {
|
|||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FileTree {
|
||||
status: FileStatus,
|
||||
path: PathBuf,
|
||||
pub(crate) path: PathBuf,
|
||||
// TODO directories and files are now both represented as a string associated with a nested
|
||||
// map. For files the nested map is simple empty.
|
||||
// We could potentially optimise this.
|
||||
nested: HashMap<String, FileTree>,
|
||||
pub(crate) nested: HashMap<String, FileTree>,
|
||||
}
|
||||
|
||||
impl AsRef<FileTree> for FileTree {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,26 @@
|
|||
use crate::activate;
|
||||
use crate::activate::etc_files::FileTree;
|
||||
|
||||
use super::ActivationResult;
|
||||
use std::process;
|
||||
|
||||
type TmpFilesActivationResult = ActivationResult<()>;
|
||||
|
||||
pub fn activate() -> TmpFilesActivationResult {
|
||||
pub fn activate(etc_tree: &FileTree) -> TmpFilesActivationResult {
|
||||
let conf_files = etc_tree
|
||||
.nested
|
||||
.get("etc")
|
||||
.unwrap()
|
||||
.nested
|
||||
.get("tmpfiles.d")
|
||||
.unwrap()
|
||||
.nested
|
||||
.iter()
|
||||
.map(|(_, node)| node.path.to_string_lossy().to_string())
|
||||
.collect::<Vec<_>>();
|
||||
let mut cmd = process::Command::new("systemd-tmpfiles");
|
||||
cmd.arg("--create")
|
||||
.arg("--remove")
|
||||
.arg("/etc/tmpfiles.d/00-system-manager.conf");
|
||||
cmd.arg("--create").arg("--remove").args(conf_files);
|
||||
log::debug!("running {:#?}", cmd);
|
||||
let output = cmd
|
||||
.stdout(process::Stdio::inherit())
|
||||
.stderr(process::Stdio::inherit())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue