diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..16ef6c1 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,12 @@ +[defaults] +inventory = inventory +library = library +vault_password_file = ./.ansible_vault_pass + +[privilege_escalation] +become = true +become_method = su +become_user = root + +[ssh_connection] +scp_if_ssh=True diff --git a/inventory/group_vars/all/users.yml b/inventory/group_vars/all/users.yml new file mode 100644 index 0000000..3f1c411 --- /dev/null +++ b/inventory/group_vars/all/users.yml @@ -0,0 +1,7 @@ +--- +userdb: + user: + user_group: user + user_pass: "salt" + key: "ssh-rsa" + virt_manage: True diff --git a/inventory/vm.yml b/inventory/vm.yml new file mode 100644 index 0000000..f4b46a3 --- /dev/null +++ b/inventory/vm.yml @@ -0,0 +1,9 @@ +--- +all: + hosts: + server + ansible_host: 192.168.1.100 + ansible_port: 22 + ssh_port: 22 + vars: + hosts_gateway: 192.168.1.1 diff --git a/roles/minecraft/README.md b/roles/minecraft/README.md new file mode 100644 index 0000000..9bc7ea4 --- /dev/null +++ b/roles/minecraft/README.md @@ -0,0 +1,20 @@ +# minecraft role + +Роль для разворачивания сервера майнкрафта. + +Перед прокаткой роли необходимо поставить некоторые модули к ansible: +``` +ansible-galaxy collection install community.general +``` + +На хосте должен быть настроен sshd (PermitRootLogin yes) и установлен Python3. + +Первый запуск роли происходит с помощью команды: +``` +ansible-playbook -l server roles/minecraft/minecraft.yml -u root --ask-pass +``` + +После настройки системы роль может запускаться следующим образом: +``` +ansible-playbook -l server roles/minecraft/minecraft.yml -K +``` diff --git a/roles/minecraft/defaults/main.yml b/roles/minecraft/defaults/main.yml new file mode 100644 index 0000000..7cc00f6 --- /dev/null +++ b/roles/minecraft/defaults/main.yml @@ -0,0 +1,136 @@ +--- +### COMMON ### + +alpine_version: latest-stable + + +### PACKAGES ### + +system_pkgs: + - chrony + - tzdata + - htop + - screen + - git + - wget + - mc + - ncdu + - vim + - nano + - rsync + - unzip + - tar + +mine_pkgs: + - openjdk17-jdk + - ncurses + - rcon + +ext_pkgs: + - mariadb + - mariadb-client + - mariadb-backup + - py3-pymysql + - nginx + - php82-fpm + - php-pdo_mysql + - php82-mysqli + - php82-session + + +### Nginx ### + +nginx_user: nginx +worker_processes: auto +worker_connections: 1024 +root_dir: /srv/www +log_dir: /var/log/nginx + + +### php-fpm ### + +phpfpm_ver: "php82-fpm" +phpfpm_init: "php-fpm82" +phpfpm_path: "/etc/php82/" + + +### MariaDB ### + +sql_user: minecraft_sql +sql_pass: !vault | + $ANSIBLE_VAULT;1.1;AES256 + blabla + +minecraft_db: + - dynmap + - logsec + - permissionsex + - luckperms + +### SSH ### + +# SEE in inventory lxc.yml + +### SERVER ### + +server_user: user + +MINHEAP: 2G +MAXHEAP: 10G + +### SERVER CONFIG ### + +rcon_port: 25566 +# survival, creative, adventure, spectator +gamemode: survival +enforce_secure_profile: false +level_name: world +server_status: Hello +view_distance: 10 +game_port: 25565 +# true or false +pvp: true +# Обновление блоков (актуально для редстоун машин) +# default - 1000000 +neighbor_updates: 1000 +# peaceful, easy, normal and hard +difficulty: hard +# Размер пакета до его сжатия, больше значение - большая производительность +# CPU (но при этом пользователи со слабым интернетом страдают). +# -1 отключает компрессию +network_compression_threshold: 128 +max_players: 100 +# true or false +enable_rcon: false +#Позволяет изменять права операторов. +# 1 — Операторы могут ломать / ставить блоки внутри радиуса защиты +# территории спауна. +# 2 — Операторы могут использовать команды /clear, /difficulty, /effect, +# /gamemode, /gamerule, /give, /tp, и могут изменять командные блоки. +# 3 — Операторы могут использовать команды /ban, /deop, /kick, и /op. +# 4 — Операторы могут использовать команду /stop. +op_permission_level: 3 +# Позволяет изменять дистанцию рендера энтити для клиентов в процентах. +# Более высокие значения могут привести к снижению производительности сервера, +# поскольку чем выше значение, тем выше дальность прорисовки энтити и больше +# ресурсов нужно для их обработки. +# Это настройка выражается в процентах (100% — по умолчанию). Например, +# установка этого значения на 50 уменьшит дальность рендера энтити вдвое. +# Представляет собой серверный аналог изменения прорисовки у клиента. +entity_broadcast_range: 150 +simulation_distance: 10 +rcon_password: 12345qaz +spawn_protection: 3 + + +### OPS ### + +ops: + Player: + uuid: "blabla" + level: 3 + bypassesPlayerLimit: false + Admin: + uuid: "blabla" + level: 3 + bypassesPlayerLimit: false diff --git a/roles/minecraft/files/mariadb/mariadb-server.cnf b/roles/minecraft/files/mariadb/mariadb-server.cnf new file mode 100644 index 0000000..b88f53b --- /dev/null +++ b/roles/minecraft/files/mariadb/mariadb-server.cnf @@ -0,0 +1,17 @@ +[server] +bind-address=127.0.0.1 + + +[mysqld] +#skip-networking + + +[galera] + + +[embedded] + + +[mariadb] + +[mariadb-10.5] diff --git a/roles/minecraft/files/plugins/AnarchyExploitFixes-Legacy-2.6.6.jar b/roles/minecraft/files/plugins/AnarchyExploitFixes-Legacy-2.6.6.jar new file mode 100644 index 0000000..44d1741 Binary files /dev/null and b/roles/minecraft/files/plugins/AnarchyExploitFixes-Legacy-2.6.6.jar differ diff --git a/roles/minecraft/files/plugins/AntiPopup-7.3.jar b/roles/minecraft/files/plugins/AntiPopup-7.3.jar new file mode 100644 index 0000000..aa206a4 Binary files /dev/null and b/roles/minecraft/files/plugins/AntiPopup-7.3.jar differ diff --git a/roles/minecraft/files/plugins/Dynmap-3.7-beta-4-spigot.jar b/roles/minecraft/files/plugins/Dynmap-3.7-beta-4-spigot.jar new file mode 100644 index 0000000..dc5ca20 Binary files /dev/null and b/roles/minecraft/files/plugins/Dynmap-3.7-beta-4-spigot.jar differ diff --git a/roles/minecraft/files/plugins/EssentialsX-2.20.1.jar b/roles/minecraft/files/plugins/EssentialsX-2.20.1.jar new file mode 100644 index 0000000..ae419e8 Binary files /dev/null and b/roles/minecraft/files/plugins/EssentialsX-2.20.1.jar differ diff --git a/roles/minecraft/files/plugins/EssentialsXChat-2.20.1.jar b/roles/minecraft/files/plugins/EssentialsXChat-2.20.1.jar new file mode 100644 index 0000000..7a39b98 Binary files /dev/null and b/roles/minecraft/files/plugins/EssentialsXChat-2.20.1.jar differ diff --git a/roles/minecraft/files/plugins/FastAsyncWorldEdit-Bukkit-2.8.5-SNAPSHOT-651.jar b/roles/minecraft/files/plugins/FastAsyncWorldEdit-Bukkit-2.8.5-SNAPSHOT-651.jar new file mode 100644 index 0000000..d0b92d0 Binary files /dev/null and b/roles/minecraft/files/plugins/FastAsyncWorldEdit-Bukkit-2.8.5-SNAPSHOT-651.jar differ diff --git a/roles/minecraft/files/plugins/FastChunkPregenerator-2.0.9-SNAPSHOT.jar b/roles/minecraft/files/plugins/FastChunkPregenerator-2.0.9-SNAPSHOT.jar new file mode 100644 index 0000000..6136954 Binary files /dev/null and b/roles/minecraft/files/plugins/FastChunkPregenerator-2.0.9-SNAPSHOT.jar differ diff --git a/roles/minecraft/files/plugins/Geyser-Spigot.jar b/roles/minecraft/files/plugins/Geyser-Spigot.jar new file mode 100644 index 0000000..2236fff Binary files /dev/null and b/roles/minecraft/files/plugins/Geyser-Spigot.jar differ diff --git a/roles/minecraft/files/plugins/LoginSecurity-Spigot-3.3.0.jar b/roles/minecraft/files/plugins/LoginSecurity-Spigot-3.3.0.jar new file mode 100644 index 0000000..8b93a2f Binary files /dev/null and b/roles/minecraft/files/plugins/LoginSecurity-Spigot-3.3.0.jar differ diff --git a/roles/minecraft/files/plugins/LuckPerms-Bukkit-5.4.102.jar b/roles/minecraft/files/plugins/LuckPerms-Bukkit-5.4.102.jar new file mode 100644 index 0000000..800fc5c Binary files /dev/null and b/roles/minecraft/files/plugins/LuckPerms-Bukkit-5.4.102.jar differ diff --git a/roles/minecraft/files/plugins/ProtocolLib.jar b/roles/minecraft/files/plugins/ProtocolLib.jar new file mode 100644 index 0000000..d93f3c1 Binary files /dev/null and b/roles/minecraft/files/plugins/ProtocolLib.jar differ diff --git a/roles/minecraft/files/plugins/SkinsRestorer.jar b/roles/minecraft/files/plugins/SkinsRestorer.jar new file mode 100644 index 0000000..225d319 Binary files /dev/null and b/roles/minecraft/files/plugins/SkinsRestorer.jar differ diff --git a/roles/minecraft/files/plugins/Vault.jar b/roles/minecraft/files/plugins/Vault.jar new file mode 100644 index 0000000..4bcaa89 Binary files /dev/null and b/roles/minecraft/files/plugins/Vault.jar differ diff --git a/roles/minecraft/files/plugins/floodgate-spigot.jar b/roles/minecraft/files/plugins/floodgate-spigot.jar new file mode 100644 index 0000000..68a3e56 Binary files /dev/null and b/roles/minecraft/files/plugins/floodgate-spigot.jar differ diff --git a/roles/minecraft/files/plugins/minecraft-prometheus-exporter-3.1.0.jar b/roles/minecraft/files/plugins/minecraft-prometheus-exporter-3.1.0.jar new file mode 100644 index 0000000..9170ee6 Binary files /dev/null and b/roles/minecraft/files/plugins/minecraft-prometheus-exporter-3.1.0.jar differ diff --git a/roles/minecraft/files/plugins/spark-1.10.58-bukkit.jar b/roles/minecraft/files/plugins/spark-1.10.58-bukkit.jar new file mode 100644 index 0000000..2ba87db Binary files /dev/null and b/roles/minecraft/files/plugins/spark-1.10.58-bukkit.jar differ diff --git a/roles/minecraft/files/repositories b/roles/minecraft/files/repositories new file mode 100644 index 0000000..52e839a --- /dev/null +++ b/roles/minecraft/files/repositories @@ -0,0 +1,4 @@ +# Managed by Ansible + +http://mirror.yandex.ru/mirrors/alpine/latest-stable/main +http://mirror.yandex.ru/mirrors/alpine/latest-stable/community diff --git a/roles/minecraft/files/server-icon.png b/roles/minecraft/files/server-icon.png new file mode 100644 index 0000000..cdb415c Binary files /dev/null and b/roles/minecraft/files/server-icon.png differ diff --git a/roles/minecraft/files/server-icon_1.png b/roles/minecraft/files/server-icon_1.png new file mode 100644 index 0000000..f5ed7f3 Binary files /dev/null and b/roles/minecraft/files/server-icon_1.png differ diff --git a/roles/minecraft/files/server-icon_2.png b/roles/minecraft/files/server-icon_2.png new file mode 100644 index 0000000..c001fe4 Binary files /dev/null and b/roles/minecraft/files/server-icon_2.png differ diff --git a/roles/minecraft/files/server-icon_3.png b/roles/minecraft/files/server-icon_3.png new file mode 100644 index 0000000..a23a92b Binary files /dev/null and b/roles/minecraft/files/server-icon_3.png differ diff --git a/roles/minecraft/files/server/eula.txt b/roles/minecraft/files/server/eula.txt new file mode 100644 index 0000000..02dccd9 --- /dev/null +++ b/roles/minecraft/files/server/eula.txt @@ -0,0 +1 @@ +eula=true diff --git a/roles/minecraft/files/server/paper-1.20.4-378.jar b/roles/minecraft/files/server/paper-1.20.4-378.jar new file mode 100644 index 0000000..cee1513 Binary files /dev/null and b/roles/minecraft/files/server/paper-1.20.4-378.jar differ diff --git a/roles/minecraft/handlers/main.yml b/roles/minecraft/handlers/main.yml new file mode 100644 index 0000000..8914927 --- /dev/null +++ b/roles/minecraft/handlers/main.yml @@ -0,0 +1,35 @@ +--- +- name: Restart ssh server + ansible.builtin.service: + name: sshd + state: restarted + +- name: Restart chronyd + ansible.builtin.service: + name: chronyd + state: restarted + +- name: Restart minecraft Server + ansible.builtin.service: + name: minecraftd + state: restarted + +- name: Reload minecraft Server + ansible.builtin.service: + name: minecraftd + state: reloaded + +- name: Restart MariaDB + ansible.builtin.service: + name: mariadb + state: restarted + +- name: Restart php-fpm + ansible.builtin.service: + name: "{{ phpfpm_init }}" + state: restarted + +- name: Restart nginx + ansible.builtin.service: + name: nginx + state: restarted diff --git a/roles/minecraft/minecraft.yml b/roles/minecraft/minecraft.yml new file mode 100644 index 0000000..4d5de55 --- /dev/null +++ b/roles/minecraft/minecraft.yml @@ -0,0 +1,8 @@ +--- +- name: Minecraft Role + become: yes + hosts: all + gather_facts: yes + + roles: + - ../minecraft diff --git a/roles/minecraft/tasks/backups.yml b/roles/minecraft/tasks/backups.yml new file mode 100644 index 0000000..2530b55 --- /dev/null +++ b/roles/minecraft/tasks/backups.yml @@ -0,0 +1,24 @@ +--- +- name: Create a backup directory + ansible.builtin.file: + path: "/home/{{ server_user }}/backups" + state: directory + owner: "{{ server_user }}" + group: "{{ server_user }}" + mode: '0755' + +- name: Generate backup script + ansible.builtin.template: + src: backup_server.j2 + dest: "/home/{{ server_user }}/backup_server.sh" + owner: "{{ server_user }}" + group: "{{ server_user }}" + mode: '0755' + +- name: Creates a cron file for backup + ansible.builtin.cron: + name: Backup Minecraft server + minute: "0" + hour: "1" + user: "{{ server_user }}" + job: "/home/{{ server_user }}/backup_server.sh" diff --git a/roles/minecraft/tasks/basic.yml b/roles/minecraft/tasks/basic.yml new file mode 100644 index 0000000..39bd6e3 --- /dev/null +++ b/roles/minecraft/tasks/basic.yml @@ -0,0 +1,54 @@ +--- +- name: Rename host + ansible.builtin.hostname: + name: "{{ inventory_hostname }}" + +- name: Change hosts + ansible.builtin.template: + src: hosts.j2 + dest: /etc/hosts + backup: true + +- name: Change MOTD file + ansible.builtin.template: + src: motd.j2 + dest: /etc/motd + owner: root + group: root + mode: '0644' + backup: true + +- name: Set timezone to Europe/Moscow + community.general.timezone: + name: Europe/Moscow + +- name: Modify chronyd init.d args + ansible.builtin.lineinfile: + path: /etc/conf.d/chronyd + regexp: 'ARGS=""' + line: 'ARGS="-x"' + +- name: Add Chrony to boot + ansible.builtin.service: + name: chronyd + runlevel: default + enabled: True + use: openrc + when: not ansible_check_mode + notify: Restart chronyd + +- name: Create sshd.conf + ansible.builtin.template: + src: sshd_config.j2 + dest: /etc/ssh/sshd_config + validate: /usr/sbin/sshd -t -f %s + backup: true + notify: Restart ssh server + +- name: Add sshd to boot + ansible.builtin.service: + name: sshd + runlevel: default + enabled: True + use: openrc + when: not ansible_check_mode diff --git a/roles/minecraft/tasks/main.yml b/roles/minecraft/tasks/main.yml new file mode 100644 index 0000000..8b9b2b3 --- /dev/null +++ b/roles/minecraft/tasks/main.yml @@ -0,0 +1,108 @@ +--- +- name: Update and install packets + ansible.builtin.include_tasks: + file: packets.yml + apply: + tags: + - run_update + tags: + - always + +- name: Make basic configure + ansible.builtin.include_tasks: + file: basic.yml + apply: + tags: + - run_basic + tags: + - always + +- name: Create users + ansible.builtin.include_tasks: + file: users.yml + apply: + tags: + - run_users + tags: + - always + +- name: Deploy Initd server daemon + ansible.builtin.include_tasks: + file: service.yml + apply: + tags: + - run_service + tags: + - always + +- name: Deploy Server + ansible.builtin.include_tasks: + file: server.yml + apply: + tags: + - run_server + tags: + - always + +- name: Make backuping + ansible.builtin.include_tasks: + file: backups.yml + apply: + tags: + - run_backups + tags: + - always + +- name: Install plugins + ansible.builtin.include_tasks: + file: plugins.yml + apply: + tags: + - run_plugins + tags: + - always + +- name: Config OPs + ansible.builtin.include_tasks: + file: ops.yml + apply: + tags: + - run_ops + tags: + - always + +- name: Configure MariaDB server + ansible.builtin.include_tasks: + file: mariadb.yml + apply: + tags: + - run_mariadb + tags: + - always + +- name: Configure php-fpm + ansible.builtin.include_tasks: + file: php.yml + apply: + tags: + - run_php + tags: + - always + +- name: Configure nginx + ansible.builtin.include_tasks: + file: nginx.yml + apply: + tags: + - run_nginx + tags: + - always + +- name: Tuning server and plugins + ansible.builtin.include_tasks: + file: tuning.yml + apply: + tags: + - run_tuning + tags: + - always diff --git a/roles/minecraft/tasks/mariadb.yml b/roles/minecraft/tasks/mariadb.yml new file mode 100644 index 0000000..a600d41 --- /dev/null +++ b/roles/minecraft/tasks/mariadb.yml @@ -0,0 +1,101 @@ +--- +- name: Update repositories + community.general.apk: + update_cache: true + +- name: Install ext packages + community.general.apk: + name: "{{ ext_pkgs }}" + state: present + when: not ansible_check_mode + +- name: Check that the mysql dir exists + ansible.builtin.stat : + path: /var/lib/mysql + register: stat_result + +- name: Init Mariadb + ansible.builtin.service: + name: mariadb + state: stopped + args: setup + when: not stat_result.stat.exists + +- name: Deploy mariadb config + copy: + src: "files/mariadb/mariadb-server.cnf" + dest: "/etc/my.cnf.d/mariadb-server.cnf" + mode: '0644' + notify: Restart MariaDB + +- name: Flush handlers + meta: flush_handlers + +- name: mysql_secure_installation + when: not stat_result.stat.exists + block: + - name: Removes all anonymous user accounts + community.mysql.mysql_user: + login_user: root + login_unix_socket: /run/mysqld/mysqld.sock + name: '' + host_all: true + state: absent + + - name: Delete Hostname based MySQL user + community.mysql.mysql_user: + login_user: root + login_unix_socket: /run/mysqld/mysqld.sock + name: root + host: "{{ansible_nodename}}" + state: absent + + - name: Remove MySQL test database + community.mysql.mysql_db: + login_user: root + login_unix_socket: /run/mysqld/mysqld.sock + name: test + state: absent + + - name: Reload privilege tables + ansible.builtin.command: 'mysql -ne "{{ item }}"' + with_items: + - FLUSH PRIVILEGES + changed_when: False + +- name: Add MariaDB to boot + ansible.builtin.service: + name: mariadb + runlevel: default + enabled: True + use: openrc + when: not ansible_check_mode + +# Minecraft Role Tasks +- name: Config Mysql Users And DB for Minecraft + tags: mine_db + block: + - name: Create a Dynmap Database + community.mysql.mysql_db: + login_user: root + login_unix_socket: /run/mysqld/mysqld.sock + name: "{{ minecraft_db }}" + state: present + + - name: Create user and priv db + community.mysql.mysql_user: + login_user: root + login_unix_socket: /run/mysqld/mysqld.sock + name: "{{ sql_user }}" + password: "{{ sql_pass }}" + priv: + "{{ item }}.*:ALL" + state: present + append_privs: True + with_items: "{{ minecraft_db }}" + + - name: Reload privilege tables + ansible.builtin.command: 'mysql -ne "{{ item }}"' + with_items: + - FLUSH PRIVILEGES + changed_when: False diff --git a/roles/minecraft/tasks/nginx.yml b/roles/minecraft/tasks/nginx.yml new file mode 100644 index 0000000..1a07310 --- /dev/null +++ b/roles/minecraft/tasks/nginx.yml @@ -0,0 +1,24 @@ +--- +- name: Update repositories + community.general.apk: + update_cache: true + +- name: Install ext packages + community.general.apk: + name: "{{ ext_pkgs }}" + state: present + when: not ansible_check_mode + +- name: Add nginx to boot + ansible.builtin.service: + name: nginx + runlevel: default + enabled: True + use: openrc + when: not ansible_check_mode + +- name: Deploy nginx.conf + template: + src: templates/nginx.j2 + dest: /etc/nginx/nginx.conf + notify: Restart nginx diff --git a/roles/minecraft/tasks/ops.yml b/roles/minecraft/tasks/ops.yml new file mode 100644 index 0000000..7140c6e --- /dev/null +++ b/roles/minecraft/tasks/ops.yml @@ -0,0 +1,25 @@ +--- +- name: Initiate Op List + ansible.builtin.set_fact: + op_list: [] + +- name: Add new JSON Objects to List + ansible.builtin.set_fact: + op_list: "{{ op_list + + [{ 'uuid': ops[item].uuid, + 'name': item, + 'level': ops[item].level, + 'bypassesPlayerLimit': ops[item].bypassesPlayerLimit}] }}" + with_items: "{{ ops }}" + +- name: Debug + ansible.builtin.debug: + var: op_list + +- name: Write output json file + ansible.builtin.copy: + dest: "/home/{{ server_user }}/minecraft/ops.json" + owner: "{{ server_user }}" + group: "{{ server_user }}" + mode: '0644' + content: "{{ op_list | to_nice_json(sort_keys=False, indent=2) }}" diff --git a/roles/minecraft/tasks/packets.yml b/roles/minecraft/tasks/packets.yml new file mode 100644 index 0000000..fe706cd --- /dev/null +++ b/roles/minecraft/tasks/packets.yml @@ -0,0 +1,29 @@ +--- +- name: Config repos + ansible.builtin.copy: + src: repositories + dest: /etc/apk/ + owner: root + group: root + mode: '0644' + backup: true + +- name: Update repositories + community.general.apk: + update_cache: true + +- name: Update all installed packages to the latest versions + community.general.apk: + upgrade: yes + +- name: Install system packages + community.general.apk: + name: "{{ system_pkgs }}" + state: present + when: not ansible_check_mode + +- name: Install minecraft packages + community.general.apk: + name: "{{ mine_pkgs }}" + state: present + when: not ansible_check_mode diff --git a/roles/minecraft/tasks/php.yml b/roles/minecraft/tasks/php.yml new file mode 100644 index 0000000..c0ba731 --- /dev/null +++ b/roles/minecraft/tasks/php.yml @@ -0,0 +1,28 @@ +--- +- name: Update repositories + community.general.apk: + update_cache: true + +- name: Install ext packages + community.general.apk: + name: "{{ ext_pkgs }}" + state: present + when: not ansible_check_mode + +- name: Add php-fpm to boot + ansible.builtin.service: + name: "{{ phpfpm_init }}" + runlevel: default + enabled: True + use: openrc + when: not ansible_check_mode + +- name: Configure php-fpm + lineinfile: + dest: "{{ phpfpm_path}}/php-fpm.d/www.conf" + regexp: "^{{ item.property | regex_escape() }} = " + line: "{{ item.property }} = {{ item.value }}" + with_items: + - { property: 'user', value: 'nginx' } + - { property: 'group', value: 'nginx' } + notify: Restart php-fpm diff --git a/roles/minecraft/tasks/plugins.yml b/roles/minecraft/tasks/plugins.yml new file mode 100644 index 0000000..fb00809 --- /dev/null +++ b/roles/minecraft/tasks/plugins.yml @@ -0,0 +1,9 @@ +--- +- name: Deploy plugins + copy: + src: "files/plugins/" + dest: "/home/{{ server_user }}/minecraft/plugins/" + owner: "{{ server_user }}" + group: "{{ server_user }}" + mode: '0644' + notify: Restart minecraft Server diff --git a/roles/minecraft/tasks/server.yml b/roles/minecraft/tasks/server.yml new file mode 100644 index 0000000..e6d04f4 --- /dev/null +++ b/roles/minecraft/tasks/server.yml @@ -0,0 +1,38 @@ +--- +- name: Create a server directory + ansible.builtin.file: + path: "/home/{{ server_user }}/minecraft" + state: directory + owner: "{{ server_user }}" + group: "{{ server_user }}" + mode: '0755' + +- name: Deploy server files + copy: + src: "files/server/" + dest: "/home/{{ server_user }}/minecraft/" + owner: "{{ server_user }}" + group: "{{ server_user }}" + mode: '0644' + notify: Restart minecraft Server + tags: update_server + +- name: Deploy server icon + ansible.builtin.copy: + src: server-icon.png + dest: "/home/{{ server_user }}/minecraft/" + owner: "{{ server_user }}" + group: "{{ server_user }}" + mode: '0644' + backup: true + notify: Restart minecraft Server + tags: icon_deploy + +- name: Generate server config + ansible.builtin.template: + src: server.properties.j2 + dest: "/home/{{ server_user }}/minecraft/server.properties" + owner: "{{ server_user }}" + group: "{{ server_user }}" + notify: Restart minecraft Server + tags: config_deploy diff --git a/roles/minecraft/tasks/service.yml b/roles/minecraft/tasks/service.yml new file mode 100644 index 0000000..386f6df --- /dev/null +++ b/roles/minecraft/tasks/service.yml @@ -0,0 +1,26 @@ +--- +- name: Deploy openrc service params + ansible.builtin.template: + src: minecraft-rc.j2 + dest: /etc/conf.d/minecraftd + mode: '0644' + +- name: Deploy base openrc service + ansible.builtin.template: + src: minecraft.j2 + dest: /etc/init.d/minecraft + mode: '0755' + +- name: Create a symbolic link to openrc service + ansible.builtin.file: + src: /etc/init.d/minecraft + dest: /etc/init.d/minecraftd + state: link + mode: '0755' + +- name: Add minecraft server to boot + ansible.builtin.service: + name: minecraftd + runlevel: default + enabled: True + use: openrc diff --git a/roles/minecraft/tasks/tuning.yml b/roles/minecraft/tasks/tuning.yml new file mode 100644 index 0000000..b58cda5 --- /dev/null +++ b/roles/minecraft/tasks/tuning.yml @@ -0,0 +1,2 @@ +--- +# Disable plugin list diff --git a/roles/minecraft/tasks/users.yml b/roles/minecraft/tasks/users.yml new file mode 100644 index 0000000..e92c16f --- /dev/null +++ b/roles/minecraft/tasks/users.yml @@ -0,0 +1,22 @@ +--- +- name: Ensure group "{{ userdb[item].user_group }}" exists + ansible.builtin.group: + name: "{{ userdb[item].user_group }}" + state: present + with_items: "{{ userdb }}" + +- name: Add user "{{ item }}" + ansible.builtin.user: + name: "{{ item }}" + # shell: /bin/bash + group: "{{ userdb[item].user_group }}" + password: "{{ userdb[item].user_pass }}" + comment: "My Default user" + with_items: "{{ userdb }}" + +- name: Deploy authorized key for users + ansible.posix.authorized_key: + user: "{{ item }}" + key: "{{ userdb[item].key }}" + with_items: "{{ userdb }}" + when: not ansible_check_mode diff --git a/roles/minecraft/templates/1minecraft-rc.j2 b/roles/minecraft/templates/1minecraft-rc.j2 new file mode 100644 index 0000000..3a22212 --- /dev/null +++ b/roles/minecraft/templates/1minecraft-rc.j2 @@ -0,0 +1,11 @@ +# /etc/conf.d/minecraft +# +# Minecraft - OpenRC scripts +# Copyright (C) 2017-2019 João Brázio [joao@brazio.org] +# + +MINHEAP={{ MINHEAP }} +MAXHEAP={{ MAXHEAP }} + +# https://aikar.co/2018/07/02/tuning-the-jvm-g1gc-garbage-collector-flags-for-minecraft/ +#CUSTOMARGS="-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" diff --git a/roles/minecraft/templates/1minecraft.j2 b/roles/minecraft/templates/1minecraft.j2 new file mode 100644 index 0000000..4e074d3 --- /dev/null +++ b/roles/minecraft/templates/1minecraft.j2 @@ -0,0 +1,125 @@ +#!/sbin/openrc-run +# /etc/init.d/minecraft +# +# Minecraft - OpenRC scripts +# Copyright (C) 2017-2019 João Brázio [joao@brazio.org] +# +# Expects the game folder to be located at /srv/minecraft/ +# Don't use directly the /etc/init.d/minecraft script, create a symlink for you instance. +# +# This is an example for Paper: +# - mkdir -p /srv/minecraft/paper +# - Download paper jar and place it there +# - ln -s /etc/init.d/minecraft /etc/init.d/minecraft.paper +# - cp /etc/conf.d/minecraft /etc/conf.d/minecraft.paper +# +# Dependencies: +# - Java VM at /usr/bin/java +# - mcrcon [https://github.com/Tiiffi/mcrcon] +# + +USER={{ server_user }} +GROUP={{ server_user }} + +INSTANCE=${RC_SVCNAME##*.} +BASE="/home/{{ server_user }}/minecraft" +PIDFILE="/var/run/${RC_SVCNAME}.pid" +RCON="/usr/bin/rcon" +BIN="$(ls ${BASE} -v 2>/dev/null | grep -i "craftbukkit.*jar\\|spigot.*jar\\|paper*.*jar\\|minecraft_server.*jar" | head -n 1)" + +config_get () { + echo $(grep ${1} "${BASE}/server.properties" | cut -d '=' -f 2) +} + +depend () { + need net +} + +start_pre () { + if [ -z "${BIN}" ]; then + eerror "${RC_SVCNAME} cannot find a proper server jar." + eerror "Check your game installation at ${BASE}." + return 1 + fi + + [ -f "${PIDFILE}" ] && rm ${PIDFILE} + + return 0 +} + +start () { + ebegin "Starting Minecraft server ${INSTANCE}" + start-stop-daemon --start --chdir ${BASE} --pidfile ${PIDFILE} --make-pidfile \ + --exec /usr/bin/java --user ${USER} --group ${GROUP} \ + --background -- -server -Xms${MINHEAP:-128M} -Xmx${MAXHEAP:-1024M} \ + ${CUSTOMARGS} -jar ${BIN} nogui + eend $? +} + +stop_pre () { + if [ ! -f "${BASE}/server.properties" ]; then + eerror "${RC_SVCNAME} cannot find a proper server config file." + eerror "Check your game installation at ${BASE}." + return 1 + fi + + return 0 +} + +stop () { + ebegin "Stopping Minecraft server ${INSTANCE}" + + if [ "$(config_get enable-rcon)" = "true" ]; then + # Fetch rcon configuration + RCON_SRV=$(config_get server.ip) + RCON_PORT=$(config_get rcon.port) + RCON_PASS=$(config_get rcon.password) + + # Try to soft kill the server + ${RCON} -H ${RCON_SRV:-127.0.0.1} -p ${RCON_PORT} -m -P ${RCON_PASS} save-all 1>/dev/null 2>&1 + ${RCON} -H ${RCON_SRV:-127.0.0.1} -p ${RCON_PORT} -m -P ${RCON_PASS} stop 1>/dev/null 2>&1 + + i=0 + PID=$(cat ${PIDFILE}) + + while [ "${i}" -le 30 ]; do + kill -0 ${PID} 2>/dev/null && sleep 1 || break + i=$(( i + 1 )) + done + fi + + # Hard stop the server + start-stop-daemon --stop --chdir ${BASE} --pidfile ${PIDFILE} --user ${USER} --group ${GROUP} --retry 5 2>/dev/null + eend 0 +} + +status () { + if [ "$(config_get enable-rcon)" = "true" ]; then + # Fetch rcon configuration + RCON_SRV=$(config_get server.ip) + RCON_PORT=$(config_get rcon.port) + RCON_PASS=$(config_get rcon.password) + + ${RCON} -H ${RCON_SRV:-127.0.0.1} -p ${RCON_PORT} -m -P ${RCON_PASS} version + ${RCON} -H ${RCON_SRV:-127.0.0.1} -p ${RCON_PORT} -m -P ${RCON_PASS} tps + fi +} + + +backup() { + saveoff + + NOW=`date "+%Y-%m-%d_%Hh%M"` + BACKUP_FILE="${BACKUP_BASE}/backup_${NOW}.tar" + einfo "Backing up minecraft world..." + as_user "tar -C \"${BASE}\" -cf \"$BACKUP_FILE\" ${WORLDS}" + + einfo "Backing up ${BIN}" + as_user "tar -C \"${BASE}\" -rf \"$BACKUP_FILE\" ${BIN} server.properties" + + saveon + + einfo "Compressing backup..." + as_user "gzip -f \"$BACKUP_FILE\"" + einfo "Done." +} diff --git a/roles/minecraft/templates/backup_server.j2 b/roles/minecraft/templates/backup_server.j2 new file mode 100644 index 0000000..80ffb27 --- /dev/null +++ b/roles/minecraft/templates/backup_server.j2 @@ -0,0 +1,8 @@ +#!/bin/sh + +# Working dir +cd /home/{{ server_user }}/backups +# Delete old backups +find . -name "backup_*.tar.gz" -type f -mtime +1 -delete +# Start backup +rc-service minecraftd backup diff --git a/roles/minecraft/templates/hosts.j2 b/roles/minecraft/templates/hosts.j2 new file mode 100644 index 0000000..3aff323 --- /dev/null +++ b/roles/minecraft/templates/hosts.j2 @@ -0,0 +1 @@ +127.0.0.1 {{ inventory_hostname }}.my.domain {{ inventory_hostname }} localhost.localdomain localhost diff --git a/roles/minecraft/templates/minecraft-rc.j2 b/roles/minecraft/templates/minecraft-rc.j2 new file mode 100644 index 0000000..fbd3853 --- /dev/null +++ b/roles/minecraft/templates/minecraft-rc.j2 @@ -0,0 +1,23 @@ +# /etc/conf.d/minecraft +# +# Minecraft - OpenRC scripts +# Copyright (C) 2024 Santic Zombie [email@santic-zombie.ru] +# +# + +MINHEAP={{ MINHEAP }} +MAXHEAP={{ MAXHEAP }} + +USER={{ server_user }} +GROUP={{ server_user }} + +BASE="/home/{{ server_user }}/minecraft" +BACKUP_BASE="/home/{{ server_user }}/backups" + +SCREENNAME="Minecraft" + +WORLDS="{{ level_name }} {{ level_name }}_nether {{ level_name }}_the_end" + + +# https://aikar.co/2018/07/02/tuning-the-jvm-g1gc-garbage-collector-flags-for-minecraft/ +#CUSTOMARGS="-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" diff --git a/roles/minecraft/templates/minecraft.j2 b/roles/minecraft/templates/minecraft.j2 new file mode 100644 index 0000000..9c0de6e --- /dev/null +++ b/roles/minecraft/templates/minecraft.j2 @@ -0,0 +1,158 @@ +#!/sbin/openrc-run +# /etc/init.d/minecraft +# +# Minecraft - OpenRC scripts +# Copyright (C) 2024 Santic Zombie [email@santic-zombie.ru] +# +# + +extra_commands="reload backup listen" + +INSTANCE=${RC_SVCNAME##*.} +PIDFILE="/var/run/${RC_SVCNAME}.pid" +BIN="$(ls ${BASE} -v 2>/dev/null | grep -i "craftbukkit.*jar\\|spigot.*jar\\|paper*.*jar\\|minecraft_server.*jar" | head -n 1)" +INVOCATION="/usr/bin/java -server -Xms${MINHEAP:-128M} -Xmx${MAXHEAP:-1024M} \ +${CUSTOMARGS} -jar ${BIN} nogui" + +depend() { + need net localmount + after bootmisc + use logger +} + +ME=`whoami` +as_user() { + if [ "${ME}" = "${USER}" ] ; then + ash -c "$1" + else + su - "${USER}" -c "$1" + fi +} + +start_pre () { + if [ -z "${BIN}" ]; then + eerror "${RC_SVCNAME} cannot find a proper server jar." + eerror "Check your game installation at ${BASE}." + return 1 + fi + + [ -f "${PIDFILE}" ] && rm ${PIDFILE} + + return 0 +} + +start () { + ebegin "Starting Minecraft server daemon" + if pgrep -u "${USER}" -f "${BIN}" > /dev/null ; then + einfo "Minecraft server is already running!" + else + ebegin "Starting in progress" + cd "${BASE}" + as_user "cd ${BASE} && screen -dmS ${SCREENNAME} ${INVOCATION}" + sleep 10 + pgrep -f "${BIN}" | tail -1 > "${PIDFILE}" + if pgrep -u "${USER}" -f "${BIN}" | tail -1 > /dev/null ; then + einfo "${INSTANCE} is now running." + else + eerror "Error! Could not start ${INSTANCE}! :(" + return 2 + fi + fi +} + +stop() { + ebegin "Stopping Minecraft server daemon" + if pgrep -u "${USER}" -f "${BIN}" > /dev/null ; then + ebegin "Stopping in progress" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"say SERVER SHUTTING DOWN IN 30 SECONDS. Saving map...\"\015'" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"save-all\"\015'" + sleep 10 + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"stop\"\015'" + sleep 10 + else + einfo "${INSTANCE} was not running." + fi + if pgrep -u "${USER}" -f "${BIN}" > /dev/null ; then + eerror "Error! ${INSTANCE} could not be stopped." + else + einfo "${INSTANCE} is stopped." + fi + + # Hard stop the server + start-stop-daemon --stop --chdir ${BASE} --pidfile ${PIDFILE} --user ${USER} --group ${GROUP} --retry 5 2>/dev/null + eend 0 +} + +restart() { + ebegin "Reload Minecraft server daemon" + stop + start + eend $? +} + +reload() { + ebegin "Reload Minecraft server" + if pgrep -u "${USER}" -f "${BIN}" > /dev/null ; then + ebegin "Reloading in progress" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"say SERVER RELOADING IN 40 SECONDS. Saving map...\"\015'" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"save-all\"\015'" + sleep 10 + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"reload\"\015'" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"reload confirm\"\015'" + sleep 10 + else + einfo "${INSTANCE} was not running." + fi + if pgrep -u "${USER}" -f "${BIN}" > /dev/null ; then + einfo "Server reloaded." + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"say SERVER SUCCESSFULLY RELOADED!\"\015'" + else + eerror "Error! ${INSTANCE} could not reloaded! :(" + fi +} + +saveoff() { + if pgrep -u "${USER}" -f "${BIN}" > /dev/null ; then + einfo "Server is running... suspending saves" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"say SERVER BACKUP STARTING. Server going readonly...\"\015'" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"save-off\"\015'" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"save-all\"\015'" + sync + sleep 10 + else + einfo "${INSTANCE} is not running." + fi +} + +saveon() { + if pgrep -u "${USER}" -f "${BIN}" > /dev/null ; then + einfo "Server is running... re-enabling saves" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"save-on\"\015'" + as_user "screen -p 0 -S ${SCREENNAME} -X eval 'stuff \"say SERVER BACKUP ENDED. Server going read-write...\"\015'" + else + echo "${INSTANCE} is not running. Not resuming saves." + fi +} + +backup() { + saveoff + + NOW=`date "+%Y-%m-%d_%Hh%M"` + BACKUP_FILE="${BACKUP_BASE}/backup_${NOW}.tar" + einfo "Backing up minecraft server..." + as_user "tar -C \"${BASE}\" -cf \"$BACKUP_FILE\" ." + + saveon + + einfo "Compressing backup..." + as_user "gzip -f \"$BACKUP_FILE\"" + einfo "Done." +} + +listen() { + if pgrep -u "${USER}" -f "${BIN}" > /dev/null ; then + as_user "tail -f ${BASE}/logs/latest.log" + else + echo "${INSTANCE} is not running. Cannot listen to server." + fi +} diff --git a/roles/minecraft/templates/motd.j2 b/roles/minecraft/templates/motd.j2 new file mode 100644 index 0000000..3ac8d08 --- /dev/null +++ b/roles/minecraft/templates/motd.j2 @@ -0,0 +1,14 @@ + +Welcome to {{ inventory_hostname }} Server! ^_^ + + :\ /; _ + ; \___/ ; ; ; + ,:-"' `"-:. / ; +_ /,---. ,---.\ _ _; / +_:>(( | ) ( | ))<:_ ,-""_," + \````` `````/""""",-"" + '-.._ v _..-' ) + / ___ ____,.. \ + / / | | | ( \. \ +nya / / | | | | \ \ + `" `" `" `" diff --git a/roles/minecraft/templates/nginx.j2 b/roles/minecraft/templates/nginx.j2 new file mode 100644 index 0000000..9ea73b1 --- /dev/null +++ b/roles/minecraft/templates/nginx.j2 @@ -0,0 +1,58 @@ +user {{ nginx_user }}; +worker_processes {{ worker_processes }}; + +error_log {{ log_dir }}/error.log; +error_log {{ log_dir }}/error.log notice; +error_log {{ log_dir }}/error.log info; + +events { + worker_connections {{ worker_connections }}; +} + +http { + include mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log {{ log_dir }}/access.log main; + + sendfile on; + tcp_nopush on; + #keepalive_timeout 65; + gzip on; + + server { + listen 80 default_server; + #server_name _; + + root /srv/dynmap/web; + + index index.php index.html index.htm; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } + + # pass PHP scripts to FastCGI server + + location ~ \.php$ { + fastcgi_pass 127.0.0.1:9000; + fastcgi_index index.php; + include fastcgi.conf; + } + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + location ~ /\.ht { + deny all; + } + } + + #include sites-enabled/*; +} diff --git a/roles/minecraft/templates/server.properties.j2 b/roles/minecraft/templates/server.properties.j2 new file mode 100644 index 0000000..aff96e2 --- /dev/null +++ b/roles/minecraft/templates/server.properties.j2 @@ -0,0 +1,59 @@ +enable-jmx-monitoring=false +rcon.port={{ rcon_port }} +level-seed= +gamemode={{ gamemode }} +enable-command-block=false +enable-query=false +generator-settings={} +enforce-secure-profile={{ enforce_secure_profile }} +level-name={{ level_name }} +motd={{ server_status }} +query.port={{ game_port }} +pvp={{ pvp }} +generate-structures=true +max-chained-neighbor-updates={{ neighbor_updates }} +difficulty={{ difficulty }} +network-compression-threshold={{ network_compression_threshold }} +max-tick-time=60000 +require-resource-pack=false +use-native-transport=true +max-players={{ max_players }} +online-mode=false +enable-status=true +allow-flight=false +initial-disabled-packs= +broadcast-rcon-to-ops=true +view-distance={{ view_distance }} +server-ip= +resource-pack-prompt= +allow-nether=true +server-port={{ game_port }} +enable-rcon={{ enable_rcon }} +sync-chunk-writes=true +resource-pack-id= +op-permission-level={{ op_permission_level }} +prevent-proxy-connections=false +hide-online-players=false +resource-pack= +entity-broadcast-range-percentage={{ entity_broadcast_range }} +simulation-distance={{ simulation_distance }} +rcon.password={{ rcon_password }} +player-idle-timeout=0 +debug=false +force-gamemode=false +rate-limit=0 +hardcore=false +white-list=false +broadcast-console-to-ops=true +spawn-npcs=true +spawn-animals=true +log-ips=true +function-permission-level=2 +initial-enabled-packs=vanilla +level-type=minecraft\:normal +text-filtering-config= +spawn-monsters=true +enforce-whitelist=false +spawn-protection={{ spawn_protection }} +resource-pack-sha1= +max-world-size=29999984 diff --git a/roles/minecraft/templates/sshd_config.j2 b/roles/minecraft/templates/sshd_config.j2 new file mode 100644 index 0000000..0e4d1ba --- /dev/null +++ b/roles/minecraft/templates/sshd_config.j2 @@ -0,0 +1,6 @@ +Port {{ ssh_port }} +PubkeyAuthentication yes +PasswordAuthentication no +PermitEmptyPasswords no +ChallengeResponseAuthentication no +Subsystem sftp /usr/lib/ssh/sftp-server