Skip to content

Quick Start

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

Quick Start

Use this only for a new Ubuntu 24.04 server. Replace example values before running anything.

1. Prepare the controller

git clone git@github.com:0x4e3/server-bootsrtap.git
cd server-bootsrtap
uv sync --group dev
uv run pre-commit install
uv run pre-commit install --hook-type commit-msg

Your controller needs:

  • Python 3.12 or newer
  • uv
  • just, for the project check recipes
  • a running Docker engine, for lightweight tests
  • SSH access to the server as root or a user with passwordless or interactive sudo access
  • a public SSH key, for example ~/.ssh/id_ed25519.pub

2. Configure inventory

Edit inventories/production/hosts.yaml:

---
all:
  children:
    bootstrap:
      hosts:
        server-01:
          ansible_host: 203.0.113.10
          ansible_user: root
    traefik_hosts:
      hosts:
        server-01:
    vaultwarden_hosts:
      hosts: {}
    three_x_ui_hosts:
      hosts: {}
    telemt_hosts:
      hosts: {}

Keep the host in bootstrap until bootstrap is complete. Add it to traefik_hosts only when it should receive Docker and Traefik.

3. Create the encrypted secret file

group_vars/vault.yaml is ignored by Git. Create it with Ansible Vault:

uv run ansible-vault create group_vars/vault.yaml

Add this minimum bootstrap content. Use your real public key and generate a strong password and a random salt.

---
vault_bootstrap_login_user_ssh_public_keys:
  - "ssh-ed25519 AAAA... you@example"
vault_bootstrap_users_default_password: "replace-with-a-long-random-password"
vault_bootstrap_users_password_salt: "replace-with-a-random-salt"
vault_traefik_acme_email: "ops@example.com"
vault_traefik_dashboard_password: "replace-if-dashboard-is-enabled"
vault_vaultwarden_admin_token: "replace-if-vaultwarden-is-enabled"
vault_telemt_config: "replace-if-telemt-is-enabled"

Verify that Git ignores it:

git check-ignore -v group_vars/vault.yaml

4. Open network access before migration

At the cloud provider, router, or security group level, allow:

  • TCP 22 temporarily, for the first setup run
  • TCP 22571, the current default hardened SSH port
  • TCP 80 and 443 for every traefik_hosts server

If the new SSH port is not reachable from the controller, do not start setup. You can lock yourself out.

5. Bootstrap the managed user

uv run ansible-playbook \
  -i inventories/production/hosts.yaml \
  --ask-vault-pass \
  playbooks/bootstrap.yaml

If the initial ansible_user needs a sudo password, add -K to this command and enter that sudo password when prompted. Do not add -K when connecting as root or a user with passwordless sudo.

The default managed user is bootstraper. Bootstrap can upgrade packages and reboot the server. Wait for the play to finish successfully.

Test the new user before moving on:

ssh -i ~/.ssh/id_ed25519 bootstraper@203.0.113.10 'sudo -n true'

6. Run setup from the current SSH port

For a fresh server still listening on 22:

uv run ansible-playbook \
  -i inventories/production/hosts.yaml \
  --ask-vault-pass \
  playbooks/setup.yaml \
  -e 'setup_ssh_port=22'

Add -K here too only when the bootstrap user does not have passwordless sudo.

After it completes, test the hardened SSH port:

ssh -i ~/.ssh/id_ed25519 -p 22571 bootstraper@203.0.113.10 'sudo -n true'

If this command fails, do not run applications. Read Setup and SSH Migration.

7. Verify the baseline

ssh -i ~/.ssh/id_ed25519 -p 22571 bootstraper@203.0.113.10 \
  'sudo systemctl is-active crowdsec crowdsec-firewall-bouncer && sudo iptables -S INPUT'

For a Traefik host, also check:

ssh -i ~/.ssh/id_ed25519 -p 22571 bootstraper@203.0.113.10 \
  'sudo systemctl is-active docker && sudo docker ps'

8. Add applications only when configured

Read Applications, add the host to the appropriate application group, configure its required variables, then run:

uv run ansible-playbook \
  -i inventories/production/hosts.yaml \
  --ask-vault-pass \
  playbooks/apps.yaml

Clone this wiki locally