# Project Structure

> Repository layout and the purpose of each top-level file and directory.

---

LLMS index: [llms.txt](/kubeclaw/llms.txt)

---

```
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 |

<div class="alert alert-primary" role="alert"><div class="h4 alert-heading" role="heading">Module mounts</div>


`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.
</div>
