A clean slate
Starting fresh on a cloud server feels great—no clutter, no surprises, just you and a terminal.
This guide sets up a typical fullstack-ready environment: PostgreSQL, Redis, Node.js (with a side of Bun) or Deno, and good DevOps ergonomics with ZSH and some security basics.
In this blog, the commands without sudo
prefix are executed under the root user by default.
But once everything is ready, it may be safer to use your newly created user for future operations.
Basic essentials
First, get your system up to date and grab a few basics.
apt update
apt upgrade -y
apt install -y curl wget vim git screen
These are the bare minimums. You’ll be using them a lot.
Locking down SSH
Let’s tweak some basic security. Edit your SSH config:
vim /etc/ssh/sshd_config
Look for:
Port
– change it to something customPermitRootLogin
– switch this toprohibit-password
orno
Run this on your computer if you don’t have a SSH keypair:
ssh-keygen -t ed25519
cat .ssh/id_ed25519.pub
Copy the public key in the cat
output, create the file .ssh/authorized_keys
on your server and paste the key:
vim .ssh/authorized_keys
# Paste the key
# For example:
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL7Zk5I9svfvcKv0ZAMaCTD5MjW9wAHwl2I+DQboqd1Y username@yourcomputer
Then reload SSH:
systemctl restart ssh
reboot
Why? Because bots are real and they’re relentless.
A new user, a new hostname
vim /etc/hostname # change to a one you like
adduser newuser
usermod -aG newuser
Create a user to actually work with—best practice is to avoid root
as much as possible.
Shell vibes: ZSH + Oh My Zsh
For a friendlier shell:
apt install zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Then for your new user:
su newuser
chsh -s $(which zsh)
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Update your .zshrc
:
vim ~/.zshrc
Add:
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="robbyrussell"
plugins=(
git
zsh-autosuggestions
zsh-syntax-highlighting
)
source $ZSH/oh-my-zsh.sh
alias ll='ls -alh'
alias la='ls -a'
alias c='clear'
Then install the extra plugins:
cd ~/.oh-my-zsh/custom/plugins
git clone https://github.com/zsh-users/zsh-syntax-highlighting
git clone https://github.com/zsh-users/zsh-autosuggestions
cd
source ~/.zshrc
A pleasant shell experience is underrated.
Basic brute-force protection (Fail2ban)
Install and configure:
apt install -y fail2ban
systemctl start fail2ban
systemctl enable fail2ban
Custom config:
vim /etc/fail2ban/jail.local
Paste this:
[sshd]
enabled = true
port = 37192
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 60
bantime = 3600
ignoreip = 127.0.0.1
Then:
systemctl restart fail2ban
This helps keep SSH brute-force attempts at bay.
PostgreSQL
Add the PostgreSQL repo:
sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
apt update
apt install postgresql-17
Then start and enable:
systemctl start postgresql
systemctl enable postgresql
Configure:
su - postgres
psql
In the prompt:
ALTER USER postgres WITH PASSWORD 'password';
CREATE USER user; -- Change it to a username you like
ALTER USER user WITH PASSWORD 'password';
\q
Then:
systemctl restart postgresql
Now your DB is ready.
Redis
Simple and solid key-value store:
apt install -y redis-server
systemctl start redis-server
systemctl enable redis-server
Nginx
Web server + reverse proxy:
apt install -y nginx
systemctl start nginx
systemctl enable nginx
You’ll set up actual sites/configs later, but this gets you going.
Bun & Deno
Two modern runtimes worth having.
su newuser
sudo apt install unzip
sudo curl -fsSL https://deno.land/install.sh | sh
sudo curl -fsSL https://bun.sh/install | bash
They play nicely together.
UFW – Because default deny is your friend
Enable and configure:
systemctl start ufw
systemctl enable ufw
ufw enable
Then allow only what you need:
ufw allow 80 # HTTP
ufw allow 443 # HTTPS
ufw allow 22 # Change it to the custom SSH port you specified
Final thoughts
This setup doesn’t cover everything, but it gives you a sane, secure, and solid foundation to build on. From here, you can layer on Docker, CI/CD, SSL with Let’s Encrypt, and deploy your apps however you like.