installed firewalld and selinux permissions
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"sessionID": "ses_f63e23ebcffe7Q6sJKCl9W8sFt",
|
"sessionID": "ses_f63e23ebcffe7Q6sJKCl9W8sFt",
|
||||||
"updatedAt": "2026-09-13T19:25:59.636Z",
|
"updatedAt": "2026-09-13T19:33:29.129Z",
|
||||||
"sources": {
|
"sources": {
|
||||||
"background-task": {
|
"background-task": {
|
||||||
"state": "idle",
|
"state": "idle",
|
||||||
"updatedAt": "2026-09-13T19:25:59.636Z"
|
"updatedAt": "2026-09-13T19:33:29.129Z"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
30
README.md
30
README.md
@@ -56,11 +56,12 @@ Ansible automation that **hardens a Fedora 44 server**, installs **rootless Podm
|
|||||||
| Stage | Actions |
|
| Stage | Actions |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **System** | `dnf update` all packages; install `git`, `curl`, `openssl` |
|
| **System** | `dnf update` all packages; install `git`, `curl`, `openssl` |
|
||||||
| **Firewall** | firewalld default-deny; allow `ssh`, `http`, `https`, `7881/tcp`, `50000-50100/udp` (LiveKit voice) |
|
| **Firewall** | installs + starts firewalld (native/minimal Fedora may not ship it); default-deny; allow `ssh`, `http`, `https`, `7881/tcp`, `50000-50100/udp` (LiveKit voice) |
|
||||||
| **Fail2Ban** | `sshd` jail (3 retries → 1 h ban, incremental for repeat offenders) |
|
| **Fail2Ban** | `sshd` jail (3 retries → 1 h ban, incremental for repeat offenders) |
|
||||||
| **Auto-updates** | `dnf5-plugin-automatic`, security-only, `apply_updates = yes`, started timer |
|
| **Auto-updates** | `dnf5-plugin-automatic`, security-only, `apply_updates = yes`, started timer |
|
||||||
| **Logs** | logrotate rule for fail2ban logs (daily, 7 rotations, compressed) |
|
| **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 |
|
| **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`) |
|
||||||
| **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` |
|
| **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` |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -87,6 +88,7 @@ Ansible automation that **hardens a Fedora 44 server**, installs **rootless Podm
|
|||||||
| `stoat_video` | `true` | enable camera/screen sharing (LiveKit) |
|
| `stoat_video` | `true` | enable camera/screen sharing (LiveKit) |
|
||||||
| `stoat_service_user` | `stoat` | unprivileged user running rootless podman |
|
| `stoat_service_user` | `stoat` | unprivileged user running rootless podman |
|
||||||
| `podman_unprivileged_port_start` | `80` | lowest port rootless containers may bind |
|
| `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 |
|
| `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 |
|
| `firewall_services` / `firewall_ports` | ssh,http,https / 7881, UDP range | firewalld allow rules |
|
||||||
|
|
||||||
@@ -138,6 +140,32 @@ 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.
|
||||||
|
|
||||||
|
If a service misbehaves, check for denials before anything else:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ausearch -m avc -ts recent | grep -i stoat # recent denials
|
||||||
|
# or find the exact rule suggestion:
|
||||||
|
sudo grep "denied" /var/log/audit/audit.log | tail -20 | audit2why
|
||||||
|
```
|
||||||
|
|
||||||
|
Common knobs if a denial shows up (only set what the denial actually requires):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# containers connecting to non-default ports on the host
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Caveats & notes
|
## 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`).
|
- **First start pulls ~2 GB of images** and initializes MongoDB — allow a few minutes; the systemd unit tolerates up to 15 min (`TimeoutStartSec=900`).
|
||||||
|
|||||||
@@ -67,6 +67,14 @@ sshd_password_authentication: yes
|
|||||||
# out. Leave false unless you know what you are doing.
|
# out. Leave false unless you know what you are doing.
|
||||||
sshd_mfa_required: false
|
sshd_mfa_required: false
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Hardening - SELinux
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Native Fedora 44 ships SELinux enforcing; the role keeps it in
|
||||||
|
# this mode and installs container-selinux + policycoreutils
|
||||||
|
# (semanage / audit2why) for diagnosing container denials.
|
||||||
|
selinux_mode: enforcing
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# Hardening - firewall (firewalld, default deny)
|
# Hardening - firewall (firewalld, default deny)
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
---
|
---
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# Firewall (firewalld) - default deny, allow only what is needed
|
# Firewall (firewalld) - default deny, allow only what is needed
|
||||||
|
# Native/minimal Fedora installs may not ship firewalld, so
|
||||||
|
# install it explicitly before starting it.
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
- name: Install firewalld
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: firewalld
|
||||||
|
state: present
|
||||||
|
|
||||||
- name: Start and enable firewalld
|
- name: Start and enable firewalld
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: firewalld
|
name: firewalld
|
||||||
|
|||||||
@@ -30,4 +30,34 @@
|
|||||||
# on boot without an interactive login.
|
# on boot without an interactive login.
|
||||||
- name: Enable lingering for the service user
|
- name: Enable lingering for the service user
|
||||||
ansible.builtin.command: "loginctl enable-linger {{ stoat_service_user }}"
|
ansible.builtin.command: "loginctl enable-linger {{ stoat_service_user }}"
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# SELinux - keep enforcing, ensure the container policy and
|
||||||
|
# diagnostic tools are present for resolving any denials.
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
- name: Install SELinux container policy and diagnostics tools
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name:
|
||||||
|
- container-selinux
|
||||||
|
- policycoreutils-python-utils
|
||||||
|
- setools-console
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Check current SELinux mode
|
||||||
|
ansible.builtin.command: getenforce
|
||||||
|
register: selinux_current_mode
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Configure SELinux mode in /etc/selinux/config
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/selinux/config
|
||||||
|
regexp: '^SELINUX='
|
||||||
|
line: 'SELINUX={{ selinux_mode }}'
|
||||||
|
|
||||||
|
- name: Apply SELinux mode now
|
||||||
|
ansible.builtin.command: "setenforce {{ selinux_mode }}"
|
||||||
|
when:
|
||||||
|
- selinux_mode | lower == "enforcing"
|
||||||
|
- selinux_current_mode.stdout | lower != "enforcing"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
Reference in New Issue
Block a user