removed stoat service user
This commit is contained in:
39
README.md
39
README.md
@@ -1,6 +1,6 @@
|
||||
# Stoat — Fedora 44 self-hosted chat deployment
|
||||
|
||||
Ansible automation that **hardens a Fedora 44 server**, installs **rootless Podman**, and deploys a self-hosted **[Stoat](https://stoat.chat)** instance (open-source community chat, formerly Revolt) using the official [`stoatchat/self-hosted`](https://github.com/stoatchat/self-hosted) stack.
|
||||
Ansible automation that **hardens a Fedora 44 server**, installs **Podman**, and deploys a self-hosted **[Stoat](https://stoat.chat)** instance (open-source community chat, formerly Revolt) using the official [`stoatchat/self-hosted`](https://github.com/stoatchat/self-hosted) stack.
|
||||
|
||||
**Target host:** `stoat-demo`
|
||||
|
||||
@@ -17,7 +17,7 @@ Ansible automation that **hardens a Fedora 44 server**, installs **rootless Podm
|
||||
│ ├── main.yml # imports, in order
|
||||
│ ├── system.yml # dnf full update + base packages
|
||||
│ ├── harden.yml # firewalld, sshd, fail2ban, dnf5-automatic, logrotate
|
||||
│ ├── podman.yml # rootless podman, compose, service user, linger
|
||||
│ ├── podman.yml # podman, compose, SELinux container policy
|
||||
│ └── stoat.yml # clone repo → generate config → systemd unit → start
|
||||
├── handlers/main.yml
|
||||
└── templates/
|
||||
@@ -60,8 +60,8 @@ Ansible automation that **hardens a Fedora 44 server**, installs **rootless Podm
|
||||
| **Fail2Ban** | `sshd` jail (3 retries → 1 h ban, incremental for repeat offenders) |
|
||||
| **Auto-updates** | `dnf5-plugin-automatic`, security-only, `apply_updates = yes`, started timer |
|
||||
| **Logs** | logrotate rule for fail2ban logs (daily, 7 rotations, compressed) |
|
||||
| **Podman** | rootless engine + `podman-compose` + `podman-docker`; `net.ipv4.ip_unprivileged_port_start=80` so Caddy can bind 80/443; dedicated `stoat` service user with lingering enabled |
|
||||
| **SELinux** | keeps mode enforcing; installs `container-selinux` (container policy) + `policycoreutils-python-utils` / `setools-console` (`semanage`, `audit2why`) |
|
||||
| **Podman** | engine + `podman-compose` + `podman-docker`; runs as root (no unprivileged service user, no linger) |
|
||||
| **SELinux** | keeps mode enforcing; installs `container-selinux` (container policy) + `policycoreutils-python-utils` / `setools-console` (`semanage`, `audit2why`); registers the deployment tree as `container_file_t` so rootful containers can use the bind mounts |
|
||||
| **Stoat** | clone `stoatchat/self-hosted` to `/opt/stoat/self-hosted`; run `generate_config.sh <domain>` (answers: built-in Caddy, video enabled); start stack under `podman-compose-stoat.service` |
|
||||
|
||||
---
|
||||
@@ -86,8 +86,6 @@ Ansible automation that **hardens a Fedora 44 server**, installs **rootless Podm
|
||||
| `stoat_version` | `main` | git ref of `self-hosted` repo |
|
||||
| `stoat_reverse_proxy` | `false` | `true` = move Caddy to `:8880`, bring your own front proxy/TLS |
|
||||
| `stoat_video` | `true` | enable camera/screen sharing (LiveKit) |
|
||||
| `stoat_service_user` | `stoat` | unprivileged user running rootless podman |
|
||||
| `podman_unprivileged_port_start` | `80` | lowest port rootless containers may bind |
|
||||
| `selinux_mode` | `enforcing` | SELinux mode the role enforces (config + setenforce) |
|
||||
| `fail2ban_port` / `fail2ban_maxretry` / `fail2ban_bantime` | `22` / `3` / `3600` | sshd jail tuning |
|
||||
| `firewall_services` / `firewall_ports` | ssh,http,https / 7881, UDP range | firewalld allow rules |
|
||||
@@ -114,7 +112,7 @@ ansible-playbook -i inventory.ini site.yml -k -e "stoat_domain=chat.example.org
|
||||
|
||||
## Day-to-day operations
|
||||
|
||||
All commands run on the server, mostly as the `stoat` user (`sudo -u stoat` when needed):
|
||||
All commands run on the server as root:
|
||||
|
||||
```bash
|
||||
# Stack status
|
||||
@@ -122,14 +120,14 @@ systemctl status podman-compose-stoat
|
||||
podman ps
|
||||
|
||||
# Logs (per service: api / events / web / livekit / database …)
|
||||
sudo -u stoat podman logs -f api
|
||||
podman logs -f api
|
||||
|
||||
# Restart the whole stack
|
||||
sudo systemctl restart podman-compose-stoat
|
||||
systemctl restart podman-compose-stoat
|
||||
|
||||
# Update Stoat to new images (run in /opt/stoat/self-hosted as stoat)
|
||||
sudo -u stoat podman-compose pull
|
||||
sudo -u stoat podman-compose up -d
|
||||
# Update Stoat to new images (run in /opt/stoat/self-hosted)
|
||||
podman-compose pull
|
||||
podman-compose up -d
|
||||
|
||||
# Fail2Ban status
|
||||
sudo fail2ban-client status sshd
|
||||
@@ -142,7 +140,7 @@ sudo firewall-cmd --list-all
|
||||
|
||||
## SELinux notes
|
||||
|
||||
Fedora 44 ships SELinux **enforcing**; the role pins that mode. The stack runs in **rootless** podman, where containers run in the user's own SELinux domain and can read/write the `stoat` user's files — bind mounts under `/opt/stoat/self-hosted/data` generally need no relabeling or `:Z` flags.
|
||||
Fedora 44 ships SELinux **enforcing**; the role pins that mode. Containers run as root under the `container_t` domain, so the role registers `/opt/stoat/self-hosted` as **`container_file_t`** (via `semanage fcontext` + `restorecon`) — that's what lets the rootful containers read/write the bind-mounted `data/` volumes and config files without per-volume `:Z` flags, and the registration is persistent (survives `restorecon`).
|
||||
|
||||
If a service misbehaves, check for denials before anything else:
|
||||
|
||||
@@ -159,9 +157,10 @@ Common knobs if a denial shows up (only set what the denial actually requires):
|
||||
sudo setsebool -P container_connect_any 1
|
||||
# container needs to manage cgroups (systemd inside a container)
|
||||
sudo setsebool -P container_manage_cgroup 1
|
||||
# give a specific bind-mounted volume its container context (last resort,
|
||||
# only if audit2why points at file labeling):
|
||||
sudo chcon -R -t container_file_t /opt/stoat/self-hosted/data
|
||||
# re-apply file contexts if you add bind mounts outside the
|
||||
# deployment tree (the role only labels /opt/stoat/self-hosted):
|
||||
sudo semanage fcontext -a -t container_file_t '/opt/stoat/moredata(/.*)?'
|
||||
sudo restorecon -RF /opt/stoat/moredata
|
||||
```
|
||||
|
||||
---
|
||||
@@ -169,8 +168,8 @@ sudo chcon -R -t container_file_t /opt/stoat/self-hosted/data
|
||||
## Caveats & notes
|
||||
|
||||
- **First start pulls ~2 GB of images** and initializes MongoDB — allow a few minutes; the systemd unit tolerates up to 15 min (`TimeoutStartSec=900`).
|
||||
- **Podman, not Docker**: the upstream stack is docker-compose based; this deployment runs it with `podman-compose` (rootless). It supports the compose features this stack needs (`depends_on: condition: service_healthy`, bind mounts, port ranges).
|
||||
- **`generate_config.sh` is guarded** by `creates:` — it never overwrites existing `secrets.env`/`Revolt.toml` unintentionally. To regenerate config deliberately, run it manually with `--overwrite` as the `stoat` user (after backing up secrets).
|
||||
- **Security posture**: rootless containers, fail2ban, firewalld default-deny, security-only auto-updates. SSH configuration is left exactly as you set it. (Aligned with the upstream guide's recommendations.)
|
||||
- **Rootless bind mounts**: data persists in `/opt/stoat/self-hosted/data/` (mongodb, rabbitmq, minio, caddy).
|
||||
- **Podman, not Docker**: the upstream stack is docker-compose based; this deployment runs it with `podman-compose` as root. It supports the compose features this stack needs (`depends_on: condition: service_healthy`, bind mounts, port ranges).
|
||||
- **`generate_config.sh` is guarded** by `creates:` — it never overwrites existing `secrets.env`/`Revolt.toml` unintentionally. To regenerate config deliberately, run it manually with `--overwrite` (after backing up secrets).
|
||||
- **Security posture**: fail2ban, firewalld default-deny, security-only auto-updates, SELinux enforcing with `container_file_t` labels. SSH configuration is left exactly as you set it. (Aligned with the upstream guide's recommendations.)
|
||||
- **Data persistence**: everything persists in `/opt/stoat/self-hosted/data/` (mongodb, rabbitmq, minio, caddy) — keep it out of the git clone/reset.
|
||||
- System hardening + Stoat are one role run; to re-apply only config changes, re-running `site.yml` is idempotent.
|
||||
Reference in New Issue
Block a user