A server is a computer which is accessible over the internet. A server allows a developer to share their work between different machines. It is all a developer needs to create their own personal cloud[1].
After completing this guide, you will have a secure personal server that you can access over the internet. This guide will use specific tools to accomplish its task, but the principles are universal.
Again, a server is just a computer which is accessible over the internet. This is a low bar to clear, especially because performance is rarely a concern - most servers spend 99.99% of their time doing absolutely nothing. Given this, there are two main ways of setting up the hardware for a server:
Due to the economics of scale, it will almost always be cheaper and simpler to rent a machine from a cloud provider. This site is currently hosted on a $3.00/month virtual machine from Vultr. Other cloud providers like AWS are also a good choice. The cheapest machine will usually be enough. Cloud providers normally allow you to grow your drives and request more compute capacity with just a few button presses, so starting small is a good idea. However, if renting a machine, make sure you get an IPV4 address and consider purchasing regular backups as well. IPV6 still isn't ready, and the backups are nice peace of mind for right now. We can save some cash by implementing backups ourselves later.
If you're still concerned about renting a cloud machine for privacy reasons, understand that true privacy is currently impossible[2], but at by setting up a private server, you are taking massive leaps in the right direction. Quick movement in the right direction is progress. Holding off until perfection can be achieved is procrastination. That being said, if your primary concern is privacy, self-hosting on bare-metal ARM or RISC-V processors seems like the way to go.
The following configuration needs to be done on the server itself, since it is not accessible via the internet yet.
There are three critical pieces of software that our server will need:
An OS: This site runs on OpenBSD. OpenBSD is UNIX-like, and is designed with security and standardization as primary goals. These are very nice properties for servers. This, combined with other benefits[3], makes OpenBSD an easy recommendation for a server OS.
In my opinion, the BSDs (OpenBSD, FreeBSD, NetBSD) are the best choices for servers. Linux distros are also a good choice (Fedora, Debian, Arch, etc). I'd stay away from Windows and MacOS - these are simply the wrong tools for the job.
A Firewall: This allows us to control what type of messages we can send and receive on our server - which is great for security. There is firewall software, or you can have physical (hardware) firewall which sits in between the router and the server. A physical firewall has a few benefits:
Since we're starting off with just a single machine, these
issues are not a concern, and there are no significant
differences in security between software and hardware firewalls,
so a software firewall is the way to go. Some good options are
pf
(or a variant) which is preinstalled on the
BSDs, and ufw
(or whatever the OS recommends) on Linux.
ssh: this allows you to securely connect to your server over the internet. OpenSSH comes pre-installed on almost every OS.
Other software, such as your prefered text editor, are not mentioned.
Before we allow our machine to be accessible over the internet, we'll want to configure it to be secure:
useradd
interactive tool.
The adduser
tool is available otherwise.
Give your user a password.
/etc/doas.conf
file, replacing [user] with your own
username:
On Linux, this you would instead edit the/etc/doas.conf on OpenBSD server. . . permit [user] as root . . .
/etc/sudoers
file. Check the manpage for what specifically to change.
/etc/ssh/sshd_config
config file to
disallow password logins and to make the ssh daemon run on a
non-standard,
unused port. We keep ssh off of port 22 to reduce the amount of spam we get
from lowest common denominator web attacks. This is not a security
measure. The following lines are usually changed (remember to modify
[secret-port] to fit your setup):
Restart the ssh daemon after this is done. On openbsd this is likely:/etc/ssh/sshd_config. . . Port [secret-port] PasswordAuthentication no . . .
rcctl restart sshd
ssh-keygen -t ed25519 -f ~/.ssh/myserver
~/.ssh/authorized_keys
file on your server.
This assumes your home directory is the home directory of
the (unprivelaged) user who you would like to login as.
Append the contents on a new line.
~/.ssh/config on client. . . Host myserver Hostname [server-ip] User [server-user] IdentityFile ~/.ssh/myserver Port [secret-port] ...
pf
firewall config file below. pf
is a
stateful firewall for OpenBSD, meaning that one only needs
to set a firewall rule for request packets. The connection
state will then be cached, and response packets on the same
connection will be allowed since the state is matched.
have your firewall block all incoming and outgoing network
traffic.
Then, allow the following:
ping
requests.
/etc/pf.conf
file as a result of these
changes. It is customized towards a Vultr-provided machine. Remember
to change [secret-port]
. The last two block rules came
by default with OpenBSD:
NOTE: It is odd that IPv6 requires me to pass pass these rules both in and out. I discovered that this IPv6 configuration worked only through testing, and it needs further understanding./etc/pf.conf on OpenBSD server# $OpenBSD: pf.conf,v 1.55 2017/12/03 20:40:04 sthen Exp $ # # See pf.conf(5) and /etc/examples/pf.conf block all # block all trafic by default set block-policy return # return a failure message on drop. debugging only. set skip on lo # local requests are allowed pass in proto { tcp udp } to port [secret-port] # ssh pass in inet proto icmp icmp-type { echoreq } # Allow for pinging IPv4 pass inet6 proto icmp6 icmp6-type { unreach timex echoreq routeradv neighbrsol neighbradv} # Allow for pinging IPv6 pass out proto { tcp udp } to { 108.61.10.10 2001:19f0:300:1704::6 } port 53 # Vultr high-speed DNS IPv4/6. Use Quad9 or Cloudflare otherwise. pass out proto udp to { time.constant.com } port 123 # Vultr high-speed NTP server. Use pool.ntp.org otherwise. pass out proto { tcp udp } to { 9.9.9.9 2620:fe::fe www.google.com } port 443 # NTP constraints pass out proto tcp to cdn.openbsd.org port 443 # HTTPS for package downloads
ksh
shell look much prettier with
a color-coded prompt.
We need to reach our server over the internet. We have a few options here:
If decide not to use a domain name, skip over this section. Otherwise, you'll want to buy a domain from a reputable registrar. The registrar is only useful for us to:
These are typically short and infrequent actions, so don't get too hung up on who your registrar is. This site's domain is rented from Epik for $15/yr, simply because someone else told me to use Epik years ago, and I've never had a problem. Again the choice isn't critical. The main difference between registrars will be their fees and privacy policies. Regardless, you can transfer your domain between registrars.
When we buy a domain from a registrar, we receive exclusive rights to use that domain, yet, but we also receive a set amount of space on a their servers where we are meant to put information about our domain. This info is called our DNS (Domain Name Server) records. Among other information, these records store a mapping from a domain to an IP address.
Cloudflare has a great explanation on how DNS works. The short version is that we need something called an A record to point to an IPv4 address, or an AAAA record to point to an IPv6 address. There will be a TTL (time-to-live) field as well whic tells the DNS server how long to cache your records for before an update. Higher TTL will result in quicker DNS lookups due to caching, but while we are just setting up our server, lets leave the TTL to 300 so that we can make changes relatively quickly. Once everything is set up, its not a bad idea to increase this TTL. Here's roughly what your A/AAAA DNS records should look like:
A/AAAA DNS Recordsprefix record type value TTL -------------------------------------------- A 192.0.2.1 300 AAAA [2001:3f37::] 300 www A 192.0.2.1 300 www AAAA [2001:3f37::] 300
As you can see, my site has 2 A records and 2 AAAA records. Since I am using both A and AAAA, this means that my server must have both a valid IPv4 and a valid IPv6 address. Each record will exist for 300 seconds (5 minutes) before it is updated. In additional to having A/AAAA records with no prefix, I've also included A/AAAA records with the www. This way both example.com (no prefix) and www.example.com (www prefix) will resolve to the same server. You may also commonly see DNS records printed out using a different format called the BIND format.
At this point you should have a personal server. This is the foundation to begin building your personal cloud onto. Check out some other guides so that we can start making this server work for us.