Merge pull request #197613 from shyim/add-coder

coder: fix web frontend building

authored by Domen Kožar and committed by GitHub 6a231a6e d95021fe

+298 -4
+1
nixos/modules/module-list.nix
··· 1129 ./services/web-apps/baget.nix 1130 ./services/web-apps/bookstack.nix 1131 ./services/web-apps/calibre-web.nix 1132 ./services/web-apps/changedetection-io.nix 1133 ./services/web-apps/cloudlog.nix 1134 ./services/web-apps/code-server.nix
··· 1129 ./services/web-apps/baget.nix 1130 ./services/web-apps/bookstack.nix 1131 ./services/web-apps/calibre-web.nix 1132 + ./services/web-apps/coder.nix 1133 ./services/web-apps/changedetection-io.nix 1134 ./services/web-apps/cloudlog.nix 1135 ./services/web-apps/code-server.nix
+217
nixos/modules/services/web-apps/coder.nix
···
··· 1 + { config, lib, options, pkgs, ... }: 2 + 3 + with lib; 4 + 5 + let 6 + cfg = config.services.coder; 7 + name = "coder"; 8 + in { 9 + options = { 10 + services.coder = { 11 + enable = mkEnableOption (lib.mdDoc "Coder service"); 12 + 13 + user = mkOption { 14 + type = types.str; 15 + default = "coder"; 16 + description = lib.mdDoc '' 17 + User under which the coder service runs. 18 + 19 + ::: {.note} 20 + If left as the default value this user will automatically be created 21 + on system activation, otherwise it needs to be configured manually. 22 + ::: 23 + ''; 24 + }; 25 + 26 + group = mkOption { 27 + type = types.str; 28 + default = "coder"; 29 + description = lib.mdDoc '' 30 + Group under which the coder service runs. 31 + 32 + ::: {.note} 33 + If left as the default value this group will automatically be created 34 + on system activation, otherwise it needs to be configured manually. 35 + ::: 36 + ''; 37 + }; 38 + 39 + package = mkOption { 40 + type = types.package; 41 + default = pkgs.coder; 42 + description = lib.mdDoc '' 43 + Package to use for the service. 44 + ''; 45 + defaultText = literalExpression "pkgs.coder"; 46 + }; 47 + 48 + homeDir = mkOption { 49 + type = types.str; 50 + description = lib.mdDoc '' 51 + Home directory for coder user. 52 + ''; 53 + default = "/var/lib/coder"; 54 + }; 55 + 56 + listenAddress = mkOption { 57 + type = types.str; 58 + description = lib.mdDoc '' 59 + Listen address. 60 + ''; 61 + default = "127.0.0.1:3000"; 62 + }; 63 + 64 + accessUrl = mkOption { 65 + type = types.nullOr types.str; 66 + description = lib.mdDoc '' 67 + Access URL should be a external IP address or domain with DNS records pointing to Coder. 68 + ''; 69 + default = null; 70 + example = "https://coder.example.com"; 71 + }; 72 + 73 + wildcardAccessUrl = mkOption { 74 + type = types.nullOr types.str; 75 + description = lib.mdDoc '' 76 + If you are providing TLS certificates directly to the Coder server, you must use a single certificate for the root and wildcard domains. 77 + ''; 78 + default = null; 79 + example = "*.coder.example.com"; 80 + }; 81 + 82 + database = { 83 + createLocally = mkOption { 84 + type = types.bool; 85 + default = true; 86 + description = lib.mdDoc '' 87 + Create the database and database user locally. 88 + ''; 89 + }; 90 + 91 + host = mkOption { 92 + type = types.str; 93 + default = "/run/postgresql"; 94 + description = lib.mdDoc '' 95 + Hostname hosting the database. 96 + ''; 97 + }; 98 + 99 + database = mkOption { 100 + type = types.str; 101 + default = "coder"; 102 + description = lib.mdDoc '' 103 + Name of database. 104 + ''; 105 + }; 106 + 107 + username = mkOption { 108 + type = types.str; 109 + default = "coder"; 110 + description = lib.mdDoc '' 111 + Username for accessing the database. 112 + ''; 113 + }; 114 + 115 + password = mkOption { 116 + type = types.nullOr types.str; 117 + default = null; 118 + description = lib.mdDoc '' 119 + Password for accessing the database. 120 + ''; 121 + }; 122 + 123 + sslmode = mkOption { 124 + type = types.nullOr types.str; 125 + default = "disable"; 126 + description = lib.mdDoc '' 127 + Password for accessing the database. 128 + ''; 129 + }; 130 + }; 131 + 132 + tlsCert = mkOption { 133 + type = types.nullOr types.path; 134 + description = lib.mdDoc '' 135 + The path to the TLS certificate. 136 + ''; 137 + default = null; 138 + }; 139 + 140 + tlsKey = mkOption { 141 + type = types.nullOr types.path; 142 + description = lib.mdDoc '' 143 + The path to the TLS key. 144 + ''; 145 + default = null; 146 + }; 147 + }; 148 + }; 149 + 150 + config = mkIf cfg.enable { 151 + assertions = [ 152 + { assertion = cfg.database.createLocally -> cfg.database.username == name; 153 + message = "services.coder.database.username must be set to ${user} if services.coder.database.createLocally is set true"; 154 + } 155 + ]; 156 + 157 + systemd.services.coder = { 158 + description = "Coder - Self-hosted developer workspaces on your infra"; 159 + after = [ "network.target" ]; 160 + wantedBy = [ "multi-user.target" ]; 161 + 162 + environment = { 163 + CODER_ACCESS_URL = cfg.accessUrl; 164 + CODER_WILDCARD_ACCESS_URL = cfg.wildcardAccessUrl; 165 + CODER_PG_CONNECTION_URL = "user=${cfg.database.username} ${optionalString (cfg.database.password != null) "password=${cfg.database.password}"} database=${cfg.database.database} host=${cfg.database.host} ${optionalString (cfg.database.sslmode != null) "sslmode=${cfg.database.sslmode}"}"; 166 + CODER_ADDRESS = cfg.listenAddress; 167 + CODER_TLS_ENABLE = optionalString (cfg.tlsCert != null) "1"; 168 + CODER_TLS_CERT_FILE = cfg.tlsCert; 169 + CODER_TLS_KEY_FILE = cfg.tlsKey; 170 + }; 171 + 172 + serviceConfig = { 173 + ProtectSystem = "full"; 174 + PrivateTmp = "yes"; 175 + PrivateDevices = "yes"; 176 + SecureBits = "keep-caps"; 177 + AmbientCapabilities = "CAP_IPC_LOCK CAP_NET_BIND_SERVICE"; 178 + CacheDirectory = "coder"; 179 + CapabilityBoundingSet = "CAP_SYSLOG CAP_IPC_LOCK CAP_NET_BIND_SERVICE"; 180 + KillSignal = "SIGINT"; 181 + KillMode = "mixed"; 182 + NoNewPrivileges = "yes"; 183 + Restart = "on-failure"; 184 + ExecStart = "${cfg.package}/bin/coder server"; 185 + User = cfg.user; 186 + Group = cfg.group; 187 + }; 188 + }; 189 + 190 + services.postgresql = lib.mkIf cfg.database.createLocally { 191 + enable = true; 192 + ensureDatabases = [ 193 + cfg.database.database 194 + ]; 195 + ensureUsers = [{ 196 + name = cfg.database.username; 197 + ensurePermissions = { 198 + "DATABASE \"${cfg.database.database}\"" = "ALL PRIVILEGES"; 199 + }; 200 + } 201 + ]; 202 + }; 203 + 204 + users.groups = optionalAttrs (cfg.group == name) { 205 + "${cfg.group}" = {}; 206 + }; 207 + users.users = optionalAttrs (cfg.user == name) { 208 + ${name} = { 209 + description = "Coder service user"; 210 + group = cfg.group; 211 + home = cfg.homeDir; 212 + createHome = true; 213 + isSystemUser = true; 214 + }; 215 + }; 216 + }; 217 + }
+1
nixos/tests/all-tests.nix
··· 137 cntr = handleTestOn ["aarch64-linux" "x86_64-linux"] ./cntr.nix {}; 138 cockpit = handleTest ./cockpit.nix {}; 139 cockroachdb = handleTestOn ["x86_64-linux"] ./cockroachdb.nix {}; 140 collectd = handleTest ./collectd.nix {}; 141 connman = handleTest ./connman.nix {}; 142 consul = handleTest ./consul.nix {};
··· 137 cntr = handleTestOn ["aarch64-linux" "x86_64-linux"] ./cntr.nix {}; 138 cockpit = handleTest ./cockpit.nix {}; 139 cockroachdb = handleTestOn ["x86_64-linux"] ./cockroachdb.nix {}; 140 + coder = handleTest ./coder.nix {}; 141 collectd = handleTest ./collectd.nix {}; 142 connman = handleTest ./connman.nix {}; 143 consul = handleTest ./consul.nix {};
+24
nixos/tests/coder.nix
···
··· 1 + import ./make-test-python.nix ({ pkgs, ... }: { 2 + name = "coder"; 3 + meta = with pkgs.lib.maintainers; { 4 + maintainers = [ shyim ghuntley ]; 5 + }; 6 + 7 + nodes.machine = 8 + { pkgs, ... }: 9 + { 10 + services.coder = { 11 + enable = true; 12 + accessUrl = "http://localhost:3000"; 13 + }; 14 + }; 15 + 16 + testScript = '' 17 + machine.start() 18 + machine.wait_for_unit("postgresql.service") 19 + machine.wait_for_unit("coder.service") 20 + machine.wait_for_open_port(3000) 21 + 22 + machine.succeed("curl --fail http://localhost:3000") 23 + ''; 24 + })
+55 -4
pkgs/development/tools/coder/default.nix
··· 1 - { buildGoModule 2 , fetchFromGitHub 3 , installShellFiles 4 - , lib 5 }: 6 buildGoModule rec { 7 pname = "coder"; 8 version = "0.17.1"; ··· 14 hash = "sha256-FHBaefwSGZXwn1jdU7zK8WhwjarknvyeUJTlhmk/hPM="; 15 }; 16 17 # integration tests require network access 18 doCheck = false; 19 20 - vendorHash = "sha256-+AvmJkZCFovE2+5Lg98tUvA7f2kBHUMzhl5IyrEGuy8="; 21 22 - nativeBuildInputs = [ installShellFiles ]; 23 24 postInstall = '' 25 installShellCompletion --cmd coder \ 26 --bash <($out/bin/coder completion bash) \ 27 --fish <($out/bin/coder completion fish) \ 28 --zsh <($out/bin/coder completion zsh) 29 ''; 30 31 meta = with lib; {
··· 1 + { lib 2 , fetchFromGitHub 3 , installShellFiles 4 + , makeWrapper 5 + , buildGoModule 6 + , fetchYarnDeps 7 + , fixup_yarn_lock 8 + , pkg-config 9 + , nodejs 10 + , yarn 11 + , nodePackages 12 + , python3 13 + , terraform 14 }: 15 + 16 buildGoModule rec { 17 pname = "coder"; 18 version = "0.17.1"; ··· 24 hash = "sha256-FHBaefwSGZXwn1jdU7zK8WhwjarknvyeUJTlhmk/hPM="; 25 }; 26 27 + offlineCache = fetchYarnDeps { 28 + yarnLock = src + "/site/yarn.lock"; 29 + hash = "sha256-4GbM7GNZ3wHIZJIJuHw1v/SwjUNc1vi8IHRGaGwPGZQ="; 30 + }; 31 + 32 + subPackages = [ "cmd/..." ]; 33 + 34 + vendorHash = "sha256-+AvmJkZCFovE2+5Lg98tUvA7f2kBHUMzhl5IyrEGuy8="; 35 + 36 # integration tests require network access 37 doCheck = false; 38 39 + ldflags = [ 40 + "-s" 41 + "-w" 42 + "-X github.com/coder/coder/buildinfo.tag=${version}" 43 + ]; 44 + 45 + preBuild = '' 46 + export HOME=$TEMPDIR 47 + 48 + pushd site 49 + yarn config --offline set yarn-offline-mirror ${offlineCache} 50 + fixup_yarn_lock yarn.lock 51 + 52 + # node-gyp tries to download always the headers and fails: https://github.com/NixOS/nixpkgs/issues/195404 53 + yarn remove --offline jest-canvas-mock canvas 54 + 55 + NODE_ENV=production node node_modules/.bin/vite build 56 + 57 + popd 58 + ''; 59 + 60 + tags = [ "embed" ]; 61 62 + nativeBuildInputs = [ 63 + fixup_yarn_lock 64 + installShellFiles 65 + makeWrapper 66 + nodePackages.node-pre-gyp 67 + nodejs 68 + pkg-config 69 + python3 70 + yarn 71 + ]; 72 73 postInstall = '' 74 installShellCompletion --cmd coder \ 75 --bash <($out/bin/coder completion bash) \ 76 --fish <($out/bin/coder completion fish) \ 77 --zsh <($out/bin/coder completion zsh) 78 + 79 + wrapProgram $out/bin/coder --prefix PATH : ${lib.makeBinPath [ terraform ]} 80 ''; 81 82 meta = with lib; {