1 { config, lib, options, pkgs, ... }:
6 cfg = config.services.coder;
11 enable = mkEnableOption "Coder service";
17 User under which the coder service runs.
20 If left as the default value this user will automatically be created
21 on system activation, otherwise it needs to be configured manually.
30 Group under which the coder service runs.
33 If left as the default value this group will automatically be created
34 on system activation, otherwise it needs to be configured manually.
39 package = mkPackageOption pkgs "coder" { };
44 Home directory for coder user.
46 default = "/var/lib/coder";
49 listenAddress = mkOption {
54 default = "127.0.0.1:3000";
57 accessUrl = mkOption {
58 type = types.nullOr types.str;
60 Access URL should be a external IP address or domain with DNS records pointing to Coder.
63 example = "https://coder.example.com";
66 wildcardAccessUrl = mkOption {
67 type = types.nullOr types.str;
69 If you are providing TLS certificates directly to the Coder server, you must use a single certificate for the root and wildcard domains.
72 example = "*.coder.example.com";
78 description = "Extra environment variables to pass run Coder's server with. See Coder documentation.";
81 CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS = true;
82 CODER_OAUTH2_GITHUB_ALLOWED_ORGS = "your-org";
86 type = types.nullOr types.path;
87 description = "Systemd environment file to add to Coder.";
93 createLocally = mkOption {
97 Create the database and database user locally.
103 default = "/run/postgresql";
105 Hostname hosting the database.
109 database = mkOption {
117 username = mkOption {
121 Username for accessing the database.
125 password = mkOption {
126 type = types.nullOr types.str;
129 Password for accessing the database.
134 type = types.nullOr types.str;
137 Password for accessing the database.
143 type = types.nullOr types.path;
145 The path to the TLS certificate.
151 type = types.nullOr types.path;
153 The path to the TLS key.
160 config = mkIf cfg.enable {
162 { assertion = cfg.database.createLocally -> cfg.database.username == name && cfg.database.database == cfg.database.username;
163 message = "services.coder.database.username must be set to ${name} if services.coder.database.createLocally is set true";
167 systemd.services.coder = {
168 description = "Coder - Self-hosted developer workspaces on your infra";
169 after = [ "network.target" ];
170 wantedBy = [ "multi-user.target" ];
172 environment = cfg.environment.extra // {
173 CODER_ACCESS_URL = cfg.accessUrl;
174 CODER_WILDCARD_ACCESS_URL = cfg.wildcardAccessUrl;
175 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}"}";
176 CODER_ADDRESS = cfg.listenAddress;
177 CODER_TLS_ENABLE = optionalString (cfg.tlsCert != null) "1";
178 CODER_TLS_CERT_FILE = cfg.tlsCert;
179 CODER_TLS_KEY_FILE = cfg.tlsKey;
183 ProtectSystem = "full";
185 PrivateDevices = "yes";
186 SecureBits = "keep-caps";
187 AmbientCapabilities = "CAP_IPC_LOCK CAP_NET_BIND_SERVICE";
188 CacheDirectory = "coder";
189 CapabilityBoundingSet = "CAP_SYSLOG CAP_IPC_LOCK CAP_NET_BIND_SERVICE";
190 KillSignal = "SIGINT";
192 NoNewPrivileges = "yes";
193 Restart = "on-failure";
194 ExecStart = "${cfg.package}/bin/coder server";
197 EnvironmentFile = lib.mkIf (cfg.environment.file != null) cfg.environment.file;
201 services.postgresql = lib.mkIf cfg.database.createLocally {
204 cfg.database.database
208 ensureDBOwnership = true;
213 users.groups = optionalAttrs (cfg.group == name) {
216 users.users = optionalAttrs (cfg.user == name) {
218 description = "Coder service user";
226 meta.maintainers = pkgs.coder.meta.maintainers;