Add debian common role
This commit is contained in:
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Ansible fact - dhcp_status
|
||||
# {{ ansible_managed }}
|
||||
DHCP_STATUS="$( grep -o 'dhcp' /etc/network/interfaces | uniq )"
|
||||
echo "\"${DHCP_STATUS}\""
|
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Ansible fact - host_group
|
||||
# {{ ansible_managed }}
|
||||
HOST_GROUP="$( hostname -s | sed 's/[0-9]*//g' )"
|
||||
echo "\"${HOST_GROUP}\""
|
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Ansible fact - host_id
|
||||
# {{ ansible_managed }}
|
||||
HOST_ID="$( hostname -s | grep -o '[0-9]\+' )"
|
||||
if [[ -z ${HOST_ID} ]]; then
|
||||
HOST_ID="0"
|
||||
fi
|
||||
echo "\"${HOST_ID}\""
|
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Ansible fact - moe_release
|
||||
# {{ ansible_managed }}
|
||||
DPKG_ARCHITECTURE="$( dpkg --print-architecture )"
|
||||
DEBIAN_CODENAME="$( grep 'VERSION_CODENAME=' /etc/os-release | sed 's/VERSION_CODENAME=//' )"
|
||||
DEBIAN_VERSION="$( grep 'VERSION_ID=' /etc/os-release | sed -E 's/VERSION_ID="(.*)"/\1/' )"
|
||||
MOE_VERSION="1.$(( ${DEBIAN_VERSION} - 11 ))"
|
||||
echo "{ \"dpkg_architecture\": \"${DPKG_ARCHITECTURE}\", \"moe_version\": \"${MOE_VERSION}\", \"debian_version\": \"${DEBIAN_VERSION}\", \"debian_codename\": \"${DEBIAN_CODENAME}\" }"
|
@ -0,0 +1,5 @@
|
||||
# apt configuration: disable recommends
|
||||
# {{ ansible_managed }}
|
||||
|
||||
APT::Install-Recommends "0";
|
||||
APT::Install-Suggests "0";
|
@ -0,0 +1,5 @@
|
||||
# apt configuration: enable apt-cacher-ng proxy
|
||||
# {{ ansible_managed }}
|
||||
|
||||
Acquire::http::Proxy::debian.mirror.rafal.ca "http://{{ blsedomains_admindomain }}:3142";
|
||||
Acquire::http::Proxy::security.debian.org "http://{{ blsedomains_admindomain }}:3142";
|
@ -0,0 +1,30 @@
|
||||
# apt configuration: unattended upgrades
|
||||
# {{ ansible_managed }}
|
||||
|
||||
Unattended-Upgrade::Origins-Pattern {
|
||||
"origin=Debian,codename=${distro_codename},label=Debian";
|
||||
"origin=Debian,codename=${distro_codename},label=Debian-Security";
|
||||
};
|
||||
|
||||
Unattended-Upgrade::Package-Blacklist {
|
||||
# "libc6$";
|
||||
# "libc6-dev$";
|
||||
# "libc6-i686$";
|
||||
};
|
||||
|
||||
# General configurations
|
||||
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
|
||||
Unattended-Upgrade::MinimalSteps "true";
|
||||
Unattended-Upgrade::InstallOnShutdown "false";
|
||||
Unattended-Upgrade::Mail "";
|
||||
Unattended-Upgrade::MailOnlyOnError "true";
|
||||
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
|
||||
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
|
||||
Unattended-Upgrade::Remove-Unused-Dependencies "true";
|
||||
Unattended-Upgrade::SyslogEnable "true";
|
||||
Unattended-Upgrade::SyslogFacility "daemon";
|
||||
Unattended-Upgrade::Verbose "false";
|
||||
Unattended-Upgrade::Debug "false";
|
||||
|
||||
# Reboot configurations - do not reboot automatically
|
||||
Unattended-Upgrade::Automatic-Reboot "false";
|
11
common-debian/templates/etc/apt/preferences.d/pins.j2
Normal file
11
common-debian/templates/etc/apt/preferences.d/pins.j2
Normal file
@ -0,0 +1,11 @@
|
||||
# apt configuration: pinning preferences
|
||||
# {{ ansible_managed }}
|
||||
|
||||
Package: *
|
||||
Pin: release a={{ moe_release.debian_codename }}
|
||||
Pin-Priority: 999
|
||||
|
||||
# Ensure backports are not installed by default
|
||||
Package: *
|
||||
Pin: release a={{ moe_release.debian_codename }}-backports
|
||||
Pin-Priority: -1
|
7
common-debian/templates/etc/apt/sources.list.d/source.j2
Normal file
7
common-debian/templates/etc/apt/sources.list.d/source.j2
Normal file
@ -0,0 +1,7 @@
|
||||
# {{ item.name }} sources.list entry
|
||||
# {{ ansible_managed }}
|
||||
|
||||
deb {% if item.gpg_url is defined and item.gpg_url -%}[signed-by=/etc/apt/trusted.gpg.d/{{ item.name }}.gpg] {% endif -%} {{ item.url }} {{ item.distribution }} {{ item.components|join(' ') }}
|
||||
{% if item.has_src %}
|
||||
deb-src {% if item.gpg_url is defined and item.gpg_url -%}[signed-by=/etc/apt/trusted.gpg.d/{{ item.name }}.gpg] {% endif -%} {{ item.url }} {{ item.distribution }} {{ item.components|join(' ') }}
|
||||
{% endif %}
|
126
common-debian/templates/etc/bash.bashrc.j2
Executable file
126
common-debian/templates/etc/bash.bashrc.j2
Executable file
@ -0,0 +1,126 @@
|
||||
# System-wide .bashrc file for interactive bash(1) shells.
|
||||
# {{ ansible_managed }}
|
||||
|
||||
# To enable the settings / commands in this file for login shells as well,
|
||||
# this file has to be sourced in /etc/profile.
|
||||
|
||||
# Fix the preceeding space stupidity
|
||||
export HISTCONTROL=ignorespace
|
||||
|
||||
# If not running interactively, don't do anything
|
||||
[ -z "$PS1" ] && return
|
||||
|
||||
# check the window size after each command and, if necessary,
|
||||
# update the values of LINES and COLUMNS.
|
||||
shopt -s checkwinsize
|
||||
|
||||
# set variable identifying the chroot you work in (used in the prompt below)
|
||||
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
|
||||
debian_chroot=$(cat /etc/debian_chroot)
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Returncode.
|
||||
#------------------------------------------------------------------------------
|
||||
function returncode
|
||||
{
|
||||
returncode=$?
|
||||
if [ $returncode != 0 ]; then
|
||||
echo "[$returncode]"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
alias ll='ls -al'
|
||||
|
||||
use_color=false
|
||||
|
||||
# Set colorful PS1 only on colorful terminals.
|
||||
# dircolors --print-database uses its own built-in database
|
||||
# instead of using /etc/DIR_COLORS. Try to use the external file
|
||||
# first to take advantage of user additions. Use internal bash
|
||||
# globbing instead of external grep binary.
|
||||
safe_term=${TERM//[^[:alnum:]]/?} # sanitize TERM
|
||||
match_lhs=""
|
||||
[[ -f ~/.dir_colors ]] && match_lhs="${match_lhs}$(<~/.dir_colors)"
|
||||
[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(</etc/DIR_COLORS)"
|
||||
[[ -z ${match_lhs} ]] \
|
||||
&& type -P dircolors >/dev/null \
|
||||
&& match_lhs=$(dircolors --print-database)
|
||||
[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true
|
||||
|
||||
if ${use_color} ; then
|
||||
# Enable colors for ls, etc. Prefer ~/.dir_colors #64489
|
||||
if type -P dircolors >/dev/null ; then
|
||||
if [[ -f ~/.dir_colors ]] ; then
|
||||
eval $(dircolors -b ~/.dir_colors)
|
||||
elif [[ -f /etc/DIR_COLORS ]] ; then
|
||||
eval $(dircolors -b /etc/DIR_COLORS)
|
||||
else
|
||||
eval $(dircolors)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ${EUID} == 0 ]] ; then
|
||||
PS1='\[\033[0;31m\]$(returncode)\[\033[0;37m\]\[\033[0;35m\]${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\H\[\033[01;34m\] \w \$\[\033[00m\] '
|
||||
elif [[ ${UID} == 200 ]] ; then
|
||||
PS1='\[\033[0;31m\]$(returncode)\[\033[0;37m\]\[\033[0;35m\]${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u@\H\[\033[01;34m\] \w \$\[\033[00m\] '
|
||||
else
|
||||
PS1='\[\033[0;31m\]$(returncode)\[\033[0;37m\]\[\033[0;35m\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\H\[\033[01;34m\] \w \$\[\033[00m\] '
|
||||
fi
|
||||
|
||||
alias ls='ls --color=auto'
|
||||
alias grep='grep --colour=auto'
|
||||
alias fgrep='fgrep --colour=auto'
|
||||
alias egrep='egrep --colour=auto'
|
||||
alias ll='ls -lF'
|
||||
alias la='ls -A'
|
||||
alias l='ls -CF'
|
||||
else
|
||||
if [[ ${EUID} == 0 ]] ; then
|
||||
# show root@ when we don't have colors
|
||||
PS1='\[$(returncode)\]\u@\H \w \$ '
|
||||
else
|
||||
PS1='\[$(returncode)\]\u@\H \w \$ '
|
||||
fi
|
||||
fi
|
||||
|
||||
# Try to keep environment pollution down, EPA loves us.
|
||||
unset use_color safe_term match_lhs
|
||||
|
||||
# Commented out, don't overwrite xterm -T "title" -n "icontitle" by default.
|
||||
# If this is an xterm set the title to user@host:dir
|
||||
#case "$TERM" in
|
||||
#xterm*|rxvt*)
|
||||
# PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
|
||||
# ;;
|
||||
#*)
|
||||
# ;;
|
||||
#esac
|
||||
|
||||
# enable bash completion in interactive shells
|
||||
if ! shopt -oq posix; then
|
||||
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
||||
. /usr/share/bash-completion/bash_completion
|
||||
elif [ -f /etc/bash_completion ]; then
|
||||
. /etc/bash_completion
|
||||
fi
|
||||
fi
|
||||
|
||||
# if the command-not-found package is installed, use it
|
||||
if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then
|
||||
function command_not_found_handle {
|
||||
# check because c-n-f could've been removed in the meantime
|
||||
if [ -x /usr/lib/command-not-found ]; then
|
||||
/usr/bin/python /usr/lib/command-not-found -- "$1"
|
||||
return $?
|
||||
elif [ -x /usr/share/command-not-found/command-not-found ]; then
|
||||
/usr/bin/python /usr/share/command-not-found/command-not-found -- "$1"
|
||||
return $?
|
||||
else
|
||||
printf "%s: command not found\n" "$1" >&2
|
||||
return 127
|
||||
fi
|
||||
}
|
||||
fi
|
58
common-debian/templates/etc/check_mk/logwatch.cfg.j2
Normal file
58
common-debian/templates/etc/check_mk/logwatch.cfg.j2
Normal file
@ -0,0 +1,58 @@
|
||||
# +------------------------------------------------------------------+
|
||||
# | ____ _ _ __ __ _ __ |
|
||||
# | / ___| |__ ___ ___| | __ | \/ | |/ / |
|
||||
# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
|
||||
# | | |___| | | | __/ (__| < | | | | . \ |
|
||||
# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
|
||||
# | |
|
||||
# | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
|
||||
# +------------------------------------------------------------------+
|
||||
#
|
||||
# This file is part of Check_MK.
|
||||
# The official homepage is at http://mathias-kettner.de/check_mk.
|
||||
#
|
||||
# check_mk is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation in version 2. check_mk is distributed
|
||||
# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
|
||||
# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU General Public License for more de-
|
||||
# tails. You should have received a copy of the GNU General Public
|
||||
# License along with GNU Make; see the file COPYING. If not, write
|
||||
# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
# Boston, MA 02110-1301 USA.
|
||||
|
||||
# logwatch.cfg
|
||||
# This file configures mk_logwatch. Define your logfiles
|
||||
# and patterns to be looked for here.
|
||||
|
||||
# Patterns are indented with one space are prefixed with:
|
||||
# C: Critical messages
|
||||
# W: Warning messages
|
||||
# I: ignore these lines (OK)
|
||||
# R: Rewrite the output previous match. You can use \1, \2 etc. for refer to groups (.*) of this match
|
||||
# The first match decided. Lines that do not match any pattern
|
||||
# are ignored
|
||||
|
||||
# Globbing patterns are allowed:
|
||||
# /sapdata/*/saptrans.log
|
||||
# C ORA-
|
||||
|
||||
/var/log/kern.log
|
||||
I registered panic notifier
|
||||
C panic
|
||||
C Oops
|
||||
W generic protection rip
|
||||
W .*Unrecovered read error - auto reallocate failed
|
||||
|
||||
/var/log/auth.log
|
||||
I sshd.*Corrupted MAC on input
|
||||
|
||||
/var/log/system.log
|
||||
C Fail event detected on md device
|
||||
I mdadm.*: Rebuild.*event detected
|
||||
W mdadm\[
|
||||
W ata.*hard resetting link
|
||||
W ata.*soft reset failed (.*FIS failed)
|
||||
W device-mapper: thin:.*reached low water mark
|
||||
C device-mapper: thin:.*no free space
|
6
common-debian/templates/etc/cron.d/update-motd.j2
Normal file
6
common-debian/templates/etc/cron.d/update-motd.j2
Normal file
@ -0,0 +1,6 @@
|
||||
# cron file for motd
|
||||
# {{ ansible_managed }}
|
||||
|
||||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
@reboot root /usr/local/sbin/update-motd.sh &>/dev/null
|
||||
*/5 * * * * root /usr/local/sbin/update-motd.sh &>/dev/null
|
12
common-debian/templates/etc/crontab.j2
Normal file
12
common-debian/templates/etc/crontab.j2
Normal file
@ -0,0 +1,12 @@
|
||||
# /etc/crontab: system-wide crontab
|
||||
# {{ ansible_managed }}
|
||||
|
||||
SHELL=/bin/sh
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
# m h dom mon dow user command
|
||||
00 * * * * root cd / && run-parts --report /etc/cron.hourly
|
||||
05 0 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
|
||||
15 0 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
|
||||
30 0 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
|
||||
#
|
7
common-debian/templates/etc/default/locale.j2
Normal file
7
common-debian/templates/etc/default/locale.j2
Normal file
@ -0,0 +1,7 @@
|
||||
# Default locale settings
|
||||
# {{ ansible_managed }}
|
||||
|
||||
LANGUAGE={{ locale }}
|
||||
LC_ALL={{ locale }}
|
||||
LANG={{ locale }}
|
||||
LC_TYPE={{ locale }}
|
25
common-debian/templates/etc/default/zramswap.j2
Normal file
25
common-debian/templates/etc/default/zramswap.j2
Normal file
@ -0,0 +1,25 @@
|
||||
# Default zramswap settings
|
||||
# {{ ansible_managed }}
|
||||
|
||||
# Compression algorithm selection
|
||||
# speed: lz4 > zstd > lzo
|
||||
# compression: zstd > lzo > lz4
|
||||
# This is not inclusive of all that is available in latest kernels
|
||||
# See /sys/block/zram0/comp_algorithm (when zram module is loaded) to see
|
||||
# what is currently set and available for your kernel[1]
|
||||
# [1] https://github.com/torvalds/linux/blob/master/Documentation/blockdev/zram.txt#L86
|
||||
ALGO=zstd
|
||||
|
||||
# Specifies the amount of RAM that should be used for zram
|
||||
# based on a percentage the total amount of available memory
|
||||
# This takes precedence and overrides SIZE below
|
||||
PERCENT=50
|
||||
|
||||
# Specifies a static amount of RAM that should be used for
|
||||
# the ZRAM devices, this is in MiB
|
||||
#SIZE=256
|
||||
|
||||
# Specifies the priority for the swap devices, see swapon(2)
|
||||
# for more details. Higher number = higher priority
|
||||
# This should probably be higher than hdd/ssd swaps.
|
||||
PRIORITY=1000
|
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
# Disasble resolv.conf generation from DHCP
|
||||
# {{ ansible_managed }}
|
||||
make_resolv_conf() {
|
||||
:
|
||||
}
|
15
common-debian/templates/etc/fail2ban/action.d/route.conf.j2
Normal file
15
common-debian/templates/etc/fail2ban/action.d/route.conf.j2
Normal file
@ -0,0 +1,15 @@
|
||||
# fail2ban action - route
|
||||
|
||||
[Definition]
|
||||
actionban = ip route add <blocktype> <ip>
|
||||
actionunban = ip route del <blocktype> <ip>
|
||||
actioncheck =
|
||||
actionstart =
|
||||
actionstop =
|
||||
|
||||
[Init]
|
||||
|
||||
# Option: blocktype
|
||||
# Note: Type can be blackhole, unreachable and prohibit. Unreachable and prohibit correspond to the ICMP reject messages.
|
||||
# Values: STRING
|
||||
blocktype = blackhole
|
51
common-debian/templates/etc/fail2ban/filter.d/sshd.conf.j2
Normal file
51
common-debian/templates/etc/fail2ban/filter.d/sshd.conf.j2
Normal file
@ -0,0 +1,51 @@
|
||||
# Fail2Ban filter for openssh
|
||||
# {{ ansible_managed }}
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
# Read common prefixes. If any customizations available -- read them from
|
||||
# common.local
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
_daemon = sshd
|
||||
|
||||
failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error|failed) for .* from <HOST>( via \S+)?\s*$
|
||||
^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
|
||||
^%(__prefix_line)sFailed \S+ for (?P<cond_inv>invalid user )?(?P<user>(?P<cond_user>\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+)) from <HOST>(?: port \d+)?(?: ssh\d*)?(?(cond_user):|(?:(?:(?! from ).)*)$)
|
||||
^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
|
||||
^%(__prefix_line)s[iI](?:llegal|nvalid) user .*? from <HOST>(?: port \d+)?\s*$
|
||||
^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers\s*$
|
||||
^%(__prefix_line)sUser .+ from <HOST> not allowed because listed in DenyUsers\s*$
|
||||
^%(__prefix_line)sUser .+ from <HOST> not allowed because not in any group\s*$
|
||||
^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
|
||||
^%(__prefix_line)s(?:error: )?Received disconnect from <HOST>: 3: .*: Auth fail(?: \[preauth\])?$
|
||||
^%(__prefix_line)sUser .+ from <HOST> not allowed because a group is listed in DenyGroups\s*$
|
||||
^%(__prefix_line)sUser .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$
|
||||
^(?P<__prefix>%(__prefix_line)s)User .+ not allowed because account is locked<SKIPLINES>(?P=__prefix)(?:error: )?Received disconnect from <HOST>: 11: .+ \[preauth\]$
|
||||
^(?P<__prefix>%(__prefix_line)s)Disconnecting: Too many authentication failures for .+? \[preauth\]<SKIPLINES>(?P=__prefix)(?:error: )?Connection closed by <HOST> \[preauth\]$
|
||||
^(?P<__prefix>%(__prefix_line)s)Connection from <HOST> port \d+(?: on \S+ port \d+)?<SKIPLINES>(?P=__prefix)Disconnecting: Too many authentication failures for .+? \[preauth\]$
|
||||
^%(__prefix_line)s(error: )?maximum authentication attempts exceeded for .* from <HOST>(?: port \d*)?(?: ssh\d*)? \[preauth\]$
|
||||
^%(__prefix_line)spam_unix\(sshd:auth\):\s+authentication failure;\s*logname=\S*\s*uid=\d*\s*euid=\d*\s*tty=\S*\s*ruser=\S*\s*rhost=<HOST>\s.*$
|
||||
^%(__prefix_line)sUnable to negotiate with <HOST> .*$
|
||||
^%(__prefix_line)sConnection reset by authenticating user .* <HOST> port .* \[preauth\]$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
[Init]
|
||||
|
||||
# "maxlines" is number of log lines to buffer for multi-line regex searches
|
||||
maxlines = 10
|
||||
|
||||
journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd
|
||||
|
||||
# DEV Notes:
|
||||
#
|
||||
# "Failed \S+ for .*? from <HOST>..." failregex uses non-greedy catch-all because
|
||||
# it is coming before use of <HOST> which is not hard-anchored at the end as well,
|
||||
# and later catch-all's could contain user-provided input, which need to be greedily
|
||||
# matched away first.
|
||||
#
|
||||
# Author: Cyril Jaquier, Yaroslav Halchenko, Petr Voralek, Daniel Black
|
||||
|
@ -0,0 +1,4 @@
|
||||
[DEFAULT]
|
||||
maxretry = 3
|
||||
bantime = 14400
|
||||
ignoreip = 127.0.0.0/8 10.0.0.0/8 198.55.48.48/28 24.53.125.139
|
30
common-debian/templates/etc/fail2ban/jail.d/sshd.conf.j2
Normal file
30
common-debian/templates/etc/fail2ban/jail.d/sshd.conf.j2
Normal file
@ -0,0 +1,30 @@
|
||||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Wolfgang Karall (based on sshd.conf from Cyril Jaquier)
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
# Read common prefixes. If any customizations available -- read them from
|
||||
# common.local
|
||||
before = common.conf
|
||||
|
||||
|
||||
[Definition]
|
||||
|
||||
_daemon = sshd
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = ^%(__prefix_line)sUnable to negotiate with <HOST> .*$
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex = ^%(__prefix_line)sDid not receive identification string from .*$
|
@ -0,0 +1,5 @@
|
||||
[ssh]
|
||||
enabled = true
|
||||
filter = sshd
|
||||
action = route
|
||||
logpath = /var/log/auth.log
|
14
common-debian/templates/etc/hosts.j2
Normal file
14
common-debian/templates/etc/hosts.j2
Normal file
@ -0,0 +1,14 @@
|
||||
# Local system hosts file
|
||||
# {{ ansible_managed }}
|
||||
|
||||
127.0.0.1 localhost
|
||||
::1 ip6-localhost ip6-loopback
|
||||
ff02::1 ip6-allmodes
|
||||
ff02::2 ip6-allrouters
|
||||
|
||||
{% if hosts_entries is defined %}
|
||||
{% for host in hosts_entries %}
|
||||
{{ host.ip }}{% for name in host.names %} {{ name }}{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
{% endif %}
|
39
common-debian/templates/etc/htoprc.j2
Normal file
39
common-debian/templates/etc/htoprc.j2
Normal file
@ -0,0 +1,39 @@
|
||||
# htop configuration file (Debian)
|
||||
# {{ ansible_managed }}
|
||||
fields=0 48 17 18 38 39 40 2 46 47 49 1
|
||||
sort_key=46
|
||||
sort_direction=0
|
||||
tree_sort_key=0
|
||||
tree_sort_direction=1
|
||||
hide_kernel_threads=0
|
||||
hide_userland_threads=0
|
||||
shadow_other_users=0
|
||||
show_thread_names=1
|
||||
show_program_path=1
|
||||
highlight_base_name=1
|
||||
highlight_megabytes=1
|
||||
highlight_threads=1
|
||||
highlight_changes=0
|
||||
highlight_changes_delay_secs=5
|
||||
find_comm_in_cmdline=1
|
||||
strip_exe_from_cmdline=1
|
||||
show_merged_command=0
|
||||
tree_view=0
|
||||
tree_view_always_by_pid=0
|
||||
header_margin=1
|
||||
detailed_cpu_time=1
|
||||
cpu_count_from_one=1
|
||||
show_cpu_usage=1
|
||||
show_cpu_frequency=0
|
||||
show_cpu_temperature=0
|
||||
degree_fahrenheit=0
|
||||
update_process_names=1
|
||||
account_guest_in_cpu_meter=1
|
||||
color_scheme=0
|
||||
enable_mouse=1
|
||||
delay=15
|
||||
left_meters=Hostname Clock Uptime Blank LeftCPUs2 Blank CPU Blank
|
||||
left_meter_modes=2 2 2 2 1 2 1 2
|
||||
right_meters=LoadAverage Tasks Systemd Blank RightCPUs2 Blank Memory Swap
|
||||
right_meter_modes=2 2 2 2 1 2 1 1
|
||||
hide_function_bar=0
|
4
common-debian/templates/etc/locale.gen.j2
Normal file
4
common-debian/templates/etc/locale.gen.j2
Normal file
@ -0,0 +1,4 @@
|
||||
# Locales configuration file
|
||||
# {{ ansible_managed }}
|
||||
|
||||
en_CA.UTF-8 UTF-8
|
10
common-debian/templates/etc/logrotate.d/backup-rsync.j2
Normal file
10
common-debian/templates/etc/logrotate.d/backup-rsync.j2
Normal file
@ -0,0 +1,10 @@
|
||||
# Logrotate configuration for backup rsync log
|
||||
# {{ ansible_managed }}
|
||||
|
||||
/var/backups/rsync.log
|
||||
{
|
||||
rotate 1
|
||||
weekly
|
||||
missingok
|
||||
notifempty
|
||||
}
|
22
common-debian/templates/etc/logrotate.d/rsyslog.j2
Normal file
22
common-debian/templates/etc/logrotate.d/rsyslog.j2
Normal file
@ -0,0 +1,22 @@
|
||||
# Logrotate configuration for standard log files
|
||||
# {{ ansible_managed }}
|
||||
|
||||
/var/log/kern.log
|
||||
/var/log/daemon.log
|
||||
/var/log/auth.log
|
||||
/var/log/cron.log
|
||||
/var/log/mail.log
|
||||
/var/log/boot.log
|
||||
/var/log/system.log
|
||||
{
|
||||
rotate {{ logrotate_keepcount }}
|
||||
{{ logrotate_interval }}
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
delaycompress
|
||||
sharedscripts
|
||||
postrotate
|
||||
/usr/lib/rsyslog/rsyslog-rotate
|
||||
endscript
|
||||
}
|
25
common-debian/templates/etc/nftables.conf.j2
Normal file
25
common-debian/templates/etc/nftables.conf.j2
Normal file
@ -0,0 +1,25 @@
|
||||
#!/usr/sbin/nft -f
|
||||
# {{ ansible_managed }}
|
||||
|
||||
flush ruleset
|
||||
|
||||
table inet filter {
|
||||
chain input {
|
||||
type filter hook input priority 0;
|
||||
{% for rule in nftables_rules if rule.chain == "input" %}
|
||||
{{ rule.rule }};
|
||||
{% endfor %}
|
||||
}
|
||||
chain forward {
|
||||
type filter hook forward priority 0;
|
||||
{% for rule in nftables_rules if rule.chain == "forward" %}
|
||||
{{ rule.rule }};
|
||||
{% endfor %}
|
||||
}
|
||||
chain output {
|
||||
type filter hook output priority 0;
|
||||
{% for rule in nftables_rules if rule.chain == "output" %}
|
||||
{{ rule.rule }};
|
||||
{% endfor %}
|
||||
}
|
||||
}
|
38
common-debian/templates/etc/ntp.conf.j2
Normal file
38
common-debian/templates/etc/ntp.conf.j2
Normal file
@ -0,0 +1,38 @@
|
||||
# Main NTP configuration
|
||||
# {{ ansible_managed }}
|
||||
|
||||
driftfile /var/lib/ntp/ntp.drift
|
||||
|
||||
statistics loopstats peerstats clockstats
|
||||
|
||||
filegen loopstats file loopstats type day enable
|
||||
filegen peerstats file peerstats type day enable
|
||||
filegen clockstats file clockstats type day enable
|
||||
|
||||
{% if 'remote' in group_names %}
|
||||
server time.nrc.ca
|
||||
server time.chu.nrc.ca
|
||||
|
||||
restrict -4 default kod notrap nomodify nopeer
|
||||
restrict -6 default kod notrap nomodify nopeer
|
||||
|
||||
{% elif 'role_ceph' in group_names %}
|
||||
server 10.60.0.251 iburst
|
||||
server 10.60.0.252 iburst
|
||||
server ceph1 iburst
|
||||
server ceph2 iburst
|
||||
server ceph3 iburst
|
||||
|
||||
restrict -4 default notrap nomodify
|
||||
restrict -6 default notrap nomodify
|
||||
|
||||
{% else %}
|
||||
server 10.100.0.251 burst
|
||||
server 10.100.0.252 burst
|
||||
|
||||
restrict -4 default notrap nomodify
|
||||
restrict -6 default notrap nomodify
|
||||
|
||||
{% endif %}
|
||||
restrict 127.0.0.1
|
||||
restrict ::1
|
54
common-debian/templates/etc/pam.d/sshd.j2
Normal file
54
common-debian/templates/etc/pam.d/sshd.j2
Normal file
@ -0,0 +1,54 @@
|
||||
# PAM configuration for the Secure Shell service
|
||||
# {{ ansible_managed }}
|
||||
|
||||
# Standard Un*x authentication.
|
||||
@include common-auth
|
||||
|
||||
# Disallow non-root logins when /etc/nologin exists.
|
||||
account required pam_nologin.so
|
||||
|
||||
# Uncomment and edit /etc/security/access.conf if you need to set complex
|
||||
# access limits that are hard to express in sshd_config.
|
||||
# account required pam_access.so
|
||||
|
||||
# Standard Un*x authorization.
|
||||
@include common-account
|
||||
|
||||
# SELinux needs to be the first session rule. This ensures that any
|
||||
# lingering context has been cleared. Without this it is possible that a
|
||||
# module could execute code in the wrong domain.
|
||||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
|
||||
|
||||
# Set the loginuid process attribute.
|
||||
session required pam_loginuid.so
|
||||
|
||||
# Create a new session keyring.
|
||||
session optional pam_keyinit.so force revoke
|
||||
|
||||
# Standard Un*x session setup and teardown.
|
||||
@include common-session
|
||||
|
||||
# Print the message of the day upon successful login.
|
||||
session optional pam_motd.so motd=/run/blse-motd.dynamic
|
||||
session optional pam_motd.so noupdate
|
||||
|
||||
# Print the status of the user's mailbox upon successful login.
|
||||
#session optional pam_mail.so standard noenv # [1]
|
||||
|
||||
# Set up user limits from /etc/security/limits.conf.
|
||||
session required pam_limits.so
|
||||
|
||||
# Read environment variables from /etc/environment and
|
||||
# /etc/security/pam_env.conf.
|
||||
session required pam_env.so # [1]
|
||||
# In Debian 4.0 (etch), locale-related environment variables were moved to
|
||||
# /etc/default/locale, so read that as well.
|
||||
session required pam_env.so user_readenv=1 envfile=/etc/default/locale
|
||||
|
||||
# SELinux needs to intervene at login time to ensure that the process starts
|
||||
# in the proper default security context. Only sessions which are intended
|
||||
# to run in the user's context should be run after this.
|
||||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
|
||||
|
||||
# Standard Un*x password updating.
|
||||
@include common-password
|
22
common-debian/templates/etc/postfix/main.cf.j2
Normal file
22
common-debian/templates/etc/postfix/main.cf.j2
Normal file
@ -0,0 +1,22 @@
|
||||
# Postfix main configuration for non-MTA hosts
|
||||
# {{ ansible_managed }}
|
||||
|
||||
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
|
||||
biff = no
|
||||
append_dot_mydomain = no
|
||||
readme_directory = no
|
||||
smtpd_use_tls=no
|
||||
|
||||
alias_maps = hash:/etc/postfix/aliases
|
||||
alias_database = hash:/etc/postfix/aliases
|
||||
mydestination =
|
||||
relayhost = {{ postfix_relay }}
|
||||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
|
||||
mailbox_size_limit = 0
|
||||
recipient_delimiter = +
|
||||
myorigin = $mydomain
|
||||
mydomain = {{ postfix_domain }}
|
||||
#inet_interfaces = 127.0.0.1,::1
|
||||
inet_interfaces = 127.0.0.1
|
||||
#inet_protocols = ipv4,ipv6
|
||||
inet_protocols = ipv4
|
7
common-debian/templates/etc/profile.d/w.sh.j2
Normal file
7
common-debian/templates/etc/profile.d/w.sh.j2
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Message of the day script to print active users
|
||||
# {{ ansible_managed }}
|
||||
|
||||
export PROCPS_FROMLEN=36 PROCPS_USERLEN=12
|
||||
w
|
19
common-debian/templates/etc/resolv.conf.j2
Normal file
19
common-debian/templates/etc/resolv.conf.j2
Normal file
@ -0,0 +1,19 @@
|
||||
# DNS resolver configuration
|
||||
# {{ ansible_managed }}
|
||||
|
||||
options timeout:1 attempts:3 rotate
|
||||
{% if 'remote' in group_names %}
|
||||
search {{ blsedomains_admindomain }}. {{ blsedomains_rootdomain }}.
|
||||
nameserver 8.8.8.8
|
||||
nameserver 8.8.4.4
|
||||
{% else %}
|
||||
{% if 'role_env' in group_names %}
|
||||
search {{ blsedomains_mandomain }}. {{ blsedomains_hostdomain }}. {{ blsedomains_rootdomain }}.
|
||||
{% elif 'physical' in group_names %}
|
||||
search {{ blsedomains_mandomain }}. {{ blsedomains_hostdomain }}. {{ blsedomains_admindomain }}. {{ blsedomains_rootdomain }}.
|
||||
{% else %}
|
||||
search {{ blsedomains_hostdomain }}. {{ blsedomains_admindomain }}. {{ blsedomains_rootdomain }}.
|
||||
{% endif %}
|
||||
nameserver {{ blsecluster_rns1v4 }}
|
||||
nameserver {{ blsecluster_rns2v4 }}
|
||||
{% endif %}
|
73
common-debian/templates/etc/rsyslog.conf.j2
Normal file
73
common-debian/templates/etc/rsyslog.conf.j2
Normal file
@ -0,0 +1,73 @@
|
||||
# Main rsyslog configuration
|
||||
# {{ ansible_managed }}
|
||||
|
||||
#### ####
|
||||
#### MODULES ####
|
||||
#### ####
|
||||
|
||||
module(load="imuxsock") # provides support for local system logging (e.g. via logger command)
|
||||
module(load="imklog") # provides kernel logging support (previously done by rklogd)
|
||||
|
||||
{% if 'role_log' in group_names %}
|
||||
module(load="imtcp" MaxSessions="1024")
|
||||
{% else %}
|
||||
$ModLoad imudp
|
||||
$UDPServerAddress ::1
|
||||
$UDPServerRun 514
|
||||
{% endif %}
|
||||
|
||||
#### ####
|
||||
#### GLOBAL DIRECTIVES ####
|
||||
#### ####
|
||||
|
||||
$PreserveFQDN on
|
||||
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
|
||||
|
||||
#### ####
|
||||
|
||||
$FileOwner root
|
||||
$FileGroup adm
|
||||
$FileCreateMode 0640
|
||||
$DirCreateMode 0755
|
||||
$Umask 0022
|
||||
|
||||
$WorkDirectory /var/spool/rsyslog
|
||||
#### RULES ####
|
||||
#### ####
|
||||
|
||||
ruleset(name="local") {
|
||||
kern.* /var/log/kern.log
|
||||
auth,authpriv.* /var/log/auth.log
|
||||
{% if not 'rpi' in group_names %}
|
||||
cron.* /var/log/cron.log
|
||||
daemon,user.* /var/log/daemon.log
|
||||
mail.* /var/log/mail.log
|
||||
local5.* /var/log/nginx.log
|
||||
local6.* /var/log/haproxy.log
|
||||
local7.* /var/log/boot.log
|
||||
*.info;kern,daemon,user,auth,authpriv,cron,mail,local6.none,local7.none /var/log/system.log
|
||||
{% endif %}
|
||||
{% if 'remote' in group_names %}
|
||||
# Send everything to central logserver (rsyslog)
|
||||
*.* @@log.{{ blsedomains_admindomain }}:514
|
||||
{% else %}
|
||||
# Send everything to central logserver (rsyslog)
|
||||
*.* @@log.{{ blsedomains_hostdomain }}:514
|
||||
{% endif %}
|
||||
}
|
||||
$DefaultRuleset local
|
||||
{% if 'role_log' in group_names %}
|
||||
|
||||
ruleset(name="remote") {
|
||||
kern.* /srv/log/kern.log
|
||||
daemon,user.* /srv/log/daemon.log
|
||||
auth,authpriv.* /srv/log/auth.log
|
||||
cron.* /srv/log/cron.log
|
||||
mail.* /srv/log/mail.log
|
||||
local5.* /srv/log/nginx.log
|
||||
local6.* /srv/log/haproxy.log
|
||||
local7.* /srv/log/boot.log
|
||||
*.info;kern,daemon,user,auth,authpriv,cron,mail,local6.none,local7.none /srv/log/system.log
|
||||
}
|
||||
input(type="imtcp" port="514" ruleset="remote")
|
||||
{% endif %}
|
8
common-debian/templates/etc/ssh/shosts.equiv.j2
Normal file
8
common-debian/templates/etc/ssh/shosts.equiv.j2
Normal file
@ -0,0 +1,8 @@
|
||||
# SSH remote allowed hosts
|
||||
# {{ ansible_managed }}
|
||||
|
||||
{% if hostbased_auth is defined and hostbased_auth %}
|
||||
{% for entry in hostbased_auth %}
|
||||
{{ entry }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
44
common-debian/templates/etc/ssh/ssh_config.j2
Normal file
44
common-debian/templates/etc/ssh/ssh_config.j2
Normal file
@ -0,0 +1,44 @@
|
||||
# Default SSH client configuration
|
||||
# {{ ansible_managed }}
|
||||
|
||||
Host *
|
||||
# ForwardAgent no
|
||||
# ForwardX11 no
|
||||
# ForwardX11Trusted yes
|
||||
# RhostsRSAAuthentication no
|
||||
# RSAAuthentication yes
|
||||
# PasswordAuthentication yes
|
||||
# EnableSSHKeysign yes
|
||||
# HostbasedAuthentication yes
|
||||
# GSSAPIAuthentication no
|
||||
# GSSAPIDelegateCredentials no
|
||||
# GSSAPIKeyExchange no
|
||||
# GSSAPITrustDNS no
|
||||
# BatchMode no
|
||||
# CheckHostIP yes
|
||||
# AddressFamily any
|
||||
# ConnectTimeout 0
|
||||
# StrictHostKeyChecking ask
|
||||
# IdentityFile ~/.ssh/identity
|
||||
# IdentityFile ~/.ssh/id_rsa
|
||||
# IdentityFile ~/.ssh/id_dsa
|
||||
# Port 22
|
||||
# Protocol 2,1
|
||||
# Cipher 3des
|
||||
# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
|
||||
# MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
|
||||
# EscapeChar ~
|
||||
# Tunnel no
|
||||
# TunnelDevice any:any
|
||||
# PermitLocalCommand no
|
||||
# VisualHostKey no
|
||||
# ProxyCommand ssh -q -W %h:%p gateway.example.com
|
||||
# PreferredAuthentications hostbased,pubkey
|
||||
SendEnv LANG LC_*
|
||||
HashKnownHosts no
|
||||
GSSAPIAuthentication yes
|
||||
GSSAPIDelegateCredentials no
|
||||
PubkeyAuthentication yes
|
||||
HostbasedAuthentication yes
|
||||
EnableSSHKeysign yes
|
||||
CheckHostIP no
|
8
common-debian/templates/etc/ssh/ssh_known_hosts.j2
Normal file
8
common-debian/templates/etc/ssh/ssh_known_hosts.j2
Normal file
@ -0,0 +1,8 @@
|
||||
# SSH remote allowed hosts
|
||||
# {{ ansible_managed }}
|
||||
|
||||
{% if hostbased_auth is defined and hostbased_auth %}
|
||||
{% for entry in hostbased_auth %}
|
||||
{{ hostvars[entry]['ansible_hostname'] }},{{ hostvars[entry]['ansible_fqdn'] }},{{ hostvars[entry]['inventory_hostname'] }} ssh-ed25519 {{ hostvars[entry]['ansible_ssh_host_key_ed25519_public'] }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
40
common-debian/templates/etc/ssh/sshd_config.j2
Normal file
40
common-debian/templates/etc/ssh/sshd_config.j2
Normal file
@ -0,0 +1,40 @@
|
||||
# Main SSH daemon configuraton
|
||||
# {{ ansible_managed }}
|
||||
|
||||
Port 22
|
||||
ListenAddress ::
|
||||
ListenAddress 0.0.0.0
|
||||
Protocol 2
|
||||
HostKey /etc/ssh/ssh_host_ed25519_key
|
||||
HostKey /etc/ssh/ssh_host_rsa_key
|
||||
SyslogFacility AUTH
|
||||
LogLevel INFO
|
||||
LoginGraceTime 30
|
||||
UsePAM yes
|
||||
StrictModes yes
|
||||
X11Forwarding no
|
||||
PrintMotd no
|
||||
PrintLastLog yes
|
||||
TCPKeepAlive yes
|
||||
AcceptEnv LANG LC_*
|
||||
|
||||
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
|
||||
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
|
||||
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com,hmac-sha1,hmac-sha1-96,hmac-md5,hmac-md5-96
|
||||
|
||||
PubkeyAuthentication yes
|
||||
PermitEmptyPasswords no
|
||||
ChallengeResponseAuthentication no
|
||||
PasswordAuthentication no
|
||||
{% if 'role_hv' in group_names %}
|
||||
HostbasedAuthentication yes
|
||||
HostbasedUsesNameFromPacketOnly yes
|
||||
IgnoreRhosts no
|
||||
PermitRootLogin yes
|
||||
{% else %}
|
||||
HostbasedAuthentication no
|
||||
IgnoreRhosts yes
|
||||
PermitRootLogin no
|
||||
{% endif %}
|
||||
|
||||
Subsystem sftp /usr/lib/openssh/sftp-server -f AUTH -l INFO
|
19
common-debian/templates/etc/sudoers.j2
Normal file
19
common-debian/templates/etc/sudoers.j2
Normal file
@ -0,0 +1,19 @@
|
||||
# sudoers configuraton; per-host declarations go in /etc/sudoers.d
|
||||
# {{ ansible_managed }}
|
||||
|
||||
Defaults env_reset
|
||||
Defaults mail_badpass
|
||||
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
Cmnd_Alias BACKUPS = /usr/bin/rsync, /var/backups/timestamp.sh
|
||||
|
||||
root ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
backup ALL=(root) NOPASSWD: BACKUPS
|
||||
deploy ALL=(ALL:ALL) NOPASSWD: /bin/sh
|
||||
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
|
||||
{% if ansible_local.moe_release is defined and ansible_local.moe_release.debian_version|int >= 11 %}
|
||||
@includedir /etc/sudoers.d
|
||||
{% else %}
|
||||
#includedir /etc/sudoers.d
|
||||
{% endif %}
|
55
common-debian/templates/etc/sysctl.d/moe.conf.j2
Normal file
55
common-debian/templates/etc/sysctl.d/moe.conf.j2
Normal file
@ -0,0 +1,55 @@
|
||||
# General sysctl parameters for MOE
|
||||
# {{ ansible_managed }}
|
||||
|
||||
{% if 'virtual' in group_names %}
|
||||
# Turn off swap entirely
|
||||
vm.swappiness = 100
|
||||
{% else %}
|
||||
# Lower swappiness
|
||||
vm.swappiness = 80
|
||||
{% endif %}
|
||||
|
||||
# Increase the cache pressure
|
||||
vm.vfs_cache_pressure = 200
|
||||
|
||||
# enable Spoof protection (reverse-path filter)
|
||||
# Turn on Source Address Verification in all interfaces to
|
||||
# prevent some spoofing attacks
|
||||
net.ipv4.conf.default.rp_filter = 1
|
||||
net.ipv4.conf.all.rp_filter = 1
|
||||
|
||||
# Ignore ICMP broadcasts
|
||||
net.ipv4.icmp_echo_ignore_broadcasts = 1
|
||||
|
||||
# Ignore bogus ICMP errors
|
||||
net.ipv4.icmp_ignore_bogus_error_responses = 1
|
||||
|
||||
# Do not accept ICMP redirects (prevent MITM attacks)
|
||||
net.ipv4.conf.all.accept_redirects = 0
|
||||
{% if not 'rpi' in group_names %}
|
||||
net.ipv6.conf.all.accept_redirects = 0
|
||||
{% endif %}
|
||||
|
||||
# Do not send ICMP redirects (we are not a router)
|
||||
net.ipv4.conf.all.send_redirects = 0
|
||||
|
||||
# Do not accept IP source route packets (we are not a router)
|
||||
net.ipv4.conf.all.accept_source_route = 0
|
||||
{% if not 'rpi' in group_names %}
|
||||
net.ipv6.conf.all.accept_source_route = 0
|
||||
{% endif %}
|
||||
|
||||
# Don't log Martian Packets
|
||||
net.ipv4.conf.all.log_martians = 0
|
||||
|
||||
# Explicit Congestion Notification (ECN)
|
||||
net.ipv4.tcp_ecn = 1
|
||||
|
||||
# number of seconds the kernel waits before rebooting on a panic
|
||||
kernel.panic = 60
|
||||
|
||||
# Panic on an OOPS
|
||||
kernel.panic_on_oops = 1
|
||||
|
||||
# Restrict dmesg
|
||||
kernel.dmesg_restrict = 1
|
7
common-debian/templates/etc/systemd/journald.conf.j2
Normal file
7
common-debian/templates/etc/systemd/journald.conf.j2
Normal file
@ -0,0 +1,7 @@
|
||||
# Journald configuration
|
||||
# {{ ansible_managed }}
|
||||
[Journal]
|
||||
Storage=persistent
|
||||
ForwardToSyslog=yes
|
||||
SystemMaxFiles=8
|
||||
RuntimeMaxFiles=8
|
18
common-debian/templates/usr/local/sbin/dpkg-cleanup.sh.j2
Executable file
18
common-debian/templates/usr/local/sbin/dpkg-cleanup.sh.j2
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
# dpkg-cleanup.sh - Remove obsolete packages and config files
|
||||
# {{ ansible_managed }}
|
||||
|
||||
# Phase 1 - purge `rc` packages
|
||||
PACKAGE_LIST=( $( dpkg --list | awk '/^rc/{ print $2 } /^ri/{ print $2 }' ) )
|
||||
apt purge -y ${PACKAGE_LIST[@]}
|
||||
|
||||
# Phase 2 - autoremove packages
|
||||
apt autoremove --purge -y
|
||||
|
||||
# Phase 3 - clean archives
|
||||
apt clean
|
||||
|
||||
# Phase 4 - find and remove obsolete config files
|
||||
OLD_FILES_LIST=( $( find /etc -type f -a \( -name '*.dpkg-*' -o -name '*.ucf-*' -o -name '*.update-*' \) 2>/dev/null ) )
|
||||
rm -f ${OLD_FILES_LIST[@]}
|
55
common-debian/templates/usr/local/sbin/kernel-cleanup.sh.j2
Executable file
55
common-debian/templates/usr/local/sbin/kernel-cleanup.sh.j2
Executable file
@ -0,0 +1,55 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# kernel-cleanup.sh - Remove obsolete packages and config files
|
||||
# {{ ansible_managed }}
|
||||
|
||||
# Determine the active running kernel
|
||||
RUNNING_KERNEL="$( uname -v | awk '{ print $4 }' )"
|
||||
|
||||
# Determine the list of installed kernels (latest is always last)
|
||||
INSTALLED_KERNELS=( $( dpkg -l | grep 'linux-image-[0-9]' | awk '{ print $3 }' | sort -n ) )
|
||||
echo ${INSTALLED_KERNELS}
|
||||
NUM_INSTALLED=${{ '{#' }}INSTALLED_KERNELS[@]}
|
||||
|
||||
if [[ ${NUM_INSTALLED} -le 1 ]]; then
|
||||
echo "A single kernel is installed, aborting cleanly."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
LATEST_KERNEL="${INSTALLED_KERNELS[-1]}"
|
||||
if [[ ${LATEST_KERNEL} == ${RUNNING_KERNEL} ]]; then
|
||||
force=""
|
||||
else
|
||||
force="--allow-remove-essential"
|
||||
fi
|
||||
|
||||
# Remove the latest kernel from the array
|
||||
NUM_REMOVABLE=$(( ${NUM_INSTALLED} - 1 ))
|
||||
REMOVABLE_KERNELS=( ${INSTALLED_KERNELS[@]:0:${NUM_REMOVABLE}} )
|
||||
|
||||
PURGE_PACKAGES=()
|
||||
for KERNEL in ${REMOVABLE_KERNELS[@]}; do
|
||||
PURGE_PACKAGES+=( $( dpkg -l | grep ${KERNEL} | grep -v 'linux-image-amd64\|linux-headers-amd64' | awk '{ print $2 }' ) )
|
||||
done
|
||||
|
||||
# Override the "linux-check-removal" script
|
||||
mv /usr/bin/linux-check-removal /usr/bin/linux-check-removal.orig
|
||||
echo -e '#!/bin/sh\necho "Overriding default linux-check-removal script!"\nexit 0' > /usr/bin/linux-check-removal
|
||||
chmod +x /usr/bin/linux-check-removal
|
||||
|
||||
# Remove the packages
|
||||
echo "Removing: ${PURGE_PACKAGES[@]}"
|
||||
apt-get purge --yes ${force} ${PURGE_PACKAGES[@]}
|
||||
|
||||
# Restore the "linux-check-removal" script
|
||||
mv /usr/bin/linux-check-removal.orig /usr/bin/linux-check-removal
|
||||
|
||||
# Make sure there is still a valid kernel installed (just in case something broke)
|
||||
if [[ $( dpkg -l | grep 'linux-image-[0-9]' | wc -l ) -lt 1 ]]; then
|
||||
echo "WARNING: NO KERNEL IS INSTALLED. THROWING ERROR AND ABORTING."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
update-grub
|
||||
|
||||
exit 0
|
75
common-debian/templates/usr/local/sbin/update-motd.sh.j2
Executable file
75
common-debian/templates/usr/local/sbin/update-motd.sh.j2
Executable file
@ -0,0 +1,75 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Update dynamic MOTD file
|
||||
# {{ ansible_managed }}
|
||||
|
||||
set -o errexit
|
||||
|
||||
TMPFILE=$(mktemp)
|
||||
TGTFILE=/run/blse-motd.dynamic
|
||||
{% if ansible_distribution_release == "jessie" %}
|
||||
BLSEVER="BLSE 2.x (Debian Jessie)"
|
||||
{% elif ansible_distribution_release == "stretch" %}
|
||||
BLSEVER="BLSE 2.1 (Debian Stretch)"
|
||||
{% elif ansible_distribution_release == "buster" %}
|
||||
BLSEVER="BLSE 2.2 (Debian Buster)"
|
||||
{% elif ansible_distribution_release == "bullseye" %}
|
||||
BLSEVER="BLSE 2.3 (Debian Bullseye)"
|
||||
{% elif ansible_distribution_release == "bookworm" %}
|
||||
BLSEVER="BLSE 2.4 (Debian Bookworm)"
|
||||
{% endif %}
|
||||
|
||||
echo >> $TMPFILE
|
||||
echo "\033[01;34mBoniface Labs Server Environment \033[01;36m${BLSEVER}\033[0m" >> $TMPFILE
|
||||
echo -n "> \033[01;32m$(hostname)\033[0m" >> $TMPFILE
|
||||
if test -f /etc/hostdesc; then
|
||||
echo " - $( cat /etc/hostdesc )" >> $TMPFILE
|
||||
else
|
||||
echo >> $TMPFILE
|
||||
fi
|
||||
echo -n "> " >> $TMPFILE
|
||||
|
||||
# Get virtual machine info from vhostmd if it exists
|
||||
VENDOR="$(/usr/sbin/dmidecode | grep Vendor | tr -d ' \t\n\r')"
|
||||
if [ "$VENDOR" = "Vendor:Bochs" ] || [ "$VENDOR" = "Vendor:SeaBIOS" ]; then
|
||||
hvhostname=$(/usr/sbin/vm-dump-metrics | grep -A1 HostName | awk -F'>' '{ if ($1 == " <value") print $2 }')
|
||||
hvvirtproductinfo=$(/usr/sbin/vm-dump-metrics | grep -A1 VirtProductInfo | awk -F'>' '{ if ($1 == " <value") print $2 }')
|
||||
if [ "$hvhostname" ]; then
|
||||
echo "\033[1;37mKVM virtual machine\033[0m on node \033[1;31m${hvhostname}\033[0m (${hvvirtproductinfo})" >> $TMPFILE
|
||||
else
|
||||
echo "\033[1;37mRemote KVM virtual machine\033[0m" >> $TMPFILE
|
||||
fi
|
||||
elif [ "$VENDOR" = 'Vendor:DigitalOcean' ]; then
|
||||
echo "\033[1;37mRemote KVM virtual machine\033[0m on \033[1;31mDigitalOcean\033[0m" >> $TMPFILE
|
||||
else
|
||||
# Are we a KVM hypervsor
|
||||
if [ "$(hostname | grep dcrhv)" ]; then
|
||||
echo "\033[1;37mRouter Hypervisor\033[0m on \033[1;31m$(/usr/sbin/dmidecode | grep -A1 'Base Board Information' | tail -1 | awk -F':' '{print $2}' | tr -s ' ' | sed 's/^ //' )\033[0m hardware" >> $TMPFILE
|
||||
# Are we a Ceph node?
|
||||
elif [ "$(hostname | grep ceph)" ]; then
|
||||
echo "\033[1;37mCeph Storage Node\033[0m on \033[1;31m$(/usr/sbin/dmidecode | grep -A1 'Base Board Information' | tail -1 | awk -F':' '{print $2}' | tr -s ' ' | sed 's/^ //' )\033[0m hardware" >> $TMPFILE
|
||||
# Are we a GPU node?
|
||||
elif [ "$(hostname | grep gpu)" ]; then
|
||||
echo "\033[1;37mGPU Processing Host\033[0m on \033[1;31m$(/usr/sbin/dmidecode | grep -A1 'Base Board Information' | tail -1 | awk -F':' '{print $2}' | tr -s ' ' | sed 's/^ //' )\033[0m hardware" >> $TMPFILE
|
||||
# Are we Base?
|
||||
elif [ "$(hostname | grep base)" ]; then
|
||||
echo "\033[1;37mHome Base\033[0m on \033[1;31m$(/usr/sbin/dmidecode | grep -A1 'Base Board Information' | tail -1 | awk -F':' '{print $2}' | tr -s ' ' | sed 's/^ //' )\033[0m hardware" >> $TMPFILE
|
||||
# Are we Env?
|
||||
elif [ "$(hostname | grep env)" ]; then
|
||||
echo "\033[1;37mEnvironmental Monitor\033[0m on \033[1;31mRaspberry Pi\033[0m hardware" >> $TMPFILE
|
||||
# Are we Kal?
|
||||
elif [ "$(hostname | grep kal)" ]; then
|
||||
echo "\033[1;37mVoice Control Node\033[0m on \033[1;31mRaspberry Pi\033[0m hardware" >> $TMPFILE
|
||||
# Are we IR?
|
||||
elif [ "$(hostname | grep ir)" ]; then
|
||||
echo "\033[1;37mInfared Control Node\033[0m on \033[1;31mRaspberry Pi\033[0m hardware" >> $TMPFILE
|
||||
# Otherwise, we're generic
|
||||
else
|
||||
echo "\033[1;37mGeneric server\033[0m on \033[1;31m$(/usr/sbin/dmidecode | grep -A1 'Base Board Information' | tail -1 | awk -F':' '{print $2}' | tr -s ' ' | sed 's/^ //' )\033[0m hardware" >> $TMPFILE
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "> $(/bin/uname -srvmo)" >> $TMPFILE
|
||||
|
||||
mv $TMPFILE $TGTFILE || rm $TMPFILE
|
||||
chmod 644 $TGTFILE
|
@ -0,0 +1,6 @@
|
||||
# backup user authorized_keys
|
||||
# {{ ansible_managed }}
|
||||
|
||||
{% for entry in backup_ssh_keys %}
|
||||
{{ entry.type }} {{ entry.key }} {{ entry.name }} {{ entry.date }}
|
||||
{% endfor %}
|
11
common-debian/templates/var/backups/timestamp.sh.j2
Executable file
11
common-debian/templates/var/backups/timestamp.sh.j2
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Writes timestamps on successful BackupPC completion and updates dynamic share inventory for this host
|
||||
# {{ ansible_managed }}
|
||||
|
||||
OK="$1"
|
||||
SHARE="$2"
|
||||
grep -F "${SHARE}" /var/backups/shares || echo "${SHARE}" >> /var/backups/shares
|
||||
if [[ ${OK} -eq 1 ]]; then
|
||||
/bin/date +%s > ${SHARE}/.backup
|
||||
fi
|
@ -0,0 +1,8 @@
|
||||
# deploy user authorized_keys
|
||||
# {{ ansible_managed }}
|
||||
|
||||
{% for user in admin_users %}
|
||||
{% for entry in user.ssh_keys %}
|
||||
{{ entry.type }} {{ entry.key }} {{ entry.name }} {{ entry.date }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
7
common-debian/templates/var/home/user/bash_logout.j2
Executable file
7
common-debian/templates/var/home/user/bash_logout.j2
Executable file
@ -0,0 +1,7 @@
|
||||
# BLSE 2.x bash_logout file
|
||||
# {{ ansible_managed }}
|
||||
|
||||
# when leaving the console clear the screen to increase privacy
|
||||
if [ "$SHLVL" = 1 ]; then
|
||||
[ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
|
||||
fi
|
149
common-debian/templates/var/home/user/bashrc.j2
Executable file
149
common-debian/templates/var/home/user/bashrc.j2
Executable file
@ -0,0 +1,149 @@
|
||||
#!/bin/bash
|
||||
|
||||
# BLSE 2.x bashrc file
|
||||
# {{ ansible_managed }}
|
||||
|
||||
#
|
||||
# GENERAL SETTINGS
|
||||
#
|
||||
|
||||
# Before anything, see if we're running interactively. If not, skip everything here.
|
||||
[[ $- == *i* ]] || return
|
||||
|
||||
# Ensure bash completion is enabled if installed
|
||||
if ! shopt -oq posix; then
|
||||
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
||||
. /usr/share/bash-completion/bash_completion
|
||||
elif [ -f /etc/bash_completion ]; then
|
||||
. /etc/bash_completion
|
||||
fi
|
||||
fi
|
||||
|
||||
# Some other tweaks
|
||||
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
|
||||
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
|
||||
debian_chroot=$(cat /etc/debian_chroot)
|
||||
fi
|
||||
|
||||
# Set history limits and values
|
||||
shopt -s cdspell
|
||||
shopt -s dirspell
|
||||
shopt -s dotglob
|
||||
shopt -s histreedit
|
||||
shopt -s histverify
|
||||
shopt -s histappend
|
||||
PROMPT_COMMAND="history -a;$PROMPT_COMMAND"
|
||||
HISTCONTROL=ignoreboth
|
||||
HISTSIZE=25000
|
||||
HISTFILESIZE=25000
|
||||
|
||||
#
|
||||
# BASH SETTINGS
|
||||
#
|
||||
|
||||
# Set a shiny Linux Mint-style PS1 with spaces for easy double-click-select
|
||||
git_branch() {
|
||||
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/git:\1 /'
|
||||
}
|
||||
export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\[\033[01;32m\]\H\[\033[01;34m\] \[\e[35m\]$(git_branch)\[\033[01;34m\]\w \$\[\033[00m\] '
|
||||
|
||||
# Sensible PATH (find things in *sbin* as non-root user)
|
||||
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:/usr/lib/check_mk_agent/plugins"
|
||||
|
||||
# Set PATH to include ~/Scripts if it exists
|
||||
if [ -d ~/Scripts ]; then
|
||||
export PATH=~/Scripts:$PATH
|
||||
fi
|
||||
|
||||
# Set editor to vim
|
||||
export EDITOR=/usr/bin/vim
|
||||
|
||||
# Force SCREEN to xterm due to Debian weirdness
|
||||
export SCREEN="xterm"
|
||||
|
||||
|
||||
#
|
||||
# ALIASES
|
||||
#
|
||||
|
||||
# Coloured command aliases
|
||||
alias ls='ls --color=always'
|
||||
alias dir='dir --color=always'
|
||||
alias vdir='vdir --color=always'
|
||||
alias grep='grep --color=always'
|
||||
alias fgrep='fgrep --color=always'
|
||||
alias egrep='egrep --color=always'
|
||||
alias xzgrep='xzgrep --color=always'
|
||||
alias less='less -r'
|
||||
|
||||
# Convenient ls aliases
|
||||
alias ll='ls -alh'
|
||||
alias la='ls -A'
|
||||
alias l='ls -lh'
|
||||
|
||||
# Always-sudo commands, because fuck typing sudo all the time
|
||||
alias service='sudo service'
|
||||
alias systemctl='sudo systemctl'
|
||||
alias journalctl='sudo journalctl'
|
||||
alias dmesg='sudo dmesg'
|
||||
alias apt='sudo apt'
|
||||
alias dpkg='sudo dpkg'
|
||||
alias find='sudo find'
|
||||
alias htop='sudo htop'
|
||||
alias powertop='sudo powertop'
|
||||
alias jnettop='sudo jnettop'
|
||||
alias wavemon='sudo wavemon'
|
||||
alias parted='sudo parted'
|
||||
alias fdisk='sudo fdisk'
|
||||
alias gdisk='sudo gdisk'
|
||||
alias chroot='sudo chroot'
|
||||
alias mount='sudo mount'
|
||||
alias umount='sudo umount'
|
||||
alias virsh='sudo virsh -c qemu:///system'
|
||||
alias ceph='sudo ceph'
|
||||
alias rbd='sudo rbd'
|
||||
alias mysql='sudo mysql'
|
||||
alias zpool='sudo zpool'
|
||||
alias zfs='sudo zfs'
|
||||
alias crm='sudo crm'
|
||||
|
||||
# Cool aliases
|
||||
alias cccp='sudo rsync -auv --progress'
|
||||
alias untmp='sudo umount /tmp/tmp.*{/*/*,/*,} 2>/dev/null'
|
||||
alias txz='tar -p --same-owner -I "xz -T4"'
|
||||
alias stxz='sudo tar -p --same-owner -I "xz -T4"'
|
||||
alias hatop='sudo hatop -s /var/lib/haproxy/admin.sock'
|
||||
alias zkcli='sudo /usr/share/zookeeper/bin/zkCli.sh -server $(hostname -s):2181'
|
||||
alias patronictl='sudo patronictl -c /etc/patroni/config.yml -d zookeeper://$(hostname -s):2181'
|
||||
alias repo='sudo reprepro -b /srv/debrepo'
|
||||
alias beet='sudo -u debian-deluged beet --config=/srv/deluged/config.beets/config.yaml'
|
||||
alias glances='sudo glances -t 5'
|
||||
{% if 'role_mon' in group_names %}
|
||||
alias icli='sudo -u monitor icli --status-file /omd/sites/monitor/tmp/nagios/status.dat --config /omd/sites/monitor/var/nagios/objects.cache -z \!o'
|
||||
|
||||
#
|
||||
# Show monitoring stats
|
||||
#
|
||||
|
||||
icli
|
||||
{% endif %}
|
||||
|
||||
#
|
||||
# SOURCE OTHER SCRIPTS
|
||||
#
|
||||
|
||||
if [[ -d ~/.bashrc.d ]]; then
|
||||
for script in ~/.bashrc.d/*; do
|
||||
. "$script"
|
||||
done
|
||||
fi
|
||||
|
||||
#
|
||||
# NICE AND CLEAN
|
||||
#
|
||||
|
||||
echo
|
||||
|
||||
#
|
||||
# END OF FILE
|
||||
#
|
25
common-debian/templates/var/home/user/config/htop/htoprc.j2
Normal file
25
common-debian/templates/var/home/user/config/htop/htoprc.j2
Normal file
@ -0,0 +1,25 @@
|
||||
# htop config file
|
||||
# {{ ansible_managed }}
|
||||
fields=0 48 17 18 38 39 40 2 46 47 49 1
|
||||
sort_key=46
|
||||
sort_direction=0
|
||||
hide_threads=0
|
||||
hide_kernel_threads=0
|
||||
hide_userland_threads=0
|
||||
shadow_other_users=0
|
||||
show_thread_names=1
|
||||
highlight_base_name=1
|
||||
highlight_megabytes=1
|
||||
highlight_threads=1
|
||||
tree_view=0
|
||||
header_margin=1
|
||||
detailed_cpu_time=1
|
||||
cpu_count_from_zero=0
|
||||
update_process_names=1
|
||||
account_guest_in_cpu_meter=1
|
||||
color_scheme=0
|
||||
delay=15
|
||||
left_meters=LeftCPUs2 Blank CPU Blank Blank Memory Swap
|
||||
left_meter_modes=1 2 1 2 2 1 1
|
||||
right_meters=RightCPUs2 Blank LoadAverage Tasks Blank Hostname Clock Uptime Blank
|
||||
right_meter_modes=1 2 2 2 2 2 2 2 2
|
16
common-debian/templates/var/home/user/profile.j2
Normal file
16
common-debian/templates/var/home/user/profile.j2
Normal file
@ -0,0 +1,16 @@
|
||||
# {{ ansible_managed }}
|
||||
|
||||
EDITOR=/usr/bin/vim
|
||||
|
||||
# if running bash
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
# include .bashrc if it exists
|
||||
if [ -f "$HOME/.bashrc" ]; then
|
||||
. "$HOME/.bashrc"
|
||||
fi
|
||||
fi
|
||||
|
||||
# set PATH so it includes user's private bin if it exists
|
||||
if [ -d "$HOME/bin" ] ; then
|
||||
PATH="$HOME/bin:$PATH"
|
||||
fi
|
@ -0,0 +1,6 @@
|
||||
# administrative shell user authorized_keys ({{ item.name }})
|
||||
# {{ ansible_managed }}
|
||||
|
||||
{% for entry in item.ssh_keys %}
|
||||
{{ entry.type }} {{ entry.key }} {{ entry.name }} {{ entry.date }}
|
||||
{% endfor %}
|
13
common-debian/templates/var/home/user/vimrc.j2
Normal file
13
common-debian/templates/var/home/user/vimrc.j2
Normal file
@ -0,0 +1,13 @@
|
||||
set showcmd
|
||||
set number
|
||||
set cursorline
|
||||
set autoindent
|
||||
set expandtab
|
||||
set tabstop=4
|
||||
set viminfo='100,<1000,s1000,h
|
||||
hi CursorLine term=bold cterm=bold guibg=Grey40
|
||||
syntax on
|
||||
set ruler
|
||||
set directory=~/.vim
|
||||
set mouse=
|
||||
autocmd Filetype gitcommit setlocal spell textwidth=72
|
Reference in New Issue
Block a user