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:
@@ -0,0 +1,162 @@
|
||||
# 🏛 Architecture
|
||||
|
||||
> Jak je celá home infrastruktura poskládaná.
|
||||
|
||||
## 🎯 Přehled
|
||||
|
||||
Home lab běží na jednom fyzickém serveru (Ubuntu 22.04/24.04 LTS) s Docker.
|
||||
Všechny služby jsou **containerizované**, za **Nginx Proxy Manager** (reverse proxy + HTTPS).
|
||||
|
||||
## 🌐 Vrstvy
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Layer 7: Aplikační služby │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │Nextcloud │ │Vaultwarden│ │ Gitea │ │ Jotty │ │
|
||||
│ │ :11000 │ │ :2999 │ │ :3000/222│ │ :1122 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Portainer│ │ Plex │ │Audiobook-│ │ Calibre │ │
|
||||
│ │ :9000 │ │ :32400 │ │shelf:13378│ │-Web:8083 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ ... dalších 7 služeb (rustdesk, wikijs, speedtest, ...) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
▲
|
||||
│ HTTPS
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Layer 4-7: Reverzní proxy + Let's Encrypt │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ Nginx Proxy Manager (:80, :443) │ │
|
||||
│ │ - SSL terminace (Let's Encrypt) │ │
|
||||
│ │ - HTTP → HTTPS redirect │ │
|
||||
│ │ - Access Lists │ │
|
||||
│ │ - Load balancing (volitelně) │ │
|
||||
│ └──────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
▲
|
||||
│ HTTP
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Layer 2-3: Docker bridge networks │
|
||||
│ Každá služba má vlastní bridge: │
|
||||
│ portainer_default, vaultwarden_default, gitea_default, ... │
|
||||
│ Izolace: služby mezi sebou nekomunikují (default) │
|
||||
│ Komunikace: přes reverzní proxy (NPM) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
▲
|
||||
│ Docker API
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Layer 1: Fyzický server │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ Ubuntu 22.04/24.04 LTS │ │
|
||||
│ │ - Docker CE 29.x │ │
|
||||
│ │ - Portainer CE (UI pro Docker) │ │
|
||||
│ │ - Watchtower (auto-update monitoring) │ │
|
||||
│ │ - deploy user (UID 1000) │ │
|
||||
│ │ - UFW firewall + fail2ban │ │
|
||||
│ │ - SSH hardening │ │
|
||||
│ └──────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 🔌 Služby (detail)
|
||||
|
||||
| Služba | Port | Databáze | Volume | Backup |
|
||||
|---|---|---|---|---|
|
||||
| Portainer | 9000, 9443 | SQLite (interní) | `./data` | rsync |
|
||||
| Nginx Proxy Manager | 80, 443, 81 | MariaDB | `./data`, `./letsencrypt` | rsync |
|
||||
| Vaultwarden | 2999 | SQLite | `./data` | rsync (kritické!) |
|
||||
| Nextcloud AIO | 11000 | MariaDB | `./data` | AIO Borg |
|
||||
| Gitea | 3000, 222 | SQLite | `./gitea` | rsync |
|
||||
| Jotty | 1122 | SQLite | `./data` | rsync |
|
||||
| RustDesk | 21115-21119 | SQLite | `./data` | rsync |
|
||||
| Audiobookshelf | 13378 | SQLite | `./data` + `./audiobooks` | rsync |
|
||||
| Calibre-Web | 8083 | SQLite | `./data` + `./books` | rsync |
|
||||
| Plex | 32400 | SQLite | `./data` + `./media` | rsync |
|
||||
| Erugo | 61080 | SQLite | `./data` | rsync |
|
||||
| Wiki.js | 9180 | MariaDB | `./data` | rsync |
|
||||
| Speedtest | 8765 | SQLite | `./data` | rsync |
|
||||
| Watchtower | – | – | – | – |
|
||||
|
||||
## 💾 Zálohovací schéma
|
||||
|
||||
```
|
||||
┌────────────┐
|
||||
│ Server │ rsync (denně, 03:00) → NAS /Volumes/Backups
|
||||
│ /home/.../│
|
||||
└────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────┐
|
||||
│ NAS │ Off-site sync (Backblaze B2, týdně)
|
||||
│ /Backups/ │
|
||||
└────────────┘
|
||||
```
|
||||
|
||||
Viz `install-scripts/backup-all.sh` a `install-scripts/restore-all.sh`.
|
||||
|
||||
## 🔐 Bezpečnost
|
||||
|
||||
### Perimetrie
|
||||
- **UFW** – default deny, povoleno: SSH, HTTP, HTTPS
|
||||
- **fail2ban** – ban po 3 neúspěšných SSH pokusech
|
||||
- **Cloudflare Tunnel** (volitelně) – přístup zvenčí bez veřejné IP
|
||||
|
||||
### Auth
|
||||
- **SSH klíče** – hesla zakázána (`PasswordAuthentication no`)
|
||||
- **2FA** – na všech web službách (Gitea, Vaultwarden, Nextcloud, …)
|
||||
- **Vaultwarden** – single source of truth pro hesla
|
||||
|
||||
### Network
|
||||
- **Bridge isolation** – služby spolu nekomunikují (default)
|
||||
- **No host network** – kromě Plex (HW transkódování)
|
||||
- **DNS-over-HTTPS** (volitelně)
|
||||
|
||||
## 🔄 Deployment workflow
|
||||
|
||||
```
|
||||
Developer
|
||||
│
|
||||
├─→ git push (do Gitea)
|
||||
│
|
||||
├─→ Ansible (na server)
|
||||
│ │
|
||||
│ └─→ docker compose pull && up -d
|
||||
│
|
||||
└─→ Watchtower (auto, týdně)
|
||||
└─→ image: pull, container: restart
|
||||
```
|
||||
|
||||
Viz `ansible/playbooks/`.
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
- **Watchtower** – Docker image notifikace (email/Telegram)
|
||||
- **Speedtest Tracker** – internet speed
|
||||
- **Nextcloud Talk** – interní chat
|
||||
- **Portainer** – Docker container status
|
||||
|
||||
## 🛠 Maintenance
|
||||
|
||||
| Úkol | Jak často | Skript/Ansible |
|
||||
|---|---|---|
|
||||
| Backup | Denně 03:00 | `backup-all.sh` (cron) |
|
||||
| Update OS | Týdně | `apt update && apt upgrade` |
|
||||
| Update Docker image | Týdně (auto) | Watchtower |
|
||||
| Cert renewal | Auto (Let's Encrypt 30d) | NPM interní |
|
||||
| Health check | Denně | `docker ps` + alerting |
|
||||
|
||||
## 🔮 Roadmap
|
||||
|
||||
- **Kubernetes** – přechod z docker compose na k3s (1 server node, multi-workload)
|
||||
- **GitOps** – ArgoCD pro plnou automatizaci
|
||||
- **CI/CD** – Gitea Actions pro testování Ansible playbooks
|
||||
- **Off-site backup** – Backblaze B2 s encryption
|
||||
- **Monitoring stack** – Prometheus + Grafana + Loki
|
||||
|
||||
## 📚 Reference
|
||||
|
||||
- [Docker docs](https://docs.docker.com/)
|
||||
- [Nginx Proxy Manager](https://nginxproxymanager.com/)
|
||||
- [Ansible best practices](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html)
|
||||
- [12-factor app](https://12factor.net/)
|
||||
@@ -0,0 +1,116 @@
|
||||
# 🤝 Contributing
|
||||
|
||||
> Jak přispívat do tohoto repozitáře.
|
||||
|
||||
## 📝 Pravidla
|
||||
|
||||
### Commit messages
|
||||
|
||||
Používej **Conventional Commits**:
|
||||
|
||||
- `feat:` – nová služba nebo funkce
|
||||
- `fix:` – oprava chyby
|
||||
- `docs:` – pouze dokumentace
|
||||
- `chore:` – údržba, refactoring
|
||||
- `style:` – formatting, bez funkční změny
|
||||
- `refactor:` – přestavba kódu
|
||||
- `test:` – přidání testů
|
||||
|
||||
Příklad: `feat(vaultwarden): přidat 2FA podporu`
|
||||
|
||||
### Branch naming
|
||||
|
||||
- `feature/<name>` – nová feature
|
||||
- `fix/<name>` – bugfix
|
||||
- `docs/<name>` – dokumentace
|
||||
|
||||
Příklad: `feature/audiobookshelf-metadata`
|
||||
|
||||
### Pull Request
|
||||
|
||||
1. Fork → branch → commit → push → PR
|
||||
2. **Titulek PR** – krátký, výstižný
|
||||
3. **Popis** – co, proč, jak
|
||||
4. **Screenshoty** – pokud měníš UI/dokumentaci
|
||||
5. **Testy** – pokud měníš Ansible playbooks
|
||||
|
||||
## 🏗 Struktura
|
||||
|
||||
```
|
||||
repo/
|
||||
├── docker-services/ # Každá služba v samostatném adresáři
|
||||
├── install-scripts/ # Bash skripty pro nové servery
|
||||
├── ansible/ # Playbooky + role
|
||||
├── hermes-install/ # Hermes CLI setup
|
||||
├── macos-setup/ # Homebrew + macOS defaults
|
||||
├── home-nas-tools/ # Metadata (žádné binárky!)
|
||||
└── docs/ # Architektura, bezpečnost
|
||||
```
|
||||
|
||||
## ✅ Checklist pro novou službu
|
||||
|
||||
- [ ] `docker-services/<service>/docker-compose.yml` – generický, placeholders
|
||||
- [ ] `docker-services/<service>/.env.example` – šablona env vars
|
||||
- [ ] `docker-services/<service>/README.md` – dokumentace
|
||||
- [ ] Aktualizován `docker-services/README.md` (tabulka)
|
||||
- [ ] Aktualizován hlavní `README.md` (pokud je service klíčová)
|
||||
- [ ] **Žádné citlivé údaje** v commitu
|
||||
|
||||
## 🔐 Bezpečnost
|
||||
|
||||
- ❌ **NEcommituj** hesla, API klíče, IP adresy serveru
|
||||
- ❌ **NEcommituj** `~/.env` (je v `.gitignore`)
|
||||
- ❌ **NEcommituj** SSH klíče
|
||||
- ✅ **Vždy** používej `.env.example` jako šablonu
|
||||
- ✅ **Vždy** testuj nové compose lokálně před commitem
|
||||
|
||||
## 🧪 Testování
|
||||
|
||||
Před commitem:
|
||||
|
||||
```bash
|
||||
# Validace YAML
|
||||
python3 -c "import yaml; yaml.safe_load(open('docker-services/<service>/docker-compose.yml'))"
|
||||
|
||||
# Validace compose (na serveru)
|
||||
docker compose -f docker-services/<service>/docker-compose.yml config
|
||||
|
||||
# Syntax check bash
|
||||
shellcheck install-scripts/<script>.sh
|
||||
|
||||
# Lint Ansible
|
||||
ansible-lint ansible/playbooks/<playbook>.yml
|
||||
```
|
||||
|
||||
## 📋 Verzování
|
||||
|
||||
- **Semver** – `MAJOR.MINOR.PATCH`
|
||||
- **Tagy:** `v1.0.0`, `v1.1.0`, …
|
||||
- **Release notes** – v GitHub/Gitea Releases
|
||||
|
||||
## 🐛 Hlášení chyb
|
||||
|
||||
Vytvoř **issue** v Gitea s:
|
||||
|
||||
1. **Název** – krátký popis
|
||||
2. **Kroky k reprodukci** – co jsi udělal
|
||||
3. **Očekávané chování** – co jsi čekal
|
||||
4. **Skutečné chování** – co se stalo
|
||||
5. **Verze** – `git describe` + verze OS
|
||||
|
||||
## 💡 Návrhy features
|
||||
|
||||
1. Otevři **issue** s labelem `enhancement`
|
||||
2. Popiš use case – co chceš dělat
|
||||
3. Jaké alternativy jsi zvážil
|
||||
4. Jak to navrhuješ implementovat
|
||||
|
||||
## 📞 Kontakt
|
||||
|
||||
- **Issues:** Gitea
|
||||
- **Email:** viz Gitea profil
|
||||
- **Diskuze:** Gitea Discussions (pokud povoleno)
|
||||
|
||||
## 📜 Licence
|
||||
|
||||
Přispěním do tohoto repo souhlasíš s licencí [MIT](../LICENSE).
|
||||
@@ -0,0 +1,152 @@
|
||||
# 🔐 Security
|
||||
|
||||
> Bezpečnostní checklisty, hardening, threat model.
|
||||
|
||||
## 🛡 Defense in depth
|
||||
|
||||
### Layer 1: Fyzický
|
||||
- Server v uzamčené místnosti
|
||||
- UPS (nepřerušitelný zdroj)
|
||||
- Teplotní monitoring (smart home)
|
||||
|
||||
### Layer 2: Síť (perimetrie)
|
||||
- ✅ UFW firewall (default deny)
|
||||
- ✅ fail2ban (3 SSH pokusy = ban)
|
||||
- ✅ Cloudflare Tunnel (žádná veřejná IP)
|
||||
- ✅ VLAN izolace (IoT vs servery)
|
||||
|
||||
### Layer 3: OS
|
||||
- ✅ Ubuntu LTS (pravidelné bezpečnostní updaty)
|
||||
- ✅ unattended-upgrades (auto security updates)
|
||||
- ✅ SSH klíče (hesla zakázána)
|
||||
- ✅ PermitRootLogin no
|
||||
- ✅ Auditd (logování)
|
||||
|
||||
### Layer 4: Docker
|
||||
- ✅ Bridge network isolation
|
||||
- ✅ Read-only filesystémy kde to jde
|
||||
- ✅ USER_UID/GID pro file ownership
|
||||
- ✅ No `--privileged` (pokud to není nutné)
|
||||
- ✅ No `--net=host` (kromě Plex)
|
||||
- ✅ Health checks pro monitoring
|
||||
- ✅ Logging: json-file driver, 10 MB × 3
|
||||
|
||||
### Layer 5: Aplikace
|
||||
- ✅ HTTPS terminuje NPM (Let's Encrypt)
|
||||
- ✅ 2FA na všech web službách
|
||||
- ✅ API klíče v keychainu, ne v env souborech
|
||||
- ✅ Rate limiting (NPM, fail2ban)
|
||||
|
||||
### Layer 6: Data
|
||||
- ✅ Backup na NAS (denně)
|
||||
- ✅ Off-site backup (Backblaze B2)
|
||||
- ✅ Šifrované citlivé volumes (LUKS, v budoucnu)
|
||||
- ✅ Retention policy (7 dní denně, 4 týdny týdně, 12 měsíců měsíčně)
|
||||
|
||||
## 🔑 Správa hesel
|
||||
|
||||
- **Vaultwarden** – single source of truth
|
||||
- **API klíče** – v macOS keychainu (`security add-generic-password`)
|
||||
- **SSH klíče** – `~/.ssh/id_ed25519`, passphrase v keychainu
|
||||
- **2FA** – TOTP, hardwarový klíč (doporučeno YubiKey)
|
||||
|
||||
## 🚨 Incident Response
|
||||
|
||||
### Detekce
|
||||
- Watchtower notifikace (image outdated)
|
||||
- fail2ban email alert
|
||||
- Speedtest alert (interní outage)
|
||||
- Cloudflare Tunnel logy
|
||||
|
||||
### Postup
|
||||
1. **Identifikuj** – logy, monitoring
|
||||
2. **Izoluj** – zastavit kontejner / odpojit síť
|
||||
3. **Analyzuj** – root cause, scope
|
||||
4. **Oprav** – patch, konfigurace
|
||||
5. **Dokumentuj** – incident log v `~/Skripty/incident-YYYY-MM-DD.md`
|
||||
|
||||
### Recovery
|
||||
- `restore-all.sh` pro Docker data
|
||||
- Vaultwarden backup pro credentials
|
||||
- DNS failover (Cloudflare)
|
||||
|
||||
## 🛠 Hardening checklist
|
||||
|
||||
### Server
|
||||
- [ ] Ubuntu LTS nainstalován
|
||||
- [ ] UFW aktivní, default deny
|
||||
- [ ] fail2ban nakonfigurován
|
||||
- [ ] SSH klíče, root login zakázán
|
||||
- [ ] unattended-upgrades aktivní
|
||||
- [ ] auditd běží
|
||||
- [ ] Docker nainstalován z oficiálního repo
|
||||
|
||||
### Docker
|
||||
- [ ] Bridge networks (žádný host network, kromě Plex)
|
||||
- [ ] USER_UID=1000, USER_GID=1000 pro všechny kontejnery
|
||||
- [ ] Volumes na hostu (./data), ne anonymous
|
||||
- [ ] Health checks v compose
|
||||
- [ ] Logging: 10 MB × 3 soubory
|
||||
- [ ] Restart: unless-stopped
|
||||
|
||||
### Služby
|
||||
- [ ] HTTPS terminuje NPM
|
||||
- [ ] Let's Encrypt auto-renew
|
||||
- [ ] 2FA na všech účtech
|
||||
- [ ] Admin heslo změněno z default
|
||||
- [ ] Registrace vypnuta (pokud ne private)
|
||||
- [ ] SMTP nastaveno (pro notifikace)
|
||||
|
||||
### Zálohy
|
||||
- [ ] rsync skript cron (denně 03:00)
|
||||
- [ ] Off-site backup (Backblaze B2)
|
||||
- [ ] Test obnovy (čtvrtletně)
|
||||
- [ ] Šifrované zálohy (GPG + age)
|
||||
|
||||
## 📜 Compliance
|
||||
|
||||
- **GDPR** – osobní data v Nextcloud (kontrola přístupu)
|
||||
- **PCI DSS** – N/A (žádné platby)
|
||||
- **NIS2** – pokud provozuješ služby pro třetí strany
|
||||
|
||||
## 🔍 Threat model
|
||||
|
||||
| Hrozba | Pravděpodobnost | Dopad | Mitigace |
|
||||
|---|---|---|---|
|
||||
| Brute force SSH | Vysoká | Nízký | fail2ban, key-only |
|
||||
| Phishing | Střední | Vysoký | 2FA, edukace |
|
||||
| Docker escape | Nízká | Kritický | Bridge isolation, USER_UID, pravidelné updaty |
|
||||
| Supply chain (image) | Nízká | Vysoký | Oficiální image, Watchtower, GPG signing |
|
||||
| Insider threat | Nízká | Střední | Audit logy, 2FA, hesla v keychainu |
|
||||
| Ransomware | Nízká | Kritický | Off-site backup, 3-2-1 rule |
|
||||
| DDoS | Střední | Střední | Cloudflare, fail2ban |
|
||||
| DNS hijack | Nízká | Vysoký | DNSSEC, HTTPS |
|
||||
| Zero-day v OS | Střední | Kritický | unattended-upgrades, WAF |
|
||||
|
||||
## 🔐 API token management
|
||||
|
||||
```bash
|
||||
# Uložení do keychainu
|
||||
security add-generic-password \
|
||||
-s "service:api:192.168.0.148" \
|
||||
-a "user" \
|
||||
-w "TOKEN" -U
|
||||
|
||||
# Čtení v skriptech
|
||||
TOKEN=$(security find-generic-password \
|
||||
-s "service:api:192.168.0.148" \
|
||||
-a "user" -w)
|
||||
```
|
||||
|
||||
**Pravidla:**
|
||||
- Token **nikdy** v `.env` souborech
|
||||
- Token **nikdy** v `docker-compose.yml`
|
||||
- Token **nikdy** v git history
|
||||
- Token **pouze** v keychainu nebo env variables
|
||||
|
||||
## 📚 Reference
|
||||
|
||||
- [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker)
|
||||
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
|
||||
- [NIST Cybersecurity Framework](https://www.nist.gov/cyberframework)
|
||||
- [CIS Ubuntu Linux Benchmark](https://www.cisecurity.org/benchmark/ubuntu_linux)
|
||||
Reference in New Issue
Block a user