--- - name: Basic Debian Linux Setup hosts: all tasks: #- name: Print all available facts # ansible.builtin.debug: # var: ansible_facts - name: Install Basic Packages apt: name: - dhcpcd5 - hd-idle - psutils - psmisc - procps - htop - iotop - sysstat - jnettop - strace - vim - git - man-db - net-tools - tmux - netcat - ethtool - debconf-utils - iputils-ping - lsof - inotify-tools - rsync - dos2unix - locales - iproute2 - logrotate - curl - moreutils - ffmpeg - mediainfo - smartmontools - telnet - libstring-approx-perl - postfix - zip - nmap - whois - libfile-readbackwards-perl - libcrypt-cbc-perl - libcrypt-des-perl - at - pwgen - certbot - btrfs-progs - ufw - jq - btrfsmaintenance - cifs-utils - apt-transport-https - sudo - golang - make - openssh-server update_cache: yes install_recommends: no - name: add dhcpcd to startup command: systemctl enable dhcpcd args: creates: /etc/systemd/system/multi-user.target.wants/dhcpcd.service - name: No DHCPcd for internal interfaces ansible.builtin.lineinfile: path: /etc/dhcpcd.conf line: denyinterfaces docker0 virbr0 tornet0 veth* br* - name: Disable all Network-config but source interfaces.d in /etc/network/interfaces because dhcpcd will do the job replace: path: /etc/network/interfaces regexp: '(^iface .*)' replace: '#\1' - name: Disable all Network-config but source interfaces.d in /etc/network/interfaces because dhcpcd will do the job replace: path: /etc/network/interfaces regexp: '(^allow-hotplug .*)' replace: '#\1' - name: Disable all Network-config but source interfaces.d in /etc/network/interfaces because dhcpcd will do the job replace: path: /etc/network/interfaces regexp: '(^auto .*)' replace: '#\1' - name: Set a hostname ansible.builtin.hostname: name: "{{inventory_hostname}}" - name: Set timezone to Europe/Berlin community.general.timezone: name: Europe/Berlin # - name: Create {{ ansible_facts['hostname'] }}adm User # ansible.builtin.user: # name: "{{ ansible_facts['hostname'] }}adm" # comment: "{{ ansible_facts['hostname'] }}-Admin" # uid: 1000 # group: users # password: $6$Zqar9GCRvbVgPlZ/$L2xAMekMjE5PXuWY0WbmUcugJkqD14O6/cgC02O0hT5vOdiDj5Pcp6FU/Zz.rCkWKVSPsmTc2OtXAmQIHLc1V1 - name: Allow the hostnameadm User all sudo commands community.general.sudoers: name: ALL state: present user: "{{ ansible_facts['hostname'] }}adm" commands: ALL - name: Remove root-Password user: name: root password: '*' - name: German keyboard layout ansible.builtin.lineinfile: path: /etc/default/keyboard regexp: '^XKBLAYOUT=".+$' line: 'XKBLAYOUT="de"' backup: yes notify: setupcon - name: nodeadkeys ansible.builtin.lineinfile: path: /etc/default/keyboard regexp: '^XKBVARIANT=".+$' line: 'XKBVARIANT="nodeadkeys"' backup: yes notify: setupcon - name: Prefer ipv4 over ipv6 to avoid problems and waiting times ansible.builtin.lineinfile: path: /etc/gai.conf regexp: '^#precedence ::ffff:0:0/96 100' line: "precedence ::ffff:0:0/96 100 # CHANGED BY ANSIBLE" backup: yes - name: Ensure en_US.UTF-8 locale exists community.general.locale_gen: name: en_US.UTF-8 state: present - name: Ensure en_GB.UTF-8 locale exists community.general.locale_gen: name: en_GB.UTF-8 state: present - name: Ensure de_DE.UTF-8 locale exists community.general.locale_gen: name: de_DE.UTF-8 state: present notify: localectl - name: SSHD hardening blockinfile: path: /etc/ssh/sshd_config.d/hardening.conf mode: "0444" owner: root group: root create: yes insertbefore: BOF # Beginning of the file marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | Port 22 Port 33 PermitRootLogin without-password PubkeyAuthentication yes X11Forwarding no AllowAgentForwarding no AllowTcpForwarding yes Subsystem sftp internal-sftp -f AUTH -l INFO -u 0007 ## Ciphers Check https://sshcheck.com/server/{{inventory_hostname}}/ # nmap -p22 -n -sV --script ssh2-enum-algos localhost KexAlgorithms curve25519-sha256@libssh.org HostKeyAlgorithms ssh-ed25519 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com IgnoreRhosts yes LogLevel VERBOSE AddressFamily any backup: yes validate: /usr/sbin/sshd -T -f %s notify: - Restart sshd - name: Disable external sftp-Subsystem replace: path: /etc/ssh/sshd_config regexp: '(^Subsystem.*sftp.*)' replace: '#\1' validate: /usr/sbin/sshd -T -f %s backup: yes notify: - Restart sshd - name: Create .ssh dir ansible.builtin.file: path: /root/.ssh owner: root group: root state: directory mode: '0550' - name: Generate an OpenSSH keypair ed25519 community.crypto.openssh_keypair: path: /root/.ssh/id_ed25519 type: ed25519 - ansible.posix.sysctl: name: vm.swappiness value: '5' state: present - name: shell profile blockinfile: path: /etc/profile.d/settings-from-ansible.sh create: yes mode: "0444" owner: root group: root marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | if ${use_color} ; then if [[ ${EUID} == 0 ]] ; then PS1='\[\033[01;31m\]\h\[\033[01;34m\] \w \$\[\033[00m\] ' else PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] ' fi EDITOR="/usr/bin/vim" HISTSIZE=10000 HISTFILESIZE=10000 if [ -f /etc/debian_version ] then export PATH="$PATH:/usr/local/bin:/usr/local/sbin" export LANG="en_US.UTF-8" export DEBIAN_FRONTEND='noninteractive' alias ls='ls --color=auto' alias grep='grep --colour=auto' alias egrep='egrep --colour=auto' alias fgrep='fgrep --colour=auto' fi else # show root@ when we don't have colors PS1+='\u@\h \w \$' fi backup: yes validate: /bin/bash -n %s - name: vim settings blockinfile: path: /etc/vim/vimrc.local mode: "0444" owner: root group: root create: yes marker: "\" {mark} ANSIBLE MANAGED BLOCK" block: | :syntax on let g:skip_defaults_vim = 1 set encoding=utf-8 syntax match nonascii "[^[:alnum:][:punct:][:space:]]/" highlight nonascii guibg=Red ctermbg=2 backup: yes #- name: gaboshlib.include # copy: # src: configs/etc/bash # dest: /etc/ # owner: root # group: root # mode: "0444" # directory_mode: "0555" # backup: yes # validate: /bin/bash -n %s - name: gaboshlib from git ansible.builtin.git: repo: 'https://gitea.ds9.dedyn.io/olli/gaboshlib.git' dest: /etc/bash - name: systemd-journald settings blockinfile: path: /etc/systemd/journald.conf.d/journald.local.conf create: yes mode: "0444" owner: root group: root marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | [Journal] Storage=persistent SystemMaxUse=30M ForwardToSyslog=yes backup: yes notify: - Restart journald - name: Create updates dir /usr/local/sbin/autoupdate.d ansible.builtin.file: path: /usr/local/sbin/autoupdate.d owner: root group: root state: directory mode: '0700' - name: /usr/local/sbin/autoupdate.sh blockinfile: path: /usr/local/sbin/autoupdate.sh mode: "0500" owner: root group: root create: yes marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | . /etc/bash/gaboshlib.include g_nice g_lockfile g_all-to-syslog set -o pipefail find /usr/local/sbin/autoupdate.d -name "*.update" -type f | sort | while read update do g_echo "Running: $update" . "$update" sleep 60 done backup: yes validate: /bin/bash -n %s - name: /usr/local/sbin/autoupdate.sh shebang lineinfile: path: /usr/local/sbin/autoupdate.sh insertbefore: BOF line: "#!/bin/bash" - name: /usr/local/sbin/autoupdate.d/debian.update blockinfile: path: /usr/local/sbin/autoupdate.d/debian.update mode: "0400" owner: root group: root create: yes marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | g_echo_ok "Prüfe auf Systemupdates" apt-get update || g_echo_error "apt-get update fehlgeschlagen" if ! apt-get -s dist-upgrade 2>&1 | sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/" | tee $g_tmp/sys-updatelist | egrep "^0.+, 0 .+, 0 .+ 0 .+\." then g_echo_warn "Systemupdate wird eingespielt: $(cat $g_tmp/sys-updatelist)" DEBIAN_FRONTEND=noninteractive apt-get -yy dist-upgrade | sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/" | tee $g_tmp/sys-update || g_echo_error "apt-get -yy dist-upgrade failed $($g_tmp/sys-update)" DEBIAN_FRONTEND=noninteractive needrestart -b -r a | egrep -q "^NEEDRESTART-KSTA: [2|3]" && g_echo_warn "Server Reboot benötigt" fi backup: yes validate: /bin/bash -n %s - name: /etc/cron.d/autoupdate_local blockinfile: path: /etc/cron.d/autoupdate_local mode: "0400" owner: root group: root create: yes marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | ## Auto-Update 5 6 * * * root /usr/local/sbin/autoupdate.sh backup: yes # - name: Autoupdate # copy: # src: configs/usr/local/sbin/autoupdate.sh # dest: /usr/local/sbin/autoupdate.sh # owner: root # group: root # mode: "0555" # backup: yes # validate: /bin/bash -n %s # - name: Autoupdate Cronb # copy: # src: configs/etc/cron.d/autoupdate_local # dest: /etc/cron.d/autoupdate_local # owner: root # group: root # mode: "0444" # backup: yes - name: /etc/rsyslog.d/00-services-remote.conf blockinfile: path: /etc/rsyslog.d/00-services-remote.conf create: yes mode: "0444" owner: root group: root marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | # Listen for remote Logging (UDP) module(load="imudp") input(type="imudp" port="514") # Hosts if $hostname startswith '192.168.1.1' and $msg contains 'User admin login from 192.168.1.2 successful' then stop if $hostname != '{{ ansible_facts['hostname'] }}' and $msg contains 'wdGetDidSendCredentials not implemented' and $programname contains 'citrix-wfica' then stop if $hostname != '{{ ansible_facts['hostname'] }}' and $msg contains 'CGPrecv: socket 0x' and $programname contains 'citrix-wfica' then stop if $hostname != '{{ ansible_facts['hostname'] }}' and $msg contains 'doEncryptData inbuffersize: ' and $programname contains 'citrix-wfica' then stop if $hostname != '{{ ansible_facts['hostname'] }}' and $msg contains 'SSLPutDataFn inbuffersize: ' and $programname contains 'citrix-wfica' then stop if $hostname != '{{ ansible_facts['hostname'] }}' and $msg contains 'SRC=192.168.' and $programname contains 'kernel' then stop if $hostname startswith '192.168.1.1' then /var/log/zyxel.log if $hostname startswith '192.168.1.1' then stop if $hostname startswith 'raspberry-' then /var/log/Raspberrys.log if $hostname startswith 'raspberry-' then stop if $hostname startswith 'router-' then /var/log/router.log if $hostname startswith 'router-' then stop # Auth success (for share-auth 2FA) #if $programname == 'nextcloud-audit' and $msg contains 'Login successful:' then /var/log/auth-success.log #if $programname == 'imaps' and $msg contains 'TLS User logged in' then /var/log/auth-success.log if $hostname == 'xgabosh' then /var/log/xgabosh.log if $hostname == 'xgabosh' then stop if $hostname != '{{ ansible_facts['hostname'] }}' and $hostname != 'share' and $hostname != 'backup-chroot' then /var/log/GTC-Hosts.log if $hostname != '{{ ansible_facts['hostname'] }}' and $hostname != 'share' and $hostname != 'backup-chroot' then stop backup: yes notify: - Restart rsyslog - name: rsyslog-config local copy: src: configs/etc/rsyslog.d/01-services-local.conf dest: /etc owner: root group: root mode: "0444" backup: yes notify: - Restart rsyslog - name: hd-idle for spinning down disks after XXX seconds idle blockinfile: path: /etc/default/hd-idle create: yes mode: "0444" owner: root group: root marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | HD_IDLE_OPTS="-i 300 -l /var/log/hd-idle.log" backup: yes notify: - Restart hd-idle - name: /etc/default/btrfsmaintenance blockinfile: path: /etc/default/btrfsmaintenance mode: "0444" owner: root group: root create: yes insertbefore: EOF marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | BTRFS_LOG_OUTPUT="syslog" BTRFS_BALANCE_MOUNTPOINTS="auto" BTRFS_BALANCE_PERIOD="monthly" BTRFS_SCRUB_MOUNTPOINTS="auto" BTRFS_SCRUB_PERIOD="monthly" backup: yes - name: /etc/logrotate.conf (weekly->daily) ansible.builtin.lineinfile: path: /etc/logrotate.conf regexp: '^weekly$' line: 'daily' backup: yes - name: /etc/logrotate.d/apache2 (remove delaycompress) ansible.builtin.lineinfile: path: /etc/logrotate.d/apache2 regexp: '.*delaycompress$' state: absent - name: /etc/logrotate.d/00-local blockinfile: path: /etc/logrotate.d/00-local mode: "0444" owner: root group: root create: yes marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | /var/log/dmesgcron /var/log/messages /var/log/*.log { rotate 7 daily missingok notifempty copytruncate compress postrotate /usr/lib/rsyslog/rsyslog-rotate endscript } - name: Remove logrotates ansible.builtin.file: path: /etc/logrotate.d/alternatives state: absent - name: Remove logrotates ansible.builtin.file: path: /etc/logrotate.d/dpkg state: absent - name: Remove logrotates ansible.builtin.file: path: /etc/logrotate.d/rsyslog state: absent handlers: - name: setupcon ansible.builtin.shell: setupcon - name: localectl ansible.builtin.shell: localectl set-locale LANG=de_DE.UTF-8 - name: Restart sshd service: name: sshd state: restarted - name: Restart journald service: name: systemd-journald state: restarted - name: Restart rsyslog service: name: rsyslog state: restarted - name: Restart hd-idle service: name: hd-idle state: restarted