Skip to content

NixOS Droplet via CloudInit.

License

Notifications You must be signed in to change notification settings

polis-dev/nixlet.tf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

58 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

NixOS + droplet = "nixlet" πŸ¦—

a terraform module to create a nixos droplet on digitalocean. heavily inspired by elitak/nixos-infect but tuned explicitly for our tools, processes, and preferences. the goal is a quick to setup (ephemeral or long-lasting!) nixos host on digitalocean without too much headache and to provide an easy way for new developers to begin experimenting with this operating-system/platform.

🌟 features

  • πŸ–οΈ no nix installation necessary! 😌 only terraform and a DIGITALOCEAN_TOKEN!
  • ⏲️ deployed and ready in "under 5-microwave minutes" πŸ—.
  • πŸ‘·β€β™‚οΈ custom configuration is easy! 🍬 (but also not required) πŸ’†
  • πŸ“‘ advanced droplet monitoring enabled! πŸ‘½ πŸ›Έ

πŸ“‹ use cases

πŸš€ module

Configuration can live next to .tf files, by using file():

module "nixlet" {
  # note that every other value (besides source) is NOT required.
  source        = "github.com/polis-dev/nixlet.tf"

  # increased droplet size to make nixlet go vroooom!
  droplet_size  = "s-4vcpu-8gb-intel"

  # defaults to nixos-unstable, with flakes, and other sane defaults.
  nixos_channel = "nixos-unstable"

  # custom nixos configuration can be specified via file() like so.
  nixos_config  = file("${path.module}/custom.nix")
}

OR configurations can embed/inline the nix file to leverage terraform's string interpolation:

locals { domain = "example.com" }
module "nixlet" {
  # note that every other value (besides source) is NOT required.
  source        = "github.com/polis-dev/nixlet.tf"
  nixos_config  = <<-NIXOS_CONFIG
  { config, lib, pkgs, ... }: {
    networking.domain = "${local.domain}";
    /*
    add your configuration here...
    */
  }
  NIXOS_CONFIG
}

Then run terraform init and then terraform plan.

Providers

Name Version
cloudinit ~> 2.3
digitalocean ~> 2.32

Resources

Name Type
digitalocean_droplet.main resource
digitalocean_floating_ip.main resource
cloudinit_config.user_data data source
digitalocean_ssh_keys.all data source
digitalocean_vpc.main data source

Inputs

Name Description Type Default Required
backups enable regular digitalocean droplet backups bool false no
droplet_size which digitalocean droplet size should be used? string "s-1vcpu-1gb-intel" no
droplet_tags tags to apply to droplet. list(string) [] no
flake_config file contents of flake.nix (if empty, default will be generated) string "" no
floating_ip reserve a floating IP droplet host? bool true no
graceful_shutdown allow this droplet to shutdown gracefully? bool false no
hostname what name should be given to instance? string "nixlet" no
image change this at your own risk. it "just works" like this... string "debian-11-x64" no
infect_script file contents of infect.sh (if empty, default will be used) string "" no
ipv6 enable ipv6? bool true no
nixos_channel which nix channel should be used for managed hosts? string "nixos-unstable" no
nixos_config file contents of custom.nix (if empty, default will be used) string "" no
nixos_system n/a string "x86_64-linux" no
region which digitalocean region should be used? string "nyc3" no
resize_disk resize disk when resizing the droplet (permanent change) bool false no
ssh_key_ids ssh key ids to grant root ssh access. does not create them. if unspecified, all currently available ssh keys will be used (within the project containing this API token). list(number) [] no
volume_ids list of volumes to be mounted to the created droplet. list(number) [] no
vpc_name name of the VPC to target, if "default" will be appended with -$region string "default" no

Outputs

Name Description
droplet (augmented) droplet resource
floating_ip (augmented) floating_ip resource
ipv4_address public ipv4 address
ipv6_address public ipv6 address

stand-alone / local setup

  1. install terraform and terraform-docs.

  2. clone the repository and run ./terraform.sh init to setup providers. you can run ./terraform.sh to see available commands.

  3. export DIGITALOCEAN_TOKEN=... (directly, or via the newly created .envrc) to set your access credentials.

  4. plan a deployment with ./terraform.sh plan.

  5. apply the plan with ./terraform.sh apply. allow ~5 minutes (with default config) to provision completely (or just tail -f /var/log/cloud-init-output.log).

  6. ssh to your host and enjoy! clean up everything with ./terraform.sh destroy.

troubleshooting

"i logged into my host and its not nixos! its debian!":

well, "future self at 3am", you can read through the log output from cloud-init with less /var/log/cloud-init-output.log. often a small syntax error or a minor typo can cause the initial build to fail. you will almost certainly want to start the provisioning process over entirely after making your correction locally; luckily with terraform thats pretty easy: ./terraform.sh apply -destroy, then ./terraform.sh apply to create it again.

NOTE that the documentation is automatically updated by terraform-docs.