Silvan Mosberger 84d4f874c2 treewide: format all inactive Nix files
After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build a08b3a4d19.tar.gz \
      --argstr baseRev 78e9caf153f5a339bf1d4c000ff6f0a503a369c8
    result/bin/apply-formatting $NIXPKGS_PATH
2024-12-10 20:23:58 +01:00

336 lines
10 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types literalExpression;
cfg = config.services.hedgedoc;
# 21.03 will not be an official release - it was instead 21.05. This
# versionAtLeast statement remains set to 21.03 for backwards compatibility.
# See https://github.com/NixOS/nixpkgs/pull/108899 and
# https://github.com/NixOS/rfcs/blob/master/rfcs/0080-nixos-release-schedule.md.
name = if lib.versionAtLeast config.system.stateVersion "21.03" then "hedgedoc" else "codimd";
settingsFormat = pkgs.formats.json { };
in
{
meta.maintainers = with lib.maintainers; [
SuperSandro2000
h7x4
];
imports = [
(lib.mkRenamedOptionModule [ "services" "codimd" ] [ "services" "hedgedoc" ])
(lib.mkRenamedOptionModule
[ "services" "hedgedoc" "configuration" ]
[ "services" "hedgedoc" "settings" ]
)
(lib.mkRenamedOptionModule
[ "services" "hedgedoc" "groups" ]
[ "users" "users" "hedgedoc" "extraGroups" ]
)
(lib.mkRemovedOptionModule [ "services" "hedgedoc" "workDir" ] ''
This option has been removed in favor of systemd managing the state directory.
If you have set this option without specifying `services.hedgedoc.settings.uploadsPath`,
please move these files to `/var/lib/hedgedoc/uploads`, or set the option to point
at the correct location.
'')
];
options.services.hedgedoc = {
package = lib.mkPackageOption pkgs "hedgedoc" { };
enable = lib.mkEnableOption "the HedgeDoc Markdown Editor";
settings = mkOption {
type = types.submodule {
freeformType = settingsFormat.type;
options = {
domain = mkOption {
type = with types; nullOr str;
default = null;
example = "hedgedoc.org";
description = ''
Domain to use for website.
This is useful if you are trying to run hedgedoc behind
a reverse proxy.
'';
};
urlPath = mkOption {
type = with types; nullOr str;
default = null;
example = "hedgedoc";
description = ''
URL path for the website.
This is useful if you are hosting hedgedoc on a path like
`www.example.com/hedgedoc`
'';
};
host = mkOption {
type = with types; nullOr str;
default = "localhost";
description = ''
Address to listen on.
'';
};
port = mkOption {
type = types.port;
default = 3000;
example = 80;
description = ''
Port to listen on.
'';
};
path = mkOption {
type = with types; nullOr path;
default = null;
example = "/run/hedgedoc/hedgedoc.sock";
description = ''
Path to UNIX domain socket to listen on
::: {.note}
If specified, {option}`host` and {option}`port` will be ignored.
:::
'';
};
protocolUseSSL = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Use `https://` for all links.
This is useful if you are trying to run hedgedoc behind
a reverse proxy.
::: {.note}
Only applied if {option}`domain` is set.
:::
'';
};
allowOrigin = mkOption {
type = with types; listOf str;
default = with cfg.settings; [ host ] ++ lib.optionals (domain != null) [ domain ];
defaultText = literalExpression ''
with config.services.hedgedoc.settings; [ host ] ++ lib.optionals (domain != null) [ domain ]
'';
example = [
"localhost"
"hedgedoc.org"
];
description = ''
List of domains to whitelist.
'';
};
db = mkOption {
type = types.attrs;
default = {
dialect = "sqlite";
storage = "/var/lib/${name}/db.sqlite";
};
defaultText = literalExpression ''
{
dialect = "sqlite";
storage = "/var/lib/hedgedoc/db.sqlite";
}
'';
example = literalExpression ''
db = {
username = "hedgedoc";
database = "hedgedoc";
host = "localhost:5432";
# or via socket
# host = "/run/postgresql";
dialect = "postgresql";
};
'';
description = ''
Specify the configuration for sequelize.
HedgeDoc supports `mysql`, `postgres`, `sqlite` and `mssql`.
See <https://sequelize.readthedocs.io/en/v3/>
for more information.
::: {.note}
The relevant parts will be overriden if you set {option}`dbURL`.
:::
'';
};
useSSL = mkOption {
type = types.bool;
default = false;
description = ''
Enable to use SSL server.
::: {.note}
This will also enable {option}`protocolUseSSL`.
It will also require you to set the following:
- {option}`sslKeyPath`
- {option}`sslCertPath`
- {option}`sslCAPath`
- {option}`dhParamPath`
:::
'';
};
uploadsPath = mkOption {
type = types.path;
default = "/var/lib/${name}/uploads";
defaultText = "/var/lib/hedgedoc/uploads";
description = ''
Directory for storing uploaded images.
'';
};
# Declared because we change the default to false.
allowGravatar = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to enable [Libravatar](https://wiki.libravatar.org/) as
profile picture source on your instance.
Despite the naming of the setting, Hedgedoc replaced Gravatar
with Libravatar in [CodiMD 1.4.0](https://hedgedoc.org/releases/1.4.0/)
'';
};
};
};
description = ''
HedgeDoc configuration, see
<https://docs.hedgedoc.org/configuration/>
for documentation.
'';
};
environmentFile = mkOption {
type = with types; nullOr path;
default = null;
example = "/var/lib/hedgedoc/hedgedoc.env";
description = ''
Environment file as defined in {manpage}`systemd.exec(5)`.
Secrets may be passed to the service without adding them to the world-readable
Nix store, by specifying placeholder variables as the option value in Nix and
setting these variables accordingly in the environment file.
```
# snippet of HedgeDoc-related config
services.hedgedoc.settings.dbURL = "postgres://hedgedoc:\''${DB_PASSWORD}@db-host:5432/hedgedocdb";
services.hedgedoc.settings.minio.secretKey = "$MINIO_SECRET_KEY";
```
```
# content of the environment file
DB_PASSWORD=verysecretdbpassword
MINIO_SECRET_KEY=verysecretminiokey
```
Note that this file needs to be available on the host on which
`HedgeDoc` is running.
'';
};
};
config = lib.mkIf cfg.enable {
users.groups.${name} = { };
users.users.${name} = {
description = "HedgeDoc service user";
group = name;
isSystemUser = true;
};
services.hedgedoc.settings = {
defaultNotePath = lib.mkDefault "${cfg.package}/share/hedgedoc/public/default.md";
docsPath = lib.mkDefault "${cfg.package}/share/hedgedoc/public/docs";
viewPath = lib.mkDefault "${cfg.package}/share/hedgedoc/public/views";
};
systemd.services.hedgedoc = {
description = "HedgeDoc Service";
documentation = [ "https://docs.hedgedoc.org/" ];
wantedBy = [ "multi-user.target" ];
after = [ "networking.target" ];
preStart =
let
configFile = settingsFormat.generate "hedgedoc-config.json" {
production = cfg.settings;
};
in
''
${pkgs.envsubst}/bin/envsubst \
-o /run/${name}/config.json \
-i ${configFile}
${pkgs.coreutils}/bin/mkdir -p ${cfg.settings.uploadsPath}
'';
serviceConfig = {
User = name;
Group = name;
Restart = "always";
ExecStart = lib.getExe cfg.package;
RuntimeDirectory = [ name ];
StateDirectory = [ name ];
WorkingDirectory = "/run/${name}";
ReadWritePaths = [
"-${cfg.settings.uploadsPath}"
] ++ lib.optionals (cfg.settings.db ? "storage") [ "-${cfg.settings.db.storage}" ];
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
Environment = [
"CMD_CONFIG_FILE=/run/${name}/config.json"
"NODE_ENV=production"
];
# Hardening
AmbientCapabilities = "";
CapabilityBoundingSet = "";
LockPersonality = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
# Required for connecting to database sockets,
# and listening to unix socket at `cfg.settings.path`
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SocketBindAllow = lib.mkIf (cfg.settings.path == null) cfg.settings.port;
SocketBindDeny = "any";
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged @obsolete"
"@pkey"
];
UMask = "0007";
};
};
};
}