Refactor Docker Compose configurations and add deployment workflows for cloud-pc and mini-pc services
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
[defaults]
|
||||
inventory = inventory/hosts.yml
|
||||
|
||||
[ssh_connection]
|
||||
pipelining = true
|
||||
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
|
||||
@@ -0,0 +1,31 @@
|
||||
all:
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
ansible_user: ada
|
||||
|
||||
children:
|
||||
servers:
|
||||
hosts:
|
||||
ru-vps:
|
||||
ansible_host: vps
|
||||
|
||||
cloud-pc:
|
||||
ansible_host: 10.122.62.51
|
||||
# ansible_host: 192.168.1.5
|
||||
ansible_ssh_common_args: '-J mini-pc'
|
||||
expected_lan_ip: 192.168.1.5
|
||||
storage_mounts:
|
||||
- src: UUID=ae278333-4116-4225-9b95-595496fadd26
|
||||
path: /opt/data
|
||||
fstype: ext4
|
||||
- src: UUID=940a9a4e-10cf-4380-9d22-a71549066561
|
||||
path: /mnt/backup
|
||||
fstype: ext4
|
||||
- src: UUID=89024d30-1ab6-4b2e-b23b-62837455b24a
|
||||
path: /opt/samba
|
||||
fstype: ext4
|
||||
|
||||
mini-pc:
|
||||
ansible_host: 10.122.62.95
|
||||
ansible_ssh_common_args: '-J vps'
|
||||
expected_lan_ip: 192.168.1.10
|
||||
@@ -0,0 +1,15 @@
|
||||
- name: Base server setup
|
||||
hosts: servers
|
||||
gather_facts: true
|
||||
become: false
|
||||
tasks:
|
||||
- name: Ping hosts
|
||||
ansible.builtin.ping:
|
||||
|
||||
- name: Check expected LAN IP
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- expected_lan_ip in ansible_all_ipv4_addresses
|
||||
fail_msg: "{{ inventory_hostname }} must have {{ expected_lan_ip }}; found: {{ ansible_all_ipv4_addresses | join(', ') }}"
|
||||
success_msg: "{{ inventory_hostname }} has {{ expected_lan_ip }}"
|
||||
when: expected_lan_ip is defined
|
||||
@@ -0,0 +1,10 @@
|
||||
# Запускать один раз на новом сервере от имени root или пользователя с полным sudo:
|
||||
# ansible-playbook -i inventory/hosts.yml playbooks/bootstrap.yml -K
|
||||
#
|
||||
# После выполнения: Ansible-плейбуки всё равно требуют -K (become),
|
||||
# но деплой через GitOps (docker compose) работает без пароля.
|
||||
- name: Bootstrap servers
|
||||
hosts: servers
|
||||
become: true
|
||||
roles:
|
||||
- bootstrap
|
||||
@@ -0,0 +1,117 @@
|
||||
- name: Directory structure — cloud-pc
|
||||
hosts: cloud-pc
|
||||
become: true
|
||||
vars:
|
||||
data_user: ada
|
||||
data_group: ada
|
||||
tasks:
|
||||
- name: Create base mount points
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: directory
|
||||
owner: "{{ data_user }}"
|
||||
group: "{{ data_group }}"
|
||||
mode: "0755"
|
||||
loop: "{{ storage_mounts | default([]) }}"
|
||||
|
||||
- name: Mount base storage disks
|
||||
ansible.posix.mount:
|
||||
path: "{{ item.path }}"
|
||||
src: "{{ item.src }}"
|
||||
fstype: "{{ item.fstype }}"
|
||||
opts: "{{ item.opts | default('defaults,nofail') }}"
|
||||
state: mounted
|
||||
loop: "{{ storage_mounts | default([]) }}"
|
||||
|
||||
- name: Create service data and config directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ data_user }}"
|
||||
group: "{{ data_group }}"
|
||||
mode: "0755"
|
||||
loop:
|
||||
- /opt/data/postgres
|
||||
- /opt/data/nextcloud
|
||||
- /opt/data/gitea
|
||||
- /opt/data/gitea-runner
|
||||
- /opt/data/syncthing
|
||||
- /opt/data/zerotier
|
||||
- /opt/samba/media
|
||||
- /opt/samba/documents
|
||||
- /opt/samba/backups_win
|
||||
- /opt/configs
|
||||
- /opt/configs/nextcloud/app
|
||||
- /opt/configs/syncthing
|
||||
|
||||
- name: Create /opt/services
|
||||
ansible.builtin.file:
|
||||
path: /opt/services
|
||||
state: directory
|
||||
owner: "{{ data_user }}"
|
||||
group: "{{ data_group }}"
|
||||
mode: "0755"
|
||||
|
||||
- name: Create backup directories (3TB)
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ data_user }}"
|
||||
group: "{{ data_group }}"
|
||||
mode: "0755"
|
||||
loop:
|
||||
- /mnt/backup/restic/services
|
||||
- /mnt/backup/restic/samba
|
||||
- /mnt/backup/devices/proxmox
|
||||
- /mnt/backup/devices/ada-x1
|
||||
|
||||
- name: Directory structure — mini-pc
|
||||
hosts: mini-pc
|
||||
become: true
|
||||
vars:
|
||||
data_user: ada
|
||||
data_group: ada
|
||||
tasks:
|
||||
- name: Create service directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ data_user }}"
|
||||
group: "{{ data_group }}"
|
||||
mode: "0755"
|
||||
loop:
|
||||
- /opt/services
|
||||
- /opt/data
|
||||
- /opt/configs
|
||||
- /opt/data/vaultwarden
|
||||
- /opt/data/adguard/work
|
||||
- /opt/data/caddy
|
||||
- /opt/data/gitea-runner
|
||||
- /opt/data/npm
|
||||
- /opt/data/zerotier
|
||||
- /opt/configs/adguard
|
||||
- /opt/configs/caddy
|
||||
- /opt/configs/npm/letsencrypt
|
||||
|
||||
- name: Directory structure — ru-vps
|
||||
hosts: ru-vps
|
||||
become: true
|
||||
vars:
|
||||
data_user: ada
|
||||
data_group: ada
|
||||
tasks:
|
||||
- name: Create service directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ data_user }}"
|
||||
group: "{{ data_group }}"
|
||||
mode: "0755"
|
||||
loop:
|
||||
- /opt/services
|
||||
- /opt/data
|
||||
- /opt/configs
|
||||
- /opt/data/caddy
|
||||
- /opt/data/gitea-runner
|
||||
- /opt/data/zerotier
|
||||
- /opt/configs/caddy
|
||||
@@ -0,0 +1,2 @@
|
||||
bootstrap_user: ada
|
||||
bootstrap_ssh_public_keys: [ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIWNsUQmppB6cQccXX1ZaBbFIcmM6RmghsTVbG9TgoZB ada@ada-x1]
|
||||
@@ -0,0 +1,4 @@
|
||||
- name: restart sshd
|
||||
ansible.builtin.service:
|
||||
name: sshd
|
||||
state: restarted
|
||||
@@ -0,0 +1,60 @@
|
||||
- name: Ensure user exists
|
||||
ansible.builtin.user:
|
||||
name: "{{ bootstrap_user }}"
|
||||
shell: /bin/bash
|
||||
groups: sudo
|
||||
append: true
|
||||
create_home: true
|
||||
state: present
|
||||
|
||||
# docker group создаётся только после установки Docker.
|
||||
# Добавление происходит в роли docker, не здесь.
|
||||
|
||||
- name: Add SSH authorized keys
|
||||
ansible.posix.authorized_key:
|
||||
user: "{{ bootstrap_user }}"
|
||||
key: "{{ item }}"
|
||||
state: present
|
||||
loop: "{{ bootstrap_ssh_public_keys }}"
|
||||
when: bootstrap_ssh_public_keys | length > 0
|
||||
|
||||
# Команды, которые реально нужны без пароля:
|
||||
# apt / apt-get — обновление пакетов
|
||||
# systemctl — управление сервисами
|
||||
# ufw — фаервол
|
||||
# resticprofile — установка systemd-таймеров бэкапа
|
||||
#
|
||||
# Ansible become НЕ входит в этот список намеренно:
|
||||
# для плейбуков запускать с -K. Это сознательный компромисс
|
||||
# между удобством и тем, чтобы не давать python3 NOPASSWD (= root).
|
||||
- name: Configure sudoers — NOPASSWD for specific commands
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/sudoers.d/{{ bootstrap_user }}
|
||||
content: |
|
||||
{{ bootstrap_user }} ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get
|
||||
{{ bootstrap_user }} ALL=(ALL) NOPASSWD: /usr/bin/systemctl
|
||||
{{ bootstrap_user }} ALL=(ALL) NOPASSWD: /usr/bin/ufw
|
||||
{{ bootstrap_user }} ALL=(ALL) NOPASSWD: /usr/local/bin/resticprofile
|
||||
validate: /usr/sbin/visudo -cf %s
|
||||
mode: "0440"
|
||||
|
||||
# Drop-in конфиг — не трогаем основной sshd_config.
|
||||
# Требует Debian 12+ (OpenSSH 8.9+).
|
||||
- name: Harden SSH
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/ssh/sshd_config.d/99-hardening.conf
|
||||
content: |
|
||||
PasswordAuthentication no
|
||||
PermitRootLogin no
|
||||
PubkeyAuthentication yes
|
||||
mode: "0644"
|
||||
notify: restart sshd
|
||||
|
||||
- name: Ensure sshd_config.d is included
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
line: Include /etc/ssh/sshd_config.d/*.conf
|
||||
state: present
|
||||
insertbefore: BOF
|
||||
validate: /usr/sbin/sshd -t -f %s
|
||||
notify: restart sshd
|
||||
Reference in New Issue
Block a user