←Back

How to host a webapp on the internet locally

Published on 16-10-2024

Why?

How to host locally... Why host locally? While there are plenty of companies/platforms that offer hosting, storage, compute services, which are free or cheap, setting them up ourselves can be a tedious task. Let's not forget about running the server and making sure it can handle requests and scale as the number of users grow. But why? Because it's fun, I can learn a few things, and more importantly I can proudly say, "I self host btw". There's nothing wrong with self-hosting, but we have to handle a lot of challenges which are usually managed by the platforms offering these services, such as AWS, which ensures VMs are running regardless of the status of the host. However, you can also use a bare metal server and host everything yourself. At the end of the day, it's up to you or your company to decide how and where to host. I am doing it for the sheer fun of it.

Overview

To keep things simple, I am going to host this complex blog page on my Raspberry Pi. It uses a Go server that serves the files. I am not going in-depth into making this complex app, but I will focus on hosting it. Since my Pi is running 24/7, I am going to use it to host the app.

The Server

The first step would be setting up your local machine and ensuring it runs 24/7. I am currently running ubuntu server on my Raspberry Pi. You can learn more about setting up your linux machine from this channel.

Once your local machine is ready, the next step would be deploying your application. This can be a simple blog website like this one, or any other app you wish to make it available on the internet. Since this is a simple app, the Pi can handle it. The complexity of your app will depend on your needs and the hardware available.

Magic

Here comes the interesting part. Our app is running locally on the LAN (behind a NAT). Most of the time, your router is a part of a larger network which is still hidden from the internet (cannot access directly). Therefore, the server is not accessible from other parts of the world - only devices within the LAN can access it. There are many options to host our site, which include:

  1. Hosting online
  2. Get a static IP and hosting, and
  3. Tunnels

There are many options for tunnels which include Ngrok and opensource alternatives. All the options mentioned above have their own implementations. Most of them require another host that acts as the other end of the tunnel, or a foreign host is provided to us. We are going to use Cloudflare tunnels because it offers tunnels as a service and is production-ready as well.

Domain

Before we can proceed, we need a domain so that our site is reachable. You can buy domains for a relatively cheap price. I bought mine at hostinger. Once the domain is ready, you can link the domain records in the cloudflare page. To proceed with this we need a cloudflare account. After creating an account, go to the home page and click the "Add a domain" button. Once you've entered your domain name, you can either do a quick scan or import the DNS files. Hostinger allows us to change the name server. Hence I chose the first option. You can proceed with whichever option suits you best. Cloudflare also provides the option to buy a domain directly from their website.

Tunnels

Once our domain is ready, navigate to the dashboard and find "Zero trust". After completing the initial setup, go to tunnels under the networks section. Create a new tunnel, set the tunnel type as Cloudflared, and follow the on screen instructions. Once the tunnel is created, install cloudflared on your server and use the command provided on the dashboard to start the connector. If the connector is set up properly, it will be visible on the dashboard. You need to enter the public URL and the local URL on the dashboard. Once this setup is done, you are good to go.

Monitoring

Once everything is set up, we need a way to monitor the status of the server. There are multiple ways to achieve this. I already have an ntfy instance running on my Pi, hence I am using it to check whether the blog server is up or not. I am utilizing the built-in cron utility to ping my app and make sure it's up and running. One caveat with this solution is that if the whole server goes down, there is no way to know unless we manually check. But this is something I will look into later.

Docker

You can use docker and host your app on your machine. Combine docker with watchtower, and you needn't touch the server for every code change. Watchtower will scan for changes in the docker image published on docker hub. If a new image is available, it will pull down the image and automatically restart the docker instance.

You can either launch multiple instances manually, or use docker or other tools to spawn multiple instances. Add a load balancer to route the requests to these instances. Use the local url of the load balancer in the cloudflared service instead of the app's url. The reason we run multiple instances is that if one instance goes down, the other instances are still available to serve the requests.

Future updates

This solution works perfectly when there are only a few users using this app. In case your app needs to scale, you can use a load balancer and run multiple instances of the app (as mentioned above). By using kubernetes and docker, we can scale them up and down by configuring everything properly. These are some aspects I will look into as I continue to build apps and experiment with them.

Closing remarks

By now, you would have realised cloudflare tunnel has done the heavy lifting while we concentrated on our project. Solutions like these enable us to explore more ways to host apps and ensure they reach people. This was a simple project and relatively easy to employ, but I plan to do more self hosting and learn a lot along the way. There are numerous ways to "self-host", but I find this a quick and easy method.

This blog is heavily inspired by Web Dev Cody and Dreams of Code. Like Web Dev Cody does in this video , you can host your application online and use tunnels to protect your application from DDOS attacks. More care should be taken to protect all the routes and resources used by the app.

This is my first time writing blogs. So feel free to give suggestions and feedbacks via twitter or mail.

Thank you 😃