Kieran's opinionated (and probably slightly dumb) nix config
at main 3.7 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.atelier.services.emojibot; 9in 10{ 11 options.atelier.services.emojibot = { 12 enable = lib.mkEnableOption "Emojibot Slack emoji management service"; 13 14 domain = lib.mkOption { 15 type = lib.types.str; 16 description = "Domain to serve emojibot on"; 17 }; 18 19 port = lib.mkOption { 20 type = lib.types.port; 21 default = 3002; 22 description = "Port to run emojibot on"; 23 }; 24 25 dataDir = lib.mkOption { 26 type = lib.types.path; 27 default = "/var/lib/emojibot"; 28 description = "Directory to store emojibot data"; 29 }; 30 31 secretsFile = lib.mkOption { 32 type = lib.types.path; 33 description = '' 34 Path to secrets file containing: 35 - SLACK_SIGNING_SECRET 36 - SLACK_BOT_TOKEN 37 - SLACK_APP_TOKEN 38 - SLACK_BOT_USER_TOKEN (get from browser, see emojibot README) 39 - SLACK_COOKIE (get from browser, see emojibot README) 40 - SLACK_WORKSPACE (e.g. "myworkspace" for myworkspace.slack.com) 41 - SLACK_CHANNEL (channel ID where emojis are posted) 42 - ADMINS (comma-separated list of slack user IDs) 43 ''; 44 }; 45 46 repository = lib.mkOption { 47 type = lib.types.str; 48 default = "https://github.com/taciturnaxolotl/emojibot.git"; 49 description = "Git repository URL (optional, for auto-deployment)"; 50 }; 51 52 autoUpdate = lib.mkEnableOption "Automatically git pull on service restart"; 53 }; 54 55 config = lib.mkIf cfg.enable { 56 users.groups.services = { }; 57 58 users.users.emojibot = { 59 isSystemUser = true; 60 group = "emojibot"; 61 extraGroups = [ "services" ]; 62 home = cfg.dataDir; 63 createHome = true; 64 shell = pkgs.bash; 65 }; 66 67 users.groups.emojibot = { }; 68 69 security.sudo.extraRules = [ 70 { 71 users = [ "emojibot" ]; 72 commands = [ 73 { 74 command = "/run/current-system/sw/bin/systemctl restart emojibot.service"; 75 options = [ "NOPASSWD" ]; 76 } 77 ]; 78 } 79 ]; 80 81 systemd.services.emojibot = { 82 description = "Emojibot Slack emoji management service"; 83 wantedBy = [ "multi-user.target" ]; 84 after = [ "network.target" ]; 85 path = [ pkgs.git ]; 86 87 preStart = '' 88 if [ ! -d ${cfg.dataDir}/app/.git ]; then 89 ${pkgs.git}/bin/git clone ${cfg.repository} ${cfg.dataDir}/app 90 fi 91 92 cd ${cfg.dataDir}/app 93 '' + lib.optionalString cfg.autoUpdate '' 94 ${pkgs.git}/bin/git pull 95 '' + '' 96 97 if [ ! -f src/index.ts ]; then 98 echo "No code found at ${cfg.dataDir}/app/src/index.ts" 99 exit 1 100 fi 101 102 echo "Installing dependencies..." 103 ${pkgs.unstable.bun}/bin/bun install 104 ''; 105 106 serviceConfig = { 107 Type = "simple"; 108 User = "emojibot"; 109 Group = "emojibot"; 110 EnvironmentFile = cfg.secretsFile; 111 Environment = [ 112 "NODE_ENV=production" 113 "PORT=${toString cfg.port}" 114 ]; 115 ExecStart = "${pkgs.bash}/bin/bash -c 'cd ${cfg.dataDir}/app && ${pkgs.unstable.bun}/bin/bun run src/index.ts'"; 116 Restart = "always"; 117 RestartSec = "10s"; 118 }; 119 120 serviceConfig.ExecStartPre = [ 121 "+${pkgs.writeShellScript "emojibot-setup" '' 122 mkdir -p ${cfg.dataDir}/app 123 chown -R emojibot:services ${cfg.dataDir} 124 chmod -R g+rwX ${cfg.dataDir} 125 ''}" 126 ]; 127 }; 128 129 services.caddy.virtualHosts.${cfg.domain} = { 130 extraConfig = '' 131 tls { 132 dns cloudflare {env.CLOUDFLARE_API_TOKEN} 133 } 134 135 reverse_proxy localhost:${toString cfg.port} 136 ''; 137 }; 138 }; 139}