1{ lib, pkgs, ... }:
2let
3 accessKey = "BKIKJAA5BMMU2RHO6IBB";
4 secretKey = "V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12";
5 rootCredentialsFile = pkgs.writeText "minio-credentials-full" ''
6 MINIO_ROOT_USER=${accessKey}
7 MINIO_ROOT_PASSWORD=${secretKey}
8 '';
9
10 certs = import ./snakeoil-certs.nix;
11 domain = certs.domain;
12in
13{
14 name = "ente";
15 meta.maintainers = [ lib.maintainers.oddlama ];
16
17 nodes.minio =
18 { ... }:
19 {
20 environment.systemPackages = [ pkgs.minio-client ];
21 services.minio = {
22 enable = true;
23 inherit rootCredentialsFile;
24 };
25
26 networking.firewall.allowedTCPPorts = [
27 9000
28 ];
29
30 systemd.services.minio.environment = {
31 MINIO_SERVER_URL = "https://s3.${domain}";
32 };
33 };
34
35 nodes.ente =
36 {
37 config,
38 nodes,
39 lib,
40 ...
41 }:
42 {
43 security.pki.certificateFiles = [ certs.ca.cert ];
44
45 networking.extraHosts = ''
46 ${config.networking.primaryIPAddress} accounts.${domain} albums.${domain} api.${domain} cast.${domain} photos.${domain} s3.${domain}
47 '';
48
49 networking.firewall.allowedTCPPorts = [
50 80
51 443
52 ];
53
54 services.nginx = {
55 recommendedProxySettings = true;
56 virtualHosts =
57 lib.genAttrs
58 [
59 "accounts.${domain}"
60 "albums.${domain}"
61 "api.${domain}"
62 "cast.${domain}"
63 "photos.${domain}"
64 ]
65 (_: {
66 sslCertificate = certs.${domain}.cert;
67 sslCertificateKey = certs.${domain}.key;
68 })
69 // {
70 "s3.${domain}" = {
71 forceSSL = true;
72 sslCertificate = certs.${domain}.cert;
73 sslCertificateKey = certs.${domain}.key;
74 locations."/".proxyPass = "http://${nodes.minio.networking.primaryIPAddress}:9000";
75 extraConfig = ''
76 client_max_body_size 32M;
77 proxy_buffering off;
78 proxy_request_buffering off;
79 '';
80 };
81 };
82 };
83
84 services.ente = {
85 web = {
86 enable = true;
87 domains = {
88 accounts = "accounts.${domain}";
89 albums = "albums.${domain}";
90 cast = "cast.${domain}";
91 photos = "photos.${domain}";
92 };
93 };
94 api = {
95 enable = true;
96 nginx.enable = true;
97 enableLocalDB = true;
98 domain = "api.${domain}";
99 settings = {
100 s3 = {
101 use_path_style_urls = true;
102 b2-eu-cen = {
103 endpoint = "https://s3.${domain}";
104 region = "us-east-1";
105 bucket = "ente";
106 key._secret = pkgs.writeText "accesskey" accessKey;
107 secret._secret = pkgs.writeText "secretkey" secretKey;
108 };
109 };
110 key = {
111 encryption._secret = pkgs.writeText "encryption" "T0sn+zUVFOApdX4jJL4op6BtqqAfyQLH95fu8ASWfno=";
112 hash._secret = pkgs.writeText "hash" "g/dBZBs1zi9SXQ0EKr4RCt1TGr7ZCKkgrpjyjrQEKovWPu5/ce8dYM6YvMIPL23MMZToVuuG+Z6SGxxTbxg5NQ==";
113 };
114 jwt.secret._secret = pkgs.writeText "jwt" "i2DecQmfGreG6q1vBj5tCokhlN41gcfS2cjOs9Po-u8=";
115 };
116 };
117 };
118 };
119
120 testScript = ''
121 minio.start()
122 minio.wait_for_unit("minio.service")
123 minio.wait_for_open_port(9000)
124
125 # Create a test bucket on the server
126 minio.succeed("mc alias set minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4")
127 minio.succeed("mc mb -p minio/ente")
128
129 # Start ente
130 ente.start()
131 ente.wait_for_unit("ente.service")
132 ente.wait_for_unit("nginx.service")
133
134 # Wait until api is up
135 ente.wait_until_succeeds("journalctl --since -2m --unit ente.service --grep 'We have lift-off.'", timeout=30)
136 # Wait until photos app is up
137 ente.wait_until_succeeds("curl -Ls https://photos.${domain}/ | grep -q 'Ente Photos'", timeout=30)
138 '';
139}