diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..ed865bf --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +inventory = hosts diff --git a/group_vars/all.yml b/group_vars/all.yml new file mode 100644 index 0000000..6b2c956 --- /dev/null +++ b/group_vars/all.yml @@ -0,0 +1,30 @@ +--- +# general settings +default_username: debian +dot_forward_email: +private_key: .ssh/id_rsa +public_key: .ssh/id_rsa.pub +ntpserver: pool.ntp.org +timezone: Europe/Rome + +# default sshd port +sshd_port: 22 + +# generate random passwords for default user and root user +default_password: "{{lookup('password', '/dev/null length=15 chars=ascii_letters,digits,punctuation')}}" +root_password: "{{lookup('password', '/dev/null length=15 chars=ascii_letters,digits,punctuation')}}" + +# unattended packages install configuration +unattended_mail: "{{dot_forward_email}}" +unattended_remove_unused_dependencies: true +unattended_automatic_reboot_time: "03:00" +unattended_update_days: "Sat" +unattended_clean_interval: 7 + +# fail2ban +fail2ban_loglevel: INFO +fail2ban_services: + - name: ssh + port: ssh + filter: sshd + logpath: /var/log/auth.log diff --git a/group_vars/apt.yml b/group_vars/apt.yml new file mode 100644 index 0000000..913e77c --- /dev/null +++ b/group_vars/apt.yml @@ -0,0 +1,49 @@ +--- +# packages to install +packages_to_install: + - sudo + - python-apt + - git-core + - ufw + - dnsutils + - build-essential + - acl + - screen + - bash-completion + - ntp + - jq + - htop + - psmisc + - python-pip + - python3-pip + - vim + - netcat + - net-tools + - nmap + - lynx + - wget + - curl + - gzip + - rsync + - logrotate + # - logcheck + - rkhunter + - cryptsetup + - python-glade2 + - dos2unix + - mlocate + - rclone + - bc + - zsh + - hddtemp + - lm-sensors + - qemu-guest-agent + - atop + - sshfs + - reptyr + - lvm2 + - parted + - rename + - glances + - gnupg + - exim4 diff --git a/group_vars/docker.yml b/group_vars/docker.yml new file mode 100644 index 0000000..ac86adc --- /dev/null +++ b/group_vars/docker.yml @@ -0,0 +1,23 @@ +--- +# flag to install or skip docker module installation and configuration +install_docker: true + +# docker +docker__channel: ["stable"] +docker__version: "19.03.5" +docker__state: "present" +docker__compose_version: "1.25.0" +docker__users: ["{{default_username}}"] +docker__daemon_flags: + - "-H unix://" + #- "-H unix:// --iptables=false" +# "a" removes unused images (useful in production). +# "f" forces it to happen without prompting you to agree. +docker__cron_jobs_prune_flags: "af" +docker__cron_jobs: + - name: "Docker disk clean up" + job: "docker system prune -{{docker__cron_jobs_prune_flags}} > /dev/null 2>&1" + schedule: ["0", "0", "*", "*", "0"] + cron_file: "docker-disk-clean-up" + user: "{{(docker__users | first) | d('root')}}" + state: "present" diff --git a/group_vars/monit.yml b/group_vars/monit.yml new file mode 100644 index 0000000..4e06d66 --- /dev/null +++ b/group_vars/monit.yml @@ -0,0 +1,30 @@ +--- +# monit +config_monit: true +monit_enable_email_notifications: false +monit_email_to: "{{dot_forward_email}}" +monit_enable_web_server: false +monit_web_server_allow_list: + - localhost +monit_web_server_local_only: true +monit_monitor_services: + - name: "cron" + monitored: true + pidfile: "/var/run/crond.pid" + start_program: "/usr/sbin/service cron start" + stop_program: "/usr/sbin/service cron stop" + - name: "fail2ban" + monitored: true + pidfile: "/var/run/fail2ban/fail2ban.pid" + start_program: "/etc/init.d/fail2ban start" + stop_program: "/etc/init.d/fail2ban stop" + - name: "sshd" + monitored: true + pidfile: "/var/run/sshd.pid" + start_program: "/etc/init.d/ssh start" + stop_program: "/etc/init.d/ssh stop" + - name: "syslogd" + monitored: true + pidfile: "/var/run/rsyslogd.pid" + start_program: "/etc/init.d/rsyslog start" + stop_program: "/etc/init.d/rsyslog stop" diff --git a/group_vars/networking.yml b/group_vars/networking.yml new file mode 100644 index 0000000..4127604 --- /dev/null +++ b/group_vars/networking.yml @@ -0,0 +1,14 @@ +--- +# Local LAN IP-range addresses +local_lan: "192.168.0.0/16" +docker_overlay_ips: "172.0.0.0/8" + +# ufw rules +ufw_rules: + - {rule: allow, port: 22, src: "{{local_lan}}", proto: tcp, direction: "in"} + - {rule: allow, port: 22, src: "{{docker_overlay_ips}}", proto: tcp, direction: "in"} + # - {rule: allow, port: 80, src: "0.0.0.0/0", proto: tcp, direction: "in"} + # - {rule: allow, port: 443, src: "0.0.0.0/0", proto: tcp, direction: "in"} + +# network configuration for our server +interfaces_template: "interfaces-dhcp-server.j2" diff --git a/group_vars/vault.yml b/group_vars/vault.yml new file mode 100644 index 0000000..6b57e0e --- /dev/null +++ b/group_vars/vault.yml @@ -0,0 +1,15 @@ +$ANSIBLE_VAULT;1.1;AES256 +36663239336238393633346563366232393635633365343535663163336438613066633062626133 +3630376365643565653430363030616132383332306339370a393139616163366461376133373935 +35386535363862353237306264336230646334346162316666613238343863303336633533626538 +3364313966306362330a626634313961326664303761363635633039333138353331306132636261 +35623366333637353962383730613966336461623936376235313365303661663238316563613838 +33303032306137373863303564643236653530333366366136363837666661663864376139626634 +64613839333335663237333533633464393831663331356437376133396330396661366366373461 +33353462393063313731316364333034373066653563336533363032363038326331303433666634 +62376637343463386538333566303234313330663234313664616433653563353165386366653638 +65613736633135316463316537653638326233353134343537393239663537613734313762346434 +63393437356366613332623666383532363365303239666637666362626366623862666334303537 +35333663343137643737383533323134363937386239616136326534653261636361386463326236 +64306433666465343066333136346434656537626631656632393737626565396130373036333530 +3265646137373062393035636531376339623231366139373664 diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..f23cf49 --- /dev/null +++ b/install.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +usage() { + echo "USAGE: ${0} [-h] [-D] -H hostname [-p password_file]" + echo "" + echo "Configures the given role for the given hostname." + echo "" + echo "Options:" + echo " -h runs help (this screen)" + echo " -D debug mode on (more verbose output)" + echo "" + echo " -H the target hostname to configure" + echo " -p password_file is an optional path to a password file for Ansible" + echo "" +} + +# check invocation +if (! getopts ":hDH:p:" opt); then + usage + exit $E_OPTERROR; +fi + +debug_mode=0 + +# parse arguments +while getopts ":hDH:p:" opt; do + case $opt in + h) + usage + exit 1 + ;; + D) + debug_mode=1 + ;; + H) + hostname=($OPTARG) + ;; + p) + password_file=($OPTARG) + ;; + \?) + echo "Invalid option: -${OPTARG}" >&2 + usage + exit 1 + ;; + esac +done +shift $((OPTIND -1)) + +virtualenv -q -p $(which python3) venv +source venv/bin/activate + +# install local requirements for ansible +ansible-galaxy install -r requirements.yml +# install additional pre-requirements +pip install jmespath dnspython + +# export ansible variables +export ANSIBLE_LOAD_CALLBACK_PLUGINS=1 +if [ $debug_mode -eq 0 ] ; then + export ANSIBLE_STDOUT_CALLBACK="unixy" +else + export ANSIBLE_STDOUT_CALLBACK="skippy" +fi + +# create hosts file +echo "[prod]" > hosts +echo "${hostname}" >> hosts + +# run ansible +if [ -z $password_file ] ; then + ansible-playbook -i hosts provision.yml --vault-id @prompt +else + ansible-playbook -i hosts provision.yml --vault-password-file $password_file +fi + +deactivate diff --git a/provision.yml b/provision.yml new file mode 100644 index 0000000..366867c --- /dev/null +++ b/provision.yml @@ -0,0 +1,38 @@ +--- +- hosts: prod + vars_files: + - group_vars/all.yml + - group_vars/apt.yml + - group_vars/docker.yml + - group_vars/monit.yml + - group_vars/networking.yml + - group_vars/vault.yml + user: "{{default_username}}" # run whole script with default user + become: yes + roles: # order is not random! + - role: nickjj.fail2ban + tags: fail2ban + - role: common + tags: common + - role: ufw + tags: ufw + - role: user + tags: user + - role: ssh + tags: ssh + - role: nickjj.docker + when: install_docker == true + tags: docker + - role: docker + when: install_docker == true + tags: docker + - role: jnv.debian-backports + tags: common + - role: ansible-monit + tags: common + - role: jnv.unattended-upgrades + tags: common + - role: networking + tags: networking + - role: reboot + tags: reboot diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000..435ed59 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,6 @@ +--- +- src: nickjj.fail2ban +- src: nickjj.docker +- src: https://github.com/mrlesmithjr/ansible-monit +- src: jnv.debian-backports +- src: jnv.unattended-upgrades diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml new file mode 100644 index 0000000..c12fc3c --- /dev/null +++ b/roles/common/handlers/main.yml @@ -0,0 +1,20 @@ +--- +- name: restart ntp + service: + name: ntp + state: restarted + +- name: restart cron + service: + name: cron + state: restarted + +- name: restart fail2ban + service: + name: fail2ban + state: restarted + +- name: restart exim4 + service: + name: exim4 + state: restarted diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml new file mode 100644 index 0000000..618969a --- /dev/null +++ b/roles/common/tasks/main.yml @@ -0,0 +1,95 @@ +--- +- name: Upgrade packages + apt: + upgrade: full + +- name: Install packages + apt: + name: "{{packages_to_install}}" + state: present + update_cache: yes + allow_unauthenticated: yes + +- name: Install mozilla/sops + get_url: + url: https://github.com/mozilla/sops/releases/download/v3.5.0/sops-v3.5.0.linux + dest: /usr/bin/sops + mode: "0755" + owner: root + group: root + +- name: Enable dm_crypt module + modprobe: + name: dm_crypt + state: present + +- name: Enable compress on logrotate + lineinfile: + dest: /etc/logrotate.conf + regexp: "^#?compress" + line: "compress" + state: present + +# - name: Send logcheck results to right email address +# lineinfile: +# dest: /etc/logcheck/logcheck.conf +# regexp: "^#?SENDMAILTO=" +# line: "SENDMAILTO=\"{{dot_forward_email}}\"" +# state: present + +# - name: Copy local logcheck ignore rules +# copy: +# src: templates/local-rules +# dest: /etc/logcheck/ignore.d.server/local-rules +# owner: root +# group: logcheck +# mode: u=rw,g=r,o=r + +- name: Configure timezone + timezone: + name: "{{timezone}}" + +- name: Configure ntp client and restart it + template: + src: ntp.conf.j2 + dest: /etc/ntp.conf + notify: + - restart ntp + - restart cron + +- name: Set up exim4 conf + template: + src: update-exim4.conf.conf.j2 + dest: /etc/exim4/update-exim4.conf.conf + owner: root + group: root + mode: 0644 + +- name: Set up exim4 password file + template: + src: passwd.client.j2 + dest: /etc/exim4/passwd.client + owner: root + group: Debian-exim + mode: 0640 + +- name: Set up exim4 localmacros + template: + src: exim4.conf.localmacros.j2 + dest: /etc/exim4/exim4.conf.localmacros + owner: root + group: root + mode: 0644 + notify: restart exim4 + +- name: Make fail2ban work with ufw + lineinfile: + dest: "{{item}}" + regexp: "^banaction" + line: "banaction = ufw" + state: present + with_items: + - /etc/fail2ban/jail.conf + - /etc/fail2ban/jail.local + notify: + - restart fail2ban diff --git a/roles/common/templates/exim4.conf.localmacros.j2 b/roles/common/templates/exim4.conf.localmacros.j2 new file mode 100644 index 0000000..07fb376 --- /dev/null +++ b/roles/common/templates/exim4.conf.localmacros.j2 @@ -0,0 +1 @@ +AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS = 1 diff --git a/roles/common/templates/local-rules b/roles/common/templates/local-rules new file mode 100644 index 0000000..57455f5 --- /dev/null +++ b/roles/common/templates/local-rules @@ -0,0 +1,241 @@ +#Avahi daemon casues a lot of spam. Add rules for the following type of messages; +#Feb 7 19:15:47 alias avahi-daemon[772]: Invalid query packet. +#Feb 7 19:16:51 alias avahi-daemon[772]: last message repeated 5 times +#Feb 7 19:35:46 alias avahi-daemon[772]: Invalid response packet from host 130.89.170.253. +#Note that the next rule is ugly, but i'm not sure how to filter it otherwise (except stopping rsyslog from summaryzing) +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ avahi-daemon\[[0-9]+\]: last message repeated [0-9]+ time(s)?$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ avahi-daemon\[[0-9]+\]: Invalid query packet.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ avahi-daemon\[[0-9]+\]: Invalid response packet from host [[:alnum:]:.]+.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ avahi-daemon\[[0-9]+\]: Received response from host [[:alnum:].]+ with invalid source port [0-9]+ on interface '[[:alnum:]:.]+'$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ avahi-daemon\[[0-9]+\]: Registering new address record for [:0-9a-f]+ on [[:alnum:]]+\.\*.$ +#Remove like: +#Feb 8 16:55:24 alias avahi-daemon[908]: Received response from host 130.89.164.246 with invalid source port 52031 on interface 'eth0.0' +#Feb 8 16:55:23 alias avahi-daemon[908]: Invalid legacy unicast query packet. +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ avahi-daemon\[[0-9]+\]: Invalid legacy unicast query packet.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ avahi-daemon\[[0-9]+\]: Received response with invalid source port [0-9]+ on interface '[[:alnum:].]+'$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ avahi-daemon\[[0-9]+\]: Invalid response packet.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ CRON\[[0-9]+\]:.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ cron-apt: Get: +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ cron-apt: The following package was automatically installed and is no longer required: +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ cron-apt: Use 'apt-get autoremove' to remove it\. +# Process accounting resumed +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel: \[[\.0-9]+\] Process accounting resumed$ +# perf samples too long (KVM/X58/5 series chipset issue) +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel: \[[\.0-9]+\] perf samples too long \([0-9]{3,5} > [0-9]{3,5}\), lowering kernel\.perf_event_max_sample_rate to [0-9]{3,5}$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel: \[[\.0-9]+\] perf interrupt took too long \([0-9]{3,5} > [0-9]{3,5}\), lowering kernel\.perf_event_max_sample_rate to [0-9]{3,5}$ +# ext4 remounts +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel: \[[\.0-9]+\] EXT4-fs \([a-zA-Z]{2,3}-[0-9]{1,2}\): re-mounted\. Opts: \(null\)$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel: \[[\.0-9]+\] list passed to list_sort\(\) too long for efficiency$ +#Lines zoals: +#Feb 6 17:21:26 alias ntpd[1030]: clock is now synced +#Feb 6 17:39:54 alias ntpd[1030]: clock is now unsynced +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: clock is now synced$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: clock is now unsynced$ +#Allow NTPD to make small adjustments to the local clock without spam +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: adjusting local clock by (-)?[0-9].[0-9]+s$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: adjusting clock frequency by (-)?[0-9]\.[0-9]+ to (-)?[0-9]{0,2}\.[0-9]+ppm$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: skew change (-)?[0-9]+.[0-9]+ exceeds limit$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: peer [[:alnum:]:\.]{7,39} now (valid|invalid)$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: reply from [[:alnum:]:\.]{7,39}: not synced( \(alarm\))?, next query [0-9]+s$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: reply from [[:alnum:]:\.]{7,39}: negative delay -0\.[0-9]+(, next query [0-9]+s)?$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: (message repeated [0-9]{1,3} times: \[ )?sendto: Network is unreachable(\])$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: peers refreshed$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: new interface\(s\) found: waking up resolver$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: Listen normally on [0-9]+ (eth|br)[0-9]+ [[:alnum:]:\.]{7,39} UDP [0-9]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: [[:alnum:]:\.]{7,39} interface [[:alnum:]:\.]{7,39} -> ([[:alnum:]:\.]{7,39}|\(none\))$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ntpd[[0-9]+]: Deleting interface \#[0-9]+ [[:alnum:]]{3,4}, [[:alnum:]:\.]{7,39}#[0-9]+, interface stats: received=[0-9]+, sent=[0-9=}, dropped=[0-9]+, active_time=[0-9]+ secs$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix/smtp\[[[:digit:]]+\]: [[:alnum:]]+: replace: header +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ postfix/pipe\[[[:digit:]]+\]:.+delivered via omvnotificationfilter service.+$ + +#Ignore UDP connects to public community on localhost +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ snmpd\[[0-9]+\]: Connection from UDP: \[127.0.0.1\]->\[127.0.0.1\]:-[0-9]+$ +# Logcheck rules for systemd, organized by component. + +# Automount +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Set up|Unset) automount .+\.$ + +# Busname & Socket +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Closed|Listening on) .+\.$ + +# Device +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Expecting device [^[:space:]]+\.device\.\.\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Found device [^[:space:]]+\.$ + +# Device +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Successfully loaded the IMA custom policy [^[:space:]]+\.$ + +# Job & Service & Unit +# FIXME: Don't want to match "Stopped \(with error\) .+\.$" +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Started|Stopped|Reloaded) .+\.$ +# FIXME: Don't want to match "Starting of .+ not supported\.$" +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Starting|Stopping|Reloading) .+\.$ + +# Log +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd(-[^[:space:]]+)?\[[[:digit:]]+\]: Received SIG[^[:space:]]+( from PID [[:digit:]]+ \([^[:space:]]+\))?\.$ + +# Main +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Reexecuting|Reloading|Shutting down|Switching root)\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Detected architecture [^[:space:]]+\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Detected virtualization [^[:space:]]+\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: RTC configured in localtime, applying delta of -?[[:digit:]]+ minutes to system time\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Running in initial RAM disk\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: systemd [[:digit:]]+ running in (test )?system mode. \((\+[[:alnum:]]+ ?)+\)$ + +# Manager +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Startup finished in [[:digit:]]+ms\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Time has been changed$ + +# Mount +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Mounted|Unmounted) .+\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Mounting .+\.\.\.$ + +# PAM +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd: pam_unix\(systemd-user:session\): session (opened|closed) for user [^[:space:]]+( by \(uid=[[:digit:]]+\))?$ + +# SELinux +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Successfully loaded SELinux policy in [^[:space:]]+\.$ + +# Smack +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Successfully loaded Smack(/CIPSO)? policies\.$ + +# Slice +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Created|Removed) slice User Slice of .+\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Created|Removed) slice [^[:space:]]+\.slice\.$ + +# Swap +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Activated|Deactivated) swap .+\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: Activating swap .+\.\.\.$ + +# Target +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: (Reached|Stopped) target .+\.$ + +# Unit +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: [^[:space:]]+: Unit is bound to inactive unit [^[:space:]]+\. Stopping, too\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd\[[[:digit:]]+\]: [^[:space:]]+: Unit not needed anymore\. Stopping\.$ + +# systemd-journald +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd-journald\[[[:digit:]]+\]: Received request to (flush|rotate) runtime journal from PID [[:digit:]]+$ + +# systemd-logind +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd-logind\[[[:digit:]]+\]: New session [^[:space:]]+ of user [^[:space:]]+\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd-logind\[[[:digit:]]+\]: Removed session [^[:space:]]+\.$ + +# systemd-sleep +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd-sleep\[[[:digit:]]+\]: Suspending system\.\.\.$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd-sleep\[[[:digit:]]+\]: System resumed\.$ + +# systemd-timesyncd +# Note: Only required for systemd 218 and earlier due to +# https://bugs.freedesktop.org/show_bug.cgi?id=88926 +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd-timesyncd\[[[:digit:]]+\]: interval/delta/delay/jitter/drift [[:digit:]]+s/(\+|-)[.[:digit:]]+s/-?[.[:digit:]]+s/-?[.[:digit:]]+s/(\+|-)[[:digit:]]+ppm( \(ignored\))?$ + +# /etc/logcheck/ignore.d.server/local-rules +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel: \[[. [:digit:]]+\] perf samples too long \([[:digit:]]+ > [0-9]+\), lowering kernel.perf_event_max_sample_rate to [[:digit:]]+$ +ntpd\[[0-9]+\]: adjusting clock frequency by [0-9]+\.[0-9]+ to [0-9]+\.[0-9]+ppm +ntpd\[[0-9]+\]: adjusting clock frequency by [0-9]+\.[0-9]+ to -[0-9]+\.[0-9]+ppm +ntpd\[[0-9]+\]: adjusting clock frequency by -[0-9]+\.[0-9]+ to [0-9]+\.[0-9]+ppm +ntpd\[[0-9]+\]: adjusting clock frequency by -[0-9]+\.[0-9]+ to -[0-9]+\.[0-9]+ppm +ntpd\[[0-9]+\]: adjusting local clock by [-]*[0-9]+\.[0-9]+s +ntpd\[[0-9]+\]: bad peer from pool [0-9]+.debian.pool.ntp.org +ntpd\[[0-9]+\]: Soliciting pool server +ntpd\[[0-9]+\]: [0-9]+ out of [0-9]+ peers valid +ntpd\[[0-9]+\]: reply from [\.0-9]+: not synced, next query [0-9]+s +auditd\[[0-9]+\]: Audit daemon rotating log files +kernel\[[0-9]+\]: \[[0-9]+\.[0-9]+\] INFO: NMI handler (perf_event_nmi_handler) took too long to run: [0-9]+.[0-9]+ msecs +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel: \[[. [:digit:]]+\] hrtimer: interrupt took [[:digit:]]+ ns$ +rrdcached\[[0-9]+\]: Received FLUSHALL +rrdcached\[[0-9]+\]: flushing old values +rrdcached\[[0-9]+\]: removing old journal /var/lib/rrdcached/journal/rrd.journal.[0-9]+\.[0-9]+ +rrdcached\[[0-9]+\]: rotating journals +rrdcached\[[0-9]+\]: started new journal /var/lib/rrdcached/journal/rrd.journal.[0-9]+\.[0-9]+ +systemd-logind\[[0-9]+\]: New session c[0-9]+ of user nobody. +systemd-logind\[[0-9]+\]: New session [0-9]+ of user vagrant. +systemd-logind\[[0-9]+\]: Removed session [0-9]+. +systemd-logind\[[0-9]+\]: Removed session c[0-9]+. +## suppress issues that arise with publicly available services that people try to exploit. https://gist.github.com/towo/9600375 +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: Did not receive identification string from ::ffff:[\.0-9]+$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: fatal: Read from socket failed: Connection reset by peer \[preauth\]$ +#^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: I(llegal|nvalid) user [^[:space:]]* from ([:.[:xdigit:]]+|UNKNOWN)$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: invalid public DH value: <= 1 \[preauth\]$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: Disconnecting: bad client public DH value \[preauth\]$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: Disconnecting: Change of username or service not allowed: \([[:alpha:]]+,ssh-connection\) -> \([[:alpha:]]+,ssh-connection\) \[preauth\]$ +#^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: Received disconnect from [:.[:xdigit:]]+: 3: com.jcraft.jsch.JSchException: Auth fail \[preauth\]$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: error: Received disconnect from [:.[:xdigit:]]+: 3: com.jcraft.jsch.JSchException: Auth fail \[preauth\]$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: Received disconnect from [\.0-9]+: 11: Bye Bye \[preauth\]$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: Received disconnect from [:.[:xdigit:]]+: 11: Goodbye \[preauth\]$ +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: Received disconnect from [:.[:xdigit:]]+: 11: PECL/ssh2 \(http://pecl.php.net/packages/ssh2\) \[preauth\]$ +## +##dhclient\[[[:digit:]]+\]: DHCPREQUEST of [\.0-9]+ on eth0 to [\.0-9]+ port [0-9]+ (xid=0x[0-9a-f]+) +#dhclient\[[0-9]+\]: DHCPREQUEST of [\.0-9]+ on eth0 to [\.0-9]+ port [0-9]+ (xid=0x[0-9a-f]+) +sh\[[0-9]+\]: Generated new chapter thumbnails for +sh\[[0-9]+\]: Warning: strange ID3v2 tag in +sh\[[0-9]+\]: __code__:699: FutureWarning: The behavior of this method will change in future versions. Use specific 'len\(elem\)' or 'elem is not None' test instead. +sh\[[0-9]+\]: self.processTRCK\( self.frameId, self.frameFlags, self.data \) +sh\[[0-9]+\]: Got nothing for: Series None None +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ cron-apt: Del +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ cron-apt: Calculating upgrade\.\.\. +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ cron-apt: CRON-APT LINE: +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ rsyslogd-[0-9]+: action 'action 20' suspended, next retry is +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ rsyslogd-?[0-9]+: action 'action 20' resumed +kernel: \[[0-9]+\.[0-9]+\] Peer .+ unexpectedly shrunk window .+ \(repaired\) +openmediavault-update-smart-drivedb: Updating smartmontools .+ drive database \.\.\. +cron-apt: The following packages were automatically installed and are no longer required: +cron-apt: Use 'apt-get autoremove' to remove them\. +openmediavault-webgui\[[[:digit:]]+\]: Authorized login from +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel: \[.+\] kvm \[[0-9]+]: vcpu[0-9]+ unimplemented perfctr wrmsr: +Exception AttributeError: "'ZipArchive' object has no attribute '_zip'" in +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd-timesyncd\[[0-9]+\]: Timed out waiting for reply from +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ systemd-timesyncd\[[0-9]+\]: Using NTP server +transmission-daemon\[[0-9]+\]: .+ which was just downloaded, failed its checksum test +systemd[\[0-9\]+]: Failed to reset devices.list on /system\.slice: Invalid argument +systemd[\[0-9\]+]: Failed to reset devices.list on /machine\.slice: Invalid argument +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ rsyslogd[0-9\-]+: action 'action [0-9]+' suspended, next retry is +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ rsyslogd[0-9\-]+: action 'action [0-9]+' resumed +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9\-]+\]: Connection closed by [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ port +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ systemd\[[0-9\-]+\]: .+\.timer: Adding .+ random time\. +^\w{3} [ :0-9]{11} [. [:alnum:]-]+ liblogging-stdlog:.+rsyslogd was HUPed$ +^\w{3} [ :0-9]{11} [. [:alnum:]-]+ liblogging-stdlog:.+rsyslogd.+ exiting on signal.+$ +^\w{3} [ :0-9]{11} [. [:alnum:]-]+ liblogging-stdlog:.+rsyslogd.+ start$ +^\w{3} [ :0-9]{11} [. [:alnum:]-]+ liblogging-stdlog: warning.+action is deprecated, consider using the 'stop' statement instead.+$ +^\w{3} [ :0-9]{11} [. [:alnum:]-]+ sh\[[0-9]+\]: GUI: +^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: Accepted (gssapi(-with-mic|-keyex)?|rsa|dsa|password|publickey|keyboard-interactive/pam|hostbased) for [^[:space:]]+ from [^[:space:]]+ port [[:digit:]]+( (ssh|ssh2))?: (RSA|ECDSA|ED25519) (SHA256:)?[/+:[:alnum:]]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ postfix/smtpd\[[0-9]+\]: warning: dict_nis_init: NIS domain name not set - NIS lookups disabled +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ postfix/smtpd\[[0-9]+\]: disconnect from +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ monit\[[0-9]+\]: .+ cpu user usage.+ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ monit\[[0-9]+\]: .+ loadavg.+ matches resource limit.+ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ monit\[[0-9]+\]: .+ loadavg.+ check succeeded.+ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ proftpd\[[0-9]+\]: Stopping ftp server: proftpd.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ proftpd\[[0-9]+\]: Starting ftp server: proftpd.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ su\[[0-9]+\]: pam_[[:alnum:]]+\(su:session\): Cannot create session: Already running in a session$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupsrv: Login successful for admin from .+ via web interface +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupsrv: Client authentication failure for .+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupclientbackend\[[0-9]+\]: ERROR: Creating shadowcopy of "root" failed.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupclientbackend\[[0-9]+\]: ERROR: Token id for user.+not found$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupclientbackend\[[0-9]+\]: ERROR: Token id for group.+not found$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupclientbackend\[[0-9]+\]: ERROR: Error getting file type of.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupclientbackend\[[0-9]+\]: ERROR: Error getting extended attribute.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupclientbackend\[[0-9]+\]: ERROR: Error stating file .+ to get file tokens. Errno: 13$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ urbackupclientbackend\[[0-9]+\]: No LSB modules are available\.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Received disconnect from .+ disconnected by user$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Disconnected from .+ port .+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ postfix/pipe\[[0-9]+\]: .+ delivered via omvnotificationfilter service.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ systemd-logind\[[0-9]+\]: Watching system buttons on /dev/input/event.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ systemd\[[0-9]+\]: Configuration file .+ is marked executable\. Please remove executable permission bits\. Proceeding anyway\.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nmbd\[[0-9]+\]:.+source3/nmbd/nmbd_namequery\.c:.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nmbd\[[0-9]+\]:.+query_name_response: Multiple \([0-9]+\) responses received for a query on subnet.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nmbd\[[0-9]+\]:.+This response was from.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ansible-setup: Invoked with.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ansible-apt: Invoked with.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ansible-apt: \[WARNING\] Could not find aptitude\. Using apt-get instead\.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sSMTP\[[0-9]+\]: Creating SSL connection to host +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sSMTP\[[0-9]+\]: SSL connection using.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sSMTP\[[0-9]+\]: Sent mail for.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ kernel: \[[0-9\.]+\] \[UFW BLOCK\].+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ [a-f0-9]+\[[0-9]+\]: t=.+ lvl=info msg=".+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Invalid user .+ from .+ port [0-9]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Received disconnect from .+ port [0-9]+.+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Did not receive identification string from .+ port [0-9]+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Unable to negotiate with .+ port [0-9]+: no matching cipher found. Their offer: .+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Unable to negotiate with .+ port [0-9]+: no matching key exchange method found. Their offer: .+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Bad protocol version identification .+$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Connection reset by .+$ diff --git a/roles/common/templates/ntp.conf.j2 b/roles/common/templates/ntp.conf.j2 new file mode 100644 index 0000000..09cd04d --- /dev/null +++ b/roles/common/templates/ntp.conf.j2 @@ -0,0 +1,8 @@ +driftfile /var/lib/ntp/drift + +restrict 127.0.0.1 +restrict -6 ::1 + +restrict source notrap nomodify noquery + +server {{ntpserver}} diff --git a/roles/common/templates/passwd.client.j2 b/roles/common/templates/passwd.client.j2 new file mode 100644 index 0000000..53d804c --- /dev/null +++ b/roles/common/templates/passwd.client.j2 @@ -0,0 +1,8 @@ +# password file used when the local exim is authenticating to a remote +# host as a client. +# +# see exim4_passwd_client(5) for more documentation +# +# Example: +### target.mail.server.example:login:password +*:{{smtp_auth_user}}:{{smtp_auth_pass}} diff --git a/roles/common/templates/update-exim4.conf.conf.j2 b/roles/common/templates/update-exim4.conf.conf.j2 new file mode 100644 index 0000000..dcb6cb7 --- /dev/null +++ b/roles/common/templates/update-exim4.conf.conf.j2 @@ -0,0 +1,31 @@ +# /etc/exim4/update-exim4.conf.conf +# +# Edit this file and /etc/mailname by hand and execute update-exim4.conf +# yourself or use 'dpkg-reconfigure exim4-config' +# +# Please note that this is _not_ a dpkg-conffile and that automatic changes +# to this file might happen. The code handling this will honor your local +# changes, so this is usually fine, but will break local schemes that mess +# around with multiple versions of the file. +# +# update-exim4.conf uses this file to determine variable values to generate +# exim configuration macros for the configuration file. +# +# Most settings found in here do have corresponding questions in the +# Debconf configuration, but not all of them. +# +# This is a Debian specific file + +dc_eximconfig_configtype='satellite' +dc_other_hostnames='{{ansible_host}}' +dc_local_interfaces='127.0.0.1 ; ::1' +dc_readhost='{{ansible_host}}' +dc_relay_domains='' +dc_minimaldns='false' +dc_relay_nets='' +dc_smarthost='{{smtp_hostname}}::{{smtp_port}}' +CFILEMODE='644' +dc_use_split_config='false' +dc_hide_mailname='true' +dc_mailname_in_oh='true' +dc_localdelivery='mail_spool' diff --git a/roles/docker/handlers/main.yml b/roles/docker/handlers/main.yml new file mode 100644 index 0000000..e490eac --- /dev/null +++ b/roles/docker/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: restart docker + service: + name: docker + state: restarted + +- name: restart rsyslog + service: + name: rsyslog + state: restarted diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml new file mode 100644 index 0000000..bc60233 --- /dev/null +++ b/roles/docker/tasks/main.yml @@ -0,0 +1,27 @@ +--- +- name: Ensure group "docker" exists + group: + name: docker + state: present + +- name: Ensure default user belongs also to docker group + user: + name: "{{default_username}}" + groups: docker + append: yes + +- name: Add rsyslog custom rules for Docker + copy: + src: templates/docker.conf + dest: /etc/rsyslog.d/docker.conf + owner: root + group: root + mode: u=rw,g=r,o=r + +- name: Add logrotate custom rules for Docker logs + copy: + src: templates/logrotate_docker + dest: /etc/logrotate.d/docker + owner: root + group: root + mode: u=rw,g=r,o=r diff --git a/roles/docker/templates/docker.conf b/roles/docker/templates/docker.conf new file mode 100644 index 0000000..385a626 --- /dev/null +++ b/roles/docker/templates/docker.conf @@ -0,0 +1,2 @@ +if $syslogtag contains 'docker/' then /var/log/docker.log +& ~ diff --git a/roles/docker/templates/logrotate_docker b/roles/docker/templates/logrotate_docker new file mode 100644 index 0000000..ee9d3e3 --- /dev/null +++ b/roles/docker/templates/logrotate_docker @@ -0,0 +1,12 @@ +/var/log/docker.log +{ + rotate 7 + daily + missingok + notifempty + delaycompress + compress + postrotate + invoke-rc.d rsyslog rotate > /dev/null + endscript +} diff --git a/roles/networking/tasks/main.yml b/roles/networking/tasks/main.yml new file mode 100644 index 0000000..1470a92 --- /dev/null +++ b/roles/networking/tasks/main.yml @@ -0,0 +1,17 @@ +--- +- name: Configure /etc/network/interfaces + template: + src: "{{interfaces_template}}" + dest: /etc/network/interfaces + register: _configure_interfaces + +- block: + - name: Reboot for networking changes + shell: "sleep 5 && shutdown -r now 'Networking changes found, rebooting'" + async: 1 + poll: 0 + + - name: Wait for server to come back online + wait_for_connection: + delay: 15 + when: _configure_interfaces is changed diff --git a/roles/networking/templates/interfaces-dhcp-server.j2 b/roles/networking/templates/interfaces-dhcp-server.j2 new file mode 100644 index 0000000..b6ee173 --- /dev/null +++ b/roles/networking/templates/interfaces-dhcp-server.j2 @@ -0,0 +1,9 @@ +# The loopback network interface +auto lo +iface lo inet loopback + +# eth0 network interface +auto eth0 +allow-hotplug eth0 +iface eth0 inet dhcp + dns-search server diff --git a/roles/reboot/tasks/main.yml b/roles/reboot/tasks/main.yml new file mode 100644 index 0000000..8c3292e --- /dev/null +++ b/roles/reboot/tasks/main.yml @@ -0,0 +1,12 @@ +--- +- name: Reboot machine to finalize setup + shell: "sleep 5 && reboot" + async: 1 + poll: 0 + +- name: Wait for the reboot to complete + wait_for_connection: + connect_timeout: 20 + sleep: 5 + delay: 5 + timeout: 300 diff --git a/roles/ssh/handlers/main.yml b/roles/ssh/handlers/main.yml new file mode 100644 index 0000000..822887e --- /dev/null +++ b/roles/ssh/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart ssh + service: + name: ssh + state: restarted diff --git a/roles/ssh/tasks/main.yml b/roles/ssh/tasks/main.yml new file mode 100644 index 0000000..6fefe85 --- /dev/null +++ b/roles/ssh/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: Remove any PermitRootLogin instruction + lineinfile: + dest: /etc/ssh/sshd_config + regexp: "^PermitRootLogin" + state: absent + notify: restart ssh + +- name: Disable SSH root login + lineinfile: + dest: /etc/ssh/sshd_config + regexp: "^PermitRootLogin" + line: "PermitRootLogin prohibit-password" + state: present + notify: restart ssh + +- name: Disable password authentication + lineinfile: + dest: /etc/ssh/sshd_config + regexp: "^#?PasswordAuthentication" + line: "PasswordAuthentication no" + state: present + notify: restart ssh + +- name: Set SSH port + lineinfile: + dest: /etc/ssh/sshd_config + regexp: "^Port" + line: "Port {{sshd_port}}" + state: present + notify: restart ssh + +- name: Test + lineinfile diff --git a/roles/ufw/handlers/main.yml b/roles/ufw/handlers/main.yml new file mode 100644 index 0000000..964114c --- /dev/null +++ b/roles/ufw/handlers/main.yml @@ -0,0 +1,4 @@ +--- +- name: reload ufw + ufw: + state: reloaded diff --git a/roles/ufw/tasks/main.yml b/roles/ufw/tasks/main.yml new file mode 100644 index 0000000..17449f3 --- /dev/null +++ b/roles/ufw/tasks/main.yml @@ -0,0 +1,18 @@ +--- +- name: Apply custom connection ufw rules + ufw: rule="{{item.rule}}" port="{{item.port}}" src="{{item.src}}" proto="{{item.proto}}" direction="{{item.direction}}" + with_items: "{{ufw_rules}}" + +#- name: Limit SSH connection rate +# ufw: rule=limit port=22 proto=tcp + +- name: Deny all incoming connections + ufw: "direction=incoming policy=reject" + +- name: Enable logging + ufw: + logging: on + +- name: Enable firewall + ufw: state=enabled + notify: reload ufw diff --git a/roles/user/tasks/main.yml b/roles/user/tasks/main.yml new file mode 100644 index 0000000..3ca9cc3 --- /dev/null +++ b/roles/user/tasks/main.yml @@ -0,0 +1,91 @@ +--- +- name: Update default user, belonging to sudo group + user: + name: "{{default_username}}" + password: "{{default_password | password_hash('sha512')}}" + groups: sudo + create_home: yes + shell: /bin/bash + generate_ssh_key: yes + ssh_key_bits: 2048 + ssh_key_file: .ssh/id_rsa + update_password: always + state: present + +- name: Ensure sudo group has sudo privileges without password + lineinfile: + dest: /etc/sudoers + state: present + regexp: "^%sudo" + line: "%sudo ALL=(ALL) NOPASSWD:ALL" + validate: "/usr/sbin/visudo -cf %s" + +# copy local files to remote +- name: Install .forward file in users' folders + template: + src: dot.forward.j2 + dest: "{{item}}/.forward" + owner: "{{default_username}}" + group: "{{default_username}}" + with_items: + - "/root" + - "/home/{{default_username}}" + +- name: Clone dotfiles repository + become_user: "{{item.user}}" + git: + repo: "https://github.com/olivomarco/dotfiles.git" + version: master + dest: "{{item.path}}" + accept_hostkey: yes + clone: yes + update: yes + with_items: + - {user: "{{default_username}}", path: "/home/{{default_username}}/dotfiles"} + - {user: "root", path: "/root/dotfiles"} + +# - name: Run dotfiles/setup/setup-user.sh for {{item.user}} +# become_user: "{{item.user}}" +# shell: "{{item.path}}/setup/setup-user.sh" +# with_items: +# - {user: "{{default_username}}", path: "/home/{{default_username}}/dotfiles"} +# - {user: "root", path: "/root/dotfiles"} + +- name: Change owner of dotfiles in {{default_username}} folder + file: + path: "/home/{{default_username}}/dotfiles" + owner: "{{default_username}}" + group: "{{default_username}}" + recurse: yes + +# other setup +- name: Assign public ssh key to a variable + shell: cat /home/{{default_username}}/{{public_key}} + register: ssh_public_key + +- name: Add default username's public SSH key to its authorized_keys file + lineinfile: + dest: "/home/{{default_username}}/.ssh/authorized_keys" + line: "{{ssh_public_key.stdout}}" + state: present + create: yes + +- name: Change root password + user: + name: root + password: "{{root_password | password_hash('sha512')}}" + update_password: always + +- name: chsh to /usr/bin/zsh for default user and root + user: + name: "{{item}}" + shell: /usr/bin/zsh + with_items: + - "{{default_username}}" + - "root" + +- debug: + msg: "user '{{default_username}}' generated password: {{default_password}}" + +- debug: + msg: "user 'root' generated password: {{root_password}}" diff --git a/roles/user/templates/dot.forward.j2 b/roles/user/templates/dot.forward.j2 new file mode 100644 index 0000000..55d5f6b --- /dev/null +++ b/roles/user/templates/dot.forward.j2 @@ -0,0 +1 @@ +{{dot_forward_email}}