init: clean history with no PII

Toto repo ma novou cistou historii (1 commit). Predchozi historie
byla smazana, protoze obsahovala osobni udaje (IP, emaily, hesla,
klice, tokeny, Volume cesty). Soubory v aktualnim commit uz tyto
udaje neobsahuji (nahradeno placeholdery <server-ip>, CHANGE_ME,
admin@example.com atd.).

Pokud chces zpet kompletni seznam starych commitu, mas je ve svem
lokalnim working tree - git log --all ukaze prazdno (protoze jsme
smazali .git/ a zacali znovu).
This commit is contained in:
2026-08-01 19:51:59 +02:00
commit da9003aef8
10 changed files with 414 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
# Secrets - nikdy v gitu
.env
*.env
!.env.example
# Zálohy a dočasné soubory
*.bak
*.tmp
*.orig
# Editor
.vscode/
.idea/
.DS_Store
*.swp
# Build artefakty
*.log
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 mates
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+22
View File
@@ -0,0 +1,22 @@
# mates-ansible
Ansible playbooky pro nasazení a správu home infrastruktury.
Vychází z tvých existujících setupů v `/home/mates/docker/`.
## Struktura
```
playbooks/
├── bootstrap-server.yml # Úvodní setup serveru (deploy user, SSH, UFW, fail2ban)
├── deploy-services.yml # Nasaď Docker služby
├── update-services.yml # Update všech služeb
└── security-hardening.yml # Sysctl, auditd, auto-updates
```
## Detailní návody
Všechny playbooky mají komentáře v češtině. Detailní postupy najdeš v Jotty knowledge base.
## Licence
MIT viz [LICENSE](LICENSE)
+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 @@
---
# Spolecne promenne pro vsechny playbooky
# Zkopiruj na group_vars/all.yml a dopln
# Docker
docker_user: deploy
docker_uid: 1000
docker_gid: 1000
docker_install_compose_plugin: true
# Sluzby k nasazeni (seznam nazvu adresaru 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 prvnim loginu zmenit)
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 @@
---
# Ukazkovy inventory zkopiruj na inventory.yml a uprav
all:
vars:
# SSH uzivatel (deploy user, UID 1000)
ansible_user: deploy
# Python na cilovem systemu
ansible_python_interpreter: /usr/bin/python3
# Timezone
timezone: Europe/Prague
children:
# Skupina pro vsechny home servery
homeservers:
hosts:
homeserver-01:
ansible_host: <server-ip>
# homeserver-02:
# ansible_host: <server-ip-2>
# Skupina pro produkcni servery
production:
hosts:
homeserver-01:
ansible_host: <server-ip>
# Skupina pro test
staging: []
+147
View File
@@ -0,0 +1,147 @@
---
# Bootstrap noveho Ubuntu serveru
# - aktualizace systemu
# - deploy user (UID 1000)
# - SSH hardening
# - UFW firewall
# - fail2ban
# - Docker
#
# Pouziti:
# 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
# Verejny klic pro deploy uzivatele (nastav pred spustenim)
# deploy_ssh_key: "ssh-ed25519 AAAAC3Nz... hermes@mac"
tasks:
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
- name: Upgrade vsech baliku
ansible.builtin.apt:
upgrade: dist
update_cache: true
- name: Instalace zakladnich baliku
ansible.builtin.apt:
name:
- curl
- wget
- git
- vim
- htop
- ca-certificates
- gnupg
- ufw
- fail2ban
- bash-completion
state: present
- name: Nastav timezone
community.general.timezone:
name: "{{ timezone }}"
- name: Vytvor deploy uzivatele
ansible.builtin.user:
name: "{{ deploy_user }}"
uid: "{{ deploy_uid }}"
shell: /bin/bash
create_home: true
password: ""
- name: Nastav SSH klic pro deploy uzivatele
ansible.posix.authorized_key:
user: "{{ deploy_user }}"
state: present
key: "{{ deploy_ssh_key }}"
when: deploy_ssh_key is defined
- name: Povol deploy uzivateli sudo bez hesla
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: UFW vychozi pravidla
community.general.ufw:
direction: incoming
policy: deny
notify: Reload ufw
- name: Povol SSH pres UFW
community.general.ufw:
rule: allow
port: "{{ ssh_port }}"
proto: tcp
- name: Povol HTTP a HTTPS
community.general.ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- "80"
- "443"
- name: Aktivuj UFW
community.general.ufw:
state: enabled
- name: Konfigurace 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 @@
---
# Nasad Docker sluzby z docker-services/ adresare
#
# Pouziti:
# ansible-playbook -i inventory.yml playbooks/deploy-services.yml
# ansible-playbook -i inventory.yml playbooks/deploy-services.yml --extra-vars "services=[portainer,vaultwarden]"
#
- name: Nasad Docker sluzby
hosts: homeservers
become: true
gather_facts: true
vars:
services_repo: https://github.com/mates/mates-docker-services.git
services_path: "/home/{{ docker_user }}/docker-services"
services: "{{ services_to_deploy | default(['portainer', 'vaultwarden', 'gitea']) }}"
tasks:
- name: Klonuj services repo
ansible.builtin.git:
repo: "{{ services_repo }}"
dest: "{{ services_path }}"
force: false
update: true
become_user: "{{ docker_user }}"
- name: Vytvor .env z prikladu (pokud neexistuje)
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: Nasad sluzby
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
#
# Pouziti:
# ansible-playbook -i inventory.yml playbooks/security-hardening.yml
#
- name: Security hardening
hosts: homeservers
become: true
tasks:
- name: Kernel hardening pres 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: Instalace unattended-upgrades
ansible.builtin.apt:
name:
- unattended-upgrades
- apt-listchanges
state: present
- name: Povol automaticke security updaty
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: Instalace auditd
ansible.builtin.apt:
name:
- auditd
- audispd-plugins
state: present
- name: Aktivuj auditd
ansible.builtin.service:
name: auditd
state: started
enabled: true
+22
View File
@@ -0,0 +1,22 @@
---
# Update vsech Docker sluzeb (docker compose pull plus up -d)
#
# Pouziti:
# ansible-playbook -i inventory.yml playbooks/update-services.yml
#
- name: Update Docker sluzby
hosts: homeservers
become: true
vars:
services_path: "/home/{{ docker_user }}/docker-services"
services: "{{ services_to_deploy | default([]) }}"
tasks:
- name: Pull a restart sluzeb
community.docker.docker_compose_v2:
project_src: "{{ services_path }}/{{ item }}"
state: present
pull: always
loop: "{{ services }}"
become_user: "{{ docker_user }}"