lol

nixos/coder: init module

+298 -82
+1
nixos/modules/module-list.nix
··· 1120 1120 ./services/web-apps/baget.nix 1121 1121 ./services/web-apps/bookstack.nix 1122 1122 ./services/web-apps/calibre-web.nix 1123 + ./services/web-apps/coder.nix 1123 1124 ./services/web-apps/changedetection-io.nix 1124 1125 ./services/web-apps/cloudlog.nix 1125 1126 ./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
··· 135 135 cloudlog = handleTest ./cloudlog.nix {}; 136 136 cntr = handleTestOn ["aarch64-linux" "x86_64-linux"] ./cntr.nix {}; 137 137 cockroachdb = handleTestOn ["x86_64-linux"] ./cockroachdb.nix {}; 138 + coder = handleTest ./coder.nix {}; 138 139 collectd = handleTest ./collectd.nix {}; 139 140 connman = handleTest ./connman.nix {}; 140 141 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 + })
-76
pkgs/applications/misc/coder/default.nix
··· 1 - { lib, pkgs, fetchFromGitHub, installShellFiles, buildGoModule, fetchYarnDeps }: 2 - 3 - let 4 - pname = "coder"; 5 - version = "0.10.2"; 6 - 7 - src = fetchFromGitHub { 8 - owner = "coder"; 9 - repo = "coder"; 10 - rev = "v${version}"; 11 - sha256 = "sha256-h5bN75agNocRAjShbufRCJr45huYJOzCBd4OcGpF4C4="; 12 - }; 13 - 14 - offlineCache = fetchYarnDeps { 15 - yarnLock = src + "/site/yarn.lock"; 16 - sha256 = "sha256-uDNPRQTpsgxyC5ks+2Qq/wiKjkbjWwSO+cJc5X6qmAA="; 17 - }; 18 - 19 - yarn16 = pkgs.yarn.override { nodejs = pkgs.nodejs-16_x; }; 20 - nodePackages16 = pkgs.nodePackages.override { nodejs = pkgs.nodejs-16_x; }; 21 - in 22 - buildGoModule rec { 23 - inherit pname version src; 24 - 25 - subPackages = [ "cmd/coder" ]; 26 - 27 - vendorSha256 = "sha256-+3Zy0zArCXkvD4ogfKdu9W9gJXveAhwFXKG1VRDvOkI="; 28 - 29 - # Flags as provided by the build automation of the project: 30 - # https://github.com/coder/coder/blob/075e891f287b27cdb481a48e129f20a1e6a7de12/scripts/build_go.sh#L89 31 - ldflags = [ 32 - "-s" 33 - "-w" 34 - "-X github.com/coder/coder/buildinfo.tag=${version}" 35 - ]; 36 - 37 - preBuild = '' 38 - export HOME=$(mktemp -d) 39 - mkdir -p $HOME 40 - 41 - cd site 42 - yarn config --offline set yarn-offline-mirror ${offlineCache} 43 - fixup_yarn_lock yarn.lock 44 - 45 - # node-gyp tries to download always the headers and fails: https://github.com/NixOS/nixpkgs/issues/195404 46 - yarn remove --offline jest-canvas-mock canvas 47 - 48 - NODE_ENV=production node node_modules/.bin/vite build 49 - cd .. 50 - ''; 51 - 52 - tags = [ "embed" ]; 53 - 54 - nativeBuildInputs = with pkgs; [ 55 - fixup_yarn_lock 56 - nodejs-16_x 57 - yarn16 58 - nodePackages16.node-pre-gyp 59 - python3 60 - pkg-config 61 - installShellFiles 62 - ]; 63 - 64 - postInstall = '' 65 - installShellCompletion --cmd coder \ 66 - --bash <($out/bin/coder completion bash) \ 67 - --zsh <($out/bin/coder completion zsh) 68 - ''; 69 - 70 - meta = with lib; { 71 - description = "Software development on any infrastructure"; 72 - license = licenses.agpl3Only; 73 - homepage = "https://coder.com/"; 74 - maintainers = with maintainers; [ shyim ]; 75 - }; 76 - }
+55 -4
pkgs/development/tools/coder/default.nix
··· 1 - { buildGoModule 1 + { lib 2 2 , fetchFromGitHub 3 3 , installShellFiles 4 - , lib 4 + , makeWrapper 5 + , buildGoModule 6 + , fetchYarnDeps 7 + , fixup_yarn_lock 8 + , pkg-config 9 + , nodejs 10 + , yarn 11 + , nodePackages 12 + , python3 13 + , terraform 5 14 }: 15 + 6 16 buildGoModule rec { 7 17 pname = "coder"; 8 18 version = "0.16.0"; ··· 14 24 hash = "sha256-3rGpyJzGkZYUEvKKDzj2I5sqrUImmmX7cXWM9UClPLY="; 15 25 }; 16 26 27 + offlineCache = fetchYarnDeps { 28 + yarnLock = src + "/site/yarn.lock"; 29 + hash = "sha256-4GbM7GNZ3wHIZJIJuHw1v/SwjUNc1vi8IHRGaGwPGZQ="; 30 + }; 31 + 32 + subPackages = [ "cmd/..." ]; 33 + 34 + vendorHash = "sha256-bb9jBno7elO6qKGjacpX3rxgrpJpGpTxMQtdBYjBzMk="; 35 + 17 36 # integration tests require network access 18 37 doCheck = false; 19 38 20 - vendorHash = "sha256-bb9jBno7elO6qKGjacpX3rxgrpJpGpTxMQtdBYjBzMk="; 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" ]; 21 61 22 - nativeBuildInputs = [ installShellFiles ]; 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 + ]; 23 72 24 73 postInstall = '' 25 74 installShellCompletion --cmd coder \ 26 75 --bash <($out/bin/coder completion bash) \ 27 76 --fish <($out/bin/coder completion fish) \ 28 77 --zsh <($out/bin/coder completion zsh) 78 + 79 + wrapProgram $out/bin/coder --prefix PATH : ${lib.makeBinPath [ terraform ]} 29 80 ''; 30 81 31 82 meta = with lib; {
-2
pkgs/top-level/all-packages.nix
··· 4174 4174 electron = electron_11; 4175 4175 }; 4176 4176 4177 - coder = callPackage ../applications/misc/coder {}; 4178 - 4179 4177 contrast = callPackage ../applications/accessibility/contrast { }; 4180 4178 4181 4179 cplex = callPackage ../applications/science/math/cplex (config.cplex or {});