<?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 - All Forums]]></title>
		<link>https://adminsforum.com/</link>
		<description><![CDATA[AdminsForum - https://adminsforum.com]]></description>
		<pubDate>Thu, 15 Oct 2026 03:36:14 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Fix 413 Request Entity Too Large Errors in aaPanel]]></title>
			<link>https://adminsforum.com/Thread-guide-fix-413-request-entity-too-large-errors-in-aapanel</link>
			<pubDate>Thu, 15 Oct 2026 11:34:38 +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-413-request-entity-too-large-errors-in-aapanel</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">A 413 “Request Entity Too Large” response can come from a request-size limit before PHP handles an upload. Identify the layer returning it, check the matching log and change the smallest relevant limit. Increasing PHP's upload setting alone cannot fix a request rejected by Nginx.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: Ubuntu 22.04.5 and the aaPanel lab's installed Nginx 1.30.5 binary. We ran a separate temporary Nginx instance listening only on 127.0.0.1, with its own configuration, PID and logs. A 2KiB request failed under a 1KiB limit and reached a dummy 200 handler under a 4KiB limit. We shut down the test instance afterwards. The normal website configuration and PHP settings were not changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Record the failed operation</span><br />
Note the hostname/path, time/timezone, method, approximate file size, total request size and HTTP status. Find out whether a small upload works and a larger one fails. A multipart request contains framing and other fields in addition to the file bytes.<br />
Check the browser's failed network request and the response. The wording may vary by Nginx version or another proxy. A CDN, reverse proxy, application or upload service can impose a separate limit; a response logo alone is not proof of the failing layer.<br />
Do not repeatedly submit production imports or other actions that might create duplicate records. Use a controlled test workflow and harmless input.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Match the Nginx access and error logs</span><br />
In the tested aaPanel interface, open Website → PHP Project → the site's Log button → Access log / Error log. Confirm the hostname and source path. Read <a href="https://adminsforum.com/Thread-guide-check-website-logs-in-aapanel-to-troubleshoot-site-errors" target="_blank" rel="noopener" class="mycode_url">the website-log guide</a> for detailed searching and time matching.<br />
Our isolated test access log recorded POST /request-size-check with status 413. Its matching error said:<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>client intended to send too large body: 2048 bytes</code></div></div>This supported a Nginx request-size diagnosis. It was not evidence of a PHP memory error, missing extension or failed database connection. If your website has no matching request, investigate the correct host/log and any earlier proxy layer before editing PHP.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Understand the tiny lab comparison</span><br />
We sent the same 2,048-byte raw request body in both phases. With the relevant location set 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>client_max_body_size 1k;</code></div></div>Nginx returned 413. We changed only that test limit 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>client_max_body_size 4k;</code></div></div>After validation and a reload of the isolated instance, the same request received 200 and the dummy response text. The access log recorded both outcomes.<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=321" target="_blank" title="">nginx-413-20261015.jpg</a> (Size: 124.89 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original experiment, not a terminal screenshot.</span><br />
<br />
The handler returned a fixed message. This demonstrates the Nginx size gate; it does not prove PHP parsed multipart data, an application validated a file or anything was stored successfully. The endpoint was private, no public firewall port was opened and the normal website remained available.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Inspect the effective site configuration</span><br />
For a real aaPanel incident, locate the affected website under Website → PHP Project and inspect its Conf/site configuration. Labels vary by release. Back up the relevant file before changing it and confirm which server/location handles the failing URL.<br />
The Nginx directive can appear in http, server or location context. Check inherited settings and a more specific location rather than assuming a global value controls every route. Avoid adding duplicate directives in the same context or replacing an existing PHP handler with an incomplete example location.<br />
An administrator can inspect the effective configuration privately with the installed binary:<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/nginx/sbin/nginx -T</code></div></div>The output can contain private configuration details. Do not upload the entire dump to a public thread.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Choose a finite limit for the actual workflow</span><br />
An illustrative site-level value 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>client_max_body_size 80m;</code></div></div>This is an example, not a value applied to the existing lab website or a universal recommendation. Place a chosen limit in the appropriate existing context and consider legitimate request size, concurrent uploads, temporary storage and application policy. Setting the Nginx value to zero disables its body-size check; it was not needed for our test.<br />
Keep limits purposeful instead of making every upload unlimited. A narrow policy can be appropriate for a particular route, but it must preserve the route's existing processing/authentication configuration.<br />
If a CDN or another reverse proxy rejects the request earlier, an origin-only change cannot remove that layer's limit. Review the actual service's documented current limits and supported workflow rather than weakening unrelated security controls.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Align PHP and application limits separately</span><br />
When the request reaches PHP, check the site's selected PHP version and its active FPM settings. Relevant settings include upload_max_filesize for an uploaded file and post_max_size for the total POST data. Allow for request overhead and multiple files according to the intended application behavior.<br />
Exceeding PHP's POST limit can leave POST/file data empty, so the application's error may differ from a Nginx 413. Verify the effective serving runtime; a CLI setting may not describe the website's PHP-FPM pool.<br />
Follow <a href="https://adminsforum.com/Thread-guide-change-php-upload-and-memory-limits-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Change PHP Upload and Memory Limits</a> and <a href="https://adminsforum.com/Thread-guide-increase-wordpress-php-upload-limits-in-aapanel-to-64-mb" target="_blank" rel="noopener" class="mycode_url">the tested WordPress 64MB upload guide</a> for those existing workflows. Application/plugin limits, validation and available temporary storage still matter. We did not change PHP limits in this experiment.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Validate and verify a real repair</span><br />
Before reloading the affected site configuration on a normal aaPanel-managed Nginx installation:<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/nginx/sbin/nginx -t</code></div></div>Use the panel's supported reload control only after validation succeeds. Our experiment reloaded only its separately configured test process, so the existing website configuration was not involved.<br />
Test a small permitted upload and the intended larger upload through the real application, inspect the response/content and confirm the expected file or record was created. Check fresh logs and a normal page. Do not treat a dummy HTTP 200 as proof that a production upload completed.<br />
Preserve a rollback copy. If a change breaks another route or causes resource pressure, restore the previous configuration, validate and repeat the relevant health checks.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Cleanup and test limits</span><br />
The temporary listener was stopped, its PID file was removed by shutdown and a connection check confirmed its port was closed. The main Nginx configuration hash was unchanged and the normal website health check returned 200.<br />
We retained the private experiment configuration and result logs as documentation. No real uploaded user file, production upload cap, PHP pool or database was modified. The tiny request was chosen to demonstrate the mechanism with bounded work rather than sending large files at a busy server.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References</span>: <a href="https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size" target="_blank" rel="noopener" class="mycode_url">Nginx client_max_body_size</a> and <a href="https://www.php.net/manual/en/ini.core.php#ini.post-max-size" target="_blank" rel="noopener" class="mycode_url">PHP POST-size configuration</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">A 413 “Request Entity Too Large” response can come from a request-size limit before PHP handles an upload. Identify the layer returning it, check the matching log and change the smallest relevant limit. Increasing PHP's upload setting alone cannot fix a request rejected by Nginx.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: Ubuntu 22.04.5 and the aaPanel lab's installed Nginx 1.30.5 binary. We ran a separate temporary Nginx instance listening only on 127.0.0.1, with its own configuration, PID and logs. A 2KiB request failed under a 1KiB limit and reached a dummy 200 handler under a 4KiB limit. We shut down the test instance afterwards. The normal website configuration and PHP settings were not changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Record the failed operation</span><br />
Note the hostname/path, time/timezone, method, approximate file size, total request size and HTTP status. Find out whether a small upload works and a larger one fails. A multipart request contains framing and other fields in addition to the file bytes.<br />
Check the browser's failed network request and the response. The wording may vary by Nginx version or another proxy. A CDN, reverse proxy, application or upload service can impose a separate limit; a response logo alone is not proof of the failing layer.<br />
Do not repeatedly submit production imports or other actions that might create duplicate records. Use a controlled test workflow and harmless input.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Match the Nginx access and error logs</span><br />
In the tested aaPanel interface, open Website → PHP Project → the site's Log button → Access log / Error log. Confirm the hostname and source path. Read <a href="https://adminsforum.com/Thread-guide-check-website-logs-in-aapanel-to-troubleshoot-site-errors" target="_blank" rel="noopener" class="mycode_url">the website-log guide</a> for detailed searching and time matching.<br />
Our isolated test access log recorded POST /request-size-check with status 413. Its matching error said:<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>client intended to send too large body: 2048 bytes</code></div></div>This supported a Nginx request-size diagnosis. It was not evidence of a PHP memory error, missing extension or failed database connection. If your website has no matching request, investigate the correct host/log and any earlier proxy layer before editing PHP.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Understand the tiny lab comparison</span><br />
We sent the same 2,048-byte raw request body in both phases. With the relevant location set 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>client_max_body_size 1k;</code></div></div>Nginx returned 413. We changed only that test limit 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>client_max_body_size 4k;</code></div></div>After validation and a reload of the isolated instance, the same request received 200 and the dummy response text. The access log recorded both outcomes.<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=321" target="_blank" title="">nginx-413-20261015.jpg</a> (Size: 124.89 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original experiment, not a terminal screenshot.</span><br />
<br />
The handler returned a fixed message. This demonstrates the Nginx size gate; it does not prove PHP parsed multipart data, an application validated a file or anything was stored successfully. The endpoint was private, no public firewall port was opened and the normal website remained available.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Inspect the effective site configuration</span><br />
For a real aaPanel incident, locate the affected website under Website → PHP Project and inspect its Conf/site configuration. Labels vary by release. Back up the relevant file before changing it and confirm which server/location handles the failing URL.<br />
The Nginx directive can appear in http, server or location context. Check inherited settings and a more specific location rather than assuming a global value controls every route. Avoid adding duplicate directives in the same context or replacing an existing PHP handler with an incomplete example location.<br />
An administrator can inspect the effective configuration privately with the installed binary:<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/nginx/sbin/nginx -T</code></div></div>The output can contain private configuration details. Do not upload the entire dump to a public thread.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Choose a finite limit for the actual workflow</span><br />
An illustrative site-level value 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>client_max_body_size 80m;</code></div></div>This is an example, not a value applied to the existing lab website or a universal recommendation. Place a chosen limit in the appropriate existing context and consider legitimate request size, concurrent uploads, temporary storage and application policy. Setting the Nginx value to zero disables its body-size check; it was not needed for our test.<br />
Keep limits purposeful instead of making every upload unlimited. A narrow policy can be appropriate for a particular route, but it must preserve the route's existing processing/authentication configuration.<br />
If a CDN or another reverse proxy rejects the request earlier, an origin-only change cannot remove that layer's limit. Review the actual service's documented current limits and supported workflow rather than weakening unrelated security controls.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Align PHP and application limits separately</span><br />
When the request reaches PHP, check the site's selected PHP version and its active FPM settings. Relevant settings include upload_max_filesize for an uploaded file and post_max_size for the total POST data. Allow for request overhead and multiple files according to the intended application behavior.<br />
Exceeding PHP's POST limit can leave POST/file data empty, so the application's error may differ from a Nginx 413. Verify the effective serving runtime; a CLI setting may not describe the website's PHP-FPM pool.<br />
Follow <a href="https://adminsforum.com/Thread-guide-change-php-upload-and-memory-limits-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Change PHP Upload and Memory Limits</a> and <a href="https://adminsforum.com/Thread-guide-increase-wordpress-php-upload-limits-in-aapanel-to-64-mb" target="_blank" rel="noopener" class="mycode_url">the tested WordPress 64MB upload guide</a> for those existing workflows. Application/plugin limits, validation and available temporary storage still matter. We did not change PHP limits in this experiment.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Validate and verify a real repair</span><br />
Before reloading the affected site configuration on a normal aaPanel-managed Nginx installation:<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/nginx/sbin/nginx -t</code></div></div>Use the panel's supported reload control only after validation succeeds. Our experiment reloaded only its separately configured test process, so the existing website configuration was not involved.<br />
Test a small permitted upload and the intended larger upload through the real application, inspect the response/content and confirm the expected file or record was created. Check fresh logs and a normal page. Do not treat a dummy HTTP 200 as proof that a production upload completed.<br />
Preserve a rollback copy. If a change breaks another route or causes resource pressure, restore the previous configuration, validate and repeat the relevant health checks.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Cleanup and test limits</span><br />
The temporary listener was stopped, its PID file was removed by shutdown and a connection check confirmed its port was closed. The main Nginx configuration hash was unchanged and the normal website health check returned 200.<br />
We retained the private experiment configuration and result logs as documentation. No real uploaded user file, production upload cap, PHP pool or database was modified. The tiny request was chosen to demonstrate the mechanism with bounded work rather than sending large files at a busy server.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References</span>: <a href="https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size" target="_blank" rel="noopener" class="mycode_url">Nginx client_max_body_size</a> and <a href="https://www.php.net/manual/en/ini.core.php#ini.post-max-size" target="_blank" rel="noopener" class="mycode_url">PHP POST-size configuration</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Fix 403 Forbidden Errors in aaPanel Using Logs]]></title>
			<link>https://adminsforum.com/Thread-guide-fix-403-forbidden-errors-in-aapanel-using-logs</link>
			<pubDate>Wed, 14 Oct 2026 21:18:55 +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-403-forbidden-errors-in-aapanel-using-logs</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">A 403 Forbidden response means the request was denied, but it does not identify the rule or permission responsible. Read the matching error before changing file ownership, enabling directory listings or disabling security controls.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5 and Nginx 1.30.5. We created one temporary public-text fixture, withheld file access to reproduce a permission-related 403, then permitted group read on that file and verified HTTP 200. It was removed afterwards. No application directory, access rule or global service setting was changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify the request and the layer denying it</span><br />
Record hostname/path, time/timezone, status, request method, client context and recent changes. Check whether one file, a directory URL, all website pages or only an authenticated action is denied.<br />
Cloudflare/WAF, Nginx and the application can each deny a request. A status or response logo is a clue, not proof of the source. A browser login failure may need account/application evidence rather than filesystem permissions.<br />
For a harmless GET you control:<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 -sS --max-time 15 -D - -o /dev/null https://example.com/affected-path</code></div></div>Replace the hostname/path; use curl.exe and NUL on Windows. Keep certificate validation enabled. Do not test protected data by bypassing an access policy merely to get a successful response.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Match the website's access and error logs</span><br />
In our aaPanel interface: Website → PHP Project → the exact site's Log button → Access log / Error log. Confirm the source path and use Refresh. Read <a href="https://adminsforum.com/Thread-guide-check-website-logs-in-aapanel-to-troubleshoot-site-errors" target="_blank" rel="noopener" class="mycode_url">the website log guide</a> for detailed searching and timestamp checks.<br />
Our test request appeared as 403 in the access log. The corresponding Nginx error named the temporary text file and reported:<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>open() ... failed (13: Permission denied)</code></div></div>This supported a filesystem-access diagnosis for that static file. It was different from a missing file (404) or an undefined PHP function (500).<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Inspect the exact file and its parent directories</span><br />
Before a repair, record permissions, owner and group:<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>ls -l /path/to/affected-file
namei -l /path/to/affected-file</code></div></div>Use the actual path from the matching error. namei displays path components so you can inspect parent-directory traversal as well as the final file. Availability depends on your Linux tools.<br />
A server needs appropriate read access to a served static file and search/traverse access to its parent directories. An unreadable file and a non-traversable parent require different targeted changes. ACLs and platform security controls can also affect access; mode bits alone do not explain every denial.<br />
Our fixture's parents were traversable, and the denied file had mode 000 with owner root and group www. No parent permissions were changed during the test.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Confirm the process that needs access</span><br />
Our Nginx master ran as root, but its workers ran as www:www. The worker identity is the relevant one for this static request; an administrator being able to read the file does not prove the web worker can.<br />
A useful check that avoids full process arguments 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>ps -eo user,group,comm</code></div></div>Inspect the Nginx rows. Do not assume that every panel uses www: different services and PHP pools can run under different users. Ownership should follow your deployment model, not a blanket command copied from another server.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Apply the smallest justified permission change</span><br />
For our existing fixture ownership root:www, mode 640 gave the owner read/write, the group read and others no access. Because the workers used group www, this permitted the intended static response without allowing them to write to the file.<br />
Our one-file repair was equivalent 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>chmod 640 /www/wwwroot/adminslab.com/af-http403-lab-20261014.txt</code></div></div>That path was our disposable text fixture. Before adapting the command, verify the intended owner/group and runtime identity, record the original mode and select only the affected file. It does not change ownership or grant a different group access.<br />
This was a file-specific lab example, not a universal website permission preset. Other deployments may use another group or access model. A directory needs traversal permissions, so do not apply file mode 640 recursively to directories.<br />
The existing guide <a href="https://adminsforum.com/Thread-guide-set-file-permissions-and-ownership-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Set File Permissions and Ownership in aaPanel</a> covers the panel controls. Preserve the original mode/owner/group so a real repair can be reversed. Do not recursively apply chmod 777 or give a runtime write access to all application code just to eliminate a 403.<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=319" target="_blank" title="">http403-permission-20261014.jpg</a> (Size: 131.87 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original experiment, not a panel screenshot.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Verify the response and new log evidence</span><br />
After the targeted file change, the same URL returned HTTP 200 with the expected text. The access log recorded 200, no new error entry matched that file, and the normal homepage also returned 200.<br />
No Nginx reload or restart was needed for this filesystem-mode change. If you instead edit a server configuration, validate it and use the supported reload procedure before testing its behavior.<br />
We removed the temporary fixture after verification. The deliberately inaccessible file should not be left as a public test URL. Existing application files and permissions remained untouched.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Distinguish other 403 causes</span><br />
The following are investigation examples, not failures induced in this test:<ul class="mycode_list"><li>Directory URL denied: inspect the intended default document, running/document root and directory-index configuration. A missing expected index is not a reason to expose a directory listing of website files.<br />
</li>
<li>Access-rule denial: inspect the matching Nginx location and ordered allow/deny rules, or the applicable panel access restriction. Confirm whether the denial is intentional before changing it.<br />
</li>
<li>WAF/CDN denial: inspect the corresponding security event and request context. Resolve a verified false positive narrowly; do not disable the whole firewall or WAF as a shortcut.<br />
</li>
<li>Application denial: inspect account role, authentication/session state, CSRF checks and the application logger. A filesystem chmod will not correct an authorization decision.<br />
</li>
<li>Permission denied despite apparently suitable modes: inspect the process identity, parent traversal, ACLs and security-policy evidence. Do not disable the system's protection without establishing the cause.<br />
</li>
</ul>
Several layers can be involved. Compare the same request at the correct layer without publishing private upstream services or weakening authentication.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Be careful with proxy addresses</span><br />
An IP-based access rule may see a CDN/proxy address rather than the visitor address unless trusted real-IP handling is configured correctly. Do not trust arbitrary forwarded headers or whitelist large address ranges without understanding the effective client identity.<br />
Our test used loopback and a local HTTPS request with the correct hostname and certificate validation. It did not audit CDN rules or demonstrate all remote client conditions.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Retain a rollback and share a small safe excerpt</span><br />
Keep the affected file's original ownership/mode and a backup before a real deployment repair. Retest the denied path, a normal page and relevant authenticated behavior. A new 200 alone is not a success if it accidentally makes protected content public.<br />
For support, include versions, time/timezone, path, status, recent change and the redacted matching message. Remove tokens, visitor IPs, private contact details and unrelated requests. Logs are evidence to interpret, not instructions to execute.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References</span>: <a href="https://www.gnu.org/software/coreutils/manual/html_node/Mode-Structure.html" target="_blank" rel="noopener" class="mycode_url">GNU file-mode structure</a>, <a href="https://nginx.org/en/docs/http/ngx_http_access_module.html" target="_blank" rel="noopener" class="mycode_url">Nginx access rules</a> and <a href="https://nginx.org/en/docs/http/ngx_http_autoindex_module.html" target="_blank" rel="noopener" class="mycode_url">Nginx directory listings</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">A 403 Forbidden response means the request was denied, but it does not identify the rule or permission responsible. Read the matching error before changing file ownership, enabling directory listings or disabling security controls.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5 and Nginx 1.30.5. We created one temporary public-text fixture, withheld file access to reproduce a permission-related 403, then permitted group read on that file and verified HTTP 200. It was removed afterwards. No application directory, access rule or global service setting was changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify the request and the layer denying it</span><br />
Record hostname/path, time/timezone, status, request method, client context and recent changes. Check whether one file, a directory URL, all website pages or only an authenticated action is denied.<br />
Cloudflare/WAF, Nginx and the application can each deny a request. A status or response logo is a clue, not proof of the source. A browser login failure may need account/application evidence rather than filesystem permissions.<br />
For a harmless GET you control:<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 -sS --max-time 15 -D - -o /dev/null https://example.com/affected-path</code></div></div>Replace the hostname/path; use curl.exe and NUL on Windows. Keep certificate validation enabled. Do not test protected data by bypassing an access policy merely to get a successful response.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Match the website's access and error logs</span><br />
In our aaPanel interface: Website → PHP Project → the exact site's Log button → Access log / Error log. Confirm the source path and use Refresh. Read <a href="https://adminsforum.com/Thread-guide-check-website-logs-in-aapanel-to-troubleshoot-site-errors" target="_blank" rel="noopener" class="mycode_url">the website log guide</a> for detailed searching and timestamp checks.<br />
Our test request appeared as 403 in the access log. The corresponding Nginx error named the temporary text file and reported:<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>open() ... failed (13: Permission denied)</code></div></div>This supported a filesystem-access diagnosis for that static file. It was different from a missing file (404) or an undefined PHP function (500).<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Inspect the exact file and its parent directories</span><br />
Before a repair, record permissions, owner and group:<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>ls -l /path/to/affected-file
namei -l /path/to/affected-file</code></div></div>Use the actual path from the matching error. namei displays path components so you can inspect parent-directory traversal as well as the final file. Availability depends on your Linux tools.<br />
A server needs appropriate read access to a served static file and search/traverse access to its parent directories. An unreadable file and a non-traversable parent require different targeted changes. ACLs and platform security controls can also affect access; mode bits alone do not explain every denial.<br />
Our fixture's parents were traversable, and the denied file had mode 000 with owner root and group www. No parent permissions were changed during the test.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Confirm the process that needs access</span><br />
Our Nginx master ran as root, but its workers ran as www:www. The worker identity is the relevant one for this static request; an administrator being able to read the file does not prove the web worker can.<br />
A useful check that avoids full process arguments 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>ps -eo user,group,comm</code></div></div>Inspect the Nginx rows. Do not assume that every panel uses www: different services and PHP pools can run under different users. Ownership should follow your deployment model, not a blanket command copied from another server.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Apply the smallest justified permission change</span><br />
For our existing fixture ownership root:www, mode 640 gave the owner read/write, the group read and others no access. Because the workers used group www, this permitted the intended static response without allowing them to write to the file.<br />
Our one-file repair was equivalent 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>chmod 640 /www/wwwroot/adminslab.com/af-http403-lab-20261014.txt</code></div></div>That path was our disposable text fixture. Before adapting the command, verify the intended owner/group and runtime identity, record the original mode and select only the affected file. It does not change ownership or grant a different group access.<br />
This was a file-specific lab example, not a universal website permission preset. Other deployments may use another group or access model. A directory needs traversal permissions, so do not apply file mode 640 recursively to directories.<br />
The existing guide <a href="https://adminsforum.com/Thread-guide-set-file-permissions-and-ownership-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Set File Permissions and Ownership in aaPanel</a> covers the panel controls. Preserve the original mode/owner/group so a real repair can be reversed. Do not recursively apply chmod 777 or give a runtime write access to all application code just to eliminate a 403.<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=319" target="_blank" title="">http403-permission-20261014.jpg</a> (Size: 131.87 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original experiment, not a panel screenshot.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Verify the response and new log evidence</span><br />
After the targeted file change, the same URL returned HTTP 200 with the expected text. The access log recorded 200, no new error entry matched that file, and the normal homepage also returned 200.<br />
No Nginx reload or restart was needed for this filesystem-mode change. If you instead edit a server configuration, validate it and use the supported reload procedure before testing its behavior.<br />
We removed the temporary fixture after verification. The deliberately inaccessible file should not be left as a public test URL. Existing application files and permissions remained untouched.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Distinguish other 403 causes</span><br />
The following are investigation examples, not failures induced in this test:<ul class="mycode_list"><li>Directory URL denied: inspect the intended default document, running/document root and directory-index configuration. A missing expected index is not a reason to expose a directory listing of website files.<br />
</li>
<li>Access-rule denial: inspect the matching Nginx location and ordered allow/deny rules, or the applicable panel access restriction. Confirm whether the denial is intentional before changing it.<br />
</li>
<li>WAF/CDN denial: inspect the corresponding security event and request context. Resolve a verified false positive narrowly; do not disable the whole firewall or WAF as a shortcut.<br />
</li>
<li>Application denial: inspect account role, authentication/session state, CSRF checks and the application logger. A filesystem chmod will not correct an authorization decision.<br />
</li>
<li>Permission denied despite apparently suitable modes: inspect the process identity, parent traversal, ACLs and security-policy evidence. Do not disable the system's protection without establishing the cause.<br />
</li>
</ul>
Several layers can be involved. Compare the same request at the correct layer without publishing private upstream services or weakening authentication.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Be careful with proxy addresses</span><br />
An IP-based access rule may see a CDN/proxy address rather than the visitor address unless trusted real-IP handling is configured correctly. Do not trust arbitrary forwarded headers or whitelist large address ranges without understanding the effective client identity.<br />
Our test used loopback and a local HTTPS request with the correct hostname and certificate validation. It did not audit CDN rules or demonstrate all remote client conditions.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Retain a rollback and share a small safe excerpt</span><br />
Keep the affected file's original ownership/mode and a backup before a real deployment repair. Retest the denied path, a normal page and relevant authenticated behavior. A new 200 alone is not a success if it accidentally makes protected content public.<br />
For support, include versions, time/timezone, path, status, recent change and the redacted matching message. Remove tokens, visitor IPs, private contact details and unrelated requests. Logs are evidence to interpret, not instructions to execute.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References</span>: <a href="https://www.gnu.org/software/coreutils/manual/html_node/Mode-Structure.html" target="_blank" rel="noopener" class="mycode_url">GNU file-mode structure</a>, <a href="https://nginx.org/en/docs/http/ngx_http_access_module.html" target="_blank" rel="noopener" class="mycode_url">Nginx access rules</a> and <a href="https://nginx.org/en/docs/http/ngx_http_autoindex_module.html" target="_blank" rel="noopener" class="mycode_url">Nginx directory listings</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Fix PHP HTTP 500 Errors in aaPanel Using Error Logs]]></title>
			<link>https://adminsforum.com/Thread-guide-fix-php-http-500-errors-in-aapanel-using-error-logs</link>
			<pubDate>Wed, 14 Oct 2026 21:11:00 +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-php-http-500-errors-in-aapanel-using-error-logs</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">HTTP 500 means the server could not complete the request. It does not tell you which PHP error occurred. Match the request with the relevant logs, identify the actual cause, make one targeted repair and verify the response and fresh log entries.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5, Nginx 1.30.5 and PHP 8.5.11. An isolated temporary PHP page called an undefined function, returned 500 and generated a fatal-error record. Removing that call returned 200 with the intended response and no new matching error entry. We removed the test page afterwards. No production application or global PHP settings were changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Record the failing request</span><br />
Write down the exact hostname/path, time and timezone, method, status and recent changes. Check whether static files work, every PHP page fails or only one application action fails. Do not repeatedly submit an order, email or other side-effecting request merely to collect errors.<br />
For a harmless GET endpoint you control:<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 -sS --max-time 15 -D - -o /dev/null https://example.com/problem-page</code></div></div>Replace the hostname and path. On Windows use curl.exe and NUL. Keep certificate validation enabled, and separately inspect the body. A browser's generic error page is not a diagnostic explanation.<br />
A CDN or application framework can return its own 500. Determine which layer handled the request before assuming the PHP service has stopped.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Open the matching website logs</span><br />
In the tested aaPanel interface choose Website → PHP Project → the exact site's Log button. Inspect Access log and Error log and use Refresh. Confirm the displayed source path and selected hostname.<br />
Our site used /www/wwwlogs/adminslab.com.log and /www/wwwlogs/adminslab.com.error.log. The application may use another private log too. The panel's administrative log is not a substitute for the website's log.<br />
Read <a href="https://adminsforum.com/Thread-guide-check-website-logs-in-aapanel-to-troubleshoot-site-errors" target="_blank" rel="noopener" class="mycode_url">Check Website Logs in aaPanel</a> for time matching, rotation and safe SSH searches.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Find the fatal error, not just the status code</span><br />
The lab access log recorded the temporary page with HTTP 500 at 13:08:03 UTC. The matching Nginx error entry contained:<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>FastCGI sent in stderr:
PHP Fatal error: Uncaught Error:
Call to undefined function af_lab_missing_function()
.../af-http500-verified-20261014.php:4</code></div></div>This identified an undefined function in the temporary script. It did not indicate that Nginx, MySQL or the entire VPS needed reinstalling. The file/line and error type directed the investigation.<br />
A framework stack can include several files. Trace the relevant application operation and recent deployment instead of editing a random vendor file named in the stack. Preserve a small matching excerpt before changing anything.<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=310" target="_blank" title="">php-http500-20261014.jpg</a> (Size: 133.63 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original lab test, not a terminal screenshot. The image abbreviates the lab script path.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand what a syntax check proves</span><br />
Our faulty script passed:<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/php/85/bin/php -l /path/to/the/affected-file.php</code></div></div>Replace the path with an actual file and use the intended installed PHP binary. This command checks PHP syntax without executing the normal application workflow. It did not detect that our function was unavailable when the request ran.<br />
A successful lint does not establish runtime compatibility, autoloading, database access or correct application behavior. The CLI and PHP-FPM can also load different ini files and extensions. Verify the website's selected PHP version and its effective serving environment; do not change versions blindly to hide an error.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Repair the cause shown by the error</span><br />
In our isolated demonstration, the repair was to remove the deliberately undefined call and return a fixed test message. We then repeated the same request. No service restart or pool increase was needed for this code error.<br />
For a real application, first back up and use staging or a reversible deployment. Example investigations include:<ul class="mycode_list"><li>Undefined function: check the function name, expected application include/autoloader or required extension. Determine which component supplies it before installing anything.<br />
</li>
<li>Class not found: inspect the deployment's dependencies and autoload configuration, including case-sensitive paths. Do not run arbitrary downloaded repair scripts.<br />
</li>
<li>Parse error: inspect the named file and recent edit, validate with the matching PHP version and deploy a corrected or known-good copy.<br />
</li>
<li>Memory exhausted: identify the request and resource cause. Raising memory limits without measurement may increase pressure across concurrent workers.<br />
</li>
<li>Database exception: inspect the application connection and matching database error; keep credentials out of public logs or support posts.<br />
</li>
</ul>
These are investigation examples, not additional failures triggered in this test. A 500 can have causes outside PHP as well; use the evidence actually recorded.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Keep diagnostics private and respect log-path restrictions</span><br />
Use error logging rather than public stack traces. For the controlled request we kept display_errors off and log_errors enabled. Global settings may need to be set before execution to capture startup or parse failures; a line inside a script may not execute when parsing fails.<br />
Our earlier attempt to choose a private custom log outside the website's allowed paths was blocked by open_basedir. The error appeared through FastCGI in the Nginx error log instead. We left the restriction intact and used the existing destination for the clean verification.<br />
If a configured log is empty, check effective PHP settings, its permitted path and write permissions. Do not disable open_basedir globally or apply chmod 777 as a logging fix. Choose a supported private destination that the application's restrictions permit, or use the existing SAPI/application logger.<br />
The FPM master log describes service diagnostics; it need not contain every application's fatal error. Avoid exposing phpinfo, debug logs or tokens on the website to discover a setting.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Verify HTTP status, content and fresh logs</span><br />
At 13:08:06 UTC, the same temporary endpoint returned HTTP 200 and the text "AdminsForum clean recovery verified". Its access entry changed to 200, and there were no new error-log lines matching that page after the fix. The normal homepage also returned 200.<br />
We allowed timestamp revalidation time before checking the changed file. If your deployment disables OPcache timestamp checking, use its approved invalidation/reload process; a browser refresh alone does not guarantee fresh PHP bytecode.<br />
An old fatal entry remains historical evidence. Compare new timestamps and requests rather than clearing the log. Test an ordinary page and relevant application behavior, including reads/writes on staging where appropriate. A 200 with an error message in its body is not a complete recovery.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Clean up and retain a rollback</span><br />
We removed both temporary diagnostic pages created during the experiment and retained private test records. Existing website content, PHP pool settings and security restrictions were unchanged.<br />
Remove your own test files and temporary diagnostics after the observation window. Keep a known-good code/configuration backup and deliberate log retention. If a targeted change fails, restore it and verify service/application health again.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Distinguish a PHP 500 from a gateway failure</span><br />
A 502 or upstream connection refusal may mean Nginx cannot get a usable upstream response. An executing PHP script's fatal error is a different finding. Correlate upstream service and website logs before choosing a fix.<br />
For slow executing requests, use <a href="https://adminsforum.com/Thread-guide-find-slow-php-requests-in-aapanel-with-php-fpm-slow-logs" target="_blank" rel="noopener" class="mycode_url">PHP-FPM slow logs</a>; for shared-server pressure, use <a href="https://adminsforum.com/Thread-guide-monitor-server-resources-during-aapanel-website-traffic-tests" target="_blank" rel="noopener" class="mycode_url">resource monitoring during a controlled test</a>. Restarting everything can interrupt healthy services and hide useful evidence.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://www.php.net/manual/en/errorfunc.configuration.php" target="_blank" rel="noopener" class="mycode_url">Official PHP error logging configuration</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">HTTP 500 means the server could not complete the request. It does not tell you which PHP error occurred. Match the request with the relevant logs, identify the actual cause, make one targeted repair and verify the response and fresh log entries.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5, Nginx 1.30.5 and PHP 8.5.11. An isolated temporary PHP page called an undefined function, returned 500 and generated a fatal-error record. Removing that call returned 200 with the intended response and no new matching error entry. We removed the test page afterwards. No production application or global PHP settings were changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Record the failing request</span><br />
Write down the exact hostname/path, time and timezone, method, status and recent changes. Check whether static files work, every PHP page fails or only one application action fails. Do not repeatedly submit an order, email or other side-effecting request merely to collect errors.<br />
For a harmless GET endpoint you control:<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 -sS --max-time 15 -D - -o /dev/null https://example.com/problem-page</code></div></div>Replace the hostname and path. On Windows use curl.exe and NUL. Keep certificate validation enabled, and separately inspect the body. A browser's generic error page is not a diagnostic explanation.<br />
A CDN or application framework can return its own 500. Determine which layer handled the request before assuming the PHP service has stopped.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Open the matching website logs</span><br />
In the tested aaPanel interface choose Website → PHP Project → the exact site's Log button. Inspect Access log and Error log and use Refresh. Confirm the displayed source path and selected hostname.<br />
Our site used /www/wwwlogs/adminslab.com.log and /www/wwwlogs/adminslab.com.error.log. The application may use another private log too. The panel's administrative log is not a substitute for the website's log.<br />
Read <a href="https://adminsforum.com/Thread-guide-check-website-logs-in-aapanel-to-troubleshoot-site-errors" target="_blank" rel="noopener" class="mycode_url">Check Website Logs in aaPanel</a> for time matching, rotation and safe SSH searches.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Find the fatal error, not just the status code</span><br />
The lab access log recorded the temporary page with HTTP 500 at 13:08:03 UTC. The matching Nginx error entry contained:<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>FastCGI sent in stderr:
PHP Fatal error: Uncaught Error:
Call to undefined function af_lab_missing_function()
.../af-http500-verified-20261014.php:4</code></div></div>This identified an undefined function in the temporary script. It did not indicate that Nginx, MySQL or the entire VPS needed reinstalling. The file/line and error type directed the investigation.<br />
A framework stack can include several files. Trace the relevant application operation and recent deployment instead of editing a random vendor file named in the stack. Preserve a small matching excerpt before changing anything.<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=310" target="_blank" title="">php-http500-20261014.jpg</a> (Size: 133.63 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original lab test, not a terminal screenshot. The image abbreviates the lab script path.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand what a syntax check proves</span><br />
Our faulty script passed:<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/php/85/bin/php -l /path/to/the/affected-file.php</code></div></div>Replace the path with an actual file and use the intended installed PHP binary. This command checks PHP syntax without executing the normal application workflow. It did not detect that our function was unavailable when the request ran.<br />
A successful lint does not establish runtime compatibility, autoloading, database access or correct application behavior. The CLI and PHP-FPM can also load different ini files and extensions. Verify the website's selected PHP version and its effective serving environment; do not change versions blindly to hide an error.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Repair the cause shown by the error</span><br />
In our isolated demonstration, the repair was to remove the deliberately undefined call and return a fixed test message. We then repeated the same request. No service restart or pool increase was needed for this code error.<br />
For a real application, first back up and use staging or a reversible deployment. Example investigations include:<ul class="mycode_list"><li>Undefined function: check the function name, expected application include/autoloader or required extension. Determine which component supplies it before installing anything.<br />
</li>
<li>Class not found: inspect the deployment's dependencies and autoload configuration, including case-sensitive paths. Do not run arbitrary downloaded repair scripts.<br />
</li>
<li>Parse error: inspect the named file and recent edit, validate with the matching PHP version and deploy a corrected or known-good copy.<br />
</li>
<li>Memory exhausted: identify the request and resource cause. Raising memory limits without measurement may increase pressure across concurrent workers.<br />
</li>
<li>Database exception: inspect the application connection and matching database error; keep credentials out of public logs or support posts.<br />
</li>
</ul>
These are investigation examples, not additional failures triggered in this test. A 500 can have causes outside PHP as well; use the evidence actually recorded.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Keep diagnostics private and respect log-path restrictions</span><br />
Use error logging rather than public stack traces. For the controlled request we kept display_errors off and log_errors enabled. Global settings may need to be set before execution to capture startup or parse failures; a line inside a script may not execute when parsing fails.<br />
Our earlier attempt to choose a private custom log outside the website's allowed paths was blocked by open_basedir. The error appeared through FastCGI in the Nginx error log instead. We left the restriction intact and used the existing destination for the clean verification.<br />
If a configured log is empty, check effective PHP settings, its permitted path and write permissions. Do not disable open_basedir globally or apply chmod 777 as a logging fix. Choose a supported private destination that the application's restrictions permit, or use the existing SAPI/application logger.<br />
The FPM master log describes service diagnostics; it need not contain every application's fatal error. Avoid exposing phpinfo, debug logs or tokens on the website to discover a setting.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Verify HTTP status, content and fresh logs</span><br />
At 13:08:06 UTC, the same temporary endpoint returned HTTP 200 and the text "AdminsForum clean recovery verified". Its access entry changed to 200, and there were no new error-log lines matching that page after the fix. The normal homepage also returned 200.<br />
We allowed timestamp revalidation time before checking the changed file. If your deployment disables OPcache timestamp checking, use its approved invalidation/reload process; a browser refresh alone does not guarantee fresh PHP bytecode.<br />
An old fatal entry remains historical evidence. Compare new timestamps and requests rather than clearing the log. Test an ordinary page and relevant application behavior, including reads/writes on staging where appropriate. A 200 with an error message in its body is not a complete recovery.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Clean up and retain a rollback</span><br />
We removed both temporary diagnostic pages created during the experiment and retained private test records. Existing website content, PHP pool settings and security restrictions were unchanged.<br />
Remove your own test files and temporary diagnostics after the observation window. Keep a known-good code/configuration backup and deliberate log retention. If a targeted change fails, restore it and verify service/application health again.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Distinguish a PHP 500 from a gateway failure</span><br />
A 502 or upstream connection refusal may mean Nginx cannot get a usable upstream response. An executing PHP script's fatal error is a different finding. Correlate upstream service and website logs before choosing a fix.<br />
For slow executing requests, use <a href="https://adminsforum.com/Thread-guide-find-slow-php-requests-in-aapanel-with-php-fpm-slow-logs" target="_blank" rel="noopener" class="mycode_url">PHP-FPM slow logs</a>; for shared-server pressure, use <a href="https://adminsforum.com/Thread-guide-monitor-server-resources-during-aapanel-website-traffic-tests" target="_blank" rel="noopener" class="mycode_url">resource monitoring during a controlled test</a>. Restarting everything can interrupt healthy services and hide useful evidence.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://www.php.net/manual/en/errorfunc.configuration.php" target="_blank" rel="noopener" class="mycode_url">Official PHP error logging configuration</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[CloudPanel Backups and Security: Remote Backups, Firewall and Basic Auth]]></title>
			<link>https://adminsforum.com/Thread-guide-cloudpanel-backups-and-security-remote-backups-firewall-and-basic-auth</link>
			<pubDate>Wed, 14 Oct 2026 21:10:47 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://adminsforum.com/member.php?action=profile&uid=1">JAY</a>]]></dc:creator>
			<guid isPermaLink="false">https://adminsforum.com/Thread-guide-cloudpanel-backups-and-security-remote-backups-firewall-and-basic-auth</guid>
			<description><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel backups and security: remote backups, firewall and Basic Auth</span></span><br />
<br />
The steps that protect a CloudPanel server: off-server backups, locking down the panel, per-site blocking, and keeping everything updated. Tested on CloudPanel 2.5.4, Ubuntu 24.04.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 1: Remote backups</span></span><br />
A backup on the same server isn't a backup if the server dies. Go to <span style="font-weight: bold;" class="mycode_b">Admin Area → Backups</span> and choose a <span style="font-weight: bold;" class="mycode_b">Storage Provider</span>: Amazon S3, Wasabi, DigitalOcean Spaces, Dropbox, Google Drive, Hetzner Storage Box, SFTP or a custom Rclone config.<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=311" target="_blank" title="">g7-01-ae55.jpg</a> (Size: 87.42 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
Turn on <span style="font-weight: bold;" class="mycode_b">Enable Remote Backup</span> and set the <span style="font-weight: bold;" class="mycode_b">Frequency</span> and <span style="font-weight: bold;" class="mycode_b">Time</span>. Pick a quiet hour, such as 02:00.<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=312" target="_blank" title="">g7-02-ae56.jpg</a> (Size: 112.26 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
Enter the <span style="font-weight: bold;" class="mycode_b">bucket</span> and <span style="font-weight: bold;" class="mycode_b">region</span>, an <span style="font-weight: bold;" class="mycode_b">access key</span> and <span style="font-weight: bold;" class="mycode_b">secret key</span>, the storage directory, the <span style="font-weight: bold;" class="mycode_b">retention period</span> (days to keep) and any <span style="font-weight: bold;" class="mycode_b">excludes</span> such as cache folders, then save. (The keys in our screenshot are CloudPanel's example values, not real keys.) Create a key that can only access this one bucket.<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=313" target="_blank" title="">g7-03-ae57.jpg</a> (Size: 113.31 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 2: The firewall</span></span><br />
In <span style="font-weight: bold;" class="mycode_b">Admin Area → Security → Firewall</span>, CloudPanel by default allows SSH (22), HTTP (80), HTTPS (443) and the panel (8443) from anywhere.<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=314" target="_blank" title="">g7-04-ae58.jpg</a> (Size: 104.35 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Best single step: allow port 8443 only from your own IP.</span> Click <span style="font-weight: bold;" class="mycode_b">Add Rule</span>, type <span style="font-weight: bold;" class="mycode_b">CloudPanel</span>, source <span style="font-weight: bold;" class="mycode_b">Custom</span>, your IP with <span style="font-weight: bold;" class="mycode_b">/32</span>, and save. <span style="font-weight: bold;" class="mycode_b">Add your rule first</span>, then delete the rules that allow 8443 from anywhere, so you don't lock yourself out. Do the same for SSH if you have a fixed IP.<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=315" target="_blank" title="">g7-05-ae60.jpg</a> (Size: 103.36 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 3: Basic Auth in front of the panel</span></span><br />
If your IP changes often, use <span style="font-weight: bold;" class="mycode_b">Basic Auth</span> instead (Admin Area → Security → Basic Auth). It puts a second username and password in front of CloudPanel's login page, which stops bots from even reaching it. As root you can also toggle it with:<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>clpctl cloudpanel:enable:basic-auth --userName=john --password='a-strong-password'
clpctl cloudpanel:disable:basic-auth</code></div></div><!-- 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=316" target="_blank" title="">g7-06-ae61.jpg</a> (Size: 89.63 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 4: Site-level security</span></span><br />
Each site has its own <span style="font-weight: bold;" class="mycode_b">Security</span> tab:<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">IP Blocking:</span> block single IPs or whole ranges.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Bot Blocking:</span> block bad bots by user agent, such as the scanners you'll see in your access logs.<br />
</li>
</ul>
<!-- 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=317" target="_blank" title="">g7-07-ae40.jpg</a> (Size: 96.39 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Basic Authentication:</span> password-protect staging copies the public shouldn't see, with a list of <span style="font-weight: bold;" class="mycode_b">whitelisted IPs</span> that skip it.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Cloudflare:</span> "Allow traffic from Cloudflare only", so nobody can bypass Cloudflare by hitting your server's IP directly.<br />
</li>
</ul>
<!-- 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=318" target="_blank" title="">g7-08-ae42.jpg</a> (Size: 84.98 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 5: Keep everything updated</span></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>apt update &amp;&amp; apt -y upgrade
# take a snapshot of the server at your provider first
clp-update
reboot   # when a new kernel was installed</code></div></div><br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Security checklist</span></span><ul class="mycode_list"><li>Remote backups on, with a tested restore.<br />
</li>
<li>Port 8443 restricted to your IP, or Basic Auth enabled.<br />
</li>
<li>Two-factor authentication on your CloudPanel admin user.<br />
</li>
<li>SSH keys instead of passwords; SSH restricted if you have a fixed IP.<br />
</li>
<li>Bad bots and abusive IPs blocked per site; Cloudflare-only mode if you use Cloudflare.<br />
</li>
<li>OS and CloudPanel updated regularly.<br />
</li>
</ul>
<br />
Questions? Ask in <span style="font-weight: bold;" class="mycode_b">CloudPanel Security Support</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel guide series</span></span><br />
<ol type="1" class="mycode_list"><li><a href="https://adminsforum.com/Thread-guide-what-is-cloudpanel-complete-overview-of-the-free-hosting-control-panel-2026" target="_blank" rel="noopener" class="mycode_url">What is CloudPanel? Complete overview</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-system-requirements-2026-os-cpu-ram-disk-and-ports" target="_blank" rel="noopener" class="mycode_url">CloudPanel system requirements</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-features-the-complete-list-2026" target="_blank" rel="noopener" class="mycode_url">CloudPanel features: the complete list</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-create-a-php-site-in-cloudpanel-step-by-step-2026" target="_blank" rel="noopener" class="mycode_url">How to create a PHP site</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-a-free-let-s-encrypt-ssl-certificate-in-cloudpanel" target="_blank" rel="noopener" class="mycode_url">How to install free Let's Encrypt SSL</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-wordpress-in-cloudpanel-one-click-setup-guide" target="_blank" rel="noopener" class="mycode_url">How to install WordPress (one-click)</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-databases-create-a-database-users-and-use-phpmyadmin" target="_blank" rel="noopener" class="mycode_url">Databases, users and phpMyAdmin</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-ssh-sftp-ftp-and-file-manager-how-to-upload-files" target="_blank" rel="noopener" class="mycode_url">SSH, SFTP, FTP and File Manager</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-cron-jobs-logs-and-varnish-cache-complete-guide" target="_blank" rel="noopener" class="mycode_url">Cron jobs, logs and Varnish Cache</a><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Backups, firewall and Basic Auth</span> (you are here)<br />
</li>
</ol>
]]></description>
			<content:encoded><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel backups and security: remote backups, firewall and Basic Auth</span></span><br />
<br />
The steps that protect a CloudPanel server: off-server backups, locking down the panel, per-site blocking, and keeping everything updated. Tested on CloudPanel 2.5.4, Ubuntu 24.04.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 1: Remote backups</span></span><br />
A backup on the same server isn't a backup if the server dies. Go to <span style="font-weight: bold;" class="mycode_b">Admin Area → Backups</span> and choose a <span style="font-weight: bold;" class="mycode_b">Storage Provider</span>: Amazon S3, Wasabi, DigitalOcean Spaces, Dropbox, Google Drive, Hetzner Storage Box, SFTP or a custom Rclone config.<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=311" target="_blank" title="">g7-01-ae55.jpg</a> (Size: 87.42 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
Turn on <span style="font-weight: bold;" class="mycode_b">Enable Remote Backup</span> and set the <span style="font-weight: bold;" class="mycode_b">Frequency</span> and <span style="font-weight: bold;" class="mycode_b">Time</span>. Pick a quiet hour, such as 02:00.<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=312" target="_blank" title="">g7-02-ae56.jpg</a> (Size: 112.26 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
Enter the <span style="font-weight: bold;" class="mycode_b">bucket</span> and <span style="font-weight: bold;" class="mycode_b">region</span>, an <span style="font-weight: bold;" class="mycode_b">access key</span> and <span style="font-weight: bold;" class="mycode_b">secret key</span>, the storage directory, the <span style="font-weight: bold;" class="mycode_b">retention period</span> (days to keep) and any <span style="font-weight: bold;" class="mycode_b">excludes</span> such as cache folders, then save. (The keys in our screenshot are CloudPanel's example values, not real keys.) Create a key that can only access this one bucket.<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=313" target="_blank" title="">g7-03-ae57.jpg</a> (Size: 113.31 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 2: The firewall</span></span><br />
In <span style="font-weight: bold;" class="mycode_b">Admin Area → Security → Firewall</span>, CloudPanel by default allows SSH (22), HTTP (80), HTTPS (443) and the panel (8443) from anywhere.<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=314" target="_blank" title="">g7-04-ae58.jpg</a> (Size: 104.35 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Best single step: allow port 8443 only from your own IP.</span> Click <span style="font-weight: bold;" class="mycode_b">Add Rule</span>, type <span style="font-weight: bold;" class="mycode_b">CloudPanel</span>, source <span style="font-weight: bold;" class="mycode_b">Custom</span>, your IP with <span style="font-weight: bold;" class="mycode_b">/32</span>, and save. <span style="font-weight: bold;" class="mycode_b">Add your rule first</span>, then delete the rules that allow 8443 from anywhere, so you don't lock yourself out. Do the same for SSH if you have a fixed IP.<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=315" target="_blank" title="">g7-05-ae60.jpg</a> (Size: 103.36 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 3: Basic Auth in front of the panel</span></span><br />
If your IP changes often, use <span style="font-weight: bold;" class="mycode_b">Basic Auth</span> instead (Admin Area → Security → Basic Auth). It puts a second username and password in front of CloudPanel's login page, which stops bots from even reaching it. As root you can also toggle it with:<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>clpctl cloudpanel:enable:basic-auth --userName=john --password='a-strong-password'
clpctl cloudpanel:disable:basic-auth</code></div></div><!-- 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=316" target="_blank" title="">g7-06-ae61.jpg</a> (Size: 89.63 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 4: Site-level security</span></span><br />
Each site has its own <span style="font-weight: bold;" class="mycode_b">Security</span> tab:<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">IP Blocking:</span> block single IPs or whole ranges.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Bot Blocking:</span> block bad bots by user agent, such as the scanners you'll see in your access logs.<br />
</li>
</ul>
<!-- 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=317" target="_blank" title="">g7-07-ae40.jpg</a> (Size: 96.39 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Basic Authentication:</span> password-protect staging copies the public shouldn't see, with a list of <span style="font-weight: bold;" class="mycode_b">whitelisted IPs</span> that skip it.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Cloudflare:</span> "Allow traffic from Cloudflare only", so nobody can bypass Cloudflare by hitting your server's IP directly.<br />
</li>
</ul>
<!-- 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=318" target="_blank" title="">g7-08-ae42.jpg</a> (Size: 84.98 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 5: Keep everything updated</span></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>apt update &amp;&amp; apt -y upgrade
# take a snapshot of the server at your provider first
clp-update
reboot   # when a new kernel was installed</code></div></div><br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Security checklist</span></span><ul class="mycode_list"><li>Remote backups on, with a tested restore.<br />
</li>
<li>Port 8443 restricted to your IP, or Basic Auth enabled.<br />
</li>
<li>Two-factor authentication on your CloudPanel admin user.<br />
</li>
<li>SSH keys instead of passwords; SSH restricted if you have a fixed IP.<br />
</li>
<li>Bad bots and abusive IPs blocked per site; Cloudflare-only mode if you use Cloudflare.<br />
</li>
<li>OS and CloudPanel updated regularly.<br />
</li>
</ul>
<br />
Questions? Ask in <span style="font-weight: bold;" class="mycode_b">CloudPanel Security Support</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel guide series</span></span><br />
<ol type="1" class="mycode_list"><li><a href="https://adminsforum.com/Thread-guide-what-is-cloudpanel-complete-overview-of-the-free-hosting-control-panel-2026" target="_blank" rel="noopener" class="mycode_url">What is CloudPanel? Complete overview</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-system-requirements-2026-os-cpu-ram-disk-and-ports" target="_blank" rel="noopener" class="mycode_url">CloudPanel system requirements</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-features-the-complete-list-2026" target="_blank" rel="noopener" class="mycode_url">CloudPanel features: the complete list</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-create-a-php-site-in-cloudpanel-step-by-step-2026" target="_blank" rel="noopener" class="mycode_url">How to create a PHP site</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-a-free-let-s-encrypt-ssl-certificate-in-cloudpanel" target="_blank" rel="noopener" class="mycode_url">How to install free Let's Encrypt SSL</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-wordpress-in-cloudpanel-one-click-setup-guide" target="_blank" rel="noopener" class="mycode_url">How to install WordPress (one-click)</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-databases-create-a-database-users-and-use-phpmyadmin" target="_blank" rel="noopener" class="mycode_url">Databases, users and phpMyAdmin</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-ssh-sftp-ftp-and-file-manager-how-to-upload-files" target="_blank" rel="noopener" class="mycode_url">SSH, SFTP, FTP and File Manager</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-cron-jobs-logs-and-varnish-cache-complete-guide" target="_blank" rel="noopener" class="mycode_url">Cron jobs, logs and Varnish Cache</a><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Backups, firewall and Basic Auth</span> (you are here)<br />
</li>
</ol>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[CloudPanel Cron Jobs, Logs and Varnish Cache: Complete Guide]]></title>
			<link>https://adminsforum.com/Thread-guide-cloudpanel-cron-jobs-logs-and-varnish-cache-complete-guide</link>
			<pubDate>Wed, 14 Oct 2026 21:10:14 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://adminsforum.com/member.php?action=profile&uid=1">JAY</a>]]></dc:creator>
			<guid isPermaLink="false">https://adminsforum.com/Thread-guide-cloudpanel-cron-jobs-logs-and-varnish-cache-complete-guide</guid>
			<description><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel cron jobs, logs and Varnish Cache</span></span><br />
<br />
Three tools you'll use on every CloudPanel site: <span style="font-weight: bold;" class="mycode_b">cron jobs</span> for scheduled tasks, the <span style="font-weight: bold;" class="mycode_b">Logs</span> tab for troubleshooting, and <span style="font-weight: bold;" class="mycode_b">Varnish Cache</span> for fast page loads. Tested on CloudPanel 2.5.4, Ubuntu 24.04.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 1: Cron jobs</span></span><br />
Open the site's <span style="font-weight: bold;" class="mycode_b">Cron Jobs</span> tab and click <span style="font-weight: bold;" class="mycode_b">Add Cron Job</span>. The <span style="font-weight: bold;" class="mycode_b">Template</span> menu fills in common schedules for you, from every minute to once a month, or you can type the five fields yourself: minute, hour, day, month and weekday.<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=305" target="_blank" title="">g6-01-ae47.jpg</a> (Size: 98.57 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Example: a real cron for WordPress.</span> WordPress's built-in cron only runs when someone visits the site. Run it every 5 minutes with real cron instead:<ul class="mycode_list"><li>Template: <span style="font-weight: bold;" class="mycode_b">Every 5 minutes</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>*/5 * * * *</code></div></div>)<br />
</li>
<li>Command:<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>php /home/SITE_USER/htdocs/YOUR_DOMAIN/wp-cron.php &gt; /dev/null 2&gt;&amp;1</code></div></div></li>
</ul>
<!-- 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=306" target="_blank" title="">g6-02-ae48.jpg</a> (Size: 103.82 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
Then add this line to <span style="font-weight: bold;" class="mycode_b">wp-config.php</span> so WordPress doesn't also run it on page loads:<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>define('DISABLE_WP_CRON', true);</code></div></div><br />
The job is saved and runs <span style="font-weight: bold;" class="mycode_b">as the site user</span>, with exactly the same permissions as the website.<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=307" target="_blank" title="">g6-03-ae52.jpg</a> (Size: 101.13 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 2: Logs</span></span><br />
When something breaks, open the <span style="font-weight: bold;" class="mycode_b">Logs</span> tab. Choose the source (<span style="font-weight: bold;" class="mycode_b">NGINX</span> or <span style="font-weight: bold;" class="mycode_b">PHP</span>), the file (<span style="font-weight: bold;" class="mycode_b">access</span> or <span style="font-weight: bold;" class="mycode_b">error</span>) and how many lines to show, then click <span style="font-weight: bold;" class="mycode_b">Update</span>.<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=308" target="_blank" title="">g6-04-ae50.jpg</a> (Size: 148.44 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
Each access-log line is one request: time, visitor IP, URL and status code. In our screenshot, a bot was probing for <span style="font-weight: bold;" class="mycode_b">.env</span> files (which can contain secrets) minutes after the site went live. That's normal on the internet, and a good reason to block bad bots in the site's Security tab.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Troubleshooting tip:</span> for 500 errors or blank pages, check the <span style="font-weight: bold;" class="mycode_b">PHP error log</span> first; for 404s and redirects, the <span style="font-weight: bold;" class="mycode_b">Nginx access log</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 3: Varnish Cache</span></span><br />
Varnish stores finished pages in memory, so repeat visitors are served without running PHP at all. It's <span style="font-weight: bold;" class="mycode_b">off by default</span>; switch it on per site in the <span style="font-weight: bold;" class="mycode_b">Varnish Cache</span> tab.<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Cache Lifetime:</span> how long pages are kept.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Excluded Params:</span> requests with these parameters bypass the cache (for example sessions).<br />
</li>
</ul>
<!-- 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=309" target="_blank" title="">g6-05-ae39.jpg</a> (Size: 103.92 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-weight: bold;" class="mycode_b">When to use it:</span> Varnish is a big win for blogs and content sites. For shops and member areas, test carefully: logged-in pages must never be cached for everyone. For WordPress, CloudPanel's <span style="font-weight: bold;" class="mycode_b">CLP Varnish Cache</span> plugin clears the cache when you publish.<br />
<br />
Questions? Ask in <span style="font-weight: bold;" class="mycode_b">CloudPanel Varnish Cache &amp; Performance Support</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel guide series</span></span><br />
<ol type="1" class="mycode_list"><li><a href="https://adminsforum.com/Thread-guide-what-is-cloudpanel-complete-overview-of-the-free-hosting-control-panel-2026" target="_blank" rel="noopener" class="mycode_url">What is CloudPanel? Complete overview</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-system-requirements-2026-os-cpu-ram-disk-and-ports" target="_blank" rel="noopener" class="mycode_url">CloudPanel system requirements</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-features-the-complete-list-2026" target="_blank" rel="noopener" class="mycode_url">CloudPanel features: the complete list</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-create-a-php-site-in-cloudpanel-step-by-step-2026" target="_blank" rel="noopener" class="mycode_url">How to create a PHP site</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-a-free-let-s-encrypt-ssl-certificate-in-cloudpanel" target="_blank" rel="noopener" class="mycode_url">How to install free Let's Encrypt SSL</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-wordpress-in-cloudpanel-one-click-setup-guide" target="_blank" rel="noopener" class="mycode_url">How to install WordPress (one-click)</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-databases-create-a-database-users-and-use-phpmyadmin" target="_blank" rel="noopener" class="mycode_url">Databases, users and phpMyAdmin</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-ssh-sftp-ftp-and-file-manager-how-to-upload-files" target="_blank" rel="noopener" class="mycode_url">SSH, SFTP, FTP and File Manager</a><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Cron jobs, logs and Varnish Cache</span> (you are here)<br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-backups-and-security-remote-backups-firewall-and-basic-auth" target="_blank" rel="noopener" class="mycode_url">Backups, firewall and Basic Auth</a><br />
</li>
</ol>
]]></description>
			<content:encoded><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel cron jobs, logs and Varnish Cache</span></span><br />
<br />
Three tools you'll use on every CloudPanel site: <span style="font-weight: bold;" class="mycode_b">cron jobs</span> for scheduled tasks, the <span style="font-weight: bold;" class="mycode_b">Logs</span> tab for troubleshooting, and <span style="font-weight: bold;" class="mycode_b">Varnish Cache</span> for fast page loads. Tested on CloudPanel 2.5.4, Ubuntu 24.04.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 1: Cron jobs</span></span><br />
Open the site's <span style="font-weight: bold;" class="mycode_b">Cron Jobs</span> tab and click <span style="font-weight: bold;" class="mycode_b">Add Cron Job</span>. The <span style="font-weight: bold;" class="mycode_b">Template</span> menu fills in common schedules for you, from every minute to once a month, or you can type the five fields yourself: minute, hour, day, month and weekday.<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=305" target="_blank" title="">g6-01-ae47.jpg</a> (Size: 98.57 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Example: a real cron for WordPress.</span> WordPress's built-in cron only runs when someone visits the site. Run it every 5 minutes with real cron instead:<ul class="mycode_list"><li>Template: <span style="font-weight: bold;" class="mycode_b">Every 5 minutes</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>*/5 * * * *</code></div></div>)<br />
</li>
<li>Command:<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>php /home/SITE_USER/htdocs/YOUR_DOMAIN/wp-cron.php &gt; /dev/null 2&gt;&amp;1</code></div></div></li>
</ul>
<!-- 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=306" target="_blank" title="">g6-02-ae48.jpg</a> (Size: 103.82 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
Then add this line to <span style="font-weight: bold;" class="mycode_b">wp-config.php</span> so WordPress doesn't also run it on page loads:<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>define('DISABLE_WP_CRON', true);</code></div></div><br />
The job is saved and runs <span style="font-weight: bold;" class="mycode_b">as the site user</span>, with exactly the same permissions as the website.<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=307" target="_blank" title="">g6-03-ae52.jpg</a> (Size: 101.13 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 2: Logs</span></span><br />
When something breaks, open the <span style="font-weight: bold;" class="mycode_b">Logs</span> tab. Choose the source (<span style="font-weight: bold;" class="mycode_b">NGINX</span> or <span style="font-weight: bold;" class="mycode_b">PHP</span>), the file (<span style="font-weight: bold;" class="mycode_b">access</span> or <span style="font-weight: bold;" class="mycode_b">error</span>) and how many lines to show, then click <span style="font-weight: bold;" class="mycode_b">Update</span>.<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=308" target="_blank" title="">g6-04-ae50.jpg</a> (Size: 148.44 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
Each access-log line is one request: time, visitor IP, URL and status code. In our screenshot, a bot was probing for <span style="font-weight: bold;" class="mycode_b">.env</span> files (which can contain secrets) minutes after the site went live. That's normal on the internet, and a good reason to block bad bots in the site's Security tab.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Troubleshooting tip:</span> for 500 errors or blank pages, check the <span style="font-weight: bold;" class="mycode_b">PHP error log</span> first; for 404s and redirects, the <span style="font-weight: bold;" class="mycode_b">Nginx access log</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Part 3: Varnish Cache</span></span><br />
Varnish stores finished pages in memory, so repeat visitors are served without running PHP at all. It's <span style="font-weight: bold;" class="mycode_b">off by default</span>; switch it on per site in the <span style="font-weight: bold;" class="mycode_b">Varnish Cache</span> tab.<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Cache Lifetime:</span> how long pages are kept.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Excluded Params:</span> requests with these parameters bypass the cache (for example sessions).<br />
</li>
</ul>
<!-- 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=309" target="_blank" title="">g6-05-ae39.jpg</a> (Size: 103.92 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-weight: bold;" class="mycode_b">When to use it:</span> Varnish is a big win for blogs and content sites. For shops and member areas, test carefully: logged-in pages must never be cached for everyone. For WordPress, CloudPanel's <span style="font-weight: bold;" class="mycode_b">CLP Varnish Cache</span> plugin clears the cache when you publish.<br />
<br />
Questions? Ask in <span style="font-weight: bold;" class="mycode_b">CloudPanel Varnish Cache &amp; Performance Support</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel guide series</span></span><br />
<ol type="1" class="mycode_list"><li><a href="https://adminsforum.com/Thread-guide-what-is-cloudpanel-complete-overview-of-the-free-hosting-control-panel-2026" target="_blank" rel="noopener" class="mycode_url">What is CloudPanel? Complete overview</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-system-requirements-2026-os-cpu-ram-disk-and-ports" target="_blank" rel="noopener" class="mycode_url">CloudPanel system requirements</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-features-the-complete-list-2026" target="_blank" rel="noopener" class="mycode_url">CloudPanel features: the complete list</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-create-a-php-site-in-cloudpanel-step-by-step-2026" target="_blank" rel="noopener" class="mycode_url">How to create a PHP site</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-a-free-let-s-encrypt-ssl-certificate-in-cloudpanel" target="_blank" rel="noopener" class="mycode_url">How to install free Let's Encrypt SSL</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-wordpress-in-cloudpanel-one-click-setup-guide" target="_blank" rel="noopener" class="mycode_url">How to install WordPress (one-click)</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-databases-create-a-database-users-and-use-phpmyadmin" target="_blank" rel="noopener" class="mycode_url">Databases, users and phpMyAdmin</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-ssh-sftp-ftp-and-file-manager-how-to-upload-files" target="_blank" rel="noopener" class="mycode_url">SSH, SFTP, FTP and File Manager</a><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Cron jobs, logs and Varnish Cache</span> (you are here)<br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-backups-and-security-remote-backups-firewall-and-basic-auth" target="_blank" rel="noopener" class="mycode_url">Backups, firewall and Basic Auth</a><br />
</li>
</ol>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[CloudPanel SSH, SFTP, FTP and File Manager: How to Upload Files]]></title>
			<link>https://adminsforum.com/Thread-guide-cloudpanel-ssh-sftp-ftp-and-file-manager-how-to-upload-files</link>
			<pubDate>Wed, 14 Oct 2026 21:09:43 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://adminsforum.com/member.php?action=profile&uid=1">JAY</a>]]></dc:creator>
			<guid isPermaLink="false">https://adminsforum.com/Thread-guide-cloudpanel-ssh-sftp-ftp-and-file-manager-how-to-upload-files</guid>
			<description><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel SSH, SFTP, FTP and File Manager: how to upload files</span></span><br />
<br />
This guide covers every way to get files onto a CloudPanel site: the site user over SSH and SFTP, SSH keys, extra SSH and FTP users for developers, and the built-in File Manager, plus the one habit that prevents permission problems. Tested on CloudPanel 2.5.4, Ubuntu 24.04.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. The site user: your main login</span></span><br />
Every site already has one login: its <span style="font-weight: bold;" class="mycode_b">site user</span>. In the site's <span style="font-weight: bold;" class="mycode_b">Settings</span> tab you can reset its password, or paste your <span style="font-weight: bold;" class="mycode_b">public SSH key</span> to log in with a key instead of a password.<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=302" target="_blank" title="">g5-01-ae10.jpg</a> (Size: 76.29 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Log in over SSH</span></span><br />
From your own computer:<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>ssh SITE_USER@YOUR_SERVER_IP
ls
# backups  htdocs  logs  tmp
ls htdocs
# example.com</code></div></div>You land in the site user's home. Your website lives in <span style="font-weight: bold;" class="mycode_b">htdocs/YOUR_DOMAIN</span>. A site user can't see any other site.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Upload with SFTP (FileZilla, WinSCP, Cyberduck)</span></span><br />
Use <span style="font-weight: bold;" class="mycode_b">SFTP</span>, not plain FTP:<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>Protocol: SFTP
Host:     YOUR_SERVER_IP
Port:     22
User:     SITE_USER  (password or SSH key)
Folder:   /home/SITE_USER/htdocs/YOUR_DOMAIN</code></div></div><br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">4. Extra SSH and FTP users</span></span><br />
Need to give a developer access without sharing the main login? Open the <span style="font-weight: bold;" class="mycode_b">SSH/FTP</span> tab → <span style="font-weight: bold;" class="mycode_b">SSH Users</span> → <span style="font-weight: bold;" class="mycode_b">Add User</span>. They get their own password or key, and you delete them when the job's done.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">FTP Users</span> work the same way, for older tools that only speak FTP. Plain FTP isn't encrypted, so prefer SFTP. If you do use FTP, you'll also need to allow the FTP and passive ports in the firewall (Admin Area → Security).<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=303" target="_blank" title="">g5-02-ae43.jpg</a> (Size: 97.02 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">5. The File Manager</span></span><br />
The <span style="font-weight: bold;" class="mycode_b">File Manager</span> tab works in your browser: upload, create, edit, rename, compress and extract files, and see the owner and permissions of each one. Everything is owned by the site user, which is exactly what PHP needs to write uploads and caches.<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=304" target="_blank" title="">g5-03-ae45.jpg</a> (Size: 132.72 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Avoid permission problems: don't work as root</span></span><br />
Don't create site files as <span style="font-weight: bold;" class="mycode_b">root</span> over SSH. They'd be owned by root, and the site couldn't change them (failed uploads, cache errors, plugin updates that won't install). Always log in as the <span style="font-weight: bold;" class="mycode_b">site user</span> (or an extra SSH user for that site) and you'll never have permission problems.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Security tips</span></span><ul class="mycode_list"><li>Prefer SSH keys over passwords.<br />
</li>
<li>Remove extra SSH/FTP users as soon as they're not needed.<br />
</li>
<li>If you have a fixed IP, restrict port 22 to it in Admin Area → Security → Firewall.<br />
</li>
</ul>
<br />
Questions? Ask in <span style="font-weight: bold;" class="mycode_b">CloudPanel Users, SSH &amp; SFTP Support</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel guide series</span></span><br />
<ol type="1" class="mycode_list"><li><a href="https://adminsforum.com/Thread-guide-what-is-cloudpanel-complete-overview-of-the-free-hosting-control-panel-2026" target="_blank" rel="noopener" class="mycode_url">What is CloudPanel? Complete overview</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-system-requirements-2026-os-cpu-ram-disk-and-ports" target="_blank" rel="noopener" class="mycode_url">CloudPanel system requirements</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-features-the-complete-list-2026" target="_blank" rel="noopener" class="mycode_url">CloudPanel features: the complete list</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-create-a-php-site-in-cloudpanel-step-by-step-2026" target="_blank" rel="noopener" class="mycode_url">How to create a PHP site</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-a-free-let-s-encrypt-ssl-certificate-in-cloudpanel" target="_blank" rel="noopener" class="mycode_url">How to install free Let's Encrypt SSL</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-wordpress-in-cloudpanel-one-click-setup-guide" target="_blank" rel="noopener" class="mycode_url">How to install WordPress (one-click)</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-databases-create-a-database-users-and-use-phpmyadmin" target="_blank" rel="noopener" class="mycode_url">Databases, users and phpMyAdmin</a><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">SSH, SFTP, FTP and File Manager</span> (you are here)<br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-cron-jobs-logs-and-varnish-cache-complete-guide" target="_blank" rel="noopener" class="mycode_url">Cron jobs, logs and Varnish Cache</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-backups-and-security-remote-backups-firewall-and-basic-auth" target="_blank" rel="noopener" class="mycode_url">Backups, firewall and Basic Auth</a><br />
</li>
</ol>
]]></description>
			<content:encoded><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel SSH, SFTP, FTP and File Manager: how to upload files</span></span><br />
<br />
This guide covers every way to get files onto a CloudPanel site: the site user over SSH and SFTP, SSH keys, extra SSH and FTP users for developers, and the built-in File Manager, plus the one habit that prevents permission problems. Tested on CloudPanel 2.5.4, Ubuntu 24.04.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. The site user: your main login</span></span><br />
Every site already has one login: its <span style="font-weight: bold;" class="mycode_b">site user</span>. In the site's <span style="font-weight: bold;" class="mycode_b">Settings</span> tab you can reset its password, or paste your <span style="font-weight: bold;" class="mycode_b">public SSH key</span> to log in with a key instead of a password.<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=302" target="_blank" title="">g5-01-ae10.jpg</a> (Size: 76.29 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Log in over SSH</span></span><br />
From your own computer:<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>ssh SITE_USER@YOUR_SERVER_IP
ls
# backups  htdocs  logs  tmp
ls htdocs
# example.com</code></div></div>You land in the site user's home. Your website lives in <span style="font-weight: bold;" class="mycode_b">htdocs/YOUR_DOMAIN</span>. A site user can't see any other site.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Upload with SFTP (FileZilla, WinSCP, Cyberduck)</span></span><br />
Use <span style="font-weight: bold;" class="mycode_b">SFTP</span>, not plain FTP:<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>Protocol: SFTP
Host:     YOUR_SERVER_IP
Port:     22
User:     SITE_USER  (password or SSH key)
Folder:   /home/SITE_USER/htdocs/YOUR_DOMAIN</code></div></div><br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">4. Extra SSH and FTP users</span></span><br />
Need to give a developer access without sharing the main login? Open the <span style="font-weight: bold;" class="mycode_b">SSH/FTP</span> tab → <span style="font-weight: bold;" class="mycode_b">SSH Users</span> → <span style="font-weight: bold;" class="mycode_b">Add User</span>. They get their own password or key, and you delete them when the job's done.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">FTP Users</span> work the same way, for older tools that only speak FTP. Plain FTP isn't encrypted, so prefer SFTP. If you do use FTP, you'll also need to allow the FTP and passive ports in the firewall (Admin Area → Security).<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=303" target="_blank" title="">g5-02-ae43.jpg</a> (Size: 97.02 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">5. The File Manager</span></span><br />
The <span style="font-weight: bold;" class="mycode_b">File Manager</span> tab works in your browser: upload, create, edit, rename, compress and extract files, and see the owner and permissions of each one. Everything is owned by the site user, which is exactly what PHP needs to write uploads and caches.<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=304" target="_blank" title="">g5-03-ae45.jpg</a> (Size: 132.72 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Avoid permission problems: don't work as root</span></span><br />
Don't create site files as <span style="font-weight: bold;" class="mycode_b">root</span> over SSH. They'd be owned by root, and the site couldn't change them (failed uploads, cache errors, plugin updates that won't install). Always log in as the <span style="font-weight: bold;" class="mycode_b">site user</span> (or an extra SSH user for that site) and you'll never have permission problems.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Security tips</span></span><ul class="mycode_list"><li>Prefer SSH keys over passwords.<br />
</li>
<li>Remove extra SSH/FTP users as soon as they're not needed.<br />
</li>
<li>If you have a fixed IP, restrict port 22 to it in Admin Area → Security → Firewall.<br />
</li>
</ul>
<br />
Questions? Ask in <span style="font-weight: bold;" class="mycode_b">CloudPanel Users, SSH &amp; SFTP Support</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel guide series</span></span><br />
<ol type="1" class="mycode_list"><li><a href="https://adminsforum.com/Thread-guide-what-is-cloudpanel-complete-overview-of-the-free-hosting-control-panel-2026" target="_blank" rel="noopener" class="mycode_url">What is CloudPanel? Complete overview</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-system-requirements-2026-os-cpu-ram-disk-and-ports" target="_blank" rel="noopener" class="mycode_url">CloudPanel system requirements</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-features-the-complete-list-2026" target="_blank" rel="noopener" class="mycode_url">CloudPanel features: the complete list</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-create-a-php-site-in-cloudpanel-step-by-step-2026" target="_blank" rel="noopener" class="mycode_url">How to create a PHP site</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-a-free-let-s-encrypt-ssl-certificate-in-cloudpanel" target="_blank" rel="noopener" class="mycode_url">How to install free Let's Encrypt SSL</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-wordpress-in-cloudpanel-one-click-setup-guide" target="_blank" rel="noopener" class="mycode_url">How to install WordPress (one-click)</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-databases-create-a-database-users-and-use-phpmyadmin" target="_blank" rel="noopener" class="mycode_url">Databases, users and phpMyAdmin</a><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">SSH, SFTP, FTP and File Manager</span> (you are here)<br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-cron-jobs-logs-and-varnish-cache-complete-guide" target="_blank" rel="noopener" class="mycode_url">Cron jobs, logs and Varnish Cache</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-backups-and-security-remote-backups-firewall-and-basic-auth" target="_blank" rel="noopener" class="mycode_url">Backups, firewall and Basic Auth</a><br />
</li>
</ol>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[CloudPanel Databases: Create a Database, Users and Use phpMyAdmin]]></title>
			<link>https://adminsforum.com/Thread-guide-cloudpanel-databases-create-a-database-users-and-use-phpmyadmin</link>
			<pubDate>Wed, 14 Oct 2026 21:09:13 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://adminsforum.com/member.php?action=profile&uid=1">JAY</a>]]></dc:creator>
			<guid isPermaLink="false">https://adminsforum.com/Thread-guide-cloudpanel-databases-create-a-database-users-and-use-phpmyadmin</guid>
			<description><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel databases: create a database and users, and use phpMyAdmin</span></span><br />
<br />
In CloudPanel, <span style="font-weight: bold;" class="mycode_b">databases belong to a site</span>. This guide shows how to create a database and user, add extra users with limited rights, open phpMyAdmin, handle large imports from the command line, and where CloudPanel keeps automatic database backups. Tested on CloudPanel 2.5.4, Ubuntu 24.04, MySQL 8.4.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 1: Open the site's Databases tab</span></span><br />
Open <span style="font-weight: bold;" class="mycode_b">Sites</span> → <span style="font-weight: bold;" class="mycode_b">Manage</span> → <span style="font-weight: bold;" class="mycode_b">Databases</span>. Our WordPress database is already listed, created by the one-click installer. Note the connection details at the top: host <span style="font-weight: bold;" class="mycode_b">127.0.0.1</span>, port <span style="font-weight: bold;" class="mycode_b">3306</span>. Your app uses these.<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=298" target="_blank" title="">g4-01-ae34.jpg</a> (Size: 103.25 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 2: Add a database</span></span><br />
Click <span style="font-weight: bold;" class="mycode_b">Add Database</span> and enter a database name, a database user name and a password. CloudPanel creates both and grants the user access in one step.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 3: Add extra database users</span></span><br />
The <span style="font-weight: bold;" class="mycode_b">Database Users</span> list shows every user, the database it can reach and its permissions. Use <span style="font-weight: bold;" class="mycode_b">Add Database User</span> for extra users, with <span style="font-weight: bold;" class="mycode_b">Read and Write</span> or <span style="font-weight: bold;" class="mycode_b">Read Only</span> access. A read-only user is ideal for reporting or backup tools, which then can never change your data.<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=299" target="_blank" title="">g4-02-ae36.jpg</a> (Size: 104.64 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 4: Open phpMyAdmin with one click</span></span><br />
Click <span style="font-weight: bold;" class="mycode_b">Manage</span> next to a database user and phpMyAdmin opens already logged in as that user, with no extra password to type. Browse tables, run SQL, and import or export from the tabs at the top.<br />
<br />
On the right, phpMyAdmin shows the server. On our install it's <span style="font-weight: bold;" class="mycode_b">Percona Server 8.4</span>, a drop-in MySQL build, chosen when we ran the installer.<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=300" target="_blank" title="">g4-03-ae38.jpg</a> (Size: 178.15 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 5: Big imports and exports with clpctl</span></span><br />
Large databases can time out in the browser. As root, use clpctl instead:<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># export a compressed dump
clpctl db:export --databaseName=my-database --file=/tmp/dump.sql.gz

# import a dump
clpctl db:import --databaseName=my-database --file=/tmp/dump.sql.gz

# create a database and user from the shell
clpctl db:add --domainName=example.com --databaseName=my-database --databaseUserName=myuser --databaseUserPassword='a-strong-password'

# show the database root (master) login
clpctl db:show:master-credentials</code></div></div><br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Automatic database backups</span></span><br />
CloudPanel also dumps every database automatically each night (at 03:15 on our server) into the <span style="font-weight: bold;" class="mycode_b">backups</span> folder in the site user's home, and keeps 7 days of them. It's a useful safety net, but it's on the same server, so also set up <span style="font-weight: bold;" class="mycode_b">remote backups</span> in the Admin Area.<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=301" target="_blank" title="">g4-04-ae45.jpg</a> (Size: 132.72 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Tips</span></span><ul class="mycode_list"><li>Give each app its own database user, and use read-only users wherever writing isn't needed.<br />
</li>
<li>Never expose port 3306 in the firewall; apps on the same server connect via 127.0.0.1.<br />
</li>
<li>Keep the master credentials for emergencies only.<br />
</li>
</ul>
<br />
Questions? Ask in <span style="font-weight: bold;" class="mycode_b">CloudPanel Databases &amp; phpMyAdmin Support</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel guide series</span></span><br />
<ol type="1" class="mycode_list"><li><a href="https://adminsforum.com/Thread-guide-what-is-cloudpanel-complete-overview-of-the-free-hosting-control-panel-2026" target="_blank" rel="noopener" class="mycode_url">What is CloudPanel? Complete overview</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-system-requirements-2026-os-cpu-ram-disk-and-ports" target="_blank" rel="noopener" class="mycode_url">CloudPanel system requirements</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-features-the-complete-list-2026" target="_blank" rel="noopener" class="mycode_url">CloudPanel features: the complete list</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-create-a-php-site-in-cloudpanel-step-by-step-2026" target="_blank" rel="noopener" class="mycode_url">How to create a PHP site</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-a-free-let-s-encrypt-ssl-certificate-in-cloudpanel" target="_blank" rel="noopener" class="mycode_url">How to install free Let's Encrypt SSL</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-wordpress-in-cloudpanel-one-click-setup-guide" target="_blank" rel="noopener" class="mycode_url">How to install WordPress (one-click)</a><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Databases, users and phpMyAdmin</span> (you are here)<br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-ssh-sftp-ftp-and-file-manager-how-to-upload-files" target="_blank" rel="noopener" class="mycode_url">SSH, SFTP, FTP and File Manager</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-cron-jobs-logs-and-varnish-cache-complete-guide" target="_blank" rel="noopener" class="mycode_url">Cron jobs, logs and Varnish Cache</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-backups-and-security-remote-backups-firewall-and-basic-auth" target="_blank" rel="noopener" class="mycode_url">Backups, firewall and Basic Auth</a><br />
</li>
</ol>
]]></description>
			<content:encoded><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel databases: create a database and users, and use phpMyAdmin</span></span><br />
<br />
In CloudPanel, <span style="font-weight: bold;" class="mycode_b">databases belong to a site</span>. This guide shows how to create a database and user, add extra users with limited rights, open phpMyAdmin, handle large imports from the command line, and where CloudPanel keeps automatic database backups. Tested on CloudPanel 2.5.4, Ubuntu 24.04, MySQL 8.4.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 1: Open the site's Databases tab</span></span><br />
Open <span style="font-weight: bold;" class="mycode_b">Sites</span> → <span style="font-weight: bold;" class="mycode_b">Manage</span> → <span style="font-weight: bold;" class="mycode_b">Databases</span>. Our WordPress database is already listed, created by the one-click installer. Note the connection details at the top: host <span style="font-weight: bold;" class="mycode_b">127.0.0.1</span>, port <span style="font-weight: bold;" class="mycode_b">3306</span>. Your app uses these.<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=298" target="_blank" title="">g4-01-ae34.jpg</a> (Size: 103.25 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 2: Add a database</span></span><br />
Click <span style="font-weight: bold;" class="mycode_b">Add Database</span> and enter a database name, a database user name and a password. CloudPanel creates both and grants the user access in one step.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 3: Add extra database users</span></span><br />
The <span style="font-weight: bold;" class="mycode_b">Database Users</span> list shows every user, the database it can reach and its permissions. Use <span style="font-weight: bold;" class="mycode_b">Add Database User</span> for extra users, with <span style="font-weight: bold;" class="mycode_b">Read and Write</span> or <span style="font-weight: bold;" class="mycode_b">Read Only</span> access. A read-only user is ideal for reporting or backup tools, which then can never change your data.<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=299" target="_blank" title="">g4-02-ae36.jpg</a> (Size: 104.64 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 4: Open phpMyAdmin with one click</span></span><br />
Click <span style="font-weight: bold;" class="mycode_b">Manage</span> next to a database user and phpMyAdmin opens already logged in as that user, with no extra password to type. Browse tables, run SQL, and import or export from the tabs at the top.<br />
<br />
On the right, phpMyAdmin shows the server. On our install it's <span style="font-weight: bold;" class="mycode_b">Percona Server 8.4</span>, a drop-in MySQL build, chosen when we ran the installer.<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=300" target="_blank" title="">g4-03-ae38.jpg</a> (Size: 178.15 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Step 5: Big imports and exports with clpctl</span></span><br />
Large databases can time out in the browser. As root, use clpctl instead:<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># export a compressed dump
clpctl db:export --databaseName=my-database --file=/tmp/dump.sql.gz

# import a dump
clpctl db:import --databaseName=my-database --file=/tmp/dump.sql.gz

# create a database and user from the shell
clpctl db:add --domainName=example.com --databaseName=my-database --databaseUserName=myuser --databaseUserPassword='a-strong-password'

# show the database root (master) login
clpctl db:show:master-credentials</code></div></div><br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Automatic database backups</span></span><br />
CloudPanel also dumps every database automatically each night (at 03:15 on our server) into the <span style="font-weight: bold;" class="mycode_b">backups</span> folder in the site user's home, and keeps 7 days of them. It's a useful safety net, but it's on the same server, so also set up <span style="font-weight: bold;" class="mycode_b">remote backups</span> in the Admin Area.<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=301" target="_blank" title="">g4-04-ae45.jpg</a> (Size: 132.72 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Tips</span></span><ul class="mycode_list"><li>Give each app its own database user, and use read-only users wherever writing isn't needed.<br />
</li>
<li>Never expose port 3306 in the firewall; apps on the same server connect via 127.0.0.1.<br />
</li>
<li>Keep the master credentials for emergencies only.<br />
</li>
</ul>
<br />
Questions? Ask in <span style="font-weight: bold;" class="mycode_b">CloudPanel Databases &amp; phpMyAdmin Support</span>.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CloudPanel guide series</span></span><br />
<ol type="1" class="mycode_list"><li><a href="https://adminsforum.com/Thread-guide-what-is-cloudpanel-complete-overview-of-the-free-hosting-control-panel-2026" target="_blank" rel="noopener" class="mycode_url">What is CloudPanel? Complete overview</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-system-requirements-2026-os-cpu-ram-disk-and-ports" target="_blank" rel="noopener" class="mycode_url">CloudPanel system requirements</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-features-the-complete-list-2026" target="_blank" rel="noopener" class="mycode_url">CloudPanel features: the complete list</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-create-a-php-site-in-cloudpanel-step-by-step-2026" target="_blank" rel="noopener" class="mycode_url">How to create a PHP site</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-a-free-let-s-encrypt-ssl-certificate-in-cloudpanel" target="_blank" rel="noopener" class="mycode_url">How to install free Let's Encrypt SSL</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-how-to-install-wordpress-in-cloudpanel-one-click-setup-guide" target="_blank" rel="noopener" class="mycode_url">How to install WordPress (one-click)</a><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Databases, users and phpMyAdmin</span> (you are here)<br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-ssh-sftp-ftp-and-file-manager-how-to-upload-files" target="_blank" rel="noopener" class="mycode_url">SSH, SFTP, FTP and File Manager</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-cron-jobs-logs-and-varnish-cache-complete-guide" target="_blank" rel="noopener" class="mycode_url">Cron jobs, logs and Varnish Cache</a><br />
</li>
<li><a href="https://adminsforum.com/Thread-guide-cloudpanel-backups-and-security-remote-backups-firewall-and-basic-auth" target="_blank" rel="noopener" class="mycode_url">Backups, firewall and Basic Auth</a><br />
</li>
</ol>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Monitor Server Resources During aaPanel Website Traffic Tests]]></title>
			<link>https://adminsforum.com/Thread-guide-monitor-server-resources-during-aapanel-website-traffic-tests</link>
			<pubDate>Wed, 14 Oct 2026 20:51:09 +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-monitor-server-resources-during-aapanel-website-traffic-tests</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Response times tell you that a site slowed down; simultaneous server measurements help explain why. This guide pairs a bounded WordPress traffic test with CPU, memory, swap and I/O observations on an aaPanel lab VPS.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Test environment</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5, two virtual CPUs and about 3.8GiB RAM, with Nginx, WordPress and PHP 8.5. The server also runs database, mail and other lab services. A separate Windows client generated traffic. We changed no server settings for this run.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Define the question before generating traffic</span><br />
Are slow responses accompanied by CPU activity, memory pressure, storage waiting or application queueing? Choose a harmless lab endpoint and collect a baseline. Do not test destructive application actions or run an unlimited traffic loop.<br />
Our test used the WordPress homepage with unique query strings. The existing FastCGI rules bypass query-string requests, verified in the earlier cache guide. A cached anonymous homepage could hide the PHP work we wanted to observe.<br />
Start with <a href="https://adminsforum.com/Thread-guide-run-a-controlled-wordpress-load-test-on-an-aapanel-vps" target="_blank" rel="noopener" class="mycode_url">the controlled load-test guide</a> for request limits, TLS checks and timing definitions. This follow-up adds simultaneous resource evidence rather than repeating a capacity claim.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Capture memory and load snapshots</span><br />
On the lab server, use a private SSH session:<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>date -Is
uptime
free -h
cat /proc/meminfo</code></div></div>Record the clock and timezone. The client and server must have reasonably aligned clocks to correlate events. Low free memory alone does not demonstrate a problem; include available memory and swap activity. A load average is also not a direct CPU percentage.<br />
Our MemAvailable snapshots were 2,849,192KiB before and 2,813,252KiB after, approximately 2.72GiB and 2.68GiB. These are two snapshots, not the minimum available memory throughout the run.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Start a finite interval sampler</span><br />
Our existing vmstat utility required no additional package installation. We ran:<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>LC_ALL=C vmstat -n -t 1 25</code></div></div>This requests one-second updates and a finite count. Keep the output in a private administration session or log, and note the sampler's start/end time. It should overlap the request phases, not run only after the workload finishes.<br />
The first data row includes activity averages since boot. We excluded it from interval summaries. Process and memory columns are snapshots; later activity columns cover the sampling interval. In this run we retained 24 interval rows across the traffic and surrounding idle time.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand the useful columns</span><ul class="mycode_list"><li>r: runnable work; compare repeated values with the CPU count, not one isolated spike.<br />
</li>
<li>b: work blocked waiting for I/O completion.<br />
</li>
<li>us and sy: user and kernel CPU percentages. Our CPU activity summary used 100 minus idle, I/O wait and steal.<br />
</li>
<li>id, wa and st: idle, I/O-wait and virtual-machine steal percentages; these describe different conditions.<br />
</li>
<li>si and so: swap-in and swap-out activity. Existing swap usage without current transfers is different from sustained swapping.<br />
</li>
<li>bi and bo: block input/output activity. These alone do not identify which disk or application is responsible.<br />
</li>
</ul>
Check the local manual for units and version details. Small one-second samples can hide shorter spikes, while whole-server measurements combine activity from every service.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Run a bounded client workload</span><br />
We used 80 requests at concurrency 4, followed by 80 at concurrency 8. Every request used HTTPS with normal certificate validation, a 15-second maximum time and no retry. The run would stop before a later phase if any request failed or its sample p95 TTFB exceeded five seconds.<br />
The generator ran off the VPS, so its local client work did not consume the VPS CPUs being measured. It used a finite worker pool: after one request completed, a worker could submit another. This closed-loop workload does not reproduce every real traffic pattern.<br />
Keep important service health under observation and stop if your lab becomes unstable. Do not increase concurrency just to force a failure.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Compare the recorded results</span><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=297" target="_blank" title="">monitor-load-20261014.jpg</a> (Size: 128.09 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original measurements, not a terminal screenshot.</span><br />
<ul class="mycode_list"><li>Concurrency 4: 80/80 HTTP 200, median TTFB 313ms, sample p95 467ms, elapsed phase about 10.20 seconds.<br />
</li>
<li>Concurrency 8: 80/80 HTTP 200, median TTFB 414ms, sample p95 539ms, elapsed phase about 5.76 seconds.<br />
</li>
<li>Across the 24 resource intervals: CPU activity peaked at 88%, I/O wait at 0%, steal at 1%, and runnable work at 6.<br />
</li>
<li>Every interval reported zero swap-in and zero swap-out; available-memory snapshots remained about 2.7GiB.<br />
</li>
</ul>
The higher-concurrency phase completed its finite batch sooner but had higher median latency. These short phases were not repeated in randomized order, and other lab services may contribute to whole-server CPU activity.<br />
The resource summary includes idle time around the test. Its peak values should not be confused with a phase average. We did not measure FPM queue lengths, individual query timing, per-process CPU attribution or device latency in this run.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Form a hypothesis without overstating it</span><br />
The observations do not show sampled swap pressure or I/O-wait activity. CPU work is a plausible next investigation because activity increased during this request workload. They do not prove that CPU is the only bottleneck or that the VPS can sustain this traffic indefinitely.<br />
For a stronger diagnosis, correlate process CPU, private FPM queue/status observations and application timings with the same request timestamps. Read <a href="https://adminsforum.com/Thread-guide-find-slow-php-requests-in-aapanel-with-php-fpm-slow-logs" target="_blank" rel="noopener" class="mycode_url">the PHP slow-log guide</a> to locate executing requests and <a href="https://adminsforum.com/Thread-guide-tune-mariadb-queries-in-aapanel-with-explain-and-index-tests" target="_blank" rel="noopener" class="mycode_url">the database index guide</a> when SQL is implicated.<br />
If storage is suspected, collect device-level latency and queue information as a separate test. A sampled wa value of zero is not proof that every storage operation was instantaneous.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Choose the next change from evidence</span><br />
CPU-heavy PHP work may benefit from application improvements or appropriate caching; adding workers can increase contention. Memory pressure calls for examining actual process use and service budgets. Slow SQL calls for a query plan, not an arbitrary increase to max_connections.<br />
Change one variable, retain a rollback copy and repeat the same workload with the sampler running. Check content correctness and errors as well as speed. HTTP 200 alone cannot establish that an application returned the intended page.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Keep the test reproducible</span><br />
Save phase times, raw request outcomes, resource intervals and configuration versions. Keep logs private and remove secrets before sharing. Use representative authenticated and write workflows only in an appropriate disposable test environment.<br />
This test added no public diagnostic endpoint, altered no application data and left server settings unchanged. Longer runs and realistic workload mixes remain necessary for production planning.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://manpages.ubuntu.com/manpages/jammy/man8/vmstat.8.html" target="_blank" rel="noopener" class="mycode_url">Ubuntu vmstat manual</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Response times tell you that a site slowed down; simultaneous server measurements help explain why. This guide pairs a bounded WordPress traffic test with CPU, memory, swap and I/O observations on an aaPanel lab VPS.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Test environment</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5, two virtual CPUs and about 3.8GiB RAM, with Nginx, WordPress and PHP 8.5. The server also runs database, mail and other lab services. A separate Windows client generated traffic. We changed no server settings for this run.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Define the question before generating traffic</span><br />
Are slow responses accompanied by CPU activity, memory pressure, storage waiting or application queueing? Choose a harmless lab endpoint and collect a baseline. Do not test destructive application actions or run an unlimited traffic loop.<br />
Our test used the WordPress homepage with unique query strings. The existing FastCGI rules bypass query-string requests, verified in the earlier cache guide. A cached anonymous homepage could hide the PHP work we wanted to observe.<br />
Start with <a href="https://adminsforum.com/Thread-guide-run-a-controlled-wordpress-load-test-on-an-aapanel-vps" target="_blank" rel="noopener" class="mycode_url">the controlled load-test guide</a> for request limits, TLS checks and timing definitions. This follow-up adds simultaneous resource evidence rather than repeating a capacity claim.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Capture memory and load snapshots</span><br />
On the lab server, use a private SSH session:<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>date -Is
uptime
free -h
cat /proc/meminfo</code></div></div>Record the clock and timezone. The client and server must have reasonably aligned clocks to correlate events. Low free memory alone does not demonstrate a problem; include available memory and swap activity. A load average is also not a direct CPU percentage.<br />
Our MemAvailable snapshots were 2,849,192KiB before and 2,813,252KiB after, approximately 2.72GiB and 2.68GiB. These are two snapshots, not the minimum available memory throughout the run.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Start a finite interval sampler</span><br />
Our existing vmstat utility required no additional package installation. We ran:<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>LC_ALL=C vmstat -n -t 1 25</code></div></div>This requests one-second updates and a finite count. Keep the output in a private administration session or log, and note the sampler's start/end time. It should overlap the request phases, not run only after the workload finishes.<br />
The first data row includes activity averages since boot. We excluded it from interval summaries. Process and memory columns are snapshots; later activity columns cover the sampling interval. In this run we retained 24 interval rows across the traffic and surrounding idle time.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand the useful columns</span><ul class="mycode_list"><li>r: runnable work; compare repeated values with the CPU count, not one isolated spike.<br />
</li>
<li>b: work blocked waiting for I/O completion.<br />
</li>
<li>us and sy: user and kernel CPU percentages. Our CPU activity summary used 100 minus idle, I/O wait and steal.<br />
</li>
<li>id, wa and st: idle, I/O-wait and virtual-machine steal percentages; these describe different conditions.<br />
</li>
<li>si and so: swap-in and swap-out activity. Existing swap usage without current transfers is different from sustained swapping.<br />
</li>
<li>bi and bo: block input/output activity. These alone do not identify which disk or application is responsible.<br />
</li>
</ul>
Check the local manual for units and version details. Small one-second samples can hide shorter spikes, while whole-server measurements combine activity from every service.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Run a bounded client workload</span><br />
We used 80 requests at concurrency 4, followed by 80 at concurrency 8. Every request used HTTPS with normal certificate validation, a 15-second maximum time and no retry. The run would stop before a later phase if any request failed or its sample p95 TTFB exceeded five seconds.<br />
The generator ran off the VPS, so its local client work did not consume the VPS CPUs being measured. It used a finite worker pool: after one request completed, a worker could submit another. This closed-loop workload does not reproduce every real traffic pattern.<br />
Keep important service health under observation and stop if your lab becomes unstable. Do not increase concurrency just to force a failure.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Compare the recorded results</span><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=297" target="_blank" title="">monitor-load-20261014.jpg</a> (Size: 128.09 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original measurements, not a terminal screenshot.</span><br />
<ul class="mycode_list"><li>Concurrency 4: 80/80 HTTP 200, median TTFB 313ms, sample p95 467ms, elapsed phase about 10.20 seconds.<br />
</li>
<li>Concurrency 8: 80/80 HTTP 200, median TTFB 414ms, sample p95 539ms, elapsed phase about 5.76 seconds.<br />
</li>
<li>Across the 24 resource intervals: CPU activity peaked at 88%, I/O wait at 0%, steal at 1%, and runnable work at 6.<br />
</li>
<li>Every interval reported zero swap-in and zero swap-out; available-memory snapshots remained about 2.7GiB.<br />
</li>
</ul>
The higher-concurrency phase completed its finite batch sooner but had higher median latency. These short phases were not repeated in randomized order, and other lab services may contribute to whole-server CPU activity.<br />
The resource summary includes idle time around the test. Its peak values should not be confused with a phase average. We did not measure FPM queue lengths, individual query timing, per-process CPU attribution or device latency in this run.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Form a hypothesis without overstating it</span><br />
The observations do not show sampled swap pressure or I/O-wait activity. CPU work is a plausible next investigation because activity increased during this request workload. They do not prove that CPU is the only bottleneck or that the VPS can sustain this traffic indefinitely.<br />
For a stronger diagnosis, correlate process CPU, private FPM queue/status observations and application timings with the same request timestamps. Read <a href="https://adminsforum.com/Thread-guide-find-slow-php-requests-in-aapanel-with-php-fpm-slow-logs" target="_blank" rel="noopener" class="mycode_url">the PHP slow-log guide</a> to locate executing requests and <a href="https://adminsforum.com/Thread-guide-tune-mariadb-queries-in-aapanel-with-explain-and-index-tests" target="_blank" rel="noopener" class="mycode_url">the database index guide</a> when SQL is implicated.<br />
If storage is suspected, collect device-level latency and queue information as a separate test. A sampled wa value of zero is not proof that every storage operation was instantaneous.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Choose the next change from evidence</span><br />
CPU-heavy PHP work may benefit from application improvements or appropriate caching; adding workers can increase contention. Memory pressure calls for examining actual process use and service budgets. Slow SQL calls for a query plan, not an arbitrary increase to max_connections.<br />
Change one variable, retain a rollback copy and repeat the same workload with the sampler running. Check content correctness and errors as well as speed. HTTP 200 alone cannot establish that an application returned the intended page.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Keep the test reproducible</span><br />
Save phase times, raw request outcomes, resource intervals and configuration versions. Keep logs private and remove secrets before sharing. Use representative authenticated and write workflows only in an appropriate disposable test environment.<br />
This test added no public diagnostic endpoint, altered no application data and left server settings unchanged. Longer runs and realistic workload mixes remain necessary for production planning.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://manpages.ubuntu.com/manpages/jammy/man8/vmstat.8.html" target="_blank" rel="noopener" class="mycode_url">Ubuntu vmstat manual</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Check Website Logs in aaPanel to Troubleshoot Site Errors]]></title>
			<link>https://adminsforum.com/Thread-guide-check-website-logs-in-aapanel-to-troubleshoot-site-errors</link>
			<pubDate>Wed, 14 Oct 2026 20:48:47 +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-check-website-logs-in-aapanel-to-troubleshoot-site-errors</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Start website troubleshooting by recording the failing request, its time and its HTTP status. Then match that request with the website's access log, error log and application evidence. This guide shows a real missing-file diagnosis in aaPanel and explains where to look for other failures.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5 and Nginx 1.30.5. We inspected the native website log viewer, generated one missing-file request, matched its access/error entries and verified a temporary file corrected that request. The test file was removed afterwards. Other error types below are interpretation examples, not deliberately triggered failures.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Write down the symptom before changing anything</span><br />
Record the exact hostname and path, time with timezone, HTTP status, request method, whether all pages fail or one route fails, and the last relevant change. Distinguish a browser connection failure from an HTTP response delivered by a server.<br />
A request may pass through Cloudflare/CDN, Nginx, PHP-FPM and the application. A status code alone does not identify which layer caused it. Avoid restarting every service before collecting the relevant evidence.<br />
For a harmless GET endpoint you control:<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 -sS --max-time 15 -D - -o /dev/null https://example.com/problem-path</code></div></div>Replace the hostname and path. Keep certificate verification enabled. This Linux example shows headers and discards the body; on Windows use curl.exe and NUL. Separately inspect the response content, because HTTP 200 can still contain an application error.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Open the website's native aaPanel logs</span><br />
In our current interface:<ul class="mycode_list"><li>Open Website and select PHP Project.<br />
</li>
<li>Find the exact site row and click Log.<br />
</li>
<li>The Site modification window provides Access log and Error log views, alongside Response log and Log Security Analysis.<br />
</li>
<li>Use Refresh to retrieve current information. The access view offers recent 50, 100, 500 or All lines and displays the source log path.<br />
</li>
</ul>
Labels differ between versions and project types. The main left-menu Logs section is a separate panel-wide entry; do not assume its administrative log is the website's application log. Node/Python projects have their own runtime logging to inspect as well.<br />
Our website access log was /www/wwwlogs/adminslab.com.log; its error log was /www/wwwlogs/adminslab.com.error.log. These are lab paths, not universal names. Confirm the selected website and effective Nginx access_log/error_log directives if the viewer shows no matching entries.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Locate the request in the access log</span><br />
The access log tells you that the server handled a request and records configured fields such as method, path, status and byte count. Our matching entry contained:<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>[14/Oct/2026:12:40:54 +0000]
GET /af-log-troubleshooting-missing-20261014.txt HTTP/2.0
404</code></div></div>The full entry used loopback client 127.0.0.1 because our request came from the server itself. For proxied visitor traffic, an address in a log may identify the proxy unless trusted real-IP handling is configured. Do not treat arbitrary forwarded headers as verified visitor identity.<br />
Match the time, hostname, path and method rather than assuming the latest error belongs to your browser. Check browser/CDN caching and timezone differences when the times seem inconsistent.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Match the error log at the same time</span><br />
At 12:40:54 UTC, our error log reported an open() failure for the expected file under /www/wwwroot/adminslab.com, with error 2: No such file or directory.<br />
This supported a missing-file diagnosis for this static test URL. We created only that temporary file at the expected root path and repeated the request. At 12:41:34 UTC the response was HTTP 200 with the intended test content, and the access log recorded 200.<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=296" target="_blank" title="">log-troubleshooting-20261014.jpg</a> (Size: 129.35 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of our synthetic request and matching log entries, not a screenshot. Unrelated visitor entries are excluded.</span><br />
<br />
We removed the fixture after verification. This was a lab demonstration, not a recommendation to create an empty file whenever a route returns 404. An application route may instead require the right document root or rewrite rules. For WordPress pretty URLs, see <a href="https://adminsforum.com/Thread-guide-fix-wordpress-permalink-404s-in-aapanel-free-edition-nginx" target="_blank" rel="noopener" class="mycode_url">the permalink 404 guide</a>.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Read common messages as clues</span><ul class="mycode_list"><li>No such file or directory: inspect the exact path, document root, deployment contents or upstream socket named by the message. A missing static file and a missing FPM socket have different fixes.<br />
</li>
<li>Permission denied: identify the object, runtime user and required access. Review ownership, parent-directory traversal and applicable security controls; do not recursively apply chmod 777.<br />
</li>
<li>Connection refused while connecting to upstream: inspect the configured upstream and whether the intended service is listening. Check its own error/startup logs before restarting it.<br />
</li>
<li>Upstream timed out: investigate the upstream's workload and dependencies. Raising a timeout without finding the delay can keep resources occupied longer.<br />
</li>
<li>PHP fatal/uncaught exception: locate the application stack and matching runtime log, then review the relevant code, dependency and recent change. A 500 is not always a PHP syntax error.<br />
</li>
</ul>
These are example interpretations. Use the complete message and request context. For 502 troubleshooting, correlate web-server and upstream evidence; do not use HTTP curl against a FastCGI socket as though it were an HTTP endpoint.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Know the difference between PHP-FPM and application logs</span><br />
The lab FPM master error_log was /www/server/php/85/var/log/php-fpm.log. This captures FPM service diagnostics; it is not a guarantee that every PHP application's warning appears there.<br />
A private FPM settings probe confirmed PHP loaded /www/server/php/85/etc/php.ini, with log_errors enabled, display_errors off and no explicit PHP error_log path. An empty PHP error_log value delegates the destination to the SAPI. Inspect the effective runtime, web-server FastCGI error output and application logger rather than assuming a file name.<br />
The CLI runtime can load a different ini file. Never publish phpinfo or stack traces on an unprotected website just to discover a setting. Our probe was outside the web root, used through the private socket and removed afterwards.<br />
PHP slow logs answer a different question: where a long-running worker was executing. Follow <a href="https://adminsforum.com/Thread-guide-find-slow-php-requests-in-aapanel-with-php-fpm-slow-logs" target="_blank" rel="noopener" class="mycode_url">the tested slow-log guide</a> for that workflow.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Check the application logger</span><br />
Frameworks and CMS plugins may capture exceptions in their own log location or service journal. Check the application's documented logging configuration and make sure the runtime can write to its intended private directory.<br />
For WordPress, official debug logging supports a chosen file path while display can remain disabled. Use a staging copy and backup before temporary debug changes; do not expose wp-content/debug.log publicly or leave development debugging enabled on a live site. This article did not alter WordPress debug settings.<br />
For a database-related exception, examine the corresponding database evidence and query. A web-server access log usually cannot tell you which SQL statement was slow or failed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Search bounded log output through SSH</span><br />
If the panel cannot reach an older entry, use the actual private log paths:<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>tail -n 100 /www/wwwlogs/example.com.error.log
grep -F -- '/problem-path' /www/wwwlogs/example.com.log
tail -F /www/wwwlogs/example.com.error.log</code></div></div>Replace example.com and the path with your own. tail -n shows recent lines; grep -F matches literal text; tail -F follows a log and can handle its replacement during rotation. Stop live following with Ctrl+C. For very large files, restrict the time/file range instead of dumping everything.<br />
A rotated log may contain yesterday's evidence. Read the appropriate archive with supported tools; do not clear or delete logs merely to make the view shorter. Preserve useful evidence and maintain deliberate retention.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. When no matching entry appears</span><br />
Confirm that the request reached the expected server and virtual host. Check DNS, CDN responses, HTTPS/redirect paths, selected website, enabled logging and rotation. Some locations intentionally suppress logging; absence of an entry does not prove the request never happened.<br />
If the web server cannot start, a per-site access log may be irrelevant. Inspect the server's startup/configuration error and validate the actual panel-managed configuration. For our Nginx installation the syntax check 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/server/nginx/sbin/nginx -t</code></div></div>Do not reload an invalid configuration. Retain a backup before a repair and check normal pages after applying it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">10. Verify the fix and ask for help with safe evidence</span><br />
Change one identified cause, repeat the same request, inspect the new status and content, and confirm the matching fresh log entry. Check a normal page too. An old error remaining in the log does not mean the fix failed: compare timestamps.<br />
When posting support details, include versions, affected path, time/timezone, status, last change and a small redacted matching excerpt. Remove credentials, cookies, tokens, private email addresses, visitor IPs and unrelated user data. Logs are evidence to interpret, not instructions to execute.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References</span>: <a href="https://nginx.org/en/docs/beginners_guide.html" target="_blank" rel="noopener" class="mycode_url">Nginx beginner's guide</a>, <a href="https://www.php.net/manual/en/errorfunc.configuration.php" target="_blank" rel="noopener" class="mycode_url">PHP error logging configuration</a> and <a href="https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/" target="_blank" rel="noopener" class="mycode_url">WordPress debugging documentation</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Start website troubleshooting by recording the failing request, its time and its HTTP status. Then match that request with the website's access log, error log and application evidence. This guide shows a real missing-file diagnosis in aaPanel and explains where to look for other failures.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5 and Nginx 1.30.5. We inspected the native website log viewer, generated one missing-file request, matched its access/error entries and verified a temporary file corrected that request. The test file was removed afterwards. Other error types below are interpretation examples, not deliberately triggered failures.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Write down the symptom before changing anything</span><br />
Record the exact hostname and path, time with timezone, HTTP status, request method, whether all pages fail or one route fails, and the last relevant change. Distinguish a browser connection failure from an HTTP response delivered by a server.<br />
A request may pass through Cloudflare/CDN, Nginx, PHP-FPM and the application. A status code alone does not identify which layer caused it. Avoid restarting every service before collecting the relevant evidence.<br />
For a harmless GET endpoint you control:<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 -sS --max-time 15 -D - -o /dev/null https://example.com/problem-path</code></div></div>Replace the hostname and path. Keep certificate verification enabled. This Linux example shows headers and discards the body; on Windows use curl.exe and NUL. Separately inspect the response content, because HTTP 200 can still contain an application error.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Open the website's native aaPanel logs</span><br />
In our current interface:<ul class="mycode_list"><li>Open Website and select PHP Project.<br />
</li>
<li>Find the exact site row and click Log.<br />
</li>
<li>The Site modification window provides Access log and Error log views, alongside Response log and Log Security Analysis.<br />
</li>
<li>Use Refresh to retrieve current information. The access view offers recent 50, 100, 500 or All lines and displays the source log path.<br />
</li>
</ul>
Labels differ between versions and project types. The main left-menu Logs section is a separate panel-wide entry; do not assume its administrative log is the website's application log. Node/Python projects have their own runtime logging to inspect as well.<br />
Our website access log was /www/wwwlogs/adminslab.com.log; its error log was /www/wwwlogs/adminslab.com.error.log. These are lab paths, not universal names. Confirm the selected website and effective Nginx access_log/error_log directives if the viewer shows no matching entries.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Locate the request in the access log</span><br />
The access log tells you that the server handled a request and records configured fields such as method, path, status and byte count. Our matching entry contained:<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>[14/Oct/2026:12:40:54 +0000]
GET /af-log-troubleshooting-missing-20261014.txt HTTP/2.0
404</code></div></div>The full entry used loopback client 127.0.0.1 because our request came from the server itself. For proxied visitor traffic, an address in a log may identify the proxy unless trusted real-IP handling is configured. Do not treat arbitrary forwarded headers as verified visitor identity.<br />
Match the time, hostname, path and method rather than assuming the latest error belongs to your browser. Check browser/CDN caching and timezone differences when the times seem inconsistent.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Match the error log at the same time</span><br />
At 12:40:54 UTC, our error log reported an open() failure for the expected file under /www/wwwroot/adminslab.com, with error 2: No such file or directory.<br />
This supported a missing-file diagnosis for this static test URL. We created only that temporary file at the expected root path and repeated the request. At 12:41:34 UTC the response was HTTP 200 with the intended test content, and the access log recorded 200.<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=296" target="_blank" title="">log-troubleshooting-20261014.jpg</a> (Size: 129.35 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of our synthetic request and matching log entries, not a screenshot. Unrelated visitor entries are excluded.</span><br />
<br />
We removed the fixture after verification. This was a lab demonstration, not a recommendation to create an empty file whenever a route returns 404. An application route may instead require the right document root or rewrite rules. For WordPress pretty URLs, see <a href="https://adminsforum.com/Thread-guide-fix-wordpress-permalink-404s-in-aapanel-free-edition-nginx" target="_blank" rel="noopener" class="mycode_url">the permalink 404 guide</a>.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Read common messages as clues</span><ul class="mycode_list"><li>No such file or directory: inspect the exact path, document root, deployment contents or upstream socket named by the message. A missing static file and a missing FPM socket have different fixes.<br />
</li>
<li>Permission denied: identify the object, runtime user and required access. Review ownership, parent-directory traversal and applicable security controls; do not recursively apply chmod 777.<br />
</li>
<li>Connection refused while connecting to upstream: inspect the configured upstream and whether the intended service is listening. Check its own error/startup logs before restarting it.<br />
</li>
<li>Upstream timed out: investigate the upstream's workload and dependencies. Raising a timeout without finding the delay can keep resources occupied longer.<br />
</li>
<li>PHP fatal/uncaught exception: locate the application stack and matching runtime log, then review the relevant code, dependency and recent change. A 500 is not always a PHP syntax error.<br />
</li>
</ul>
These are example interpretations. Use the complete message and request context. For 502 troubleshooting, correlate web-server and upstream evidence; do not use HTTP curl against a FastCGI socket as though it were an HTTP endpoint.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Know the difference between PHP-FPM and application logs</span><br />
The lab FPM master error_log was /www/server/php/85/var/log/php-fpm.log. This captures FPM service diagnostics; it is not a guarantee that every PHP application's warning appears there.<br />
A private FPM settings probe confirmed PHP loaded /www/server/php/85/etc/php.ini, with log_errors enabled, display_errors off and no explicit PHP error_log path. An empty PHP error_log value delegates the destination to the SAPI. Inspect the effective runtime, web-server FastCGI error output and application logger rather than assuming a file name.<br />
The CLI runtime can load a different ini file. Never publish phpinfo or stack traces on an unprotected website just to discover a setting. Our probe was outside the web root, used through the private socket and removed afterwards.<br />
PHP slow logs answer a different question: where a long-running worker was executing. Follow <a href="https://adminsforum.com/Thread-guide-find-slow-php-requests-in-aapanel-with-php-fpm-slow-logs" target="_blank" rel="noopener" class="mycode_url">the tested slow-log guide</a> for that workflow.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Check the application logger</span><br />
Frameworks and CMS plugins may capture exceptions in their own log location or service journal. Check the application's documented logging configuration and make sure the runtime can write to its intended private directory.<br />
For WordPress, official debug logging supports a chosen file path while display can remain disabled. Use a staging copy and backup before temporary debug changes; do not expose wp-content/debug.log publicly or leave development debugging enabled on a live site. This article did not alter WordPress debug settings.<br />
For a database-related exception, examine the corresponding database evidence and query. A web-server access log usually cannot tell you which SQL statement was slow or failed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Search bounded log output through SSH</span><br />
If the panel cannot reach an older entry, use the actual private log paths:<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>tail -n 100 /www/wwwlogs/example.com.error.log
grep -F -- '/problem-path' /www/wwwlogs/example.com.log
tail -F /www/wwwlogs/example.com.error.log</code></div></div>Replace example.com and the path with your own. tail -n shows recent lines; grep -F matches literal text; tail -F follows a log and can handle its replacement during rotation. Stop live following with Ctrl+C. For very large files, restrict the time/file range instead of dumping everything.<br />
A rotated log may contain yesterday's evidence. Read the appropriate archive with supported tools; do not clear or delete logs merely to make the view shorter. Preserve useful evidence and maintain deliberate retention.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. When no matching entry appears</span><br />
Confirm that the request reached the expected server and virtual host. Check DNS, CDN responses, HTTPS/redirect paths, selected website, enabled logging and rotation. Some locations intentionally suppress logging; absence of an entry does not prove the request never happened.<br />
If the web server cannot start, a per-site access log may be irrelevant. Inspect the server's startup/configuration error and validate the actual panel-managed configuration. For our Nginx installation the syntax check 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/server/nginx/sbin/nginx -t</code></div></div>Do not reload an invalid configuration. Retain a backup before a repair and check normal pages after applying it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">10. Verify the fix and ask for help with safe evidence</span><br />
Change one identified cause, repeat the same request, inspect the new status and content, and confirm the matching fresh log entry. Check a normal page too. An old error remaining in the log does not mean the fix failed: compare timestamps.<br />
When posting support details, include versions, affected path, time/timezone, status, last change and a small redacted matching excerpt. Remove credentials, cookies, tokens, private email addresses, visitor IPs and unrelated user data. Logs are evidence to interpret, not instructions to execute.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References</span>: <a href="https://nginx.org/en/docs/beginners_guide.html" target="_blank" rel="noopener" class="mycode_url">Nginx beginner's guide</a>, <a href="https://www.php.net/manual/en/errorfunc.configuration.php" target="_blank" rel="noopener" class="mycode_url">PHP error logging configuration</a> and <a href="https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/" target="_blank" rel="noopener" class="mycode_url">WordPress debugging documentation</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Find Slow PHP Requests in aaPanel with PHP-FPM Slow Logs]]></title>
			<link>https://adminsforum.com/Thread-guide-find-slow-php-requests-in-aapanel-with-php-fpm-slow-logs</link>
			<pubDate>Wed, 14 Oct 2026 20:35:09 +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-find-slow-php-requests-in-aapanel-with-php-fpm-slow-logs</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">PHP-FPM's slow log can show where a PHP request was executing after it crossed a time threshold. Use that evidence to investigate application work before raising worker counts or timeouts.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5 and PHP 8.5.11. We ran one synthetic four-second request through the private PHP-FPM Unix socket. It generated a slow-log trace, after which we restored the original pool settings and removed the test script. No production website was changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify the PHP version and pool</span><br />
Check the website's selected PHP version in aaPanel. Inspect its Nginx PHP handler if you administer the server. Our site used /tmp/php-cgi-85.sock and pool www. The default command-line PHP binary may load a different configuration and cannot prove which pool serves the site.<br />
The lab pool configuration was /www/server/php/85/etc/php-fpm.conf. Version numbers and paths vary: discover the actual file before editing. Read <a href="https://adminsforum.com/Thread-guide-tune-php-fpm-workers-in-aapanel-with-measured-memory-limits" target="_blank" rel="noopener" class="mycode_url">the PHP-FPM worker guide</a> for the distinction between worker limits and request cost.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Check existing logging settings</span><br />
Our original configuration included:<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>request_slowlog_timeout = 30
slowlog = var/log/slow.log
request_terminate_timeout = 100</code></div></div>A request below the slow-log threshold will not generate a slow trace simply because a visitor considers it slow. The relative log path must be interpreted in the running FPM installation; do not assume it is inside the website directory. We used an explicit absolute path for the experiment to avoid that ambiguity.<br />
The slow-log threshold requests a diagnostic backtrace. The termination timeout is a separate setting that can kill a long-running worker request; we left it unchanged. Raising either is not a cure for slow SQL or an unavailable API.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Back up and select a diagnostic threshold</span><br />
Keep an original copy of the pool configuration and a working SSH recovery route. On a shared PHP version, the change can affect several websites. Choose a threshold suited to the symptom and a limited observation window, rather than permanently logging every ordinary request.<br />
For our isolated lab example we temporarily used:<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>request_slowlog_timeout = 2
slowlog = /www/server/php/85/var/log/af-slowlog-lab-20261014.log</code></div></div>Keep logs outside publicly served directories and restrict access. Paths and stack traces can reveal implementation details. Use your own private log path and ensure the FPM master can open it; avoid broad permission changes such as chmod 777.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Validate before reloading</span><br />
On this lab installation:<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/php/85/sbin/php-fpm -t
/etc/init.d/php-fpm-85 reload</code></div></div>The configuration test passed. Reload only after success and inspect application health afterwards. Use the service names and binary for your selected version. A valid configuration does not guarantee the diagnostic backtrace will succeed on every container or host; inspect FPM errors if tracing is restricted.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Generate one controlled slow request</span><br />
Our test script contained only:<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>&lt;?php
sleep(4);
echo "AdminsForum slow-log lab completed&#92;n";</code></div></div>It was stored outside the website root and executed through cgi-fcgi over /tmp/php-cgi-85.sock using a local administrator session. The request had a client timeout and completed in about 4.004 seconds. We did not publish a slow test URL, start a traffic loop or trigger real customer actions.<br />
If reproducing this lesson, use an isolated lab and its actual private socket. Do not upload a deliberate delay script to a public production website. For a real symptom, collect traces from a bounded legitimate test workflow instead.<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=295" target="_blank" title="">php-slowlog-20261014.jpg</a> (Size: 111.23 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original lab result, not a terminal screenshot. The image abbreviates the private diagnostic path.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Read the trace</span><br />
The log named pool www and the test script, then identified sleep() on line 1. That is consistent with the intentional waiting operation. It confirms that slow logging worked for this request.<br />
A trace is a snapshot of execution, not a complete timeline or a ranked profiler. A function visible in one sample is not automatically the root cause. Compare several relevant traces and correlate the request time with application, database and web-server evidence.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Follow the evidence to the right component</span><ul class="mycode_list"><li>A database call in the trace: identify the corresponding query and inspect its plan and database timing. Follow <a href="https://adminsforum.com/Thread-guide-tune-mariadb-queries-in-aapanel-with-explain-and-index-tests" target="_blank" rel="noopener" class="mycode_url">the EXPLAIN and index test guide</a>.<br />
</li>
<li>An HTTP/API operation: inspect destination latency, connection errors and application timeout handling. Do not repeatedly retry a side-effecting request just to gather samples.<br />
</li>
<li>Repeated application functions: use a suitable application profiler in a controlled environment and compare expensive paths. The slow log alone does not quantify every function's cost.<br />
</li>
<li>Many occupied workers: combine traces with CPU, memory and FPM queue observations. Queueing before a request starts running in a worker may not be explained by its eventual slow trace.<br />
</li>
</ul>
A full-page cache HIT may bypass PHP entirely. Use the cache verification guide to distinguish that path from a PHP request. Do not infer that logging is broken solely because cached pages produce no PHP trace.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Restore and verify</span><br />
Our test restored the original configuration byte for byte, validated it and reloaded the service. We removed the temporary script and retained the private trace and backup for documentation. The original 30-second threshold and existing log path were restored; the termination limit was unchanged.<br />
After your diagnostic window, restore the previous settings or choose a deliberate long-term policy with log retention and disk monitoring. Keep raw traces private and redact paths and user-related details before asking for public help.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Retest the actual fix</span><br />
Change one identified cause, repeat the same meaningful workflow and compare response time, errors and resource use. Keep a rollback plan. Disabling diagnostics, adding workers or increasing a timeout without evidence does not establish that the cause was fixed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://www.php.net/manual/en/install.fpm.configuration.php" target="_blank" rel="noopener" class="mycode_url">Official PHP-FPM configuration documentation</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">PHP-FPM's slow log can show where a PHP request was executing after it crossed a time threshold. Use that evidence to investigate application work before raising worker counts or timeouts.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5 and PHP 8.5.11. We ran one synthetic four-second request through the private PHP-FPM Unix socket. It generated a slow-log trace, after which we restored the original pool settings and removed the test script. No production website was changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify the PHP version and pool</span><br />
Check the website's selected PHP version in aaPanel. Inspect its Nginx PHP handler if you administer the server. Our site used /tmp/php-cgi-85.sock and pool www. The default command-line PHP binary may load a different configuration and cannot prove which pool serves the site.<br />
The lab pool configuration was /www/server/php/85/etc/php-fpm.conf. Version numbers and paths vary: discover the actual file before editing. Read <a href="https://adminsforum.com/Thread-guide-tune-php-fpm-workers-in-aapanel-with-measured-memory-limits" target="_blank" rel="noopener" class="mycode_url">the PHP-FPM worker guide</a> for the distinction between worker limits and request cost.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Check existing logging settings</span><br />
Our original configuration included:<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>request_slowlog_timeout = 30
slowlog = var/log/slow.log
request_terminate_timeout = 100</code></div></div>A request below the slow-log threshold will not generate a slow trace simply because a visitor considers it slow. The relative log path must be interpreted in the running FPM installation; do not assume it is inside the website directory. We used an explicit absolute path for the experiment to avoid that ambiguity.<br />
The slow-log threshold requests a diagnostic backtrace. The termination timeout is a separate setting that can kill a long-running worker request; we left it unchanged. Raising either is not a cure for slow SQL or an unavailable API.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Back up and select a diagnostic threshold</span><br />
Keep an original copy of the pool configuration and a working SSH recovery route. On a shared PHP version, the change can affect several websites. Choose a threshold suited to the symptom and a limited observation window, rather than permanently logging every ordinary request.<br />
For our isolated lab example we temporarily used:<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>request_slowlog_timeout = 2
slowlog = /www/server/php/85/var/log/af-slowlog-lab-20261014.log</code></div></div>Keep logs outside publicly served directories and restrict access. Paths and stack traces can reveal implementation details. Use your own private log path and ensure the FPM master can open it; avoid broad permission changes such as chmod 777.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Validate before reloading</span><br />
On this lab installation:<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/php/85/sbin/php-fpm -t
/etc/init.d/php-fpm-85 reload</code></div></div>The configuration test passed. Reload only after success and inspect application health afterwards. Use the service names and binary for your selected version. A valid configuration does not guarantee the diagnostic backtrace will succeed on every container or host; inspect FPM errors if tracing is restricted.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Generate one controlled slow request</span><br />
Our test script contained only:<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>&lt;?php
sleep(4);
echo "AdminsForum slow-log lab completed&#92;n";</code></div></div>It was stored outside the website root and executed through cgi-fcgi over /tmp/php-cgi-85.sock using a local administrator session. The request had a client timeout and completed in about 4.004 seconds. We did not publish a slow test URL, start a traffic loop or trigger real customer actions.<br />
If reproducing this lesson, use an isolated lab and its actual private socket. Do not upload a deliberate delay script to a public production website. For a real symptom, collect traces from a bounded legitimate test workflow instead.<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=295" target="_blank" title="">php-slowlog-20261014.jpg</a> (Size: 111.23 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original lab result, not a terminal screenshot. The image abbreviates the private diagnostic path.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Read the trace</span><br />
The log named pool www and the test script, then identified sleep() on line 1. That is consistent with the intentional waiting operation. It confirms that slow logging worked for this request.<br />
A trace is a snapshot of execution, not a complete timeline or a ranked profiler. A function visible in one sample is not automatically the root cause. Compare several relevant traces and correlate the request time with application, database and web-server evidence.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Follow the evidence to the right component</span><ul class="mycode_list"><li>A database call in the trace: identify the corresponding query and inspect its plan and database timing. Follow <a href="https://adminsforum.com/Thread-guide-tune-mariadb-queries-in-aapanel-with-explain-and-index-tests" target="_blank" rel="noopener" class="mycode_url">the EXPLAIN and index test guide</a>.<br />
</li>
<li>An HTTP/API operation: inspect destination latency, connection errors and application timeout handling. Do not repeatedly retry a side-effecting request just to gather samples.<br />
</li>
<li>Repeated application functions: use a suitable application profiler in a controlled environment and compare expensive paths. The slow log alone does not quantify every function's cost.<br />
</li>
<li>Many occupied workers: combine traces with CPU, memory and FPM queue observations. Queueing before a request starts running in a worker may not be explained by its eventual slow trace.<br />
</li>
</ul>
A full-page cache HIT may bypass PHP entirely. Use the cache verification guide to distinguish that path from a PHP request. Do not infer that logging is broken solely because cached pages produce no PHP trace.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Restore and verify</span><br />
Our test restored the original configuration byte for byte, validated it and reloaded the service. We removed the temporary script and retained the private trace and backup for documentation. The original 30-second threshold and existing log path were restored; the termination limit was unchanged.<br />
After your diagnostic window, restore the previous settings or choose a deliberate long-term policy with log retention and disk monitoring. Keep raw traces private and redact paths and user-related details before asking for public help.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Retest the actual fix</span><br />
Change one identified cause, repeat the same meaningful workflow and compare response time, errors and resource use. Keep a rollback plan. Disabling diagnostics, adding workers or increasing a timeout without evidence does not establish that the cause was fixed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://www.php.net/manual/en/install.fpm.configuration.php" target="_blank" rel="noopener" class="mycode_url">Official PHP-FPM configuration documentation</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Verify WordPress FastCGI Cache Hits and Bypass Rules in aaPanel]]></title>
			<link>https://adminsforum.com/Thread-guide-verify-wordpress-fastcgi-cache-hits-and-bypass-rules-in-aapanel</link>
			<pubDate>Wed, 14 Oct 2026 20:24: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-verify-wordpress-fastcgi-cache-hits-and-bypass-rules-in-aapanel</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">FastCGI page caching can let Nginx answer an anonymous request without running PHP. Verify both cache hits and exclusions before relying on it: private or personalized responses must not be served from a shared anonymous cache.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Scope</span>: We tested an existing WordPress FastCGI cache in aaPanel Free 8.0.7 with Nginx and PHP 8.5. This guide verifies the existing setup; it does not claim we installed a new cache or fully audited every authenticated workflow.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify the cache layer</span><br />
Page caching stores a rendered HTTP response. OPcache stores compiled PHP bytecode; Redis object caching stores application objects. They solve different problems. A page-cache HIT may avoid PHP, so it cannot be used to measure PHP or SQL tuning alone.<br />
Inspect the website's Nginx configuration and included PHP handler. Our WordPress site included enable-php-85-wpfastcgi.conf and used a WORDPRESS FastCGI cache zone.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Read the rules before testing</span><br />
Our existing rules bypassed POST requests, nonempty query strings, WordPress administrative/login-related paths and cookies matching WordPress login or password-protected content. These rules must be checked against the actual applications on the site.<br />
The handler used both:<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>fastcgi_cache_bypass &#36;skip_cache;
fastcgi_no_cache &#36;skip_cache;</code></div></div>The first controls whether an existing cached response is used; the second controls whether the upstream response is stored. A correct private-response policy needs both aspects considered. Do not copy an incomplete location block or override application Set-Cookie behavior blindly.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Inspect cache headers</span><br />
Our configuration exposed Nginx-Cache with the upstream cache status. Your site may use another header or expose none.<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 -sS -D - -o /dev/null https://example.com/</code></div></div>Replace the hostname. Read the HTTP status and cache header. HIT means a stored response was served. MISS means the cache did not supply an entry; an eligible response may subsequently be stored. BYPASS means the rules skipped reading the cache. Absence of a header does not prove caching is disabled.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Repeat an anonymous request</span><br />
We sent five sequential requests to the same lab homepage over loopback HTTPS with certificate validation. All five returned HTTP 200 and HIT; median time to first byte was approximately 58ms.<br />
The page was already cached. We did not claim to demonstrate a fresh MISS-to-HIT transition, clear the whole cache or measure maximum throughput. Five requests are a small diagnostic sample.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Check query and cookie exclusions</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>curl -sS -D - -o /dev/null 'https://example.com/?cache_check=1'
curl -sS -D - -o /dev/null &#92;
  -H 'Cookie: wordpress_logged_in_lab=synthetic-test' https://example.com/
curl -sS -D - -o /dev/null https://example.com/wp-login.php</code></div></div>The query-string request, synthetic login-cookie request and login page each returned HTTP 200 and BYPASS in our lab. The synthetic cookie contains no real login token; it tests the configured cookie-name rule only. It does not authenticate a user or prove actual account privacy end to end.<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=293" target="_blank" title="">cache-performance-20261014.jpg</a> (Size: 105.63 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original checks, not a screenshot.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Test actual personalized workflows before rollout</span><br />
With a controlled test account, verify that logged-in pages, shopping carts, checkout, account settings and password-protected content are excluded. Test two separate sessions and inspect rendered content, not just a fast response. Review authorization, cookies, cache keys and application-specific paths.<br />
Our short check did not perform these authenticated workflows. Treat them as required verification before enabling shared page caching for a real personalized application.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Verify freshness and controlled purging</span><br />
After updating a public test page, confirm when anonymous visitors receive the new content. Purge the relevant cache entry using your supported administration workflow and verify the result. Do not expose an unrestricted public purge endpoint.<br />
Our existing configuration restricted its purge location to loopback. We did not weaken that restriction or perform a global purge for this guide. Cache lifetime and invalidation should match how frequently your pages change.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Troubleshoot a persistent BYPASS or stale page</span><br />
Check whether a query string, cookie, request method or path matches an exclusion. Inspect the effective Nginx configuration and logs. If a public page bypasses unexpectedly, identify the cause rather than deleting all exclusions.<br />
For stale content, check the correct hostname, cache key, purge method and any additional CDN or browser cache. A browser refresh alone may leave server caches untouched.<br />
Back up before changing rules, validate Nginx syntax, reload and repeat both anonymous and private-response tests. Restore the original rules if personalized content is cached or application behavior changes.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache_bypass" target="_blank" rel="noopener" class="mycode_url">Official Nginx FastCGI cache controls</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">FastCGI page caching can let Nginx answer an anonymous request without running PHP. Verify both cache hits and exclusions before relying on it: private or personalized responses must not be served from a shared anonymous cache.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Scope</span>: We tested an existing WordPress FastCGI cache in aaPanel Free 8.0.7 with Nginx and PHP 8.5. This guide verifies the existing setup; it does not claim we installed a new cache or fully audited every authenticated workflow.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify the cache layer</span><br />
Page caching stores a rendered HTTP response. OPcache stores compiled PHP bytecode; Redis object caching stores application objects. They solve different problems. A page-cache HIT may avoid PHP, so it cannot be used to measure PHP or SQL tuning alone.<br />
Inspect the website's Nginx configuration and included PHP handler. Our WordPress site included enable-php-85-wpfastcgi.conf and used a WORDPRESS FastCGI cache zone.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Read the rules before testing</span><br />
Our existing rules bypassed POST requests, nonempty query strings, WordPress administrative/login-related paths and cookies matching WordPress login or password-protected content. These rules must be checked against the actual applications on the site.<br />
The handler used both:<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>fastcgi_cache_bypass &#36;skip_cache;
fastcgi_no_cache &#36;skip_cache;</code></div></div>The first controls whether an existing cached response is used; the second controls whether the upstream response is stored. A correct private-response policy needs both aspects considered. Do not copy an incomplete location block or override application Set-Cookie behavior blindly.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Inspect cache headers</span><br />
Our configuration exposed Nginx-Cache with the upstream cache status. Your site may use another header or expose none.<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 -sS -D - -o /dev/null https://example.com/</code></div></div>Replace the hostname. Read the HTTP status and cache header. HIT means a stored response was served. MISS means the cache did not supply an entry; an eligible response may subsequently be stored. BYPASS means the rules skipped reading the cache. Absence of a header does not prove caching is disabled.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Repeat an anonymous request</span><br />
We sent five sequential requests to the same lab homepage over loopback HTTPS with certificate validation. All five returned HTTP 200 and HIT; median time to first byte was approximately 58ms.<br />
The page was already cached. We did not claim to demonstrate a fresh MISS-to-HIT transition, clear the whole cache or measure maximum throughput. Five requests are a small diagnostic sample.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Check query and cookie exclusions</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>curl -sS -D - -o /dev/null 'https://example.com/?cache_check=1'
curl -sS -D - -o /dev/null &#92;
  -H 'Cookie: wordpress_logged_in_lab=synthetic-test' https://example.com/
curl -sS -D - -o /dev/null https://example.com/wp-login.php</code></div></div>The query-string request, synthetic login-cookie request and login page each returned HTTP 200 and BYPASS in our lab. The synthetic cookie contains no real login token; it tests the configured cookie-name rule only. It does not authenticate a user or prove actual account privacy end to end.<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=293" target="_blank" title="">cache-performance-20261014.jpg</a> (Size: 105.63 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original checks, not a screenshot.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Test actual personalized workflows before rollout</span><br />
With a controlled test account, verify that logged-in pages, shopping carts, checkout, account settings and password-protected content are excluded. Test two separate sessions and inspect rendered content, not just a fast response. Review authorization, cookies, cache keys and application-specific paths.<br />
Our short check did not perform these authenticated workflows. Treat them as required verification before enabling shared page caching for a real personalized application.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Verify freshness and controlled purging</span><br />
After updating a public test page, confirm when anonymous visitors receive the new content. Purge the relevant cache entry using your supported administration workflow and verify the result. Do not expose an unrestricted public purge endpoint.<br />
Our existing configuration restricted its purge location to loopback. We did not weaken that restriction or perform a global purge for this guide. Cache lifetime and invalidation should match how frequently your pages change.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Troubleshoot a persistent BYPASS or stale page</span><br />
Check whether a query string, cookie, request method or path matches an exclusion. Inspect the effective Nginx configuration and logs. If a public page bypasses unexpectedly, identify the cause rather than deleting all exclusions.<br />
For stale content, check the correct hostname, cache key, purge method and any additional CDN or browser cache. A browser refresh alone may leave server caches untouched.<br />
Back up before changing rules, validate Nginx syntax, reload and repeat both anonymous and private-response tests. Restore the original rules if personalized content is cached or application behavior changes.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache_bypass" target="_blank" rel="noopener" class="mycode_url">Official Nginx FastCGI cache controls</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Run a Controlled WordPress Load Test on an aaPanel VPS]]></title>
			<link>https://adminsforum.com/Thread-guide-run-a-controlled-wordpress-load-test-on-an-aapanel-vps</link>
			<pubDate>Wed, 14 Oct 2026 20:22:42 +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-run-a-controlled-wordpress-load-test-on-an-aapanel-vps</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">A controlled load test helps compare one workload at several concurrency levels. It does not prove how many visitors an entire website can support. This guide records a bounded external-client test and explains the measurements still needed for a production decision.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Environment</span>: two-CPU shared Ubuntu VPS, aaPanel Free 8.0.7, Nginx, WordPress and PHP 8.5. The tested FPM pool had a maximum of eight children and OPcache enabled. Existing FastCGI cache rules bypassed query-string requests. The generator ran on a separate Windows machine.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Choose a safe target and scope</span><br />
Use a lab server you control. Choose a harmless GET endpoint and a finite request count. Exclude actions that create accounts, orders, mail or database writes. Agree a maintenance window for production testing and monitor other services sharing the machine.<br />
Our target was the WordPress homepage with a unique test query on each request. We verified the query rule returned Nginx-Cache: BYPASS before the run. This measures an uncached homepage path, not checkout, search, login or an entire browsing session.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Record the baseline and configuration</span><br />
Write down PHP version, FPM worker limits, cache states, database version and application version/plugins. Keep those constant between phases. Record server memory, swap and CPU before testing; arrange an interval resource sampler if you need to locate saturation.<br />
This run did not collect a simultaneous server resource trace. We therefore report response results without claiming whether PHP, CPU or SQL limited throughput.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Set explicit limits and stop conditions</span><br />
Our client used 40 requests per phase at concurrency 2, then 4, then 8. Each curl request had a 15-second maximum time, used normal HTTPS certificate validation and performed no retries. Later phases would stop if any request failed or the sample p95 time to first byte exceeded five seconds.<br />
A short request count bounds the total work but can miss sustained bottlenecks. Avoid unbounded loops and high concurrency simply to generate a dramatic result. Watch availability and stop manually if important services degrade.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand the client measurements</span><br />
A single request example 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>curl.exe -sS --max-time 15 -o NUL &#92;
  -w "%{http_code} %{time_starttransfer} %{time_total}" &#92;
  "https://example.com/?load_test=unique_value"</code></div></div>This is a Windows example: NUL discards the body. Use /dev/null on Linux. Replace the hostname and make each test query unique if your verified rules use query strings to bypass caching. Do not disable certificate checks.<br />
Time to first byte includes client-side connection and network effects as well as server waiting. Total time includes body transfer. An HTTP 200 alone does not prove the content is correct; separately inspect a sample response for application errors.<br />
We used a bounded client worker pool to run the finite requests concurrently, waited for each phase to complete, then calculated its results. These are closed-loop tests: workers submit another request after the previous one finishes, rather than maintaining a fixed independent arrival rate.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Read the actual results</span><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=294" target="_blank" title="">load-performance-20261014.jpg</a> (Size: 124.63 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original client test, not a screenshot.</span><br />
<ul class="mycode_list"><li>Concurrency 2: 40/40 HTTP 200; median TTFB 295ms; sample p95 334ms; phase elapsed 8.46 seconds; about 4.73 completed requests/second.<br />
</li>
<li>Concurrency 4: 40/40 HTTP 200; median TTFB 334ms; sample p95 431ms; phase elapsed 4.91 seconds; about 8.15 completed requests/second.<br />
</li>
<li>Concurrency 8: 40/40 HTTP 200; median TTFB 377ms; sample p95 609ms; phase elapsed 2.88 seconds; about 13.87 completed requests/second.<br />
</li>
</ul>
All 120 requests completed with HTTP 200 and no client request failure. Concurrency increased the observed completion rate and latency. The phases were short, were not repeated in randomized order, and did not isolate cache-warmth or resource effects. Do not interpret the numbers as a guaranteed sustained rate or maximum visitors.<br />
The sample p95 is a nearest-rank estimate from forty observations, not a precise long-term tail metric. Network variation and shared-server activity can affect it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Add resource evidence before tuning</span><br />
For a repeat test, sample CPU utilization, iowait, free memory, swap activity, FPM queues and active database work throughout the phases. Private FPM status and slow logs can help locate queueing. Keep diagnostic endpoints private and redact logs before sharing.<br />
If latency rises with CPU saturation, more FPM workers may worsen contention. If queries dominate, inspect SQL plans. If the client itself is saturated, the generator may be the limit. These conclusions need measurements; this run does not establish them.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Repeat a representative workload</span><br />
Use the same test after one targeted change. Include realistic page mixes, authenticated workflows under controlled accounts, writes in a disposable environment and sustained runs appropriate to your service. Measure errors and content correctness alongside latency.<br />
Test anonymous cache HIT and uncached behavior separately. A fast cached homepage cannot prove that private or dynamic pages perform well. Never increase a pool limit solely because a cached benchmark looks good.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Preserve results and restore experimental changes</span><br />
Keep raw request outcomes, timing definitions and configuration snapshots. Remove only your own disposable fixtures when no longer needed. Retain rollback copies for settings changed during earlier tests. This load run itself changed no server configuration or website content.<br />
<br />
Use <a href="https://adminsforum.com/Thread-guide-measure-aapanel-website-performance-before-tuning-your-server" target="_blank" rel="noopener" class="mycode_url">the baseline guide</a>, the measured PHP-FPM pool guide and the database index test as a repeatable series. Present the workload and its limits whenever quoting performance numbers.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">A controlled load test helps compare one workload at several concurrency levels. It does not prove how many visitors an entire website can support. This guide records a bounded external-client test and explains the measurements still needed for a production decision.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Environment</span>: two-CPU shared Ubuntu VPS, aaPanel Free 8.0.7, Nginx, WordPress and PHP 8.5. The tested FPM pool had a maximum of eight children and OPcache enabled. Existing FastCGI cache rules bypassed query-string requests. The generator ran on a separate Windows machine.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Choose a safe target and scope</span><br />
Use a lab server you control. Choose a harmless GET endpoint and a finite request count. Exclude actions that create accounts, orders, mail or database writes. Agree a maintenance window for production testing and monitor other services sharing the machine.<br />
Our target was the WordPress homepage with a unique test query on each request. We verified the query rule returned Nginx-Cache: BYPASS before the run. This measures an uncached homepage path, not checkout, search, login or an entire browsing session.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Record the baseline and configuration</span><br />
Write down PHP version, FPM worker limits, cache states, database version and application version/plugins. Keep those constant between phases. Record server memory, swap and CPU before testing; arrange an interval resource sampler if you need to locate saturation.<br />
This run did not collect a simultaneous server resource trace. We therefore report response results without claiming whether PHP, CPU or SQL limited throughput.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Set explicit limits and stop conditions</span><br />
Our client used 40 requests per phase at concurrency 2, then 4, then 8. Each curl request had a 15-second maximum time, used normal HTTPS certificate validation and performed no retries. Later phases would stop if any request failed or the sample p95 time to first byte exceeded five seconds.<br />
A short request count bounds the total work but can miss sustained bottlenecks. Avoid unbounded loops and high concurrency simply to generate a dramatic result. Watch availability and stop manually if important services degrade.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand the client measurements</span><br />
A single request example 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>curl.exe -sS --max-time 15 -o NUL &#92;
  -w "%{http_code} %{time_starttransfer} %{time_total}" &#92;
  "https://example.com/?load_test=unique_value"</code></div></div>This is a Windows example: NUL discards the body. Use /dev/null on Linux. Replace the hostname and make each test query unique if your verified rules use query strings to bypass caching. Do not disable certificate checks.<br />
Time to first byte includes client-side connection and network effects as well as server waiting. Total time includes body transfer. An HTTP 200 alone does not prove the content is correct; separately inspect a sample response for application errors.<br />
We used a bounded client worker pool to run the finite requests concurrently, waited for each phase to complete, then calculated its results. These are closed-loop tests: workers submit another request after the previous one finishes, rather than maintaining a fixed independent arrival rate.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Read the actual results</span><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=294" target="_blank" title="">load-performance-20261014.jpg</a> (Size: 124.63 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original client test, not a screenshot.</span><br />
<ul class="mycode_list"><li>Concurrency 2: 40/40 HTTP 200; median TTFB 295ms; sample p95 334ms; phase elapsed 8.46 seconds; about 4.73 completed requests/second.<br />
</li>
<li>Concurrency 4: 40/40 HTTP 200; median TTFB 334ms; sample p95 431ms; phase elapsed 4.91 seconds; about 8.15 completed requests/second.<br />
</li>
<li>Concurrency 8: 40/40 HTTP 200; median TTFB 377ms; sample p95 609ms; phase elapsed 2.88 seconds; about 13.87 completed requests/second.<br />
</li>
</ul>
All 120 requests completed with HTTP 200 and no client request failure. Concurrency increased the observed completion rate and latency. The phases were short, were not repeated in randomized order, and did not isolate cache-warmth or resource effects. Do not interpret the numbers as a guaranteed sustained rate or maximum visitors.<br />
The sample p95 is a nearest-rank estimate from forty observations, not a precise long-term tail metric. Network variation and shared-server activity can affect it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Add resource evidence before tuning</span><br />
For a repeat test, sample CPU utilization, iowait, free memory, swap activity, FPM queues and active database work throughout the phases. Private FPM status and slow logs can help locate queueing. Keep diagnostic endpoints private and redact logs before sharing.<br />
If latency rises with CPU saturation, more FPM workers may worsen contention. If queries dominate, inspect SQL plans. If the client itself is saturated, the generator may be the limit. These conclusions need measurements; this run does not establish them.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Repeat a representative workload</span><br />
Use the same test after one targeted change. Include realistic page mixes, authenticated workflows under controlled accounts, writes in a disposable environment and sustained runs appropriate to your service. Measure errors and content correctness alongside latency.<br />
Test anonymous cache HIT and uncached behavior separately. A fast cached homepage cannot prove that private or dynamic pages perform well. Never increase a pool limit solely because a cached benchmark looks good.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Preserve results and restore experimental changes</span><br />
Keep raw request outcomes, timing definitions and configuration snapshots. Remove only your own disposable fixtures when no longer needed. Retain rollback copies for settings changed during earlier tests. This load run itself changed no server configuration or website content.<br />
<br />
Use <a href="https://adminsforum.com/Thread-guide-measure-aapanel-website-performance-before-tuning-your-server" target="_blank" rel="noopener" class="mycode_url">the baseline guide</a>, the measured PHP-FPM pool guide and the database index test as a repeatable series. Present the workload and its limits whenever quoting performance numbers.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Test Nginx Performance and Gzip Compression in aaPanel]]></title>
			<link>https://adminsforum.com/Thread-guide-test-nginx-performance-and-gzip-compression-in-aapanel</link>
			<pubDate>Wed, 14 Oct 2026 20:21: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-test-nginx-performance-and-gzip-compression-in-aapanel</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Nginx tuning should start with measurements, not a list of larger limits. This guide checks worker settings and gzip behavior, demonstrates a real compression tradeoff, and explains when to restore a change.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Nginx 1.30.5 and Ubuntu 22.04.5 on the shared two-CPU lab VPS. No production configuration was changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Inspect the active configuration</span><br />
Open App Store → Installed → Nginx → Setting and inspect its configuration. Paths and interface labels can differ by release. Our global file was /www/server/nginx/conf/nginx.conf; website configurations were included separately.<br />
A configuration dump can help identify includes:<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/nginx/sbin/nginx -T</code></div></div>Keep the output private because it can reveal hostnames, paths and configuration details. Identify which file owns the directive before editing it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Review workers and connection limits</span><br />
Our server already used worker_processes auto and worker_connections 51200. We did not increase either. More permitted connections do not mean more requests per second: upstream connections, open-file limits, PHP workers, database work and CPU also constrain throughput.<br />
Inspect actual worker count, active connections, system file limits and errors during representative traffic. Raise a limit only if it is the observed bottleneck and the server has resources to support it. Avoid treating a high worker_connections value as a visitor-capacity guarantee.<br />
Keepalive settings also need workload evidence. Shorter idle time can reduce held connections but increase connection setup; longer idle time can retain resources. We left the existing 60-second setting unchanged.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Back up before a compression experiment</span><br />
Make a private copy of the active file. Our baseline already had gzip enabled, a 1KiB minimum length, compression level 5 and gzip_vary on. Its gzip_types included text, JavaScript, CSS, JSON and several image types.<br />
Inspect response headers and actual transfer sizes before changing MIME types. Many image formats contain compressed data, but the effect of an additional gzip layer depends on the particular file.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Test text and image responses</span><br />
We created an original 24,500-byte text fixture in the lab website and used an existing 3,113-byte WordPress PNG. We requested gzip explicitly over loopback HTTPS with normal certificate validation.<br />
A basic header check 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>curl -sS -D - -o /dev/null &#92;
  -H 'Accept-Encoding: gzip' https://example.com/test.txt</code></div></div>Use your own hostname and a safe test file. Inspect Content-Encoding, Vary and HTTP status. To compare raw encoded bytes, save the response body without automatic decompression. curl --compressed instead requests supported compression and decompresses the body, so do not confuse decoded size with wire size.<br />
Our test compared the baseline against removing JPEG/GIF/PNG from gzip_types. It did not change the compression level or worker limits.<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=292" target="_blank" title="">nginx-performance-20261014.jpg</a> (Size: 116.44 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the experiment, not a screenshot.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Interpret the evidence</span><ul class="mycode_list"><li>Text: gzip was used in both phases; the body transferred was 156 bytes and decoded to 24,500 bytes.<br />
</li>
<li>PNG before: gzip body 2,487 bytes, decoded to 3,113 bytes.<br />
</li>
<li>PNG after: no gzip; body transferred 3,113 bytes.<br />
</li>
<li>All responses returned HTTP 200, and decoded content hashes matched.<br />
</li>
</ul>
Removing image compression increased transfer size for this particular small PNG. We did not measure CPU savings, so we did not claim the change improved performance. These body sizes exclude headers and transport overhead; one file does not represent an entire image library.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Validate, reload and restore when appropriate</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/nginx/sbin/nginx -t
/www/server/nginx/sbin/nginx -s reload</code></div></div>Validation passed for the experiment. Because we had no demonstrated overall benefit, we restored the original configuration, validated it again and reloaded Nginx. A successful reload is not an application test: check important pages, TLS, redirects, upstream errors and logs afterwards.<br />
Do not keep an optimization solely because it looks conventional. Record the tradeoff and test enough representative content to support a decision.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Apply this method to a real high-traffic site</span><br />
Collect response latency, transfer sizes, CPU, connection counts and upstream timing over comparable windows. Separate cached and uncached requests. Change one variable at a time and repeat the same workload. Keep a rollback copy and stop if errors or resource pressure increase.<br />
A compression change cannot repair slow SQL or exhausted PHP workers. Use the database and PHP-FPM guides alongside this test, then investigate the bottleneck actually observed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://nginx.org/en/docs/http/ngx_http_gzip_module.html" target="_blank" rel="noopener" class="mycode_url">Official Nginx gzip module documentation</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Nginx tuning should start with measurements, not a list of larger limits. This guide checks worker settings and gzip behavior, demonstrates a real compression tradeoff, and explains when to restore a change.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested</span>: aaPanel Free 8.0.7, Nginx 1.30.5 and Ubuntu 22.04.5 on the shared two-CPU lab VPS. No production configuration was changed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Inspect the active configuration</span><br />
Open App Store → Installed → Nginx → Setting and inspect its configuration. Paths and interface labels can differ by release. Our global file was /www/server/nginx/conf/nginx.conf; website configurations were included separately.<br />
A configuration dump can help identify includes:<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/nginx/sbin/nginx -T</code></div></div>Keep the output private because it can reveal hostnames, paths and configuration details. Identify which file owns the directive before editing it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Review workers and connection limits</span><br />
Our server already used worker_processes auto and worker_connections 51200. We did not increase either. More permitted connections do not mean more requests per second: upstream connections, open-file limits, PHP workers, database work and CPU also constrain throughput.<br />
Inspect actual worker count, active connections, system file limits and errors during representative traffic. Raise a limit only if it is the observed bottleneck and the server has resources to support it. Avoid treating a high worker_connections value as a visitor-capacity guarantee.<br />
Keepalive settings also need workload evidence. Shorter idle time can reduce held connections but increase connection setup; longer idle time can retain resources. We left the existing 60-second setting unchanged.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Back up before a compression experiment</span><br />
Make a private copy of the active file. Our baseline already had gzip enabled, a 1KiB minimum length, compression level 5 and gzip_vary on. Its gzip_types included text, JavaScript, CSS, JSON and several image types.<br />
Inspect response headers and actual transfer sizes before changing MIME types. Many image formats contain compressed data, but the effect of an additional gzip layer depends on the particular file.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Test text and image responses</span><br />
We created an original 24,500-byte text fixture in the lab website and used an existing 3,113-byte WordPress PNG. We requested gzip explicitly over loopback HTTPS with normal certificate validation.<br />
A basic header check 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>curl -sS -D - -o /dev/null &#92;
  -H 'Accept-Encoding: gzip' https://example.com/test.txt</code></div></div>Use your own hostname and a safe test file. Inspect Content-Encoding, Vary and HTTP status. To compare raw encoded bytes, save the response body without automatic decompression. curl --compressed instead requests supported compression and decompresses the body, so do not confuse decoded size with wire size.<br />
Our test compared the baseline against removing JPEG/GIF/PNG from gzip_types. It did not change the compression level or worker limits.<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=292" target="_blank" title="">nginx-performance-20261014.jpg</a> (Size: 116.44 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the experiment, not a screenshot.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Interpret the evidence</span><ul class="mycode_list"><li>Text: gzip was used in both phases; the body transferred was 156 bytes and decoded to 24,500 bytes.<br />
</li>
<li>PNG before: gzip body 2,487 bytes, decoded to 3,113 bytes.<br />
</li>
<li>PNG after: no gzip; body transferred 3,113 bytes.<br />
</li>
<li>All responses returned HTTP 200, and decoded content hashes matched.<br />
</li>
</ul>
Removing image compression increased transfer size for this particular small PNG. We did not measure CPU savings, so we did not claim the change improved performance. These body sizes exclude headers and transport overhead; one file does not represent an entire image library.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Validate, reload and restore when appropriate</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/nginx/sbin/nginx -t
/www/server/nginx/sbin/nginx -s reload</code></div></div>Validation passed for the experiment. Because we had no demonstrated overall benefit, we restored the original configuration, validated it again and reloaded Nginx. A successful reload is not an application test: check important pages, TLS, redirects, upstream errors and logs afterwards.<br />
Do not keep an optimization solely because it looks conventional. Record the tradeoff and test enough representative content to support a decision.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Apply this method to a real high-traffic site</span><br />
Collect response latency, transfer sizes, CPU, connection counts and upstream timing over comparable windows. Separate cached and uncached requests. Change one variable at a time and repeat the same workload. Keep a rollback copy and stop if errors or resource pressure increase.<br />
A compression change cannot repair slow SQL or exhausted PHP workers. Use the database and PHP-FPM guides alongside this test, then investigate the bottleneck actually observed.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://nginx.org/en/docs/http/ngx_http_gzip_module.html" target="_blank" rel="noopener" class="mycode_url">Official Nginx gzip module documentation</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Tune MariaDB Queries in aaPanel with EXPLAIN and Index Tests]]></title>
			<link>https://adminsforum.com/Thread-guide-tune-mariadb-queries-in-aapanel-with-explain-and-index-tests</link>
			<pubDate>Wed, 14 Oct 2026 20:17:01 +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-tune-mariadb-queries-in-aapanel-with-explain-and-index-tests</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">A slow website does not automatically need a larger database buffer or more connections. First identify the query, inspect its execution plan and measure a targeted change. This guide demonstrates that workflow in a separate MariaDB lab database.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested environment</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5 and MariaDB 10.11.10. MySQL and MariaDB releases differ; verify your installed version before copying configuration advice. We used 50,000 synthetic rows and changed no global database settings.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify the database and establish a baseline</span><br />
Open aaPanel → Databases and confirm which service and database the website uses. Inspect application logs and slow queries rather than assuming the homepage represents all workloads. Administrative diagnostics require suitable database permissions; keep credentials out of commands, screenshots and public tutorials.<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>SELECT VERSION();
SHOW VARIABLES WHERE Variable_name IN
('innodb_buffer_pool_size','max_connections','slow_query_log','long_query_time');
SHOW GLOBAL STATUS WHERE Variable_name IN
('Threads_connected','Max_used_connections','Innodb_buffer_pool_reads','Innodb_buffer_pool_read_requests');</code></div></div>Our lab had a 384MiB InnoDB buffer pool, max_connections 200, slow logging enabled and a 3-second threshold. Maximum used connections was 3 at that observation. These are observations, not recommended settings for every server.<br />
Counters may accumulate since startup. Take interval snapshots under representative traffic; a one-time cache ratio is not enough to justify allocating more RAM.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Find the actual slow query</span><br />
If slow logging is enabled, review its configured path through an administrator session. Logs can contain query text and user data: keep access restricted and do not upload raw logs to a public thread. A 3-second threshold will miss many shorter queries; choose a diagnostic threshold deliberately and monitor storage overhead.<br />
Find frequently repeated queries as well as individually expensive ones. Record execution count, latency and examined rows. A fast query executed thousands of times may still consume significant resources.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Create a separate practice database</span><br />
Use a disposable database, never a production table, for this example. Our new database was af_performance_index_lab_20261014. In MariaDB 10.11, the sequence table below provides synthetic integers; this syntax is not a portable MySQL recipe.<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>CREATE DATABASE af_performance_index_lab_20261014;
USE af_performance_index_lab_20261014;
CREATE TABLE events (
  id INT PRIMARY KEY,
  account_id INT NOT NULL,
  status VARCHAR(16) NOT NULL,
  payload VARCHAR(100) NOT NULL
) ENGINE=InnoDB;
INSERT INTO events
SELECT seq, MOD(seq,1000),
       IF(MOD(seq,2)=0,'active','closed'), REPEAT('x',100)
FROM seq_1_to_50000;</code></div></div>Check that your chosen database name does not already exist. This example creates only synthetic data; adapt names and versions for your own isolated lab.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Inspect the query plan before changing anything</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>EXPLAIN SELECT SQL_NO_CACHE COUNT(*)
FROM events WHERE account_id=321 AND status='closed';</code></div></div>SQL_NO_CACHE is used here to exclude MariaDB's query-result cache; it does not empty the InnoDB buffer pool. Do not copy this clause into an incompatible database release.<br />
Our plan showed type ALL and an estimated 50,000 rows. EXPLAIN estimates are not measured execution counts, but this plan indicates a full table scan to evaluate the filters.<br />
The query returned 50 matching rows. Record the result so that a faster but incorrect rewrite is not accepted.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Test a targeted composite index</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>ALTER TABLE events
  ADD INDEX idx_account_status(account_id,status);
ANALYZE TABLE events;
EXPLAIN SELECT SQL_NO_CACHE COUNT(*)
FROM events WHERE account_id=321 AND status='closed';</code></div></div>The new plan used idx_account_status, type ref and an estimated 50 rows. It also reported Using index: this count query can be satisfied from the index entries needed for the filters.<br />
Index design depends on the actual predicates, sorting and joins. Column order matters for other queries using only part of a composite index. Avoid creating an index for every column: indexes use storage and add work to writes.<br />
On a large production table, building an index can consume time, space and locks. Check version-specific online DDL behavior, back up and plan the change before applying it to real data.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Compare the same query</span><br />
We used MariaDB session profiling for this lab: one warmup followed by ten measured executions in each phase. The same database session setting and query were used before and after. Warm data remained possible in the buffer pool; this is not a cold-storage benchmark.<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>SET profiling=1;
SELECT SQL_NO_CACHE COUNT(*)
FROM events WHERE account_id=321 AND status='closed';
SHOW PROFILES;</code></div></div>Repeat the SELECT for your sample and inspect its reported duration. Session profiling is version-specific; use the diagnostic tools available in your actual database release. Disable temporary profiling when finished.<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=291" target="_blank" title="">database-index-comparison-20261014.jpg</a> (Size: 115.87 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original lab test, not a terminal screenshot.</span><br />
<br />
The median of ten measured executions was about 12.72ms before and 0.188ms after. Both phases returned 50 rows. This supports this index for this synthetic query; it does not promise the same improvement for every website or establish production capacity.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Tune resources only after reviewing evidence</span><br />
For InnoDB buffer sizing, account for the working data set and sustained physical reads, while reserving memory for PHP-FPM, Nginx, OS, mail and other services. Dedicated database-server percentage rules are unsuitable for every shared aaPanel VPS.<br />
For max_connections, inspect concurrent connections, application pooling and per-connection memory. Raising the limit can worsen overload. Our observed maximum of 3 did not justify increasing the limit of 200.<br />
Change one setting at a time, retain its original value, validate the database configuration and repeat representative workloads. Monitor swap, OOM events, errors and query latency. A restart can temporarily alter cache warmth and distort comparisons.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Verify the website and retain a rollback plan</span><br />
Test real reads and writes, not just this SELECT. Compare execution plans and results, then monitor normal traffic. For our disposable table, the index can be removed with:<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>ALTER TABLE events DROP INDEX idx_account_status;</code></div></div>Do not remove an existing production index without checking its other uses. We retained this isolated lab database and its index for repeatable demonstrations; no application database was modified.<br />
<br />
Continue with <a href="https://adminsforum.com/Thread-guide-tune-php-fpm-workers-in-aapanel-with-measured-memory-limits" target="_blank" rel="noopener" class="mycode_url">PHP-FPM memory limits</a> to balance the shared server, rather than tuning each service as though it owns all RAM.<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References</span>: <a href="https://mariadb.com/docs/server/reference/sql-statements/administrative-sql-statements/analyze-and-explain-statements/explain" target="_blank" rel="noopener" class="mycode_url">MariaDB EXPLAIN</a> and <a href="https://mariadb.com/docs/server/reference/sql-statements/administrative-sql-statements/show/show-profiles" target="_blank" rel="noopener" class="mycode_url">SHOW PROFILES</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">A slow website does not automatically need a larger database buffer or more connections. First identify the query, inspect its execution plan and measure a targeted change. This guide demonstrates that workflow in a separate MariaDB lab database.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested environment</span>: aaPanel Free 8.0.7, Ubuntu 22.04.5 and MariaDB 10.11.10. MySQL and MariaDB releases differ; verify your installed version before copying configuration advice. We used 50,000 synthetic rows and changed no global database settings.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Identify the database and establish a baseline</span><br />
Open aaPanel → Databases and confirm which service and database the website uses. Inspect application logs and slow queries rather than assuming the homepage represents all workloads. Administrative diagnostics require suitable database permissions; keep credentials out of commands, screenshots and public tutorials.<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>SELECT VERSION();
SHOW VARIABLES WHERE Variable_name IN
('innodb_buffer_pool_size','max_connections','slow_query_log','long_query_time');
SHOW GLOBAL STATUS WHERE Variable_name IN
('Threads_connected','Max_used_connections','Innodb_buffer_pool_reads','Innodb_buffer_pool_read_requests');</code></div></div>Our lab had a 384MiB InnoDB buffer pool, max_connections 200, slow logging enabled and a 3-second threshold. Maximum used connections was 3 at that observation. These are observations, not recommended settings for every server.<br />
Counters may accumulate since startup. Take interval snapshots under representative traffic; a one-time cache ratio is not enough to justify allocating more RAM.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Find the actual slow query</span><br />
If slow logging is enabled, review its configured path through an administrator session. Logs can contain query text and user data: keep access restricted and do not upload raw logs to a public thread. A 3-second threshold will miss many shorter queries; choose a diagnostic threshold deliberately and monitor storage overhead.<br />
Find frequently repeated queries as well as individually expensive ones. Record execution count, latency and examined rows. A fast query executed thousands of times may still consume significant resources.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Create a separate practice database</span><br />
Use a disposable database, never a production table, for this example. Our new database was af_performance_index_lab_20261014. In MariaDB 10.11, the sequence table below provides synthetic integers; this syntax is not a portable MySQL recipe.<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>CREATE DATABASE af_performance_index_lab_20261014;
USE af_performance_index_lab_20261014;
CREATE TABLE events (
  id INT PRIMARY KEY,
  account_id INT NOT NULL,
  status VARCHAR(16) NOT NULL,
  payload VARCHAR(100) NOT NULL
) ENGINE=InnoDB;
INSERT INTO events
SELECT seq, MOD(seq,1000),
       IF(MOD(seq,2)=0,'active','closed'), REPEAT('x',100)
FROM seq_1_to_50000;</code></div></div>Check that your chosen database name does not already exist. This example creates only synthetic data; adapt names and versions for your own isolated lab.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Inspect the query plan before changing anything</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>EXPLAIN SELECT SQL_NO_CACHE COUNT(*)
FROM events WHERE account_id=321 AND status='closed';</code></div></div>SQL_NO_CACHE is used here to exclude MariaDB's query-result cache; it does not empty the InnoDB buffer pool. Do not copy this clause into an incompatible database release.<br />
Our plan showed type ALL and an estimated 50,000 rows. EXPLAIN estimates are not measured execution counts, but this plan indicates a full table scan to evaluate the filters.<br />
The query returned 50 matching rows. Record the result so that a faster but incorrect rewrite is not accepted.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Test a targeted composite index</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>ALTER TABLE events
  ADD INDEX idx_account_status(account_id,status);
ANALYZE TABLE events;
EXPLAIN SELECT SQL_NO_CACHE COUNT(*)
FROM events WHERE account_id=321 AND status='closed';</code></div></div>The new plan used idx_account_status, type ref and an estimated 50 rows. It also reported Using index: this count query can be satisfied from the index entries needed for the filters.<br />
Index design depends on the actual predicates, sorting and joins. Column order matters for other queries using only part of a composite index. Avoid creating an index for every column: indexes use storage and add work to writes.<br />
On a large production table, building an index can consume time, space and locks. Check version-specific online DDL behavior, back up and plan the change before applying it to real data.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Compare the same query</span><br />
We used MariaDB session profiling for this lab: one warmup followed by ten measured executions in each phase. The same database session setting and query were used before and after. Warm data remained possible in the buffer pool; this is not a cold-storage benchmark.<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>SET profiling=1;
SELECT SQL_NO_CACHE COUNT(*)
FROM events WHERE account_id=321 AND status='closed';
SHOW PROFILES;</code></div></div>Repeat the SELECT for your sample and inspect its reported duration. Session profiling is version-specific; use the diagnostic tools available in your actual database release. Disable temporary profiling when finished.<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=291" target="_blank" title="">database-index-comparison-20261014.jpg</a> (Size: 115.87 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original lab test, not a terminal screenshot.</span><br />
<br />
The median of ten measured executions was about 12.72ms before and 0.188ms after. Both phases returned 50 rows. This supports this index for this synthetic query; it does not promise the same improvement for every website or establish production capacity.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Tune resources only after reviewing evidence</span><br />
For InnoDB buffer sizing, account for the working data set and sustained physical reads, while reserving memory for PHP-FPM, Nginx, OS, mail and other services. Dedicated database-server percentage rules are unsuitable for every shared aaPanel VPS.<br />
For max_connections, inspect concurrent connections, application pooling and per-connection memory. Raising the limit can worsen overload. Our observed maximum of 3 did not justify increasing the limit of 200.<br />
Change one setting at a time, retain its original value, validate the database configuration and repeat representative workloads. Monitor swap, OOM events, errors and query latency. A restart can temporarily alter cache warmth and distort comparisons.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Verify the website and retain a rollback plan</span><br />
Test real reads and writes, not just this SELECT. Compare execution plans and results, then monitor normal traffic. For our disposable table, the index can be removed with:<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>ALTER TABLE events DROP INDEX idx_account_status;</code></div></div>Do not remove an existing production index without checking its other uses. We retained this isolated lab database and its index for repeatable demonstrations; no application database was modified.<br />
<br />
Continue with <a href="https://adminsforum.com/Thread-guide-tune-php-fpm-workers-in-aapanel-with-measured-memory-limits" target="_blank" rel="noopener" class="mycode_url">PHP-FPM memory limits</a> to balance the shared server, rather than tuning each service as though it owns all RAM.<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References</span>: <a href="https://mariadb.com/docs/server/reference/sql-statements/administrative-sql-statements/analyze-and-explain-statements/explain" target="_blank" rel="noopener" class="mycode_url">MariaDB EXPLAIN</a> and <a href="https://mariadb.com/docs/server/reference/sql-statements/administrative-sql-statements/show/show-profiles" target="_blank" rel="noopener" class="mycode_url">SHOW PROFILES</a>.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Measure PHP OPcache Performance in aaPanel]]></title>
			<link>https://adminsforum.com/Thread-guide-measure-php-opcache-performance-in-aapanel</link>
			<pubDate>Wed, 14 Oct 2026 20:14: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-measure-php-opcache-performance-in-aapanel</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">OPcache stores compiled PHP bytecode so PHP-FPM can reuse it instead of compiling the same scripts for every request. This guide measures that effect on a small WordPress lab and explains how to verify the serving runtime.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Test environment</span><br />
aaPanel Free 8.0.7, Ubuntu 22.04.5, PHP 8.5.11, Nginx and WordPress. OPcache was already enabled before the experiment. We temporarily disabled it for the comparison and left it enabled afterwards. No production website was used.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Confirm the PHP version serving the website</span><br />
Open Website → your site and inspect its PHP version. Our site used PHP 8.5 through /tmp/php-cgi-85.sock. A command-line PHP result alone cannot prove what PHP-FPM is doing: CLI and FPM may load different configuration files.<br />
Read <a href="https://adminsforum.com/Thread-guide-check-php-opcache-in-aapanel-cli-vs-php-fpm" target="_blank" rel="noopener" class="mycode_url">Check PHP OPcache: CLI vs PHP-FPM</a> first if those results disagree.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Back up the active configuration</span><br />
In App Store → Installed → PHP-8.5 → Setting, inspect the configuration and available extensions. Interface labels depend on the panel release. Confirm the active FPM php.ini before editing; our FPM runtime loaded /www/server/php/85/etc/php.ini, while CLI loaded php-cli.ini.<br />
Keep a backup and working SSH access. A setting change affects the websites sharing that PHP version. Schedule a suitable maintenance window for a busy server.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Use a measured starting configuration</span><br />
Our retained lab settings were:<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>[opcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.validate_timestamps=1
opcache.revalidate_freq=2</code></div></div>The memory value is MiB. The file setting controls the script-cache table size; the actual key capacity may differ from the number configured. Check the runtime rather than assuming they are identical.<br />
Timestamp validation allows changed files to be detected; the revalidation interval controls how frequently checks occur. Disabling validation requires a reliable deployment invalidation process. We kept it enabled and did not change JIT settings.<br />
Do not increase these values merely because traffic increased. Look for cache exhaustion, restarts and the application’s script count, while reserving RAM for other services.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Validate and reload the correct pool</span><br />
Our SSH checks were:<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/php/85/sbin/php-fpm -t
/etc/init.d/php-fpm-85 reload</code></div></div>Validation passed before each reload. Syntax success does not prove the application works: check important pages and error logs afterwards. Restore the backup and reload if the change causes failures.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Verify OPcache through PHP-FPM privately</span><br />
Our diagnostic script used opcache_get_status(false) and php_ini_loaded_file() through the private Unix socket. It was outside the website root. Passing false excludes the detailed cached-script path listing.<br />
The enabled phase reported FPM SAPI fpm-fcgi, PHP 8.5.11, 532 cached scripts, about 29MiB used and 99MiB free, with zero out-of-memory and hash restarts at that observation. These values describe this small workload, not the needs of every WordPress installation.<br />
Do not publish phpinfo or cache status on an unprotected URL: configuration and paths can disclose server details. Remove temporary diagnostics when finished.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Separate page caching from bytecode caching</span><br />
A full-page cache HIT may avoid PHP entirely. We used unique query strings and verified Nginx-Cache: BYPASS under our existing rules. Query strings do not universally bypass caches; check your own configuration and response headers.<br />
Each phase used 20 warmup requests followed by 20 measured requests at concurrency 2. Requests used loopback HTTPS with normal certificate validation. This isolates much of the network variation but does not represent a remote visitor’s full browser experience.<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=290" target="_blank" title="">opcache-comparison-20261014.jpg</a> (Size: 117.41 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original experiment, not a terminal screenshot.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Interpret the results</span><ul class="mycode_list"><li>OPcache off: 20/20 HTTP 200; median time to first byte 490ms; small-sample p95 555ms.<br />
</li>
<li>OPcache on: 20/20 HTTP 200; median time to first byte 168ms; small-sample p95 190ms.<br />
</li>
</ul>
This workload was faster with OPcache enabled. Twenty requests give limited tail-latency evidence and do not establish maximum visitor capacity. Repeat tests on expensive pages and representative workloads before making production promises.<br />
Runtime hit/miss counters can include warmup and other requests since the cache started; do not treat a cumulative hit ratio as the measured phase alone.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Monitor and revisit sizing</span><br />
Inspect memory used/free/wasted, cached-script count, misses and restart counters over a representative period. An exhausted cache may need additional memory or key capacity; frequent deployments and invalidation also affect results. Check PHP errors and memory pressure alongside cache statistics.<br />
OPcache does not replace SQL indexes, object caching or page caching. Use <a href="https://adminsforum.com/Thread-guide-tune-php-fpm-workers-in-aapanel-with-measured-memory-limits" target="_blank" rel="noopener" class="mycode_url">measured PHP-FPM worker limits</a> to control concurrent process memory separately.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://www.php.net/manual/en/opcache.configuration.php" target="_blank" rel="noopener" class="mycode_url">Official PHP OPcache configuration documentation</a>.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">OPcache stores compiled PHP bytecode so PHP-FPM can reuse it instead of compiling the same scripts for every request. This guide measures that effect on a small WordPress lab and explains how to verify the serving runtime.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Test environment</span><br />
aaPanel Free 8.0.7, Ubuntu 22.04.5, PHP 8.5.11, Nginx and WordPress. OPcache was already enabled before the experiment. We temporarily disabled it for the comparison and left it enabled afterwards. No production website was used.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Confirm the PHP version serving the website</span><br />
Open Website → your site and inspect its PHP version. Our site used PHP 8.5 through /tmp/php-cgi-85.sock. A command-line PHP result alone cannot prove what PHP-FPM is doing: CLI and FPM may load different configuration files.<br />
Read <a href="https://adminsforum.com/Thread-guide-check-php-opcache-in-aapanel-cli-vs-php-fpm" target="_blank" rel="noopener" class="mycode_url">Check PHP OPcache: CLI vs PHP-FPM</a> first if those results disagree.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Back up the active configuration</span><br />
In App Store → Installed → PHP-8.5 → Setting, inspect the configuration and available extensions. Interface labels depend on the panel release. Confirm the active FPM php.ini before editing; our FPM runtime loaded /www/server/php/85/etc/php.ini, while CLI loaded php-cli.ini.<br />
Keep a backup and working SSH access. A setting change affects the websites sharing that PHP version. Schedule a suitable maintenance window for a busy server.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Use a measured starting configuration</span><br />
Our retained lab settings were:<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>[opcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.validate_timestamps=1
opcache.revalidate_freq=2</code></div></div>The memory value is MiB. The file setting controls the script-cache table size; the actual key capacity may differ from the number configured. Check the runtime rather than assuming they are identical.<br />
Timestamp validation allows changed files to be detected; the revalidation interval controls how frequently checks occur. Disabling validation requires a reliable deployment invalidation process. We kept it enabled and did not change JIT settings.<br />
Do not increase these values merely because traffic increased. Look for cache exhaustion, restarts and the application’s script count, while reserving RAM for other services.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Validate and reload the correct pool</span><br />
Our SSH checks were:<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/php/85/sbin/php-fpm -t
/etc/init.d/php-fpm-85 reload</code></div></div>Validation passed before each reload. Syntax success does not prove the application works: check important pages and error logs afterwards. Restore the backup and reload if the change causes failures.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Verify OPcache through PHP-FPM privately</span><br />
Our diagnostic script used opcache_get_status(false) and php_ini_loaded_file() through the private Unix socket. It was outside the website root. Passing false excludes the detailed cached-script path listing.<br />
The enabled phase reported FPM SAPI fpm-fcgi, PHP 8.5.11, 532 cached scripts, about 29MiB used and 99MiB free, with zero out-of-memory and hash restarts at that observation. These values describe this small workload, not the needs of every WordPress installation.<br />
Do not publish phpinfo or cache status on an unprotected URL: configuration and paths can disclose server details. Remove temporary diagnostics when finished.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Separate page caching from bytecode caching</span><br />
A full-page cache HIT may avoid PHP entirely. We used unique query strings and verified Nginx-Cache: BYPASS under our existing rules. Query strings do not universally bypass caches; check your own configuration and response headers.<br />
Each phase used 20 warmup requests followed by 20 measured requests at concurrency 2. Requests used loopback HTTPS with normal certificate validation. This isolates much of the network variation but does not represent a remote visitor’s full browser experience.<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=290" target="_blank" title="">opcache-comparison-20261014.jpg</a> (Size: 117.41 KB / Downloads: 4)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">AdminsForum formatted transcript of the original experiment, not a terminal screenshot.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Interpret the results</span><ul class="mycode_list"><li>OPcache off: 20/20 HTTP 200; median time to first byte 490ms; small-sample p95 555ms.<br />
</li>
<li>OPcache on: 20/20 HTTP 200; median time to first byte 168ms; small-sample p95 190ms.<br />
</li>
</ul>
This workload was faster with OPcache enabled. Twenty requests give limited tail-latency evidence and do not establish maximum visitor capacity. Repeat tests on expensive pages and representative workloads before making production promises.<br />
Runtime hit/miss counters can include warmup and other requests since the cache started; do not treat a cumulative hit ratio as the measured phase alone.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Monitor and revisit sizing</span><br />
Inspect memory used/free/wasted, cached-script count, misses and restart counters over a representative period. An exhausted cache may need additional memory or key capacity; frequent deployments and invalidation also affect results. Check PHP errors and memory pressure alongside cache statistics.<br />
OPcache does not replace SQL indexes, object caching or page caching. Use <a href="https://adminsforum.com/Thread-guide-tune-php-fpm-workers-in-aapanel-with-measured-memory-limits" target="_blank" rel="noopener" class="mycode_url">measured PHP-FPM worker limits</a> to control concurrent process memory separately.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference</span>: <a href="https://www.php.net/manual/en/opcache.configuration.php" target="_blank" rel="noopener" class="mycode_url">Official PHP OPcache configuration documentation</a>.]]></content:encoded>
		</item>
	</channel>
</rss>