Begin moving openbao and authentik server to new setup
Former-commit-id: 8cd2737aca
This commit is contained in:
parent
3a42f156f7
commit
7a995baca4
43 changed files with 1006 additions and 481 deletions
|
@ -1,3 +1,6 @@
|
|||
{
|
||||
...
|
||||
}:
|
||||
{
|
||||
khscodes.khs.enable = true;
|
||||
khscodes.khs.shell.oh-my-posh.enable = true;
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
...
|
||||
}:
|
||||
{
|
||||
khscodes.khs.enable = true;
|
||||
khscodes.khs.shell.oh-my-posh.enable = true;
|
||||
}
|
10
nix/homes/x86_64-linux/khs/default.nix
Normal file
10
nix/homes/x86_64-linux/khs/default.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
khscodes.khs.enable = true;
|
||||
khscodes.khs.shell.oh-my-posh.enable = true;
|
||||
imports = lib.lists.optional config.khscodes.desktop.enable ./desktop.nix;
|
||||
}
|
9
nix/homes/x86_64-linux/khs/desktop.nix
Normal file
9
nix/homes/x86_64-linux/khs/desktop.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{ pkgs, lib, ... }:
|
||||
{
|
||||
imports = lib.lists.optional (lib.strings.hasSuffix "-linux" pkgs.system) ./linux-desktop.nix;
|
||||
home.packages = [
|
||||
pkgs.bitwarden-cli
|
||||
pkgs.nerd-fonts.inconsolata
|
||||
pkgs.google-chrome
|
||||
];
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
{ pkgs, ... }:
|
||||
{
|
||||
imports = [ ./khs-desktop.nix ];
|
||||
home.packages = [ pkgs.spotify ];
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{ inputs, ... }:
|
||||
{
|
||||
imports = [ "${inputs.self}/nix/profiles/home/khs-linux-desktop.nix" ];
|
||||
}
|
|
@ -53,7 +53,7 @@ in
|
|||
dnsNames = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = "DNS names for the server";
|
||||
default = lib.lists.unique ([ fqdn ] ++ config.networking.aliases);
|
||||
default = lib.lists.unique ([ fqdn ] ++ config.khscodes.networking.aliases);
|
||||
};
|
||||
bucket = {
|
||||
key = lib.mkOption {
|
||||
|
@ -62,14 +62,6 @@ in
|
|||
default = "${fqdn}.tfstate";
|
||||
};
|
||||
};
|
||||
secretsSource = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"bitwarden"
|
||||
"vault"
|
||||
];
|
||||
description = "Whether to load opentofu secrets from Bitwarden or Vault";
|
||||
default = "vault";
|
||||
};
|
||||
datacenter = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "The Hetzner datacenter to create a server in";
|
||||
|
@ -159,7 +151,7 @@ in
|
|||
inherit labels;
|
||||
name = fqdn;
|
||||
initial_image = "debian-12";
|
||||
rdns = fqdn;
|
||||
rdns = lib.mkIf cfg.mapRdns fqdn;
|
||||
ssh_keys = [ config.khscodes.hcloud.output.data.ssh_key.khs.id ];
|
||||
user_data = provisioningUserData;
|
||||
};
|
||||
|
@ -211,7 +203,6 @@ in
|
|||
khscodes.services.read-vault-auth-from-userdata.url = "http://169.254.169.254/latest/user-data";
|
||||
khscodes.infrastructure.provisioning.pre = {
|
||||
modules = modules;
|
||||
secretsSource = cfg.secretsSource;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
9
nix/modules/nixos/infrastructure/openbao/default.nix
Normal file
9
nix/modules/nixos/infrastructure/openbao/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
options.khscodes.infrastructure.openbao = {
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "vault.kaareskovgaard.net";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -7,6 +7,8 @@ let
|
|||
cfg = config.khscodes.infrastructure.vault-loki-sender;
|
||||
fqdn = config.khscodes.networking.fqdn;
|
||||
vaultRoleName = config.khscodes.infrastructure.vault-server-approle.role_name;
|
||||
client_key = "/var/lib/alloy/loki.key";
|
||||
client_cert = "/var/lib/alloy/loki.cert";
|
||||
in
|
||||
{
|
||||
options.khscodes.infrastructure.vault-loki-sender = {
|
||||
|
@ -56,8 +58,8 @@ in
|
|||
{{ .Key }}
|
||||
{{ .Cert }}
|
||||
{{ .CA }}
|
||||
{{ .Key | writeToFile "${config.khscodes.services.alloy.loki.client_key}" "${config.khscodes.services.alloy.user}" "${config.khscodes.services.alloy.group}" "0600" }}
|
||||
{{ .Cert | writeToFile "${config.khscodes.services.alloy.loki.client_cert}" "${config.khscodes.services.alloy.user}" "${config.khscodes.services.alloy.group}" "0644" }}
|
||||
{{ .Key | writeToFile "${client_key}" "${config.khscodes.services.alloy.user}" "${config.khscodes.services.alloy.group}" "0600" }}
|
||||
{{ .Cert | writeToFile "${client_cert}" "${config.khscodes.services.alloy.user}" "${config.khscodes.services.alloy.group}" "0644" }}
|
||||
{{- end -}}
|
||||
'';
|
||||
destination = "/var/lib/alloy/cache.key";
|
||||
|
@ -69,10 +71,13 @@ in
|
|||
];
|
||||
khscodes.services.alloy = {
|
||||
enable = true;
|
||||
loki = {
|
||||
client_key = "/var/lib/alloy/loki_cert.key";
|
||||
client_cert = "/var/lib/alloy/loki_cert.pem";
|
||||
environment = {
|
||||
LOKI_CLIENT_KEY = client_key;
|
||||
LOKI_CLIENT_CERT = client_cert;
|
||||
};
|
||||
};
|
||||
environment.etc."alloy/loki.alloy" = {
|
||||
source = ./loki.alloy;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
// Collect logs from systemd journal for node_exporter integration
|
||||
loki.source.journal "logs_integrations_integrations_node_exporter_journal_scrape" {
|
||||
// Only collect logs from the last 24 hours
|
||||
max_age = "24h0m0s"
|
||||
// Apply relabeling rules to the logs
|
||||
relabel_rules = discovery.relabel.logs_integrations_integrations_node_exporter_journal_scrape.rules
|
||||
// Send logs to the local Loki instance
|
||||
forward_to = [loki.write.local.receiver]
|
||||
}
|
||||
|
||||
// Define which log files to collect for node_exporter
|
||||
local.file_match "logs_integrations_integrations_node_exporter_direct_scrape" {
|
||||
path_targets = [{
|
||||
// Target localhost for log collection
|
||||
__address__ = "localhost",
|
||||
// Collect standard system logs
|
||||
__path__ = "/var/log/{syslog,messages,*.log}",
|
||||
// Add instance label with hostname
|
||||
instance = constants.hostname,
|
||||
// Add job label for logs
|
||||
job = "integrations/node_exporter",
|
||||
}]
|
||||
}
|
||||
|
||||
// Define relabeling rules for systemd journal logs
|
||||
discovery.relabel "logs_integrations_integrations_node_exporter_journal_scrape" {
|
||||
targets = []
|
||||
|
||||
rule {
|
||||
// Extract systemd unit information into a label
|
||||
source_labels = ["__journal__systemd_unit"]
|
||||
target_label = "unit"
|
||||
}
|
||||
|
||||
rule {
|
||||
// Extract boot ID information into a label
|
||||
source_labels = ["__journal__boot_id"]
|
||||
target_label = "boot_id"
|
||||
}
|
||||
|
||||
rule {
|
||||
// Extract transport information into a label
|
||||
source_labels = ["__journal__transport"]
|
||||
target_label = "transport"
|
||||
}
|
||||
|
||||
rule {
|
||||
// Extract log priority into a level label
|
||||
source_labels = ["__journal_priority_keyword"]
|
||||
target_label = "level"
|
||||
}
|
||||
|
||||
rule {
|
||||
// Set the instance label to the hostname of the machine
|
||||
target_label = "instance"
|
||||
replacement = constants.hostname
|
||||
}
|
||||
}
|
||||
|
||||
// Collect logs from files for node_exporter
|
||||
loki.source.file "logs_integrations_integrations_node_exporter_direct_scrape" {
|
||||
// Use targets defined in local.file_match
|
||||
targets = local.file_match.logs_integrations_integrations_node_exporter_direct_scrape.targets
|
||||
// Send logs to the local Loki instance
|
||||
forward_to = [loki.write.local.receiver]
|
||||
}
|
||||
|
||||
// Define where to send logs for storage
|
||||
loki.write "local" {
|
||||
endpoint {
|
||||
// Send logs to a locally running Loki instance
|
||||
url = "https://loki.kaareskovgaard.net/loki/api/v1/push"
|
||||
tls_config {
|
||||
cert_file = sys.env("LOKI_CLIENT_CERT")
|
||||
key_file = sys.env("LOKI_CLIENT_KEY")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,13 +7,15 @@ let
|
|||
cfg = config.khscodes.infrastructure.vault-prometheus-sender;
|
||||
fqdn = config.khscodes.networking.fqdn;
|
||||
vaultRoleName = config.khscodes.infrastructure.vault-server-approle.role_name;
|
||||
client_key = "/var/lib/alloy/prometheus.key";
|
||||
client_cert = "/var/lib/alloy/prometheus.cert";
|
||||
in
|
||||
{
|
||||
options.khscodes.infrastructure.vault-prometheus-sender = {
|
||||
enable = lib.mkEnableOption "Configures the server approle to allow sending data to prometheus";
|
||||
terranixBackendName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "This should only be configured for the server hosting prometheus, to allow setting up dependencies in terraform";
|
||||
description = "This should only be configured for the server hosting vault, to allow setting up dependencies in terraform";
|
||||
default = "prometheus-mtls";
|
||||
};
|
||||
};
|
||||
|
@ -56,8 +58,8 @@ in
|
|||
{{ .Key }}
|
||||
{{ .Cert }}
|
||||
{{ .CA }}
|
||||
{{ .Key | writeToFile "${config.khscodes.services.alloy.prometheus.client_key}" "${config.khscodes.services.alloy.user}" "${config.khscodes.services.alloy.group}" "0600" }}
|
||||
{{ .Cert | writeToFile "${config.khscodes.services.alloy.prometheus.client_cert}" "${config.khscodes.services.alloy.user}" "${config.khscodes.services.alloy.group}" "0644" }}
|
||||
{{ .Key | writeToFile "${client_key}" "${config.khscodes.services.alloy.user}" "${config.khscodes.services.alloy.group}" "0600" }}
|
||||
{{ .Cert | writeToFile "${client_cert}" "${config.khscodes.services.alloy.user}" "${config.khscodes.services.alloy.group}" "0644" }}
|
||||
{{- end -}}
|
||||
'';
|
||||
destination = "/var/lib/alloy/cache.key";
|
||||
|
@ -69,10 +71,13 @@ in
|
|||
];
|
||||
khscodes.services.alloy = {
|
||||
enable = true;
|
||||
prometheus = {
|
||||
client_key = "/var/lib/alloy/prometheus_cert.key";
|
||||
client_cert = "/var/lib/alloy/prometheus_cert.pem";
|
||||
environment = {
|
||||
PROMETHEUS_CLIENT_KEY = client_key;
|
||||
PROMETHEUS_CLIENT_CERT = client_cert;
|
||||
};
|
||||
};
|
||||
environment.etc."alloy/prometheus.alloy" = {
|
||||
source = ./prometheus.alloy;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// This block relabels metrics coming from node_exporter to add standard labels
|
||||
discovery.relabel "integrations_node_exporter" {
|
||||
targets = prometheus.exporter.unix.integrations_node_exporter.targets
|
||||
|
||||
rule {
|
||||
// Set the instance label to the hostname of the machine
|
||||
target_label = "instance"
|
||||
replacement = constants.hostname
|
||||
}
|
||||
|
||||
rule {
|
||||
// Set a standard job name for all node_exporter metrics
|
||||
target_label = "job"
|
||||
replacement = "integrations/node_exporter"
|
||||
}
|
||||
}
|
||||
//
|
||||
// Configure the node_exporter integration to collect system metrics
|
||||
prometheus.exporter.unix "integrations_node_exporter" {
|
||||
// Disable unnecessary collectors to reduce overhead
|
||||
disable_collectors = ["ipvs", "btrfs", "infiniband", "xfs", "zfs"]
|
||||
enable_collectors = ["meminfo"]
|
||||
|
||||
filesystem {
|
||||
// Exclude filesystem types that aren't relevant for monitoring
|
||||
fs_types_exclude = "^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|tmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$"
|
||||
// Exclude mount points that aren't relevant for monitoring
|
||||
mount_points_exclude = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)"
|
||||
// Timeout for filesystem operations
|
||||
mount_timeout = "5s"
|
||||
}
|
||||
|
||||
netclass {
|
||||
// Ignore virtual and container network interfaces
|
||||
ignored_devices = "^(veth.*|cali.*|[a-f0-9]{15})$"
|
||||
}
|
||||
|
||||
netdev {
|
||||
// Exclude virtual and container network interfaces from device metrics
|
||||
device_exclude = "^(veth.*|cali.*|[a-f0-9]{15})$"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Define how to scrape metrics from the node_exporter
|
||||
prometheus.scrape "integrations_node_exporter" {
|
||||
scrape_interval = "15s"
|
||||
// Use the targets with labels from the discovery.relabel component
|
||||
targets = discovery.relabel.integrations_node_exporter.output
|
||||
// Send the scraped metrics to the relabeling component
|
||||
forward_to = [otelcol.receiver.prometheus.default.receiver]
|
||||
}
|
||||
|
||||
otelcol.receiver.prometheus "default" {
|
||||
output {
|
||||
metrics = [otelcol.exporter.otlphttp.default.input]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Define where to send the metrics for storage
|
||||
otelcol.exporter.otlphttp "default" {
|
||||
client {
|
||||
endpoint = "https://prometheus.kaareskovgaard.net/api/v1/otlp/"
|
||||
tls {
|
||||
cert_file = sys.env("PROMETHEUS_CLIENT_CERT")
|
||||
key_file = sys.env("PROMETHEUS_CLIENT_KEY")
|
||||
}
|
||||
}
|
||||
encoding = "proto"
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
}:
|
||||
let
|
||||
cfg = config.khscodes.infrastructure.vault-server-approle;
|
||||
vaultDomain = config.khscodes.infrastructure.openbao.domain;
|
||||
in
|
||||
{
|
||||
options.khscodes.infrastructure.vault-server-approle = {
|
||||
|
@ -18,6 +19,11 @@ in
|
|||
description = "The provisioning stage that should include the provisioning. This should be pre for every server except the OpenBAO server itself";
|
||||
default = "pre";
|
||||
};
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "approle";
|
||||
description = "Sets the path, as a terraform expression, for the approle to get created in. Not useful for most instances, but useful when doing bootstrapping, to establish a dependency.";
|
||||
};
|
||||
role_name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Name of the role being created";
|
||||
|
@ -52,18 +58,30 @@ in
|
|||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
khscodes.services.read-vault-auth-from-userdata.enable = true;
|
||||
khscodes.services.read-vault-auth-from-userdata.enable = cfg.stage == "pre";
|
||||
khscodes.services.vault-agent.enable = true;
|
||||
khscodes.infrastructure.provisioning.${cfg.stage} = {
|
||||
modules = [
|
||||
(
|
||||
{ config, ... }:
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
imports = [ inputs.self.terranixModules.vault ];
|
||||
output = lib.mkIf (cfg.stage == "post") {
|
||||
role-id = {
|
||||
value = config.khscodes.vault.output.approle_auth_backend_role.${cfg.role_name}.role_id;
|
||||
sensitive = false;
|
||||
};
|
||||
secret-id-wrapped = {
|
||||
value =
|
||||
config.khscodes.vault.output.approle_auth_backend_role_secret_id.${cfg.role_name}.wrapping_token;
|
||||
sensitive = true;
|
||||
};
|
||||
};
|
||||
khscodes.vault = {
|
||||
enable = true;
|
||||
domain = vaultDomain;
|
||||
approle_auth_backend_role.${cfg.role_name} = {
|
||||
backend = "approle";
|
||||
backend = cfg.path;
|
||||
role_name = cfg.role_name;
|
||||
# Secret IDs never expire, to allow vault agent to restart without issues.
|
||||
# TODO: Look into doing this in a better way going forward, such that this won't
|
||||
|
@ -76,7 +94,7 @@ in
|
|||
token_policies = [ cfg.role_name ];
|
||||
};
|
||||
approle_auth_backend_role_secret_id.${cfg.role_name} = {
|
||||
backend = "approle";
|
||||
backend = cfg.path;
|
||||
# Not hardcoding the role name here, as reading it like this will create a dependency
|
||||
# on the role being created first, which is needed.
|
||||
role_name = config.khscodes.vault.output.approle_auth_backend_role.${cfg.role_name}.role_name;
|
||||
|
|
25
nix/modules/nixos/machine/default.nix
Normal file
25
nix/modules/nixos/machine/default.nix
Normal file
|
@ -0,0 +1,25 @@
|
|||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.khscodes.machine;
|
||||
in
|
||||
rec {
|
||||
options.khscodes.machine = {
|
||||
type = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"server"
|
||||
"desktop"
|
||||
];
|
||||
description = "The kind of machine that is running";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
home-manager.sharedModules = [
|
||||
{
|
||||
inherit options;
|
||||
config = {
|
||||
khscodes.desktop.enable = cfg.type == "desktop";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
15
nix/modules/nixos/nix/default.nix
Normal file
15
nix/modules/nixos/nix/default.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.khscodes.nix;
|
||||
in
|
||||
{
|
||||
options.khscodes.nix = {
|
||||
nix-community.enable = lib.mkEnableOption "Enables nix-community substituters";
|
||||
};
|
||||
config = {
|
||||
nix.settings = lib.mkIf cfg.nix-community.enable {
|
||||
substituters = [ "https://nix-community.cachix.org" ];
|
||||
trusted-public-keys = [ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" ];
|
||||
};
|
||||
};
|
||||
}
|
55
nix/modules/nixos/os/auto-update/default.nix
Normal file
55
nix/modules/nixos/os/auto-update/default.nix
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.khscodes.os.auto-update;
|
||||
upgradePath = "/var/lib/system-upgrade";
|
||||
upgradeVersion = "/var/lib/system-upgrade.version";
|
||||
prepareUpgrade = pkgs.writeShellApplication {
|
||||
runtimeInputs = [
|
||||
pkgs.uutils-coreutils-noprefix
|
||||
pkgs.nix
|
||||
];
|
||||
name = "nixos-prepare-upgrade";
|
||||
text = ''
|
||||
|
||||
|
||||
current_version=""
|
||||
if [[ -f ${upgradeVersion} ]]; then
|
||||
current_version="$(cat ${upgradeVersion})"
|
||||
fi
|
||||
if [[ "$current_version" != "${inputs.self.outPath}" ]]; then
|
||||
rm -rf ${upgradePath}
|
||||
cp -r ${inputs.self.outPath} ${upgradePath}
|
||||
echo -n ${inputs.self.outPath} > ${upgradeVersion}
|
||||
fi
|
||||
cd ${upgradePath}
|
||||
NIX_CONFIG="extra-experimental-features=flake nix-command" nix flake update
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
options.khscodes.os.auto-update = {
|
||||
enable = lib.mkEnableOption "Enables automatic OS updates";
|
||||
dates = "02:00";
|
||||
randomizedDelaySec = "45min";
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
system.autoUpgrade = {
|
||||
enable = true;
|
||||
flake = upgradePath;
|
||||
};
|
||||
systemd.services.nixos-upgrade-prepare-flake = {
|
||||
wantedBy = [ "nixos-upgrade.service" ];
|
||||
before = [ "nixos-upgrade.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = lib.getExe prepareUpgrade;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
// This block relabels metrics coming from node_exporter to add standard labels
|
||||
discovery.relabel "integrations_node_exporter" {
|
||||
targets = prometheus.exporter.unix.integrations_node_exporter.targets
|
||||
|
||||
rule {
|
||||
// Set the instance label to the hostname of the machine
|
||||
target_label = "instance"
|
||||
replacement = constants.hostname
|
||||
}
|
||||
|
||||
rule {
|
||||
// Set a standard job name for all node_exporter metrics
|
||||
target_label = "job"
|
||||
replacement = "integrations/node_exporter"
|
||||
}
|
||||
}
|
||||
//
|
||||
// Configure the node_exporter integration to collect system metrics
|
||||
prometheus.exporter.unix "integrations_node_exporter" {
|
||||
// Disable unnecessary collectors to reduce overhead
|
||||
disable_collectors = ["ipvs", "btrfs", "infiniband", "xfs", "zfs"]
|
||||
enable_collectors = ["meminfo"]
|
||||
|
||||
filesystem {
|
||||
// Exclude filesystem types that aren't relevant for monitoring
|
||||
fs_types_exclude = "^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|tmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$"
|
||||
// Exclude mount points that aren't relevant for monitoring
|
||||
mount_points_exclude = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)"
|
||||
// Timeout for filesystem operations
|
||||
mount_timeout = "5s"
|
||||
}
|
||||
|
||||
netclass {
|
||||
// Ignore virtual and container network interfaces
|
||||
ignored_devices = "^(veth.*|cali.*|[a-f0-9]{15})$"
|
||||
}
|
||||
|
||||
netdev {
|
||||
// Exclude virtual and container network interfaces from device metrics
|
||||
device_exclude = "^(veth.*|cali.*|[a-f0-9]{15})$"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Define how to scrape metrics from the node_exporter
|
||||
prometheus.scrape "integrations_node_exporter" {
|
||||
scrape_interval = "15s"
|
||||
// Use the targets with labels from the discovery.relabel component
|
||||
targets = discovery.relabel.integrations_node_exporter.output
|
||||
// Send the scraped metrics to the relabeling component
|
||||
forward_to = [otelcol.receiver.prometheus.default.receiver]
|
||||
}
|
||||
|
||||
otelcol.receiver.prometheus "default" {
|
||||
output {
|
||||
metrics = [otelcol.exporter.otlphttp.default.input]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Define where to send the metrics for storage
|
||||
otelcol.exporter.otlphttp "default" {
|
||||
client {
|
||||
endpoint = "https://prometheus.kaareskovgaard.net/api/v1/otlp/"
|
||||
tls {
|
||||
cert_file = "$PROMETHEUS_CLIENT_CERT"
|
||||
key_file = "$PROMETHEUS_CLIENT_KEY"
|
||||
}
|
||||
}
|
||||
encoding = "proto"
|
||||
}
|
||||
|
||||
// Collect logs from systemd journal for node_exporter integration
|
||||
loki.source.journal "logs_integrations_integrations_node_exporter_journal_scrape" {
|
||||
// Only collect logs from the last 24 hours
|
||||
max_age = "24h0m0s"
|
||||
// Apply relabeling rules to the logs
|
||||
relabel_rules = discovery.relabel.logs_integrations_integrations_node_exporter_journal_scrape.rules
|
||||
// Send logs to the local Loki instance
|
||||
forward_to = [loki.write.local.receiver]
|
||||
}
|
||||
|
||||
// Define which log files to collect for node_exporter
|
||||
local.file_match "logs_integrations_integrations_node_exporter_direct_scrape" {
|
||||
path_targets = [{
|
||||
// Target localhost for log collection
|
||||
__address__ = "localhost",
|
||||
// Collect standard system logs
|
||||
__path__ = "/var/log/{syslog,messages,*.log}",
|
||||
// Add instance label with hostname
|
||||
instance = constants.hostname,
|
||||
// Add job label for logs
|
||||
job = "integrations/node_exporter",
|
||||
}]
|
||||
}
|
||||
|
||||
// Define relabeling rules for systemd journal logs
|
||||
discovery.relabel "logs_integrations_integrations_node_exporter_journal_scrape" {
|
||||
targets = []
|
||||
|
||||
rule {
|
||||
// Extract systemd unit information into a label
|
||||
source_labels = ["__journal__systemd_unit"]
|
||||
target_label = "unit"
|
||||
}
|
||||
|
||||
rule {
|
||||
// Extract boot ID information into a label
|
||||
source_labels = ["__journal__boot_id"]
|
||||
target_label = "boot_id"
|
||||
}
|
||||
|
||||
rule {
|
||||
// Extract transport information into a label
|
||||
source_labels = ["__journal__transport"]
|
||||
target_label = "transport"
|
||||
}
|
||||
|
||||
rule {
|
||||
// Extract log priority into a level label
|
||||
source_labels = ["__journal_priority_keyword"]
|
||||
target_label = "level"
|
||||
}
|
||||
|
||||
rule {
|
||||
// Set the instance label to the hostname of the machine
|
||||
target_label = "instance"
|
||||
replacement = constants.hostname
|
||||
}
|
||||
}
|
||||
|
||||
// Collect logs from files for node_exporter
|
||||
loki.source.file "logs_integrations_integrations_node_exporter_direct_scrape" {
|
||||
// Use targets defined in local.file_match
|
||||
targets = local.file_match.logs_integrations_integrations_node_exporter_direct_scrape.targets
|
||||
// Send logs to the local Loki instance
|
||||
forward_to = [loki.write.local.receiver]
|
||||
}
|
||||
|
||||
// Define where to send logs for storage
|
||||
loki.write "local" {
|
||||
endpoint {
|
||||
// Send logs to a locally running Loki instance
|
||||
url = "https://loki.kaareskovgaard.net/loki/api/v1/push"
|
||||
tls_config {
|
||||
cert_file = "$LOKI_CLIENT_CERT"
|
||||
key_file = "$LOKI_CLIENT_KEY"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +1,10 @@
|
|||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.khscodes.services.alloy;
|
||||
configFile =
|
||||
lib.strings.replaceStrings
|
||||
[ "$LOKI_CLIENT_KEY" "$LOKI_CLIENT_CERT" "$PROMETHEUS_CLIENT_KEY" "$PROMETHEUS_CLIENT_CERT" ]
|
||||
[ cfg.loki.client_key cfg.loki.client_cert cfg.prometheus.client_key cfg.prometheus.client_cert ]
|
||||
(builtins.readFile ./config.alloy);
|
||||
in
|
||||
{
|
||||
options.khscodes.services.alloy = {
|
||||
enable = lib.mkEnableOption "Enables alloy";
|
||||
loki = {
|
||||
client_key = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
client_cert = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
prometheus = {
|
||||
client_key = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
client_cert = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "alloy";
|
||||
|
@ -34,6 +13,10 @@ in
|
|||
type = lib.types.str;
|
||||
default = "alloy";
|
||||
};
|
||||
environment = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
@ -44,6 +27,7 @@ in
|
|||
User = "${cfg.user}";
|
||||
Group = "${cfg.group}";
|
||||
};
|
||||
environment = cfg.environment;
|
||||
};
|
||||
users.users.${cfg.user} = {
|
||||
description = "Alloy service user";
|
||||
|
@ -51,8 +35,5 @@ in
|
|||
group = cfg.group;
|
||||
};
|
||||
users.groups.${cfg.group} = { };
|
||||
environment.etc."alloy/config.alloy" = {
|
||||
text = configFile;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ in
|
|||
enable = lib.mkEnableOption "Enables openssh service for the instance";
|
||||
hostCertificate = {
|
||||
enable = lib.mkEnableOption "Enables getting host certificates from OpenBAO";
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "ssh-host";
|
||||
};
|
||||
hostNames = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = "The list of host names to get certificates for";
|
||||
|
@ -48,7 +52,7 @@ in
|
|||
{
|
||||
khscodes.vault.ssh_secret_backend_role.${vaultRoleName} = {
|
||||
name = fqdn;
|
||||
backend = sshHostBackend;
|
||||
backend = cfg.hostCertificate.path;
|
||||
key_type = "ca";
|
||||
allow_host_certificates = true;
|
||||
allow_bare_domains = true;
|
||||
|
|
|
@ -93,7 +93,7 @@ in
|
|||
address = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Address of the Vault/OpenBAO service";
|
||||
default = "https://vault.kaareskovgaard.net";
|
||||
default = "https://${config.khscodes.infrastructure.openbao.domain}";
|
||||
};
|
||||
roleIdFilePath = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
|
|
|
@ -5,6 +5,9 @@ in
|
|||
{
|
||||
options.khscodes.vault = {
|
||||
enable = lib.mkEnableOption "Enables the openbao provider";
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
policy = lib.mkOption {
|
||||
type = lib.types.attrsOf (
|
||||
lib.khscodes.mkSubmodule {
|
||||
|
@ -34,7 +37,7 @@ in
|
|||
|
||||
config = lib.mkIf cfg.enable {
|
||||
provider.vault = {
|
||||
address = "https://vault.kaareskovgaard.net";
|
||||
address = "https://${cfg.domain}";
|
||||
};
|
||||
terraform.required_providers.vault = {
|
||||
source = "hashicorp/vault";
|
||||
|
|
|
@ -18,15 +18,25 @@ in
|
|||
default = null;
|
||||
};
|
||||
default_lease_ttl_seconds = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
type = lib.types.nullOr lib.types.int;
|
||||
description = "Default lease ttl in seconds";
|
||||
default = null;
|
||||
};
|
||||
max_lease_ttl_seconds = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
type = lib.types.nullOr lib.types.int;
|
||||
description = "Max lease ttl in seconds";
|
||||
default = null;
|
||||
};
|
||||
options = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.attrs;
|
||||
description = "Options for the mount";
|
||||
default = null;
|
||||
};
|
||||
description = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "Usage description for the mount";
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
description = "vault_mount";
|
||||
}
|
||||
|
|
|
@ -13,11 +13,28 @@ in
|
|||
type = lib.types.str;
|
||||
description = "The name of the role. Can be used instead of hardcoding the role, to create a dependency in OpenTofu";
|
||||
};
|
||||
role_id = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "ID of the role";
|
||||
};
|
||||
};
|
||||
description = "vault_approle_auth_backend_role output";
|
||||
}
|
||||
);
|
||||
};
|
||||
approle_auth_backend_role_secret_id = lib.mkOption {
|
||||
type = lib.types.attrsOf (
|
||||
lib.khscodes.mkSubmodule {
|
||||
options = {
|
||||
wrapping_token = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "The generated wrapping token";
|
||||
};
|
||||
};
|
||||
description = "vault_approle_auth_backend_role_secret_id";
|
||||
}
|
||||
);
|
||||
};
|
||||
mount = lib.mkOption {
|
||||
type = lib.types.attrsOf (
|
||||
lib.khscodes.mkSubmodule {
|
||||
|
@ -41,8 +58,18 @@ in
|
|||
in
|
||||
{
|
||||
role_name = "\${ vault_approle_auth_backend_role.${sanitizedName}.role_name }";
|
||||
role_id = "\${ vault_approle_auth_backend_role.${sanitizedName}.role_id }";
|
||||
}
|
||||
) cfg.approle_auth_backend_role;
|
||||
khscodes.vault.output.approle_auth_backend_role_secret_id = lib.mapAttrs (
|
||||
name: value:
|
||||
let
|
||||
sanitizedName = lib.khscodes.sanitize-terraform-name name;
|
||||
in
|
||||
{
|
||||
wrapping_token = "\${ vault_approle_auth_backend_role_secret_id.${sanitizedName}.wrapping_token }";
|
||||
}
|
||||
) cfg.approle_auth_backend_role_secret_id;
|
||||
khscodes.vault.output.mount = lib.mapAttrs (
|
||||
name: value:
|
||||
let
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"AUTHENTIK_TOKEN" = "Admin API Token";
|
||||
"TF_VAR_authentik_username" = "login.username";
|
||||
};
|
||||
"vault.kaareskovgaard.net" = {
|
||||
"vault-test.kaareskovgaard.net" = {
|
||||
"VAULT_TOKEN" = "Initial root token";
|
||||
};
|
||||
}
|
||||
|
|
33
nix/packages/post-provisioning/default.nix
Normal file
33
nix/packages/post-provisioning/default.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
}:
|
||||
pkgs.writeShellApplication {
|
||||
name = "pre-provisioning";
|
||||
runtimeInputs = [
|
||||
pkgs.nix
|
||||
pkgs.khscodes.bw-opentofu
|
||||
pkgs.khscodes.instance-opentofu
|
||||
pkgs.khscodes.openbao-helper
|
||||
pkgs.jq
|
||||
];
|
||||
# TODO: Use secret source and required secrets to set up the correct env variables
|
||||
text = ''
|
||||
hostname="$1"
|
||||
cmd="''${2:-apply}"
|
||||
baseAttr='${inputs.self}#nixosConfigurations."'"$hostname"'".config.khscodes.infrastructure.provisioning'
|
||||
config="$(nix build --no-link --print-out-paths "''${baseAttr}.postConfig")"
|
||||
secretsSource="$(nix eval --raw "''${baseAttr}.post.secretsSource")"
|
||||
endpoints="$(nix eval --show-trace --json "''${baseAttr}.postEndpoints")"
|
||||
if [[ "$config" == "null" ]]; then
|
||||
echo "No preprovisioning needed"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$secretsSource" == "vault" ]]; then
|
||||
readarray -t endpoints_args < <(echo "$endpoints" | jq -cr 'map(["-e", .])[][]')
|
||||
openbao-helper wrap-program "''${endpoints_args[@]}" -- instance-opentofu "$hostname" "$config" "$cmd"
|
||||
exit 0
|
||||
fi
|
||||
bw-opentofu "$hostname" "$config" "$cmd"
|
||||
'';
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{ pkgs, ... }:
|
||||
{
|
||||
imports = [ ./khs-base.nix ];
|
||||
home.packages = [
|
||||
pkgs.bitwarden-cli
|
||||
pkgs.nerd-fonts.inconsolata
|
||||
pkgs.google-chrome
|
||||
];
|
||||
khscodes = {
|
||||
desktop.enable = true;
|
||||
};
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
{ ... }:
|
||||
{
|
||||
imports = [ ./nix-base.nix ];
|
||||
imports = [ ./khs-server.nix ];
|
||||
config.khscodes = {
|
||||
hetzner.enable = true;
|
||||
services.openssh.enable = true;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ pkgs, ... }:
|
||||
{ pkgs, config, ... }:
|
||||
{
|
||||
imports = [ ./nix-base.nix ];
|
||||
snowfallorg.users.khs.admin = true;
|
||||
|
@ -12,7 +12,7 @@
|
|||
environment = {
|
||||
systemPackages = [ pkgs.openbao ];
|
||||
variables = {
|
||||
BAO_ADDR = "https://vault.kaareskovgaard.net";
|
||||
BAO_ADDR = "https://${config.khscodes.infrastructure.openbao.domain}";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
{
|
||||
imports = [ ./khs-base.nix ];
|
||||
khscodes.virtualisation.qemu-guest.enableWhenVmTarget = true;
|
||||
khscodes.machine.type = "desktop";
|
||||
|
||||
services.desktopManager.cosmic.enable = true;
|
||||
services.displayManager.cosmic-greeter.enable = true;
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
{ lib, ... }:
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
imports = [ ./nix-base.nix ];
|
||||
config.khscodes = {
|
||||
services.openssh.enable = true;
|
||||
infrastructure = {
|
||||
vault-server-approle.enable = lib.mkDefault true;
|
||||
vault-loki-sender = lib.mkDefault true;
|
||||
config = {
|
||||
khscodes = {
|
||||
services.openssh.enable = true;
|
||||
machine.type = "server";
|
||||
os.auto-update.enable = true;
|
||||
infrastructure = {
|
||||
vault-server-approle.enable = lib.mkDefault true;
|
||||
vault-loki-sender.enable = lib.mkDefault true;
|
||||
};
|
||||
};
|
||||
stylix = {
|
||||
enable = true;
|
||||
autoEnable = false;
|
||||
base16Scheme = lib.mkDefault "${pkgs.base16-schemes}/share/themes/solarized-dark.yaml";
|
||||
targets.console.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# After creating the instance
|
||||
|
||||
Open https://vault.kaareskovgaard.net and initialize OpenBAO. Remember to get some sort of auto unsealing set up afterwards, currently this is implemented with a cronjob on TrueNAS. Doing it this way allows various certificates to continue getting issued, even as OpenBAO gets sealed (due to auto updates).
|
||||
|
||||
After this, run the post provisioning script to initialize the various OpenBAO parts needed. Then `nix run '.#bitwarden-to-vault` can transfer the needed Bitwarden secrets to vault.
|
|
@ -0,0 +1,61 @@
|
|||
# { config, ... }:
|
||||
# let
|
||||
# secretsFile = "/var/lib/authentik/authentik-env";
|
||||
# domain = "auth-test.kaareskovgaard.net";
|
||||
# in
|
||||
# {
|
||||
# config = {
|
||||
# khscodes.nix.nix-community.enable = true;
|
||||
# services.authentik = {
|
||||
# enable = true;
|
||||
# environmentFile = secretsFile;
|
||||
# settings = {
|
||||
# email = {
|
||||
# host = "smtp.soverin.net";
|
||||
# port = 587;
|
||||
# username = "kaare@kaareskovgaard.net";
|
||||
# use_tls = true;
|
||||
# use_ssl = false;
|
||||
# from = "kaare@kaareskovgaard.net";
|
||||
# };
|
||||
# disable_startup_analytics = true;
|
||||
# avatars = "initials";
|
||||
# };
|
||||
# };
|
||||
# khscodes.services.nginx.virtualHosts.${domain} = {
|
||||
# locations."/" = {
|
||||
# proxyPass = "https://localhost:9443";
|
||||
# recommendedProxySettings = true;
|
||||
# };
|
||||
# };
|
||||
# services.postgresqlBackup = {
|
||||
# enable = true;
|
||||
# databases = [ "authentik" ];
|
||||
# };
|
||||
|
||||
# systemd.services = {
|
||||
# authentik-migrate = {
|
||||
# unitConfig = {
|
||||
# ConditionPathExists = secretsFile;
|
||||
# };
|
||||
# };
|
||||
# authentik-worker = {
|
||||
# unitConfig = {
|
||||
# ConditionPathExists = secretsFile;
|
||||
# };
|
||||
# serviceConfig = {
|
||||
# LoadCredential = [
|
||||
# "${domain}.pem:${config.security.acme.certs.${domain}.directory}/fullchain.pem"
|
||||
# "${domain}.key:${config.security.acme.certs.${domain}.directory}/key.pem"
|
||||
# ];
|
||||
# };
|
||||
# };
|
||||
# authentik = {
|
||||
# unitConfig = {
|
||||
# ConditionPathExists = secretsFile;
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
# }
|
||||
{ }
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
"${inputs.self}/nix/profiles/nixos/hetzner-server.nix"
|
||||
./authentik.nix
|
||||
./openbao.nix
|
||||
./post/openbao
|
||||
];
|
||||
khscodes.services.nginx.enable = true;
|
||||
khscodes.infrastructure.hetzner-instance = {
|
||||
enable = true;
|
||||
server_type = "cax11";
|
||||
};
|
||||
virtualisation.vmVariant.virtualisation.host.pkgs = import inputs.nixpkgs {
|
||||
system = "aarch64-darwin";
|
||||
};
|
||||
# Cannot use vault for secrets source, as this is the server containing vault.
|
||||
khscodes.infrastructure.provisioning.pre.secretsSource = "bitwarden";
|
||||
khscodes.infrastructure.provisioning.post.secretsSource = "bitwarden";
|
||||
khscodes.infrastructure.vault-server-approle.stage = "post";
|
||||
khscodes.networking.fqdn = "security.kaareskovgaard.net";
|
||||
users.users.khs = {
|
||||
initialPassword = "changeme";
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqY0FHnWFKfLG2yfgr4qka5sR9CK+EMAhzlHUkaQyWHTKD+G0/vC/fNPyL1VV3Dxc/ajxGuPzVE+mBMoyxazL3EtuCDOVvHJ5CR+MUSEckg/DDwcGHqy6rC8BvVVpTAVL04ByQdwFnpE1qNSBaQLkxaFVdtriGKkgMkc7+UNeYX/bv7yn+APqfP1a3xr6wdkSSdO8x4N2jsSygOIMx10hLyCV4Ueu7Kp8Ww4rGY8j5o7lKJhbgfItBfSOuQHdppHVF/GKYRhdnK6Y2fZVYbhq4KipUtclbZ6O/VYd8/sOO98+LMm7cOX+K35PQjUpYgcoNy5+Sw3CNS/NHn4JvOtTaUEYP7fK6c9LhMULOO3T7Cm6TMdiFjUKHkyG+s2Mu/LXJJoilw571zwuh6chkeitW8+Ht7k0aPV96kNEvTdoXwLhBifVEaChlAsLAzSUjUq+YYCiXVk0VIXCZQWKj8LoVNTmaqDksWwbcT64fw/FpVC0N18WHbKcFUEIW/O4spJMa30CQwf9FeqpoWoaF1oRClCSDPvX0AauCu0JcmRinz1/JmlXljnXWbSfm20/V+WyvktlI0wTD0cdpNuSasT9vS77YfJ8nutcWWZKSkCj4R4uHeCNpDTX5YXzapy7FxpM9ANCXLIvoGX7Yafba2Po+er7SSsUIY1AsnBBr8ZoDVw=="
|
||||
];
|
||||
};
|
||||
khscodes.infrastructure.openbao.domain = "vault-test.kaareskovgaard.net";
|
||||
system.stateVersion = "25.05";
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
{ pkgs, config, ... }:
|
||||
let
|
||||
domain = "vault-test.kaareskovgaard.net";
|
||||
in
|
||||
{
|
||||
config = {
|
||||
services.openbao = {
|
||||
enable = true;
|
||||
package = pkgs.openbao;
|
||||
settings = {
|
||||
ui = true;
|
||||
listener.tcp = {
|
||||
type = "tcp";
|
||||
tls_cert_file = "${config.security.acme.certs.${domain}.directory}/fullchain.pem";
|
||||
tls_key_file = "${config.security.acme.certs.${domain}.directory}/key.pem";
|
||||
};
|
||||
api_addr = "https://${domain}";
|
||||
storage.postgresql.connection_url = "postgres://openbao?host=/run/postgresql";
|
||||
};
|
||||
};
|
||||
security.acme.certs.${domain}.reloadServices = [ "openbao.service" ];
|
||||
|
||||
systemd.services.openbao.after = [ "postgresql.service" ];
|
||||
|
||||
# Allow openbao to read the certificate file
|
||||
users.groups.nginx.members = [ "openbao" ];
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "openbao" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "openbao";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.postgresqlBackup = {
|
||||
enable = true;
|
||||
databases = [ "openbao" ];
|
||||
};
|
||||
|
||||
khscodes.services.nginx.virtualHosts.${domain} = {
|
||||
locations."/" = {
|
||||
proxyPass = "https://${config.services.openbao.settings.listener.tcp.address}/";
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
khscodes.infrastructure.vault-server-approle.path = "\${ vault_auth_backend.approle.path }";
|
||||
khscodes.infrastructure.provisioning.post.modules = [
|
||||
{
|
||||
resource.vault_auth_backend.approle = {
|
||||
type = "approle";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
imports = [
|
||||
./approle.nix
|
||||
./ssh-host.nix
|
||||
./loki-mtls.nix
|
||||
./prometheus-mtls.nix
|
||||
];
|
||||
khscodes.infrastructure.vault-server-approle.path = "\${ vault_auth_backend.approle.path }";
|
||||
khscodes.infrastructure.provisioning.post.modules = [
|
||||
(
|
||||
{ config, ... }:
|
||||
{
|
||||
khscodes.vault.mount.opentofu = {
|
||||
path = "opentofu";
|
||||
type = "kv";
|
||||
options = {
|
||||
version = "2";
|
||||
};
|
||||
description = "Secrets used during provisioning";
|
||||
};
|
||||
resource.vault_kv_secret_backend_v2.opentofu = {
|
||||
mount = config.khscodes.vault.output.mount.opentofu.path;
|
||||
max_versions = 5;
|
||||
cas_required = false;
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
# This should go into the setup of the vault server itself, as the vault server also needs stuff that depends on this.
|
||||
{
|
||||
khscodes.infrastructure.vault-loki-sender = {
|
||||
terranixBackendName = "\${ vault_mount.loki-mtls.path }";
|
||||
};
|
||||
khscodes.infrastructure.provisioning.post.modules = [
|
||||
(
|
||||
{ config, ... }:
|
||||
{
|
||||
khscodes.vault.enable = true;
|
||||
khscodes.vault.mount.loki-mtls = {
|
||||
type = "pki";
|
||||
path = "loki-mtls";
|
||||
max_lease_ttl_seconds = 10 * 365 * 24 * 60 * 60;
|
||||
default_lease_ttl_seconds = 60 * 60;
|
||||
};
|
||||
khscodes.vault.pki_secret_backend_root_cert.loki-mtls = {
|
||||
backend = config.khscodes.vault.output.mount.loki-mtls.path;
|
||||
type = "internal";
|
||||
common_name = "loki.kaareskovgaard.net";
|
||||
issuer_name = "loki-mtls-root-ca";
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
# This should go into the setup of the vault server itself, as the vault server also needs stuff that depends on this.
|
||||
{
|
||||
khscodes.infrastructure.vault-prometheus-sender = {
|
||||
# This is quite ugly, but should get the job done. Sadly I cannot reference the output from here.
|
||||
terranixBackendName = "\${ vault_mount.prometheus-mtls.path }";
|
||||
};
|
||||
khscodes.infrastructure.provisioning.post.modules = [
|
||||
(
|
||||
{ config, ... }:
|
||||
{
|
||||
khscodes.vault.enable = true;
|
||||
khscodes.vault.mount.prometheus-mtls = {
|
||||
type = "pki";
|
||||
path = "prometheus-mtls";
|
||||
max_lease_ttl_seconds = 10 * 365 * 24 * 60 * 60;
|
||||
default_lease_ttl_seconds = 60 * 60;
|
||||
};
|
||||
khscodes.vault.pki_secret_backend_root_cert.prometheus-mtls = {
|
||||
backend = config.khscodes.vault.output.mount.prometheus-mtls.path;
|
||||
type = "internal";
|
||||
common_name = "prometheus.kaareskovgaard.net";
|
||||
issuer_name = "prometheus-mtls-root-ca";
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
khscodes.services.openssh.hostCertificate.path = "\${ vault_mount.ssh-host.path }";
|
||||
khscodes.infrastructure.provisioning.post.modules = [
|
||||
(
|
||||
{ config, ... }:
|
||||
{
|
||||
khscodes.vault.mount.ssh-host = {
|
||||
type = "ssh";
|
||||
path = "ssh-host";
|
||||
default_lease_ttl_seconds = 24 * 60 * 60;
|
||||
max_lease_ttl_seconds = 24 * 60 * 60;
|
||||
};
|
||||
|
||||
resource.vault_ssh_secret_backend_ca.ssh-host = {
|
||||
backend = config.khscodes.vault.output.mount.ssh-host.path;
|
||||
generate_signing_key = true;
|
||||
key_type = "ed25519";
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
|
@ -10,5 +10,11 @@
|
|||
device = "/dev/sda";
|
||||
diskName = "nixos";
|
||||
};
|
||||
users.users.khs = {
|
||||
initialPassword = "changeme";
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqY0FHnWFKfLG2yfgr4qka5sR9CK+EMAhzlHUkaQyWHTKD+G0/vC/fNPyL1VV3Dxc/ajxGuPzVE+mBMoyxazL3EtuCDOVvHJ5CR+MUSEckg/DDwcGHqy6rC8BvVVpTAVL04ByQdwFnpE1qNSBaQLkxaFVdtriGKkgMkc7+UNeYX/bv7yn+APqfP1a3xr6wdkSSdO8x4N2jsSygOIMx10hLyCV4Ueu7Kp8Ww4rGY8j5o7lKJhbgfItBfSOuQHdppHVF/GKYRhdnK6Y2fZVYbhq4KipUtclbZ6O/VYd8/sOO98+LMm7cOX+K35PQjUpYgcoNy5+Sw3CNS/NHn4JvOtTaUEYP7fK6c9LhMULOO3T7Cm6TMdiFjUKHkyG+s2Mu/LXJJoilw571zwuh6chkeitW8+Ht7k0aPV96kNEvTdoXwLhBifVEaChlAsLAzSUjUq+YYCiXVk0VIXCZQWKj8LoVNTmaqDksWwbcT64fw/FpVC0N18WHbKcFUEIW/O4spJMa30CQwf9FeqpoWoaF1oRClCSDPvX0AauCu0JcmRinz1/JmlXljnXWbSfm20/V+WyvktlI0wTD0cdpNuSasT9vS77YfJ8nutcWWZKSkCj4R4uHeCNpDTX5YXzapy7FxpM9ANCXLIvoGX7Yafba2Po+er7SSsUIY1AsnBBr8ZoDVw=="
|
||||
];
|
||||
};
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue