Files
Internal-apps/ansible-playbook.yml
2026-09-15 15:27:59 -06:00

385 lines
13 KiB
YAML
Executable File

---
- hosts: internal-apps
become: true
vars_files:
- ./vars.yml
tasks:
- name: Update Packages
ansible.builtin.dnf:
update_cache: yes
- name: Install Packages
ansible.builtin.dnf:
name:
- vim
- podman
- fail2ban
- python3-libdnf5
state: present
- name: Create directories
file:
path: "{{ item }}"
state: directory
mode: '0755'
loop: "{{ directories }}"
- name: Create Jellyfin directories
file:
path: "{{ item }}"
state: directory
mode: '0777'
loop: "{{ directories_jellyfin }}"
- name: Create internal podman network
containers.podman.podman_network:
name: npm_internal
ip_range: 10.10.0.128/25
subnet: 10.10.0.0/24
gateway: 10.10.0.1
state: present
- name: Ensure WireGuard kernel module is loaded
ansible.builtin.modprobe:
name: wireguard
state: present
- name: Persist WireGuard kernel module across reboots
ansible.builtin.copy:
dest: /etc/modules-load.d/wg-easy.conf
content: |
wireguard
mode: '0644'
- name: Enable IP forwarding on host
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: '1'
sysctl_set: true
state: present
reload: true
- name: Enable source valid mark on host
ansible.posix.sysctl:
name: net.ipv4.conf.all.src_valid_mark
value: '1'
sysctl_set: true
state: present
reload: true
- name: Raise vm.max_map_count for Wazuh indexer
ansible.posix.sysctl:
name: vm.max_map_count
value: '262144'
sysctl_set: true
state: present
reload: true
- name: pull images
containers.podman.podman_image:
name: "{{ item }}"
loop: "{{ images }}"
- name: Deploy Nginx Proxy Manager
containers.podman.podman_container:
image: "docker.io/jc21/nginx-proxy-manager:latest"
name: npm
restart_policy: always
recreate: true
state: started
ports:
- "80:80"
- "81:81"
- "443:443"
volumes:
- "/opt/apps/npm:/data:z"
- "/opt/apps/letsencrypt:/etc/letsencrypt:z"
network:
- npm_internal
ip: '10.10.0.19'
- name: Deploy Gitea
containers.podman.podman_container:
image: docker.gitea.com/gitea:nightly
name: gitea
env:
USER_UID: 1000
USER_GID: 1000
restart_policy: always
recreate: true
state: started
volumes:
- /opt/apps/gitea:/data:z
- /usr/share/zoneinfo/America/Denver:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
network:
- npm_internal
ip: '10.10.0.25'
ports:
# - "3000:3000"
- "222:22"
- name: Deploy Jellyfin
containers.podman.podman_container:
image: lscr.io/linuxserver/jellyfin:latest
name: jellyfin
env:
USER_UID: 1000
USER_GID: 1000
JELLYFIN_PublishedServerUrl: http://jellyfin.boxswapper.io
restart_policy: always
recreate: true
state: started
volumes:
- /opt/apps/jellyfin/config:/config:z
- /opt/apps/jellyfin/tvseries:/data/tvshows:z
- /opt/apps/jellyfin/movies:/data/movies:z
- /usr/share/zoneinfo/America/Denver:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
network:
- npm_internal
ip: '10.10.0.30'
# ports:
# - 8096:8096
# - 8920:8920 #optional
# - 7359:7359/udp #optional
# - 1900:1900/udp #optional
# WireGuard Easy VPN — deployed on npm_internal behind NPM
# After first deploy, you MUST add NAT hooks in the wg-easy UI:
# 1. Open http://10.10.0.36:51821 in a browser
# 2. Log in with the username/password from vars.yml
# 3. Go to the "Hooks" tab
# 4. PostUp — paste this EXACTLY:
# nft add table inet wg_table; nft add chain inet wg_table prerouting { type nat hook prerouting priority 100 \; }; nft add chain inet wg_table postrouting { type nat hook postrouting priority 100 \; }; nft add rule inet wg_table postrouting ip saddr {{ipv4Cidr}} oifname {{device}} masquerade; nft add rule inet wg_table postrouting ip6 saddr {{ipv6Cidr}} oifname {{device}} masquerade; nft add chain inet wg_table input { type filter hook input priority 0 \; policy accept \; }; nft add rule inet wg_table input udp dport {{port}} accept; nft add rule inet wg_table input tcp dport {{uiPort}} accept; nft add chain inet wg_table forward { type filter hook forward priority 0 \; policy accept \; }; nft add rule inet wg_table forward iifname "wg0" accept; nft add rule inet wg_table forward oifname "wg0" accept;
# 5. PostDown — paste this EXACTLY:
# nft delete table inet wg_table
# 6. Click Save and restart the container
# These hooks enable VPN clients to reach your app containers (10.10.0.0/24)
- name: Deploy WireGuard Easy (wg-easy)
containers.podman.podman_container:
name: wg-easy
image: "{{ wireguard_image }}"
restart_policy: always
recreate: true
state: started
env:
INIT_ENABLED: "true"
INIT_USERNAME: "{{ wireguard_ui_username }}"
INIT_PASSWORD: "{{ wireguard_ui_password }}"
INIT_HOST: "{{ wireguard_host }}"
INIT_PORT: "{{ wireguard_port }}"
INIT_DNS: "{{ wireguard_default_dns }}"
INIT_IPV4_CIDR: "{{ wireguard_cidr }}"
INIT_IPV6_CIDR: "{{ wireguard_ipv6_cidr }}"
INIT_ALLOWED_IPS: "{{ wireguard_allowed_ips }}"
PORT: "{{ wireguard_ui_port }}"
INSECURE: "true"
DISABLE_VERSION_CHECK: "true"
ports:
- "{{ wireguard_port }}:{{ wireguard_port }}/udp"
- "{{ wireguard_ui_port }}:{{ wireguard_ui_port }}/tcp"
volumes:
- "/opt/apps/wireguard:/etc/wireguard:z"
- "/lib/modules:/lib/modules:ro"
cap_add:
- NET_ADMIN
- SYS_MODULE
- NET_RAW
sysctl:
net.ipv4.ip_forward: "1"
net.ipv4.conf.all.src_valid_mark: "1"
network:
- npm_internal
ip: '{{ wireguard_ip }}'
# Wazuh SIEM (single-node: indexer + manager + dashboard) on npm_internal
# Dashboard is NOT exposed on host ports — NPM proxies wazuh.boxswapper.io to https://10.10.0.40:5601
# DNS record must be grey-cloud (Cloudflare 523 lesson from vpn.boxswapper.io), cert via NPM
# Config is copied from ./wazuh-docker/config before first deploy
- name: Copy Wazuh config files to host
ansible.builtin.copy:
src: ./wazuh-docker/config/
dest: /opt/apps/wazuh/config/
owner: root
group: root
mode: preserve
force: true
- name: Generate Wazuh certificates
ansible.builtin.command: podman run --rm -e CERT_TOOL_VERSION=4.14 -v /opt/apps/wazuh/config/certs.yml:/config/certs.yml:z -v /opt/apps/wazuh/config/wazuh_indexer_ssl_certs/:/certificates:z docker.io/wazuh/wazuh-certs-generator:0.0.3
args:
creates: /opt/apps/wazuh/config/wazuh_indexer_ssl_certs/root-ca.pem
- name: Copy root CA as manager root CA
ansible.builtin.copy:
src: /opt/apps/wazuh/config/wazuh_indexer_ssl_certs/root-ca.pem
dest: /opt/apps/wazuh/config/wazuh_indexer_ssl_certs/root-ca-manager.pem
remote_src: true
force: false
- name: Deploy Wazuh indexer
containers.podman.podman_container:
name: wazuh.indexer
image: "docker.io/wazuh/wazuh-indexer:{{ wazuh_version }}"
hostname: wazuh.indexer
restart_policy: always
recreate: true
state: started
env:
OPENSEARCH_JAVA_OPTS: "-Xms1g -Xmx1g"
ulimit:
- "memlock=-1:-1"
- "nofile=65536:65536"
volumes:
- "wazuh-indexer-data:/var/lib/wazuh-indexer"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/config/certs/root-ca.pem:z"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.key:z"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.pem:z"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/config/certs/admin.pem:z"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/config/certs/admin-key.pem:z"
- "/opt/apps/wazuh/config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/config/opensearch.yml:z"
- "/opt/apps/wazuh/config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/config/opensearch-security/internal_users.yml:z"
network:
- npm_internal
ip: '{{ wazuh_indexer_ip }}'
- name: Wait for Wazuh indexer to be ready
ansible.builtin.wait_for:
host: '{{ wazuh_indexer_ip }}'
port: 9200
delay: 10
timeout: 300
- name: Deploy Wazuh manager
containers.podman.podman_container:
name: wazuh.manager
image: "docker.io/wazuh/wazuh-manager:{{ wazuh_version }}"
hostname: wazuh.manager
restart_policy: always
recreate: true
state: started
env:
INDEXER_URL: "https://wazuh.indexer:9200"
INDEXER_USERNAME: "admin"
INDEXER_PASSWORD: "SecretPassword"
FILEBEAT_SSL_VERIFICATION_MODE: "full"
SSL_CERTIFICATE_AUTHORITIES: "/etc/ssl/root-ca.pem"
SSL_CERTIFICATE: "/etc/ssl/filebeat.pem"
SSL_KEY: "/etc/ssl/filebeat.key"
API_USERNAME: "wazuh-wui"
API_PASSWORD: "MyS3cr37P450r.*-"
ulimit:
- "memlock=-1:-1"
- "nofile=655360:655360"
ports:
- "1514:1514"
- "1515:1515"
- "514:514/udp"
- "55000:55000"
volumes:
- "wazuh_api_configuration:/var/ossec/api/configuration"
- "wazuh_etc:/var/ossec/etc"
- "wazuh_logs:/var/ossec/logs"
- "wazuh_queue:/var/ossec/queue"
- "wazuh_var_multigroups:/var/ossec/var/multigroups"
- "wazuh_active_response:/var/ossec/active-response/bin"
- "wazuh_wodles:/var/ossec/wodles"
- "filebeat_etc:/etc/filebeat"
- "filebeat_var:/var/lib/filebeat"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem:z"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem:z"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key:z"
- "/opt/apps/wazuh/config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf:z"
network:
- npm_internal
ip: '{{ wazuh_manager_ip }}'
- name: Deploy Wazuh dashboard
containers.podman.podman_container:
name: wazuh.dashboard
image: "docker.io/wazuh/wazuh-dashboard:{{ wazuh_version }}"
hostname: wazuh.dashboard
restart_policy: always
recreate: true
state: started
env:
INDEXER_USERNAME: "admin"
INDEXER_PASSWORD: "SecretPassword"
WAZUH_API_URL: "https://wazuh.manager"
DASHBOARD_USERNAME: "kibanaserver"
DASHBOARD_PASSWORD: "kibanaserver"
API_USERNAME: "wazuh-wui"
API_PASSWORD: "MyS3cr37P450r.*-"
volumes:
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem:z"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem:z"
- "/opt/apps/wazuh/config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem:z"
- "/opt/apps/wazuh/config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml:z"
- "/opt/apps/wazuh/config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml:z"
- "wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config"
- "wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom"
network:
- npm_internal
ip: '{{ wazuh_dashboard_ip }}'
#----N8N deployment, no GPU avail for deployment ------#
# - name: Deploy n8n
# containers.podman.podman_container:
# image: docker.n8n.io/n8nio/n8n
# name: n8n
# env:
# N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: true
# N8N_RUNNERS_ENABLED: true
# restart_policy: always
# recreate: true
# state: started
# volumes:
# - /opt/apps/n8n/data:/home/node/.n8n:z
# - /opt/apps/n8n/files:/files:z
# - /usr/share/zoneinfo/America/Denver:/etc/timezone:ro
# - /etc/localtime:/etc/localtime:ro
# network:
# - npm_internal
# ip: '10.10.0.35'
# # ports:
# # - 5678:5678