<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"
    xmlns:fh="http://purl.org/syndication/history/1.0"
    xmlns:at="http://purl.org/atompub/tombstones/1.0">

    <title>Sockpuppet: Blog</title>
    
    <subtitle><![CDATA[Updates, articles, and behind-the-scenes content.]]></subtitle>
    
    <link href="https://sockpuppet.band/blog/feed?id=2089&amp;tag=technology" rel="self" />
    
    <link href="https://sockpuppet.band/blog/feed?tag=technology" rel="current" />
    <fh:archive/>
    

    <link href="https://busybee.superfeedr.com" rel="hub" />
    
    
    <link href="https://sockpuppet.band/blog/" />
    <id>tag:sockpuppet.band,2026-05-14:blog</id>
    <updated>2026-08-28T01:11:03-07:00</updated>

    

    <entry>
        
        <title>Self-hosted streaming CDN</title>
        <link href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN" rel="alternate" type="text/html" />
        <published>2025-09-26T20:22:51-07:00</published>
        <updated>2026-08-28T01:11:03-07:00</updated>
        <id>urn:uuid:2a025873-f8cb-59b0-a816-98cf02912659</id>
        <author><name>fluffy</name></author>
        <summary type="html"><![CDATA[<p>Performers who do streaming-based performances on VRChat and other places have a few options for actually providing their stream. Once upon a time it was preetty common for people to use Twitch or YouTube Live, but those are now being locked down due to advertising considerations. So, many people currently use <a href="https://vrcdn.live/">VRCDN</a>, an inexpensive but limited hosted service that you have to pay monthly for. But for folks with a bit more technical acumen, there&rsquo;s another choice, <a href="https://owncast.online/">Owncast</a>, which is basically a self-hosted Twitch-like.</p>]]></summary>
        <content type="html"><![CDATA[

		

        



        <p>Performers who do streaming-based performances on VRChat and other places have a few options for actually providing their stream. Once upon a time it was preetty common for people to use Twitch or YouTube Live, but those are now being locked down due to advertising considerations. So, many people currently use <a href="https://vrcdn.live/">VRCDN</a>, an inexpensive but limited hosted service that you have to pay monthly for. But for folks with a bit more technical acumen, there&rsquo;s another choice, <a href="https://owncast.online/">Owncast</a>, which is basically a self-hosted Twitch-like.</p><p>Here&rsquo;s how I have mine set up and how I run it for (basically<sup id="r_e2089_fn1"><a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#d_e2089_fn1" rel="footnote">1</a></sup>) free.</p>

        
            <h3 id="2089_h3_1_Local-server-origin">Local server (origin)<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_1_Local-server-origin" class="toc_link"></a></h3><p>First off, I have an Intel NUC running Linux<sup id="r_e2089_fn2"><a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#d_e2089_fn2" rel="footnote">2</a></sup> on my home network. This computer runs a bunch of my home services but mostly sits idle. Its CPU is a 2.7GHz i7-8559U, which is sufficient to transcode my stream to a number of bitrates and resolutions simultaneously. I currently have the following bitrates configured:</p>
<ul>
<li>Original/raw stream (as configured in OBS; usually 1080p60 @ 6000 Kbps)</li>
<li>1080p60 @ 4500 Kbps</li>
<li>720p30 @ 2000 Kbps</li>
<li>360p24 @ 1000 Kbps</li>
<li>180p24 @ 500 Kbps</li>
</ul>
<p>In theory I should also be able to configure it to use Intel Quick Sync for a bit lower CPU utilization, although I haven&rsquo;t gone through the rigmarole to make that happen, as it hasn&rsquo;t been necessary.</p><p>Anyway, Owncast is running on its own user account, creatively called <code>owncast</code>. To make the server automatically start up, I have the following systemd unit file:</p><figure class="blockcode"><figcaption>/home/owncast/.config/system/user/owncast.service</figcaption><pre class="highlight" data-language="systemd" data-line-numbers><span class="line" id="e2089cb1L1"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L1"></a><span class="line-content"><span class="k">[Unit]</span></span></span>
<span class="line" id="e2089cb1L2"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L2"></a><span class="line-content"><span class="na">Description</span><span class="o">=</span><span class="s">Owncast Service</span></span></span>
<span class="line" id="e2089cb1L3"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L3"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb1L4"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L4"></a><span class="line-content"><span class="k">[Service]</span></span></span>
<span class="line" id="e2089cb1L5"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L5"></a><span class="line-content"><span class="na">WorkingDirectory</span><span class="o">=</span><span class="s">/home/owncast/owncast</span></span></span>
<span class="line" id="e2089cb1L6"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L6"></a><span class="line-content"><span class="na">ExecStart</span><span class="o">=</span><span class="s">/home/owncast/owncast/owncast</span></span></span>
<span class="line" id="e2089cb1L7"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L7"></a><span class="line-content"><span class="na">Restart</span><span class="o">=</span><span class="s">always</span></span></span>
<span class="line" id="e2089cb1L8"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L8"></a><span class="line-content"><span class="na">RestartSec</span><span class="o">=</span><span class="s">5</span></span></span>
<span class="line" id="e2089cb1L9"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L9"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb1L10"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L10"></a><span class="line-content"><span class="k">[Install]</span></span></span>
<span class="line" id="e2089cb1L11"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L11"></a><span class="line-content"><span class="na">WantedBy</span><span class="o">=</span><span class="s">default.target</span></span></span>
</pre></figure><p>To make this run, I had to enable lingering for the account, with <code>sudo loginctl enable-linger owncast</code> from an administrative user, and <code>systemctl --user enable owncast.service</code> from the owncast account.</p><h3 id="2089_h3_2_Proxy-server">Proxy server<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_2_Proxy-server" class="toc_link"></a></h3><p>The next thing to do was to expose this server to the greater Internet. There&rsquo;s a few ways you can go about doing this. The most straightforward, if you have an ISP that allows it, is to set up your home router to forward a particular port to the Owncast instance. However, many ISPs do not allow you to run servers this way, and even though mine does, I wasn&rsquo;t super comfortable with the idea of exposing a network port to the wider Internet or with having my home IP address be part of any public Internet service.</p><p>However, I already have a VPS with <a href="https://linode.com/">Akamai Cloud</a> which I use to run all of my websites. So, I set up an ssh tunnel (specifically using <a href="https://www.harding.motd.ca/autossh/">autossh</a> to automatically restart the connection if it drops). To that end, I made a second systemd unit:</p><figure class="blockcode"><figcaption>/home/owncast/.config/systemd/user/owncast-tunnel.service</figcaption><pre class="highlight" data-language="systemd" data-line-numbers><span class="line" id="e2089cb2L1"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L1"></a><span class="line-content"><span class="k">[Unit]</span></span></span>
<span class="line" id="e2089cb2L2"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L2"></a><span class="line-content"><span class="na">Description</span><span class="o">=</span><span class="s">Owncast ssh tunnel</span></span></span>
<span class="line" id="e2089cb2L3"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L3"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb2L4"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L4"></a><span class="line-content"><span class="k">[Service]</span></span></span>
<span class="line" id="e2089cb2L5"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L5"></a><span class="line-content"><span class="na">ExecStart</span><span class="o">=</span><span class="s">autossh -NT -R 29929:localhost:8080 MYSERVER.example.com</span></span></span>
<span class="line" id="e2089cb2L6"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L6"></a><span class="line-content"><span class="na">Restart</span><span class="o">=</span><span class="s">always</span></span></span>
<span class="line" id="e2089cb2L7"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L7"></a><span class="line-content"><span class="na">RestartSec</span><span class="o">=</span><span class="s">5</span></span></span>
<span class="line" id="e2089cb2L8"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L8"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb2L9"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L9"></a><span class="line-content"><span class="k">[Install]</span></span></span>
<span class="line" id="e2089cb2L10"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L10"></a><span class="line-content"><span class="na">WantedBy</span><span class="o">=</span><span class="s">default.target</span></span></span>
</pre></figure><p>where <code>MYSERVER.example.com</code> is the actual hostname of my VPS. I enabled this service with <code>systemctl --user enable owncast-tunnel.service</code> and now localhost connections to 29929 on my VPS connect to port 8080 on my NUC. (No need for Tailscale!)</p><p>Finally, I set up a caching reverse proxy for <a href="https://live.sockpuppet.band">my owncast server</a>. This is how I did it in nginx:</p><figure class="blockcode"><figcaption>/etc/nginx/vhosts-enabled/live.sockpuppet.band</figcaption><pre class="highlight" data-language="nginx" data-line-numbers><span class="line" id="e2089cb3L1"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L1"></a><span class="line-content"><span class="k">server</span><span class="w"> </span><span class="p">{</span></span></span>
<span class="line" id="e2089cb3L2"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L2"></a><span class="line-content"><span class="w">    </span><span class="kn">listen</span><span class="w"> </span><span class="mi">80</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L3"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L3"></a><span class="line-content"><span class="w">    </span><span class="kn">listen</span><span class="w"> </span><span class="s">[::]:80</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L4"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L4"></a><span class="line-content"><span class="w">    </span><span class="kn">server_name</span><span class="w"> </span><span class="s">live.sockpuppet.band</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L5"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L5"></a><span class="line-content"><span class="w">    </span><span class="kn">return</span><span class="w"> </span><span class="mi">301</span><span class="w"> </span><span class="s">https://</span><span class="nv">$host$request_uri</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L6"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L6"></a><span class="line-content"><span class="p">}</span></span></span>
<span class="line" id="e2089cb3L7"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L7"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb3L8"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L8"></a><span class="line-content"><span class="k">proxy_cache_path</span><span class="w"> </span><span class="s">/var/tmp/live_sockpuppet</span><span class="w"> </span><span class="s">levels=1:2</span><span class="w"> </span><span class="s">keys_zone=live_sockpuppet:10m</span><span class="w"> </span><span class="s">max_size=10g</span></span></span>
<span class="line" id="e2089cb3L9"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L9"></a><span class="line-content"><span class="w">                 </span><span class="s">inactive=60m</span><span class="w"> </span><span class="s">use_temp_path=off</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L10"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L10"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb3L11"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L11"></a><span class="line-content"><span class="k">server</span><span class="w"> </span><span class="p">{</span></span></span>
<span class="line" id="e2089cb3L12"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L12"></a><span class="line-content"><span class="w">    </span><span class="kn">server_name</span><span class="w"> </span><span class="s">live.sockpuppet.band</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L13"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L13"></a><span class="line-content"><span class="w">    </span><span class="kn">listen</span><span class="w"> </span><span class="mi">443</span><span class="w"> </span><span class="s">ssl</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L14"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L14"></a><span class="line-content"><span class="w">    </span><span class="kn">ssl_certificate</span><span class="w"> </span><span class="s">/path/to/sockpuppet.band.crt</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L15"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L15"></a><span class="line-content"><span class="w">    </span><span class="kn">ssl_certificate_key</span><span class="w"> </span><span class="s">/path/to/sockpuppet.band.key</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L16"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L16"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb3L17"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L17"></a><span class="line-content"><span class="w">    </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span></span></span>
<span class="line" id="e2089cb3L18"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L18"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Host</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L19"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L19"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Host</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L20"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L20"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Server</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L21"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L21"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Proto</span><span class="w"> </span><span class="nv">$scheme</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L22"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L22"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Real-IP</span><span class="w"> </span><span class="nv">$remote_addr</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L23"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L23"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-For</span><span class="w"> </span><span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L24"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L24"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_http_version</span><span class="w"> </span><span class="mi">1</span><span class="s">.1</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L25"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L25"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Upgrade</span><span class="w"> </span><span class="nv">$http_upgrade</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L26"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L26"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Connection</span><span class="w"> </span><span class="nv">$connection_upgrade</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L27"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L27"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_pass</span><span class="w"> </span><span class="s">http://127.0.0.1:29929</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L28"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L28"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_cache</span><span class="w"> </span><span class="s">live_sockpuppet</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L29"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L29"></a><span class="line-content"><span class="w">    </span><span class="p">}</span></span></span>
<span class="line" id="e2089cb3L30"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L30"></a><span class="line-content"><span class="p">}</span></span></span>
</pre></figure><p>This caching configuration means that this edge server only needs to proxy each HLS segment from my home network once, so in theory I can get a full gigabit of upstream from my VPS without overly burdening my home connection (although my home connection has plenty of bandwidth to spare, all the same).</p><h3 id="2089_h3_3_Wider-distribution-with-a-CDN">Wider distribution with a CDN<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_3_Wider-distribution-with-a-CDN" class="toc_link"></a></h3><p>This is optional, but <del>I use <a href="https://cloudflare.com/">Cloudflare CDN</a> for DDOS and bot mitigation, as well as better caching performance worldwide</del>. So far I&rsquo;ve never come even <em>remotely</em> close to exceeding the bandwidth capacity of my VPS (which should theoretically be able to serve around 200 simultaneous viewers), but Cloudflare&rsquo;s free tier means I don&rsquo;t have to worry about scaling at all. <mark>Update:</mark> I no longer use Cloudflare. Right now if I were to need a better scaling solution I&rsquo;d probably make use of Owncast&rsquo;s support for S3/B2 block storage instead, or maybe I&rsquo;d see if there&rsquo;s a way to use Akamai.</p><p>I&rsquo;m not a huge fan of Cloudflare for a number of reasons, but it&rsquo;s made it a lot easier for me to deal with the constant deluge of AI bot traffic that&rsquo;s been causing me so much stress lately, and having a proper geographically-distributed CDN is a nice bonus.</p><p>In theory, if your ISP allows running servers, you could also configure Cloudflare to talk directly to your home router, although I believe doing arbitrary port forwards requires a paid plan.</p><h3 id="2089_h3_4_Finally-streaming">Finally, streaming!<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_4_Finally-streaming" class="toc_link"></a></h3><p>To send a stream out, instead of using the public-facing hostname (live.sockpuppet.band), I connect OBS to the local IP address, so that I don&rsquo;t have to go out to the public Internet just to be routed back home. This way I also don&rsquo;t have to expose Owncast&rsquo;s RTMP port to the public Internet, which gives me better security. On the minus side, this means I cannot easily share my server with others to allow others to stream with my infrastructure, but that&rsquo;s never come up. If I ever wanted to do a cooperative stream with someone, I could use a WebRTC proxy such as <a href="https://vdo.ninja/">VDO.ninja</a>, but setting that up is outside the scope of this blog post.</p><p>Anyway, when someone connects to <a href="https://live.sockpuppet.band">my owncast</a> they are viewing it through <del>Cloudflare, which pulls the data from</del> my VPS, which in turn proxies it over the SSH tunnel to the Owncast instance running on my device at home. The raw stream (used, for example, by a VRChat in-world player) is available at <code>https://live.sockpuppet.band/hls/stream.m3u8</code>.</p><h3 id="2089_h3_5_How-to-roll-your-own-streaming-C">How to roll your own streaming CDN<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_5_How-to-roll-your-own-streaming-C" class="toc_link"></a></h3><p>Okay so let&rsquo;s say you just want to roll your own VRCDN-like thing, and don&rsquo;t care about having your streaming box be directly on your local network. Here&rsquo;s what I&rsquo;d do for that:</p>
<ol>
<li>Set up a VPS of some sort, even one which only runs when you need it to (which both DigitalOcean and Linode/Akamai support)</li>
<li>Install <a href="https://owncast.online/">owncast</a> on it</li>
<li>Install nginx or apache as a fronting webserver, and have it just reverse proxy into Owncast (so you can run Owncast on port 80/443 without having to run Owncast itself as root)</li>
<li>Front the server with a CDN such as Cloudflare or Akamai, and have it cache aggressively</li>
</ol>
<p>For streaming you&rsquo;ll need to connect directly to the server by IP address (or by having a hostname that&rsquo;s <em>not</em> Cloudflare-proxied), but otherwise you&rsquo;re good to go from here.</p><p>In such a setup you&rsquo;ll probably need to limit the bitrates that you provide.</p><p>Anyway, a suitably-capable VPS will cost around 5.4¢/hour while it&rsquo;s running, and theoretically be able to support hundreds, if not thousands, of simultaneous viewers.</p>
            
                <hr/><ol><li id="d_e2089_fn1"><p>It&rsquo;s only basically free because I already have a public Internet server I run my websites on and a local computer I can use for Owncast. If you don&rsquo;t already have a VPS of some sort, my particular setup won&rsquo;t work for you.&nbsp;<a href="/blog/2089-Self-hosted-streaming-CDN#r_e2089_fn1" rev="footnote">↩</a></p></li><li id="d_e2089_fn2"><p>All of this could also be run on Windows or macOS, but setting up a persistent server and ssh tunnel on those platforms is not something I&rsquo;ve had to internalize.&nbsp;<a href="/blog/2089-Self-hosted-streaming-CDN#r_e2089_fn2" rev="footnote">↩</a></p></li></ol>
            

            

        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=technology">#Technology</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=owncast">#Owncast</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=streaming">#Streaming</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VRChat">#VRChat</a>
        

        ]]>



        </content>
        <category term="Blog" label="Blog" />
        
        
        <category term="Technology" label="technology" />
        
        <category term="Owncast" label="owncast" />
        
        <category term="Streaming" label="streaming" />
        
        <category term="VRChat" label="VRChat" />
        

        

    </entry>
    

    
</feed>