Project Structure
Repository layout and the purpose of each top-level file and directory.
kubeclaw/
├── main.tf # Infrastructure (providers, network, firewalls, servers)
├── variables.tf # All configurable inputs
├── outputs.tf # IPs, SSH keys, ssh_config_snippet, next-steps banner
├── terraform.tfvars.example # Example configuration
├── hugo.yaml # Hugo + Docsy configuration
├── package.json # Docsy asset dependencies
├── themes/docsy/ # Pinned Docsy theme submodule
├── aibox.toml # Dev Container source of truth (aibox apply)
├── aibox.lock # Pinned aibox toolchain versions
├── CLAUDE.md # Claude Code project instructions
├── README.md # Project overview (concise)
├── LICENSE # MIT License
├── .gitignore
├── .devcontainer/
│ ├── devcontainer.json # Generated by aibox; do not edit directly
│ ├── Dockerfile # Generated by aibox; do not edit directly
│ ├── docker-compose.yml # Generated by aibox; do not edit directly
│ ├── Dockerfile.local # Project layer: installs cloudflared
│ └── docker-compose.override.yml # Project override: writable SSH mount
├── cloud-init/
│ ├── admin-node.yaml.tpl # Admin node (temporary jump host with public IPv6)
│ ├── control-node.yaml.tpl # Control node (cloudflared on master, UFW, fail2ban, k8s prereqs)
│ └── worker-node.yaml.tpl # Worker node (isolated, outbound DNS/HTTP/S only, k8s prereqs)
├── scripts/
│ ├── setup-ssh.sh # Export SSH keys from tofu state, generate ~/.ssh/config
│ ├── ssh-agent-setup.sh # Fix SSH permissions, start ssh-agent, load keys
│ ├── generate-ansible-inventory.sh # Build ansible/inventory.ini from tofu state
│ ├── build-docs.sh # Build Hugo site locally
│ ├── serve-docs.sh # Preview Hugo site locally
│ └── deploy-docs.sh # Build and deploy Hugo to gh-pages
├── ansible/
│ ├── ansible.cfg # Ansible defaults (user, pipelining, SSH args)
│ ├── inventory.ini # Auto-generated inventory (do not hand-edit)
│ └── playbooks/
│ ├── update-system.yml # System updates with optional reboot
│ ├── security-hardening.yml # Unattended upgrades, fail2ban, sysctl hardening
│ ├── configure-nat64.yml # NAT64/DNS64 for IPv4 reachability on running nodes
│ └── prepare-k8s-nodes.yml # Kubernetes prerequisites (container runtime, kubeadm) on running nodes
├── assets/ # Project brand layer for the Hugo site
│ ├── icons/logo.svg # projectious mark used in the navbar
│ └── scss/ # Brand tokens and Docsy surface styles
├── layouts/ # Project template overrides (favicons, head hooks)
├── static/favicons/ # Brand favicon set
├── content/ # Hugo documentation source
│ ├── _index.md # Branded landing page
│ └── docs/ # Documentation section
│ ├── _index.md # Documentation overview
│ ├── quick-start.md # Combined prerequisites + deployment steps
│ ├── introduction/ # Concepts: architecture, security, DNS/NAT64
│ ├── guide/ # Ordered deployment path (dev container -> OpenClaw)
│ ├── how-to/ # Focused procedures, incl. the manual setup alternative
│ ├── reference/ # Variables, outputs, templates, playbooks, structure
│ ├── operations/ # Day-two: scaling, rotation, upgrades, troubleshooting
│ ├── roadmap/ # Planned work
│ └── contributing/ # Development setup and code of conduct
└── public/ # Generated site output (gitignored)
Key Files
Infrastructure (root level)
| File | Purpose |
|---|
main.tf | Core infrastructure: providers, SSH keys, network/subnet, firewalls, servers, cloud-init rendering |
variables.tf | All configurable inputs with types, defaults, and descriptions |
outputs.tf | Exposes IPs, SSH keys (sensitive), ssh_config_snippet, and next-steps banner |
terraform.tfvars.example | Reference configuration (actual .tfvars is gitignored) |
Cloud-Init Templates
| File | Purpose |
|---|
cloud-init/admin-node.yaml.tpl | Minimal jump host: admin user, SSH hardening, fail2ban, public SSH |
cloud-init/control-node.yaml.tpl | Control plane: cloudflared (master only), UFW, fail2ban, optional NAT64 + K8s prereqs |
cloud-init/worker-node.yaml.tpl | Worker: restrictive UFW, no TCP forwarding, optional NAT64 + K8s prereqs |
Scripts
| File | Purpose |
|---|
scripts/setup-ssh.sh | Export SSH keys, generate ~/.ssh/config with backup |
scripts/ssh-agent-setup.sh | Fix SSH permissions, start ssh-agent, load keys |
scripts/generate-ansible-inventory.sh | Build Ansible inventory from OpenTofu state |
scripts/build-docs.sh | Build the Hugo site locally |
scripts/serve-docs.sh | Preview the site locally |
scripts/deploy-docs.sh | Build Hugo and push to gh-pages |
Dev Container
The aibox configuration in aibox.toml is the source of truth for generated
Dev Container files. Run aibox apply after changing it; do not hand-edit
.devcontainer/Dockerfile, docker-compose.yml, or devcontainer.json.
Dockerfile.local and docker-compose.override.yml are project-owned
extensions and are safe to edit.
Ansible
| File | Purpose |
|---|
ansible/ansible.cfg | Defaults: remote user, host key checking, privilege escalation |
ansible/inventory.ini | Auto-generated inventory with control_nodes, worker_nodes, k8s_cluster groups |
Documentation site
| File | Purpose |
|---|
hugo.yaml | Hugo + Docsy configuration, menus, version list, and module mounts |
assets/scss/_variables_project.scss | projectious brand tokens mapped onto Bootstrap/Docsy variables |
assets/scss/_styles_project.scss | Brand surface styles: type scale, code theme, dark mode, chrome |
assets/icons/logo.svg | The projectious mark inlined into the navbar |
layouts/partials/favicons.html | Favicon set override (Docsy’s default references assets this project does not ship) |
layouts/partials/hooks/head-end.html | Brand web-font loading |
static/favicons/ | Brand favicon and touch-icon assets |
Module mounts
`hugo.yaml` declares `module.mounts` for the vendored Bootstrap and Font Awesome
assets. Declaring any mount for a component replaces Hugo's default mount for
that component, so the config also restores `assets` and `static` explicitly.
Removing those two entries silently disables every project-level brand asset.