Test bringing up openstack instance
This commit is contained in:
parent
ea031511cf
commit
748e1763ad
24 changed files with 932 additions and 99 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,6 +1,4 @@
|
||||||
.direnv/
|
.direnv/
|
||||||
result/
|
result/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.terraform-cache/*/*/config.tf.json
|
|
||||||
.terraform-cache/*/*/.terraform
|
|
||||||
rust/target
|
rust/target
|
||||||
|
|
47
.terraform-cache/khs.codes/pre/.terraform.lock.hcl
generated
47
.terraform-cache/khs.codes/pre/.terraform.lock.hcl
generated
|
@ -1,47 +0,0 @@
|
||||||
# This file is maintained automatically by "tofu init".
|
|
||||||
# Manual edits may be lost in future updates.
|
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
|
||||||
version = "4.52.0"
|
|
||||||
constraints = "~> 4.0"
|
|
||||||
hashes = [
|
|
||||||
"h1:Pi5M+GeoMSN2eJ6QnIeXjBf19O+rby/74CfB2ocpv20=",
|
|
||||||
"zh:19be1a91c982b902c42aba47766860dfa5dc151eed1e95fd39ca642229381ef0",
|
|
||||||
"zh:1de451c4d1ecf7efbe67b6dace3426ba810711afdd644b0f1b870364c8ae91f8",
|
|
||||||
"zh:352b4a2120173298622e669258744554339d959ac3a95607b117a48ee4a83238",
|
|
||||||
"zh:3c6f1346d9154afbd2d558fabb4b0150fc8d559aa961254144fe1bc17fe6032f",
|
|
||||||
"zh:4c4c92d53fb535b1e0eff26f222bbd627b97d3b4c891ec9c321268676d06152f",
|
|
||||||
"zh:53276f68006c9ceb7cdb10a6ccf91a5c1eadd1407a28edb5741e84e88d7e29e8",
|
|
||||||
"zh:7925a97773948171a63d4f65bb81ee92fd6d07a447e36012977313293a5435c9",
|
|
||||||
"zh:7dfb0a4496cfe032437386d0a2cd9229a1956e9c30bd920923c141b0f0440060",
|
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
|
||||||
"zh:8d4aa79f0a414bb4163d771063c70cd991c8fac6c766e685bac2ee12903c5bd6",
|
|
||||||
"zh:a67540c13565616a7e7e51ee9366e88b0dc60046e1d75c72680e150bd02725bb",
|
|
||||||
"zh:a936383a4767f5393f38f622e92bf2d0c03fe04b69c284951f27345766c7b31b",
|
|
||||||
"zh:d4887d73c466ff036eecf50ad6404ba38fd82ea4855296b1846d244b0f13c380",
|
|
||||||
"zh:e9093c8bd5b6cd99c81666e315197791781b8f93afa14fc2e0f732d1bb2a44b7",
|
|
||||||
"zh:efd3b3f1ec59a37f635aa1d4efcf178734c2fcf8ddb0d56ea690bec342da8672",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
provider "registry.opentofu.org/hetznercloud/hcloud" {
|
|
||||||
version = "1.45.0"
|
|
||||||
constraints = "~> 1.45.0"
|
|
||||||
hashes = [
|
|
||||||
"h1:dh2iL5GHfDui5DbZFD/kcWlwzmC6slgUirA0FbZBK7g=",
|
|
||||||
"zh:1c4b44a698cfaca215bdbadaf92669dd23533210c3cbf32895fbf4ff7acf6c24",
|
|
||||||
"zh:2915f8385559694e5097d8d0df16358200e9f0d9efb80559e9ea0bd072d792b9",
|
|
||||||
"zh:3a6b37b0bba50d263bd3dba26185bde13c825e59b6b301ab3f9f45686a21456b",
|
|
||||||
"zh:3e3910fa22a3a8d73d1aed38cc479c3e1958e9168b5f4a7d0da6cf03c2dfc155",
|
|
||||||
"zh:3f8d7d09e5c93162a1e9e6c89acac0799fb55765b44b7d1d020763c814263c57",
|
|
||||||
"zh:40bc5e94bff495440e1b4f797165d7f0dcee2282a86a61b158f47fe4bc57e9fb",
|
|
||||||
"zh:473f51d464b897d0e8e3d5ca2eb175b37e2f7ce03c8b26f47cc35885cf620946",
|
|
||||||
"zh:6fdd4bf71c19cfad78d7e1d2336be873eb8567a139d53e672e78ebcbc36a4d7d",
|
|
||||||
"zh:9e08638cbfc90d69f1c21ee34191db077d58d040cf7a9eed07a1dc335d463e97",
|
|
||||||
"zh:b1ed5ea81bc6d2c88efdefaeb244322874508d90d8217ac2e3541445254bdadc",
|
|
||||||
"zh:ced05776c27d550d15d4a71360243740ecb4ea1e65e67229fb2273a27353b00c",
|
|
||||||
"zh:da79b8a1a982a1d365ea206a2654e8b5003aeba9ccdc9c8751bb6ee3f40d8c49",
|
|
||||||
"zh:fabbad25bab09dd74f2b819992ab99b939c642374d6ca080b18d6e2a91d8d487",
|
|
||||||
"zh:fb0e083d2925f289999dc561ef1c2f84a9e0ab11388c40162ca8b470f50f71f5",
|
|
||||||
]
|
|
||||||
}
|
|
12
flake.nix
12
flake.nix
|
@ -86,5 +86,17 @@
|
||||||
inherit inputs;
|
inherit inputs;
|
||||||
khscodesLib = inputs.self.lib;
|
khscodesLib = inputs.self.lib;
|
||||||
};
|
};
|
||||||
|
terranixModules.s3 = import ./nix/modules/terranix/s3 {
|
||||||
|
inherit inputs;
|
||||||
|
khscodesLib = inputs.self.lib;
|
||||||
|
};
|
||||||
|
terranixModules.openstack = import ./nix/modules/terranix/openstack {
|
||||||
|
inherit inputs;
|
||||||
|
khscodesLib = inputs.self.lib;
|
||||||
|
};
|
||||||
|
terranixModules.unifi = import ./nix/modules/terranix/unifi {
|
||||||
|
inherit inputs;
|
||||||
|
khscodesLib = inputs.self.lib;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sanitize-terraform-name = name: builtins.replaceStrings [ "." ] [ "_" ] name;
|
sanitize-terraform-name = name: builtins.replaceStrings [ "." ":" "/" ] [ "_" "_" "_" ] name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
inputs,
|
inputs,
|
||||||
pkgs,
|
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
@ -75,11 +74,6 @@ in
|
||||||
description = "The Hetzner datacenter to create a server in";
|
description = "The Hetzner datacenter to create a server in";
|
||||||
default = "hel1-dc2";
|
default = "hel1-dc2";
|
||||||
};
|
};
|
||||||
output = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.package;
|
|
||||||
description = "The terranix package built from the configuration";
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
mapRdns = lib.mkOption {
|
mapRdns = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
description = "Sets up RDNS for the server";
|
description = "Sets up RDNS for the server";
|
||||||
|
@ -148,23 +142,13 @@ in
|
||||||
imports = [
|
imports = [
|
||||||
inputs.self.terranixModules.cloudflare
|
inputs.self.terranixModules.cloudflare
|
||||||
inputs.self.terranixModules.hcloud
|
inputs.self.terranixModules.hcloud
|
||||||
|
inputs.self.terranixModules.s3
|
||||||
];
|
];
|
||||||
config = {
|
config = {
|
||||||
terraform.backend.s3 = {
|
khscodes.s3 = {
|
||||||
bucket = "bw-terraform";
|
enable = true;
|
||||||
key = cfg.bucket.key;
|
bucket.key = cfg.bucket.key;
|
||||||
region = "auto";
|
|
||||||
endpoints = {
|
|
||||||
s3 = "https://477b394a6a545699445c40953e40f00b.r2.cloudflarestorage.com";
|
|
||||||
};
|
};
|
||||||
use_path_style = true;
|
|
||||||
skip_credentials_validation = true;
|
|
||||||
skip_region_validation = true;
|
|
||||||
skip_metadata_api_check = true;
|
|
||||||
skip_requesting_account_id = true;
|
|
||||||
skip_s3_checksum = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
khscodes.hcloud.data.ssh_key.khs = {
|
khscodes.hcloud.data.ssh_key.khs = {
|
||||||
name = "ca.kaareskovgaard.net";
|
name = "ca.kaareskovgaard.net";
|
||||||
};
|
};
|
||||||
|
@ -229,7 +213,7 @@ in
|
||||||
khscodes.provisioning.pre = {
|
khscodes.provisioning.pre = {
|
||||||
modules = modules;
|
modules = modules;
|
||||||
secretsSource = cfg.secretsSource;
|
secretsSource = cfg.secretsSource;
|
||||||
endspoints = [
|
endpoints = [
|
||||||
"aws"
|
"aws"
|
||||||
"cloudflare"
|
"cloudflare"
|
||||||
"hcloud"
|
"hcloud"
|
||||||
|
|
245
nix/modules/nixos/khs-openstack-instance/default.nix
Normal file
245
nix/modules/nixos/khs-openstack-instance/default.nix
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.khscodes.khs-openstack-instance;
|
||||||
|
fqdn = config.khscodes.fqdn;
|
||||||
|
firewallTcpRules = lib.lists.flatten (
|
||||||
|
lib.lists.map (p: [
|
||||||
|
{
|
||||||
|
direction = "ingress";
|
||||||
|
ethertype = "IPv4";
|
||||||
|
protocol = "tcp";
|
||||||
|
port = p;
|
||||||
|
remote_subnet = "0.0.0.0/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "ingress";
|
||||||
|
ethertype = "IPv6";
|
||||||
|
protocol = "tcp";
|
||||||
|
port = p;
|
||||||
|
remote_subnet = "::/0";
|
||||||
|
}
|
||||||
|
]) config.networking.firewall.allowedTCPPorts
|
||||||
|
);
|
||||||
|
firewallUdpRules = lib.lists.flatten (
|
||||||
|
lib.lists.map (p: [
|
||||||
|
{
|
||||||
|
direction = "ingress";
|
||||||
|
ethertype = "IPv4";
|
||||||
|
protocol = "udp";
|
||||||
|
port = p;
|
||||||
|
remote_subnet = "0.0.0.0/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "ingress";
|
||||||
|
ethertype = "IPv6";
|
||||||
|
protocol = "udp";
|
||||||
|
port = p;
|
||||||
|
remote_subnet = "::/0";
|
||||||
|
}
|
||||||
|
]) config.networking.firewall.allowedUDPPorts
|
||||||
|
);
|
||||||
|
firewallIcmpRules = lib.lists.optionals config.networking.firewall.allowPing [
|
||||||
|
{
|
||||||
|
direction = "ingress";
|
||||||
|
ethertype = "IPv4";
|
||||||
|
protocol = "icmp";
|
||||||
|
remote_subnet = "0.0.0.0/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "ingress";
|
||||||
|
ethertype = "IPv6";
|
||||||
|
protocol = "icmp";
|
||||||
|
remote_subnet = "::/0";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
firewallRules = firewallTcpRules ++ firewallUdpRules ++ firewallIcmpRules ++ cfg.extraFirewallRules;
|
||||||
|
tldFromFqdn =
|
||||||
|
fqdn:
|
||||||
|
let
|
||||||
|
split = lib.strings.splitString "." fqdn;
|
||||||
|
in
|
||||||
|
if lib.lists.length split < 3 then
|
||||||
|
fqdn
|
||||||
|
else
|
||||||
|
lib.strings.removePrefix "${builtins.head split}." fqdn;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.khscodes.khs-openstack-instance = {
|
||||||
|
enable = lib.mkEnableOption "enables generating a opentofu config for khs openstack instance";
|
||||||
|
dnsNames = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
description = "DNS names for the instance";
|
||||||
|
default = [ fqdn ];
|
||||||
|
};
|
||||||
|
bucket = {
|
||||||
|
key = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Key for use in the bucket";
|
||||||
|
default = "${fqdn}.tfstate";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
secretsSource = lib.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"bitwarden"
|
||||||
|
"vault"
|
||||||
|
];
|
||||||
|
description = "Whether to load opentofu secrets from Bitwarden or Vault";
|
||||||
|
default = "vault";
|
||||||
|
};
|
||||||
|
flavor = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
description = "The server type to create";
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
ssh_key = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "SSH key for the server (this only applies to the initial creation, deploying NixOS will render this key useless). Changing this will recreate the instance";
|
||||||
|
default = "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==";
|
||||||
|
};
|
||||||
|
extraFirewallRules = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.attrs;
|
||||||
|
description = "Extra firewall rules added to the instance";
|
||||||
|
default = [
|
||||||
|
{
|
||||||
|
direction = "egress";
|
||||||
|
ethertype = "IPv4";
|
||||||
|
protocol = "tcp";
|
||||||
|
port = 80;
|
||||||
|
remote_subnet = "0.0.0.0/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "egress";
|
||||||
|
ethertype = "IPv6";
|
||||||
|
protocol = "tcp";
|
||||||
|
port = 80;
|
||||||
|
remote_subnet = "::/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "egress";
|
||||||
|
ethertype = "IPv4";
|
||||||
|
protocol = "tcp";
|
||||||
|
port = 443;
|
||||||
|
remote_subnet = "0.0.0.0/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "egress";
|
||||||
|
ethertype = "IPv6";
|
||||||
|
protocol = "tcp";
|
||||||
|
port = 443;
|
||||||
|
remote_subnet = "::/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "egress";
|
||||||
|
ethertype = "IPv4";
|
||||||
|
protocol = "udp";
|
||||||
|
port = 443;
|
||||||
|
remote_subnet = "0.0.0.0/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "egress";
|
||||||
|
ethertype = "IPv6";
|
||||||
|
protocol = "udp";
|
||||||
|
port = 443;
|
||||||
|
remote_subnet = "::/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "egress";
|
||||||
|
ethertype = "IPv4";
|
||||||
|
protocol = "icmp";
|
||||||
|
remote_subnet = "0.0.0.0/0";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
direction = "egress";
|
||||||
|
ethertype = "IPv6";
|
||||||
|
protocol = "icmp";
|
||||||
|
remote_subnet = "::/0";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable (
|
||||||
|
let
|
||||||
|
tags = [ fqdn ];
|
||||||
|
modules = [
|
||||||
|
(
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
inputs.self.terranixModules.cloudflare
|
||||||
|
inputs.self.terranixModules.openstack
|
||||||
|
inputs.self.terranixModules.unifi
|
||||||
|
inputs.self.terranixModules.s3
|
||||||
|
];
|
||||||
|
config = {
|
||||||
|
khscodes.s3 = {
|
||||||
|
enable = true;
|
||||||
|
bucket.key = cfg.bucket.key;
|
||||||
|
};
|
||||||
|
khscodes.openstack.enable = true;
|
||||||
|
khscodes.openstack.compute_instance.compute = {
|
||||||
|
inherit tags;
|
||||||
|
name = fqdn;
|
||||||
|
initial_image = "Ubuntu-22.04";
|
||||||
|
flavor = cfg.flavor;
|
||||||
|
ssh_public_key = cfg.ssh_key;
|
||||||
|
firewall_rules = firewallRules;
|
||||||
|
};
|
||||||
|
khscodes.cloudflare = {
|
||||||
|
enable = true;
|
||||||
|
dns = {
|
||||||
|
enable = true;
|
||||||
|
zone_name = tldFromFqdn fqdn;
|
||||||
|
aRecords = [
|
||||||
|
{
|
||||||
|
inherit fqdn;
|
||||||
|
content = config.khscodes.openstack.output.compute_instance.compute.ipv4_address;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
aaaaRecords = [
|
||||||
|
{
|
||||||
|
inherit fqdn;
|
||||||
|
content = config.khscodes.openstack.output.compute_instance.compute.ipv6_address;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
output.ipv4_address = {
|
||||||
|
value = config.khscodes.openstack.output.compute_instance.compute.ipv4_address;
|
||||||
|
sensitive = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
output.ipv6_address = {
|
||||||
|
value = config.khscodes.openstack.output.compute_instance.compute.ipv6_address;
|
||||||
|
sensitive = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = config.khscodes.fqdn != null;
|
||||||
|
message = "Must set config.khscodes.fqdn when using opentofu";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
khscodes.provisioning.pre = {
|
||||||
|
modules = modules;
|
||||||
|
secretsSource = cfg.secretsSource;
|
||||||
|
endpoints = [
|
||||||
|
"aws"
|
||||||
|
"cloudflare"
|
||||||
|
"openstack"
|
||||||
|
"unifi"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
1
nix/modules/nixos/openstack/default.nix
Normal file
1
nix/modules/nixos/openstack/default.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{ ... }: { }
|
|
@ -21,7 +21,7 @@ let
|
||||||
description = "Where to get the secrets for the provisioning from";
|
description = "Where to get the secrets for the provisioning from";
|
||||||
default = "vault";
|
default = "vault";
|
||||||
};
|
};
|
||||||
endspoints = lib.mkOption {
|
endpoints = lib.mkOption {
|
||||||
type = lib.types.listOf (
|
type = lib.types.listOf (
|
||||||
lib.types.enum [
|
lib.types.enum [
|
||||||
"openstack"
|
"openstack"
|
||||||
|
|
|
@ -88,7 +88,7 @@ in
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
hcloud.enable = true;
|
hcloud.enable = true;
|
||||||
terraform.required_providers.hcloud.version = "~> 1.45.0";
|
terraform.required_providers.hcloud.version = "~> 1.51.0";
|
||||||
resource.hcloud_server = mapSanitizedAttrs (
|
resource.hcloud_server = mapSanitizedAttrs (
|
||||||
{ name, value }:
|
{ name, value }:
|
||||||
{
|
{
|
||||||
|
|
454
nix/modules/terranix/openstack/default.nix
Normal file
454
nix/modules/terranix/openstack/default.nix
Normal file
|
@ -0,0 +1,454 @@
|
||||||
|
{ khscodesLib, inputs }:
|
||||||
|
{ lib, config, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.khscodes.openstack;
|
||||||
|
modules = [
|
||||||
|
./output.nix
|
||||||
|
];
|
||||||
|
firewallRuleModule = khscodesLib.mkSubmodule {
|
||||||
|
description = "Firewall rule";
|
||||||
|
options = {
|
||||||
|
direction = lib.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"ingress"
|
||||||
|
"egress"
|
||||||
|
];
|
||||||
|
description = "The direction of the firewall rule";
|
||||||
|
};
|
||||||
|
ethertype = lib.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"IPv4"
|
||||||
|
"IPv6"
|
||||||
|
];
|
||||||
|
description = "The IP version";
|
||||||
|
};
|
||||||
|
protocol = lib.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"tcp"
|
||||||
|
"udp"
|
||||||
|
"icmp"
|
||||||
|
];
|
||||||
|
description = "The protocol";
|
||||||
|
};
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
description = "The port (for udp and tcp rules) to apply the rule to";
|
||||||
|
};
|
||||||
|
remote_subnet = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "The remote subnet to apply the rule to";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
mapFirewallRule =
|
||||||
|
security_group_id: rule:
|
||||||
|
{
|
||||||
|
inherit (rule) direction ethertype;
|
||||||
|
inherit security_group_id;
|
||||||
|
protocol =
|
||||||
|
if rule.ethertype == "IPv6" && rule.protocol == "icmp" then "ipv6-icmp" else rule.protocol;
|
||||||
|
remote_ip_prefix = rule.remote_subnet;
|
||||||
|
}
|
||||||
|
// (lib.attrsets.optionalAttrs (rule.protocol != "icmp") {
|
||||||
|
port_range_min = rule.port;
|
||||||
|
port_range_max = rule.port;
|
||||||
|
});
|
||||||
|
openstackComputeInstance = khscodesLib.mkSubmodule {
|
||||||
|
description = "Openstack compute instance";
|
||||||
|
options = {
|
||||||
|
name = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Name of the instance";
|
||||||
|
};
|
||||||
|
flavor = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Flavor of the instance";
|
||||||
|
};
|
||||||
|
initial_image = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Initial image of the server";
|
||||||
|
};
|
||||||
|
ssh_public_key = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "The ssh key added to the server";
|
||||||
|
};
|
||||||
|
ip4_cidr = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "IPv4 cidr of the private virtual network";
|
||||||
|
default = "172.24.0.0/24";
|
||||||
|
};
|
||||||
|
ip4_dns_nameservers = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
description = "DNS (IPv4) nameservers to set (in DHCP) for the ipv4 subnet";
|
||||||
|
default = [
|
||||||
|
"1.1.1.1"
|
||||||
|
"1.0.0.1"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
volume_size = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
description = "Size of the root volume, in gigabytes";
|
||||||
|
default = 30;
|
||||||
|
};
|
||||||
|
volume_type = lib.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"Encrypted"
|
||||||
|
"__DEFAULT__"
|
||||||
|
];
|
||||||
|
description = "The type of volume to create";
|
||||||
|
default = "Encrypted";
|
||||||
|
};
|
||||||
|
ip6_dns_nameservers = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
description = "DNS (IPv6) nameservers to set (in DHCP) for the ipv4 subnet";
|
||||||
|
default = [
|
||||||
|
"2606:4700:4700::1111"
|
||||||
|
"2606:4700:4700::1001"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
tags = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
};
|
||||||
|
firewall_rules = lib.mkOption {
|
||||||
|
type = lib.types.listOf firewallRuleModule;
|
||||||
|
description = "List of firewall rules to apply to the server";
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.khscodes.openstack = {
|
||||||
|
enable = lib.mkEnableOption "Enables the openstack provider";
|
||||||
|
compute_instance = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf openstackComputeInstance;
|
||||||
|
description = "Defines an openstack compute instance";
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
imports = lib.lists.map (m: import m { inherit khscodesLib inputs; }) modules;
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
terraform.required_providers.openstack = {
|
||||||
|
source = "terraform-provider-openstack/openstack";
|
||||||
|
version = "~> 3.2.0";
|
||||||
|
};
|
||||||
|
provider.openstack = {
|
||||||
|
user_name = "\${ var.openstack_username }";
|
||||||
|
tenant_name = "\${ var.openstack_tenant_name }";
|
||||||
|
password = "\${ var.openstack_password }";
|
||||||
|
auth_url = "\${ var.openstack_auth_url }";
|
||||||
|
region = "\${ var.openstack_region }";
|
||||||
|
endpoint_type = "\${ var.openstack_endpoint_type }";
|
||||||
|
};
|
||||||
|
variable = {
|
||||||
|
openstack_username = {
|
||||||
|
type = "string";
|
||||||
|
};
|
||||||
|
openstack_password = {
|
||||||
|
type = "string";
|
||||||
|
sensitive = true;
|
||||||
|
};
|
||||||
|
openstack_tenant_name = {
|
||||||
|
type = "string";
|
||||||
|
};
|
||||||
|
openstack_auth_url = {
|
||||||
|
type = "string";
|
||||||
|
};
|
||||||
|
openstack_endpoint_type = {
|
||||||
|
type = "string";
|
||||||
|
};
|
||||||
|
openstack_region = {
|
||||||
|
type = "string";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# DATA
|
||||||
|
|
||||||
|
# flavor
|
||||||
|
data.openstack_compute_flavor_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
name = value.flavor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# image
|
||||||
|
data.openstack_images_image_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
name = value.initial_image;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# provider network
|
||||||
|
data.openstack_networking_network_v2.provider = {
|
||||||
|
name = "public";
|
||||||
|
};
|
||||||
|
|
||||||
|
# provider subnet pool (for ipv6)
|
||||||
|
data.openstack_networking_subnetpool_v2.provider = {
|
||||||
|
name = "provider-subnet-pool";
|
||||||
|
};
|
||||||
|
|
||||||
|
# RESOURCE
|
||||||
|
|
||||||
|
# keypair
|
||||||
|
resource.openstack_compute_keypair_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
name = khscodesLib.sanitize-terraform-name value.name;
|
||||||
|
public_key = value.ssh_public_key;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# router
|
||||||
|
resource.openstack_networking_router_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
name = value.name;
|
||||||
|
external_network_id = "\${ data.openstack_networking_network_v2.provider.id }";
|
||||||
|
tags = value.tags;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# network
|
||||||
|
resource.openstack_networking_network_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
name = value.name;
|
||||||
|
tags = value.tags;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# subnet
|
||||||
|
resource.openstack_networking_subnet_v2 =
|
||||||
|
(lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "${sanitizedName}_ip4";
|
||||||
|
value = {
|
||||||
|
name = "ip4: ${value.name}";
|
||||||
|
cidr = value.ip4_cidr;
|
||||||
|
ip_version = 4;
|
||||||
|
network_id = "\${ openstack_networking_network_v2.${sanitizedName}.id }";
|
||||||
|
dns_nameservers = value.ip4_dns_nameservers;
|
||||||
|
tags = value.tags;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance)
|
||||||
|
// (lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "${sanitizedName}_ip6";
|
||||||
|
value = {
|
||||||
|
name = "ip6: ${value.name}";
|
||||||
|
ip_version = 6;
|
||||||
|
ipv6_address_mode = "dhcpv6-stateless";
|
||||||
|
ipv6_ra_mode = "dhcpv6-stateless";
|
||||||
|
subnetpool_id = "\${ data.openstack_networking_subnetpool_v2.provider.id }";
|
||||||
|
dns_nameservers = value.ip6_dns_nameservers;
|
||||||
|
network_id = "\${ openstack_networking_network_v2.${sanitizedName}.id }";
|
||||||
|
tags = value.tags;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance);
|
||||||
|
|
||||||
|
# router interface
|
||||||
|
resource.openstack_networking_router_interface_v2 =
|
||||||
|
(lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "${sanitizedName}_ip4";
|
||||||
|
value = {
|
||||||
|
router_id = "\${ openstack_networking_router_v2.${sanitizedName}.id }";
|
||||||
|
subnet_id = "\${ openstack_networking_subnet_v2.${sanitizedName}_ip4.id }";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance)
|
||||||
|
// (lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "${sanitizedName}_ip6";
|
||||||
|
value = {
|
||||||
|
router_id = "\${ openstack_networking_router_v2.${sanitizedName}.id }";
|
||||||
|
subnet_id = "\${ openstack_networking_subnet_v2.${sanitizedName}_ip6.id }";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance);
|
||||||
|
|
||||||
|
# floating ip
|
||||||
|
resource.openstack_networking_floatingip_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
pool = "public";
|
||||||
|
tags = value.tags;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# volume
|
||||||
|
resource.openstack_blockstorage_volume_v3 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
name = value.name;
|
||||||
|
size = value.volume_size;
|
||||||
|
image_id = "\${ data.openstack_images_image_v2.${sanitizedName}.id }";
|
||||||
|
volume_type = value.volume_type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# security group
|
||||||
|
resource.openstack_networking_secgroup_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
name = value.name;
|
||||||
|
tags = value.tags;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# security group rules (firewall rules)
|
||||||
|
resource.openstack_networking_secgroup_rule_v2 = lib.attrsets.mergeAttrsList (
|
||||||
|
lib.lists.flatten (
|
||||||
|
lib.lists.map (
|
||||||
|
{ name, value }:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
lib.listToAttrs (
|
||||||
|
lib.lists.map (
|
||||||
|
rule:
|
||||||
|
let
|
||||||
|
protocol =
|
||||||
|
if rule.protocol == "icmp" then "icmp" else "${rule.protocol}_${builtins.toString rule.port}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "${sanitizedName}_${rule.direction}_${rule.ethertype}_${protocol}_${khscodesLib.sanitize-terraform-name rule.remote_subnet}";
|
||||||
|
value = mapFirewallRule "\${ resource.openstack_networking_secgroup_v2.${sanitizedName}.id }" rule;
|
||||||
|
}
|
||||||
|
) value.firewall_rules
|
||||||
|
)
|
||||||
|
) (lib.attrsToList cfg.compute_instance)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
# instance
|
||||||
|
data.openstack_networking_port_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
device_id = "\${ openstack_compute_instance_v2.${sanitizedName}.id }";
|
||||||
|
network_id = "\${ openstack_networking_network_v2.${sanitizedName}.id }";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
resource.openstack_compute_instance_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
name = value.name;
|
||||||
|
tags = value.tags;
|
||||||
|
flavor_id = "\${ data.openstack_compute_flavor_v2.${sanitizedName}.id }";
|
||||||
|
key_pair = "\${ openstack_compute_keypair_v2.${sanitizedName}.name }";
|
||||||
|
block_device = [
|
||||||
|
{
|
||||||
|
uuid = "\${ openstack_blockstorage_volume_v3.${sanitizedName}.id }";
|
||||||
|
source_type = "volume";
|
||||||
|
boot_index = 0;
|
||||||
|
destination_type = "volume";
|
||||||
|
delete_on_termination = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
security_groups = [ "\${ openstack_networking_secgroup_v2.${sanitizedName}.name }" ];
|
||||||
|
network = [
|
||||||
|
{
|
||||||
|
uuid = "\${ openstack_networking_network_v2.${sanitizedName}.id }";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
|
||||||
|
# floating ip associate
|
||||||
|
resource.openstack_networking_floatingip_associate_v2 = lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = sanitizedName;
|
||||||
|
value = {
|
||||||
|
floating_ip = "\${ openstack_networking_floatingip_v2.${sanitizedName}.address }";
|
||||||
|
port_id = "\${ data.openstack_networking_port_v2.${sanitizedName}.id }";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) cfg.compute_instance;
|
||||||
|
};
|
||||||
|
}
|
51
nix/modules/terranix/openstack/output.nix
Normal file
51
nix/modules/terranix/openstack/output.nix
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
{ khscodesLib, ... }:
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.khscodes.openstack;
|
||||||
|
openstackOutputInstanceModule = khscodesLib.mkSubmodule {
|
||||||
|
description = "Instance output";
|
||||||
|
options = {
|
||||||
|
id = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "ID of the instance, as a terraform string expression";
|
||||||
|
};
|
||||||
|
ipv4_address = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "IPv4 address of the instance, as a terraform string expression";
|
||||||
|
};
|
||||||
|
ipv6_address = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "IPv6 address of the instance, as a terraform string expression";
|
||||||
|
};
|
||||||
|
ipv6_external_gateway = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "The IPv6 external gateway for the network. This is useful to eg. create static routes in Unifi";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.khscodes.openstack = {
|
||||||
|
output.compute_instance = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf openstackOutputInstanceModule;
|
||||||
|
description = "Set by this module to be read by other modules when needing results of defining a compute instance";
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
khscodes.openstack.output.compute_instance = lib.attrsets.mapAttrs (
|
||||||
|
name: value:
|
||||||
|
(
|
||||||
|
let
|
||||||
|
sanitizedName = khscodesLib.sanitize-terraform-name name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
id = "\${ openstack_compute_instance_v2.${sanitizedName}.id }";
|
||||||
|
ipv4_address = "\${ openstack_networking_floatingip_v2.${sanitizedName}.address }";
|
||||||
|
ipv6_address = "\${ data.openstack_networking_port_v2.${sanitizedName}.all_fixed_ips[1] }";
|
||||||
|
ipv6_external_gateway = "\${ [for ip in openstack_networking_router_v2.${sanitizedName}.external_fixed_ip : ip.ip_address if replace(ip.ip_address, \":\", \"\") != ip.ip_address][0] }";
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) cfg.compute_instance;
|
||||||
|
};
|
||||||
|
}
|
33
nix/modules/terranix/s3/default.nix
Normal file
33
nix/modules/terranix/s3/default.nix
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{ ... }:
|
||||||
|
{ lib, config, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.khscodes.s3;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.khscodes.s3 = {
|
||||||
|
enable = lib.mkEnableOption "Enables the s3 backend";
|
||||||
|
bucket = {
|
||||||
|
key = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "key for the bucket to use";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
terraform.backend.s3 = {
|
||||||
|
bucket = "bw-terraform";
|
||||||
|
key = cfg.bucket.key;
|
||||||
|
region = "auto";
|
||||||
|
endpoints = {
|
||||||
|
s3 = "https://477b394a6a545699445c40953e40f00b.r2.cloudflarestorage.com";
|
||||||
|
};
|
||||||
|
use_path_style = true;
|
||||||
|
skip_credentials_validation = true;
|
||||||
|
skip_region_validation = true;
|
||||||
|
skip_metadata_api_check = true;
|
||||||
|
skip_requesting_account_id = true;
|
||||||
|
skip_s3_checksum = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
23
nix/modules/terranix/unifi/default.nix
Normal file
23
nix/modules/terranix/unifi/default.nix
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{ khscodesLib, inputs }:
|
||||||
|
{ lib, config, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.khscodes.unifi;
|
||||||
|
modules = [
|
||||||
|
./output.nix
|
||||||
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.khscodes.unifi = {
|
||||||
|
enable = lib.mkEnableOption "Enables the unifi provider";
|
||||||
|
bucket = {
|
||||||
|
key = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "key for the bucket to use";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
imports = lib.lists.map (m: import m { inherit khscodesLib inputs; }) modules;
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable { };
|
||||||
|
}
|
12
nix/modules/terranix/unifi/output.nix
Normal file
12
nix/modules/terranix/unifi/output.nix
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{ khscodesLib, ... }:
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.khscodes.unifi;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.khscodes.unifi = {
|
||||||
|
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
};
|
||||||
|
}
|
|
@ -5,26 +5,7 @@ let
|
||||||
# for now this map just needs to include every secret we could need, which also makes the reading of secrets take way longer than
|
# for now this map just needs to include every secret we could need, which also makes the reading of secrets take way longer than
|
||||||
# needed.
|
# needed.
|
||||||
secrets = import ./secrets-map.nix;
|
secrets = import ./secrets-map.nix;
|
||||||
wrappedScript = pkgs.writeShellApplication {
|
wrappedScript = pkgs.khscodes.instance-opentofu;
|
||||||
name = "bw-opentofu-wrapped";
|
|
||||||
runtimeInputs = [
|
|
||||||
pkgs.uutils-coreutils-noprefix
|
|
||||||
pkgs.bitwarden-cli
|
|
||||||
pkgs.khscodes.find-flake-root
|
|
||||||
opentofu
|
|
||||||
];
|
|
||||||
text = ''
|
|
||||||
fqdn="$1"
|
|
||||||
config="$2"
|
|
||||||
phase="$3"
|
|
||||||
flakeRoot="$(find-flake-root)"
|
|
||||||
dir="$flakeRoot/.terraform-cache/$fqdn/$phase"
|
|
||||||
mkdir -p "$dir"
|
|
||||||
cat "''${config}" > "$dir/config.tf.json"
|
|
||||||
tofu -chdir="$dir" init
|
|
||||||
tofu -chdir="$dir" apply
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in
|
in
|
||||||
lib.khscodes.mkBwEnv {
|
lib.khscodes.mkBwEnv {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
|
22
nix/packages/instance-opentofu/default.nix
Normal file
22
nix/packages/instance-opentofu/default.nix
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
opentofu = pkgs.khscodes.opentofu;
|
||||||
|
in
|
||||||
|
pkgs.writeShellApplication {
|
||||||
|
name = "instance-opentofu";
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.uutils-coreutils-noprefix
|
||||||
|
opentofu
|
||||||
|
];
|
||||||
|
text = ''
|
||||||
|
fqdn="$1"
|
||||||
|
config="$2"
|
||||||
|
cmd="''${3:-apply}"
|
||||||
|
dir="$(mktemp -dt "$fqdn-pre-provisioning.XXXXXX")"
|
||||||
|
mkdir -p "$dir"
|
||||||
|
cat "''${config}" > "$dir/config.tf.json"
|
||||||
|
|
||||||
|
tofu -chdir="$dir" init > /dev/null
|
||||||
|
tofu -chdir="$dir" "$cmd"
|
||||||
|
'';
|
||||||
|
}
|
|
@ -1 +1,7 @@
|
||||||
{ pkgs }: pkgs.opentofu.withPlugins (p: [ pkgs.khscodes.terraform-provider-unifi ])
|
{ pkgs }:
|
||||||
|
pkgs.opentofu.withPlugins (p: [
|
||||||
|
pkgs.khscodes.terraform-provider-unifi
|
||||||
|
pkgs.khscodes.terraform-provider-cloudflare
|
||||||
|
pkgs.khscodes.terraform-provider-hcloud
|
||||||
|
pkgs.khscodes.terraform-provider-openstack
|
||||||
|
])
|
||||||
|
|
|
@ -7,21 +7,27 @@ pkgs.writeShellApplication {
|
||||||
runtimeInputs = [
|
runtimeInputs = [
|
||||||
pkgs.nix
|
pkgs.nix
|
||||||
pkgs.khscodes.bw-opentofu
|
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
|
# TODO: Use secret source and required secrets to set up the correct env variables
|
||||||
text = ''
|
text = ''
|
||||||
hostname="$1"
|
hostname="$1"
|
||||||
|
cmd="''${2:-apply}"
|
||||||
baseAttr='${inputs.self}#nixosConfigurations."'"$hostname"'".config.khscodes.provisioning'
|
baseAttr='${inputs.self}#nixosConfigurations."'"$hostname"'".config.khscodes.provisioning'
|
||||||
config="$(nix eval --raw "''${baseAttr}.preConfig")"
|
config="$(nix build --no-link --print-out-paths "''${baseAttr}.preConfig")"
|
||||||
secretsSource="$(nix eval --raw "''${baseAttr}.pre.secretsSource")"
|
secretsSource="$(nix eval --raw "''${baseAttr}.pre.secretsSource")"
|
||||||
|
endpoints="$(nix eval --json "''${baseAttr}.pre.endpoints")"
|
||||||
if [[ "$config" == "null" ]]; then
|
if [[ "$config" == "null" ]]; then
|
||||||
echo "No preprovisioning needed"
|
echo "No preprovisioning needed"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [[ "$secretsSource" == "vault" ]]; then
|
if [[ "$secretsSource" == "vault" ]]; then
|
||||||
>&2 echo "Provisioning using vault is not yet implemented"
|
readarray -t endpoints_args < <(echo "$endpoints" | jq -cr 'map(["-e", .])[][]')
|
||||||
exit 1
|
openbao-helper wrap-program "''${endpoints_args[@]}" -- instance-opentofu "$hostname" "$config" "$cmd"
|
||||||
|
exit 0
|
||||||
fi
|
fi
|
||||||
bw-opentofu "$hostname" "$config" "pre"
|
bw-opentofu "$hostname" "$config" "$cmd"
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
10
nix/packages/terraform-provider-cloudflare/default.nix
Normal file
10
nix/packages/terraform-provider-cloudflare/default.nix
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{ pkgs }:
|
||||||
|
pkgs.terraform-providers.mkProvider {
|
||||||
|
hash = "sha256-rgXsROzfjtUw994JH8x+j/UNMyl7E9cZ+77Fczc3uB8=";
|
||||||
|
homepage = "https://registry.terraform.io/providers/cloudflare/cloudflare";
|
||||||
|
owner = "cloudflare";
|
||||||
|
repo = "terraform-provider-cloudflare";
|
||||||
|
rev = "v4.52.0";
|
||||||
|
spdx = "MPL-2.0";
|
||||||
|
vendorHash = "sha256-RULgejA/RTDHhRJRiqlgckK4Ut3GLvIE081/i6gQTjI=";
|
||||||
|
}
|
10
nix/packages/terraform-provider-hcloud/default.nix
Normal file
10
nix/packages/terraform-provider-hcloud/default.nix
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{ pkgs }:
|
||||||
|
pkgs.terraform-providers.mkProvider {
|
||||||
|
hash = "sha256-/BcK9K/jNEU4r7mFc4rrhNnPlyH98UrDUCgIluY52fA=";
|
||||||
|
homepage = "https://registry.terraform.io/providers/hetznercloud/hcloud";
|
||||||
|
owner = "hetznercloud";
|
||||||
|
repo = "terraform-provider-hcloud";
|
||||||
|
rev = "v1.51.0";
|
||||||
|
spdx = "MPL-2.0";
|
||||||
|
vendorHash = "sha256-jbNkhNSSO9jT20J6dVhBEbN9cwtNrvx5EUcyOZcMd4Y=";
|
||||||
|
}
|
10
nix/packages/terraform-provider-openstack/default.nix
Normal file
10
nix/packages/terraform-provider-openstack/default.nix
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{ pkgs }:
|
||||||
|
pkgs.terraform-providers.mkProvider {
|
||||||
|
hash = "sha256-pGNHWhg/1LM1IJYEVLppCJWVzow+j3WPW+H8yWQXMyM=";
|
||||||
|
homepage = "https://registry.terraform.io/providers/terraform-provider-openstack/openstack";
|
||||||
|
owner = "terraform-provider-openstack";
|
||||||
|
repo = "terraform-provider-openstack";
|
||||||
|
rev = "v3.2.0";
|
||||||
|
spdx = "MPL-2.0";
|
||||||
|
vendorHash = "sha256-mTWLix4A0GRe7ayHTwU3Jt+DfDKMIKJlt1I6JuL3wXU=";
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
{ ... }:
|
{ modulesPath, ... }:
|
||||||
{
|
{
|
||||||
|
imports = [ "${modulesPath}/profiles/qemu-guest.nix" ];
|
||||||
config.khscodes = {
|
config.khscodes = {
|
||||||
hetzner.enable = true;
|
hetzner.enable = true;
|
||||||
sshd.enable = true;
|
sshd.enable = true;
|
||||||
|
|
7
nix/profiles/khs-openstack-server.nix
Normal file
7
nix/profiles/khs-openstack-server.nix
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{ modulesPath, ... }:
|
||||||
|
{
|
||||||
|
imports = [ "${modulesPath}/profiles/qemu-guest.nix" ];
|
||||||
|
config.khscodes = {
|
||||||
|
sshd.enable = true;
|
||||||
|
};
|
||||||
|
}
|
14
nix/systems/x86_64-linux/test.kaareskovgaard.net/default.nix
Normal file
14
nix/systems/x86_64-linux/test.kaareskovgaard.net/default.nix
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [ "${inputs.self}/nix/profiles/khs-openstack-server.nix" ];
|
||||||
|
khscodes.khs-openstack-instance = {
|
||||||
|
enable = true;
|
||||||
|
flavor = "m.medium";
|
||||||
|
secretsSource = "vault";
|
||||||
|
};
|
||||||
|
khscodes.fqdn = "test.kaareskovgaard.net";
|
||||||
|
system.stateVersion = "25.05";
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue