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
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:
@@ -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: 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 .
|
||||
run: |
|
||||
yamllint -c .yamllint.yml .
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run ansible-lint
|
||||
run: ansible-lint
|
||||
run: |
|
||||
ansible-lint --project-dir . playbooks/
|
||||
continue-on-error: true
|
||||
|
||||
- name: Validate inventory files
|
||||
- name: Validate Ansible syntax
|
||||
run: |
|
||||
ansible-inventory --list -i inventories/production/hosts.yml
|
||||
ansible-inventory --list -i inventories/staging/hosts.yml
|
||||
ansible-playbook --syntax-check playbooks/site.yml -i inventories/staging/hosts.yml
|
||||
continue-on-error: true
|
||||
|
||||
deploy:
|
||||
structure-validation:
|
||||
name: Project Structure Validation
|
||||
runs-on: ubuntu-latest
|
||||
environment: ${{ github.event.inputs.environment || 'staging' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- 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: Deploy to staging
|
||||
if: ${{ github.event.inputs.environment == 'staging' || github.ref == 'refs/heads/develop' }}
|
||||
- name: Test staging connectivity
|
||||
run: |
|
||||
ansible-playbook -i inventories/staging/hosts.yml site.yml \
|
||||
--vault-password-file ~/.ansible_vault_pass \
|
||||
--private-key ~/.ssh/ansible_key
|
||||
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: 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 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
1
.yamllint.yml
Normal file
@@ -0,0 +1 @@
|
||||
.yamllint.yml
|
@@ -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
|
@@ -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
9
playbooks/hardening.yml
Normal 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']
|
9
playbooks/install-java.yml
Normal file
9
playbooks/install-java.yml
Normal 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']
|
15
playbooks/install-minecraft.yml
Normal file
15
playbooks/install-minecraft.yml
Normal 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']
|
9
playbooks/setup-backups.yml
Normal file
9
playbooks/setup-backups.yml
Normal 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
44
playbooks/site.yml
Normal 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 }}"
|
9
playbooks/update-system.yml
Normal file
9
playbooks/update-system.yml
Normal 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
8
requirements.yml
Normal 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"
|
@@ -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: []
|
@@ -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"
|
@@ -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
|
@@ -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"
|
@@ -1,7 +0,0 @@
|
||||
---
|
||||
- name: Install UFW firewall
|
||||
package:
|
||||
name: ufw
|
||||
state: present
|
||||
tags:
|
||||
- firewall-install
|
32
roles/01-server_hardening/tasks/03-firewall-setup.yml
Normal file
32
roles/01-server_hardening/tasks/03-firewall-setup.yml
Normal 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"
|
23
roles/01-server_hardening/tasks/04-fail2ban-setup.yml
Normal file
23
roles/01-server_hardening/tasks/04-fail2ban-setup.yml
Normal 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
|
@@ -1,8 +0,0 @@
|
||||
---
|
||||
- name: Install fail2ban
|
||||
package:
|
||||
name: fail2ban
|
||||
state: present
|
||||
when: fail2ban_enabled
|
||||
tags:
|
||||
- fail2ban-install
|
@@ -1,12 +0,0 @@
|
||||
---
|
||||
- name: Disable unused services
|
||||
systemd:
|
||||
name: "{{ item }}"
|
||||
state: stopped
|
||||
enabled: no
|
||||
loop:
|
||||
- bluetooth
|
||||
- cups
|
||||
ignore_errors: yes
|
||||
tags:
|
||||
- disable-services
|
20
roles/01-server_hardening/tasks/05-additional-security.yml
Normal file
20
roles/01-server_hardening/tasks/05-additional-security.yml
Normal 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'
|
17
roles/01-server_hardening/tasks/06-ssh-keys-management.yml
Normal file
17
roles/01-server_hardening/tasks/06-ssh-keys-management.yml
Normal 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
|
@@ -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
|
11
roles/01-server_hardening/templates/fail2ban-jail.local.j2
Normal file
11
roles/01-server_hardening/templates/fail2ban-jail.local.j2
Normal 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 }}
|
@@ -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
|
@@ -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
|
||||
# Security settings
|
||||
PermitEmptyPasswords no
|
||||
ChallengeResponseAuthentication no
|
||||
UsePAM yes
|
||||
X11Forwarding no
|
||||
PermitTunnel no
|
||||
GatewayPorts no
|
||||
AllowAgentForwarding no
|
||||
PrintMotd no
|
||||
AcceptEnv LANG LC_*
|
||||
Subsystem sftp /usr/lib/openssh/sftp-server
|
@@ -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
|
@@ -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
|
@@ -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"
|
||||
|
||||
# Minimum required Java version for Spigot 1.21.6
|
||||
required_java_version: "17"
|
@@ -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"
|
10
roles/02-installation-java/tasks/01-check-java-presence.yml
Normal file
10
roles/02-installation-java/tasks/01-check-java-presence.yml
Normal 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 }}"
|
@@ -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']
|
@@ -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'
|
@@ -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 }}"
|
@@ -1,6 +0,0 @@
|
||||
---
|
||||
- name: Verify Java installation
|
||||
command: java -version
|
||||
register: java_verify
|
||||
changed_when: false
|
||||
tags: ['java-verify']
|
@@ -1,7 +0,0 @@
|
||||
---
|
||||
- name: Set Java home environment variable
|
||||
lineinfile:
|
||||
path: /etc/environment
|
||||
line: "JAVA_HOME={{ java_home }}"
|
||||
state: present
|
||||
tags: ['java-validate']
|
@@ -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 }}"
|
@@ -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
|
@@ -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"
|
@@ -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: []
|
@@ -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"
|
@@ -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
|
@@ -1,6 +0,0 @@
|
||||
---
|
||||
- name: Create minecraft group
|
||||
group:
|
||||
name: "{{ minecraft_group }}"
|
||||
state: present
|
||||
tags: ['minecraft-user']
|
@@ -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"
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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'
|
@@ -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']
|
@@ -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']
|
@@ -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
|
@@ -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"
|
@@ -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"
|
@@ -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'
|
@@ -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']
|
@@ -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
|
@@ -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 }}
|
||||
}
|
@@ -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
|
@@ -1,10 +1,10 @@
|
||||
[
|
||||
{% for op in minecraft_ops | default([]) %}
|
||||
{% for op in minecraft_ops %}
|
||||
{
|
||||
"uuid": "{{ op.uuid }}",
|
||||
"name": "{{ op.name }}",
|
||||
"level": {{ op.level | default(4) }},
|
||||
"bypassesPlayerLimit": {{ op.bypass_limit | default(false) | lower }}
|
||||
"bypassesPlayerLimit": {{ op.bypass_player_limit | default(false) | ternary('true', 'false') }}
|
||||
}{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
]
|
@@ -1,24 +1,46 @@
|
||||
# Minecraft server properties
|
||||
server-name=Spigot Server
|
||||
# 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
|
@@ -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
|
@@ -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"
|
@@ -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"
|
18
roles/04-backups/tasks/01-create-backup-directories.yml
Normal file
18
roles/04-backups/tasks/01-create-backup-directories.yml
Normal 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
|
@@ -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']
|
@@ -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']
|
17
roles/04-backups/tasks/02-setup-daily-backup.yml
Normal file
17
roles/04-backups/tasks/02-setup-daily-backup.yml
Normal 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
|
@@ -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']
|
18
roles/04-backups/tasks/03-setup-weekly-backup.yml
Normal file
18
roles/04-backups/tasks/03-setup-weekly-backup.yml
Normal 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
|
18
roles/04-backups/tasks/04-setup-monthly-backup.yml
Normal file
18
roles/04-backups/tasks/04-setup-monthly-backup.yml
Normal 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
|
@@ -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']
|
38
roles/04-backups/tasks/05-setup-backup-scripts.yml
Normal file
38
roles/04-backups/tasks/05-setup-backup-scripts.yml
Normal 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'
|
8
roles/04-backups/tasks/06-setup-restore-scripts.yml
Normal file
8
roles/04-backups/tasks/06-setup-restore-scripts.yml
Normal 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'
|
@@ -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
|
@@ -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"
|
@@ -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"
|
@@ -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"
|
116
roles/04-backups/templates/restore-backup.sh.j2
Normal file
116
roles/04-backups/templates/restore-backup.sh.j2
Normal 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"
|
@@ -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}"
|
@@ -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"
|
@@ -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
|
@@ -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"
|
@@ -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']
|
16
roles/05-update/tasks/01-update-ssh-keys.yml
Normal file
16
roles/05-update/tasks/01-update-ssh-keys.yml
Normal 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
|
@@ -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
|
@@ -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 }}"
|
@@ -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'
|
||||
timeout: 300
|
||||
force: true
|
17
roles/05-update/tasks/05-compile-new-spigot.yml
Normal file
17
roles/05-update/tasks/05-compile-new-spigot.yml
Normal 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' }}"
|
@@ -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
|
1
roles/05-update/tasks/06-configure-new-version.yml
Normal file
1
roles/05-update/tasks/06-configure-new-version.yml
Normal file
@@ -0,0 +1 @@
|
||||
06-configure-new-version.yml
|
@@ -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
|
@@ -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)
|
83
roles/05-update/tasks/07-switch-versions.yml
Normal file
83
roles/05-update/tasks/07-switch-versions.yml
Normal 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
|
@@ -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
|
@@ -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
0
secrets.example
Normal file
Reference in New Issue
Block a user