diff options
-rw-r--r-- | ansible.cfg | 10 | ||||
-rw-r--r-- | files/etc/apt/listchanges.conf | 9 | ||||
-rw-r--r-- | files/etc/nftables.conf | 59 | ||||
-rw-r--r-- | files/etc/ssh/sshd_config.d/local.conf | 10 | ||||
-rw-r--r-- | files/etc/systemd/resolved.conf.d/local.conf | 3 | ||||
-rw-r--r-- | files/etc/systemd/timesyncd.conf.d/local.conf | 2 | ||||
-rw-r--r-- | handlers/main.yml | 30 | ||||
-rw-r--r-- | hosts.ini | 2 | ||||
-rw-r--r-- | setup.yml | 15 | ||||
-rw-r--r-- | tasks/apt.yml | 46 | ||||
-rw-r--r-- | tasks/base.yml | 141 | ||||
-rw-r--r-- | tasks/firewall.yml | 13 | ||||
-rw-r--r-- | tasks/hosts.yml | 31 | ||||
-rw-r--r-- | tasks/network.yml | 84 | ||||
-rw-r--r-- | tasks/ssh.yml | 20 | ||||
-rw-r--r-- | tasks/sysctl.yml | 22 | ||||
-rw-r--r-- | templates/etc/apt/sources.list.d/debian.sources.j2 | 9 | ||||
-rw-r--r-- | templates/etc/systemd/network/01-wired.network.j2 | 13 |
18 files changed, 519 insertions, 0 deletions
diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..a35402e --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,10 @@ +[defaults] +inventory = ./hosts.ini + +[privilege_escalation] +become = True +become_ask_pass = True + +control_path = ${XDG_RUNTIME_DIR}/ssh-ansible-%%C +ssh_args = -oStrictHostKeyChecking=yes -oControlMaster=auto -oControlPersist=60s +pipelining = True diff --git a/files/etc/apt/listchanges.conf b/files/etc/apt/listchanges.conf new file mode 100644 index 0000000..96910a0 --- /dev/null +++ b/files/etc/apt/listchanges.conf @@ -0,0 +1,9 @@ +[apt] +frontend=mail +which=news +email_address=root +email_format=text +confirm=false +headers=false +reverse=false +save_seen=/var/lib/apt/listchanges.db diff --git a/files/etc/nftables.conf b/files/etc/nftables.conf new file mode 100644 index 0000000..e8784ab --- /dev/null +++ b/files/etc/nftables.conf @@ -0,0 +1,59 @@ +#!/usr/sbin/nft -f + +flush ruleset + +table inet raw { + chain PREROUTING-stateless { + # XXX can't add that to the ingress hook as that happens before IP defragmentation + # so we don't have the TCP header in later fragments (we don't want to drop IP + # fragments, see https://blog.cloudflare.com/ip-fragmentation-is-broken/ ) + type filter hook prerouting priority -399 # > NF_IP_PRI_CONNTRACK_DEFRAG (-400) + policy accept + + # stateless filter for bogus TCP packets + tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 counter drop # null packet + tcp flags & (fin|psh|urg) == fin|psh|urg counter drop # XMAS packet + tcp flags & (syn|rst) == syn|rst counter drop + tcp flags & (fin|rst) == fin|rst counter drop + tcp flags & (fin|syn) == fin|syn counter drop + tcp flags & (fin|psh|ack) == fin|psh counter drop + } + + chain PREROUTING { + type filter hook prerouting priority -199 # > NF_IP_PRI_CONNTRACK (-200) + policy accept + + # stateful filter + ct state invalid counter drop + } +} + +table inet filter { + chain input { + type filter hook input priority 0 + policy drop + + iif lo accept + + ct state related,established accept + meta l4proto { icmp, icmpv6 } counter accept + + tcp dport 22 ct state new counter accept + } + + chain output { + type filter hook output priority 0 + policy drop + + oif lo accept + ct state related,established accept + meta l4proto { icmp, icmpv6 } counter accept + + ct state new counter accept + + # graceful reject + meta l4proto tcp counter reject with tcp reset + meta l4proto udp counter reject + counter reject + } +} diff --git a/files/etc/ssh/sshd_config.d/local.conf b/files/etc/ssh/sshd_config.d/local.conf new file mode 100644 index 0000000..3a5323f --- /dev/null +++ b/files/etc/ssh/sshd_config.d/local.conf @@ -0,0 +1,10 @@ +HostKey /etc/ssh/ssh_host_rsa_key +HostKey /etc/ssh/ssh_host_ed25519_key + +PermitRootLogin no +AllowGroups ssh-login + +PasswordAuthentication no +PermitEmptyPasswords no +ChallengeResponseAuthentication no +X11Forwarding no diff --git a/files/etc/systemd/resolved.conf.d/local.conf b/files/etc/systemd/resolved.conf.d/local.conf new file mode 100644 index 0000000..812e6b5 --- /dev/null +++ b/files/etc/systemd/resolved.conf.d/local.conf @@ -0,0 +1,3 @@ +[Resolve] +# Quad9 +DNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net diff --git a/files/etc/systemd/timesyncd.conf.d/local.conf b/files/etc/systemd/timesyncd.conf.d/local.conf new file mode 100644 index 0000000..632cd3f --- /dev/null +++ b/files/etc/systemd/timesyncd.conf.d/local.conf @@ -0,0 +1,2 @@ +[Time] +NTP=ntp.hetzner.com diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..d3d7755 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,30 @@ +# 'service: name=... state=started' tasks should NOT run if there is a +# corresponding state=restarted handler. (Register the task notifying +# the handler, and add a conditional.) +--- +- name: systemctl daemon-reload + command: /usr/bin/systemctl daemon-reload + +- name: Refresh hostname + command: /usr/bin/hostnamectl hostname {{ inventory_hostname_short }} + +- name: apt-get update + apt: update_cache=yes + +- name: Restart nftables + service: name=nftables.service state=restarted + +- name: Restart systemd-networkd + service: name=systemd-networkd.service state=restarted + +- name: Restart systemd-resolved + service: name=systemd-resolved.service state=restarted + +- name: Restart systemd-timesyncd + service: name=systemd-timesyncd.service state=restarted + +- name: Restart OpenSSH + service: name=ssh.service state=restarted + +- name: Update initramfs + command: /usr/sbin/update-initramfs -u diff --git a/hosts.ini b/hosts.ini new file mode 100644 index 0000000..45620a1 --- /dev/null +++ b/hosts.ini @@ -0,0 +1,2 @@ +[hel01] +hel01.guilhem.se diff --git a/setup.yml b/setup.yml new file mode 100644 index 0000000..cf51ece --- /dev/null +++ b/setup.yml @@ -0,0 +1,15 @@ +- name: Base system + hosts: all + gather_facts: True + tasks: + - name: Install etckeeper + apt: pkg=etckeeper + - import_tasks: ./tasks/firewall.yml + - import_tasks: ./tasks/network.yml + - import_tasks: ./tasks/sysctl.yml + - import_tasks: ./tasks/hosts.yml + - import_tasks: ./tasks/apt.yml + - import_tasks: ./tasks/ssh.yml + - import_tasks: ./tasks/base.yml + handlers: + - import_tasks: ./handlers/main.yml diff --git a/tasks/apt.yml b/tasks/apt.yml new file mode 100644 index 0000000..1023908 --- /dev/null +++ b/tasks/apt.yml @@ -0,0 +1,46 @@ +- name: Install various APT tools (1) + apt: pkg={{ packages }} + vars: + packages: + - apt + - lsb-release + +- name: Remove /etc/apt/sources.list + file: path=/etc/apt/sources.list state=absent + notify: + - apt-get update + +- name: Remove /etc/apt/sources.list.d/hetzner-* + file: path={{ item }} state=absent + with_fileglob: /etc/apt/sources.list.d/hetzner-* + notify: + - apt-get update + +- name: Copy /etc/apt/sources.list.d/debian.sources + template: src=etc/apt/sources.list.d/debian.sources.j2 + dest=/etc/apt/sources.list.d/debian.sources + owner=root group=root + mode=0644 + notify: + - apt-get update + +- name: Remove /etc/apt/apt.conf.d/*hetzner + file: path={{ item }} state=absent + with_fileglob: /etc/apt/apt.conf.d/*hetzner + +# We should run 'apt-get update' before proceeding to any other task. +- meta: flush_handlers + +- name: Install various APT tools (2) + apt: pkg={{ packages }} + vars: + packages: + - apt-listchanges + - needrestart + - unattended-upgrades + +- name: Configure apt-listchanges + copy: src=etc/apt/listchanges.conf + dest=/etc/apt/listchanges.conf + owner=root group=root + mode=0644 diff --git a/tasks/base.yml b/tasks/base.yml new file mode 100644 index 0000000..7086ce9 --- /dev/null +++ b/tasks/base.yml @@ -0,0 +1,141 @@ +- name: Remove some packages + apt: pkg={{ packages }} state=absent purge=yes + vars: + packages: + - aptitude + - byobu + - at + - bc + - cryptsetup* + - mdadm + - netcat-traditional + - nano + - emacs-* + - hc-utils + - shorewall + - iptables + - lvm2 + - dosfstools + - eatmydata + - acpid + - acl + - fdisk + - gdisk + - genisoimage + - gnupg* + - gpg-wks-* + - mtr-tiny + - net-tools + - mtr-tiny + - net-tools + - xfsprogs + - traceroute + - wget + - python3-lib2to3 + - efibootmgr + - busybox + - console-setup + - debconf-i18n + - dmidecode + - task-* + - tasksel-* + - inetutils-telnet + - os-prober + ## + - chkrootkit + - debian-faq + - debian-handbook + - debian-policy + - debian-reference + - doc-debian + - iamerican + - ibritish + - ienglish-common + - installation-report + - laptop-detect + - lynx + - manpages-de + - mutt + - reportbug + - rkhunter + - vnstati + - wmanx + - python3-reportbug + - python3-debianbts + - locales-all + ## + - wamerican + - wamerican-huge + - wamerican-insane + - wamerican-large + - wamerican-small + - wbrazilian + - wbritish + - wbritish-huge + - wbritish-insane + - wbritish-large + - wbritish-small + - wbulgarian + - wcanadian + - wcanadian-huge + - wcanadian-insane + - wcanadian-large + - wcanadian-small + - wcatalan + - wdanish + - wdutch + - wfaroese + - wfrench + - wgaelic + - wgalician-minimos + - wgerman-medical + - wirish + - witalian + - wngerman + - wnorwegian + - wogerman + - wpolish + - wportuguese + - wspanish + - wswedish + - wswiss + - wukrainian + - xauth + +- name: Install some common packages + apt: pkg={{ packages }} + vars: + packages: + - bind9-dnsutils + - bzip2 + - htop + - ca-certificates + - rsync + - python3 + - less + - iproute2 + - git + - curl + - screen + - sudo + - vim-nox + - qemu-guest-agent + # Useful for `getent passwd dynamic_user` + - libnss-systemd + +- name: Set /etc/timezone + copy: dest=/etc/timezone content="Europe/Stockholm\n" + owner=root group=root + mode=0644 + +- name: Remove ~root/.ssh/authorized_keys + file: path=/root/.ssh/authorized_keys state=absent + +- name: Disable root password + user: name=root password="!" update_password=always + +- name: Set RESUME=none in initramfs.conf + copy: dest=/etc/initramfs-tools/conf.d/resume content="RESUME=none\n" + owner=root group=root + mode=0644 + notify: Update initramfs diff --git a/tasks/firewall.yml b/tasks/firewall.yml new file mode 100644 index 0000000..fa46ade --- /dev/null +++ b/tasks/firewall.yml @@ -0,0 +1,13 @@ +- name: Install nftables + apt: pkg=nftables + +- name: Configure nftables + copy: src=etc/nftables.conf + dest=/etc/nftables + owner=root group=root + mode=0644 + notify: + - Restart nftables + +- name: Start nftables + service: name=nftables.service enabled=true state=started diff --git a/tasks/hosts.yml b/tasks/hosts.yml new file mode 100644 index 0000000..b8e5931 --- /dev/null +++ b/tasks/hosts.yml @@ -0,0 +1,31 @@ +- name: Set hostname + # Use double quoted scalars to force expansion of escape sequences + # cf. https://groups.google.com/forum/#!topic/ansible-project/ZaB6o-eqDzw + copy: "content='{{ inventory_hostname_short }}\n' + dest=/etc/hostname + owner=root group=root + mode=0644" + tags: hostname + notify: + - Refresh hostname + +- name: Set mailname + copy: "content='{{ inventory_hostname }}\n' + dest=/etc/mailname + owner=root group=root + mode=0644" + tags: mailname + +- name: Fix /etc/hosts (1) + lineinfile: "dest=/etc/hosts create=yes + regexp='^127\\.0\\.0\\.1\\s+' + line='127.0.0.1\tlocalhost'" + tags: hosts + +- name: Fix /etc/hosts (2) + lineinfile: "dest=/etc/hosts create=yes + regexp='^127\\.0\\.1\\.1\\s+' + line='127.0.1.1\t{{ inventory_hostname }} {{ inventory_hostname_short }}'" + tags: hosts + +- meta: flush_handlers diff --git a/tasks/network.yml b/tasks/network.yml new file mode 100644 index 0000000..6b282f8 --- /dev/null +++ b/tasks/network.yml @@ -0,0 +1,84 @@ +- name: Copy systemd.network(5) configuration + template: src=etc/systemd/network/01-wired.network.j2 + dest=/etc/systemd/network/01-wired.network + owner=root group=root + mode=0644 + notify: + - Restart systemd-networkd + +- name: Start systemd-networkd + service: name=systemd-networkd.service enabled=true state=started + +- meta: flush_handlers + +- name: Remove ifupdown and isc-dhcp-* + apt: pkg={{ packages }} state=absent purge=yes + vars: + packages: + - ifupdown + - isc-dhcp-client + - isc-dhcp-common + +- name: Remove /etc/network/interfaces and /etc/network/interfaces.d + file: path={{ item }} state=absent + with_items: + - /etc/network/interfaces + - /etc/network/interfaces.d/ + + +- name: Install systemd-resolved + apt: pkg={{ packages }} + vars: + packages: + - systemd-resolved + - libnss-resolve + +- name: Create directory /etc/systemd/resolved.conf.d + file: path=/etc/systemd/resolved.conf.d + state=directory + owner=root group=root + mode=0755 + +- name: Configure systemd-resolved + copy: src=etc/systemd/resolved.conf.d/local.conf + dest=/etc/systemd/resolved.conf.d/local.conf + owner=root group=root + mode=0644 + notify: + - Restart systemd-resolved + +- name: Start systemd-resolved + service: name=systemd-resolved.service enabled=true state=started + +- name: Remove resolvconf + apt: pkg=resolvconf state=absent purge=yes + + +- name: Install systemd-timesyncd + apt: pkg=systemd-timesyncd + +- name: Create directory /etc/systemd/timesyncd.conf.d + file: path=/etc/systemd/timesyncd.conf.d + state=directory + owner=root group=root + mode=0755 + +- name: Configure systemd-timesyncd + copy: src=etc/systemd/timesyncd.conf.d/local.conf + dest=/etc/systemd/timesyncd.conf.d/local.conf + owner=root group=root + mode=0644 + notify: + - Restart systemd-timesyncd + +- name: Start systemd-timesyncd + service: name=systemd-timesyncd.service enabled=true state=started + +- name: Remove ntp + apt: pkg={{ packages }} state=absent purge=yes + vars: + packages: + - ntp + - ntpdate + - ntpsec + - ntpsec-ntpdate diff --git a/tasks/ssh.yml b/tasks/ssh.yml new file mode 100644 index 0000000..341a96d --- /dev/null +++ b/tasks/ssh.yml @@ -0,0 +1,20 @@ +--- +- name: Install OpenSSH server + apt: pkg={{ packages }} + vars: + packages: + - openssh-server + +- name: Create system group 'ssh-login' + group: name=ssh-login system=true + +- name: Copy sshd_config configuration + copy: src=etc/ssh/sshd_config.d/local.conf + dest=/etc/ssh/sshd_config.d/local.conf + owner=root group=root + mode=0644 + notify: + - Restart OpenSSH + +- name: Start Openssh + service: name=ssh enabled=true state=started diff --git a/tasks/sysctl.yml b/tasks/sysctl.yml new file mode 100644 index 0000000..0f0a985 --- /dev/null +++ b/tasks/sysctl.yml @@ -0,0 +1,22 @@ +- name: Configure network-related sysctl.conf(5). + sysctl: name={{ item.key }} value={{ item.val }} + sysctl_file=/etc/sysctl.d/network.conf reload=true + with_items: + - { key: net.ipv4.tcp_timestamps, val: 0 } + - { key: net.ipv4.conf.default.accept_source_route, val: 0 } + - { key: net.ipv4.conf.default.send_redirects, val: 0 } + - { key: net.ipv4.conf.all.accept_source_route, val: 0 } + - { key: net.ipv4.conf.all.send_redirects, val: 0 } + - { key: net.ipv6.conf.default.autoconf, val: 0 } + - { key: net.ipv6.conf.default.accept_ra, val: 0 } + - { key: net.ipv6.conf.default.accept_ra_defrtr, val: 0 } + - { key: net.ipv6.conf.default.accept_ra_rtr_pref, val: 0 } + - { key: net.ipv6.conf.default.accept_ra_pinfo, val: 0 } + - { key: net.ipv6.conf.default.accept_source_route, val: 0 } + - { key: net.ipv6.conf.all.autoconf, val: 0 } + - { key: net.ipv6.conf.all.accept_ra, val: 0 } + - { key: net.ipv6.conf.all.accept_ra_defrtr, val: 0 } + - { key: net.ipv6.conf.all.accept_ra_rtr_pref, val: 0 } + - { key: net.ipv6.conf.all.accept_ra_pinfo, val: 0 } + - { key: net.ipv6.conf.all.accept_source_route, val: 0 } + - { key: net.ipv6.conf.all.accept_redirects, val: 0 } diff --git a/templates/etc/apt/sources.list.d/debian.sources.j2 b/templates/etc/apt/sources.list.d/debian.sources.j2 new file mode 100644 index 0000000..980daaf --- /dev/null +++ b/templates/etc/apt/sources.list.d/debian.sources.j2 @@ -0,0 +1,9 @@ +Types: deb +URIs: https://deb.debian.org/debian +Suites: {{ ansible_lsb.codename }} {{ ansible_lsb.codename }}-updates +Components: main non-free-firmware + +Types: deb +URIs: https://deb.debian.org/debian-security +Suites: {{ ansible_lsb.codename }}-security +Components: main non-free-firmware diff --git a/templates/etc/systemd/network/01-wired.network.j2 b/templates/etc/systemd/network/01-wired.network.j2 new file mode 100644 index 0000000..7be5d21 --- /dev/null +++ b/templates/etc/systemd/network/01-wired.network.j2 @@ -0,0 +1,13 @@ +[Match] +Name={{ ansible_default_ipv4.interface }} + +[Network] +DHCP=yes + +{% if ansible_default_ipv6.get('scope', '') == 'global' %} +[Address] +Address={{ ansible_default_ipv6.address }}/{{ ansible_default_ipv6.prefix }} + +[Route] +Gateway={{ ansible_default_ipv6.gateway }} +{%- endif %} |