From 6146fac8c3add4cc7d1e52d4816384ad99a4af83 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 19 Feb 2026 17:01:22 +0000 Subject: [PATCH] Add "Infrastructure" --- Infrastructure.md | 268 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 Infrastructure.md diff --git a/Infrastructure.md b/Infrastructure.md new file mode 100644 index 0000000..4807154 --- /dev/null +++ b/Infrastructure.md @@ -0,0 +1,268 @@ +# Infrastructure + +> Container management (LinuxKit/QEMU/Hyperkit), Hetzner cloud provisioning, and CloudNS DNS management. + +## Container Management + +The `container` package manages LinuxKit-based virtual machines using QEMU on Linux and Hyperkit on macOS. + +### Container + +A `Container` represents a running VM instance. + +```go +type Container struct { + ID string // Unique container ID + Name string // Human-readable name + Image string // LinuxKit image used + Status string // running, stopped, error + PID int // Process ID of the VM + Ports map[string]string // Port mappings (host:container) + Memory string // Allocated memory (e.g. "4G") + CPUs int // Allocated CPU cores +} +``` + +### RunOptions + +Configuration for starting a new VM. + +```go +type RunOptions struct { + Name string // Container name + Detach bool // Run in background + Memory string // Memory allocation (e.g. "2G", "4G") + CPUs int // CPU core count + Ports map[string]string // Port forwarding (host:container) + Volumes []string // Volume mounts (host:container) + SSHPort int // SSH port for access (default: auto-assigned) + SSHKey string // Path to SSH key for authentication +} +``` + +### Manager Interface + +The `Manager` interface provides a unified API for VM lifecycle operations, regardless of the underlying hypervisor. + +```go +type Manager interface { + Run(ctx context.Context, opts RunOptions) (*Container, error) + Stop(ctx context.Context, id string) error + Logs(ctx context.Context, id string) (string, error) + Exec(ctx context.Context, id string, cmd []string) (string, error) + Inspect(ctx context.Context, id string) (*Container, error) +} +``` + +### Creating a Manager + +The `NewLinuxKitManager` factory selects the appropriate hypervisor backend based on the host platform. + +```go +import "forge.lthn.ai/core/go-devops/container" + +// QEMU backend (Linux, or explicit selection) +mgr := container.NewLinuxKitManager("qemu") + +// Hyperkit backend (macOS) +mgr := container.NewLinuxKitManager("hyperkit") +``` + +### Running a VM + +```go +ctr, err := mgr.Run(ctx, container.RunOptions{ + Name: "dev-environment", + Memory: "4G", + CPUs: 4, + Ports: map[string]string{ + "8080": "80", // Host 8080 -> Container 80 + "8443": "443", // Host 8443 -> Container 443 + }, + Volumes: []string{ + "/home/dev/project:/workspace", + }, + SSHPort: 2222, + SSHKey: "~/.ssh/id_ed25519", +}) + +fmt.Printf("Container %s running (PID: %d)\n", ctr.Name, ctr.PID) +``` + +### Executing Commands + +```go +output, err := mgr.Exec(ctx, ctr.ID, []string{"uname", "-a"}) +fmt.Println(output) // Linux dev-environment 5.15.0 ... +``` + +### Viewing Logs + +```go +logs, err := mgr.Logs(ctx, ctr.ID) +fmt.Println(logs) +``` + +## DevOps Environment + +The `devops` package provides higher-level environment management on top of the container layer. + +### DevOps and Config + +```go +type DevOps struct { + Config Config + Images *ImageManager +} + +type Config struct { + DataDir string // Persistent data directory + CacheDir string // Image and artefact cache + StateFile string // Environment state file +} +``` + +### ImageManager + +The `ImageManager` handles pulling, caching, and verifying LinuxKit images. + +```go +type ImageManager struct { + // Internal: cache dir, registry config +} + +// Pull an image (uses cache if available) +img, err := images.Pull(ctx, "linuxkit/kernel:5.15") + +// Verify image integrity +ok, err := images.Verify(img, expectedChecksum) + +// List cached images +cached, err := images.List() +``` + +## Hetzner Cloud Provisioning + +The `infra` package includes a provisioner for Hetzner Cloud servers. + +```go +type HetznerProvisioner struct { + // Internal: API client, SSH keys, default config +} +``` + +### Provisioning a Server + +```go +import "forge.lthn.ai/core/go-devops/infra" + +provisioner := infra.NewHetznerProvisioner(apiToken) + +server, err := provisioner.Create(ctx, infra.ServerConfig{ + Name: "worker-eu-01", + Type: "cx31", // 2 vCPU, 8GB RAM, 80GB + Location: "fsn1", // Falkenstein, Germany + Image: "ubuntu-24.04", + SSHKeys: []string{"deploy-key"}, + Labels: map[string]string{ + "role": "worker", + "cluster": "production", + }, +}) + +fmt.Printf("Server %s created at %s\n", server.Name, server.PublicIP) +``` + +### Server Lifecycle + +```go +// List all servers +servers, err := provisioner.List(ctx) + +// Get server details +server, err := provisioner.Get(ctx, serverID) + +// Delete a server +err := provisioner.Delete(ctx, serverID) +``` + +## CloudNS DNS Management + +The `infra` package also provides DNS record management via CloudNS. + +```go +type CloudNSManager struct { + // Internal: API credentials, zone cache +} +``` + +### Managing DNS Records + +```go +dns := infra.NewCloudNSManager(authID, password) + +// Create an A record +err := dns.CreateRecord(ctx, infra.DNSRecord{ + Zone: "lthn.ai", + Name: "worker-01", + Type: "A", + TTL: 300, + Value: server.PublicIP, +}) + +// Create a CNAME record +err := dns.CreateRecord(ctx, infra.DNSRecord{ + Zone: "lthn.ai", + Name: "api", + Type: "CNAME", + TTL: 3600, + Value: "worker-01.lthn.ai", +}) + +// List records for a zone +records, err := dns.ListRecords(ctx, "lthn.ai") + +// Delete a record +err := dns.DeleteRecord(ctx, "lthn.ai", recordID) +``` + +## Example: Full Provisioning Workflow + +```go +import ( + "forge.lthn.ai/core/go-devops/infra" + "forge.lthn.ai/core/go-devops/ansible" +) + +// 1. Provision a Hetzner server +provisioner := infra.NewHetznerProvisioner(hetznerToken) +server, err := provisioner.Create(ctx, infra.ServerConfig{ + Name: "web-prod-01", + Type: "cx31", + Location: "fsn1", + Image: "ubuntu-24.04", + SSHKeys: []string{"deploy-key"}, +}) + +// 2. Create DNS record +dns := infra.NewCloudNSManager(authID, password) +dns.CreateRecord(ctx, infra.DNSRecord{ + Zone: "lthn.ai", + Name: "web-prod-01", + Type: "A", + TTL: 300, + Value: server.PublicIP, +}) + +// 3. Configure with Ansible +executor := ansible.NewExecutor("./playbooks") +executor.SetInventory("./inventory/dynamic.yml") +executor.SetVar("target_host", server.PublicIP) +result, err := executor.Run(ctx, "configure.yml") +``` + +## See Also + +- [[Home]] — Package overview +- [[Build-System]] — Building artefacts for deployment +- [[Ansible-Executor]] — Configuring provisioned infrastructure