diff --git a/package/secubox/secubox-app-pinafore/Makefile b/package/secubox/secubox-app-pinafore/Makefile new file mode 100644 index 00000000..c79c7486 --- /dev/null +++ b/package/secubox/secubox-app-pinafore/Makefile @@ -0,0 +1,36 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=secubox-app-pinafore +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=SecuBox +PKG_LICENSE:=AGPL-3.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/secubox-app-pinafore + SECTION:=secubox + CATEGORY:=SecuBox + SUBMENU:=Apps + TITLE:=Pinafore Mastodon Web Client + DEPENDS:=+wget +python3-light + PKGARCH:=all +endef + +define Package/secubox-app-pinafore/description + Pinafore is a web client for Mastodon and other ActivityPub servers. + Use it as a frontend for GoToSocial or any Mastodon-compatible instance. +endef + +define Build/Compile +endef + +define Package/secubox-app-pinafore/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) ./files/usr/sbin/pinaforectl $(1)/usr/sbin/ + + $(INSTALL_DIR) $(1)/srv/pinafore +endef + +$(eval $(call BuildPackage,secubox-app-pinafore)) diff --git a/package/secubox/secubox-app-pinafore/files/usr/sbin/pinaforectl b/package/secubox/secubox-app-pinafore/files/usr/sbin/pinaforectl new file mode 100755 index 00000000..6704efbb --- /dev/null +++ b/package/secubox/secubox-app-pinafore/files/usr/sbin/pinaforectl @@ -0,0 +1,293 @@ +#!/bin/sh +# SecuBox Pinafore Controller +# Mastodon web client hub - redirects to public clients with instance pre-configured + +VERSION="1.0.0" +DATA_PATH="/srv/pinafore" +PORT="${PINAFORE_PORT:-4002}" +PID_FILE="/var/run/pinafore.pid" + +# Default GoToSocial instance +DEFAULT_INSTANCE="social.gk2.secubox.in" + +log_info() { echo "[INFO] $*"; } +log_error() { echo "[ERROR] $*" >&2; } + +usage() { + cat <<'EOF' +Pinafore Controller for SecuBox + +Usage: pinaforectl + +Commands: + install [inst] Create client hub page (default: social.gk2.secubox.in) + start Start web server + stop Stop web server + restart Restart web server + status Show status + emancipate Expose via HAProxy with domain + +Examples: + pinaforectl install social.example.com + pinaforectl start + pinaforectl emancipate client.gk2.secubox.in +EOF +} + +pinafore_running() { + [ -f "$PID_FILE" ] && kill -0 "$(cat $PID_FILE)" 2>/dev/null +} + +cmd_install() { + local instance="${1:-$DEFAULT_INSTANCE}" + + log_info "Creating Mastodon client hub for $instance..." + + mkdir -p "$DATA_PATH" + + # Create landing page with links to public clients + cat > "$DATA_PATH/index.html" < + + + + + Mastodon Clients - ${instance} + + + + + + +HTMLEOF + + log_info "Client hub created at $DATA_PATH" + log_info "Run 'pinaforectl start' to start the server" +} + +cmd_start() { + if pinafore_running; then + log_info "Pinafore already running (PID: $(cat $PID_FILE))" + return 0 + fi + + if [ ! -d "$DATA_PATH" ] || [ ! -f "$DATA_PATH/index.html" ]; then + log_error "Pinafore not installed. Run 'pinaforectl install' first" + return 1 + fi + + log_info "Starting Pinafore on port $PORT..." + + # Use uhttpd (OpenWrt native) or socat as fallback + if command -v uhttpd >/dev/null 2>&1; then + uhttpd -p "0.0.0.0:$PORT" -h "$DATA_PATH" -f & + echo $! > "$PID_FILE" + elif command -v python3 >/dev/null 2>&1; then + cd "$DATA_PATH" && python3 -m http.server "$PORT" --bind 0.0.0.0 >/dev/null 2>&1 & + echo $! > "$PID_FILE" + else + log_error "No suitable HTTP server found (uhttpd/python3)" + return 1 + fi + + sleep 1 + if pinafore_running; then + log_info "Pinafore started (PID: $(cat $PID_FILE))" + log_info "Access at http://localhost:$PORT" + else + log_error "Failed to start Pinafore" + return 1 + fi +} + +cmd_stop() { + if ! pinafore_running; then + log_info "Pinafore is not running" + return 0 + fi + + log_info "Stopping Pinafore..." + kill "$(cat $PID_FILE)" 2>/dev/null + rm -f "$PID_FILE" + log_info "Pinafore stopped" +} + +cmd_restart() { + cmd_stop + sleep 1 + cmd_start +} + +cmd_status() { + local running="false" + local pid="" + + if pinafore_running; then + running="true" + pid=$(cat "$PID_FILE") + fi + + cat <" + return 1 + fi + + log_info "Exposing Pinafore at $domain..." + + # Create HAProxy backend + local backend_name="pinafore" + local vhost_name=$(echo "$domain" | tr '.' '_') + + # Add backend if not exists + if ! uci -q get haproxy.$backend_name >/dev/null 2>&1; then + uci set haproxy.$backend_name=backend + uci set haproxy.$backend_name.name='pinafore' + uci set haproxy.$backend_name.mode='http' + uci set haproxy.$backend_name.balance='roundrobin' + uci set haproxy.$backend_name.enabled='1' + + uci set haproxy.${backend_name}_srv=server + uci set haproxy.${backend_name}_srv.backend='pinafore' + uci set haproxy.${backend_name}_srv.name='pinafore' + uci set haproxy.${backend_name}_srv.address='192.168.255.1' + uci set haproxy.${backend_name}_srv.port="$PORT" + fi + + # Add vhost + uci set haproxy.$vhost_name=vhost + uci set haproxy.$vhost_name.domain="$domain" + uci set haproxy.$vhost_name.backend='pinafore' + uci set haproxy.$vhost_name.ssl='1' + uci set haproxy.$vhost_name.ssl_redirect='1' + uci set haproxy.$vhost_name.acme='1' + uci set haproxy.$vhost_name.enabled='1' + uci set haproxy.$vhost_name.description='Pinafore Mastodon Client' + + uci commit haproxy + + # Reload HAProxy + haproxyctl reload 2>/dev/null || /etc/init.d/haproxy reload 2>/dev/null + + # Sync mitmproxy routes + mitmproxyctl sync-routes 2>/dev/null + + log_info "Pinafore exposed at https://$domain" +} + +# Main +case "$1" in + install) cmd_install ;; + start) cmd_start ;; + stop) cmd_stop ;; + restart) cmd_restart ;; + status) cmd_status ;; + emancipate) shift; cmd_emancipate "$@" ;; + help|--help|-h|"") usage ;; + *) log_error "Unknown command: $1"; usage; exit 1 ;; +esac