wlroots: 0.18.1 -> 0.18.2 (#364488)
[NixPkgs.git] / nixos / modules / services / web-servers / keter / default.nix
blob515d44f7ee5b43d9b1f76429a1ec3f2847e37c73
2   config,
3   pkgs,
4   lib,
5   ...
6 }:
7 let
8   cfg = config.services.keter;
9   yaml = pkgs.formats.yaml { };
12   meta = {
13     maintainers = with lib.maintainers; [ jappie ];
14   };
16   imports = [
17     (lib.mkRenamedOptionModule [ "services" "keter" "keterRoot" ] [ "services" "keter" "root" ])
18     (lib.mkRenamedOptionModule [ "services" "keter" "keterPackage" ] [ "services" "keter" "package" ])
19   ];
21   options.services.keter = {
22     enable = lib.mkEnableOption ''
23       keter, a web app deployment manager.
24       Note that this module only support loading of webapps:
25       Keep an old app running and swap the ports when the new one is booted
26     '';
28     root = lib.mkOption {
29       type = lib.types.str;
30       default = "/var/lib/keter";
31       description = "Mutable state folder for keter";
32     };
34     package = lib.mkOption {
35       type = lib.types.package;
36       default = pkgs.haskellPackages.keter;
37       defaultText = lib.literalExpression "pkgs.haskellPackages.keter";
38       description = "The keter package to be used";
39     };
41     globalKeterConfig = lib.mkOption {
42       type = lib.types.submodule {
43         freeformType = yaml.type;
44         options = {
45           ip-from-header = lib.mkOption {
46             default = true;
47             type = lib.types.bool;
48             description = "You want that ip-from-header in the nginx setup case. It allows nginx setting the original ip address rather then it being localhost (due to reverse proxying)";
49           };
50           listeners = lib.mkOption {
51             default = [
52               {
53                 host = "*";
54                 port = 6981;
55               }
56             ];
57             type = lib.types.listOf (
58               lib.types.submodule {
59                 options = {
60                   host = lib.mkOption {
61                     type = lib.types.str;
62                     description = "host";
63                   };
64                   port = lib.mkOption {
65                     type = lib.types.port;
66                     description = "port";
67                   };
68                 };
69               }
70             );
71             description = ''
72               You want that ip-from-header in
73               the nginx setup case.
74               It allows nginx setting the original ip address rather
75               then it being localhost (due to reverse proxying).
76               However if you configure keter to accept connections
77               directly you may want to set this to false.'';
78           };
79           rotate-logs = lib.mkOption {
80             default = false;
81             type = lib.types.bool;
82             description = ''
83               emits keter logs and it's applications to stderr.
84               which allows journald to capture them.
85               Set to true to let keter put the logs in files
86               (useful on non systemd systems, this is the old approach
87               where keter handled log management)'';
88           };
89         };
90       };
91       description = "Global config for keter, see <https://github.com/snoyberg/keter/blob/master/etc/keter-config.yaml> for reference";
92     };
94     bundle = {
95       appName = lib.mkOption {
96         type = lib.types.str;
97         default = "myapp";
98         description = "The name keter assigns to this bundle";
99       };
101       executable = lib.mkOption {
102         type = lib.types.path;
103         description = "The executable to be run";
104       };
106       domain = lib.mkOption {
107         type = lib.types.str;
108         default = "example.com";
109         description = "The domain keter will bind to";
110       };
112       publicScript = lib.mkOption {
113         type = lib.types.str;
114         default = "";
115         description = ''
116           Allows loading of public environment variables,
117           these are emitted to the log so it shouldn't contain secrets.
118         '';
119         example = "ADMIN_EMAIL=hi@example.com";
120       };
122       secretScript = lib.mkOption {
123         type = lib.types.str;
124         default = "";
125         description = "Allows loading of private environment variables";
126         example = "MY_AWS_KEY=$(cat /run/keys/AWS_ACCESS_KEY_ID)";
127       };
128     };
130   };
132   config = lib.mkIf cfg.enable (
133     let
134       incoming = "${cfg.root}/incoming";
136       globalKeterConfigFile = pkgs.writeTextFile {
137         name = "keter-config.yml";
138         text = (lib.generators.toYAML { } (cfg.globalKeterConfig // { root = cfg.root; }));
139       };
141       # If things are expected to change often, put it in the bundle!
142       bundle = pkgs.callPackage ./bundle.nix (
143         cfg.bundle
144         // {
145           keterExecutable = executable;
146           keterDomain = cfg.bundle.domain;
147         }
148       );
150       # This indirection is required to ensure the nix path
151       # gets copied over to the target machine in remote deployments.
152       # Furthermore, it's important that we use exec to
153       # run the binary otherwise we get process leakage due to this
154       # being executed on every change.
155       executable = pkgs.writeShellScript "bundle-wrapper" ''
156         set -e
157         ${cfg.bundle.secretScript}
158         set -xe
159         ${cfg.bundle.publicScript}
160         exec ${cfg.bundle.executable}
161       '';
163     in
164     {
165       systemd.services.keter = {
166         description = "keter app loader";
167         script = ''
168           set -xe
169           mkdir -p ${incoming}
170           ${lib.getExe cfg.package} ${globalKeterConfigFile};
171         '';
172         wantedBy = [
173           "multi-user.target"
174           "nginx.service"
175         ];
177         serviceConfig = {
178           Restart = "always";
179           RestartSec = "10s";
180         };
182         after = [
183           "network.target"
184           "local-fs.target"
185           "postgresql.service"
186         ];
187       };
189       # On deploy this will load our app, by moving it into the incoming dir
190       # If the bundle content changes, this will run again.
191       # Because the bundle content contains the nix path to the executable,
192       # we inherit nix based cache busting.
193       systemd.services.load-keter-bundle = {
194         description = "load keter bundle into incoming folder";
195         after = [ "keter.service" ];
196         wantedBy = [ "multi-user.target" ];
197         # we can't override keter bundles because it'll stop the previous app
198         # https://github.com/snoyberg/keter#deploying
199         script = ''
200           set -xe
201           cp ${bundle}/bundle.tar.gz.keter ${incoming}/${cfg.bundle.appName}.keter
202         '';
203         path = [
204           executable
205           cfg.bundle.executable
206         ]; # this is a hack to get the executable copied over to the machine.
207       };
208     }
209   );