first commit
commit
62e3463029
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
|
||||||
|
LUCI_TITLE:=LuCI support for owncast
|
||||||
|
LUCI_PKGARCH:=all
|
||||||
|
LUCI_DEPENDS:=+lsblk +docker +luci-lib-taskd
|
||||||
|
|
||||||
|
define Package/luci-app-owncast/conffiles
|
||||||
|
/etc/config/owncast
|
||||||
|
endef
|
||||||
|
|
||||||
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|
||||||
|
# call BuildPackage - OpenWrt buildroot signature
|
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
module("luci.controller.owncast", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
entry({"admin", "apps"}, firstchild(), _("Apps") , 45).dependent = false
|
||||||
|
if not nixio.fs.access("/etc/config/owncast") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local page = entry({"admin", "apps", "owncast"}, cbi("owncast"), _("owncast"))
|
||||||
|
page.order = 10
|
||||||
|
page.dependent = true
|
||||||
|
page.acl_depends = { "luci-app-owncast" }
|
||||||
|
entry({"admin","apps","owncast","status"},call("act_status")).leaf=true
|
||||||
|
end
|
@ -0,0 +1,47 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local taskd = require "luci.model.tasks"
|
||||||
|
local owncast_model = require "luci.model.owncast"
|
||||||
|
local m, s, o
|
||||||
|
|
||||||
|
m = taskd.docker_map("owncast", "owncast", "/usr/libexec/apps/owncast/owncast.sh",
|
||||||
|
translate("owncast"),
|
||||||
|
translate("Owncast is an open source, self-hosted live video and chat server for use with existing popular broadcasting software. With streaming + chat out of the box you can take control over your content by running it yourself. For hosting with TorGuard Wireguard make sure to fw internal and external tcp port 1935")
|
||||||
|
.. translate("Official website:") .. ' <a href=\"https://owncast.online/\" target=\"_blank\">hhttps://owncast.online/</a>')
|
||||||
|
|
||||||
|
s = m:section(SimpleSection, translate("Service Status"), translate("owncast status:"))
|
||||||
|
s:append(Template("owncast/status"))
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "owncast", translate("Setup"), translate("admin/password is default login. Please make note of your stream key."))
|
||||||
|
s.addremove=false
|
||||||
|
s.anonymous=true
|
||||||
|
|
||||||
|
o = s:option(Value, "port", translate("Port").."<b>*</b>")
|
||||||
|
o.rmempty = false
|
||||||
|
o.default = "8387"
|
||||||
|
o.datatype = "port"
|
||||||
|
|
||||||
|
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||||
|
o.rmempty = false
|
||||||
|
o.datatype = "string"
|
||||||
|
o:value("owncast/owncast:latest", "owncast/owncast:latest")
|
||||||
|
o.default = "owncast/owncast:latest"
|
||||||
|
|
||||||
|
local blocks = owncast_model.blocks()
|
||||||
|
local home = owncast_model.home()
|
||||||
|
|
||||||
|
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
|
||||||
|
o.rmempty = false
|
||||||
|
o.datatype = "string"
|
||||||
|
o:value("/opt/docker2/compose/owncast", "/opt/docker2/compose/owncast")
|
||||||
|
o.default = "/opt/docker2/compose/owncast"
|
||||||
|
|
||||||
|
local paths, default_path = owncast_model.find_paths(blocks, home, "Configs")
|
||||||
|
for _, val in pairs(paths) do
|
||||||
|
o:value(val, val)
|
||||||
|
end
|
||||||
|
o.default = default_path
|
||||||
|
|
||||||
|
return m
|
@ -0,0 +1,55 @@
|
|||||||
|
local util = require "luci.util"
|
||||||
|
local jsonc = require "luci.jsonc"
|
||||||
|
|
||||||
|
local owncast = {}
|
||||||
|
|
||||||
|
owncast.blocks = function()
|
||||||
|
local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r")
|
||||||
|
local vals = {}
|
||||||
|
if f then
|
||||||
|
local ret = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
local obj = jsonc.parse(ret)
|
||||||
|
for _, val in pairs(obj["blockdevices"]) do
|
||||||
|
local fsize = val["fssize"]
|
||||||
|
if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then
|
||||||
|
-- fsize > 1G
|
||||||
|
vals[#vals+1] = val["mountpoint"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return vals
|
||||||
|
end
|
||||||
|
|
||||||
|
owncast.home = function()
|
||||||
|
local uci = require "luci.model.uci".cursor()
|
||||||
|
local home_dirs = {}
|
||||||
|
home_dirs["main_dir"] = uci:get_first("quickstart", "main", "main_dir", "/root")
|
||||||
|
home_dirs["Configs"] = uci:get_first("quickstart", "main", "conf_dir", home_dirs["main_dir"].."/Configs")
|
||||||
|
home_dirs["Public"] = uci:get_first("quickstart", "main", "pub_dir", home_dirs["main_dir"].."/Public")
|
||||||
|
home_dirs["Downloads"] = uci:get_first("quickstart", "main", "dl_dir", home_dirs["Public"].."/Downloads")
|
||||||
|
home_dirs["Caches"] = uci:get_first("quickstart", "main", "tmp_dir", home_dirs["main_dir"].."/Caches")
|
||||||
|
return home_dirs
|
||||||
|
end
|
||||||
|
|
||||||
|
owncast.find_paths = function(blocks, home_dirs, path_name)
|
||||||
|
local default_path = ''
|
||||||
|
local configs = {}
|
||||||
|
|
||||||
|
default_path = home_dirs[path_name] .. "/owncast"
|
||||||
|
if #blocks == 0 then
|
||||||
|
table.insert(configs, default_path)
|
||||||
|
else
|
||||||
|
for _, val in pairs(blocks) do
|
||||||
|
table.insert(configs, val .. "/" .. path_name .. "/owncast")
|
||||||
|
end
|
||||||
|
local without_conf_dir = "/root/" .. path_name .. "/owncast"
|
||||||
|
if default_path == without_conf_dir then
|
||||||
|
default_path = configs[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return configs, default_path
|
||||||
|
end
|
||||||
|
|
||||||
|
return owncast
|
@ -0,0 +1,31 @@
|
|||||||
|
<%
|
||||||
|
local util = require "luci.util"
|
||||||
|
local container_status = util.trim(util.exec("/usr/libexec/apps/owncast/owncast.sh status"))
|
||||||
|
local container_install = (string.len(container_status) > 0)
|
||||||
|
local container_running = container_status == "running"
|
||||||
|
-%>
|
||||||
|
<div class="cbi-value">
|
||||||
|
<label class="cbi-value-title"><%:Status%></label>
|
||||||
|
<div class="cbi-value-field">
|
||||||
|
<% if container_running then %>
|
||||||
|
<button class="cbi-button cbi-button-success" disabled="true"><%:owncast is running%></button>
|
||||||
|
<% else %>
|
||||||
|
<button class="cbi-button cbi-button-negative" disabled="true"><%:owncast is not running%></button>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%
|
||||||
|
if container_running then
|
||||||
|
local port=util.trim(util.exec("/usr/libexec/apps/owncast/owncast.sh port"))
|
||||||
|
if port == "" then
|
||||||
|
port="8387"
|
||||||
|
end
|
||||||
|
-%>
|
||||||
|
<div class="cbi-value cbi-value-last">
|
||||||
|
<label class="cbi-value-title"> </label>
|
||||||
|
<div class="cbi-value-field">
|
||||||
|
|
||||||
|
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open owncast%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
@ -0,0 +1,5 @@
|
|||||||
|
config owncast
|
||||||
|
option 'port' '8387'
|
||||||
|
option 'config_path' '/opt/docker2/compose/owncast'
|
||||||
|
option 'image_name' 'owncast/owncast:latest'
|
||||||
|
|
@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
config_dir=`uci -q get owncast.@owncast[0].config_path`
|
||||||
|
|
||||||
|
data_dir=`docker inspect --format '{{.Mounts}}' owncast | grep -Eom1 '[^ ]+/_data /var/www/html local true ' | cut -d' ' -f1`
|
||||||
|
|
||||||
|
if [ -n "$data_dir" -a "$data_dir" != "$config_dir" ]; then
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
set owncast.@owncast[0].config_path="$data_dir"
|
||||||
|
commit owncast
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
@ -0,0 +1,113 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ACTION=${1}
|
||||||
|
shift 1
|
||||||
|
|
||||||
|
get_image() {
|
||||||
|
IMAGE_NAME="owncast/owncast:latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_install_detail() {
|
||||||
|
local config=`uci get owncast.@owncast[0].config_path 2>/dev/null`
|
||||||
|
local port=`uci get owncast.@owncast[0].port 2>/dev/null`
|
||||||
|
local IMAGE_NAME=`uci get owncast.@owncast[0].image_name 2>/dev/null`
|
||||||
|
local username=`uci get owncast.@owncast[0].username 2>/dev/null`
|
||||||
|
local password=`uci get owncast.@owncast[0].password 2>/dev/null`
|
||||||
|
|
||||||
|
#Generate the generic environment variables for the docker-compose
|
||||||
|
|
||||||
|
GEN_PASS=$(< /dev/urandom tr -dc A-Za-z0-9 2>/dev/null | head -c14; echo)
|
||||||
|
GEN_PASS2=$(< /dev/urandom tr -dc A-Za-z0-9 2>/dev/null | head -c14; echo)
|
||||||
|
|
||||||
|
# Get our local LAN IP Address
|
||||||
|
LAN_IP=$(uci get network.lan.ipaddr)
|
||||||
|
# Strip trailing network mask
|
||||||
|
LAN_IP="${LAN_IP%/*}"
|
||||||
|
|
||||||
|
if [ -z "$config" ]; then
|
||||||
|
echo "config path is empty!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -z "$port" ] && port=8387
|
||||||
|
[ -z "$IMAGE_NAME" ] && IMAGE_NAME=owncast/owncast:latest
|
||||||
|
|
||||||
|
|
||||||
|
# Create Docker Compose file with custom variables
|
||||||
|
|
||||||
|
# Create Docker Compose file with custom variables
|
||||||
|
touch docker-compose.yml
|
||||||
|
cat > docker-compose.yml <<EOF
|
||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
owncast:
|
||||||
|
image: owncast/owncast:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "$port:8080"
|
||||||
|
environment:
|
||||||
|
- OWNCAST_ADMIN_USERNAME=admin
|
||||||
|
- OWNCAST_ADMIN_PASSWORD=password
|
||||||
|
- OWNCAST_TITLE=My Owncast Stream
|
||||||
|
- OWNCAST_STREAM_KEY=${GEN_PASS}
|
||||||
|
- OWNCAST_HTTP_ROOT=/stream
|
||||||
|
volumes:
|
||||||
|
- $config:/app/data
|
||||||
|
labels:
|
||||||
|
plugsy.name: "Owncast"
|
||||||
|
plugsy.category: "Home"
|
||||||
|
plugsy.icon: "@styled-icons/simple-icons/Owncast"
|
||||||
|
plugsy.link: "http://${LAN_IP}:$port"
|
||||||
|
# Fw internal/external TorGuard wireguard port tcp 1935
|
||||||
|
EOF
|
||||||
|
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# Add a new list option to the "shortcutmenu" configuration file
|
||||||
|
uci add shortcutmenu lists
|
||||||
|
uci set shortcutmenu.@lists[-1].webname="$IMAGE_NAME"
|
||||||
|
uci set shortcutmenu.@lists[-1].weburl="$LAN_IP:$port"
|
||||||
|
uci set shortcutmenu.@lists[-1].webpath="/"
|
||||||
|
uci commit shortcutmenu
|
||||||
|
|
||||||
|
echo "Default username is admin and default password is password."
|
||||||
|
echo "Your Owncast Stream Key is:" {$GEN_PASS}
|
||||||
|
echo "Please make note of these details"
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "usage: $0 sub-command"
|
||||||
|
echo "where sub-command is one of:"
|
||||||
|
echo " install Install owncast"
|
||||||
|
echo " upgrade Upgrade owncast"
|
||||||
|
echo " rm/start/stop/restart Remove/Start/Stop/Restart owncast"
|
||||||
|
echo " status owncast status"
|
||||||
|
echo " port owncast port"
|
||||||
|
}
|
||||||
|
|
||||||
|
case ${ACTION} in
|
||||||
|
"install")
|
||||||
|
get_image
|
||||||
|
do_install_detail
|
||||||
|
;;
|
||||||
|
"upgrade")
|
||||||
|
get_image
|
||||||
|
do_install_detail
|
||||||
|
;;
|
||||||
|
"rm")
|
||||||
|
docker rm -f owncast
|
||||||
|
;;
|
||||||
|
"start" | "stop" | "restart")
|
||||||
|
docker ${ACTION} owncast
|
||||||
|
;;
|
||||||
|
"status")
|
||||||
|
docker ps --all -f 'name=owncast' --format '{{.State}}'
|
||||||
|
;;
|
||||||
|
"port")
|
||||||
|
docker ps --all -f 'name=owncast' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"luci-app-owncast": {
|
||||||
|
"description": "Grant UCI access for luci-app-owncast",
|
||||||
|
"read": {
|
||||||
|
"uci": [ "owncast" ]
|
||||||
|
},
|
||||||
|
"write": {
|
||||||
|
"uci": [ "owncast" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue