<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[AdminsForum - aaPanel Websites & Web Servers Support]]></title>
		<link>https://adminsforum.com/</link>
		<description><![CDATA[AdminsForum - https://adminsforum.com]]></description>
		<pubDate>Thu, 15 Oct 2026 07:04:49 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Fix Python and Flask 502 Bad Gateway in aaPanel]]></title>
			<link>https://adminsforum.com/Thread-guide-fix-python-and-flask-502-bad-gateway-in-aapanel</link>
			<pubDate>Wed, 14 Oct 2026 15:10:30 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://adminsforum.com/member.php?action=profile&uid=2">DEV</a>]]></dc:creator>
			<guid isPermaLink="false">https://adminsforum.com/Thread-guide-fix-python-and-flask-502-bad-gateway-in-aapanel</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">A 502 Bad Gateway response from Nginx usually means it could not get a valid response from the application behind it. For a Flask project, diagnose Gunicorn and the local port before changing DNS or opening firewall ports.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested lab:</span> aaPanel Free 8.0.7 on Ubuntu 22.04.5. Project af_flask_lab uses Gunicorn on 127.0.0.1:3200 and Nginx serves flask.adminslab.com. We deliberately stopped this disposable project, reproduced public HTTP 502, then started it and recovered HTTP 200. No production website was stopped.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=220" target="_blank" title="">python-502-workflow-20261014.jpg</a> (Size: 93.17 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Diagnostic workflow diagram: check the app before changing its proxy configuration.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Separate the error from a certificate problem</span><br />
Open the hostname and record the actual response. A page saying 502 Bad Gateway is different from a TLS certificate warning, DNS failure or application-generated 500. Do not disable certificate validation to make the test appear successful.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Test the local application port</span><br />
From the VPS terminal, replacing 3200 with your actual port:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>curl -i http://127.0.0.1:3200/
ss -lntp | grep ':3200'</code></div></div><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Connection refused/no listener:</span> the app is stopped, failed at startup or bound to another port.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">HTTP 200 locally but 502 publicly:</span> inspect Nginx mapping and compare its upstream with the working listener.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Application 500 locally:</span> investigate the application traceback, configuration and database dependencies.<br />
</li>
</ul>
Do not expose the Gunicorn port to the Internet as a workaround. Nginx can reach a localhost listener without a public firewall rule for 3200.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Check aaPanel project status and logs</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Website → Python Project</span>, click the project name, then open <span style="font-weight: bold;" class="mycode_b">Project logs</span>. In our lab the log is:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>/www/wwwlogs/python/af_flask_lab/error.log</code></div></div>Read the newest startup messages. Look for ModuleNotFoundError, an incorrect callable, Permission denied, Address already in use or a missing environment executable. These need different fixes.<br />
<br />
For our app, <span style="font-weight: bold;" class="mycode_b">Project information</span> uses:<ul class="mycode_list"><li>Environment: af_python_lab<br />
</li>
<li>Path: /www/wwwroot/af-flask-lab<br />
</li>
<li>Startup way: Command Startup<br />
</li>
<li>User: www<br />
</li>
<li>Command: gunicorn --workers 1 --bind 127.0.0.1:3200 app:app<br />
</li>
</ul>
The first app in app:app means app.py; the second means the Flask object named app. Match your own module and object instead of copying this blindly.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Confirm the right packages are installed</span><br />
Use the selected environment's Python executable, not an unrelated system pip:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>/www/server/pyporject_evn/af_python_lab/bin/python -m pip show Flask gunicorn
/www/server/pyporject_evn/af_python_lab/bin/python -m pip check</code></div></div>The path above is the actual directory name used by this lab's aaPanel version. Use your environment path if different. Install missing application packages from its reviewed requirements file, then retry startup. Do not solve package errors by installing everything globally as root.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Compare the Nginx mapping</span><br />
In the project window, open <span style="font-weight: bold;" class="mycode_b">Mapping</span>. Confirm external network mapping is enabled and its detected port matches the actual Gunicorn listener. Ensure the domain is attached to this project in <span style="font-weight: bold;" class="mycode_b">Domain Manager</span>.<br />
<br />
For our HTTP Gunicorn app, Nginx routes to:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>proxy_pass http://127.0.0.1:3200;</code></div></div>A wrong port or using https for a plain-HTTP upstream can prevent Nginx from connecting. If you edit Nginx configuration, back it up, validate it and reload only after validation succeeds. Avoid replacing the entire configuration with an unrelated example.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Start the app and verify both paths</span><br />
Use the project's Start control after fixing the cause. Wait for the process to initialize, then test localhost and the public hostname again. In our controlled lab test:<ul class="mycode_list"><li>Before stopping: public HTTPS returned HTTP 200 and AdminsForum Flask lab.<br />
</li>
<li>After the native stop command: public HTTPS returned HTTP 502.<br />
</li>
<li>After the native start command: public HTTPS returned HTTP 200 with the expected Flask response.<br />
</li>
</ul>
This proves a stopped upstream can produce this symptom. It does not prove every 502 has that cause.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">If the problem occurs after reboot</span><br />
Check the native Startup option and allow for its advertised 120-second daemon interval. See <a href="https://adminsforum.com/Thread-guide-auto-start-python-and-flask-apps-after-reboot-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Python startup and reboot recovery</a>. That guide also documents a lab-version issue where saving project settings removed the SSL listener; verify HTTPS separately after settings changes.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">When asking for support</span><br />
Share the aaPanel version, startup method, sanitized command, local HTTP result, mapping port and relevant recent log lines. Remove passwords, tokens, cookies, private keys and database connection secrets before posting.<br />
<br />
<span style="font-style: italic;" class="mycode_i">AdminsForum lab-tested troubleshooting guide. Illustration is a workflow diagram, not a screenshot of an error page.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">A 502 Bad Gateway response from Nginx usually means it could not get a valid response from the application behind it. For a Flask project, diagnose Gunicorn and the local port before changing DNS or opening firewall ports.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested lab:</span> aaPanel Free 8.0.7 on Ubuntu 22.04.5. Project af_flask_lab uses Gunicorn on 127.0.0.1:3200 and Nginx serves flask.adminslab.com. We deliberately stopped this disposable project, reproduced public HTTP 502, then started it and recovered HTTP 200. No production website was stopped.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=220" target="_blank" title="">python-502-workflow-20261014.jpg</a> (Size: 93.17 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Diagnostic workflow diagram: check the app before changing its proxy configuration.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Separate the error from a certificate problem</span><br />
Open the hostname and record the actual response. A page saying 502 Bad Gateway is different from a TLS certificate warning, DNS failure or application-generated 500. Do not disable certificate validation to make the test appear successful.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Test the local application port</span><br />
From the VPS terminal, replacing 3200 with your actual port:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>curl -i http://127.0.0.1:3200/
ss -lntp | grep ':3200'</code></div></div><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Connection refused/no listener:</span> the app is stopped, failed at startup or bound to another port.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">HTTP 200 locally but 502 publicly:</span> inspect Nginx mapping and compare its upstream with the working listener.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Application 500 locally:</span> investigate the application traceback, configuration and database dependencies.<br />
</li>
</ul>
Do not expose the Gunicorn port to the Internet as a workaround. Nginx can reach a localhost listener without a public firewall rule for 3200.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Check aaPanel project status and logs</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Website → Python Project</span>, click the project name, then open <span style="font-weight: bold;" class="mycode_b">Project logs</span>. In our lab the log is:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>/www/wwwlogs/python/af_flask_lab/error.log</code></div></div>Read the newest startup messages. Look for ModuleNotFoundError, an incorrect callable, Permission denied, Address already in use or a missing environment executable. These need different fixes.<br />
<br />
For our app, <span style="font-weight: bold;" class="mycode_b">Project information</span> uses:<ul class="mycode_list"><li>Environment: af_python_lab<br />
</li>
<li>Path: /www/wwwroot/af-flask-lab<br />
</li>
<li>Startup way: Command Startup<br />
</li>
<li>User: www<br />
</li>
<li>Command: gunicorn --workers 1 --bind 127.0.0.1:3200 app:app<br />
</li>
</ul>
The first app in app:app means app.py; the second means the Flask object named app. Match your own module and object instead of copying this blindly.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Confirm the right packages are installed</span><br />
Use the selected environment's Python executable, not an unrelated system pip:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>/www/server/pyporject_evn/af_python_lab/bin/python -m pip show Flask gunicorn
/www/server/pyporject_evn/af_python_lab/bin/python -m pip check</code></div></div>The path above is the actual directory name used by this lab's aaPanel version. Use your environment path if different. Install missing application packages from its reviewed requirements file, then retry startup. Do not solve package errors by installing everything globally as root.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Compare the Nginx mapping</span><br />
In the project window, open <span style="font-weight: bold;" class="mycode_b">Mapping</span>. Confirm external network mapping is enabled and its detected port matches the actual Gunicorn listener. Ensure the domain is attached to this project in <span style="font-weight: bold;" class="mycode_b">Domain Manager</span>.<br />
<br />
For our HTTP Gunicorn app, Nginx routes to:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>proxy_pass http://127.0.0.1:3200;</code></div></div>A wrong port or using https for a plain-HTTP upstream can prevent Nginx from connecting. If you edit Nginx configuration, back it up, validate it and reload only after validation succeeds. Avoid replacing the entire configuration with an unrelated example.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Start the app and verify both paths</span><br />
Use the project's Start control after fixing the cause. Wait for the process to initialize, then test localhost and the public hostname again. In our controlled lab test:<ul class="mycode_list"><li>Before stopping: public HTTPS returned HTTP 200 and AdminsForum Flask lab.<br />
</li>
<li>After the native stop command: public HTTPS returned HTTP 502.<br />
</li>
<li>After the native start command: public HTTPS returned HTTP 200 with the expected Flask response.<br />
</li>
</ul>
This proves a stopped upstream can produce this symptom. It does not prove every 502 has that cause.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">If the problem occurs after reboot</span><br />
Check the native Startup option and allow for its advertised 120-second daemon interval. See <a href="https://adminsforum.com/Thread-guide-auto-start-python-and-flask-apps-after-reboot-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Python startup and reboot recovery</a>. That guide also documents a lab-version issue where saving project settings removed the SSL listener; verify HTTPS separately after settings changes.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">When asking for support</span><br />
Share the aaPanel version, startup method, sanitized command, local HTTP result, mapping port and relevant recent log lines. Remove passwords, tokens, cookies, private keys and database connection secrets before posting.<br />
<br />
<span style="font-style: italic;" class="mycode_i">AdminsForum lab-tested troubleshooting guide. Illustration is a workflow diagram, not a screenshot of an error page.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Fix Python venv and ensurepip Errors in aaPanel on Ubuntu]]></title>
			<link>https://adminsforum.com/Thread-guide-fix-python-venv-and-ensurepip-errors-in-aapanel-on-ubuntu</link>
			<pubDate>Wed, 14 Oct 2026 14:17:07 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://adminsforum.com/member.php?action=profile&uid=2">DEV</a>]]></dc:creator>
			<guid isPermaLink="false">https://adminsforum.com/Thread-guide-fix-python-venv-and-ensurepip-errors-in-aapanel-on-ubuntu</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">If aaPanel reports that Python virtual-environment creation returned non-zero exit status 1, the popup alone does not identify the cause. In our Ubuntu lab, the selected system Python lacked ensurepip support because its venv package was not installed. Installing the matching Ubuntu package fixed the creation failure.</span><br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=212" target="_blank" title="">python-venv-error-20261014.jpg</a> (Size: 106.4 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">The actual aaPanel virtual-environment creation failure in the lab.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested:</span> Ubuntu 22.04.5 LTS, aaPanel Free 8.0.7, selected interpreter /usr/bin/python3.10. Tested on 14 October 2026. The package and paths below apply to this specific combination; do not assume every exit-status-1 error has the same cause.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Record the failed command</span><br />
The popup showed that aaPanel attempted:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>/usr/bin/python3.10 -m venv /www/server/pyporject_evn/af_python_lab</code></div></div>Record the interpreter and target directory. Do not delete a working environment to investigate an unrelated creation error.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Read the underlying error</span><br />
Over SSH, repeat the creation command only for the newly failed lab target, or choose a fresh unused diagnostic directory. In our test, the error explained that ensurepip was not available and recommended python3.10-venv.<br />
<br />
Use the exact selected interpreter. Running a different python command could test another Python installation and hide the problem.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Check the matching package</span><br />
On our Ubuntu server:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>apt-cache policy python3.10-venv</code></div></div>It showed Installed: (none), with a candidate available from Ubuntu's repository. Confirm the selected Python version and repository source before installing a package. Other distributions and vendor-managed interpreters have different prerequisite workflows.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Install venv support</span><br />
As an administrator:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>sudo apt-get install python3.10-venv</code></div></div>Our package manager installed python3.10-venv and its pip/setuptools wheel prerequisites. No unrelated packages were removed. Keep package-manager errors if installation fails; do not continue as if the prerequisite is ready.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Retry the aaPanel form</span><br />
Return to Website → Python Project → Python Environment. Dismiss the error popup, then retry the new environment's creation form. We used the same selected system interpreter and environment name. It succeeded and appeared in the environment list.<br />
<br />
A failed attempt may leave a partial directory. In our lab the retry completed it successfully. Do not recursively delete a directory unless you have verified that it belongs only to the failed disposable attempt and no project uses it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Verify the result</span><br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>/www/server/pyporject_evn/af_python_lab/bin/python --version
/www/server/pyporject_evn/af_python_lab/bin/python -m pip --version
/www/server/pyporject_evn/af_python_lab/bin/python -c 'import sys; print(sys.prefix != sys.base_prefix)'</code></div></div>The lab returned Python 3.10.12, pip 22.0.2 inside the new environment and True for the isolation check. Substitute the actual interpreter path from your environment.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">If the error continues</span><br />
Check available disk space, parent-directory permissions, the selected interpreter and the complete command error. Missing ensurepip was our verified cause, not a universal diagnosis. Avoid changing aaPanel's own environment or reinstalling the whole panel before identifying the failure.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Related guide:</span> <a href="https://adminsforum.com/Thread-guide-create-a-python-virtual-environment-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Create a Python virtual environment in aaPanel</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">If aaPanel reports that Python virtual-environment creation returned non-zero exit status 1, the popup alone does not identify the cause. In our Ubuntu lab, the selected system Python lacked ensurepip support because its venv package was not installed. Installing the matching Ubuntu package fixed the creation failure.</span><br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=212" target="_blank" title="">python-venv-error-20261014.jpg</a> (Size: 106.4 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">The actual aaPanel virtual-environment creation failure in the lab.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested:</span> Ubuntu 22.04.5 LTS, aaPanel Free 8.0.7, selected interpreter /usr/bin/python3.10. Tested on 14 October 2026. The package and paths below apply to this specific combination; do not assume every exit-status-1 error has the same cause.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Record the failed command</span><br />
The popup showed that aaPanel attempted:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>/usr/bin/python3.10 -m venv /www/server/pyporject_evn/af_python_lab</code></div></div>Record the interpreter and target directory. Do not delete a working environment to investigate an unrelated creation error.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Read the underlying error</span><br />
Over SSH, repeat the creation command only for the newly failed lab target, or choose a fresh unused diagnostic directory. In our test, the error explained that ensurepip was not available and recommended python3.10-venv.<br />
<br />
Use the exact selected interpreter. Running a different python command could test another Python installation and hide the problem.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Check the matching package</span><br />
On our Ubuntu server:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>apt-cache policy python3.10-venv</code></div></div>It showed Installed: (none), with a candidate available from Ubuntu's repository. Confirm the selected Python version and repository source before installing a package. Other distributions and vendor-managed interpreters have different prerequisite workflows.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Install venv support</span><br />
As an administrator:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>sudo apt-get install python3.10-venv</code></div></div>Our package manager installed python3.10-venv and its pip/setuptools wheel prerequisites. No unrelated packages were removed. Keep package-manager errors if installation fails; do not continue as if the prerequisite is ready.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Retry the aaPanel form</span><br />
Return to Website → Python Project → Python Environment. Dismiss the error popup, then retry the new environment's creation form. We used the same selected system interpreter and environment name. It succeeded and appeared in the environment list.<br />
<br />
A failed attempt may leave a partial directory. In our lab the retry completed it successfully. Do not recursively delete a directory unless you have verified that it belongs only to the failed disposable attempt and no project uses it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Verify the result</span><br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>/www/server/pyporject_evn/af_python_lab/bin/python --version
/www/server/pyporject_evn/af_python_lab/bin/python -m pip --version
/www/server/pyporject_evn/af_python_lab/bin/python -c 'import sys; print(sys.prefix != sys.base_prefix)'</code></div></div>The lab returned Python 3.10.12, pip 22.0.2 inside the new environment and True for the isolation check. Substitute the actual interpreter path from your environment.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">If the error continues</span><br />
Check available disk space, parent-directory permissions, the selected interpreter and the complete command error. Missing ensurepip was our verified cause, not a universal diagnosis. Avoid changing aaPanel's own environment or reinstalling the whole panel before identifying the failure.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Related guide:</span> <a href="https://adminsforum.com/Thread-guide-create-a-python-virtual-environment-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Create a Python virtual environment in aaPanel</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Fix Node.js 502 Bad Gateway in aaPanel: Check Ports, Mapping and Logs]]></title>
			<link>https://adminsforum.com/Thread-guide-fix-node-js-502-bad-gateway-in-aapanel-check-ports-mapping-and-logs</link>
			<pubDate>Wed, 14 Oct 2026 10:52:21 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://adminsforum.com/member.php?action=profile&uid=2">DEV</a>]]></dc:creator>
			<guid isPermaLink="false">https://adminsforum.com/Thread-guide-fix-node-js-502-bad-gateway-in-aapanel-check-ports-mapping-and-logs</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">For a Node.js website behind aaPanel's Nginx mapping, a 502 Bad Gateway often means the web server could not get a usable response from the application. Start by testing the app locally, then compare its listening port with the mapping. Reinstalling Node.js or disabling the firewall is not a useful first diagnostic step.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested lab:</span> aaPanel Free 8.0.7, Node.js 24.21.0, project afnodelab, app at 127.0.0.1:3100, domain node.adminslab.com. On 14 October 2026 we stopped only this sample app using aaPanel's native project controls, observed HTTPS 502, started it again and observed HTTPS 200. The app is restored and running.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify which layer fails</span><br />
Run these checks over SSH on the VPS:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>curl -i http://127.0.0.1:3100/
curl -I https://node.adminslab.com/</code></div></div>Replace the sample port and domain with yours. The local request reaches the Node application directly. The domain request goes through DNS, TLS and the web server. Compare the results:<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Local connection refused + public 502:</span> Check whether the app is running and whether the port is correct.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Local 200 + public 502:</span> Check the mapping's upstream address and port, then the website error log.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Both return 200:</span> The fault may have cleared. Check logs and monitoring before changing settings.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">TLS validation fails:</span> Investigate the certificate separately; a certificate error is different from an HTTP 502 response.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">2. Find the actual listening port</span><br />
For our sample:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>ss -ltnp | grep ':3100'</code></div></div>The expected listener is 127.0.0.1:3100. We also tested 127.0.0.1:3101, where no app was listening, and curl returned connection refused. This demonstrates why guessing an upstream port is unreliable. We did not deliberately change the live mapping to that incorrect port.<br />
<br />
If your app listens on another port, use that port in the local check and the aaPanel project settings. For an app behind a local reverse proxy, a localhost-only listener is appropriate. It does not need its application port opened publicly just to be reached by Nginx on the same machine.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Check project configuration</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Website → Node.js Project</span>, click the project name and inspect <span style="font-weight: bold;" class="mycode_b">Project config</span>. Compare the directory, start command, selected runtime, run user and port against the application's own configuration.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=205" target="_blank" title="">node-app-config-20261014.jpg</a> (Size: 191.89 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Reference screenshot from the sample deployment: project port 3100, www user and Node.js runtime.</span><br />
<br />
Changing the Project Port field does not rewrite a hard-coded port in server.js. The two must agree. Also check that the selected directory contains the expected package.json and startup file. Our sample uses start → node server.js and runs as www.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Read Project log before restarting</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Project log</span>. Look for the latest startup message and any error that precedes it.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=206" target="_blank" title="">node-app-log-20261014.jpg</a> (Size: 161.85 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Reference startup log from the sample deployment shows the app listening on localhost:3100.</span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Module not found:</span> Check the application's dependency installation and selected runtime.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Permission denied:</span> Check the run user's access to the app directory and required resources.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Address already in use:</span> Identify the existing listener; do not start duplicate copies.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">App starts then exits:</span> Read the exit error and check required environment variables or external services.<br />
</li>
</ul>
Do not switch the app to root or use permissions 777 to hide an access problem. Fix the specific missing permission instead.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Check the mapping</span><br />
In <span style="font-weight: bold;" class="mycode_b">Domain Manager</span>, confirm the intended hostname is present. In <span style="font-weight: bold;" class="mycode_b">Mapping</span>, confirm mapping is enabled. Check the relevant web-server configuration read-only before making changes.<br />
<br />
Our generated configuration contains:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>server_name node.adminslab.com;
proxy_pass http://127.0.0.1:3100;</code></div></div>That upstream matches the app's listener. Configuration filenames differ between projects and versions; inspect the relevant site's configuration rather than editing an unrelated file. Prefer the panel's controls for changes, and validate the web-server configuration before reloading it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Restore a stopped application</span><br />
Use <span style="font-weight: bold;" class="mycode_b">Service status → Start</span> for a stopped project, or Restart when appropriate for the selected app. Confirm the action and wait for startup to finish. Repeat the local and domain checks; a Running label alone does not prove the application returns the expected page.<br />
<br />
Our controlled test produced:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>Native project stop: Stopped successfully
HTTPS while stopped: 502
Native project start: Successfully started
HTTPS after recovery: 200</code></div></div>This test changed only the isolated sample project's process state and restored it in the same test. It did not require changing DNS, TLS, firewall rules or the working mapping.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Watch for a reboot startup delay</span><br />
We previously saw a brief 502 while the VPS was coming back after reboot. The app then recovered automatically with Boot enabled. See <a href="https://adminsforum.com/Thread-guide-auto-start-node-js-apps-after-reboot-in-aapanel-logs-and-recovery-checks" target="_blank" rel="noopener" class="mycode_url">Auto-start Node.js apps after reboot in aaPanel</a> for the recovery test.<br />
<br />
Allow a reasonable startup period and check the app log. If 502 persists, investigate it; do not assume that every 502 will resolve itself. If you manually start the app, record the intervention so you do not mistake it for successful automatic recovery.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Confirm the result</span><br />
Check the expected response body as well as the status:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>curl -i http://127.0.0.1:3100/
curl -i https://node.adminslab.com/</code></div></div>Use normal TLS validation. Save the relevant error and the change that fixed it. If requesting support, include the aaPanel version, Node runtime, start command, listening port and redacted error excerpt. Keep credentials and private configuration values out of the post.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Related setup:</span> <a href="https://adminsforum.com/Thread-guide-deploy-a-node-js-app-in-aapanel-with-a-domain-and-https" target="_blank" rel="noopener" class="mycode_url">Deploy a Node.js app in aaPanel with a domain and HTTPS</a>.<br />
<span style="font-weight: bold;" class="mycode_b">Reference:</span> <a href="https://www.aapanel.com/docs/Function/Node.html" target="_blank" rel="noopener" class="mycode_url">aaPanel Node.js project documentation</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">For a Node.js website behind aaPanel's Nginx mapping, a 502 Bad Gateway often means the web server could not get a usable response from the application. Start by testing the app locally, then compare its listening port with the mapping. Reinstalling Node.js or disabling the firewall is not a useful first diagnostic step.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested lab:</span> aaPanel Free 8.0.7, Node.js 24.21.0, project afnodelab, app at 127.0.0.1:3100, domain node.adminslab.com. On 14 October 2026 we stopped only this sample app using aaPanel's native project controls, observed HTTPS 502, started it again and observed HTTPS 200. The app is restored and running.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify which layer fails</span><br />
Run these checks over SSH on the VPS:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>curl -i http://127.0.0.1:3100/
curl -I https://node.adminslab.com/</code></div></div>Replace the sample port and domain with yours. The local request reaches the Node application directly. The domain request goes through DNS, TLS and the web server. Compare the results:<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Local connection refused + public 502:</span> Check whether the app is running and whether the port is correct.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Local 200 + public 502:</span> Check the mapping's upstream address and port, then the website error log.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Both return 200:</span> The fault may have cleared. Check logs and monitoring before changing settings.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">TLS validation fails:</span> Investigate the certificate separately; a certificate error is different from an HTTP 502 response.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">2. Find the actual listening port</span><br />
For our sample:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>ss -ltnp | grep ':3100'</code></div></div>The expected listener is 127.0.0.1:3100. We also tested 127.0.0.1:3101, where no app was listening, and curl returned connection refused. This demonstrates why guessing an upstream port is unreliable. We did not deliberately change the live mapping to that incorrect port.<br />
<br />
If your app listens on another port, use that port in the local check and the aaPanel project settings. For an app behind a local reverse proxy, a localhost-only listener is appropriate. It does not need its application port opened publicly just to be reached by Nginx on the same machine.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Check project configuration</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Website → Node.js Project</span>, click the project name and inspect <span style="font-weight: bold;" class="mycode_b">Project config</span>. Compare the directory, start command, selected runtime, run user and port against the application's own configuration.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=205" target="_blank" title="">node-app-config-20261014.jpg</a> (Size: 191.89 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Reference screenshot from the sample deployment: project port 3100, www user and Node.js runtime.</span><br />
<br />
Changing the Project Port field does not rewrite a hard-coded port in server.js. The two must agree. Also check that the selected directory contains the expected package.json and startup file. Our sample uses start → node server.js and runs as www.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Read Project log before restarting</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Project log</span>. Look for the latest startup message and any error that precedes it.<br />
<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="JPG Image" border="0" alt=".jpg" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=206" target="_blank" title="">node-app-log-20261014.jpg</a> (Size: 161.85 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Reference startup log from the sample deployment shows the app listening on localhost:3100.</span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Module not found:</span> Check the application's dependency installation and selected runtime.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Permission denied:</span> Check the run user's access to the app directory and required resources.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Address already in use:</span> Identify the existing listener; do not start duplicate copies.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">App starts then exits:</span> Read the exit error and check required environment variables or external services.<br />
</li>
</ul>
Do not switch the app to root or use permissions 777 to hide an access problem. Fix the specific missing permission instead.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Check the mapping</span><br />
In <span style="font-weight: bold;" class="mycode_b">Domain Manager</span>, confirm the intended hostname is present. In <span style="font-weight: bold;" class="mycode_b">Mapping</span>, confirm mapping is enabled. Check the relevant web-server configuration read-only before making changes.<br />
<br />
Our generated configuration contains:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>server_name node.adminslab.com;
proxy_pass http://127.0.0.1:3100;</code></div></div>That upstream matches the app's listener. Configuration filenames differ between projects and versions; inspect the relevant site's configuration rather than editing an unrelated file. Prefer the panel's controls for changes, and validate the web-server configuration before reloading it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Restore a stopped application</span><br />
Use <span style="font-weight: bold;" class="mycode_b">Service status → Start</span> for a stopped project, or Restart when appropriate for the selected app. Confirm the action and wait for startup to finish. Repeat the local and domain checks; a Running label alone does not prove the application returns the expected page.<br />
<br />
Our controlled test produced:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>Native project stop: Stopped successfully
HTTPS while stopped: 502
Native project start: Successfully started
HTTPS after recovery: 200</code></div></div>This test changed only the isolated sample project's process state and restored it in the same test. It did not require changing DNS, TLS, firewall rules or the working mapping.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Watch for a reboot startup delay</span><br />
We previously saw a brief 502 while the VPS was coming back after reboot. The app then recovered automatically with Boot enabled. See <a href="https://adminsforum.com/Thread-guide-auto-start-node-js-apps-after-reboot-in-aapanel-logs-and-recovery-checks" target="_blank" rel="noopener" class="mycode_url">Auto-start Node.js apps after reboot in aaPanel</a> for the recovery test.<br />
<br />
Allow a reasonable startup period and check the app log. If 502 persists, investigate it; do not assume that every 502 will resolve itself. If you manually start the app, record the intervention so you do not mistake it for successful automatic recovery.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Confirm the result</span><br />
Check the expected response body as well as the status:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>curl -i http://127.0.0.1:3100/
curl -i https://node.adminslab.com/</code></div></div>Use normal TLS validation. Save the relevant error and the change that fixed it. If requesting support, include the aaPanel version, Node runtime, start command, listening port and redacted error excerpt. Keep credentials and private configuration values out of the post.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Related setup:</span> <a href="https://adminsforum.com/Thread-guide-deploy-a-node-js-app-in-aapanel-with-a-domain-and-https" target="_blank" rel="noopener" class="mycode_url">Deploy a Node.js app in aaPanel with a domain and HTTPS</a>.<br />
<span style="font-weight: bold;" class="mycode_b">Reference:</span> <a href="https://www.aapanel.com/docs/Function/Node.html" target="_blank" rel="noopener" class="mycode_url">aaPanel Node.js project documentation</a>.]]></content:encoded>
		</item>
	</channel>
</rss>