Skip to content
Alexander Lebedev edited this page Sep 6, 2026 · 1 revision

Server Bootstrap Wiki

This project bootstraps an Ubuntu server, then configures the repeatable server baseline and optional applications. It is designed for a fresh server and a controller machine that can reach it with SSH.

Read this first

  • Production provisioning is documented for Ubuntu 24.04.
  • The CI lightweight tests run against Ubuntu 22.04, 24.04, and 26.04.
  • Do not put passwords, private keys, API tokens, or real domains in Git.
  • Do not run setup until the bootstrap login user's public key is installed and tested.
  • Do not change the SSH port until the cloud firewall/security group allows the new port.
  • Do not publish application ports directly. Applications are reached through Traefik on TCP 80 and 443.

Deployment order

Run these stages in order. Stop and fix the current stage before continuing.

  1. Controller and Secrets
  2. Inventory and Variables
  3. Bootstrap
  4. Setup and SSH Migration
  5. Docker and Traefik, if this is a traefik_hosts host
  6. Applications, if the host runs Vaultwarden, 3x-ui, or Telemt
  7. Operations and Troubleshooting

What each playbook does

Playbook Target group What it does
playbooks/bootstrap.yaml bootstrap Creates the managed login user, installs its SSH key, optionally upgrades packages, and reboots.
playbooks/setup.yaml all, then traefik_hosts Hardens SSH, applies IPv4 firewall rules, installs tools, Docker, Traefik, and CrowdSec.
playbooks/apps.yaml Application groups Deploys Vaultwarden, 3x-ui, and Telemt.

Host model

Every host gets SSH hardening, the IPv4 firewall, system tools, CrowdSec, and the CrowdSec firewall bouncer.

traefik_hosts also gets Docker and Traefik. A host in any application group must also be in traefik_hosts; the application roles enforce that requirement.

Fast command reference

# One-time user creation from the initial SSH identity.
uv run ansible-playbook playbooks/bootstrap.yaml

# First setup while the server still listens on port 22.
uv run ansible-playbook playbooks/setup.yaml -e 'setup_ssh_port=22'

# Later repeatable setup runs use the hardened SSH port by default.
uv run ansible-playbook playbooks/setup.yaml

# Deploy every configured application group.
uv run ansible-playbook playbooks/apps.yaml

Wiki map

Clone this wiki locally