mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-10-03 13:30:36 +00:00
711 lines
22 KiB
Nix
711 lines
22 KiB
Nix
{
|
|
lib,
|
|
pkgs,
|
|
config,
|
|
options,
|
|
...
|
|
}:
|
|
|
|
let
|
|
cfg = config.services.dawarich;
|
|
opt = options.services.dawarich;
|
|
|
|
dataDir = "/var/lib/dawarich";
|
|
|
|
isRedisUnixSocket = lib.hasPrefix "/" cfg.redis.host;
|
|
|
|
redisEnv =
|
|
if isRedisUnixSocket then
|
|
{
|
|
REDIS_URL = "unix://${config.services.redis.servers.dawarich.unixSocket}";
|
|
}
|
|
else
|
|
{
|
|
# Does not support passwords, but upstream does not provide an adequate env variable
|
|
# Perhaps patch or make a PR upstream in the future
|
|
REDIS_URL = "redis://${cfg.redis.host}:${toString cfg.redis.port}";
|
|
};
|
|
|
|
env = {
|
|
RAILS_ENV = "production";
|
|
NODE_ENV = "production";
|
|
BUNDLE_USER_HOME = "/tmp/bundle"; # will use private tmp inside systemd unit
|
|
|
|
SELF_HOSTED = "true";
|
|
STORE_GEODATA = "true";
|
|
APPLICATION_PROTOCOL = "http";
|
|
TIME_ZONE = config.time.timeZone; # otherwise upstream forces it to Europe/London
|
|
DOMAIN = cfg.localDomain;
|
|
APPLICATION_HOSTS = "127.0.0.1,::1,${cfg.localDomain}";
|
|
|
|
BOOTSNAP_CACHE_DIR = "/var/cache/dawarich/precompile";
|
|
LD_PRELOAD = "${lib.getLib pkgs.jemalloc}/lib/libjemalloc.so";
|
|
|
|
DATABASE_USER = cfg.database.user;
|
|
DATABASE_HOST = cfg.database.host;
|
|
DATABASE_NAME = cfg.database.name;
|
|
DATABASE_PORT = toString cfg.database.port;
|
|
|
|
SMTP_SERVER = cfg.smtp.host;
|
|
SMTP_PORT = toString cfg.smtp.port;
|
|
SMTP_FROM = cfg.smtp.fromAddress;
|
|
SMTP_USERNAME = cfg.smtp.user;
|
|
PORT = toString cfg.webPort;
|
|
}
|
|
// redisEnv
|
|
// cfg.environment;
|
|
|
|
systemCallFilter =
|
|
let
|
|
allowedSystemCalls = [
|
|
"@cpu-emulation"
|
|
"@debug"
|
|
"@keyring"
|
|
"@ipc"
|
|
"@mount"
|
|
"@obsolete"
|
|
"@privileged"
|
|
"@setuid"
|
|
];
|
|
in
|
|
[
|
|
("~" + lib.concatStringsSep " " allowedSystemCalls)
|
|
"@chown"
|
|
"pipe"
|
|
"pipe2"
|
|
];
|
|
|
|
cfgService = {
|
|
User = cfg.user;
|
|
Group = cfg.group;
|
|
WorkingDirectory = cfg.package;
|
|
CacheDirectory = "dawarich";
|
|
CacheDirectoryMode = "0750";
|
|
StateDirectory = "dawarich";
|
|
StateDirectoryMode = "0750";
|
|
LogsDirectory = "dawarich";
|
|
LogsDirectoryMode = "0750";
|
|
ProcSubset = "pid";
|
|
ProtectProc = "invisible";
|
|
UMask = "0027";
|
|
CapabilityBoundingSet = "";
|
|
NoNewPrivileges = true;
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
PrivateDevices = true;
|
|
PrivateUsers = true;
|
|
ProtectClock = true;
|
|
ProtectHostname = true;
|
|
ProtectKernelLogs = true;
|
|
ProtectKernelModules = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectControlGroups = true;
|
|
RestrictAddressFamilies = [
|
|
"AF_UNIX"
|
|
"AF_INET"
|
|
"AF_INET6"
|
|
"AF_NETLINK"
|
|
];
|
|
RestrictNamespaces = true;
|
|
LockPersonality = true;
|
|
MemoryDenyWriteExecute = false;
|
|
RestrictRealtime = true;
|
|
RestrictSUIDSGID = true;
|
|
RemoveIPC = true;
|
|
PrivateMounts = true;
|
|
SystemCallArchitectures = "native";
|
|
SystemCallFilter = systemCallFilter;
|
|
|
|
# ensure permissions to connect to the redis socket
|
|
SupplementaryGroups = lib.mkIf (cfg.redis.createLocally && isRedisUnixSocket) [
|
|
config.services.redis.servers.dawarich.group
|
|
];
|
|
};
|
|
|
|
# Units that all Dawarich units After= and Requires= on
|
|
commonUnits =
|
|
lib.optional cfg.redis.createLocally "redis-dawarich.service"
|
|
++ lib.optional cfg.database.createLocally "postgresql.target"
|
|
++ lib.optional cfg.automaticMigrations "dawarich-init-db.service";
|
|
|
|
defaultSecretKeyBaseFile = "${dataDir}/secrets/secret-key-base";
|
|
needsGenCredentialsUnit = cfg.secretKeyBaseFile == null;
|
|
credentials = {
|
|
SECRET_KEY_BASE = lib.defaultTo defaultSecretKeyBaseFile cfg.secretKeyBaseFile;
|
|
}
|
|
// lib.optionalAttrs (cfg.database.passwordFile != null) {
|
|
DATABASE_PASSWORD = cfg.database.passwordFile;
|
|
}
|
|
// lib.optionalAttrs (cfg.smtp.passwordFile != null) {
|
|
SMTP_PASSWORD = cfg.smtp.passwordFile;
|
|
};
|
|
loadCredentialsIntoEnv = lib.concatMapAttrsStringSep "\n" (
|
|
name: _: ''export ${name}="$(systemd-creds cat ${name})"''
|
|
) credentials;
|
|
loadCredentials = lib.mapAttrsToList (name: path: "${name}:${path}") credentials;
|
|
|
|
dawarichRails = pkgs.writeShellApplication {
|
|
name = "dawarich-rails";
|
|
|
|
text =
|
|
let
|
|
sourceExtraEnv = lib.concatMapStrings (p: "source ${p}\n") cfg.extraEnvFiles;
|
|
command = pkgs.writeShellScript "dawarich-rails-unwrapped" ''
|
|
${sourceExtraEnv}
|
|
${loadCredentialsIntoEnv}
|
|
export RAILS_ROOT="${cfg.package}"
|
|
exec ${lib.getExe' cfg.package "rails"} "$@"
|
|
'';
|
|
env' = lib.filterAttrs (_: value: value != null) env;
|
|
supplementaryGroups = lib.optionalString (cfg.redis.createLocally && isRedisUnixSocket) (
|
|
lib.escapeShellArg "--property=SupplementaryGroups=${config.services.redis.servers.dawarich.group}"
|
|
);
|
|
in
|
|
''
|
|
exec ${lib.getExe' config.systemd.package "systemd-run"} \
|
|
${
|
|
lib.escapeShellArgs (map (credential: "--property=LoadCredential=${credential}") loadCredentials)
|
|
} \
|
|
${
|
|
lib.escapeShellArgs (lib.mapAttrsToList (name: value: "--setenv=${name}=${toString value}") env')
|
|
} \
|
|
--uid=${lib.escapeShellArg cfg.user} \
|
|
--gid=${lib.escapeShellArg cfg.group} \
|
|
${supplementaryGroups} \
|
|
--working-directory=${lib.escapeShellArg cfg.package} \
|
|
--property=PrivateTmp=yes \
|
|
--pty \
|
|
--wait \
|
|
--collect \
|
|
--service-type=exec \
|
|
--quiet \
|
|
-- \
|
|
${command} "$@"
|
|
'';
|
|
};
|
|
dawarichConsole = pkgs.writeShellScriptBin "dawarich-console" ''
|
|
exec ${lib.getExe dawarichRails} console "$@"
|
|
'';
|
|
|
|
sidekiqUnits = lib.attrsets.mapAttrs' (
|
|
name: processCfg:
|
|
lib.nameValuePair "dawarich-sidekiq-${name}" (
|
|
let
|
|
jobClassArgs = lib.concatMapStringsSep " " (c: "-q ${c}") processCfg.jobClasses;
|
|
jobClassLabel = lib.optionalString (
|
|
processCfg.jobClasses != [ ]
|
|
) " (${lib.concatStringsSep ", " processCfg.jobClasses})";
|
|
threads = toString (if processCfg.threads == null then cfg.sidekiqThreads else processCfg.threads);
|
|
in
|
|
{
|
|
after = [
|
|
"network.target"
|
|
]
|
|
++ lib.optional needsGenCredentialsUnit "dawarich-init-credentials.service"
|
|
++ commonUnits;
|
|
requires = lib.optional needsGenCredentialsUnit "dawarich-init-credentials.service" ++ commonUnits;
|
|
description = "Dawarich sidekiq${jobClassLabel}";
|
|
wantedBy = [ "dawarich.target" ];
|
|
environment = env // {
|
|
RAILS_MAX_THREADS = threads;
|
|
};
|
|
script = ''
|
|
${loadCredentialsIntoEnv}
|
|
|
|
${lib.getExe' cfg.package "sidekiq"} ${jobClassArgs} -c ${threads} -r ${cfg.package}
|
|
'';
|
|
serviceConfig = {
|
|
Restart = "always";
|
|
RestartSec = 20;
|
|
LoadCredential = loadCredentials;
|
|
EnvironmentFile = cfg.extraEnvFiles;
|
|
LimitNOFILE = "1024000";
|
|
}
|
|
// cfgService;
|
|
}
|
|
)
|
|
) cfg.sidekiqProcesses;
|
|
|
|
in
|
|
{
|
|
|
|
options = {
|
|
services.dawarich = {
|
|
enable = lib.mkEnableOption "Dawarich, a self-hostable alternative to Google Location History";
|
|
|
|
configureNginx = lib.mkOption {
|
|
description = ''
|
|
Configure nginx as a reverse proxy for dawarich.
|
|
Alternatively you can configure a reverse-proxy of your choice to serve these paths:
|
|
|
|
`/ -> ''${pkgs.dawarich}/public`
|
|
|
|
`/ -> 127.0.0.1:{{ webPort }} `(If there was no file in the directory above.)
|
|
|
|
Make sure that websockets are forwarded properly. You might want to set up caching
|
|
of some requests. Take a look at dawarich's provided reverse proxy configurations at
|
|
`https://dawarich.app/docs/tutorials/reverse-proxy`.
|
|
'';
|
|
type = lib.types.bool;
|
|
default = true;
|
|
};
|
|
|
|
user = lib.mkOption {
|
|
description = ''
|
|
User under which dawarich runs. If it is set to "dawarich",
|
|
that user will be created, otherwise it should be set to the
|
|
name of a user created elsewhere.
|
|
'';
|
|
type = lib.types.str;
|
|
default = "dawarich";
|
|
};
|
|
|
|
group = lib.mkOption {
|
|
description = ''
|
|
Group under which dawarich runs.
|
|
'';
|
|
type = lib.types.str;
|
|
default = "dawarich";
|
|
};
|
|
|
|
webPort = lib.mkOption {
|
|
description = "TCP port used by the dawarich web service.";
|
|
type = lib.types.port;
|
|
default = 3000;
|
|
};
|
|
|
|
sidekiqThreads = lib.mkOption {
|
|
description = ''
|
|
Worker threads used by the dawarich-sidekiq-all service.
|
|
If `sidekiqProcesses` is configured and any processes specify null `threads`, this value is used.
|
|
'';
|
|
type = lib.types.int;
|
|
default = 3;
|
|
};
|
|
|
|
sidekiqProcesses = lib.mkOption {
|
|
description = ''
|
|
How many Sidekiq processes should be used to handle background jobs, and which job classes they handle.
|
|
Can be used to [speed up](https://dawarich.app/docs/FAQ/#how-to-speed-up-the-import-process) the import process.
|
|
'';
|
|
type =
|
|
with lib.types;
|
|
attrsOf (submodule {
|
|
options = {
|
|
jobClasses = lib.mkOption {
|
|
# https://github.com/Freika/dawarich/blob/0.37.2/config/sidekiq.yml
|
|
type = listOf (enum [
|
|
"app_version_checking"
|
|
"archival"
|
|
"cache"
|
|
"data_migrations"
|
|
"default"
|
|
"digests"
|
|
"exports"
|
|
"families"
|
|
"highest_priority"
|
|
"imports"
|
|
"low_priority"
|
|
"mailers"
|
|
"places"
|
|
"points"
|
|
"posters"
|
|
"reverse_geocoding"
|
|
"stats"
|
|
"tracks"
|
|
"trips"
|
|
"visit_suggesting"
|
|
]);
|
|
description = ''
|
|
If not empty, which job classes should be executed by this process.
|
|
*If left empty, all job classes will be executed by this process.*
|
|
'';
|
|
};
|
|
threads = lib.mkOption {
|
|
type = nullOr int;
|
|
description = ''
|
|
Number of threads this process should use for executing jobs.
|
|
If null, the configured `sidekiqThreads` are used.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = {
|
|
all = {
|
|
jobClasses = [ ];
|
|
threads = null;
|
|
};
|
|
};
|
|
example = {
|
|
all = {
|
|
jobClasses = [ ];
|
|
threads = null;
|
|
};
|
|
geocoding = {
|
|
jobClasses = [ "reverse_geocoding" ];
|
|
threads = 10;
|
|
};
|
|
};
|
|
};
|
|
|
|
localDomain = lib.mkOption {
|
|
description = "The domain serving your Dawarich instance.";
|
|
example = "dawarich.example.org";
|
|
type = lib.types.str;
|
|
};
|
|
|
|
secretKeyBaseFile = lib.mkOption {
|
|
description = ''
|
|
Path to file containing the secret key base.
|
|
A new secret key base can be generated by running:
|
|
|
|
`nix build -f '<nixpkgs>' dawarich; cd result; bin/bundle exec rails secret`
|
|
|
|
This file is loaded using systemd credentials, and therefore does not need to be
|
|
owned by the dawarich user.
|
|
|
|
If this option is null, it will be created at ${defaultSecretKeyBaseFile}
|
|
with a new secret key base.
|
|
'';
|
|
default = null;
|
|
type = lib.types.nullOr lib.types.str;
|
|
};
|
|
|
|
redis = {
|
|
createLocally = lib.mkOption {
|
|
description = ''
|
|
Whether to configure a local Redis server for Dawarich.
|
|
The connection is performed via Unix sockets by default,
|
|
but that can be changed by configuring {option}`${opt.redis.host}` and {option}`${opt.redis.port}`.
|
|
'';
|
|
type = lib.types.bool;
|
|
default = true;
|
|
};
|
|
|
|
host = lib.mkOption {
|
|
description = "The redis host Dawarich will connect to.";
|
|
type = lib.types.str;
|
|
default = config.services.redis.servers.dawarich.unixSocket;
|
|
defaultText = lib.literalExpression "config.services.redis.servers.dawarich.unixSocket";
|
|
};
|
|
|
|
port = lib.mkOption {
|
|
description = "The port of the redis server Dawarich will connect to. Set to zero to disable TCP and use Unix sockets instead.";
|
|
type = lib.types.port;
|
|
default = 0;
|
|
};
|
|
};
|
|
|
|
database = {
|
|
createLocally = lib.mkOption {
|
|
description = ''
|
|
Whether to configure a local PostgreSQL server and database for Dawarich.
|
|
The connection is performed via Unix sockets.
|
|
'';
|
|
type = lib.types.bool;
|
|
default = true;
|
|
};
|
|
|
|
host = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "/run/postgresql";
|
|
example = "127.0.0.1";
|
|
description = "Hostname or address of the postgresql server. If an absolute path is given here, it will be interpreted as a unix socket path.";
|
|
};
|
|
|
|
port = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.port;
|
|
default = 5432;
|
|
description = "Port of the postgresql server.";
|
|
};
|
|
|
|
name = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "dawarich";
|
|
description = "The name of the dawarich database.";
|
|
};
|
|
|
|
user = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "dawarich";
|
|
description = "The database user for dawarich.";
|
|
};
|
|
|
|
passwordFile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
example = "/run/keys/dawarich-db-password";
|
|
description = ''
|
|
A file containing the password corresponding to {option}`${opt.database.user}`.
|
|
'';
|
|
};
|
|
};
|
|
|
|
smtp = {
|
|
host = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "SMTP host used when sending emails to users.";
|
|
};
|
|
|
|
port = lib.mkOption {
|
|
type = lib.types.port;
|
|
default = 25;
|
|
description = "SMTP port used when sending emails to users.";
|
|
};
|
|
|
|
fromAddress = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "dawarich@example.com";
|
|
description = ''"From" address used when sending emails to users.'';
|
|
};
|
|
|
|
user = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "dawarich@example.com";
|
|
description = "SMTP login name.";
|
|
};
|
|
|
|
passwordFile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
example = "/run/keys/dawarich-smtp-password";
|
|
description = ''
|
|
Path to file containing the SMTP password.
|
|
'';
|
|
};
|
|
};
|
|
|
|
package = lib.mkPackageOption pkgs "dawarich" { };
|
|
|
|
environment = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
attrsOf (
|
|
nullOr (oneOf [
|
|
str
|
|
path
|
|
package
|
|
])
|
|
);
|
|
default = { };
|
|
description = ''
|
|
Extra environment variables to pass to all dawarich services.
|
|
'';
|
|
};
|
|
|
|
extraEnvFiles = lib.mkOption {
|
|
type = with lib.types; listOf path;
|
|
default = [ ];
|
|
description = ''
|
|
Extra environment files to pass to all Dawarich services. Useful for passing down environment secrets.
|
|
'';
|
|
example = [ "/etc/dawarich/secret.env" ];
|
|
};
|
|
|
|
automaticMigrations = lib.mkOption {
|
|
description = "Whether to perform database migrations automatically";
|
|
type = lib.types.bool;
|
|
default = true;
|
|
};
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable (
|
|
lib.mkMerge [
|
|
{
|
|
assertions = [
|
|
{
|
|
assertion = !isRedisUnixSocket -> cfg.redis.port != 0;
|
|
message = ''
|
|
`services.dawarich.redis.port` needs to be configured if `services.dawarich.redis.host` is not a unix socket.
|
|
'';
|
|
}
|
|
];
|
|
|
|
environment.systemPackages = [
|
|
dawarichConsole
|
|
dawarichRails
|
|
];
|
|
|
|
systemd.targets.dawarich = {
|
|
description = "Target for all Dawarich services";
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ "network.target" ];
|
|
};
|
|
|
|
systemd.services.dawarich-init-credentials = lib.mkIf needsGenCredentialsUnit {
|
|
script = ''
|
|
umask 077
|
|
''
|
|
+ lib.optionalString (cfg.secretKeyBaseFile == null) ''
|
|
if ! test -f ${defaultSecretKeyBaseFile}; then
|
|
mkdir -p $(dirname ${defaultSecretKeyBaseFile})
|
|
bin/bundle exec rails secret > ${defaultSecretKeyBaseFile}
|
|
fi
|
|
'';
|
|
|
|
environment = env;
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
SyslogIdentifier = "dawarich-init-dirs";
|
|
# System Call Filtering
|
|
SystemCallFilter = [ "~@resources" ] ++ systemCallFilter;
|
|
}
|
|
// cfgService;
|
|
|
|
after = [ "network.target" ];
|
|
};
|
|
|
|
systemd.services.dawarich-init-db = lib.mkIf cfg.automaticMigrations {
|
|
script = ''
|
|
${loadCredentialsIntoEnv}
|
|
|
|
# Run primary database migrations first (needed before other migrations)
|
|
echo "Running primary database migrations..."
|
|
rails db:migrate
|
|
|
|
# Run data migrations
|
|
echo "Running DATA migrations..."
|
|
rake data:migrate
|
|
|
|
echo "Running seeds..."
|
|
rails db:seed
|
|
'';
|
|
path = [ cfg.package ];
|
|
environment = env;
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
LoadCredential = loadCredentials;
|
|
EnvironmentFile = cfg.extraEnvFiles;
|
|
WorkingDirectory = cfg.package;
|
|
# System Call Filtering
|
|
SystemCallFilter = [ "~@resources" ] ++ systemCallFilter;
|
|
}
|
|
// cfgService;
|
|
# both postgres and redis are needed for the migrations to work
|
|
after = [
|
|
"network.target"
|
|
]
|
|
++ lib.optional needsGenCredentialsUnit "dawarich-init-credentials.service"
|
|
++ lib.optional cfg.database.createLocally "postgresql.target"
|
|
++ lib.optional cfg.redis.createLocally "redis-dawarich.service";
|
|
requires =
|
|
lib.optional needsGenCredentialsUnit "dawarich-init-credentials.service"
|
|
++ lib.optional cfg.database.createLocally "postgresql.target"
|
|
++ lib.optional cfg.redis.createLocally "redis-dawarich.service";
|
|
};
|
|
|
|
systemd.services.dawarich-web = {
|
|
after = [
|
|
"network.target"
|
|
]
|
|
++ lib.optional needsGenCredentialsUnit "dawarich-init-credentials.service"
|
|
++ commonUnits;
|
|
requires = lib.optional needsGenCredentialsUnit "dawarich-init-credentials.service" ++ commonUnits;
|
|
wantedBy = [ "dawarich.target" ];
|
|
description = "Dawarich web";
|
|
environment = env;
|
|
script = ''
|
|
${loadCredentialsIntoEnv}
|
|
|
|
${lib.getExe' cfg.package "rails"} server
|
|
'';
|
|
serviceConfig = {
|
|
Restart = "always";
|
|
RestartSec = 20;
|
|
LoadCredential = loadCredentials;
|
|
EnvironmentFile = cfg.extraEnvFiles;
|
|
WorkingDirectory = cfg.package;
|
|
# Runtime directory and mode
|
|
RuntimeDirectory = "dawarich-web";
|
|
RuntimeDirectoryMode = "0750";
|
|
}
|
|
// cfgService;
|
|
};
|
|
|
|
systemd.tmpfiles.settings."dawarich"."${dataDir}/imports/watched".d = {
|
|
group = "dawarich";
|
|
mode = "700";
|
|
user = "dawarich";
|
|
};
|
|
|
|
services.nginx = lib.mkIf cfg.configureNginx {
|
|
enable = true;
|
|
virtualHosts."${cfg.localDomain}" = {
|
|
root = "${cfg.package}/public/";
|
|
|
|
locations."/" = {
|
|
tryFiles = "$uri @proxy";
|
|
};
|
|
|
|
locations."@proxy" = {
|
|
proxyPass = "http://127.0.0.1:${toString cfg.webPort}";
|
|
recommendedProxySettings = true;
|
|
proxyWebsockets = true;
|
|
};
|
|
};
|
|
};
|
|
|
|
services.redis.servers = lib.mkIf cfg.redis.createLocally {
|
|
dawarich = {
|
|
enable = true;
|
|
port = cfg.redis.port;
|
|
bind = lib.mkIf (!isRedisUnixSocket) cfg.redis.host;
|
|
};
|
|
};
|
|
|
|
services.postgresql = lib.mkIf cfg.database.createLocally {
|
|
enable = true;
|
|
extensions = ps: with ps; [ postgis ];
|
|
ensureUsers = [
|
|
{
|
|
inherit (cfg.database) name;
|
|
ensureDBOwnership = true;
|
|
}
|
|
];
|
|
ensureDatabases = [ cfg.database.name ];
|
|
};
|
|
|
|
systemd.services.postgresql-setup.serviceConfig.ExecStartPost =
|
|
let
|
|
# https://github.com/Freika/dawarich/blob/0.30.6/db/schema.rb#L15-L16
|
|
# https://postgis.net/documentation/getting_started/
|
|
sqlFile = pkgs.writeText "dawarich-postgres-setup.sql" ''
|
|
CREATE EXTENSION IF NOT EXISTS postgis;
|
|
SELECT postgis_extensions_upgrade();
|
|
'';
|
|
in
|
|
lib.mkIf cfg.database.createLocally [
|
|
''
|
|
${lib.getExe' config.services.postgresql.package "psql"} -d "${cfg.database.name}" -f "${sqlFile}"
|
|
''
|
|
];
|
|
|
|
users.users = lib.mkIf (cfg.user == "dawarich") {
|
|
dawarich = {
|
|
isSystemUser = true;
|
|
home = cfg.package;
|
|
inherit (cfg) group;
|
|
};
|
|
};
|
|
users.groups = lib.mkIf (cfg.group == "dawarich") { ${cfg.group} = { }; };
|
|
}
|
|
{
|
|
systemd.services = lib.mkMerge [
|
|
sidekiqUnits
|
|
];
|
|
}
|
|
]
|
|
);
|
|
|
|
meta.maintainers = with lib.maintainers; [
|
|
diogotcorreia
|
|
tmarkus
|
|
];
|
|
|
|
}
|