forked from
lass.pds.lassul.us/superconfig
This repository has no description
4.1 kB
139 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. Book reads its events back:
39 # deleting, moving or confirming one there manages the booking.
40 caldav = {
41 url = "http://127.0.0.1:5232";
42 user = "lass";
43 calendar = "calendar";
44 };
45 # Local postfix (configs/mailserver.nix) accepts from localhost and DKIM-signs.
46 smtp = {
47 host = "127.0.0.1";
48 port = 25;
49 from = "book@lassul.us";
50 notify = "lass@lassul.us";
51 };
52 database = "/var/lib/book/book.db";
53 };
54in
55{
56 # book: request-and-approve booking page (tools/book). Requests land in
57 # radicale (configs/radicale.nix) as TENTATIVE events and in lass's inbox
58 # with an approve link.
59 systemd.services.book = {
60 description = "book.lassul.us booking page";
61 wantedBy = [ "multi-user.target" ];
62 wants = [ "radicale.service" ];
63 after = [
64 "network.target"
65 "radicale.service"
66 ];
67 serviceConfig = {
68 ExecStart = lib.escapeShellArgs [
69 (lib.getExe self.packages.${pkgs.stdenv.hostPlatform.system}.book)
70 "--config"
71 (pkgs.writeText "book.json" (builtins.toJSON settings))
72 "--caldav-password-file"
73 "%d/caldav-password"
74 "--busy-token-file"
75 "%d/busy-token"
76 ];
77 LoadCredential = [
78 "caldav-password:${config.clan.core.vars.generators.radicale-lass.files."password".path}"
79 "busy-token:${config.clan.core.vars.generators.busy-feed.files."token".path}"
80 ];
81 DynamicUser = true;
82 StateDirectory = "book";
83 Restart = "on-failure";
84 CapabilityBoundingSet = "";
85 NoNewPrivileges = true;
86 PrivateDevices = true;
87 PrivateTmp = true;
88 ProtectHome = true;
89 ProtectSystem = "strict";
90 ProtectKernelTunables = true;
91 ProtectKernelModules = true;
92 ProtectControlGroups = true;
93 RestrictAddressFamilies = [
94 "AF_INET"
95 "AF_INET6"
96 "AF_UNIX"
97 ];
98 RestrictNamespaces = true;
99 LockPersonality = true;
100 SystemCallArchitectures = "native";
101 };
102 };
103
104 # Secret of the busy-only feed https://cal.lassul.us/busy/<token>.ics, for
105 # the availability polls on when.lassul.us (configs/timeful.nix).
106 clan.core.vars.generators.busy-feed = {
107 files."token" = { };
108 runtimeInputs = [ pkgs.coreutils ];
109 script = ''
110 head -c 24 /dev/urandom | basenc --base64url | tr -d '\n' > "$out/token"
111 '';
112 };
113
114 # book answers 404 for every /busy/ path but the one with the token.
115 services.nginx.virtualHosts."cal.lassul.us".locations."/busy/" = {
116 proxyPass = "http://127.0.0.1:${toString port}";
117 extraConfig = ''
118 proxy_set_header Host $host;
119 proxy_set_header X-Real-IP $remote_addr;
120 '';
121 };
122
123 services.nginx.virtualHosts.${domain} = {
124 enableACME = true;
125 forceSSL = true;
126 locations."/" = {
127 proxyPass = "http://127.0.0.1:${toString port}";
128 # book rate-limits per X-Real-IP; set it from the socket, never from
129 # a client-supplied header.
130 extraConfig = ''
131 proxy_set_header Host $host;
132 proxy_set_header X-Real-IP $remote_addr;
133 client_max_body_size 16k;
134 '';
135 };
136 # The busy feed is served on cal.lassul.us only.
137 locations."/busy/".return = "404";
138 };
139}