memory-leaks

Still reachable: lots of words in many pages.
git clone https://git.kevinlegouguec.net/memory-leaks
Log | Files | Refs | README | LICENSE

vps.org (6237B)


      1 * Security
      2 ** APT
      3 *** Switch to HTTPS
      4 ~sudo sed -i 's/http:/https:/' /etc/apt/sources.list~
      5 
      6 Granted, the repository signature provides enough protection; still,
      7 no sense in wasting bandwidth and CPU if someone is meddling.
      8 ** fail2ban
      9 ~lastb~ says there's about 4000 login attempts per day; that makes
     10 =/var/log/btmp= much bigger than it needs to be.
     11 
     12 Debian's fail2ban comes with a jail for ~sshd~, so it's just a matter
     13 of ~apt install fail2ban~.
     14 ** Accounts
     15 *** =root=
     16 On OVH's Debian image:
     17 - The =root= account has no password.
     18 - =PermitRootLogin= defaults to =prohibit-password=: set it to =no=.
     19 *** =debian=
     20 Seems popular among bots looking for valid usernames.
     21 
     22 Ideally I'd just rename the =debian= account, but renaming is not a
     23 well-defined operation: ~usermod --login $name --move-home --home
     24 /home/$name debian~ gets partway there, but leaves a bunch of
     25 miscellany to take care of (e.g. sudoers).
     26 
     27 So instead,
     28 - create my own user account: ~sudo adduser 𝓊~
     29 - add it to all groups =debian= belongs to:
     30   #+begin_src sh
     31   groups=$(groups | tr ' ' '\n' | grep -v debian | paste -sd,)
     32   sudo usermod --append --groups ${groups} 𝓊
     33   #+end_src
     34 - only allow authentication over SSH for this user:
     35   #+begin_src conf
     36   AllowUsers 𝓊
     37   #+end_src
     38 - in case I ever change my mind about =AllowUsers=, at least limit
     39   password authentication to this user:
     40   #+begin_src conf
     41   PasswordAuthentication no
     42   Match User 𝓊
     43   	PasswordAuthentication yes
     44   #+end_src
     45 
     46 * System
     47 #+begin_src sh
     48 sudo hostnamectl set-hostname $DOMAIN
     49 sudo timedatectl set-timezone $tz
     50 #+end_src
     51 
     52 ** Console keyboard
     53 To avoid stammering at the OVH KVM console:
     54 #+begin_src sh
     55 sudo apt install console-setup keyboard-configuration
     56 # Pick "French - French (legacy, alt.)" for fr latin9.
     57 # To bring up this selection again:
     58 sudo dpkg-reconfigure keyboard-configuration
     59 #+end_src
     60 Then add =ctrl:nocaps= to =XKBOPTIONS= in =/etc/default/keyboard=,
     61 =setupcon= in the KVM console, reboot.
     62 * Services
     63 ** Web server
     64 Run ~sudo apt install nginx~; then, in
     65 =/etc/nginx/sites-available/$DOMAIN=:
     66 #+begin_src conf
     67 server {
     68 	listen 80;
     69 	listen [::]:80;
     70 
     71 	server_name $DOMAIN www.$DOMAIN;
     72 	access_log /var/log/nginx/$DOMAIN.access.log;
     73 
     74 	root /var/www/$DOMAIN/html;
     75 	index index.html;
     76 
     77 	location / {
     78 		try_files $uri $uri/ =404;
     79 	}
     80 }
     81 #+end_src
     82 Use one =access_log= file per site, to simplify analytics.
     83 
     84 Run ~sudo systemctl restart nginx~.
     85 *** fail2ban
     86 With the following files in =$HOME=:
     87 #+begin_src conf
     88 # nginx-botsearch.local
     89 [Init]
     90 
     91 block = \S*(php|wp-|wordpress|jenkins|hudson|sql|boaform)[^,]*
     92 
     93 [Definition]
     94 
     95 # Change from distro: just remove the leading slash before <block>.
     96 failregex = ^<HOST> \- \S+ \[\] \"(GET|POST|HEAD) <block> \S+\" 404 .+$
     97             ^ \[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+\"\, .*?$
     98 
     99 # jail.local
    100 [nginx-http-auth]
    101 enabled = true
    102 
    103 [nginx-botsearch]
    104 enabled = true
    105 # Assume that each requests to $DOMAIN will be logged to "$DOMAIN.access.log".
    106 logpath = /var/log/nginx/*access.log
    107 #+end_src
    108 
    109 Then:
    110 #+begin_src sh
    111 sudo cp ~/nginx-botsearch.local /etc/fail2ban/filter.d/
    112 sudo cp ~/jail.local /etc/fail2ban/
    113 sudo systemctl restart fail2ban
    114 #+end_src
    115 
    116 Check how these rules fare against real bot searches with:
    117 #+begin_src sh
    118 fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-botsearch.local
    119 #+end_src
    120 
    121 *** HTTPS
    122 #+begin_src sh
    123 sudo apt install certbot python3-certbot-nginx
    124 sudo certbot --nginx -d $DOMAIN www.$DOMAIN
    125 sudo systemctl reload nginx
    126 #+end_src
    127 
    128 ** Git server
    129 *** SSH access
    130 #+begin_src sh
    131 sudo apt install git
    132 sudo tee -a /etc/shells <<< $(which git-shell)
    133 sudo adduser git --disabled-password --shell $(which git-shell)
    134 sudo mkdir /srv/git
    135 sudo chown git:git /srv/git
    136 # For every new repo:
    137 sudo -u git git init --bare --shared=group /srv/git/${repo}
    138 #+end_src
    139 
    140 *** Web mirror
    141 With =/etc/nginx/sites-available/git.$DOMAIN=:
    142 #+begin_src conf
    143 server {
    144 	listen 80;
    145 	listen [::]:80;
    146 
    147 	server_name git.$DOMAIN;
    148 	access_log /var/log/nginx/git.$DOMAIN.access.log;
    149 
    150 	root /usr/share/cgit;
    151 	try_files $uri @cgit;
    152 
    153 	location @cgit {
    154 		include fastcgi_params;
    155 		fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
    156 		fastcgi_param PATH_INFO $uri;
    157 		fastcgi_param QUERY_STRING $args;
    158 		fastcgi_param HTTP_HOST $server_name;
    159 		fastcgi_pass unix:/run/fcgiwrap.socket;
    160 	}
    161 }
    162 #+end_src
    163 
    164 And =/etc/cgitrc/=:
    165 #+begin_src conf
    166 css=/cgit.css
    167 logo=/cgit.png
    168 
    169 virtual-root=/
    170 # Change to https:// after setting up certbot:
    171 clone-url=http://git.$DOMAIN/$CGIT_REPO_URL
    172 snapshots=tar.xz
    173 
    174 enable-git-config=1
    175 enable-http-clone=1
    176 enable-index-owner=0
    177 
    178 scan-path=/srv/git
    179 #+end_src
    180 
    181 In each repository:
    182 - fill in =description=,
    183 - fill =[cgit]= section in =config= (=hide=, =owner=, =section=).
    184 
    185 Do:
    186 #+begin_src sh
    187 sudo apt install cgit fcgiwrap
    188 ( cd /etc/sites-enabled/ && ln -s ../sites-avaiable/git.$DOMAIN . )
    189 sudo systemctl restart nginx
    190 # Make fail2ban notice the new log file.
    191 sudo systemctl restart fail2ban
    192 #+end_src
    193 
    194 **** "Idle" vs default branch
    195 cgit struggles to guess what to print for the "Idle" column on the
    196 index page when the default branch is not "master".  [[https://lists.zx2c4.com/pipermail/cgit/2020-August/004515.html][Workarounds]]:
    197 
    198 - set =repo.defbranch=,
    199 - update =agefile= with [[https://git.zx2c4.com/cgit/tree/contrib/hooks/post-receive.agefile][a post-receive hook]].
    200 ** CGI
    201 I like the idea of [[https://en.wikipedia.org/wiki/Common_Gateway_Interface#Using_CGI_scripts][CGI "scripts"]], i.e. having the web server fire a
    202 program to handle requests:
    203 
    204 - URI bits are passed through environment variables and stdin;
    205 - the program spits the page on stdout.
    206 
    207 Had some fun toying with Python's ~cgi~ module; sadly though the
    208 project has [[https://peps.python.org/pep-0594/#cgi][decided to deprecate it]].  The docs [[https://docs.python.org/3.11/library/cgi.html][suggest some migration
    209 paths]], and there's a [[https://pypi.org/project/legacy-cgi/][legacy-cgi package on PyPI]] if I really want to
    210 keep using it I guess.
    211 
    212 Also nginx has no support for CGI either, though their documentation
    213 explains how to combine their FastCGI support with ~fcgiwrap~ to
    214 enable CGI scripts.