check new version
Some checks failed
Ansible Minecraft Server CI/CD / lint (push) Failing after 21s
Ansible Minecraft Server CI/CD / test (push) Has been skipped
Ansible Minecraft Server CI/CD / deploy (push) Has been skipped

This commit is contained in:
2025-08-27 07:59:19 +02:00
parent 7a2ccb537b
commit 9ea9ac7254
125 changed files with 2696 additions and 1511 deletions

26
.ansible-lint Normal file
View File

@@ -0,0 +1,26 @@
---
exclude_paths:
- .gitea/
- .git/
skip_list:
- yaml[line-length]
- name[casing]
- no-changed-when
- command-instead-of-module
warn_list:
- experimental
- role-name[path]
enable_list:
- fqcn-builtins
- no-log-password
- no-same-owner
kinds:
- tasks: "**/tasks/*.yml"
- vars: "**/vars/*.yml"
- defaults: "**/defaults/*.yml"
- handlers: "**/handlers/*.yml"
- meta: "**/meta/*.yml"

View File

@@ -1,211 +1,145 @@
---
name: Ansible Minecraft CI/CD Pipeline
name: Ansible Minecraft Server CI/CD
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
ANSIBLE_FORCE_COLOR: 1
ANSIBLE_HOST_KEY_CHECKING: false
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy'
required: true
default: 'staging'
type: choice
options:
- staging
- production
jobs:
lint:
name: Ansible Lint Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install ansible ansible-lint yamllint
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ansible ansible-lint yamllint
- name: Run yamllint
run: |
yamllint -c .yamllint.yml .
continue-on-error: true
- name: Run yamllint
run: |
yamllint -c .yamllint .
continue-on-error: true
- name: Run ansible-lint
run: |
ansible-lint --project-dir . playbooks/
continue-on-error: true
- name: Run ansible-lint
run: |
ansible-lint --exclude .gitea/ .
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
- name: Validate ansible syntax
run: |
ansible-playbook site.yml --syntax-check
structure-validation:
name: Project Structure Validation
test:
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v3
- name: Validate required files
run: |
# Check main playbook exists
[ -f "playbooks/site.yml" ] || exit 1
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
# 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
- name: Install Ansible
run: |
python -m pip install --upgrade pip
pip install ansible
# 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
- name: Install Ansible collections
run: |
ansible-galaxy collection install -r requirements.yml
echo "Project structure validation passed"
- name: Test playbook structure
run: |
# Verify all roles exist
for role in 01-server_hardening 02-installation-java 03-Installation-Minecraft 04-backups 05-Update; do
if [ ! -d "roles/$role" ]; then
echo "Role $role not found"
exit 1
fi
done
security-scan:
name: Security Scan
- name: Check inventory files
run: |
ansible-inventory -i inventories/staging/hosts.yml --list
ansible-inventory -i inventories/production/hosts.yml --list
deploy:
runs-on: ubuntu-latest
needs: [lint, test]
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v3
- 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: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- 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
- name: Install Ansible
run: |
python -m pip install --upgrade pip
pip install ansible
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: [lint, structure-validation, security-scan]
if: github.ref == 'refs/heads/develop'
- name: Install collections
run: |
ansible-galaxy collection install -r requirements.yml
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ANSIBLE_SSH_KEY }}" > ~/.ssh/ansible_key
chmod 600 ~/.ssh/ansible_key
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Setup vault password
run: |
echo "${{ secrets.ANSIBLE_VAULT_PASSWORD }}" > .vault_pass
chmod 600 .vault_pass
- name: Install Ansible
run: |
pip install ansible
- name: Determine environment
id: env
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" == "refs/heads/main" ]; then
echo "environment=production" >> $GITHUB_OUTPUT
else
echo "environment=staging" >> $GITHUB_OUTPUT
fi
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ANSIBLE_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name: Deploy to environment
env:
ANSIBLE_HOST_KEY_CHECKING: false
ANSIBLE_VAULT_PASSWORD_FILE: .vault_pass
run: |
ansible-playbook \
-i inventories/${{ steps.env.outputs.environment }}/hosts.yml \
site.yml \
--limit minecraft_servers \
--diff
- 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: 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
run: |
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"
- name: Clean up
if: always()
run: |
rm -f ~/.ssh/ansible_key
rm -f .vault_pass

View File

@@ -1 +1,18 @@
.yamllint.yml
---
extends: default
rules:
line-length:
max: 150
level: warning
truthy:
allowed-values: ['true', 'false', 'yes', 'no']
comments:
min-spaces-from-content: 1
indentation:
spaces: 2
indent-sequences: true
ignore: |
.gitea/
*.md

View File

@@ -1,15 +1,21 @@
[defaults]
host_key_checking = False
inventory = inventories/production/hosts.yml
inventory = ./inventories/production/hosts.yml
remote_user = ansible
private_key_file = ~/.ssh/ansible_key
roles_path = roles
stdout_callback = yaml
roles_path = ./roles
collections_path = ./collections
retry_files_enabled = False
gathering = smart
fact_caching = memory
forks = 5
timeout = 30
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400
stdout_callback = yaml
callback_whitelist = profile_tasks
deprecation_warnings = False
command_warnings = False
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
pipelining = True
control_path = /tmp/ansible-ssh-%%h-%%p-%%r

View File

@@ -1,18 +1,31 @@
---
# Environment
environment: production
# Variables globales pour la production
ansible_user: ansible
ansible_ssh_private_key_file: ~/.ssh/ansible_key
ansible_become: true
ansible_become_method: sudo
# Minecraft Configuration
# Configuration Minecraft
minecraft_version: "1.21.6"
minecraft_memory_min: "2G"
minecraft_memory_max: "4G"
minecraft_type: "spigot"
minecraft_user: minecraft
minecraft_group: minecraft
minecraft_base_dir: /opt/minecraft
minecraft_server_dir: /opt/minecraft/server
minecraft_sources_dir: /opt/minecraft/sources
minecraft_tools_dir: /opt/minecraft/tools
minecraft_backup_dir: /opt/minecraft/backups
# Security
ssh_port: 22
fail2ban_enabled: true
firewall_enabled: true
# Configuration Java
java_version: 21
java_vendor: openjdk
# Backup settings
backup_retention_days: 30
backup_retention_weeks: 12
backup_retention_months: 6
# Configuration Réseau
server_port: 25565
rcon_port: 25575
enable_rcon: true
# Configuration Backup
backup_retention_daily: 7
backup_retention_weekly: 4
backup_retention_monthly: 3

View File

@@ -4,10 +4,12 @@ all:
minecraft_servers:
hosts:
minecraft-prod-01:
ansible_host: 192.168.1.100
ansible_host: 192.168.1.10
ansible_user: ansible
ansible_ssh_private_key_file: ~/.ssh/ansible_key
minecraft-prod-02:
ansible_host: 192.168.1.101
ansible_host: 192.168.1.11
ansible_user: ansible
ansible_ssh_private_key_file: ~/.ssh/ansible_key
vars:
environment: production
minecraft_memory: 4096
minecraft_port: 25565

View File

@@ -1,18 +1,31 @@
---
# Environment
environment: staging
# Variables globales pour le staging
ansible_user: ansible
ansible_ssh_private_key_file: ~/.ssh/ansible_key
ansible_become: true
ansible_become_method: sudo
# Minecraft Configuration
# Configuration Minecraft (staging)
minecraft_version: "1.21.6"
minecraft_memory_min: "1G"
minecraft_memory_max: "2G"
minecraft_type: "spigot"
minecraft_user: minecraft
minecraft_group: minecraft
minecraft_base_dir: /opt/minecraft
minecraft_server_dir: /opt/minecraft/server
minecraft_sources_dir: /opt/minecraft/sources
minecraft_tools_dir: /opt/minecraft/tools
minecraft_backup_dir: /opt/minecraft/backups
# Security
ssh_port: 22
fail2ban_enabled: true
firewall_enabled: true
# Configuration Java
java_version: 21
java_vendor: openjdk
# Backup settings
backup_retention_days: 7
backup_retention_weeks: 4
backup_retention_months: 2
# Configuration Réseau
server_port: 25565
rcon_port: 25575
enable_rcon: true
# Configuration Backup
backup_retention_daily: 3
backup_retention_weekly: 2
backup_retention_monthly: 1

View File

@@ -4,6 +4,9 @@ all:
minecraft_servers:
hosts:
minecraft-staging-01:
ansible_host: 192.168.1.200
ansible_host: 192.168.2.10
ansible_user: ansible
ansible_ssh_private_key_file: ~/.ssh/ansible_key
vars:
environment: staging
minecraft_memory: 2048
minecraft_port: 25565

View File

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

View File

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

View File

@@ -1,15 +0,0 @@
---
- 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

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

View File

@@ -1,44 +0,0 @@
---
- 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

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

View File

@@ -1,8 +1,8 @@
---
collections:
- name: community.general
version: ">=7.0.0"
- name: ansible.posix
version: ">=1.5.0"
- name: community.crypto
version: ">=2.15.0"
version: ">=1.5.4"
- name: community.general
version: ">=8.0.0"
roles: []

View File

@@ -1,22 +1,36 @@
---
# SSH Configuration
# Configuration SSH par défaut
ssh_port: 22
ssh_permit_root_login: false
ssh_password_authentication: false
ssh_permit_root_login: "no"
ssh_password_authentication: "no"
ssh_pubkey_authentication: "yes"
ssh_max_auth_tries: 3
ssh_max_sessions: 10
ssh_client_alive_interval: 300
ssh_client_alive_count_max: 2
# Firewall Configuration
firewall_allowed_ports:
- "{{ ssh_port }}/tcp"
- "25565/tcp" # Minecraft default port
# Configuration Firewall
firewall_allowed_tcp_ports:
- 22
- 25565
- 25575
firewall_allowed_udp_ports: []
# Fail2ban Configuration
fail2ban_jail_ssh_enabled: true
fail2ban_jail_ssh_port: "{{ ssh_port }}"
fail2ban_jail_ssh_maxretry: 3
fail2ban_jail_ssh_bantime: 600
# Configuration Fail2ban
fail2ban_enabled: true
fail2ban_bantime: 3600
fail2ban_findtime: 600
fail2ban_maxretry: 5
# System users
# Paquets de sécurité à installer
security_packages:
- ufw
- fail2ban
- unattended-upgrades
- apt-listchanges
- logwatch
- rkhunter
- chkrootkit
# Administrateurs SSH
admin_users: []

View File

@@ -1,17 +1,23 @@
---
- name: restart ssh
ansible.builtin.systemd:
name: ssh
name: sshd
state: restarted
listen: "restart ssh service"
daemon_reload: true
listen: restart ssh service
- name: restart fail2ban
ansible.builtin.systemd:
name: fail2ban
state: restarted
listen: "restart fail2ban service"
daemon_reload: true
listen: restart fail2ban service
- name: reload ufw
community.general.ufw:
state: reloaded
listen: "reload firewall"
listen: reload firewall
- name: reload sysctl
ansible.builtin.command: sysctl -p
listen: reload sysctl settings

View File

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

View File

@@ -0,0 +1,14 @@
---
- name: Upgrade all packages
ansible.builtin.apt:
upgrade: dist
autoremove: yes
autoclean: yes
when: ansible_os_family == "Debian"
register: system_upgraded
- name: Install security packages
ansible.builtin.apt:
name: "{{ security_packages }}"
state: present
when: ansible_os_family == "Debian"

View File

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

View File

@@ -0,0 +1,11 @@
---
- name: Configure SSH daemon
ansible.builtin.template:
src: sshd_config.j2
dest: "{{ ssh_config_file }}"
owner: root
group: root
mode: '0600'
backup: yes
validate: '/usr/sbin/sshd -t -f %s'
notify: restart ssh service

View File

@@ -1,32 +0,0 @@
---
- 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,27 @@
---
- name: Install UFW firewall
ansible.builtin.apt:
name: ufw
state: present
when: ansible_os_family == "Debian"
- name: Configure UFW defaults
community.general.ufw:
direction: "{{ item.direction }}"
policy: "{{ item.policy }}"
loop:
- { direction: 'incoming', policy: 'deny' }
- { direction: 'outgoing', policy: 'allow' }
notify: reload firewall
- name: Allow TCP ports
community.general.ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop: "{{ firewall_allowed_tcp_ports }}"
notify: reload firewall
- name: Enable UFW
community.general.ufw:
state: enabled

View File

@@ -1,20 +0,0 @@
---
- 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

@@ -3,21 +3,21 @@
ansible.builtin.apt:
name: fail2ban
state: present
when: fail2ban_enabled | bool
when: ansible_os_family == "Debian"
- name: Configure fail2ban jail
ansible.builtin.template:
src: fail2ban-jail.local.j2
dest: /etc/fail2ban/jail.local
src: fail2ban.jail.local.j2
dest: "{{ fail2ban_config_dir }}/jail.local"
owner: root
group: root
mode: '0644'
when: fail2ban_enabled | bool
notify: "restart fail2ban service"
backup: yes
notify: restart fail2ban service
- name: Start and enable fail2ban
- name: Ensure fail2ban is started and enabled
ansible.builtin.systemd:
name: fail2ban
state: started
enabled: true
when: fail2ban_enabled | bool
enabled: yes
daemon_reload: yes

View File

@@ -0,0 +1,17 @@
---
- name: Create .ssh directory for ansible user
ansible.builtin.file:
path: /home/ansible/.ssh
state: directory
owner: ansible
group: ansible
mode: '0700'
- name: Add SSH keys for administrators
ansible.posix.authorized_key:
user: ansible
state: present
key: "{{ item.key }}"
comment: "{{ item.name }}"
loop: "{{ admin_ssh_keys | default([]) }}"
when: admin_ssh_keys is defined

View File

@@ -1,17 +0,0 @@
---
- 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

@@ -0,0 +1,9 @@
---
- name: Configure kernel parameters for security
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
reload: yes
loop: "{{ hardening_sysctl_settings }}"
notify: reload sysctl settings

View File

@@ -1,18 +1,23 @@
---
- name: Include system update tasks
ansible.builtin.include_tasks: 01-system-update.yml
- name: restart ssh
ansible.builtin.systemd:
name: sshd
state: restarted
daemon_reload: true
listen: restart ssh service
- name: Include SSH hardening tasks
ansible.builtin.include_tasks: 02-ssh-hardening.yml
- name: restart fail2ban
ansible.builtin.systemd:
name: fail2ban
state: restarted
daemon_reload: true
listen: restart fail2ban service
- name: Include firewall setup tasks
ansible.builtin.include_tasks: 03-firewall-setup.yml
- name: reload ufw
community.general.ufw:
state: reloaded
listen: reload firewall
- name: Include fail2ban setup tasks
ansible.builtin.include_tasks: 04-fail2ban-setup.yml
- 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
- name: reload sysctl
ansible.builtin.command: sysctl -p
listen: reload sysctl settings

View File

@@ -1,11 +1,30 @@
# {{ ansible_managed }}
[DEFAULT]
bantime = {{ fail2ban_jail_ssh_bantime }}
findtime = 600
maxretry = {{ fail2ban_jail_ssh_maxretry }}
ignoreip = 127.0.0.1/8 ::1
bantime = {{ fail2ban_bantime }}
findtime = {{ fail2ban_findtime }}
maxretry = {{ fail2ban_maxretry }}
backend = systemd
[sshd]
enabled = {{ fail2ban_jail_ssh_enabled | ternary('true', 'false') }}
port = {{ fail2ban_jail_ssh_port }}
enabled = true
port = {{ ssh_port }}
filter = sshd
logpath = /var/log/auth.log
maxretry = {{ fail2ban_jail_ssh_maxretry }}
maxretry = {{ fail2ban_maxretry }}
[sshd-ddos]
enabled = true
port = {{ ssh_port }}
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 10
[minecraft]
enabled = true
port = {{ minecraft_port | default(25565) }}
filter = minecraft
logpath = {{ minecraft_server_dir | default('/opt/minecraft/server') }}/logs/latest.log
maxretry = 10
findtime = 600
bantime = 3600

View File

@@ -1,25 +1,47 @@
# SSH Configuration - Managed by Ansible
# {{ ansible_managed }}
# SSH Server Configuration
Port {{ ssh_port }}
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
# Logging
SyslogFacility AUTH
LogLevel INFO
# Authentication
PermitRootLogin {{ ssh_permit_root_login | ternary('yes', 'no') }}
PasswordAuthentication {{ ssh_password_authentication | ternary('yes', 'no') }}
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
LoginGraceTime 120
PermitRootLogin {{ ssh_permit_root_login }}
StrictModes yes
MaxAuthTries {{ ssh_max_auth_tries }}
MaxSessions {{ ssh_max_sessions }}
# Connection settings
ClientAliveInterval {{ ssh_client_alive_interval }}
ClientAliveCountMax {{ ssh_client_alive_count_max }}
MaxSessions 10
MaxStartups 10:30:60
PubkeyAuthentication {{ ssh_pubkey_authentication }}
AuthorizedKeysFile .ssh/authorized_keys
# Security settings
PasswordAuthentication {{ ssh_password_authentication }}
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
# Security
IgnoreRhosts yes
HostbasedAuthentication no
X11Forwarding no
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
Compression delayed
# Client alive
ClientAliveInterval {{ ssh_client_alive_interval }}
ClientAliveCountMax {{ ssh_client_alive_count_max }}
# Allow only ansible user
AllowUsers ansible
# Disable unused features
UsePAM yes
Banner none
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server

View File

@@ -0,0 +1,16 @@
# {{ ansible_managed }}
# UFW Rules Configuration
# Allow SSH
-A ufw-user-input -p tcp --dport {{ ssh_port }} -j ACCEPT
# Allow Minecraft
-A ufw-user-input -p tcp --dport {{ minecraft_port | default(25565) }} -j ACCEPT
# Allow RCON if enabled
{% if enable_rcon | default(false) %}
-A ufw-user-input -p tcp --dport {{ rcon_port | default(25575) }} -j ACCEPT
{% endif %}
# Drop everything else
-A ufw-user-input -j DROP

View File

@@ -1,13 +1,24 @@
---
# Internal variables for server hardening
security_packages:
- ufw
- fail2ban
- unattended-upgrades
- logwatch
- rkhunter
- chkrootkit
# Variables spécifiques au rôle server_hardening
hardening_sysctl_settings:
- name: net.ipv4.tcp_syncookies
value: 1
- name: net.ipv4.conf.all.rp_filter
value: 1
- name: net.ipv4.conf.default.rp_filter
value: 1
- name: net.ipv4.conf.all.accept_source_route
value: 0
- name: net.ipv4.conf.default.accept_source_route
value: 0
- name: net.ipv4.icmp_echo_ignore_broadcasts
value: 1
- name: net.ipv4.icmp_ignore_bogus_error_responses
value: 1
- name: net.ipv4.conf.all.log_martians
value: 1
- name: net.ipv4.conf.default.log_martians
value: 1
required_directories:
- /var/log/security
- /etc/security/limits.d
ssh_config_file: /etc/ssh/sshd_config
fail2ban_config_dir: /etc/fail2ban

View File

@@ -1,8 +1,5 @@
---
# 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"
java_version: 21
java_vendor: openjdk
java_home: /usr/lib/jvm/java-{{ java_version }}-openjdk-amd64
java_bin_path: "{{ java_home }}/bin"

View File

@@ -1,6 +1,8 @@
---
- 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"
ansible.builtin.command: update-alternatives --config java
listen: update java configuration
- name: reload environment
ansible.builtin.command: source /etc/environment
listen: reload system environment

View File

@@ -1,10 +0,0 @@
---
- 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,21 +0,0 @@
---
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
when: ansible_os_family == "Debian"
- name: Install OpenJDK
ansible.builtin.apt:
name: "{{ java_package }}"
state: present
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,21 @@
---
- name: Remove old Java versions
ansible.builtin.apt:
name: "{{ item }}"
state: absent
purge: yes
loop:
- openjdk-8-jdk
- openjdk-8-jre
- openjdk-11-jdk
- openjdk-11-jre
- openjdk-17-jdk
- openjdk-17-jre
when: ansible_os_family == "Debian"
ignore_errors: yes
- name: Clean apt cache after removal
ansible.builtin.apt:
autoclean: yes
autoremove: yes
when: ansible_os_family == "Debian"

View File

@@ -0,0 +1,24 @@
---
- name: Add Java repository for Ubuntu
ansible.builtin.apt_repository:
repo: "{{ java_apt_repository.ubuntu }}"
state: present
when: ansible_distribution == "Ubuntu"
- name: Add backports repository for Debian
ansible.builtin.apt_repository:
repo: "{{ java_apt_repository.debian }}"
state: present
when: ansible_distribution == "Debian"
- name: Update apt cache
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
when: ansible_os_family == "Debian"
- name: Install Java packages
ansible.builtin.apt:
name: "{{ java_packages[ansible_distribution | lower] }}"
state: present
when: ansible_os_family == "Debian"

View File

@@ -1,10 +0,0 @@
---
- 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

@@ -0,0 +1,27 @@
---
- name: Set JAVA_HOME environment variable
ansible.builtin.lineinfile:
path: /etc/environment
line: "JAVA_HOME={{ java_home }}"
create: yes
state: present
- name: Add Java to PATH
ansible.builtin.lineinfile:
path: /etc/environment
line: 'PATH="{{ java_bin_path }}:$PATH"'
state: present
- name: Create Java profile script
ansible.builtin.template:
src: java.sh.j2
dest: /etc/profile.d/java.sh
owner: root
group: root
mode: '0644'
- name: Set default Java version
ansible.builtin.alternatives:
name: java
path: "{{ java_home }}/bin/java"
notify: update java configuration

View File

@@ -1,15 +0,0 @@
---
- 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

@@ -0,0 +1,21 @@
---
- name: Verify Java installation
ansible.builtin.command: "{{ java_home }}/bin/java -version"
register: java_version_output
changed_when: false
- name: Display Java version
ansible.builtin.debug:
msg: "Java version installed: {{ java_version_output.stderr_lines[0] }}"
- name: Verify Java compiler
ansible.builtin.command: "{{ java_home }}/bin/javac -version"
register: javac_version_output
changed_when: false
- name: Validate Java version matches requirement
ansible.builtin.assert:
that:
- "'{{ java_version }}' in java_version_output.stderr"
fail_msg: "Java version {{ java_version }} not properly installed"
success_msg: "Java version {{ java_version }} successfully installed"

View File

@@ -0,0 +1,6 @@
---
- name: Check if Java is installed
ansible.builtin.command: java -version
register: java_installed
failed_when: false
changed_when: false

View File

@@ -1,13 +1,17 @@
---
- name: Include Java presence check tasks
ansible.builtin.include_tasks: 01-check-java-presence.yml
- name: Include check Java tasks
ansible.builtin.include_tasks: 01-check-java.yml
- name: Include Java installation tasks
ansible.builtin.include_tasks: 02-install-java.yml
when: java_needs_installation | default(true)
- name: Include remove old Java tasks
ansible.builtin.include_tasks: 02-remove-old-java.yml
when: java_needs_update | default(false)
- name: Include Java installation verification tasks
ansible.builtin.include_tasks: 03-verify-java-installation.yml
- name: Include install Java tasks
ansible.builtin.include_tasks: 03-install-java.yml
when: java_not_installed | default(false) or java_needs_update | default(false)
- name: Include Java version validation tasks
ansible.builtin.include_tasks: 04-validate-java-version.yml
- name: Include configure Java tasks
ansible.builtin.include_tasks: 04-configure-java.yml
- name: Include validate installation tasks
ansible.builtin.include_tasks: 05-validate-installation.yml

View File

@@ -0,0 +1,5 @@
#!/bin/bash
# {{ ansible_managed }}
export JAVA_HOME={{ java_home }}
export PATH=$JAVA_HOME

View File

@@ -1,14 +1,12 @@
---
# Java installation variables
supported_java_versions:
- "17"
- "18"
- "19"
- "20"
- "21"
java_packages:
debian:
- "openjdk-{{ java_version }}-jdk"
- "openjdk-{{ java_version }}-jre"
ubuntu:
- "openjdk-{{ java_version }}-jdk"
- "openjdk-{{ java_version }}-jre"
java_compatibility_matrix:
"1.21.6": "17"
"1.21.5": "17"
"1.21.4": "17"
"1.21.3": "17"
java_apt_repository:
debian: "deb http://deb.debian.org/debian {{ ansible_distribution_release }}-backports main"
ubuntu: "ppa:openjdk-r/ppa"

View File

@@ -1,35 +1,57 @@
---
# Minecraft user and group
# Utilisateur et groupe
minecraft_user: minecraft
minecraft_group: minecraft
# Minecraft directories
# Répertoires
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_server_dir: /opt/minecraft/server
minecraft_sources_dir: /opt/minecraft/sources
minecraft_tools_dir: /opt/minecraft/tools
# Minecraft configuration
# Version et mémoire
minecraft_version: "1.21.6"
minecraft_memory_min: "1G"
minecraft_memory_max: "2G"
minecraft_port: 25565
minecraft_eula: true
minecraft_memory_min: 1024
minecraft_memory_max: 4096
# Server properties
# URLs de téléchargement
minecraft_build_tools_url: "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
mcrcon_url: "https://github.com/Tiiffi/mcrcon/releases/latest/download/mcrcon-linux-x86_64.tar.gz"
# Configuration serveur
server_name: "Minecraft Server"
server_motd: "A Minecraft Server"
server_port: 25565
max_players: 20
difficulty: "normal"
gamemode: "survival"
pvp_enabled: true
# MCRCON configuration
mcrcon_version: "0.7.2"
rcon_enabled: true
view_distance: 10
gamemode: survival
difficulty: normal
enable_command_block: false
enable_rcon: true
rcon_port: 25575
rcon_password: "changeme"
rcon_password: "{{ vault_rcon_password | default('ChangeMe123!') }}"
online_mode: true
pvp: true
white_list: false
spawn_protection: 16
max_world_size: 29999984
level_seed: ""
level_type: "DEFAULT"
generate_structures: true
spawn_animals: true
spawn_monsters: true
spawn_npcs: true
# Default operators (will be populated from ops_list variable)
# Service
minecraft_service_name: minecraft.service
minecraft_service_enabled: true
minecraft_service_state: started
# Plugins par défaut
minecraft_plugins_list:
- name: "EssentialsX"
url: "https://github.com/EssentialsX/Essentials/releases/latest/download/EssentialsX.jar"
- name: "Vault"
url: "https://github.com/MilkBowl/Vault/releases/latest/download/Vault.jar"
# Opérateurs
minecraft_ops: []

View File

@@ -1,18 +1,24 @@
---
- name: restart minecraft
ansible.builtin.systemd:
name: minecraft
name: "{{ minecraft_service_name }}"
state: restarted
daemon_reload: true
listen: "restart minecraft service"
listen: restart minecraft server
- name: reload minecraft
ansible.builtin.systemd:
name: "{{ minecraft_service_name }}"
state: reloaded
listen: reload minecraft server
- name: reload systemd
ansible.builtin.systemd:
daemon_reload: true
listen: "systemd daemon reload"
listen: reload systemd daemon
- name: restart logrotate
- name: restart rsyslog
ansible.builtin.systemd:
name: logrotate
name: rsyslog
state: restarted
listen: "restart log rotation"
listen: restart rsyslog service

View File

@@ -0,0 +1,31 @@
---
galaxy_info:
author: Tips-Of-Mine
description: Installation et configuration complète d'un serveur Minecraft Spigot
company: Tips-Of-Mine
license: MIT
min_ansible_version: "2.14"
platforms:
- name: Debian
versions:
- bullseye # 11
- bookworm # 12
- trixie # 13
- buster # 10
- name: Ubuntu
versions:
- focal # 20.04
- jammy # 22.04
- noble # 24.04
galaxy_tags:
- minecraft
- spigot
- gaming
- server
- java
- backup
- monitoring
dependencies:
- role: 02-installation-java
when: java_required | default(true)

View File

@@ -3,13 +3,21 @@
ansible.builtin.group:
name: "{{ minecraft_group }}"
state: present
system: yes
- name: Create minecraft user
ansible.builtin.user:
name: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
groups: []
append: no
home: "{{ minecraft_base_dir }}"
shell: /bin/bash
system: true
create_home: false
system: yes
create_home: yes
state: present
comment: "Minecraft Server User"
- name: Set minecraft user password to never expire
ansible.builtin.command: chage -M -1 {{ minecraft_user }}
changed_when: false

View File

@@ -1,16 +1,25 @@
---
- name: Create minecraft base directories
- name: Create minecraft directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
loop:
- "{{ minecraft_base_dir }}"
- "{{ minecraft_sources_dir }}"
- "{{ minecraft_server_dir }}"
- "{{ minecraft_tools_dir }}"
- "{{ minecraft_plugins_dir }}"
- "{{ minecraft_base_dir }}/logs"
- "{{ minecraft_base_dir }}/backups"
loop: "{{ minecraft_dirs }}"
- name: Create .ssh directory for minecraft user
ansible.builtin.file:
path: "{{ minecraft_base_dir }}/.ssh"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0700'
- name: Set correct permissions on base directory
ansible.builtin.file:
path: "{{ minecraft_base_dir }}"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
recurse: yes

View File

@@ -1,9 +1,30 @@
---
- name: Install required packages for building
ansible.builtin.apt:
name: "{{ build_packages }}"
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: Check if BuildTools already exists
ansible.builtin.stat:
path: "{{ minecraft_sources_dir }}/{{ buildtools_jar }}"
register: buildtools_exists
- 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"
url: "{{ minecraft_build_tools_url }}"
dest: "{{ minecraft_sources_dir }}/{{ buildtools_jar }}"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
timeout: 300
force: yes
when: not buildtools_exists.stat.exists or force_download | default(false)
- name: Create work directory for compilation
ansible.builtin.file:
path: "{{ minecraft_sources_dir }}/work"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'

View File

@@ -0,0 +1,52 @@
---
- name: Check if Spigot is already compiled
ansible.builtin.stat:
path: "{{ minecraft_sources_dir }}/{{ spigot_jar_name }}"
register: spigot_compiled
- name: Remove old work directory if exists
ansible.builtin.file:
path: "{{ minecraft_sources_dir }}/work"
state: absent
when: not spigot_compiled.stat.exists
- name: Compile Spigot with BuildTools
ansible.builtin.shell: |
cd {{ minecraft_sources_dir }}
java -Xmx1024M -jar {{ buildtools_jar }} --rev {{ minecraft_version }} --compile-if-changed
args:
creates: "{{ minecraft_sources_dir }}/{{ spigot_jar_name }}"
become_user: "{{ minecraft_user }}"
when: not spigot_compiled.stat.exists
register: compile_result
async: 1800
poll: 30
- name: Wait for compilation to complete
ansible.builtin.async_status:
jid: "{{ compile_result.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 60
delay: 30
when: compile_result.ansible_job_id is defined
- name: Verify Spigot jar was created
ansible.builtin.stat:
path: "{{ minecraft_sources_dir }}/{{ spigot_jar_name }}"
register: spigot_jar_check
failed_when: not spigot_jar_check.stat.exists
- name: Copy compiled Spigot to server directory
ansible.builtin.copy:
src: "{{ minecraft_sources_dir }}/{{ spigot_jar_name }}"
dest: "{{ minecraft_server_dir }}/{{ spigot_jar_name }}"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
remote_src: yes
- name: Clean up work directory
ansible.builtin.file:
path: "{{ minecraft_sources_dir }}/work"
state: absent

View File

@@ -1,32 +0,0 @@
---
- name: Install packages needed for MCRCON compilation
ansible.builtin.apt:
name:
- git
- build-essential
state: present
- 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 +0,0 @@
---
- 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"
register: spigot_compilation
timeout: 1800
- name: Copy compiled Spigot to server directory
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: true

View File

@@ -0,0 +1,57 @@
---
- 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'
backup: yes
- name: Accept EULA
ansible.builtin.template:
src: eula.txt.j2
dest: "{{ minecraft_server_dir }}/eula.txt"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
- name: Create spigot.yml configuration
ansible.builtin.template:
src: spigot.yml.j2
dest: "{{ minecraft_server_dir }}/spigot.yml"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
- name: Create bukkit.yml configuration
ansible.builtin.template:
src: bukkit.yml.j2
dest: "{{ minecraft_server_dir }}/bukkit.yml"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
- name: Create start script
ansible.builtin.template:
src: start.sh.j2
dest: "{{ minecraft_base_dir }}/scripts/start.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Create stop script
ansible.builtin.template:
src: stop.sh.j2
dest: "{{ minecraft_base_dir }}/scripts/stop.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Store current version
ansible.builtin.copy:
content: "{{ minecraft_version }}"
dest: "{{ minecraft_server_dir }}/.version"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'

View File

@@ -1,17 +0,0 @@
---
- 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

@@ -0,0 +1,46 @@
---
- name: Check if mcrcon is already installed
ansible.builtin.stat:
path: "{{ minecraft_tools_dir }}/mcrcon"
register: mcrcon_installed
- name: Download mcrcon
ansible.builtin.get_url:
url: "{{ mcrcon_url }}"
dest: "{{ minecraft_tools_dir }}/mcrcon.tar.gz"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
when: not mcrcon_installed.stat.exists
- name: Extract mcrcon
ansible.builtin.unarchive:
src: "{{ minecraft_tools_dir }}/mcrcon.tar.gz"
dest: "{{ minecraft_tools_dir }}"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
remote_src: yes
creates: "{{ minecraft_tools_dir }}/mcrcon"
when: not mcrcon_installed.stat.exists
- name: Make mcrcon executable
ansible.builtin.file:
path: "{{ minecraft_tools_dir }}/mcrcon"
mode: '0755'
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
- name: Create mcrcon wrapper script
ansible.builtin.copy:
content: |
#!/bin/bash
{{ minecraft_tools_dir }}/mcrcon -H localhost -P {{ rcon_port }} -p "{{ rcon_password }}" "$@"
dest: "{{ minecraft_base_dir }}/scripts/rcon.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Clean up mcrcon archive
ansible.builtin.file:
path: "{{ minecraft_tools_dir }}/mcrcon.tar.gz"
state: absent

View File

@@ -0,0 +1,36 @@
---
- name: Create minecraft systemd service
ansible.builtin.template:
src: minecraft.service.j2
dest: "/etc/systemd/system/{{ minecraft_service_name }}"
owner: root
group: root
mode: '0644'
notify:
- reload systemd daemon
- restart minecraft server
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: yes
- name: Enable minecraft service
ansible.builtin.systemd:
name: "{{ minecraft_service_name }}"
enabled: "{{ minecraft_service_enabled }}"
masked: no
- name: Start minecraft service
ansible.builtin.systemd:
name: "{{ minecraft_service_name }}"
state: "{{ minecraft_service_state }}"
when: minecraft_service_state == "started"
- name: Wait for server to be ready
ansible.builtin.wait_for:
port: "{{ server_port }}"
delay: 10
timeout: 120
state: started
host: 127.0.0.1
when: minecraft_service_state == "started"

View File

@@ -1,17 +0,0 @@
---
- 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

@@ -0,0 +1,36 @@
---
- name: Configure logrotate for minecraft logs
ansible.builtin.template:
src: minecraft-logrotate.j2
dest: /etc/logrotate.d/minecraft
owner: root
group: root
mode: '0644'
- name: Create rsyslog configuration for minecraft
ansible.builtin.copy:
content: |
# Minecraft Server Logging
:programname, isequal, "minecraft" /var/log/minecraft.log
& stop
dest: /etc/rsyslog.d/30-minecraft.conf
owner: root
group: root
mode: '0644'
notify: restart rsyslog service
- name: Create minecraft log file
ansible.builtin.file:
path: /var/log/minecraft.log
state: touch
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
modification_time: preserve
access_time: preserve
- name: Test logrotate configuration
ansible.builtin.command: logrotate -d /etc/logrotate.d/minecraft
register: logrotate_test
changed_when: false
failed_when: logrotate_test.rc != 0

View File

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

View File

@@ -0,0 +1,32 @@
---
- name: Check if ops.json exists
ansible.builtin.stat:
path: "{{ minecraft_server_dir }}/ops.json"
register: ops_file
- 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'
backup: yes
when: minecraft_ops is defined and minecraft_ops | length > 0
- name: Create empty ops.json if no ops defined
ansible.builtin.copy:
content: "[]"
dest: "{{ minecraft_server_dir }}/ops.json"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
force: no
when: not ops_file.stat.exists and (minecraft_ops is not defined or minecraft_ops | length == 0)
- name: Set permissions on ops.json
ansible.builtin.file:
path: "{{ minecraft_server_dir }}/ops.json"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'

View File

@@ -1,10 +0,0 @@
---
- 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'
when: minecraft_ops is defined and minecraft_ops | length > 0
notify: "restart minecraft service"

View File

@@ -0,0 +1,39 @@
---
- name: Create plugins directory
ansible.builtin.file:
path: "{{ minecraft_server_dir }}/plugins"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Download plugins
ansible.builtin.get_url:
url: "{{ item.url }}"
dest: "{{ minecraft_server_dir }}/plugins/{{ item.name }}.jar"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0644'
timeout: 30
loop: "{{ minecraft_plugins_list }}"
when: minecraft_plugins_list is defined and minecraft_plugins_list | length > 0
ignore_errors: yes
- name: Create plugins config directory
ansible.builtin.file:
path: "{{ minecraft_server_dir }}/plugins/{{ item.name }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
loop: "{{ minecraft_plugins_list }}"
when: minecraft_plugins_list is defined and item.create_config_dir | default(false)
- name: Restart server to load new plugins
ansible.builtin.systemd:
name: "{{ minecraft_service_name }}"
state: restarted
when:
- minecraft_plugins_list is defined
- minecraft_plugins_list | length > 0
- restart_after_plugins | default(false)

View File

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

View File

@@ -0,0 +1,12 @@
[
{% for ip in minecraft_banned_ips | default([]) %}
{
"ip": "{{ ip.address }}",
"created": "{{ ip.created | default(ansible_date_time.iso8601) }}",
"source": "{{ ip.source | default('Server') }}",
"expires": "{{ ip.expires | default('forever') }}",
"reason": "{{ ip.reason | default('Banned by administrator') }}"
}{% if not loop.last %},{% endif %}
{% endfor %}
]

View File

@@ -0,0 +1,13 @@
[
{% for player in minecraft_banned_players | default([]) %}
{
"uuid": "{{ player.uuid }}",
"name": "{{ player.name }}",
"created": "{{ player.created | default(ansible_date_time.iso8601) }}",
"source": "{{ player.source | default('Server') }}",
"expires": "{{ player.expires | default('forever') }}",
"reason": "{{ player.reason | default('Banned by administrator') }}"
}{% if not loop.last %},{% endif %}
{% endfor %}
]

View File

@@ -0,0 +1,39 @@
# {{ ansible_managed }}
# This is the main configuration file for Bukkit.
# Bukkit version: {{ minecraft_version }}
settings:
allow-end: true
warn-on-overload: true
permissions-file: permissions.yml
update-folder: update
plugin-profiling: false
connection-throttle: 4000
query-plugins: true
deprecated-verbose: default
shutdown-message: Server closed
minimum-api: none
spawn-limits:
monsters: 70
animals: 10
water-animals: 5
water-ambient: 20
water-underground-creature: 5
axolotls: 5
ambient: 15
chunk-gc:
period-in-ticks: 600
ticks-per:
animal-spawns: 400
monster-spawns: 1
water-spawns: 1
water-ambient-spawns: 1
water-underground-creature-spawns: 1
axolotl-spawns: 1
ambient-spawns: 1
autosave: 6000
aliases: now-in-commands.yml

View File

@@ -0,0 +1,4 @@
# {{ ansible_managed }}
# By changing the setting below to TRUE you are indicating your agreement to our EULA (https://aka.ms/MinecraftEULA).
# Generated on {{ ansible_date_time.iso8601 }}
eula=true

View File

@@ -1,21 +1,30 @@
{{ minecraft_base_dir }}/logs/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
copytruncate
su {{ minecraft_user }} {{ minecraft_group }}
}
# {{ ansible_managed }}
{{ minecraft_server_dir }}/logs/*.log {
daily
missingok
rotate 30
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
su {{ minecraft_user }} {{ minecraft_group }}
create 0644 {{ minecraft_user }} {{ minecraft_group }}
sharedscripts
postrotate
# Demander au serveur de recharger les logs
if systemctl is-active --quiet {{ minecraft_service_name }}; then
{{ minecraft_tools_dir }}/mcrcon -H localhost -P {{ rcon_port }} -p "{{ rcon_password }}" "say Rotation des logs effectuée" > /dev/null 2>&1 || true
fi
endscript
}
/var/log/minecraft.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 0644 {{ minecraft_user }} {{ minecraft_group }}
postrotate
systemctl reload rsyslog > /dev/null 2>&1 || true
endscript
}

View File

@@ -0,0 +1,64 @@
#!/bin/bash
# {{ ansible_managed }}
# Script de backup intégré pour Minecraft
BACKUP_DIR="{{ minecraft_backup_dir | default('/opt/minecraft/backups') }}"
SERVER_DIR="{{ minecraft_server_dir }}"
MCRCON="{{ minecraft_tools_dir }}/mcrcon"
RCON_PORT="{{ rcon_port }}"
RCON_PASS="{{ rcon_password }}"
DATE=$(date +%Y%m%d_%H%M%S)
# Créer le répertoire de backup si nécessaire
mkdir -p "$BACKUP_DIR"
# Fonction pour envoyer des commandes RCON
send_command() {
$MCRCON -H localhost -P $RCON_PORT -p "$RCON_PASS" "$1" 2>/dev/null
}
# Fonction de backup
perform_backup() {
echo "[$(date)] Démarrage du backup..."
# Avertir les joueurs
send_command "say Backup automatique dans 10 secondes..."
sleep 5
send_command "say Backup en cours, lag possible..."
# Forcer la sauvegarde
send_command "save-all flush"
sleep 2
# Désactiver l'auto-save temporairement
send_command "save-off"
# Créer le backup
tar -czf "$BACKUP_DIR/minecraft_backup_$DATE.tar.gz" \
-C "$(dirname $SERVER_DIR)" \
"$(basename $SERVER_DIR)" \
--exclude='*.log' \
--exclude='logs/*.gz' \
--exclude='crash-reports/*'
# Réactiver l'auto-save
send_command "save-on"
# Informer les joueurs
send_command "say Backup terminé!"
echo "[$(date)] Backup créé: minecraft_backup_$DATE.tar.gz"
# Nettoyer les vieux backups (garder les 7 derniers)
ls -t "$BACKUP_DIR"/minecraft_backup_*.tar.gz 2>/dev/null | tail -n +8 | xargs rm -f
}
# Vérifier si le serveur est actif
if systemctl is-active --quiet {{ minecraft_service_name }}; then
perform_backup
else
echo "[$(date)] Serveur inactif, backup sans RCON..."
tar -czf "$BACKUP_DIR/minecraft_backup_offline_$DATE.tar.gz" \
-C "$(dirname $SERVER_DIR)" \
"$(basename $SERVER_DIR)"
fi

View File

@@ -0,0 +1,194 @@
#!/bin/bash
# {{ ansible_managed }}
# Script de commandes utiles pour Minecraft
MCRCON="{{ minecraft_tools_dir }}/mcrcon"
RCON_HOST="localhost"
RCON_PORT="{{ rcon_port }}"
RCON_PASS="{{ rcon_password }}"
# Fonction d'exécution RCON
rcon() {
$MCRCON -H $RCON_HOST -P $RCON_PORT -p "$RCON_PASS" "$@"
}
# Commandes disponibles
case "$1" in
say)
shift
rcon "say $@"
;;
list)
rcon "list"
;;
save)
echo "Sauvegarde du monde..."
rcon "save-all flush"
echo "Sauvegarde terminée"
;;
whitelist-add)
if [ -z "$2" ]; then
echo "Usage: $0 whitelist-add <joueur>"
exit 1
fi
rcon "whitelist add $2"
;;
whitelist-remove)
if [ -z "$2" ]; then
echo "Usage: $0 whitelist-remove <joueur>"
exit 1
fi
rcon "whitelist remove $2"
;;
whitelist-list)
rcon "whitelist list"
;;
ban)
if [ -z "$2" ]; then
echo "Usage: $0 ban <joueur> [raison]"
exit 1
fi
shift
rcon "ban $@"
;;
unban)
if [ -z "$2" ]; then
echo "Usage: $0 unban <joueur>"
exit 1
fi
rcon "pardon $2"
;;
kick)
if [ -z "$2" ]; then
echo "Usage: $0 kick <joueur> [raison]"
exit 1
fi
shift
rcon "kick $@"
;;
op)
if [ -z "$2" ]; then
echo "Usage: $0 op <joueur>"
exit 1
fi
rcon "op $2"
;;
deop)
if [ -z "$2" ]; then
echo "Usage: $0 deop <joueur>"
exit 1
fi
rcon "deop $2"
;;
tp)
if [ -z "$3" ]; then
echo "Usage: $0 tp <joueur1> <joueur2>"
exit 1
fi
rcon "tp $2 $3"
;;
gamemode)
if [ -z "$3" ]; then
echo "Usage: $0 gamemode <mode> <joueur>"
echo "Modes: survival, creative, adventure, spectator"
exit 1
fi
rcon "gamemode $2 $3"
;;
time)
if [ -z "$2" ]; then
echo "Usage: $0 time <set|add> <valeur>"
exit 1
fi
shift
rcon "time $@"
;;
weather)
if [ -z "$2" ]; then
echo "Usage: $0 weather <clear|rain|thunder> [durée]"
exit 1
fi
shift
rcon "weather $@"
;;
difficulty)
if [ -z "$2" ]; then
echo "Usage: $0 difficulty <peaceful|easy|normal|hard>"
exit 1
fi
rcon "difficulty $2"
;;
give)
if [ -z "$3" ]; then
echo "Usage: $0 give <joueur> <item> [quantité]"
exit 1
fi
shift
rcon "give $@"
;;
reload)
echo "Rechargement de la configuration..."
rcon "reload"
echo "Configuration rechargée"
;;
stop)
echo "Arrêt du serveur..."
rcon "stop"
;;
console)
# Mode console interactif
echo "Mode console RCON (tapez 'exit' pour quitter)"
while true; do
read -p "minecraft> " cmd
if [ "$cmd" = "exit" ]; then
break
fi
rcon "$cmd"
done
;;
*)
echo "Commandes Minecraft disponibles:"
echo ""
echo " $0 say <message> - Envoyer un message à tous"
echo " $0 list - Liste des joueurs connectés"
echo " $0 save - Sauvegarder le monde"
echo " $0 whitelist-add <joueur> - Ajouter à la whitelist"
echo " $0 whitelist-remove <joueur> - Retirer de la whitelist"
echo " $0 whitelist-list - Afficher la whitelist"
echo " $0 ban <joueur> [raison] - Bannir un joueur"
echo " $0 unban <joueur> - Débannir un joueur"
echo " $0 kick <joueur> [raison] - Expulser un joueur"
echo " $0 op <joueur> - Donner les droits OP"
echo " $0 deop <joueur> - Retirer les droits OP"
echo " $0 tp <joueur1> <joueur2> - Téléporter un joueur"
echo " $0 gamemode <mode> <joueur> - Changer le mode de jeu"
echo " $0 time <set|add> <valeur> - Gérer le temps"
echo " $0 weather <type> [durée] - Changer la météo"
echo " $0 difficulty <niveau> - Changer la difficulté"
echo " $0 give <joueur> <item> [qty] - Donner des objets"
echo " $0 reload - Recharger la configuration"
echo " $0 stop - Arrêter le serveur"
echo " $0 console - Mode console interactif"
exit 1
;;
esac

View File

@@ -0,0 +1,133 @@
#!/bin/bash
# {{ ansible_managed }}
# Script de monitoring pour le serveur Minecraft
SERVER_DIR="{{ minecraft_server_dir }}"
MCRCON="{{ minecraft_tools_dir }}/mcrcon"
RCON_PORT="{{ rcon_port }}"
RCON_PASS="{{ rcon_password }}"
SERVICE_NAME="{{ minecraft_service_name }}"
LOG_FILE="/var/log/minecraft-monitor.log"
# Fonction de log
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
# Fonction pour vérifier le statut
check_server_status() {
if ! systemctl is-active --quiet "$SERVICE_NAME"; then
echo "OFFLINE"
return 1
fi
# Tester RCON
if ! $MCRCON -H localhost -P $RCON_PORT -p "$RCON_PASS" "list" &>/dev/null; then
echo "RCON_FAILED"
return 2
fi
echo "ONLINE"
return 0
}
# Fonction pour obtenir les métriques
get_metrics() {
local status=$(check_server_status)
if [ "$status" = "ONLINE" ]; then
# Nombre de joueurs
local players=$($MCRCON -H localhost -P $RCON_PORT -p "$RCON_PASS" "list" 2>/dev/null | grep -oP '\d+(?= of a max)' || echo "0")
# TPS (si disponible avec un plugin)
local tps=$($MCRCON -H localhost -P $RCON_PORT -p "$RCON_PASS" "tps" 2>/dev/null || echo "N/A")
# Utilisation mémoire du processus
local pid=$(systemctl show -p MainPID "$SERVICE_NAME" | cut -d= -f2)
local mem="0"
if [ "$pid" != "0" ]; then
mem=$(ps -o rss= -p "$pid" 2>/dev/null | awk '{printf "%.2f", $1/1024}' || echo "0")
fi
# Utilisation CPU
local cpu="0"
if [ "$pid" != "0" ]; then
cpu=$(ps -o %cpu= -p "$pid" 2>/dev/null | awk '{print $1}' || echo "0")
fi
# Espace disque du serveur
local disk=$(du -sh "$SERVER_DIR" 2>/dev/null | cut -f1 || echo "N/A")
# Affichage JSON pour intégration
cat <<EOF
{
"status": "$status",
"players": $players,
"tps": "$tps",
"memory_mb": $mem,
"cpu_percent": $cpu,
"disk_usage": "$disk",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
else
cat <<EOF
{
"status": "$status",
"players": 0,
"tps": "N/A",
"memory_mb": 0,
"cpu_percent": 0,
"disk_usage": "N/A",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
fi
}
# Fonction de redémarrage automatique
auto_restart_check() {
local status=$(check_server_status)
case "$status" in
"OFFLINE")
log_message "ALERTE: Serveur hors ligne, tentative de redémarrage..."
systemctl restart "$SERVICE_NAME"
sleep 30
if check_server_status >/dev/null; then
log_message "INFO: Serveur redémarré avec succès"
else
log_message "ERREUR: Échec du redémarrage du serveur"
fi
;;
"RCON_FAILED")
log_message "AVERTISSEMENT: RCON ne répond pas, vérification..."
# Attendre 60 secondes avant de considérer comme critique
sleep 60
if [ "$(check_server_status)" = "RCON_FAILED" ]; then
log_message "ERREUR: RCON toujours en échec, redémarrage du serveur..."
systemctl restart "$SERVICE_NAME"
fi
;;
"ONLINE")
# Tout va bien
;;
esac
}
# Main
case "${1:-status}" in
status)
check_server_status
;;
metrics)
get_metrics
;;
monitor)
auto_restart_check
;;
*)
echo "Usage: $0 {status|metrics|monitor}"
exit 1
;;
esac

View File

@@ -1,18 +1,54 @@
# {{ ansible_managed }}
[Unit]
Description=Minecraft Spigot Server
After=network.target
Description=Minecraft Server (Spigot {{ minecraft_version }})
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
Type=simple
User={{ minecraft_user }}
Group={{ minecraft_group }}
WorkingDirectory={{ minecraft_server_dir }}
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
# Start command with optimized JVM flags
ExecStart=/usr/bin/java \
-Xms{{ minecraft_memory_min }}M \
-Xmx{{ minecraft_memory_max }}M \
{{ jvm_flags }} \
-jar {{ spigot_jar_name }} \
--nogui
# Stop command using mcrcon
ExecStop={{ minecraft_tools_dir }}/mcrcon -H localhost -P {{ rcon_port }} -p "{{ rcon_password }}" stop
# Restart settings
Restart=on-failure
RestartSec=20
RestartSec=10
StartLimitInterval=600
StartLimitBurst=3
# Security settings
PrivateTmp=yes
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths={{ minecraft_base_dir }}
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
# Resource limits
LimitNOFILE=100000
LimitNPROC=512
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=minecraft
[Install]
WantedBy=multi-user.target

View File

@@ -1,10 +1,11 @@
[
{% 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 %}
{
"uuid": "{{ op.uuid }}",
"name": "{{ op.name }}",
"level": {{ op.level | default(4) }},
"bypassesPlayerLimit": {{ op.bypassesPlayerLimit | default(false) | lower }}
}{% if not loop.last %},{% endif %}
{% endfor %}
]

View File

@@ -0,0 +1,188 @@
# {{ ansible_managed }}
# Paper configuration file - only used if Paper is detected
# Version: {{ minecraft_version }}
verbose: false
config-version: 28
settings:
console-has-all-permissions: false
region-file-cache-size: 256
incoming-packet-spam-threshold: 300
max-joins-per-tick: 3
track-plugin-scoreboards: false
suggest-player-names-when-null-tab-completions: true
use-display-name-in-quit-message: false
load-permissions-yml-before-plugins: true
bungee-online-mode: false
unsupported-settings:
allow-permanent-block-break-exploits: false
allow-piston-duplication: false
allow-headless-pistons: false
watchdog:
early-warning-every: 5000
early-warning-delay: 10000
spam-limiter:
recipe-spam-increment: 1
recipe-spam-limit: 20
tab-spam-increment: 1
tab-spam-limit: 500
book-size:
page-max: 2560
total-multiplier: 0.98
async-chunks:
enable: true
threads: -1
velocity-support:
enabled: false
online-mode: false
secret: ''
world-settings:
default:
fix-climbing-bypassing-cramming-rule: false
max-leash-distance: 10.0
show-sign-click-command-failure-msgs-to-player: false
piglins-guard-chests: true
should-remove-dragon: false
max-auto-save-chunks-per-tick: 24
baby-zombie-movement-modifier: 0.5
optimize-explosions: false
disable-teleportation-suffocation-check: false
fixed-chunk-inhabited-time: -1
use-vanilla-world-scoreboard-name-coloring: false
prevent-moving-into-unloaded-chunks: false
spawn-limits:
monsters: -1
animals: -1
water-animals: -1
water-ambient: -1
water-underground-creature: -1
axolotls: -1
ambient: -1
despawn-ranges:
monster:
soft: 32
hard: 128
creature:
soft: 32
hard: 128
ambient:
soft: 32
hard: 128
axolotls:
soft: 32
hard: 128
water-creature:
soft: 32
hard: 128
water-ambient:
soft: 32
hard: 64
water-underground-creature:
soft: 32
hard: 128
misc:
soft: 32
hard: 128
frosted-ice:
enabled: true
delay:
min: 20
max: 40
lootables:
auto-replenish: false
restrict-player-reloot: true
reset-seed-on-fill: true
max-refills: -1
refresh-min: 12h
refresh-max: 2d
filter-nbt-data-from-spawn-eggs-and-related: true
max-entity-collisions: 8
disable-creeper-lingering-effect: false
duplicate-uuid-resolver: saferegen
duplicate-uuid-saferegen-delete-range: 32
per-player-mob-spawns: true
experience-merge-max-value: -1
prevent-tnt-from-moving-in-water: false
falling-block-height-nerf: 0
tnt-entity-height-nerf: 0
slime-spawn-height:
swamp-biome:
maximum: 70
minimum: 50
slime-chunk:
maximum: 40
portal-search-radius: 128
portal-create-radius: 16
portal-search-vanilla-dimension-scaling: true
enable-treasure-maps: true
treasure-maps-find-already-discovered:
loot-tables: default
villager-trade: false
disable-thunder: false
disable-ice-and-snow: false
disable-explosion-knockback: false
keep-spawn-loaded: true
keep-spawn-loaded-range: 10
auto-save-interval: -1
disable-mob-spawner-spawn-egg-transformation: false
entities-target-with-follow-range: false
zombies-target-turtle-eggs: true
zombie-villager-infection-chance: -1.0
all-chunks-are-slime-chunks: false
mob-spawner-tick-rate: 1
light-queue-size: 20
grass-spread-tick-rate: 1
redstone-implementation: vanilla
armor-stands-tick: true
water-over-lava-flow-speed: 5
use-faster-eigencraft-redstone: false
disable-move-event: false
container-update-tick-rate: 1
non-player-arrow-despawn-rate: -1
creative-arrow-despawn-rate: -1
skeleton-horse-thunder-spawn-chance: 0.01
disable-ice-and-snow: false
iron-golems-can-spawn-in-air: false
count-all-mobs-for-spawning: false
delay-chunk-unloads-by: 10s
seed-based-feature-search: true
seed-based-feature-search-loads-chunks: true
water-flow-speed: 5
lava-flow-speed:
normal: 30
nether: 10
fix-items-merging-through-walls: false
prevent-lightning-strike-blocks-from-decaying: false
squid-spawn-height:
minimum: 45
maximum: 0
disable-pillager-patrols: false
game-mechanics:
scan-for-legacy-ender-dragon: true
disable-chest-cat-detection: false
nerf-pigmen-from-nether-portals: false
disable-player-crits: false
disable-sprint-interruption-on-attack: false
shield-blocking-delay: 5
disable-end-credits: false
disable-relative-projectile-velocity: false
disable-mob-spawner-spawn-egg-transformation: false
pillager-patrols:
spawn-chance: 0.2
spawn-delay:
per-player: false
ticks: 12000
start:
per-player: false
day: 5
max-growth-height:
cactus: 3
reeds: 3
bamboo:
max: 16
min: 11
fishing-time-range:
minimum: 100
maximum: 600

View File

@@ -0,0 +1,54 @@
# {{ ansible_managed }}
# Permissions configuration for Bukkit
# Default permissions
default:
default: true
permissions:
bukkit.command.help: true
bukkit.command.list: true
bukkit.command.me: true
bukkit.command.msg: true
bukkit.command.tell: true
bukkit.command.trigger: true
# Moderator permissions
moderator:
default: false
inheritance:
- default
permissions:
bukkit.command.kick: true
bukkit.command.ban: true
bukkit.command.ban.ip: true
bukkit.command.ban.list: true
bukkit.command.unban: true
bukkit.command.unban.ip: true
bukkit.command.pardon: true
bukkit.command.pardon.ip: true
bukkit.command.whitelist: true
bukkit.command.whitelist.add: true
bukkit.command.whitelist.remove: true
bukkit.command.whitelist.list: true
bukkit.command.whitelist.on: true
bukkit.command.whitelist.off: true
bukkit.command.whitelist.reload: true
# Admin permissions
admin:
default: false
inheritance:
- moderator
permissions:
bukkit.command.op: true
bukkit.command.op.give: true
bukkit.command.op.take: true
bukkit.command.save: true
bukkit.command.save.disable: true
bukkit.command.save.enable: true
bukkit.command.save.perform: true
bukkit.command.stop: true
bukkit.command.restart: true
bukkit.command.reload: true
bukkit.command.version: true
bukkit.command.plugins: true

View File

@@ -1,46 +1,66 @@
# Minecraft server properties
# Generated by Ansible
# {{ ansible_managed }}
# Minecraft server properties - Generated on {{ ansible_date_time.iso8601 }}
# Server settings
server-name={{ server_name }}
motd={{ server_motd }}
server-port={{ minecraft_port }}
max-players={{ max_players }}
# Game settings
gamemode={{ gamemode }}
difficulty={{ difficulty }}
pvp={{ pvp_enabled | ternary('true', 'false') }}
hardcore=false
enable-command-block=false
spawn-protection=16
max-world-size=29999984
# RCON settings
enable-rcon={{ rcon_enabled | ternary('true', 'false') }}
# Server Settings
server-port={{ server_port }}
server-ip=
max-tick-time=60000
enable-rcon={{ enable_rcon | lower }}
rcon.port={{ rcon_port }}
rcon.password={{ rcon_password }}
# Network settings
server-ip=
online-mode=true
white-list=false
enable-status=true
enable-query=false
query.port=25565
query.port={{ server_port }}
# World generation
level-name=world
level-seed=
level-type=minecraft\:normal
generate-structures=true
spawn-animals=true
spawn-monsters=true
spawn-npcs=true
# Performance settings
view-distance=10
# Gameplay
gamemode={{ gamemode }}
difficulty={{ difficulty }}
hardcore=false
pvp={{ pvp | lower }}
enable-command-block={{ enable_command_block | lower }}
max-players={{ max_players }}
online-mode={{ online_mode | lower }}
white-list={{ white_list | lower }}
enforce-whitelist={{ white_list | lower }}
op-permission-level=4
player-idle-timeout=0
prevent-proxy-connections=false
hide-online-players=false
simulation-distance=10
max-tick-time=60000
# World
level-name=world
level-seed={{ level_seed }}
level-type={{ level_type }}
generate-structures={{ generate_structures | lower }}
spawn-protection={{ spawn_protection }}
max-world-size={{ max_world_size }}
max-build-height=319
view-distance={{ view_distance }}
spawn-animals={{ spawn_animals | lower }}
spawn-monsters={{ spawn_monsters | lower }}
spawn-npcs={{ spawn_npcs | lower }}
allow-nether=true
# Performance
network-compression-threshold=256
rate-limit=0
sync-chunk-writes=true
use-native-transport=true
allow-flight=false
# Messages
motd={{ server_name }}
resource-pack=
resource-pack-prompt=
resource-pack-sha1=
require-resource-pack=false
# Advanced
enable-jmx-monitoring=false
enable-status=true
entity-broadcast-range-percentage=100
force-gamemode=false
function-permission-level=2
initial-disabled-packs=
initial-enabled-packs=vanilla
text-filtering-config=

View File

@@ -0,0 +1,130 @@
# {{ ansible_managed }}
# This is the main configuration file for Spigot.
# Spigot version: {{ minecraft_version }}
settings:
debug: false
save-user-cache-on-stop-only: false
bungeecord: false
late-bind: false
sample-count: 12
player-shuffle: 0
user-cache-size: 1000
moved-wrongly-threshold: 0.0625
moved-too-quickly-multiplier: 10.0
timeout-time: 60
restart-on-crash: true
restart-script: {{ minecraft_base_dir }}/scripts/start.sh
netty-threads: 4
log-villager-deaths: true
log-named-deaths: true
attribute:
maxHealth:
max: 2048.0
movementSpeed:
max: 2048.0
attackDamage:
max: 2048.0
messages:
whitelist: You are not whitelisted on this server!
unknown-command: Unknown command. Type "/help" for help.
server-full: The server is full!
outdated-client: Outdated client! Please use {0}
outdated-server: Outdated server! I'm still on {0}
restart: Server is restarting
commands:
replace-commands:
- setblock
- summon
- testforblock
- tellraw
spam-exclusions:
- /skill
silent-commandblock-console: false
log: true
tab-complete: -1
send-namespaced: true
advancements:
disable-saving: false
disabled:
- minecraft:story/disabled
players:
disable-saving: false
world-settings:
default:
below-zero-generation-in-existing-chunks: true
merge-radius:
exp: 3.0
item: 2.5
growth:
cactus-modifier: 100
cane-modifier: 100
melon-modifier: 100
mushroom-modifier: 100
pumpkin-modifier: 100
sapling-modifier: 100
beetroot-modifier: 100
carrot-modifier: 100
potato-modifier: 100
wheat-modifier: 100
netherwart-modifier: 100
vine-modifier: 100
cocoa-modifier: 100
bamboo-modifier: 100
sweetberry-modifier: 100
kelp-modifier: 100
entity-activation-range:
animals: 32
monsters: 32
raiders: 48
misc: 16
tick-inactive-villagers: true
entity-tracking-range:
players: 48
animals: 48
monsters: 48
misc: 32
other: 64
ticks-per:
hopper-transfer: 8
hopper-check: 1
hopper-amount: 1
save-structure-info: true
dragon-death-sound-radius: 0
seed-village: 10387312
seed-desert: 14357617
seed-igloo: 14357618
seed-jungle: 14357619
seed-swamp: 14357620
seed-monument: 10387313
seed-shipwreck: 165745295
seed-ocean: 14357621
seed-outpost: 165745296
seed-endcity: 10387313
seed-slime: 987234911
seed-bastion: 30084232
seed-fortress: 30084232
seed-mansion: 10387319
seed-fossil: 14357921
seed-portal: 34222645
max-tnt-per-tick: 100
enable-zombie-pigmen-portal-spawns: true
item-despawn-rate: 6000
view-distance: default
simulation-distance: default
thunder-chance: 100000
wither-spawn-sound-radius: 0
arrow-despawn-rate: 1200
trident-despawn-rate: 1200
hanging-tick-frequency: 100
zombie-aggressive-towards-villager: true
nerf-spawner-mobs: false
mob-spawn-range: 8
end-portal-sound-radius: 0
config-version: 12

View File

@@ -0,0 +1,17 @@
#!/bin/bash
# {{ ansible_managed }}
# Configuration
SERVER_DIR="{{ minecraft_server_dir }}"
JAR_FILE="{{ spigot_jar_name }}"
MIN_RAM="{{ minecraft_memory_min }}M"
MAX_RAM="{{ minecraft_memory_max }}M"
# JVM Flags optimisés pour Minecraft
JVM_FLAGS="{{ jvm_flags }}"
# Aller dans le répertoire du serveur
cd "$SERVER_DIR" || exit 1
# Démarrer le serveur
exec java -Xms${MIN_RAM} -Xmx${MAX_RAM} ${JVM_FLAGS} -jar ${JAR_FILE} --nogui

View File

@@ -0,0 +1,39 @@
#!/bin/bash
# {{ ansible_managed }}
MCRCON="{{ minecraft_tools_dir }}/mcrcon"
RCON_HOST="localhost"
RCON_PORT="{{ rcon_port }}"
RCON_PASS="{{ rcon_password }}"
# Fonction pour envoyer des commandes au serveur
send_command() {
$MCRCON -H $RCON_HOST -P $RCON_PORT -p "$RCON_PASS" "$1"
}
# Avertir les joueurs
echo "Avertissement des joueurs..."
send_command "say Le serveur va redémarrer dans 60 secondes!"
sleep 30
send_command "say Le serveur va redémarrer dans 30 secondes!"
sleep 20
send_command "say Le serveur va redémarrer dans 10 secondes!"
sleep 5
for i in 5 4 3 2 1; do
send_command "say Arrêt dans $i..."
sleep 1
done
# Sauvegarder le monde
echo "Sauvegarde du monde..."
send_command "save-all"
sleep 5
# Arrêter le serveur
echo "Arrêt du serveur..."
send_command "stop"
echo "Serveur arrêté proprement."

View File

@@ -0,0 +1,9 @@
[
{% for player in minecraft_whitelist | default([]) %}
{
"uuid": "{{ player.uuid }}",
"name": "{{ player.name }}"
}{% if not loop.last %},{% endif %}
{% endfor %}
]

View File

@@ -1,21 +1,32 @@
---
# Internal variables for Minecraft installation
required_packages:
- openjdk-17-jdk
# Variables internes du rôle
spigot_jar_name: "spigot-{{ minecraft_version }}.jar"
buildtools_jar: "BuildTools.jar"
server_jar_path: "{{ minecraft_server_dir }}/{{ spigot_jar_name }}"
# Liste des répertoires à créer
minecraft_dirs:
- "{{ minecraft_base_dir }}"
- "{{ minecraft_server_dir }}"
- "{{ minecraft_sources_dir }}"
- "{{ minecraft_tools_dir }}"
- "{{ minecraft_server_dir }}/plugins"
- "{{ minecraft_server_dir }}/world"
- "{{ minecraft_server_dir }}/world_nether"
- "{{ minecraft_server_dir }}/world_the_end"
- "{{ minecraft_server_dir }}/logs"
- "{{ minecraft_server_dir }}/crash-reports"
- "{{ minecraft_base_dir }}/scripts"
# Packages requis pour la compilation
build_packages:
- git
- build-essential
- screen
- htop
- iotop
- wget
- curl
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
# Configuration JVM
jvm_flags: "-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1"

View File

@@ -1,26 +1,11 @@
---
# Backup configuration
backup_base_dir: "{{ minecraft_base_dir }}/backups"
backup_base_dir: /opt/minecraft/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"
backup_retention_daily: 7
backup_retention_weekly: 4
backup_retention_monthly: 3
backup_time_daily: "03:00"
backup_time_weekly: "04:00"
backup_time_monthly: "05:00"

View File

@@ -1,26 +1,6 @@
---
# 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"
- name: reload cron
ansible.builtin.service:
name: cron
state: reloaded
listen: reload cron service

View File

@@ -1,18 +0,0 @@
---
- 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

@@ -0,0 +1,9 @@
---
- name: Create backup directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
loop: "{{ backup_dirs }}"

View File

@@ -0,0 +1,6 @@
---
- name: Install rsync
ansible.builtin.apt:
name: rsync
state: present
when: ansible_os_family == "Debian"

View File

@@ -1,17 +0,0 @@
---
- 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

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

View File

@@ -1,18 +0,0 @@
---
- 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,29 @@
---
- name: Setup daily backup cron job
ansible.builtin.cron:
name: "Minecraft daily backup"
user: "{{ minecraft_user }}"
hour: "{{ backup_time_daily.split(':')[0] }}"
minute: "{{ backup_time_daily.split(':')[1] }}"
job: "{{ minecraft_base_dir }}/backup.sh daily"
notify: reload cron service
- name: Setup weekly backup cron job
ansible.builtin.cron:
name: "Minecraft weekly backup"
user: "{{ minecraft_user }}"
hour: "{{ backup_time_weekly.split(':')[0] }}"
minute: "{{ backup_time_weekly.split(':')[1] }}"
weekday: "0"
job: "{{ minecraft_base_dir }}/backup.sh weekly"
notify: reload cron service
- name: Setup monthly backup cron job
ansible.builtin.cron:
name: "Minecraft monthly backup"
user: "{{ minecraft_user }}"
hour: "{{ backup_time_monthly.split(':')[0] }}"
minute: "{{ backup_time_monthly.split(':')[1] }}"
day: "1"
job: "{{ minecraft_base_dir }}/backup.sh monthly"
notify: reload cron service

View File

@@ -1,18 +0,0 @@
---
- 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

@@ -0,0 +1,26 @@
---
- name: Create restore script
ansible.builtin.template:
src: restore.sh.j2
dest: "{{ minecraft_base_dir }}/restore.sh"
owner: "{{ minecraft_user }}"
group: "{{ minecraft_group }}"
mode: '0755'
- name: Stop minecraft server before restore
ansible.builtin.systemd:
name: "{{ minecraft_service_name }}"
state: stopped
when: restore_backup_type is defined
- name: Execute restore
ansible.builtin.command:
cmd: "{{ minecraft_base_dir }}/restore.sh {{ restore_backup_type }} {{ restore_backup_date | default('latest') }}"
become_user: "{{ minecraft_user }}"
when: restore_backup_type is defined
- name: Start minecraft server after restore
ansible.builtin.systemd:
name: "{{ minecraft_service_name }}"
state: started
when: restore_backup_type is defined

View File

@@ -1,38 +0,0 @@
---
- 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

@@ -1,8 +0,0 @@
---
- 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,18 +1,16 @@
---
- name: Include backup directories creation tasks
ansible.builtin.include_tasks: 01-create-backup-directories.yml
- name: Include create backup directories tasks
ansible.builtin.include_tasks: 01-create-backup-dirs.yml
- name: Include daily backup setup tasks
ansible.builtin.include_tasks: 02-setup-daily-backup.yml
- name: Include install rsync tasks
ansible.builtin.include_tasks: 02-install-rsync.yml
- name: Include weekly backup setup tasks
ansible.builtin.include_tasks: 03-setup-weekly-backup.yml
- name: Include configure backup script tasks
ansible.builtin.include_tasks: 03-configure-backup-script.yml
- name: Include monthly backup setup tasks
ansible.builtin.include_tasks: 04-setup-monthly-backup.yml
- name: Include setup cron tasks
ansible.builtin.include_tasks: 04-setup-cron.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
- name: Include restore backup tasks
ansible.builtin.include_tasks: 05-restore-backup.yml
when: restore_backup | default(false)

Some files were not shown because too many files have changed in this diff Show More