Nowadays everything is a service. You buy some cloud service, you package your app in the way they tell you to, and that’s it.
There’s nothing wrong with that, but services aren’t always the answer. Also, you miss out on a true learning experience. It’s always valuable to know what happens under the hood. The more you know, the better you are at hunting down bugs, and designing complex systems.
In this post I’ll show how to create a simple DIY server, and how to host a simple web app. But not only that, we’ll start from the ground up, and understand how every piece works. At least to a level of detail relevant to most developers out there 🙂
Networking
Let’s start from the beginning and talk about networking for a minute.
When two computers want to talk over the internet (e.g., your personal computer loading this blog post) they need a way to package and send information back and forth. This data exchange is managed by your computer’s operating system, which coordinates your networking chip, so it can talk to your router, and in turn to your Internet Service Provider (ISP). Your ISP is what actually carries and routes your data across the internet.
The most common ways to package information (known as protocols) are TCP and UDP. TCP establishes a formal, guaranteed connection (like a phone call), while UDP is fire-and-forget (like dropping postcards in the mail).
TCP is used for reliability, and it’s what web applications use. UDP is used for performance, and it’s used by real-time systems like video calls and online games.
If you’ve ever heard the term “dropping packets”, it just means some of those data packages got lost on their way across the internet. With TCP, your computer will notice, pause, and ask for those lost packages to be resent. With UDP, your computer doesn’t care, it just keeps moving forward, which is why your video call might briefly glitch or pixelate instead of freezing entirely.
Now, web servers don’t use TCP directly, but instead they have a layer on top called HTTP. Nowadays though we use the modern, secure version: HTTPS. To keep things simple I’ll just use HTTP and HTTPS interchangeably from now on.
TCP is only the transportation layer, but it doesn’t care about what data it’s actually carrying. HTTP is the shape of that data. If TCP is the delivery truck, HTTP is the actual envelope that you receive.
Your browser then opens that HTTP envelope to render the page on your screen. Inside, the web server has packed the raw HTML, CSS, images, and other assets that make up the website, all safely transported over the wire via TCP.
Servers
A server is computer configured to receive network connections. For example, a web server is a computer somewhere in the world that uses the TCP protocol to listen for incoming HTTP requests and return HTTP responses.
A web application is, at its core, a web server that receives HTTP requests, and returns HTTP responses. You could write your own server from scratch if you wanted, but realistically, most developers will use a library or framework to do the heavy lifting.
Express.js is a good example of how simple this can be:
const express = require('express');const app = express();// When someone makes an HTTP GET request to our root URL ('/'),// we send back an HTTP response containing some HTML.app.get('/', (req, res) => {res.send("<h1>Hello, world!</h1>");});app.listen(3000); // Tell the server to start listening for TCP connections on port 3000
When you run your server with, for example, node server.js, it will start listening for TCP connections on port 3000. This means if you open up your browser and navigate to http://localhost:3000, your browser will send an HTTP request to your local server, and you’ll see “Hello, world!” rendered as a large heading on the page.
From localhost to the World
This works when running your app locally, but how do you make it accessible to everyone on the internet? This is where hosting services come in.
If your ISP allows it, you actually can host it right from your living room. You would just need to configure your router to direct incoming traffic to your computer (a process called port forwarding), open port 3000 on your firewall, and give people your home’s public IP address.
If they typed http://<your-public-ip>:3000 into their browser, they would connect directly to your laptop!
Of course, most applications need an actual dedicated machine to function as servers, as well as a special, high-speed internet connection. Some companies do have physical machines they keep either at their offices or in some special data center that work somewhat like that.
Of course, most production applications need a dedicated machine to function as a reliable server, along with a high-speed, enterprise-grade internet connection. Some companies still buy and maintain their own physical machines, either keeping them right in their offices or renting space in a specialized datacenter.
However, most developers and companies today simply rent a Virtual Machine (VM) from a cloud provider like AWS, DigitalOcean, or Linode. These companies specialize in managing physical infrastructure. They have massive datacenters with lightning-fast internet connections, backup power generator systems, and pre-configured routers. When you rent a VM, you’re essentially getting a private slice of a much larger physical computer. All you have to do is log in, set up your operating system, and run your code!
Most of these companies offer more than just VMs, they also offer fully managed services. Essentially, you can just hand them your application code, and they will run it, scale it, and keep it online. There’s no need for you to configure a server, worry about Linux updates, or manage firewalls.
Sometimes, using those services is the best solution. In this article, we’ll take a look at how to configure a VM to host a simple web app in a modern, standard way.
Configuring your VM
This is where we’ll get down business. I’ll use VirtualBox to create a VM in my personal computer, this way I don’t need a paid cloud account, and you can do the same to follow along.
While the exact steps might vary slightly depending on your operating system or chosen cloud provider, the core concepts remain identical. This section isn’t meant to be a rigid, step-by-step tutorial (there are already fantastic step-by-step guides all over the internet, like the DigitalOcean tutorials). Instead, our goal here is to help you understand all the moving pieces, how they interact, and why we configure them the way we do.