Linux Basics
In this guide, you will learn everything you need to know about linux. Starting from simple things like shells and terminals to slightly harder topics like SSH. These will be the most important things you learn about linux which will stay with you till the end.
Why Linux?
Because these are the tools and concepts you'll return to every day. Whether you're installing software, fixing a broken service or simply exploring the system, understanding shells, the filesystem, permissions, service management, remote access and process monitoring gives you both power and confidence.
Why Debian?
Because Debian is one of the most widely used distros.
- TAILS is based on Debian.
- Whonix is based on Kicksecure, which is based on Debian.
- QubesOS ships with Debian templates.
What Is a Shell?
A shell is the program that reads your input, runs commands and shows you output.
- Terminal emulator: the window application (e.g. GNOME Terminal, xterm) where you type commands.
- Bash: A widely-used default interactive shell in most distros. Has some features like autocompletion and history.
- Fish: It's like bash, but more feature-complete. Better autocomplete, prompts, and a better experience in general.
If you launch a terminal, you will see a line which probably looks like this:
user@debian:~$
This is called a prompt.
This is where you type commands such as ls
, cd
, apt update
, which the shell interprets.
When a prompt ends in '$', it is a user-level prompt.
When a prompt ends in '#', it is an administrator (sudo) prompt.
The Linux Filesystem
Debian follows the Filesystem Hierarchy Standard (FHS). Key directories:
Path | Description | Examples |
---|---|---|
/ |
Root of the filesystem tree | |
/bin |
Essential system binaries | cd , ls |
/sbin |
System binaries requiring root privileges | iptables , fsck |
/etc |
Configuration files | /etc/ssh/sshd_config , /etc/fstab |
/usr |
Shareable, read-only data | |
/usr/bin |
User-installed binaries | python , rust |
/usr/lib |
Libraries and modules | |
/var |
Variable data | Logs (/var/log/ ), mail spools, package cache |
/home |
User home directories | |
/home/user |
Current user's home directory | /home/user is the same as ~/ if logged in as user |
~/.config |
Per-user application configuration files (XDG compliant) | ~/.config/emacs ~/config/gnome-terminal |
~/.cache |
Per-user application cache files | |
~/.local |
Per-user application data, state, and user-installed binaries | |
~/.icons |
Per-user icon packs | |
~/.themes |
Per-user theme files | |
/opt |
Add-on application packages | |
/dev |
Device files | Disks, pendrives, and other storage devices. (/dev/sda1 ) |
/proc |
Virtual filesystem exposing process and kernel information | |
/sys |
Virtual filesystem exposing system and kernel interfaces |
How to navigate using the terminal
Now that you know what terminals, shells, and important directories on your system are, let's see how you can actually move around using your terminal.
"But why should I use a terminal when I can just use \<insert graphical file manager>?"
- Typing is faster.
- You can automate tasks by writing scripts.
- Terminal programs use low resources and have smaller or no dependencies.
- When connecting to remote servers, using SSH for example, there is no GUI. Only a terminal.
- CLI (Command Line Interface) programs are reproducible. For example, a UI update could change where a certain option was, and it becomes annoying to figure out where they moved it. This problem literally doesn't exist in CLI programs.
The command you'll use the most is cd
. With this, you can change your current working directory.
user@debian:~$ cd Documents/
user@debian:~/Documents/$
The next command is ls
. This is to list files in the current directory.
user@debian:~/Documents/$ ls
important.pdf project Passwords.kdbx
user@debian:~/Documents/$
But this doesn't really give us much information. There is a better way to view the files.
It is by passing the -l
flag.
user@debian:~/Documents/$ ls -l
-rw-r--r-- 1 user users 22 Jun 26 22:05 important.pdf
-rw-r--r-- 1 root root 1234 Jun 29 09:15 notes.txt
-rw-r--r-- 1 user users 22 Jun 26 20:12 Passwords.kdbx
drwxr-xr-x 5 user users 4096 Apr 12 10:23 projects
user@debian:~/Documents/$
There. That looks way better.
You might not understand it yet, but there is a lot of information from just that output. Let's see what each part of the output means in the next chapter.
Where to go from here
You now know all the different kinds of files are present in different locations across the system and how you can get to them. I will leave a list of more useful commands below.
nano
: A terminal-based text editor.mousepad
: GUI-based text editor.- While
nano
andmousepad
might be comfortable to use, you should consider learningvim
/neovim
. Once you learn it, it becomes a million times faster to write anything, as you will not need to use a mouse anymore. - Once you've mastered
vim
, trydoomemacs
. It is anemacs
configuration that works withvim
keybindings by default. - These two are infinitely better ways of writing β code or otherwise.
man
: Manual pages for commands. (useman nano
for example.)touch
: Create an empty file. (touch notes.txt
)pwd
: Print Working Directory.ls
: List files in the current directory.rm
: Remove (delete) files. (rm -rf
to delete a folder.)rm
deletes files permanently. It doesn't go to any recycle bin or trash.cp
: Copy files (cp file1 copy_file1
)mv
: Move files (mv file1 ~/Documents/
)tldr
: A shorter manual page listing common/useful commands. Usually not included out-of-the-box in most distros.sudo passwd
: Change current user's password.kill -9 $(pidof firefox)
: Kill firefox if it isn't responding. Replace firefox with whatever program you want to kill.
I just can't recommend enough that you read manpages. This is the linux way. You won't find youtube tutorials of every program you want to use, but you will find manuals. So get in the habit of reading manpages and documentation early on. It'll save you a lot of headache in the future.
APT
APT (Advanced Package Tool) is a front-end for dpkg
that handles package retrieval, dependency resolution, and installation.
1. Updating Package Lists Always refresh your local cache before installing or upgrading by doing:
sudo apt update
- Fetches the latest package metadata from all repositories defined in
/etc/apt/sources.list
and/etc/apt/sources.list.d/
. - Doesn't change any installed packages.
2. Installing Packages
sudo apt install <package1> [<package2> ...]
- Installs the specified packages and any missing dependencies.
-
Example:
sudo apt install curl git build-essential
3. Removing and Purging
-
Remove (keeps configuration files):
sudo apt remove <package>
-
Purge (removes package and its configuration files):
sudo apt purge <package>
4. Upgrading Packages
-
Upgrade: Installs available updates for installed packages, but never removes or installs new packages:
sudo apt upgrade
-
Full Upgrade (formerly "distβupgrade")βcan add or remove packages to satisfy dependencies:
sudo apt full-upgrade
5. Cleaning Up
-
Remove packages no longer required (e.g. old dependencies):
sudo apt autoremove
-
Clear out downloaded
.deb
files from the cache:sudo apt autoclean sudo apt clean
6. Searching for Packages
apt search <keyword>
- Matches package names and short descriptions.
7. Showing Package Details
apt show <package>
- Displays version, dependencies, installed size, repository origin, description, etc.
Working with Sources
/etc/apt/sources.list
Lines take the form:
deb http://deb.debian.org/debian buster main contrib non-free
deb-src http://deb.debian.org/debian buster main
- deb = binary packages
-
deb-src = source packages
-
Components:
main
β free softwarecontrib
β free but depends on non-free softwarenon-free
β non-free licenses
Troubleshooting
-
Broken dependencies:
sudo apt --fix-broken install
-
Corrupt package cache:
sudo rm -rf /var/lib/apt/lists/* sudo apt update
-
Held packages (prevent upgrade):
apt-mark showhold sudo apt-mark unhold <package>
-
Inspect logs:
/var/log/apt/history.log
: what APT has done/var/log/apt/term.log
: detailed terminal output
Best Practices
- Regularly
update
before any install/upgrade. - Use
full-upgrade
. - Limit
recommends
if disk space is tight:
sudo apt install --no-install-recommends <package>
File Permissions
Every file and directory on linux has 3 permission groups:
- Owner: Permissions for who owns the file/directory.
- Group: Permissions that apply for the group assigned to the file/directory.
- Others: Permissions that all the other users have.
All you need to remember is:
d
= is a directory.r
= can read the file.w
= can write to the file or modify directory contents.x
= can be executed a file or access/traverse a directory.-
= permission not granted.
drwxr-x--- 2 user users 4096 Jun 30 12:00 projects
The first part of the output, drwxr-x---
can be broken down as follows:
- It is a directory.
- The owner can read, write, and execute.
- The users in the 'users' group can read and execute, but not write.
- Other users can't read, write, or execute.
Note: The directory has execute permissions so that files inside it can be listed. Do not get this confused with executables.
This also means that if you remove execute permissions on a directory, ls
will not work in it, but you can still read files if you know the filename.
Another example:
-rw-r--r-- 1 root root 1234 Jun 29 09:15 notes.txt
- Owned by root
- root can read and write but not execute.
- Users in the group 'root' can only read the file.
- Everyone else can only read the file.
To change the permissions of a file or a directory, use the following commands:
-
chown
to change the owner and/or group.bleak@debian:~/Documents/$ ls -l drwxr-x--- 2 user users 4096 Jun 30 12:00 projects bleak@debian:~/Documents/$ sudo chown bleak projects/ bleak@debian:~/Documents/$ ls -l drwxr-x--- 2 bleak users 4096 Jun 30 12:00 projects bleak@debian:~/Documents/$ sudo chown bleak:contributors projects/ bleak@debian:~/Documents/$ ls -l drwxr-x--- 2 bleak contributors 4096 Jun 30 12:00 projects
-
chmod
change the permissions using the Linux Scoring System. Before you learn how to use this, you should know some basic math (and the following values). The arithmetic value of read, write, and execute are as follows.r
= 4w
= 2x
= 1
Let me illustrate this with an example:
The permissions -rw-rw-r--
would be equal to 661
. Here's how.
From here, if you wanted to add execute privilege for the owner (green) and group (yellow), we add 1 to the first two digits.
rwx
= 4+2+1 = 7rwx
= 4+2+1 = 7r--
= 4+0+0 = 4
So, the final permissions, -rwx-rwx-r--
would be the same as 774
.
This is how you would use chmod
.
user@debian:~/Documents/$ ls -l
-rw-rw-r-- 2 user users 30 Jun 30 12:00 notes.txt
user@debian:~/Documents/$ sudo chmod 774 notes.txt
user@debian:~/Documents/$ ls -l
-rwxrwxr-- 2 user users 30 Jun 30 12:00 notes.txt
In case you accidentally mess up file permissions, here are the base permissions:
- For files, 644.
- For directories, 755.
- For key-pairs, 400.
This method is called the numeric or octal mode. There's another way to use chmod
, and it is the text or symbolic mode.
The basic format is as follows:
chmod [who][operator][permission] [file]
Below are the same example commands in both the formats. I hope it helps you put things in to perspective easily. The key is to learn this intuitively instead of memorizing it. It's easy once you get the hang of it.
-
Text/Symbolic mode
chmod u+x script.sh # Add execute for user chmod go-w file.txt # Remove write from group and others chmod a=r file.txt # Set read-only for all chmod u=rwx,go= file # Full for user, none for group/others
-
Numeric/Octal mode
chmod 755 script.sh # rwxr-xr-x chmod 644 file.txt # rw-r--r-- chmod 700 secret.txt # rwx------ chmod 000 noaccess.txt # ----------
Systemd
Before you understand what systemd
is, you need to understand what an init system is.
In simple terms, it is the first process the kernel starts on boot. (So always a PID of 1 + Highest privilege) Its job is to:
- Bring the system up
- Mount filesystems
- Start essential kernel services
- Configure networking
- Launch and supervise services (Daemons)
- Start Apache webserver
- Start tor
- Start the login manager
- Monitor and restart services whenever required
- Handle shutdown and reboot
- Stop services in the correct order
- Unmount filesystems cleanly
- Tell the kernel to poweroff or reboot.
In the early days, Unix-like systems used a simple "SysV init" approach: a single script (/etc/init.d/...) invoked by numbered runlevels (/etc/rc#.d/...) in serial order. Over time that model showed limitations:
- Serial Startup: Services could start only one after another, slowing boot times.
- Limited automation: If a service failed, you'd have to troubleshoot it manually. There was no built-in restart.
So, then came systemd
. A modern, fully integrated service-management system.
- Declarative
.service
,.socket
,.mount
,.target
files instead of shell scripts. - Built-in dependency resolution. (
After=
Requires=
) - Journald, a centralized logging system with indexing and structed metadata.
- Easier on-demand operations. (Like locking your system automatically before sleep)
Debian uses systemd as its init system. It handles:
- Units: service (
.service
), mount (.mount
), target (.target
) files in/lib/systemd/system/
or/etc/systemd/system/
. - Dependencies: units declare when they start relative to others.
- Logging:
journalctl
lets you read the system journal.
Common commands:
sudo systemctl start apache2.service # start a service now
sudo systemctl stop apache2.service # stop it
sudo systemctl enable apache2.service # always start at boot
sudo systemctl status apache2.service # view current status
journalctl -u apache2.service # view its logs
Systemd's parallel startup and on-demand activation make boot faster and services more reliable.
Controversy
You might have heard that some people absolutely hate systemd, and that's not without good reason.
- A major issue for some people is that it violates the Unix philosophy of "do one thing and do it well." As you've read above,
systemd
handles a lot of things than just starting and stopping services. Managing network configuration, locales and even hostnames make it "bloated". - Rather than a suite of small, interchangeable tools (like GNU coreutils), systemd is a single, large codebase. This makes replacing parts a lot harder.
- For most people, it's just a philosophical debate between minimal software and ease of use.
But for the average person, systemd
is good enough. It just works and is easy to configure and learn.
sudo
and the /etc/sudoers
file
Sudo stands for 'Superuser Do'. It allows a permitted user to execute a command as the superuser (root) or another user, as specified by the security policy.
sudo
is primarily used for:
- Privilege escalation: Running commands as the root user without having to log out and log back in as the root user.
- Administrative tasks: Performing system administration, like creating a new user, installing packages, modifying configuration, etc.
- Security: Providing a way to grant limited administrative access to users while maintaining a secure environment.
For example,
user@debian:~$ sudo apt update
apt update
is being run with root permissions.
(This is required for apt update
so it can create and use lock files, which prevent multiple instances of apt
from running at the same time.)
/etc/sudoers
is a configuration file for sudo
.
- Defines permissions: Which users or groups can run which commands. The syntax is as follows:
user host = (runas) command
- Defaults: Global settings that apply to all users.
- Comments: Lines starting with
#
are comments and are ignored by the parser. - Included Files: You can include other files for modular configuration (instead of everything in one file), often found in
/etc/sudoers.d/
.
Example:
alice ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart apache2
alice
to run the command systemctl restart sshd
, which requires a root password without having to enter a password. (Because we defined it with NOPASSWD:
)
Creating a new user
-
Create a new user with a password
user@debian:~$ sudo useradd -m bob # -m creates bob's home dir automatically user@debian:~$ sudo passwd bob # to set a password. New password: Retype new password: passwd: password updated successfully
-
Give the new user sudo rights
user@debian:~$ sudo usermod -aG sudo bob
-
Switch into the new user
user@debian:~$ su --login bob # you can also use '-' instead of '--login' Password: bob@debian:~$ whoami bob
-
Deleting a user Before you delete a user, make sure you aren't logged in as that user. (You can't delete a user that's logged in.)
user@debian:~$ sudo userdel bob
Processes, PIDs and Htop
A process is any running program; each has a unique PID (process ID). To see them:
ps aux
lists all processes.top
shows an interactive, updating view.
On Debian you can install htop or btop for a friendlier interface:
htop
You will see a window that looks as follows. The top part is mostly self-explanatory, but here are the main things.
Now press the t
or F5
key to toggle between tree mode.
You can scroll down using your arrow keys. A few common shortcuts are listed below.
Shortcut | Action |
---|---|
F1 / h | Open help screen (list all keybindings) |
F2 / F6 | Open Setup (customize meters, columns, colors, header) |
F3 / / | Search for a process by name or PID |
F4 / \ | Filter processes (show only those matching a pattern) |
F5 / t | Toggle Tree View (show parent-child process hierarchy) |
F6 / s | Sort by a different column (choose %CPU , %MEM , TIME+ , etc.) |
F7 / β | Nice β: decrease priority (make process more "nice") |
F8 / β | Nice +: increase priority (make process less "nice") |
F9 / k | Kill a process (select signal to send, default SIGTERM) |
F10 / q | Quit htop |
Space | Tag/untag a process (for batch operations, e.g. killing multiple) |
U | Untag all processes |
L | Toggle display of load average and uptime in header |
M | Sort by memory usage |
P | Sort by CPU usage |
T | Sort by time+ (cumulative CPU time) |
Logging (dmesg
and journalctl
)
dmesg
: Kernel messages like hardware events and driver messages can be read usingdmesg
.journalctl
: Like you've read above, it is managed by systemd and it contains the logs of systemd services (and some kernel messages).
Why is it important to understand logs?
- If your system breaks, the logs are your only way to fixing it. You won't always get an error message telling you what broke, but there will always be logs for that.
journalctl
With that out of the way, run journalctl
on your terminal.
You will see a long list of lines, and in the beginning you'll see the date and time of the log. You can scroll down to the newer logs using your arrow keys.
user@debian:~$ journalctl
Jun 29 15:01:04 debian systemd-journald[22]: Journal started
Jun 29 15:01:04 debian systemd-journald[22]: Runtime Journal (/run/log/journal/e349af82dd4849b9a5ec02e1bd6a1d2f) is 8M, max 158.7M, 150.7M free.
Jun 29 15:01:04 debian systemd[1]: Finished Remount Root and Kernel File Systems.
Jun 29 15:01:04 debian systemd[1]: Finished Load udev Rules from Credentials.
Jun 29 15:01:04 debian systemd[1]: Rebuild Hardware Database was skipped because no trigger condition checks were met.
Jun 29 15:01:04 debian systemd[1]: Starting Flush Journal to Persistent Storage...
Jun 29 15:01:04 debian systemd[1]: Load/Save OS Random Seed was skipped because of an unmet condition check (ConditionVirtualization=!container).
Jun 29 15:01:04 debian systemd[1]: TPM SRK Setup was skipped because of an unmet condition check (ConditionSecurity=measured-uki).
Jun 29 15:01:04 debian systemd[1]: Starting User Database Manager...
Jun 29 15:01:04 debian systemd-journald[22]: Time spent on flushing to /var/log/journal/e349af82dd4849b9a5ec02e1bd6a1d2f is 2.414ms for 9 entries.
Jun 29 15:01:04 debian systemd-journald[22]: System Journal (/var/log/journal/e349af82dd4849b9a5ec02e1bd6a1d2f) is 8M, max 1.8G, 1.8G free.
Jun 29 15:01:04 debian systemd[1]: Started User Database Manager.
Jun 29 15:01:04 debian systemd[1]: Finished Flush Journal to Persistent Storage.
Jun 29 15:01:04 debian systemd[1]: Finished Create Static Device Nodes in /dev gracefully.
Jun 29 15:01:04 debian systemd[1]: Starting Create System Users...
[...]
These logs are actually located in /var/log/journal
. Logs of other programs are in /var/log
.
But looking at so many lines at once is redundant. You can limit how many logs are displayed by using the following commands.
# Show only logs from the current boot (to check if something broke, for example)
journalctl -b
# Show logs from previous boots; '-b -1' is the last boot, '-b -2' two boots ago, etc.
journalctl -b -1
# The output updates in realtime. (follow)
journalctl -f
# Print the last 50 lines and then follow.
journalctl -n 50 -f
# Show only entries from a specific systemd unit.
journalctl -u sshd.service
# Show only errors and above.
journalctl -p err
# Combine: errors from sshd only.
journalctl -u sshd.service -p err
# Only entries since a given time:
journalctl --since "2025-06-28 14:00" --until "2025-06-28 16:00"
# Relative times also work:
journalctl --since "2 hours ago"
Tip: You can also output the logs in json
format by adding the flag -o json
or -o json-pretty
to any of the commands above.
dmesg
To use dmesg
, you need sudo previlages. Simply run sudo dmesg
to dump all the kernel messages. These can be very long but you can't scroll through the output by default. So, you should use pipe the output into a pager like less
.
user@debian:~$ sudo dmesg | less
dmesg
also has a 'follow' mode like journalctl.
dmesg --follow
# or
dmesg -w
Below is a table illustrating when to use which program.
Aspect | journalctl |
dmesg |
---|---|---|
Source | systemd-journal (services & kernel messages) | kernel ring buffer |
Persistence | Binary on disk (if enabled) | In-memory, lost on reboot |
Granularity | Structured fields, metadata, per-unit tags | Kernel-only, raw buffer |
Filtering | Rich (units, priorities, fields, time) | Basic (level, timestamp, follow) |
Use case | Service failures, audit, long-term analysis | Early boot/hardware debugging, ring buffer inspection |
How to clear logs
Firstly, let me start this part by saying, you should (generally) never delete your logs this way. If you're paranoid about having logs, you should use a live system like TAILS or Kicksecure.
You should never delete all your logs because:
- You won't be able to troubleshoot if something went wrong.
- Some services or daemons assume access to historical logs for features like rate-limiting, correlation, or state tracking.
- For example,
journald
might misbehave if its logging directory suddenly got nuked. - Some security daemons might throw errors too.
But, if you absolutely NEED to, then below is a simple bash script you can run.
Make sure you give it executable permissions and run it as root or with sudo
.
#!/usr/bin/env bash
#
# WARNING: This will irreversibly delete your logs.
set -euo pipefail
# Ensure running as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Use sudo." >&2
exit 1
fi
echo "==== Clearing systemd journal logs ===="
# Rotate and vacuum to remove everything
journalctl --rotate
# Vacuum everything (keep only entries newer than 1 second ago = effectively none)
journalctl --vacuum-time=1s
# If persistent journals exist, remove them
if [[ -d /var/log/journal ]]; then
rm -rf /var/log/journal/*
echo "Removed /var/log/journal/*"
fi
echo "==== Clearing kernel ring buffer (dmesg) ===="
dmesg -C
echo "==== Truncating /var/log/*.log and subdirectories ===="
# Find all .log files under /var/log and zero them
find /var/log -type f -name '*.log' -print0 \
| xargs -0 --no-run-if-empty truncate --size 0
echo "==== Truncating wtmp, btmp, lastlog ===="
for f in /var/log/{wtmp,btmp,lastlog}; do
if [[ -f $f ]]; then
truncate --size 0 "$f"
echo "Truncated $f"
fi
done
echo "==== Clearing audit logs (if present) ===="
if [[ -d /var/log/audit ]]; then
find /var/log/audit -type f -name '*.log' -print0 \
| xargs -0 --no-run-if-empty truncate --size 0
echo "Truncated audit logs"
fi
echo "==== All logs cleared ===="
SSH (Secure Shell)
SSH is a program for securely logging into a remote machine and execute commands on that machine. It provides a secure and encrypted communication between two untrusted hosts over an untrusted network.
Note: 'untrusted' here means that ssh
always assumes the network (and the endpoints) may be hostileβi.e. that an attacker can eavesdrop on, modify, or inject packets at will. SSH therefore provides mutual authentication, confidentiality, and integrity protection to defend against passive and active network attacks.
Below is a quick overview on how SSH works.
- Client: Your system from which you want to connect to the server.
- Server: The remote machine on which SSH is running and listening.
Note: If you want to authenticate using key-pairs, the server should know your public key. We will see how to set it up below.
- When you connect to the server, it sends a random message to you (the client).
- The client encrypts the same message with the secret key and sends it back.
- The server decrypts it with the public key.
- After decrypting, it checks if it is the same message as it sent in step 2.
- If yes, it authenticates the client and a random session key is generated.
- This key is used to symmetrically encrypt everything from this point.
Symmetric Encryption: This is a kind of encryption where instead of using keys, a password is used to encrypt data. - E.g. RSA.
Authentication:
- Password (less secure).
- Key pair (public/private)
SSH encrypts all traffic, including passwords, and can forward ports, run commands remotely and tunnel GUI applications.
Setting things up
To follow this tutorial step by step, you need at least two machines. A server and a client. If you do not have an extra device, try setting up a Virtual Machine (VM). The steps will be the same regardless of what you do.
-
Setting up the SERVER.
- Go to the other device or a VM and do the following:
server@debian:~$ sudo systemctl start sshd # start ssh if it isn't running server@debian:~$ sudo systemctl status sshd # check ssh status β sshd.service - OpenSSH Daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled; preset: disabled) Active: active (running) since Tue 2025-07-01 **:**:** UTC; 47min ago Invocation: e924ae7e07404b9ba1d5122eaed675d1 Main PID: 751 (sshd) Tasks: 1 (limit: 9501) Memory: 4.7M (peak: 22.7M) CPU: 254ms CGroup: /system.slice/sshd.service ββ751 "sshd: /usr/bin/sshd -D [listener] 0 of 10-100 startups" Jul 01 **:**:** debian systemd[1]: Starting OpenSSH Daemon... Jul 01 **:**:** debian sshd[1089]: Server listening on 0.0.0.0 port 22. Jul 01 **:**:** debian sshd[1089]: Server listening on :: port 22. Jul 01 **:**:** debian systemd[1]: Started OpenSSH Daemon.
- As you can see, our SSH server is listening on the default port 22.
- Now you need to find out the server's ip address.
server@debian:~$ ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host noprefixroute valid_lft forever preferred_lft forever 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 52:54:00:0b:52:4e brd ff:ff:ff:ff:ff:ff altname enx5254000b524e inet 192.168.1.156/24 metric 1024 brd 192.168.122.255 scope global dynamic enp1s0 # <---- this line has the ip address we need. valid_lft 3552sec preferred_lft 3552sec inet6 fe80::5054:ff:fe0b:524e/64 scope link proto kernel_ll valid_lft forever preferred_lft forever
- The ip we have is
192.168.1.156
. Keep that in mind for later.
-
CLIENT
- In order to have maximum security, we should generate a key-pair. Fortunately, the process is simple and straightforward.
- Keep the defaults, and DEFINITELY USE A PASSWORD.
client@debian:~$ ssh-keygen Generating public/private ed25519 key pair. Enter file in which to save the key (/home/client/.ssh/id_ed25519): Enter passphrase for "/home/client/.ssh/id_ed25519" (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/client/.ssh/id_ed25519 Your public key has been saved in /home/client/.ssh/id_ed25519.pub The key fingerprint is: SHA256:7CUFvhY1/RqeZf/9+27iQS9MsQncVGxoPDNy4dHqRI0 client@debian The key's randomart image is: +--[ED25519 256]--+ | . o. .+O.| | . o oo+E.=| | o . o*+* | | . + ..*+ | | S .. O=. | | o o ++...| | . + +| | .o+| | ..=B| +----[SHA256]-----+
- Now we have our keys. The only thing left to do is send the public key to the server. This is also quite simple.
- We can use
ssh-copy-id
to copy the public key. No need of any mental gymnastics like copying it over from a pendrive or cloud.
client@debian:~$ ssh-copy-id -i ~/.ssh/id_ed25519.pub server@192.168.1.156 bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/client/.ssh/id_ed25519.pub" bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys server@192.168.1.156's password: # <--- enter the user's password. Number of key(s) added: 1 Now try logging into the machine, with: "ssh -i /home/client/.ssh/id_ed25519 'server@192.168.1.156'" and check to make sure that only the key(s) you wanted were added.
- Now you are asked to enter the user's password in the server. The username in my example is 'server'.
- All the setup is now finished. We can finally login.
client@debian:~$ ssh server@192.168.1.156 Enter passphrase for key '/home/client/.ssh/id_ed25519': # <--- the password you created for the key [server@debian:~$] whoami server
See? It's as simple as that. It is as if you opened at terminal on the server. You can now run any commands on it like usual.
Setting up aliases:
- Instead of typing out the username and ip address (or hostname) every time, you can set up an alias. Here's how open your client's
~/.ssh/config
invim
or your preferred text editor and add the following lines and save the file. Customize the values as you like.:Host customhostname User host HostName 192.168.1.156
- And that's it. You can now use 'customhostname' instead of 'server@192.168.1.156'.
client@debian:~$ ssh customhostname Enter passphrase for key '/home/client/.ssh/id_ed25519': # <--- the password you created for the key [server@debian:~$] whoami server
Now let's see how to use rsync
, an amazing tool to copy or sync files, mainly used over SSH.
Rsync
Why rsync
instead of cp
or mv
?
-
There are two really useful features that
rsync
has which neither of the two coreutils tools have:- Delta Transfers: Basically sync. It copies over only those files that have been changed.
- Partial Transfers: Splits files into chunks instead of transfering full files. This helps if you have a faulty cable which keeps disconnecting. If you used
cp
ormv
, you'd have to start over if the cable disconnected. Very annoying when dealing with large files.
Basic commands:
-
To simply copy a file from the client to the server,
client@debian:~$ rsync important.org server@ip
-
General flags to use (almost) all the time:
Flag | Description |
---|---|
--progress |
Show progress during transfer (bytes transferred, transfer rate, ETA) |
--stats |
Give a detailed set of statistics on the file transfer |
--partial |
Uses partial transfer as explained above |
-v |
Verbose mode; show detailed file-transfer information |
-P |
Equivalent to --partial --progress ; keeps partially transferred files and shows progress |
-r |
Recursive; copy directories and their contents |
-u |
Update; skip files that are newer on the destination |
-h |
Human-readable; output numbers in a human-friendly format (e.g. "1.1M" instead of "1100000") |
-a |
Archive mode; equals -rlptgoD (recursively copy files. links, perms, times, group, owner and devices information will be preserved.) |
-z |
Compress file data during transfer |
--delete |
Delete extraneous files from destination dirs (those not present in the source) |
-e <ssh_cmd> |
Specify remote shell to use, e.g. -e "ssh -p 2222" |
--dry-run |
Perform a trial run without making any changes |
Note: When copying directories, make sure you don't have the '/' in the end. If you add the '/', it will not create a folder and just put all the files outside.
I recommend you to read the manual page for rsync
. This tool has so many features it deserves a writeup of its own.
Making a custom systemd service to back up a folder using rsync
In this section you will learn how to create a systemd service which backs up a folder to your server.
-
Write the bash script
To make things easier for you, I've written a simple script that even YOU, can understand.
#!/usr/bin/env bash SOURCE="$HOME/Documents/project" DEST="server:/backups/$USER/Documents/project" # <--- remember we aliased 'server' to the actual address? If you didn't do that, mention the full address here. LOGFILE="$HOME/Documents/logs/daily-backup.log" # Run rsync rsync -avh --delete "$SOURCE" "$DEST" >> "$LOGFILE" 2>&1 # Log completion echo "Backup completed at $(date)" >> "$LOGFILE"
Save this file in
/usr/local/bin/
and give it executable permissions as discussed in previous chapters. (chmod +x backup.sh
) -
Setting up the systemd service
Create
/etc/systemd/system/backup.service
. You will need to use sudo.Enter the following code:client@debian:~$ sudo vim /etc/systemd/system/backup.service
[Unit] Description=Daily rsync backup of ~/Documents/project Wants=network-online.target After=network-online.target [Service] Type=oneshot ExecStart=/usr/local/bin/backup.sh User=client # <--- your username [Install] WantedBy=multi-user.target
Now we define a timer unit.
client@debian:~$ sudo vim /etc/systemd/system/backup.timer
Enter the following code; adjust wherever needed.
[Unit] Description=Run backup.service every day at 2 AM [Timer] OnCalendar=*-*-* 02:00:00 Persistent=true # If the system was down at the scheduled time, it runs at the next boot. [Install] WantedBy=timers.target
Now, before we enable the service, you should keep in mind that currently, IF you need to enter the password for your ssh key, this won't work automatically. But there's a workaround for it. 2.1. Setting up an SSH agent. (optional. do this only if you set up a password for your ssh key.) Add the following to one of your shell-startup files (
~/.bashrc
in debian)# ===== SSH-Agent Setup ===== if [ -z "$SSH_AUTH_SOCK" ] ; then # start a new agent and record its pid/socket eval "$(ssh-agent -s)" # load your key (you'll type the passphrase once) ssh-add ~/.ssh/id_ed25519 # or ~/.ssh/id_rsa, whichever you made / exists. fi # ===========================
-
Enable the service
# Reload to recognize new units sudo systemctl daemon-reload # Enable & start the timer (this also pulls in the service) sudo systemctl enable --now daily-backup.timer
-
Check if it is working
sudo systemctl start daily-backup.service sudo systemctl status daily-backup.service
Final notes
I hope you enjoyed reading this guide as much as I enjoyed writing it. I want to leave with you a few pieces of advice, about linux or otherwise.
- You should learn to use only your keyboard for everything. Switch to using WM (Window Managers) instead of Desktop Managers like gnome. They are bloat considering a suckless philosophy.
- Check out https://suckless.org They make epic software.
- Use Suckless's DWM (Dynamic Window Manager) where everything is done just using the keyboard. You literally don't even need a mouse.
- Practice digital minimalism; reduce your surface area. And eventually, this minimalism will bleed into your daily life.
- ACAB
- Read books. Read philosophy. Read fiction, nonfiction, or literally anything. If you need help deciding what book to read, start with Ray Bradbury's Fahrenheit 451. If I could get everyone in the world to read a book, it would be this one.
- Morality is subjective.
- The abyss does gaze back into you.
- The answer IS a hut in the woods. Depression turtle was wrong.
Suggest changes
bleak 2025-06-30
43fPQSRfkorKmDrC7Toqw67yimcV8VKbxYudY1zQp6Z7XiuboXTmnAdifGrsCP5bF8A7qNDedAhEQ3TwCegudmrA1U5bgUp Donate XMR to the author: