Adding Blocky and NAS selfhosted Incus configs. - infra - Terraform IoC for my remote (Hetzner) and local (Incus) servers.
DIR Log
DIR Files
DIR Refs
DIR README
---
DIR commit 18dc7341334c0ae572dd8e1fe37a9f5bfe91c598
DIR parent d5730ddfc770cf4d3daaec8224f90d10eb986d4c
HTML Author: Jay Scott <me@jay.scot>
Date: Thu, 18 Jul 2024 17:30:37 +0100
Adding Blocky and NAS selfhosted Incus configs.
I am currently porting most of my selfhosted services over to Incus from
K8 one at a time. The Terraform could easily be refactored but I shall
do that at a later date once I have an idea of expectations.
Diffstat:
A local/.terraform.lock.hcl | 23 +++++++++++++++++++++++
A local/cloudinit/blocky-net.yaml | 6 ++++++
A local/cloudinit/blocky-user.yaml | 41 +++++++++++++++++++++++++++++++
A local/cloudinit/nas-net.yaml | 6 ++++++
A local/cloudinit/nas-user.yaml | 35 +++++++++++++++++++++++++++++++
A local/main.tf | 44 +++++++++++++++++++++++++++++++
A local/terraform.tfvars | 22 ++++++++++++++++++++++
A local/variables.tf | 13 +++++++++++++
D terraform/.terraform.lock.hcl | 24 ------------------------
D terraform/checks.tf | 8 --------
D terraform/files/id_rsa.pub | 1 -
D terraform/main.tf | 71 -------------------------------
D terraform/outputs.tf | 3 ---
D terraform/terraform.tfvars | 48 -------------------------------
D terraform/user_data/boot.yml | 16 ----------------
D terraform/user_data/docker.yml | 25 -------------------------
D terraform/variables.tf | 25 -------------------------
17 files changed, 190 insertions(+), 221 deletions(-)
---
DIR diff --git a/local/.terraform.lock.hcl b/local/.terraform.lock.hcl
@@ -0,0 +1,23 @@
+# This file is maintained automatically by "tofu init".
+# Manual edits may be lost in future updates.
+
+provider "registry.opentofu.org/lxc/incus" {
+ version = "0.1.2"
+ constraints = "0.1.2"
+ hashes = [
+ "h1:tsoQEChWE++F07sxzmqZq79hTA1a1Wxs94UZGgH+90E=",
+ "zh:0f7996e7ba9b81eca2372b1afe93120fdece292466e8b5133ce9e1ffc732012d",
+ "zh:536db13c42b1809bbe9e5ac25e4e99263403add754525854a8cfbd58559ea216",
+ "zh:5b31043a99d278ff29b755ae1ce24675cbf17bbcdffc2e09dc55d9ba086c78a0",
+ "zh:79a3b47fb979e287b7a3c91fb079718304e379ff04aa3b05eb005afa1f5a8b9c",
+ "zh:85ac7e469d60386561f35ef5217c281c4dd4686d341f9f21a35a1a75f326ae22",
+ "zh:85c81e4a982bc0ef2eb5d88bb3a70c28f305c88b97d028d5bc392082d130919b",
+ "zh:8f2978706aa86a05e0f647c7003edfe58e90efc1cca9b56c4666cff642f375f3",
+ "zh:a70970fdeb0efa4e32a6f63a7f995fbe59e961577497ecd3e3f5fd8de6897cad",
+ "zh:abed445784eb47cebb9772ad2fc76993e2d31df87335042f8216f9c982eedf99",
+ "zh:b226508cc60697939c3f28de1b25cd233b91546541b294ec9e019c16c190f3d9",
+ "zh:b6fa368791dec8fa417c779dfd9b56540543c9cf9cd039517332a7998834adbd",
+ "zh:c681633d8cd6e8d4c71f21b22b58b6a4e02e9191b66a197ab7a26dcd45599675",
+ "zh:e63f8b466d0c50cac2c62aaade44babc25c4c4d1c0ec422ebbd235ae5e3ec6d3",
+ ]
+}
DIR diff --git a/local/cloudinit/blocky-net.yaml b/local/cloudinit/blocky-net.yaml
@@ -0,0 +1,6 @@
+version: 2
+ethernets:
+ eth0:
+ addresses:
+ - 192.168.2.10/24
+ gateway4: 192.168.2.1
DIR diff --git a/local/cloudinit/blocky-user.yaml b/local/cloudinit/blocky-user.yaml
@@ -0,0 +1,41 @@
+#cloud-config
+package_upgrade: true
+hostname: blocky.jay.scot
+timezone: Europe/London
+manage_resolv_conf: true
+resolv_conf:
+ nameservers: ['192.168.2.10', '1.1.1.1']
+packages:
+ - blocky
+runcmd:
+ - rc-service blocky start
+write_files:
+ - path: /etc/blocky/config.yml
+ permissions: '0644'
+ defer: true
+ content: |
+ upstreams:
+ groups:
+ default:
+ - https://dns.quad9.net/dns-query
+ - https://anycast.uncensoreddns.org/dns-query
+
+ blocking:
+ blackLists:
+ ads:
+ - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
+ clientGroupsBlock:
+ default:
+ - ads
+
+ ports:
+ dns: 53
+
+ customDNS:
+ customTTL: 5m
+ filterUnmappedTypes: true
+ mapping:
+ blocky.jay.scot: 192.168.2.10
+ git.jay.scot: 192.168.2.12
+ nas.jay.scot: 192.168.2.14
+ jellyfin.jay.scot: 192.168.2.15
DIR diff --git a/local/cloudinit/nas-net.yaml b/local/cloudinit/nas-net.yaml
@@ -0,0 +1,6 @@
+version: 2
+ethernets:
+ eth0:
+ addresses:
+ - 192.168.2.14/24
+ gateway4: 192.168.2.1
DIR diff --git a/local/cloudinit/nas-user.yaml b/local/cloudinit/nas-user.yaml
@@ -0,0 +1,35 @@
+#cloud-config
+package_upgrade: true
+hostname: nas.jay.scot
+timezone: Europe/London
+manage_resolv_conf: true
+
+resolv_conf:
+ nameservers: ['192.168.2.10', '1.1.1.1']
+
+packages:
+ - samba
+
+users:
+ - name: samba
+ group: users
+ passwd: $6$WNXusbujTtdH5X3z$43RgrNloS.Qz9nVoN5jIiaSpzgrur9KpRwfiQP.3rVMOPVweJYVpqHKNH19PUrKbGQ7/hc04AqGXXe1USnpya0
+
+write_files:
+ - path: /etc/samba/smb.conf
+ permissions: '0644'
+ defer: true
+ content: |
+ [global]
+ allow insecure wide links = yes
+ workgroup = WORKGROUP
+ dos charset = cp866
+ unix charset = utf-8
+ force user = samba
+
+ [storage]
+ follow symlinks = yes
+ wide links = yes
+ browseable = yes
+ writeable = yes
+ path = /share
DIR diff --git a/local/main.tf b/local/main.tf
@@ -0,0 +1,44 @@
+terraform {
+ required_providers {
+ incus = {
+ source = "lxc/incus"
+ version = "0.1.2"
+ }
+ }
+}
+
+provider "incus" {
+ generate_client_certificates = true
+ accept_remote_certificate = true
+
+ remote {
+ name = "incus-server-1"
+ scheme = "https"
+ address = "192.168.1.148"
+ token = "eyJjbGllbnRfbmFtZSI6InRlcnJhZm9ybSIsImZpbmdlcnByaW50IjoiOTVmMDI2ZTZlOGY0YWZhYjYwOTgzMmQ0NDRmNjA1YzcwYTA3NTEzMjhhYzJlN2E0NGI5NmNiNWM3ZGY3OTk5ZCIsImFkZHJlc3NlcyI6WyIxOTIuMTY4LjEuMTQ4Ojg0NDMiLCIxOTIuMTY4LjIuMTo4NDQzIiwiW2ZkNDI6ODk1Nzo3YTA2Ojk5N2U6OjFdOjg0NDMiXSwic2VjcmV0IjoiMTMzZTVmN2VmM2Q0M2JjNzZkYmMyZDRlNjhhOWZhMThmMjg1NTI0YjUwZjM4Y2YwOTEzYjMyMmJjOGZmMDI4ZiIsImV4cGlyZXNfYXQiOiIwMDAxLTAxLTAxVDAwOjAwOjAwWiJ9"
+ default = true
+ }
+}
+
+resource "incus_instance" "main" {
+ for_each = var.nodes
+
+ name = each.key
+ image = each.value.image
+
+ config = {
+ "cloud-init.user-data" = file(each.value.cloudinit_userdata)
+ "cloud-init.network-config" = file(each.value.cloudinit_network)
+ }
+
+ dynamic "device" {
+ for_each = each.value.devices
+
+ content {
+ name = device.key
+ type = device.value.type
+ properties = device.value.properties
+ }
+
+ }
+}
DIR diff --git a/local/terraform.tfvars b/local/terraform.tfvars
@@ -0,0 +1,22 @@
+nodes = {
+ blocky = {
+ image = "images:alpine/3.20/cloud"
+ cloudinit_userdata = "./cloudinit/blocky-user.yaml"
+ cloudinit_network = "./cloudinit/blocky-net.yaml"
+ }
+ nas = {
+ image = "images:alpine/3.20/cloud"
+ cloudinit_userdata = "./cloudinit/nas-user.yaml"
+ cloudinit_network = "./cloudinit/nas-net.yaml"
+ devices = {
+ storage = {
+ type = "disk"
+ properties = {
+ path = "/share"
+ source = "/srv"
+ shift = true
+ }
+ }
+ }
+ }
+}
DIR diff --git a/local/variables.tf b/local/variables.tf
@@ -0,0 +1,13 @@
+variable "nodes" {
+ description = "Configuration settings for each required node."
+ type = map(object({
+ image = string
+ cloudinit_userdata = string
+ cloudinit_network = string
+ devices = optional(map(object({
+ type = string
+ properties = map(any)
+ })), {})
+ }))
+ default = {}
+}
DIR diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl
@@ -1,24 +0,0 @@
-# This file is maintained automatically by "terraform init".
-# Manual edits may be lost in future updates.
-
-provider "registry.terraform.io/hetznercloud/hcloud" {
- version = "1.45.0"
- constraints = "1.45.0"
- hashes = [
- "h1:BEE0B6hv1ZAmTLIO12uqIm7s3oSjmGzZLm6OzudlxAw=",
- "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",
- ]
-}
DIR diff --git a/terraform/checks.tf b/terraform/checks.tf
@@ -1,8 +0,0 @@
-check "server_status" {
- assert {
- condition = alltrue([
- for k, v in var.nodes : hcloud_server.this[k].status == "running"
- ])
- error_message = "Server status check failed."
- }
-}
DIR diff --git a/terraform/files/id_rsa.pub b/terraform/files/id_rsa.pub
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCRWnkYAChsjuT/T/IoENtm8OT18tPereaw6OOqmZ5Kvx2W8wCLL8zaBK1ieYRTeDfNU6cnAEkZdn0B2/twWvDLwyTihkWKa6FxdZ8Pv+4BEDhUS5jpxUhpBbLMOKu1SRTu9cr3jv7CcK90ouMes4d9Mnm76C0yskCBTiXdNKZ0LEYf+7hbRN1UnF9tG+RNHpnqx/3uKSWEjAEwu0lXLzOsJhNZMUXaruoKVohvRS1h9C3CT5SKWjhVX7f0oVWtSt4BhExO9B4lOgfPFZ46Aj+AsFffk2TluQq9ChdJXmSxd6OBRUae4KuX4QykHty9cU+63O45PZp92Ay8Gk5tlSqlFn2DUc4gU68CKcAwQSM018ASQiWou4Gw9Dq8sKa6R1HIi7X3marVJW/wKLu7xFyIiWYddyUGNhuINpj+vx0fk5ET+dE+5i43kM6YVWSAyazyGRhholPFFh7y4+FbdG+lkMnU9ScvnB8j0nTMOptu9HwIAVhVqHK1s+aJgRp4QU= me@jay.scot
DIR diff --git a/terraform/main.tf b/terraform/main.tf
@@ -1,71 +0,0 @@
-terraform {
- required_version = ">=1.7.0"
- required_providers {
- hcloud = {
- source = "hetznercloud/hcloud"
- version = "1.45.0"
- }
- }
- cloud {
- }
-}
-
-resource "hcloud_ssh_key" "this" {
- for_each = var.public_ssh_keys
-
- name = each.key
- public_key = file(each.value)
-}
-
-
-resource "hcloud_firewall" "this" {
- for_each = var.firewall_rules
-
- name = each.key
-
- dynamic "rule" {
- for_each = each.value.rules
-
- content {
- description = rule.key
- direction = rule.value.direction
- protocol = rule.value.protocol
- source_ips = rule.value.source_ips
- port = rule.value.port
- }
- }
-}
-
-
-resource "hcloud_server" "this" {
- for_each = var.nodes
-
- name = each.key
- image = each.value.image
- server_type = each.value.server_type
- location = each.value.location
- labels = each.value.labels
- ssh_keys = [hcloud_ssh_key.this[each.value.public_key].id]
- user_data = file(each.value.user_data)
- firewall_ids = [hcloud_firewall.this[each.key].id]
-
- public_net {
- ipv4_enabled = each.value.ipv4
- ipv6_enabled = each.value.ipv6
- }
-
- lifecycle {
- postcondition {
- condition = self.status == "running"
- error_message = "Instance must be running."
- }
- }
-}
-
-resource "hcloud_rdns" "this" {
- for_each = hcloud_server.this
-
- server_id = each.value.id
- ip_address = each.value.ipv4_address
- dns_ptr = var.nodes[each.key].reverse_dns
-}
DIR diff --git a/terraform/outputs.tf b/terraform/outputs.tf
@@ -1,3 +0,0 @@
-output "public_ip_address" {
- value = { for name, server in hcloud_server.this : name => server.ipv4_address }
-}
DIR diff --git a/terraform/terraform.tfvars b/terraform/terraform.tfvars
@@ -1,48 +0,0 @@
-public_ssh_keys = {
- main = "./files/id_rsa.pub"
-}
-
-firewall_rules = {
- "docker-1" = {
- rules = {
- gopher = {
- direction = "in"
- protocol = "tcp"
- source_ips = ["0.0.0.0/0", "::/0"]
- port = "70"
- }
- ssh = {
- direction = "in"
- protocol = "tcp"
- source_ips = ["0.0.0.0/0", "::/0"]
- port = "22"
- }
- fingerd = {
- direction = "in"
- protocol = "tcp"
- source_ips = ["0.0.0.0/0", "::/0"]
- port = "79"
- }
- }
- }
-
-}
-
-nodes = {
- "docker-1" = {
- image = "debian-12"
- location = "hel1",
- server_type = "cx11",
- reverse_dns = "jay.scot"
- user_data = "user_data/docker.yml"
- public_key = "main"
- ipv4 = true
- ipv6 = true
- labels = {
- gopher = "true"
- docker = "true"
- finger = "true"
- }
- }
-
-}
DIR diff --git a/terraform/user_data/boot.yml b/terraform/user_data/boot.yml
@@ -1,16 +0,0 @@
-#cloud-config
-
-# disable ssh password authentication
-ssh_pwauth: false
-
-# TODO: add in a ansible pull on boot at somepoint.
-# add an ansible user
-users:
- - name: ansible
- gecos: Ansible User
- groups: users,wheel
- sudo: ALL=(ALL) NOPASSWD:ALL
- shell: /bin/bash
- lock_passwd: true
- ssh_authorized_keys:
- - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCRWnkYAChsjuT/T/IoENtm8OT18tPereaw6OOqmZ5Kvx2W8wCLL8zaBK1ieYRTeDfNU6cnAEkZdn0B2/twWvDLwyTihkWKa6FxdZ8Pv+4BEDhUS5jpxUhpBbLMOKu1SRTu9cr3jv7CcK90ouMes4d9Mnm76C0yskCBTiXdNKZ0LEYf+7hbRN1UnF9tG+RNHpnqx/3uKSWEjAEwu0lXLzOsJhNZMUXaruoKVohvRS1h9C3CT5SKWjhVX7f0oVWtSt4BhExO9B4lOgfPFZ46Aj+AsFffk2TluQq9ChdJXmSxd6OBRUae4KuX4QykHty9cU+63O45PZp92Ay8Gk5tlSqlFn2DUc4gU68CKcAwQSM018ASQiWou4Gw9Dq8sKa6R1HIi7X3marVJW/wKLu7xFyIiWYddyUGNhuINpj+vx0fk5ET+dE+5i43kM6YVWSAyazyGRhholPFFh7y4+FbdG+lkMnU9ScvnB8j0nTMOptu9HwIAVhVqHK1s+aJgRp4QU= jay@elma.jay.scot
DIR diff --git a/terraform/user_data/docker.yml b/terraform/user_data/docker.yml
@@ -1,25 +0,0 @@
-#cloud-config
-
-# disable ssh password authentication
-ssh_pwauth: false
-
-package_update: true
-
-packages:
- - htop
- - vim
- - lynx
- - finger
- - unattended-upgrades
- - apparmor-utils
- - docker.io
-
-users:
- - name: jay
- gecos: Jay Scott
- groups: users,wheel,docker
- sudo: ALL=(ALL) NOPASSWD:ALL
- shell: /bin/bash
- lock_passwd: true
- ssh_authorized_keys:
- - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCRWnkYAChsjuT/T/IoENtm8OT18tPereaw6OOqmZ5Kvx2W8wCLL8zaBK1ieYRTeDfNU6cnAEkZdn0B2/twWvDLwyTihkWKa6FxdZ8Pv+4BEDhUS5jpxUhpBbLMOKu1SRTu9cr3jv7CcK90ouMes4d9Mnm76C0yskCBTiXdNKZ0LEYf+7hbRN1UnF9tG+RNHpnqx/3uKSWEjAEwu0lXLzOsJhNZMUXaruoKVohvRS1h9C3CT5SKWjhVX7f0oVWtSt4BhExO9B4lOgfPFZ46Aj+AsFffk2TluQq9ChdJXmSxd6OBRUae4KuX4QykHty9cU+63O45PZp92Ay8Gk5tlSqlFn2DUc4gU68CKcAwQSM018ASQiWou4Gw9Dq8sKa6R1HIi7X3marVJW/wKLu7xFyIiWYddyUGNhuINpj+vx0fk5ET+dE+5i43kM6YVWSAyazyGRhholPFFh7y4+FbdG+lkMnU9ScvnB8j0nTMOptu9HwIAVhVqHK1s+aJgRp4QU= jay@elma.jay.scot
DIR diff --git a/terraform/variables.tf b/terraform/variables.tf
@@ -1,25 +0,0 @@
-
-variable "public_ssh_keys" {
- description = "Public SSH key location to attach to instance."
- type = map(any)
-}
-
-variable "firewall_rules" {
- description = "Firewall configuration settings."
- type = map(any)
-}
-
-variable "nodes" {
- description = "Configuration settings for each required node."
- type = map(object({
- image = string
- location = string
- server_type = string
- reverse_dns = string
- user_data = string
- public_key = string
- labels = map(any)
- ipv4 = bool
- ipv6 = bool
- }))
-}