![]() |
|
Guide Automatically Update the Pure-FTPd FTPS Certificate in aaPanel - Printable Version +- AdminsForum (https://adminsforum.com) +-- Forum: Free & open-source control panels (https://adminsforum.com/Forum-free-open-source-control-panels) +--- Forum: aaPanel (https://adminsforum.com/Forum-aapanel) +---- Forum: aaPanel Guides & Tutorials (https://adminsforum.com/Forum-aapanel-guides-tutorials) +----- Forum: aaPanel FTP, SFTP & File Transfer Guides (https://adminsforum.com/Forum-aapanel-ftp-sftp-file-transfer-guides) +----- Thread: Guide Automatically Update the Pure-FTPd FTPS Certificate in aaPanel (/Thread-guide-automatically-update-the-pure-ftpd-ftps-certificate-in-aapanel) |
Automatically Update the Pure-FTPd FTPS Certificate in aaPanel - DEV - 10-13-2026 Renewing a website or mail certificate does not automatically update a separate Pure-FTPd PEM bundle. If you manually copied a certificate for FTPS, the FTP service can keep using an older certificate after the original renews. This guide closes that gap using a checked deployment helper. What this does The helper reads an already renewed certificate managed by aaPanel, validates it, and deploys the combined certificate/key bundle used by Pure-FTPd. It does not request a new certificate or replace the existing certificate-renewal mechanism. You must keep that original renewal working and monitor its result. 1. Confirm the source and destination In our lab the certificate belongs to mail.adminslab.com. Its source files are: Code: /www/server/panel/vhost/cert/mail.adminslab.com/fullchain.pem
/www/server/panel/vhost/cert/mail.adminslab.com/privkey.pemCode: /etc/ssl/private/pure-ftpd.pem2. Install the helper after reviewing it Save the following as /usr/local/sbin/af-sync-ftps-certificate.py using your authorized root session. The code below is the lab version. Adapt the hostname, source folder and private backup folder to your server before using it. It expects Python 3, OpenSSL, ss and systemctl, and the existing pure-ftpd.service. Code: #!/usr/bin/python3
"""Deploy an already-renewed aaPanel certificate to Pure-FTPd without exposing its key."""
import argparse,fcntl,hashlib,os,ssl,subprocess,tempfile
from pathlib import Path
parser=argparse.ArgumentParser();parser.add_argument('--dry-run',action='store_true');args=parser.parse_args()
if os.geteuid()!=0: raise SystemExit('Root required')
lock=open('/run/af-ftps-certificate-sync.lock','w');fcntl.flock(lock,fcntl.LOCK_EX|fcntl.LOCK_NB)
source=Path('/www/server/panel/vhost/cert/mail.adminslab.com');target=Path('/etc/ssl/private/pure-ftpd.pem')
cert=source/'fullchain.pem';key=source/'privkey.pem'
for p in [cert,key,target]:
if not p.is_file() or p.is_symlink():raise SystemExit('Expected regular certificate file missing')
subprocess.run(['openssl','x509','-in',str(cert),'-noout','-checkend','604800'],check=True,stdout=subprocess.DEVNULL)
subprocess.run(['openssl','verify','-CApath','/etc/ssl/certs','-verify_hostname','mail.adminslab.com','-untrusted',str(cert),str(cert)],check=True,stdout=subprocess.DEVNULL)
bundle=cert.read_bytes().rstrip()+bytes([10])+key.read_bytes().rstrip()+bytes([10])
fd,name=tempfile.mkstemp(prefix='.af-ftps-',dir=str(target.parent));tmp=Path(name)
try:
os.fchmod(fd,0o600)
with os.fdopen(fd,'wb') as out:out.write(bundle);out.flush();os.fsync(out.fileno())
context=ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER);context.load_cert_chain(str(tmp))
old=target.read_bytes()
if old==bundle:print('FTPS certificate already synchronized; no restart');raise SystemExit(0)
if args.dry_run:print('DRY RUN PASS: chain, hostname, expiry and matching key validated; update required');raise SystemExit(0)
sessions=subprocess.check_output(['ss','-Hnt','state','established','sport','=',':21'],text=True)
if sessions.strip():raise SystemExit('Active FTP control session: deferred until next run')
backup=Path('/root/af-hosting-batch-20261012/ftps-renewal-20261013');backup.mkdir(mode=0o700,parents=True,exist_ok=True)
previous=backup/'previous-bundle.pem';previous.write_bytes(old);previous.chmod(0o600)
os.replace(tmp,target);os.chmod(target,0o600)
try:
subprocess.run(['systemctl','restart','pure-ftpd.service'],check=True)
except Exception:
target.write_bytes(old);target.chmod(0o600);subprocess.run(['systemctl','restart','pure-ftpd.service'],check=False);raise
print('FTPS certificate deployed; Pure-FTPd restarted')
finally:
if tmp.exists():tmp.unlink()Code: chown root:root /usr/local/sbin/af-sync-ftps-certificate.py
chmod 700 /usr/local/sbin/af-sync-ftps-certificate.py
/usr/local/sbin/af-sync-ftps-certificate.py --dry-run3. Deploy once and verify trusted FTPS Run the helper without --dry-run. When the source differs, it preserves the previous bundle privately, replaces the file with mode 600 and restarts Pure-FTPd. It attempts to restore the old bundle if the restart fails. Code: /usr/local/sbin/af-sync-ftps-certificate.pyActual lab deployment: updated bundle, trusted TLS 1.3, then an unchanged second run with no restart. 4. Add the scheduled check Our lab uses a root-owned /etc/cron.d/af-ftps-certificate-sync file with: Code: SHELL=/bin/sh
PATH=/usr/sbin:/usr/bin:/sbin:/bin
17 * * * * root /usr/local/sbin/af-sync-ftps-certificate.py >> /var/log/af-ftps-certificate-sync.log 2>&15. Monitor the complete renewal path Read the private log for validation errors, deferred sessions or a failed restart. Inspect source certificate expiration and the actual certificate presented by FTPS. Persistent FTP sessions can delay deployment; plan a maintenance window if that continues. The old backup bundle includes a private key and must remain private. Arrange suitable log retention and an alert route outside the server. 6. Troubleshooting
Verified scope The lab passed dry validation, live deployment, trusted FTPS TLS 1.3, an unchanged no-restart run, and cron-service/schedule checks. A future certificate issuance and a future automatic renewal have not yet occurred, so this is not a claim that the next renewal has already succeeded. The existing aaPanel certificate-renewal job was preserved. Start with the FTPS setup guide. Original helper and lab evidence: © AdminsForum. |