's'
This commit is contained in:
131
scripts/ssh-restore-lounge.py
Normal file
131
scripts/ssh-restore-lounge.py
Normal file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Restore corrupted The Lounge config.js on production VPS."""
|
||||
from __future__ import annotations
|
||||
|
||||
import paramiko
|
||||
|
||||
import os
|
||||
|
||||
HOST = os.getenv("NOMAD_SSH_HOST", "82.157.112.245")
|
||||
USER = os.getenv("NOMAD_SSH_USER", "ubuntu")
|
||||
PASSWORD = os.getenv("NOMAD_SSH_PASSWORD", "")
|
||||
|
||||
INSPECT = [
|
||||
"cat /var/lib/thelounge/config.js 2>&1 | head -20",
|
||||
"ls -la /var/lib/thelounge/ 2>&1",
|
||||
"ls -la /var/lib/thelounge/*.bak /var/lib/thelounge/config.js.* 2>&1 || true",
|
||||
"cat /etc/systemd/system/thelounge.service 2>&1",
|
||||
"sudo ls -la /var/lib/thelounge/ 2>&1",
|
||||
]
|
||||
|
||||
LOUNGE_CONFIG = r"""'use strict';
|
||||
|
||||
module.exports = {
|
||||
host: '127.0.0.1',
|
||||
port: 9000,
|
||||
public: true,
|
||||
theme: 'morning',
|
||||
prefetch: false,
|
||||
disableLog: false,
|
||||
fileUpload: false,
|
||||
transports: ['websocket', 'polling'],
|
||||
defaults: {
|
||||
name: 'NomadCNA',
|
||||
username: 'nomad',
|
||||
realname: 'NomadCNA Community',
|
||||
join: '#nomadcna,#online-events',
|
||||
},
|
||||
lockNetwork: true,
|
||||
messageStorage: [],
|
||||
useHexIp: false,
|
||||
maxHistory: 10000,
|
||||
displayNetwork: true,
|
||||
networks: [
|
||||
{
|
||||
name: 'NomadCNA',
|
||||
host: '127.0.0.1',
|
||||
port: 6667,
|
||||
tls: false,
|
||||
rejectUnauthorized: false,
|
||||
nick: 'nomad',
|
||||
username: 'nomad',
|
||||
realname: 'NomadCNA Community',
|
||||
join: '#nomadcna,#online-events',
|
||||
commands: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
"""
|
||||
|
||||
|
||||
def run(commands: list[str]) -> None:
|
||||
client = paramiko.SSHClient()
|
||||
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
client.connect(HOST, username=USER, password=PASSWORD, timeout=25)
|
||||
try:
|
||||
for cmd in commands:
|
||||
print(f"\n=== {cmd} ===")
|
||||
_, stdout, stderr = client.exec_command(cmd, timeout=60, get_pty=True)
|
||||
out = stdout.read().decode("utf-8", errors="replace")
|
||||
err = stderr.read().decode("utf-8", errors="replace")
|
||||
if out:
|
||||
print(out.rstrip())
|
||||
if err:
|
||||
print("ERR:", err.rstrip())
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
def restore() -> None:
|
||||
client = paramiko.SSHClient()
|
||||
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
client.connect(HOST, username=USER, password=PASSWORD, timeout=25)
|
||||
try:
|
||||
sftp = client.open_sftp()
|
||||
remote_tmp = "/tmp/thelounge-config.js"
|
||||
with sftp.file(remote_tmp, "w") as f:
|
||||
f.write(LOUNGE_CONFIG)
|
||||
sftp.close()
|
||||
|
||||
cmds = [
|
||||
f"echo '{PASSWORD}' | sudo -S cp /var/lib/thelounge/config.js /var/lib/thelounge/config.js.broken-$(date +%Y%m%d%H%M%S) 2>/dev/null || true",
|
||||
f"echo '{PASSWORD}' | sudo -S cp {remote_tmp} /var/lib/thelounge/config.js",
|
||||
f"echo '{PASSWORD}' | sudo -S chown thelounge:thelounge /var/lib/thelounge/config.js",
|
||||
f"echo '{PASSWORD}' | sudo -S chmod 640 /var/lib/thelounge/config.js",
|
||||
f"echo '{PASSWORD}' | sudo -S systemctl restart thelounge.service",
|
||||
"sleep 3",
|
||||
"systemctl is-active thelounge.service",
|
||||
"curl -sI http://127.0.0.1:9000/ | head -8",
|
||||
"curl -sI https://lounge.nomadro.cn/ | head -8",
|
||||
"journalctl -u thelounge.service -n 15 --no-pager",
|
||||
]
|
||||
for cmd in cmds:
|
||||
print(f"\n=== {cmd.replace(PASSWORD, '***')} ===")
|
||||
_, stdout, stderr = client.exec_command(cmd, timeout=60, get_pty=True)
|
||||
out = stdout.read().decode("utf-8", errors="replace")
|
||||
err = stderr.read().decode("utf-8", errors="replace")
|
||||
if out:
|
||||
print(out.rstrip())
|
||||
if err:
|
||||
print("ERR:", err.rstrip())
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
VERIFY = [
|
||||
"systemctl is-active thelounge.service ergo.service",
|
||||
"curl -s 'https://lounge.nomadro.cn/socket.io/?EIO=4&transport=polling&t=health' | cut -c1-120",
|
||||
"{ printf 'NICK health\\r\\nUSER health 0 * :NomadCNA Health\\r\\nJOIN #nomadcna\\r\\nQUIT :healthcheck\\r\\n'; sleep 1; } | timeout 5s nc 127.0.0.1 6667 2>&1 | head -5",
|
||||
"curl -sI 'https://lounge.nomadro.cn/' | head -3",
|
||||
]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "restore":
|
||||
restore()
|
||||
elif len(sys.argv) > 1 and sys.argv[1] == "verify":
|
||||
run(VERIFY)
|
||||
else:
|
||||
run(INSPECT)
|
||||
Reference in New Issue
Block a user