forked from test2/Amnezia-Web-Panel-main
Add optional Mieru (mita v3.28.0) install per server with mierus:// share links.
EOF Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -103,7 +103,7 @@ else:
|
||||
application_path = os.path.dirname(__file__)
|
||||
|
||||
DATA_FILE = os.path.join(application_path, 'data.json') # legacy JSON; used only for one-shot import / export
|
||||
CURRENT_VERSION = "v2.6.3"
|
||||
CURRENT_VERSION = "v2.6.4"
|
||||
RELEASES_REPO_URL = repo_url()
|
||||
RELEASES_API_LATEST = api_latest_url()
|
||||
BIN_DIR = os.environ.get('TUNNEL_BIN_DIR', os.path.join(application_path, 'bin'))
|
||||
@@ -1111,8 +1111,9 @@ async def wait_for_tunnel_url(provider: str, seconds: int = 20):
|
||||
return get_tunnel_status(provider)
|
||||
|
||||
|
||||
BASE_PROTOCOLS = ['awg', 'awg2', 'awg_legacy', 'xray', 'telemt', 'hysteria', 'naiveproxy', 'dns', 'wireguard', 'socks5', 'adguard', 'nginx']
|
||||
BASE_PROTOCOLS = ['awg', 'awg2', 'awg_legacy', 'xray', 'telemt', 'hysteria', 'naiveproxy', 'mieru', 'dns', 'wireguard', 'socks5', 'adguard', 'nginx']
|
||||
MULTI_INSTANCE_PROTOCOLS = {'awg', 'awg2', 'awg_legacy', 'xray', 'telemt', 'hysteria', 'socks5'}
|
||||
NON_DOCKER_PROTOCOLS = frozenset({'mieru'})
|
||||
|
||||
|
||||
def protocol_base(protocol: str) -> str:
|
||||
@@ -1154,6 +1155,7 @@ def protocol_display_name(protocol: str) -> str:
|
||||
'telemt': 'Telemt',
|
||||
'hysteria': 'Hysteria 2',
|
||||
'naiveproxy': 'NaiveProxy',
|
||||
'mieru': 'Mieru',
|
||||
'dns': 'AmneziaDNS',
|
||||
'wireguard': 'WireGuard',
|
||||
'socks5': 'SOCKS5',
|
||||
@@ -1175,6 +1177,7 @@ def protocol_container_name(protocol: str) -> Optional[str]:
|
||||
'telemt': 'telemt',
|
||||
'hysteria': 'amnezia-hysteria',
|
||||
'naiveproxy': 'amnezia-naiveproxy',
|
||||
'mieru': 'mita',
|
||||
'dns': 'amnezia-dns',
|
||||
'wireguard': 'amnezia-wireguard',
|
||||
'socks5': 'amnezia-socks5proxy',
|
||||
@@ -1220,6 +1223,9 @@ def get_protocol_manager(ssh, protocol: str):
|
||||
elif base == 'naiveproxy':
|
||||
from managers.naiveproxy_manager import NaiveProxyManager
|
||||
return NaiveProxyManager(ssh, protocol)
|
||||
elif base == 'mieru':
|
||||
from managers.mieru_manager import MieruManager
|
||||
return MieruManager(ssh, protocol)
|
||||
from managers.awg_manager import AWGManager
|
||||
return AWGManager(ssh)
|
||||
|
||||
@@ -1281,7 +1287,7 @@ def _manager_call(manager, method, protocol, *args, **kwargs):
|
||||
|
||||
|
||||
# Protocols that own VPN clients (can list/link connections)
|
||||
CLIENT_VPN_BASES = {'awg', 'awg2', 'awg_legacy', 'xray', 'telemt', 'wireguard', 'hysteria', 'naiveproxy', 'xui'}
|
||||
CLIENT_VPN_BASES = {'awg', 'awg2', 'awg_legacy', 'xray', 'telemt', 'wireguard', 'hysteria', 'naiveproxy', 'mieru', 'xui'}
|
||||
|
||||
|
||||
def generate_vpn_link(config_text):
|
||||
@@ -3466,6 +3472,12 @@ async def api_check_server(request: Request, server_id: int):
|
||||
merged[key] = db_proto[key]
|
||||
if db_proto.get('port') and not merged.get('port'):
|
||||
merged['port'] = db_proto['port']
|
||||
if protocol_base(proto) == 'mieru':
|
||||
for key in ('release',):
|
||||
if db_proto.get(key) not in (None, '') and not merged.get(key):
|
||||
merged[key] = db_proto[key]
|
||||
if db_proto.get('port') and not merged.get('port'):
|
||||
merged['port'] = db_proto['port']
|
||||
return merged
|
||||
|
||||
def should_preserve_saved_protocol(proto, result=None, err=None):
|
||||
@@ -3480,8 +3492,9 @@ async def api_check_server(request: Request, server_id: int):
|
||||
|
||||
def check_proto(proto):
|
||||
cname = protocol_container_name(proto)
|
||||
base = protocol_base(proto)
|
||||
# Fast path: skip deep manager probes when container is absent
|
||||
if cname and cname not in inventory:
|
||||
if cname and cname not in inventory and base not in NON_DOCKER_PROTOCOLS:
|
||||
return proto, merge_saved_protocol_status(proto, {
|
||||
'container_exists': False,
|
||||
'container_running': False,
|
||||
@@ -3574,7 +3587,9 @@ async def api_install_protocol(request: Request, server_id: int, req: InstallPro
|
||||
|
||||
ssh = get_ssh(server)
|
||||
ssh.connect()
|
||||
docker_install_log = ensure_docker_installed(ssh)
|
||||
docker_install_log = ''
|
||||
if install_base not in NON_DOCKER_PROTOCOLS:
|
||||
docker_install_log = ensure_docker_installed(ssh)
|
||||
manager = get_protocol_manager(ssh, install_protocol)
|
||||
|
||||
# Pass parameters to installer
|
||||
@@ -3631,6 +3646,11 @@ async def api_install_protocol(request: Request, server_id: int, req: InstallPro
|
||||
domain=req.naiveproxy_domain,
|
||||
email=req.naiveproxy_email,
|
||||
)
|
||||
elif install_base == 'mieru':
|
||||
result = manager.install_protocol(
|
||||
protocol_type=install_protocol,
|
||||
port=req.port,
|
||||
)
|
||||
else:
|
||||
result = manager.install_protocol(install_protocol, port=req.port)
|
||||
|
||||
@@ -3680,6 +3700,11 @@ async def api_install_protocol(request: Request, server_id: int, req: InstallPro
|
||||
proto_record['email'] = result.get('email')
|
||||
if result.get('port'):
|
||||
proto_record['port'] = str(result['port'])
|
||||
if install_base == 'mieru':
|
||||
if result.get('port'):
|
||||
proto_record['port'] = str(result['port'])
|
||||
if result.get('release'):
|
||||
proto_record['release'] = result.get('release')
|
||||
proto_record['base_protocol'] = install_base
|
||||
proto_record['instance'] = protocol_instance(install_protocol)
|
||||
proto_record['display_name'] = protocol_display_name(install_protocol)
|
||||
@@ -3867,6 +3892,7 @@ CONTAINER_NAMES = {
|
||||
'telemt': 'telemt',
|
||||
'hysteria': 'amnezia-hysteria',
|
||||
'naiveproxy': 'amnezia-naiveproxy',
|
||||
'mieru': 'mita',
|
||||
'dns': 'amnezia-dns',
|
||||
'wireguard': 'amnezia-wireguard',
|
||||
'socks5': 'amnezia-socks5proxy',
|
||||
@@ -4164,6 +4190,35 @@ async def api_container_toggle(request: Request, server_id: int, req: ProtocolRe
|
||||
server = data['servers'][server_id]
|
||||
ssh = get_ssh(server)
|
||||
ssh.connect()
|
||||
base = protocol_base(req.protocol)
|
||||
if base in NON_DOCKER_PROTOCOLS:
|
||||
manager = get_protocol_manager(ssh, req.protocol)
|
||||
is_running = manager.check_container_running(req.protocol)
|
||||
if is_running:
|
||||
manager.stop_service()
|
||||
action = 'stopped'
|
||||
else:
|
||||
manager.start_service()
|
||||
action = 'started'
|
||||
diag = manager.get_container_diagnostics(req.protocol)
|
||||
error = diag.get('error_summary') or ''
|
||||
recent_logs = diag.get('recent_logs') or ''
|
||||
if action == 'started' and not diag.get('running'):
|
||||
ssh.disconnect()
|
||||
return JSONResponse({
|
||||
'error': error or 'Mieru failed to start',
|
||||
'action': action,
|
||||
'container': container,
|
||||
'recent_logs': recent_logs,
|
||||
}, status_code=400)
|
||||
ssh.disconnect()
|
||||
return {
|
||||
'status': 'success',
|
||||
'action': action,
|
||||
'container': container,
|
||||
'error': error,
|
||||
'recent_logs': recent_logs,
|
||||
}
|
||||
# Check current state
|
||||
out, _, _ = ssh.run_sudo_command(
|
||||
f"docker inspect -f '{{{{.State.Running}}}}' {container} 2>/dev/null"
|
||||
@@ -4227,6 +4282,20 @@ async def api_container_logs(request: Request, server_id: int, req: ContainerLog
|
||||
container = protocol_container_name(req.protocol)
|
||||
ssh = get_ssh(server)
|
||||
ssh.connect()
|
||||
if protocol_base(req.protocol) in NON_DOCKER_PROTOCOLS:
|
||||
mgr = get_protocol_manager(ssh, req.protocol)
|
||||
logs = mgr.get_logs(req.protocol, tail=req.tail or 200)
|
||||
diag = mgr.get_container_diagnostics(req.protocol)
|
||||
ssh.disconnect()
|
||||
return {
|
||||
'status': 'success',
|
||||
'protocol': req.protocol,
|
||||
'container': container,
|
||||
'logs': logs,
|
||||
'running': bool(diag.get('running')),
|
||||
'error': diag.get('error_summary') or '',
|
||||
'container_status': diag.get('status') or '',
|
||||
}
|
||||
if protocol_base(req.protocol) == 'hysteria':
|
||||
from managers.hysteria_manager import HysteriaManager
|
||||
mgr = HysteriaManager(ssh, req.protocol)
|
||||
@@ -4292,6 +4361,17 @@ async def api_container_logs_stream(request: Request, server_id: int, protocol:
|
||||
ssh = get_ssh(server)
|
||||
ssh.connect()
|
||||
try:
|
||||
if protocol_base(protocol) in NON_DOCKER_PROTOCOLS:
|
||||
mgr = get_protocol_manager(ssh, protocol)
|
||||
logs = mgr.get_logs(protocol, tail=tail)
|
||||
diag = mgr.get_container_diagnostics(protocol)
|
||||
state = '|'.join([
|
||||
diag.get('status') or '',
|
||||
'true' if diag.get('running') else 'false',
|
||||
'',
|
||||
diag.get('error_summary') or '',
|
||||
])
|
||||
return logs, state
|
||||
out, err, _ = ssh.run_sudo_command(
|
||||
f"docker logs --tail {tail} --timestamps {shlex.quote(container)} 2>&1",
|
||||
timeout=25,
|
||||
|
||||
Reference in New Issue
Block a user