Appliance Basic Setup - Ansible
Here is my freshly revised Playbook to prepare the Appliance.
And no, i haven't had the need for complex roles so it's just a play.
Requirements on Appliance
- root password set (for access via ssh)
- Network configured (The MachineID fix might lead to a new ip with dhcp)
Requirements on Workstation
mkdir -p group_vars
echo pubkey_url: https://what.ever/some/pubkey.pub >> ~/group_vars/all
cat << EOF > inventory.yaml
grommunio:
hosts:
grommunio-test-1.your.network.local:
EOF
Tasks
- Fixes Systemd-Machine-ID
- Auto-accept Repo-Keys and apply latest Updates
- Set Timezone
- Install various Software-Packages
- Install virtualizing agent depending on the Hardware (QEMU, VMware or Hyper-V)
- Activate ZRAM (100%)
- Enable automatic installation of security updates / daily
- Enable group wheel and allow sudo for them (no user creation included)
- Grub timeout 2 seconds instead of 10
- Install SSH pubkey for root via http link
- Disable Password Auth for SSH (pubkey only!)
- Enable tmpfs for /tmp
prepare-appliance.json
[
{
"name": "SystemD",
"hosts": "all",
"become": false,
"tags": "systemd",
"tasks": [
{
"name": "DiffUUIDs",
"ansible.builtin.command": "diff -q /etc/machine-id /var/lib/dbus/machine-id",
"ignore_errors": true,
"register": "diffuuid"
},
{
"name": "DeleteUUID",
"ansible.builtin.file": {
"path": "{{ item }}",
"state": "absent"
},
"when": "diffuuid.rc != 0",
"register": "tmpfsdeleted",
"with_items": [
"/etc/machine-id",
"/var/lib/dbus/machine-id"
]
},
{
"name": "MachineID",
"ansible.builtin.command": "/usr/bin/systemd-machine-id-setup",
"register": "machinedactivate",
"changed_when": "machinedactivate"
},
{
"name": "DBUS-UUIDGEN",
"ansible.builtin.command": "/usr/bin/dbus-uuidgen --ensure",
"register": "dbusactivate",
"changed_when": "dbusactivate"
},
{
"name": "JournalDPersistent",
"ansible.builtin.replace": {
"path": "/etc/systemd/journald.conf",
"regexp": "^#Storage=auto",
"replace": "Storage=persistent"
}
}
]
},
{
"name": "Install Updates",
"hosts": "all",
"become": false,
"tags": "updates",
"tasks": [
{
"name": "TestRepo",
"ansible.builtin.shell": "zypper --quiet repos --name grommunio >/dev/null 2>&1",
"register": "grommuniorepo",
"ignore_errors": true,
"changed_when": "grommuniorepo"
},
{
"name": "Refresh-Repos-Accept-Keys",
"ansible.builtin.command": "zypper --quiet --gpg-auto-import-keys ref",
"when": "grommuniorepo.rc != 0",
"register": "refret",
"changed_when": "refret"
},
{
"name": "Activate-Grommunio-Repo-And-Upgrade",
"ansible.builtin.command": "grommunio-update upgrade community --noreboot --nopostfix",
"ignore_errors": true,
"when": "grommuniorepo.rc != 0",
"register": "ignoreerrors",
"changed_when": "ignoreerrors"
},
{
"name": "Update all packages on OpenSUSE/SUSE Linux",
"community.general.zypper": {
"name": "*",
"state": "latest"
}
},
{
"name": "Check if a reboot is needed on all SUSE/OpenSUSE based servers",
"ansible.builtin.stat": {
"path": "/boot/do_purge_kernels"
},
"register": "linux_reboot_required_file"
},
{
"name": "Reboot the SUSE/OpenSUSE box if kernel updated",
"ansible.builtin.reboot": {
"msg": "Reboot initiated by Ansible for kernel updates",
"connect_timeout": 5,
"reboot_timeout": 300,
"pre_reboot_delay": 0,
"post_reboot_delay": 30,
"test_command": "uptime"
},
"when": "linux_reboot_required_file.stat.exists"
}
]
},
{
"name": "Basics",
"hosts": "all",
"become": false,
"gather_facts": true,
"handlers": [
{
"name": "Restart ssh",
"ansible.builtin.systemd": {
"name": "sshd",
"daemon_reload": true
}
},
{
"name": "Grub2MkConfig",
"ansible.builtin.command": "grub2-mkconfig -o /boot/grub2/grub.cfg"
}
],
"tasks": [
{
"name": "Timezone",
"community.general.timezone": {
"name": "Europe/Berlin"
}
},
{
"name": "Required-software",
"community.general.zypper": {
"name": [
"ShellCheck",
"acl",
"bash-completion",
"bzip2",
"git",
"growpart",
"htop",
"jq",
"man",
"man-pages",
"coreutils-doc",
"nfs-client",
"php8-APCu",
"purge-kernels-service",
"yast2-online-update-configuration",
"python3-argcomplete",
"sshfs",
"system-group-wheel",
"zram-generator",
"vim-data"
],
"state": "present",
"disable_recommends": true
},
"tags": "software"
},
{
"name": "QemuGuestAgent",
"community.general.zypper": {
"name": [
"qemu-guest-agent"
],
"state": "installed",
"disable_recommends": true,
"clean_deps": true
},
"tags": "hypervisor",
"when": "ansible_system_vendor == \"QEMU\""
},
{
"name": "EnableQemuAgent",
"ansible.builtin.systemd": {
"name": "qemu-guest-agent.service",
"state": "started",
"enabled": true
},
"tags": "hypervisor",
"when": "ansible_system_vendor == \"QEMU\""
},
{
"name": "HyperV",
"community.general.zypper": {
"name": [
"hyper-v"
],
"state": "installed",
"disable_recommends": true,
"clean_deps": true
},
"tags": "hypervisor",
"when": "ansible_system_vendor == \"Microsoft Corporation\""
},
{
"name": "EnableHyperV",
"ansible.builtin.systemd": {
"name": "{{ item }}.service",
"state": "started",
"enabled": true
},
"with_items": [
"hv_fcopy_daemon",
"hv_kvp_daemon",
"hv_vss_daemon"
],
"tags": "hypervisor",
"when": "ansible_system_vendor == \"Microsoft Corporation\""
},
{
"name": "OpenVMTools",
"community.general.zypper": {
"name": [
"open-vm-tools"
],
"state": "installed",
"disable_recommends": true,
"clean_deps": true
},
"tags": "hypervisor",
"when": "ansible_system_vendor == \"VMware, Inc.\""
},
{
"name": "EnableOpenVMTools",
"ansible.builtin.systemd": {
"name": "{{ item }}.service",
"state": "started",
"enabled": true
},
"with_items": [
"vgauthd",
"vmtoolsd"
],
"tags": "hypervisor",
"when": "ansible_system_vendor == \"VMware, Inc.\""
},
{
"name": "Online-Update-Config",
"ansible.builtin.lineinfile": {
"dest": "/etc/sysconfig/automatic_online_update",
"regexp": "^AOU_PATCH_CATEGORIES=\"\"",
"line": "AOU_PATCH_CATEGORIES=\"security\"",
"state": "present"
},
"tags": "autoupdates"
},
{
"name": "Enable Daily Security Updates",
"ansible.builtin.file": {
"src": "/usr/lib/YaST2/bin/online_update",
"dest": "/etc/cron.daily/automatic_online_update",
"state": "link"
},
"tags": "autoupdates",
"register": "autoupdateenabled",
"changed_when": "autoupdateenabled.changed"
},
{
"name": "Zram0",
"ansible.builtin.blockinfile": {
"path": "/etc/systemd/zram-generator.conf.d/0.conf",
"create": true,
"owner": "root",
"group": "root",
"mode": "0660",
"block": "[zram0]\nzram-size = int(ram)\n"
},
"tags": "zram"
},
{
"name": "Sudoers_wheel",
"ansible.builtin.blockinfile": {
"path": "/etc/sudoers.d/wheel",
"create": true,
"owner": "root",
"group": "root",
"mode": "0440",
"block": "%wheel ALL=(ALL:ALL) ALL\n"
},
"tags": "sudo"
},
{
"name": "Grub2Timeout",
"ansible.builtin.lineinfile": {
"dest": "/etc/default/grub",
"regexp": "^GRUB_TIMEOUT=10",
"line": "GRUB_TIMEOUT=2",
"state": "present"
},
"tags": "grub",
"notify": [
"Grub2MkConfig"
]
},
{
"name": "Sudoers_user_pw",
"ansible.builtin.replace": {
"path": "/etc/sudoers",
"regexp": "'^Defaults targetpw'",
"replace": "'#Defaults targetpw'"
},
"tags": "sudo"
},
{
"name": "Set root authorized_keys",
"tags": "ssh",
"ansible.posix.authorized_key": {
"user": "root",
"state": "present",
"key": "{{ lookup('url', pubkey_url, split_lines=False) }}"
},
"tags": "sudo"
},
{
"name": "Set only Password-Auth",
"tags": "ssh",
"ansible.builtin.lineinfile": {
"dest": "/etc/ssh/sshd_config",
"regexp": "^#PasswordAuthe",
"line": "PasswordAuthentication no",
"state": "present",
"backup": true
},
"tags": "ssh"
},
{
"name": "Set ChallengeResponseAuth",
"tags": "ssh",
"ansible.builtin.lineinfile": {
"dest": "/etc/ssh/sshd_config",
"regexp": "^ChallengeResponse",
"line": "ChallengeResponseAuthentication no",
"state": "present",
"backup": true
},
"tags": "ssh"
},
{
"name": "Set root only pubkey",
"tags": "ssh",
"ansible.builtin.lineinfile": {
"dest": "/etc/ssh/sshd_config",
"regexp": "^PermitRootLogin",
"line": "PermitRootLogin without-password",
"state": "present",
"backup": true
},
"notify": [
"Restart ssh"
],
"tags": "sudo"
}
]
},
{
"name": "TmpFS_Enable",
"hosts": "all",
"tags": "tmpfs",
"become": false,
"tasks": [
{
"name": "FindMntTmp",
"ansible.builtin.command": "findmnt --types=tmpfs --target=/tmp --noheadings",
"ignore_errors": true,
"register": "notmpfs"
},
{
"name": "DeleteTmp",
"ansible.builtin.file": {
"path": "/tmp",
"state": "absent"
},
"when": "notmpfs.rc != 0",
"register": "tmpfsdeleted"
},
{
"name": "CreateTmp",
"ansible.builtin.file": {
"path": "/tmp",
"state": "directory",
"mode": "0755"
},
"when": "notmpfs != 0",
"register": "tmpfsempty"
},
{
"name": "TmpfsEnable",
"ansible.builtin.file": {
"src": "/usr/share/systemd/tmp.mount",
"dest": "/etc/systemd/system/tmp.mount",
"state": "link"
},
"register": "tmpfsenabled",
"when": "tmpfsempty",
"changed_when": "tmpfsenabled.changed"
},
{
"name": "Reboot",
"ansible.builtin.reboot": {
"msg": "Reboot initiated by Ansible for TmpFS",
"connect_timeout": 5,
"reboot_timeout": 300,
"pre_reboot_delay": 0,
"post_reboot_delay": 30,
"test_command": "uptime"
},
"when": "tmpfsenabled.changed"
}
],
"tags": "tmpfs"
}
]
First run with ask-pass
ansible-playbook prepare-appliance.json -l grommunio-test-1.your.network.local -k
If everything worked out you will need to ommit the -k
as that is only for password auth.
From here i usually configure an additional mount for /var/lib/gromox
but that i do manually followed by grommunio-setup
.