-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
{ | ||
config, | ||
lib, | ||
pkgs, | ||
... | ||
}: | ||
let | ||
|
||
cfg = config.services.froide; | ||
format = pkgs.formats.toml { }; | ||
|
||
in | ||
{ | ||
options.services.froide = { | ||
|
||
enable = lib.mkEnableOption "Freedom of information portal web app Froide"; | ||
|
||
package = lib.mkPackageOption pkgs "froide" { }; | ||
|
||
port = lib.mkOption { | ||
type = with lib.types; nullOr port; | ||
default = 8001; | ||
description = "Port to listen on."; | ||
}; | ||
|
||
dataDir = lib.mkOption { | ||
type = lib.types.str; | ||
default = "/var/lib/froide"; | ||
description = "Directory to store the Froide server data."; | ||
}; | ||
|
||
openFirewall = lib.mkOption { | ||
type = lib.types.bool; | ||
default = false; | ||
description = '' | ||
Whether to open ports in the firewall for the server. | ||
''; | ||
}; | ||
|
||
settings = lib.mkOption { | ||
default = { }; | ||
description = '' | ||
IMAP authentication configuration for rspamd-trainer. For supplying | ||
the IMAP password, use the `secrets` option. | ||
''; | ||
type = lib.types.submodule { freeformType = format.type; }; | ||
example = lib.literalExpression '' | ||
{ | ||
HOST = "localhost"; | ||
USERNAME = "[email protected]"; | ||
INBOXPREFIX = "INBOX/"; | ||
} | ||
''; | ||
}; | ||
|
||
secrets = lib.mkOption { | ||
type = with lib.types; listOf path; | ||
description = '' | ||
A list of files containing the various secrets. Should be in the | ||
format expected by systemd's `EnvironmentFile` directory. For the | ||
IMAP account password use `PASSWORD = mypassword`. | ||
''; | ||
default = [ ]; | ||
}; | ||
|
||
}; | ||
|
||
config = lib.mkIf cfg.enable { | ||
|
||
services.postgresql = { | ||
enable = true; | ||
ensureDatabases = [ "froide" ]; | ||
ensureUsers = [ | ||
{ | ||
name = "froide"; | ||
ensureDBOwnership = true; | ||
} | ||
]; | ||
extraPlugins = ps: with ps; [ postgis ]; | ||
authentication = '' | ||
host froide froide localhost trust | ||
''; | ||
initialScript = pkgs.writeText "backend-initScript" '' | ||
ALTER USER froide WITH SUPERUSER; | ||
''; | ||
}; | ||
|
||
systemd.services = { | ||
|
||
postgresql.serviceConfig.ExecStartPost = | ||
let | ||
sqlFile = pkgs.writeText "froide-pgvectors-setup.sql" '' | ||
ALTER USER froide WITH SUPERUSER; | ||
#CREATE EXTENSION IF NOT EXISTS postgis; | ||
#ALTER SCHEMA govplan OWNER TO govplan; | ||
#ALTER EXTENSION govplan UPDATE; | ||
''; | ||
in | ||
[ | ||
'' | ||
${lib.getExe' config.services.postgresql.package "psql"} -d froide -f "${sqlFile}" | ||
'' | ||
]; | ||
|
||
froide = { | ||
description = "Gouvernment planer Govplan"; | ||
serviceConfig = { | ||
ExecStart = "${lib.getExe cfg.package} runserver 0.0.0.0:8000"; | ||
WorkingDirectory = cfg.dataDir; | ||
StateDirectory = [ cfg.dataDir ]; | ||
DynamicUser = true; | ||
EnvironmentFile = [ | ||
(format.generate "froide-env" cfg.settings) | ||
cfg.secrets | ||
]; | ||
Environment = [ "DJANGO_CONFIGURATION=Production" ]; | ||
}; | ||
after = [ "postgresql.service" ]; | ||
wantedBy = [ "multi-user.target" ]; | ||
preStart = '' | ||
# Auto-migrate on first run or if the package has changed | ||
versionFile="${cfg.dataDir}/src-version" | ||
if [[ $(cat "$versionFile" 2>/dev/null) != ${cfg.package} ]]; then | ||
etebase-server migrate --no-input | ||
etebase-server collectstatic --no-input --clear | ||
echo ${cfg.package} > "$versionFile" | ||
fi | ||
# FIXME adapt paperless-ngx check for new versions | ||
${lib.getExe cfg.package} collectstatic | ||
${lib.getExe cfg.package} migrate | ||
''; | ||
}; | ||
}; | ||
|
||
environment.systemPackages = [ pkgs.froide ]; | ||
|
||
networking.firewall = lib.mkIf cfg.openFirewall { | ||
allowedTCPPorts = [ cfg.port ]; | ||
}; | ||
|
||
}; | ||
|
||
meta.maintainers = with lib.maintainers; [ onny ]; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import ./make-test-python.nix ({ lib, ... }: { | ||
name = "paperless"; | ||
meta.maintainers = with lib.maintainers; [ leona SuperSandro2000 erikarvstedt ]; | ||
|
||
nodes = let self = { | ||
simple = { pkgs, ... }: { | ||
environment.systemPackages = with pkgs; [ imagemagick jq ]; | ||
services.paperless = { | ||
enable = true; | ||
passwordFile = builtins.toFile "password" "admin"; | ||
}; | ||
}; | ||
postgres = { config, pkgs, ... }: { | ||
imports = [ self.simple ]; | ||
services.postgresql = { | ||
enable = true; | ||
ensureDatabases = [ "paperless" ]; | ||
ensureUsers = [ | ||
{ name = config.services.paperless.user; | ||
ensureDBOwnership = true; | ||
} | ||
]; | ||
}; | ||
services.paperless.settings = { | ||
PAPERLESS_DBHOST = "/run/postgresql"; | ||
PAPERLESS_OCR_LANGUAGE = "deu"; | ||
}; | ||
}; | ||
}; in self; | ||
|
||
testScript = '' | ||
import json | ||
def test_paperless(node): | ||
node.wait_for_unit("paperless-consumer.service") | ||
with subtest("Add a document via the file system"): | ||
node.succeed( | ||
"convert -size 400x40 xc:white -font 'DejaVu-Sans' -pointsize 20 -fill black " | ||
"-annotate +5+20 'hello world 16-10-2005' /var/lib/paperless/consume/doc.png" | ||
) | ||
with subtest("Web interface gets ready"): | ||
node.wait_for_unit("paperless-web.service") | ||
# Wait until server accepts connections | ||
node.wait_until_succeeds("curl -fs localhost:28981") | ||
# Required for consuming documents via the web interface | ||
with subtest("Task-queue gets ready"): | ||
node.wait_for_unit("paperless-task-queue.service") | ||
with subtest("Add a png document via the web interface"): | ||
node.succeed( | ||
"convert -size 400x40 xc:white -font 'DejaVu-Sans' -pointsize 20 -fill black " | ||
"-annotate +5+20 'hello web 16-10-2005' /tmp/webdoc.png" | ||
) | ||
node.wait_until_succeeds("curl -u admin:admin -F document=@/tmp/webdoc.png -fs localhost:28981/api/documents/post_document/") | ||
with subtest("Add a txt document via the web interface"): | ||
node.succeed( | ||
"echo 'hello web 16-10-2005' > /tmp/webdoc.txt" | ||
) | ||
node.wait_until_succeeds("curl -u admin:admin -F document=@/tmp/webdoc.txt -fs localhost:28981/api/documents/post_document/") | ||
with subtest("Documents are consumed"): | ||
node.wait_until_succeeds( | ||
"(($(curl -u admin:admin -fs localhost:28981/api/documents/ | jq .count) == 3))" | ||
) | ||
docs = json.loads(node.succeed("curl -u admin:admin -fs localhost:28981/api/documents/"))['results'] | ||
assert "2005-10-16" in docs[0]['created'] | ||
assert "2005-10-16" in docs[1]['created'] | ||
assert "2005-10-16" in docs[2]['created'] | ||
# Detects gunicorn issues, see PR #190888 | ||
with subtest("Document metadata can be accessed"): | ||
metadata = json.loads(node.succeed("curl -u admin:admin -fs localhost:28981/api/documents/1/metadata/")) | ||
assert "original_checksum" in metadata | ||
metadata = json.loads(node.succeed("curl -u admin:admin -fs localhost:28981/api/documents/2/metadata/")) | ||
assert "original_checksum" in metadata | ||
metadata = json.loads(node.succeed("curl -u admin:admin -fs localhost:28981/api/documents/3/metadata/")) | ||
assert "original_checksum" in metadata | ||
test_paperless(simple) | ||
simple.send_monitor_command("quit") | ||
simple.wait_for_shutdown() | ||
test_paperless(postgres) | ||
''; | ||
}) |