Setup for Debian VPS.
Tested on:
- Debian 13 on BinaryLane
Invalid locale warning
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory
_____________________________________________________________________
WARNING! Your environment specifies an invalid locale.
The unknown environment variables are:
LC_CTYPE=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_ALL=en_US.UTF-8
This can affect your user experience significantly, including the
ability to manage packages. You may install the locales by running:
sudo dpkg-reconfigure locales
and select the missing language. Alternatively, you can install the
locales-all package:
sudo apt-get install locales-all
To disable this message for all users, run:
sudo touch /var/lib/cloud/instance/locale-check.skip
_____________________________________________________________________
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory
ELI5: Your client is asking locale not installed in the debian.
Install it as directed:
sudo dpkg-reconfigure locales
No regular user in machine (root only)
Setup a passwordless user, create new user and add it to sudoers:
adduser --disabled-password darcien
usermod -aG sudo darcien
visudo -f /etc/sudoers.d/darcien
Put this in the file then save.
darcien ALL=(ALL) NOPASSWD: ALL
Duplicate the root SSH key to the regular user so regular user can authenticate SSH with key. (or create different key for regular user)
cp -r /root/.ssh /home/darcien/
chown -R darcien:darcien /home/darcien/.ssh
chmod 700 /home/darcien/.ssh
chmod 600 /home/darcien/.ssh/authorized_keys
Test the ssh as regular user
ssh -v darcien@<server>
Hardening SSH
Check ssh version in the server
sshd -V
# or ssh if no sshd from regular user
ssh -V
Should be newer than 6.7, then we can apply modern config.
Modify the server ssh config as needed:
nano /etc/ssh/sshd_config
[!WARNING] Only disable root ssh login after confirming regular user + sudo works.
# Supported HostKey algorithms by order of preference.
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
# Password based logins are disabled - only public key based logins are allowed.
AuthenticationMethods publickey
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp /usr/lib/ssh/sftp-server -f AUTHPRIV -l INFO
# Root login is not allowed for auditing reasons. This is because it's difficult to track which process belongs to which root user:
#
# On Linux, user sessions are tracking using a kernel-side session id, however, this session id is not recorded by OpenSSH.
# Additionally, only tools such as systemd and auditd record the process session id.
# On other OSes, the user session id is not necessarily recorded at all kernel-side.
# Using regular users in combination with /bin/su or /usr/bin/sudo ensure a clear audit track.
PermitRootLogin No
Any ssh config change:
# Validate new config
sshd -t
# Restart server to apply changes
systemctl restart sshd
Tailscale
Once SSH server is hardened, install Tailscale + setup Tailscale SSH to minimise the key needed to SSH into the machine from different devices.
See linux install guide.
It probably looks like:
# Add Tailscale's GPG key
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkgs.tailscale.com/stable/debian/trixie.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
# Add the tailscale repository
curl -fsSL https://pkgs.tailscale.com/stable/debian/trixie.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
# Install Tailscale
sudo apt-get update && sudo apt-get install tailscale
# Start Tailscale!
sudo tailscale up
Then enable Tailscale SSH:
tailscale set --ssh
Then test SSH from existing Tailscale device:
ssh -v <device-name>
Debug logs contain this:
debug1: Remote protocol version 2.0, remote software version Tailscale
And it should output:
# Tailscale SSH requires an additional check.
# To authenticate, visit: https://login.tailscale.com/a/<blah>
SSO with Tailscale, then you should be logged in.
Disable Tailscale key expiry if this is a permanent machine.
Eternal Terminal (et)
See https://eternalterminal.dev/download/
echo "deb [signed-by=/etc/apt/keyrings/et.gpg] https://mistertea.github.io/debian-et/debian-source/ $(grep VERSION_CODENAME /etc/os-release | cut -d= -f2) main" | sudo tee -a /etc/apt/sources.list.d/et.list
curl -sSL https://github.com/MisterTea/debian-et/raw/master/et.gpg | sudo tee /etc/apt/keyrings/et.gpg >/dev/null
sudo apt update
sudo apt install et
Make sure the default et port (2022) is not blocked.
Zsh + Git etc.
In case the debian is super slim
Need these for homebrew + chezmoi + dotfiles.
sudo apt-get install git jq rsync unzip zsh
Change default shell to zsh (yes, needs sudo because chsh needs to authenticate the user, but the regular user is passwordless)
sudo chsh -s $(which zsh) darcien
Homebrew on Linux
Yes, Homebrew.
# Usually these are already installed
sudo apt-get install build-essential procps curl file git
# Same installation script but pipe from echo to avoid prompt
echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Installing utilities + dotfiles
See dotfiles for details.
brew install chezmoi
chezmoi init --repo git@github.com:darcien/dotfiles.git
chezmoi apply
Angie (web server)
Follow the official setup above, then install:
sudo apt-get install -y angie
# Install extra modules
sudo apt-get install -y angie-module-brotli angie-module-zstd
Swap
Create 1 GB swap file if machine has no swap by default
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
unattended-upgrades
You don’t want outdated OS over the time. See https://wiki.debian.org/PeriodicUpdates
Usually already installed, try configuring and answer yes:
sudo dpkg-reconfigure unattended-upgrades
Check next trigger time:
sudo systemctl status apt-daily.timer
Changelog
- 2026-02-24: add unattended-upgrades
- 2026-02-22: add et
- 2026-02-16: initial version