summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2024-01-04 12:59:39 +0100
committerGuilhem Moulin <guilhem@fripost.org>2024-01-04 13:42:18 +0100
commit6691410f945719e62601c3d69d9b2ff9c4cfb4fb (patch)
tree9ea4170a6d5d50ac14a326f42fa8b13303734241
parent609574f51c5c08af71419bddc1be16ad5668882a (diff)
Base system.
-rw-r--r--ansible.cfg10
-rw-r--r--files/etc/apt/listchanges.conf9
-rw-r--r--files/etc/nftables.conf59
-rw-r--r--files/etc/ssh/sshd_config.d/local.conf10
-rw-r--r--files/etc/systemd/resolved.conf.d/local.conf3
-rw-r--r--files/etc/systemd/timesyncd.conf.d/local.conf2
-rw-r--r--handlers/main.yml30
-rw-r--r--hosts.ini2
-rw-r--r--setup.yml15
-rw-r--r--tasks/apt.yml46
-rw-r--r--tasks/base.yml141
-rw-r--r--tasks/firewall.yml13
-rw-r--r--tasks/hosts.yml31
-rw-r--r--tasks/network.yml84
-rw-r--r--tasks/ssh.yml20
-rw-r--r--tasks/sysctl.yml22
-rw-r--r--templates/etc/apt/sources.list.d/debian.sources.j29
-rw-r--r--templates/etc/systemd/network/01-wired.network.j213
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 %}