20 KiB
All-in-one
Combines the install and nixos-rebuild module in one interface to install NixOS with nixos-anywhere and then keep it up-to-date with nixos-rebuild.
Example
locals {
ipv4 = "192.0.2.1"
}
module "deploy" {
source = "github.com/nix-community/nixos-anywhere//terraform/all-in-one"
# with flakes
nixos_system_attr = ".#nixosConfigurations.mymachine.config.system.build.toplevel"
nixos_partitioner_attr = ".#nixosConfigurations.mymachine.config.system.build.diskoScript"
# without flakes
# file can use (pkgs.nixos []) function from nixpkgs
#file = "${path.module}/../.."
#nixos_system_attr = "config.system.build.toplevel"
#nixos_partitioner_attr = "config.system.build.diskoScript"
target_host = local.ipv4
# when instance id changes, it will trigger a reinstall
instance_id = local.ipv4
# useful if something goes wrong
# debug_logging = true
# build the closure on the remote machine instead of locally
# build_on_remote = true
# script is below
extra_files_script = "${path.module}/decrypt-ssh-secrets.sh"
disk_encryption_key_scripts = [{
path = "/tmp/secret.key"
# script is below
script = "${path.module}/decrypt-zfs-key.sh"
}]
# Optional, arguments passed to special_args here will be available from a NixOS module in this example the `terraform` argument:
# { terraform, ... }: {
# networking.interfaces.enp0s3.ipv4.addresses = [{ address = terraform.ip; prefixLength = 24; }];
# }
# Note that this will means that your NixOS configuration will always depend on terraform!
# Skip to `Pass data persistently to the NixOS` for an alternative approach
#special_args = {
# terraform = {
# ip = "192.0.2.0"
# }
#}
}
Note: You need to mark scripts as executable (chmod +x
)
./decrypt-ssh-secrets.sh
#!/usr/bin/env bash
mkdir -p etc/ssh var/lib/secrets
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
umask 0177
sops --extract '["initrd_ssh_key"]' --decrypt "$SCRIPT_DIR/secrets.yaml" >./var/lib/secrets/initrd_ssh_key
# restore umask
umask 0022
for keyname in ssh_host_rsa_key ssh_host_rsa_key.pub ssh_host_ed25519_key ssh_host_ed25519_key.pub; do
if [[ $keyname == *.pub ]]; then
umask 0133
else
umask 0177
fi
sops --extract '["'$keyname'"]' --decrypt "$SCRIPT_DIR/secrets.yaml" >"./etc/ssh/$keyname"
done
./decrypt-zfs-key.sh
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
cd "$SCRIPT_DIR"
sops --extract '["zfs-key"]' --decrypt "$SCRIPT_DIR/secrets.yaml"
See also
- nixos-wiki setup for hetzner-cloud
Pass data persistently to the NixOS
This guide outlines how to pass data from Terraform to NixOS by generating a file during Terraform execution and including it in your NixOS configuration. This approach works well if your Terraform and NixOS configurations are stored in the same Git repository.
Why Use This Method?
This method provides a straightforward way to transfer values from Terraform to NixOS without relying on special_args.
- Advantages:
- You can continue to use nix build or nixos-rebuild to evaluate your configuration without interruption. Simplifies configuration management by centralizing state in a single repository.
- Disadvantages:
- Deploying new machines requires tracking additional state. Every time Terraform updates the JSON file, you'll need to commit these changes to your repository.
Implementation
Add the following snippet to your Terraform configuration to create and manage a JSON file containing the necessary variables for NixOS. This file will be automatically added to your Git repository, ensuring the data persists.
Assuming you have your terraform and nixos configuration in the same git
repository. You can use the following snippet to git add
a file generated by
terraform
during execution to pass data from terraform to NixOS. These changes
should be committed afterwards. This is an alternative over using
special_args
. Advantage: you can still use nix build or nixos-rebuild on your
flake to evaluate your configuration. Disadvantage: Deploying new machines also
means you need to track additional state and make additional commits whenever
terraform updates the json file.
locals {
nixos_vars_file = "nixos-vars.json" # Path to the JSON file containing NixOS variables
nixos_vars = {
ip = "192.0.2.0" # Replace with actual variables
}
}
resource "local_file" "nixos_vars" {
content = jsonencode(local.nixos_vars) # Converts variables to JSON
filename = local.nixos_vars_file # Specifies the output file path
file_permission = "600"
# Automatically adds the generated file to Git
provisioner "local-exec" {
interpreter = ["bash", "-c"]
command = "git add -f '${local.nixos_vars_file}'"
}
}
After applying the Terraform changes, ensure you commit the updated
nixos-vars.json
file to your Git repository:
git commit -m "Update NixOS variables from Terraform"
You can import this json file into your configuration like this:
let
nixosVars = builtins.fromJSON (builtins.readFile ./nixos-vars.json);
in
{
# Example usage of imported variables
networking.hostName = "example-machine";
networking.interfaces.eth0.ipv4.addresses = [
{
address = nixosVars.ip; # Use the IP from nixos-vars.json
prefixLength = 24;
}
];
}
Requirements
No requirements.
Providers
No providers.
Modules
Name | Source | Version |
---|---|---|
install | ../install | n/a |
nixos-rebuild | ../nixos-rebuild | n/a |
partitioner-build | ../nix-build | n/a |
system-build | ../nix-build | n/a |
Resources
No resources.
Inputs
Name | Description | Type | Default | Required |
---|---|---|---|---|
debug_logging | Enable debug logging | bool |
false |
no |
deployment_ssh_key | Content of private key used to deploy to the target_host after initial installation. To ensure maximum security, it is advisable to connect to your host using ssh-agent instead of relying on this variable | string |
null |
no |
disk_encryption_key_scripts | Each script will be executed locally. Output of each will be created at the given path to disko during installation. The keys will be not copied to the final system | list(object({ |
[] |
no |
extra_environment | Extra environment variables to be set during installation. This can be useful to set extra variables for the extra_files_script or disk_encryption_key_scripts | map(string) |
{} |
no |
extra_files_script | A script that should place files in the current directory that will be copied to the targets / directory | string |
null |
no |
file | Nix file containing the nixos_system_attr and nixos_partitioner_attr. Use this if you are not using flake | string |
null |
no |
install_port | SSH port used to connect to the target_host, before installing NixOS. If null than the value of target_port is used |
string |
null |
no |
install_ssh_key | Content of private key used to connect to the target_host during initial installation | string |
null |
no |
install_user | SSH user used to connect to the target_host, before installing NixOS. If null than the value of target_host is used |
string |
null |
no |
instance_id | The instance id of the target_host, used to track when to reinstall the machine | string |
null |
no |
kexec_tarball_url | NixOS kexec installer tarball url | string |
null |
no |
nix_options | the options of nix | map(string) |
{} |
no |
nixos_facter_path | Path to which to write a facter.json generated by nixos-facter . |
string |
"" |
no |
nixos_generate_config_path | Path to which to write a hardware-configuration.nix generated by nixos-generate-config . |
string |
"" |
no |
nixos_partitioner_attr | Nixos partitioner and mount script i.e. your-flake#nixosConfigurations.your-evaluated-nixos.config.system.build.diskoNoDeps or just your-evaluated.config.system.build.diskNoDeps. config.system.build.diskNoDeps is provided by the disko nixos module |
string |
n/a | yes |
nixos_system_attr | The nixos system to deploy i.e. your-flake#nixosConfigurations.your-evaluated-nixos.config.system.build.toplevel or just your-evaluated-nixos.config.system.build.toplevel if you are not using flakes | string |
n/a | yes |
no_reboot | DEPRECATED: Use phases instead. Do not reboot after installation |
bool |
false |
no |
phases | Phases to run. See nixos-anywhere --help for more information |
set(string) |
[ |
no |
special_args | A map exposed as NixOS's specialArgs thru a file. |
any |
{} |
no |
build_on_remote | Build the closure on the remote machine instead of building it locally and copying it over | bool |
false |
no |
stop_after_disko | DEPRECATED: Use phases instead. Exit after disko formatting |
bool |
false |
no |
target_host | DNS host to deploy to | string |
n/a | yes |
target_port | SSH port used to connect to the target_host after installing NixOS. If install_port is not set than this port is also used before installing. | number |
22 |
no |
target_user | SSH user used to connect to the target_host after installing NixOS. If install_user is not set than this user is also used before installing. | string |
"root" |
no |
Outputs
Name | Description |
---|---|
result | n/a |