1{ config, pkgs, lib, ... }:
2
3with lib;
4
5let
6 cfg = config.services.lxd-image-server;
7 format = pkgs.formats.toml {};
8
9 location = "/var/www/simplestreams";
10in
11{
12 options = {
13 services.lxd-image-server = {
14 enable = mkEnableOption (lib.mdDoc "lxd-image-server");
15
16 group = mkOption {
17 type = types.str;
18 description = lib.mdDoc "Group assigned to the user and the webroot directory.";
19 default = "nginx";
20 example = "www-data";
21 };
22
23 settings = mkOption {
24 type = format.type;
25 description = lib.mdDoc ''
26 Configuration for lxd-image-server.
27
28 Example see <https://github.com/Avature/lxd-image-server/blob/master/config.toml>.
29 '';
30 default = {};
31 };
32
33 nginx = {
34 enable = mkEnableOption (lib.mdDoc "nginx");
35 domain = mkOption {
36 type = types.str;
37 description = lib.mdDoc "Domain to use for nginx virtual host.";
38 example = "images.example.org";
39 };
40 };
41 };
42 };
43
44 config = mkMerge [
45 (mkIf (cfg.enable) {
46 users.users.lxd-image-server = {
47 isSystemUser = true;
48 group = cfg.group;
49 };
50 users.groups.${cfg.group} = {};
51
52 environment.etc."lxd-image-server/config.toml".source = format.generate "config.toml" cfg.settings;
53
54 services.logrotate.settings.lxd-image-server = {
55 files = "/var/log/lxd-image-server/lxd-image-server.log";
56 frequency = "daily";
57 rotate = 21;
58 create = "755 lxd-image-server ${cfg.group}";
59 compress = true;
60 delaycompress = true;
61 copytruncate = true;
62 };
63
64 systemd.tmpfiles.rules = [
65 "d /var/www/simplestreams 0755 lxd-image-server ${cfg.group}"
66 ];
67
68 systemd.services.lxd-image-server = {
69 wantedBy = [ "multi-user.target" ];
70 after = [ "network.target" ];
71
72 description = "LXD Image Server";
73
74 script = ''
75 ${pkgs.lxd-image-server}/bin/lxd-image-server init
76 ${pkgs.lxd-image-server}/bin/lxd-image-server watch
77 '';
78
79 serviceConfig = {
80 User = "lxd-image-server";
81 Group = cfg.group;
82 DynamicUser = true;
83 LogsDirectory = "lxd-image-server";
84 RuntimeDirectory = "lxd-image-server";
85 ExecReload = "${pkgs.lxd-image-server}/bin/lxd-image-server reload";
86 ReadWritePaths = [ location ];
87 };
88 };
89 })
90 # this is separate so it can be enabled on mirrored hosts
91 (mkIf (cfg.nginx.enable) {
92 # https://github.com/Avature/lxd-image-server/blob/master/resources/nginx/includes/lxd-image-server.pkg.conf
93 services.nginx.virtualHosts = {
94 "${cfg.nginx.domain}" = {
95 forceSSL = true;
96 enableACME = mkDefault true;
97
98 root = location;
99
100 locations = {
101 "/streams/v1/" = {
102 index = "index.json";
103 };
104
105 # Serve json files with content type header application/json
106 "~ \.json$" = {
107 extraConfig = ''
108 add_header Content-Type application/json;
109 '';
110 };
111
112 "~ \.tar.xz$" = {
113 extraConfig = ''
114 add_header Content-Type application/octet-stream;
115 '';
116 };
117
118 "~ \.tar.gz$" = {
119 extraConfig = ''
120 add_header Content-Type application/octet-stream;
121 '';
122 };
123
124 # Deny access to document root and the images folder
125 "~ ^/(images/)?$" = {
126 return = "403";
127 };
128 };
129 };
130 };
131 })
132 ];
133}