336 lines
6.8 KiB
Markdown
336 lines
6.8 KiB
Markdown
# Server Setup
|
|
|
|
Debian 12 minimal installation, ensure the SSH server and standard system tools are included.
|
|
|
|
|
|
## Base Configuration
|
|
|
|
Internal hostname, replace "myhostname":
|
|
|
|
```
|
|
hostnamectl set-hostname myhostname
|
|
```
|
|
|
|
**/etc/hosts**
|
|
|
|
```
|
|
127.0.0.1 localhost
|
|
127.0.1.1 myhostname
|
|
```
|
|
|
|
Install packages:
|
|
|
|
```
|
|
apt-get update
|
|
|
|
echo "iptables-persistent iptables-persistent/autosave_v4 boolean true" | debconf-set-selections
|
|
echo "iptables-persistent iptables-persistent/autosave_v6 boolean true" | debconf-set-selections
|
|
echo "unattended-upgrades unattended-upgrades/enable_auto_updates boolean true" | debconf-set-selections
|
|
|
|
apt-get install curl sysstat unattended-upgrades iptables-persistent \
|
|
man less vim rsync bc net-tools git git-lfs sqlite3 strace sudo \
|
|
apparmor-utils rsyslog
|
|
```
|
|
|
|
Install packages without `recommends`:
|
|
|
|
```
|
|
apt-get install --no-install-recommends smem \
|
|
nginx nginx-core libnginx-mod-stream \
|
|
certbot python3-certbot-nginx
|
|
```
|
|
|
|
Set up services:
|
|
|
|
```
|
|
systemctl disable remote-fs.target rsync.service
|
|
systemctl enable sysstat unattended-upgrades netfilter-persistent
|
|
```
|
|
|
|
As needed:
|
|
|
|
```
|
|
apt-get update
|
|
apt-get full-upgrade
|
|
reboot
|
|
```
|
|
|
|
|
|
## User Setup
|
|
|
|
Add a login user:
|
|
|
|
```
|
|
export MYUSER="frankthetank"
|
|
useradd -m -d /home/${MYUSER} -s /bin/bash -g users -G sudo ${MYUSER}
|
|
passwd ${MYUSER}
|
|
|
|
mkdir -p /var/xyzzy/bin
|
|
chown -R ${MYUSER}: /var/xyzzy
|
|
```
|
|
|
|
If `ssh-copy-id` can't be used:
|
|
|
|
```
|
|
mkdir /home/${MYUSER}/.ssh
|
|
cp /root/.ssh/authorized_keys /home/${MYUSER}/.ssh/
|
|
chmod 0700 /home/${MYUSER}/.ssh
|
|
chmod 0600 /home/${MYUSER}/.ssh/authorized_keys
|
|
chown -R ${MYUSER}:users /home/${MYUSER}/.ssh
|
|
```
|
|
|
|
Disable root login:
|
|
|
|
```
|
|
_SCFG="/etc/ssh/sshd_config"
|
|
if $(grep -iEq '^PermitRootLogin[[:space:]]+yes' "${_SCFG}"); then
|
|
sed -i.bak -e 's/^PermitRootLogin.*/PermitRootLogin no/gi' "${_SCFG}"
|
|
else
|
|
sed -i.bak -e 's/^#PermitRootLogin.*/PermitRootLogin no/gi' "${_SCFG}"
|
|
fi
|
|
```
|
|
|
|
After confirming the change is correct:
|
|
|
|
```
|
|
systemctl restart sshd
|
|
```
|
|
|
|
Test logging in again as the user and sudo to root in another term.
|
|
|
|
|
|
## Server Configuration
|
|
|
|
Get rid of mouse in `vim`:
|
|
|
|
```
|
|
echo 'set mouse=' >> ~/.vimrc
|
|
```
|
|
|
|
Get rid of bracketed paste:
|
|
|
|
```
|
|
echo 'set enable-bracketed-paste Off' >> ~/.inputrc
|
|
```
|
|
|
|
Enable `sysstat`:
|
|
|
|
```
|
|
sed -i.bak -e 's|^ENABLED=".*"|ENABLED="true"|g' /etc/default/sysstat
|
|
```
|
|
|
|
Configure `unattended-upgrades`:
|
|
|
|
```
|
|
cp 02periodic /etc/apt/apt.conf.d/
|
|
```
|
|
|
|
Configure `iptables` and `ip6tables`:
|
|
|
|
```
|
|
cp rules.* /etc/iptables/
|
|
```
|
|
|
|
Configure tweaks:
|
|
|
|
```
|
|
mkdir /etc/systemd/journald.conf.d
|
|
mkdir /etc/systemd/system/nginx.service.d
|
|
cp sysctl.d/local.conf /etc/sysctl.d/
|
|
cp systemd/journald.conf.d/local.conf \
|
|
/etc/systemd/journald.conf.d/
|
|
cp systemd/system/nginx.service.d/override.conf \
|
|
/etc/systemd/system/nginx.service.d/
|
|
systemctl daemon-reload
|
|
```
|
|
|
|
|
|
## Fail2ban Setup
|
|
|
|
SSH jail:
|
|
|
|
```
|
|
apt-get install fail2ban
|
|
cp jail.local /etc/fail2ban/
|
|
systemctl enable --now fail2ban
|
|
```
|
|
|
|
Maintenance tasks:
|
|
|
|
```
|
|
cp dbpurge.sql /etc/fail2ban/
|
|
cp f2b-cleanup /etc/cron.weekly/
|
|
chown root:root /etc/cron.weekly/f2b-cleanup
|
|
chmod 0755 /etc/cron.weekly/f2b-cleanup
|
|
|
|
cp bin/jailstat.sh /var/xyzzy/bin/
|
|
```
|
|
|
|
|
|
## Nginx Setup
|
|
|
|
Gitea first-time setup is easier with nginx + SSL already working.
|
|
|
|
#### Basic Prep
|
|
```
|
|
cd /etc/nginx/modules-enabled
|
|
|
|
rm \
|
|
50-mod-http-geoip.conf \
|
|
50-mod-http-image-filter.conf \
|
|
50-mod-http-xslt-filter.conf \
|
|
50-mod-mail.conf \
|
|
70-mod-stream-geoip.conf
|
|
|
|
cp security.conf /etc/nginx/conf.d/
|
|
```
|
|
|
|
|
|
#### Site Prep
|
|
```
|
|
mkdir /var/xyzzy/html
|
|
cp html* /var/xyzzy/html/
|
|
|
|
cp xyzzy.ee.conf.bootstrap /etc/nginx/sites-available/xyzzy.ee.conf
|
|
cp xyzzy.fi.conf.bootstrap /etc/nginx/sites-available/xyzzy.fi.conf
|
|
cp git.xyzzy.ee.conf.bootstrap /etc/nginx/sites-available/git.xyzzy.ee.conf
|
|
|
|
cd /etc/nginx/sites-enabled
|
|
rm default
|
|
ln -s /etc/nginx/sites-available/xyzzy.ee.conf 00xyzzy.ee.conf
|
|
ln -s /etc/nginx/sites-available/xyzzy.fi.conf 01xyzzy.fi.conf
|
|
ln -s /etc/nginx/sites-available/git.xyzzy.ee.conf 02git.xyzzy.ee.conf
|
|
nginx -t
|
|
systemctl restart nginx
|
|
|
|
certbot --nginx -d xyzzy.ee,www.xyzzy.ee \
|
|
--agree-tos -m "hostmaster@xyzzy.ee" --no-eff-email \
|
|
--deploy-hook "systemctl reload nginx"
|
|
|
|
certbot --nginx -d xyzzy.fi,www.xyzzy.fi \
|
|
--agree-tos -m "hostmaster@xyzzy.fi" --no-eff-email \
|
|
--deploy-hook "systemctl reload nginx"
|
|
|
|
certbot --nginx -d git.xyzzy.ee \
|
|
--agree-tos -m "hostmaster@xyzzy.ee" --no-eff-email \
|
|
--deploy-hook "systemctl reload nginx"
|
|
|
|
cp xyzzy.ee.conf /etc/nginx/sites-available/xyzzy.ee.conf
|
|
cp xyzzy.fi.conf /etc/nginx/sites-available/xyzzy.fi.conf
|
|
cp git.xyzzy.ee.conf /etc/nginx/sites-available/git.xyzzy.ee.conf
|
|
nginx -t
|
|
systemctl restart nginx
|
|
```
|
|
|
|
|
|
## Gitea Setup
|
|
|
|
All content lives under `/var/xyzzy`:
|
|
|
|
```
|
|
cp bin/teaup.sh /var/xyzzy/bin/
|
|
cd /var/xyzzy/bin
|
|
|
|
export TVER="1.21.8"
|
|
curl -L --output-dir /var/xyzzy/bin --remote-name-all \
|
|
"https://github.com/go-gitea/gitea/releases/download/v${TVER}/gitea-${TVER}-linux-amd64" \
|
|
"https://github.com/go-gitea/gitea/releases/download/v${TVER}/gitea-${TVER}-linux-amd64.sha256"
|
|
|
|
sha256sum -c "gitea-${TVER}-linux-amd64.sha256"
|
|
chmod +x "gitea-${TVER}-linux-amd64"
|
|
ln -s "gitea-${TVER}-linux-amd64" gitea
|
|
```
|
|
|
|
Primary `git` user:
|
|
|
|
```
|
|
adduser \
|
|
--system \
|
|
--shell /bin/bash \
|
|
--gecos 'git' \
|
|
--group \
|
|
--disabled-password \
|
|
--home /var/xyzzy/git \
|
|
git
|
|
```
|
|
|
|
Gitea prep:
|
|
|
|
```
|
|
mkdir -p /var/xyzzy/gitea/{custom,data,log}
|
|
chown -R git:git /var/xyzzy/gitea/
|
|
chmod -R 750 /var/xyzzy/gitea/
|
|
mkdir -p /var/xyzzy/etc/gitea
|
|
chown root:git /var/xyzzy/etc/gitea
|
|
chmod 770 /var/xyzzy/etc/gitea
|
|
|
|
cp gitea.service /etc/systemd/system/
|
|
systemctl daemon-reload
|
|
```
|
|
|
|
Gitea init:
|
|
```
|
|
systemctl start gitea.service
|
|
( browser -> https://git.xyzzy.ee )
|
|
systemctl stop gitea.service
|
|
```
|
|
|
|
Gitea deploy: (app.ini needs secrets set)
|
|
|
|
```
|
|
cp custom/* /var/xyzzy/gitea/custom/
|
|
cp app.ini /var/xyzzy/etc/gitea/
|
|
chmod 750 /var/xyzzy/etc/gitea
|
|
chmod 640 /var/xyzzy/etc/gitea/app.ini
|
|
chown root:git /var/xyzzy/etc/gitea/app.ini
|
|
|
|
systemctl enable --now gitea.service
|
|
```
|
|
|
|
|
|
## AppArmor
|
|
|
|
```
|
|
cp apparmor.d/* /etc/apparmor.d/
|
|
systemctl restart apparmor.service
|
|
```
|
|
|
|
|
|
## Backup
|
|
|
|
See `teabak.sh`; prep: (HCPING needs set in script)
|
|
|
|
```
|
|
groupadd --system bkp
|
|
mkdir /var/xyzzy/backup
|
|
chmod 0750 /var/xyzzy/backup
|
|
chown git:bkp /var/xyzzy/backup
|
|
|
|
cp teaback.sh /var/xyzzy/bin/
|
|
chmod 0755 /var/xyzzy/bin/teabak.sh
|
|
|
|
cp teabak.service teabak.timer /etc/systemd/system/
|
|
systemctl daemon-reload
|
|
systemctl enable --now teabak.timer
|
|
```
|
|
|
|
Allow restricted backup user to rsync the data:
|
|
|
|
```
|
|
adduser \
|
|
--shell /bin/bash \
|
|
--gecos 'reposync' \
|
|
--ingroup bkp \
|
|
--disabled-password \
|
|
--home /home/reposync \
|
|
reposync
|
|
```
|
|
|
|
The "reposync" user has a restricted `.ssh/authorized_keys` like so:
|
|
|
|
```
|
|
command="/usr/bin/rrsync -ro /var/xyzzy/backup/",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict ssh-ed25519 ...
|
|
```
|
|
|
|
The `rrsync` script is part of the Debian `rsync` package
|
|
|