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": "grommunio",
"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": "Virtualization",
"hosts": "grommunio",
"become": false,
"tags": "virtualization",
"gather_facts": true,
"tasks": [
{
"name": "Install QemuGuestAgent",
"community.general.zypper": {
"name": [
"qemu-guest-agent"
],
"state": "installed",
"disable_recommends": true,
"clean_deps": true
},
"tags": "hypervisor",
"when": "ansible_system_vendor == \"QEMU\""
},
{
"name": "Enable qemu-guest-agent",
"ansible.builtin.systemd": {
"name": "qemu-guest-agent.service",
"state": "started",
"enabled": true
},
"tags": "hypervisor",
"when": "ansible_system_vendor == \"QEMU\""
},
{
"name": "Install HyperV agent",
"community.general.zypper": {
"name": [
"hyper-v"
],
"state": "installed",
"disable_recommends": true,
"clean_deps": true
},
"tags": "hypervisor",
"when": "ansible_system_vendor == \"Microsoft Corporation\""
},
{
"name": "Enable HyperV agent",
"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": "Install 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": "Enable OpenVMTools",
"ansible.builtin.systemd": {
"name": "{{ item }}.service",
"state": "started",
"enabled": true
},
"with_items": [
"vgauthd",
"vmtoolsd"
],
"tags": "hypervisor",
"when": "ansible_system_vendor == \"VMware, Inc.\""
}
]
},
{
"name": "TmpFS_Enable",
"hosts": "grommunio",
"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"
}
]
},
{
"name": "Install Updates",
"hosts": "grommunio",
"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",
"ignore_errors": true,
"register": "ignoreerrors",
"changed_when": "ignoreerrors"
}
]
},
{
"name": "Basics",
"hosts": "grommunio",
"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",
"aaa_base-extras",
"acl",
"bzip2",
"git",
"growpart",
"gron",
"htop",
"jq",
"man",
"man-pages",
"coreutils-doc",
"nfs-client",
"php8-APCu",
"purge-kernels-service",
"python3-argcomplete",
"bash-completion",
"sshfs",
"system-group-wheel",
"zram-generator",
"vim-data"
],
"state": "present",
"disable_recommends": true
},
"tags": "software"
},
{
"name": "Uninstall replaced thingies",
"community.general.zypper": {
"name": [
"systemd-zram-service",
"yast2-online-update-configuration"
],
"state": "absent"
},
"tags": [ "software", "uninstall", "deprecated" ]
},
{
"name": "Cleanup yast2-online-update-configuration",
"ansible.builtin.file": {
"path": "{{ item }}",
"state": "absent"
},
"with_items": [
"/etc/cron.daily/automatic_online_update",
"/etc/cron.daily/opensuse.org-online_update"
]
},
{
"name": "Install os-update + rebootmgr",
"community.general.zypper": {
"name": [
"os-update",
"rebootmgr"
],
"state": "present",
"disable_recommends": true
},
"tags": [ "software", "os-update", "updates", "rebootmgr" ]
},
{
"name": "os-update only do security-updates",
"ansible.builtin.lineinfile": {
"dest": "/etc/os-update.conf",
"regexp": "^UPDATE_CMD=.*",
"line": "UPDATE_CMD=\"security\"",
"state": "present"
},
"tags": [ "os-update", "updates" ]
},
{
"name": "Enable os-update.timer",
"ansible.builtin.systemd": {
"name": "os-update.timer",
"enabled": true
},
"tags": "software"
},
{
"name": "Etckeeper install",
"community.general.zypper": {
"name": [
"etckeeper",
"etckeeper-bash-completion",
"etckeeper-zsh-completion",
"etckeeper-zypp-plugin"
],
"state": "present",
"disable_recommends": true
},
"tags": [ "software", "etckeeper" ]
},
{
"name": "Enable etckeeper.timer",
"ansible.builtin.systemd": {
"name": "etckeeper.timer",
"enabled": true
},
"tags": "software"
},
{
"name": "Check if Etckeeper is already initialized",
"ansible.builtin.stat": {
"path": "/etc/.git/"
},
"register": "etckeeperinit"
},
{
"name": "Etckeeper init",
"ansible.builtin.command": "etckeeper init",
"when": "not etckeeperinit.stat.exists",
"tags": [ "software", "etckeeper" ]
},
{
"name": "Etckeeper Commit",
"ansible.builtin.command": "etckeeper commit -m 'init'",
"when": "not etckeeperinit.stat.exists",
"tags": [ "software", "etckeeper" ]
},
{
"name": "Enable purgekernels",
"ansible.builtin.systemd": {
"name": "purge-kernels.service",
"enabled": true
},
"tags": "software"
},
{
"name": "Enable 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 g=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 2sec",
"ansible.builtin.lineinfile": {
"dest": "/etc/default/grub",
"regexp": "^GRUB_TIMEOUT=10",
"line": "GRUB_TIMEOUT=2",
"state": "present"
},
"tags": "grub",
"notify": [
"Grub2MkConfig"
]
},
{
"name": "Sudoers use userpass",
"ansible.builtin.replace": {
"path": "/etc/sudoers",
"regexp": "'^Defaults targetpw'",
"replace": "'#Defaults targetpw'"
},
"tags": "sudo"
},
{
"name": "Set authorized_keys for root",
"tags": "ssh",
"ansible.posix.authorized_key": {
"user": "root",
"state": "present",
"key": "{{ lookup('url', pubkey_url, split_lines=False) }}"
}
},
{
"name": "SSHD No PasswordAuthentication",
"ansible.builtin.lineinfile": {
"dest": "/etc/ssh/sshd_config",
"regexp": "^#PasswordAuthe.*$",
"line": "PasswordAuthentication no",
"state": "present",
"backup": true
},
"tags": "ssh"
},
{
"name": "SSHD No ChallengeResponseAuthentication",
"ansible.builtin.lineinfile": {
"dest": "/etc/ssh/sshd_config",
"regexp": "^#ChallengeResponse.*$",
"line": "ChallengeResponseAuthentication no",
"state": "present",
"backup": true
},
"tags": "ssh"
},
{
"name": "SSHD PermitRootlogin without-password",
"ansible.builtin.lineinfile": {
"dest": "/etc/ssh/sshd_config",
"regexp": "^PermitRootLogin",
"line": "PermitRootLogin without-password",
"state": "present",
"backup": true
},
"notify": [
"Restart ssh"
],
"tags": "ssh"
}
]
}
]
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
.