399 lines
14 KiB
Nix
399 lines
14 KiB
Nix
{ config, lib, pkgs, self, ... }:
|
|
|
|
let
|
|
contributors = import ../../../contributors.nix;
|
|
identities = contributors.identities;
|
|
linearGroups = contributors.groups.linear;
|
|
stripNewline = value: lib.replaceStrings [ "\n" ] [ "" ] value;
|
|
authentikPasswordSecretPath = identity:
|
|
if identity ? authentikPasswordSecret
|
|
then config.age.secrets.${identity.authentikPasswordSecret}.path
|
|
else null;
|
|
bootstrapUsers = lib.mapAttrsToList
|
|
(
|
|
username: identity: {
|
|
inherit username;
|
|
name = identity.displayName;
|
|
email = identity.canonicalEmail;
|
|
isAdmin = identity.isAdmin or false;
|
|
groups = lib.optionals (identity.isAdmin or false) [ linearGroups.owners ];
|
|
passwordFile = authentikPasswordSecretPath identity;
|
|
}
|
|
)
|
|
(lib.filterAttrs (_: identity: identity.bootstrapAuthentik or false) identities);
|
|
headscaleBootstrapUsers = lib.mapAttrsToList
|
|
(
|
|
username: identity: {
|
|
name = username;
|
|
displayName = identity.displayName;
|
|
email = identity.canonicalEmail;
|
|
}
|
|
)
|
|
(lib.filterAttrs (_: identity: identity.bootstrapAuthentik or false) identities);
|
|
forgeUnixUsernames =
|
|
builtins.attrNames (lib.filterAttrs (_: identity: identity.forgeUnixUser or false) identities);
|
|
forgeUnixUsers = lib.genAttrs forgeUnixUsernames (username:
|
|
let
|
|
identity = identities.${username};
|
|
sshKeys = lib.optional (identity ? sshPublicKeyPath) (stripNewline (builtins.readFile identity.sshPublicKeyPath));
|
|
in
|
|
{
|
|
isNormalUser = true;
|
|
createHome = true;
|
|
home = "/home/${username}";
|
|
shell = pkgs.bashInteractive;
|
|
extraGroups = lib.optional (identity.isAdmin or false) "wheel";
|
|
openssh.authorizedKeys.keys = sshKeys;
|
|
});
|
|
forgeUnixAdminUsernames =
|
|
builtins.attrNames (lib.filterAttrs (_: identity: (identity.forgeUnixUser or false) && (identity.isAdmin or false)) identities);
|
|
forgeAuthorizedKeys = map
|
|
(username: builtins.readFile identities.${username}.sshPublicKeyPath)
|
|
(builtins.attrNames (lib.filterAttrs (_: identity: identity.forgeAuthorized or false) identities));
|
|
forgejoNscMaterializeTokenCache = ''
|
|
install -d -m 700 -o forgejo-nsc -g forgejo-nsc /var/lib/forgejo-nsc/.config/ns
|
|
${pkgs.python3}/bin/python3 - <<'PY'
|
|
import json
|
|
from pathlib import Path
|
|
|
|
raw = Path("/var/lib/forgejo-nsc/nsc.token").read_text(encoding="utf-8").strip()
|
|
if not raw:
|
|
raise SystemExit("empty Namespace token")
|
|
if raw.startswith("{"):
|
|
data = json.loads(raw)
|
|
if "bearer_token" not in data and "session_token" not in data:
|
|
raise SystemExit("Namespace token JSON must contain bearer_token or session_token")
|
|
else:
|
|
data = {"session_token": raw}
|
|
Path("/var/lib/forgejo-nsc/.config/ns/token.json").write_text(
|
|
json.dumps(data) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
PY
|
|
chown forgejo-nsc:forgejo-nsc /var/lib/forgejo-nsc/.config/ns/token.json
|
|
chmod 600 /var/lib/forgejo-nsc/.config/ns/token.json
|
|
'';
|
|
in
|
|
|
|
{
|
|
imports = [
|
|
./hardware-configuration.nix
|
|
./disko-config.nix
|
|
self.nixosModules.burrow-forge
|
|
self.nixosModules.burrow-forge-runner
|
|
self.nixosModules.burrow-forgejo-nsc
|
|
self.nixosModules.burrow-authentik
|
|
self.nixosModules.burrow-garage
|
|
self.nixosModules.burrow-headscale
|
|
self.nixosModules.burrow-nix-cache
|
|
self.nixosModules.burrow-observability
|
|
self.nixosModules.burrow-zulip
|
|
self.nixosModules.burrow-openbao
|
|
self.nixosModules.burrow-jitsi
|
|
];
|
|
|
|
system.stateVersion = "24.11";
|
|
|
|
time.timeZone = "America/Los_Angeles";
|
|
|
|
nix.settings.experimental-features = [
|
|
"nix-command"
|
|
"flakes"
|
|
];
|
|
|
|
users.users = forgeUnixUsers;
|
|
|
|
security.sudo.extraRules = lib.map (username: {
|
|
users = [ username ];
|
|
commands = [
|
|
{
|
|
command = "ALL";
|
|
options = [ "NOPASSWD" ];
|
|
}
|
|
];
|
|
}) forgeUnixAdminUsernames;
|
|
|
|
environment.systemPackages = lib.optionals config.services.forgejo-nsc.enable [
|
|
self.packages.${pkgs.stdenv.hostPlatform.system}.nsc
|
|
];
|
|
|
|
age.identityPaths = [ "/var/lib/agenix/agenix.key" ];
|
|
age.secrets.burrowAuthentikEnv = {
|
|
file = ../../../secrets/infra/authentik.env.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowHeadscaleOidcClientSecret = {
|
|
file = ../../../secrets/infra/headscale-oidc-client-secret.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowForgejoOidcClientSecret = {
|
|
file = ../../../secrets/infra/forgejo-oidc-client-secret.age;
|
|
owner = "forgejo";
|
|
group = "forgejo";
|
|
mode = "0440";
|
|
};
|
|
age.secrets.burrowGrafanaAdminPassword = {
|
|
file = ../../../secrets/infra/grafana-admin-password.age;
|
|
owner = "grafana";
|
|
group = "grafana";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowGrafanaSecretKey = {
|
|
file = ../../../secrets/infra/grafana-secret-key.age;
|
|
owner = "grafana";
|
|
group = "grafana";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowGrafanaOidcClientSecret = {
|
|
file = ../../../secrets/infra/grafana-oidc-client-secret.age;
|
|
owner = "grafana";
|
|
group = "grafana";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowTailscaleOidcClientSecret = {
|
|
file = ../../../secrets/infra/tailscale-oidc-client-secret.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowLinearScimToken = {
|
|
file = ../../../secrets/infra/linear-scim-token.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowAuthentikGoogleClientId = {
|
|
file = ../../../secrets/infra/authentik-google-client-id.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowAuthentikGoogleClientSecret = {
|
|
file = ../../../secrets/infra/authentik-google-client-secret.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowAuthentikGoogleAccountMap = {
|
|
file = ../../../secrets/infra/authentik-google-account-map.json.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowAuthentikGoogleWifClientSecret = {
|
|
file = ../../../secrets/infra/authentik-google-wif-client-secret.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowAuthentikUiTestPassword = {
|
|
file = ../../../secrets/infra/authentik-ui-test-password.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowForgejoNscToken = {
|
|
file = ../../../secrets/infra/forgejo-nsc-token.age;
|
|
owner = "forgejo-nsc";
|
|
group = "forgejo-nsc";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowForgejoNscDispatcherConfig = {
|
|
file = ../../../secrets/infra/forgejo-nsc-dispatcher-config.age;
|
|
owner = "forgejo-nsc";
|
|
group = "forgejo-nsc";
|
|
mode = "0400";
|
|
};
|
|
age.secrets.burrowForgejoNscAutoscalerConfig = {
|
|
file = ../../../secrets/infra/forgejo-nsc-autoscaler-config.age;
|
|
owner = "forgejo-nsc";
|
|
group = "forgejo-nsc";
|
|
mode = "0400";
|
|
};
|
|
|
|
age.secrets.burrowZulipPostgresPassword = {
|
|
file = ../../../secrets/infra/zulip-postgres-password.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
|
|
age.secrets.burrowZulipRabbitmqPassword = {
|
|
file = ../../../secrets/infra/zulip-rabbitmq-password.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
|
|
age.secrets.burrowZulipRedisPassword = {
|
|
file = ../../../secrets/infra/zulip-redis-password.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
|
|
age.secrets.burrowZulipSecretKey = {
|
|
file = ../../../secrets/infra/zulip-secret-key.age;
|
|
owner = "root";
|
|
group = "root";
|
|
mode = "0400";
|
|
};
|
|
|
|
networking.extraHosts = ''
|
|
127.0.0.1 burrow.net git.burrow.net auth.burrow.net ts.burrow.net chat.burrow.net graphs.burrow.net vault.burrow.net meet.burrow.net inbox.burrow.net nsc-autoscaler.burrow.net
|
|
::1 burrow.net git.burrow.net auth.burrow.net ts.burrow.net chat.burrow.net graphs.burrow.net vault.burrow.net meet.burrow.net inbox.burrow.net nsc-autoscaler.burrow.net
|
|
'';
|
|
|
|
services.burrow.forge = {
|
|
enable = true;
|
|
contactEmail = identities.contact.canonicalEmail;
|
|
adminUsername = "contact";
|
|
adminEmail = identities.contact.canonicalEmail;
|
|
adminPasswordFile = "/var/lib/burrow/intake/forgejo_pass_contact_at_burrow_net.txt";
|
|
oidcAdminGroup = contributors.groups.admins;
|
|
oidcRestrictedGroup = contributors.groups.users;
|
|
oidcClientSecretFile = config.age.secrets.burrowForgejoOidcClientSecret.path;
|
|
authorizedKeys = forgeAuthorizedKeys;
|
|
};
|
|
|
|
services.burrow.forgeRunner = {
|
|
enable = true;
|
|
sshPrivateKeyFile = "/var/lib/burrow/intake/agent_at_burrow_net_ed25519";
|
|
labels = [
|
|
"self-hosted"
|
|
"linux"
|
|
"x86_64"
|
|
"burrow-forge"
|
|
];
|
|
};
|
|
|
|
services.forgejo-nsc = {
|
|
enable = true;
|
|
nscPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.nsc;
|
|
nscTokenFile = config.age.secrets.burrowForgejoNscToken.path;
|
|
dispatcher = {
|
|
configFile = config.age.secrets.burrowForgejoNscDispatcherConfig.path;
|
|
};
|
|
autoscaler = {
|
|
enable = true;
|
|
configFile = config.age.secrets.burrowForgejoNscAutoscalerConfig.path;
|
|
};
|
|
};
|
|
|
|
systemd.services.forgejo-nsc-dispatcher.preStart = lib.mkAfter forgejoNscMaterializeTokenCache;
|
|
systemd.services.forgejo-nsc-autoscaler.preStart = lib.mkAfter forgejoNscMaterializeTokenCache;
|
|
|
|
services.burrow.authentik = {
|
|
enable = true;
|
|
envFile = config.age.secrets.burrowAuthentikEnv.path;
|
|
forgejoClientSecretFile = config.age.secrets.burrowForgejoOidcClientSecret.path;
|
|
grafanaClientSecretFile = config.age.secrets.burrowGrafanaOidcClientSecret.path;
|
|
grafanaAccessGroupName = contributors.groups.users;
|
|
headscaleClientSecretFile = config.age.secrets.burrowHeadscaleOidcClientSecret.path;
|
|
tailscaleClientSecretFile = config.age.secrets.burrowTailscaleOidcClientSecret.path;
|
|
defaultExternalApplicationSlug = "tailscale";
|
|
googleClientIDFile = config.age.secrets.burrowAuthentikGoogleClientId.path;
|
|
googleClientSecretFile = config.age.secrets.burrowAuthentikGoogleClientSecret.path;
|
|
googleAccountMapFile = config.age.secrets.burrowAuthentikGoogleAccountMap.path;
|
|
googleWifClientSecretFile = config.age.secrets.burrowAuthentikGoogleWifClientSecret.path;
|
|
googleWifAccessGroupName = contributors.groups.automation;
|
|
googleLoginMode = "redirect";
|
|
userGroupName = contributors.groups.users;
|
|
adminGroupName = contributors.groups.admins;
|
|
extraGroupNames = [ contributors.groups.automation ];
|
|
tailscaleAccessGroupName = contributors.groups.users;
|
|
bootstrapUsers = bootstrapUsers;
|
|
linearAcsUrl = "https://api.linear.app/auth/sso/d0ca13dc-ac41-4824-8aab-e0ca352fc3de/acs";
|
|
linearAudience = "https://auth.linear.app/sso/d0ca13dc-ac41-4824-8aab-e0ca352fc3de";
|
|
linearDefaultRelayState = "https://linear.app/auth/sso/d0ca13dc-ac41-4824-8aab-e0ca352fc3de";
|
|
linearScimUrl = "https://api.linear.app/auth/scim/d0ca13dc-ac41-4824-8aab-e0ca352fc3de";
|
|
linearScimTokenFile = config.age.secrets.burrowLinearScimToken.path;
|
|
linearScimUserIdentifier = "email";
|
|
linearOwnerGroupName = linearGroups.owners;
|
|
linearAdminGroupName = linearGroups.admins;
|
|
linearGuestGroupName = linearGroups.guests;
|
|
zulipAccessGroupName = contributors.groups.users;
|
|
};
|
|
|
|
services.grafana = {
|
|
enable = true;
|
|
settings = {
|
|
server = {
|
|
domain = "graphs.burrow.net";
|
|
root_url = "https://graphs.burrow.net/";
|
|
http_addr = "127.0.0.1";
|
|
http_port = 3001;
|
|
enforce_domain = true;
|
|
};
|
|
analytics = {
|
|
reporting_enabled = false;
|
|
check_for_updates = false;
|
|
check_for_plugin_updates = false;
|
|
};
|
|
security = {
|
|
admin_user = "admin";
|
|
admin_password = "$__file{${config.age.secrets.burrowGrafanaAdminPassword.path}}";
|
|
secret_key = "$__file{${config.age.secrets.burrowGrafanaSecretKey.path}}";
|
|
cookie_secure = true;
|
|
cookie_samesite = "strict";
|
|
disable_gravatar = true;
|
|
};
|
|
users = {
|
|
allow_sign_up = false;
|
|
auto_assign_org = true;
|
|
auto_assign_org_role = "Viewer";
|
|
};
|
|
auth = {
|
|
disable_login_form = false;
|
|
oauth_auto_login = false;
|
|
};
|
|
"auth.generic_oauth" = {
|
|
enabled = true;
|
|
name = "burrow.net";
|
|
allow_sign_up = true;
|
|
auto_login = true;
|
|
client_id = "graphs.burrow.net";
|
|
client_secret = "$__file{${config.age.secrets.burrowGrafanaOidcClientSecret.path}}";
|
|
scopes = "openid profile email groups";
|
|
auth_url = "https://auth.burrow.net/application/o/grafana/authorize/";
|
|
token_url = "https://auth.burrow.net/application/o/grafana/token/";
|
|
api_url = "https://auth.burrow.net/application/o/grafana/userinfo/";
|
|
role_attribute_path = "contains(groups[*], 'burrow-admins') && 'Admin' || 'Viewer'";
|
|
};
|
|
};
|
|
};
|
|
|
|
services.caddy.virtualHosts."graphs.burrow.net".extraConfig = ''
|
|
encode gzip zstd
|
|
reverse_proxy 127.0.0.1:3001
|
|
'';
|
|
|
|
services.burrow.headscale = {
|
|
enable = true;
|
|
oidcClientSecretFile = config.age.secrets.burrowHeadscaleOidcClientSecret.path;
|
|
bootstrapUsers = headscaleBootstrapUsers;
|
|
};
|
|
|
|
services.burrow.garage = {
|
|
enable = true;
|
|
enableApiProxy = true;
|
|
enableWebProxy = true;
|
|
};
|
|
|
|
services.burrow.nixCache.enable = true;
|
|
|
|
services.burrow.observability.enable = true;
|
|
|
|
services.burrow.zulip = {
|
|
enable = true;
|
|
administratorEmail = identities.contact.canonicalEmail;
|
|
postgresPasswordFile = config.age.secrets.burrowZulipPostgresPassword.path;
|
|
rabbitmqPasswordFile = config.age.secrets.burrowZulipRabbitmqPassword.path;
|
|
redisPasswordFile = config.age.secrets.burrowZulipRedisPassword.path;
|
|
secretKeyFile = config.age.secrets.burrowZulipSecretKey.path;
|
|
};
|
|
}
|