first commit
This commit is contained in:
81
ansible-playbooks/common/create-ansible-user.yml
Normal file
81
ansible-playbooks/common/create-ansible-user.yml
Normal file
@@ -0,0 +1,81 @@
|
||||
# command: ansible-playbook -i config/<target manifest>.ini common/create-ansible-user.yml --ask-become-pass
|
||||
# Note: this playbook requires an interactive mode or passed secret for privilege escalation
|
||||
---
|
||||
- name: Create ansible user and configure passwordless sudo
|
||||
hosts: all
|
||||
become: true
|
||||
become_method: sudo
|
||||
vars:
|
||||
ansible_user: khwezi
|
||||
tasks:
|
||||
- name: Ensure 'ansible' user exists
|
||||
ansible.builtin.user:
|
||||
name: ansible
|
||||
groups: sudo
|
||||
append: yes
|
||||
shell: /bin/bash
|
||||
state: present
|
||||
- name: Check if passwordless sudo is already configured for 'ansible'
|
||||
ansible.builtin.shell: |
|
||||
grep -Fxq "ansible ALL=(ALL) NOPASSWD: ALL" /etc/sudoers.d/ansible
|
||||
register: sudoers_check
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
- name: Allow 'ansible' user passwordless sudo
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/sudoers.d/ansible
|
||||
content: "ansible ALL=(ALL) NOPASSWD: ALL\n"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0440'
|
||||
when: sudoers_check.rc != 0
|
||||
- name: Ensure /home/ansible/.ssh directory exists
|
||||
ansible.builtin.file:
|
||||
path: /home/ansible/.ssh
|
||||
state: directory
|
||||
owner: ansible
|
||||
group: ansible
|
||||
mode: '0700'
|
||||
- name: Copy id_ed25519 private key to ansible user
|
||||
ansible.builtin.copy:
|
||||
src: ~/.ssh/id_ed25519
|
||||
dest: /home/ansible/.ssh/id_ed25519
|
||||
owner: ansible
|
||||
group: ansible
|
||||
mode: '0600'
|
||||
- name: Copy id_ed25519 public key to ansible user
|
||||
ansible.builtin.copy:
|
||||
src: ~/.ssh/id_ed25519.pub
|
||||
dest: /home/ansible/.ssh/id_ed25519.pub
|
||||
owner: ansible
|
||||
group: ansible
|
||||
mode: '0644'
|
||||
- name: Ensure authorized_keys exists
|
||||
ansible.builtin.file:
|
||||
path: /home/ansible/.ssh/authorized_keys
|
||||
state: touch
|
||||
owner: ansible
|
||||
group: ansible
|
||||
mode: '0600'
|
||||
- name: Read public key content
|
||||
ansible.builtin.slurp:
|
||||
src: /home/ansible/.ssh/id_ed25519.pub
|
||||
register: pubkey_content
|
||||
- name: Ensure public key is present in authorized_keys
|
||||
ansible.builtin.lineinfile:
|
||||
path: /home/ansible/.ssh/authorized_keys
|
||||
line: "{{ pubkey_content['content'] | b64decode | trim }}"
|
||||
owner: ansible
|
||||
group: ansible
|
||||
mode: '0600'
|
||||
create: yes
|
||||
state: present
|
||||
|
||||
- name: Allow 'ansible' user to write to /etc/systemd/resolved.conf
|
||||
ansible.builtin.file:
|
||||
path: /etc/systemd/resolved.conf
|
||||
owner: ansible
|
||||
group: ansible
|
||||
mode: '0664'
|
||||
state: file
|
||||
become: true
|
||||
86
ansible-playbooks/common/install-docker.yml
Normal file
86
ansible-playbooks/common/install-docker.yml
Normal file
@@ -0,0 +1,86 @@
|
||||
# command: ansible-playbook -i config/<target manifest>.ini common/install-docker.yml
|
||||
---
|
||||
- name: Install Docker and Test
|
||||
hosts: all
|
||||
become: true
|
||||
become_method: sudo
|
||||
|
||||
tasks:
|
||||
- name: Ensure required apt packages are installed
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- lsb-release
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Ensure gpg is installed
|
||||
ansible.builtin.apt:
|
||||
name: gpg
|
||||
state: present
|
||||
|
||||
- name: Remove old Docker keyring files if present
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
- /usr/share/keyrings/docker-archive-keyring.gpg.asc
|
||||
|
||||
- name: Download Docker's official GPG key (ASCII)
|
||||
ansible.builtin.get_url:
|
||||
url: https://download.docker.com/linux/ubuntu/gpg
|
||||
dest: /usr/share/keyrings/docker-archive-keyring.gpg.asc
|
||||
mode: '0644'
|
||||
force: yes
|
||||
|
||||
- name: Convert Docker GPG key to binary format
|
||||
ansible.builtin.command: >
|
||||
gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg /usr/share/keyrings/docker-archive-keyring.gpg.asc
|
||||
|
||||
- name: Add Docker repository if not present (modern method)
|
||||
ansible.builtin.apt_repository:
|
||||
repo: "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
|
||||
state: present
|
||||
filename: docker
|
||||
|
||||
- name: Update apt cache after adding Docker repo
|
||||
ansible.builtin.apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Check if Docker is already installed
|
||||
ansible.builtin.command: docker --version
|
||||
register: docker_check
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
|
||||
- name: Install Docker Engine
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
state: present
|
||||
when: docker_check.rc != 0
|
||||
|
||||
- name: Check Docker version (post-install)
|
||||
ansible.builtin.command: docker --version
|
||||
register: docker_version
|
||||
changed_when: false
|
||||
|
||||
- name: Show Docker version
|
||||
ansible.builtin.debug:
|
||||
var: docker_version.stdout
|
||||
|
||||
- name: Run hello-world container to test Docker
|
||||
ansible.builtin.command: docker run --name hello-test --rm hello-world
|
||||
register: hello_world_output
|
||||
changed_when: false
|
||||
|
||||
- name: Show hello-world output
|
||||
ansible.builtin.debug:
|
||||
var: hello_world_output.stdout
|
||||
|
||||
28
ansible-playbooks/common/update-docker.yml
Normal file
28
ansible-playbooks/common/update-docker.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
# command: ansible-playbook -i config/<target manifest>.ini common/update-docker.yml
|
||||
---
|
||||
- name: Update Docker only on hosts where it is installed
|
||||
hosts: all
|
||||
become: true
|
||||
become_method: sudo
|
||||
|
||||
tasks:
|
||||
- name: Check if Docker is installed
|
||||
ansible.builtin.command: docker --version
|
||||
register: docker_check
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
|
||||
- name: Update Docker packages if installed
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
state: latest
|
||||
update_cache: yes
|
||||
when: docker_check.rc == 0
|
||||
|
||||
- name: Debug message if Docker is not installed
|
||||
ansible.builtin.debug:
|
||||
msg: "Docker is not installed on this host. Skipping update."
|
||||
when: docker_check.rc != 0
|
||||
19
ansible-playbooks/common/update-hosts.yml
Normal file
19
ansible-playbooks/common/update-hosts.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
# command: ansible-playbook -i config/<target manifest>.ini common/update-hosts.yml
|
||||
---
|
||||
- name: Update and upgrade all apt packages
|
||||
hosts: all
|
||||
become: true
|
||||
become_method: sudo
|
||||
|
||||
tasks:
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Upgrade all packages
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
|
||||
- name: Autoremove unused packages
|
||||
ansible.builtin.apt:
|
||||
autoremove: yes
|
||||
7
ansible-playbooks/config.ini
Normal file
7
ansible-playbooks/config.ini
Normal file
@@ -0,0 +1,7 @@
|
||||
[all:vars]
|
||||
ansible_python_interpreter=/usr/bin/python3
|
||||
ansible_user=ansible
|
||||
ansible_ssh_private_key_file=~/.ssh/id_ed25519
|
||||
|
||||
[gameservers]
|
||||
minecraft ansible_host=minecraft.mngoma.lab
|
||||
105
ansible-playbooks/minecraft/install-playbook.yml
Normal file
105
ansible-playbooks/minecraft/install-playbook.yml
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
- name: Full Minecraft Server Setup (Paper + Geyser + Floodgate)
|
||||
hosts: gameservers
|
||||
become: yes
|
||||
vars:
|
||||
minecraft_user: minecraft
|
||||
minecraft_home: /opt/minecraft
|
||||
paper_version: "1.21.1"
|
||||
paper_build: "130"
|
||||
java_opts: "-Xms1G -Xmx3G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -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"
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Ensure required packages
|
||||
apt:
|
||||
name:
|
||||
- openjdk-21-jdk
|
||||
- curl
|
||||
- unzip
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Create minecraft user
|
||||
user:
|
||||
name: "{{ minecraft_user }}"
|
||||
shell: /bin/bash
|
||||
create_home: yes
|
||||
home: "{{ minecraft_home }}"
|
||||
|
||||
- name: Create server directory
|
||||
file:
|
||||
path: "{{ minecraft_home }}"
|
||||
state: directory
|
||||
owner: "{{ minecraft_user }}"
|
||||
group: "{{ minecraft_user }}"
|
||||
mode: '0755'
|
||||
|
||||
- name: Download PaperMC server
|
||||
get_url:
|
||||
url: "https://api.papermc.io/v2/projects/paper/versions/{{ paper_version }}/builds/{{ paper_build }}/downloads/paper-{{ paper_version }}-{{ paper_build }}.jar"
|
||||
dest: "{{ minecraft_home }}/paper.jar"
|
||||
owner: "{{ minecraft_user }}"
|
||||
group: "{{ minecraft_user }}"
|
||||
mode: '0755'
|
||||
|
||||
- name: Download Geyser-Spigot plugin
|
||||
get_url:
|
||||
url: "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/master/lastSuccessfulBuild/artifact/bootstrap/spigot/target/Geyser-Spigot.jar"
|
||||
dest: "{{ minecraft_home }}/plugins/Geyser-Spigot.jar"
|
||||
owner: "{{ minecraft_user }}"
|
||||
group: "{{ minecraft_user }}"
|
||||
mode: '0644'
|
||||
|
||||
- name: Download Floodgate plugin
|
||||
get_url:
|
||||
url: "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/lastSuccessfulBuild/artifact/spigot/build/libs/floodgate-spigot.jar"
|
||||
dest: "{{ minecraft_home }}/plugins/floodgate-spigot.jar"
|
||||
owner: "{{ minecraft_user }}"
|
||||
group: "{{ minecraft_user }}"
|
||||
mode: '0644'
|
||||
|
||||
- name: Create start.sh script
|
||||
copy:
|
||||
dest: "{{ minecraft_home }}/start.sh"
|
||||
content: |
|
||||
#!/bin/bash
|
||||
cd {{ minecraft_home }}
|
||||
exec java {{ java_opts }} -jar paper.jar nogui
|
||||
owner: "{{ minecraft_user }}"
|
||||
group: "{{ minecraft_user }}"
|
||||
mode: '0755'
|
||||
|
||||
- name: Accept EULA
|
||||
copy:
|
||||
dest: "{{ minecraft_home }}/eula.txt"
|
||||
content: "eula=true"
|
||||
owner: "{{ minecraft_user }}"
|
||||
group: "{{ minecraft_user }}"
|
||||
mode: '0644'
|
||||
|
||||
- name: Create systemd service
|
||||
copy:
|
||||
dest: /etc/systemd/system/minecraft.service
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Minecraft Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User={{ minecraft_user }}
|
||||
WorkingDirectory={{ minecraft_home }}
|
||||
ExecStart={{ minecraft_home }}/start.sh
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload systemd and enable Minecraft service
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
name: minecraft
|
||||
enabled: yes
|
||||
state: started
|
||||
80
ansible-playbooks/minecraft/update-playbook.yml
Normal file
80
ansible-playbooks/minecraft/update-playbook.yml
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
- name: Update Minecraft Server
|
||||
hosts: minecraft
|
||||
become: true
|
||||
vars:
|
||||
minecraft_user: minecraft
|
||||
minecraft_home: /opt/minecraft
|
||||
mc_service_name: minecraft
|
||||
mc_version_manifest: https://piston-meta.mojang.com/mc/game/version_manifest.json
|
||||
backup_dir: "{{ minecraft_home }}/backup"
|
||||
timestamp: "{{ lookup('pipe', 'date +%Y%m%d%H%M%S') }}"
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Ensure jq and wget are installed
|
||||
apt:
|
||||
name: [ wget, jq ]
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Stop Minecraft service
|
||||
systemd:
|
||||
name: "{{ mc_service_name }}"
|
||||
state: stopped
|
||||
|
||||
- name: Create backup directory
|
||||
file:
|
||||
path: "{{ backup_dir }}"
|
||||
state: directory
|
||||
owner: "{{ minecraft_user }}"
|
||||
group: "{{ minecraft_user }}"
|
||||
mode: "0755"
|
||||
|
||||
- name: Backup current server.jar
|
||||
copy:
|
||||
src: "{{ minecraft_home }}/server.jar"
|
||||
dest: "{{ backup_dir }}/server.jar.{{ timestamp }}"
|
||||
remote_src: true
|
||||
ignore_errors: yes # in case it's missing (first run)
|
||||
|
||||
- name: Backup world data folder
|
||||
archive:
|
||||
path: "{{ minecraft_home }}/world"
|
||||
dest: "{{ backup_dir }}/world-{{ timestamp }}.tar.gz"
|
||||
format: gz
|
||||
become_user: "{{ minecraft_user }}"
|
||||
when: ansible.builtin.stat.path is not none
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Download latest Minecraft server JAR
|
||||
shell: |
|
||||
set -e
|
||||
cd "{{ minecraft_home }}"
|
||||
latest_url=$(wget -qO- {{ mc_version_manifest }} | jq -r '.latest.release as $v | .versions[] | select(.id == $v) | .url')
|
||||
server_url=$(wget -qO- "$latest_url" | jq -r '.downloads.server.url')
|
||||
wget -qO server.jar "$server_url"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
|
||||
- name: Ensure correct ownership of files
|
||||
file:
|
||||
path: "{{ minecraft_home }}"
|
||||
owner: "{{ minecraft_user }}"
|
||||
group: "{{ minecraft_user }}"
|
||||
recurse: true
|
||||
|
||||
- name: Start Minecraft service
|
||||
systemd:
|
||||
name: "{{ mc_service_name }}"
|
||||
state: started
|
||||
|
||||
- name: Verify service is running
|
||||
systemd:
|
||||
name: "{{ mc_service_name }}"
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Display success message
|
||||
debug:
|
||||
msg: "Minecraft server updated and restarted successfully on {{ inventory_hostname }}"
|
||||
19
ansible-playbooks/webmin/commands.md
Normal file
19
ansible-playbooks/webmin/commands.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# 1. Install using script
|
||||
|
||||
```bash
|
||||
curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh
|
||||
sudo sh webmin-setup-repo.sh
|
||||
```
|
||||
|
||||
# 2. Install Webmin
|
||||
|
||||
```shell
|
||||
sudo apt update
|
||||
sudo apt install webmin
|
||||
```
|
||||
|
||||
# 3. Open port
|
||||
|
||||
```bash
|
||||
ufw allow 10000
|
||||
```
|
||||
25
ansible-playbooks/webmin/fix-apt-playbook.yml
Normal file
25
ansible-playbooks/webmin/fix-apt-playbook.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
- name: Cleanup broken Webmin repository
|
||||
hosts: all
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Remove old Webmin repository file
|
||||
file:
|
||||
path: /etc/apt/sources.list.d/webmin.list
|
||||
state: absent
|
||||
|
||||
- name: Remove Webmin GPG keyring (optional)
|
||||
file:
|
||||
path: /usr/share/keyrings/webmin.gpg
|
||||
state: absent
|
||||
|
||||
- name: Clean apt cache
|
||||
apt:
|
||||
autoclean: yes
|
||||
autoremove: yes
|
||||
|
||||
- name: Update apt cache
|
||||
apt:
|
||||
update_cache: yes
|
||||
56
ansible-playbooks/webmin/install-playbook.yml
Normal file
56
ansible-playbooks/webmin/install-playbook.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
- name: Install Webmin using official setup script
|
||||
hosts: all
|
||||
become: yes
|
||||
vars:
|
||||
webmin_port: 10000
|
||||
webmin_script: /tmp/webmin-setup-repo.sh
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Ensure required packages are installed
|
||||
apt:
|
||||
name:
|
||||
- curl
|
||||
- ufw
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Download Webmin setup script
|
||||
get_url:
|
||||
url: https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh
|
||||
dest: "{{ webmin_script }}"
|
||||
mode: '0755'
|
||||
|
||||
- name: Run Webmin setup script non-interactively
|
||||
command: "sh {{ webmin_script }}"
|
||||
args:
|
||||
stdin: "y\n"
|
||||
creates: /etc/apt/sources.list.d/webmin.list
|
||||
|
||||
- name: Update apt cache after script
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Install Webmin
|
||||
apt:
|
||||
name: webmin
|
||||
state: latest
|
||||
|
||||
- name: Ensure Webmin service is running
|
||||
systemd:
|
||||
name: webmin
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Allow Webmin port through UFW
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ webmin_port }}"
|
||||
proto: tcp
|
||||
register: ufw_rule
|
||||
|
||||
- name: Confirm UFW rule applied
|
||||
debug:
|
||||
msg: "UFW rule for Webmin (port {{ webmin_port }}) is present."
|
||||
when: ufw_rule.changed or ufw_rule.skipped
|
||||
55
ansible-playbooks/webmin/update-playbook.yml
Normal file
55
ansible-playbooks/webmin/update-playbook.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
- name: Safely update Webmin on all hosts
|
||||
hosts: all
|
||||
become: yes
|
||||
vars:
|
||||
webmin_repo: "deb http://download.webmin.com/download/repository sarge contrib"
|
||||
webmin_key_url: "http://www.webmin.com/jcameron-key.asc"
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Ensure required packages are installed for HTTPS repositories
|
||||
apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- software-properties-common
|
||||
- gnupg
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Add Webmin GPG key (idempotent)
|
||||
ansible.builtin.apt_key:
|
||||
url: "{{ webmin_key_url }}"
|
||||
state: present
|
||||
|
||||
- name: Ensure Webmin repository is present
|
||||
ansible.builtin.apt_repository:
|
||||
repo: "{{ webmin_repo }}"
|
||||
state: present
|
||||
|
||||
- name: Update apt cache
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Check if Webmin is installed
|
||||
command: dpkg -l webmin
|
||||
register: webmin_installed
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Upgrade Webmin if installed
|
||||
apt:
|
||||
name: webmin
|
||||
state: latest
|
||||
when: webmin_installed.rc == 0
|
||||
|
||||
- name: Install Webmin if not installed
|
||||
apt:
|
||||
name: webmin
|
||||
state: present
|
||||
when: webmin_installed.rc != 0
|
||||
|
||||
- name: Ensure Webmin service is running
|
||||
systemd:
|
||||
name: webmin
|
||||
state: restarted
|
||||
enabled: yes
|
||||
Reference in New Issue
Block a user