Initial commit

This commit is contained in:
2026-06-17 22:31:40 +01:00
commit 799b19d445
11 changed files with 635 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env sh
set -e
err() { echo "$@" >&2; exit 1; }
log() { echo "$@" >&2; }
[ "$(id -u)" -ne 0 ] && err "You must run this script as root"
# Install minimal packages for provisioning
PACKAGES="dropbear openssh-sftp-server python3 py3-yaml py3-kubernetes cloud-utils-growpart e2fsprogs-extra lsblk"
apk update && apk upgrade
apk add ${PACKAGES}
# Enable and start services
enable_and_start() {
service="$1"
rc-update add "${service}" default
service "${service}" start
}
enable_and_start dropbear
# increase root partition size
root_dev=$(readlink -f /dev/root)
disk=$(lsblk -no pkname "$root_dev")
part_num=$(echo "$root_dev" | sed 's|.*[^0-9]||')
echo "Growing /dev/${disk}${part_num}..."
# Grow partition and resize
growpart "/dev/$disk" "$part_num" || err "Partition growth failed"
resize2fs "$root_dev" || err "Filesystem resize failed"
+202
View File
@@ -0,0 +1,202 @@
# ------
# Locals
# ------
locals {
root_disk_size = "16GiB"
ext_disk_size = "16GiB"
network_cidr = "10.150.0.1/24"
master_count = 2
worker_count = 0
}
# ---------
# Resources
# ---------
resource "incus_project" "this" {
name = "deskpi-cluster"
description = "The emulated DeskPi Super6C stack."
}
resource "incus_image" "alpine" {
project = incus_project.this.name
source_image = {
remote = "images"
name = "alpine/edge"
type = "virtual-machine"
}
}
resource "incus_profile" "this" {
name = "Default"
description = "The default profile applied to both masters and workers."
project = incus_project.this.name
depends_on = [incus_network.this]
config = {
"limits.cpu" = var.cpus
"limits.memory" = var.memory
"boot.autostart" = false
"security.secureboot" = false
}
device {
name = "root"
type = "disk"
properties = {
"pool" = "default"
"path" = "/"
"size" = local.root_disk_size
}
}
}
resource "incus_network" "this" {
name = "deskpi-cluster"
description = "An emulated network for the DeskPi Super6C cluster project."
project = incus_project.this.name
type = "bridge"
config = {
"ipv4.address" = local.network_cidr
"ipv4.nat" = true
}
}
resource "incus_instance" "master" {
count = local.master_count
name = "master-${count.index}"
description = "Kubernetes Master ${count.index}"
project = incus_project.this.name
type = "virtual-machine"
image = incus_image.alpine.fingerprint
profiles = [incus_profile.this.name]
wait_for {
type = "agent"
}
file {
source_path = "bootstrap.sh"
target_path = "/bootstrap.sh"
}
file {
source_path = "../ansible/.ssh/key.pub"
target_path = "/root/.ssh/authorized_keys"
create_directories = true
}
device {
name = "eth0"
type = "nic"
properties = {
"network" = incus_network.this.name
"ipv4.address" = cidrhost(local.network_cidr, 2 + (2 * count.index))
}
}
device {
name = "ext"
type = "disk"
properties = {
"pool" = "default"
"source" = incus_storage_volume.master[count.index].name
}
}
exec = { "00-init" = { command = ["/bootstrap.sh"] } }
}
resource "incus_storage_volume" "master" {
count = local.master_count
name = "master-ext-${count.index}"
description = "External drive for master ${count.index}"
pool = "default"
project = incus_project.this.name
content_type = "block"
config = {
"size" = local.ext_disk_size
}
}
resource "incus_instance" "worker" {
count = local.worker_count
name = "worker-${count.index}"
description = "Kubernetes Worker ${count.index}"
project = incus_project.this.name
type = "virtual-machine"
image = incus_image.alpine.fingerprint
profiles = [incus_profile.this.name]
wait_for {
type = "agent"
}
file {
source_path = "bootstrap.sh"
target_path = "/bootstrap.sh"
}
file {
source_path = "../ansible/.ssh/key.pub"
target_path = "/root/.ssh/authorized_keys"
create_directories = true
}
device {
name = "eth0"
type = "nic"
properties = {
"network" = incus_network.this.name
"ipv4.address" = cidrhost(local.network_cidr, 3 + (2 * count.index))
}
}
exec = { "00-init" = { command = ["/bootstrap.sh"] } }
}
# -------
# Outputs
# -------
output "master_addresses" {
value = incus_instance.master[*].ipv4_address
}
output "worker_addresses" {
value = incus_instance.worker[*].ipv4_address
}
# ---------
# Terraform
# ---------
terraform {
required_version = "~> 1"
required_providers {
incus = {
source = "lxc/incus"
version = "~> 1"
}
}
}
provider "incus" {
}
+18
View File
@@ -0,0 +1,18 @@
variable "cpus" {
description = "The number of CPU cores allocated to each virtual machine."
type = number
default = 2
nullable = false
validation {
condition = var.cpus >= 1
error_message = "Allocated CPUs must be equal to or greater than 1."
}
}
variable "memory" {
description = "The amount of memory allocated to each virtual machine."
type = string
default = "4GiB"
nullable = false
}