Scaffold incremental Terraform foundations for docker and proxmox

This commit is contained in:
beatz174-bit
2026-04-14 18:08:56 +10:00
parent 7279ade925
commit 228413d780
18 changed files with 301 additions and 15 deletions
+14
View File
@@ -0,0 +1,14 @@
.terraform/
*.tfstate
*.tfstate.*
*.tfvars
*.tfvars.json
crash.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json
*.tfplan
plan.out
state/
artifacts/
+38
View File
@@ -0,0 +1,38 @@
# Terraform foundations
This directory introduces Terraform in a conservative, incremental way for this homelab repo.
## Purpose in this repository
Terraform is used here to **document and gradually adopt management** of existing infrastructure without disrupting running services.
Current intent:
- Start with imported live Docker resources so infrastructure is visible and reproducible in code.
- Add Proxmox inventory/configuration later once provider details and import IDs are confirmed.
- Keep this phase local-state and learning-oriented (no remote backend yet).
## Tool boundaries
- **Docker Compose**: day-to-day application/service runtime definitions already used by this repo.
- **Terraform**: infrastructure state capture and controlled resource management (starting with imports).
- **Ansible**: follow-on host/configuration management after Terraform inventory and targets are stable.
- **NixOS**: host OS/system-level declarative configuration, separate from per-service compose workflows.
## Layout
- `docker/`: Docker provider scaffold and incremental import workflow.
- `proxmox/`: placeholder scaffold for later Proxmox adoption.
- `modules/`: placeholder module directories for future shared patterns.
## Incremental adoption plan
1. Import Docker containers one-by-one into Terraform state.
2. Reconcile and stabilize Docker Terraform configuration until `terraform plan` is clean.
3. Add Proxmox inventory/configuration scaffolding and imports later.
4. Introduce Ansible workflow after Terraform-managed inventory is trustworthy.
## Safety notes
- State files are intentionally gitignored for safety and portability.
- Do **not** run `terraform apply` until imported resources are fully reconciled and plan output is reviewed as no-op for intended targets.
- No remote backend is configured yet by design.
+48
View File
@@ -0,0 +1,48 @@
# Docker Terraform scaffold
This directory is for **incremental, import-first Terraform adoption** of existing Docker containers.
## What this directory is for
- Document existing live Docker resources in Terraform.
- Import containers one-by-one.
- Reconcile Terraform code with real runtime values until plan is clean.
## Initialize
From this directory:
```bash
terraform init
```
## Safe incremental import workflow
1. Add one `docker_container` resource block in `main.tf` for an already-running container.
2. Import it into state:
```bash
terraform import docker_container.<resource_name> <container_id_or_container_name>
```
3. Inspect imported state:
```bash
terraform state show docker_container.<resource_name>
```
4. Copy required/meaningful arguments from state output into `main.tf`.
5. Run `terraform plan` and refine until there are no unintended changes.
## Reconciliation guidance
- Keep one resource block per imported container.
- Prefer explicit values for arguments that affect recreation.
- Avoid broad changes; reconcile each container independently.
- Do **not** run `terraform apply` until plan output is intentionally clean.
## State and secrets handling
- State files are ignored via `../.gitignore` because they may contain environment-specific metadata.
- Do not commit real `.tfvars` files with machine-specific values.
- Use `terraform.tfvars.example` as a safe starter template.
+16 -15
View File
@@ -1,16 +1,17 @@
terraform { # Docker Terraform workflow in this repo:
required_providers { # 1) Add a minimal resource block for ONE existing container.
docker = { # 2) Import that live container into state:
source = "kreuzwerker/docker" # terraform import docker_container.<name> <container_id_or_name>
version = "~> 3.0" # 3) Inspect imported arguments:
} # terraform state show docker_container.<name>
} # 4) Copy required arguments into this file and refine.
} # 5) Repeat until terraform plan shows no unintended changes.
provider "docker" { # Example skeleton for future imported containers (intentionally commented):
host = "unix:///var/run/docker.sock" # resource "docker_container" "example_service" {
} # name = "existing-container-name"
resource "docker_container" "searxng" { # image = "repo/image:tag"
name = "searxng-webapp" #
image = "searxng/searxng" # # Add additional arguments based on `terraform state show` output.
} # # Keep values aligned with the live container so plan is a no-op.
# }
@@ -0,0 +1,19 @@
output "docker_host_in_use" {
description = "Docker daemon endpoint currently targeted by this workspace."
value = var.docker_host
}
output "managed_container_names" {
description = "Names of containers intentionally tracked in Terraform configuration."
value = var.managed_container_names
}
output "import_reconciliation_steps" {
description = "Short reminder of the safe import-first workflow."
value = [
"Create one docker_container block for an existing container.",
"Run terraform import for that block.",
"Run terraform state show and copy required arguments.",
"Refine config until terraform plan has no unintended changes.",
]
}
@@ -0,0 +1,4 @@
provider "docker" {
# Local Docker socket default for incremental import/documentation workflow.
host = var.docker_host
}
@@ -0,0 +1,9 @@
# Example only. Copy to terraform.tfvars for local use if needed.
# Do not commit host-specific overrides.
# docker_host = "unix:///var/run/docker.sock"
# Optional: list container names intentionally tracked in Terraform outputs.
managed_container_names = [
"example-container-name"
]
@@ -0,0 +1,11 @@
variable "docker_host" {
description = "Docker daemon host for local import workflow."
type = string
default = "unix:///var/run/docker.sock"
}
variable "managed_container_names" {
description = "Human-maintained list of containers intentionally tracked in Terraform docs/outputs."
type = list(string)
default = []
}
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.6.0"
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "3.0.2"
}
}
}
@@ -0,0 +1,6 @@
# docker_container_placeholder module
Placeholder module directory for future shared Docker container patterns.
This is intentionally empty during initial import-first adoption.
Keep per-container resources explicit in `../../docker/main.tf` until stable patterns emerge.
@@ -0,0 +1,6 @@
# proxmox_vm_placeholder module
Placeholder module directory for future shared Proxmox VM patterns.
This is intentionally empty until provider schemas, import ID formats,
and non-destructive reconciliation strategy are validated.
@@ -0,0 +1,36 @@
# Proxmox Terraform scaffold
This directory is a **placeholder scaffold** for future Proxmox Terraform adoption.
## What this directory is for
- Prepare provider/version/variable structure now.
- Delay real Proxmox resource management until import strategy is validated.
## Initialize
From this directory:
```bash
terraform init
```
## Current status
- No live Proxmox resources are defined yet.
- Provider auth variables are placeholders only.
- Import IDs and resource schemas must be verified against provider docs before adding resources.
## Future safe workflow
1. Add one resource block for an existing VM/object.
2. Import it with the provider-specific ID format.
3. Inspect with `terraform state show`.
4. Reconcile `.tf` arguments until `terraform plan` is clean.
5. Repeat incrementally.
## Safety notes
- Do not commit real credentials in `.tf` files or tracked `.tfvars`.
- State files are ignored by the Terraform-level `.gitignore`.
- Do not run `terraform apply` until plan is intentionally no-op for existing resources.
+14
View File
@@ -0,0 +1,14 @@
# Proxmox scaffold only.
#
# IMPORTANT:
# - Resource blocks are intentionally omitted for now.
# - Before adding resources, confirm:
# 1) provider resource schemas,
# 2) exact import ID formats,
# 3) non-destructive reconciliation strategy for existing VMs.
#
# Suggested future workflow mirrors docker/:
# - Define one resource for an existing object.
# - Import it.
# - Use `terraform state show` to reconcile config.
# - Proceed incrementally.
@@ -0,0 +1,9 @@
output "proxmox_scaffold_ready" {
description = "Indicates this directory is a placeholder scaffold for future Proxmox adoption."
value = true
}
output "proxmox_endpoint_configured" {
description = "Whether a non-empty endpoint has been provided."
value = var.proxmox_endpoint != ""
}
@@ -0,0 +1,11 @@
provider "proxmox" {
# Placeholder-only scaffold.
# Confirm exact provider auth mode and endpoint details before real use.
endpoint = var.proxmox_endpoint
insecure = var.proxmox_insecure
username = var.proxmox_username
password = var.proxmox_password
api_token = var.proxmox_api_token
}
@@ -0,0 +1,9 @@
# Example placeholders only. Do not commit real credentials.
proxmox_endpoint = "https://pve.example.local:8006/api2/json"
proxmox_insecure = false
# Use either username/password or API token based on your chosen auth flow.
proxmox_username = "root@pam"
proxmox_password = "REPLACE_ME"
proxmox_api_token = "REPLACE_ME"
@@ -0,0 +1,31 @@
variable "proxmox_endpoint" {
description = "Proxmox API endpoint URL, for example https://pve.example.local:8006/api2/json"
type = string
default = ""
}
variable "proxmox_insecure" {
description = "Set true only for local testing with self-signed TLS; prefer false in stable environments."
type = bool
default = false
}
variable "proxmox_username" {
description = "Username for password-based auth (placeholder; optional if token auth is used)."
type = string
default = ""
}
variable "proxmox_password" {
description = "Password for password-based auth (placeholder; optional if token auth is used)."
type = string
default = ""
sensitive = true
}
variable "proxmox_api_token" {
description = "API token for token-based auth (placeholder; optional if username/password is used)."
type = string
default = ""
sensitive = true
}
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.6.0"
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.68.0"
}
}
}