Vps setup smk
VPS Setup Redacted (smk)π
Assuming you got root password from some vnc console in freshly installed VPS. Letβs setup.
Setup Localeπ
Upgrade Systemπ
Install Basic Toolsπ
Add user & grant sudoπ
user=smk
adduser $user
# grant sudo
usermod -a $user -G sudo
# add basic authorized keys
cd /home/$user
mkdir -p .ssh
chmod 700 .ssh
echo "YOUR_KEY" > .ssh/authorized_keys
chown -R $user:$user /home/$user
# try now ssh thru this user
SUDO without passwordπ
Create a file named 90-cloud-init-users
.
Put following text in it.
now copy this file to /etc/sudoers.d
Warning : This step if not done properly can brick the box!
Also do not edit the file once its in directory. This may also brick the box. Safest way is to edit is somewhere else and then copy result into the directory in question
Harden Securityπ
This sets up our box in safe state to use. Disable RootLogin as well if you want extra security.
Setting up fail2banπ
sudo apt install fail2ban sendmail-bin sendmail
# you can edit this .local because it overrides the default conf
cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# to view your chain traffic drop configuration
iptables -L f2b-sshd -v -n --line-numbers
# to delete a rule applied to an IP address
iptables -D chain rulenum
# some jail settings all things are pretty well documented and we care about these
# https://www.linode.com/docs/guides/using-fail2ban-to-secure-your-server-a-tutorial/
ignoreip = 127.0.0.1/8 123.45.67.89
bantime = 600
findtime = 600
maxretry = 3
# to check status
fail2ban-client status
Setup DNSπ
TODO : Add domain setup steps here before
NOTE : if your domain hostname is set but domain doesnβt point the server then you will always get an error regarding resolv.conf referring to host not found. To fix make sure hostname domain actually points the server you are setting up a dns.
# replace the default DNS generated by solus VM in Racknerd
echo "nameserver 127.0.0.1" > /tmp/resolv.conf
cp /tmp/resolv.conf /etc/resolv.conf
# lock the file, you can't edit it unless you do chattr -i
chattr +i /etc/resolv.conf
# note backup contens of resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
# install dnsmasq
sudo apt-get install dnsmasq
# put the following text in /etc/dnsmasq.conf
echo "all-servers
cache-size=10000
log-queries
interface=lo
no-resolv
address=/bacon.eggs/2.3.4.5
server=208.67.220.220 # OpenDNS
server=8.8.8.8 # Google
server=1.1.1.1" > /tmp/dnsmasq.conf
cp /tmp/dnsmasq.conf /etc/dnsmasq.conf
dnsmasq
is a caching DNS server. To flush the cache, restart the dnsmasq
service.
Setup Hostnameπ
Generate dhparam.pem
π
Execute the following command and wait for it to finish. For a high-end box, use 4096 here instead of 2048. Donβt try to use 4096 on a low-end or medium-level box.
Subsequent to completion, check the output and confirm that no errors occurred.
cat /tmp/dhparam.log
Then :
This is required for setting up ssl certs for websites.
Setup Ngnixπ
# install nginx
sudo apt-get install nginx
# visit your domain/ip that points to box and you should be greeted with nginx page
More on this Page : Pre-requiste
See Also :
Setting up source pathsπ
Create a text file /etc/profile.d/smkbin.sh
containing :
NOTE : Donβt use #!/bin/bash -e
here.
for dir in \
/opt/minetest/mtbin \
/opt/minetest/smkbin \
/opt/smkbin
do
if [ -d $dir ]; then PATH=$dir:$PATH; fi
done
This file needs to be readable, but it doesnβt need to be executable.
Edit secure_path
setting in etc/sudoers
to prepend directories from preceding scripts which exists. Note use visudo
to edit the file.π
Log-out and back in. You can now add useful scripts and tools to the two new directories.
Applicationπ
Installing golangπ
#!/bin/bash -e
mkdir -p /opt/
cd /opt/
rm -fr go golang
GOBALL=go1.21.6.linux-amd64.tar.gz
wget -c https://dl.google.com/go/$GOBALL
tar zxf $GOBALL
rm $GOBALL
mv go golang
mkdir -p /opt/smkbin/
ln -nsf /opt/golang/bin/go /opt/smkbin/
Installing legoπ
#!/bin/bash -e
export GOPATH=/tmp/gobuild
GOPROG=$GOPATH/lego/dist/lego
rm -fr $GOPATH
mkdir -p $GOPATH
cd $GOPATH
git clone https://github.com/go-acme/lego.git
cd lego
make build
strip $GOPROG
# upx --lzma $GOPROG # for some reason upx is not packaged for bookworm
mv $GOPROG /opt/smkbin/
rm -fr $GOPATH
Set up node
, npm
and yarn
π
NOTE: Installs python3, gcc, g++ as well
#!/bin/bash -e
apt-get install curl software-properties-common -y
curl -sL https://deb.nodesource.com/setup_21.x | sudo bash -
apt-get update
apt-get install gcc g++ make nodejs -y
LINK="https://dl.yarnpkg.com/debian"
curl -sL $LINK/pubkey.gpg | sudo apt-key add -
echo "deb $LINK/ stable main" | \
sudo tee /etc/apt/sources.list.d/yarn.list
apt-get update
apt-get -y install yarn
Installing Docker on VPSπ
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# managing docker as non root user
$USER=smk
sudo groupadd docker
sudo usermod -aG docker $USER
# refresh group
newgrp docker
# test docker run hello-world
# NOTE : fix .docker dir due to previous root runs if you get config errors
sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
sudo chmod g+rwx "$HOME/.docker" -R
Installing PHPπ
NOTES: Manually building binary : link
Add more PHP featureπ
NOTE : If nginx is not booting up due to port bind already in use, most likely its apache2 running disable it.
#!/bin/bash -e
apt-get install \
libmcrypt-dev \
php-apcu php-bcmath php-cli php-common \
php-curl php-dev php-fpm php-gd \
php-imagick php-intl php-json php-ldap \
php-mbstring php-mysql php-pear php-readline \
php-redis php-soap php-sqlite3 \
php-xml php-xmlrpc php-zip
# note : php-smbclient is not working
pecl channel-update pecl.php.net
pecl install channel://pecl.php.net/mcrypt-1.0.2
Installing ntfπ
# refer https://github.com/hrntknr/ntf
sudo curl -L https://github.com/hrntknr/ntf/releases/download/v1.0.1/ntf-x86_64-unknown-linux-gnu -o /usr/local/bin/ntf
sudo chmod +x /usr/local/bin/ntf
echo -e 'backends: ["pushover"]\npushover: {"user_key": "t0k3n"}' > ~/.ntf.yml
ntf send test
ntf send -t BOX_SAYS_HELLO hello from box
Alert on Reboot using ntf (systemd: donβt hate me)π
touch /lib/systemd/system/reboot_ntf.service
echo "[Unit]
Description=ntf reboot script
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/bin/bash -c 'sleep 2 && /usr/local/bin/ntf send -t REBOOT minetest.in just rebooted! > /var/log/reboot_ntf.log 2>&1'
Type=oneshot
RemainAfterExit=true
Environment=HOME=/root/
[Install]
WantedBy=multi-user.target" > /lib/systemd/system/reboot_ntf.service
sudo systemctl enable reboot_ntf.service
sudo systemctl restart reboot_ntf.service
sudo chmod 644 /lib/systemd/system/reboot_ntf.service
# To create a generic service
# systemctl enable reboot_ntf.service
Create a Backup (rclone-pcloud Setup)π
Installing rcloneπ
sudo apt-get install unzip -y
curl -O https://downloads.rclone.org/rclone-current-linux-amd64.zip
unzip rclone-current-linux-amd64.zip
cd rclone-*-linux-amd64
# copy the binary
sudo cp rclone /opt/smkbin
sudo chown root:root /opt/smkbin/rclone
sudo chmod 755 /opt/smkbin/rclone
# install man page
sudo mkdir -p /usr/local/share/man/man1
sudo cp rclone.1 /usr/local/share/man/man1/
sudo mandb
# configure rclone
rclone config
# remote config for headless server : https://rclone.org/remote_setup/
# NOTE : choose advance config because pcloud has two regions
# so pass all default except region select it correctly
# testing if rclone works for remote name : pcloud
rclone lsd pcloud:
Backup Scriptπ
#!/bin/bash
# /*
# * --------------------------------------------------------------------
# * @file pcloud-bkp
# * @brief A simple backup util for pcloud
# * @author smk ([email protected])
# * @version 20221129
# * @license BSD3
# * @bugs No known bugs
# * --------------------------------------------------------------------
# */
set -e
set -o pipefail
REMOTE_NAME="pcloud:vps_bkp/minetest.in"
RCLONE_BIN="/opt/smkbin/rclone"
WHOAMI=$(whoami)
if [ "@$WHOAMI" != "@root" ]; then
echo "Error: Must be run as root"
exit 1
fi
# Check if required binaries exist
check_binaries() {
for bin in "$@"; do
if ! command -v "$bin" &> /dev/null; then
echo "Error: $bin not found. Please install it."
exit 1
fi
done
}
check_binaries tar pv "$RCLONE_BIN"
backup_dirs=("etc" "home" "root" "var/www" "opt")
#backup_dirs=("etc" "home/smk" "root" "var/www" "usr/local/bin" "usr/local/sbin" "opt")
bkp_dir="/tmp/bkp_$(date +"%Y%m%d")"
mkdir -p "${bkp_dir}"
pushd /
for i in "${!backup_dirs[@]}"; do
# bkp_name=$(basename "${backup_dirs[i]}")
echo "$bkp_name"
echo "Starting tar of ${backup_dirs[$i]} ..."
tar czf "${bkp_dir}/${backup_dirs[$i]//\//_}.tgz" --directory="/" "${backup_dirs[$i]}"
# tar czf - "${backup_dirs[$i]//_//}" -P | pv -s $(du -sb "/${backup_dirs[$i]//_//}" | awk '{print $1}') | gzip > "${bkp_dir}/${backup_dirs[$i]}.tgz"
echo "Done tar of ${backup_dirs[$i]}"
done
popd
echo "Created backups at : ${bkp_dir}"
echo "----------------BKP------------------"
du -sh "${bkp_dir}"/* | sort -h
# Uncomment the following lines if you are ready to use rclone
echo "--------------- RCLONE ---------------"
bkp_name=$(basename ${bkp_dir})
"${RCLONE_BIN}" copy "${bkp_dir}" "${REMOTE_NAME}/${bkp_name}" -P -v
echo "--------------- Cleanup --------------"
rm -rf ${bkp_dir}
Create a cron jobπ
# you could wrap above script in ntfy and then setup a cron job
# open crontab file
crontab -e
# crontab for monthly execution
#0 0 1 * * /opt/smkbin/pcloud-bkp or
0 0 1 * * ntf -t MONTHLY_BACKUP done /opt/smkbin/pcloud-bkp
Installing portainer & dockgeπ
Create compose.yml
in the portainer directory
# be careful when setting up proxy_pass as it decides the uri_scheme traffic will be served on
# use https://127.0.0.1:6789/ if that is mapped inside container to 9443
version: "3.3"
services:
portainer-ce:
ports:
- 8000:8000
# - 6789:9000 : Note use this for serving portainer on HTTP
- 9443:9443 # This is for HTTPS port
container_name: portainer
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
image: portainer/portainer-ce:latest
volumes:
portainer_data: {}
networks: {}
Setting up dockgeπ
version: "3.8"
services:
dockge:
image: louislam/dockge:1
restart: unless-stopped
ports:
- 5678:5001
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- /home/docker/dockge:/home/docker/dockge
environment:
# Tell Dockge where to find the stacks
- DOCKGE_STACKS_DIR=/home/docker/dockge
Installing Postgresql & pg-adminπ
sudo apt-get update && sudo apt-get install postgresql postgresql-contrib
# note by default postgres is not exposed to anyone outside localhost
# and it should be left this way, don't use connection from outside the box
# verify above by accessing /etc/postgresql/x.x/main/pg_hba.conf
local all postgres peer local all all peer host all all 127.0.0.1/32 md5 host all all ::1/128 md5
# neither root nor smk can access the psql (its good that way)
sudo su - postgres
psql
# create user for yourself
CREATE USER smk WITH PASSWORD 'your_password';
CREATE DATABSE test_db;
GRANT CONNECT ON DATABASE test_db TO smk;
GRANT USAGE ON SCHEMA public TO smk;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO smk;
# we granted everything to smk, but be careful to grant to other users
\q # to quit
# as user smk try to login
psql -h localhost -U smk -d test_db
# yaml for db
version: '3.8'
services:
postgres:
image: postgres:latest
container_name: example-database
environment:
POSTGRES_DB: test_db
POSTGRES_USER: smk
POSTGRES_PASSWORD: example-database-password
ports:
- "5433:5432"
networks:
- pg-network
volumes:
- pg-data:/var/lib/postgresql/data
- ./initdb/:/docker-entrypoint-initdb.d/
pgadmin:
image: dpage/pgadmin4:latest
container_name: pg-admin
environment:
PGADMIN_DEFAULT_EMAIL: [email protected]
PGADMIN_DEFAULT_PASSWORD: admin_password_probably
ports:
- "5678:80"
networks:
- pg-network
networks:
pg-network:
volumes:
pg-data:
# create a script initdb/init-user-db.sh
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER "$POSTGRES_USER" WITH PASSWORD '$POSTGRES_PASSWORD';
CREATE DATABASE "$POSTGRES_DB" WITH OWNER "$POSTGRES_USER";
GRANT ALL PRIVILEGES ON DATABASE "$POSTGRES_DB" TO "$POSTGRES_USER";
EOSQL
Installing JupyterHubπ
docker run -d -p 5678:8000 --name jupyterhub jupyterhub/jupyterhub jupyterhub
# enter in container
docker exec -it jupyterhub bash
# then :
adduser test