* Security ** Switch APT to HTTPS ~sudo sed -i 's/http:/https:/' /etc/apt/sources.list~ Granted, the repository signature provides enough protection; still, no sense in wasting bandwidth and CPU if someone is meddling. ** Tweak root access On OVH's Debian image: - The =root= account has no password. - =PermitRootLogin= defaults to =prohibit-password=: set it to =no=. ** Enable fail2ban ~lastb~ says there's about 4000 login attempts per day; that makes =/var/log/btmp= much bigger than it needs to be. Debian's fail2ban comes with a jail for ~sshd~, so it's just a matter of ~apt install fail2ban~. ** Tweak user accounts =debian= seems mildly popular among bots looking for valid usernames. Ideally I'd just rename the =debian= account, but renaming does not seem to be a very well-defined operation: ~usermod --login $name --move-home --home /home/$name debian~ gets partway there, but leaves a bunch of miscellany to take care of (e.g. sudoers). So instead, I'll - create my own user account: ~sudo adduser $name~ - add it to all groups =debian= belongs to: #+begin_src sh groups=$(groups | sed -e 's/ *debian *//' -e 's/ /,/g') sudo usermod --append --groups ${groups} ${name} #+end_src - only allow password authentication over SSH for this new user account: #+begin_src conf PasswordAuthentication no Match User … PasswordAuthentication yes #+end_src * System ** Hostname #+begin_src sh sudo hostnamectl set-hostname $fqdn #+end_src * Web server Run ~sudo apt install nginx~; then, in =/etc/nginx/sites-available/$FQDN=: #+begin_src conf server { listen 80; listen [::]:80; root /var/www/$FQDN/html; index index.html; server_name $FQDN www.$FQDN; access_log /var/log/nginx/$FQDN.access.log; location / { try_files $uri $uri/ =404; } } #+end_src Use one =access_log= file per site, to simplify analytics. Run ~sudo systemctl restart nginx~. ** fail2ban With the following files in =$HOME=: #+begin_src conf # nginx-botsearch.local [Init] block = \S*(php|wp-|wordpress|jenkins|hudson|sql|boaform)[^,]* [Definition] # Change from distro: just remove the leading slash before . failregex = ^ \- \S+ \[\] \"(GET|POST|HEAD) \S+\" 404 .+$ ^ \[error\] \d+#\d+: \*\d+ (\S+ )?\"\S+\" (failed|is not found) \(2\: No such file or directory\), client\: \, server\: \S*\, request: \"(GET|POST|HEAD) \/ \S+\"\, .*?$ # jail.local [nginx-http-auth] enabled = true [nginx-botsearch] enabled = true # Assume that each requests to $fqdn will be logged to "$fqdn.access.log". logpath = /var/log/nginx/*access.log #+end_src Then: #+begin_src sh sudo cp ~/nginx-botsearch.local /etc/fail2ban/filter.d/ sudo cp ~/jail.local /etc/fail2ban/ sudo systemctl restart fail2ban #+end_src Check how these rules fare against real bot searches with ~fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-botsearch.local~.