---
title: 'Safely Selfhosting'
date: 2024-09-28T12:14:03+03:00
draft: false
---

Selfhosting is a great way to fight decentralization, however, you might find yourself scratching your head as to how to expose those services to the internet. You could just port forward, but you'll have to deal with the problems of having to constantly update your home IP or having to constantly worry that some script kiddie will be able to take down your internet at home, which if you work from home, isn't very good. Thankfully, you can mitigate this issue by proxying everything through a VPS.

## Why should I do this?
* You won't have to deal with dynamic DNS
* You won't have to deal with skids taking down your internet.
* You won't have your ISP banging at your door, demanding that you upgrade your internet service because your website is too popular.
* You can technically run your whole setup off mobile data, but should you? No, not at all, but in case your ISP goes down you could do this.

## Requirements:
* **A VPS**: ~~I reccomend https://buyvm.net/~~ ([BuyVM's future is uncertain](https://lowendtalk.com/discussion/201647/for-immediate-release-buyvm-joins-cloudzy-ai/p1)) but you can get away with most VPS providers, granted your service doesn't break their AUP. Since I am too poor to rent another VPS from them for the sake of this tutorial, I decided to use Oracle Cloud's generous free tier.
* **A domain**: This isn't really required but realistically you're going to need one. I like https://namecheap.com/ but you could get it from other places too
* **A server**: Duh, if you don't have one of those you'll obviously have to run your services on the VPS, which at this point, why even follow this tutorial?

## Step 1. setting the VPS up.
I'll be using Ubuntu, but these commands will work on Debian too.
```
sudo apt install curl nginx certbot python3-certbot-nginx
sudo systemctl enable --now nginx
```

Now if we go to your VPS's IP we'll get the default nginx page.
![](https://fzorb.xyz/i/dnuvk.png)

## Step 2. getting a VPN up and running.
For this we'll be using OpenVPN since that's what I know best, however, you will get similar results using Wireguard if you want.

To make this guide as simple as possible, we'll be using [angristan/openvpn-install](https://github.com/angristan/openvpn-install), a script which automatically sets up an openvpn server.
```
curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh
chmod +x openvpn-install.sh
sudo ./openvpn-install.sh
```
The setup is fairly straightforward, as such, I don't think it's necesarry I document it here. You can run the script again to add additional clients.

## Step 3. setting the actual server up.
I won't go into detail on how to setup the services you want to expose to the internet. 

First, we'll make the client connect to our OpenVPN server. You must put your .ovpn file in the /etc/openvpn/client directory, and you'll also need to change the .ovpn extension to .conf
```
sudo mv *.ovpn server.conf
sudo systemctl enable --now openvpn-client@server # so we get connected on startup.
```
To check if you've done it correctly, you can do this:
```
~~curl https://fzorb.xyz/ip # this is currently broken~~
```
~~... and if it outputs your VPS's IP, congratulations, you've just connected your server to your VPS!~~  
You should instead check it with `ip a` and see if you have a `tun0` or similar interface for now.

## Step 4. forwarding HTTP requests to your own box.
When a user wants to access your website, the Nginx server running on the VPS will reverse proxy whatever site they want to access. It's pretty simple.

I'll assume you know how Nginx works, so I won't go into too much detail about how to configure. Below is a pretty simple configuration which can be edited however you want. Do with it as you will.
```conf
server {
	server_name example;
	location / {
		proxy_pass http://10.8.0.2;
		proxy_set_header Host            $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
	}
	listen 80;
	listen [::]:80;
}
``` 

And that's not all, you can also use [Nginx TCP streams](https://docs.nginx.com/nginx/admin-guide/load-balancer/tcp-udp-load-balancer/) to forward non-HTTP services, like let's say, a Minecraft server. The possibilities are truly endless, aren't they?

## Step 5. profit.
Now you've successfully exposed your service to the world wide web, isn't that cool?
