This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / configs / timeful.nix
3.9 kB 123 lines
1{ 2 config, 3 lib, 4 pkgs, 5 self, 6 ... 7}: 8let 9 domain = "when.lassul.us"; 10 port = 3002; 11 timeful = self.packages.${pkgs.system}.timeful; 12in 13{ 14 # timeful (formerly schej): crab.fit/when2meet-style availability polls. 15 # Creating a poll and painting availability work without an account; 16 # signing in (GitHub OAuth, see pkgs/timeful/self-host.patch) keeps a 17 # dashboard of your polls. 18 services.mongodb = { 19 enable = true; 20 # prebuilt binary; the default `mongodb` builds from source for hours 21 package = pkgs.mongodb-ce; 22 }; 23 24 lass.backup.state.timeful.preBackup = '' 25 ${pkgs.mongodb-tools}/bin/mongodump --uri=mongodb://127.0.0.1:27017 \ 26 --db=schej-it --gzip --archive=/var/backup/timeful.archive.gz 27 ''; 28 29 clan.core.vars.generators.timeful = { 30 files.env = { }; 31 runtimeInputs = [ pkgs.openssl ]; 32 # ENCRYPTION_KEY is fed raw to aes.NewCipher, so it must be exactly 33 # 16/24/32 bytes (upstream's `openssl rand -base64 32` hint is 44 bytes). 34 script = '' 35 { 36 echo "SESSION_SECRET=$(openssl rand -hex 32)" 37 echo "ENCRYPTION_KEY=$(openssl rand -hex 16)" 38 } > $out/env 39 ''; 40 }; 41 42 # GitHub OAuth app (https://github.com/settings/developers), callback URL 43 # https://when.lassul.us/api/auth/github/callback 44 clan.core.vars.generators.timeful-github = { 45 files.env = { }; 46 prompts.client_id = { 47 description = "GitHub OAuth app client ID for ${domain}"; 48 persist = true; 49 }; 50 prompts.client_secret = { 51 description = "GitHub OAuth app client secret for ${domain}"; 52 type = "hidden"; 53 persist = true; 54 }; 55 script = '' 56 printf 'GITHUB_CLIENT_ID=%s\nGITHUB_CLIENT_SECRET=%s\n' \ 57 "$(cat "$prompts"/client_id)" "$(cat "$prompts"/client_secret)" > "$out/env" 58 ''; 59 }; 60 61 systemd.services.timeful = { 62 description = "timeful availability polls"; 63 wantedBy = [ "multi-user.target" ]; 64 requires = [ "mongodb.service" ]; 65 after = [ 66 "network.target" 67 "mongodb.service" 68 ]; 69 environment = { 70 LISTEN_ADDR = "127.0.0.1:${toString port}"; 71 MONGODB_URI = "mongodb://127.0.0.1:27017"; 72 CORS_ORIGINS = "https://${domain}"; 73 # no listmonk mailing list; skip its HTTP calls on sign-up 74 LISTMONK_ENABLED = "false"; 75 }; 76 serviceConfig = { 77 ExecStart = "${lib.getExe timeful} -release"; 78 # The server unconditionally appends everything it prints to 79 # ./logs.log, which would grow forever; the journal already has it. 80 ExecStartPre = "${pkgs.coreutils}/bin/ln -sfn /dev/null logs.log"; 81 EnvironmentFile = [ 82 config.clan.core.vars.generators.timeful.files.env.path 83 config.clan.core.vars.generators.timeful-github.files.env.path 84 ]; 85 DynamicUser = true; 86 StateDirectory = "timeful"; 87 WorkingDirectory = "/var/lib/timeful"; 88 Restart = "on-failure"; 89 CapabilityBoundingSet = ""; 90 NoNewPrivileges = true; 91 PrivateDevices = true; 92 ProtectHome = true; 93 ProtectKernelTunables = true; 94 ProtectKernelModules = true; 95 ProtectControlGroups = true; 96 RestrictAddressFamilies = [ 97 "AF_INET" 98 "AF_INET6" 99 "AF_UNIX" 100 ]; 101 RestrictNamespaces = true; 102 LockPersonality = true; 103 SystemCallArchitectures = "native"; 104 }; 105 }; 106 107 services.nginx.virtualHosts.${domain} = { 108 enableACME = true; 109 forceSSL = true; 110 locations."/" = { 111 proxyPass = "http://127.0.0.1:${toString port}"; 112 # gin trusts every proxy and takes the leftmost X-Forwarded-For entry 113 # for its per-IP rate limiter, so overwrite instead of appending 114 # (recommendedProxySettings appends a client-controlled value). 115 extraConfig = '' 116 proxy_set_header Host $host; 117 proxy_set_header X-Real-IP $remote_addr; 118 proxy_set_header X-Forwarded-For $remote_addr; 119 proxy_set_header X-Forwarded-Proto $scheme; 120 ''; 121 }; 122 }; 123}