Initial template repository
🎬 ARR Suite Template Bootstrap - Complete Media Automation Stack Features: - 16 production services (Prowlarr, Sonarr, Radarr, Plex, etc.) - One-command Ansible deployment - VPN-protected downloads via Gluetun - Tailscale secure access - Production-ready security (UFW, Fail2Ban) - Automated backups and monitoring - Comprehensive documentation Ready for customization and deployment to any VPS. Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
185
tasks/security_setup.yml
Normal file
185
tasks/security_setup.yml
Normal file
@@ -0,0 +1,185 @@
|
||||
---
|
||||
# Security and firewall configuration tasks
|
||||
|
||||
- name: Configure SSH security
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
backup: yes
|
||||
loop:
|
||||
- { regexp: '^#?PermitRootLogin', line: 'PermitRootLogin yes' }
|
||||
- { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication {{ "yes" if not ssh_key_based_auth else "no" }}' }
|
||||
- { regexp: '^#?PubkeyAuthentication', line: 'PubkeyAuthentication yes' }
|
||||
- { regexp: '^#?Port', line: 'Port {{ ssh_port }}' }
|
||||
- { regexp: '^#?MaxAuthTries', line: 'MaxAuthTries 3' }
|
||||
- { regexp: '^#?ClientAliveInterval', line: 'ClientAliveInterval 300' }
|
||||
- { regexp: '^#?ClientAliveCountMax', line: 'ClientAliveCountMax 2' }
|
||||
notify: restart sshd
|
||||
tags: ['ssh_security']
|
||||
|
||||
- name: Configure fail2ban for SSH
|
||||
template:
|
||||
src: jail.local.j2
|
||||
dest: /etc/fail2ban/jail.local
|
||||
backup: yes
|
||||
notify: restart fail2ban
|
||||
tags: ['fail2ban']
|
||||
|
||||
- name: Configure fail2ban filter for Plex
|
||||
template:
|
||||
src: plex-fail2ban-filter.j2
|
||||
dest: /etc/fail2ban/filter.d/plex.conf
|
||||
backup: yes
|
||||
when: plex_public_access | default(false)
|
||||
notify: restart fail2ban
|
||||
tags: ['fail2ban', 'plex']
|
||||
|
||||
- name: Start and enable fail2ban
|
||||
systemd:
|
||||
name: fail2ban
|
||||
state: started
|
||||
enabled: yes
|
||||
tags: ['fail2ban']
|
||||
|
||||
- name: Reset UFW to defaults
|
||||
ufw:
|
||||
state: reset
|
||||
when: ufw_enabled
|
||||
tags: ['firewall']
|
||||
|
||||
- name: Configure UFW default policies
|
||||
ufw:
|
||||
direction: "{{ item.direction }}"
|
||||
policy: "{{ item.policy }}"
|
||||
loop:
|
||||
- { direction: 'incoming', policy: "{{ ufw_default_policy_incoming }}" }
|
||||
- { direction: 'outgoing', policy: "{{ ufw_default_policy_outgoing }}" }
|
||||
when: ufw_enabled
|
||||
tags: ['firewall']
|
||||
|
||||
- name: Allow SSH through UFW
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
when: ufw_enabled
|
||||
tags: ['firewall']
|
||||
|
||||
- name: Check if Tailscale is installed
|
||||
command: which tailscale
|
||||
register: tailscale_check
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
when: tailscale_enabled
|
||||
tags: ['tailscale']
|
||||
|
||||
- name: Install Tailscale
|
||||
shell: |
|
||||
curl -fsSL https://tailscale.com/install.sh | sh
|
||||
when: tailscale_enabled and tailscale_check.rc != 0
|
||||
tags: ['tailscale']
|
||||
|
||||
- name: Get Tailscale interface information
|
||||
shell: ip addr show {{ tailscale_interface }} | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1
|
||||
register: tailscale_ip
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
when: tailscale_enabled
|
||||
tags: ['tailscale']
|
||||
|
||||
- name: Allow Tailscale interface through UFW
|
||||
ufw:
|
||||
rule: allow
|
||||
interface: "{{ tailscale_interface }}"
|
||||
direction: in
|
||||
when: ufw_enabled and tailscale_enabled
|
||||
tags: ['firewall', 'tailscale']
|
||||
|
||||
- name: Allow Arrs services from Tailscale network
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ item.value }}"
|
||||
proto: tcp
|
||||
src: "{{ tailscale_ip.stdout | regex_replace('\\.[0-9]+$', '.0/24') }}"
|
||||
loop: "{{ ports | dict2items }}"
|
||||
when: ufw_enabled and tailscale_enabled and tailscale_ip.stdout != ""
|
||||
tags: ['firewall', 'tailscale']
|
||||
|
||||
- name: Allow Docker bridge network communication
|
||||
ufw:
|
||||
rule: allow
|
||||
from_ip: "{{ docker_network_subnet }}"
|
||||
to_ip: "{{ docker_network_subnet }}"
|
||||
when: ufw_enabled
|
||||
tags: ['firewall', 'docker']
|
||||
|
||||
- name: Allow Plex Media Server through UFW (public access)
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ item.port }}"
|
||||
proto: "{{ item.proto }}"
|
||||
comment: "{{ item.comment }}"
|
||||
loop:
|
||||
- { port: "32400", proto: "tcp", comment: "Plex Media Server" }
|
||||
- { port: "3005", proto: "tcp", comment: "Plex Home Theater via Plex Companion" }
|
||||
- { port: "8324", proto: "tcp", comment: "Plex for Roku via Plex Companion" }
|
||||
- { port: "32469", proto: "tcp", comment: "Plex DLNA Server" }
|
||||
- { port: "1900", proto: "udp", comment: "Plex DLNA Server" }
|
||||
- { port: "32410", proto: "udp", comment: "Plex GDM network discovery" }
|
||||
- { port: "32412", proto: "udp", comment: "Plex GDM network discovery" }
|
||||
- { port: "32413", proto: "udp", comment: "Plex GDM network discovery" }
|
||||
- { port: "32414", proto: "udp", comment: "Plex GDM network discovery" }
|
||||
when: ufw_enabled and plex_public_access | default(false)
|
||||
tags: ['firewall', 'plex']
|
||||
|
||||
- name: Enable UFW
|
||||
ufw:
|
||||
state: enabled
|
||||
when: ufw_enabled
|
||||
tags: ['firewall']
|
||||
|
||||
- name: Configure Docker security options
|
||||
template:
|
||||
src: docker-security.json.j2
|
||||
dest: /etc/docker/seccomp-profile.json
|
||||
mode: '0644'
|
||||
notify: restart docker
|
||||
tags: ['docker_security']
|
||||
|
||||
- name: Create AppArmor profile for Docker containers
|
||||
template:
|
||||
src: docker-apparmor.j2
|
||||
dest: /etc/apparmor.d/docker-arrs
|
||||
mode: '0644'
|
||||
notify: reload apparmor
|
||||
tags: ['apparmor']
|
||||
|
||||
- name: Set secure file permissions
|
||||
file:
|
||||
path: "{{ item.path }}"
|
||||
mode: "{{ item.mode }}"
|
||||
owner: "{{ item.owner | default('root') }}"
|
||||
group: "{{ item.group | default('root') }}"
|
||||
loop:
|
||||
- { path: '/etc/ssh/sshd_config', mode: '0600' }
|
||||
- { path: '/etc/fail2ban/jail.local', mode: '0644' }
|
||||
- { path: '/etc/docker', mode: '0755' }
|
||||
tags: ['file_permissions']
|
||||
|
||||
- name: Configure log monitoring
|
||||
template:
|
||||
src: rsyslog-docker.conf.j2
|
||||
dest: /etc/rsyslog.d/30-docker.conf
|
||||
mode: '0644'
|
||||
notify: restart rsyslog
|
||||
tags: ['logging']
|
||||
|
||||
- name: Create security audit script
|
||||
template:
|
||||
src: security-audit.sh.j2
|
||||
dest: "{{ docker_root }}/scripts/security-audit.sh"
|
||||
owner: "{{ docker_user }}"
|
||||
group: "{{ docker_group }}"
|
||||
mode: '0755'
|
||||
tags: ['security_audit']
|
||||
Reference in New Issue
Block a user