Introduction

I recently came up with the idea of running my own little URL shortener to be able to easily shortcut longer URLs. Something like this can become useful if you have limited text lengths but still want to share longer links or if you just need an easy-to-remember link for a complex URL. And since I like to be in control of my own services, I quickly built something like this myself.

Prerequisites and first ideas

Since I’m always quite eager to buy new domain names, I quickly found a suitable one and registered it with my trusted registrar: bluemedia.re (“.re” in this case was intended as an abbreviation for “redirect”).

After the usual setup of DNS and (default) mail addresses, all that was missing now was the logic that would do the actual shortening. Because I wanted to keep the whole thing as simple as possible (not yet another container or yet another database), I decided to implement the solution directly in Nginx. Since I use Nginx almost everywhere as a reverse proxy, an already-running instance of it can easily take care of this.

The configuration is very simple: There is a mapping between the desired short URI and the actual source URL, and Nginx resolves the mapping when a request is made. If no mapping exists for the specified URI, a fallback URL is used instead. The redirect is done using the HTTP status code 302 (Found), which has the advantage that you don’t get any problems with search engine indexing and also ensures that any existing embeds in the source link are still displayed by social networks and messengers.

Getting it done

The following section shows the necessary configuration, including some example short links. I’ve also added a small endpoint that simply returns an HTTP 200 status with the text “healthy.” That one is used by my status page to check if the service is actually serving requests.

# Mapping of a short URI (bluemedia.re/<URI>) to a corresponding source URL
map $uri $link_shortener_redirect_url {
  "/github" "https://github.com/BluemediaGER";
  "/mastodon" "https://chaos.social/@Bluemedia";
  "/matrix" "https://matrix.to/#/@bluemedia:chatwire.eu";
  default "https://bluemedia.dev";
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name bluemedia.re;

    access_log /log/link-shortener/access.log;
    error_log /log/link-shortener/error.log warn;

    # Truncated TLS configuration (only for the sake of completeness)
    ssl_certificate /cert/bluemedia.re/fullchain.cer;
    ssl_certificate_key /cert/bluemedia.re/bluemedia.re.key;

    # HSTS
    add_header Strict-Transport-Security "max-age=63072000" always;

    # Monitoring endpoint for Gatus
    location /uptime-kuma-healthcheck {
        default_type text/html;
        return 200 "healthy";
    }

    # Redirect to the coresponding source URL
    location / {
        return 302 $link_shortener_redirect_url;
    }
}

More short links can be easily added to the map at the top of the config file, and after reloading Nginx, you’re ready to go. That’s not nearly as elegant as a fancy management web interface and some database-backed system, but the goal of simplicity is definitely achieved.