<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[AdminsForum - aaPanel Security Guides]]></title>
		<link>https://adminsforum.com/</link>
		<description><![CDATA[AdminsForum - https://adminsforum.com]]></description>
		<pubDate>Thu, 15 Oct 2026 06:11:12 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Set File Permissions and Ownership in aaPanel]]></title>
			<link>https://adminsforum.com/Thread-guide-set-file-permissions-and-ownership-in-aapanel</link>
			<pubDate>Wed, 14 Oct 2026 18:08:57 +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-set-file-permissions-and-ownership-in-aapanel</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">aaPanel's file permission editor lets you change a selected file's access mode and owner. Understand who needs access before changing a number: the correct permission depends on the application user and the specific file.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested:</span> aaPanel Free 8.0.7 on Ubuntu 22.04.5. We changed one disposable non-public file from 644 to 600 through the native Files permission dialog, verified owner access and denial for an unrelated user, then restored 644. No application directory was changed recursively.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Understand owner, group and others</span><br />
Linux permission digits describe three classes in this order: owner, group and others. Each digit combines read (4), write (2) and execute (1).<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">6</span> = read + write.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">4</span> = read only.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">7</span> = read + write + execute.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">5</span> = read + execute.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">0</span> = no permissions for that class.<br />
</li>
</ul>
For a regular file, execute means it can be executed where other conditions permit. For a directory, execute permits traversal/search; read allows listing names, and write permits directory-entry changes subject to other rules. Parent directory access also matters.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Common modes, with their limits</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">644 file:</span> owner reads/writes; group and others read. Suitable for some public source/static files, but not a universal choice for private configuration.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">600 file:</span> only the owner reads/writes under ordinary mode bits. Useful where just the intended owner needs access; it can break an app running as another user.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">640 file:</span> owner reads/writes and group reads. Requires the correct group membership and parent-directory access.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">755 directory:</span> owner can manage entries; group and others can list/traverse. It does not mean every directory should be public or writable.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">777:</span> gives every class write access. Do not use it as a general fix for application permission errors.<br />
</li>
</ul>
Privileged administrators can have access beyond ordinary mode bits. ACLs, filesystem attributes and other security controls can also affect the result, so test the actual application user.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Find the exact file in aaPanel</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Files</span> and navigate to the file's directory. Check the filename, full path and current <span style="font-weight: bold;" class="mycode_b">PMSN/Owner</span> value. Our test file was /www/af-composer-lab/af-protection-lab.txt, owned by www with mode 644.<br />
<br />
Select the intended row, open its <span style="font-weight: bold;" class="mycode_b">Operate</span> menu and choose <span style="font-weight: bold;" class="mycode_b">Permission</span>. In our version this opened <span style="font-weight: bold;" class="mycode_b">Set Permission</span> with the full target path in the title.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Review the dialog before applying</span><br />
The dialog shows read/write/execute controls, the numeric permission field, an Owner selector and <span style="font-weight: bold;" class="mycode_b">Apply to subdir</span>. Record the existing mode and ownership so you can restore them.<br />
<br />
For a single-file test, leave Apply to subdir unchecked. Do not apply one identical mode recursively across files and directories: directories need traversal permissions, while ordinary text files usually do not need executable bits.<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=231" target="_blank" title="">file-permissions-600-20261014.jpg</a> (Size: 147.64 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Native aaPanel permission dialog for the disposable file, with owner-only mode 600 entered.</span><br />
<br />
We retained owner www, entered <span style="font-weight: bold;" class="mycode_b">600</span> and clicked <span style="font-weight: bold;" class="mycode_b">Apply</span>. The Files row updated to 600 / www.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Verify as the intended user</span><br />
From an authorized SSH administrator session, our 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>stat -c '%a %U:%G' /www/af-composer-lab/af-protection-lab.txt
runuser -u www -- cat /www/af-composer-lab/af-protection-lab.txt
runuser -u nobody -- cat /www/af-composer-lab/af-protection-lab.txt</code></div></div>The first command reported <span style="font-weight: bold;" class="mycode_b">600 www:www</span>. The owner www read the harmless text successfully. The unrelated nobody account received <span style="font-weight: bold;" class="mycode_b">Permission denied</span>. Those accounts already existed; we did not create another login or grant access.<br />
<br />
Use your actual application user when testing. A successful root read is not proof that PHP, Nginx or a Python worker can read the file.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Understand ownership before changing it</span><br />
The Owner selector changes who owns the file. Do not choose www merely because this guide uses it: check the service or deployment user for your application. Different sites and services can use different users.<br />
<br />
For this lesson we kept existing ownership unchanged. We inspected the owner control but did not claim a tested ownership migration. Changing ownership can allow one service to write files or prevent another service from accessing them, so review the intended account before applying it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Restore and verify after the test</span><br />
We reopened Operate → Permission, changed 600 back to <span style="font-weight: bold;" class="mycode_b">644</span> and applied it to the same file only. An SSH check confirmed 644 www:www, and the original harmless text was unchanged.<br />
<br />
For real maintenance, verify the application action you intended to repair: reading configuration, uploading a file or creating a cache entry. Restore the previous settings if the change fails, then investigate the underlying user/path problem instead of widening access repeatedly.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Diagnose Permission denied</span><ul class="mycode_list"><li>Check the exact target and every parent directory's traversal permissions.<br />
</li>
<li>Identify the process user and group instead of assuming it runs as root.<br />
</li>
<li>Check whether it needs read access, write access or directory-entry access.<br />
</li>
<li>Inspect ACLs and filesystem attributes if mode bits appear correct.<br />
</li>
<li>Check a read-only filesystem or service isolation where applicable.<br />
</li>
<li>If the immutable i flag is present, chmod does not remove it. See <a href="https://adminsforum.com/Thread-guide-protect-files-on-an-aapanel-server-with-linux-chattr" target="_blank" rel="noopener" class="mycode_url">Linux file protection with chattr</a>.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">Completion checklist</span><ul class="mycode_list"><li>Exact file and current settings recorded.<br />
</li>
<li>Required user and access identified.<br />
</li>
<li>Change limited to the intended path.<br />
</li>
<li>Actual user access tested.<br />
</li>
<li>Application behavior checked and rollback available.<br />
</li>
</ul>
<br />
<span style="font-style: italic;" class="mycode_i">AdminsForum lab-tested native aaPanel guide. The screenshot contains our own disposable file; ownership changes and recursive updates were not performed.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">aaPanel's file permission editor lets you change a selected file's access mode and owner. Understand who needs access before changing a number: the correct permission depends on the application user and the specific file.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested:</span> aaPanel Free 8.0.7 on Ubuntu 22.04.5. We changed one disposable non-public file from 644 to 600 through the native Files permission dialog, verified owner access and denial for an unrelated user, then restored 644. No application directory was changed recursively.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Understand owner, group and others</span><br />
Linux permission digits describe three classes in this order: owner, group and others. Each digit combines read (4), write (2) and execute (1).<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">6</span> = read + write.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">4</span> = read only.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">7</span> = read + write + execute.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">5</span> = read + execute.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">0</span> = no permissions for that class.<br />
</li>
</ul>
For a regular file, execute means it can be executed where other conditions permit. For a directory, execute permits traversal/search; read allows listing names, and write permits directory-entry changes subject to other rules. Parent directory access also matters.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Common modes, with their limits</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">644 file:</span> owner reads/writes; group and others read. Suitable for some public source/static files, but not a universal choice for private configuration.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">600 file:</span> only the owner reads/writes under ordinary mode bits. Useful where just the intended owner needs access; it can break an app running as another user.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">640 file:</span> owner reads/writes and group reads. Requires the correct group membership and parent-directory access.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">755 directory:</span> owner can manage entries; group and others can list/traverse. It does not mean every directory should be public or writable.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">777:</span> gives every class write access. Do not use it as a general fix for application permission errors.<br />
</li>
</ul>
Privileged administrators can have access beyond ordinary mode bits. ACLs, filesystem attributes and other security controls can also affect the result, so test the actual application user.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Find the exact file in aaPanel</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Files</span> and navigate to the file's directory. Check the filename, full path and current <span style="font-weight: bold;" class="mycode_b">PMSN/Owner</span> value. Our test file was /www/af-composer-lab/af-protection-lab.txt, owned by www with mode 644.<br />
<br />
Select the intended row, open its <span style="font-weight: bold;" class="mycode_b">Operate</span> menu and choose <span style="font-weight: bold;" class="mycode_b">Permission</span>. In our version this opened <span style="font-weight: bold;" class="mycode_b">Set Permission</span> with the full target path in the title.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Review the dialog before applying</span><br />
The dialog shows read/write/execute controls, the numeric permission field, an Owner selector and <span style="font-weight: bold;" class="mycode_b">Apply to subdir</span>. Record the existing mode and ownership so you can restore them.<br />
<br />
For a single-file test, leave Apply to subdir unchecked. Do not apply one identical mode recursively across files and directories: directories need traversal permissions, while ordinary text files usually do not need executable bits.<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=231" target="_blank" title="">file-permissions-600-20261014.jpg</a> (Size: 147.64 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Native aaPanel permission dialog for the disposable file, with owner-only mode 600 entered.</span><br />
<br />
We retained owner www, entered <span style="font-weight: bold;" class="mycode_b">600</span> and clicked <span style="font-weight: bold;" class="mycode_b">Apply</span>. The Files row updated to 600 / www.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Verify as the intended user</span><br />
From an authorized SSH administrator session, our 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>stat -c '%a %U:%G' /www/af-composer-lab/af-protection-lab.txt
runuser -u www -- cat /www/af-composer-lab/af-protection-lab.txt
runuser -u nobody -- cat /www/af-composer-lab/af-protection-lab.txt</code></div></div>The first command reported <span style="font-weight: bold;" class="mycode_b">600 www:www</span>. The owner www read the harmless text successfully. The unrelated nobody account received <span style="font-weight: bold;" class="mycode_b">Permission denied</span>. Those accounts already existed; we did not create another login or grant access.<br />
<br />
Use your actual application user when testing. A successful root read is not proof that PHP, Nginx or a Python worker can read the file.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Understand ownership before changing it</span><br />
The Owner selector changes who owns the file. Do not choose www merely because this guide uses it: check the service or deployment user for your application. Different sites and services can use different users.<br />
<br />
For this lesson we kept existing ownership unchanged. We inspected the owner control but did not claim a tested ownership migration. Changing ownership can allow one service to write files or prevent another service from accessing them, so review the intended account before applying it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Restore and verify after the test</span><br />
We reopened Operate → Permission, changed 600 back to <span style="font-weight: bold;" class="mycode_b">644</span> and applied it to the same file only. An SSH check confirmed 644 www:www, and the original harmless text was unchanged.<br />
<br />
For real maintenance, verify the application action you intended to repair: reading configuration, uploading a file or creating a cache entry. Restore the previous settings if the change fails, then investigate the underlying user/path problem instead of widening access repeatedly.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Diagnose Permission denied</span><ul class="mycode_list"><li>Check the exact target and every parent directory's traversal permissions.<br />
</li>
<li>Identify the process user and group instead of assuming it runs as root.<br />
</li>
<li>Check whether it needs read access, write access or directory-entry access.<br />
</li>
<li>Inspect ACLs and filesystem attributes if mode bits appear correct.<br />
</li>
<li>Check a read-only filesystem or service isolation where applicable.<br />
</li>
<li>If the immutable i flag is present, chmod does not remove it. See <a href="https://adminsforum.com/Thread-guide-protect-files-on-an-aapanel-server-with-linux-chattr" target="_blank" rel="noopener" class="mycode_url">Linux file protection with chattr</a>.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">Completion checklist</span><ul class="mycode_list"><li>Exact file and current settings recorded.<br />
</li>
<li>Required user and access identified.<br />
</li>
<li>Change limited to the intended path.<br />
</li>
<li>Actual user access tested.<br />
</li>
<li>Application behavior checked and rollback available.<br />
</li>
</ul>
<br />
<span style="font-style: italic;" class="mycode_i">AdminsForum lab-tested native aaPanel guide. The screenshot contains our own disposable file; ownership changes and recursive updates were not performed.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Protect Files on an aaPanel Server with Linux chattr]]></title>
			<link>https://adminsforum.com/Thread-guide-protect-files-on-an-aapanel-server-with-linux-chattr</link>
			<pubDate>Wed, 14 Oct 2026 18:02: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-protect-files-on-an-aapanel-server-with-linux-chattr</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Linux's immutable file attribute can prevent a selected file from being modified while the attribute is set. On an aaPanel server, you can test this through SSH using chattr and lsattr, then remove the attribute before legitimate updates.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Scope:</span> This is a Linux SSH method tested on our Ubuntu 22.04.5 VPS with aaPanel Free 8.0.7. It is not a walkthrough of aaPanel Pro's File Protection feature. In this Free installation, clicking a file's Unprotected control opened a Pro upgrade screen; we did not purchase or activate Pro and did not test its protection settings.<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=230" target="_blank" title="">file-protection-transcript-20261014.jpg</a> (Size: 105.42 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Formatted transcript of our disposable file test: protected write blocked, unlock succeeded, and original contents restored.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">What this method protects</span><br />
The immutable i attribute prevents normal modification of the protected file while set. It is separate from ordinary chmod read/write permissions. An authorized administrator with the relevant capability can remove it, so it is not protection against a fully privileged attacker and does not replace updates, least-privilege access or backups.<br />
<br />
Do not apply it recursively across a running website. Uploads, cache files, databases, logs, certificate renewals and application updates need to write files. Start with one disposable file outside a public website root.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Choose a disposable file and confirm its path</span><br />
Our test file was:<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/af-composer-lab/af-protection-lab.txt</code></div></div>It contained only the text AdminsForum disposable file protection lab. It was owned by www with mode 644 and was not served as a public website file. The surrounding directory already existed; we did not change its application files.<br />
<br />
Create your own harmless test file in a private lab directory. Verify its contents before proceeding:<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>cat /absolute/path/to/test-file.txt
ls -l /absolute/path/to/test-file.txt
lsattr /absolute/path/to/test-file.txt</code></div></div>The examples below use a placeholder path. Replace it with the exact file you intend to test, not a directory or wildcard.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Apply the immutable flag</span><br />
From an authorized administrator terminal:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>sudo chattr +i /absolute/path/to/test-file.txt
lsattr /absolute/path/to/test-file.txt</code></div></div>In our lab, chattr returned exit 0 and lsattr displayed the i flag. Other letters such as e may already be present; the significant change for this test is i.<br />
<br />
If the command reports Operation not supported, investigate the filesystem and hosting environment. Containers, filesystem types and available capabilities can affect support. Do not claim protection is active without checking the result.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Verify a write is blocked</span><br />
Attempt a harmless append only on that disposable file:<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>printf 'disposable write test
' &gt;&gt; /absolute/path/to/test-file.txt</code></div></div>Our administrator-side write attempt failed with <span style="font-weight: bold;" class="mycode_b">Operation not permitted</span>, and the original file content remained unchanged. Read it again to confirm the attempted text was not added. This test verifies one file's behavior; it does not establish protection for every path on the VPS.<br />
<br />
If the append succeeds, stop and investigate the attribute and actual target path. Do not treat a successful chattr message alone as proof.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Remove protection before legitimate maintenance</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>sudo chattr -i /absolute/path/to/test-file.txt
lsattr /absolute/path/to/test-file.txt</code></div></div>Confirm the i flag is absent. On the disposable file, test the append again and read its contents. Our second write succeeded after unlocking. We then restored the original harmless text and checked that the final contents matched the original and the i flag remained absent.<br />
<br />
For a real protected configuration file, plan the maintenance process: unlock only the intended file, perform the reviewed change, verify the application and then reapply protection if it is still appropriate. Keep a record of protected paths so future updates do not fail unexpectedly.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Understand the aaPanel UI boundary</span><br />
The Files page in our panel has a Protected column and Unprotected controls. In this Free lab, using that control opened a Pro upgrade prompt rather than a protection dialog. That observation does not establish the internal mechanism or capabilities of the Pro implementation.<br />
<br />
Do not assume an SSH chattr change will be fully managed or accurately represented by every panel protection screen. Use lsattr and an actual disposable write test for this method. A separate Pro tutorial should test the native UI, enable/disable behavior and compatibility with application updates on a licensed test server.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Troubleshooting</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">chmod does not make the file writable:</span> check lsattr; ordinary permission changes do not remove immutable protection.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">File editor or deployment cannot save:</span> confirm whether the exact target is intentionally protected, then use the planned unlock process.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Operation not supported:</span> check filesystem support and virtualization restrictions rather than repeatedly changing permissions.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Operation not permitted when changing attributes:</span> check your administrative privileges and relevant capabilities.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Application updates fail:</span> review whether protection was applied to files that must change; avoid bulk protection of a live app.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">What our lab verified</span><ul class="mycode_list"><li>One disposable non-public file was created with harmless contents.<br />
</li>
<li>chattr +i succeeded and lsattr showed i.<br />
</li>
<li>A write was blocked and original contents stayed unchanged.<br />
</li>
<li>chattr -i succeeded and a subsequent write worked.<br />
</li>
<li>Original contents were restored and the file was left unlocked.<br />
</li>
</ul>
<br />
<span style="font-style: italic;" class="mycode_i">AdminsForum lab-tested SSH tutorial. The illustration is a formatted result transcript; native aaPanel Pro File Protection remains a separate test.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Linux's immutable file attribute can prevent a selected file from being modified while the attribute is set. On an aaPanel server, you can test this through SSH using chattr and lsattr, then remove the attribute before legitimate updates.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Scope:</span> This is a Linux SSH method tested on our Ubuntu 22.04.5 VPS with aaPanel Free 8.0.7. It is not a walkthrough of aaPanel Pro's File Protection feature. In this Free installation, clicking a file's Unprotected control opened a Pro upgrade screen; we did not purchase or activate Pro and did not test its protection settings.<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=230" target="_blank" title="">file-protection-transcript-20261014.jpg</a> (Size: 105.42 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Formatted transcript of our disposable file test: protected write blocked, unlock succeeded, and original contents restored.</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">What this method protects</span><br />
The immutable i attribute prevents normal modification of the protected file while set. It is separate from ordinary chmod read/write permissions. An authorized administrator with the relevant capability can remove it, so it is not protection against a fully privileged attacker and does not replace updates, least-privilege access or backups.<br />
<br />
Do not apply it recursively across a running website. Uploads, cache files, databases, logs, certificate renewals and application updates need to write files. Start with one disposable file outside a public website root.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Choose a disposable file and confirm its path</span><br />
Our test file was:<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/af-composer-lab/af-protection-lab.txt</code></div></div>It contained only the text AdminsForum disposable file protection lab. It was owned by www with mode 644 and was not served as a public website file. The surrounding directory already existed; we did not change its application files.<br />
<br />
Create your own harmless test file in a private lab directory. Verify its contents before proceeding:<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>cat /absolute/path/to/test-file.txt
ls -l /absolute/path/to/test-file.txt
lsattr /absolute/path/to/test-file.txt</code></div></div>The examples below use a placeholder path. Replace it with the exact file you intend to test, not a directory or wildcard.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Apply the immutable flag</span><br />
From an authorized administrator terminal:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>sudo chattr +i /absolute/path/to/test-file.txt
lsattr /absolute/path/to/test-file.txt</code></div></div>In our lab, chattr returned exit 0 and lsattr displayed the i flag. Other letters such as e may already be present; the significant change for this test is i.<br />
<br />
If the command reports Operation not supported, investigate the filesystem and hosting environment. Containers, filesystem types and available capabilities can affect support. Do not claim protection is active without checking the result.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Verify a write is blocked</span><br />
Attempt a harmless append only on that disposable file:<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>printf 'disposable write test
' &gt;&gt; /absolute/path/to/test-file.txt</code></div></div>Our administrator-side write attempt failed with <span style="font-weight: bold;" class="mycode_b">Operation not permitted</span>, and the original file content remained unchanged. Read it again to confirm the attempted text was not added. This test verifies one file's behavior; it does not establish protection for every path on the VPS.<br />
<br />
If the append succeeds, stop and investigate the attribute and actual target path. Do not treat a successful chattr message alone as proof.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Remove protection before legitimate maintenance</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>sudo chattr -i /absolute/path/to/test-file.txt
lsattr /absolute/path/to/test-file.txt</code></div></div>Confirm the i flag is absent. On the disposable file, test the append again and read its contents. Our second write succeeded after unlocking. We then restored the original harmless text and checked that the final contents matched the original and the i flag remained absent.<br />
<br />
For a real protected configuration file, plan the maintenance process: unlock only the intended file, perform the reviewed change, verify the application and then reapply protection if it is still appropriate. Keep a record of protected paths so future updates do not fail unexpectedly.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Understand the aaPanel UI boundary</span><br />
The Files page in our panel has a Protected column and Unprotected controls. In this Free lab, using that control opened a Pro upgrade prompt rather than a protection dialog. That observation does not establish the internal mechanism or capabilities of the Pro implementation.<br />
<br />
Do not assume an SSH chattr change will be fully managed or accurately represented by every panel protection screen. Use lsattr and an actual disposable write test for this method. A separate Pro tutorial should test the native UI, enable/disable behavior and compatibility with application updates on a licensed test server.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Troubleshooting</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">chmod does not make the file writable:</span> check lsattr; ordinary permission changes do not remove immutable protection.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">File editor or deployment cannot save:</span> confirm whether the exact target is intentionally protected, then use the planned unlock process.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Operation not supported:</span> check filesystem support and virtualization restrictions rather than repeatedly changing permissions.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Operation not permitted when changing attributes:</span> check your administrative privileges and relevant capabilities.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Application updates fail:</span> review whether protection was applied to files that must change; avoid bulk protection of a live app.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">What our lab verified</span><ul class="mycode_list"><li>One disposable non-public file was created with harmless contents.<br />
</li>
<li>chattr +i succeeded and lsattr showed i.<br />
</li>
<li>A write was blocked and original contents stayed unchanged.<br />
</li>
<li>chattr -i succeeded and a subsequent write worked.<br />
</li>
<li>Original contents were restored and the file was left unlocked.<br />
</li>
</ul>
<br />
<span style="font-style: italic;" class="mycode_i">AdminsForum lab-tested SSH tutorial. The illustration is a formatted result transcript; native aaPanel Pro File Protection remains a separate test.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Enable Hotlink Protection in aaPanel Without Breaking Images]]></title>
			<link>https://adminsforum.com/Thread-guide-enable-hotlink-protection-in-aapanel-without-breaking-images</link>
			<pubDate>Wed, 14 Oct 2026 02:25:26 +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-enable-hotlink-protection-in-aapanel-without-breaking-images</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">aaPanel hotlink protection can restrict image requests based on their HTTP Referer header.</span> Open Website → Conf → Hotlink Protection, choose the protected extensions and allowed domains, then test actual requests. The empty-referrer setting matters: direct image links can fail when it is disabled.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested environment</span><br />
Ubuntu 22.04, aaPanel 8.0.7 Free Edition, Nginx 1.30.5 and a separate static demo website. We protected PNG files, allowed the demo hostname and used the panel's 404 response. Same-site requests returned 200, an outside referrer returned 404, and direct requests changed from 200 to 404 when we disabled empty-referrer access. We reverted the test configuration afterwards.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">What this feature does</span><br />
Hotlinking occurs when another page embeds a resource hosted on your server. Referrer filtering can reduce ordinary browser-based embedding from domains you have not allowed. It is not authentication, copyright enforcement or complete download prevention: the Referer header can be supplied by a client, and legitimate browsers sometimes omit it. Use an access-controlled delivery method when a file must be private.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Record your current settings</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Website</span>, locate the site and choose <span style="font-weight: bold;" class="mycode_b">Conf → Hotlink Protection</span>. Record whether protection is enabled, the suffix list, allowed domains, response and empty-referrer setting before editing. Work on a test site first.<br />
<br />
Our original demo settings had protection disabled, suffixes jpg,jpeg,gif,png,js,css, allowed domain demo.adminslab.com and response 404. We narrowed the test to <span style="font-weight: bold;" class="mycode_b">png</span> so other file types were outside this exercise. Protecting JavaScript or CSS without testing your integrations can affect more than images.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Set allowed domains and direct-access behaviour</span><br />
Use <span style="font-weight: bold;" class="mycode_b">URL suffix</span> for the comma-separated extensions you intend to protect. In <span style="font-weight: bold;" class="mycode_b">Access domain</span>, include the actual site hostname and any legitimate embedding domains required by your workflow. Do not copy our lab hostname into your own configuration.<br />
<br />
Select <span style="font-weight: bold;" class="mycode_b">Enable hotlink protection</span>. For the first test, also select <span style="font-weight: bold;" class="mycode_b">Allow empty HTTP_REFERER requests</span>. This allows requests without a Referer header while the allowed-domain check still applies to requests carrying one. Keep the configured 404 response for this walkthrough and click <span style="font-weight: bold;" class="mycode_b">Save</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=159" target="_blank" title="">hotlink-direct-allowed-20261013.jpg</a> (Size: 203.83 KB / Downloads: 8)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">PNG-only protection enabled, demo hostname allowed, and empty-referrer requests allowed.</span><br />
<br />
In our panel, changing these checkboxes submitted immediately; text fields and the Save button were separate controls. Wait for any submitting message to finish and recheck the visible states. Some fields became disabled while protection was enabled. Do not assume an unsaved-looking checkbox is only a draft.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Test three request types</span><br />
Choose one existing protected image. Our test used the static sample's /images/firefox-icon.png. Test the image directly, with the site's own page as Referer, and with an outside Referer. We used example.com only as a simulated header value; no request was sent to that domain.<br />
<br />
The verified results with empty-referrer access allowed 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>No Referer header:                     HTTP 200
Referer: https://demo.adminslab.com/    HTTP 200
Referer: https://example.com/          HTTP 404</code></div></div><br />
Optional commands for your own site:<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 -o /dev/null -w '%{http_code}
' 'https://YOUR_DOMAIN/images/test.png'
curl -o /dev/null -w '%{http_code}
' -e 'https://YOUR_DOMAIN/' 'https://YOUR_DOMAIN/images/test.png'
curl -o /dev/null -w '%{http_code}
' -e 'https://example.com/' 'https://YOUR_DOMAIN/images/test.png'</code></div></div>Replace the hostname and image path. These examples use Linux's /dev/null; on Windows use NUL. A 404 in the outside-referrer test does not mean the file was deleted. Compare it with the same-site response.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand the stricter empty-referrer option</span><br />
We then unchecked <span style="font-weight: bold;" class="mycode_b">Allow empty HTTP_REFERER requests</span> while protection remained enabled.<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=160" target="_blank" title="">hotlink-direct-blocked-20261013.jpg</a> (Size: 203.71 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Stricter test: empty-referrer requests are no longer allowed.</span><br />
<br />
Fresh requests returned <span style="font-weight: bold;" class="mycode_b">404</span> without a Referer and <span style="font-weight: bold;" class="mycode_b">200</span> with the allowed same-site Referer. This directly demonstrates the effect of the setting in our Nginx installation. A bookmarked image URL or a client that omits the header can be affected. Verify real pages, image previews and any required integrations before adopting that stricter setting. We did not test every browser, CDN or search-engine preview.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Revert the lab test or apply your chosen production policy</span><br />
For this tutorial we unchecked <span style="font-weight: bold;" class="mycode_b">Enable hotlink protection</span>, restored the original suffix list and saved. Both checkboxes returned to their original unchecked states. The allowed hostname and response stayed unchanged.<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=161" target="_blank" title="">hotlink-disabled-20261013.jpg</a> (Size: 204.81 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">The demo restored to its original disabled-protection state after testing.</span><br />
<br />
A fresh request with the simulated outside Referer then returned <span style="font-weight: bold;" class="mycode_b">200</span>, confirming cleanup. On your actual website, keep protection enabled only after choosing and verifying the access policy you need. Our disabled final state is lab cleanup, not a recommendation for every site.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Troubleshooting</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Images disappear on your own pages:</span> compare the actual embedding hostname with Access domain. Check the empty-referrer option and any privacy or referrer policy involved.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">External requests still succeed:</span> confirm the suffix matches the requested file and test the server response rather than a cached image. A CDN may serve a previously cached copy; this lab did not test CDN cache behaviour.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Direct links return 404:</span> repeat the request with and without a same-site Referer to distinguish filtering from a missing file.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">New domain or subdomain:</span> review the allowed-domain list after a site move. Test required root and www hostnames individually.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Files must be confidential:</span> referrer filtering is insufficient. Use real authentication or another appropriate access-control mechanism.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">Reference:</span> <a href="https://nginx.org/en/docs/http/ngx_http_referer_module.html" target="_blank" rel="noopener" class="mycode_url">Official Nginx Referer module documentation</a> explains its purpose and limitations.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Need help?</span> Include the aaPanel/web-server versions, protected suffix, allowed hostname, empty-referrer setting and status results in Server Security Support. Avoid sharing private URLs or tokens.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">aaPanel hotlink protection can restrict image requests based on their HTTP Referer header.</span> Open Website → Conf → Hotlink Protection, choose the protected extensions and allowed domains, then test actual requests. The empty-referrer setting matters: direct image links can fail when it is disabled.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Tested environment</span><br />
Ubuntu 22.04, aaPanel 8.0.7 Free Edition, Nginx 1.30.5 and a separate static demo website. We protected PNG files, allowed the demo hostname and used the panel's 404 response. Same-site requests returned 200, an outside referrer returned 404, and direct requests changed from 200 to 404 when we disabled empty-referrer access. We reverted the test configuration afterwards.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">What this feature does</span><br />
Hotlinking occurs when another page embeds a resource hosted on your server. Referrer filtering can reduce ordinary browser-based embedding from domains you have not allowed. It is not authentication, copyright enforcement or complete download prevention: the Referer header can be supplied by a client, and legitimate browsers sometimes omit it. Use an access-controlled delivery method when a file must be private.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Record your current settings</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Website</span>, locate the site and choose <span style="font-weight: bold;" class="mycode_b">Conf → Hotlink Protection</span>. Record whether protection is enabled, the suffix list, allowed domains, response and empty-referrer setting before editing. Work on a test site first.<br />
<br />
Our original demo settings had protection disabled, suffixes jpg,jpeg,gif,png,js,css, allowed domain demo.adminslab.com and response 404. We narrowed the test to <span style="font-weight: bold;" class="mycode_b">png</span> so other file types were outside this exercise. Protecting JavaScript or CSS without testing your integrations can affect more than images.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Set allowed domains and direct-access behaviour</span><br />
Use <span style="font-weight: bold;" class="mycode_b">URL suffix</span> for the comma-separated extensions you intend to protect. In <span style="font-weight: bold;" class="mycode_b">Access domain</span>, include the actual site hostname and any legitimate embedding domains required by your workflow. Do not copy our lab hostname into your own configuration.<br />
<br />
Select <span style="font-weight: bold;" class="mycode_b">Enable hotlink protection</span>. For the first test, also select <span style="font-weight: bold;" class="mycode_b">Allow empty HTTP_REFERER requests</span>. This allows requests without a Referer header while the allowed-domain check still applies to requests carrying one. Keep the configured 404 response for this walkthrough and click <span style="font-weight: bold;" class="mycode_b">Save</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=159" target="_blank" title="">hotlink-direct-allowed-20261013.jpg</a> (Size: 203.83 KB / Downloads: 8)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">PNG-only protection enabled, demo hostname allowed, and empty-referrer requests allowed.</span><br />
<br />
In our panel, changing these checkboxes submitted immediately; text fields and the Save button were separate controls. Wait for any submitting message to finish and recheck the visible states. Some fields became disabled while protection was enabled. Do not assume an unsaved-looking checkbox is only a draft.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Test three request types</span><br />
Choose one existing protected image. Our test used the static sample's /images/firefox-icon.png. Test the image directly, with the site's own page as Referer, and with an outside Referer. We used example.com only as a simulated header value; no request was sent to that domain.<br />
<br />
The verified results with empty-referrer access allowed 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>No Referer header:                     HTTP 200
Referer: https://demo.adminslab.com/    HTTP 200
Referer: https://example.com/          HTTP 404</code></div></div><br />
Optional commands for your own site:<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 -o /dev/null -w '%{http_code}
' 'https://YOUR_DOMAIN/images/test.png'
curl -o /dev/null -w '%{http_code}
' -e 'https://YOUR_DOMAIN/' 'https://YOUR_DOMAIN/images/test.png'
curl -o /dev/null -w '%{http_code}
' -e 'https://example.com/' 'https://YOUR_DOMAIN/images/test.png'</code></div></div>Replace the hostname and image path. These examples use Linux's /dev/null; on Windows use NUL. A 404 in the outside-referrer test does not mean the file was deleted. Compare it with the same-site response.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand the stricter empty-referrer option</span><br />
We then unchecked <span style="font-weight: bold;" class="mycode_b">Allow empty HTTP_REFERER requests</span> while protection remained enabled.<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=160" target="_blank" title="">hotlink-direct-blocked-20261013.jpg</a> (Size: 203.71 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Stricter test: empty-referrer requests are no longer allowed.</span><br />
<br />
Fresh requests returned <span style="font-weight: bold;" class="mycode_b">404</span> without a Referer and <span style="font-weight: bold;" class="mycode_b">200</span> with the allowed same-site Referer. This directly demonstrates the effect of the setting in our Nginx installation. A bookmarked image URL or a client that omits the header can be affected. Verify real pages, image previews and any required integrations before adopting that stricter setting. We did not test every browser, CDN or search-engine preview.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Revert the lab test or apply your chosen production policy</span><br />
For this tutorial we unchecked <span style="font-weight: bold;" class="mycode_b">Enable hotlink protection</span>, restored the original suffix list and saved. Both checkboxes returned to their original unchecked states. The allowed hostname and response stayed unchanged.<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=161" target="_blank" title="">hotlink-disabled-20261013.jpg</a> (Size: 204.81 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">The demo restored to its original disabled-protection state after testing.</span><br />
<br />
A fresh request with the simulated outside Referer then returned <span style="font-weight: bold;" class="mycode_b">200</span>, confirming cleanup. On your actual website, keep protection enabled only after choosing and verifying the access policy you need. Our disabled final state is lab cleanup, not a recommendation for every site.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Troubleshooting</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Images disappear on your own pages:</span> compare the actual embedding hostname with Access domain. Check the empty-referrer option and any privacy or referrer policy involved.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">External requests still succeed:</span> confirm the suffix matches the requested file and test the server response rather than a cached image. A CDN may serve a previously cached copy; this lab did not test CDN cache behaviour.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Direct links return 404:</span> repeat the request with and without a same-site Referer to distinguish filtering from a missing file.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">New domain or subdomain:</span> review the allowed-domain list after a site move. Test required root and www hostnames individually.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Files must be confidential:</span> referrer filtering is insufficient. Use real authentication or another appropriate access-control mechanism.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">Reference:</span> <a href="https://nginx.org/en/docs/http/ngx_http_referer_module.html" target="_blank" rel="noopener" class="mycode_url">Official Nginx Referer module documentation</a> explains its purpose and limitations.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Need help?</span> Include the aaPanel/web-server versions, protected suffix, allowed hostname, empty-referrer setting and status results in Server Security Support. Avoid sharing private URLs or tokens.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Install Fail2ban Manager in aaPanel and Verify SSH Protection]]></title>
			<link>https://adminsforum.com/Thread-guide-install-fail2ban-manager-in-aapanel-and-verify-ssh-protection</link>
			<pubDate>Tue, 13 Oct 2026 15:27: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-install-fail2ban-manager-in-aapanel-and-verify-ssh-protection</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Fail2ban watches configured logs and applies a ban action when failures reach a jail's threshold.</span> Installing a plugin is only the first step: the service, log source, filter and ban action must all match your server. This guide follows an actual Ubuntu 22.04 aaPanel lab installation.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Prepare before installation</span><br />
Keep your existing panel and SSH connections open, and confirm that the VPS provider console works. Record the actual SSH port. Review backups and firewall rules. Do not intentionally fail your own SSH login repeatedly to test a rule: you can block your management address. A firewall and strong authentication remain necessary.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Install the official manager</span><br />
Open <span style="font-weight: bold;" class="mycode_b">App Store → Official App → ALL</span>. Search for <span style="font-weight: bold;" class="mycode_b">Fail2ban</span>. Confirm the row says <span style="font-weight: bold;" class="mycode_b">Fail2ban Manager</span>, developer <span style="font-weight: bold;" class="mycode_b">official</span>, and review the displayed price. Our catalog listed it as Free. Click <span style="font-weight: bold;" class="mycode_b">Install</span>, inspect the version dialog and choose <span style="font-weight: bold;" class="mycode_b">Install Now</span>. Wait until the row changes to <span style="font-weight: bold;" class="mycode_b">Setting / Uninstall</span>. Our installation produced Manager version 2.2.5. Panel/plugin versions and availability can change.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Open the controls and check the service</span><br />
Choose <span style="font-weight: bold;" class="mycode_b">Setting → Service status</span>. The lab showed <span style="font-weight: bold;" class="mycode_b">Current status: On</span>. The manager also contains WebSite protection, Server protection, Black IP, White IP, Alarm Settings and CDN Provide. Installing this version produced SSH and FTP jail rows automatically; inspect the resulting rules immediately rather than assuming installation creates no active protection.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand a server-protection rule</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Server protection</span>. Existing services offer <span style="font-weight: bold;" class="mycode_b">Edit</span> and <span style="font-weight: bold;" class="mycode_b">Log</span>. The Create dialog offers these fields:<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=137" target="_blank" title="">fail2ban-rule-branded-20261013.jpg</a> (Size: 188.99 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Status:</span> whether the rule is enabled.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Maxretry:</span> the failure threshold used by that rule.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Findtime:</span> the period in which failures are counted, in seconds.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Bantime:</span> how long the ban lasts, in seconds.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Port:</span> the service's actual port; the default 22 is not correct for every SSH setup.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Server:</span> the selected service/filter family. This dialog listed sshd, mysql, dovecot, postfix and ftpd.<br />
</li>
</ul>
The illustrated Create dialog defaults are not a recommended policy. Our installed sshd and ftpd rows showed Maxretry 5, Findtime 300 and Bantime 86400. That ban duration is one day. Review whether that is appropriate before deployment. Do not create a duplicate service rule when one already exists. We inspected the dialog and cancelled it; no extra rule was created for this illustration.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Verify the backend, not just the plugin row</span><br />
Use aaPanel Terminal or your authorized SSH session for these read-only checks:<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>fail2ban-client ping
fail2ban-client status
fail2ban-client status sshd
fail2ban-client status ftpd
fail2ban-client -t</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=136" target="_blank" title="">fail2ban-proof-branded-20261013.jpg</a> (Size: 188.02 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Original lab checks: service responded, sshd and ftpd jails were listed, and the configuration test passed. IP addresses are omitted from the illustration.</span><br />
Our SSH jail used /var/log/auth.log and reported detected failures and two bans during observation. Those were service observations, not a deliberate controlled login test. The SSH listener remained available. This does not prove every rule blocks traffic correctly from every network.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Check the log path for each service</span><br />
The lab FTP jail reported /var/log/messages. Our follow-up test deliberately supplied an invalid password to the existing lab FTP account over trusted TLS. Pure-FTPd returned 530 and wrote the expected authentication failure to /var/log/messages. Localhost is excluded by the jail, so that local check did not ban the administrator. We then sent distinct synthetic failure records for documentation address 203.0.113.123: Fail2ban detected them, created a UFW REJECT rule, and removed it when the test address was unbanned. Other bans were preserved. This verifies real log placement plus synthetic detection/firewall enforcement; it does not prove external packet reachability. Repeated identical log messages can be collapsed by syslog, so use distinguishable records in a synthetic test.<br />
<br />
For SSH, confirm the backend fits your system's logging arrangement. Some installations use files; others use the system journal. If the expected events are missing, inspect the service logging and jail configuration before changing thresholds.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Review bans and recovery</span><br />
Use the relevant rule's <span style="font-weight: bold;" class="mycode_b">Log</span> control and the Black IP/White IP sections to inspect the manager's view. Check the exact IP and jail before unbanning a legitimate user. If you lose management access, use the provider console and investigate the specific ban. Avoid disabling all protection simply because one legitimate client was affected. Only add trusted addresses to exclusions; large or public ranges can undermine protection.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Website and CDN rules require a separate test</span><br />
Website protection depends on the correct web-server logs. The manager warns that rules need to be recreated after changing the web server or log path. A reverse proxy/CDN can alter which IP reaches the origin; verify real-client-IP handling before using IP-based bans. Do not ban a shared proxy address based on unverified logging. This guide does not configure website/CDN rules or notification accounts.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Installation result</span><br />
Manager 2.2.5 installed; service responded; two jails loaded; configuration test succeeded. SSH failures and bans were observed. FTP log placement, synthetic detection and the UFW ban/unban action subsequently passed. An external network ban test remains unverified. No new public port was opened for this plugin.<br />
<br />
<a href="https://adminsforum.com/Thread-guide-configure-aapanel-firewall-rules-without-losing-ssh-access" target="_blank" rel="noopener" class="mycode_url">Continue with aaPanel firewall rules</a>.<br />
<span style="font-weight: bold;" class="mycode_b">References:</span> <a href="https://www.aapanel.com/docs/Function/AppStore.html" target="_blank" rel="noopener" class="mycode_url">aaPanel App Store documentation</a> and <a href="https://github.com/fail2ban/fail2ban/wiki" target="_blank" rel="noopener" class="mycode_url">Fail2ban project documentation</a>. Screenshots and lab observations: © AdminsForum.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Fail2ban watches configured logs and applies a ban action when failures reach a jail's threshold.</span> Installing a plugin is only the first step: the service, log source, filter and ban action must all match your server. This guide follows an actual Ubuntu 22.04 aaPanel lab installation.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Prepare before installation</span><br />
Keep your existing panel and SSH connections open, and confirm that the VPS provider console works. Record the actual SSH port. Review backups and firewall rules. Do not intentionally fail your own SSH login repeatedly to test a rule: you can block your management address. A firewall and strong authentication remain necessary.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Install the official manager</span><br />
Open <span style="font-weight: bold;" class="mycode_b">App Store → Official App → ALL</span>. Search for <span style="font-weight: bold;" class="mycode_b">Fail2ban</span>. Confirm the row says <span style="font-weight: bold;" class="mycode_b">Fail2ban Manager</span>, developer <span style="font-weight: bold;" class="mycode_b">official</span>, and review the displayed price. Our catalog listed it as Free. Click <span style="font-weight: bold;" class="mycode_b">Install</span>, inspect the version dialog and choose <span style="font-weight: bold;" class="mycode_b">Install Now</span>. Wait until the row changes to <span style="font-weight: bold;" class="mycode_b">Setting / Uninstall</span>. Our installation produced Manager version 2.2.5. Panel/plugin versions and availability can change.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Open the controls and check the service</span><br />
Choose <span style="font-weight: bold;" class="mycode_b">Setting → Service status</span>. The lab showed <span style="font-weight: bold;" class="mycode_b">Current status: On</span>. The manager also contains WebSite protection, Server protection, Black IP, White IP, Alarm Settings and CDN Provide. Installing this version produced SSH and FTP jail rows automatically; inspect the resulting rules immediately rather than assuming installation creates no active protection.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Understand a server-protection rule</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Server protection</span>. Existing services offer <span style="font-weight: bold;" class="mycode_b">Edit</span> and <span style="font-weight: bold;" class="mycode_b">Log</span>. The Create dialog offers these fields:<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=137" target="_blank" title="">fail2ban-rule-branded-20261013.jpg</a> (Size: 188.99 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Status:</span> whether the rule is enabled.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Maxretry:</span> the failure threshold used by that rule.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Findtime:</span> the period in which failures are counted, in seconds.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Bantime:</span> how long the ban lasts, in seconds.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Port:</span> the service's actual port; the default 22 is not correct for every SSH setup.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Server:</span> the selected service/filter family. This dialog listed sshd, mysql, dovecot, postfix and ftpd.<br />
</li>
</ul>
The illustrated Create dialog defaults are not a recommended policy. Our installed sshd and ftpd rows showed Maxretry 5, Findtime 300 and Bantime 86400. That ban duration is one day. Review whether that is appropriate before deployment. Do not create a duplicate service rule when one already exists. We inspected the dialog and cancelled it; no extra rule was created for this illustration.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Verify the backend, not just the plugin row</span><br />
Use aaPanel Terminal or your authorized SSH session for these read-only checks:<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>fail2ban-client ping
fail2ban-client status
fail2ban-client status sshd
fail2ban-client status ftpd
fail2ban-client -t</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=136" target="_blank" title="">fail2ban-proof-branded-20261013.jpg</a> (Size: 188.02 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Original lab checks: service responded, sshd and ftpd jails were listed, and the configuration test passed. IP addresses are omitted from the illustration.</span><br />
Our SSH jail used /var/log/auth.log and reported detected failures and two bans during observation. Those were service observations, not a deliberate controlled login test. The SSH listener remained available. This does not prove every rule blocks traffic correctly from every network.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Check the log path for each service</span><br />
The lab FTP jail reported /var/log/messages. Our follow-up test deliberately supplied an invalid password to the existing lab FTP account over trusted TLS. Pure-FTPd returned 530 and wrote the expected authentication failure to /var/log/messages. Localhost is excluded by the jail, so that local check did not ban the administrator. We then sent distinct synthetic failure records for documentation address 203.0.113.123: Fail2ban detected them, created a UFW REJECT rule, and removed it when the test address was unbanned. Other bans were preserved. This verifies real log placement plus synthetic detection/firewall enforcement; it does not prove external packet reachability. Repeated identical log messages can be collapsed by syslog, so use distinguishable records in a synthetic test.<br />
<br />
For SSH, confirm the backend fits your system's logging arrangement. Some installations use files; others use the system journal. If the expected events are missing, inspect the service logging and jail configuration before changing thresholds.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Review bans and recovery</span><br />
Use the relevant rule's <span style="font-weight: bold;" class="mycode_b">Log</span> control and the Black IP/White IP sections to inspect the manager's view. Check the exact IP and jail before unbanning a legitimate user. If you lose management access, use the provider console and investigate the specific ban. Avoid disabling all protection simply because one legitimate client was affected. Only add trusted addresses to exclusions; large or public ranges can undermine protection.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Website and CDN rules require a separate test</span><br />
Website protection depends on the correct web-server logs. The manager warns that rules need to be recreated after changing the web server or log path. A reverse proxy/CDN can alter which IP reaches the origin; verify real-client-IP handling before using IP-based bans. Do not ban a shared proxy address based on unverified logging. This guide does not configure website/CDN rules or notification accounts.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Installation result</span><br />
Manager 2.2.5 installed; service responded; two jails loaded; configuration test succeeded. SSH failures and bans were observed. FTP log placement, synthetic detection and the UFW ban/unban action subsequently passed. An external network ban test remains unverified. No new public port was opened for this plugin.<br />
<br />
<a href="https://adminsforum.com/Thread-guide-configure-aapanel-firewall-rules-without-losing-ssh-access" target="_blank" rel="noopener" class="mycode_url">Continue with aaPanel firewall rules</a>.<br />
<span style="font-weight: bold;" class="mycode_b">References:</span> <a href="https://www.aapanel.com/docs/Function/AppStore.html" target="_blank" rel="noopener" class="mycode_url">aaPanel App Store documentation</a> and <a href="https://github.com/fail2ban/fail2ban/wiki" target="_blank" rel="noopener" class="mycode_url">Fail2ban project documentation</a>. Screenshots and lab observations: © AdminsForum.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Secure aaPanel After Installation: HTTPS, Access and Backups]]></title>
			<link>https://adminsforum.com/Thread-guide-secure-aapanel-after-installation-https-access-and-backups</link>
			<pubDate>Tue, 13 Oct 2026 13:17:03 +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-secure-aapanel-after-installation-https-access-and-backups</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">After installing aaPanel, secure management access before adding production websites.</span> This checklist separates settings verified on our lab from account changes you must complete yourself. It does not claim that enabling one option makes a server fully secure.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Save a recovery route first</span><br />
Confirm you can open the VPS provider console. Keep a working SSH session while changing management settings. Store the actual panel address and security entrance in a private password manager. Create an off-server backup of website files, databases and the configuration needed to restore them. A backup that has never been restored is not a verified recovery plan.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Use a hostname with trusted HTTPS</span><br />
Create a DNS-only record such as cp.example.com pointing to the panel server. aaPanel's port may not be supported by a CDN proxy; our lab uses 18443 with DNS-only resolution. In <span style="font-weight: bold;" class="mycode_b">Settings → Panel SSL</span>, request and install a certificate for the hostname. Open the panel using that exact name, not the IP address. Check the browser's certificate information and expiration date.<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=132" target="_blank" title="">panel-cert-branded-20261013.jpg</a> (Size: 53.76 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">The lab panel uses a trusted certificate for cp.adminslab.com. The private login entrance is intentionally omitted.</span><br />
<a href="https://adminsforum.com/Thread-guide-install-a-trusted-ssl-certificate-for-the-aapanel-login" target="_blank" rel="noopener" class="mycode_url">Follow the complete panel SSL tutorial</a>. Monitor renewal before expiry. A currently valid certificate does not prove that a future renewal has succeeded.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Review the firewall</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Security → Firewall</span> and preserve your actual SSH and panel ports. Keep only the services required for websites, mail and file transfers. Review TCP and UDP separately and check IPv6. Databases and internal web-server backends should not be generally accessible from the Internet. Our lab retains management access while denying direct database and backend ports; Redis also binds to localhost.<br />
<a href="https://adminsforum.com/Thread-guide-configure-aapanel-firewall-rules-without-losing-ssh-access" target="_blank" rel="noopener" class="mycode_url">Use the tested firewall walkthrough</a>. Do not run a firewall reset or remove a management rule before confirming a recovery route.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Strengthen the panel account</span><br />
Use a unique, strong password stored in your password manager. If your installed panel offers multi-factor authentication, enroll it and keep recovery information privately. Check the account or security settings for session controls and notifications. Sign in successfully from a second session before ending the first. Password rotation and MFA enrollment were <span style="font-weight: bold;" class="mycode_b">not performed</span> during this lab walkthrough; these require the owner to complete the credential and recovery steps.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Review SSH authentication</span><br />
Prepare a non-root administrator account and a tested SSH key before considering removal of password authentication. Confirm that the new account can sign in and use the administration privileges it needs. Keep the provider console available. Validate the SSH configuration before reloading it, and test another connection afterward. Do not disable root/password access based only on a screenshot or an untested key. The lab's SSH authentication method has not been changed in this article.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Use encrypted file transfer</span><br />
Use SFTP over SSH or explicitly encrypted FTPS. Restrict FTP users to the folder they need, deny anonymous access, validate the FTPS certificate and encrypt the data channel as well as the login. Our restricted lab account passed a protected upload/download check, and access outside its assigned folder was refused.<br />
<a href="https://adminsforum.com/Thread-guide-enable-ftps-encryption-and-ssl-for-pure-ftpd-in-aapanel" target="_blank" rel="noopener" class="mycode_url">FTPS configuration and certificate guide</a>. The lab FTPS certificate bundle was manually deployed: renewal must also update that service's bundle and be verified.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Keep runtime versions and plugins maintainable</span><br />
Review panel, operating-system and installed app updates. Back up first and check compatibility before a major runtime change. The App Store may still list old PHP versions; availability does not mean security support. Remove unused plugins through the supported uninstall workflow after checking dependencies. Avoid installing every optional service on a small VPS.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Verify backups without overwriting the live site</span><br />
Check archive integrity, extract into an isolated private folder, import the database under a separate name and verify the staged application. Keep staged credentials and files out of the public web root. Our lab restore rehearsal checked 3,935 file hashes, imported 12 tables and bootstrapped WordPress in an isolated copy. It did not overwrite the live site or prove every browser workflow.<br />
<a href="https://adminsforum.com/Thread-guide-verify-a-full-wordpress-backup-restore-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Full restore verification walkthrough</a>.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Monitor and repeat the checks</span><br />
Review panel/SSH login events, service failures, disk space, backup results and certificate expiry. Investigate unexpected open ports after installing apps. Test website access, mail and file transfers after changes. Store logs privately and redact credentials, tokens and personal details before posting a support question.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Lab verification summary</span><br />
Trusted panel HTTPS, reviewed IPv4/IPv6 firewall rules, protected FTPS, localhost Redis and an isolated WordPress restore were checked. Owner password rotation, MFA enrollment and SSH-key migration remain separate owner actions. These checks are useful evidence, not a security audit of every installed application.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference:</span> <a href="https://www.aapanel.com/docs/Function/Settings.html" target="_blank" rel="noopener" class="mycode_url">aaPanel Settings documentation</a>. Original lab image: © AdminsForum.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">After installing aaPanel, secure management access before adding production websites.</span> This checklist separates settings verified on our lab from account changes you must complete yourself. It does not claim that enabling one option makes a server fully secure.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Save a recovery route first</span><br />
Confirm you can open the VPS provider console. Keep a working SSH session while changing management settings. Store the actual panel address and security entrance in a private password manager. Create an off-server backup of website files, databases and the configuration needed to restore them. A backup that has never been restored is not a verified recovery plan.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Use a hostname with trusted HTTPS</span><br />
Create a DNS-only record such as cp.example.com pointing to the panel server. aaPanel's port may not be supported by a CDN proxy; our lab uses 18443 with DNS-only resolution. In <span style="font-weight: bold;" class="mycode_b">Settings → Panel SSL</span>, request and install a certificate for the hostname. Open the panel using that exact name, not the IP address. Check the browser's certificate information and expiration date.<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=132" target="_blank" title="">panel-cert-branded-20261013.jpg</a> (Size: 53.76 KB / Downloads: 7)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">The lab panel uses a trusted certificate for cp.adminslab.com. The private login entrance is intentionally omitted.</span><br />
<a href="https://adminsforum.com/Thread-guide-install-a-trusted-ssl-certificate-for-the-aapanel-login" target="_blank" rel="noopener" class="mycode_url">Follow the complete panel SSL tutorial</a>. Monitor renewal before expiry. A currently valid certificate does not prove that a future renewal has succeeded.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Review the firewall</span><br />
Open <span style="font-weight: bold;" class="mycode_b">Security → Firewall</span> and preserve your actual SSH and panel ports. Keep only the services required for websites, mail and file transfers. Review TCP and UDP separately and check IPv6. Databases and internal web-server backends should not be generally accessible from the Internet. Our lab retains management access while denying direct database and backend ports; Redis also binds to localhost.<br />
<a href="https://adminsforum.com/Thread-guide-configure-aapanel-firewall-rules-without-losing-ssh-access" target="_blank" rel="noopener" class="mycode_url">Use the tested firewall walkthrough</a>. Do not run a firewall reset or remove a management rule before confirming a recovery route.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Strengthen the panel account</span><br />
Use a unique, strong password stored in your password manager. If your installed panel offers multi-factor authentication, enroll it and keep recovery information privately. Check the account or security settings for session controls and notifications. Sign in successfully from a second session before ending the first. Password rotation and MFA enrollment were <span style="font-weight: bold;" class="mycode_b">not performed</span> during this lab walkthrough; these require the owner to complete the credential and recovery steps.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Review SSH authentication</span><br />
Prepare a non-root administrator account and a tested SSH key before considering removal of password authentication. Confirm that the new account can sign in and use the administration privileges it needs. Keep the provider console available. Validate the SSH configuration before reloading it, and test another connection afterward. Do not disable root/password access based only on a screenshot or an untested key. The lab's SSH authentication method has not been changed in this article.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Use encrypted file transfer</span><br />
Use SFTP over SSH or explicitly encrypted FTPS. Restrict FTP users to the folder they need, deny anonymous access, validate the FTPS certificate and encrypt the data channel as well as the login. Our restricted lab account passed a protected upload/download check, and access outside its assigned folder was refused.<br />
<a href="https://adminsforum.com/Thread-guide-enable-ftps-encryption-and-ssl-for-pure-ftpd-in-aapanel" target="_blank" rel="noopener" class="mycode_url">FTPS configuration and certificate guide</a>. The lab FTPS certificate bundle was manually deployed: renewal must also update that service's bundle and be verified.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">7. Keep runtime versions and plugins maintainable</span><br />
Review panel, operating-system and installed app updates. Back up first and check compatibility before a major runtime change. The App Store may still list old PHP versions; availability does not mean security support. Remove unused plugins through the supported uninstall workflow after checking dependencies. Avoid installing every optional service on a small VPS.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">8. Verify backups without overwriting the live site</span><br />
Check archive integrity, extract into an isolated private folder, import the database under a separate name and verify the staged application. Keep staged credentials and files out of the public web root. Our lab restore rehearsal checked 3,935 file hashes, imported 12 tables and bootstrapped WordPress in an isolated copy. It did not overwrite the live site or prove every browser workflow.<br />
<a href="https://adminsforum.com/Thread-guide-verify-a-full-wordpress-backup-restore-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Full restore verification walkthrough</a>.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">9. Monitor and repeat the checks</span><br />
Review panel/SSH login events, service failures, disk space, backup results and certificate expiry. Investigate unexpected open ports after installing apps. Test website access, mail and file transfers after changes. Store logs privately and redact credentials, tokens and personal details before posting a support question.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Lab verification summary</span><br />
Trusted panel HTTPS, reviewed IPv4/IPv6 firewall rules, protected FTPS, localhost Redis and an isolated WordPress restore were checked. Owner password rotation, MFA enrollment and SSH-key migration remain separate owner actions. These checks are useful evidence, not a security audit of every installed application.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference:</span> <a href="https://www.aapanel.com/docs/Function/Settings.html" target="_blank" rel="noopener" class="mycode_url">aaPanel Settings documentation</a>. Original lab image: © AdminsForum.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Configure aaPanel Firewall Rules Without Losing SSH Access]]></title>
			<link>https://adminsforum.com/Thread-guide-configure-aapanel-firewall-rules-without-losing-ssh-access</link>
			<pubDate>Tue, 13 Oct 2026 13:15:30 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://adminsforum.com/member.php?action=profile&uid=2">DEV</a>]]></dc:creator>
			<guid isPermaLink="false">https://adminsforum.com/Thread-guide-configure-aapanel-firewall-rules-without-losing-ssh-access</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">A firewall should allow the services you use and block direct access to internal services.</span> This walkthrough shows the rules checked on our Ubuntu aaPanel lab. Your panel, SSH and application ports may differ: inspect them before making changes.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Prepare a recovery route</span><br />
Keep the current SSH session and panel tab open. Make sure your VPS provider console works before changing SSH or panel rules. Record your actual SSH port and panel URL. Export or privately copy the existing firewall rules so you can restore the previous configuration. Do not publish that backup: it can include infrastructure details.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Inspect the existing firewall</span><br />
In aaPanel, open <span style="font-weight: bold;" class="mycode_b">Security → Firewall</span>. Look at protocol, port, Allow/Deny, direction and source. On Ubuntu, the following read-only commands help confirm the effective configuration:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>sudo ufw status verbose
sudo ufw status numbered
sudo ss -lntup</code></div></div>A listening service is not necessarily reachable from the Internet. The listener report and firewall rules answer different questions. Check IPv6 rules as well as IPv4. Do not reset UFW simply to reproduce a tutorial.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Preserve management and application access</span><br />
Our lab uses SSH TCP 22 and panel port 18443. The panel also has a UDP listener on 18443, so its existing TCP and UDP rules were preserved. Do not copy this port number if yours differs. Preserve HTTP/HTTPS for websites and the mail or FTP ports you actually need. Passive FTP also needs its configured passive port range; opening port 21 alone is insufficient. Ports 887/888 were left unchanged because existing aaPanel applications use them.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Block direct backend and database access</span><br />
Our existing rules already denied TCP 7080, 8188–8190 and 8288–8290. We found backend UDP listeners too and added matching UDP denies. We also added explicit TCP denies for database port 3306 and Redis port 6379. Redis was already bound to localhost. These rules were added for IPv4 and IPv6, ahead of general rules.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Important:</span> A remote database application or deliberately public backend needs its own reviewed access plan. A broad deny can break it. Before adding a rule, check existing allows and identify the clients that depend on that port. Prefer a private network and specific trusted sources where remote database access is required.<br />
<br />
To create a rule in the panel, choose <span style="font-weight: bold;" class="mycode_b">Add port rule</span>, select the correct protocol, enter the port or range, choose <span style="font-weight: bold;" class="mycode_b">Deny</span> for unwanted inbound access, and review the source and direction before saving. Labels can vary by panel version. Apply one change at a time. Review ordering afterward: an earlier allow can defeat a later deny.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Verify the result</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=131" target="_blank" title="">firewall-branded-20261013.jpg</a> (Size: 141.39 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Original lab result: explicit backend/database denies in both address families, with SSH and panel rules preserved.</span><br />
Our post-change checks confirmed the SSH listener remained available and the panel still passed trusted certificate verification using TLS 1.3. Existing application allow rules were preserved. This evidence is a rules review and service check; it is not a comprehensive external penetration test or an external UDP reachability test.<br />
<br />
Open a second SSH connection and sign in to the panel before closing your original session. Check your websites, mail and FTPS from the clients that use them. A timeout on a blocked port is expected; a failed website or management login needs investigation. The overview's “Allowed ports” summary is less useful than the actual Allow/Deny table and effective operating-system rules.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Recovery and ongoing maintenance</span><br />
If access breaks, use the provider console and restore the reviewed previous rules. Remove or amend the specific conflicting rule rather than disabling the firewall indefinitely. Recheck rules after installing apps, changing service ports or enabling IPv6. Keep databases and internal backend services protected even when the panel reports them as listening.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Related guides</span><br />
<a href="https://adminsforum.com/Thread-guide-enable-ftps-encryption-and-ssl-for-pure-ftpd-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Enable secure FTPS</a><br />
<a href="https://adminsforum.com/Thread-guide-install-a-trusted-ssl-certificate-for-the-aapanel-login" target="_blank" rel="noopener" class="mycode_url">Install trusted panel HTTPS</a><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference:</span> <a href="https://ubuntu.com/server/docs/how-to/security/firewalls/" target="_blank" rel="noopener" class="mycode_url">Ubuntu firewall documentation</a>. Screenshots and lab verification: © AdminsForum.]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">A firewall should allow the services you use and block direct access to internal services.</span> This walkthrough shows the rules checked on our Ubuntu aaPanel lab. Your panel, SSH and application ports may differ: inspect them before making changes.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Prepare a recovery route</span><br />
Keep the current SSH session and panel tab open. Make sure your VPS provider console works before changing SSH or panel rules. Record your actual SSH port and panel URL. Export or privately copy the existing firewall rules so you can restore the previous configuration. Do not publish that backup: it can include infrastructure details.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Inspect the existing firewall</span><br />
In aaPanel, open <span style="font-weight: bold;" class="mycode_b">Security → Firewall</span>. Look at protocol, port, Allow/Deny, direction and source. On Ubuntu, the following read-only commands help confirm the effective configuration:<br />
<div class="codeblock"><div class="title af-code-title"><span>Code:</span><button type="button" class="af-code-copy" aria-label="Copy code" title="Copy code"><i class="far fa-copy" aria-hidden="true"></i><span>Copy</span></button><span class="af-code-status" role="status" aria-live="polite"></span></div><div class="body" dir="ltr"><code>sudo ufw status verbose
sudo ufw status numbered
sudo ss -lntup</code></div></div>A listening service is not necessarily reachable from the Internet. The listener report and firewall rules answer different questions. Check IPv6 rules as well as IPv4. Do not reset UFW simply to reproduce a tutorial.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Preserve management and application access</span><br />
Our lab uses SSH TCP 22 and panel port 18443. The panel also has a UDP listener on 18443, so its existing TCP and UDP rules were preserved. Do not copy this port number if yours differs. Preserve HTTP/HTTPS for websites and the mail or FTP ports you actually need. Passive FTP also needs its configured passive port range; opening port 21 alone is insufficient. Ports 887/888 were left unchanged because existing aaPanel applications use them.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Block direct backend and database access</span><br />
Our existing rules already denied TCP 7080, 8188–8190 and 8288–8290. We found backend UDP listeners too and added matching UDP denies. We also added explicit TCP denies for database port 3306 and Redis port 6379. Redis was already bound to localhost. These rules were added for IPv4 and IPv6, ahead of general rules.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Important:</span> A remote database application or deliberately public backend needs its own reviewed access plan. A broad deny can break it. Before adding a rule, check existing allows and identify the clients that depend on that port. Prefer a private network and specific trusted sources where remote database access is required.<br />
<br />
To create a rule in the panel, choose <span style="font-weight: bold;" class="mycode_b">Add port rule</span>, select the correct protocol, enter the port or range, choose <span style="font-weight: bold;" class="mycode_b">Deny</span> for unwanted inbound access, and review the source and direction before saving. Labels can vary by panel version. Apply one change at a time. Review ordering afterward: an earlier allow can defeat a later deny.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Verify the result</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=131" target="_blank" title="">firewall-branded-20261013.jpg</a> (Size: 141.39 KB / Downloads: 5)
<!-- end: postbit_attachments_attachment --><br />
<span style="font-style: italic;" class="mycode_i">Original lab result: explicit backend/database denies in both address families, with SSH and panel rules preserved.</span><br />
Our post-change checks confirmed the SSH listener remained available and the panel still passed trusted certificate verification using TLS 1.3. Existing application allow rules were preserved. This evidence is a rules review and service check; it is not a comprehensive external penetration test or an external UDP reachability test.<br />
<br />
Open a second SSH connection and sign in to the panel before closing your original session. Check your websites, mail and FTPS from the clients that use them. A timeout on a blocked port is expected; a failed website or management login needs investigation. The overview's “Allowed ports” summary is less useful than the actual Allow/Deny table and effective operating-system rules.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">6. Recovery and ongoing maintenance</span><br />
If access breaks, use the provider console and restore the reviewed previous rules. Remove or amend the specific conflicting rule rather than disabling the firewall indefinitely. Recheck rules after installing apps, changing service ports or enabling IPv6. Keep databases and internal backend services protected even when the panel reports them as listening.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Related guides</span><br />
<a href="https://adminsforum.com/Thread-guide-enable-ftps-encryption-and-ssl-for-pure-ftpd-in-aapanel" target="_blank" rel="noopener" class="mycode_url">Enable secure FTPS</a><br />
<a href="https://adminsforum.com/Thread-guide-install-a-trusted-ssl-certificate-for-the-aapanel-login" target="_blank" rel="noopener" class="mycode_url">Install trusted panel HTTPS</a><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Reference:</span> <a href="https://ubuntu.com/server/docs/how-to/security/firewalls/" target="_blank" rel="noopener" class="mycode_url">Ubuntu firewall documentation</a>. Screenshots and lab verification: © AdminsForum.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Change Your aaPanel Free Edition Password]]></title>
			<link>https://adminsforum.com/Thread-guide-change-your-aapanel-free-edition-password</link>
			<pubDate>Sun, 11 Oct 2026 00:11:29 +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-change-your-aapanel-free-edition-password</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Change your aaPanel login password under Settings → Global → Panel password → Modify.</span> This changes the panel account password, not your VPS SSH password or a website database password.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Before you begin</span><br />
Keep working SSH access and your server provider’s recovery console available. Save the full panel address privately, including its port and security entrance. Use a password manager to generate and store a long, unique password. Do not reuse your forum, email or SSH password.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Open the password settings</span><br />
Log in to your panel, open Settings and select Global. Find Panel password under Authentication &amp; Security, then click Modify. You can use Search settings to locate it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Complete the change-password form</span><br />
The current aaPanel Free Edition 8.0.6 form has three fields: Old Password, New Password and Repeat. Enter your current panel password, your chosen new password and the same new password again. Check that the confirmation matches before clicking Confirm. The screenshot below has its values hidden.<br />
<img src="https://adminsforum.com/attachment.php?aid=12" loading="lazy"  alt="[Image: attachment.php?aid=12]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Verify the new login</span><br />
After the panel reports success, open its saved HTTPS address in a separate private browser window and sign in using the new password. Retain recovery access until this fresh login works. Update the password-manager entry and close any session you no longer need.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Forgot the current password?</span><br />
The normal form requires the old password. If you own the server and have authorized root SSH access, aaPanel’s official Quick Start documents <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>bt 5</code></div></div> as the password-reset command. Follow the interactive prompt privately, then test the panel login. Never paste the resulting password or complete panel login output into a forum post.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Common problems</span><br />
If Old Password is rejected, check that you are entering the panel password rather than the Linux root password. If Repeat does not match, re-enter both new-password fields. If the page returns 404 before a login form appears, verify the saved security entrance; that is a different problem from an incorrect password.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Verification note</span><br />
The settings route and three-field form were inspected on our Ubuntu 22.04.5 / aaPanel Free 8.0.6 lab on 10 October 2026. We cancelled the form to preserve the tutorial lab login; a completed password change is not claimed.<br />
<br />
<a href="https://adminsforum.com/Thread-guide-install-aapanel-free-edition-on-ubuntu-22-04" target="_blank" rel="noopener" class="mycode_url">Install aaPanel Free Edition on Ubuntu 22.04</a><br />
<a href="https://adminsforum.com/Thread-guide-aapanel-free-edition-install-nginx-php-mariadb" target="_blank" rel="noopener" class="mycode_url">Web stack setup and tutorial series</a><br />
<a href="https://adminsforum.com/Thread-guide-secure-aapanel-free-edition-https-ssh-keys-panel-port" target="_blank" rel="noopener" class="mycode_url">Secure aaPanel Free Edition</a><br />
<a href="https://www.aapanel.com/docs/guide/quickstart.html" target="_blank" rel="noopener" class="mycode_url">Official aaPanel Quick Start and password recovery</a><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=12" target="_blank" title="">password-annotated-20261010.jpg</a> (Size: 25.93 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Change your aaPanel login password under Settings → Global → Panel password → Modify.</span> This changes the panel account password, not your VPS SSH password or a website database password.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Before you begin</span><br />
Keep working SSH access and your server provider’s recovery console available. Save the full panel address privately, including its port and security entrance. Use a password manager to generate and store a long, unique password. Do not reuse your forum, email or SSH password.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Open the password settings</span><br />
Log in to your panel, open Settings and select Global. Find Panel password under Authentication &amp; Security, then click Modify. You can use Search settings to locate it.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Complete the change-password form</span><br />
The current aaPanel Free Edition 8.0.6 form has three fields: Old Password, New Password and Repeat. Enter your current panel password, your chosen new password and the same new password again. Check that the confirmation matches before clicking Confirm. The screenshot below has its values hidden.<br />
<img src="https://adminsforum.com/attachment.php?aid=12" loading="lazy"  alt="[Image: attachment.php?aid=12]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Verify the new login</span><br />
After the panel reports success, open its saved HTTPS address in a separate private browser window and sign in using the new password. Retain recovery access until this fresh login works. Update the password-manager entry and close any session you no longer need.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Forgot the current password?</span><br />
The normal form requires the old password. If you own the server and have authorized root SSH access, aaPanel’s official Quick Start documents <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>bt 5</code></div></div> as the password-reset command. Follow the interactive prompt privately, then test the panel login. Never paste the resulting password or complete panel login output into a forum post.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Common problems</span><br />
If Old Password is rejected, check that you are entering the panel password rather than the Linux root password. If Repeat does not match, re-enter both new-password fields. If the page returns 404 before a login form appears, verify the saved security entrance; that is a different problem from an incorrect password.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Verification note</span><br />
The settings route and three-field form were inspected on our Ubuntu 22.04.5 / aaPanel Free 8.0.6 lab on 10 October 2026. We cancelled the form to preserve the tutorial lab login; a completed password change is not claimed.<br />
<br />
<a href="https://adminsforum.com/Thread-guide-install-aapanel-free-edition-on-ubuntu-22-04" target="_blank" rel="noopener" class="mycode_url">Install aaPanel Free Edition on Ubuntu 22.04</a><br />
<a href="https://adminsforum.com/Thread-guide-aapanel-free-edition-install-nginx-php-mariadb" target="_blank" rel="noopener" class="mycode_url">Web stack setup and tutorial series</a><br />
<a href="https://adminsforum.com/Thread-guide-secure-aapanel-free-edition-https-ssh-keys-panel-port" target="_blank" rel="noopener" class="mycode_url">Secure aaPanel Free Edition</a><br />
<a href="https://www.aapanel.com/docs/guide/quickstart.html" target="_blank" rel="noopener" class="mycode_url">Official aaPanel Quick Start and password recovery</a><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=12" target="_blank" title="">password-annotated-20261010.jpg</a> (Size: 25.93 KB / Downloads: 6)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Secure aaPanel Free Edition: HTTPS, SSH Keys & Panel Port]]></title>
			<link>https://adminsforum.com/Thread-guide-secure-aapanel-free-edition-https-ssh-keys-panel-port</link>
			<pubDate>Sat, 10 Oct 2026 23:08:12 +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-secure-aapanel-free-edition-https-ssh-keys-panel-port</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Protect aaPanel Free Edition management access with HTTPS, a carefully tested panel-port change and SSH keys.</span> This guide records our Ubuntu 22.04 lab results from 10 October 2026. It follows <a href="https://adminsforum.com/Thread-guide-install-aapanel-free-edition-on-ubuntu-22-04" target="_blank" rel="noopener" class="mycode_url">panel installation</a> and <a href="https://adminsforum.com/Thread-guide-aapanel-free-edition-install-nginx-php-mariadb" target="_blank" rel="noopener" class="mycode_url">web stack setup</a>.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Keep a recovery route and back up configuration</span></span><br />
Before changing access settings, keep your provider's recovery console available and an existing SSH session open. Save configuration backups off the server. Our lab has no snapshots, so we saved an off-server copy of the SSH, firewall, Nginx and panel configuration.<br />
<br />
A configuration archive is not a complete website/database backup. aaPanel's Auto Backup Panel setting also states that it excludes website and MySQL data. A separate backup-and-restore exercise is required for those.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Check panel HTTPS</span></span><br />
Open <span style="font-weight: bold;" class="mycode_b">Settings → Panel SSL</span>. The numbered screenshot shows HTTPS enabled, a trusted certificate and its expiry information:<br />
<br />
<img src="https://adminsforum.com/attachment.php?aid=5" loading="lazy"  alt="[Image: attachment.php?aid=5]" class="mycode_img" /><br />
<br />
Our panel already had a certificate that validated without bypassing browser warnings. Check your own hostname/IP, certificate status and expiry. The lab's IP certificate has a short lifetime; renewal still needs verification. Panel HTTPS and your website's HTTPS certificate are separate settings.<br />
<br />
If your browser reports a certificate error, investigate it before sending login credentials. Enabling a switch alone is not proof that the certificate is valid for the address you use.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Change the panel port without locking yourself out</span></span><br />
Changing the port can reduce routine scanning noise, but it does not replace strong authentication or access restrictions. We used 18443 as an example; choose an unused port appropriate for your setup.<br />
<br />
<ol type="1" class="mycode_list"><li>Note the current panel port and keep the current SSH session open.<br />
</li>
<li>Allow the new TCP port in the server firewall and any provider security group first. Restrict management access to trusted sources when practical.<br />
</li>
<li>In <span style="font-weight: bold;" class="mycode_b">Settings → Panel port → Modify</span>, enter the new port.<br />
</li>
<li>Read the dialog, acknowledge that the new port is allowed, then confirm. The panel restarts.<br />
</li>
<li>Open the new HTTPS URL with the same private entrance path. Sign in through a fresh connection.<br />
</li>
<li>Only after the new connection works, remove the old management-port firewall rule.<br />
</li>
</ol>
<br />
<img src="https://adminsforum.com/attachment.php?aid=6" loading="lazy"  alt="[Image: attachment.php?aid=6]" class="mycode_img" /><br />
<br />
Our new panel login succeeded before we removed the old firewall opening. Preserve the private entrance path and credentials in secure notes, not public screenshots. If access fails, use the still-open SSH session or provider console to restore the previous port/firewall configuration.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">4. Test SSH key access</span></span><br />
Generate a dedicated key on your own computer. An interactive key can use a passphrase:<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-keygen -t ed25519 -f ~/.ssh/aapanel_lab</code></div></div>Copy the public key to the correct server account. On a workstation with ssh-copy-id:<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-copy-id -i ~/.ssh/aapanel_lab.pub YOUR_USER@YOUR_SERVER_IP</code></div></div>Windows OpenSSH users can add the public key through their existing authenticated session. Keep the private key on your computer; only the .pub key belongs in the server's authorized_keys file. Verify the server host fingerprint through a trusted route.<br />
<br />
Open a fresh connection with the key:<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 -i ~/.ssh/aapanel_lab YOUR_USER@YOUR_SERVER_IP</code></div></div>We tested fresh Ed25519 sessions before and after reboot. We retained password access during the disposable lab exercises. For production, plan a separate tested move to a sudo account and key-only authentication; do not disable a working recovery route before verifying its replacement.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">5. Review the remaining protections</span></span><br />
Our aaPanel Free 8.0.6 interface includes <span style="font-weight: bold;" class="mycode_b">Google Authenticator</span> and <span style="font-weight: bold;" class="mycode_b">Authorized IP</span> controls. We have not enabled them in this lab: authenticator enrollment needs the owner's device, and an allowlist needs a stable management address or VPN. Configure and test these for your environment without blocking legitimate access or certificate renewal.<br />
<br />
Review optional phpMyAdmin and FTP exposure. MariaDB does not need a public database-port opening for a website running on the same server. Use encrypted file transfer and allow only the services you actually need.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Verified results and remaining checks</span></span><br />
Our Ubuntu updates and reboot completed. Fresh SSH key access, panel login, Nginx, MariaDB and PHP-FPM recovered successfully. The local default website returned HTTP 200. The panel-port change and current certificate validation passed.<br />
<br />
We also disabled phpMyAdmin’s separate public-access service and verified that the setting remained off. Its authenticated panel launch still needs troubleshooting; see the <a href="https://adminsforum.com/Thread-guide-install-phpmyadmin-in-aapanel-free-edition" target="_blank" rel="noopener" class="mycode_url">phpMyAdmin installation guide</a>.<br />
<br />
Certificate renewal, two-factor enrollment, a stable management allowlist and full website/database restore testing remain separate checks. This guide does not claim that every production-hardening task is complete.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Next:</span> Add a website, connect its domain, issue its own HTTPS certificate and create its database.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References:</span> <a href="https://www.aapanel.com/docs/Function/Settings.html" target="_blank" rel="noopener" class="mycode_url">aaPanel Settings documentation</a> and <a href="https://ubuntu.com/server/docs/how-to/security/openssh-server/" target="_blank" rel="noopener" class="mycode_url">Ubuntu OpenSSH documentation</a>.<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=5" target="_blank" title="">aapanel-ssl-annotated-20261010.png</a> (Size: 85.38 KB / Downloads: 22)
<!-- end: postbit_attachments_attachment --><br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=6" target="_blank" title="">aapanel-port-dialog-annotated-20261010.png</a> (Size: 117.83 KB / Downloads: 17)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Protect aaPanel Free Edition management access with HTTPS, a carefully tested panel-port change and SSH keys.</span> This guide records our Ubuntu 22.04 lab results from 10 October 2026. It follows <a href="https://adminsforum.com/Thread-guide-install-aapanel-free-edition-on-ubuntu-22-04" target="_blank" rel="noopener" class="mycode_url">panel installation</a> and <a href="https://adminsforum.com/Thread-guide-aapanel-free-edition-install-nginx-php-mariadb" target="_blank" rel="noopener" class="mycode_url">web stack setup</a>.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Keep a recovery route and back up configuration</span></span><br />
Before changing access settings, keep your provider's recovery console available and an existing SSH session open. Save configuration backups off the server. Our lab has no snapshots, so we saved an off-server copy of the SSH, firewall, Nginx and panel configuration.<br />
<br />
A configuration archive is not a complete website/database backup. aaPanel's Auto Backup Panel setting also states that it excludes website and MySQL data. A separate backup-and-restore exercise is required for those.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Check panel HTTPS</span></span><br />
Open <span style="font-weight: bold;" class="mycode_b">Settings → Panel SSL</span>. The numbered screenshot shows HTTPS enabled, a trusted certificate and its expiry information:<br />
<br />
<img src="https://adminsforum.com/attachment.php?aid=5" loading="lazy"  alt="[Image: attachment.php?aid=5]" class="mycode_img" /><br />
<br />
Our panel already had a certificate that validated without bypassing browser warnings. Check your own hostname/IP, certificate status and expiry. The lab's IP certificate has a short lifetime; renewal still needs verification. Panel HTTPS and your website's HTTPS certificate are separate settings.<br />
<br />
If your browser reports a certificate error, investigate it before sending login credentials. Enabling a switch alone is not proof that the certificate is valid for the address you use.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Change the panel port without locking yourself out</span></span><br />
Changing the port can reduce routine scanning noise, but it does not replace strong authentication or access restrictions. We used 18443 as an example; choose an unused port appropriate for your setup.<br />
<br />
<ol type="1" class="mycode_list"><li>Note the current panel port and keep the current SSH session open.<br />
</li>
<li>Allow the new TCP port in the server firewall and any provider security group first. Restrict management access to trusted sources when practical.<br />
</li>
<li>In <span style="font-weight: bold;" class="mycode_b">Settings → Panel port → Modify</span>, enter the new port.<br />
</li>
<li>Read the dialog, acknowledge that the new port is allowed, then confirm. The panel restarts.<br />
</li>
<li>Open the new HTTPS URL with the same private entrance path. Sign in through a fresh connection.<br />
</li>
<li>Only after the new connection works, remove the old management-port firewall rule.<br />
</li>
</ol>
<br />
<img src="https://adminsforum.com/attachment.php?aid=6" loading="lazy"  alt="[Image: attachment.php?aid=6]" class="mycode_img" /><br />
<br />
Our new panel login succeeded before we removed the old firewall opening. Preserve the private entrance path and credentials in secure notes, not public screenshots. If access fails, use the still-open SSH session or provider console to restore the previous port/firewall configuration.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">4. Test SSH key access</span></span><br />
Generate a dedicated key on your own computer. An interactive key can use a passphrase:<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-keygen -t ed25519 -f ~/.ssh/aapanel_lab</code></div></div>Copy the public key to the correct server account. On a workstation with ssh-copy-id:<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-copy-id -i ~/.ssh/aapanel_lab.pub YOUR_USER@YOUR_SERVER_IP</code></div></div>Windows OpenSSH users can add the public key through their existing authenticated session. Keep the private key on your computer; only the .pub key belongs in the server's authorized_keys file. Verify the server host fingerprint through a trusted route.<br />
<br />
Open a fresh connection with the key:<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 -i ~/.ssh/aapanel_lab YOUR_USER@YOUR_SERVER_IP</code></div></div>We tested fresh Ed25519 sessions before and after reboot. We retained password access during the disposable lab exercises. For production, plan a separate tested move to a sudo account and key-only authentication; do not disable a working recovery route before verifying its replacement.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">5. Review the remaining protections</span></span><br />
Our aaPanel Free 8.0.6 interface includes <span style="font-weight: bold;" class="mycode_b">Google Authenticator</span> and <span style="font-weight: bold;" class="mycode_b">Authorized IP</span> controls. We have not enabled them in this lab: authenticator enrollment needs the owner's device, and an allowlist needs a stable management address or VPN. Configure and test these for your environment without blocking legitimate access or certificate renewal.<br />
<br />
Review optional phpMyAdmin and FTP exposure. MariaDB does not need a public database-port opening for a website running on the same server. Use encrypted file transfer and allow only the services you actually need.<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Verified results and remaining checks</span></span><br />
Our Ubuntu updates and reboot completed. Fresh SSH key access, panel login, Nginx, MariaDB and PHP-FPM recovered successfully. The local default website returned HTTP 200. The panel-port change and current certificate validation passed.<br />
<br />
We also disabled phpMyAdmin’s separate public-access service and verified that the setting remained off. Its authenticated panel launch still needs troubleshooting; see the <a href="https://adminsforum.com/Thread-guide-install-phpmyadmin-in-aapanel-free-edition" target="_blank" rel="noopener" class="mycode_url">phpMyAdmin installation guide</a>.<br />
<br />
Certificate renewal, two-factor enrollment, a stable management allowlist and full website/database restore testing remain separate checks. This guide does not claim that every production-hardening task is complete.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Next:</span> Add a website, connect its domain, issue its own HTTPS certificate and create its database.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">References:</span> <a href="https://www.aapanel.com/docs/Function/Settings.html" target="_blank" rel="noopener" class="mycode_url">aaPanel Settings documentation</a> and <a href="https://ubuntu.com/server/docs/how-to/security/openssh-server/" target="_blank" rel="noopener" class="mycode_url">Ubuntu OpenSSH documentation</a>.<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=5" target="_blank" title="">aapanel-ssl-annotated-20261010.png</a> (Size: 85.38 KB / Downloads: 22)
<!-- end: postbit_attachments_attachment --><br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://adminsforum.com/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=6" target="_blank" title="">aapanel-port-dialog-annotated-20261010.png</a> (Size: 117.83 KB / Downloads: 17)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
	</channel>
</rss>