This repository has no description
3.1 kB
114 lines
1let
2 domain = "book.lassul.us";
3 port = 8772;
4in
5{
6 config,
7 lib,
8 pkgs,
9 self,
10 ...
11}:
12let
13 settings = {
14 listen = "127.0.0.1:${toString port}";
15 baseUrl = "https://${domain}";
16 owner = "lassulus";
17 intro = "Pick a time for a call: nix, nixos, infrastructure, or anything else.";
18 timezone = "Europe/Berlin";
19 eventTypes = [
20 {
21 slug = "30min";
22 title = "30 minute call";
23 minutes = 30;
24 }
25 {
26 slug = "60min";
27 title = "1 hour call";
28 minutes = 60;
29 }
30 ];
31 hours = lib.genAttrs [ "mon" "tue" "wed" "thu" "fri" ] (_: [ "10:00-18:00" ]);
32 slotStep = 30;
33 bufferMinutes = 15;
34 minNoticeHours = 24;
35 horizonDays = 28;
36 # lass/calendar is the only calendar (configs/radicale.nix): free/busy is
37 # read from it, and requests and bookings are mirrored into it, next to
38 # lass's own events and whatever Hermes adds.
39 caldav = {
40 url = "http://127.0.0.1:5232";
41 user = "lass";
42 calendar = "calendar";
43 };
44 # Local postfix (configs/mailserver.nix) accepts from localhost and DKIM-signs.
45 smtp = {
46 host = "127.0.0.1";
47 port = 25;
48 from = "book@lassul.us";
49 notify = "lass@lassul.us";
50 };
51 database = "/var/lib/book/book.db";
52 };
53in
54{
55 # book: request-and-approve booking page (tools/book). Requests land in
56 # radicale (configs/radicale.nix) as TENTATIVE events and in lass's inbox
57 # with an approve link.
58 systemd.services.book = {
59 description = "book.lassul.us booking page";
60 wantedBy = [ "multi-user.target" ];
61 wants = [ "radicale.service" ];
62 after = [
63 "network.target"
64 "radicale.service"
65 ];
66 serviceConfig = {
67 ExecStart = lib.escapeShellArgs [
68 (lib.getExe self.packages.${pkgs.stdenv.hostPlatform.system}.book)
69 "--config"
70 (pkgs.writeText "book.json" (builtins.toJSON settings))
71 "--caldav-password-file"
72 "%d/caldav-password"
73 ];
74 LoadCredential = "caldav-password:${
75 config.clan.core.vars.generators.radicale-lass.files."password".path
76 }";
77 DynamicUser = true;
78 StateDirectory = "book";
79 Restart = "on-failure";
80 CapabilityBoundingSet = "";
81 NoNewPrivileges = true;
82 PrivateDevices = true;
83 PrivateTmp = true;
84 ProtectHome = true;
85 ProtectSystem = "strict";
86 ProtectKernelTunables = true;
87 ProtectKernelModules = true;
88 ProtectControlGroups = true;
89 RestrictAddressFamilies = [
90 "AF_INET"
91 "AF_INET6"
92 "AF_UNIX"
93 ];
94 RestrictNamespaces = true;
95 LockPersonality = true;
96 SystemCallArchitectures = "native";
97 };
98 };
99
100 services.nginx.virtualHosts.${domain} = {
101 enableACME = true;
102 forceSSL = true;
103 locations."/" = {
104 proxyPass = "http://127.0.0.1:${toString port}";
105 # book rate-limits per X-Real-IP; set it from the socket, never from
106 # a client-supplied header.
107 extraConfig = ''
108 proxy_set_header Host $host;
109 proxy_set_header X-Real-IP $remote_addr;
110 client_max_body_size 16k;
111 '';
112 };
113 };
114}