first commit
commit
fa1a906475
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
|
||||||
|
LUCI_TITLE:=LuCI support for mastodon
|
||||||
|
LUCI_PKGARCH:=all
|
||||||
|
LUCI_DEPENDS:=+lsblk +docker +luci-lib-taskd
|
||||||
|
|
||||||
|
define Package/luci-app-mastodon/conffiles
|
||||||
|
/etc/config/mastodon
|
||||||
|
endef
|
||||||
|
|
||||||
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|
||||||
|
# call BuildPackage - OpenWrt buildroot signature
|
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
module("luci.controller.mastodon", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
entry({"admin", "apps"}, firstchild(), _("Apps") , 45).dependent = false
|
||||||
|
if not nixio.fs.access("/etc/config/mastodon") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local page = entry({"admin", "apps", "mastodon"}, cbi("mastodon"), _("mastodon"))
|
||||||
|
page.order = 10
|
||||||
|
page.dependent = true
|
||||||
|
page.acl_depends = { "luci-app-mastodon" }
|
||||||
|
entry({"admin","apps","mastodon","status"},call("act_status")).leaf=true
|
||||||
|
end
|
@ -0,0 +1,47 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local taskd = require "luci.model.tasks"
|
||||||
|
local mastodon_model = require "luci.model.mastodon"
|
||||||
|
local m, s, o
|
||||||
|
|
||||||
|
m = taskd.docker_map("mastodon", "mastodon", "/usr/libexec/apps/mastodon/mastodon.sh",
|
||||||
|
translate("mastodon"),
|
||||||
|
translate("Mastodon is a decentralized social network made up of independent servers organized around specific themes, topics, or interests. People can join servers, follow each other, engage in conversations, and otherwise do all sorts of things they'd expect to do on a social network like Twitter.")
|
||||||
|
.. translate("Official website:") .. ' <a href=\"https://joinmastodon.org/\" target=\"_blank\">https://joinmastodon.org/</a>')
|
||||||
|
|
||||||
|
s = m:section(SimpleSection, translate("Service Status"), translate("mastodon status:"))
|
||||||
|
s:append(Template("mastodon/status"))
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "mastodon", translate("Setup"), translate("Enter domain name instead of router ip if self hosting via domain."))
|
||||||
|
s.addremove=false
|
||||||
|
s.anonymous=true
|
||||||
|
|
||||||
|
o = s:option(Value, "port", translate("Port").."<b>*</b>")
|
||||||
|
o.rmempty = false
|
||||||
|
o.default = "8660"
|
||||||
|
o.datatype = "port"
|
||||||
|
|
||||||
|
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||||
|
o.rmempty = false
|
||||||
|
o.datatype = "string"
|
||||||
|
o:value("lscr.io/linuxserver/mastodon:latest", "lscr.io/linuxserver/mastodon:latest")
|
||||||
|
o.default = "lscr.io/linuxserver/mastodon:latest"
|
||||||
|
|
||||||
|
local blocks = mastodon_model.blocks()
|
||||||
|
local home = mastodon_model.home()
|
||||||
|
|
||||||
|
o = s:option(Value, "config_path", translate("Enter router IP or domain name").."<b>*</b>")
|
||||||
|
o.rmempty = false
|
||||||
|
o.datatype = "string"
|
||||||
|
o:value("192.168.70.1", "192.168.70.1")
|
||||||
|
o.default = "192.168.70.1"
|
||||||
|
|
||||||
|
local paths, default_path = mastodon_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 mastodon = {}
|
||||||
|
|
||||||
|
mastodon.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
|
||||||
|
|
||||||
|
mastodon.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
|
||||||
|
|
||||||
|
mastodon.find_paths = function(blocks, home_dirs, path_name)
|
||||||
|
local default_path = ''
|
||||||
|
local configs = {}
|
||||||
|
|
||||||
|
default_path = home_dirs[path_name] .. "/mastodon"
|
||||||
|
if #blocks == 0 then
|
||||||
|
table.insert(configs, default_path)
|
||||||
|
else
|
||||||
|
for _, val in pairs(blocks) do
|
||||||
|
table.insert(configs, val .. "/" .. path_name .. "/mastodon")
|
||||||
|
end
|
||||||
|
local without_conf_dir = "/root/" .. path_name .. "/mastodon"
|
||||||
|
if default_path == without_conf_dir then
|
||||||
|
default_path = configs[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return configs, default_path
|
||||||
|
end
|
||||||
|
|
||||||
|
return mastodon
|
@ -0,0 +1,31 @@
|
|||||||
|
<%
|
||||||
|
local util = require "luci.util"
|
||||||
|
local container_status = util.trim(util.exec("/usr/libexec/apps/mastodon/mastodon.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"><%:mastodon is running%></button>
|
||||||
|
<% else %>
|
||||||
|
<button class="cbi-button cbi-button-negative" disabled="true"><%:mastodon is not running%></button>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%
|
||||||
|
if container_running then
|
||||||
|
local port=util.trim(util.exec("/usr/libexec/apps/mastodon/mastodon.sh port"))
|
||||||
|
if port == "" then
|
||||||
|
port="8660"
|
||||||
|
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 mastodon%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
@ -0,0 +1,5 @@
|
|||||||
|
config mastodon
|
||||||
|
option 'port' '8660'
|
||||||
|
option 'config_path' '192.168.70.1'
|
||||||
|
option 'image_name' 'lscr.io/linuxserver/mastodon:latest'
|
||||||
|
|
@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
config_dir=`uci -q get mastodon.@mastodon[0].config_path`
|
||||||
|
|
||||||
|
data_dir=`docker inspect --format '{{.Mounts}}' mastodon | 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 mastodon.@mastodon[0].config_path="$data_dir"
|
||||||
|
commit mastodon
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
@ -0,0 +1,169 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ACTION=${1}
|
||||||
|
shift 1
|
||||||
|
|
||||||
|
get_image() {
|
||||||
|
IMAGE_NAME="lscr.io/linuxserver/mastodon:latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_install_detail() {
|
||||||
|
local config=`uci get mastodon.@mastodon[0].config_path 2>/dev/null`
|
||||||
|
local port=`uci get mastodon.@mastodon[0].port 2>/dev/null`
|
||||||
|
local IMAGE_NAME=`uci get mastodon.@mastodon[0].image_name 2>/dev/null`
|
||||||
|
local username=`uci get mastodon.@mastodon[0].username 2>/dev/null`
|
||||||
|
local password=`uci get mastodon.@mastodon[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)
|
||||||
|
|
||||||
|
|
||||||
|
# rake secrets
|
||||||
|
secret=$(docker run --rm -it --entrypoint /bin/bash lscr.io/linuxserver/mastodon generate-secret)
|
||||||
|
base=$(docker run --rm -it --entrypoint /bin/bash lscr.io/linuxserver/mastodon generate-secret)
|
||||||
|
|
||||||
|
output=$(docker run --rm -it --entrypoint /bin/bash lscr.io/linuxserver/mastodon generate-vapid)
|
||||||
|
|
||||||
|
private_key=$(echo "$output" | grep VAPID_PRIVATE_KEY | awk -F= '{print $2}')
|
||||||
|
public_key=$(echo "$output" | grep VAPID_PUBLIC_KEY | awk -F= '{print $2}')
|
||||||
|
|
||||||
|
|
||||||
|
# Create Docker Compose file with custom variables
|
||||||
|
touch docker-compose.yml
|
||||||
|
cat > docker-compose.yml <<EOF
|
||||||
|
version: "2.1"
|
||||||
|
services:
|
||||||
|
mastodon:
|
||||||
|
image: $IMAGE_NAME
|
||||||
|
container_name: mastodon
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Etc/UTC
|
||||||
|
- LOCAL_DOMAIN=$config
|
||||||
|
- REDIS_HOST=redis
|
||||||
|
- REDIS_PORT=6379
|
||||||
|
- DB_HOST=db
|
||||||
|
- DB_USER=toot
|
||||||
|
- DB_NAME=mastodondb
|
||||||
|
- DB_PASS=$GEN_PASS
|
||||||
|
- DB_PORT=5432
|
||||||
|
- ES_ENABLED=false
|
||||||
|
- SECRET_KEY_BASE=$secret
|
||||||
|
- OTP_SECRET=$base
|
||||||
|
- VAPID_PRIVATE_KEY=$private_key
|
||||||
|
- VAPID_PUBLIC_KEY=$public_key
|
||||||
|
- SMTP_SERVER=mail.example.com
|
||||||
|
- SMTP_PORT=25
|
||||||
|
- SMTP_LOGIN=
|
||||||
|
- SMTP_PASSWORD=
|
||||||
|
- SMTP_FROM_ADDRESS=notifications@example.com
|
||||||
|
- S3_ENABLED=false
|
||||||
|
#- WEB_DOMAIN=mastodon.example.com #optional
|
||||||
|
#- ES_HOST=es #optional
|
||||||
|
#- ES_PORT=9200 #optional
|
||||||
|
#- ES_USER=elastic #optional
|
||||||
|
#- ES_PASS=elastic #optional
|
||||||
|
#- S3_BUCKET= #optional
|
||||||
|
#- AWS_ACCESS_KEY_ID= #optional
|
||||||
|
#- AWS_SECRET_ACCESS_KEY= #optional
|
||||||
|
#- S3_ALIAS_HOST= #optional
|
||||||
|
#- SIDEKIQ_ONLY=false #optional
|
||||||
|
#- SIDEKIQ_QUEUE= #optional
|
||||||
|
#- SIDEKIQ_DEFAULT=false #optional
|
||||||
|
#- SIDEKIQ_THREADS=5 #optional
|
||||||
|
#- DB_POOL=5 #optional
|
||||||
|
volumes:
|
||||||
|
- /opt/docker2/compose/mastodon/config:/config
|
||||||
|
ports:
|
||||||
|
- "$port:80"
|
||||||
|
- "4643:443"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- redis
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:14
|
||||||
|
container_name: db
|
||||||
|
volumes:
|
||||||
|
- /opt/docker2/compose/mastodon/data/postgres:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=mastodondb
|
||||||
|
- POSTGRES_USER=toot
|
||||||
|
- POSTGRES_PASSWORD=$GEN_PASS
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
container_name: redis
|
||||||
|
expose:
|
||||||
|
- "6379"
|
||||||
|
restart: unless-stopped
|
||||||
|
EOF
|
||||||
|
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
|
||||||
|
if [ -z "$config" ]; then
|
||||||
|
echo "config path is empty!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -z "$port" ] && port=""
|
||||||
|
[ -z "$IMAGE_NAME" ] && IMAGE_NAME=lscr.io/linuxserver/mastodon:latest
|
||||||
|
|
||||||
|
|
||||||
|
# Create Docker Compose file with custom variables
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "usage: $0 sub-command"
|
||||||
|
echo "where sub-command is one of:"
|
||||||
|
echo " install Install mastodon"
|
||||||
|
echo " upgrade Upgrade mastodon"
|
||||||
|
echo " rm/start/stop/restart Remove/Start/Stop/Restart mastodon"
|
||||||
|
echo " status mastodon status"
|
||||||
|
echo " port mastodon port"
|
||||||
|
}
|
||||||
|
|
||||||
|
case ${ACTION} in
|
||||||
|
"install")
|
||||||
|
|
||||||
|
do_install_detail
|
||||||
|
;;
|
||||||
|
"upgrade")
|
||||||
|
|
||||||
|
do_install_detail
|
||||||
|
;;
|
||||||
|
"rm")
|
||||||
|
docker rm -f mastodon
|
||||||
|
;;
|
||||||
|
"start" | "stop" | "restart")
|
||||||
|
docker ${ACTION} mastodon
|
||||||
|
;;
|
||||||
|
"status")
|
||||||
|
docker ps --all -f 'name=mastodon' --format '{{.State}}'
|
||||||
|
;;
|
||||||
|
"port")
|
||||||
|
docker ps --all -f 'name=mastodon' --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-mastodon": {
|
||||||
|
"description": "Grant UCI access for luci-app-mastodon",
|
||||||
|
"read": {
|
||||||
|
"uci": [ "mastodon" ]
|
||||||
|
},
|
||||||
|
"write": {
|
||||||
|
"uci": [ "mastodon" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue