mirror of
https://github.com/fscotto/infra.git
synced 2026-09-27 11:02:47 +00:00
Harden Atlas network, SSH, firewall, and sharing
This commit is contained in:
11
AGENTS.md
11
AGENTS.md
@@ -55,6 +55,8 @@ Ansible-driven personal infrastructure repo for Fedora and Void desktops, Fedora
|
||||
- Server compose render: `podman-compose -f /opt/docker/server/docker-compose.yml config` and `systemctl status podman-compose-server`
|
||||
- Atlas media stack:
|
||||
`ansible-playbook ansible/site.yml --limit atlas --tags storage,sharing,containers --check --diff`
|
||||
- Atlas network/share hardening:
|
||||
`ansible-playbook ansible/site.yml --limit atlas --tags hardening,sharing --check --diff`
|
||||
- Atlas phase-one rootless services:
|
||||
`ansible-playbook ansible/site.yml --limit atlas --tags backend_phase1 --check --diff`
|
||||
- Prometheus/Atlas WireGuard overlay:
|
||||
@@ -142,8 +144,9 @@ The dotfile vars follow the same split: `desktop_common_dotfiles` carries mode-i
|
||||
- The `immich` system account is fixed to UID/GID `1100`, has no login shell or `wheel` membership, and receives only
|
||||
the `video` and `render` supplementary groups. Immich's rootful Quadlets run as `1100:1100`; Server and ML receive
|
||||
`/dev/dri`, while the Photobook external library is read-only at `/external/photobook`.
|
||||
- Atlas exports Photobook only to the configured Aegis IP with all access squashed to UID/GID `1100`. SMB3 exposes
|
||||
`Archive` to Vault-backed authorized accounts and admits the configured LAN without host-specific exclusions.
|
||||
- Atlas applies persistent kernel network hardening: redirects and source routes are rejected, martians logged, reverse-path filtering remains loose for WireGuard, and IPv4 forwarding is disabled. SSH permits only the declared administrator using public-key authentication; root login, passwords, agent and remote forwarding
|
||||
are disabled, while local forwarding remains available for private administrative tunnels. Photobook is exported only to the configured Aegis IP with all access squashed to UID/GID
|
||||
`1100`. Targeted SELinux is enforced persistently; a required reboot is reported but never initiated automatically. The primary LAN interface is assigned explicitly to the managed firewalld zone, and firewall rules are applied before NFS or SMB are started; their service state and TCP listeners are then verified. SMB3 exposes `Archive` to Vault-backed authorized accounts on mandatory encrypted, signed SMB3 over TCP/445 only and admits the configured LAN without host-specific exclusions.
|
||||
- Atlas NPM and Immich share a rootful Podman network. NPM publishes HTTP/HTTPS, but its administration port remains
|
||||
bound to `127.0.0.1:81`; do not expose it directly to the LAN or Internet.
|
||||
- `profile_backend_phase1` is limited to rootless Navidrome and Syncthing user Quadlets on Atlas. Official Navidrome
|
||||
@@ -155,8 +158,8 @@ The dotfile vars follow the same split: `desktop_common_dotfiles` carries mode-i
|
||||
Atlas and its SQLite database verified. The playbook renders the target but never migrates or deletes application
|
||||
data; after cutover, set the flag true to enable and start Navidrome and Syncthing.
|
||||
- Phase 1 must not change Prometheus' existing NPM deployment. NPM continues to be managed exactly by `profile_server`;
|
||||
use `10.0.0.2:4533` for Navidrome and `10.0.0.2:8384` for the Syncthing GUI. Native Syncthing transfer/discovery does
|
||||
not use the HTTP proxy.
|
||||
use `10.0.0.2:4533` for Navidrome and `10.0.0.2:8384` for the Syncthing GUI. Syncthing does not use host networking:
|
||||
its GUI, transfer, QUIC and discovery ports are explicitly published only on `10.0.0.2`; native transfer/discovery does not use the HTTP proxy.
|
||||
- `wireguard_overlay` manages the required `wg0` path between Prometheus and Atlas, persists private keys only on their
|
||||
respective hosts, and exchanges only derived public keys. The initial run must include both hosts. Prometheus
|
||||
opens `51820/udp`; the Atlas backend role admits service ports only in the WireGuard firewalld zone.
|
||||
|
||||
11
README.it.md
11
README.it.md
@@ -196,8 +196,8 @@ Nextcloud resta disabilitato e il profilo non crea directory `/srv/nextcloud`.
|
||||
La fase 1 su Atlas non modifica questo deployment NPM ne i suoi dati persistenti. Dopo aver attivato
|
||||
WireGuard e i servizi Atlas, configurare i proxy host NPM correnti con upstream Navidrome
|
||||
`http://10.0.0.2:4533` e upstream per la GUI Syncthing `http://10.0.0.2:8384`. Solo la GUI web di
|
||||
Syncthing usa NPM; il traffico di sincronizzazione resta sulle porte native limitate a WireGuard.
|
||||
Configurare l'autenticazione Syncthing e una policy di accesso NPM adeguata prima di pubblicare la GUI.
|
||||
Syncthing usa NPM; il traffico di sincronizzazione resta sulle porte native pubblicate esplicitamente solo
|
||||
sull'indirizzo WireGuard di Atlas. Configurare l'autenticazione Syncthing e una policy di accesso NPM adeguata prima di pubblicare la GUI.
|
||||
|
||||
### DuckDNS
|
||||
|
||||
@@ -274,9 +274,10 @@ Con la gestione storage attiva, Atlas crea l'intera gerarchia sotto il pool `zpo
|
||||
`media/photobook`, `backups`, `backups/services` e `backup_prometheus`. I dataset applicativi e
|
||||
di archivio usano `zstd`; media, Syncthing e backup dei servizi usano `lz4`;
|
||||
`backups/services` mantiene inoltre una `refreservation` di `500G`.
|
||||
SMB3 pubblica `Archive` solo agli account Samba configurati con password in Vault e ammette la LAN
|
||||
configurata senza esclusioni specifiche per host. NFSv4 esporta soltanto
|
||||
`media/photobook` all'IP configurato di Aegis con `all_squash` verso UID/GID anonimi `1100`.
|
||||
Atlas impone SELinux targeted in modo persistente e segnala, senza avviarlo, l’eventuale reboot necessario per attivarlo. Assegna esplicitamente l’interfaccia LAN primaria alla zona firewalld gestita e applica hardening persistente del kernel di rete: rifiuta redirect e source-route, registra i martian, usa reverse-path filtering loose per WireGuard e disabilita il forwarding IPv4. SSH consente solo l’amministratore dichiarato tramite chiave pubblica; root, password, agent e forwarding
|
||||
remoto sono disabilitati, mentre il forwarding locale resta disponibile per tunnel amministrativi privati. SMB3 pubblica `Archive` solo agli account Samba configurati con password in Vault e
|
||||
ammette la LAN configurata su SMB3 cifrato e firmato, esclusivamente su TCP/445. NFSv4 esporta soltanto
|
||||
`media/photobook` all'IP configurato di Aegis su TCP/2049, con `all_squash` verso UID/GID anonimi `1100`.
|
||||
|
||||
L'account di sistema `immich` usa UID/GID `1100`, shell senza login, nessuna appartenenza a `wheel` e
|
||||
i gruppi supplementari `video` e `render`. I Quadlet rootful di Immich Server, ML, cache compatibile
|
||||
|
||||
13
README.md
13
README.md
@@ -119,8 +119,9 @@ does not provision any `/srv/nextcloud` directories.
|
||||
The Atlas phase-one work does not change this NPM deployment or its persistent data. Once WireGuard
|
||||
and the Atlas services are active, configure the current NPM proxy hosts with Navidrome upstream
|
||||
`http://10.0.0.2:4533` and Syncthing GUI upstream `http://10.0.0.2:8384`. Only the Syncthing web GUI
|
||||
uses NPM; synchronization traffic remains on its native WireGuard-restricted ports. Configure both
|
||||
Syncthing authentication and an appropriate NPM access policy before publishing its GUI.
|
||||
uses NPM; synchronization traffic remains on explicitly published native ports bound only to the Atlas
|
||||
WireGuard address. Configure both Syncthing authentication and an appropriate NPM access policy before
|
||||
publishing its GUI.
|
||||
|
||||
Server identity comes from `server_username`, `server_user_group`, and `server_user_home` in `ansible/inventory/group_vars/server.yml`. `server_username` defaults to `username`, but it can be overridden, for example:
|
||||
|
||||
@@ -230,9 +231,11 @@ explicitly bootstrapped `zpool`: `work`, `archive`, `archive/app_data`, the sepa
|
||||
`archive/app_data/syncthing` application datasets, `media`, `media/music`, `media/photobook`,
|
||||
`backups`, `backups/services`, and `backup_prometheus`. Application/archive datasets use `zstd`,
|
||||
while media, Syncthing and service-backup datasets use `lz4`; `backups/services` also has a `500G`
|
||||
refreservation. SMB3 exposes `Archive` only to the configured Vault-backed Samba accounts and admits
|
||||
the configured LAN without host-specific exclusions. NFSv4 exports only
|
||||
`media/photobook` to the configured Aegis IP, using `all_squash` with anonymous UID/GID `1100`.
|
||||
refreservation. Atlas enforces targeted SELinux persistently and reports, without initiating, any reboot required to activate it. It assigns its primary LAN interface explicitly to the managed firewalld zone and applies persistent kernel network hardening: redirects and source routes are rejected, martians logged, reverse-path filtering remains loose for WireGuard, and IPv4 forwarding is disabled. SSH permits only the declared administrator using public-key authentication; root login, passwords,
|
||||
agent and remote forwarding are disabled, while local forwarding remains available for private administrative tunnels. SMB3 exposes `Archive` only to the configured Vault-backed
|
||||
Samba accounts on encrypted, signed SMB3 over TCP/445 only and admits the configured LAN without host-specific
|
||||
exclusions. NFSv4 exports only `media/photobook` to the configured Aegis IP over TCP/2049, using
|
||||
`all_squash` with anonymous UID/GID `1100`.
|
||||
|
||||
The `immich` system account is fixed to UID/GID `1100`, has no login shell or `wheel` membership, and
|
||||
receives `video` and `render` access. The rootful Immich Server, ML, Redis-compatible cache, PostgreSQL,
|
||||
|
||||
@@ -14,6 +14,7 @@ atlas_admin_uid: 1000
|
||||
atlas_admin_gid: 1000
|
||||
atlas_admin_ssh_keys: "{{ vault_atlas_authorized_ssh_keys | default([]) }}"
|
||||
atlas_admin_password_hash: "{{ vault_atlas_admin_password_hash | default('!') }}"
|
||||
atlas_ssh_allow_tcp_forwarding: local
|
||||
|
||||
atlas_lan_subnet: 192.168.178.0/24
|
||||
atlas_aegis_ip: 192.168.178.54
|
||||
@@ -63,7 +64,9 @@ rocky_podman_packages:
|
||||
host_packages:
|
||||
- cockpit
|
||||
- nfs-utils
|
||||
- policycoreutils
|
||||
- policycoreutils-python-utils
|
||||
- python3-libselinux
|
||||
- samba
|
||||
- samba-client
|
||||
- samba-common-tools
|
||||
@@ -82,6 +85,7 @@ atlas_nfs_exports:
|
||||
|
||||
atlas_samba_share_name: Archive
|
||||
atlas_samba_workgroup: WORKGROUP
|
||||
atlas_samba_encryption: required
|
||||
# Append any pre-existing laptop Unix account here and keep its Samba password in Vault.
|
||||
atlas_samba_accounts:
|
||||
- username: "{{ atlas_admin_username }}"
|
||||
@@ -91,12 +95,10 @@ atlas_samba_valid_users: "{{ atlas_samba_accounts | map(attribute='username') |
|
||||
atlas_immich_db_password: "{{ vault_atlas_immich_db_password | default('') }}"
|
||||
|
||||
atlas_firewalld_rich_rules:
|
||||
- 'rule family="ipv4" source address="{{ atlas_lan_subnet }}" service name="ssh" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_lan_subnet }}" service name="cockpit" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_aegis_ip }}" service name="nfs" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_lan_subnet }}" service name="samba" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_lan_subnet }}" service name="http" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_lan_subnet }}" service name="https" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_lan_subnet }}" port port="22" protocol="tcp" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_lan_subnet }}" port port="9090" protocol="tcp" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_aegis_ip }}" port port="2049" protocol="tcp" accept'
|
||||
- 'rule family="ipv4" source address="{{ atlas_lan_subnet }}" port port="445" protocol="tcp" accept'
|
||||
|
||||
host_enabled_services:
|
||||
- sshd
|
||||
|
||||
@@ -11,6 +11,8 @@ atlas_admin_uid: 1000
|
||||
atlas_admin_gid: 1000
|
||||
atlas_admin_ssh_keys: []
|
||||
atlas_admin_password_hash: "!"
|
||||
# Local forwarding permits an administrator to tunnel a private service without allowing remote forwards.
|
||||
atlas_ssh_allow_tcp_forwarding: local
|
||||
|
||||
atlas_immich_username: immich
|
||||
atlas_immich_group: immich
|
||||
@@ -24,6 +26,25 @@ atlas_lan_subnet: CHANGEME_LAN_SUBNET
|
||||
atlas_aegis_ip: CHANGEME_AEGIS_IP
|
||||
atlas_manage_firewall: false
|
||||
atlas_firewalld_zone: public
|
||||
atlas_hardening_sysctls:
|
||||
net.ipv4.conf.all.accept_redirects: "0"
|
||||
net.ipv4.conf.default.accept_redirects: "0"
|
||||
net.ipv4.conf.all.send_redirects: "0"
|
||||
net.ipv4.conf.default.send_redirects: "0"
|
||||
net.ipv4.conf.all.accept_source_route: "0"
|
||||
net.ipv4.conf.default.accept_source_route: "0"
|
||||
net.ipv4.conf.all.log_martians: "1"
|
||||
net.ipv4.conf.default.log_martians: "1"
|
||||
net.ipv4.conf.all.rp_filter: "2"
|
||||
net.ipv4.conf.default.rp_filter: "2"
|
||||
net.ipv4.tcp_syncookies: "1"
|
||||
net.ipv4.icmp_echo_ignore_broadcasts: "1"
|
||||
net.ipv4.icmp_ignore_bogus_error_responses: "1"
|
||||
net.ipv4.ip_forward: "0"
|
||||
net.ipv6.conf.all.accept_redirects: "0"
|
||||
net.ipv6.conf.default.accept_redirects: "0"
|
||||
net.ipv6.conf.all.accept_source_route: "0"
|
||||
net.ipv6.conf.default.accept_source_route: "0"
|
||||
atlas_zfs_pool: CHANGEME_ZFS_POOL
|
||||
atlas_zfs_dataset_work: work
|
||||
atlas_zfs_dataset_archive: archive
|
||||
@@ -72,6 +93,8 @@ atlas_nfs_exports:
|
||||
- "anongid={{ atlas_immich_gid }}"
|
||||
atlas_samba_share_name: Archive
|
||||
atlas_samba_workgroup: WORKGROUP
|
||||
# Keep encryption mandatory unless a verified client-compatibility exception is explicitly required.
|
||||
atlas_samba_encryption: required
|
||||
atlas_samba_valid_users: []
|
||||
atlas_samba_accounts: []
|
||||
atlas_samba_password_marker_dir: /var/lib/samba/private/ansible-passwords
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
- atlas_admin_username != 'CHANGEME_ATLAS_ADMIN'
|
||||
- (atlas_admin_ssh_keys | default([])) | length > 0
|
||||
- atlas_admin_password_hash not in ['', '!', '*']
|
||||
- atlas_ssh_allow_tcp_forwarding in ['no', 'yes', 'local', 'remote', 'all']
|
||||
- "'wheel' not in atlas_immich_supplementary_groups"
|
||||
fail_msg: >-
|
||||
Define atlas_admin_username, vault_atlas_authorized_ssh_keys and
|
||||
@@ -149,6 +150,18 @@
|
||||
- "'pubkeyauthentication yes' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'passwordauthentication no' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'kbdinteractiveauthentication no' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'authenticationmethods publickey' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'x11forwarding no' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "('allowtcpforwarding ' ~ atlas_ssh_allow_tcp_forwarding) in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'allowagentforwarding no' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'gatewayports no' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'permittunnel no' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'permituserenvironment no' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'maxauthtries 3' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'logingracetime 30' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'clientaliveinterval 300' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'clientalivecountmax 2' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "'loglevel VERBOSE' in atlas_sshd_effective_configuration.stdout_lines"
|
||||
- "('allowusers ' ~ atlas_admin_username) in atlas_sshd_effective_configuration.stdout_lines"
|
||||
fail_msg: The effective Atlas SSH configuration does not match the required hardening.
|
||||
when: not ansible_check_mode
|
||||
|
||||
45
ansible/roles/profile_atlas/tasks/hardening.yml
Normal file
45
ansible/roles/profile_atlas/tasks/hardening.yml
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
- name: Enforce targeted SELinux on Atlas
|
||||
tags: [atlas, hardening, security]
|
||||
ansible.posix.selinux:
|
||||
policy: targeted
|
||||
state: enforcing
|
||||
update_kernel_param: true
|
||||
register: atlas_selinux_enforcement
|
||||
|
||||
- name: Report when Atlas requires a reboot for SELinux enforcement
|
||||
tags: [atlas, hardening, security]
|
||||
ansible.builtin.debug:
|
||||
msg: Reboot Atlas before relying on SELinux enforcement.
|
||||
when: atlas_selinux_enforcement.reboot_required | default(false)
|
||||
|
||||
- name: Apply Atlas network-kernel hardening
|
||||
tags: [atlas, hardening, security]
|
||||
ansible.posix.sysctl:
|
||||
name: "{{ item.key }}"
|
||||
value: "{{ item.value }}"
|
||||
state: present
|
||||
sysctl_set: true
|
||||
reload: true
|
||||
loop: "{{ atlas_hardening_sysctls | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item.key }}={{ item.value }}"
|
||||
|
||||
- name: Read active Atlas SELinux mode
|
||||
tags: [atlas, hardening, security]
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- getenforce
|
||||
register: atlas_selinux_mode
|
||||
changed_when: false
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Require active SELinux enforcement on Atlas
|
||||
tags: [atlas, hardening, security]
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- atlas_selinux_mode.stdout == 'Enforcing'
|
||||
fail_msg: >-
|
||||
Atlas SELinux is not enforcing. Reboot if requested by the preceding
|
||||
SELinux task, then rerun the hardening role before enabling services.
|
||||
when: not ansible_check_mode
|
||||
@@ -5,6 +5,9 @@
|
||||
- name: Import Atlas 45Drives tasks
|
||||
ansible.builtin.import_tasks: cockpit.yml
|
||||
|
||||
- name: Import Atlas network hardening tasks
|
||||
ansible.builtin.import_tasks: hardening.yml
|
||||
|
||||
- name: Import Atlas pool bootstrap tasks
|
||||
ansible.builtin.import_tasks: pool.yml
|
||||
|
||||
|
||||
@@ -1,4 +1,50 @@
|
||||
---
|
||||
- name: Require completed Atlas firewall placeholders
|
||||
tags: [atlas, sharing, services]
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- atlas_lan_subnet != 'CHANGEME_LAN_SUBNET'
|
||||
- atlas_aegis_ip != 'CHANGEME_AEGIS_IP'
|
||||
- atlas_firewalld_zone | length > 0
|
||||
- ansible_facts.default_ipv4.interface | default('') | length > 0
|
||||
fail_msg: Replace the Atlas LAN, Aegis and firewall-zone placeholders.
|
||||
when: atlas_manage_firewall | bool
|
||||
|
||||
- name: Apply Atlas firewalld rich rules
|
||||
tags: [atlas, sharing, services]
|
||||
ansible.posix.firewalld:
|
||||
rich_rule: "{{ item }}"
|
||||
permanent: true
|
||||
immediate: true
|
||||
state: enabled
|
||||
zone: "{{ atlas_firewalld_zone }}"
|
||||
loop: "{{ atlas_firewalld_rich_rules }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: atlas_manage_firewall | bool
|
||||
|
||||
- name: Assign primary Atlas LAN interface to managed firewalld zone
|
||||
tags: [atlas, sharing, services]
|
||||
ansible.posix.firewalld:
|
||||
interface: "{{ ansible_facts.default_ipv4.interface }}"
|
||||
zone: "{{ atlas_firewalld_zone }}"
|
||||
state: enabled
|
||||
permanent: true
|
||||
immediate: true
|
||||
when: atlas_manage_firewall | bool
|
||||
|
||||
- name: Remove unrestricted Atlas services from firewalld zone
|
||||
tags: [atlas, sharing, services]
|
||||
ansible.posix.firewalld:
|
||||
service: "{{ item }}"
|
||||
permanent: true
|
||||
immediate: true
|
||||
state: disabled
|
||||
zone: "{{ atlas_firewalld_zone }}"
|
||||
loop: "{{ atlas_firewalld_restricted_services }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: atlas_manage_firewall | bool
|
||||
|
||||
- name: Render Atlas NFS exports
|
||||
tags: [atlas, sharing]
|
||||
ansible.builtin.template:
|
||||
@@ -10,19 +56,6 @@
|
||||
notify: Reload NFS exports
|
||||
when: atlas_manage_sharing | bool
|
||||
|
||||
- name: Enable Atlas file-sharing services
|
||||
tags: [atlas, sharing, services]
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop:
|
||||
- nfs-server.service
|
||||
- smb.service
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: atlas_manage_sharing | bool
|
||||
|
||||
- name: Configure Atlas NFSv4-only service
|
||||
tags: [atlas, sharing]
|
||||
ansible.builtin.template:
|
||||
@@ -99,6 +132,7 @@
|
||||
tags: [atlas, sharing]
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- atlas_samba_encryption in ['required', 'desired']
|
||||
- atlas_samba_accounts | length > 0
|
||||
- >-
|
||||
atlas_samba_accounts | map(attribute='username') | list
|
||||
@@ -131,38 +165,87 @@
|
||||
no_log: true
|
||||
when: atlas_manage_sharing | bool
|
||||
|
||||
- name: Require completed Atlas firewall placeholders
|
||||
- name: Enable Atlas file-sharing services
|
||||
tags: [atlas, sharing, services]
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop:
|
||||
- nfs-server.service
|
||||
- smb.service
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: atlas_manage_sharing | bool
|
||||
|
||||
- name: Gather effective Atlas firewalld zone configuration
|
||||
tags: [atlas, sharing, services, security]
|
||||
ansible.posix.firewalld_info:
|
||||
zones:
|
||||
- "{{ atlas_firewalld_zone }}"
|
||||
register: atlas_firewalld_info
|
||||
when:
|
||||
- atlas_manage_firewall | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Verify effective Atlas firewalld restrictions
|
||||
tags: [atlas, sharing, services, security]
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- atlas_lan_subnet != 'CHANGEME_LAN_SUBNET'
|
||||
- atlas_aegis_ip != 'CHANGEME_AEGIS_IP'
|
||||
- atlas_firewalld_zone | length > 0
|
||||
fail_msg: Replace the Atlas LAN, Aegis and firewall-zone placeholders.
|
||||
when: atlas_manage_firewall | bool
|
||||
- atlas_firewalld_zone in atlas_firewalld_info.firewalld_info.zones
|
||||
- >-
|
||||
ansible_facts.default_ipv4.interface
|
||||
in atlas_firewalld_info.firewalld_info.zones[atlas_firewalld_zone].interfaces
|
||||
- >-
|
||||
atlas_firewalld_restricted_services
|
||||
| intersect(atlas_firewalld_info.firewalld_info.zones[atlas_firewalld_zone].services)
|
||||
| length == 0
|
||||
fail_msg: >-
|
||||
The effective Atlas firewalld zone does not restrict the primary LAN
|
||||
interface and unmanaged service exposure as declared.
|
||||
when:
|
||||
- atlas_manage_firewall | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Apply Atlas firewalld rich rules
|
||||
tags: [atlas, sharing, services]
|
||||
ansible.posix.firewalld:
|
||||
rich_rule: "{{ item }}"
|
||||
permanent: true
|
||||
immediate: true
|
||||
state: enabled
|
||||
zone: "{{ atlas_firewalld_zone }}"
|
||||
loop: "{{ atlas_firewalld_rich_rules }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: atlas_manage_firewall | bool
|
||||
- name: Apply pending Atlas sharing handlers before verification
|
||||
tags: [atlas, sharing, services, security]
|
||||
ansible.builtin.meta: flush_handlers
|
||||
when:
|
||||
- atlas_manage_sharing | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Remove unrestricted Atlas services from firewalld zone
|
||||
tags: [atlas, sharing, services]
|
||||
ansible.posix.firewalld:
|
||||
service: "{{ item }}"
|
||||
permanent: true
|
||||
immediate: true
|
||||
state: disabled
|
||||
zone: "{{ atlas_firewalld_zone }}"
|
||||
loop: "{{ atlas_firewalld_restricted_services }}"
|
||||
- name: Read Atlas file-sharing service state
|
||||
tags: [atlas, sharing, services, security]
|
||||
ansible.builtin.service_facts:
|
||||
when:
|
||||
- atlas_manage_sharing | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Require active Atlas file-sharing services
|
||||
tags: [atlas, sharing, services, security]
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_facts.services['nfs-server.service'] is defined
|
||||
- ansible_facts.services['nfs-server.service'].state == 'running'
|
||||
- ansible_facts.services['smb.service'] is defined
|
||||
- ansible_facts.services['smb.service'].state == 'running'
|
||||
fail_msg: Atlas NFSv4 or SMB3 did not start after its managed configuration was applied.
|
||||
when:
|
||||
- atlas_manage_sharing | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Require Atlas file-sharing TCP listeners
|
||||
tags: [atlas, sharing, services, security]
|
||||
ansible.builtin.wait_for:
|
||||
host: 127.0.0.1
|
||||
port: "{{ item }}"
|
||||
state: started
|
||||
timeout: 15
|
||||
loop:
|
||||
- 2049
|
||||
- 445
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: atlas_manage_firewall | bool
|
||||
label: "{{ item }}/tcp"
|
||||
when:
|
||||
- atlas_manage_sharing | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
@@ -3,4 +3,16 @@ PermitRootLogin no
|
||||
PubkeyAuthentication yes
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
AuthenticationMethods publickey
|
||||
X11Forwarding no
|
||||
AllowTcpForwarding {{ atlas_ssh_allow_tcp_forwarding }}
|
||||
AllowAgentForwarding no
|
||||
GatewayPorts no
|
||||
PermitTunnel no
|
||||
PermitUserEnvironment no
|
||||
MaxAuthTries 3
|
||||
LoginGraceTime 30
|
||||
ClientAliveInterval 300
|
||||
ClientAliveCountMax 2
|
||||
LogLevel VERBOSE
|
||||
AllowUsers {{ atlas_admin_username }}
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
security = user
|
||||
map to guest = Never
|
||||
server min protocol = SMB3
|
||||
server signing = mandatory
|
||||
smb encrypt = {{ atlas_samba_encryption }}
|
||||
disable netbios = yes
|
||||
smb ports = 445
|
||||
hosts allow = {{ atlas_lan_subnet }}
|
||||
include = registry
|
||||
|
||||
|
||||
@@ -6,13 +6,16 @@ Description=Atlas rootless Syncthing backend
|
||||
ContainerName=atlas-syncthing
|
||||
Image={{ backend_phase1_syncthing_image }}
|
||||
HostName=atlas-syncthing
|
||||
Network=host
|
||||
UserNS=keep-id
|
||||
User={{ backend_phase1_uid }}
|
||||
Group={{ backend_phase1_gid }}
|
||||
PublishPort={{ backend_phase1_wireguard_address }}:{{ backend_phase1_syncthing_gui_port }}:{{ backend_phase1_syncthing_gui_port }}
|
||||
PublishPort={{ backend_phase1_wireguard_address }}:{{ backend_phase1_syncthing_transfer_port }}:{{ backend_phase1_syncthing_transfer_port }}
|
||||
PublishPort={{ backend_phase1_wireguard_address }}:{{ backend_phase1_syncthing_transfer_port }}:{{ backend_phase1_syncthing_transfer_port }}/udp
|
||||
PublishPort={{ backend_phase1_wireguard_address }}:{{ backend_phase1_syncthing_discovery_port }}:{{ backend_phase1_syncthing_discovery_port }}/udp
|
||||
Environment=HOME=/var/syncthing
|
||||
Environment=STHOMEDIR=/var/syncthing/config
|
||||
Environment=STGUIADDRESS={{ backend_phase1_wireguard_address }}:{{ backend_phase1_syncthing_gui_port }}
|
||||
Environment=STGUIADDRESS=0.0.0.0:{{ backend_phase1_syncthing_gui_port }}
|
||||
Environment=TZ={{ backend_phase1_timezone }}
|
||||
Volume={{ backend_phase1_syncthing_root }}:/var/syncthing:Z
|
||||
NoNewPrivileges=true
|
||||
|
||||
Reference in New Issue
Block a user