Skip to content

Commit 24a8206

Browse files
committed
feat: talos-image SBC overlay support, fix talosconfig output format
- talos-image module: Add sbc_overlay variable for single-board computers - Support for turingrk1, rock5b, rpi_generic, jetson_nano, and 16+ SBC boards - Auto-detection of overlay images from overlay name - talos-cluster module: Fix talosconfig output format - Now generates proper YAML with context, endpoints, nodes - Add talosconfig_path output - talos-wipe.sh: Remove eMMC wipe attempt (system disk), add --yes flag - Update CHANGELOG.md and README.md for v1.3.9
1 parent 559fdc3 commit 24a8206

File tree

8 files changed

+142
-45
lines changed

8 files changed

+142
-45
lines changed

CHANGELOG.md

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.3.9] - 2026-01-19
11+
1012
### Added
13+
- **talos-image module**: SBC overlay support for single-board computers
14+
- New `sbc_overlay` variable for board-specific overlays (turingrk1, rpi_generic, rock5b, etc.)
15+
- Auto-detection of overlay images from overlay name
16+
- Supports 16+ SBC boards across Rockchip, Raspberry Pi, Jetson, and Allwinner families
17+
- **talos-cluster module**: Added `talosconfig_path` output
18+
- **talos-wipe.sh**: Added `--yes` / `-y` flag for non-interactive automation
1119
- **scripts/find-armbian-image.sh** - Find and download Armbian images for Turing RK1 from GitHub releases
12-
- Lists all available images with `--list`
13-
- Downloads images with `--download`
14-
- Generates Armbian autoconfig files for first-boot setup with `--autoconfig`
15-
- SSH public key setup with `--ssh-key` for passwordless access
16-
- Static IP configuration with `--static-ip`, `--gateway`, `--netmask`, `--dns`
20+
- **test/addon-test/** - Comprehensive addon module test configuration
21+
- **test/provider-test/** - Provider data source test configuration
1722

1823
### Fixed
19-
- Shellcheck SC2002 warnings in helper scripts (replaced `cat file | cmd` with `cmd < file`)
24+
- **talos-cluster module**: Fixed talosconfig output format - now generates proper YAML with context, endpoints, nodes (previously output unusable JSON)
25+
- **talos-wipe.sh**: Removed eMMC wipe attempt - eMMC is system disk and cannot be wiped via talosctl reset
26+
- Shellcheck SC2002 warnings in helper scripts
2027

2128
### Changed
22-
- Enhanced docs/WORKFLOWS.md with comprehensive K3s deployment steps
23-
- Network planning section with DHCP reservation recommendation
24-
- Static IP configuration via autoconfig for networks without DHCP reservations
25-
- Direct URL flashing via BMC API
26-
- Autoconfig generation for automated first-boot setup
27-
- Node configuration scripts for password, hostname, SSH keys
28-
- K3s prerequisites (open-iscsi, nfs-common) for Longhorn support
29+
- Enhanced docs/WORKFLOWS.md with comprehensive K3s and Talos deployment steps
30+
- Updated README version references to ~> 1.3.9
31+
32+
### Verified
33+
- All addon modules tested on Talos v1.9.2 (Turing RK1 with turingrk1 overlay)
34+
- metallb: L2 mode with IP pool 10.10.88.80-89
35+
- ingress-nginx: LoadBalancer service on 10.10.88.80
36+
- cert-manager: Self-signed CA and ClusterIssuers ready
37+
- longhorn: StorageClass created with NVMe storage class
38+
- monitoring: Prometheus + Grafana with persistent storage
39+
- portainer: Agent accessible on 10.10.88.81:9001
40+
- Talos Image Factory integration with SBC overlays verified
2941

3042
## [1.3.8] - 2026-01-19
3143

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Reusable Terraform modules for Turing Pi cluster provisioning and management.
3333
# Deploy Talos cluster
3434
module "talos" {
3535
source = "jfreed-dev/modules/turingpi//modules/talos-cluster"
36-
version = ">= 1.3.0"
36+
version = "~> 1.3.9"
3737
3838
cluster_name = "homelab"
3939
cluster_endpoint = "https://192.168.1.101:6443"
@@ -65,7 +65,7 @@ module "metallb" {
6565
# Deploy K3s cluster
6666
module "k3s" {
6767
source = "jfreed-dev/modules/turingpi//modules/k3s-cluster"
68-
version = ">= 1.3.0"
68+
version = "~> 1.3.9"
6969
7070
cluster_name = "homelab"
7171
@@ -239,9 +239,19 @@ module "monitoring" {
239239
## Requirements
240240

241241
- Terraform >= 1.0
242-
- [Turing Pi Provider](https://github.com/jfreed-dev/terraform-provider-turingpi) >= 1.3.0 (for flashing)
242+
- [Turing Pi Provider](https://github.com/jfreed-dev/terraform-provider-turingpi) ~> 1.3.9 (for flashing)
243243
- [Talos Provider](https://github.com/siderolabs/terraform-provider-talos) >= 0.7 (for Talos clusters)
244244

245+
## Verified Configurations
246+
247+
Tested and verified on v1.3.9:
248+
- K3s v1.31.4+k3s1 on Armbian 26.2.0-trunk.151 (trixie)
249+
- BMC firmware v2.3.4
250+
- MetalLB L2 mode with IP pool assignment
251+
- Longhorn with 2-replica volumes
252+
- Prometheus/Grafana with persistent storage
253+
- Ingress-NGINX with LoadBalancer service
254+
245255
## License
246256

247257
Apache License 2.0

modules/talos-cluster/main.tf

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,24 @@ resource "local_file" "kubeconfig" {
9797
}
9898

9999
# Write talosconfig to file if path specified
100+
# Format: proper talosctl YAML with context, endpoints, and nodes
100101
resource "local_file" "talosconfig" {
101-
count = var.talosconfig_path != null ? 1 : 0
102-
content = yamlencode(talos_machine_secrets.this.client_configuration)
102+
count = var.talosconfig_path != null ? 1 : 0
103+
content = yamlencode({
104+
context = var.cluster_name
105+
contexts = {
106+
(var.cluster_name) = {
107+
endpoints = [for node in var.control_plane : node.host]
108+
nodes = concat(
109+
[for node in var.control_plane : node.host],
110+
[for node in var.workers : node.host]
111+
)
112+
ca = talos_machine_secrets.this.client_configuration.ca_certificate
113+
crt = talos_machine_secrets.this.client_configuration.client_certificate
114+
key = talos_machine_secrets.this.client_configuration.client_key
115+
}
116+
}
117+
})
103118
filename = var.talosconfig_path
104119
file_permission = "0600"
105120
}

modules/talos-cluster/outputs.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ output "kubeconfig_path" {
3131
value = var.kubeconfig_path != null ? var.kubeconfig_path : null
3232
}
3333

34+
output "talosconfig_path" {
35+
description = "Path to talosconfig file (if written)"
36+
value = var.talosconfig_path != null ? var.talosconfig_path : null
37+
}
38+
3439
output "nvme_enabled" {
3540
description = "Whether NVMe storage is configured"
3641
value = var.nvme_storage_enabled

modules/talos-image/main.tf

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,70 @@ locals {
88
full = ["siderolabs/iscsi-tools", "siderolabs/util-linux-tools", "siderolabs/nfs-utils", "siderolabs/qemu-guest-agent"]
99
}
1010

11+
# SBC overlay image mapping (overlay name -> image)
12+
sbc_overlay_images = {
13+
# Rockchip-based boards
14+
turingrk1 = "siderolabs/sbc-rockchip"
15+
rock5b = "siderolabs/sbc-rockchip"
16+
rockpi4 = "siderolabs/sbc-rockchip"
17+
rockpi4c = "siderolabs/sbc-rockchip"
18+
rock4cplus = "siderolabs/sbc-rockchip"
19+
rock4se = "siderolabs/sbc-rockchip"
20+
rock64 = "siderolabs/sbc-rockchip"
21+
nanopi-r4s = "siderolabs/sbc-rockchip"
22+
nanopi-r5s = "siderolabs/sbc-rockchip"
23+
orangepi-r1-plus-lts = "siderolabs/sbc-rockchip"
24+
helios64 = "siderolabs/sbc-rockchip"
25+
# Raspberry Pi boards
26+
rpi_generic = "siderolabs/sbc-raspberrypi"
27+
# Jetson boards
28+
jetson_nano = "siderolabs/sbc-jetson"
29+
# Allwinner-based boards
30+
bananapi_m64 = "siderolabs/sbc-allwinner"
31+
libretech_all_h3_cc_h5 = "siderolabs/sbc-allwinner"
32+
pine64 = "siderolabs/sbc-allwinner"
33+
}
34+
35+
# Determine the overlay image (explicit or auto-detected)
36+
resolved_overlay_image = var.sbc_overlay != null ? coalesce(
37+
var.sbc_overlay_image,
38+
lookup(local.sbc_overlay_images, var.sbc_overlay, null)
39+
) : null
40+
1141
# Merge preset extensions with custom extensions
1242
all_extensions = distinct(concat(
1343
local.preset_extensions[var.preset],
1444
var.extensions
1545
))
1646

17-
# Build the schematic YAML
18-
schematic_yaml = yamlencode({
19-
customization = {
20-
systemExtensions = length(local.all_extensions) > 0 ? {
21-
officialExtensions = local.all_extensions
22-
} : null
23-
extraKernelArgs = length(var.extra_kernel_args) > 0 ? var.extra_kernel_args : null
24-
}
25-
})
47+
# Build the schematic YAML (with optional SBC overlay)
48+
schematic_yaml = yamlencode(merge(
49+
{
50+
customization = {
51+
systemExtensions = length(local.all_extensions) > 0 ? {
52+
officialExtensions = local.all_extensions
53+
} : null
54+
extraKernelArgs = length(var.extra_kernel_args) > 0 ? var.extra_kernel_args : null
55+
}
56+
},
57+
var.sbc_overlay != null && local.resolved_overlay_image != null ? {
58+
overlay = {
59+
name = var.sbc_overlay
60+
image = local.resolved_overlay_image
61+
}
62+
} : {}
63+
))
2664

2765
# Known schematic IDs for common configurations (saves API calls)
66+
# Note: Overlays are version-specific, so we can only cache non-overlay schematics
2867
known_schematics = {
29-
# iscsi-tools + util-linux-tools (Longhorn support)
68+
# iscsi-tools + util-linux-tools (Longhorn support) - no overlay
3069
"siderolabs/iscsi-tools,siderolabs/util-linux-tools" = "613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245"
3170
}
3271

33-
# Check if we have a known schematic ID
72+
# Check if we have a known schematic ID (only when no overlay is specified)
3473
extensions_key = join(",", sort(local.all_extensions))
35-
known_schematic = lookup(local.known_schematics, local.extensions_key, null)
74+
known_schematic = var.sbc_overlay == null ? lookup(local.known_schematics, local.extensions_key, null) : null
3675
use_known = local.known_schematic != null
3776
}
3877

modules/talos-image/outputs.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,13 @@ output "download_command" {
3737
description = "curl command to download the image"
3838
value = local.schematic_id != null ? "curl -LO ${local.image_base_url}/${var.platform}-${var.architecture}.raw.xz" : null
3939
}
40+
41+
output "sbc_overlay" {
42+
description = "SBC overlay name (if configured)"
43+
value = var.sbc_overlay
44+
}
45+
46+
output "sbc_overlay_image" {
47+
description = "SBC overlay image (if configured)"
48+
value = local.resolved_overlay_image
49+
}

modules/talos-image/variables.tf

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,16 @@ variable "preset" {
4949
error_message = "Preset must be 'none', 'longhorn', 'longhorn-nfs', 'qemu', or 'full'."
5050
}
5151
}
52+
53+
# SBC Overlay configuration
54+
variable "sbc_overlay" {
55+
description = "SBC overlay name for single-board computers (e.g., 'turingrk1', 'rpi_generic', 'rock5b'). Required for SBC hardware support."
56+
type = string
57+
default = null
58+
}
59+
60+
variable "sbc_overlay_image" {
61+
description = "SBC overlay image name (e.g., 'siderolabs/sbc-rockchip'). If not specified, auto-detected from overlay name."
62+
type = string
63+
default = null
64+
}

scripts/talos-wipe.sh

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
# -p, --password PASS BMC password (default: turing, or TURINGPI_PASSWORD env)
1414
# -d, --disks DEVICES Comma-separated user disks to wipe (default: /dev/nvme0n1)
1515
# --no-nvme Skip NVMe wipe
16-
# --no-emmc Skip eMMC wipe (eMMC wiped by default)
1716
# --clean-terraform Also clean terraform state files
1817
# --force-power-off Force power off via BMC if graceful shutdown fails
18+
# --yes, -y Skip interactive confirmation (for automation)
1919
# --log FILE Log output to file
2020
# --dry-run Show commands without executing
2121
# -h, --help Show this help message
@@ -38,11 +38,10 @@ BMC_IP="${TURINGPI_ENDPOINT:-}"
3838
BMC_USER="${TURINGPI_USERNAME:-}"
3939
BMC_PASSWORD="${TURINGPI_PASSWORD:-}"
4040
USER_DISKS="/dev/nvme0n1"
41-
EMMC_DEVICE="/dev/mmcblk0"
4241
WIPE_NVME=true
43-
WIPE_EMMC=true
4442
CLEAN_TERRAFORM=false
4543
FORCE_POWER_OFF=false
44+
SKIP_CONFIRM=false
4645
LOG_FILE=""
4746
DRY_RUN=false
4847

@@ -117,9 +116,9 @@ while [[ $# -gt 0 ]]; do
117116
-p|--password) BMC_PASSWORD="$2"; shift 2 ;;
118117
-d|--disks) USER_DISKS="$2"; shift 2 ;;
119118
--no-nvme) WIPE_NVME=false; shift ;;
120-
--no-emmc) WIPE_EMMC=false; shift ;;
121119
--clean-terraform) CLEAN_TERRAFORM=true; shift ;;
122120
--force-power-off) FORCE_POWER_OFF=true; shift ;;
121+
--yes|-y) SKIP_CONFIRM=true; shift ;;
123122
--log) LOG_FILE="$2"; shift 2 ;;
124123
--dry-run) DRY_RUN=true; shift ;;
125124
-h|--help) show_help ;;
@@ -282,20 +281,18 @@ echo ""
282281
echo "Data to be PERMANENTLY DESTROYED:"
283282
echo " • Talos system partitions (STATE, EPHEMERAL)"
284283
[[ "$WIPE_NVME" == "true" ]] && echo -e " ${RED}• NVMe drives: $USER_DISKS${NC}"
285-
[[ "$WIPE_EMMC" == "true" ]] && echo -e " ${RED}• eMMC boot drives: $EMMC_DEVICE${NC}"
284+
echo ""
285+
echo -e "${YELLOW}Note: eMMC is system disk and cannot be wiped via talosctl reset${NC}"
286286
echo ""
287287
[[ "$CLEAN_TERRAFORM" == "true" ]] && echo "Terraform cleanup: enabled"
288288
[[ "$FORCE_POWER_OFF" == "true" ]] && echo "Force power off: enabled"
289289
[[ -n "$LOG_FILE" ]] && echo "Logging to: $LOG_FILE"
290290
[[ "$DRY_RUN" == "true" ]] && echo -e "${YELLOW}DRY RUN MODE - No changes will be made${NC}"
291291
echo ""
292292

293-
# Confirm before proceeding
294-
if [[ "$DRY_RUN" != "true" ]]; then
293+
# Confirm before proceeding (unless --yes flag or dry-run)
294+
if [[ "$DRY_RUN" != "true" && "$SKIP_CONFIRM" != "true" ]]; then
295295
echo -e "${RED}This will PERMANENTLY DESTROY ALL DATA on these nodes!${NC}"
296-
if [[ "$WIPE_EMMC" == "true" ]]; then
297-
echo -e "${RED}Nodes will be UNBOOTABLE until re-flashed via BMC!${NC}"
298-
fi
299296
echo ""
300297
read -p "Type 'DESTROY' to confirm: " confirm
301298
if [[ "$confirm" != "DESTROY" ]]; then
@@ -317,18 +314,14 @@ if [[ -f "$TALOSCONFIG" ]]; then
317314
WIPE_CMD+=" --system-labels-to-wipe STATE --system-labels-to-wipe EPHEMERAL"
318315

319316
# Add NVMe disks if enabled
317+
# Note: eMMC is system disk and cannot be wiped via talosctl reset
320318
if [[ "$WIPE_NVME" == "true" && -n "$USER_DISKS" ]]; then
321319
IFS=',' read -ra DISK_ARRAY <<< "$USER_DISKS"
322320
for disk in "${DISK_ARRAY[@]}"; do
323321
WIPE_CMD+=" --user-disks-to-wipe $disk"
324322
done
325323
fi
326324

327-
# Add eMMC disk if enabled
328-
if [[ "$WIPE_EMMC" == "true" && -n "$EMMC_DEVICE" ]]; then
329-
WIPE_CMD+=" --user-disks-to-wipe $EMMC_DEVICE"
330-
fi
331-
332325
# Don't reboot - we want to shutdown
333326
WIPE_CMD+=" --reboot=false"
334327

0 commit comments

Comments
 (0)