Wire hosts to internal nix cache
This commit is contained in:
@@ -246,6 +246,38 @@ in
|
||||
description = "Enable inbound SSH in the NixOS host config. AWS ingress is managed by OpenTofu.";
|
||||
};
|
||||
|
||||
nixCache = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Pull from the internal Quixos Attic cache.";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "nix-cache.internal.quixos.org";
|
||||
description = "Internal cache hostname.";
|
||||
};
|
||||
|
||||
hostAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Private IP address mapped to nixCache.domain in /etc/hosts.";
|
||||
};
|
||||
|
||||
substituter = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "http://nix-cache.internal.quixos.org/quixos";
|
||||
description = "Nix substituter URL.";
|
||||
};
|
||||
|
||||
publicKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Attic cache public key.";
|
||||
};
|
||||
};
|
||||
|
||||
devHome = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
@@ -516,11 +548,22 @@ in
|
||||
assertion = cfg.sourceCheckout.path != cfg.packagesPath;
|
||||
message = "services.quixosHost.sourceCheckout.path must be separate from services.quixosHost.packagesPath.";
|
||||
}
|
||||
{
|
||||
assertion = (!cfg.nixCache.enable) || (cfg.nixCache.hostAddress != "" && cfg.nixCache.publicKey != "");
|
||||
message = "services.quixosHost.nixCache requires hostAddress and publicKey when enabled.";
|
||||
}
|
||||
];
|
||||
|
||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||
nix.settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
substituters = lib.mkIf cfg.nixCache.enable (lib.mkAfter [ cfg.nixCache.substituter ]);
|
||||
trusted-public-keys = lib.mkIf cfg.nixCache.enable (lib.mkAfter [ cfg.nixCache.publicKey ]);
|
||||
};
|
||||
|
||||
networking.hostId = cfg.hostId;
|
||||
networking.hosts = lib.mkIf cfg.nixCache.enable {
|
||||
${cfg.nixCache.hostAddress} = [ cfg.nixCache.domain ];
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
boot.zfs.extraPools = [ cfg.nixZfsPool ];
|
||||
|
||||
@@ -66,10 +66,75 @@ in
|
||||
default = "71786363";
|
||||
description = "Eight hex digit hostId required by ZFS.";
|
||||
};
|
||||
|
||||
nixCache = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Use the internal Quixos Attic cache and upload this host closure to it.";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "nix-cache.internal.quixos.org";
|
||||
description = "Internal cache hostname.";
|
||||
};
|
||||
|
||||
hostAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Private IP address mapped to nixCache.domain in /etc/hosts.";
|
||||
};
|
||||
|
||||
endpoint = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "http://nix-cache.internal.quixos.org";
|
||||
description = "Attic server endpoint used for login.";
|
||||
};
|
||||
|
||||
substituter = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "http://nix-cache.internal.quixos.org/quixos";
|
||||
description = "Nix substituter URL.";
|
||||
};
|
||||
|
||||
publicKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Attic cache public key.";
|
||||
};
|
||||
|
||||
cacheName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "quixos";
|
||||
description = "Attic cache name.";
|
||||
};
|
||||
|
||||
pushTokenParameter = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/quixos/nix-cache/central-push-token";
|
||||
description = "SSM parameter containing the central push token.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||
assertions = [
|
||||
{
|
||||
assertion = (!cfg.nixCache.enable) || (cfg.nixCache.hostAddress != "" && cfg.nixCache.publicKey != "");
|
||||
message = "services.quixosAppServer.nixCache requires hostAddress and publicKey when enabled.";
|
||||
}
|
||||
];
|
||||
|
||||
nix.settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
substituters = lib.mkIf cfg.nixCache.enable (lib.mkAfter [ cfg.nixCache.substituter ]);
|
||||
trusted-public-keys = lib.mkIf cfg.nixCache.enable (lib.mkAfter [ cfg.nixCache.publicKey ]);
|
||||
};
|
||||
|
||||
networking.hosts = lib.mkIf cfg.nixCache.enable {
|
||||
${cfg.nixCache.hostAddress} = [ cfg.nixCache.domain ];
|
||||
};
|
||||
|
||||
networking.hostId = cfg.hostId;
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
@@ -99,6 +164,8 @@ in
|
||||
pkgs.git
|
||||
pkgs.htop
|
||||
pkgs.jq
|
||||
pkgs.attic-client
|
||||
pkgs.awscli2
|
||||
pkgs.moreutils
|
||||
pkgs.nix
|
||||
pkgs.pv
|
||||
@@ -236,6 +303,37 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.quixos-nix-cache-push = lib.mkIf cfg.nixCache.enable {
|
||||
description = "Upload central system closure to Quixos Nix cache";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
path = [ pkgs.attic-client pkgs.awscli2 pkgs.coreutils ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
WorkingDirectory = "/tmp";
|
||||
};
|
||||
script = ''
|
||||
set -eu
|
||||
|
||||
export XDG_CONFIG_HOME=/run/quixos-nix-cache-push/config
|
||||
rm -rf "$XDG_CONFIG_HOME"
|
||||
mkdir -p "$XDG_CONFIG_HOME"
|
||||
|
||||
token="$(
|
||||
aws ssm get-parameter \
|
||||
--with-decryption \
|
||||
--name ${lib.escapeShellArg cfg.nixCache.pushTokenParameter} \
|
||||
--query Parameter.Value \
|
||||
--output text
|
||||
)"
|
||||
|
||||
attic login --set-default quixos ${lib.escapeShellArg cfg.nixCache.endpoint} "$token" >/dev/null
|
||||
attic push ${lib.escapeShellArg cfg.nixCache.cacheName} /run/current-system
|
||||
'';
|
||||
};
|
||||
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
package = pkgs.caddy.withPlugins {
|
||||
|
||||
@@ -21,6 +21,22 @@ data "aws_ssm_parameter" "ami" {
|
||||
name = var.ami_ssm_parameter_name
|
||||
}
|
||||
|
||||
data "terraform_remote_state" "nix_cache" {
|
||||
count = var.nix_cache_enable ? 1 : 0
|
||||
backend = "s3"
|
||||
|
||||
config = {
|
||||
bucket = var.nix_cache_state_bucket
|
||||
key = var.nix_cache_state_key
|
||||
region = var.nix_cache_state_region
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_ssm_parameter" "nix_cache_public_key" {
|
||||
count = var.nix_cache_enable ? 1 : 0
|
||||
name = data.terraform_remote_state.nix_cache[0].outputs.public_key_parameter_name
|
||||
}
|
||||
|
||||
resource "random_id" "central" {
|
||||
byte_length = 4
|
||||
}
|
||||
@@ -39,6 +55,15 @@ locals {
|
||||
app_server_enabled = var.app_server_ami_id != null || var.ami_id != null || var.ami_ssm_parameter_name != null
|
||||
app_server_flake_uri = "git+${var.app_server_repo_url}?dir=services/app-server&${var.app_server_ref_is_rev ? "rev" : "ref"}=${urlencode(var.app_server_ref)}"
|
||||
app_server_persist_device = "/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_${replace(aws_ebs_volume.persist.id, "-", "")}"
|
||||
nix_cache_outputs = var.nix_cache_enable ? data.terraform_remote_state.nix_cache[0].outputs : null
|
||||
nix_cache_hosts_parts = var.nix_cache_enable ? split(" ", local.nix_cache_outputs.hosts_entry) : []
|
||||
nix_cache_host_address = var.nix_cache_enable ? local.nix_cache_hosts_parts[0] : ""
|
||||
nix_cache_domain = var.nix_cache_enable ? local.nix_cache_outputs.domain : ""
|
||||
nix_cache_endpoint = var.nix_cache_enable ? "http://${local.nix_cache_outputs.domain}" : ""
|
||||
nix_cache_substituter = var.nix_cache_enable ? local.nix_cache_outputs.cache_url : ""
|
||||
nix_cache_cache_name = var.nix_cache_enable ? trimprefix(local.nix_cache_outputs.cache_url, "http://${local.nix_cache_outputs.domain}/") : ""
|
||||
nix_cache_public_key = var.nix_cache_enable ? data.aws_ssm_parameter.nix_cache_public_key[0].value : ""
|
||||
nix_cache_push_parameter = var.nix_cache_enable ? local.nix_cache_outputs.central_push_token_parameter_name : ""
|
||||
platform_vpc_id = var.platform_vpc_enable ? aws_vpc.platform[0].id : local.vpc_id
|
||||
platform_public_subnet_id = var.platform_vpc_enable ? aws_subnet.central_public[0].id : local.subnet_id
|
||||
platform_runtime_subnet_id = var.platform_vpc_enable ? aws_subnet.runtime_public[0].id : local.subnet_id
|
||||
@@ -325,6 +350,30 @@ resource "aws_iam_role_policy" "app_server_route53" {
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "app_server_nix_cache" {
|
||||
count = local.app_server_enabled && var.nix_cache_enable ? 1 : 0
|
||||
name = "${local.resource_name}-nix-cache"
|
||||
role = aws_iam_role.app_server[0].name
|
||||
|
||||
policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"ssm:GetParameter"
|
||||
]
|
||||
Resource = "arn:aws:ssm:${var.aws_region}:*:parameter${local.nix_cache_push_parameter}"
|
||||
},
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = "kms:Decrypt"
|
||||
Resource = "*"
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_iam_instance_profile" "app_server" {
|
||||
count = local.app_server_enabled ? 1 : 0
|
||||
name = "${local.resource_name}-app-server"
|
||||
@@ -348,6 +397,14 @@ resource "aws_instance" "app_server" {
|
||||
dev_app_wildcard_domain = local.dev_app_wildcard_domain
|
||||
domain = local.app_server_domain
|
||||
persist_device = local.app_server_persist_device
|
||||
nix_cache_enable = var.nix_cache_enable
|
||||
nix_cache_domain = local.nix_cache_domain
|
||||
nix_cache_host_address = local.nix_cache_host_address
|
||||
nix_cache_endpoint = local.nix_cache_endpoint
|
||||
nix_cache_substituter = local.nix_cache_substituter
|
||||
nix_cache_public_key = local.nix_cache_public_key
|
||||
nix_cache_cache_name = local.nix_cache_cache_name
|
||||
nix_cache_push_parameter = local.nix_cache_push_parameter
|
||||
proxy_grant_public_key_pem = jsonencode(tls_private_key.proxy_grants.public_key_pem)
|
||||
route53_zone_id = var.route53_zone_id
|
||||
system = var.app_server_system
|
||||
|
||||
@@ -27,6 +27,16 @@
|
||||
persistZfsPool = "quixos-shared";
|
||||
route53HostedZoneId = "${route53_zone_id}";
|
||||
proxyGrantPublicKeyPem = ${proxy_grant_public_key_pem};
|
||||
nixCache = {
|
||||
enable = ${nix_cache_enable};
|
||||
domain = "${nix_cache_domain}";
|
||||
hostAddress = "${nix_cache_host_address}";
|
||||
endpoint = "${nix_cache_endpoint}";
|
||||
substituter = "${nix_cache_substituter}";
|
||||
publicKey = ${jsonencode(nix_cache_public_key)};
|
||||
cacheName = "${nix_cache_cache_name}";
|
||||
pushTokenParameter = "${nix_cache_push_parameter}";
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "25.05";
|
||||
|
||||
@@ -147,3 +147,27 @@ variable "app_server_ref_is_rev" {
|
||||
default = false
|
||||
description = "Treat app_server_ref as an exact commit rev instead of a branch/tag ref."
|
||||
}
|
||||
|
||||
variable "nix_cache_enable" {
|
||||
type = bool
|
||||
default = true
|
||||
description = "Configure the central app server to pull from and push to the internal Quixos Nix cache."
|
||||
}
|
||||
|
||||
variable "nix_cache_state_bucket" {
|
||||
type = string
|
||||
default = "quixos-opentofu-state"
|
||||
description = "S3 bucket containing nix-cache OpenTofu state."
|
||||
}
|
||||
|
||||
variable "nix_cache_state_key" {
|
||||
type = string
|
||||
default = "nix-cache/terraform.tfstate"
|
||||
description = "S3 key containing nix-cache OpenTofu state."
|
||||
}
|
||||
|
||||
variable "nix_cache_state_region" {
|
||||
type = string
|
||||
default = "us-west-2"
|
||||
description = "AWS region for nix-cache OpenTofu state."
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ const repoRoot = process.env.QUIXOS_REPO_ROOT ?? path.resolve(sourceScriptDir, "
|
||||
const scriptDir = process.env.QUIXOS_RUNTIME_DIR ?? path.resolve(repoRoot, "tofu/runtime");
|
||||
const amiBuilderDir = path.resolve(scriptDir, "../ami-builder");
|
||||
const centralDir = path.resolve(scriptDir, "../central");
|
||||
const nixCacheDir = path.resolve(scriptDir, "../nix-cache");
|
||||
const legacyResolvedAmiVarsFile = "resolved-ami.auto.tfvars.json";
|
||||
const resolvedDeployVarsFile = "zz-qx-deploy.auto.tfvars.json";
|
||||
|
||||
@@ -30,6 +31,10 @@ const deployExclusiveVars = new Set([
|
||||
"proxy_registration_grant",
|
||||
"proxy_registration_url",
|
||||
"proxy_registration_mode",
|
||||
"nix_cache_host_address",
|
||||
"nix_cache_domain",
|
||||
"nix_cache_public_key",
|
||||
"nix_cache_substituter",
|
||||
"package_tree_ref",
|
||||
"quixos_ref",
|
||||
"quixos_ref_is_rev",
|
||||
@@ -67,6 +72,14 @@ Options:
|
||||
--central-proxy-trusted-cidr <cidr>
|
||||
Trust X-Forwarded-* headers from this central proxy CIDR.
|
||||
May be passed more than once.
|
||||
--nix-cache-host-address <addr>
|
||||
Internal address for nix-cache.internal.quixos.org
|
||||
--nix-cache-public-key <key>
|
||||
Attic public key for the internal Nix cache
|
||||
--nix-cache-domain <name> Internal Nix cache hostname
|
||||
--nix-cache-substituter <url>
|
||||
Internal Nix substituter URL
|
||||
--no-nix-cache Do not configure this runtime to pull from the internal cache
|
||||
--base-domain <name> Base DNS domain for generated deployment names
|
||||
(default: QUIXOS_BASE_DOMAIN, TF_VAR_base_domain,
|
||||
terraform.tfvars base_domain, or quixos.org)
|
||||
@@ -115,6 +128,10 @@ Environment:
|
||||
QUIXOS_AMI_PROJECT_NAME
|
||||
QUIXOS_SHARED_PERSIST_VOLUME_ID
|
||||
QUIXOS_CENTRAL_PROXY_SECURITY_GROUP_ID
|
||||
QUIXOS_NIX_CACHE_HOST_ADDRESS
|
||||
QUIXOS_NIX_CACHE_DOMAIN
|
||||
QUIXOS_NIX_CACHE_PUBLIC_KEY
|
||||
QUIXOS_NIX_CACHE_SUBSTITUTER
|
||||
QUIXOS_VPC_ID
|
||||
QUIXOS_SUBNET_ID
|
||||
QUIXOS_BASE_DOMAIN
|
||||
@@ -236,6 +253,37 @@ const centralOutputJson = (name, { env, required = false } = {}) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
const nixCacheOutput = (name, { env, required = false } = {}) => {
|
||||
if (!fs.existsSync(nixCacheDir)) {
|
||||
if (required) {
|
||||
throw new Error(`Missing tofu/nix-cache directory at ${nixCacheDir}.`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const result = captureMaybe("tofu", ["-chdir=" + nixCacheDir, "output", "-raw", name], { env });
|
||||
const value = result.stdout.trim();
|
||||
if (result.status === 0 && value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (required) {
|
||||
const initHint = /Backend initialization required|please run "tofu init"|run\s+"tofu init"/i.test(result.stderr)
|
||||
? "Initialize nix-cache explicitly with: (cd tofu/nix-cache && ./init-backend.sh -reconfigure)"
|
||||
: "";
|
||||
const details = [
|
||||
`Unable to read tofu/nix-cache output '${name}'.`,
|
||||
`Command: tofu -chdir=${nixCacheDir} output -raw ${name}`,
|
||||
result.stderr.trimEnd(),
|
||||
result.stdout.trimEnd(),
|
||||
initHint,
|
||||
].filter(Boolean).join("\n");
|
||||
throw new Error(details);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const captureAsync = (command, args, options = {}) => new Promise((resolve, reject) => {
|
||||
const child = spawn(command, args, {
|
||||
cwd: options.cwd ?? repoRoot,
|
||||
@@ -473,6 +521,11 @@ const parseArgs = (argv) => {
|
||||
proxyRegistrationUrl: process.env.QUIXOS_PROXY_REGISTRATION_URL ?? "",
|
||||
proxyRegistrationGrant: process.env.QUIXOS_PROXY_REGISTRATION_GRANT ?? "",
|
||||
proxyRegistrationPrivateKeyPem: "",
|
||||
nixCacheDisabled: false,
|
||||
nixCacheHostAddress: process.env.QUIXOS_NIX_CACHE_HOST_ADDRESS ?? "",
|
||||
nixCacheDomain: process.env.QUIXOS_NIX_CACHE_DOMAIN ?? "nix-cache.internal.quixos.org",
|
||||
nixCachePublicKey: process.env.QUIXOS_NIX_CACHE_PUBLIC_KEY ?? "",
|
||||
nixCacheSubstituter: process.env.QUIXOS_NIX_CACHE_SUBSTITUTER ?? "http://nix-cache.internal.quixos.org/quixos",
|
||||
assignIpv6Address: false,
|
||||
baseDomain: String(process.env.QUIXOS_BASE_DOMAIN ?? process.env.TF_VAR_base_domain ?? operatorTfvars.base_domain ?? "quixos.org").replace(/\.$/, ""),
|
||||
baseDomainSpecified: Boolean(process.env.QUIXOS_BASE_DOMAIN || process.env.TF_VAR_base_domain || operatorTfvars.base_domain),
|
||||
@@ -541,6 +594,27 @@ const parseArgs = (argv) => {
|
||||
state.centralProxyTrustedCidrs.push(takeValue(argv, i, arg));
|
||||
i += 1;
|
||||
break;
|
||||
case "--nix-cache-host-address":
|
||||
state.nixCacheHostAddress = takeValue(argv, i, arg);
|
||||
i += 1;
|
||||
break;
|
||||
case "--nix-cache-public-key":
|
||||
state.nixCachePublicKey = takeValue(argv, i, arg);
|
||||
i += 1;
|
||||
break;
|
||||
case "--nix-cache-domain":
|
||||
state.nixCacheDomain = takeValue(argv, i, arg).replace(/\.$/, "");
|
||||
i += 1;
|
||||
break;
|
||||
case "--nix-cache-substituter":
|
||||
state.nixCacheSubstituter = takeValue(argv, i, arg);
|
||||
i += 1;
|
||||
break;
|
||||
case "--no-nix-cache":
|
||||
state.nixCacheDisabled = true;
|
||||
state.nixCacheHostAddress = "";
|
||||
state.nixCachePublicKey = "";
|
||||
break;
|
||||
case "--base-domain":
|
||||
state.baseDomain = takeValue(argv, i, arg).replace(/\.$/, "");
|
||||
state.baseDomainSpecified = true;
|
||||
@@ -1027,6 +1101,54 @@ const resolveCentralRuntimeNetwork = (state, tofuEnv) => {
|
||||
}
|
||||
};
|
||||
|
||||
const resolveNixCache = (state, tofuEnv) => {
|
||||
if (state.nixCacheDisabled) {
|
||||
return;
|
||||
}
|
||||
if (state.nixCacheHostAddress && state.nixCachePublicKey) {
|
||||
return;
|
||||
}
|
||||
if (state.nixCacheHostAddress || state.nixCachePublicKey) {
|
||||
throw new Error("Nix cache configuration is incomplete. Pass both --nix-cache-host-address and --nix-cache-public-key, or pass --no-nix-cache.");
|
||||
}
|
||||
|
||||
const hostsEntry = nixCacheOutput("hosts_entry", { env: tofuEnv });
|
||||
const cacheUrl = nixCacheOutput("cache_url", { env: tofuEnv });
|
||||
const domain = nixCacheOutput("domain", { env: tofuEnv });
|
||||
const publicKeyParameterName = nixCacheOutput("public_key_parameter_name", { env: tofuEnv });
|
||||
|
||||
if (!hostsEntry || !cacheUrl || !domain || !publicKeyParameterName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [hostAddress] = hostsEntry.split(/\s+/).filter(Boolean);
|
||||
if (!hostAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
const publicKeyResult = captureMaybe("aws", [
|
||||
"ssm",
|
||||
"get-parameter",
|
||||
"--name",
|
||||
publicKeyParameterName,
|
||||
"--query",
|
||||
"Parameter.Value",
|
||||
"--output",
|
||||
"text",
|
||||
], { env: tofuEnv });
|
||||
const publicKey = publicKeyResult.stdout.trim();
|
||||
if (publicKeyResult.status !== 0 || !publicKey) {
|
||||
console.error(style.yellow(`Nix cache state exists, but ${publicKeyParameterName} is not readable yet; runtime will deploy without the cache.`));
|
||||
return;
|
||||
}
|
||||
|
||||
state.nixCacheHostAddress = hostAddress;
|
||||
state.nixCacheDomain = domain;
|
||||
state.nixCacheSubstituter = cacheUrl;
|
||||
state.nixCachePublicKey = publicKey;
|
||||
console.error(`Using internal Nix cache: ${state.nixCacheSubstituter} via ${state.nixCacheHostAddress}`);
|
||||
};
|
||||
|
||||
const ensureDeploymentId = async (state) => {
|
||||
if (state.deploymentId) {
|
||||
state.deploymentId = normalizeDeploymentId(state.deploymentId);
|
||||
@@ -1195,6 +1317,15 @@ const equivalentArgs = (state, resolvedPackagesRef) => {
|
||||
args.push("--central-proxy-trusted-cidr", cidr);
|
||||
}
|
||||
|
||||
if (state.nixCacheDisabled) {
|
||||
args.push("--no-nix-cache");
|
||||
} else if (state.nixCacheHostAddress && state.nixCachePublicKey) {
|
||||
args.push("--nix-cache-host-address", state.nixCacheHostAddress);
|
||||
args.push("--nix-cache-public-key", state.nixCachePublicKey);
|
||||
args.push("--nix-cache-domain", state.nixCacheDomain);
|
||||
args.push("--nix-cache-substituter", state.nixCacheSubstituter);
|
||||
}
|
||||
|
||||
if (state.explicitPackageTreeRepoUrl) {
|
||||
args.push("--packages-repo", state.packageTreeRepoUrl);
|
||||
}
|
||||
@@ -1268,6 +1399,12 @@ const printDeploySummary = (state, resolvedPackagesRef) => {
|
||||
console.error(`Trusted proxy CIDRs: ${state.centralProxyTrustedCidrs.join(", ")}`);
|
||||
console.error(`Proxy registration: ${state.proxyRegistrationUrl}`);
|
||||
}
|
||||
if (state.nixCacheHostAddress && state.nixCachePublicKey) {
|
||||
console.error(`Nix cache: ${state.nixCacheSubstituter}`);
|
||||
console.error(`Nix cache host: ${state.nixCacheHostAddress} ${state.nixCacheDomain}`);
|
||||
} else {
|
||||
console.error(`Nix cache: ${style.yellow("not configured")}`);
|
||||
}
|
||||
console.error(`Package tree: ${resolvedPackagesRef}`);
|
||||
console.error(state.quixosRefIsRev ? `Quixos rev: ${state.quixosRef}` : `Quixos ref: ${state.quixosRef}`);
|
||||
console.error(`SSH: ${state.enableSshWithLocalKey ? style.green("enabled with local key") : style.yellow("disabled")}`);
|
||||
@@ -1334,6 +1471,10 @@ const writeGeneratedDeployVars = (state, resolvedPackagesRef) => {
|
||||
central_proxy_security_group_id: state.centralProxySecurityGroupId || null,
|
||||
central_proxy_trusted_cidrs: state.centralProxyTrustedCidrs,
|
||||
assign_ipv6_address: state.assignIpv6Address,
|
||||
nix_cache_host_address: state.nixCacheHostAddress || null,
|
||||
nix_cache_domain: state.nixCacheDomain,
|
||||
nix_cache_public_key: state.nixCachePublicKey || null,
|
||||
nix_cache_substituter: state.nixCacheSubstituter,
|
||||
proxy_registration_grant: state.proxyRegistrationGrant || null,
|
||||
proxy_registration_url: state.proxyRegistrationUrl || null,
|
||||
proxy_registration_mode: state.devMode ? "dev" : "prod",
|
||||
@@ -1491,6 +1632,9 @@ const registryRecord = (state, resolvedPackagesRef, tofuEnv, status) => ({
|
||||
centralProxyTrustedCidrs: state.centralProxyTrustedCidrs,
|
||||
proxyRegistrationUrl: state.proxyRegistrationUrl,
|
||||
assignIpv6Address: state.assignIpv6Address,
|
||||
nixCacheHostAddress: state.nixCacheHostAddress,
|
||||
nixCacheDomain: state.nixCacheDomain,
|
||||
nixCacheSubstituter: state.nixCacheSubstituter,
|
||||
vpcId: state.vpcId,
|
||||
subnetId: state.subnetId,
|
||||
baseDomain: state.baseDomain,
|
||||
@@ -1909,6 +2053,7 @@ const main = async () => {
|
||||
resolveCentralProxySecurityGroup(state, tofuEnv);
|
||||
resolveCentralProxyTrustedCidrs(state, tofuEnv);
|
||||
resolveCentralProxyRegistration(state, tofuEnv);
|
||||
resolveNixCache(state, tofuEnv);
|
||||
await signProxyRegistrationGrant(state);
|
||||
const resolvedPackagesRef = resolvePackageTree(state);
|
||||
initRuntimeBackend(state, tofuEnv);
|
||||
|
||||
@@ -32,6 +32,7 @@ locals {
|
||||
ssm_parameter_prefix = "/${var.name}/${local.deployment_id}"
|
||||
effective_ami_id = var.ami_id == null ? "ami-00000000000000000" : var.ami_id
|
||||
central_proxy_enabled = var.central_proxy_security_group_id != null && var.proxy_registration_grant != null && var.proxy_registration_url != null
|
||||
nix_cache_enabled = var.nix_cache_host_address != null && var.nix_cache_public_key != null
|
||||
persist_device = "/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_${replace(aws_ebs_volume.persist.id, "-", "")}"
|
||||
tags = {
|
||||
Name = local.resource_name
|
||||
@@ -230,6 +231,11 @@ resource "aws_instance" "host" {
|
||||
proxy_registration_mode = var.proxy_registration_mode
|
||||
proxy_registration_url = var.proxy_registration_url == null ? "" : var.proxy_registration_url
|
||||
central_proxy_trusted_cidrs = var.central_proxy_trusted_cidrs
|
||||
nix_cache_enable = local.nix_cache_enabled
|
||||
nix_cache_domain = var.nix_cache_domain
|
||||
nix_cache_host_address = var.nix_cache_host_address == null ? "" : var.nix_cache_host_address
|
||||
nix_cache_public_key = var.nix_cache_public_key == null ? "" : var.nix_cache_public_key
|
||||
nix_cache_substituter = var.nix_cache_substituter
|
||||
quixos_ref = var.quixos_ref
|
||||
quixos_repo_url = var.quixos_repo_url
|
||||
quixos_flake_uri = local.quixos_flake_uri
|
||||
|
||||
@@ -71,6 +71,13 @@
|
||||
%{ endfor ~}
|
||||
];
|
||||
};
|
||||
nixCache = {
|
||||
enable = ${nix_cache_enable};
|
||||
domain = "${nix_cache_domain}";
|
||||
hostAddress = "${nix_cache_host_address}";
|
||||
substituter = "${nix_cache_substituter}";
|
||||
publicKey = ${jsonencode(nix_cache_public_key)};
|
||||
};
|
||||
|
||||
secrets = {
|
||||
provider = "aws-ssm";
|
||||
|
||||
@@ -141,6 +141,30 @@ variable "proxy_registration_mode" {
|
||||
}
|
||||
}
|
||||
|
||||
variable "nix_cache_host_address" {
|
||||
type = string
|
||||
default = null
|
||||
description = "Private host address for the internal Quixos Nix cache. When set with nix_cache_public_key, runtime pulls from the cache."
|
||||
}
|
||||
|
||||
variable "nix_cache_domain" {
|
||||
type = string
|
||||
default = "nix-cache.internal.quixos.org"
|
||||
description = "Internal Quixos Nix cache hostname."
|
||||
}
|
||||
|
||||
variable "nix_cache_public_key" {
|
||||
type = string
|
||||
default = null
|
||||
description = "Attic public key for the internal Quixos Nix cache."
|
||||
}
|
||||
|
||||
variable "nix_cache_substituter" {
|
||||
type = string
|
||||
default = "http://nix-cache.internal.quixos.org/quixos"
|
||||
description = "Internal Quixos Nix substituter URL."
|
||||
}
|
||||
|
||||
variable "quixos_repo_url" {
|
||||
type = string
|
||||
default = "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git"
|
||||
|
||||
Reference in New Issue
Block a user