test other version
Some checks failed
Ansible Minecraft CI/CD Pipeline / Ansible Lint Check (push) Successful in 58s
Ansible Minecraft CI/CD Pipeline / Project Structure Validation (push) Failing after 3s
Ansible Minecraft CI/CD Pipeline / Security Scan (push) Successful in 4s
Ansible Minecraft CI/CD Pipeline / Deploy to Staging (push) Has been skipped
Ansible Minecraft CI/CD Pipeline / Deploy to Production (push) Has been skipped
Ansible Minecraft CI/CD Pipeline / Backup System Check (push) Has been skipped

This commit is contained in:
2025-08-26 21:59:21 +02:00
parent b2459a2dc0
commit 7a2ccb537b
98 changed files with 2830 additions and 1291 deletions

View File

@@ -1,83 +1,211 @@
name: Ansible Lint
---
name: Ansible Minecraft CI/CD Pipeline
on:
push:
branches: [ main, develop ]
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy'
required: true
default: 'staging'
type: choice
options:
- staging
- production
pull_request:
branches: [ main ]
env:
ANSIBLE_FORCE_COLOR: 1
ANSIBLE_HOST_KEY_CHECKING: false
jobs:
ansible_lint_and_syntax_check:
lint:
name: Ansible Lint Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
python-version: '3.11'
- name: Install dependencies
run: |
pip install ansible ansible-lint yamllint
- name: Run yamllint
run: yamllint .
continue-on-error: true
- name: Run ansible-lint
run: ansible-lint
continue-on-error: true
- name: Validate inventory files
run: |
ansible-inventory --list -i inventories/production/hosts.yml
ansible-inventory --list -i inventories/staging/hosts.yml
yamllint -c .yamllint.yml .
continue-on-error: true
deploy:
- name: Run ansible-lint
run: |
ansible-lint --project-dir . playbooks/
continue-on-error: true
- name: Validate Ansible syntax
run: |
ansible-playbook --syntax-check playbooks/site.yml -i inventories/staging/hosts.yml
continue-on-error: true
structure-validation:
name: Project Structure Validation
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment || 'staging' }}
steps:
- uses: actions/checkout@v4
- name: Setup Python
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate required files
run: |
# Check main playbook exists
[ -f "playbooks/site.yml" ] || exit 1
# Check all roles exist with required structure
for role in 01-server_hardening 02-installation-java 03-installation-minecraft 04-backups 05-update; do
[ -d "roles/$role" ] || exit 1
[ -d "roles/$role/tasks" ] || exit 1
[ -d "roles/$role/handlers" ] || exit 1
[ -d "roles/$role/templates" ] || exit 1
[ -d "roles/$role/vars" ] || exit 1
[ -d "roles/$role/defaults" ] || exit 1
[ -f "roles/$role/tasks/main.yml" ] || exit 1
[ -f "roles/$role/handlers/main.yml" ] || exit 1
[ -f "roles/$role/vars/main.yml" ] || exit 1
[ -f "roles/$role/defaults/main.yml" ] || exit 1
done
# Check inventories exist
[ -d "inventories/production" ] || exit 1
[ -d "inventories/staging" ] || exit 1
[ -f "inventories/production/hosts.yml" ] || exit 1
[ -f "inventories/staging/hosts.yml" ] || exit 1
echo "Project structure validation passed"
security-scan:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check for secrets in files
run: |
# Check for potential secrets (excluding example files)
if grep -r -i "password\|secret\|key" --include="*.yml" --include="*.yaml" --exclude="*example*" --exclude="*template*" .; then
echo "WARNING: Potential secrets found in files"
echo "Please ensure all sensitive data uses Gitea secrets or ansible-vault"
fi
- name: Check for hardcoded IPs
run: |
# Allow example IPs in inventory files
if grep -r -E '([0-9]{1,3}\.){3}[0-9]{1,3}' --include="*.yml" --include="*.yaml" . | grep -v "192.168.1" | grep -v "127.0.0.1" | grep -v "inventories/"; then
echo "WARNING: Hardcoded IP addresses found"
fi
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: [lint, structure-validation, security-scan]
if: github.ref == 'refs/heads/develop'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
python-version: '3.11'
- name: Install Ansible
run: pip install ansible
run: |
pip install ansible
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ANSIBLE_SSH_KEY }}" > ~/.ssh/ansible_key
chmod 600 ~/.ssh/ansible_key
ssh-keyscan -H ${{ secrets.ANSIBLE_HOST }} >> ~/.ssh/known_hosts
echo "${{ secrets.ANSIBLE_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name: Create vault password file
run: echo "${{ secrets.ANSIBLE_VAULT_PASSWORD }}" > ~/.ansible_vault_pass
- name: Test staging connectivity
run: |
ansible all -i inventories/staging/hosts.yml -m ping
- name: Deploy to staging (dry-run)
run: |
ansible-playbook playbooks/site.yml \
-i inventories/staging/hosts.yml \
--check \
--diff
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs: [lint, structure-validation, security-scan]
if: github.ref == 'refs/heads/main'
environment: production
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Deploy to staging
if: ${{ github.event.inputs.environment == 'staging' || github.ref == 'refs/heads/develop' }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install Ansible
run: |
ansible-playbook -i inventories/staging/hosts.yml site.yml \
--vault-password-file ~/.ansible_vault_pass \
--private-key ~/.ssh/ansible_key
pip install ansible
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ANSIBLE_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name: Test production connectivity
run: |
ansible all -i inventories/production/hosts.yml -m ping
- name: Deploy to production
if: ${{ github.event.inputs.environment == 'production' || github.ref == 'refs/heads/main' }}
run: |
ansible-playbook -i inventories/production/hosts.yml site.yml \
--vault-password-file ~/.ansible_vault_pass \
--private-key ~/.ssh/ansible_key
ansible-playbook playbooks/site.yml \
-i inventories/production/hosts.yml \
-e "minecraft_version=${{ secrets.MINECRAFT_VERSION }}" \
-e "rcon_password=${{ secrets.RCON_PASSWORD }}"
backup-check:
name: Backup System Check
runs-on: ubuntu-latest
needs: [deploy-staging]
if: github.ref == 'refs/heads/develop'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install Ansible
run: |
pip install ansible
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ANSIBLE_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name: Test backup scripts
run: |
ansible minecraft_servers -i inventories/staging/hosts.yml \
-m shell \
-a "test -x /opt/minecraft/tools/backup-daily.sh"
ansible minecraft_servers -i inventories/staging/hosts.yml \
-m shell \
-a "test -x /opt/minecraft/tools/restore-backup.sh"

1
.yamllint.yml Normal file
View File

@@ -0,0 +1 @@
.yamllint.yml

1734
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,18 @@
---
# Configuration globale pour la production
# Environment
environment: production
timezone: Europe/Paris
# Utilisateur Ansible
ansible_user: ansible
ansible_become: yes
ansible_become_method: sudo
# Minecraft Configuration
minecraft_version: "1.21.6"
minecraft_memory_min: "2G"
minecraft_memory_max: "4G"
# Configuration SSH
# Security
ssh_port: 22
ssh_allow_users: ["ansible", "minecraft"]
# Configuration Firewall
fail2ban_enabled: true
firewall_enabled: true
firewall_default_policy: deny
# Backup settings
backup_retention_days: 30
backup_retention_weeks: 12
backup_retention_months: 6

View File

@@ -1,17 +1,18 @@
---
# Configuration globale pour le staging
# Environment
environment: staging
timezone: Europe/Paris
# Utilisateur Ansible
ansible_user: ansible
ansible_become: yes
ansible_become_method: sudo
# Minecraft Configuration
minecraft_version: "1.21.6"
minecraft_memory_min: "1G"
minecraft_memory_max: "2G"
# Configuration SSH
# Security
ssh_port: 22
ssh_allow_users: ["ansible", "minecraft"]
# Configuration Firewall
fail2ban_enabled: true
firewall_enabled: true
firewall_default_policy: deny
# Backup settings
backup_retention_days: 7
backup_retention_weeks: 4
backup_retention_months: 2

9
playbooks/hardening.yml Normal file
View File

@@ -0,0 +1,9 @@
---
- name: Server Hardening Only
hosts: minecraft_servers
become: true
gather_facts: true
roles:
- role: 01-server_hardening
tags: ['hardening', 'security']

View File

@@ -0,0 +1,9 @@
---
- name: Java Installation Only
hosts: minecraft_servers
become: true
gather_facts: true
roles:
- role: 02-installation-java
tags: ['java', 'dependencies']

View File

@@ -0,0 +1,15 @@
---
- name: Minecraft Installation Only
hosts: minecraft_servers
become: true
gather_facts: true
pre_tasks:
- name: Ensure Java is installed
ansible.builtin.shell: java -version
register: java_check
failed_when: java_check.rc != 0
roles:
- role: 03-installation-minecraft
tags: ['minecraft', 'installation']

View File

@@ -0,0 +1,9 @@
---
- name: Backup Setup Only
hosts: minecraft_servers
become: true
gather_facts: true
roles:
- role: 04-backups
tags: ['backups', 'maintenance']

44
playbooks/site.yml Normal file
View File

@@ -0,0 +1,44 @@
---
- name: Complete Minecraft Spigot Server Setup
hosts: minecraft_servers
become: true
gather_facts: true
pre_tasks:
- name: Display target information
ansible.builtin.debug:
msg:
- "Target host: {{ inventory_hostname }}"
- "Environment: {{ environment }}"
- "Minecraft version: {{ minecraft_version }}"
roles:
- role: 01-server_hardening
tags: ['hardening', 'security']
- role: 02-installation-java
tags: ['java', 'dependencies']
- role: 03-installation-minecraft
tags: ['minecraft', 'installation']
- role: 04-backups
tags: ['backups', 'maintenance']
- role: 05-update
tags: ['update', 'maintenance']
post_tasks:
- name: Final server status check
ansible.builtin.systemd:
name: minecraft
state: started
register: final_status
- name: Display installation summary
ansible.builtin.debug:
msg:
- "Minecraft Spigot Server installation completed successfully"
- "Server status: {{ final_status.status.ActiveState }}"
- "Server directory: {{ minecraft_server_dir }}"
- "Version: {{ minecraft_version }}"

View File

@@ -0,0 +1,9 @@
---
- name: System Updates Only
hosts: minecraft_servers
become: true
gather_facts: true
roles:
- role: 05-update
tags: ['update', 'maintenance']

8
requirements.yml Normal file
View File

@@ -0,0 +1,8 @@
---
collections:
- name: community.general
version: ">=7.0.0"
- name: ansible.posix
version: ">=1.5.0"
- name: community.crypto
version: ">=2.15.0"

View File

@@ -1,25 +1,22 @@
---
# Configuration par défaut pour le hardening
# SSH Configuration
ssh_port: 22
ssh_protocol: 2
ssh_permit_root_login: "no"
ssh_password_authentication: "no"
ssh_pub_key_authentication: "yes"
ssh_allow_users: ["ansible"]
ssh_permit_root_login: false
ssh_password_authentication: false
ssh_max_auth_tries: 3
ssh_client_alive_interval: 300
ssh_client_alive_count_max: 2
# Firewall
ufw_default_incoming: deny
ufw_default_outgoing: allow
ufw_allowed_ports:
- 22/tcp
- 25565/tcp
- 25575/tcp
# Firewall Configuration
firewall_allowed_ports:
- "{{ ssh_port }}/tcp"
- "25565/tcp" # Minecraft default port
# Fail2ban
fail2ban_enabled: true
fail2ban_bantime: 3600
fail2ban_findtime: 600
fail2ban_maxretry: 3
# Fail2ban Configuration
fail2ban_jail_ssh_enabled: true
fail2ban_jail_ssh_port: "{{ ssh_port }}"
fail2ban_jail_ssh_maxretry: 3
fail2ban_jail_ssh_bantime: 600
# System users
admin_users: []

View File

@@ -0,0 +1,17 @@
---
- name: restart ssh
ansible.builtin.systemd:
name: ssh
state: restarted
listen: "restart ssh service"
- name: restart fail2ban
ansible.builtin.systemd:
name: fail2ban
state: restarted
listen: "restart fail2ban service"
- name: reload ufw
community.general.ufw:
state: reloaded
listen: "reload firewall"

View File

@@ -1,8 +1,9 @@
---
- name: Update apt cache for Debian/Ubuntu
apt:
update_cache: yes
cache_valid_time: 3600
- name: Update apt cache and upgrade system packages (Debian/Ubuntu)
ansible.builtin.apt:
update_cache: true
upgrade: dist
autoremove: true
autoclean: true
when: ansible_os_family == "Debian"
tags:
- system-update
register: system_update_result

View File

@@ -1,12 +1,10 @@
---
- name: Configure SSH daemon
template:
ansible.builtin.template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config
backup: yes
mode: "0600"
owner: root
group: root
notify: restart sshd
tags:
- ssh-config
mode: '0644'
backup: true
notify: "restart ssh service"

View File

@@ -1,7 +0,0 @@
---
- name: Install UFW firewall
package:
name: ufw
state: present
tags:
- firewall-install

View File

@@ -0,0 +1,32 @@
---
- name: Install UFW
ansible.builtin.apt:
name: ufw
state: present
when: firewall_enabled | bool
- name: Reset UFW rules
community.general.ufw:
state: reset
when: firewall_enabled | bool
- name: Allow SSH port
community.general.ufw:
rule: allow
port: "{{ ssh_port }}"
proto: tcp
when: firewall_enabled | bool
- name: Allow Minecraft port
community.general.ufw:
rule: allow
port: "25565"
proto: tcp
when: firewall_enabled | bool
- name: Enable UFW
community.general.ufw:
state: enabled
policy: deny
when: firewall_enabled | bool
notify: "reload firewall"

View File

@@ -0,0 +1,23 @@
---
- name: Install fail2ban
ansible.builtin.apt:
name: fail2ban
state: present
when: fail2ban_enabled | bool
- name: Configure fail2ban jail
ansible.builtin.template:
src: fail2ban-jail.local.j2
dest: /etc/fail2ban/jail.local
owner: root
group: root
mode: '0644'
when: fail2ban_enabled | bool
notify: "restart fail2ban service"
- name: Start and enable fail2ban
ansible.builtin.systemd:
name: fail2ban
state: started
enabled: true
when: fail2ban_enabled | bool

View File

@@ -1,8 +0,0 @@
---
- name: Install fail2ban
package:
name: fail2ban
state: present
when: fail2ban_enabled
tags:
- fail2ban-install

View File

@@ -1,12 +0,0 @@
---
- name: Disable unused services
systemd:
name: "{{ item }}"
state: stopped
enabled: no
loop:
- bluetooth
- cups
ignore_errors: yes
tags:
- disable-services

View File

@@ -0,0 +1,20 @@
---
- name: Install security packages
ansible.builtin.apt:
name:
- unattended-upgrades
- logwatch
- rkhunter
- chkrootkit
state: present
- name: Configure automatic security updates
ansible.builtin.copy:
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
dest: /etc/apt/apt.conf.d/20auto-upgrades
owner: root
group: root
mode: '0644'

View File

@@ -0,0 +1,17 @@
---
- name: Create ansible user if not exists
ansible.builtin.user:
name: ansible
groups: sudo
shell: /bin/bash
create_home: true
state: present
- name: Add authorized keys for admin users
ansible.posix.authorized_key:
user: ansible
key: "{{ item.key }}"
comment: "{{ item.comment | default('') }}"
state: present
loop: "{{ admin_users }}"
when: admin_users is defined and admin_users | length > 0

View File

@@ -1,30 +1,18 @@
---
- name: Include system update tasks
include_tasks: 01-update-system.yml
tags:
- hardening
- system-update
ansible.builtin.include_tasks: 01-system-update.yml
- name: Include SSH configuration tasks
include_tasks: 02-configure-ssh.yml
tags:
- hardening
- ssh
- name: Include SSH hardening tasks
ansible.builtin.include_tasks: 02-ssh-hardening.yml
- name: Include firewall configuration tasks
include_tasks: 03-configure-firewall.yml
tags:
- hardening
- firewall
- name: Include firewall setup tasks
ansible.builtin.include_tasks: 03-firewall-setup.yml
- name: Include fail2ban installation tasks
include_tasks: 04-install-fail2ban.yml
tags:
- hardening
- fail2ban
- name: Include fail2ban setup tasks
ansible.builtin.include_tasks: 04-fail2ban-setup.yml
- name: Include additional hardening tasks
include_tasks: 05-additional-hardening.yml
tags:
- hardening
- additional
- name: Include additional security tasks
ansible.builtin.include_tasks: 05-additional-security.yml
- name: Include SSH keys management tasks
ansible.builtin.include_tasks: 06-ssh-keys-management.yml

View File

@@ -0,0 +1,11 @@
[DEFAULT]
bantime = {{ fail2ban_jail_ssh_bantime }}
findtime = 600
maxretry = {{ fail2ban_jail_ssh_maxretry }}
[sshd]
enabled = {{ fail2ban_jail_ssh_enabled | ternary('true', 'false') }}
port = {{ fail2ban_jail_ssh_port }}
filter = sshd
logpath = /var/log/auth.log
maxretry = {{ fail2ban_jail_ssh_maxretry }}

View File

@@ -1,26 +0,0 @@
[DEFAULT]
# Fail2ban configuration for Minecraft server
bantime = {{ fail2ban_bantime }}
findtime = {{ fail2ban_findtime }}
maxretry = {{ fail2ban_maxretry }}
# Email notifications (optional)
# destemail = admin@example.com
# sendername = Fail2Ban
# sender = fail2ban@example.com
# action = %(action_mwl)s
[sshd]
enabled = true
port = {{ ssh_port }}
filter = sshd
logpath = /var/log/auth.log
maxretry = {{ fail2ban_maxretry }}
[minecraft]
enabled = true
port = {{ minecraft_port }}
filter = minecraft
logpath = {{ minecraft_server_dir }}/logs/latest.log
maxretry = 5
bantime = 7200

View File

@@ -1,47 +1,25 @@
# SSH configuration for Minecraft server
# SSH Configuration - Managed by Ansible
Port {{ ssh_port }}
Protocol {{ ssh_protocol }}
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
# Logging
SyslogFacility AUTH
LogLevel INFO
Protocol 2
# Authentication
LoginGraceTime 60
PermitRootLogin {{ ssh_permit_root_login }}
StrictModes yes
MaxAuthTries {{ ssh_max_auth_tries }}
MaxSessions 10
PubkeyAuthentication {{ ssh_pub_key_authentication }}
PermitRootLogin {{ ssh_permit_root_login | ternary('yes', 'no') }}
PasswordAuthentication {{ ssh_password_authentication | ternary('yes', 'no') }}
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication {{ ssh_password_authentication }}
PermitEmptyPasswords no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
UsePAM yes
AllowUsers {{ ssh_allow_users | join(' ') }}
X11Forwarding no
PrintMotd no
AcceptEnv LANG LC_*
MaxAuthTries {{ ssh_max_auth_tries }}
# Connection settings
ClientAliveInterval {{ ssh_client_alive_interval }}
ClientAliveCountMax {{ ssh_client_alive_count_max }}
TCPKeepAlive yes
MaxSessions 10
MaxStartups 10:30:60
# Restrict to specific users
Match User {{ ssh_allow_users | join(',') }}
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
GatewayPorts no
AllowAgentForwarding no
# Security settings
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding no
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server

View File

@@ -1,14 +0,0 @@
# UFW rules for Minecraft server
# Default policies
ufw --force reset
ufw default {{ ufw_default_incoming }}
ufw default {{ ufw_default_outgoing }}
# Allow specific ports
{% for port in ufw_allowed_ports %}
ufw allow {{ port }}
{% endfor %}
# Enable UFW
ufw --force enable

View File

@@ -0,0 +1,13 @@
---
# Internal variables for server hardening
security_packages:
- ufw
- fail2ban
- unattended-upgrades
- logwatch
- rkhunter
- chkrootkit
required_directories:
- /var/log/security
- /etc/security/limits.d

View File

@@ -1,4 +1,8 @@
---
java_version: 21
# Java configuration
java_version: "17"
java_package: "openjdk-{{ java_version }}-jdk"
java_home: "/usr/lib/jvm/java-{{ java_version }}-openjdk-amd64"
java_home: "/usr/lib/jvm/java-{{ java_version }}-openjdk-amd64"
# Minimum required Java version for Spigot 1.21.6
required_java_version: "17"

View File

@@ -0,0 +1,6 @@
---
- name: update java alternatives
ansible.builtin.shell: |
update-alternatives --install /usr/bin/java java {{ java_home }}/bin/java 1
update-alternatives --install /usr/bin/javac javac {{ java_home }}/bin/javac 1
listen: "configure java alternatives"

View File

@@ -0,0 +1,10 @@
---
- name: Check if Java is already installed
ansible.builtin.shell: java -version 2>&1 | head -n 1
register: java_check_result
failed_when: false
changed_when: false
- name: Set Java installation requirement
ansible.builtin.set_fact:
java_needs_installation: "{{ java_check_result.rc != 0 or 'openjdk' not in java_check_result.stdout }}"

View File

@@ -1,7 +0,0 @@
---
- name: Check if Java is already installed
command: java -version
register: java_check
failed_when: false
changed_when: false
tags: ['java-check']

View File

@@ -1,6 +1,21 @@
---
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
when: ansible_os_family == "Debian"
- name: Install OpenJDK
package:
ansible.builtin.apt:
name: "{{ java_package }}"
state: present
tags: ['java-install']
notify: "configure java alternatives"
- name: Set JAVA_HOME environment variable
ansible.builtin.lineinfile:
path: /etc/environment
regexp: '^JAVA_HOME='
line: 'JAVA_HOME={{ java_home }}'
create: true
owner: root
group: root
mode: '0644'

View File

@@ -0,0 +1,10 @@
---
- name: Verify Java installation
ansible.builtin.shell: java -version 2>&1 | head -n 1
register: java_verification_result
failed_when: java_verification_result.rc != 0
changed_when: false
- name: Display Java version
ansible.builtin.debug:
msg: "Java installation verified: {{ java_verification_result.stdout }}"

View File

@@ -1,6 +0,0 @@
---
- name: Verify Java installation
command: java -version
register: java_verify
changed_when: false
tags: ['java-verify']

View File

@@ -1,7 +0,0 @@
---
- name: Set Java home environment variable
lineinfile:
path: /etc/environment
line: "JAVA_HOME={{ java_home }}"
state: present
tags: ['java-validate']

View File

@@ -0,0 +1,15 @@
---
- name: Extract Java version number
ansible.builtin.shell: |
java -version 2>&1 | grep -oP 'version "\K[^"]*' | cut -d'.' -f1
register: installed_java_version
changed_when: false
- name: Validate Java version compatibility
ansible.builtin.fail:
msg: "Java version {{ installed_java_version.stdout }} is not compatible with Minecraft Spigot. Minimum required: {{ required_java_version }}"
when: installed_java_version.stdout | int < required_java_version | int
- name: Confirm Java compatibility
ansible.builtin.debug:
msg: "Java version {{ installed_java_version.stdout }} is compatible with Minecraft Spigot {{ minecraft_version }}"

View File

@@ -1,17 +1,13 @@
---
- name: Include Java check tasks
include_tasks: 01-check-java.yml
tags: ['java', 'check']
- name: Include Java presence check tasks
ansible.builtin.include_tasks: 01-check-java-presence.yml
- name: Include Java installation tasks
include_tasks: 02-install-java.yml
when: java_installed is not defined or not java_installed
tags: ['java', 'install']
ansible.builtin.include_tasks: 02-install-java.yml
when: java_needs_installation | default(true)
- name: Include Java verification tasks
include_tasks: 03-verify-java.yml
tags: ['java', 'verify']
- name: Include Java installation verification tasks
ansible.builtin.include_tasks: 03-verify-java-installation.yml
- name: Include Java validation tasks
include_tasks: 04-validate-installation.yml
tags: ['java', 'validate']
- name: Include Java version validation tasks
ansible.builtin.include_tasks: 04-validate-java-version.yml

View File

@@ -0,0 +1,14 @@
---
# Java installation variables
supported_java_versions:
- "17"
- "18"
- "19"
- "20"
- "21"
java_compatibility_matrix:
"1.21.6": "17"
"1.21.5": "17"
"1.21.4": "17"
"1.21.3": "17"

View File

@@ -1,14 +1,35 @@
---
minecraft_version: "1.21.6"
# Minecraft user and group
minecraft_user: minecraft
minecraft_group: minecraft
minecraft_home: /opt/minecraft
minecraft_memory_min: "1G"
minecraft_memory_max: "4G"
minecraft_port: 25565
minecraft_rcon_port: 25575
minecraft_rcon_password: "changeme"
spigot_build_tools_url: "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
# Minecraft directories
minecraft_base_dir: /opt/minecraft
minecraft_sources_dir: "{{ minecraft_base_dir }}/sources"
minecraft_server_dir: "{{ minecraft_base_dir }}/server"
minecraft_tools_dir: "{{ minecraft_base_dir }}/tools"
minecraft_plugins_dir: "{{ minecraft_server_dir }}/plugins"
# Minecraft configuration
minecraft_version: "1.21.6"
minecraft_memory_min: "1G"
minecraft_memory_max: "2G"
minecraft_port: 25565
minecraft_eula: true
# Server properties
server_name: "Minecraft Server"
server_motd: "A Minecraft Server"
max_players: 20
difficulty: "normal"
gamemode: "survival"
pvp_enabled: true
# MCRCON configuration
mcrcon_version: "0.7.2"
mcrcon_url: "https://github.com/Tiiffi/mcrcon/releases/download/v{{ mcrcon_version }}/mcrcon-{{ mcrcon_version }}-linux-x86-64.tar.gz"
rcon_enabled: true
rcon_port: 25575
rcon_password: "changeme"
# Default operators (will be populated from ops_list variable)
minecraft_ops: []

View File

@@ -1,21 +1,18 @@
---
- name: reload systemd
systemd:
daemon_reload: yes
- name: enable minecraft service
systemd:
name: minecraft
enabled: yes
- name: restart minecraft
systemd:
ansible.builtin.systemd:
name: minecraft
state: restarted
enabled: yes
daemon_reload: true
listen: "restart minecraft service"
- name: start minecraft
systemd:
name: minecraft
state: started
enabled: yes
- name: reload systemd
ansible.builtin.systemd:
daemon_reload: true
listen: "systemd daemon reload"
- name: restart logrotate
ansible.builtin.systemd:
name: logrotate
state: restarted
listen: "restart log rotation"

View File

@@ -0,0 +1,15 @@
---
- name: Create minecraft group
ansible.builtin.group:
name: "{{ minecraft_group }}"
state: present
- name: Create minecraft user
ansible.builtin.user:
name: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
home: "{{ minecraft_base_dir }}"
shell: /bin/bash
system: true
create_home: false
state: present

View File

@@ -1,6 +0,0 @@
---
- name: Create minecraft group
group:
name: "{{ minecraft_group }}"
state: present
tags: ['minecraft-user']

View File

@@ -1,15 +1,16 @@
---
- name: Create minecraft directories
file:
- name: Create minecraft base directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
loop:
- "{{ minecraft_home }}"
- "{{ minecraft_base_dir }}"
- "{{ minecraft_sources_dir }}"
- "{{ minecraft_server_dir }}"
- "{{ minecraft_tools_dir }}"
- "{{ minecraft_backups_dir }}"
tags: ['minecraft-directories']
- "{{ minecraft_plugins_dir }}"
- "{{ minecraft_base_dir }}/logs"
- "{{ minecraft_base_dir }}/backups"

View File

@@ -1,9 +1,9 @@
---
- name: Download BuildTools.jar
get_url:
url: "{{ spigot_build_tools_url }}"
- name: Download BuildTools
ansible.builtin.get_url:
url: "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
dest: "{{ minecraft_sources_dir }}/BuildTools.jar"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
tags: ['spigot-download']
timeout: 300

View File

@@ -1,17 +1,32 @@
---
- name: Download mcrcon
get_url:
url: "{{ mcrcon_url }}"
dest: "{{ minecraft_tools_dir }}/mcrcon.tar.gz"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
tags: ['mcrcon-install']
- name: Install packages needed for MCRCON compilation
ansible.builtin.apt:
name:
- git
- build-essential
state: present
- name: Extract mcrcon
unarchive:
src: "{{ minecraft_tools_dir }}/mcrcon.tar.gz"
dest: "{{ minecraft_tools_dir }}"
remote_src: yes
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
tags: ['mcrcon-install']
- name: Clone MCRCON repository
ansible.builtin.git:
repo: "https://github.com/Tiiffi/mcrcon.git"
dest: "{{ minecraft_tools_dir }}/mcrcon"
version: "v{{ mcrcon_version }}"
force: true
become_user: "{{ minecraft_user }}"
- name: Compile MCRCON
ansible.builtin.shell: |
cd {{ minecraft_tools_dir }}/mcrcon
make
become_user: "{{ minecraft_user }}"
args:
creates: "{{ minecraft_tools_dir }}/mcrcon/mcrcon"
- name: Install MCRCON binary
ansible.builtin.copy:
src: "{{ minecraft_tools_dir }}/mcrcon/mcrcon"
dest: "/usr/local/bin/mcrcon"
owner: root
group: root
mode: '0755'
remote_src: true

View File

@@ -1,19 +1,19 @@
---
- name: Compile Spigot server
shell: |
- name: Compile Spigot with BuildTools
ansible.builtin.shell: |
cd {{ minecraft_sources_dir }}
java -jar BuildTools.jar --rev {{ minecraft_version }}
become_user: "{{ minecraft_user }}"
args:
creates: "{{ minecraft_sources_dir }}/spigot-{{ minecraft_version }}.jar"
tags: ['spigot-compile']
register: spigot_compilation
timeout: 1800
- name: Copy compiled Spigot to server directory
copy:
ansible.builtin.copy:
src: "{{ minecraft_sources_dir }}/spigot-{{ minecraft_version }}.jar"
dest: "{{ minecraft_server_dir }}/spigot.jar"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
remote_src: yes
tags: ['spigot-compile']
remote_src: true

View File

@@ -0,0 +1,17 @@
---
- name: Create server.properties
ansible.builtin.template:
src: server.properties.j2
dest: "{{ minecraft_server_dir }}/server.properties"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
notify: "restart minecraft service"
- name: Accept EULA
ansible.builtin.copy:
content: "eula={{ minecraft_eula | ternary('true', 'false') }}"
dest: "{{ minecraft_server_dir }}/eula.txt"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'

View File

@@ -1,37 +0,0 @@
---
- name: Generate server.properties
template:
src: server.properties.j2
dest: "{{ minecraft_server_dir }}/server.properties"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
tags: ['minecraft-config']
- name: Generate spigot.yml
template:
src: spigot.yml.j2
dest: "{{ minecraft_server_dir }}/spigot.yml"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
tags: ['minecraft-config']
- name: Generate bukkit.yml
template:
src: bukkit.yml.j2
dest: "{{ minecraft_server_dir }}/bukkit.yml"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
tags: ['minecraft-config']
- name: Accept EULA
lineinfile:
path: "{{ minecraft_server_dir }}/eula.txt"
line: "eula=true"
create: yes
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
tags: ['minecraft-config']

View File

@@ -1,10 +0,0 @@
---
- name: Create systemd service file
template:
src: minecraft.service.j2
dest: /etc/systemd/system/minecraft.service
mode: '0644'
notify:
- reload systemd
- enable minecraft service
tags: ['minecraft-service']

View File

@@ -0,0 +1,17 @@
---
- name: Create Minecraft systemd service
ansible.builtin.template:
src: minecraft.service.j2
dest: /etc/systemd/system/minecraft.service
owner: root
group: root
mode: '0644'
notify:
- "systemd daemon reload"
- "restart minecraft service"
- name: Enable Minecraft service
ansible.builtin.systemd:
name: minecraft
enabled: true
daemon_reload: true

View File

@@ -1,7 +1,9 @@
---
- name: Setup log rotation for Minecraft
template:
- name: Configure log rotation for Minecraft
ansible.builtin.template:
src: logrotate-minecraft.j2
dest: /etc/logrotate.d/minecraft
owner: root
group: root
mode: '0644'
tags: ['minecraft-logs']
notify: "restart log rotation"

View File

@@ -1,9 +1,10 @@
---
- name: Configure ops.json
template:
- name: Create ops.json file
ansible.builtin.template:
src: ops.json.j2
dest: "{{ minecraft_server_dir }}/ops.json"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
tags: ['minecraft-ops']
when: minecraft_ops is defined and minecraft_ops | length > 0
notify: "restart minecraft service"

View File

@@ -0,0 +1,23 @@
---
- name: Ensure plugins directory exists with correct permissions
ansible.builtin.file:
path: "{{ minecraft_plugins_dir }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Create plugins management script
ansible.builtin.copy:
content: |
#!/bin/bash
# Plugin management script
PLUGINS_DIR="{{ minecraft_plugins_dir }}"
echo "Minecraft plugins directory: $PLUGINS_DIR"
echo "Current plugins:"
ls -la "$PLUGINS_DIR"
dest: "{{ minecraft_tools_dir }}/manage-plugins.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'

View File

@@ -1,20 +0,0 @@
---
- name: Create plugins directory
file:
path: "{{ minecraft_server_dir }}/plugins"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
tags: ['minecraft-plugins']
- name: Download plugins if specified
get_url:
url: "{{ item.url }}"
dest: "{{ minecraft_server_dir }}/plugins/{{ item.name }}"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
loop: "{{ minecraft_plugins | default([]) }}"
when: minecraft_plugins is defined
tags: ['minecraft-plugins']

View File

@@ -1,40 +1,30 @@
---
- name: Include user and group creation tasks
include_tasks: 01-create-user-group.yml
tags: ['minecraft', 'user']
- name: Include minecraft user creation tasks
ansible.builtin.include_tasks: 01-create-minecraft-user.yml
- name: Include directory creation tasks
include_tasks: 02-create-directories.yml
tags: ['minecraft', 'directories']
ansible.builtin.include_tasks: 02-create-directories.yml
- name: Include Spigot download tasks
include_tasks: 03-download-spigot.yml
tags: ['minecraft', 'download']
ansible.builtin.include_tasks: 03-download-spigot.yml
- name: Include mcrcon installation tasks
include_tasks: 04-install-mcrcon.yml
tags: ['minecraft', 'mcrcon']
- name: Include MCRCON installation tasks
ansible.builtin.include_tasks: 04-install-mcrcon.yml
- name: Include Spigot compilation tasks
include_tasks: 05-compile-spigot.yml
tags: ['minecraft', 'compile']
ansible.builtin.include_tasks: 05-compile-spigot.yml
- name: Include server configuration tasks
include_tasks: 06-configure-server.yml
tags: ['minecraft', 'configure']
- name: Include Minecraft configuration tasks
ansible.builtin.include_tasks: 06-configure-minecraft.yml
- name: Include service creation tasks
include_tasks: 07-create-service.yml
tags: ['minecraft', 'service']
- name: Include systemd service setup tasks
ansible.builtin.include_tasks: 07-setup-systemd-service.yml
- name: Include log rotation setup tasks
include_tasks: 08-setup-log-rotation.yml
tags: ['minecraft', 'logs']
ansible.builtin.include_tasks: 08-setup-log-rotation.yml
- name: Include ops configuration tasks
include_tasks: 09-configure-ops.yml
tags: ['minecraft', 'ops']
- name: Include ops management setup tasks
ansible.builtin.include_tasks: 09-setup-ops-management.yml
- name: Include plugins setup tasks
include_tasks: 10-setup-plugins.yml
tags: ['minecraft', 'plugins']
- name: Include plugins directory setup tasks
ansible.builtin.include_tasks: 10-setup-plugins-directory.yml

View File

@@ -1,12 +1,21 @@
{{ minecraft_server_dir }}/logs/*.log {
{{ minecraft_base_dir }}/logs/*.log {
daily
missingok
rotate 52
rotate 30
compress
delaycompress
notifempty
create 644 {{ minecraft_user }} {{ minecraft_group }}
postrotate
systemctl reload minecraft
endscript
copytruncate
su {{ minecraft_user }} {{ minecraft_group }}
}
{{ minecraft_server_dir }}/logs/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
copytruncate
su {{ minecraft_user }} {{ minecraft_group }}
}

View File

@@ -7,11 +7,12 @@ Type=forking
User={{ minecraft_user }}
Group={{ minecraft_group }}
WorkingDirectory={{ minecraft_server_dir }}
ExecStart=/usr/bin/java -Xms{{ minecraft_memory_min }} -Xmx{{ minecraft_memory_max }} -jar {{ minecraft_server_dir }}/spigot.jar nogui
ExecStop={{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} stop
RemainAfterExit=yes
RestartSec=15
Restart=always
ExecStart=/usr/bin/java -Xms{{ minecraft_memory_min }} -Xmx{{ minecraft_memory_max }} -jar spigot.jar nogui
ExecStop=/usr/local/bin/mcrcon -H 127.0.0.1 -P {{ rcon_port }} -p {{ rcon_password }} stop
TimeoutStartSec=600
TimeoutStopSec=600
Restart=on-failure
RestartSec=20
[Install]
WantedBy=multi-user.target

View File

@@ -1,10 +1,10 @@
[
{% for op in minecraft_ops | default([]) %}
{
"uuid": "{{ op.uuid }}",
"name": "{{ op.name }}",
"level": {{ op.level | default(4) }},
"bypassesPlayerLimit": {{ op.bypass_limit | default(false) | lower }}
}{% if not loop.last %},{% endif %}
{% for op in minecraft_ops %}
{
"uuid": "{{ op.uuid }}",
"name": "{{ op.name }}",
"level": {{ op.level | default(4) }},
"bypassesPlayerLimit": {{ op.bypass_player_limit | default(false) | ternary('true', 'false') }}
}{% if not loop.last %},{% endif %}
{% endfor %}
]

View File

@@ -1,24 +1,46 @@
#Minecraft server properties
server-name=Spigot Server
# Minecraft server properties
# Generated by Ansible
# Server settings
server-name={{ server_name }}
motd={{ server_motd }}
server-port={{ minecraft_port }}
max-players=20
gamemode=survival
difficulty=normal
max-players={{ max_players }}
# Game settings
gamemode={{ gamemode }}
difficulty={{ difficulty }}
pvp={{ pvp_enabled | ternary('true', 'false') }}
hardcore=false
white-list=false
enforce-whitelist=false
pvp=true
enable-command-block=false
spawn-protection=16
op-permission-level=4
allow-flight=false
enable-rcon=true
rcon.port={{ minecraft_rcon_port }}
rcon.password={{ minecraft_rcon_password }}
motd=Minecraft Spigot Server managed by Ansible
max-world-size=29999984
# RCON settings
enable-rcon={{ rcon_enabled | ternary('true', 'false') }}
rcon.port={{ rcon_port }}
rcon.password={{ rcon_password }}
# Network settings
server-ip=
online-mode=true
spawn-monsters=true
generate-structures=true
view-distance=10
level-seed=
white-list=false
enable-status=true
enable-query=false
query.port=25565
# World generation
level-name=world
level-type=default
level-seed=
level-type=minecraft\:normal
generate-structures=true
spawn-animals=true
spawn-monsters=true
spawn-npcs=true
# Performance settings
view-distance=10
simulation-distance=10
max-tick-time=60000
use-native-transport=true
enable-jmx-monitoring=false

View File

@@ -0,0 +1,21 @@
---
# Internal variables for Minecraft installation
required_packages:
- openjdk-17-jdk
- git
- build-essential
- screen
spigot_build_tools_url: "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
mcrcon_repository: "https://github.com/Tiiffi/mcrcon.git"
# Default server configuration
default_server_properties:
server-port: 25565
max-players: 20
gamemode: survival
difficulty: normal
pvp: true
online-mode: true
white-list: false

View File

@@ -1,8 +1,26 @@
---
backup_retention_daily: 7
backup_retention_weekly: 4
backup_retention_monthly: 6
backup_compression: true
backup_remote_host: ""
backup_remote_user: ""
backup_remote_path: ""
# Backup configuration
backup_base_dir: "{{ minecraft_base_dir }}/backups"
backup_daily_dir: "{{ backup_base_dir }}/daily"
backup_weekly_dir: "{{ backup_base_dir }}/weekly"
backup_monthly_dir: "{{ backup_base_dir }}/monthly"
# Retention settings
backup_retention_days: 7
backup_retention_weeks: 4
backup_retention_months: 6
# Source directories to backup
backup_sources:
- "{{ minecraft_server_dir }}"
- "{{ minecraft_base_dir }}/logs"
# Backup schedule
backup_daily_time: "02:00"
backup_weekly_time: "03:00"
backup_weekly_day: "0" # Sunday
backup_monthly_time: "04:00"
backup_monthly_day: "1" # First day of month
# Rsync options
rsync_options: "-avz --delete"

View File

@@ -0,0 +1,26 @@
---
# Backup configuration
backup_base_dir: "{{ minecraft_base_dir }}/backups"
backup_daily_dir: "{{ backup_base_dir }}/daily"
backup_weekly_dir: "{{ backup_base_dir }}/weekly"
backup_monthly_dir: "{{ backup_base_dir }}/monthly"
# Retention settings
backup_retention_days: 7
backup_retention_weeks: 4
backup_retention_months: 6
# Source directories to backup
backup_sources:
- "{{ minecraft_server_dir }}"
- "{{ minecraft_base_dir }}/logs"
# Backup schedule
backup_daily_time: "02:00"
backup_weekly_time: "03:00"
backup_weekly_day: "0" # Sunday
backup_monthly_time: "04:00"
backup_monthly_day: "1" # First day of month
# Rsync options
rsync_options: "-avz --delete"

View File

@@ -0,0 +1,18 @@
---
- name: Create backup directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
loop:
- "{{ backup_base_dir }}"
- "{{ backup_daily_dir }}"
- "{{ backup_weekly_dir }}"
- "{{ backup_monthly_dir }}"
- name: Install rsync
ansible.builtin.apt:
name: rsync
state: present

View File

@@ -1,14 +0,0 @@
---
- name: Create backup directories
file:
path: "{{ item }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
loop:
- "{{ minecraft_backups_dir }}/daily"
- "{{ minecraft_backups_dir }}/weekly"
- "{{ minecraft_backups_dir }}/monthly"
- "{{ minecraft_backups_dir }}/scripts"
tags: ['backup-structure']

View File

@@ -1,27 +0,0 @@
---
- name: Create daily backup script
template:
src: backup-daily.sh.j2
dest: "{{ minecraft_backups_dir }}/scripts/backup-daily.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
tags: ['backup-scripts']
- name: Create weekly backup script
template:
src: backup-weekly.sh.j2
dest: "{{ minecraft_backups_dir }}/scripts/backup-weekly.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
tags: ['backup-scripts']
- name: Create monthly backup script
template:
src: backup-monthly.sh.j2
dest: "{{ minecraft_backups_dir }}/scripts/backup-monthly.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
tags: ['backup-scripts']

View File

@@ -0,0 +1,17 @@
---
- name: Create daily backup script
ansible.builtin.template:
src: backup-daily.sh.j2
dest: "{{ minecraft_tools_dir }}/backup-daily.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Setup daily backup cron job
ansible.builtin.cron:
name: "Minecraft daily backup"
minute: "0"
hour: "{{ backup_daily_time.split(':')[0] }}"
job: "{{ minecraft_tools_dir }}/backup-daily.sh"
user: "{{ minecraft_user }}"
state: present

View File

@@ -1,29 +0,0 @@
---
- name: Setup daily backup cron job
cron:
name: "Minecraft daily backup"
user: "{{ minecraft_user }}"
minute: "0"
hour: "2"
job: "{{ minecraft_backups_dir }}/scripts/backup-daily.sh"
tags: ['backup-cron']
- name: Setup weekly backup cron job
cron:
name: "Minecraft weekly backup"
user: "{{ minecraft_user }}"
minute: "0"
hour: "3"
weekday: "0"
job: "{{ minecraft_backups_dir }}/scripts/backup-weekly.sh"
tags: ['backup-cron']
- name: Setup monthly backup cron job
cron:
name: "Minecraft monthly backup"
user: "{{ minecraft_user }}"
minute: "0"
hour: "4"
day: "1"
job: "{{ minecraft_backups_dir }}/scripts/backup-monthly.sh"
tags: ['backup-cron']

View File

@@ -0,0 +1,18 @@
---
- name: Create weekly backup script
ansible.builtin.template:
src: backup-weekly.sh.j2
dest: "{{ minecraft_tools_dir }}/backup-weekly.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Setup weekly backup cron job
ansible.builtin.cron:
name: "Minecraft weekly backup"
minute: "0"
hour: "{{ backup_weekly_time.split(':')[0] }}"
weekday: "{{ backup_weekly_day }}"
job: "{{ minecraft_tools_dir }}/backup-weekly.sh"
user: "{{ minecraft_user }}"
state: present

View File

@@ -0,0 +1,18 @@
---
- name: Create monthly backup script
ansible.builtin.template:
src: backup-monthly.sh.j2
dest: "{{ minecraft_tools_dir }}/backup-monthly.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Setup monthly backup cron job
ansible.builtin.cron:
name: "Minecraft monthly backup"
minute: "0"
hour: "{{ backup_monthly_time.split(':')[0] }}"
day: "{{ backup_monthly_day }}"
job: "{{ minecraft_tools_dir }}/backup-monthly.sh"
user: "{{ minecraft_user }}"
state: present

View File

@@ -1,9 +0,0 @@
---
- name: Create restore script
template:
src: restore.sh.j2
dest: "{{ minecraft_backups_dir }}/scripts/restore.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
tags: ['backup-restore']

View File

@@ -0,0 +1,38 @@
---
- name: Create backup utility script
ansible.builtin.copy:
content: |
#!/bin/bash
# Backup utility functions
# Function to stop Minecraft server safely
stop_minecraft() {
if systemctl is-active --quiet minecraft; then
echo "Stopping Minecraft server..."
/usr/local/bin/mcrcon -H 127.0.0.1 -P {{ rcon_port }} -p "{{ rcon_password }}" "say Server backup starting in 30 seconds..."
sleep 30
/usr/local/bin/mcrcon -H 127.0.0.1 -P {{ rcon_port }} -p "{{ rcon_password }}" stop
sleep 10
fi
}
# Function to start Minecraft server
start_minecraft() {
if ! systemctl is-active --quiet minecraft; then
echo "Starting Minecraft server..."
systemctl start minecraft
fi
}
# Function to clean old backups
clean_old_backups() {
local backup_dir=$1
local retention_days=$2
find "$backup_dir" -type f -mtime +$retention_days -delete
find "$backup_dir" -type d -empty -delete
}
dest: "{{ minecraft_tools_dir }}/backup-functions.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'

View File

@@ -0,0 +1,8 @@
---
- name: Create restore backup script
ansible.builtin.template:
src: restore-backup.sh.j2
dest: "{{ minecraft_tools_dir }}/restore-backup.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'

View File

@@ -1,16 +1,18 @@
---
- name: Include backup structure setup tasks
include_tasks: 01-setup-backup-structure.yml
tags: ['backup', 'setup']
- name: Include backup directories creation tasks
ansible.builtin.include_tasks: 01-create-backup-directories.yml
- name: Include backup scripts creation tasks
include_tasks: 02-create-backup-scripts.yml
tags: ['backup', 'scripts']
- name: Include daily backup setup tasks
ansible.builtin.include_tasks: 02-setup-daily-backup.yml
- name: Include cron jobs setup tasks
include_tasks: 03-setup-cron-jobs.yml
tags: ['backup', 'cron']
- name: Include weekly backup setup tasks
ansible.builtin.include_tasks: 03-setup-weekly-backup.yml
- name: Include restore script setup tasks
include_tasks: 04-setup-restore-script.yml
tags: ['backup', 'restore']
- name: Include monthly backup setup tasks
ansible.builtin.include_tasks: 04-setup-monthly-backup.yml
- name: Include backup scripts setup tasks
ansible.builtin.include_tasks: 05-setup-backup-scripts.yml
- name: Include restore scripts setup tasks
ansible.builtin.include_tasks: 06-setup-restore-scripts.yml

View File

@@ -1,29 +1,42 @@
#!/bin/bash
# Daily Minecraft Backup Script
# Generated by Ansible
BACKUP_DIR="{{ minecraft_backups_dir }}/daily"
SERVER_DIR="{{ minecraft_server_dir }}"
set -e
# Source backup functions
source {{ minecraft_tools_dir }}/backup-functions.sh
# Configuration
BACKUP_DIR="{{ backup_daily_dir }}"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="minecraft_daily_${DATE}"
RETENTION={{ backup_retention_daily }}
BACKUP_NAME="daily_backup_$DATE"
LOG_FILE="{{ minecraft_base_dir }}/logs/backup-daily.log"
# Stop server for consistent backup
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-all
sleep 5
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-off
# Create log entry
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting daily backup..." >> "$LOG_FILE"
# Create backup
rsync -av --delete "${SERVER_DIR}/" "${BACKUP_DIR}/${BACKUP_NAME}/"
# Create backup directory
mkdir -p "$BACKUP_DIR/$BACKUP_NAME"
# Re-enable saving
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-on
# Stop Minecraft server for consistent backup
stop_minecraft
# Compress backup if enabled
{% if backup_compression %}
tar -czf "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" -C "${BACKUP_DIR}" "${BACKUP_NAME}"
rm -rf "${BACKUP_DIR}/${BACKUP_NAME}"
{% endif %}
# Perform backup
{% for source in backup_sources %}
echo "Backing up {{ source }}..." >> "$LOG_FILE"
rsync {{ rsync_options }} "{{ source }}/" "$BACKUP_DIR/$BACKUP_NAME/$(basename {{ source }})/"
{% endfor %}
# Clean old backups
find "${BACKUP_DIR}" -name "minecraft_daily_*" -type {% if backup_compression %}f{% else %}d{% endif %} -mtime +${RETENTION} -delete
# Start Minecraft server
start_minecraft
echo "Daily backup completed: ${BACKUP_NAME}"
# Clean old daily backups
clean_old_backups "$BACKUP_DIR" {{ backup_retention_days }}
# Compress backup
cd "$BACKUP_DIR"
tar -czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME"
rm -rf "$BACKUP_NAME"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Daily backup completed: ${BACKUP_NAME}.tar.gz" >> "$LOG_FILE"

View File

@@ -1,29 +1,42 @@
#!/bin/bash
# Monthly Minecraft Backup Script
# Generated by Ansible
BACKUP_DIR="{{ minecraft_backups_dir }}/monthly"
SERVER_DIR="{{ minecraft_server_dir }}"
set -e
# Source backup functions
source {{ minecraft_tools_dir }}/backup-functions.sh
# Configuration
BACKUP_DIR="{{ backup_monthly_dir }}"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="minecraft_monthly_${DATE}"
RETENTION={{ backup_retention_monthly }}
BACKUP_NAME="monthly_backup_$DATE"
LOG_FILE="{{ minecraft_base_dir }}/logs/backup-monthly.log"
# Stop server for consistent backup
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-all
sleep 5
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-off
# Create log entry
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting monthly backup..." >> "$LOG_FILE"
# Create backup
rsync -av --delete "${SERVER_DIR}/" "${BACKUP_DIR}/${BACKUP_NAME}/"
# Create backup directory
mkdir -p "$BACKUP_DIR/$BACKUP_NAME"
# Re-enable saving
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-on
# Stop Minecraft server for consistent backup
stop_minecraft
# Compress backup if enabled
{% if backup_compression %}
tar -czf "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" -C "${BACKUP_DIR}" "${BACKUP_NAME}"
rm -rf "${BACKUP_DIR}/${BACKUP_NAME}"
{% endif %}
# Perform backup
{% for source in backup_sources %}
echo "Backing up {{ source }}..." >> "$LOG_FILE"
rsync {{ rsync_options }} "{{ source }}/" "$BACKUP_DIR/$BACKUP_NAME/$(basename {{ source }})/"
{% endfor %}
# Clean old backups
find "${BACKUP_DIR}" -name "minecraft_monthly_*" -type {% if backup_compression %}f{% else %}d{% endif %} -mtime +$((${RETENTION} * 30)) -delete
# Start Minecraft server
start_minecraft
echo "Monthly backup completed: ${BACKUP_NAME}"
# Clean old monthly backups (convert months to days approximately)
clean_old_backups "$BACKUP_DIR" $(({{ backup_retention_months }} * 30))
# Compress backup
cd "$BACKUP_DIR"
tar -czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME"
rm -rf "$BACKUP_NAME"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Monthly backup completed: ${BACKUP_NAME}.tar.gz" >> "$LOG_FILE"

View File

@@ -1,29 +1,42 @@
#!/bin/bash
# Weekly Minecraft Backup Script
# Generated by Ansible
BACKUP_DIR="{{ minecraft_backups_dir }}/weekly"
SERVER_DIR="{{ minecraft_server_dir }}"
set -e
# Source backup functions
source {{ minecraft_tools_dir }}/backup-functions.sh
# Configuration
BACKUP_DIR="{{ backup_weekly_dir }}"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="minecraft_weekly_${DATE}"
RETENTION={{ backup_retention_weekly }}
BACKUP_NAME="weekly_backup_$DATE"
LOG_FILE="{{ minecraft_base_dir }}/logs/backup-weekly.log"
# Stop server for consistent backup
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-all
sleep 5
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-off
# Create log entry
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting weekly backup..." >> "$LOG_FILE"
# Create backup
rsync -av --delete "${SERVER_DIR}/" "${BACKUP_DIR}/${BACKUP_NAME}/"
# Create backup directory
mkdir -p "$BACKUP_DIR/$BACKUP_NAME"
# Re-enable saving
{{ minecraft_tools_dir }}/mcrcon -H 127.0.0.1 -P {{ minecraft_rcon_port }} -p {{ minecraft_rcon_password }} save-on
# Stop Minecraft server for consistent backup
stop_minecraft
# Compress backup if enabled
{% if backup_compression %}
tar -czf "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" -C "${BACKUP_DIR}" "${BACKUP_NAME}"
rm -rf "${BACKUP_DIR}/${BACKUP_NAME}"
{% endif %}
# Perform backup
{% for source in backup_sources %}
echo "Backing up {{ source }}..." >> "$LOG_FILE"
rsync {{ rsync_options }} "{{ source }}/" "$BACKUP_DIR/$BACKUP_NAME/$(basename {{ source }})/"
{% endfor %}
# Clean old backups
find "${BACKUP_DIR}" -name "minecraft_weekly_*" -type {% if backup_compression %}f{% else %}d{% endif %} -mtime +$((${RETENTION} * 7)) -delete
# Start Minecraft server
start_minecraft
echo "Weekly backup completed: ${BACKUP_NAME}"
# Clean old weekly backups (convert weeks to days)
clean_old_backups "$BACKUP_DIR" $(({{ backup_retention_weeks }} * 7))
# Compress backup
cd "$BACKUP_DIR"
tar -czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME"
rm -rf "$BACKUP_NAME"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Weekly backup completed: ${BACKUP_NAME}.tar.gz" >> "$LOG_FILE"

View File

@@ -0,0 +1,116 @@
#!/bin/bash
# Minecraft Backup Restore Script
# Generated by Ansible
set -e
# Usage function
usage() {
echo "Usage: $0 <backup_type> <backup_file>"
echo "backup_type: daily, weekly, or monthly"
echo "backup_file: name of the backup file to restore"
echo ""
echo "Example: $0 daily daily_backup_20241225_120000.tar.gz"
exit 1
}
# Check arguments
if [ $# -ne 2 ]; then
usage
fi
BACKUP_TYPE="$1"
BACKUP_FILE="$2"
LOG_FILE="{{ minecraft_base_dir }}/logs/restore.log"
# Source backup functions
source {{ minecraft_tools_dir }}/backup-functions.sh
# Validate backup type
case "$BACKUP_TYPE" in
daily)
BACKUP_DIR="{{ backup_daily_dir }}"
;;
weekly)
BACKUP_DIR="{{ backup_weekly_dir }}"
;;
monthly)
BACKUP_DIR="{{ backup_monthly_dir }}"
;;
*)
echo "Invalid backup type: $BACKUP_TYPE"
usage
;;
esac
# Check if backup file exists
BACKUP_PATH="$BACKUP_DIR/$BACKUP_FILE"
if [ ! -f "$BACKUP_PATH" ]; then
echo "Backup file not found: $BACKUP_PATH"
exit 1
fi
# Confirmation
echo "WARNING: This will replace the current Minecraft server data!"
echo "Backup file: $BACKUP_PATH"
echo "Type 'yes' to continue:"
read -r confirmation
if [ "$confirmation" != "yes" ]; then
echo "Restore cancelled."
exit 0
fi
# Start restoration process
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting restore from $BACKUP_FILE..." >> "$LOG_FILE"
# Stop Minecraft server
stop_minecraft
# Create temporary restore directory
TEMP_DIR="/tmp/minecraft_restore_$"
mkdir -p "$TEMP_DIR"
# Extract backup
echo "Extracting backup..." >> "$LOG_FILE"
cd "$TEMP_DIR"
tar -xzf "$BACKUP_PATH"
# Find the extracted directory
EXTRACTED_DIR=$(find . -maxdepth 1 -type d -name "*backup*" | head -1)
if [ -z "$EXTRACTED_DIR" ]; then
echo "Could not find extracted backup directory"
rm -rf "$TEMP_DIR"
exit 1
fi
# Backup current data
CURRENT_BACKUP="{{ minecraft_base_dir }}/current_backup_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$CURRENT_BACKUP"
{% for source in backup_sources %}
if [ -d "{{ source }}" ]; then
cp -r "{{ source }}" "$CURRENT_BACKUP/"
fi
{% endfor %}
echo "Current data backed up to: $CURRENT_BACKUP" >> "$LOG_FILE"
# Restore data
echo "Restoring data..." >> "$LOG_FILE"
{% for source in backup_sources %}
SOURCE_NAME=$(basename {{ source }})
if [ -d "$EXTRACTED_DIR/$SOURCE_NAME" ]; then
rm -rf "{{ source }}"
cp -r "$EXTRACTED_DIR/$SOURCE_NAME" "{{ source }}"
chown -R {{ minecraft_user }}:{{ minecraft_group }} "{{ source }}"
fi
{% endfor %}
# Cleanup temporary directory
rm -rf "$TEMP_DIR"
# Start Minecraft server
start_minecraft
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Restore completed successfully" >> "$LOG_FILE"
echo "Restore completed successfully!"
echo "Previous data backed up to: $CURRENT_BACKUP"

View File

@@ -1,59 +0,0 @@
#!/bin/bash
BACKUP_TYPE="$1" # daily, weekly, monthly
BACKUP_DATE="$2" # YYYYMMDD_HHMMSS format
SERVER_DIR="{{ minecraft_server_dir }}"
BACKUP_BASE_DIR="{{ minecraft_backups_dir }}"
if [ $# -ne 2 ]; then
echo "Usage: $0 <backup_type> <backup_date>"
echo "Example: $0 daily 20241201_020000"
echo "Available backups:"
echo "Daily:"
ls -1 "${BACKUP_BASE_DIR}/daily/" | grep minecraft_daily
echo "Weekly:"
ls -1 "${BACKUP_BASE_DIR}/weekly/" | grep minecraft_weekly
echo "Monthly:"
ls -1 "${BACKUP_BASE_DIR}/monthly/" | grep minecraft_monthly
exit 1
fi
BACKUP_NAME="minecraft_${BACKUP_TYPE}_${BACKUP_DATE}"
BACKUP_DIR="${BACKUP_BASE_DIR}/${BACKUP_TYPE}"
{% if backup_compression %}
BACKUP_FILE="${BACKUP_DIR}/${BACKUP_NAME}.tar.gz"
{% else %}
BACKUP_FILE="${BACKUP_DIR}/${BACKUP_NAME}"
{% endif %}
if [ ! -e "${BACKUP_FILE}" ]; then
echo "Backup not found: ${BACKUP_FILE}"
exit 1
fi
# Stop Minecraft server
systemctl stop minecraft
# Backup current server (just in case)
RESTORE_BACKUP_DIR="${BACKUP_BASE_DIR}/restore_backup"
mkdir -p "${RESTORE_BACKUP_DIR}"
mv "${SERVER_DIR}" "${RESTORE_BACKUP_DIR}/server_before_restore_$(date +%Y%m%d_%H%M%S)"
# Restore from backup
{% if backup_compression %}
mkdir -p "${SERVER_DIR}"
tar -xzf "${BACKUP_FILE}" -C "${BACKUP_DIR}"
rsync -av "${BACKUP_DIR}/${BACKUP_NAME}/" "${SERVER_DIR}/"
rm -rf "${BACKUP_DIR}/${BACKUP_NAME}"
{% else %}
rsync -av "${BACKUP_FILE}/" "${SERVER_DIR}/"
{% endif %}
# Fix permissions
chown -R {{ minecraft_user }}:{{ minecraft_group }} "${SERVER_DIR}"
# Start Minecraft server
systemctl start minecraft
echo "Restore completed from: ${BACKUP_FILE}"

View File

@@ -0,0 +1,16 @@
---
# Internal backup variables
backup_script_names:
- backup-daily.sh
- backup-weekly.sh
- backup-monthly.sh
- restore-backup.sh
- backup-functions.sh
cron_jobs:
- name: "Minecraft daily backup"
script: "backup-daily.sh"
- name: "Minecraft weekly backup"
script: "backup-weekly.sh"
- name: "Minecraft monthly backup"
script: "backup-monthly.sh"

View File

@@ -1,5 +1,14 @@
---
update_check_interval: daily
ssh_keys_check_enabled: true
system_update_check_enabled: true
spigot_update_check_enabled: true
# Update configuration
update_check_ssh_keys: true
update_check_system: true
update_check_spigot: true
# Spigot update settings
spigot_current_version_file: "{{ minecraft_server_dir }}/.version"
spigot_new_version_dir: "{{ minecraft_base_dir }}/new_version"
spigot_backup_dir: "{{ minecraft_base_dir }}/version_backups"
# System update settings
system_update_auto: false
system_reboot_required_check: true

View File

@@ -1,7 +1,13 @@
---
- name: reboot if needed
reboot:
reboot_timeout: 300
when:
- ansible_kernel != ansible_kernel_before_update | default(ansible_kernel)
- reboot_required | default(false)
- name: restart minecraft after update
ansible.builtin.systemd:
name: minecraft
state: restarted
daemon_reload: true
listen: "restart minecraft after version change"
- name: reload ssh after key update
ansible.builtin.systemd:
name: ssh
state: reloaded
listen: "reload ssh service"

View File

@@ -1,14 +0,0 @@
---
- name: Check for new SSH keys in authorized_keys
stat:
path: /home/{{ ansible_user }}/.ssh/authorized_keys
register: ssh_keys_stat
- name: Update SSH keys if changed
authorized_key:
user: "{{ ansible_user }}"
key: "{{ item }}"
state: present
loop: "{{ ssh_public_keys | default([]) }}"
when: ssh_public_keys is defined
tags: ['ssh-keys-update']

View File

@@ -0,0 +1,16 @@
---
- name: Check for new SSH keys to add
ansible.posix.authorized_key:
user: ansible
key: "{{ item.key }}"
comment: "{{ item.comment | default('') }}"
state: present
loop: "{{ admin_users }}"
when: admin_users is defined and admin_users | length > 0
notify: "reload ssh service"
register: ssh_keys_result
- name: Log SSH keys update
ansible.builtin.debug:
msg: "SSH keys updated for {{ ssh_keys_result.results | selectattr('changed', 'equalto', true) | list | length }} users"
when: ssh_keys_result is defined

View File

@@ -1,23 +1,41 @@
---
- name: Check for system updates (Debian/Ubuntu)
apt:
update_cache: yes
cache_valid_time: 3600
register: apt_cache_update
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
when: ansible_os_family == "Debian"
- name: Check available upgrades
shell: apt list --upgradable 2>/dev/null | grep -v WARNING | wc -l
register: available_upgrades
- name: Check for available system updates
ansible.builtin.shell: |
apt list --upgradable 2>/dev/null | grep -v "Listing..." | wc -l
register: available_updates_count
changed_when: false
when: ansible_os_family == "Debian"
- name: Apply system updates if available
apt:
upgrade: yes
autoremove: yes
autoclean: yes
- name: Display available updates count
ansible.builtin.debug:
msg: "{{ available_updates_count.stdout }} system updates available"
when: available_updates_count is defined
- name: Apply system updates if auto-update enabled
ansible.builtin.apt:
upgrade: dist
autoremove: true
autoclean: true
when:
- system_update_auto | bool
- ansible_os_family == "Debian"
- available_upgrades.stdout | int > 1
notify: reboot if needed
- available_updates_count.stdout | int > 0
register: system_update_result
- name: Check if reboot is required
ansible.builtin.stat:
path: /var/run/reboot-required
register: reboot_required_file
when: system_reboot_required_check | bool
- name: Warn about required reboot
ansible.builtin.debug:
msg: "ATTENTION: System reboot is required to complete updates"
when:
- reboot_required_file is defined
- reboot_required_file.stat.exists

View File

@@ -1,26 +1,27 @@
---
- name: Get current Spigot version
stat:
path: "{{ minecraft_server_dir }}/spigot.jar"
register: current_spigot
- name: Check latest Spigot version available
uri:
url: "https://api.papermc.io/v2/projects/paper/versions"
method: GET
return_content: yes
register: spigot_versions_api
- name: Check current Spigot version
ansible.builtin.slurp:
src: "{{ spigot_current_version_file }}"
register: current_version_file
failed_when: false
- name: Parse latest version
set_fact:
latest_spigot_version: "{{ (spigot_versions_api.json.versions | last) if spigot_versions_api.json is defined else minecraft_version }}"
- name: Set current version variable
ansible.builtin.set_fact:
current_spigot_version: "{{ (current_version_file.content | b64decode).strip() }}"
when: current_version_file.failed == false
- name: Compare versions
set_fact:
new_spigot_available: "{{ latest_spigot_version != minecraft_version }}"
when: latest_spigot_version is defined
- name: Set default current version if file doesn't exist
ansible.builtin.set_fact:
current_spigot_version: "unknown"
when: current_version_file.failed == true
- name: Check if new version is available
ansible.builtin.set_fact:
spigot_update_available: "{{ minecraft_version != current_spigot_version }}"
- name: Display version information
debug:
msg: "Current: {{ minecraft_version }}, Latest: {{ latest_spigot_version | default('Unknown') }}, Update available: {{ new_spigot_available | default(false) }}"
ansible.builtin.debug:
msg:
- "Current Spigot version: {{ current_spigot_version }}"
- "Target Spigot version: {{ minecraft_version }}"
- "Update available: {{ spigot_update_available }}"

View File

@@ -1,16 +1,18 @@
---
- name: Create temporary build directory
file:
path: "{{ minecraft_sources_dir }}/build_{{ latest_spigot_version }}"
- name: Create new version directory
ansible.builtin.file:
path: "{{ spigot_new_version_dir }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Download BuildTools for new version
get_url:
url: "{{ spigot_build_tools_url }}"
dest: "{{ minecraft_sources_dir }}/build_{{ latest_spigot_version }}/BuildTools.jar"
ansible.builtin.get_url:
url: "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
dest: "{{ spigot_new_version_dir }}/BuildTools.jar"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
mode: '0644'
timeout: 300
force: true

View File

@@ -0,0 +1,17 @@
---
- name: Compile new Spigot version
ansible.builtin.shell: |
cd {{ spigot_new_version_dir }}
java -jar BuildTools.jar --rev {{ minecraft_version }}
become_user: "{{ minecraft_user }}"
register: new_spigot_compilation
failed_when: new_spigot_compilation.rc != 0
timeout: 1800
- name: Set compilation success flag
ansible.builtin.set_fact:
spigot_compilation_successful: "{{ new_spigot_compilation.rc == 0 }}"
- name: Display compilation result
ansible.builtin.debug:
msg: "New Spigot compilation {{ 'successful' if spigot_compilation_successful else 'failed' }}"

View File

@@ -1,38 +0,0 @@
---
- name: Compile new Spigot version
shell: |
cd {{ minecraft_sources_dir }}/build_{{ latest_spigot_version }}
java -jar BuildTools.jar --rev {{ latest_spigot_version }}
become_user: "{{ minecraft_user }}"
args:
creates: "{{ minecraft_sources_dir }}/build_{{ latest_spigot_version }}/spigot-{{ latest_spigot_version }}.jar"
register: spigot_compile_result
- name: Set compilation success flag
set_fact:
new_spigot_compiled: "{{ spigot_compile_result.rc == 0 }}"
- name: Create new server directory
file:
path: "{{ minecraft_server_dir }}_{{ latest_spigot_version }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
when: new_spigot_compiled
- name: Copy new Spigot jar to new server directory
copy:
src: "{{ minecraft_sources_dir }}/build_{{ latest_spigot_version }}/spigot-{{ latest_spigot_version }}.jar"
dest: "{{ minecraft_server_dir }}_{{ latest_spigot_version }}/spigot.jar"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
remote_src: yes
when: new_spigot_compiled
- name: Copy configuration files to new server directory
shell: |
cp -r {{ minecraft_server_dir }}/* {{ minecraft_server_dir }}_{{ latest_spigot_version }}/
chown -R {{ minecraft_user }}:{{ minecraft_group }} {{ minecraft_server_dir }}_{{ latest_spigot_version }}
when: new_spigot_compiled

View File

@@ -0,0 +1 @@
06-configure-new-version.yml

View File

@@ -1,29 +0,0 @@
---
- name: Stop Minecraft service
systemd:
name: minecraft
state: stopped
- name: Create version switch script
template:
src: version-switch.sh.j2
dest: "{{ minecraft_tools_dir }}/version-switch.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Execute version switch
shell: "{{ minecraft_tools_dir }}/version-switch.sh {{ minecraft_version }} {{ latest_spigot_version }}"
become_user: "{{ minecraft_user }}"
register: version_switch_result
- name: Update minecraft_version variable
set_fact:
minecraft_version: "{{ latest_spigot_version }}"
when: version_switch_result.rc == 0
- name: Start Minecraft service
systemd:
name: minecraft
state: started
when: version_switch_result.rc == 0

View File

@@ -1,13 +0,0 @@
---
- name: Clean up old build directories
file:
path: "{{ minecraft_sources_dir }}/build_{{ item }}"
state: absent
loop: "{{ old_versions | default([]) }}"
- name: Clean up old server directories
file:
path: "{{ minecraft_server_dir }}_{{ item }}"
state: absent
loop: "{{ old_versions | default([]) }}"
when: cleanup_old_versions | default(true)

View File

@@ -0,0 +1,83 @@
---
- name: Create version backup directory
ansible.builtin.file:
path: "{{ spigot_backup_dir }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Stop Minecraft server
ansible.builtin.systemd:
name: minecraft
state: stopped
- name: Backup current version
ansible.builtin.shell: |
BACKUP_NAME="version_backup_$(date +%Y%m%d_%H%M%S)"
mkdir -p "{{ spigot_backup_dir }}/$BACKUP_NAME"
cp -r "{{ minecraft_server_dir }}"/* "{{ spigot_backup_dir }}/$BACKUP_NAME/"
become_user: "{{ minecraft_user }}"
- name: Copy world data to new version
ansible.builtin.shell: |
if [ -d "{{ minecraft_server_dir }}/world" ]; then
cp -r "{{ minecraft_server_dir }}/world" "{{ spigot_new_version_dir }}/"
fi
if [ -d "{{ minecraft_server_dir }}/world_nether" ]; then
cp -r "{{ minecraft_server_dir }}/world_nether" "{{ spigot_new_version_dir }}/"
fi
if [ -d "{{ minecraft_server_dir }}/world_the_end" ]; then
cp -r "{{ minecraft_server_dir }}/world_the_end" "{{ spigot_new_version_dir }}/"
fi
if [ -d "{{ minecraft_server_dir }}/plugins" ]; then
cp -r "{{ minecraft_server_dir }}/plugins" "{{ spigot_new_version_dir }}/"
fi
become_user: "{{ minecraft_user }}"
- name: Replace server directory with new version
ansible.builtin.shell: |
rm -rf "{{ minecraft_server_dir }}.old"
mv "{{ minecraft_server_dir }}" "{{ minecraft_server_dir }}.old"
mv "{{ spigot_new_version_dir }}" "{{ minecraft_server_dir }}"
become_user: "{{ minecraft_user }}"
- name: Update version file
ansible.builtin.copy:
content: "{{ minecraft_version }}"
dest: "{{ spigot_current_version_file }}"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
- name: Start Minecraft server with new version
ansible.builtin.systemd:
name: minecraft
state: started
notify: "restart minecraft after version change"
- name: Wait for server to start
ansible.builtin.wait_for:
port: "{{ minecraft_port }}"
delay: 30
timeout: 300
- name: Verify server is running new version
ansible.builtin.shell: |
sleep 10
/usr/local/bin/mcrcon -H 127.0.0.1 -P {{ rcon_port }} -p "{{ rcon_password }}" "version"
register: version_check
failed_when: false
- name: Display version switch result
ansible.builtin.debug:
msg:
- "Version switch completed successfully"
- "Server response: {{ version_check.stdout | default('No response') }}"
- "Old version backed up to: {{ minecraft_server_dir }}.old"
- name: Clean up old version after successful switch
ansible.builtin.file:
path: "{{ minecraft_server_dir }}.old"
state: absent
when: version_check.rc == 0

View File

@@ -1,34 +1,46 @@
---
- name: Include SSH keys check tasks
include_tasks: 01-check-ssh-keys.yml
when: ssh_keys_check_enabled
tags: ['update', 'ssh-keys']
- name: Include SSH keys update tasks
ansible.builtin.include_tasks: 01-update-ssh-keys.yml
when: update_check_ssh_keys | bool
- name: Include system updates check tasks
include_tasks: 02-check-system-updates.yml
when: system_update_check_enabled
tags: ['update', 'system']
ansible.builtin.include_tasks: 02-check-system-updates.yml
when: update_check_system | bool
- name: Include Spigot version check tasks
include_tasks: 03-check-spigot-version.yml
when: spigot_update_check_enabled
tags: ['update', 'spigot']
ansible.builtin.include_tasks: 03-check-spigot-version.yml
when: update_check_spigot | bool
- name: Include new Spigot download tasks
include_tasks: 04-download-new-spigot.yml
when: new_spigot_available | default(false)
tags: ['update', 'download']
ansible.builtin.include_tasks: 04-download-new-spigot.yml
when:
- update_check_spigot | bool
- spigot_update_available is defined
- spigot_update_available | bool
- name: Include new version compilation tasks
include_tasks: 05-compile-new-version.yml
when: new_spigot_available | default(false)
tags: ['update', 'compile']
- name: Include new Spigot compilation tasks
ansible.builtin.include_tasks: 05-compile-new-spigot.yml
when:
- update_check_spigot | bool
- spigot_update_available is defined
- spigot_update_available | bool
- name: Include version switch tasks
include_tasks: 06-switch-versions.yml
when: new_spigot_compiled | default(false)
tags: ['update', 'switch']
- name: Include new version configuration tasks
ansible.builtin.include_tasks: 06-configure-new-version.yml
when:
- update_check_spigot | bool
- spigot_update_available is defined
- spigot_update_available | bool
- spigot_compilation_successful is defined
- spigot_compilation_successful | bool
- name: Include cleanup tasks
include_tasks: 07-cleanup.yml
tags: ['update', 'cleanup']
- name: Include version switching tasks
ansible.builtin.include_tasks: 07-switch-versions.yml
when:
- update_check_spigot | bool
- spigot_update_available is defined
- spigot_update_available | bool
- spigot_compilation_successful is defined
- spigot_compilation_successful | bool
- spigot_configuration_successful is defined
- spigot_configuration_successful | bool

View File

@@ -0,0 +1,18 @@
---
# Internal update variables
update_scripts:
- check-updates.sh
- apply-updates.sh
spigot_version_pattern: "spigot-(.*?)\\.jar"
system_packages_to_update:
- openjdk-17-jdk
- git
- build-essential
- rsync
- fail2ban
- ufw
# Backup retention for version backups
version_backup_retention_days: 30

0
secrets.example Normal file
View File

View File

@@ -1,11 +0,0 @@
---
- name: Deploy Minecraft Spigot Server
hosts: minecraft_servers
become: yes
serial: 1
roles:
- 01-server_hardening
- 02-installation-java
- 03-installation-minecraft
- 04-backups
- 05-update