aymengharbi

live in prod, no console errors (yet)

Building bloodstrike backend · Lesson 3 of 4

Connecting a Domain to an OVH VPS with Caddy

Using DNS and automatic HTTPS to publish a backend safely

On this page
  1. Choosing a subdomain
  2. Creating the DNS record
  3. Checking ports 80 and 443
  4. Installing Caddy
  5. Configuring the reverse proxy
  6. Validating and reloading the configuration
  7. Testing the public health endpoint
  8. Understanding the request path
  9. Summary

A working application on a VPS is not yet easy for a browser to reach securely. It needs a domain name, a public entry point, and a valid TLS certificate. In this lesson, we connect the Bloodstrike backend to its own subdomain and configure Caddy to handle HTTPS automatically.

Choosing a subdomain

Our main domain, gworkspace.fr, is used for several applications. We wanted the Bloodstrike frontend and backend to have clear, separate addresses.

The frontend was already deployed on Vercel at:

https://bloodstrike.gworkspace.fr

For the backend, we chose:

bloodstrike-api.gworkspace.fr

The api label makes the purpose of the subdomain clear and leaves room for other applications on the same main domain.

Separating the frontend from the backend also makes it easier to change their hosting arrangements independently.

Creating the DNS record

A domain name needs to resolve to the IP address of the server that handles its traffic.

In the OVHcloud control panel, we opened the DNS zone for gworkspace.fr and created an A record.

The important fields were:

Type: A
Subdomain: bloodstrike-api
Target: YOUR_VPS_IPV4

An A record maps a hostname to an IPv4 address.

We then checked the DNS result from the VPS.

getent ahostsv4 bloodstrike-api.gworkspace.fr

The hostname resolved to the intended public IPv4 address.

DNS changes can take time to propagate, depending on caching and the record’s previous values. If a new record does not resolve immediately, it is worth checking the record and waiting before changing anything else.

Checking ports 80 and 443

Caddy needs to receive public HTTP and HTTPS traffic. Before installing it, we checked whether another service was already listening on those ports.

sudo ss -lntp | grep -E ':(80|443)\b'

In our setup, the command returned no results, so the ports were free.

Our firewall already allowed TCP ports 80 and 443. Port 22 remained available for SSH administration.

We did not add a public firewall rule for port 8080. The game server would remain behind Caddy.

Installing Caddy

Caddy is a web server and reverse proxy that can automatically obtain and renew TLS certificates for domain names.

We installed the prerequisites and added Caddy’s official package repository using the installation instructions for Debian-based systems.

After adding the repository and its signing key, we installed the package.

sudo apt update
sudo apt install -y caddy

We checked that the binary was available.

caddy version

Then we checked the system service.

sudo systemctl status caddy --no-pager

The service was active.

Using the official repository allows the package manager to receive Caddy updates along with other system packages.

Configuring the reverse proxy

Our Node.js game server was listening locally at:

127.0.0.1:8080

We configured Caddy to receive requests for the backend domain and forward them to that local address.

We edited the configuration file:

sudo nano /etc/caddy/Caddyfile

The relevant configuration was:

bloodstrike-api.gworkspace.fr {
    reverse_proxy 127.0.0.1:8080
}

This is a small configuration, but it does two important jobs.

First, Caddy recognizes the requested hostname. Second, reverse_proxy forwards incoming HTTP requests to the Node.js process.

Caddy also supports WebSocket upgrades through its reverse proxy, which is essential for a real-time game.

Validating and reloading the configuration

We validated the configuration before applying it.

sudo caddy validate --config /etc/caddy/Caddyfile

Caddy reported that the configuration was valid. A formatting warning was also shown, so we formatted the file.

sudo caddy fmt --overwrite /etc/caddy/Caddyfile

After that, we reloaded Caddy.

sudo systemctl reload caddy

With the domain resolving correctly and the necessary ports reachable, Caddy could obtain a TLS certificate and configure HTTPS automatically.

Testing the public health endpoint

We tested the backend through its public HTTPS address.

curl -i https://bloodstrike-api.gworkspace.fr/health

The response was 200 OK, with ok in the response body.

We also tested the rooms endpoint.

curl -i https://bloodstrike-api.gworkspace.fr/rooms

It returned a valid HTTP response.

These tests confirmed that requests were reaching the application through Caddy rather than requiring direct public access to port 8080.

Understanding the request path

The architecture now looks like this:

Browser or game client
        |
        | HTTPS
        v
bloodstrike-api.gworkspace.fr
        |
        v
      Caddy
        |
        | Local HTTP
        v
  127.0.0.1:8080
        |
        v
  Node.js game server

The browser connects to the public domain. Caddy handles the secure connection and forwards the request internally.

The game server does not need to expose port 8080 to the Internet.

Summary

We created a DNS record for the backend, installed Caddy, and configured a reverse proxy to the local game server.

The public health and rooms endpoints responded successfully over HTTPS. This confirmed the DNS, TLS, and HTTP proxy path.

In the next lesson, we will look at WebSockets, browser origin checks, and the final connection between the Vercel frontend and the backend.