import paramiko import sys HOST = "39.102.124.161" USER = "root" PASS = "Beast2026" VHOST_CONFIG = r"""# Redirect HTTP to HTTPS server { listen 80; server_name www.thereisnospoonadu.com thereisnospoonadu.com; location /.well-known/acme-challenge/ { root /var/www/certbot; allow all; } location / { return 301 https://$host$request_uri; } } # HTTPS Server server { listen 443 ssl; server_name www.thereisnospoonadu.com thereisnospoonadu.com; ssl_certificate /etc/letsencrypt/live/www.thereisnospoonadu.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.thereisnospoonadu.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; root /www/wwwroot/soft_download; index index.html index.htm; charset utf-8; client_max_body_size 500M; client_body_timeout 300s; send_timeout 300s; keepalive_timeout 300s; proxy_read_timeout 300s; location = / { try_files /index.html =404; add_header Access-Control-Allow-Origin *; } location = /index.html { add_header Access-Control-Allow-Origin *; } location = /login.html { add_header Access-Control-Allow-Origin *; } location = /api/validate { auth_basic "App Download Portal"; auth_basic_user_file /etc/tengine/.htpasswd; add_header Content-Type application/json; add_header Access-Control-Allow-Origin *; try_files /api/validate =404; } location ^~ /list/ { index nothing_will_match; auth_basic "App Download Portal"; auth_basic_user_file /etc/tengine/.htpasswd; alias /www/wwwroot/soft_download/; autoindex on; autoindex_exact_size off; autoindex_localtime on; autoindex_format json; add_header Access-Control-Allow-Origin *; } location ~ \.(exe|md|pdf|zip|rar|7z|tar|gz|txt|doc|docx|xls|xlsx|ppt|pptx|deb)$ { add_header Content-Disposition "attachment"; add_header X-Content-Type-Options "nosniff"; add_header Access-Control-Allow-Origin *; } location / { auth_basic "App Download Portal"; auth_basic_user_file /etc/tengine/.htpasswd; try_files $uri $uri/ =404; add_header Access-Control-Allow-Origin *; } access_log /var/log/tengine/download_access.log; error_log /var/log/tengine/download_error.log warn; server_tokens off; } """ def run_cmd(ssh, cmd, desc=""): if desc: print(f"\n{'='*60}") print(f">>> {desc}") print(f"CMD: {cmd}") print('='*60) stdin, stdout, stderr = ssh.exec_command(cmd, timeout=30) out = stdout.read().decode('utf-8', errors='replace') err = stderr.read().decode('utf-8', errors='replace') rc = stdout.channel.recv_exit_status() if out: print("STDOUT:", out) if err: print("STDERR:", err) print(f"EXIT CODE: {rc}") return rc, out, err def main(): print(f"Connecting to {HOST}...") ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(HOST, username=USER, password=PASS, timeout=15) print("Connected.\n") # Step 1: Write the vhost config print("="*60) print(">>> STEP 1: Write vhost config") print("="*60) run_cmd(ssh, "mkdir -p /etc/tengine/conf.d", "Ensure conf.d dir exists") sftp = ssh.open_sftp() with sftp.open("/etc/tengine/conf.d/thereisnospoonadu.conf", "w") as f: f.write(VHOST_CONFIG) sftp.close() print("File written: /etc/tengine/conf.d/thereisnospoonadu.conf") # Verify write run_cmd(ssh, "cat /etc/tengine/conf.d/thereisnospoonadu.conf", "Verify written file") # Step 2: Test the config run_cmd(ssh, "tengine -t", "STEP 2: tengine -t (config test)") # Step 3: Enable and start tengine run_cmd(ssh, "systemctl enable tengine && systemctl start tengine", "STEP 3: Enable and start tengine") # Step 4: Verify running and listening run_cmd(ssh, "systemctl status tengine --no-pager", "STEP 4a: systemctl status tengine") run_cmd(ssh, "ss -tlnp | grep -E '80|443'", "STEP 4b: ss -tlnp ports 80/443") # Step 5: Quick local test run_cmd(ssh, 'curl -sk https://localhost/ -o /dev/null -w "%{http_code}" --resolve www.thereisnospoonadu.com:443:127.0.0.1 -H "Host: www.thereisnospoonadu.com" 2>/dev/null || echo "curl test done"', "STEP 5: Quick local curl test" ) ssh.close() print("\nAll steps complete.") if __name__ == "__main__": main()