Dwaragesh CMy Own Server
The journey of Self Hosting:
It all started when I saw an old laptop laying around in my friend’s home. Naturally, I enquired him regarding on why it’s like that. He claimed that the laptop is most likely dead because the last time it was booted up, it took about 30 minutes along with a weird sound in the bottom side of the laptop. Hmmm. My instincts told me it should be MicroSLOP behind the slow boot or it could be a HDD as the boot drive instead of the SSD. With confusion I left his place and went to do my work. I couldn’t sleep that day. “What if the laptop has no problem and this guy hallucinates?” “What if he configured his HDD as the boot drive instead of his SSD accidentally?” “What if he broke his laptop with his cricket bat intentionally just to reason for his new gaming laptop?”. A lot more thoughts clouded my brain, not allowing me to sleep in peace. And eventually, I was able to forget this.
A few days later, I was suggested to use Supabase as a cloud-driven database (PostgreSQL) for my project to basically save up local storage and include cloud into the stack. “Is this really secure?” “How about latency?” “Why should I and why shouldn’t I?” and etc. Gosh why I am so bad at managing thoughts :( But just when I was relieving myself of this endless torture, I had a quick spark of an idea. Old laptop … remote database …. engineering…. Oh wait, that old laptop?Can it be my Supabase?
Act 1 : The Enthusiasm
Once I had this question, I immediately searched up the Internet for possible tutorials. “How to convert an old laptop into database easy tutorial”, “How to setup an old laptop as PostgreSQL server easy 5 mins” and all childish nonsense of keywords. Yeah, isn’t that enthusiasm? Well 😅. I didn’t find much resources that gave detailed information on that except some Reddit threads and Generative AI. It was actually possible. But before much research, I got to know that Supabase offers so much services than just database. Wait … What?! “Supabase is much like your back end of the software - authentication, database, simple logic, analytics and even more”. Now what this one statement, my entire enthusiasm is disturbed….
Act 2 : The Disturbance
After the initial idea of just a remote PostgreSQL server got disturbed (because I was careless about knowing all the services offered by Supabase), my thoughts are having the upper hand again. What’s the use of having a dedicated system for just a database? Why not a entire back end server … server …. why not a server? Hey! Why can’t I build a server and use it as a hosting platform?! Hey!! My voice at that moment sounded like Archimedes shouting Eureka 😂
Act 3 : The Plan
It’s easier said than done. And this suits well for a server. Without much knowledge on what is a server, I jumped into this rabbit hole, head first 😊Such an idiot I am. To start from scratch, I tried booting the device first to know if it can even dream about being useful. I honestly didn’t want to spend much on this server thing. And by whatever miracle, it booted, in 5 minutes 😀 wait, 5 minutes? The stark realization of a manipulation my friend made to buy a laptop made me tilt my sight towards him. But it wasn’t his fault. It was his first time seeing his old laptop boot this fast 😂. The specs were actually decent - 8 GB of sweet DDR4 RAM, i5 10th Gen, 4 Cores of CPU, a DGPU, 256 GB SSD, a dead HDD and a few this, few that. Overall, an amazing spec tbh! A good laptop for general usage. And now, after a clear image of what I have, straight to the plan. Wait.. what plan? No plan and, that’s the plan 😀. One thing at a time with proper research, that’s all. First, the OS. Windows is .. meh, it consumes lot of RAM and it could be possible because of that the laptop didn’t even boot. So, Linux for sure. Yay!! And Ubuntu Server suits perfect for a self hosted home lab server. Why? No GUI - meaning no resources spent for unnecessary processing along with providing a clean and no bloat working environment. Step one done! The workplace is secured. Now, how does the server work? And that’s where we move to the server architecture!
Act 4 : The Architecture
My first thought was to make a single docker container (will let you know why docker in the later steps). But, what if any service in the container failed? Debugging would be a nightmare without evidently knowing whether the front end failed or the back end. So, one container for front end, one container for the back end, and one for the database. And this is the setup for one project. There will be many such projects hosted in this server and this will be the setup for each one of them. Why docker in the first place? Docker containerization can be understood like this - am allocating/ creating a dedicated computer for a service. That’s all. Why? Imagine I install Node dependencies directly in the workplace directory. Over the time, I have to manage and check whether this is installed or where is it installed and what’s even worse is, version of your dependencies. Dockers containers are made to solve al this. So, even when a service is entirely faulty, delete the container and make a new container! No damage to your OS or directory!
Now that we have a plan of creating containers, how will the front end send API requests to the back end if they are isolated? 😶 . That’s where we use a new technology - Docker Networks! I am currently learning about this, but in short, it configures and provides linkage with the docker containers present in the network using internal DNS by routing with their container names, rather than their container IP. This is such a breakthrough in connecting different services under the hood of the project.
With this simple thought in mind, I installed the following in the server which now boots up perfectly fine:
Git
Docker
Fastfetch
Now that the project architecture is done, what will happen when I host multiple projects at once? Who will redirect and manage all the docker networks? And there comes our star, Nginx!
Act 5: Nginx and Reverse Proxy
When there’s multiple projects and conceptually, the only differentiating feature between all their API requests and responses are their URLs. Here Nginx (configured as a central container) received all the requests from users outside the server, then routes those particular requests to the correct docker network based on the URL and it’s respective project. That’s all. And that’s just a huge role.
Nginx here acts as the reverse proxy by receiving all the requests and not exposing any of the services to the users, thereby ensuring security.
We have setup the service playground (docker containers), communication lines (docker network) and even a manager for them (nginx). But we haven’t done anything so that people can interact with the server, right? Deployment! And it’s next!
Act 6: Deployment
Almost… yeah! Almost we are done with putting the services in place. But the architecture is incomplete without adding the most important piece - Deployment! There are multiple ways here - some of which is port forwarding and utilizing Cloudflare tunnels. Port forwarding involves exposing your entire IP address to the internet. Although IP addresses changes at regular intervals by your ISP, it’s still dangerous out there with automated bots constantly scanning for open IPs. So, just forget this.
Cloudflare tunnels are an awesome choice here. It’s free. Good documentation. Easy to implement. What else do you need other than this, huh? So, what is tunnels.
Cloudflare tunnels brought in a new way to host and deploy your projects to a dedicated domain without exposing any of your ports or your IP address to the internet. So, one end of the tunnel is connected to the server, and the other end to the domain (dwaragesh.me or so..). Now, how does the tunnel connect itself to the server? How does it recognize where to connect? That’s where another part comes in which is Cloudflared daemon [daemon = background process in simple terms]. This thing lodges itself in the server as another container and acts as a connector for the tunnel’s one end. Whenever one IP goes dead or inactive (during ISP’s IP cycling), the cloudlfared daemon automatically redials without any configuration.
Why this approach is easier? The concept of tunneling removes the headache of buying a static and permanent IP from the ISP, and also the risk of exposing ports directly to the internet. Cloudflare opens outbound connection to the Cloudflare edge network rather than the internet - providing additional services like CDN and load balancing for free (Interesting, isn’t it?).
And now, we can safely say that the project of making a self hosted server, comes to an end. But is there any scope to remote access and control over the server?
SSH? Absolutely! SSH is the best way to connect. But here’s a twist. Instead of connecting to the IP of the server (out of range over the LAN), connect to the CloudFlare tunnel. Follow up with their documentation after this and you’ll get a clean idea on how it goes.
Act 7 : Reflection
Now that over concept of server is done, it’s more important to understand what we have done.
Step 1: Test and Secure the hardware
Step 2: Boot Ubuntu Server by clearing out the drive [Technically you can dual boot, but when you log in to your other OS, the server is down]
Step 3: Install Docker and Git via APT (don’t use Snap Packages)
Step 4: Setup the folder architecture within the OS to clearly differentiate work environments and projects
Step 5: Clone a project from GitHub with a defined docker-compose.yaml and docker image files for the front and back end.
Step 6: Instantiate the docker containers from the compose file and setup Nginx to control the network of containers.
Step 7: Setup Cloudflare tunnels and install Cloudflared daemon in the project repository [refer documentation for the steps]
Step 8: In Cloudflare’s dashboard, connect your domain and set up DNS record for the same.
Step 9: Connect your daemon with the created tunnel’s one end.
Step 10: Run everything once and check your server!
Congratulations! Your server is now running! 🥳
Note: There are several other aspects of building a server which includes security, backup volumes, traffic routing, container logs and etc. It’s better if you experiment and learn it alongside creating your server (Though it’s not much important for hobbyist projects)