23.3. Linux Server Setup
Table of Contents
Why Linux For Backend Servers
Most production backends run on Linux. It is free, stable, scriptable, and most server tools are built for it first.
As a backend developer you do not need to become a full Linux administrator, but you must be comfortable enough to:
- Log in to a remote server
- Move around the filesystem
- Install packages and services
- Configure your app to run as a service
- Secure basic access
This chapter focuses on what you actually do when you get a fresh Linux server for deployment.
Goal of this chapter
After this chapter you should be able to log into a new Linux VPS, perform basic setup, and prepare it to run a backend application.
Choosing a Linux Distribution
For servers you almost always use a distribution like:
| Family | Examples | Package manager | Typical usage |
|---|---|---|---|
| Debian-based | Ubuntu Server, Debian | apt | Very common for web apps and VPS |
| RHEL-based | CentOS Stream, Rocky, Alma | dnf / yum | Enterprise data centers |
| Others | Arch, openSUSE | Various | Less common for beginners on servers |
For this course, you can assume Ubuntu Server LTS on a cloud VPS, because:
- Many tutorials use it
- Most hosting providers offer it
- The
aptpackage manager is beginner friendly
If you see examples using dnf or yum, you can usually translate them:
| Action | Ubuntu / Debian | RHEL family |
|---|---|---|
| Update packages | sudo apt update | sudo dnf update |
| Upgrade system | sudo apt upgrade | sudo dnf upgrade |
| Install package | sudo apt install nginx | sudo dnf install nginx |
| Remove package | sudo apt remove nginx | sudo dnf remove nginx |
Connecting To Your Server With SSH
You normally access a remote Linux server using SSH (Secure Shell).
Creating an SSH key
On your local machine (Linux, macOS, or WSL on Windows):
ssh-keygen -t ed25519 -C "your_email@example.com"You will be asked:
- Where to save: press Enter to accept default
~/.ssh/id_ed25519 - Passphrase: choose a strong passphrase, or leave empty for no passphrase
This creates two files:
| File | Description |
|---|---|
~/.ssh/id_ed25519 | Private key, keep it secret |
~/.ssh/id_ed25519.pub | Public key, safe to share |
Important
Never share your private key (id_ed25519 or id_rsa). Share only the .pub file.
View your public key:
cat ~/.ssh/id_ed25519.pubCopy this line. You will add it to the server.
Adding your SSH key to the server
Most cloud providers (DigitalOcean, AWS, etc.) let you paste your SSH public key during server creation. They put it into /home/youruser/.ssh/authorized_keys for you.
If you only have password access initially, you can:
- Connect with password:
ssh root@YOUR_SERVER_IP- On the server, create the
.sshdirectory for your user:
mkdir -p ~/.ssh
chmod 700 ~/.ssh- Edit
authorized_keysand paste your public key:
nano ~/.ssh/authorized_keys
# paste the content of your .pub key
chmod 600 ~/.ssh/authorized_keysAfter that, you can log in with your key.
Logging in via SSH
From your local machine:
ssh youruser@YOUR_SERVER_IP
If you are using the default root user (not recommended long term):
ssh root@YOUR_SERVER_IPYou will see a shell prompt like:
youruser@server-name:~$You are now working on the remote server.
Creating a Non-Root User
Running everything as root is dangerous. A safer pattern:
- Create a regular user.
- Give it
sudopermissions.
As root on the server:
adduser deploy
# follow prompts for password and info
Add the user to the sudo group (on Ubuntu):
usermod -aG sudo deploySwitch to that user:
su - deploy
Now test sudo:
sudo ls /root
It should ask for deploy's password and then show the directory listing.
Next, copy your SSH authorized keys from root to deploy (if the provider added them to root):
rsync --archive --chown=deploy:deploy /root/.ssh /home/deploy
Now you can exit and reconnect as deploy:
exit # leave root
ssh deploy@YOUR_SERVER_IP
From now on, use this non-root user with sudo for administration.
Basic File System Navigation
When you log in you are in your home directory, for example /home/deploy.
Useful paths on a server:
| Path | Purpose |
|---|---|
/home/user | User home directories |
/var/www | Often used for web app code |
/etc | Configuration files for services |
/var/log | Log files |
/usr/bin | System binaries |
/tmp | Temporary files |
Basic commands:
pwd # show current directory
ls # list files
ls -la # list with details and hidden files
cd /var/www # change directory
cd ~ # go back to home
mkdir myapp # create directory
rm file.txt # remove file
rm -r dir # remove directory recursivelyExample session:
cd /var
ls
cd www
sudo mkdir myapp
sudo chown deploy:deploy myapp
cd myapp
pwd # /var/www/myappInstalling System Packages
On Ubuntu and similar:
- Update package index:
sudo apt update- Upgrade installed packages:
sudo apt upgrade- Install a package, for example Git:
sudo apt install git- Remove a package:
sudo apt remove git- Search for packages:
apt search postgresSome typical packages for backend servers:
| Purpose | Package examples |
|---|---|
| Web server | nginx |
| Database client | postgresql-client, mysql-client |
| VCS | git |
| Basic tools | curl, wget, htop, zip |
| Python | python3, python3-venv, python3-pip |
System Users, Groups, and Permissions
Linux has users and groups. Each file has an owner, a group, and three sets of permissions:
- Owner permissions
- Group permissions
- Other (everyone else) permissions
See file details:
ls -lYou might see:
-rw-r--r-- 1 deploy deploy 1234 Aug 28 12:00 config.json
drwxr-xr-x 2 deploy deploy 4096 Aug 28 12:01 logsBreakdown of the first line:
| Part | Meaning |
|---|---|
-rw-r--r-- | File type and permissions |
deploy | Owner |
deploy | Group |
Permissions are in order r (read), w (write), x (execute):
rw-for owner: read + writer--for group: read onlyr--for others: read only
Change owner:
sudo chown deploy:deploy /var/www/myappChange permissions:
chmod 640 config.json # owner rw, group r, others none
chmod 755 scripts.sh # typical for executable scriptsTypical app dir permissions
- Application code:
deploy:deploy,755directories,644files - Configuration files with secrets:
600or640, owner-only or owner+group
Process Management and Services
You will need to:
- Check if your app or dependency services are running
- Start, stop, and restart services
Checking processes
Use ps or htop:
ps aux | grep python
This lists running processes. htop (if installed) is interactive:
sudo apt install htop
htopsystemd services
Most modern distributions use systemd with systemctl to manage services.
Common commands:
# Check service status
sudo systemctl status nginx
# Start / stop / restart
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
# Enable service on boot
sudo systemctl enable nginx
# Disable on boot
sudo systemctl disable nginxShortcut to see if a service is running:
systemctl is-active nginx
# prints: active, inactive, failed, etc.Opening, Editing, and Viewing Files
You must be able to edit configuration files on the server.
Useful tools:
| Tool | Type | Usage |
|---|---|---|
cat | Viewer | Print a file |
less | Pager | Scroll through a file |
nano | Text editor, easy | Good for beginners |
vim | Advanced editor | Powerful but steeper learning curve |
Examples:
cat /etc/os-release # view OS info
less /var/log/syslog # scroll system log
nano /etc/nginx/nginx.conf # edit nginx config
In nano:
- Edit text
Ctrl+Oto saveCtrl+Xto exit
Basic Networking on the Server
You often need to:
- Check the server IP
- Test connectivity
- See which ports your app listens on
Checking the IP address
ip a
Look for something like inet 203.0.113.10/24 on a non-loopback interface, that is your server IP.
Testing connectivity
To check if you can reach a host:
ping google.com
# Ctrl+C to stopTo fetch a URL from the server:
curl https://example.comChecking listening ports
To see which ports your server is listening on, use ss:
sudo ss -tulnpOptions:
-tTCP-uUDP-llistening sockets-nnumeric output-pshow process
Typical output line:
LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
This means nginx is listening on port 80 on all network interfaces.
Firewalls and Basic Security
On Ubuntu, a simple firewall tool is UFW (Uncomplicated Firewall).
Basic UFW usage
Install (if not present):
sudo apt install ufwCheck status:
sudo ufw statusAllow SSH and HTTP/HTTPS:
sudo ufw allow OpenSSH
sudo ufw allow http
sudo ufw allow httpsEnable firewall:
sudo ufw enableList rules:
sudo ufw status numberedDelete a rule:
sudo ufw delete 1 # deletes rule number 1 from the list
Careful with firewalls
Always ensure SSH is allowed before enabling the firewall, or you can lock yourself out:
sudo ufw allow OpenSSH first, then sudo ufw enable.
Installing Runtime Environments
You will install your app runtime, for example Python or Node.js. The exact details belong to other chapters, but the general server-side pattern is similar.
Example: Python runtime on Ubuntu
Install Python and tools:
sudo apt update
sudo apt install python3 python3-venv python3-pipVerify:
python3 --version
pip3 --versionCreate a directory for your app:
sudo mkdir -p /var/www/myapp
sudo chown deploy:deploy /var/www/myapp
cd /var/www/myappCreate a virtual environment:
python3 -m venv venv
source venv/bin/activate
pip install fastapi uvicorn[standard]You now have a Python environment dedicated to this app.
Running Your Application as a Service
Running your app in a terminal with uvicorn main:app is not enough for production. You want:
- The app to start on boot
- Automatic restart if it crashes
- Logs captured in the system
On systemd systems you create a service unit.
Example systemd service for a FastAPI app
Assume:
- Code lives in
/var/www/myapp - Virtual environment in
/var/www/myapp/venv - Uvicorn command:
uvicorn main:app --host 0.0.0.0 --port 8000
Create a service file:
sudo nano /etc/systemd/system/myapp.serviceContents:
[Unit]
Description=My FastAPI Application
After=network.target
[Service]
User=deploy
Group=deploy
WorkingDirectory=/var/www/myapp
Environment="PATH=/var/www/myapp/venv/bin"
ExecStart=/var/www/myapp/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.targetSave and exit.
Reload systemd:
sudo systemctl daemon-reloadStart and enable:
sudo systemctl start myapp
sudo systemctl enable myappCheck status:
sudo systemctl status myappYou can now stop / start / restart your app via:
sudo systemctl restart myappLogs:
journalctl -u myapp -f
-f follows logs in real time, like tail -f.
Logs and Monitoring Basics
Logs help you debug issues on a live server.
Common log locations:
| Type | Location examples |
|---|---|
| System logs | /var/log/syslog, /var/log/messages |
| Auth logs | /var/log/auth.log |
| Nginx logs | /var/log/nginx/access.log, error.log |
| App logs | Custom, often under /var/www/myapp/logs |
View logs:
sudo tail -n 100 /var/log/syslog
sudo tail -f /var/log/nginx/error.log
For systemd services:
journalctl -u myapp -n 50 # last 50 lines
journalctl -u myapp -f # followLearning to read logs is critical for troubleshooting in production.
Simple Troubleshooting Workflow
When your backend is "not working" on a Linux server, use a systematic approach.
Example checklist:
- Is the app service running?
sudo systemctl status myapp- Any recent errors in app logs?
journalctl -u myapp -n 50- Is the app listening on the expected port?
sudo ss -tulnp | grep 8000- Can the server itself reach the app?
curl http://127.0.0.1:8000/health- Is the firewall letting traffic through?
sudo ufw status- If behind Nginx or another reverse proxy, are its logs clean?
sudo tail -n 100 /var/log/nginx/error.logAs you gain experience, this kind of routine becomes quicker and mostly automatic.
Summary
In this chapter you learned:
- Why backend servers commonly use Linux
- How to connect to a server via SSH using key-based authentication
- How to create a non-root user with
sudo - Basic filesystem navigation and permissions
- Installing packages with
apt - Managing services with
systemctl - Editing configuration files on the server
- Inspecting network ports and setting up a simple firewall with UFW
- Installing a runtime environment and running your app as a
systemdservice - Where to find and read logs, and a basic troubleshooting workflow
These are the core Linux skills you need to prepare a server for production deployment. In the next chapters you will build on this foundation to containerize and deploy your backend applications.
Views: 8
KAHIBARO