push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,281 @@
{
config,
lib,
pkgs,
...
}:
# openafsMod, openafsBin, mkCellServDB
with import ./lib.nix { inherit config lib pkgs; };
let
inherit (lib)
getBin
literalExpression
mkOption
mkIf
optionalString
singleton
types
;
cfg = config.services.openafsClient;
cellServDB = pkgs.fetchurl {
url = "http://dl.central.org/dl/cellservdb/CellServDB.2018-05-14";
sha256 = "1wmjn6mmyy2r8p10nlbdzs4nrqxy8a9pjyrdciy5nmppg4053rk2";
};
clientServDB = pkgs.writeText "client-cellServDB-${cfg.cellName}" (
mkCellServDB cfg.cellName cfg.cellServDB
);
afsConfig = pkgs.runCommand "afsconfig" { preferLocalBuild = true; } ''
mkdir -p $out
echo ${cfg.cellName} > $out/ThisCell
cat ${cellServDB} ${clientServDB} > $out/CellServDB
echo "${cfg.mountPoint}:${cfg.cache.directory}:${toString cfg.cache.blocks}" > $out/cacheinfo
'';
in
{
###### interface
options = {
services.openafsClient = {
enable = mkOption {
default = false;
type = types.bool;
description = "Whether to enable the OpenAFS client.";
};
afsdb = mkOption {
default = true;
type = types.bool;
description = "Resolve cells via AFSDB DNS records.";
};
cellName = mkOption {
default = "";
type = types.str;
description = "Cell name.";
example = "grand.central.org";
};
cellServDB = mkOption {
default = [ ];
type =
with types;
listOf (submodule {
options = cellServDBConfig;
});
description = ''
This cell's database server records, added to the global
CellServDB. See {manpage}`CellServDB(5)` man page for syntax. Ignored when
`afsdb` is set to `true`.
'';
example = [
{
ip = "1.2.3.4";
dnsname = "first.afsdb.server.dns.fqdn.org";
}
{
ip = "2.3.4.5";
dnsname = "second.afsdb.server.dns.fqdn.org";
}
];
};
cache = {
blocks = mkOption {
default = 100000;
type = types.int;
description = "Cache size in 1KB blocks.";
};
chunksize = mkOption {
default = 0;
type = types.ints.between 0 30;
description = ''
Size of each cache chunk given in powers of
2. `0` resets the chunk size to its default
values (13 (8 KB) for memcache, 18-20 (256 KB to 1 MB) for
diskcache). Maximum value is 30. Important performance
parameter. Set to higher values when dealing with large files.
'';
};
directory = mkOption {
default = "/var/cache/openafs";
type = types.str;
description = "Cache directory.";
};
diskless = mkOption {
default = false;
type = types.bool;
description = ''
Use in-memory cache for diskless machines. Has no real
performance benefit anymore.
'';
};
};
crypt = mkOption {
default = true;
type = types.bool;
description = "Whether to enable (weak) protocol encryption.";
};
daemons = mkOption {
default = 2;
type = types.int;
description = ''
Number of daemons to serve user requests. Numbers higher than 6
usually do no increase performance. Default is sufficient for up
to five concurrent users.
'';
};
fakestat = mkOption {
default = false;
type = types.bool;
description = ''
Return fake data on stat() calls. If `true`,
always do so. If `false`, only do so for
cross-cell mounts (as these are potentially expensive).
'';
};
inumcalc = mkOption {
default = "compat";
type = types.strMatching "compat|md5";
description = ''
Inode calculation method. `compat` is
computationally less expensive, but `md5` greatly
reduces the likelihood of inode collisions in larger scenarios
involving multiple cells mounted into one AFS space.
'';
};
mountPoint = mkOption {
default = "/afs";
type = types.str;
description = ''
Mountpoint of the AFS file tree, conventionally
`/afs`. When set to a different value, only
cross-cells that use the same value can be accessed.
'';
};
packages = {
module = mkOption {
default = config.boot.kernelPackages.openafs;
defaultText = literalExpression "config.boot.kernelPackages.openafs";
type = types.package;
description = "OpenAFS kernel module package. MUST match the userland package!";
};
programs = mkOption {
default = getBin pkgs.openafs;
defaultText = literalExpression "getBin pkgs.openafs";
type = types.package;
description = "OpenAFS programs package. MUST match the kernel module package!";
};
};
sparse = mkOption {
default = true;
type = types.bool;
description = "Minimal cell list in /afs.";
};
startDisconnected = mkOption {
default = false;
type = types.bool;
description = ''
Start up in disconnected mode. You need to execute
`fs disco online` (as root) to switch to
connected mode. Useful for roaming devices.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
assertions = [
{
assertion = cfg.afsdb || cfg.cellServDB != [ ];
message = "You should specify all cell-local database servers in config.services.openafsClient.cellServDB or set config.services.openafsClient.afsdb.";
}
{
assertion = cfg.cellName != "";
message = "You must specify the local cell name in config.services.openafsClient.cellName.";
}
];
environment.systemPackages = [ openafsBin ];
environment.etc = {
clientCellServDB = {
source = pkgs.runCommand "CellServDB" { preferLocalBuild = true; } ''
cat ${cellServDB} ${clientServDB} > $out
'';
target = "openafs/CellServDB";
mode = "0644";
};
clientCell = {
text = ''
${cfg.cellName}
'';
target = "openafs/ThisCell";
mode = "0644";
};
};
systemd.services.afsd = {
description = "AFS client";
wantedBy = [ "multi-user.target" ];
wants = lib.optional (!cfg.startDisconnected) "network-online.target";
after = singleton (if cfg.startDisconnected then "network.target" else "network-online.target");
serviceConfig = {
RemainAfterExit = true;
};
restartIfChanged = false;
preStart = ''
mkdir -p -m 0755 ${cfg.mountPoint}
mkdir -m 0700 -p ${cfg.cache.directory}
${pkgs.kmod}/bin/insmod ${openafsMod}/lib/modules/*/extra/openafs/libafs.ko.xz
${openafsBin}/sbin/afsd \
-mountdir ${cfg.mountPoint} \
-confdir ${afsConfig} \
${optionalString (!cfg.cache.diskless) "-cachedir ${cfg.cache.directory}"} \
-blocks ${toString cfg.cache.blocks} \
-chunksize ${toString cfg.cache.chunksize} \
${optionalString cfg.cache.diskless "-memcache"} \
-inumcalc ${cfg.inumcalc} \
${if cfg.fakestat then "-fakestat-all" else "-fakestat"} \
${if cfg.sparse then "-dynroot-sparse" else "-dynroot"} \
${optionalString cfg.afsdb "-afsdb"}
${openafsBin}/bin/fs setcrypt ${if cfg.crypt then "on" else "off"}
${optionalString cfg.startDisconnected "${openafsBin}/bin/fs discon offline"}
'';
# Doing this in preStop, because after these commands AFS is basically
# stopped, so systemd has nothing to do, just noticing it. If done in
# postStop, then we get a hang + kernel oops, because AFS can't be
# stopped simply by sending signals to processes.
preStop = ''
${pkgs.util-linux}/bin/umount ${cfg.mountPoint}
${openafsBin}/sbin/afsd -shutdown
${pkgs.kmod}/sbin/rmmod libafs
'';
};
};
}

View File

@@ -0,0 +1,43 @@
{ config, lib, ... }:
let
inherit (lib)
concatStringsSep
mkOption
types
optionalString
;
in
{
mkCellServDB =
cellName: db:
''
>${cellName}
''
+ (concatStringsSep "\n" (
map (dbm: optionalString (dbm.ip != "" && dbm.dnsname != "") "${dbm.ip} #${dbm.dnsname}") db
))
+ "\n";
# CellServDB configuration type
cellServDBConfig = {
ip = mkOption {
type = types.str;
default = "";
example = "1.2.3.4";
description = "IP Address of a database server";
};
dnsname = mkOption {
type = types.str;
default = "";
example = "afs.example.org";
description = "DNS full-qualified domain name of a database server";
};
};
openafsMod = config.services.openafsClient.packages.module;
openafsBin = config.services.openafsClient.packages.programs;
openafsSrv = config.services.openafsServer.package;
}

View File

@@ -0,0 +1,348 @@
{
config,
lib,
pkgs,
...
}:
# openafsBin, openafsSrv, mkCellServDB
with import ./lib.nix { inherit config lib pkgs; };
let
inherit (lib)
concatStringsSep
literalExpression
mkIf
mkOption
mkEnableOption
mkPackageOption
optionalString
types
;
bosConfig = pkgs.writeText "BosConfig" (
''
restrictmode 1
restarttime 16 0 0 0 0
checkbintime 3 0 5 0 0
''
+ (optionalString cfg.roles.database.enable ''
bnode simple vlserver 1
parm ${openafsSrv}/libexec/openafs/vlserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.vlserverArgs}
end
bnode simple ptserver 1
parm ${openafsSrv}/libexec/openafs/ptserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.ptserverArgs}
end
'')
+ (optionalString cfg.roles.fileserver.enable ''
bnode dafs dafs 1
parm ${openafsSrv}/libexec/openafs/dafileserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.fileserverArgs}
parm ${openafsSrv}/libexec/openafs/davolserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.volserverArgs}
parm ${openafsSrv}/libexec/openafs/salvageserver ${cfg.roles.fileserver.salvageserverArgs}
parm ${openafsSrv}/libexec/openafs/dasalvager ${cfg.roles.fileserver.salvagerArgs}
end
'')
+ (optionalString
(cfg.roles.database.enable && cfg.roles.backup.enable && (!cfg.roles.backup.enableFabs))
''
bnode simple buserver 1
parm ${openafsSrv}/libexec/openafs/buserver ${cfg.roles.backup.buserverArgs} ${optionalString useBuCellServDB "-cellservdb /etc/openafs/backup/"}
end
''
)
+ (optionalString
(cfg.roles.database.enable && cfg.roles.backup.enable && cfg.roles.backup.enableFabs)
''
bnode simple buserver 1
parm ${lib.getBin pkgs.fabs}/bin/fabsys server --config ${fabsConfFile} ${cfg.roles.backup.fabsArgs}
end
''
)
);
netInfo =
if (cfg.advertisedAddresses != [ ]) then
pkgs.writeText "NetInfo" ((concatStringsSep "\nf " cfg.advertisedAddresses) + "\n")
else
null;
buCellServDB = pkgs.writeText "backup-cellServDB-${cfg.cellName}" (
mkCellServDB cfg.cellName cfg.roles.backup.cellServDB
);
useBuCellServDB = (cfg.roles.backup.cellServDB != [ ]) && (!cfg.roles.backup.enableFabs);
cfg = config.services.openafsServer;
udpSizeStr = toString cfg.udpPacketSize;
fabsConfFile = pkgs.writeText "fabs.yaml" (
builtins.toJSON (
{
afs = {
aklog = cfg.package + "/bin/aklog";
cell = cfg.cellName;
dumpscan = cfg.package + "/bin/afsdump_scan";
fs = cfg.package + "/bin/fs";
pts = cfg.package + "/bin/pts";
vos = cfg.package + "/bin/vos";
};
k5start.command = (lib.getBin pkgs.kstart) + "/bin/k5start";
}
// cfg.roles.backup.fabsExtraConfig
)
);
in
{
options = {
services.openafsServer = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
Whether to enable the OpenAFS server. An OpenAFS server needs a
complex setup. So, be aware that enabling this service and setting
some options does not give you a turn-key-ready solution. You need
at least a running Kerberos 5 setup, as OpenAFS relies on it for
authentication. See the Guide "QuickStartUnix" coming with
`pkgs.openafs.doc` for complete setup
instructions.
'';
};
advertisedAddresses = mkOption {
type = types.listOf types.str;
default = [ ];
description = "List of IP addresses this server is advertised under. See {manpage}`NetInfo(5)`";
};
cellName = mkOption {
default = "";
type = types.str;
description = "Cell name, this server will serve.";
example = "grand.central.org";
};
cellServDB = mkOption {
default = [ ];
type = with types; listOf (submodule [ { options = cellServDBConfig; } ]);
description = "Definition of all cell-local database server machines.";
};
package = mkPackageOption pkgs "openafs" { };
roles = {
fileserver = {
enable = mkOption {
default = true;
type = types.bool;
description = "Fileserver role, serves files and volumes from its local storage.";
};
fileserverArgs = mkOption {
default = "-vattachpar 128 -vhashsize 11 -L -rxpck 400 -cb 1000000";
type = types.str;
description = "Arguments to the dafileserver process. See its man page.";
};
volserverArgs = mkOption {
default = "";
type = types.str;
description = "Arguments to the davolserver process. See its man page.";
example = "-sync never";
};
salvageserverArgs = mkOption {
default = "";
type = types.str;
description = "Arguments to the salvageserver process. See its man page.";
example = "-showlog";
};
salvagerArgs = mkOption {
default = "";
type = types.str;
description = "Arguments to the dasalvager process. See its man page.";
example = "-showlog -showmounts";
};
};
database = {
enable = mkOption {
default = true;
type = types.bool;
description = ''
Database server role, maintains the Volume Location Database,
Protection Database (and Backup Database, see
`backup` role). There can be multiple
servers in the database role for replication, which then need
reliable network connection to each other.
Servers in this role appear in AFSDB DNS records or the
CellServDB.
'';
};
vlserverArgs = mkOption {
default = "";
type = types.str;
description = "Arguments to the vlserver process. See its man page.";
example = "-rxbind";
};
ptserverArgs = mkOption {
default = "";
type = types.str;
description = "Arguments to the ptserver process. See its man page.";
example = "-restricted -default_access S---- S-M---";
};
};
backup = {
enable = mkEnableOption ''
the backup server role. When using OpenAFS built-in buserver, use in conjunction with the
`database` role to maintain the Backup
Database. Normally only used in conjunction with tape storage
or IBM's Tivoli Storage Manager.
For a modern backup server, enable this role and see
{option}`enableFabs`
'';
enableFabs = mkEnableOption ''
FABS, the flexible AFS backup system. It stores volumes as dump files, relying on other
pre-existing backup solutions for handling them
'';
buserverArgs = mkOption {
default = "";
type = types.str;
description = "Arguments to the buserver process. See its man page.";
example = "-p 8";
};
cellServDB = mkOption {
default = [ ];
type = with types; listOf (submodule [ { options = cellServDBConfig; } ]);
description = ''
Definition of all cell-local backup database server machines.
Use this when your cell uses less backup database servers than
other database server machines.
'';
};
fabsArgs = mkOption {
default = "";
type = types.str;
description = ''
Arguments to the fabsys process. See
{manpage}`fabsys_server(1)` and
{manpage}`fabsys_config(1)`.
'';
};
fabsExtraConfig = mkOption {
default = { };
type = types.attrs;
description = ''
Additional configuration parameters for the FABS backup server.
'';
example = literalExpression ''
{
afs.localauth = true;
afs.keytab = config.sops.secrets.fabsKeytab.path;
}
'';
};
};
};
dottedPrincipals = mkOption {
default = false;
type = types.bool;
description = ''
If enabled, allow principal names containing (.) dots. Enabling
this has security implications!
'';
};
udpPacketSize = mkOption {
default = 1310720;
type = types.int;
description = ''
UDP packet size to use in Bytes. Higher values can speed up
communications. The default of 1 MB is a sufficient in most
cases. Make sure to increase the kernel's UDP buffer size
accordingly via `net.core(w|r|opt)mem_max`
sysctl.
'';
};
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = cfg.cellServDB != [ ];
message = "You must specify all cell-local database servers in config.services.openafsServer.cellServDB.";
}
{
assertion = cfg.cellName != "";
message = "You must specify the local cell name in config.services.openafsServer.cellName.";
}
];
environment.systemPackages = [ openafsBin ];
environment.etc = {
bosConfig = {
source = bosConfig;
target = "openafs/BosConfig";
mode = "0644";
};
cellServDB = {
text = mkCellServDB cfg.cellName cfg.cellServDB;
target = "openafs/server/CellServDB";
mode = "0644";
};
thisCell = {
text = cfg.cellName;
target = "openafs/server/ThisCell";
mode = "0644";
};
buCellServDB = {
enable = useBuCellServDB;
text = mkCellServDB cfg.cellName cfg.roles.backup.cellServDB;
target = "openafs/backup/CellServDB";
};
};
systemd.services = {
openafs-server = {
description = "OpenAFS server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
restartIfChanged = false;
unitConfig.ConditionPathExists = [
"|/etc/openafs/server/KeyFileExt"
];
preStart = ''
mkdir -m 0755 -p /var/openafs
${optionalString (netInfo != null) "cp ${netInfo} /var/openafs/netInfo"}
${optionalString useBuCellServDB "cp ${buCellServDB}"}
'';
serviceConfig = {
ExecStart = "${openafsBin}/bin/bosserver -nofork";
ExecStop = "${openafsBin}/bin/bos shutdown localhost -wait -localauth";
};
};
};
};
}