This is a story about having your own web app server in the cheapest, simplest, functional manner.
Let's assume that for whatever reason you have some apps you want to use. Me, I have two:
Gitea: sort of your own GitHub. Why? Because owning your own data is OK, I think. So I want the POSSIBILITY of having my own server. You can still clone the repos to GitHub so you lose nothing.
My own site: Because, again, what I write is mine, and why not host it myself instead of uploading to Medium or some other similarly malignant pustule of a site. Besides, I've been doing it for over 20 years, so why stop now.
It could be anything! Some app you are developing, something you want to try, OwnCloud or whatever, if you are the sort of nerd that wants his own app/site ... it's doable.
So let's configure, from scratch, everything you need to access those sites/apps.
Level 1: self hosting
For your own apps, you will need your own hardware in which they can run. Let's consider the cheapest general use computer you can buy that has some sort of network support?
A Raspberry Pi Zero W ... 10 bucks if you could buy one. But hey, I have one or six of them, the one I'll use is called pinky.
If you don't have or don't want one of those, anything that can run Linux is probably OK. Or windows. Or MacOS, but this guide assumes Linux, so I recommend that for now. The hardware can probably by any working computer, there is probably no computer too slow for this.
Or rather, it depends on what you want to run in it, so YMMV.
I won't go into details, but install whatever you want to run, and make it work locally. In my case that means:
- Gitea: it's working and visible at http://pinky.local:3000
- My site: working and visible at http://pinky.local:8000
How? Look it up for whatever thing you are trying to make work dude!
As long as it's not working and accessible in your local networ? Good, Level Up!
Level 2: remote access
What about using that site when you are not on the same local network?
Well, that won't work. Of course http://pinky.local:3000 only works locally, so let's fix that.
There are many ways, but this is one: tailscale, specifically the free one-person version.
What's tailscale? It's a VPN.
It's a personal VPN. If you register and install it in at least a couple of machines it will create a network connecting all machines to each other even when they are not in the same local network.
So if you install tailscale on a server (pinky in my case) and in the notebook you normally use (in this case salma) those machines can always see each other using some special names tailscale gives them.
Clicking on one of the machines gives details about it:
As you can see pinky now is also known as pinky.ralsina.github.beta.tailscale.net thanks to tailscale.
Don't bother trying to access that because it only works if you are members of my VPN and you ain't gonna.
But I can!
Maybe this is all you need. Right now you can access your servers from anywhere as long as you are logged into the tailscale VPN. Nice!
But what about other people? Then you need to Level UP!
Level 3: Ingress Rules
Again there are many ways to give others access to your server, but this is one I like: fly.io
Fly is a company that gives you the ability to run "stuff" on "free" virtual machines, within certain limits. For example, not more than 160GB of outgoing data a month, more than that and they start charging.
So, how about running one of those VMs and connecting it to our tailscale VPN? And then run there a reverse proxy in it so it's an intermediary that allows third parties access to our servers? Right?
Well, this is the documentation you need to connect a Fly VM to a Tailscale VPN.
Modify nginx.conf as needed to route connections where you want.
At this point you can probably not use two hostnames (later we can) and
server_name should be
the public name Fly gave you, in my case white-wave-7409.fly.dev
Once you do that, you should be able to access something using that hostname:
As you can see it's using HTTPS, because Fly also provides an "outer" reverse proxy that's doing HTTPS termination, so no need to create certificates or anything.
And now we have a website, accessible from any device with an internet connection, for free (up to 160GB) ... mission accomplished!
Except ... that URL is ugly. I would rather have Gitea use something like git.ralsina.me and my home-hosted site at home.ralsina.me, right?
Well, we need to Level UP again!
Level 4: Custom DNS
There are infinite ways to do this but this is the one I used.
Cloudflare works as a free DNS server. If you already have a domain, configure it, or use your own DNS server, or whatever.
If you don't own a domain buy or borrow one, use google, figure it out.
Once you have Cloudflare or whatever DNS working, configure CNAME records for each host you want. I did two:
Both are pointed to the name Fly gave me, so they resolve llike this:
> host git.ralsina.me git.ralsina.me is an alias for white-wave-7409.fly.dev. white-wave-7409.fly.dev has address 18.104.22.168 white-wave-7409.fly.dev has IPv6 address 2a09:8280:1::6:3716
If you are using cloudflare they must be configured as "DNS Only".
The last step is telling Fly that we use those CNAMEs so we need to create and register SSL certificates for them. Luckily that's easy, just run these commands in the machine where you are managing your Fly app:
> flyctl certs create git.ralsina.me > flyctl certs create home.ralsina.me
Again fix nginx config so it uses the hostnames to route requests wherever they should go and everything should "Just Work".
What have we achieved?
- Servers accessible from anywhere: Gitea and My site
- Which are running in the cheapest possible server
- With nice URLs
- For free
- Without having to make holes and reconfigure firewalls.
I have not seen a guide that explains this all the way, so hopefully it will be useful for someone!