Compare commits
2 commits
db70b4ba06
...
796428cbda
| Author | SHA1 | Date | |
|---|---|---|---|
| 796428cbda | |||
| 16da843131 |
8 changed files with 31 additions and 37 deletions
|
|
@ -51,9 +51,10 @@ Note: Inventory and vault password are set via `ANSIBLE_INVENTORY` and `ANSIBLE_
|
||||||
**What `deploy.yml` runs internally:**
|
**What `deploy.yml` runs internally:**
|
||||||
1. `provision.yml` - create server, auto-writes IP to hosts.yml and config.yml
|
1. `provision.yml` - create server, auto-writes IP to hosts.yml and config.yml
|
||||||
2. `dns.yml` - create DNS records
|
2. `dns.yml` - create DNS records
|
||||||
3. `storage_box.yml` - generate SSH key, configure storage box, writes storagebox.yml to stack config
|
3. `bootstrap.yml` - users, SSH hardening, packages, Docker (connects as root)
|
||||||
4. `bootstrap.yml` - users, SSH hardening, packages, Docker (connects as root)
|
4. `site.yml` - deploy all services
|
||||||
5. `site.yml` - deploy all services
|
|
||||||
|
**Note:** `storage_box.yml` must be run before `deploy.yml` when `enable_restic: true` — Ansible loads group_vars at startup, so `storagebox.yml` must exist before the playbook begins.
|
||||||
|
|
||||||
**Playbook Execution Order** (via `site.yml`):
|
**Playbook Execution Order** (via `site.yml`):
|
||||||
1. networks.yml - Pre-create all Docker networks (must run before any service)
|
1. networks.yml - Pre-create all Docker networks (must run before any service)
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,8 @@ ansible-galaxy collection install -r requirements.yml
|
||||||
full deployment order for a fresh server:
|
full deployment order for a fresh server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ansible-playbook playbooks/deploy.yml # provision → dns → storage_box → bootstrap → site (all-in-one)
|
ansible-playbook playbooks/storage_box.yml # if using restic: create storage box and install SSH key (run before deploy.yml)
|
||||||
|
ansible-playbook playbooks/deploy.yml # provision → dns → bootstrap → site (all-in-one)
|
||||||
ansible-playbook playbooks/dkim_sync.yml # generate DKIM keys and publish to DNS (run once after mail is up)
|
ansible-playbook playbooks/dkim_sync.yml # generate DKIM keys and publish to DNS (run once after mail is up)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -78,7 +79,7 @@ or step by step:
|
||||||
```bash
|
```bash
|
||||||
ansible-playbook playbooks/provision.yml # create server, writes IP to stack config
|
ansible-playbook playbooks/provision.yml # create server, writes IP to stack config
|
||||||
ansible-playbook playbooks/dns.yml # create DNS zones and records
|
ansible-playbook playbooks/dns.yml # create DNS zones and records
|
||||||
ansible-playbook playbooks/storage_box.yml # create storage box and install SSH key (if using restic)
|
ansible-playbook playbooks/storage_box.yml # if using restic: create storage box and install SSH key
|
||||||
ansible-playbook playbooks/site.yml --tags bootstrap # users, SSH hardening, packages, Docker
|
ansible-playbook playbooks/site.yml --tags bootstrap # users, SSH hardening, packages, Docker
|
||||||
ansible-playbook playbooks/site.yml # deploy all services
|
ansible-playbook playbooks/site.yml # deploy all services
|
||||||
ansible-playbook playbooks/dkim_sync.yml # generate DKIM keys and publish to DNS
|
ansible-playbook playbooks/dkim_sync.yml # generate DKIM keys and publish to DNS
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@
|
||||||
# Full first-time deployment — provisions and deploys everything in one shot.
|
# Full first-time deployment — provisions and deploys everything in one shot.
|
||||||
# Usage: ansible-playbook playbooks/deploy.yml
|
# Usage: ansible-playbook playbooks/deploy.yml
|
||||||
#
|
#
|
||||||
# Prerequisites: run setup.sh first, then review config.yml, vault.yml, dns.yml
|
# Prerequisites:
|
||||||
|
# 1. run setup.sh and review config.yml, vault.yml, dns.yml
|
||||||
|
# 2. if enable_restic: run storage_box.yml first so storagebox.yml exists
|
||||||
|
# before this playbook starts (Ansible loads group_vars at startup)
|
||||||
#
|
#
|
||||||
# This playbook is intended for initial deployments only. After the first run,
|
# This playbook is intended for initial deployments only. After the first run,
|
||||||
# bootstrap will fail (root SSH is disabled) — use site.yml for subsequent deploys.
|
# bootstrap will fail (root SSH is disabled) — use site.yml for subsequent deploys.
|
||||||
|
|
@ -13,7 +16,6 @@
|
||||||
|
|
||||||
- import_playbook: provision.yml
|
- import_playbook: provision.yml
|
||||||
- import_playbook: dns.yml
|
- import_playbook: dns.yml
|
||||||
- import_playbook: storage_box.yml
|
|
||||||
|
|
||||||
# Refresh inventory so the newly provisioned server IP is visible to subsequent plays
|
# Refresh inventory so the newly provisioned server IP is visible to subsequent plays
|
||||||
- name: Refresh inventory
|
- name: Refresh inventory
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,5 @@
|
||||||
mode: "0700"
|
mode: "0700"
|
||||||
when: restic_repo is defined and restic_repo.startswith('/') # only local path
|
when: restic_repo is defined and restic_repo.startswith('/') # only local path
|
||||||
|
|
||||||
- name: Ensure restic repo is initialized
|
- ansible.builtin.include_tasks: init.yml
|
||||||
ansible.builtin.shell: |
|
|
||||||
set -euo pipefail
|
|
||||||
source /etc/restic/restic.env
|
|
||||||
restic snapshots > /dev/null 2>&1 || restic init
|
|
||||||
touch /etc/restic/.initialized
|
|
||||||
args:
|
|
||||||
creates: /etc/restic/.initialized
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,5 @@
|
||||||
dest: /root/.ssh/config
|
dest: /root/.ssh/config
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
- name: Initialize restic repo on Storage Box (if needed)
|
- ansible.builtin.include_tasks: init.yml
|
||||||
ansible.builtin.shell: |
|
|
||||||
source /etc/restic/restic.env
|
|
||||||
restic snapshots > /dev/null 2>&1 || restic init
|
|
||||||
touch /etc/restic/.initialized
|
|
||||||
args:
|
|
||||||
creates: /etc/restic/.initialized
|
|
||||||
|
|
||||||
|
|
|
||||||
9
roles/restic/tasks/init.yml
Normal file
9
roles/restic/tasks/init.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
- name: Initialize restic repo (if needed)
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -euo pipefail
|
||||||
|
source /etc/restic/restic.env
|
||||||
|
restic snapshots > /dev/null 2>&1 || restic init
|
||||||
|
touch /etc/restic/.initialized
|
||||||
|
args:
|
||||||
|
creates: /etc/restic/.initialized
|
||||||
|
|
@ -34,30 +34,22 @@
|
||||||
api_token: "{{ hcloud_token }}"
|
api_token: "{{ hcloud_token }}"
|
||||||
access_settings:
|
access_settings:
|
||||||
ssh_enabled: true
|
ssh_enabled: true
|
||||||
|
reachable_externally: true
|
||||||
state: present
|
state: present
|
||||||
register: storagebox_result
|
register: storagebox_result
|
||||||
when: ssh_pub_key_stat.stat.exists
|
when: ssh_pub_key_stat.stat.exists
|
||||||
|
|
||||||
- name: Check SSH key auth on Storage Box
|
|
||||||
ansible.builtin.shell: |
|
|
||||||
echo "bye" | sftp -i {{ restic_local_key_path }} \
|
|
||||||
-o BatchMode=yes -o StrictHostKeyChecking=no \
|
|
||||||
-P 23 \
|
|
||||||
{{ storagebox_result.hcloud_storage_box.username }}@{{ storagebox_result.hcloud_storage_box.server }}
|
|
||||||
register: ssh_key_check
|
|
||||||
failed_when: false
|
|
||||||
changed_when: false
|
|
||||||
when: ssh_pub_key_stat.stat.exists
|
|
||||||
|
|
||||||
- name: Install SSH public key on Storage Box
|
- name: Install SSH public key on Storage Box
|
||||||
ansible.builtin.shell: |
|
ansible.builtin.shell: |
|
||||||
cat {{ restic_local_key_path }}.pub | \
|
cat {{ restic_local_key_path }}.pub | \
|
||||||
sshpass -p "{{ restic_storagebox_password }}" \
|
sshpass -e \
|
||||||
ssh -o StrictHostKeyChecking=no -p 23 \
|
ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -p 23 \
|
||||||
{{ storagebox_result.hcloud_storage_box.username }}@{{ storagebox_result.hcloud_storage_box.server }} \
|
{{ storagebox_result.hcloud_storage_box.username }}@{{ storagebox_result.hcloud_storage_box.server }} \
|
||||||
install-ssh-key
|
install-ssh-key
|
||||||
|
environment:
|
||||||
|
SSHPASS: "{{ restic_storagebox_password }}"
|
||||||
no_log: true
|
no_log: true
|
||||||
when: ssh_pub_key_stat.stat.exists and ssh_key_check.rc != 0
|
when: ssh_pub_key_stat.stat.exists
|
||||||
|
|
||||||
- name: Write storagebox.yml to stack config directory
|
- name: Write storagebox.yml to stack config directory
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
|
|
|
||||||
4
setup.sh
4
setup.sh
|
|
@ -247,7 +247,9 @@ echo "Next steps:"
|
||||||
echo " 1. Review $CONFIG"
|
echo " 1. Review $CONFIG"
|
||||||
echo " 2. Review $VAULT (ansible-vault edit)"
|
echo " 2. Review $VAULT (ansible-vault edit)"
|
||||||
echo " 3. Review $DNS_CONFIG"
|
echo " 3. Review $DNS_CONFIG"
|
||||||
echo " 4. Deploy: ansible-playbook playbooks/deploy.yml"
|
echo " 4. If restic is enabled, set up the storage box first:"
|
||||||
|
echo " ansible-playbook playbooks/storage_box.yml"
|
||||||
|
echo " 5. Deploy: ansible-playbook playbooks/deploy.yml"
|
||||||
echo ""
|
echo ""
|
||||||
echo " If mail is enabled, sync DKIM keys once the server is up:"
|
echo " If mail is enabled, sync DKIM keys once the server is up:"
|
||||||
echo " ansible-playbook playbooks/dkim_sync.yml"
|
echo " ansible-playbook playbooks/dkim_sync.yml"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue