Well, it’s official. I’m a blogger now:

This is me

Why do this?

A new hobby appears

A few weeks ago, I took a vacation so I could visit a friend for his birthday. He frequently picks up technical hobbies and projects, and on this visit, he showed me his self-hosted media server isolated to his home network.

Well hot damn, I thought that was cool!

The server offers the convenience of streaming any of your owned media to any device on your home network. For example, you could watch a video on your phone or laptop, even if it actually resides on your PC (running the media server software). I don’t know about you, but there’s something about this that I just find neat. So, inspired by my friend, I decided to set up something similar after the trip.

I was able to get a Jellyfin server up and running pretty easily. However, I ran into a problem: What media should the media server serve?

Serving media without getting served

Here’s a fun thought experiment: Let’s say you go out, buy a DVD or Blu-ray of your favorite movie, bring it home, and watch it on your Linux PC. Have you done anything wrong?

Well, according to the US Government, you have.

It is currently illegal to watch a DVD or Blu-ray on Linux. Here’s a nice article that discusses DVDs specifically, but the long story short is that the media files on a DVD or Blu-ray disc are encrypted, and decoding them without approval breaks the DMCA and/or DRM, and is therefore illegal. Physical DVD/Blu-ray players are fine since they obtain a license that permits them to decode the disc content. Interestingly, obtaining a license requires implementing other restrictions, such as region-locking the player to only play discs from the same region. So, if you buy a DVD on vacation out of the country, you may not be able to play it when you get back home.

So, even watching a DVD you own is illegal on Linux, but doesn’t seem to have been challenged in court, and so lives in a gray area. Pulling the media files off of a DVD is also a gray area, but is more clear-cut since it involves copying the content in some way. If you play a DVD for a friend in your living room, you’re legally in the clear, but if you watch the DVD with your friend virtually (e.g., streaming over Zoom or Discord), that’s illegal. And lastly, media piracy isn’t in a gray area at all, and is clearly illegal.

Unfortunately, this all boils down to one thing: Putting basically any commercial content, even if it was legally obtained, on your home media server is probably illegal. Do I have to say I’m not a lawyer, or that this isn’t legal advice? I can only dream the blog I made on a whim would be so impactful.

This leaves you with non-commercial content. For me, that means pictures and videos of my hikes / minerals / cats / blacksmithing projects / etc. All well and good. Until they outlaw cats on the internet, I think I’ll be okay.

Streaming? Like, what water does?

It took about two seconds for me to want to make my server accessible to my girlfriend and my mother. Setting up the server locally was a breeze, but safely exposing it to the wild internet is a whole different story.

I ended up moving the server software into a Docker container (and everything else I mention here will be containerized) to help limit its reach, then put a Caddy Reverse Proxy in front of it (see also TLS Termination Proxy). Caddy automatically handles the nuisance of obtaining SSL certificates and offers greater privacy and security than if you were to just expose your backend applications to the web.

This set up my PC so that it could handle incoming requests on the right ports. However, it’s not the end of the story, because we need a way for requests to get to the PC in the first place.

The easier jump to handle is that from the router to the PC. For this, all you need to do is set up port forwarding. I learned that Spectrum no longer lets you configure routers through the default gateway, and instead you have to download their stupid fucking smartphone app. Ah well, what could we expect from them?

The harder jump to handle is getting requests from the wild internet to your router. In theory, you can just share your public IP address, but that scares people, both from a security standpoint and from a technical standpoint. You can’t hand your grandpa an IP address and expect him to visit your media server, though I guess it depends on the grandpa.

How this actually gets handled is that you pay a domain registrar for (temporary) domain ownership, and then they handle pointing that domain at your public IP (i.e., they deal with getting the DNS servers updated). This took me on a small tangent, because I wondered how domain registrars even come to be. It turns out an organization called IANA administers all domain names, IP addresses, etc. Unfortunately, they don’t sell domain names directly, and require you to go through a registrar. Moreover, you probably can’t just go become a registrar yourself. I thought I’d be clever by becoming a registrar and then selling myself whatever unclaimed domains I wanted for $0. Alas, the reason not everyone does this is that it’s not actually cheap and easy and convenient. It takes a $3,500 application fee, a $4,000 yearly accreditation fee, and proof of having at least $70,000 of working capital, among other requirements. So, there’s no loophole here.

Instead, I paid about $3 for connor.wtf. As it turns out, .wtf domains aren’t actually in that high of demand! They’re cheap and available, so I was able to grab my own name. Yay!

Anyway, once that was done, all I had to do was tell my registrar to point a subdomain at my router’s IP, and that got it working. So we’re all done, right?

Nope.

A router’s IP address occasionally changes, and I don’t want to deal with that. There’s a nice project that dynamically updates DNS records using the APIs of common domain registrars, aptly named ddns-updater. All this took was flipping some switches in my registrar, grabbing API keys, and setting up another Docker container.

And then it was done!1

Weren’t we talking about a blog?

Ah, right, the blog. With all that headache, it’s surprisingly easy to just tack on a website. The work of getting communications between my PC and the wild internet is already done. A reverse proxy is already set up. All that was remaining was to set up a container with some fileserver software, and then we’d be up and running!

I ended up using another Caddy container for the fileserver. Technically, I could have used the reverse-proxy container for this purpose as well, but I didn’t for two reasons. The first is that I have the reverse proxy set up on a partition that I don’t want my website on. The other is that although Caddy can handle both concerns in one place, I can envision myself wanting a more powerful website engine someday. For now, a static website is fine, but who knows?

The last little bit of fun here was setting up Hugo, which is a static site generator. Caddy just serves files, but it doesn’t create those files in the first place. I don’t need anything complicated, which is where Hugo comes in. Hugo is a static site generator, which means it takes as input some simple representation of a website, then spits out pretty HTML files. In this case, it takes in relatively simple markdown files, and a theme, and generates the site from there. Those site files are then served by Caddy.

There are quite a few themes available, and I just chose one I liked. The cool thing is that if I want to switch to a different theme, I can just swap it out without touching the source markdown files. Neat!

The point

At long last, I can explain why I wanted a blog: It was easy and fun to slot into my existing self-hosting stack.

Wait, do you expect anyone to read it?

No, not really. However, a few times a year, I’ll work on a project and I’ll want to explain it to a friend or family member. This usually results in me sending a flurry of hastily written texts that don’t quite capture all the little details. I think it would be nice to have a place that I can not only reflect on my projects, but also easily share all those details.

What now?

I don’t know, I’ll probably get distracted by something else in a week! But for now I’ll keep playing around with this when I remember.


  1. Give or take a few more headaches that aren’t worth getting into here. ↩︎