Getting this going is a challenge. It needs some tweaks with PAM to get the authentication going. In order to get it to work we needed libpam-ldapd NOT to be confused with libpam-ldap.

libpam-ldapd brings with is changes to nsswitch.conf so that certain pam capable services are capable of using ldap. The ones we need are passwd, group and shadow


# /etc/nsswitch.conf
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.

passwd:         compat ldap
group:          compat ldap
shadow:         compat ldap

hosts:          files dns ldap
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis
aliases:        ldap

But the install using ‘apt-get install libpam-ldapd’ should ask you about all this as you install it. It’ll also ask you for the ldap server uri you want to use for them (typically in the form ldap://

The install provides two services nscd and nslcd which are the name service cache daemon and ldap cache daemon. These are the crux of talking to the ldap server so need to be configured properly.

But it does miss out some of the setting that you’ll need to actually bind to the server (unless you’re using anonymous binds). So to sort things out you’ll need to make changes to nslcd.conf – along with quite a few other changes to get the mapping of Active Directory Attributes to Unix attributes.

One of the steps taken here was to install the Unix Identification Services role onto the AD domain controller.

In nslcd.conf the important changes are for binddn and bindpw as we don’t allow anonymous binds. Then we have a lot of Active Directory specific changes to cater for the mapping of the uid to sAMAccountName etc. So far this is for a plain insecure ldap not ldaps/tls connection.

Some of the filter parameters can be changed to suit.


# /etc/nslcd.conf
# nslcd configuration file. See nslcd.conf(5)
# for details.

# The user and group nslcd should run as.
uid nslcd
gid nslcd

# The location at which the LDAP server(s) should be reachable.
uri ldap://

# The search base that will be used for all queries.
base ou=FTP Users,dc=mydomain,dc=local

# Mappings for Active Directory
pagesize 1000
referrals off
filter passwd (&(objectClass=user)(uidNumber=*)(unixHomeDirectory=*))
map    passwd uid              sAMAccountName
map    passwd homeDirectory    unixHomeDirectory
#map    passwd homeDirectory    "/home/vftp/$sAMAccountName"
map    passwd gecos            displayName
map    passwd loginShell       "/bin/false"

filter shadow (&(objectClass=user)(uidNumber=*)(unixHomeDirectory=*))
map    shadow uid              sAMAccountName
map    shadow shadowLastChange pwdLastSet

filter group  (&(objectClass=group)(gidNumber=*))
#map    group  uniqueMember     member

# The LDAP protocol version to use.
ldap_version 3

# The DN to bind with for normal lookups.
#binddn cn=annonymous,dc=example,dc=net
#bindpw secret

binddn CN=Proxy User,CN=Users,DC=mydomain,DC=local
bindpw xxxx

# The DN used for password modifications by root.
#rootpwmoddn cn=admin,dc=example,dc=com

# SSL options
#ssl off
#tls_reqcert never

# The search scope.
#scope sub

In order to match the AD user accounts the attributes for uidNumber, gid and unixHomeDirectory need to be completed. Any missing info will result in a failure to logon.

Test nslcd by stopping the daemon and running it as a manual service so you can debug it. Give get ent a try to see if it returns any of the users from AD.

# service nslcd stop
# nslcd -d
# getent passwd


The How-To notes for this are a little shaky and it takes some tweaking to get it right. The way we have it working is each ftp user gets created in AD (with the necessary Unix attributes). Then they can simply logon to the FTP service, their home directory will get created and they will be chroot’ed into it so all they can see are their own files.

This is with the exception of the ftproot user (also an ldap/AD user) as this user get’s chroot’ed into the /home/vftp location and therefore can see all the folders for the other ftp users.

One caveat with all this is that the version of vsftpd required must support the option for ‘allow_writeable_chroot=YES’ so you have to download it from an alternative apt source if you’re using version 2.3.5.


# Run standalone?  vsftpd can run either from an inetd or as a standalone
# daemon started from an initscript.

# Uncomment this to enable any form of FTP write command.

# Activate directory messages - messages given to remote users when they
# go into a certain directory.

# If enabled, vsftpd will display directory listings with the time
# in  your  local  time  zone.  The default is to display GMT. The
# times returned by the MDTM FTP command are also affected by this
# option.

# Activate logging of uploads/downloads.

# Make sure PORT transfer connections originate from port 20 (ftp-data).

# It is recommended that you define on your system a unique user which the
# ftp server can use as a totally isolated and unprivileged user.

# You may restrict local users to their home directories.  See the FAQ for
# the possible risks in this before using chroot_local_user or
# chroot_list_enable below.

# This option should be the name of a directory which is empty.  Also, the
# directory should not be writable by the ftp user. This directory is used
# as a secure chroot() jail at times vsftpd does not require filesystem
# access.

# This string is the name of the PAM service vsftpd will use.

# This option specifies the location of the RSA certificate to use for SSL
# encrypted connections.

# Useful to not write over hidden files:

# Hide the info about the owner (user and group) of the files.

# Connection limit for each IP:

# Maximum number of clients:

# Virtual users will use the same privileges as local users.
# It will grant write access to virtual users. Virtual users will use the
# same privileges as anonymous users, which tends to be more restrictive
# (especially in terms of write access).

# Set the name of the PAM service vsftpd will use

# Activates virtual users

# Automatically generate a home directory for each virtual user, based on a template.
# For example, if the home directory of the real user specified via guest_username is
# /home/virtual/$USER, and user_sub_token is set to $USER, then when virtual user vivek
# logs in, he will end up (usually chroot()'ed) in the directory /home/virtual/vivek.
# This option also takes affect if local_root contains user_sub_token.

# Usually this is mapped to Apache virtual hosting docroot, so that
# Users can upload files

# Chroot user and lock down to their home dirs

# Hide ids from user

# Logging 

ftpd_banner=Authorised Users Only 

# PASV Port settings 

# Needed to allow LDAP auth logon

# Used to give the user ftproot a different chroot 

The only thing in the user specific user_config_file for ftproot (/etc/vsftpd/ftproot) is



auth required
account required
session required
password required
session required        skel=/etc/skel umask=0002

This does to authentication AND creates the users home directory using /etc/skel as a template and allowing the user and the ftp group access to it (umask 0002) which is required for the ftproot account to access the users folders.


This was pretty straightforward. A few changes in the nslcd.conf file (as below) were needed. Also imported the ca certificate into the /etc/ssl/certs/ca-certificates.crt file and put the ldap server certificates and linked there hashes as below in SSL CA Certificates


# SSL options
ssl on
#tls_reqcert never

tls_cacertdir /etc/ssl/certs
tls_cacertfile /etc/ssl/certs/ca-certificates.crt

# The search scope.
#scope sub