--- # ============================================================================= # Minecraft Podman Deployment - Main Tasks # ============================================================================= # This role deploys a Minecraft server using Podman on Fedora # with systemd integration for service management # ----------------------------------------------------------------------------- # System Preparation # ----------------------------------------------------------------------------- - name: System Preparation block: - name: Update DNF cache ansible.builtin.dnf: update_cache: true state: present tags: [install, packages] - name: Install required packages ansible.builtin.dnf: name: - podman - podman-plugins # Podman plugins (Netavark, etc.) - fuse-overlayfs # Required for rootless storage - slirp4netns # Required for rootless networking - systemd-container # Systemd integration - firewalld - python3-firewall # For ansible firewalld module - python3-podman # For ansible podman modules - tar # For backups - gzip # For compressed backups - curl # For health checks state: present tags: [install, packages] - name: Ensure Podman is installed ansible.builtin.command: podman --version register: podman_version changed_when: false tags: [install, verify] - name: Display Podman version ansible.builtin.debug: msg: "Podman {{ podman_version.stdout }} installed" tags: [install, verify] tags: [install, packages] # ----------------------------------------------------------------------------- # User and Permissions # ----------------------------------------------------------------------------- - name: User Configuration block: - name: Create minecraft system user ansible.builtin.user: name: "{{ minecraft_user }}" system: true shell: /bin/bash home: "{{ paths.base_dir }}" create_home: false comment: "Minecraft Server User" when: minecraft_user != "root" tags: [install, user] - name: Configure subuid for rootless podman ansible.builtin.lineinfile: path: /etc/subuid line: "{{ minecraft_user }}:100000:65536" regexp: "^{{ minecraft_user }}:" state: present create: true mode: "0644" when: minecraft_user != "root" tags: [install, user] - name: Configure subgid for rootless podman ansible.builtin.lineinfile: path: /etc/subgid line: "{{ minecraft_user }}:100000:65536" regexp: "^{{ minecraft_user }}:" state: present create: true mode: "0644" when: minecraft_user != "root" tags: [install, user] - name: Create user config directory for podman ansible.builtin.file: path: "{{ paths.base_dir }}/.config/containers" state: directory owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0755" when: minecraft_user != "root" tags: [install, user] - name: Create user local share for podman storage ansible.builtin.file: path: "{{ paths.base_dir }}/.local/share/containers" state: directory owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0755" when: minecraft_user != "root" tags: [install, user] - name: Ensure systemd lingering is enabled for user ansible.builtin.command: "loginctl enable-linger {{ minecraft_user }}" changed_when: false when: minecraft_user != "root" tags: [install, user] tags: [install] # ----------------------------------------------------------------------------- # Directory Structure # ----------------------------------------------------------------------------- - name: Directory Setup block: - name: Create base directories ansible.builtin.file: path: "{{ item }}" state: directory owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0755" loop: - "{{ paths.base_dir }}" - "{{ paths.data_dir }}" - "{{ paths.backup_dir }}" - "{{ paths.data_dir }}/logs" - "{{ paths.data_dir }}/world" tags: [install, directories] - name: Create Containerfile directory ansible.builtin.file: path: "{{ paths.base_dir }}/container" state: directory owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0755" tags: [install, container] tags: [install] # ----------------------------------------------------------------------------- # Container Build (if using custom Containerfile) # ----------------------------------------------------------------------------- - name: Container Build block: - name: Copy Containerfile ansible.builtin.template: src: Containerfile.j2 dest: "{{ paths.base_dir }}/container/Containerfile" owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0644" when: minecraft.use_custom_container | default(false) tags: [install, container] - name: Build custom Minecraft container image containers.podman.podman_image: name: "{{ minecraft.custom_image_name | default('minecraft-custom') }}" build: path: "{{ paths.base_dir }}/container/" file: Containerfile tag: "{{ minecraft.version }}" state: present when: minecraft.use_custom_container | default(false) tags: [install, container] tags: [install] # ----------------------------------------------------------------------------- # Server Configuration # ----------------------------------------------------------------------------- - name: Server Configuration block: - name: Deploy server.properties ansible.builtin.template: src: server.properties.j2 dest: "{{ paths.data_dir }}/server.properties" owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0644" notify: restart minecraft tags: [config] - name: Deploy eula.txt ansible.builtin.copy: content: "eula=true\n" dest: "{{ paths.data_dir }}/eula.txt" owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0644" tags: [config] - name: Deploy environment variables ansible.builtin.template: src: minecraft.env.j2 dest: "{{ paths.base_dir }}/minecraft.env" owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0600" notify: restart minecraft tags: [config] - name: Deploy JVM options file ansible.builtin.template: src: jvm.opts.j2 dest: "{{ paths.data_dir }}/jvm.opts" owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0644" when: minecraft.jvm_opts_file | default(false) notify: restart minecraft tags: [config] tags: [config] # ----------------------------------------------------------------------------- # Firewall Configuration # ----------------------------------------------------------------------------- - name: Firewall Configuration block: - name: Ensure firewalld is running ansible.builtin.systemd: name: firewalld state: started enabled: true tags: [firewall] - name: Open Minecraft port ansible.posix.firewalld: port: "{{ minecraft.port }}/tcp" permanent: true immediate: true state: enabled tags: [firewall] - name: Open RCON port ansible.posix.firewalld: port: "{{ minecraft.rcon_port }}/tcp" permanent: true immediate: true state: enabled when: minecraft.rcon_enabled tags: [firewall] - name: Open additional firewall ports ansible.posix.firewalld: port: "{{ item }}" permanent: true immediate: true state: enabled loop: "{{ firewall.additional_ports | default([]) }}" tags: [firewall] tags: [firewall] # ----------------------------------------------------------------------------- # Systemd Service # ----------------------------------------------------------------------------- - name: Systemd Service Configuration block: - name: Deploy systemd service unit ansible.builtin.template: src: minecraft.service.j2 dest: "{{ paths.systemd_dir }}/{{ minecraft.server_name }}.service" owner: root group: root mode: "0644" notify: - reload systemd - restart minecraft tags: [service] - name: Reload systemd daemon ansible.builtin.systemd: daemon_reload: true tags: [service] - name: Enable and start Minecraft service ansible.builtin.systemd: name: "{{ minecraft.server_name }}.service" state: started enabled: true tags: [service] tags: [service] # ----------------------------------------------------------------------------- # Backup Configuration # ----------------------------------------------------------------------------- - name: Backup Configuration block: - name: Deploy backup script ansible.builtin.template: src: backup.sh.j2 dest: "{{ paths.base_dir }}/backup.sh" owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0755" when: backup.enabled tags: [backup] - name: Deploy restore script ansible.builtin.template: src: restore.sh.j2 dest: "{{ paths.base_dir }}/restore.sh" owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0755" when: backup.enabled tags: [backup] - name: Create systemd timer for backups ansible.builtin.template: src: minecraft-backup.timer.j2 dest: "{{ paths.systemd_dir }}/{{ minecraft.server_name }}-backup.timer" owner: root group: root mode: "0644" when: backup.enabled tags: [backup] - name: Create systemd service for backups ansible.builtin.template: src: minecraft-backup.service.j2 dest: "{{ paths.systemd_dir }}/{{ minecraft.server_name }}-backup.service" owner: root group: root mode: "0644" when: backup.enabled tags: [backup] - name: Enable backup timer ansible.builtin.systemd: name: "{{ minecraft.server_name }}-backup.timer" state: started enabled: true when: backup.enabled tags: [backup] tags: [backup] # ----------------------------------------------------------------------------- # Health Check # ----------------------------------------------------------------------------- - name: Health Check Configuration block: - name: Deploy health check script ansible.builtin.template: src: health-check.sh.j2 dest: "{{ paths.base_dir }}/health-check.sh" owner: "{{ minecraft_user }}" group: "{{ minecraft_user }}" mode: "0755" when: monitoring.enabled tags: [monitoring] - name: Create systemd timer for health checks ansible.builtin.template: src: minecraft-health.timer.j2 dest: "{{ paths.systemd_dir }}/{{ minecraft.server_name }}-health.timer" owner: root group: root mode: "0644" when: monitoring.enabled tags: [monitoring] - name: Create systemd service for health checks ansible.builtin.template: src: minecraft-health.service.j2 dest: "{{ paths.systemd_dir }}/{{ minecraft.server_name }}-health.service" owner: root group: root mode: "0644" when: monitoring.enabled tags: [monitoring] - name: Enable health check timer ansible.builtin.systemd: name: "{{ minecraft.server_name }}-health.timer" state: started enabled: true when: monitoring.enabled tags: [monitoring] tags: [monitoring] # ----------------------------------------------------------------------------- # Final Verification # ----------------------------------------------------------------------------- - name: Final Verification block: - name: Wait for Minecraft server to start ansible.builtin.uri: url: "http://localhost:{{ minecraft.port }}" return_content: false status_code: [401, 200] # Minecraft responds to HTTP with 401 register: server_check retries: 30 delay: 5 until: server_check.status in [401, 200] ignore_errors: true tags: [verify] - name: Check service status ansible.builtin.systemd: name: "{{ minecraft.server_name }}.service" register: service_status tags: [verify] - name: Display verification results ansible.builtin.debug: msg: | Server Status: {{ 'Running' if service_status.status.ActiveState == 'active' else 'Stopped' }} Service: {{ service_status.status.SubState }} Port {{ minecraft.port }}: {{ 'Open' if server_check is succeeded else 'Closed' }} tags: [verify] tags: [verify]