This is a short and dense guide to get started with selfhosting using technology you can fit in your head.

Securely Access a New Server

When accessing for the first time a server exposed to the open internet, the first thing you should do is ensuring you're the only one who can. The most straightforward way to do it is trough two boring technologies included in every Unix-like system, ssh and wireguard.

Public Key Login with Ssh

SSH is the standard suite of program and protocols you can use to remotely connect to a Unix system securely. Normally, you'd type ssh username@server.org, be prompted to enter the password, and be granted shell access to some machine at server.org.

Passwords can be guessed better than they can be remembered. A better way (both to login and ward off malicious login attempts) is using a pair of cryptographic keys, a public one for the server and a private key that never leaves your device.

You can generate a pair of keys using ssh-keygen.

Bash
$ ssh-keygen 
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519): /home/user/.ssh/selfhost     
Enter passphrase for "/home/user/.ssh/selfhost" (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/user/.ssh/selfhost
Your public key has been saved in /home/user/.ssh/selfhost.pub
The key fingerprint is:
SHA256:tSje77sHMmES5Y4jKkE+l9PsugD1vzpGnGf64NvsUhc rj@oldhome
The key's randomart image is
+--[ED25519 256]--+
|       ..        |
|      ..         |
| ..    .. .      |
|o. .+ .oEo .     |
|oo =o++oSo.      |
|..o.*++++ .      |
|.....*o..o .     |
| ...*+ . .  .    |
|   +=B*  .=+     |
+----[SHA256]-----+
  

You can safely share the .pub key. Some cloud providers will give you the option to upload SSH keys from their web interface during the creation of your Unix machine.

If sshd is enabled with password authentication, you can copy your keys using ssh-copy-id:

$ ssh-copy-id -i .ssh/selfhost.pub user@dekedin.me
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/selfhost.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
user@remote_host\'s password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh -i .ssh/selfhost 'user@dekedin.me'"
and check to make sure that only the key(s) you wanted were added.

Else, manually create a file /home/user/.ssh/authorized_keys, creating the .ssh folder if necessary. Paste the public key there. You can paste multiple keys, one per line.

When you're done, you should be able to log in without being prompted for a password.

When the keys are installed, make sure to disable password authentication:

Use your favorite text editor to modify /etc/ssh/sshd_config, and locate the line with PasswordAuthentication:

...

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to "no" here!
#PasswordAuthentication yes
#PermitEmptyPasswords no

...

Uncomment the line by removing the leading hashtag and change yes to no.

After you're done, make sure to restart the sshd daemon:

# one of these
$ sudo systemctl restart sshd
$ rc-service sshd restart
$ sv restart sshd

SSH is very versatile: you can run single commands or mount your remote server locally and browsing it like any folder (using sshfs).

You can create SOCKS5 proxies with SSH to route your traffic via SSH to your server, or even connect to a chain of servers (the middle ones acting as jump hosts).

Create a Wireguard Interface

While ssh is great for many uses cases, when hosting software it's much more convenient to have the machines reside in the same private LAN and to expose them to the open internet with great care.

In a similar fashion, it works by connecting peers securely using public/private key pairs, so adding peers consists in generating a pair, sharing the new public key with peers and taking note of their public keys.

Wireguard only sets up an interface and handles encryption. Complex routing scenarios are for you to setup with your OS's firewall. Many tools are built on top of wireguard and will configure peers and routing automatically, usually relying on a central server. They're very convenient, but there's no reason not to learn bare wigureard as it's actually quite limited and simple in configuration.

We'll manually set up Wireguard to create a private LAN between our devices.

This could be

You can follow the official quickstart tutorial for this step.

[TODO]

Running and Monitoring Software

On a server you mostly want applications to run forever. The way to do it reliably differs depending on what you're trying to run. You also need to update them to avoid getting hacked, and some way to keep track of how you configure them.

Running System Services

When your servers reboots for some reason, the OS-provided way to have a program restart is to create a service. On most modern linux systems this is handled via a SystemD unit script or a bash script. Most applications meant to run as services packaged by your distribution will have some sensible unit or script ready to use.

It might be useful to make the service wait for some other service to start, such as waiting for some "network" service or waiting for a database service to start.

The system-installed services are usually configured via some /etc/config file, and can be safely updated with the package manager. Some package managers also provide a way to check how your local config files are different from the default ones, which is useful as a crude "versioning" strategy. This won't consider entirely new files and is less comprehensive than keeping actual version control on /etc/.

Running Containers

[TODO]

Immutable and Disposable (Advanced)

[TODO]

top↑ end↓