grace/dots

dotfiles/nix configs

git clone https://git.gae.moe/grace/dots

Grace Yoderwafrn testing44ae0ad

wafrn-testing
5.4 KiB289 linesraw
1{
2  config,
3  pkgs,
4  lib,
5  ...
6}:
7
8let
9  domain = "wafrn.gae.moe";
10  mediaDomain = "media.wafrn.gae.moe";
11  cacheDomain = "cache.wafrn.gae.moe";
12
13  pdsDomain = "pds.gae.moe";
14
15  wafrnDir = "/mnt/ext/wafrn";
16  secretsFile = "/etc/secrets/wafrn";
17
18  wafrnPort = 8123;
19
20  wafrnEnvironment = {
21    COMPOSE_PROJECT_NAME = "wafrn";
22    COMPOSE_PROFILES = "bluesky";
23
24    DOMAIN_NAME = domain;
25    MEDIA_DOMAIN = mediaDomain;
26    CACHE_DOMAIN = cacheDomain;
27
28    FRONTEND_MEDIA_URL = "https://${mediaDomain}";
29    FRONTEND_CACHE_URL =
30      "https://${cacheDomain}/api/cache?media=";
31
32    ADMIN_USER = "admin";
33    ADMIN_EMAIL = "admin@example.com";
34
35    POSTGRES_USER = "wafrn";
36    POSTGRES_DBNAME = "wafrn";
37
38    POSTGRES_METRICS_USER = "wafrn_metrics";
39    POSTGRES_METRICS_DBNAME = "wafrn_metrics";
40
41    ENABLE_BSKY = "true";
42
43    PDS_DOMAIN_NAME = pdsDomain;
44    PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX = "unused-external-pds";
45
46    USE_WORKERS = "true";
47    REVIEW_REGISTRATIONS = "true";
48
49    UPLOAD_LIMIT = "52428800";
50    LOG_LEVEL = "info";
51
52    ACME_EMAIL = "invalid@example.com";
53
54    DISABLE_REQUIRE_SEND_EMAIL = "true";
55
56    SMTP_HOST = "";
57    SMTP_USER = "";
58    SMTP_PORT = "587";
59    SMTP_FROM = "";
60
61    WEBPUSH_EMAIL = "mailto:admin@example.com";
62  };
63
64  publicEnv = pkgs.writeText "wafrn-public.env" (
65    lib.concatStringsSep "\n" (
66      lib.mapAttrsToList
67        (name: value: "${name}=${value}")
68        wafrnEnvironment
69    )
70    + "\n"
71  );
72
73  internalCaddyfile = pkgs.writeText "wafrn-Caddyfile" ''
74    {
75      admin 0.0.0.0:2019
76      auto_https off
77    }
78
79    http://${mediaDomain} {
80      root * /var/www/html/uploads/
81      file_server
82    }
83
84    http://${cacheDomain} {
85      reverse_proxy backend:9000
86    }
87
88    http://${domain} {
89      @websocket path /api/websocket/*
90
91      handle @websocket {
92        reverse_proxy websocket:9000
93      }
94
95      @backend path \
96        /api* \
97        /fediverse* \
98        /contexts* \
99        /post* \
100        /blog* \
101        /.well-known*
102
103      handle @backend {
104        reverse_proxy backend:9000
105      }
106
107      handle {
108        root * /var/www/html/frontend/
109        try_files {path} /index.html
110        file_server
111      }
112    }
113    '';
114
115  composeOverride = pkgs.writeText "wafrn-nixos.yml" ''
116    services:
117      frontend:
118        ports: !override
119          - "127.0.0.1:${toString wafrnPort}:80"
120        volumes:
121          - "${internalCaddyfile}:/etc/caddy-nixos/Caddyfile:ro"
122        command:
123          - caddy
124          - run
125          - --config
126          - /etc/caddy-nixos/Caddyfile
127          - --adapter
128          - caddyfile
129
130      backend:
131        deploy:
132          replicas: 1
133
134      workers:
135        profiles: !override
136          - separate-workers
137
138      adminer:
139        profiles: !override
140          - tools
141
142      bullboard:
143        profiles: !override
144          - tools
145
146      pds:
147        profiles: !override
148          - local-pds
149  '';
150
151  docker = "${config.virtualisation.docker.package}/bin/docker";
152
153  stopWafrn = pkgs.writeShellScript "wafrn-stop" ''
154    cd ${wafrnDir}
155
156    exec ${docker} compose \
157      -f docker-compose.default.yml \
158      -f ${composeOverride} \
159      down
160  '';
161in
162{
163  virtualisation.docker = {
164    enable = true;
165
166    daemon.settings = {
167      "data-root" = "/mnt/ext/docker";
168
169      features = {
170        buildkit = true;
171      };
172    };
173  };
174
175  systemd.tmpfiles.rules = [
176    "d /mnt/ext/docker 0710 root root - -"
177    "d ${wafrnDir} 0750 root root - -"
178  ];
179
180  systemd.services.docker.unitConfig.RequiresMountsFor = [
181    "/mnt/ext/docker"
182  ];
183
184  environment.systemPackages = with pkgs; [
185    git
186  ];
187
188  services.caddy = {
189    enable = true;
190
191    virtualHosts = {
192      "${domain}".extraConfig = ''
193        reverse_proxy 127.0.0.1:${toString wafrnPort}
194      '';
195
196      "${mediaDomain}".extraConfig = ''
197        reverse_proxy 127.0.0.1:${toString wafrnPort}
198      '';
199
200      "${cacheDomain}".extraConfig = ''
201        reverse_proxy 127.0.0.1:${toString wafrnPort}
202      '';
203    };
204  };
205
206  systemd.services.wafrn = {
207    description = "Wafrn";
208
209    wantedBy = [
210      "multi-user.target"
211    ];
212
213    wants = [
214      "network-online.target"
215    ];
216
217    after = [
218      "network-online.target"
219      "docker.service"
220      "caddy.service"
221    ];
222
223    requires = [
224      "docker.service"
225    ];
226
227    unitConfig.RequiresMountsFor = [
228      wafrnDir
229    ];
230
231    path = with pkgs; [
232      git
233      coreutils
234      bash
235    ];
236
237    environment = wafrnEnvironment // {
238      DOCKER_BUILDKIT = "1";
239      COMPOSE_BAKE = "true";
240    };
241
242    preStart = ''
243      if [ ! -d .git ]; then
244        ${pkgs.git}/bin/git clone \
245          --branch main \
246          --single-branch \
247          https://codeberg.org/wafrn/wafrn.git \
248          .
249      fi
250
251      cat \
252        ${publicEnv} \
253        ${secretsFile} \
254        > /run/wafrn/.env
255
256      chmod 600 /run/wafrn/.env
257
258      ln -sfn \
259        /run/wafrn/.env \
260        ${wafrnDir}/.env
261    '';
262
263    script = ''
264      exec ${docker} compose \
265        -f docker-compose.default.yml \
266        -f ${composeOverride} \
267        up \
268        --build \
269        --detach \
270        --remove-orphans
271    '';
272
273    serviceConfig = {
274      Type = "oneshot";
275      RemainAfterExit = true;
276
277      WorkingDirectory = wafrnDir;
278      EnvironmentFile = secretsFile;
279
280      RuntimeDirectory = "wafrn";
281      RuntimeDirectoryMode = "0700";
282
283      ExecStop = stopWafrn;
284
285      TimeoutStartSec = 0;
286      TimeoutStopSec = 120;
287    };
288  };
289}