summaryrefslogtreecommitdiff
path: root/guides/cloud/vps.org
blob: 537f5670806195d4bd6200825b98962fd7995ef3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
* 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
#+begin_src sh
sudo hostnamectl set-hostname $fqdn
sudo timedatectl set-timezone $tz
#+end_src

* Services
** Web server
Run ~sudo apt install nginx~; then, in
=/etc/nginx/sites-available/$FQDN=:
#+begin_src conf
server {
	listen 80;
	listen [::]:80;

	server_name $FQDN www.$FQDN;
	access_log /var/log/nginx/$FQDN.access.log;

	root /var/www/$FQDN/html;
	index index.html;

	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 <block>.
failregex = ^<HOST> \- \S+ \[\] \"(GET|POST|HEAD) <block> \S+\" 404 .+$
            ^ \[error\] \d+#\d+: \*\d+ (\S+ )?\"\S+\" (failed|is not found) \(2\: No such file or directory\), client\: <HOST>\, server\: \S*\, request: \"(GET|POST|HEAD) \/<block> \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~.
** Git server
*** SSH access
#+begin_src sh
$ sudo apt install git
$ sudo tee -a /etc/shells <<< $(which git-shell)
$ sudo adduser git --disabled-password --shell $(which git-shell)
$ sudo mkdir /srv/git
$ sudo chown git:git /srv/git
# For every new repo:
$ sudo -u git git init --bare --shared=group /srv/git/${repo}
#+end_src

*** Web mirror
With =/etc/nginx/sites-available/git.$FQDN=:
#+begin_src conf
server {
	listen 80;
	listen [::]:80;

	server_name git.$FQQN;
	access_log /var/log/nginx/git.$FQQN.access.log;

	root /usr/share/cgit;
	try_files $uri @cgit;

	location @cgit {
		include fastcgi_params;
		fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
		fastcgi_param PATH_INFO $uri;
		fastcgi_param QUERY_STRING $args;
		fastcgi_param HTTP_HOST $server_name;
		fastcgi_pass unix:/run/fcgiwrap.socket;
	}
}
#+end_src

And =/etc/cgitrc/=:
#+begin_src conf
css=/cgit.css
logo=/cgit.png

virtual-root=/
clone-prefix=http://git.$FQDN
clone-url=http://git.$FQDN/$CGIT_REPO_URL

enable-git-config=1
enable-http-clone=1
enable-index-owner=0
scan-path=/srv/git
#+end_src

In each repository:
- fill in =description=,
- fill =[cgit]= section in =config= (=hide=, =owner=, =section=).

Do:
#+begin_src sh
$ sudo apt install cgit fcgiwrap
$ ( cd /etc/sites-enabled/ && ln -s ../sites-avaiable/git.$FQDN . )
$ sudo systemctl restart nginx
# Make fail2ban notice the new log file.
$ sudo systemctl restart fail2ban
#+end_src