mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-25 16:33:15 +00:00
nixos/davis: init
This commit is contained in:
parent
afaaa840c1
commit
17d73dc9a1
@ -138,6 +138,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
||||
|
||||
- [Scrutiny](https://github.com/AnalogJ/scrutiny), a S.M.A.R.T monitoring tool for hard disks with a web frontend.
|
||||
|
||||
- [davis](https://github.com/tchapi/davis), a simple CardDav and CalDav server inspired by Baïkal. Available as [services.davis]($opt-services-davis.enable).
|
||||
|
||||
- [systemd-lock-handler](https://git.sr.ht/~whynothugo/systemd-lock-handler/), a bridge between logind D-Bus events and systemd targets. Available as [services.systemd-lock-handler.enable](#opt-services.systemd-lock-handler.enable).
|
||||
|
||||
- [wastebin](https://github.com/matze/wastebin), a pastebin server written in rust. Available as [services.wastebin](#opt-services.wastebin.enable).
|
||||
|
@ -1309,6 +1309,7 @@
|
||||
./services/web-apps/cloudlog.nix
|
||||
./services/web-apps/code-server.nix
|
||||
./services/web-apps/convos.nix
|
||||
./services/web-apps/davis.nix
|
||||
./services/web-apps/dex.nix
|
||||
./services/web-apps/discourse.nix
|
||||
./services/web-apps/documize.nix
|
||||
|
32
nixos/modules/services/web-apps/davis.md
Normal file
32
nixos/modules/services/web-apps/davis.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Davis {#module-services-davis}
|
||||
|
||||
[Davis](https://github.com/tchapi/davis/) is a caldav and carrddav server. It
|
||||
has a simple, fully translatable admin interface for sabre/dav based on Symfony
|
||||
5 and Bootstrap 5, initially inspired by Baïkal.
|
||||
|
||||
## Basic Usage {#module-services-davis-basic-usage}
|
||||
|
||||
At first, an application secret is needed, this can be generated with:
|
||||
```ShellSession
|
||||
$ cat /dev/urandom | tr -dc a-zA-Z0-9 | fold -w 48 | head -n 1
|
||||
```
|
||||
|
||||
After that, `davis` can be deployed like this:
|
||||
```
|
||||
{
|
||||
services.davis = {
|
||||
enable = true;
|
||||
hostname = "davis.example.com";
|
||||
mail = {
|
||||
dsn = "smtp://username@example.com:25";
|
||||
inviteFromAddress = "davis@example.com";
|
||||
};
|
||||
adminLogin = "admin";
|
||||
adminPasswordFile = "/run/secrets/davis-admin-password";
|
||||
appSecretFile = "/run/secrets/davis-app-secret";
|
||||
nginx = {};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This deploys Davis using a sqlite database running out of `/var/lib/davis`.
|
554
nixos/modules/services/web-apps/davis.nix
Normal file
554
nixos/modules/services/web-apps/davis.nix
Normal file
@ -0,0 +1,554 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.davis;
|
||||
db = cfg.database;
|
||||
mail = cfg.mail;
|
||||
|
||||
mysqlLocal = db.createLocally && db.driver == "mysql";
|
||||
pgsqlLocal = db.createLocally && db.driver == "postgresql";
|
||||
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
|
||||
isSecret = v: lib.isAttrs v && v ? _secret && (lib.isString v._secret || builtins.isPath v._secret);
|
||||
davisEnvVars = lib.generators.toKeyValue {
|
||||
mkKeyValue = lib.flip lib.generators.mkKeyValueDefault "=" {
|
||||
mkValueString =
|
||||
v:
|
||||
if builtins.isInt v then
|
||||
toString v
|
||||
else if lib.isString v then
|
||||
"\"${v}\""
|
||||
else if true == v then
|
||||
"true"
|
||||
else if false == v then
|
||||
"false"
|
||||
else if null == v then
|
||||
""
|
||||
else if isSecret v then
|
||||
if (lib.isString v._secret) then
|
||||
builtins.hashString "sha256" v._secret
|
||||
else
|
||||
builtins.hashString "sha256" (builtins.readFile v._secret)
|
||||
else
|
||||
throw "unsupported type ${builtins.typeOf v}: ${(lib.generators.toPretty { }) v}";
|
||||
};
|
||||
};
|
||||
secretPaths = lib.mapAttrsToList (_: v: v._secret) (lib.filterAttrs (_: isSecret) cfg.config);
|
||||
mkSecretReplacement = file: ''
|
||||
replace-secret ${
|
||||
lib.escapeShellArgs [
|
||||
(
|
||||
if (lib.isString file) then
|
||||
builtins.hashString "sha256" file
|
||||
else
|
||||
builtins.hashString "sha256" (builtins.readFile file)
|
||||
)
|
||||
file
|
||||
"${cfg.dataDir}/.env.local"
|
||||
]
|
||||
}
|
||||
'';
|
||||
secretReplacements = lib.concatMapStrings mkSecretReplacement secretPaths;
|
||||
filteredConfig = lib.converge (lib.filterAttrsRecursive (
|
||||
_: v:
|
||||
!lib.elem v [
|
||||
{ }
|
||||
null
|
||||
]
|
||||
)) cfg.config;
|
||||
davisEnv = pkgs.writeText "davis.env" (davisEnvVars filteredConfig);
|
||||
in
|
||||
{
|
||||
options.services.davis = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "Davis is a caldav and carddav server");
|
||||
|
||||
user = lib.mkOption {
|
||||
default = "davis";
|
||||
description = lib.mdDoc "User davis runs as.";
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
default = "davis";
|
||||
description = lib.mdDoc "Group davis runs as.";
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption pkgs "davis" { };
|
||||
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/davis";
|
||||
description = lib.mdDoc ''
|
||||
Davis data directory.
|
||||
'';
|
||||
};
|
||||
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "davis.yourdomain.org";
|
||||
description = lib.mdDoc ''
|
||||
Domain of the host to serve davis under. You may want to change it if you
|
||||
run Davis on a different URL than davis.yourdomain.
|
||||
'';
|
||||
};
|
||||
|
||||
config = lib.mkOption {
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.nullOr (
|
||||
lib.types.either
|
||||
(lib.types.oneOf [
|
||||
lib.types.bool
|
||||
lib.types.int
|
||||
lib.types.port
|
||||
lib.types.path
|
||||
lib.types.str
|
||||
])
|
||||
(
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
_secret = lib.mkOption {
|
||||
type = lib.types.nullOr (
|
||||
lib.types.oneOf [
|
||||
lib.types.str
|
||||
lib.types.path
|
||||
]
|
||||
);
|
||||
description = lib.mdDoc ''
|
||||
The path to a file containing the value the
|
||||
option should be set to in the final
|
||||
configuration file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
default = { };
|
||||
|
||||
example = '''';
|
||||
description = lib.mdDoc '''';
|
||||
};
|
||||
|
||||
adminLogin = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "root";
|
||||
description = lib.mdDoc ''
|
||||
Username for the admin account.
|
||||
'';
|
||||
};
|
||||
adminPasswordFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = lib.mdDoc ''
|
||||
The full path to a file that contains the admin's password. Must be
|
||||
readable by the user.
|
||||
'';
|
||||
example = "/run/secrets/davis-admin-pass";
|
||||
};
|
||||
|
||||
appSecretFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = lib.mdDoc ''
|
||||
A file containing the Symfony APP_SECRET - Its value should be a series
|
||||
of characters, numbers and symbols chosen randomly and the recommended
|
||||
length is around 32 characters. Can be generated with <code>cat
|
||||
/dev/urandom | tr -dc a-zA-Z0-9 | fold -w 48 | head -n 1</code>.
|
||||
'';
|
||||
example = "/run/secrets/davis-appsecret";
|
||||
};
|
||||
|
||||
database = {
|
||||
driver = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"sqlite"
|
||||
"postgresql"
|
||||
"mysql"
|
||||
];
|
||||
default = "sqlite";
|
||||
description = lib.mdDoc "Database type, required in all circumstances.";
|
||||
};
|
||||
urlFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/run/secrets/davis-db-url";
|
||||
description = lib.mdDoc ''
|
||||
A file containing the database connection url. If set then it
|
||||
overrides all other database settings (except driver). This is
|
||||
mandatory if you want to use an external database, that is when
|
||||
`services.davis.database.createLocally` is `false`.
|
||||
'';
|
||||
};
|
||||
name = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = "davis";
|
||||
description = lib.mdDoc "Database name, only used when the databse is created locally.";
|
||||
};
|
||||
createLocally = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc "Create the database and database user locally.";
|
||||
};
|
||||
};
|
||||
|
||||
mail = {
|
||||
dsn = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc "Mail DSN for sending emails. Mutually exclusive with `services.davis.mail.dsnFile`.";
|
||||
example = "smtp://username:password@example.com:25";
|
||||
};
|
||||
dsnFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "/run/secrets/davis-mail-dsn";
|
||||
description = lib.mdDoc "A file containing the mail DSN for sending emails. Mutually exclusive with `servies.davis.mail.dsn`.";
|
||||
};
|
||||
inviteFromAddress = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc "Email address to send invitations from.";
|
||||
example = "no-reply@dav.example.com";
|
||||
};
|
||||
};
|
||||
|
||||
nginx = lib.mkOption {
|
||||
type = lib.types.submodule (
|
||||
lib.recursiveUpdate (import ../web-servers/nginx/vhost-options.nix { inherit config lib; }) { }
|
||||
);
|
||||
default = null;
|
||||
example = ''
|
||||
{
|
||||
serverAliases = [
|
||||
"dav.''${config.networking.domain}"
|
||||
];
|
||||
# To enable encryption and let let's encrypt take care of certificate
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
}
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
With this option, you can customize the nginx virtualHost settings.
|
||||
'';
|
||||
};
|
||||
|
||||
poolConfig = lib.mkOption {
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.oneOf [
|
||||
lib.types.str
|
||||
lib.types.int
|
||||
lib.types.bool
|
||||
]
|
||||
);
|
||||
default = {
|
||||
"pm" = "dynamic";
|
||||
"pm.max_children" = 32;
|
||||
"pm.start_servers" = 2;
|
||||
"pm.min_spare_servers" = 2;
|
||||
"pm.max_spare_servers" = 4;
|
||||
"pm.max_requests" = 500;
|
||||
};
|
||||
description = lib.mdDoc ''
|
||||
Options for the davis PHP pool. See the documentation on <literal>php-fpm.conf</literal>
|
||||
for details on configuration directives.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
defaultServiceConfig = {
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
User = user;
|
||||
UMask = 77;
|
||||
DeviceAllow = "";
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = 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;
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@resources"
|
||||
"~@privileged"
|
||||
];
|
||||
WorkingDirectory = "${cfg.package}/";
|
||||
};
|
||||
in
|
||||
lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = db.createLocally -> db.urlFile == null;
|
||||
message = "services.davis.database.urlFile must be unset if services.davis.database.createLocally is set true.";
|
||||
}
|
||||
{
|
||||
assertion = db.createLocally || db.urlFile != null;
|
||||
message = "One of services.davis.database.urlFile or services.davis.database.createLocally must be set.";
|
||||
}
|
||||
{
|
||||
assertion = (mail.dsn != null) != (mail.dsnFile != null);
|
||||
message = "One of (and only one of) services.davis.mail.dsn or services.davis.mail.dsnFile must be set.";
|
||||
}
|
||||
];
|
||||
services.davis.config =
|
||||
{
|
||||
APP_ENV = "prod";
|
||||
CACHE_DIR = "${cfg.dataDir}/var/cache";
|
||||
# note: we do not need the log dir (we log to stdout/journald), by davis/symfony will try to create it, and the default value is one in the nix-store
|
||||
# so we set it to a path under dataDir to avoid something like: Unable to create the "logs" directory (/nix/store/5cfskz0ybbx37s1161gjn5klwb5si1zg-davis-4.4.1/var/log).
|
||||
LOG_DIR = "${cfg.dataDir}/var/log";
|
||||
LOG_FILE_PATH = "/dev/stdout";
|
||||
DATABASE_DRIVER = db.driver;
|
||||
INVITE_FROM_ADDRESS = mail.inviteFromAddress;
|
||||
APP_SECRET._secret = cfg.appSecretFile;
|
||||
ADMIN_LOGIN = cfg.adminLogin;
|
||||
ADMIN_PASSWORD._secret = cfg.adminPasswordFile;
|
||||
APP_TIMEZONE = config.time.timeZone;
|
||||
WEBDAV_ENABLED = false;
|
||||
CALDAV_ENABLED = true;
|
||||
CARDDAV_ENABLED = true;
|
||||
}
|
||||
// (if mail.dsn != null then { MAILER_DSN = mail.dsn; } else { MAILER_DSN._secret = mail.dsnFile; })
|
||||
// (
|
||||
if db.createLocally then
|
||||
{
|
||||
DATABASE_URL =
|
||||
if db.driver == "sqlite" then
|
||||
"sqlite:///${cfg.dataDir}/davis.db" # note: sqlite needs 4 slashes for an absolute path
|
||||
else if
|
||||
pgsqlLocal
|
||||
# note: davis expects a non-standard postgres uri (due to the underlying doctrine library)
|
||||
# specifically the charset query parameter, and the dummy hostname which is overriden by the host query parameter
|
||||
then
|
||||
"postgres://${user}@localhost/${db.name}?host=/run/postgresql&charset=UTF-8"
|
||||
else if mysqlLocal then
|
||||
"mysql://${user}@localhost/${db.name}?socket=/run/mysqld/mysqld.sock"
|
||||
else
|
||||
null;
|
||||
}
|
||||
else
|
||||
{ DATABASE_URL._secret = db.urlFile; }
|
||||
);
|
||||
|
||||
users = {
|
||||
users = lib.mkIf (user == "davis") {
|
||||
davis = {
|
||||
description = "Davis service user";
|
||||
group = cfg.group;
|
||||
isSystemUser = true;
|
||||
home = cfg.dataDir;
|
||||
};
|
||||
};
|
||||
groups = lib.mkIf (group == "davis") { davis = { }; };
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.dataDir} 0710 ${user} ${group} - -"
|
||||
"d ${cfg.dataDir}/var 0700 ${user} ${group} - -"
|
||||
"d ${cfg.dataDir}/var/log 0700 ${user} ${group} - -"
|
||||
"d ${cfg.dataDir}/var/cache 0700 ${user} ${group} - -"
|
||||
];
|
||||
|
||||
services.phpfpm.pools.davis = {
|
||||
inherit user group;
|
||||
phpOptions = ''
|
||||
log_errors = on
|
||||
'';
|
||||
phpEnv = {
|
||||
ENV_DIR = "${cfg.dataDir}";
|
||||
CACHE_DIR = "${cfg.dataDir}/var/cache";
|
||||
#LOG_DIR = "${cfg.dataDir}/var/log";
|
||||
};
|
||||
settings =
|
||||
{
|
||||
"listen.mode" = "0660";
|
||||
"pm" = "dynamic";
|
||||
"pm.max_children" = 256;
|
||||
"pm.start_servers" = 10;
|
||||
"pm.min_spare_servers" = 5;
|
||||
"pm.max_spare_servers" = 20;
|
||||
}
|
||||
// (
|
||||
if cfg.nginx != null then
|
||||
{
|
||||
"listen.owner" = config.services.nginx.user;
|
||||
"listen.group" = config.services.nginx.group;
|
||||
}
|
||||
else
|
||||
{ }
|
||||
)
|
||||
// cfg.poolConfig;
|
||||
};
|
||||
|
||||
# Reading the user-provided secret files requires root access
|
||||
systemd.services.davis-env-setup = {
|
||||
description = "Setup davis environment";
|
||||
before = [
|
||||
"phpfpm-davis.service"
|
||||
"davis-db-migrate.service"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
path = [ pkgs.replace-secret ];
|
||||
restartTriggers = [
|
||||
cfg.package
|
||||
davisEnv
|
||||
];
|
||||
script = ''
|
||||
# error handling
|
||||
set -euo pipefail
|
||||
# create .env file with the upstream values
|
||||
install -T -m 0600 -o ${user} ${cfg.package}/env-upstream "${cfg.dataDir}/.env"
|
||||
# create .env.local file with the user-provided values
|
||||
install -T -m 0600 -o ${user} ${davisEnv} "${cfg.dataDir}/.env.local"
|
||||
${secretReplacements}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.davis-db-migrate = {
|
||||
description = "Migrate davis database";
|
||||
before = [ "phpfpm-davis.service" ];
|
||||
after =
|
||||
lib.optional mysqlLocal "mysql.service"
|
||||
++ lib.optional pgsqlLocal "postgresql.service"
|
||||
++ [ "davis-env-setup.service" ];
|
||||
requires =
|
||||
lib.optional mysqlLocal "mysql.service"
|
||||
++ lib.optional pgsqlLocal "postgresql.service"
|
||||
++ [ "davis-env-setup.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = defaultServiceConfig // {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
Environment = [
|
||||
"ENV_DIR=${cfg.dataDir}"
|
||||
"CACHE_DIR=${cfg.dataDir}/var/cache"
|
||||
"LOG_DIR=${cfg.dataDir}/var/log"
|
||||
];
|
||||
EnvironmentFile = "${cfg.dataDir}/.env.local";
|
||||
};
|
||||
restartTriggers = [
|
||||
cfg.package
|
||||
davisEnv
|
||||
];
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
${cfg.package}/bin/console cache:clear --no-debug
|
||||
${cfg.package}/bin/console cache:warmup --no-debug
|
||||
${cfg.package}/bin/console doctrine:migrations:migrate
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.phpfpm-davis.after = [
|
||||
"davis-env-setup.service"
|
||||
"davis-db-migrate.service"
|
||||
];
|
||||
systemd.services.phpfpm-davis.requires = [
|
||||
"davis-env-setup.service"
|
||||
"davis-db-migrate.service"
|
||||
] ++ lib.optional mysqlLocal "mysql.service" ++ lib.optional pgsqlLocal "postgresql.service";
|
||||
systemd.services.phpfpm-davis.serviceConfig.ReadWritePaths = [ cfg.dataDir ];
|
||||
|
||||
services.nginx = lib.mkIf (cfg.nginx != null) {
|
||||
enable = lib.mkDefault true;
|
||||
virtualHosts = {
|
||||
"${cfg.hostname}" = lib.mkMerge [
|
||||
cfg.nginx
|
||||
{
|
||||
root = lib.mkForce "${cfg.package}/public";
|
||||
extraConfig = ''
|
||||
charset utf-8;
|
||||
index index.php;
|
||||
'';
|
||||
locations = {
|
||||
"/" = {
|
||||
extraConfig = ''
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
'';
|
||||
};
|
||||
"~* ^/.well-known/(caldav|carddav)$" = {
|
||||
extraConfig = ''
|
||||
return 302 $http_x_forwarded_proto://$host/dav/;
|
||||
'';
|
||||
};
|
||||
"~ ^(.+\.php)(.*)$" = {
|
||||
extraConfig = ''
|
||||
try_files $fastcgi_script_name =404;
|
||||
include ${config.services.nginx.package}/conf/fastcgi_params;
|
||||
include ${config.services.nginx.package}/conf/fastcgi.conf;
|
||||
fastcgi_pass unix:${config.services.phpfpm.pools.davis.socket};
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
fastcgi_split_path_info ^(.+\.php)(.*)$;
|
||||
fastcgi_param X-Forwarded-Proto $http_x_forwarded_proto;
|
||||
fastcgi_param X-Forwarded-Port $http_x_forwarded_port;
|
||||
'';
|
||||
};
|
||||
"~ /(\\.ht)" = {
|
||||
extraConfig = ''
|
||||
deny all;
|
||||
return 404;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
services.mysql = lib.mkIf mysqlLocal {
|
||||
enable = true;
|
||||
package = lib.mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [ db.name ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = user;
|
||||
ensurePermissions = {
|
||||
"${db.name}.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.postgresql = lib.mkIf pgsqlLocal {
|
||||
enable = true;
|
||||
ensureDatabases = [ db.name ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = user;
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
doc = ./davis.md;
|
||||
maintainers = pkgs.davis.meta.maintainers;
|
||||
};
|
||||
}
|
@ -233,6 +233,7 @@ in {
|
||||
croc = handleTest ./croc.nix {};
|
||||
darling = handleTest ./darling.nix {};
|
||||
dae = handleTest ./dae.nix {};
|
||||
davis = handleTest ./davis.nix {};
|
||||
dconf = handleTest ./dconf.nix {};
|
||||
deconz = handleTest ./deconz.nix {};
|
||||
deepin = handleTest ./deepin.nix {};
|
||||
|
59
nixos/tests/davis.nix
Normal file
59
nixos/tests/davis.nix
Normal file
@ -0,0 +1,59 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
name = "davis";
|
||||
|
||||
meta.maintainers = pkgs.davis.meta.maintainers;
|
||||
|
||||
nodes.machine =
|
||||
{ config, ... }:
|
||||
{
|
||||
virtualisation = {
|
||||
memorySize = 512;
|
||||
};
|
||||
|
||||
services.davis = {
|
||||
enable = true;
|
||||
hostname = "davis.example.com";
|
||||
database = {
|
||||
driver = "postgresql";
|
||||
};
|
||||
mail = {
|
||||
dsnFile = "${pkgs.writeText "davisMailDns" "smtp://username:password@example.com:25"}";
|
||||
inviteFromAddress = "dav@example.com";
|
||||
};
|
||||
adminLogin = "admin";
|
||||
appSecretFile = "${pkgs.writeText "davisAppSecret" "52882ef142066e09ab99ce816ba72522e789505caba224"}";
|
||||
adminPasswordFile = "${pkgs.writeText "davisAdminPass" "nixos"}";
|
||||
nginx = { };
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_unit("postgresql.service")
|
||||
machine.wait_for_unit("davis-env-setup.service")
|
||||
machine.wait_for_unit("davis-db-migrate.service")
|
||||
machine.wait_for_unit("nginx.service")
|
||||
machine.wait_for_unit("phpfpm-davis.service")
|
||||
|
||||
with subtest("welcome screen loads"):
|
||||
machine.succeed(
|
||||
"curl -sSfL --resolve davis.example.com:80:127.0.0.1 http://davis.example.com/ | grep '<title>Davis</title>'"
|
||||
)
|
||||
|
||||
with subtest("login works"):
|
||||
csrf_token = machine.succeed(
|
||||
"curl -c /tmp/cookies -sSfL --resolve davis.example.com:80:127.0.0.1 http://davis.example.com/login | grep '_csrf_token' | sed -E 's,.*value=\"(.*)\".*,\\1,g'"
|
||||
)
|
||||
r = machine.succeed(
|
||||
f"curl -b /tmp/cookies --resolve davis.example.com:80:127.0.0.1 http://davis.example.com/login -X POST -F username=admin -F password=nixos -F _csrf_token={csrf_token.strip()} -D headers"
|
||||
)
|
||||
print(r)
|
||||
machine.succeed(
|
||||
"[[ $(grep -i 'location: ' headers | cut -d: -f2- | xargs echo) == /dashboard* ]]"
|
||||
)
|
||||
'';
|
||||
}
|
||||
)
|
Loading…
Reference in New Issue
Block a user