Preparing a New Server

July 8, 2026

The first login to a fresh server is where you set the foundation. Before installing services or deploying applications, you need a consistent baseline: correct time, a proper hostname, up-to-date packages, and a shell environment that doesn't fight you. The steps differ across distributions, but the goals are the same.

Setting the Timezone and NTP

A server with wrong time will break TLS certificate validation, log correlation, and cron schedules. Fix it first.

On Gentoo

Gentoo uses sntpd from net-misc/ntp for lightweight time synchronization on OpenRC systems.

echo "America/Chicago" > /etc/timezone
emerge --config sys-libs/timezone-data
emerge -av net-misc/ntp
rc-update add sntpd default
rc-service sntpd start

On Debian

Debian ships with systemd-timesyncd, which handles NTP out of the box.

timedatectl set-timezone America/Chicago
timedatectl set-ntp true
timedatectl status

Verify the NTP service is active. You should see NTP service: active in the output.

On Alpine

Alpine uses chrony, which also works well inside containers. The -x flag prevents chrony from stepping the clock, which matters in LXC/LXD environments where the host controls the hardware clock.

apk add chrony
rc-update add chronyd default
rc-service chronyd start

For containers specifically, edit /etc/chrony/chrony.conf and add:

makestep 1 -1

This allows chrony to adjust time gradually rather than stepping, which avoids clock jumps that confuse applications.

Setting the Hostname

A correct hostname matters for logging, mail delivery, and your own sanity when managing multiple servers.

On Gentoo

echo "myserver" > /etc/hostname
hostname myserver

On Debian

hostnamectl set-hostname myserver

On Alpine

echo "myserver" > /etc/hostname
hostname -F /etc/hostname

Cleaning Up the MOTD

Ubuntu and Debian ship with a dynamic MOTD that advertises services and shows system stats on every login. On a server you manage, this is noise. Remove or simplify it.

On Ubuntu, the default legal notice and dynamic MOTD scripts live in /etc/legal and /etc/update-motd.d/. To clean up:

rm -f /etc/legal

Replace the dynamic MOTD with a static one. Create /etc/motd with your hostname or any useful identifier, and remove or empty the scripts in /etc/update-motd.d/ if you don't want the login banner.

Updating the System

Before installing anything, bring the base system current. Each distribution has its own update workflow, and on Gentoo this can take significant time on a first sync.

On Gentoo

On a fresh Gentoo install, the portage tree may not exist yet. Check for it and sync if missing.

ls /var/db/repos/gentoo/profiles
# If missing:
emerge --sync

Once the tree is available, update the full system:

emerge --sync
emerge -uDN @world
emerge --depclean

The --depclean at the end removes packages that were pulled in as dependencies but are no longer needed. On a fresh system this is usually a no-op, but it's a good habit.

On Debian

apt update
apt upgrade -y

On Alpine

apk update
apk upgrade

Removing Bloatware

Fresh installs of Ubuntu in particular ship with packages and services you don't need on a server. Snap is the primary offender.

Removing Snap on Ubuntu

Snap adds latency to package management and runs background refresh services. Remove it and block reinstallation:

# Stop snap services
systemctl stop snapd.service snapd.socket snapd.seeded.service
systemctl disable snapd.service snapd.socket snapd.seeded.service

# Remove snap packages and daemon
apt purge snapd -y

# Remove leftover directories
rm -rf /snap /var/snap /var/lib/snapd /var/cache/snapd /root/snap

To prevent snap from being reinstalled as a dependency in the future, create an APT preference file:

/etc/apt/preferences.d/snapd.pref

Package: snapd
Pin: release *
Pin-Priority: -1

This sets the pin priority to -1, which tells APT to never install the package.

Disabling Ubuntu Pro Ads

Ubuntu shows advertising for Ubuntu Pro in apt output. Turn it off:

pro config set apt_news=false

Also remove the apt hook that triggers the ads:

rm -f /etc/apt/apt.conf.d/20apt-esm-hook.conf
ln -s /dev/null /etc/apt/apt.conf.d/20apt-esm-hook.conf

Symlinking to /dev/null prevents the file from being recreated on package updates.

Removing the Default Ubuntu User

Cloud images often create a default ubuntu user. If you're managing users yourself, remove it:

userdel -r ubuntu

Removing the Legal Notice

rm -f /etc/legal

On Alpine and Gentoo, there's no bloatware to remove. They ship minimal by design.

Creating Groups

Before configuring users, set up the groups they'll need. At minimum, create an sshuser group for controlling SSH access:

groupadd sshuser

This group will be referenced later in sshd_config via AllowGroups to restrict which users can log in over SSH.

Installing Bash on Alpine

Alpine ships with BusyBox ash as the default shell. If you want bash (and you probably do for consistency with your other servers):

apk add bash shadow bash-doc bash-completion findutils

Set bash as the default shell for root:

sed -i 's|^root:x:0:0:root:/root:/bin/ash|root:x:0:0:root:/root:/bin/bash|' /etc/passwd

Set bash as the default shell for all future users:

useradd -D -s /bin/bash

Installing Git

You'll need git for pulling configurations, managing dotfiles, and version-controlling anything you care about.

On Gentoo

emerge -av dev-vcs/git

On Debian

apt install -y git

On Alpine

apk add git

Set your global identity:

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Shell Configuration

A consistent shell environment across all your servers reduces cognitive overhead. The key files are .bashrc, .bash_profile, .bash_PS1, .bash_alias, and .dircolors.

The Bash Prompt

A color-coded prompt that distinguishes root from regular users prevents mistakes. Create ~/.bash_PS1:

if [[ ${EUID} == 0 ]] ; then
    PS1='\[\033[01;31m\]\h\[\033[01;34m\] \W \$\[\033[00m\] '
else
    PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
fi

Root gets a red hostname, regular users get green user@host. Both show the working directory in blue.

Aliases

Create ~/.bash_alias with shortcuts you'll use daily:

# ls
alias ls='ls --color=auto'
alias la="ls -alh"
alias lA="ls -Alh"
alias l1="ls -1h"

# navigation
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../../'

# grep
alias grep="grep --color=auto --text"
alias egrep='egrep --color=auto --text'
alias fgrep='fgrep --color=auto --text'
alias grep.nocomment='grep ^[^#]'

# screen
alias screen="export TERM=xterm; TERMINFO='/usr/share/terminfo/' /usr/bin/screen"
alias screen.sh="export TERM=xterm; TERMINFO='/usr/share/terminfo/' /usr/bin/screen -DR && exit"

# process info
alias psmem='ps auxf | sort -nr -k 4'
alias psmem10='ps auxf | sort -nr -k 4 | head -10'
alias pscpu='ps auxf | sort -nr -k 3'
alias pscpu10='ps auxf | sort -nr -k 3 | head -10'

# ssh
alias ssh.forget='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'

Directory Colors

The default blue-on-black for directories is unreadable on most terminals. Override it with white-on-blue by creating ~/.dircolors:

DIR 37;44
LINK 01;36
EXEC 01;32

For the full dircolors file including archive, image, text, and audio file colors, see the dircolors post.

Sourcing Everything from .bashrc

The .bashrc needs to source these files. Add this to the end of ~/.bashrc:

EDITOR='nano'

# directory colors
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
fi

# custom prompt
if [ -f ~/.bash_PS1 ]; then
    . ~/.bash_PS1
fi

# custom aliases
if [ -f ~/.bash_alias ]; then
    . ~/.bash_alias
fi

Deploying to /etc/skel

To apply these defaults to all future users, copy the files into /etc/skel/:

cp ~/.bash_PS1 /etc/skel/.bash_PS1
cp ~/.bash_alias /etc/skel/.bash_alias
cp ~/.dircolors /etc/skel/.dircolors
cp ~/.bashrc /etc/skel/.bashrc
cp ~/.bash_profile /etc/skel/.bash_profile

Any user created after this point will inherit the full shell configuration.

Next Steps

With the timezone, hostname, packages, and shell environment in place, the server is ready for the next layer: installing the base utility toolkit and hardening SSH access.