573 lines
15 KiB
HTML
573 lines
15 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<html>
|
||
|
||
<head>
|
||
|
||
<meta charset="utf-8" />
|
||
<meta name="generator" content="pandoc" />
|
||
<meta http-equiv="X-UA-Compatible" content="IE=EDGE" />
|
||
|
||
|
||
<meta name="author" content="Hertog" />
|
||
|
||
<meta name="date" content="2023-10-27" />
|
||
|
||
<title>Setting Up Owncast with NixOS</title>
|
||
|
||
<script src="site_libs/header-attrs-2.25/header-attrs.js"></script>
|
||
<script src="site_libs/jquery-3.6.0/jquery-3.6.0.min.js"></script>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<link href="site_libs/bootstrap-3.3.5/css/bootstrap.min.css" rel="stylesheet" />
|
||
<script src="site_libs/bootstrap-3.3.5/js/bootstrap.min.js"></script>
|
||
<script src="site_libs/bootstrap-3.3.5/shim/html5shiv.min.js"></script>
|
||
<script src="site_libs/bootstrap-3.3.5/shim/respond.min.js"></script>
|
||
<style>h1 {font-size: 34px;}
|
||
h1.title {font-size: 38px;}
|
||
h2 {font-size: 30px;}
|
||
h3 {font-size: 24px;}
|
||
h4 {font-size: 18px;}
|
||
h5 {font-size: 16px;}
|
||
h6 {font-size: 12px;}
|
||
code {color: inherit; background-color: rgba(0, 0, 0, 0.04);}
|
||
pre:not([class]) { background-color: white }</style>
|
||
<script src="site_libs/jqueryui-1.13.2/jquery-ui.min.js"></script>
|
||
<link href="site_libs/tocify-1.9.1/jquery.tocify.css" rel="stylesheet" />
|
||
<script src="site_libs/tocify-1.9.1/jquery.tocify.js"></script>
|
||
<script src="site_libs/navigation-1.1/tabsets.js"></script>
|
||
|
||
<style type="text/css">
|
||
code{white-space: pre-wrap;}
|
||
span.smallcaps{font-variant: small-caps;}
|
||
span.underline{text-decoration: underline;}
|
||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||
ul.task-list{list-style: none;}
|
||
</style>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<link rel="stylesheet" href="main.css" type="text/css" />
|
||
|
||
|
||
|
||
<style type = "text/css">
|
||
.main-container {
|
||
max-width: 940px;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
img {
|
||
max-width:100%;
|
||
}
|
||
.tabbed-pane {
|
||
padding-top: 12px;
|
||
}
|
||
.html-widget {
|
||
margin-bottom: 20px;
|
||
}
|
||
button.code-folding-btn:focus {
|
||
outline: none;
|
||
}
|
||
summary {
|
||
display: list-item;
|
||
}
|
||
details > summary > p:only-child {
|
||
display: inline;
|
||
}
|
||
pre code {
|
||
padding: 0;
|
||
}
|
||
</style>
|
||
|
||
|
||
<style type="text/css">
|
||
.dropdown-submenu {
|
||
position: relative;
|
||
}
|
||
.dropdown-submenu>.dropdown-menu {
|
||
top: 0;
|
||
left: 100%;
|
||
margin-top: -6px;
|
||
margin-left: -1px;
|
||
border-radius: 0 6px 6px 6px;
|
||
}
|
||
.dropdown-submenu:hover>.dropdown-menu {
|
||
display: block;
|
||
}
|
||
.dropdown-submenu>a:after {
|
||
display: block;
|
||
content: " ";
|
||
float: right;
|
||
width: 0;
|
||
height: 0;
|
||
border-color: transparent;
|
||
border-style: solid;
|
||
border-width: 5px 0 5px 5px;
|
||
border-left-color: #cccccc;
|
||
margin-top: 5px;
|
||
margin-right: -10px;
|
||
}
|
||
.dropdown-submenu:hover>a:after {
|
||
border-left-color: #adb5bd;
|
||
}
|
||
.dropdown-submenu.pull-left {
|
||
float: none;
|
||
}
|
||
.dropdown-submenu.pull-left>.dropdown-menu {
|
||
left: -100%;
|
||
margin-left: 10px;
|
||
border-radius: 6px 0 6px 6px;
|
||
}
|
||
</style>
|
||
|
||
<script type="text/javascript">
|
||
// manage active state of menu based on current page
|
||
$(document).ready(function () {
|
||
// active menu anchor
|
||
href = window.location.pathname
|
||
href = href.substr(href.lastIndexOf('/') + 1)
|
||
if (href === "")
|
||
href = "index.html";
|
||
var menuAnchor = $('a[href="' + href + '"]');
|
||
|
||
// mark the anchor link active (and if it's in a dropdown, also mark that active)
|
||
var dropdown = menuAnchor.closest('li.dropdown');
|
||
if (window.bootstrap) { // Bootstrap 4+
|
||
menuAnchor.addClass('active');
|
||
dropdown.find('> .dropdown-toggle').addClass('active');
|
||
} else { // Bootstrap 3
|
||
menuAnchor.parent().addClass('active');
|
||
dropdown.addClass('active');
|
||
}
|
||
|
||
// Navbar adjustments
|
||
var navHeight = $(".navbar").first().height() + 15;
|
||
var style = document.createElement('style');
|
||
var pt = "padding-top: " + navHeight + "px; ";
|
||
var mt = "margin-top: -" + navHeight + "px; ";
|
||
var css = "";
|
||
// offset scroll position for anchor links (for fixed navbar)
|
||
for (var i = 1; i <= 6; i++) {
|
||
css += ".section h" + i + "{ " + pt + mt + "}\n";
|
||
}
|
||
style.innerHTML = "body {" + pt + "padding-bottom: 40px; }\n" + css;
|
||
document.head.appendChild(style);
|
||
});
|
||
</script>
|
||
|
||
<!-- tabsets -->
|
||
|
||
<style type="text/css">
|
||
.tabset-dropdown > .nav-tabs {
|
||
display: inline-table;
|
||
max-height: 500px;
|
||
min-height: 44px;
|
||
overflow-y: auto;
|
||
border: 1px solid #ddd;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.tabset-dropdown > .nav-tabs > li.active:before, .tabset-dropdown > .nav-tabs.nav-tabs-open:before {
|
||
content: "\e259";
|
||
font-family: 'Glyphicons Halflings';
|
||
display: inline-block;
|
||
padding: 10px;
|
||
border-right: 1px solid #ddd;
|
||
}
|
||
|
||
.tabset-dropdown > .nav-tabs.nav-tabs-open > li.active:before {
|
||
content: "\e258";
|
||
font-family: 'Glyphicons Halflings';
|
||
border: none;
|
||
}
|
||
|
||
.tabset-dropdown > .nav-tabs > li.active {
|
||
display: block;
|
||
}
|
||
|
||
.tabset-dropdown > .nav-tabs > li > a,
|
||
.tabset-dropdown > .nav-tabs > li > a:focus,
|
||
.tabset-dropdown > .nav-tabs > li > a:hover {
|
||
border: none;
|
||
display: inline-block;
|
||
border-radius: 4px;
|
||
background-color: transparent;
|
||
}
|
||
|
||
.tabset-dropdown > .nav-tabs.nav-tabs-open > li {
|
||
display: block;
|
||
float: none;
|
||
}
|
||
|
||
.tabset-dropdown > .nav-tabs > li {
|
||
display: none;
|
||
}
|
||
</style>
|
||
|
||
<!-- code folding -->
|
||
|
||
|
||
|
||
<style type="text/css">
|
||
|
||
#TOC {
|
||
margin: 25px 0px 20px 0px;
|
||
}
|
||
@media (max-width: 768px) {
|
||
#TOC {
|
||
position: relative;
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
@media print {
|
||
.toc-content {
|
||
/* see https://github.com/w3c/csswg-drafts/issues/4434 */
|
||
float: right;
|
||
}
|
||
}
|
||
|
||
.toc-content {
|
||
padding-left: 30px;
|
||
padding-right: 40px;
|
||
}
|
||
|
||
div.main-container {
|
||
max-width: 1200px;
|
||
}
|
||
|
||
div.tocify {
|
||
width: 20%;
|
||
max-width: 260px;
|
||
max-height: 85%;
|
||
}
|
||
|
||
@media (min-width: 768px) and (max-width: 991px) {
|
||
div.tocify {
|
||
width: 25%;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
div.tocify {
|
||
width: 100%;
|
||
max-width: none;
|
||
}
|
||
}
|
||
|
||
.tocify ul, .tocify li {
|
||
line-height: 20px;
|
||
}
|
||
|
||
.tocify-subheader .tocify-item {
|
||
font-size: 0.90em;
|
||
}
|
||
|
||
.tocify .list-group-item {
|
||
border-radius: 0px;
|
||
}
|
||
|
||
.tocify-subheader {
|
||
display: inline;
|
||
}
|
||
.tocify-subheader .tocify-item {
|
||
font-size: 0.95em;
|
||
}
|
||
|
||
</style>
|
||
|
||
|
||
|
||
</head>
|
||
|
||
<body>
|
||
|
||
|
||
<div class="container-fluid main-container">
|
||
|
||
|
||
<!-- setup 3col/9col grid for toc_float and main content -->
|
||
<div class="row">
|
||
<div class="col-xs-12 col-sm-4 col-md-3">
|
||
<div id="TOC" class="tocify">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toc-content col-xs-12 col-sm-8 col-md-9">
|
||
|
||
|
||
|
||
|
||
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||
<div class="container">
|
||
<div class="navbar-header">
|
||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-bs-toggle="collapse" data-target="#navbar" data-bs-target="#navbar">
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
</button>
|
||
<a class="navbar-brand" href="index.html">HermitCollective Blogs</a>
|
||
</div>
|
||
<div id="navbar" class="navbar-collapse collapse">
|
||
<ul class="nav navbar-nav">
|
||
<li class="dropdown">
|
||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||
HermitCollective
|
||
|
||
<span class="caret"></span>
|
||
</a>
|
||
<ul class="dropdown-menu" role="menu">
|
||
<li>
|
||
<a href="https://hermitcollective.net/">Main Site</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://live.hermitcollective.net/">Live Streams</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://cloud.hermitcollective.net/">HermitCloud</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://feeds.hermitcollective.net/">HermitFeeds</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="dropdown">
|
||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||
Blog Posts
|
||
|
||
<span class="caret"></span>
|
||
</a>
|
||
<ul class="dropdown-menu" role="menu">
|
||
<li>
|
||
<a href="./owncast.nix.html">owncast.nix</a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul class="nav navbar-nav navbar-right">
|
||
<li>
|
||
<a href="https://git.saragerretsen.nl/Hertog/HermitBlogs">Source</a>
|
||
</li>
|
||
</ul>
|
||
</div><!--/.nav-collapse -->
|
||
</div><!--/.container -->
|
||
</div><!--/.navbar -->
|
||
|
||
<div id="header">
|
||
|
||
|
||
|
||
<h1 class="title toc-ignore">Setting Up Owncast with NixOS</h1>
|
||
<h4 class="author"><a
|
||
href="https://hertog.hermitcollective.net">Hertog</a></h4>
|
||
<h4 class="date">2023-10-27</h4>
|
||
|
||
</div>
|
||
|
||
|
||
<div id="what-is-owncast" class="section level2">
|
||
<h2>What is Owncast?</h2>
|
||
<p><a href="https://owncast.online/">Owncast</a> is a lightweight
|
||
program to set up your own livestreaming website as an alternative to
|
||
streaming on twitch or youtube.</p>
|
||
<p>It is fully free and open source licensed under the <a
|
||
href="https://mit-license.org/">MIT license</a> and can even be linked
|
||
with the <a
|
||
href="https://en.wikipedia.org/wiki/Fediverse">fediverse!</a></p>
|
||
<p>Which to me is perfect! I really wanted to get back into
|
||
livestreaming (I used to do this on twitch allot) but I wanted a
|
||
platform without adds or corporate influence and thus owncast.</p>
|
||
</div>
|
||
<div id="as-for-nixos" class="section level2">
|
||
<h2>As for NixOS</h2>
|
||
<p>I use NixOS to selfhost everything I can (including this website!)
|
||
but I couldn’t find any wiki pages or concrete owncast configurations
|
||
online, I did eventually get it working and will share my configuration
|
||
here.</p>
|
||
</div>
|
||
<div id="the-owncast-part-of-the-config" class="section level2">
|
||
<h2>The Owncast part of the config</h2>
|
||
<p>This part is the easiest it is simply enabling it setting an unused
|
||
port (the default and recommended is 8080) and then let owncast open
|
||
that part of the firewall.</p>
|
||
<pre><code>services.owncast = {
|
||
enable = true;
|
||
port = 8080;
|
||
openFirewall = true;
|
||
};</code></pre>
|
||
</div>
|
||
<div id="the-nginx-part" class="section level2">
|
||
<h2>The nginx part!</h2>
|
||
<p>Nginx is needed to setup a proxy so we can link owncast to our domain
|
||
and ensure everything will run securely. We begin by setting the
|
||
(sub)domain that we wish to point at owncast and we enable SSL and ACME.
|
||
The locations part needs to point at the port we set earlier so that
|
||
nginx knows to point at owncast. Owncast also needs websockets so we set
|
||
that to true as wel, the extra config is to ensure our proxy works.</p>
|
||
<pre><code> services.nginx.virtualHosts."live.hermitcollective.net" = {
|
||
forceSSL = true;
|
||
enableACME = true;
|
||
locations."/" = {
|
||
proxyPass = "http://localhost:8080";
|
||
proxyWebsockets = true; # needed if you need to use WebSocket
|
||
extraConfig =
|
||
# required when the target is also TLS server with multiple hosts
|
||
"proxy_ssl_server_name on;" +
|
||
# required when the server wants to use HTTP Authentication
|
||
"proxy_pass_header Authorization;"
|
||
;
|
||
};
|
||
};</code></pre>
|
||
</div>
|
||
<div id="the-full-config" class="section level2">
|
||
<h2>The full config</h2>
|
||
<p>Your entire config should look something like this now at which point
|
||
you can sudo nixos-rebuild switch!:</p>
|
||
<pre><code>{ config, pkgs, ... }:
|
||
|
||
{
|
||
services.owncast = {
|
||
enable = true;
|
||
port = 8080;
|
||
openFirewall = true;
|
||
};
|
||
# Homepages
|
||
services.nginx.virtualHosts."yourdomain.net" = {
|
||
forceSSL = true;
|
||
enableACME = true;
|
||
locations."/" = {
|
||
proxyPass = "http://localhost:8080";
|
||
proxyWebsockets = true; # needed if you need to use WebSocket
|
||
extraConfig =
|
||
# required when the target is also TLS server with multiple hosts
|
||
"proxy_ssl_server_name on;" +
|
||
# required when the server wants to use HTTP Authentication
|
||
"proxy_pass_header Authorization;"
|
||
;
|
||
};
|
||
};
|
||
}</code></pre>
|
||
</div>
|
||
<div id="extra-information" class="section level2">
|
||
<h2>Extra information</h2>
|
||
<p>We are not done yet however there is one more this that is required
|
||
on the nixos side of things and quite a few things in your owncast
|
||
webpage.</p>
|
||
<p>While we did setup nginx for this owncast we didn’t do a full nginx
|
||
setup, this is because in my homeserver nginx is used for many things
|
||
and I want to avoid duplicate nix code so I have a separate nginx config
|
||
which can be found <a
|
||
href="https://git.saragerretsen.nl/Hertog/HermitCollective.nix/src/branch/main/services/nginx.nix">here</a>.</p>
|
||
<p>Now that that is done we can go into our owncast web page at <a
|
||
href="https://yourdomain.net/admin"
|
||
class="uri">https://yourdomain.net/admin</a>. Here it will ask you to
|
||
log in the default for this is Username: Admin and Password: abc123 you
|
||
want to replace this as soon as possible! Luckely there is the owncast
|
||
admin page you just logged into for that, either hit view next to
|
||
streaming keys in the home page or head to Stream Keys in Server Setup
|
||
under the Configuration tab.</p>
|
||
<p>When you are done with that open your favourite streaming application
|
||
set the livestreaming service to custom and use this link <a
|
||
href="rtmp://yourdomain.net:1935/live"
|
||
class="uri">rtmp://yourdomain.net:1935/live</a> with the streamkey you
|
||
just set!</p>
|
||
<p>Feedback on this blog can be left <a
|
||
href="https://tech.lgbt/@hertog/111306437367785113">here</a> thank
|
||
you!</p>
|
||
</div>
|
||
<div id="further-help" class="section level2">
|
||
<h2>Further help</h2>
|
||
<p>If you need extra configuring (and know what you are doing) more
|
||
owncast options can be found <a
|
||
href="https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=owncast">here</a>
|
||
and the owncast documentation can be found <a
|
||
href="https://owncast.online/docs/">here</a>. Is your version not up to
|
||
date with Nix pkgs? run <code>nix-channel --update</code>. Lastely if
|
||
this guide gets out of date my current owncast config can be found <a
|
||
href="https://git.saragerretsen.nl/Hertog/HermitCollective.nix/src/branch/main/services/owncast.nix">here</a>.</p>
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
|
||
// add bootstrap table styles to pandoc tables
|
||
function bootstrapStylePandocTables() {
|
||
$('tr.odd').parent('tbody').parent('table').addClass('table table-condensed');
|
||
}
|
||
$(document).ready(function () {
|
||
bootstrapStylePandocTables();
|
||
});
|
||
|
||
|
||
</script>
|
||
|
||
<!-- tabsets -->
|
||
|
||
<script>
|
||
$(document).ready(function () {
|
||
window.buildTabsets("TOC");
|
||
});
|
||
|
||
$(document).ready(function () {
|
||
$('.tabset-dropdown > .nav-tabs > li').click(function () {
|
||
$(this).parent().toggleClass('nav-tabs-open');
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<!-- code folding -->
|
||
|
||
<script>
|
||
$(document).ready(function () {
|
||
|
||
// temporarily add toc-ignore selector to headers for the consistency with Pandoc
|
||
$('.unlisted.unnumbered').addClass('toc-ignore')
|
||
|
||
// move toc-ignore selectors from section div to header
|
||
$('div.section.toc-ignore')
|
||
.removeClass('toc-ignore')
|
||
.children('h1,h2,h3,h4,h5').addClass('toc-ignore');
|
||
|
||
// establish options
|
||
var options = {
|
||
selectors: "h1,h2",
|
||
theme: "bootstrap3",
|
||
context: '.toc-content',
|
||
hashGenerator: function (text) {
|
||
return text.replace(/[.\\/?&!#<>]/g, '').replace(/\s/g, '_');
|
||
},
|
||
ignoreSelector: ".toc-ignore",
|
||
scrollTo: 0
|
||
};
|
||
options.showAndHide = false;
|
||
options.smoothScroll = true;
|
||
|
||
// tocify
|
||
var toc = $("#TOC").tocify(options).data("toc-tocify");
|
||
});
|
||
</script>
|
||
|
||
<!-- dynamically load mathjax for compatibility with self-contained -->
|
||
<script>
|
||
(function () {
|
||
var script = document.createElement("script");
|
||
script.type = "text/javascript";
|
||
script.src = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
|
||
document.getElementsByTagName("head")[0].appendChild(script);
|
||
})();
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|