feat(bootstrap): add HostEurope hardening playbook and workplan
Some checks failed
railiance-tests / smoke (push) Has been cancelled

- workplans/RAIL-BS-WP-0002-hosteurope-bootstrap.md: new workplan for
  Secure Single-Server Bootstrap at HostEurope (repo goal d7092599).
  T01-T03 done; T04+T05 require ansible on a box with network access to
  92.205.62.239 (hosts.ini is gitignored — recreate on new box).

- ansible/harden.yml: new playbook — disables root/password SSH auth,
  enables UFW (allow 22/tcp 6443/tcp 8472/udp, deny-all default),
  installs fail2ban with SSH jail, sets HISTCONTROL=ignorespace.

- ansible/bootstrap.yml: import_playbook harden.yml runs before k3s.

- ansible/hosts.ini.example: add [hosteurope] group template.

- QUICKSTART.md: document two-stage bootstrap (harden → k3s).

- CLAUDE.md: add goal_guidance handling to session protocol
  (needs_workplan + alignment_warnings).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 22:50:51 +01:00
parent d83bc1049f
commit 19661ca0c6
6 changed files with 326 additions and 3 deletions

View File

@@ -0,0 +1,178 @@
---
id: RAIL-BS-WP-0002
type: workplan
title: "Secure Single-Server Bootstrap at HostEurope"
domain: railiance
repo: railiance-bootstrap
status: active
owner: railiance
topic_slug: railiance
repo_goal_id: d7092599-927b-4796-b52e-8be833301478
state_hub_workstream_id: "bf40b47e-be5b-4930-a7d2-362e76b943bb"
created: "2026-03-08"
updated: "2026-03-08"
handoff_note: "T01-T03 done locally (WSL, no ansible). T04+T05 require ansible on a Linux box with network access to 92.205.62.239. hosts.ini created with the IP (gitignored — recreate on new box). Run: ansible -i ansible/hosts.ini hosteurope -m ping, then ansible-playbook -i ansible/hosts.ini -l hosteurope ansible/bootstrap.yml"
---
# Secure Single-Server Bootstrap at HostEurope
## Goal
Bootstrap a new HostEurope server securely so that it can function as the
second Kubernetes host in the ThreePhoenix cluster. The bare Ubuntu server is
provisioned manually by Bernd. This workplan covers everything from first SSH
contact through a verified, hardened k3s node — all services secured from the
start, no shortcuts.
Scope is deliberately narrow: one server, secure from day one. Automated
provisioning of additional server resources (railiance-hosts) and the
full three-node setup are deferred.
## Boundary conditions
- Ubuntu 24.04 LTS server at HostEurope, manually provisioned
- SSH access established using existing private credentials
- All remote access must be key-based only (no password auth)
- Firewall active before k3s is installed
- No credentials committed to the repo
---
## Tasks
### T01 — Add HostEurope host to inventory
```task
id: RAIL-BS-WP-0002-T01
status: done
completed: "2026-03-08"
priority: high
state_hub_task_id: "d41e1f8e-1dc2-41e9-bf83-521c99908e18"
```
Add the HostEurope host to `ansible/hosts.ini` (create from `hosts.ini.example`
if not present). Place it in a `[hosteurope]` group so it can be targeted
independently from other nodes.
Verify Ansible can reach the host:
```bash
ansible -i ansible/hosts.ini hosteurope -m ping
```
**Done when:** ping succeeds from local control node.
---
### T02 — Create server hardening playbook
```task
id: RAIL-BS-WP-0002-T02
status: done
completed: "2026-03-08"
priority: high
state_hub_task_id: "e8abc64b-d74c-4718-9859-96d53551c654"
```
Create `ansible/harden.yml` (or a `roles/harden/` role called from
`bootstrap.yml`) covering:
- Disable root SSH login (`PermitRootLogin no`)
- Disable password authentication (`PasswordAuthentication no`)
- Enable and configure UFW: deny all inbound by default, allow SSH (22),
k3s API (6443), and Flannel VXLAN (8472/UDP) — add others as needed
- Install and enable `fail2ban` with SSH jail
- Set `HISTCONTROL=ignorespace` in `/etc/profile.d/` to allow secret-safe
shell usage
**Done when:** `ansible-lint ansible/harden.yml` passes and a dry-run
(`--check`) against the HostEurope host produces no errors.
---
### T03 — Integrate hardening into bootstrap sequence
```task
id: RAIL-BS-WP-0002-T03
status: done
completed: "2026-03-08"
priority: high
state_hub_task_id: "bf991fa3-a870-4c80-8d9e-91f96b97eb7c"
```
Ensure `ansible/bootstrap.yml` runs hardening **before** k3s installation.
Either import `harden.yml` as a play or invoke the role inline.
Order must be:
1. Harden (T02)
2. Install base packages
3. Install k3s
Update `QUICKSTART.md` step 6 to note that hardening runs automatically as
part of bootstrap.
**Done when:** `bootstrap.yml` task list reflects the correct order and the
QUICKSTART reflects it.
---
### T04 — Run bootstrap on the HostEurope host
```task
id: RAIL-BS-WP-0002-T04
status: todo
priority: high
state_hub_task_id: "f62896f2-6fed-4512-a41b-3f5b9a1ca311"
```
Execute the full bootstrap playbook against the HostEurope host:
```bash
ansible-playbook -i ansible/hosts.ini -l hosteurope ansible/bootstrap.yml
```
**Done when:**
- Playbook completes with no failed tasks
- `k3s kubectl get nodes` shows the host in `Ready` state
- UFW is active and SSH still works after the run
---
### T05 — Smoke test and record
```task
id: RAIL-BS-WP-0002-T05
status: todo
priority: medium
state_hub_task_id: "9e92effe-3531-4675-8bc8-7b2bc2c04877"
```
Run the existing smoke test:
```bash
tests/smoke_kube.sh
```
If the smoke test is not yet parameterized for a remote host, extend it or
run the equivalent `kubectl get nodes` via `ansible -m shell`.
Add a brief note to `docs/` (or a new `docs/hosteurope-bootstrap.md`) recording:
- Server specs (vCPU, RAM, disk)
- IP / hostname (public, non-sensitive — no credentials)
- Date bootstrapped
- k3s version installed
Call `add_progress_event()` in the State Hub to close out the workstream.
**Done when:** smoke test passes and the progress event is logged.
---
## References
- Repo goal: `d7092599-927b-4796-b52e-8be833301478`
- ThreePhoenix workstream: `9e208376-23f1-40c7-9813-fac1f7d6ad3b`
- Safety Net workstream: `7e8b0c20-51eb-40c9-9e3b-85dd380d7625` (safety net
passed green 2026-02-27 — safe to proceed with cluster work)
- Existing playbook: `ansible/bootstrap.yml`
- Inventory template: `ansible/hosts.ini.example`