tightening up the docs
This commit is contained in:
parent
bad5d480d1
commit
9ecc7a54fc
1 changed files with 30 additions and 75 deletions
105
README.md
105
README.md
|
|
@ -4,38 +4,25 @@
|
||||||
|
|
||||||
**[codeberg.org/opennomad/linderhof](https://codeberg.org/opennomad/linderhof)**
|
**[codeberg.org/opennomad/linderhof](https://codeberg.org/opennomad/linderhof)**
|
||||||
|
|
||||||
a self-hosting stack based on ansible and docker compose that comes with
|
a self-hosting stack based on ansible and docker compose that comes with email, web server, git hosting, matrix, monitoring, web analytics, calendar & contacts, backups, overlay networking, and intrusion prevention — no databases, no external services.
|
||||||
|
|
||||||
- email
|
set `enable_<service>: false` in `config.yml` to disable any service — DNS records, Docker networks, and deployment tasks are all skipped automatically.
|
||||||
- [docker-mailserver](https://github.com/docker-mailserver/docker-mailserver)
|
|
||||||
- [rainloop](https://www.rainloop.net/)
|
|
||||||
- web server
|
|
||||||
- [caddy](https://caddyserver.com/)
|
|
||||||
- git server
|
|
||||||
- [forgejo](https://forgejo.org/)
|
|
||||||
- matrix homeserver
|
|
||||||
- [tuwunel](https://github.com/matrix-construct/tuwunel)
|
|
||||||
- monitoring
|
|
||||||
- [alloy](https://github.com/grafana/alloy)
|
|
||||||
- [grafana](https://grafana.com/)
|
|
||||||
- [prometheus](https://prometheus.io/)
|
|
||||||
- [loki](https://github.com/grafana/loki)
|
|
||||||
- web analytics
|
|
||||||
- [goaccess](https://goaccess.io/)
|
|
||||||
- calendar & contacts
|
|
||||||
- [radicale](https://radicale.org/)
|
|
||||||
- backups
|
|
||||||
- [restic](https://github.com/restic/restic)
|
|
||||||
- overlay network
|
|
||||||
- [nebula](https://github.com/slackhq/nebula)
|
|
||||||
- docker image update notifications
|
|
||||||
- [diun](https://github.com/crazy-max/diun)
|
|
||||||
- intrusion prevention
|
|
||||||
- [fail2ban](https://github.com/fail2ban/fail2ban)
|
|
||||||
|
|
||||||
other features include:
|
| service | toggle | default | powered by |
|
||||||
- runs on opensource
|
|---|---|---|---|
|
||||||
- no databases / no external services
|
| web server | `enable_caddy` | on | [caddy](https://caddyserver.com/) |
|
||||||
|
| email | `enable_mail` | on | [docker-mailserver](https://github.com/docker-mailserver/docker-mailserver), [rainloop](https://www.rainloop.net/) |
|
||||||
|
| git hosting | `enable_forgejo` | on | [forgejo](https://forgejo.org/) |
|
||||||
|
| matrix homeserver | `enable_tuwunel` | on | [tuwunel](https://github.com/matrix-construct/tuwunel) |
|
||||||
|
| monitoring | `enable_monitoring` | on | [prometheus](https://prometheus.io/), [grafana](https://grafana.com/), [loki](https://github.com/grafana/loki), [alloy](https://github.com/grafana/alloy) |
|
||||||
|
| web analytics | `enable_goaccess` | on | [goaccess](https://goaccess.io/) |
|
||||||
|
| calendar & contacts | `enable_radicale` | on | [radicale](https://radicale.org/) |
|
||||||
|
| backups | `enable_restic` | **off** | [restic](https://github.com/restic/restic) |
|
||||||
|
| overlay network | `enable_nebula` | on | [nebula](https://github.com/slackhq/nebula) |
|
||||||
|
| image update alerts | `enable_diun` | on | [diun](https://github.com/crazy-max/diun) |
|
||||||
|
| intrusion prevention | `enable_fail2ban` | on | [fail2ban](https://github.com/fail2ban/fail2ban) |
|
||||||
|
|
||||||
|
> **restic** is off by default — it requires a [Hetzner Storage Box](https://www.hetzner.com/storage/storage-box/) for its backup target. enable it and configure `restic_repository` in `config.yml` once you have one.
|
||||||
|
|
||||||
|
|
||||||
## what you need
|
## what you need
|
||||||
|
|
@ -78,41 +65,27 @@ ansible-galaxy collection install -r requirements.yml
|
||||||
|
|
||||||
## deploy
|
## deploy
|
||||||
|
|
||||||
### provision a server (Hetzner)
|
full deployment order for a fresh server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ansible-playbook playbooks/provision.yml
|
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/site.yml --tags bootstrap # users, SSH hardening, packages, Docker
|
||||||
|
ansible-playbook playbooks/site.yml # deploy all services
|
||||||
|
ansible-playbook playbooks/dkim_sync.yml # generate DKIM keys and publish to DNS
|
||||||
```
|
```
|
||||||
|
|
||||||
creates the server, registers your SSH key, and writes the IP to your stack config automatically. default type is `cx23` (2 vCPU, 4 GB); override with `-e hcloud_server_type=cx33`.
|
**provision** creates the server on Hetzner, registers your SSH key, and writes the IP to your stack config automatically. default type is `cx23` (2 vCPU, 4 GB); override with `-e hcloud_server_type=cx33`.
|
||||||
|
|
||||||
### update DNS
|
**dns** creates all zones and records conditional on your `enable_*` settings — disabled services get no DNS entries.
|
||||||
|
|
||||||
```bash
|
**bootstrap** connects as `root` (the only user on a fresh server), creates your admin user with passwordless sudo, hardens SSH, and installs base packages including Docker.
|
||||||
ansible-playbook playbooks/dns.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
creates all DNS zones and records for your domain. records are conditional on your `enable_*` settings — disabled services won't get DNS entries.
|
**site.yml** deploys all enabled services. subsequent runs are idempotent — safe to re-run to apply config changes.
|
||||||
|
|
||||||
### bootstrap the server
|
> **note:** on first deployment, the mail role briefly stops Caddy to acquire a Let's Encrypt certificate for the mail hostname via certbot standalone. Caddy is restarted immediately after. this only happens once.
|
||||||
|
|
||||||
first-time setup of the server (users, SSH hardening, packages, Docker):
|
**dkim_sync** generates DKIM keys for all mail domains, writes them to your stack config, and publishes the `mail._domainkey` DNS records. safe to re-run.
|
||||||
|
|
||||||
```bash
|
|
||||||
ansible-playbook playbooks/bootstrap.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
this connects as `root` (the only user on a fresh server), creates your admin user with passwordless sudo, sets passwords for `root` and the admin user, hardens SSH, and installs base packages.
|
|
||||||
|
|
||||||
### deploy services
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ansible-playbook playbooks/site.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
deploys all enabled services. subsequent runs are idempotent — safe to re-run to apply config changes.
|
|
||||||
|
|
||||||
> **note:** on first deployment, the mail role briefly stops Caddy to acquire a Let's Encrypt certificate for the mail hostname via certbot standalone. Caddy is restarted immediately after. this only happens once — subsequent runs detect the existing certificate and skip it.
|
|
||||||
|
|
||||||
|
|
||||||
## bring your own server
|
## bring your own server
|
||||||
|
|
@ -120,7 +93,7 @@ deploys all enabled services. subsequent runs are idempotent — safe to re-run
|
||||||
if you already have an Ubuntu server with SSH access:
|
if you already have an Ubuntu server with SSH access:
|
||||||
|
|
||||||
1. run `./setup.sh` — enter the server's existing hostname and IP when prompted
|
1. run `./setup.sh` — enter the server's existing hostname and IP when prompted
|
||||||
2. ensure your SSH key is authorized for the admin user and they have passwordless sudo — or run `bootstrap.yml` first if starting from root access
|
2. ensure your SSH key is authorized for the admin user and they have passwordless sudo — or run `ansible-playbook playbooks/site.yml --tags bootstrap` first if starting from root access
|
||||||
3. skip `provision.yml` and `dns.yml` if you're managing DNS elsewhere
|
3. skip `provision.yml` and `dns.yml` if you're managing DNS elsewhere
|
||||||
4. run `ansible-playbook playbooks/site.yml`
|
4. run `ansible-playbook playbooks/site.yml`
|
||||||
|
|
||||||
|
|
@ -157,24 +130,6 @@ stack config lives at `$XDG_CONFIG_HOME/linderhof/<stack>/`:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## service toggles
|
|
||||||
|
|
||||||
set `enable_<service>: false` in `config.yml` to disable a service. DNS records, Docker networks, and deployment tasks for that service will all be skipped automatically.
|
|
||||||
|
|
||||||
| variable | service |
|
|
||||||
|---|---|
|
|
||||||
| `enable_mail` | email (docker-mailserver + rainloop) |
|
|
||||||
| `enable_forgejo` | git hosting |
|
|
||||||
| `enable_tuwunel` | Matrix homeserver |
|
|
||||||
| `enable_monitoring` | Prometheus, Grafana, Loki, Alloy |
|
|
||||||
| `enable_goaccess` | web analytics |
|
|
||||||
| `enable_goaccess_sync` | rsync analytics reports to a remote host (off by default) |
|
|
||||||
| `enable_radicale` | CalDAV/CardDAV |
|
|
||||||
| `enable_restic` | encrypted backups (requires a Hetzner Storage Box — off by default) |
|
|
||||||
| `enable_nebula` | overlay network |
|
|
||||||
| `enable_diun` | Docker image update notifications |
|
|
||||||
| `enable_fail2ban` | intrusion prevention |
|
|
||||||
|
|
||||||
|
|
||||||
## overriding variables
|
## overriding variables
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue