feat: initial infra repo

- docker-services: 14 generic compose templates (portainer, npm, vaultwarden, gitea, jotty, nextcloud-aio, rustdesk, audiobookshelf, calibre-web, plex, erugo, jswiki, speedtest, watchtower)
- install-scripts: bash scripts for Ubuntu server bootstrap, docker, portainer, npm, backup, restore
- ansible: 4 playbooks (bootstrap, deploy-services, update-services, security-hardening) + roles skeleton
- hermes-install: Hermes CLI setup on macOS
- macos-setup: Brewfile + osx-defaults + fish-config
- home-nas-tools: metadata index for NAS projects (no binaries)
- docs: architecture, security, contributing
- README, LICENSE (MIT), .gitignore
This commit is contained in:
2026-08-01 16:25:58 +02:00
commit 444191d16d
73 changed files with 4032 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
# 🎭 Ansible Playbooks
> Ansible role a playbooks pro nasazení a správu home infrastruktury.
> Idempotentní, testovatelné, čitelné.
## 📁 Struktura
```
ansible/
├── README.md # Tento soubor
├── ansible.cfg # Konfigurace
├── requirements.yml # Ansible Galaxy role
├── inventory.example.yml # Ukázkový inventory
├── playbooks/
│ ├── bootstrap-server.yml # Úvodní setup nového serveru
│ ├── deploy-services.yml # Nasaď všechny Docker služby
│ ├── update-services.yml # Update všech služeb
│ └── security-hardening.yml # Bezpečnostní hardening
├── roles/
│ ├── common/ # Společné úkoly (update, packages, users)
│ ├── docker/ # Docker + compose
│ ├── portainer/ # Portainer compose
│ ├── nginx-proxy/ # Nginx Proxy Manager
│ ├── vaultwarden/ # Vaultwarden
│ ├── gitea/ # Gitea
│ └── ...
└── group_vars/
└── all.yml.example # Společné proměnné
```
## 🚀 Quickstart
```bash
# 1. Příprava
pip install ansible
ansible-galaxy install -r requirements.yml
# 2. Inventory
cp inventory.example.yml inventory.yml
nano inventory.yml # nastavit IP a SSH user
# 3. Test připojení
ansible all -m ping
# 4. Bootstrap
ansible-playbook -i inventory.yml playbooks/bootstrap-server.yml
# 5. Nasaď služby
ansible-playbook -i inventory.yml playbooks/deploy-services.yml --extra-vars "services=[portainer,vaultwarden,gitea]"
# 6. Update
ansible-playbook -i inventory.yml playbooks/update-services.yml
```
## 🎯 Playbooky
### `bootstrap-server.yml`
- Update OS
- Setup deploy user (UID 1000)
- SSH hardening
- UFW firewall
- fail2ban
- Základní utility
### `deploy-services.yml`
- Nasaď vybrané Docker služby
- Idempotentní můžeš spustit víckrát
### `update-services.yml`
- `docker compose pull && up -d` pro všechny služby
- Watchtower notifikace
### `security-hardening.yml`
- Sysctl hardening
- AppArmor profily
- Auditd pravidla
- Automatické security updaty
## 🔐 Bezpečnost
- **Bez hesel v inventory** použij `ansible-vault` nebo SSH klíče
- **Privilege escalation** `become: true` jen kde potřeba
- **Idempotence** každý task kontroluje stav
## 📚 Dokumentace
- [Ansible docs](https://docs.ansible.com/)
- [Best practices](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html)
+21
View File
@@ -0,0 +1,21 @@
[defaults]
inventory = inventory.yml
roles_path = roles
host_key_checking = False
retry_files_enabled = False
stdout_callback = yaml
forks = 10
gathering = smart
fact_caching = jsonfile
fact_caching_connection = local
fact_caching_timeout = 86400
[privilege_escalation]
become = True
become_method = sudo
become_ask_pass = False
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ServerAliveInterval=30
control_path = /tmp/ansible-ssh-%%h-%%p-%%r
+35
View File
@@ -0,0 +1,35 @@
---
# Společné proměnné pro všechny playbooks
# Zkopíruj na group_vars/all.yml a doplň
# Docker
docker_user: deploy
docker_uid: 1000
docker_gid: 1000
docker_install_compose_plugin: true
# Služby k nasazení (seznam názvů adresářů v docker-services/)
services_to_deploy:
- portainer
- nginx-proxy-manager
- vaultwarden
- gitea
- jotty
- nextcloud-aio
- rustdesk
- audiobookshelf
- calibre-web
- plex
- erugo
- jswiki
- speedtest
- watchtower
# NPM admin (po prvním loginu změnit)
npm_default_email: admin@example.com
npm_default_password: changeme
# Gitea admin (po instalaci)
gitea_admin_user: admin
gitea_admin_password: changeme
gitea_admin_email: admin@example.com
+28
View File
@@ -0,0 +1,28 @@
---
# Ukázkový inventory zkopíruj na inventory.yml a uprav
all:
vars:
# SSH uživatel (deploy user, UID 1000)
ansible_user: deploy
# Python na cílovém systému
ansible_python_interpreter: /usr/bin/python3
# Timezone
timezone: Europe/Prague
children:
# Skupina pro všechny home servery
homeservers:
hosts:
homeserver-01:
ansible_host: 192.168.0.148
# homeserver-02:
# ansible_host: 192.168.0.149
# Skupina pro produkční servery
production:
hosts:
homeserver-01:
ansible_host: 192.168.0.148
# Skupina pro test
staging: []
+145
View File
@@ -0,0 +1,145 @@
---
# Bootstrap nového Ubuntu serveru
# - aktualizace systému
# - deploy user (UID 1000)
# - SSH hardening
# - UFW firewall
# - fail2ban
# - Docker
#
# Použití:
# ansible-playbook -i inventory.yml playbooks/bootstrap-server.yml
#
- name: Bootstrap home server
hosts: homeservers
become: true
gather_facts: true
vars:
deploy_user: deploy
deploy_uid: 1000
ssh_port: 22
deploy_ssh_key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
tasks:
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
- name: Upgrade all packages
ansible.builtin.apt:
upgrade: dist
update_cache: true
- name: Install base packages
ansible.builtin.apt:
name:
- curl
- wget
- git
- vim
- htop
- ca-certificates
- gnupg
- ufw
- fail2ban
- bash-completion
state: present
- name: Set timezone
community.general.timezone:
name: "{{ timezone }}"
- name: Create deploy user
ansible.builtin.user:
name: "{{ deploy_user }}"
uid: "{{ deploy_uid }}"
shell: /bin/bash
create_home: true
password: ""
- name: Setup authorized_keys for deploy user
ansible.posix.authorized_key:
user: "{{ deploy_user }}"
state: present
key: "{{ deploy_ssh_key }}"
- name: Allow deploy user sudo without password
ansible.builtin.copy:
dest: "/etc/sudoers.d/{{ deploy_user }}"
content: "{{ deploy_user }} ALL=(ALL) NOPASSWD:ALL\n"
mode: "0440"
- name: SSH hardening
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?{{ item.key }}"
line: "{{ item.key }} {{ item.value }}"
state: present
loop:
- { key: "Port", value: "{{ ssh_port }}" }
- { key: "PermitRootLogin", value: "no" }
- { key: "PasswordAuthentication", value: "no" }
- { key: "X11Forwarding", value: "no" }
- { key: "ClientAliveInterval", value: "300" }
- { key: "ClientAliveCountMax", value: "2" }
notify: Restart ssh
- name: Configure UFW defaults
community.general.ufw:
direction: incoming
policy: deny
notify: Reload ufw
- name: Allow SSH through UFW
community.general.ufw:
rule: allow
port: "{{ ssh_port }}"
proto: tcp
- name: Allow HTTP and HTTPS through UFW
community.general.ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- "80"
- "443"
- name: Enable UFW
community.general.ufw:
state: enabled
- name: Configure fail2ban
ansible.builtin.copy:
dest: /etc/fail2ban/jail.local
content: |
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
port = {{ ssh_port }}
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
mode: "0644"
notify: Restart fail2ban
handlers:
- name: Restart ssh
ansible.builtin.service:
name: sshd
state: restarted
- name: Reload ufw
community.general.ufw:
state: reloaded
- name: Restart fail2ban
ansible.builtin.service:
name: fail2ban
state: restarted
+42
View File
@@ -0,0 +1,42 @@
---
# Nasaď Docker služby z docker-services/ adresáře
#
# Použití:
# ansible-playbook -i inventory.yml playbooks/deploy-services.yml
# ansible-playbook -i inventory.yml playbooks/deploy-services.yml --extra-vars "services=[portainer,vaultwarden]"
#
- name: Deploy Docker services
hosts: homeservers
become: true
gather_facts: true
vars:
services_repo: https://github.com/<user>/mates-infra.git
services_path: "/home/{{ docker_user }}/docker-services"
services: "{{ services_to_deploy | default(['portainer', 'vaultwarden', 'gitea']) }}"
tasks:
- name: Clone services repo
ansible.builtin.git:
repo: "{{ services_repo }}"
dest: "{{ services_path }}"
force: false
update: true
become_user: "{{ docker_user }}"
- name: Create .env from example
ansible.builtin.copy:
src: "{{ services_path }}/{{ item }}/.env.example"
dest: "{{ services_path }}/{{ item }}/.env"
remote_src: true
force: false
loop: "{{ services }}"
become_user: "{{ docker_user }}"
- name: Deploy services
community.docker.docker_compose_v2:
project_src: "{{ services_path }}/{{ item }}"
state: present
pull: missing
loop: "{{ services }}"
become_user: "{{ docker_user }}"
+58
View File
@@ -0,0 +1,58 @@
---
# Security hardening sysctl, AppArmor, auditd, auto-updates
#
# Použití:
# ansible-playbook -i inventory.yml playbooks/security-hardening.yml
#
- name: Security hardening
hosts: homeservers
become: true
tasks:
- name: Kernel hardening via sysctl
ansible.posix.sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
state: present
reload: true
loop:
- { key: "net.ipv4.conf.all.rp_filter", value: "1" }
- { key: "net.ipv4.conf.default.rp_filter", value: "1" }
- { key: "net.ipv4.icmp_echo_ignore_broadcasts", value: "1" }
- { key: "net.ipv4.conf.all.accept_redirects", value: "0" }
- { key: "net.ipv4.conf.default.accept_redirects", value: "0" }
- { key: "net.ipv6.conf.all.accept_redirects", value: "0" }
- { key: "net.ipv4.conf.all.send_redirects", value: "0" }
- { key: "net.ipv4.conf.all.accept_source_route", value: "0" }
- { key: "net.ipv4.conf.default.accept_source_route", value: "0" }
- { key: "net.ipv4.tcp_syncookies", value: "1" }
- { key: "net.ipv4.conf.all.log_martians", value: "1" }
- name: Install unattended-upgrades
ansible.builtin.apt:
name:
- unattended-upgrades
- apt-listchanges
state: present
- name: Enable automatic security updates
ansible.builtin.copy:
dest: /etc/apt/apt.conf.d/20auto-upgrades
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
mode: "0644"
- name: Install auditd
ansible.builtin.apt:
name:
- auditd
- audispd-plugins
state: present
- name: Enable auditd
ansible.builtin.service:
name: auditd
state: started
enabled: true
+22
View File
@@ -0,0 +1,22 @@
---
# Update všech Docker služeb (docker compose pull + up -d)
#
# Použití:
# ansible-playbook -i inventory.yml playbooks/update-services.yml
#
- name: Update Docker services
hosts: homeservers
become: true
vars:
services_path: "/home/{{ docker_user }}/docker-services"
services: "{{ services_to_deploy | default([]) }}"
tasks:
- name: Pull and restart services
community.docker.docker_compose_v2:
project_src: "{{ services_path }}/{{ item }}"
state: present
pull: always
loop: "{{ services }}"
become_user: "{{ docker_user }}"