The Cat's den


Lately I have been playing around with Open Broadcaster Software while using nginx as a RTMP server in order to share games and videos with my friends, as well as my day-to-day amateur sysadmin fun, in a somewhat more private fashion than using a public platform like Twitch or YouTube.

When streaming to nginx from OBS, I noticed on the server that video fragments are written to the disk in order to build the streaming playlist. And when you're streaming 24/7, it adds up quite fast, especially for 1080p content at 60 FPS. At a rate of ~2.5 GB per hour, we're looking at almost 1.8 TB (!!) of data written to the disk every month, which is about twice the capacity of the drive. That will definitely cause the premature death of my SSD, or at least increase substantially its wear level.

A lot of small data chunks continuously written to disk, but only stored for a few seconds ? Sounds like a perfect job for a ramdisk.

Creating the ramdisk

Warning : By design, any file stored in a tmpfs filesystem does not survive a reboot !

Create your mount point mkdir -p /mnt/ramdisk/nginx

Declare your ramdisk in /etc/fstab by adding the following line

tmpfs /mnt/ramdisk/nginx tmpfs rw,size=32M 0 0

Mount the ramdisk with mount -a

Configuring nginx

In your nginx config file, declare recursive_error_pages on; inside the http {} block.

The recursive error pages is the trick that will allow us to serve static pages from the hard drive, as well as dynamic video content from the ramdisk.

Edit the locations in the server {} block

location / {
    root /var/www/html/;
    error_page 404 = @ramdisk;

location @ramdisk {
    root /mnt/ramdisk/nginx/;

Basically, we're instructing nginx to serve content from the hard disk by default. If no content is found (404), try to serve the content from the ramdisk.

Restart nginx and you should be good to go !

Complete nginx config file example

http {
    recursive_error_pages on;
    server {
        listen 80;
        server_name example.tld;
        location / {
            root /var/www/html/;
            error_page 404 = @ramdisk;
        location @ramdisk {
            root /mnt/ramdisk/nginx/;

TOR Header


Following this procedure will NOT GUARANTEE that the website you're serving over the Tor network cannot be traced back to you ! Just because you're serving content over the Tor network does not mean you're immune to de-anonymization !

This guide has been written for educational purposes ONLY and shall not be considered a reference for serving content anonymously over the Internet.

I will not endorse any responsibility when you're caught serving malicious or unlawful content.

Also, no offense, but if you need this tutorial to get things up and running, you probably better take a step back and reconsider what you're doing.

What do onions do ?

The technical stuff


This tutorial will assume you already have an instance of caddy up and running, serving a website on the clearnet. Our goal here is to serve this website from an .onion address over the Tor network.

Install Tor

Add the Tor Project repository to your sources

echo "deb http://deb.torproject.org/torproject.org <release_name> main" | tee /etc/apt/sources.list.d/tor-repo.list

Grab the signing key and import them

gpg --keyserver pool.sks-keyservers.net --recv A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89
gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | apt-key add -

Refresh your sources, then install the deb.torproject.org-keyring package to keep the signing key up to date, and the tor package

apt install deb.torproject.org-keyring tor

Configure Tor

Edit the /etc/tor/torrc file and declare a new hidden service :

HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80
HiddenServiceVersion 2

The HiddenServiceVersion 2 directive instructs Tor to generate an onion v2 address for your hidden service instead of an onion v3 address. Onion v3 is the new generation of Tor Onion Hidden Services. While the most noticable change is the increase in address length, onion v3 also uses better cryptography (Elliptic Curve Cryptography rather than RSA), and has an improved hidden service directory protocol.
Use onion v3.

Restart the Tor service.

After restarting, Tor generates an .onion address and its associated private key. The /var/lib/tor/hidden_service/hostname file should contain something like 5h4downetfknk6jd.onion

Reconfigure caddy

Edit the /etc/caddy/Caddyfile file and declare the previously generated .onion domain :

5h4downetfknk6jd.onion:80 {
        root /var/www/
        tls off

Restart the caddy service.

Visit your hidden service

Congratulations ! You should now be able to visit your website anonymously using the Tor Browser, without leaving the Tor network.

This blog is available at the following locations :

Bonus : Vanity addresses

If you fancy a (somewhat) custom address instead of the default garbage, you can take a look at the following software :

  • Scallion for onion v2 vanity addresses
  • mkp224o for onion v3 vanity addresses