{"id":14332,"date":"2025-12-30T11:23:50","date_gmt":"2025-12-30T05:53:50","guid":{"rendered":"https:\/\/www.youstable.com\/blog\/?p=14332"},"modified":"2025-12-30T11:23:52","modified_gmt":"2025-12-30T05:53:52","slug":"how-to-monitor-secure-ftp-on-linux-server","status":"publish","type":"post","link":"https:\/\/www.youstable.com\/blog\/how-to-monitor-secure-ftp-on-linux-server","title":{"rendered":"How to Monitor &amp; Secure FTP on Linux Server &#8211; complete guide"},"content":{"rendered":"\n<p><strong>To monitor and secure FTP<\/strong> on a Linux server, harden your daemon (disable anonymous, chroot users, enforce TLS), restrict firewall ports, enable detailed logging, and automate intrusion blocking with Fail2ban. Continuously review transfer logs, set alerts for anomalies, and prefer SFTP\/FTPS for encrypted sessions. Patch regularly and audit configuration changes.<\/p>\n\n\n\n<p>If you\u2019re wondering how to monitor and <a href=\"https:\/\/www.youstable.com\/blog\/what-is-ftp-on-linux-server\/\">secure FTP on Linux server<\/a> environments, this in-depth guide walks you through proven, beginner-friendly steps I use in production: hardening vsftpd, enabling FTPS (TLS), configuring the firewall, automating bans with Fail2ban, and continuously monitoring and alerting on suspicious activity.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"understanding-ftp-security-risks-in-linux\"><strong>Understanding FTP Security Risks in Linux<\/strong><\/h2>\n\n\n\n<p>FTP is a legacy protocol that sends credentials and files in plain text unless wrapped with encryption (FTPS) or replaced by SFTP (over SSH). Left unprotected, FTP exposes passwords, enables <a href=\"https:\/\/www.youstable.com\/blog\/what-is-fail2ban-on-linux-server\/\">brute-force attacks<\/a>, and can leak sensitive data. The goal is to reduce the attack surface, encrypt traffic, and continuously observe behavior.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"quick-hardening-and-monitoring-checklist\"><strong>Quick Hardening &amp; Monitoring Checklist<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Disable anonymous access and isolate users (chroot).<\/li>\n\n\n\n<li>Enforce encryption (FTPS) or migrate to SFTP.<\/li>\n\n\n\n<li>Limit and document passive port ranges; protect them via firewall.<\/li>\n\n\n\n<li>Enable detailed transfer\/auth logs; centralize and rotate them.<\/li>\n\n\n\n<li>Block brute-force attempts with Fail2ban.<\/li>\n\n\n\n<li>Alert on anomalies and audit config changes.<\/li>\n\n\n\n<li>Patch the OS and FTP daemon regularly.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sftp-vs-ftps-what-to-use\"><strong>SFTP vs FTPS: What to Use<\/strong><\/h2>\n\n\n\n<p>Both SFTP (SSH File Transfer Protocol) and FTPS (FTP over TLS) encrypt traffic. Pick one based on your client ecosystem and compliance needs:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"when-to-choose-sftp\"><strong>When to choose SFTP<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Simpler firewalling: uses SSH port 22 only.<\/li>\n\n\n\n<li>Native to Linux via OpenSSH; easy key-based auth.<\/li>\n\n\n\n<li>Ideal for server-to-server automation and scripts.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"when-to-choose-ftps\"><strong>When to choose FTPS<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Legacy partners require \u201cFTP with TLS\u201d.<\/li>\n\n\n\n<li>Explicit FTPS (AUTH TLS on port 21) works with many GUI clients.<\/li>\n\n\n\n<li>Can meet compliance that mandates TLS ciphers and audit trails.<\/li>\n<\/ul>\n\n\n\n<p>Best practice: prefer SFTP where possible; if you must run classic FTP, enforce FTPS and strict hardening.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"install-and-secure-vsftpd-recommended\"><strong>Install and Secure vsftpd (Recommended)<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"install-packages\"><strong>Install packages<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Ubuntu\/Debian\nsudo apt update\nsudo apt <a href=\"https:\/\/www.youstable.com\/blog\/install-fail2ban-on-linux\/\">install vsftpd fail2ban<\/a> ufw\n\n# RHEL\/CentOS\/Rocky\/Alma\nsudo dnf <a href=\"https:\/\/www.youstable.com\/blog\/install-firewalld-on-linux\/\">install vsftpd fail2ban firewalld<\/a><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"create-a-minimal-secure-vsftpd-configuration\"><strong>Create a minimal, secure vsftpd configuration<\/strong><\/h3>\n\n\n\n<p>Edit \/etc\/vsftpd.conf with these sane defaults. Adjust paths, passive ports, and banner to your environment.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>anonymous_enable=NO\nlocal_enable=YES\nwrite_enable=YES\n\n# Isolate users into their home directory (chroot)\nchroot_local_user=YES\n\n# If you need writable chroot, prefer a \/home\/user\/ftp\/uploads layout.\nallow_writeable_chroot=YES\n\n# User directories and default umask\nuser_sub_token=$USER\nlocal_root=\/home\/$USER\/ftp\nlocal_umask=022\n\n# Logging\nxferlog_enable=YES\nxferlog_std_format=NO\nlog_ftp_protocol=YES\nvsftpd_log_file=\/var\/log\/vsftpd.log\ndual_log_enable=YES\n\n# Security\nseccomp_sandbox=YES\npam_service_name=vsftpd\nuse_localtime=YES\nftpd_banner=Authorized users only.\n\n# Passive mode range (document and open in firewall)\npasv_enable=YES\npasv_min_port=40000\npasv_max_port=40100\n\n# Listen with systemd (default). Uncomment if needed for standalone.\n# listen=YES\n# listen_ipv6=YES<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"create-a-dedicated-upload-path-per-user-safer-than-writable-chroot\"><strong>Create a dedicated upload path per user (safer than writable chroot)<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Example for user \"alice\"\nsudo mkdir -p \/home\/alice\/ftp\/uploads\nsudo chown -R alice:alice \/home\/alice\/ftp\/uploads\nsudo chmod 755 \/home\/alice\n# Ensure local_root=\/home\/$USER\/ftp in vsftpd.conf<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"enable-ftps-tls-on-vsftpd\"><strong>Enable FTPS (TLS) on vsftpd<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"create-a-tls-certificate\"><strong>Create a TLS certificate<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo openssl req -x509 -nodes -newkey rsa:4096 \\\n -keyout \/etc\/ssl\/private\/vsftpd.key \\\n -out \/etc\/ssl\/certs\/vsftpd.crt -days 365\nsudo chmod 600 \/etc\/ssl\/private\/vsftpd.key<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"force-tls-and-modern-ciphers\"><strong>Force TLS and modern ciphers<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Add to \/etc\/vsftpd.conf\nssl_enable=YES\nrsa_cert_file=\/etc\/ssl\/certs\/vsftpd.crt\nrsa_private_key_file=\/etc\/ssl\/private\/vsftpd.key\n\n# Require encryption for logins and data\nforce_local_logins_ssl=YES\nforce_local_data_ssl=YES\n\n# Protocol and ciphers\nssl_sslv2=NO\nssl_sslv3=NO\nssl_tlsv1=YES\nssl_tlsv1_1=NO\nssl_tlsv1_2=YES\nrequire_ssl_reuse=NO\nssl_ciphers=HIGH<\/code><\/pre>\n\n\n\n<p>Restart and enable vsftpd on boot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart vsftpd\nsudo systemctl enable vsftpd\nsudo systemctl status vsftpd<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"firewall-hardening-for-ftp-ftps\"><strong>Firewall Hardening for FTP\/FTPS<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"ufw-ubuntu-debian\"><strong>UFW (Ubuntu\/Debian)<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow 21\/tcp\nsudo ufw allow 40000:40100\/tcp\n# If you use implicit FTPS (less common), also open 990\/tcp\n# sudo ufw allow 990\/tcp\nsudo ufw reload\nsudo ufw status<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"firewalld-rhel-centos-derivatives\"><strong>firewalld (RHEL\/CentOS derivatives)<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --permanent --add-service=ftp\nsudo firewall-cmd --permanent --add-port=40000-40100\/tcp\n# For implicit FTPS (only if used):\n# sudo firewall-cmd --permanent --add-port=990\/tcp\nsudo firewall-cmd --reload\nsudo firewall-cmd --list-all<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"monitor-ftp-logs-and-activity\"><strong>Monitor FTP Logs and Activity<\/strong><\/h2>\n\n\n\n<p>Detailed logging is your early-warning system. vsftpd writes to \/var\/log\/vsftpd.log (when log_ftp_protocol=YES) and may also use xferlog. Use these commands to watch activity in real time and build quick summaries.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"real-time-tail\"><strong>Real-time tail<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tail -f \/var\/log\/vsftpd.log\n# or with timestamps via journal:\nsudo journalctl -u vsftpd -f<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"top-failing-ips-brute-force-detection\"><strong>Top failing IPs (brute-force detection)<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>grep \"FAIL LOGIN\" \/var\/log\/vsftpd.log \\\n | awk -F'\"' '{print $2}' \\\n | sort | uniq -c | sort -nr | head<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"recent-uploads-and-downloads\"><strong>Recent uploads and downloads<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Successful uploads\ngrep \"OK UPLOAD\" \/var\/log\/vsftpd.log | tail -n 20\n\n# Successful downloads\ngrep \"OK DOWNLOAD\" \/var\/log\/vsftpd.log | tail -n 20<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"rotate-and-retain-logs\"><strong>Rotate and retain logs<\/strong><\/h3>\n\n\n\n<p>Make sure vsftpd logs are rotated and retained for audits. Most distros ship a logrotate rule, but verify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo cat \/etc\/logrotate.d\/vsftpd<\/code><\/pre>\n\n\n\n<p>For compliance and investigations, forward logs to a SIEM or central rsyslog server.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"block-attacks-automatically-with-fail2ban\"><strong>Block Attacks Automatically with Fail2ban<\/strong><\/h2>\n\n\n\n<p>Fail2ban reads logs, detects abuse (e.g., repeated failed logins), and dynamically bans IPs via your firewall.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"create-a-vsftpd-jail\"><strong>Create a vsftpd jail<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/fail2ban\/jail.local<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;vsftpd]\nenabled = true\nport    = ftp,ftp-data,40000:40100\nfilter  = vsftpd\nlogpath = \/var\/log\/vsftpd.log\nmaxretry = 5\nfindtime = 10m\nbantime  = 24h<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"filter-for-failed-logins-if-not-present\"><strong>Filter for failed logins (if not present)<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/fail2ban\/filter.d\/vsftpd.conf<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;Definition]\nfailregex = ^.*\\&#91;pid \\d+\\] \\&#91;.*\\] FAIL LOGIN: Client \".*\"$\nignoreregex =<\/code><\/pre>\n\n\n\n<p>Restart Fail2ban and confirm bans:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart fail2ban\nsudo fail2ban-client status vsftpd<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"user-and-access-controls\"><strong>User and Access Controls<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"limit-who-can-log-in\"><strong>Limit who can log in<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Allow only users listed in \/etc\/vsftpd.userlist\necho \"userlist_enable=YES\" | sudo tee -a \/etc\/vsftpd.conf\necho \"userlist_deny=NO\" | sudo tee -a \/etc\/vsftpd.conf\necho \"alice\" | sudo tee -a \/etc\/vsftpd.userlist\nsudo systemctl restart vsftpd<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"use-non-login-shells-for-ftp-only-accounts\"><strong>Use non-login shells for FTP-only accounts<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo usermod -s \/usr\/sbin\/nologin ftpuser<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"prefer-sftp-for-admins-and-automation\"><strong>Prefer SFTP for admins and automation<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Minimal SFTP-only setup (OpenSSH)\nsudo nano \/etc\/ssh\/sshd_config\n\n# Add:\nSubsystem sftp internal-sftp\nMatch Group sftpusers\n    ChrootDirectory %h\n    ForceCommand internal-sftp\n    X11Forwarding no\n    AllowTcpForwarding no\n\n# Then:\nsudo groupadd sftpusers\nsudo useradd -m -g sftpusers -s \/usr\/sbin\/nologin bob\nsudo passwd bob\nsudo mkdir -p \/home\/bob\/uploads\nsudo chown bob:sftpusers \/home\/bob\/uploads\nsudo chown root:root \/home\/bob\nsudo chmod 755 \/home\/bob\nsudo systemctl restart sshd<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"audit-and-alert-on-configuration-changes\"><strong>Audit and Alert on Configuration Changes<\/strong><\/h2>\n\n\n\n<p>Track changes to sensitive files like \/etc\/vsftpd.conf and user lists. auditd makes this easy.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Watch changes to vsftpd config\nsudo auditctl -w \/etc\/vsftpd.conf -p wa -k vsftpd_conf\n# Later, review events:\nsudo ausearch -k vsftpd_conf --format text<\/code><\/pre>\n\n\n\n<p>For larger estates, forward logs to a SIEM, set alerts for spikes in \u201cFAIL LOGIN\u201d, and create weekly reports of top uploaders, largest files, and unusual hours.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"maintenance-patching-and-backups\"><strong>Maintenance: Patching and Backups<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Apply OS and vsftpd updates promptly.<\/li>\n\n\n\n<li>Back up \/etc\/vsftpd.conf, \/etc\/vsftpd.userlist, and certificates.<\/li>\n\n\n\n<li>Regularly review users and permissions; remove stale accounts.<\/li>\n\n\n\n<li>Test restores and config rollbacks to reduce downtime risk.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"common-ftp-security-mistakes-to-avoid\"><strong>Common FTP Security Mistakes to Avoid<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Running plain FTP without TLS or SFTP.<\/li>\n\n\n\n<li>Leaving passive ports undefined or unfiltered.<\/li>\n\n\n\n<li>Allowing anonymous uploads.<\/li>\n\n\n\n<li>Writable chroot without a dedicated uploads subfolder.<\/li>\n\n\n\n<li>No brute-force protection (Fail2ban) or alerting.<\/li>\n\n\n\n<li>Ignoring logs and missing early attack signals.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"troubleshooting-tips\"><strong>Troubleshooting Tips<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Connection hangs after AUTH TLS: verify passive port range is open in the firewall and matches vsftpd.conf.<\/li>\n\n\n\n<li>\u201c530 Login incorrect\u201d: confirm user is listed in \/etc\/vsftpd.userlist (if enforced) and not locked.<\/li>\n\n\n\n<li>Uploads fail in chroot: use \/home\/user\/ftp\/uploads and avoid writing directly to the chroot root.<\/li>\n\n\n\n<li>TLS handshake errors: ensure the certificate path\/permissions are correct and SSLv2\/3 are disabled.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"real-world-example-daily-monitoring-routine\"><strong>Real-World Example: Daily Monitoring Routine<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Every morning: review Fail2ban bans and top \u201cFAIL LOGIN\u201d IPs.<\/li>\n\n\n\n<li>Spot-check last 24h \u201cOK UPLOAD\/DOWNLOAD\u201d entries and large file transfers.<\/li>\n\n\n\n<li>Weekly: rotate and archive logs, verify backups, and patch.<\/li>\n\n\n\n<li>Monthly: audit users, passive port hygiene, and TLS settings (ciphers, expiry).<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"faqs\"><strong>FAQ&#8217;s<\/strong><\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1765951540684\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"1-is-ftp-secure-on-linux-by-default\">1. <strong>Is FTP secure on Linux by default?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>No. Classic FTP is unencrypted. Secure it by enabling FTPS (TLS) in your FTP daemon or switch to SFTP (over SSH), then add firewall rules, logging, and Fail2ban.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1765951549352\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"2-ftps-vs-sftp-which-is-better\">2. <strong>FTPS vs SFTP: which is better?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>SFTP is simpler to firewall (port 22), integrates with <a href=\"https:\/\/www.youstable.com\/blog\/how-to-add-ssh-keys-to-github-account\/\">SSH keys<\/a>, and is easier to automate. <a href=\"https:\/\/www.youstable.com\/blog\/how-to-configure-ftp-on-linux\/\">FTPS is useful when partners require \u201cFTP with TLS.\u201d Both encrypt traffic if configured<\/a> correctly.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1765951562752\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"3-what-ports-should-i-open-for-ftps\">3. <strong>What ports should I open for FTPS?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>For explicit FTPS: open 21\/tcp plus your defined passive range (e.g., 40000\u201340100\/tcp). For implicit FTPS (less common), also open 990\/tcp. Never expose broad ranges you didn\u2019t define in vsftpd.conf.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1765951571369\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"4-how-do-i-stop-ftp-brute-force-attacks\">4. <strong>How do I stop FTP brute-force attacks?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Enable Fail2ban with a vsftpd jail, enforce strong <a href=\"https:\/\/www.youstable.com\/blog\/ssh-keys-vs-password-authentication\/\">passwords or SSH keys<\/a> (for SFTP), restrict allowed users, and consider IP allowlists for partner-only servers.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1765951582111\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"5-what-logs-show-ftp-uploads-and-failures\">5. <strong>What logs show FTP uploads and failures?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>vsftpd typically logs to \/var\/log\/vsftpd.log. Look for \u201cOK UPLOAD\u201d, \u201cOK DOWNLOAD\u201d, and \u201cFAIL LOGIN\u201d. Use journalctl -u vsftpd for service-level events and ensure logrotate is configured.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>To monitor and secure FTP on a Linux server, harden your daemon (disable anonymous, chroot users, enforce TLS), restrict firewall [&hellip;]<\/p>\n","protected":false},"author":13,"featured_media":16713,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[350],"tags":[],"class_list":["post-14332","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-knowledgebase"],"acf":[],"featured_image_src":"https:\/\/www.youstable.com\/blog\/wp-content\/uploads\/2025\/12\/How-to-Monitor-Secure-FTP-on-Linux-Server.jpg","author_info":{"display_name":"Prahlad Prajapati","author_link":"https:\/\/www.youstable.com\/blog\/author\/prahladblog"},"_links":{"self":[{"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/posts\/14332","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/comments?post=14332"}],"version-history":[{"count":6,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/posts\/14332\/revisions"}],"predecessor-version":[{"id":16715,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/posts\/14332\/revisions\/16715"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/media\/16713"}],"wp:attachment":[{"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/media?parent=14332"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/categories?post=14332"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/tags?post=14332"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}