Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Use vsftpd with a dedicated, non-login Linux account, a root-owned chroot directory, and a separate writable child directory. That combination gives an FTP user access to one transfer tree without SSH access or permission to write the jail itself. Encrypt the connection with FTPS, restrict passive ports in both firewalls, and test the jail from outside the VPS.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
If your client supports SSH, SFTP is usually the simpler secure choice because it uses the existing SSH service and does not need FTP’s separate passive data channel. Use FTPS when FTP compatibility is required.
As an Amazon Associate I earn from qualifying purchases.
What a limited FTP account actually restricts
An FTP account has several independent boundaries:
- Authentication: which credentials are accepted.
- Filesystem scope: the directory visible after login.
- Unix permissions: which files and subdirectories can be read, created, changed, or deleted.
- Protocol commands: whether uploads, renames, deletion, or directory creation are enabled.
- Network exposure: which control and passive data ports are reachable.
Chrooting hides the rest of the filesystem, but it is not a substitute for Unix ownership and mode bits. A user who can write every directory inside the jail can still alter every file that those permissions allow. Design the directory tree first, then configure vsftpd to match it.
Choose local users or vsftpd virtual users
There are two supported designs. Select one before editing the configuration.
#1 Best Overall
| Decision point | Local Linux user | vsftpd virtual user |
|---|---|---|
| Identity source | /etc/passwd and the system account database |
A vsftpd/PAM user database |
| Operating-system account | One account per FTP identity; its shell can be set to nologin |
FTP identities are mapped to one unprivileged local guest account |
| Best fit | One or a few administrators, contractors, or site owners | Many FTP-only customers, vendors, or application identities |
| Main risk | Review whether SSH or another service also accepts the account | Protect the credential database, PAM file, and mapped guest account |
| Administration | Use normal Linux account and permission tools | Maintain a separate password database and, commonly, one directory per virtual name |
The local-user procedure below is the shortest reliable setup. The virtual-user procedure appears later for installations that must not create a normal system account for each FTP identity.
Prerequisites and the example layout
The commands in this guide target Ubuntu or Debian with sudo. Package names and service commands differ on Red Hat–family distributions, so use that distribution’s package manager and service unit where necessary. You need:
Free tools Windows power users keep installed
One-click scans. No signup required.
- A VPS with a static public address or a stable DNS name.
- Root or
sudoaccess. - An FTP client that supports explicit TLS if credentials must be protected.
- Permission to change the VPS firewall and the cloud provider’s security group.
- A decision about whether the account is download-only or must upload.
The examples use this tree:
/srv/ftp/client-a/ # chroot root; administrative ownership only
/srv/ftp/client-a/incoming/ # writable upload directory, if required
After login, /srv/ftp/client-a appears as /. The user cannot use cd .. to reach the VPS’s real root.
Install and start vsftpd
-
Install the server package:
sudo apt update sudo apt install vsftpd -
Back up the original configuration before changing it:
sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig -
Enable the service at boot and start it:
sudo systemctl enable --now vsftpd sudo systemctl status vsftpd
If the service fails to start, read the unit log before changing more settings:
sudo journalctl -u vsftpd --no-pager -n 100
Create the limited local account
1. Build a root-owned jail
sudo install -d -o root -g root -m 755 /srv/ftp/client-a
sudo install -d -o clienta -g clienta -m 750 /srv/ftp/client-a/incoming
The second command requires the account to exist, so create the account first if you are following these commands literally. A complete order is:
sudo useradd --home-dir /srv/ftp/client-a --shell /usr/sbin/nologin --no-create-home clienta
sudo passwd clienta
sudo install -d -o root -g root -m 755 /srv/ftp/client-a
sudo install -d -o clienta -g clienta -m 750 /srv/ftp/client-a/incoming
If /usr/sbin/nologin is at a different path on your distribution, find it with command -v nologin. The account still exists in the operating system, but it cannot open an interactive shell. Check that no SSH configuration, group membership, or other service grants it access you did not intend.
2. Set ownership for the files the user should download
Place downloadable files under the jail and make them readable by clienta through ownership or group permissions. For example:
sudo install -o root -g clienta -m 640 release.zip /srv/ftp/client-a/release.zip
Keep the jail directory itself owned by root (or another administrative account) and not writable by clienta. The writable incoming child is where uploads, renames, and deletions should occur.
Configure authenticated, jailed local access
Edit /etc/vsftpd.conf. Remove duplicate entries or ensure the last value is the one you intend; vsftpd configuration files are easier to audit when each option appears once.
listen=YES
listen_ipv6=NO
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=027
chroot_local_user=YES
allow_writeable_chroot=NO
# Optional command restrictions
# cmds_allowed=PASV,EPSV,LIST,MLSD,NLST,RETR,STOR,TYPE,USER,PASS,PWD,CWD,CDUP,QUIT
# TLS settings (paths shown are examples)
ssl_enable=YES
force_local_logins_ssl=YES
force_local_data_ssl=YES
rsa_cert_file=/etc/ssl/private/ftp-server.crt
rsa_private_key_file=/etc/ssl/private/ftp-server.key
ssl_sslv3=NO
ssl_tlsv1=NO
# Passive data ports
pasv_min_port=40000
pasv_max_port=40100
# Set this when the VPS is behind NAT or has a separate public address:
# pasv_address=ftp.example.com
write_enable=YES is necessary for uploads, renames, deletion, and directory creation. If the account only downloads, set it to NO or use a per-user configuration that does so. The cmds_allowed line is optional: command names must match the operations your clients need, and an overly narrow list can break directory listings or modern FTP clients.
With chroot_local_user=YES, every selected local user is jailed to its home directory. The meaning of chroot_list_file reverses in this mode: users listed there become exceptions rather than jailed users. Do not add an exception unless you have a specific reason and have reviewed its consequences.
Create a certificate and require FTPS
FTP sends credentials in clear text unless TLS is negotiated. For a temporary internal test, you can create a self-signed certificate; production clients should use a certificate they trust and verify the server name.
sudo openssl req -x509 -nodes -newkey rsa:2048 -days 365
-keyout /etc/ssl/private/ftp-server.key
-out /etc/ssl/private/ftp-server.crt
Protect the private key:
sudo chown root:root /etc/ssl/private/ftp-server.key
sudo chmod 600 /etc/ssl/private/ftp-server.key
The settings above require TLS for local-user logins and data transfers. Client labels vary: choose FTP over TLS, explicit (also called explicit FTPS) on the normal control port. A self-signed certificate will produce a trust warning until the client is configured to trust it; do not silently accept an unexpected certificate on an Internet-facing server.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsOption names and TLS capabilities vary between vsftpd builds. If vsftpd rejects an option, consult the manual installed with your package and use the strongest protocol settings that your clients support.
Open only the required network ports
FTP uses one control connection and separate data connections. Passive mode makes the server listen on a bounded range that the client connects to. Permit TCP port 21 and the exact passive range in both layers of filtering.
sudo ufw allow 21/tcp
sudo ufw allow 40000:40100/tcp
sudo ufw status
Repeat equivalent rules in the VPS provider’s security group or network firewall. If the server has a private address and a different public address, set pasv_address to the public DNS name or address that clients can reach. Never expose a broad, unbounded passive range when a small range is sufficient.
Reload and verify the local-user setup
-
Check the configuration syntax and restart the service:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteSpecial offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.sudo systemctl restart vsftpd sudo systemctl status vsftpd -
Connect from a machine outside the VPS using an FTP client configured for explicit TLS.
-
Confirm that the initial directory is the intended client root and that a directory listing works.
-
Run
cd ..repeatedly. The client must remain inside the jail. -
Download a permitted file.
-
If uploads are enabled, upload into
incoming, rename a test file there, and delete it. Do not test by making the chroot root writable.What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy. -
Attempt an upload or deletion in a read-only directory and confirm that it fails.
-
Inspect the client’s connection details and confirm that TLS protects both authentication and the data channel.
These checks prove the account’s effective behavior rather than merely proving that the daemon is running.
Use virtual users when FTP identities should not be system accounts
Virtual users are useful when you have many external identities or when you want FTP credentials that cannot be reused for SSH. vsftpd authenticates the names through PAM and maps them to one unprivileged local account.
Recommended Free Tools
1. Create the mapped guest account and directories
sudo useradd --system --home-dir /srv/ftp --shell /usr/sbin/nologin ftpguest
sudo install -d -o root -g root -m 755 /srv/ftp
sudo install -d -o ftpguest -g ftpguest -m 750 /srv/ftp/client-a/incoming
Create one directory per virtual identity. The guest account owns only the locations that virtual users need.
2. Build the credential database
Create a file containing alternating usernames and passwords, with restrictive permissions:
sudo sh -c 'umask 077; cat > /etc/vsftpd/virtual_users.txt'
Enter:
client-a
use-a-long-unique-password
Press Ctrl-D, then convert the file to a Berkeley DB database with the db_load utility (the package providing that utility varies by distribution):
sudo db_load -T -t hash -f /etc/vsftpd/virtual_users.txt /etc/vsftpd/virtual_users.db
sudo chmod 600 /etc/vsftpd/virtual_users.db
sudo shred -u /etc/vsftpd/virtual_users.txt
Keep backups of the database protected like passwords. Anyone who obtains it may be able to authenticate, depending on the database format and protections.
3. Point PAM at the database
Create a dedicated PAM service file such as /etc/pam.d/vsftpd-virtual:
auth required pam_userdb.so db=/etc/vsftpd/virtual_users
account required pam_userdb.so db=/etc/vsftpd/virtual_users
Use a separate PAM file if you also need local Linux users; do not overwrite an existing distribution file without first understanding which authentication methods it contains.
Best Value
4. Enable the virtual-user mode
Add the following settings to the vsftpd configuration:
anonymous_enable=NO
local_enable=YES
write_enable=YES
guest_enable=YES
guest_username=ftpguest
virtual_use_local_privs=YES
pam_service_name=vsftpd-virtual
user_sub_token=$USER
local_root=/srv/ftp/$USER
chroot_local_user=YES
user_config_dir=/etc/vsftpd/user_conf
pasv_min_port=40000
pasv_max_port=40100
Create the per-user directory and, when needed, an override file:
sudo install -d -o root -g root -m 755 /etc/vsftpd/user_conf
sudo sh -c 'cat > /etc/vsftpd/user_conf/client-a <<EOF
local_root=/srv/ftp/client-a
write_enable=YES
EOF'
The upstream virtual-user pattern maps authenticated names to the unprivileged guest account. Confirm that every mapped directory has the ownership and modes you expect; the virtual name is not itself a Unix UID.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Limit commands and writes further
Use the narrowest capability that meets the workflow:
- For download-only access, set
write_enable=NOglobally or in the user’s configuration. - For upload-only exchange, grant write permission to
incomingand avoid granting write permission to the jail root. - Use
user_config_dirfor per-user differences rather than making every account equally powerful. - Use
cmds_allowedorcmds_deniedonly after testing listings, passive negotiation, uploads, and the client’s required commands. - Keep the mapped guest account unprivileged and out of administrative groups.
FTP, FTPS, or SFTP?
| Protocol | How it works | Firewall and account implications | When to choose it |
|---|---|---|---|
| FTP | Traditional FTP without encryption | Credentials and data can be observed; requires control and passive data ports | Only isolated, non-sensitive networks where clear text is explicitly acceptable |
| FTPS | FTP protected by TLS | Still requires passive ports and certificate management; encrypts credentials and transfers | When an existing FTP client or workflow requires FTP semantics |
| SFTP | File transfer over SSH | Uses the SSH service and avoids FTP’s separate passive data channel; users need a shell account, usually with an SSH restriction or chroot design | The simplest secure option when clients support SSH |
Ubuntu documentation distinguishes the account models: SFTP users need a shell account, while FTP users can be assigned a nologin shell and constrained by vsftpd. If you must provide FTP compatibility, use FTPS and a tightly bounded passive range rather than unencrypted FTP.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Troubleshooting by symptom
Login is rejected
- Verify that the selected mode is enabled:
local_enable=YESfor local accounts, orguest_enable=YESwith the correct PAM service for virtual users. - Check that the account is not blocked by
userlist_enable,userlist_deny, or a distribution-specific access rule. - For local users, confirm the password, home directory, and
nologinshell path. A shell listed in/etc/shellsrules can affect authentication on some builds. - Read
journalctl -u vsftpdand the client’s exact server response.
vsftpd refuses to start or refuses the jail
Inspect ownership and mode bits:
namei -l /srv/ftp/client-a
stat -c '%U %G %a %n' /srv/ftp/client-a /srv/ftp/client-a/incoming
The chroot root must not be writable by the jailed identity. vsftpd warns that allowing a user to chroot into a directory writable by that user is potentially dangerous: a user could create an etc directory and influence library configuration loading. Keep the root administrative and use a writable child directory.
Directory listings or transfers hang
- Allow TCP 21 and the configured passive range in the VPS firewall.
- Allow the same ports in the cloud security group.
- Confirm that
pasv_addressadvertises a reachable public address or DNS name. - Check that the client is using passive mode, especially from a private network or behind NAT.
Uploads return permission denied
- Inspect Unix owner, group, mode bits, and any ACL on the destination.
- Confirm that the destination is the writable child directory, not the chroot root.
- Verify
write_enable=YESand that the requested command is not excluded bycmds_deniedor a restrictive allowlist. - On distributions using SELinux or AppArmor, inspect the policy denial and apply the distribution-approved label or profile change rather than disabling the security framework.
TLS negotiation fails
- Verify that the certificate and private-key paths exist and that the daemon can read them.
- Check the certificate name, expiration, and client trust store.
- Confirm that the client supports the TLS versions and explicit-FTPS mode required by the server.
- If encrypted sessions are mandatory, make sure the client is not attempting plain FTP.
Final least-privilege checklist
- Anonymous access is disabled.
- The FTP identity has no interactive shell.
- The chroot root is owned by an administrator and is not writable by the FTP identity.
- Only the required child directory is writable.
- Write operations are disabled unless the workflow needs them.
- FTPS is required for credentials and data, or SFTP is used instead.
- Passive ports are a small, documented range allowed in both firewall layers.
- Virtual-user databases, PAM files, and private keys are readable only by necessary administrative processes.
- An external client test confirms the jail, permitted operations, denied operations, and TLS negotiation.
The Bottom Line
For a small number of accounts, create a local user with a nologin shell, chroot it with vsftpd, and grant write access only to a child directory. For larger FTP-only populations, use vsftpd virtual users mapped to one unprivileged guest account. Prefer SFTP whenever your clients support SSH; otherwise deploy FTPS with a bounded passive-port range.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




