mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-10 19:55:41 +03:00

Format all Nix files using the officially approved formatter,
making the CI check introduced in the previous commit succeed:
nix-build ci -A fmt.check
This is the next step of the of the [implementation](https://github.com/NixOS/nixfmt/issues/153)
of the accepted [RFC 166](https://github.com/NixOS/rfcs/pull/166).
This commit will lead to merge conflicts for a number of PRs,
up to an estimated ~1100 (~33%) among the PRs with activity in the past 2
months, but that should be lower than what it would be without the previous
[partial treewide format](https://github.com/NixOS/nixpkgs/pull/322537).
Merge conflicts caused by this commit can now automatically be resolved while rebasing using the
[auto-rebase script](8616af08d9/maintainers/scripts/auto-rebase
).
If you run into any problems regarding any of this, please reach out to the
[formatting team](https://nixos.org/community/teams/formatting/) by
pinging @NixOS/nix-formatting.
365 lines
11 KiB
Nix
365 lines
11 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.services.syncplay;
|
|
|
|
cmdArgs =
|
|
[
|
|
"--port"
|
|
cfg.port
|
|
]
|
|
++ optionals (cfg.isolateRooms) [ "--isolate-rooms" ]
|
|
++ optionals (!cfg.ready) [ "--disable-ready" ]
|
|
++ optionals (!cfg.chat) [ "--disable-chat" ]
|
|
++ optionals (cfg.salt != null) [
|
|
"--salt"
|
|
cfg.salt
|
|
]
|
|
++ optionals (cfg.motdFile != null) [
|
|
"--motd-file"
|
|
cfg.motdFile
|
|
]
|
|
++ optionals (cfg.roomsDBFile != null) [
|
|
"--rooms-db-file"
|
|
cfg.roomsDBFile
|
|
]
|
|
++ optionals (cfg.permanentRoomsFile != null) [
|
|
"--permanent-rooms-file"
|
|
cfg.permanentRoomsFile
|
|
]
|
|
++ [
|
|
"--max-chat-message-length"
|
|
cfg.maxChatMessageLength
|
|
]
|
|
++ [
|
|
"--max-username-length"
|
|
cfg.maxUsernameLength
|
|
]
|
|
++ optionals (cfg.statsDBFile != null) [
|
|
"--stats-db-file"
|
|
cfg.statsDBFile
|
|
]
|
|
++ optionals (cfg.certDir != null) [
|
|
"--tls"
|
|
cfg.certDir
|
|
]
|
|
++ optionals cfg.ipv4Only [ "--ipv4-only" ]
|
|
++ optionals cfg.ipv6Only [ "--ipv6-only" ]
|
|
++ optionals (cfg.interfaceIpv4 != "") [
|
|
"--interface-ipv4"
|
|
cfg.interfaceIpv4
|
|
]
|
|
++ optionals (cfg.interfaceIpv6 != "") [
|
|
"--interface-ipv6"
|
|
cfg.interfaceIpv6
|
|
]
|
|
++ cfg.extraArgs;
|
|
|
|
useACMEHostDir = optionalString (
|
|
cfg.useACMEHost != null
|
|
) config.security.acme.certs.${cfg.useACMEHost}.directory;
|
|
in
|
|
{
|
|
imports = [
|
|
(mkRemovedOptionModule [ "services" "syncplay" "user" ]
|
|
"The syncplay service now uses DynamicUser, override the systemd unit settings if you need the old functionality."
|
|
)
|
|
(mkRemovedOptionModule [ "services" "syncplay" "group" ]
|
|
"The syncplay service now uses DynamicUser, override the systemd unit settings if you need the old functionality."
|
|
)
|
|
];
|
|
|
|
options = {
|
|
services.syncplay = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
If enabled, start the Syncplay server.
|
|
'';
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 8999;
|
|
description = ''
|
|
TCP port to bind to.
|
|
'';
|
|
};
|
|
|
|
passwordFile = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = ''
|
|
Path to the file that contains the server password. If
|
|
`null`, the server doesn't require a password.
|
|
'';
|
|
};
|
|
|
|
isolateRooms = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Enable room isolation.
|
|
'';
|
|
};
|
|
|
|
ready = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Check readiness of users.
|
|
'';
|
|
};
|
|
|
|
chat = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Chat with users in the same room.
|
|
'';
|
|
};
|
|
|
|
salt = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = ''
|
|
Salt to allow room operator passwords generated by this server
|
|
instance to still work when the server is restarted. The salt will be
|
|
readable in the nix store and the processlist. If this is not
|
|
intended use `saltFile` instead. Mutually exclusive with
|
|
{option}`services.syncplay.saltFile`.
|
|
'';
|
|
};
|
|
|
|
saltFile = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = ''
|
|
Path to the file that contains the server salt. This allows room
|
|
operator passwords generated by this server instance to still work
|
|
when the server is restarted. `null`, the server doesn't load the
|
|
salt from a file. Mutually exclusive with
|
|
{option}`services.syncplay.salt`.
|
|
'';
|
|
};
|
|
|
|
motd = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = ''
|
|
Text to display when users join. The motd will be readable in the nix store
|
|
and the processlist. If this is not intended use `motdFile` instead.
|
|
Will be overriden by {option}`services.syncplay.motdFile`.
|
|
'';
|
|
};
|
|
|
|
motdFile = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = if cfg.motd != null then (builtins.toFile "motd" cfg.motd) else null;
|
|
defaultText = literalExpression ''if services.syncplay.motd != null then (builtins.toFile "motd" services.syncplay.motd) else null'';
|
|
description = ''
|
|
Path to text to display when users join.
|
|
Will override {option}`services.syncplay.motd`.
|
|
'';
|
|
};
|
|
|
|
roomsDBFile = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "rooms.db";
|
|
description = ''
|
|
Path to SQLite database file to store room states.
|
|
Relative to the working directory provided by systemd.
|
|
'';
|
|
};
|
|
|
|
permanentRooms = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [ ];
|
|
description = ''
|
|
List of rooms that will be listed even if the room is empty.
|
|
Will be overriden by {option}`services.syncplay.permanentRoomsFile`.
|
|
'';
|
|
};
|
|
|
|
permanentRoomsFile = mkOption {
|
|
type = types.nullOr types.str;
|
|
default =
|
|
if cfg.permanentRooms != [ ] then
|
|
(builtins.toFile "perm" (builtins.concatStringsSep "\n" cfg.permanentRooms))
|
|
else
|
|
null;
|
|
defaultText = literalExpression ''if services.syncplay.permanentRooms != [ ] then (builtins.toFile "perm" (builtins.concatStringsSep "\n" services.syncplay.permanentRooms)) else null'';
|
|
description = ''
|
|
File with list of rooms that will be listed even if the room is empty,
|
|
newline delimited.
|
|
Will override {option}`services.syncplay.permanentRooms`.
|
|
'';
|
|
};
|
|
|
|
maxChatMessageLength = mkOption {
|
|
type = types.ints.unsigned;
|
|
default = 150;
|
|
description = ''
|
|
Maximum number of characters in a chat message.
|
|
'';
|
|
};
|
|
|
|
maxUsernameLength = mkOption {
|
|
type = types.ints.unsigned;
|
|
default = 16;
|
|
description = ''
|
|
Maximum number of characters in a username.
|
|
'';
|
|
};
|
|
|
|
statsDBFile = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "stats.db";
|
|
description = ''
|
|
Path to SQLite database file to store stats.
|
|
Relative to the working directory provided by systemd.
|
|
'';
|
|
};
|
|
|
|
certDir = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = ''
|
|
TLS certificates directory to use for encryption. See
|
|
<https://github.com/Syncplay/syncplay/wiki/TLS-support>.
|
|
'';
|
|
};
|
|
|
|
useACMEHost = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "syncplay.example.com";
|
|
description = ''
|
|
If set, use NixOS-generated ACME certificate with the specified name for TLS.
|
|
|
|
Note that it requires {option}`security.acme` to be setup, e.g., credentials provided if using DNS-01 validation.
|
|
'';
|
|
};
|
|
|
|
ipv4Only = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Listen only on IPv4 when strting the server.
|
|
'';
|
|
};
|
|
|
|
ipv6Only = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Listen only on IPv6 when strting the server.
|
|
'';
|
|
};
|
|
|
|
interfaceIpv4 = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
The IP address to bind to for IPv4. Leaving it empty defaults to using all.
|
|
'';
|
|
};
|
|
|
|
interfaceIpv6 = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
The IP address to bind to for IPv6. Leaving it empty defaults to using all.
|
|
'';
|
|
};
|
|
|
|
extraArgs = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [ ];
|
|
description = ''
|
|
Additional arguments to be passed to the service.
|
|
'';
|
|
};
|
|
|
|
package = mkOption {
|
|
type = types.package;
|
|
default = pkgs.syncplay-nogui;
|
|
defaultText = literalExpression "pkgs.syncplay-nogui";
|
|
description = ''
|
|
Package to use for syncplay.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
assertions = [
|
|
{
|
|
assertion = cfg.salt == null || cfg.saltFile == null;
|
|
message = "services.syncplay.salt and services.syncplay.saltFile are mutually exclusive.";
|
|
}
|
|
{
|
|
assertion = cfg.certDir == null || cfg.useACMEHost == null;
|
|
message = "services.syncplay.certDir and services.syncplay.useACMEHost are mutually exclusive.";
|
|
}
|
|
{
|
|
assertion = !cfg.ipv4Only || !cfg.ipv6Only;
|
|
message = "services.syncplay.ipv4Only and services.syncplay.ipv6Only are mutually exclusive.";
|
|
}
|
|
];
|
|
|
|
warnings =
|
|
optional (cfg.interfaceIpv4 != "" && cfg.ipv6Only)
|
|
"You have specified services.syncplay.interfaceIpv4 but IPv4 is disabled by services.syncplay.ipv6Only."
|
|
++ optional (cfg.interfaceIpv6 != "" && cfg.ipv4Only)
|
|
"You have specified services.syncplay.interfaceIpv6 but IPv6 is disabled by services.syncplay.ipv4Only.";
|
|
|
|
security.acme.certs = mkIf (cfg.useACMEHost != null) {
|
|
"${cfg.useACMEHost}".reloadServices = [ "syncplay.service" ];
|
|
};
|
|
|
|
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
|
systemd.services.syncplay = {
|
|
description = "Syncplay Service";
|
|
wantedBy = [ "multi-user.target" ];
|
|
wants = [ "network-online.target" ];
|
|
after = [ "network-online.target" ];
|
|
|
|
serviceConfig = {
|
|
DynamicUser = true;
|
|
StateDirectory = "syncplay";
|
|
WorkingDirectory = "%S/syncplay";
|
|
LoadCredential =
|
|
optional (cfg.passwordFile != null) "password:${cfg.passwordFile}"
|
|
++ optional (cfg.saltFile != null) "salt:${cfg.saltFile}"
|
|
++ optionals (cfg.useACMEHost != null) [
|
|
"cert.pem:${useACMEHostDir}/cert.pem"
|
|
"privkey.pem:${useACMEHostDir}/key.pem"
|
|
"chain.pem:${useACMEHostDir}/chain.pem"
|
|
];
|
|
};
|
|
|
|
script = ''
|
|
${optionalString (cfg.passwordFile != null) ''
|
|
export SYNCPLAY_PASSWORD=$(cat "''${CREDENTIALS_DIRECTORY}/password")
|
|
''}
|
|
${optionalString (cfg.saltFile != null) ''
|
|
export SYNCPLAY_SALT=$(cat "''${CREDENTIALS_DIRECTORY}/salt")
|
|
''}
|
|
exec ${cfg.package}/bin/syncplay-server ${escapeShellArgs cmdArgs} ${
|
|
optionalString (cfg.useACMEHost != null) "--tls $CREDENTIALS_DIRECTORY"
|
|
}
|
|
'';
|
|
};
|
|
};
|
|
}
|