imfreedom/terraform
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore Tue Jul 25 00:09:53 2023 -0500
@@ -0,0 +1,5 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile Tue Jul 25 00:09:53 2023 -0500
@@ -0,0 +1,45 @@
+PLAN_LIMIT = $(LIMIT:%= -target=%) +TFARGS = -var-file nodes/$(NODE).tfvars +plan: _require_node _state + terraform plan -parallelism=$(PARALLELISM) -out $(NODE).tfplan $(TFARGS) $(PLAN_LIMIT) +showplan: _require_node _state + terraform showplan $(NODE).tfplan +destroy: _require_node _state + terraform plan -destroy -out $(NODE).tfplan $(TFARGS) +apply: _require_node _state + terraform apply -input=true $(NODE).tfplan +refresh: _require_node _state + terraform refresh $(TFARGS) +_require_node: nodes/$(NODE).tfvars + $(warning Executing on host $(NODE)) +ifneq ("$(wildcard .terraform/terraform.tfstate)","") + rm .terraform/terraform.tfstate + terraform init --backend-config="key=$(NODE).tfstate" + @echo unknown node \"$(NODE)\" --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md Tue Jul 25 00:09:53 2023 -0500
@@ -0,0 +1,117 @@
+This repository contains [terraform](https://www.terraform.io/) for imfreedom +All machines are configured to be logged into via the `admin` user account. +There are a number of reasons for this, but the most important one is that +`sudo` uses get logged for normal users which the `admin` user is. +TLDR: install mkisofs, libvirt, [terraform](https://www.terraform.io/), +[terraform-libvirt-provider](https://github.com/dmacvicar/terraform-provider-libvirt), +and make sure the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment +variables are properly set to the imfreedom [minio](https://data.imfreedom.org) +`Terraform` can be run from anywhere that this repository is cloned to with a +few caveats. First you need to install [terraform](https://www.terraform.io/). +I typically install it to `~/.local/bin/`. Verify `Terraform` is installed and +on your path by running `terraform version`. +~~Once you have a working `Terraform` install you need to install the +[terraform-libvirt-provider](https://github.com/dmacvicar/terraform-provider-libvirt). +This should be installed into `~/.terraform.d/plugins`.~~ +This might be done by `terraform init` now. +Next we need to make sure that `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` +environment variables are set to your credentials to the imfreedom +[minio](https://data.imfreedom.org/) instance. If you need credentials, talk +to grim. To make sure these environment variables are set, I recommend using +[direnv](https://direnv.net/) and saving them to your `.envrc` in your clone. +This file is already ignored in `.hgignore` +On Debian based hosts there is an apparmor policy that is missing that will +cause permission errors. To fix it you need to add the following to +`/etc/apparmor.d/abstractions/libvirt-qemu`. I've been putting it at the end +of the file and everything is fine. + # for terraform-libvirt + /var/lib/libvirt/images/* rwk, +To actually `Terraform` a node, we first need to create a `<node>.tfvars` in +the `nodes/` directory. A bare minimal example is below. +libvirt_uri = "qemu+ssh://host/system" +`libvirt_uri` is the connect string for libvirt. +You can also use the `volume_pool` variable to use a different volume pool. +There is an optional `node_prefix` setting you can use to prefix all of the +host names for the machines. This prefix will not change the names of the +machines in libvirt, it's meant to disambiguate the machines in tailscale. It's +obvious what node they belong to when you're looking at the nodes but in +tailscale we don't have that luxury. +Once that file is created you can provision the node via: +Based on the number of vms, this can take quite a bit of time so make sure to +run it in screen/tmux and maintain a stable internet connection. +Additional configuration for the `<node>.tfvars` file is below in the section +The FreeBSD AMD64 machines have a number of options which are explained below. +These should be set in your `<node>.tfvars` file. +**freebsd_amd64_count**: How many FreeBSD AMD64 machines to create. The default +**freebsd_amd64_volume_pool**: The name of which `libvirt` volume pool to use. +This is seldomly changed, but defaults to `default`. +**freebsd_amd64_ssh_pubkeys**: A list of SSH public keys that are allowed to +connect to this machine. The default is an empty list which means you will not +be able to get into the machine. +**freebsd_amd64_base_image**: A dictionary containing information about the +This has keys for the name, source URI, and format of the image. +The name is the name to use in the libvirt storage pool. This defaults to +The `source` key is the URI to the file itself. We are currently uses images +from [bsd-cloud-image.org](https://bsd-cloud-image.org/). Getting the URIs from +there is kind of annoying as you have to start a download to get it. +Finally the `format` key the format of the image pointed to by the `source` +key. Currently this is `qcow2`. +**freebsd_amd64_volume_size**: The size of the HDD for the machine. This +**freebsd_amd64_memory_size**: The amount of memory to give to the machine. +**freebsd_amd64_cpu_count**: The number of CPUs to give the machine. Defaults +**freebsd_amd64_network_name**: The name of the libvirt network to use. This is +seldomly changed, but defaults to `default`. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/instance-freebsd-amd64.tf Tue Jul 25 00:09:53 2023 -0500
@@ -0,0 +1,117 @@
+variable freebsd_amd64_count { default = 0 } +variable freebsd_amd64_volume_pool { default = "default" } +variable freebsd_amd64_ssh_pubkeys { default = [] } +variable freebsd_amd64_base_image { default = { + "name": "freebsd-amd64-base", + "source": "https://object-storage.public.mtl1.vexxhost.net/swift/v1/1dbafeefbd4f4c80864414a441e72dd2/bsd-cloud-image.org/images/freebsd/13.2/2023-04-22/ufs/freebsd-13.2-ufs-2023-04-22.qcow2", +variable freebsd_amd64_volume_size { default = "10737418240" } # 10gb +variable freebsd_amd64_memory_size { default = "1024" } # 1gb +variable freebsd_amd64_cpu_count { default = "1" } +variable freebsd_amd64_network_name { default = "default" } +data "template_file" "freebsd_amd64_cloudinit" { + count = var.freebsd_amd64_count + ssh_authorized_keys: $${admin_ssh_pubkeys} + sudo: ALL=(ALL) NOPASSWD:ALL + ignore_growroot_disabled: false +# Uncomment this if you need to debug stuff + "fqdn": format("%sfreebsd-amd64-%02d", var.node_prefix, count.index), + "admin_ssh_pubkeys": jsonencode(var.freebsd_amd64_ssh_pubkeys), +resource "libvirt_cloudinit_disk" "freebsd_amd64_cloudinit" { + count = var.freebsd_amd64_count + name = format("freebsd-amd64-%02d-cloudinit.iso", count.index) + pool = var.freebsd_amd64_volume_pool + user_data = element(data.template_file.freebsd_amd64_cloudinit.*.rendered, count.index) +resource "libvirt_volume" "freebsd_amd64_base_image" { + count = (var.freebsd_amd64_count > 0 ? 1 : 0) + pool = var.freebsd_amd64_volume_pool + name = format("%s.%s", var.freebsd_amd64_base_image["name"], var.freebsd_amd64_base_image["format"]) + source = var.freebsd_amd64_base_image["source"] + format = var.freebsd_amd64_base_image["format"] +resource "libvirt_volume" "freebsd_amd64_image" { + count = var.freebsd_amd64_count + pool = var.freebsd_amd64_volume_pool + name = format("freebsd-amd64-%02d.%s", count.index, var.freebsd_amd64_base_image["format"]) + base_volume_id = libvirt_volume.freebsd_amd64_base_image[0].id + format = var.freebsd_amd64_base_image["format"] + size = var.freebsd_amd64_volume_size +resource "libvirt_domain" "freebsd_amd64" { + count = var.freebsd_amd64_count + name = format("freebsd-amd64-%02d", count.index) + mode = "host-passthrough" + memory = var.freebsd_amd64_memory_size + vcpu = var.freebsd_amd64_cpu_count + cloudinit = libvirt_cloudinit_disk.freebsd_amd64_cloudinit[count.index].id + volume_id = libvirt_volume.freebsd_amd64_image[count.index].id + network_name = var.freebsd_amd64_network_name + value = "${flatten(libvirt_domain.freebsd_amd64.*.network_interface.0.addresses)}" --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nodes.tf Tue Jul 25 00:09:53 2023 -0500
@@ -0,0 +1,1 @@
+variable node_prefix { default = "" } --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/provider-libvirt.tf Tue Jul 25 00:09:53 2023 -0500
@@ -0,0 +1,6 @@
+variable "libvirt_uri" { default = "qemu:///system" } + uri = "${var.libvirt_uri}" --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/terraform.tf Tue Jul 25 00:09:53 2023 -0500
@@ -0,0 +1,20 @@
+ source = "dmacvicar/libvirt" + endpoint = "https://data.imfreedom.org" + force_path_style = true + skip_credentials_validation = true + skip_region_validation = true + skip_get_ec2_platforms = true + skip_metadata_api_check = false