zitadel: init at 2.37.2; nixos/zitadel: init (#254896)
This commit is contained in:
parent
4d29250d5b
commit
638d19ac92
7 changed files with 525 additions and 0 deletions
|
@ -16285,6 +16285,16 @@
|
|||
githubId = 53029739;
|
||||
name = "Joshua Ortiz";
|
||||
};
|
||||
Sorixelle = {
|
||||
email = "ruby+nixpkgs@srxl.me";
|
||||
matrix = "@ruby:isincredibly.gay";
|
||||
name = "Ruby Iris Juric";
|
||||
github = "Sorixelle";
|
||||
githubId = 38685302;
|
||||
keys = [{
|
||||
fingerprint = "2D76 76C7 A28E 16FC 75C7 268D 1B55 6ED8 4B0E 303A";
|
||||
}];
|
||||
};
|
||||
sorki = {
|
||||
email = "srk@48.io";
|
||||
github = "sorki";
|
||||
|
|
|
@ -89,6 +89,8 @@
|
|||
|
||||
- [audiobookshelf](https://github.com/advplyr/audiobookshelf/), a self-hosted audiobook and podcast server. Available as [services.audiobookshelf](#opt-services.audiobookshelf.enable).
|
||||
|
||||
- [ZITADEL](https://zitadel.com), a turnkey identity and access management platform. Available as [services.zitadel](#opt-services.zitadel.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
|
||||
|
||||
- The `boot.loader.raspberryPi` options have been marked deprecated, with intent for removal for NixOS 24.11. They had a limited use-case, and do not work like people expect. They required either very old installs ([before mid-2019](https://github.com/NixOS/nixpkgs/pull/62462)) or customized builds out of scope of the standard and generic AArch64 support. That option set never supported the Raspberry Pi 4 family of devices.
|
||||
|
|
|
@ -1302,6 +1302,7 @@
|
|||
./services/web-apps/writefreely.nix
|
||||
./services/web-apps/youtrack.nix
|
||||
./services/web-apps/zabbix.nix
|
||||
./services/web-apps/zitadel.nix
|
||||
./services/web-servers/agate.nix
|
||||
./services/web-servers/apache-httpd/default.nix
|
||||
./services/web-servers/caddy/default.nix
|
||||
|
|
223
nixos/modules/services/web-apps/zitadel.nix
Normal file
223
nixos/modules/services/web-apps/zitadel.nix
Normal file
|
@ -0,0 +1,223 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.zitadel;
|
||||
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
in
|
||||
{
|
||||
options.services.zitadel =
|
||||
let inherit (lib) mkEnableOption mkOption mkPackageOption types;
|
||||
in {
|
||||
enable = mkEnableOption "ZITADEL, a user and identity access management platform.";
|
||||
|
||||
package = mkPackageOption pkgs "ZITADEL" { default = [ "zitadel" ]; };
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "zitadel";
|
||||
description = "The user to run ZITADEL under.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "zitadel";
|
||||
description = "The group to run ZITADEL under.";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to open the port specified in `listenPort` in the firewall.
|
||||
'';
|
||||
};
|
||||
|
||||
masterKeyFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path to a file containing a master encryption key for ZITADEL. The
|
||||
key must be 32 bytes.
|
||||
'';
|
||||
};
|
||||
|
||||
tlsMode = mkOption {
|
||||
type = types.enum [ "external" "enabled" "disabled" ];
|
||||
default = "external";
|
||||
example = "enabled";
|
||||
description = ''
|
||||
The TLS mode to use. Options are:
|
||||
|
||||
- enabled: ZITADEL accepts HTTPS connections directly. You must
|
||||
configure TLS if this option is selected.
|
||||
- external: ZITADEL forces HTTPS connections, with TLS terminated at a
|
||||
reverse proxy.
|
||||
- disabled: ZITADEL accepts HTTP connections only. Should only be used
|
||||
for testing.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options = {
|
||||
Port = mkOption {
|
||||
type = types.port;
|
||||
default = 8080;
|
||||
description = "The port that ZITADEL listens on.";
|
||||
};
|
||||
|
||||
TLS = {
|
||||
KeyPath = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "Path to the TLS certificate private key.";
|
||||
};
|
||||
Key = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The TLS certificate private key, as a base64-encoded string.
|
||||
|
||||
Note that the contents of this option will be added to the Nix
|
||||
store as world-readable plain text. Set
|
||||
[KeyPath](#opt-services.zitadel.settings.TLS.KeyPath) instead
|
||||
if this is undesired.
|
||||
'';
|
||||
};
|
||||
CertPath = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "Path to the TLS certificate.";
|
||||
};
|
||||
Cert = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The TLS certificate, as a base64-encoded string.
|
||||
|
||||
Note that the contents of this option will be added to the Nix
|
||||
store as world-readable plain text. Set
|
||||
[CertPath](#opt-services.zitadel.settings.TLS.CertPath) instead
|
||||
if this is undesired.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
Port = 8123;
|
||||
ExternalDomain = "example.com";
|
||||
TLS = {
|
||||
CertPath = "/path/to/cert.pem";
|
||||
KeyPath = "/path/to/cert.key";
|
||||
};
|
||||
Database.cockroach.Host = "db.example.com";
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
Contents of the runtime configuration file. See
|
||||
https://zitadel.com/docs/self-hosting/manage/configure for more
|
||||
details.
|
||||
'';
|
||||
};
|
||||
|
||||
extraSettingsPaths = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [ ];
|
||||
description = ''
|
||||
A list of paths to extra settings files. These will override the
|
||||
values set in [settings](#opt-services.zitadel.settings). Useful if
|
||||
you want to keep sensitive secrets out of the Nix store.
|
||||
'';
|
||||
};
|
||||
|
||||
steps = mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = { };
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
FirstInstance = {
|
||||
InstanceName = "Example";
|
||||
Org.Human = {
|
||||
UserName = "foobar";
|
||||
FirstName = "Foo";
|
||||
LastName = "Bar";
|
||||
};
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Contents of the database initialization config file. See
|
||||
https://zitadel.com/docs/self-hosting/manage/configure for more
|
||||
details.
|
||||
'';
|
||||
};
|
||||
|
||||
extraStepsPaths = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [ ];
|
||||
description = ''
|
||||
A list of paths to extra steps files. These will override the values
|
||||
set in [steps](#opt-services.zitadel.steps). Useful if you want to
|
||||
keep sensitive secrets out of the Nix store.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [{
|
||||
assertion = cfg.tlsMode == "enabled"
|
||||
-> ((cfg.settings.TLS.Key != null || cfg.settings.TLS.KeyPath != null)
|
||||
&& (cfg.settings.TLS.Cert != null || cfg.settings.TLS.CertPath
|
||||
!= null));
|
||||
message = ''
|
||||
A TLS certificate and key must be configured in
|
||||
services.zitadel.settings.TLS if services.zitadel.tlsMode is enabled.
|
||||
'';
|
||||
}];
|
||||
|
||||
networking.firewall.allowedTCPPorts =
|
||||
lib.mkIf cfg.openFirewall [ cfg.settings.Port ];
|
||||
|
||||
systemd.services.zitadel =
|
||||
let
|
||||
configFile = settingsFormat.generate "config.yaml" cfg.settings;
|
||||
stepsFile = settingsFormat.generate "steps.yaml" cfg.steps;
|
||||
|
||||
args = lib.cli.toGNUCommandLineShell { } {
|
||||
config = cfg.extraSettingsPaths ++ [ configFile ];
|
||||
steps = cfg.extraStepsPaths ++ [ stepsFile ];
|
||||
masterkeyFile = cfg.masterKeyFile;
|
||||
inherit (cfg) tlsMode;
|
||||
};
|
||||
in
|
||||
{
|
||||
description = "ZITADEL identity access management";
|
||||
path = [ cfg.package ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
script = ''
|
||||
zitadel start-from-init ${args}
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
|
||||
users.users.zitadel = lib.mkIf (cfg.user == "zitadel") {
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
};
|
||||
users.groups.zitadel = lib.mkIf (cfg.group == "zitadel") { };
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ Sorixelle ];
|
||||
}
|
51
pkgs/by-name/zi/zitadel/console.nix
Normal file
51
pkgs/by-name/zi/zitadel/console.nix
Normal file
|
@ -0,0 +1,51 @@
|
|||
{ generateProtobufCode
|
||||
, version
|
||||
, zitadelRepo
|
||||
}:
|
||||
|
||||
{ mkYarnPackage
|
||||
, fetchYarnDeps
|
||||
, lib
|
||||
}:
|
||||
|
||||
let
|
||||
protobufGenerated = generateProtobufCode {
|
||||
pname = "zitadel-console";
|
||||
workDir = "console";
|
||||
bufArgs = "../proto --include-imports --include-wkt";
|
||||
outputPath = "src/app/proto";
|
||||
hash = "sha256-s0dzmcjKd8ot7t+KlRlNVA9oiIDKVMnGOT/HjdaUjGI=";
|
||||
};
|
||||
in
|
||||
mkYarnPackage rec {
|
||||
name = "zitadel-console";
|
||||
inherit version;
|
||||
|
||||
src = "${zitadelRepo}/console";
|
||||
|
||||
packageJSON = ./package.json;
|
||||
offlineCache = fetchYarnDeps {
|
||||
yarnLock = "${src}/yarn.lock";
|
||||
hash = "sha256-48IC4LxqbkH+95k7rCmhRWT+qAlJ9CDXWwRjbric9no=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace src/styles.scss \
|
||||
--replace "/node_modules/flag-icons" "flag-icons"
|
||||
|
||||
substituteInPlace angular.json \
|
||||
--replace "./node_modules/tinycolor2" "../../node_modules/tinycolor2"
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
mkdir deps/console/src/app/proto
|
||||
cp -r ${protobufGenerated}/* deps/console/src/app/proto/
|
||||
yarn --offline build
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
cp -r deps/console/dist/console $out
|
||||
'';
|
||||
|
||||
doDist = false;
|
||||
}
|
88
pkgs/by-name/zi/zitadel/package.json
Normal file
88
pkgs/by-name/zi/zitadel/package.json
Normal file
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"name": "console",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "node prebuild.development.js && ng serve",
|
||||
"build": "ng build --configuration production --base-href=/ui/console/",
|
||||
"prelint": "npm run generate",
|
||||
"lint": "ng lint && prettier --check src",
|
||||
"lint:fix": "prettier --write src",
|
||||
"generate": "buf generate ../proto --include-imports --include-wkt"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^16.2.0",
|
||||
"@angular/cdk": "^16.2.0",
|
||||
"@angular/common": "^16.2.0",
|
||||
"@angular/compiler": "^16.2.0",
|
||||
"@angular/core": "^16.2.0",
|
||||
"@angular/forms": "^16.2.0",
|
||||
"@angular/material": "^16.2.0",
|
||||
"@angular/material-moment-adapter": "^16.2.0",
|
||||
"@angular/platform-browser": "^16.2.0",
|
||||
"@angular/platform-browser-dynamic": "^16.2.0",
|
||||
"@angular/router": "^16.2.0",
|
||||
"@angular/service-worker": "^16.2.0",
|
||||
"@ctrl/ngx-codemirror": "^6.1.0",
|
||||
"@grpc/grpc-js": "^1.8.14",
|
||||
"@ngx-translate/core": "^14.0.0",
|
||||
"angular-oauth2-oidc": "^15.0.1",
|
||||
"angularx-qrcode": "^16.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"codemirror": "^5.65.8",
|
||||
"cors": "^2.8.5",
|
||||
"file-saver": "^2.0.5",
|
||||
"flag-icons": "^6.7.0",
|
||||
"google-proto-files": "^3.0.3",
|
||||
"google-protobuf": "^3.21.2",
|
||||
"grpc-web": "^1.4.1",
|
||||
"i18n-iso-countries": "^7.6.0",
|
||||
"libphonenumber-js": "^1.10.30",
|
||||
"material-design-icons-iconfont": "^6.1.1",
|
||||
"moment": "^2.29.4",
|
||||
"opentype.js": "^1.3.4",
|
||||
"ngx-color": "^9.0.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tinycolor2": "^1.6.0",
|
||||
"tslib": "^2.4.1",
|
||||
"uuid": "^9.0.0",
|
||||
"zone.js": "~0.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^16.2.0",
|
||||
"@angular-eslint/builder": "16.1.0",
|
||||
"@angular-eslint/eslint-plugin": "16.1.0",
|
||||
"@angular-eslint/eslint-plugin-template": "16.1.0",
|
||||
"@angular-eslint/schematics": "16.1.0",
|
||||
"@angular-eslint/template-parser": "16.1.0",
|
||||
"@angular/cli": "^16.2.0",
|
||||
"@angular/compiler-cli": "^16.2.0",
|
||||
"@angular/language-service": "^16.2.0",
|
||||
"@bufbuild/buf": "^1.23.1",
|
||||
"@types/file-saver": "^2.0.2",
|
||||
"@types/google-protobuf": "^3.15.3",
|
||||
"@types/jasmine": "~4.3.3",
|
||||
"@types/jasminewd2": "~2.0.10",
|
||||
"@types/jsonwebtoken": "^9.0.1",
|
||||
"@types/node": "^18.15.11",
|
||||
"@types/opentype.js": "^1.3.4",
|
||||
"@types/qrcode": "^1.5.0",
|
||||
"@types/uuid": "^9.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.11",
|
||||
"@typescript-eslint/parser": "^5.60.1",
|
||||
"codelyzer": "^6.0.2",
|
||||
"eslint": "^8.44.0",
|
||||
"jasmine-core": "~4.6.0",
|
||||
"jasmine-spec-reporter": "~7.0.0",
|
||||
"karma": "^6.4.2",
|
||||
"karma-chrome-launcher": "^3.2.0",
|
||||
"karma-coverage-istanbul-reporter": "^3.0.3",
|
||||
"karma-jasmine": "^5.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.1.0",
|
||||
"prettier": "^2.8.7",
|
||||
"prettier-plugin-organize-imports": "^3.2.2",
|
||||
"protractor": "~7.0.0",
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
}
|
150
pkgs/by-name/zi/zitadel/package.nix
Normal file
150
pkgs/by-name/zi/zitadel/package.nix
Normal file
|
@ -0,0 +1,150 @@
|
|||
{ stdenv
|
||||
, buildGo121Module
|
||||
, callPackage
|
||||
, fetchFromGitHub
|
||||
, lib
|
||||
|
||||
, buf
|
||||
, cacert
|
||||
, grpc-gateway
|
||||
, protoc-gen-go
|
||||
, protoc-gen-go-grpc
|
||||
, protoc-gen-validate
|
||||
, sass
|
||||
, statik
|
||||
}:
|
||||
|
||||
let
|
||||
version = "2.37.2";
|
||||
zitadelRepo = fetchFromGitHub {
|
||||
owner = "zitadel";
|
||||
repo = "zitadel";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-iWEL7R7eNDV4c1CZhmxxiHHI9ExwU6gnmHI6ildaXWY=";
|
||||
};
|
||||
goModulesHash = "sha256-lk4jEiI85EKk0G4JCHvCazqBBTfiNJqSfzvrJgDZ1Nc=";
|
||||
|
||||
buildZitadelProtocGen = name:
|
||||
buildGo121Module {
|
||||
pname = "protoc-gen-${name}";
|
||||
inherit version;
|
||||
|
||||
src = zitadelRepo;
|
||||
|
||||
proxyVendor = true;
|
||||
vendorHash = goModulesHash;
|
||||
|
||||
buildPhase = ''
|
||||
go install internal/protoc/protoc-gen-${name}/main.go
|
||||
'';
|
||||
|
||||
postInstall = ''
|
||||
mv $out/bin/main $out/bin/protoc-gen-${name}
|
||||
'';
|
||||
};
|
||||
|
||||
protoc-gen-authoption = buildZitadelProtocGen "authoption";
|
||||
protoc-gen-zitadel = buildZitadelProtocGen "zitadel";
|
||||
|
||||
# Buf downloads dependencies from an external repo - there doesn't seem to
|
||||
# really be any good way around it. We'll use a fixed-output derivation so it
|
||||
# can download what it needs, and output the relevant generated code for use
|
||||
# during the main build.
|
||||
generateProtobufCode =
|
||||
{ pname
|
||||
, nativeBuildInputs ? [ ]
|
||||
, bufArgs ? ""
|
||||
, workDir ? "."
|
||||
, outputPath
|
||||
, hash
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "${pname}-buf-generated";
|
||||
|
||||
src = zitadelRepo;
|
||||
|
||||
nativeBuildInputs = nativeBuildInputs ++ [ buf ];
|
||||
|
||||
buildPhase = ''
|
||||
cd ${workDir}
|
||||
export SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt"
|
||||
HOME=$TMPDIR buf generate ${bufArgs}
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
cp -r ${outputPath} $out
|
||||
'';
|
||||
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
outputHash = hash;
|
||||
};
|
||||
|
||||
protobufGenerated = generateProtobufCode {
|
||||
pname = "zitadel";
|
||||
nativeBuildInputs = [
|
||||
grpc-gateway
|
||||
protoc-gen-authoption
|
||||
protoc-gen-go
|
||||
protoc-gen-go-grpc
|
||||
protoc-gen-validate
|
||||
protoc-gen-zitadel
|
||||
];
|
||||
outputPath = ".artifacts";
|
||||
hash = "sha256-+9UFBWBuSYNbfimKwJUSoiUh+8bDHGnPdx1MKDul1U4=";
|
||||
};
|
||||
in
|
||||
buildGo121Module rec {
|
||||
name = "zitadel";
|
||||
inherit version;
|
||||
|
||||
src = zitadelRepo;
|
||||
|
||||
nativeBuildInputs = [ sass statik ];
|
||||
|
||||
proxyVendor = true;
|
||||
vendorHash = goModulesHash;
|
||||
|
||||
# Adapted from Makefile in repo, with dependency fetching and protobuf codegen
|
||||
# bits removed
|
||||
buildPhase = ''
|
||||
mkdir -p pkg/grpc
|
||||
cp -r ${protobufGenerated}/grpc/github.com/zitadel/zitadel/pkg/grpc/* pkg/grpc
|
||||
mkdir -p openapi/v2/zitadel
|
||||
cp -r ${protobufGenerated}/grpc/zitadel/ openapi/v2/zitadel
|
||||
|
||||
go generate internal/api/ui/login/static/resources/generate.go
|
||||
go generate internal/api/ui/login/statik/generate.go
|
||||
go generate internal/notification/statik/generate.go
|
||||
go generate internal/statik/generate.go
|
||||
|
||||
mkdir -p docs/apis/assets
|
||||
go run internal/api/assets/generator/asset_generator.go -directory=internal/api/assets/generator/ -assets=docs/apis/assets/assets.md
|
||||
|
||||
cp -r ${passthru.console}/* internal/api/ui/console/static
|
||||
CGO_ENABLED=0 go build -o zitadel -v -ldflags="-s -w -X 'github.com/zitadel/zitadel/cmd/build.version=${version}'"
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
install -Dm755 zitadel $out/bin/
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
console = callPackage
|
||||
(import ./console.nix {
|
||||
inherit generateProtobufCode version zitadelRepo;
|
||||
})
|
||||
{ };
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "Identity and access management platform";
|
||||
homepage = "https://zitadel.com/";
|
||||
downloadPage = "https://github.com/zitadel/zitadel/releases";
|
||||
platforms = platforms.linux ++ platforms.darwin;
|
||||
license = licenses.asl20;
|
||||
sourceProvenance = [ sourceTypes.fromSource ];
|
||||
maintainers = with maintainers; [ Sorixelle ];
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue