nixos/coder: init module
This commit is contained in:
parent
0566d27d03
commit
56ecab709a
7 changed files with 299 additions and 83 deletions
|
@ -1120,6 +1120,7 @@
|
|||
./services/web-apps/baget.nix
|
||||
./services/web-apps/bookstack.nix
|
||||
./services/web-apps/calibre-web.nix
|
||||
./services/web-apps/coder.nix
|
||||
./services/web-apps/changedetection-io.nix
|
||||
./services/web-apps/cloudlog.nix
|
||||
./services/web-apps/code-server.nix
|
||||
|
|
217
nixos/modules/services/web-apps/coder.nix
Normal file
217
nixos/modules/services/web-apps/coder.nix
Normal file
|
@ -0,0 +1,217 @@
|
|||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.coder;
|
||||
name = "coder";
|
||||
in {
|
||||
options = {
|
||||
services.coder = {
|
||||
enable = mkEnableOption (lib.mdDoc "Coder service");
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "coder";
|
||||
description = lib.mdDoc ''
|
||||
User under which the coder service runs.
|
||||
|
||||
::: {.note}
|
||||
If left as the default value this user will automatically be created
|
||||
on system activation, otherwise it needs to be configured manually.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "coder";
|
||||
description = lib.mdDoc ''
|
||||
Group under which the coder service runs.
|
||||
|
||||
::: {.note}
|
||||
If left as the default value this group will automatically be created
|
||||
on system activation, otherwise it needs to be configured manually.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.coder;
|
||||
description = lib.mdDoc ''
|
||||
Package to use for the service.
|
||||
'';
|
||||
defaultText = literalExpression "pkgs.coder";
|
||||
};
|
||||
|
||||
homeDir = mkOption {
|
||||
type = types.str;
|
||||
description = lib.mdDoc ''
|
||||
Home directory for coder user.
|
||||
'';
|
||||
default = "/var/lib/coder";
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
description = lib.mdDoc ''
|
||||
Listen address.
|
||||
'';
|
||||
default = "127.0.0.1:3000";
|
||||
};
|
||||
|
||||
accessUrl = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = lib.mdDoc ''
|
||||
Access URL should be a external IP address or domain with DNS records pointing to Coder.
|
||||
'';
|
||||
default = null;
|
||||
example = "https://coder.example.com";
|
||||
};
|
||||
|
||||
wildcardAccessUrl = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = lib.mdDoc ''
|
||||
If you are providing TLS certificates directly to the Coder server, you must use a single certificate for the root and wildcard domains.
|
||||
'';
|
||||
default = null;
|
||||
example = "*.coder.example.com";
|
||||
};
|
||||
|
||||
database = {
|
||||
createLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Create the database and database user locally.
|
||||
'';
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "/run/postgresql";
|
||||
description = lib.mdDoc ''
|
||||
Hostname hosting the database.
|
||||
'';
|
||||
};
|
||||
|
||||
database = mkOption {
|
||||
type = types.str;
|
||||
default = "coder";
|
||||
description = lib.mdDoc ''
|
||||
Name of database.
|
||||
'';
|
||||
};
|
||||
|
||||
username = mkOption {
|
||||
type = types.str;
|
||||
default = "coder";
|
||||
description = lib.mdDoc ''
|
||||
Username for accessing the database.
|
||||
'';
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Password for accessing the database.
|
||||
'';
|
||||
};
|
||||
|
||||
sslmode = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "disable";
|
||||
description = lib.mdDoc ''
|
||||
Password for accessing the database.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
tlsCert = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
description = lib.mdDoc ''
|
||||
The path to the TLS certificate.
|
||||
'';
|
||||
default = null;
|
||||
};
|
||||
|
||||
tlsKey = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
description = lib.mdDoc ''
|
||||
The path to the TLS key.
|
||||
'';
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.username == name;
|
||||
message = "services.coder.database.username must be set to ${user} if services.coder.database.createLocally is set true";
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.coder = {
|
||||
description = "Coder - Self-hosted developer workspaces on your infra";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
environment = {
|
||||
CODER_ACCESS_URL = cfg.accessUrl;
|
||||
CODER_WILDCARD_ACCESS_URL = cfg.wildcardAccessUrl;
|
||||
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}"}";
|
||||
CODER_ADDRESS = cfg.listenAddress;
|
||||
CODER_TLS_ENABLE = optionalString (cfg.tlsCert != null) "1";
|
||||
CODER_TLS_CERT_FILE = cfg.tlsCert;
|
||||
CODER_TLS_KEY_FILE = cfg.tlsKey;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
ProtectSystem = "full";
|
||||
PrivateTmp = "yes";
|
||||
PrivateDevices = "yes";
|
||||
SecureBits = "keep-caps";
|
||||
AmbientCapabilities = "CAP_IPC_LOCK CAP_NET_BIND_SERVICE";
|
||||
CacheDirectory = "coder";
|
||||
CapabilityBoundingSet = "CAP_SYSLOG CAP_IPC_LOCK CAP_NET_BIND_SERVICE";
|
||||
KillSignal = "SIGINT";
|
||||
KillMode = "mixed";
|
||||
NoNewPrivileges = "yes";
|
||||
Restart = "on-failure";
|
||||
ExecStart = "${cfg.package}/bin/coder server";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
};
|
||||
};
|
||||
|
||||
services.postgresql = lib.mkIf cfg.database.createLocally {
|
||||
enable = true;
|
||||
ensureDatabases = [
|
||||
cfg.database.database
|
||||
];
|
||||
ensureUsers = [{
|
||||
name = cfg.database.username;
|
||||
ensurePermissions = {
|
||||
"DATABASE \"${cfg.database.database}\"" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
users.groups = optionalAttrs (cfg.group == name) {
|
||||
"${cfg.group}" = {};
|
||||
};
|
||||
users.users = optionalAttrs (cfg.user == name) {
|
||||
${name} = {
|
||||
description = "Coder service user";
|
||||
group = cfg.group;
|
||||
home = cfg.homeDir;
|
||||
createHome = true;
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -135,6 +135,7 @@ in {
|
|||
cloudlog = handleTest ./cloudlog.nix {};
|
||||
cntr = handleTestOn ["aarch64-linux" "x86_64-linux"] ./cntr.nix {};
|
||||
cockroachdb = handleTestOn ["x86_64-linux"] ./cockroachdb.nix {};
|
||||
coder = handleTest ./coder.nix {};
|
||||
collectd = handleTest ./collectd.nix {};
|
||||
connman = handleTest ./connman.nix {};
|
||||
consul = handleTest ./consul.nix {};
|
||||
|
|
24
nixos/tests/coder.nix
Normal file
24
nixos/tests/coder.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||
name = "coder";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ shyim ghuntley ];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.coder = {
|
||||
enable = true;
|
||||
accessUrl = "http://localhost:3000";
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("postgresql.service")
|
||||
machine.wait_for_unit("coder.service")
|
||||
machine.wait_for_open_port(3000)
|
||||
|
||||
machine.succeed("curl --fail http://localhost:3000")
|
||||
'';
|
||||
})
|
|
@ -1,76 +0,0 @@
|
|||
{ lib, pkgs, fetchFromGitHub, installShellFiles, buildGoModule, fetchYarnDeps }:
|
||||
|
||||
let
|
||||
pname = "coder";
|
||||
version = "0.10.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "coder";
|
||||
repo = "coder";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-h5bN75agNocRAjShbufRCJr45huYJOzCBd4OcGpF4C4=";
|
||||
};
|
||||
|
||||
offlineCache = fetchYarnDeps {
|
||||
yarnLock = src + "/site/yarn.lock";
|
||||
sha256 = "sha256-uDNPRQTpsgxyC5ks+2Qq/wiKjkbjWwSO+cJc5X6qmAA=";
|
||||
};
|
||||
|
||||
yarn16 = pkgs.yarn.override { nodejs = pkgs.nodejs-16_x; };
|
||||
nodePackages16 = pkgs.nodePackages.override { nodejs = pkgs.nodejs-16_x; };
|
||||
in
|
||||
buildGoModule rec {
|
||||
inherit pname version src;
|
||||
|
||||
subPackages = [ "cmd/coder" ];
|
||||
|
||||
vendorSha256 = "sha256-+3Zy0zArCXkvD4ogfKdu9W9gJXveAhwFXKG1VRDvOkI=";
|
||||
|
||||
# Flags as provided by the build automation of the project:
|
||||
# https://github.com/coder/coder/blob/075e891f287b27cdb481a48e129f20a1e6a7de12/scripts/build_go.sh#L89
|
||||
ldflags = [
|
||||
"-s"
|
||||
"-w"
|
||||
"-X github.com/coder/coder/buildinfo.tag=${version}"
|
||||
];
|
||||
|
||||
preBuild = ''
|
||||
export HOME=$(mktemp -d)
|
||||
mkdir -p $HOME
|
||||
|
||||
cd site
|
||||
yarn config --offline set yarn-offline-mirror ${offlineCache}
|
||||
fixup_yarn_lock yarn.lock
|
||||
|
||||
# node-gyp tries to download always the headers and fails: https://github.com/NixOS/nixpkgs/issues/195404
|
||||
yarn remove --offline jest-canvas-mock canvas
|
||||
|
||||
NODE_ENV=production node node_modules/.bin/vite build
|
||||
cd ..
|
||||
'';
|
||||
|
||||
tags = [ "embed" ];
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
fixup_yarn_lock
|
||||
nodejs-16_x
|
||||
yarn16
|
||||
nodePackages16.node-pre-gyp
|
||||
python3
|
||||
pkg-config
|
||||
installShellFiles
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
installShellCompletion --cmd coder \
|
||||
--bash <($out/bin/coder completion bash) \
|
||||
--zsh <($out/bin/coder completion zsh)
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Software development on any infrastructure";
|
||||
license = licenses.agpl3Only;
|
||||
homepage = "https://coder.com/";
|
||||
maintainers = with maintainers; [ shyim ];
|
||||
};
|
||||
}
|
|
@ -1,8 +1,18 @@
|
|||
{ buildGoModule
|
||||
{ lib
|
||||
, fetchFromGitHub
|
||||
, installShellFiles
|
||||
, lib
|
||||
, makeWrapper
|
||||
, buildGoModule
|
||||
, fetchYarnDeps
|
||||
, fixup_yarn_lock
|
||||
, pkg-config
|
||||
, nodejs
|
||||
, yarn
|
||||
, nodePackages
|
||||
, python3
|
||||
, terraform
|
||||
}:
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "coder";
|
||||
version = "0.16.0";
|
||||
|
@ -14,18 +24,59 @@ buildGoModule rec {
|
|||
hash = "sha256-3rGpyJzGkZYUEvKKDzj2I5sqrUImmmX7cXWM9UClPLY=";
|
||||
};
|
||||
|
||||
# integration tests require network access
|
||||
doCheck = false;
|
||||
offlineCache = fetchYarnDeps {
|
||||
yarnLock = src + "/site/yarn.lock";
|
||||
hash = "sha256-4GbM7GNZ3wHIZJIJuHw1v/SwjUNc1vi8IHRGaGwPGZQ=";
|
||||
};
|
||||
|
||||
subPackages = [ "cmd/..." ];
|
||||
|
||||
vendorHash = "sha256-bb9jBno7elO6qKGjacpX3rxgrpJpGpTxMQtdBYjBzMk=";
|
||||
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
# integration tests require network access
|
||||
doCheck = false;
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
"-w"
|
||||
"-X github.com/coder/coder/buildinfo.tag=${version}"
|
||||
];
|
||||
|
||||
preBuild = ''
|
||||
export HOME=$TEMPDIR
|
||||
|
||||
pushd site
|
||||
yarn config --offline set yarn-offline-mirror ${offlineCache}
|
||||
fixup_yarn_lock yarn.lock
|
||||
|
||||
# node-gyp tries to download always the headers and fails: https://github.com/NixOS/nixpkgs/issues/195404
|
||||
yarn remove --offline jest-canvas-mock canvas
|
||||
|
||||
NODE_ENV=production node node_modules/.bin/vite build
|
||||
|
||||
popd
|
||||
'';
|
||||
|
||||
tags = [ "embed" ];
|
||||
|
||||
nativeBuildInputs = [
|
||||
fixup_yarn_lock
|
||||
installShellFiles
|
||||
makeWrapper
|
||||
nodePackages.node-pre-gyp
|
||||
nodejs
|
||||
pkg-config
|
||||
python3
|
||||
yarn
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
installShellCompletion --cmd coder \
|
||||
--bash <($out/bin/coder completion bash) \
|
||||
--fish <($out/bin/coder completion fish) \
|
||||
--zsh <($out/bin/coder completion zsh)
|
||||
|
||||
wrapProgram $out/bin/coder --prefix PATH : ${lib.makeBinPath [ terraform ]}
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
|
|
|
@ -4174,8 +4174,6 @@ with pkgs;
|
|||
electron = electron_11;
|
||||
};
|
||||
|
||||
coder = callPackage ../applications/misc/coder {};
|
||||
|
||||
contrast = callPackage ../applications/accessibility/contrast { };
|
||||
|
||||
cplex = callPackage ../applications/science/math/cplex (config.cplex or {});
|
||||
|
|
Loading…
Reference in a new issue