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

@@ -1,4 +1,8 @@
---
# Stage 1: Harden the server before anything else is installed.
- import_playbook: harden.yml
# Stage 2: Install base packages and k3s.
- name: Railiance host bootstrap
hosts: all
become: true

124
ansible/harden.yml Normal file
View File

@@ -0,0 +1,124 @@
---
- name: Server hardening
hosts: all
become: true
vars:
ssh_port: 22
k3s_api_port: 6443
flannel_vxlan_port: 8472
tasks:
# ── SSH hardening ────────────────────────────────────────────────────────
- name: Disable root SSH login
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin no'
state: present
notify: Restart sshd
- name: Disable password authentication
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication no'
state: present
notify: Restart sshd
- name: Disable challenge-response authentication
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?ChallengeResponseAuthentication'
line: 'ChallengeResponseAuthentication no'
state: present
notify: Restart sshd
# ── UFW firewall ─────────────────────────────────────────────────────────
- name: Install ufw
apt:
name: ufw
state: present
update_cache: yes
- name: Set UFW default inbound policy to deny
ufw:
default: deny
direction: incoming
- name: Set UFW default outbound policy to allow
ufw:
default: allow
direction: outgoing
- name: Allow SSH
ufw:
rule: allow
port: "{{ ssh_port }}"
proto: tcp
- name: Allow k3s API server
ufw:
rule: allow
port: "{{ k3s_api_port }}"
proto: tcp
- name: Allow Flannel VXLAN (inter-node)
ufw:
rule: allow
port: "{{ flannel_vxlan_port }}"
proto: udp
- name: Enable UFW
ufw:
state: enabled
# ── fail2ban ─────────────────────────────────────────────────────────────
- name: Install fail2ban
apt:
name: fail2ban
state: present
- name: Configure fail2ban SSH jail
copy:
dest: /etc/fail2ban/jail.d/sshd.conf
content: |
[sshd]
enabled = true
port = {{ ssh_port }}
maxretry = 5
bantime = 3600
findtime = 600
mode: '0644'
notify: Restart fail2ban
- name: Enable and start fail2ban
systemd:
name: fail2ban
enabled: true
state: started
# ── Shell hygiene ─────────────────────────────────────────────────────────
- name: Set HISTCONTROL to suppress space-prefixed commands from history
copy:
dest: /etc/profile.d/histcontrol.sh
content: |
# Commands prefixed with a space are not recorded in shell history.
# Use this when typing secrets interactively.
export HISTCONTROL=ignorespace
mode: '0644'
handlers:
- name: Restart sshd
systemd:
name: sshd
state: restarted
- name: Restart fail2ban
systemd:
name: fail2ban
state: restarted

View File

@@ -4,6 +4,10 @@
[seed]
# 203.0.113.10 ansible_user=ubuntu ansible_become=true
# HostEurope server (second Kubernetes host)
[hosteurope]
# <IP> ansible_user=ubuntu ansible_become=true
# Optional: control plane / workers (future multi-node)
#[k3s_master]
# 203.0.113.11 ansible_user=ubuntu ansible_become=true