Split hosts: media (gateway at /), files, clips, sync; live gains /dock, /dock/clock, /dump, /me, /time
configure.py: three new host roles (files/sync/clips) in --full, --hosts, .env, Caddy generator; main host serves about/ at the root (/about* redirects); /time only where it is fetched same-origin. about/index.html links across hosts; addCommunityMediaServer.sh asks for the new names; Caddyfile.example regenerated; README/FRESH-INSTALL/HOSTNAME-CHANGE (procedure C)/STATUS updated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
198
configure.py
198
configure.py
@@ -6,8 +6,12 @@
|
||||
./configure.py --show print current streamers, editors, domain and the OBS settings
|
||||
./configure.py --apply regenerate everything from the values already on disk and apply (non-interactive;
|
||||
used by deploy.sh). Fails if the main hostname was never set.
|
||||
./configure.py --hosts AUTH WATCH [GIT [BOT [LIVE]]] set the Authentik/Jellyfin/Gitea/bot/live hostnames and apply (non-interactive;
|
||||
used by addCommunityMediaServer.sh)
|
||||
./configure.py --hosts AUTH WATCH [GIT [BOT [LIVE [FILES [SYNC [CLIPS]]]]]]
|
||||
set the other hostnames and apply (non-interactive; used by addCommunityMediaServer.sh).
|
||||
Pass "" to leave one unset.
|
||||
|
||||
Hosts: main = the gateway page at /, files = copyparty, clips = clip intake, sync = Syncthing UI,
|
||||
live = portal + OBS dock (/dock/, /dock/clock/, /dump, /me, /time), auth, watch, git, bot.
|
||||
|
||||
Reads : Caddyfile (hostnames), mediamtx.yml (streamers), .env
|
||||
(editors/admins are Authentik groups now: editors, media-admins, admins — nothing local)
|
||||
@@ -154,8 +158,9 @@ def gate(required_group=""):
|
||||
"""
|
||||
return block
|
||||
|
||||
def write_caddy(domain, auth_host="", watch_host="", git_host="", bot_host="", live_host=""):
|
||||
def write_caddy(domain, auth_host="", watch_host="", git_host="", bot_host="", live_host="", files_host="", sync_host="", clips_host=""):
|
||||
env = read_env()
|
||||
gate_any = gate("")
|
||||
extra = ""
|
||||
apex, target = env.get("APEX_HOST", ""), env.get("APEX_REDIRECT", "")
|
||||
if apex and target:
|
||||
@@ -164,18 +169,70 @@ def write_caddy(domain, auth_host="", watch_host="", git_host="", bot_host="", l
|
||||
{apex} {{
|
||||
redir {target} 302
|
||||
}}
|
||||
"""
|
||||
if files_host:
|
||||
extra += f"""
|
||||
# vanguard:files
|
||||
{files_host} {{
|
||||
encode zstd gzip
|
||||
{gate_any} # copyparty at the root. It honours X-Authentik-Username / -Groups only when the request also carries a header
|
||||
# whose secret NAME only this proxy knows (copyparty idp-h-key). Clients cannot forge identity.
|
||||
reverse_proxy 127.0.0.1:3923 {{
|
||||
header_up X-Vanguard-{env.get("COPYPARTY_IDP_KEY", "key")} 1
|
||||
flush_interval -1
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
if sync_host:
|
||||
extra += f"""
|
||||
# vanguard:sync
|
||||
{sync_host} {{
|
||||
encode zstd gzip
|
||||
{gate(env.get("SYNC_REQUIRE_GROUP", "media-admins"))} # Syncthing admin UI (its own GUI login is disabled; the gate + group is the login)
|
||||
reverse_proxy 127.0.0.1:8384 {{
|
||||
header_up Host {{upstream_hostport}}
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
if clips_host:
|
||||
extra += f"""
|
||||
# vanguard:clips
|
||||
{clips_host} {{
|
||||
encode zstd gzip
|
||||
{gate_any} @me path /me /me/*
|
||||
handle @me {{
|
||||
reverse_proxy 127.0.0.1:8080 # dumpd: identity + /me/clips self-service
|
||||
}}
|
||||
handle {{
|
||||
root * /srv/clips
|
||||
try_files {{path}} /index.html
|
||||
file_server
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
if live_host:
|
||||
extra += f"""
|
||||
# vanguard:live
|
||||
{live_host} {{
|
||||
encode zstd gzip
|
||||
{gate(env.get("LIVE_REQUIRE_GROUP", ""))} @me path /me /me/*
|
||||
{gate(env.get("LIVE_REQUIRE_GROUP", ""))} handle /whoami {{
|
||||
header Content-Type text/plain
|
||||
respond "user: {{http.request.header.X-Authentik-Username}}
|
||||
groups: {{http.request.header.X-Authentik-Groups}}"
|
||||
}}
|
||||
@me path /me /me/*
|
||||
handle @me {{
|
||||
reverse_proxy 127.0.0.1:8080 # dumpd: identity + /me/stream-token for the logged-in streamer (Go Live)
|
||||
reverse_proxy 127.0.0.1:8080 # dumpd: identity, stream tokens (Go Live + dock)
|
||||
}}
|
||||
handle /time {{
|
||||
reverse_proxy 127.0.0.1:8080 # server clock for the timecode strip
|
||||
reverse_proxy 127.0.0.1:8080 # server clock for the timecode strip (clock page + Go Live)
|
||||
}}
|
||||
handle /dump* {{
|
||||
reverse_proxy 127.0.0.1:8080 # dump tonight (dock)
|
||||
}}
|
||||
handle_path /dock* {{
|
||||
root * /srv/dock
|
||||
file_server # OBS browser dock + /dock/clock/
|
||||
}}
|
||||
handle_path /api/* {{
|
||||
reverse_proxy 127.0.0.1:9997
|
||||
@@ -231,24 +288,11 @@ def write_caddy(domain, auth_host="", watch_host="", git_host="", bot_host="", l
|
||||
encode zstd gzip
|
||||
reverse_proxy 127.0.0.1:8096
|
||||
}}
|
||||
"""
|
||||
sync_group = env.get("SYNC_REQUIRE_GROUP", "media-admins")
|
||||
sync_gate = ""
|
||||
if sync_group:
|
||||
g = re.escape(sync_group)
|
||||
sync_gate = f""" @sync_lacks_group {{
|
||||
path /sync /sync/*
|
||||
not header_regexp X-Authentik-Groups (^|\\|){g}(\\||$)
|
||||
}}
|
||||
handle @sync_lacks_group {{
|
||||
respond "Syncthing admin is for the '{sync_group}' group." 403
|
||||
}}
|
||||
"""
|
||||
Path("Caddyfile").write_text(f"""# vanguard:main
|
||||
{domain} {{
|
||||
encode zstd gzip
|
||||
{AUTHENTIK_FORWARD_AUTH}
|
||||
# who does Authentik say I am? (debug: shows exactly the identity headers the apps receive)
|
||||
{gate_any} # who does Authentik say I am? (debug: shows exactly the identity headers the apps receive)
|
||||
handle /whoami {{
|
||||
header Content-Type text/plain
|
||||
respond "user: {{http.request.header.X-Authentik-Username}}
|
||||
@@ -256,60 +300,24 @@ groups: {{http.request.header.X-Authentik-Groups}}
|
||||
email: {{http.request.header.X-Authentik-Email}}
|
||||
name: {{http.request.header.X-Authentik-Name}}"
|
||||
}}
|
||||
|
||||
# dump endpoint + stream tokens (python service on the host; identity from the X-Authentik-* headers Caddy just set)
|
||||
handle /dump* {{
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}}
|
||||
@me path /me /me/*
|
||||
handle @me {{
|
||||
reverse_proxy 127.0.0.1:8080 # dumpd: identity, stream tokens, clips self-service
|
||||
reverse_proxy 127.0.0.1:8080 # dumpd: identity for the gateway page
|
||||
}}
|
||||
handle /time {{
|
||||
reverse_proxy 127.0.0.1:8080 # server clock for the timecode strip
|
||||
}}
|
||||
|
||||
# Syncthing admin UI: Authentik + group {sync_group or 'any'} (Syncthing's own GUI login is disabled)
|
||||
{sync_gate} redir /sync /sync/ 308
|
||||
handle_path /sync/* {{
|
||||
reverse_proxy 127.0.0.1:8384 {{
|
||||
header_up Host {{upstream_hostport}}
|
||||
}}
|
||||
}}
|
||||
|
||||
# OBS browser dock (static)
|
||||
handle_path /dock* {{
|
||||
root * /srv/dock
|
||||
file_server
|
||||
}}
|
||||
|
||||
# gateway page: role-aware links + instructions (static; talks to /me)
|
||||
redir /about /about/ 308
|
||||
handle_path /about/* {{
|
||||
root * /srv/about
|
||||
file_server
|
||||
}}
|
||||
|
||||
# clip intake self-service (static page; talks to /me/clips)
|
||||
redir /clips /clips/ 308
|
||||
handle_path /clips/* {{
|
||||
root * /srv/clips
|
||||
file_server
|
||||
}}
|
||||
|
||||
# copyparty. It honours X-Authentik-Username / -Groups only when the request also carries a header whose
|
||||
# secret NAME only this proxy knows (copyparty idp-h-key). Clients cannot forge identity.
|
||||
redir /about* / 308 # old bookmarks: the gateway page used to live at /about/
|
||||
handle {{
|
||||
reverse_proxy 127.0.0.1:3923 {{
|
||||
header_up X-Vanguard-{env.get("COPYPARTY_IDP_KEY", "key")} 1
|
||||
flush_interval -1
|
||||
}}
|
||||
root * /srv/about
|
||||
try_files {{path}} /index.html
|
||||
file_server # the gateway page is the root of the main host
|
||||
}}
|
||||
}}
|
||||
""" + extra)
|
||||
|
||||
def write_env(watch_host, discord_token=None, discord_guild=None, git_host="", bot_host="", live_host="", main_host="", live_webhook=None):
|
||||
def write_env(watch_host, discord_token=None, discord_guild=None, git_host="", bot_host="", live_host="", main_host="", live_webhook=None, files_host="", sync_host="", clips_host=""):
|
||||
env = read_env()
|
||||
if files_host: env["FILES_HOST"] = files_host
|
||||
if sync_host: env["SYNC_HOST"] = sync_host
|
||||
if clips_host: env["CLIPS_HOST"] = clips_host
|
||||
env["LIVE_HOST"] = live_host or env.get("LIVE_HOST", "live.example.com")
|
||||
if main_host: env["MAIN_HOST"] = main_host
|
||||
if live_webhook is not None: env["LIVE_WEBHOOK_URL"] = live_webhook
|
||||
@@ -474,15 +482,15 @@ def run(cmd, **kw):
|
||||
if DRY: return 0
|
||||
return subprocess.call(cmd, **kw)
|
||||
|
||||
def apply(domain, admin_pw, streamers, editors, auth_host="", watch_host="", discord_token=None, discord_guild=None, git_host="", bot_host="", live_host="", live_webhook=None):
|
||||
def apply(domain, admin_pw, streamers, editors, auth_host="", watch_host="", discord_token=None, discord_guild=None, git_host="", bot_host="", live_host="", live_webhook=None, files_host="", sync_host="", clips_host=""):
|
||||
# admin_pw / editors are legacy no-ops: access is by Authentik group now
|
||||
if not streamers and Path("mediamtx.yml").exists() and "CHANGEME" in Path("mediamtx.yml").read_text():
|
||||
print("\n!! mediamtx.yml contains CHANGEME placeholders — it looks like the repo template was copied over the")
|
||||
print(" generated config. Applying now would leave NO streamers (OBS ingest and the dump button stop working).")
|
||||
if not yes(" continue anyway?", False): print("aborted; add streamers first ([s] in the menu)"); sys.exit(1)
|
||||
print("\n== writing configs")
|
||||
write_env(watch_host, discord_token, discord_guild, git_host, bot_host, live_host, domain, live_webhook)
|
||||
write_caddy(domain, auth_host, watch_host, git_host, bot_host, live_host); write_mediamtx(domain); write_copyparty()
|
||||
write_env(watch_host, discord_token, discord_guild, git_host, bot_host, live_host, domain, live_webhook, files_host, sync_host, clips_host)
|
||||
write_caddy(domain, auth_host, watch_host, git_host, bot_host, live_host, files_host, sync_host, clips_host); write_mediamtx(domain); write_copyparty()
|
||||
Path("stream-token.secret").write_text(read_env()["STREAM_TOKEN_SECRET"] + "\n"); os.chmod("stream-token.secret", 0o600)
|
||||
run(["sudo", "install", "-d", "-o", os.environ.get("SUDO_USER") or os.environ.get("USER") or "debian", "/srv/live"])
|
||||
print("== app data folders")
|
||||
@@ -554,11 +562,14 @@ def post_start_fixups(dc):
|
||||
if DRY: print(" (dry) installJellyfinPlugin.sh")
|
||||
else: subprocess.run(["bash", "installJellyfinPlugin.sh"], capture_output=True, text=True); print(" jellyfin plugin: ensured")
|
||||
|
||||
def show(domain, admin_pw, streamers, editors, auth_host="", watch_host="", git_host="", bot_host="", live_host=""):
|
||||
print(f"\n== domain : {domain or '(not set)'}")
|
||||
def show(domain, admin_pw, streamers, editors, auth_host="", watch_host="", git_host="", bot_host="", live_host="", files_host="", sync_host="", clips_host=""):
|
||||
print(f"\n== gateway : https://{domain or 'HOST'}/ (/whoami, /logout)")
|
||||
print(f"== files : https://{files_host}/ (copyparty; editors / media-admins)" if files_host else "== files : (not set — run --full)")
|
||||
print(f"== clips : https://{clips_host}/ (self-service clip intake, any member)" if clips_host else "== clips : (not set — run --full)")
|
||||
print(f"== sync : https://{sync_host}/ (Syncthing UI, media-admins)" if sync_host else "== sync : (not set — run --full)")
|
||||
_e = read_env()
|
||||
if _e.get("APEX_HOST") and _e.get("APEX_REDIRECT"): print(f"== apex : https://{_e['APEX_HOST']}/ -> {_e['APEX_REDIRECT']}")
|
||||
print(f"== live : https://{live_host}/ (behind Authentik forward-auth; deploy live/dist -> /srv/live; WebRTC needs 8189 open)" if live_host else "== live : (not set — run --full)")
|
||||
print(f"== live : https://{live_host}/ (portal; /dock/ for OBS; WebRTC needs 8189 open)" if live_host else "== live : (not set — run --full)")
|
||||
print(f"== bot web : https://{bot_host}/ (Authentik forward-auth; Caddy requires group '{read_env().get('BOT_REQUIRE_GROUP','bot-users') or 'any'}')" if bot_host else "== bot web : (not set — run --full)")
|
||||
print(f"== gitea : https://{git_host}/ ssh port 2222 admin {read_env().get('GITEA_ADMIN_USER','vanguard')} / {read_env().get('GITEA_ADMIN_PASSWORD','?')} (runner: ./registerGiteaRunner.sh)" if git_host else "== gitea : (not set — run --full)")
|
||||
print(f"== authentik: https://{auth_host}/ akadmin password = AUTHENTIK_BOOTSTRAP_PASSWORD in .env (set on first start; change it in the UI)" if auth_host else "== authentik: (not set — run --full)")
|
||||
@@ -572,11 +583,10 @@ def show(domain, admin_pw, streamers, editors, auth_host="", watch_host="", git_
|
||||
print("== access : by Authentik group — editors (read streams/clips, write finals), media-admins (everything), admins (dump anyone)")
|
||||
print(" Discord login only — no WebDAV; downloads via the web UI")
|
||||
print("== streamers: anyone in the Authentik 'streamers' group (Discord role). No passwords, no keys to hand out.")
|
||||
print(f" OBS: add the dock https://{domain or 'HOST'}/dock/ in OBS, log in with Discord, Go Live — it mints a 12 h token")
|
||||
print(f" OBS: add the dock https://{live_host or 'LIVE'}/dock/ in OBS, log in with Discord, Go Live — it mints a 12 h token")
|
||||
print(f" and sets the stream key itself. Manual setups: dock → 'Manual OBS setup' (rtmp://{domain or 'HOST'}:1935/ + key).")
|
||||
print(f"\n editors log in with Discord at https://{domain or 'HOST'}/")
|
||||
print(f" verify: curl -sI https://{domain or 'HOST'}/dock/ | head -1 (expect 200)")
|
||||
print(f" curl -s -o /dev/null -w '%{{http_code}}\\n' https://{domain or 'HOST'}/dump (expect 401)\n")
|
||||
print(f"\n editors: https://{files_host or 'FILES'}/ everyone: https://{domain or 'HOST'}/")
|
||||
print(f" verify: curl -s -o /dev/null -w '%{{http_code}}\\n' https://{domain or 'HOST'}/ (expect 302 → Authentik)\n")
|
||||
|
||||
# ------------------------------------------------------------------ modes
|
||||
def manage_users(kind, users):
|
||||
@@ -596,12 +606,15 @@ def manage_users(kind, users):
|
||||
else:
|
||||
users[n] = ask_pw(n, users[n])
|
||||
|
||||
def full(domain, admin_pw, streamers, editors, auth_host="", watch_host="", git_host="", bot_host="", live_host=""):
|
||||
def full(domain, admin_pw, streamers, editors, auth_host="", watch_host="", git_host="", bot_host="", live_host="", files_host="", sync_host="", clips_host=""):
|
||||
print("== FULL SETUP (enter keeps the shown default)\n")
|
||||
while True:
|
||||
domain = ask("public hostname (DNS A record must point here)", domain)
|
||||
domain = ask("main hostname = the gateway page (DNS A record must point here)", domain)
|
||||
if domain and "." in domain and " " not in domain: break
|
||||
print(" need a hostname like media.example.com")
|
||||
files_host = ask("Files (copyparty) hostname (CNAME to the above)", files_host or default_sub(domain, "files"))
|
||||
clips_host = ask("Clips self-service hostname (CNAME to the above)", clips_host or default_sub(domain, "clips"))
|
||||
sync_host = ask("Syncthing UI hostname (CNAME to the above)", sync_host or default_sub(domain, "sync"))
|
||||
auth_host = ask("Authentik hostname (CNAME to the above)", auth_host or default_sub(domain, "auth"))
|
||||
watch_host = ask("Jellyfin hostname (CNAME to the above)", watch_host or default_sub(domain, "watch"))
|
||||
git_host = ask("Gitea hostname (CNAME to the above)", git_host or default_sub(domain, "git"))
|
||||
@@ -609,7 +622,7 @@ def full(domain, admin_pw, streamers, editors, auth_host="", watch_host="", git_
|
||||
live_host = ask("Live portal hostname (CNAME to the above)", live_host or default_sub(domain, "live"))
|
||||
env0 = read_env(); parent = default_sub(domain, "x")[2:] if domain else ""
|
||||
apex = ask("Bare domain to serve too (A record must point here; blank = skip)", env0.get("APEX_HOST", parent))
|
||||
apex_to = ask(" bare domain redirects to", env0.get("APEX_REDIRECT") or (f"https://{watch_host}/" if watch_host else "")) if apex else ""
|
||||
apex_to = ask(" bare domain redirects to", env0.get("APEX_REDIRECT") or f"https://{domain}/") if apex else ""
|
||||
print("\n-- Discord bot (optional; the Bot added to the Authentik Discord application). Enter keeps the current value.")
|
||||
discord_token, discord_guild = ask_discord()
|
||||
live_webhook = ask(" Discord webhook URL for 'is live' notices (optional)", read_env().get("LIVE_WEBHOOK_URL", ""))
|
||||
@@ -636,7 +649,7 @@ def full(domain, admin_pw, streamers, editors, auth_host="", watch_host="", git_
|
||||
Path(".env").write_text("".join(f"{k}={v}\n" for k, v in e.items())) if Path(".env").exists() else None
|
||||
if not Path(".env").exists():
|
||||
Path(".env").write_text(f"APEX_HOST={apex}\nAPEX_REDIRECT={apex_to}\n"); os.chmod(".env", 0o600)
|
||||
return domain, admin_pw, streamers, editors, auth_host, watch_host, discord_token, discord_guild, git_host, bot_host, live_host, live_webhook
|
||||
return domain, admin_pw, streamers, editors, auth_host, watch_host, discord_token, discord_guild, git_host, bot_host, live_host, live_webhook, files_host, sync_host, clips_host
|
||||
|
||||
def ask_discord():
|
||||
env = read_env()
|
||||
@@ -663,27 +676,28 @@ def main():
|
||||
mode = sys.argv[1] if len(sys.argv) > 1 else ""
|
||||
hosts = read_hosts()
|
||||
domain, auth_host, watch_host, git_host, bot_host, live_host = hosts.get("main", ""), hosts.get("auth", ""), hosts.get("watch", ""), hosts.get("git", ""), hosts.get("bot", ""), hosts.get("live", "")
|
||||
files_host, sync_host, clips_host = hosts.get("files", ""), hosts.get("sync", ""), hosts.get("clips", "")
|
||||
streamers, accounts = read_streamers(), read_accounts()
|
||||
admin_pw = accounts.pop("admin", "")
|
||||
editors = accounts
|
||||
if mode == "--show":
|
||||
show(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host); return
|
||||
show(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host, files_host, sync_host, clips_host); return
|
||||
if mode == "--apply":
|
||||
if not domain: print("domain not set yet — run ./configure.py --full first"); sys.exit(1)
|
||||
apply(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host=git_host, bot_host=bot_host, live_host=live_host)
|
||||
show(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host); return
|
||||
apply(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host=git_host, bot_host=bot_host, live_host=live_host, files_host=files_host, sync_host=sync_host, clips_host=clips_host)
|
||||
show(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host, files_host, sync_host, clips_host); return
|
||||
if mode == "--hosts":
|
||||
if len(sys.argv) not in (4, 5, 6, 7): print("usage: configure.py --hosts AUTH_HOST WATCH_HOST [GIT_HOST [BOT_HOST [LIVE_HOST]]]"); sys.exit(2)
|
||||
if not 4 <= len(sys.argv) <= 10: print("usage: configure.py --hosts AUTH WATCH [GIT [BOT [LIVE [FILES [SYNC [CLIPS]]]]]]"); sys.exit(2)
|
||||
if not domain: print("domain not set yet — run ./configure.py --full first"); sys.exit(1)
|
||||
auth_host, watch_host = sys.argv[2].strip(), sys.argv[3].strip()
|
||||
if len(sys.argv) >= 5: git_host = sys.argv[4].strip()
|
||||
if len(sys.argv) >= 6: bot_host = sys.argv[5].strip()
|
||||
if len(sys.argv) == 7: live_host = sys.argv[6].strip()
|
||||
apply(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host=git_host, bot_host=bot_host, live_host=live_host)
|
||||
show(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host); return
|
||||
a = [x.strip() for x in sys.argv[2:]] + [None] * 8
|
||||
auth_host, watch_host = a[0], a[1]
|
||||
git_host, bot_host, live_host = (a[2] if a[2] is not None else git_host), (a[3] if a[3] is not None else bot_host), (a[4] if a[4] is not None else live_host)
|
||||
files_host, sync_host, clips_host = (a[5] if a[5] is not None else files_host), (a[6] if a[6] is not None else sync_host), (a[7] if a[7] is not None else clips_host)
|
||||
apply(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host=git_host, bot_host=bot_host, live_host=live_host, files_host=files_host, sync_host=sync_host, clips_host=clips_host)
|
||||
show(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host, files_host, sync_host, clips_host); return
|
||||
discord_token = discord_guild = live_webhook = None
|
||||
if mode == "--full":
|
||||
domain, admin_pw, streamers, editors, auth_host, watch_host, discord_token, discord_guild, git_host, bot_host, live_host, live_webhook = full(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host)
|
||||
domain, admin_pw, streamers, editors, auth_host, watch_host, discord_token, discord_guild, git_host, bot_host, live_host, live_webhook, files_host, sync_host, clips_host = full(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host, files_host, sync_host, clips_host)
|
||||
if not yes("\napply now (write configs, restart services)?"): print("nothing written"); return
|
||||
elif mode == "":
|
||||
r = normal(domain, admin_pw, streamers, editors)
|
||||
@@ -691,8 +705,8 @@ def main():
|
||||
discord_token, discord_guild = r
|
||||
else:
|
||||
print(__doc__); sys.exit(2)
|
||||
apply(domain, admin_pw, streamers, editors, auth_host, watch_host, discord_token, discord_guild, git_host, bot_host, live_host, live_webhook)
|
||||
show(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host)
|
||||
apply(domain, admin_pw, streamers, editors, auth_host, watch_host, discord_token, discord_guild, git_host, bot_host, live_host, live_webhook, files_host, sync_host, clips_host)
|
||||
show(domain, admin_pw, streamers, editors, auth_host, watch_host, git_host, bot_host, live_host, files_host, sync_host, clips_host)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try: main()
|
||||
|
||||
Reference in New Issue
Block a user