1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.services.mealie;
9 pkg = cfg.package;
10in
11{
12 options.services.mealie = {
13 enable = lib.mkEnableOption "Mealie, a recipe manager and meal planner";
14
15 package = lib.mkPackageOption pkgs "mealie" { };
16
17 listenAddress = lib.mkOption {
18 type = lib.types.str;
19 default = "0.0.0.0";
20 description = "Address on which the service should listen.";
21 };
22
23 port = lib.mkOption {
24 type = lib.types.port;
25 default = 9000;
26 description = "Port on which to serve the Mealie service.";
27 };
28
29 settings = lib.mkOption {
30 type = with lib.types; attrsOf anything;
31 default = { };
32 description = ''
33 Configuration of the Mealie service.
34
35 See [the mealie documentation](https://nightly.mealie.io/documentation/getting-started/installation/backend-config/) for available options and default values.
36 '';
37 example = {
38 ALLOW_SIGNUP = "false";
39 };
40 };
41
42 credentialsFile = lib.mkOption {
43 type = with lib.types; nullOr path;
44 default = null;
45 example = "/run/secrets/mealie-credentials.env";
46 description = ''
47 File containing credentials used in mealie such as {env}`POSTGRES_PASSWORD`
48 or sensitive LDAP options.
49
50 Expects the format of an `EnvironmentFile=`, as described by {manpage}`systemd.exec(5)`.
51 '';
52 };
53
54 database = {
55 createLocally = lib.mkOption {
56 type = lib.types.bool;
57 default = false;
58 description = ''
59 Configure local PostgreSQL database server for Mealie.
60 '';
61 };
62 };
63 };
64
65 config = lib.mkIf cfg.enable {
66 systemd.services.mealie = {
67 description = "Mealie, a self hosted recipe manager and meal planner";
68
69 after = [ "network-online.target" ] ++ lib.optional cfg.database.createLocally "postgresql.service";
70 requires = lib.optional cfg.database.createLocally "postgresql.service";
71 wants = [ "network-online.target" ];
72 wantedBy = [ "multi-user.target" ];
73
74 environment = {
75 PRODUCTION = "true";
76 API_PORT = toString cfg.port;
77 BASE_URL = "http://localhost:${toString cfg.port}";
78 DATA_DIR = "/var/lib/mealie";
79 NLTK_DATA = pkgs.nltk-data.averaged_perceptron_tagger_eng;
80 } // (builtins.mapAttrs (_: val: toString val) cfg.settings);
81
82 serviceConfig = {
83 DynamicUser = true;
84 User = "mealie";
85 ExecStartPre = "${pkg}/libexec/init_db";
86 ExecStart = "${lib.getExe pkg} -b ${cfg.listenAddress}:${builtins.toString cfg.port}";
87 EnvironmentFile = lib.mkIf (cfg.credentialsFile != null) cfg.credentialsFile;
88 StateDirectory = "mealie";
89 StandardOutput = "journal";
90 };
91 };
92
93 services.mealie.settings = lib.mkIf cfg.database.createLocally {
94 DB_ENGINE = "postgres";
95 POSTGRES_URL_OVERRIDE = "postgresql://mealie:@/mealie?host=/run/postgresql";
96 };
97
98 services.postgresql = lib.mkIf cfg.database.createLocally {
99 enable = true;
100 ensureDatabases = [ "mealie" ];
101 ensureUsers = [
102 {
103 name = "mealie";
104 ensureDBOwnership = true;
105 }
106 ];
107 };
108 };
109}