This will become a setup for NFS4 with Kerberos and LDAP with TLS on Debian Squeeze. The Kerberos data will be saved in LDAP. Most information in this setup comes from Heiko Noordhof. I know, there are allready pages in this wiki about NFS4, Kerberos and LDAP. This howto tries to make it easy to setup.

Server setup:

# become root:
su -

# When you did install LDAP or Kerberos or NFS before, it is a good idea to remove it to 
# have a clean start.
apt-get purge krb5-kdc-ldap gnutls-bin krb5-admin-server nfs-kernel-server \
  ldap-utils slapd krb5-kdc
rm -rfv /var/lib/ldap
rm -v /etc/ssl/certs/CAself-cert.pem
rm -v /etc/ssl/certs/*_slapd_cert.pem
rm -v /etc/ssl/*.info
rm -v /etc/ssl/private/*_slapd_key.pem
rm -v /etc/ssl/private/CAself-key.pem

# Your fqdn-hostname should be OK, it should be something like:  server1.example.com
# When it's wrong, change your /etc/hosts, there should be a line like:
# 127.0.1.1       server1.example.com   server1
# with this command you can check your fqdn hostname:
hostname --fqdn

# Main setup variables defaults
# change them when needed with something like:  DOMAIN="example2.com"
SERVER=$(hostname --fqdn)   # something like: server1.example.com
DOMAIN=${SERVER#*.}         # something like: example.com
REALM=$(echo "${DOMAIN}" | tr '[:lower:]' '[:upper:]')   # something like: EXAMPLE.COM
LDAPROOT=""; IFS="."; for DC in $DOMAIN ; do LDAPROOT="${LDAPROOT},dc=$DC"; done
LDAPROOT="${LDAPROOT#,}"    # somthing like "dc=example,dc=com"
echo "SERVER: $SERVER"; echo "DOMAIN: $DOMAIN"; echo "REALM: $REALM"; echo "LDAPROOT: $LDAPROOT"

# Install packages without questions. You can also answer the questions but this is 
# pointless, because the configuration will be overwritten later.
# Some errors are normal because of the noninteractive install
DEBIAN_FRONTEND=noninteractive apt-get install ldap-utils slapd nfs-kernel-server \
  krb5-admin-server krb5-kdc krb5-kdc-ldap krb5-doc libnss-ldap nscd libpam-ldap \
  gnutls-bin ssl-cert ntp pwgen

# Directory for temporary setup files
SETUPDIR=$(mktemp --directory /tmp/server-setup.XXXXXXXXXX)
cd "$SETUPDIR"
echo "Setup directory: $SETUPDIR"

# Setup ldap.conf for clients
cat <<EOF >/etc/ldap/ldap.conf
BASE    ${LDAPROOT}
URI     ldapi://
EOF

# Setup SSL/TLS certificate (self-signed) for TLS on LDAP
CA_KEY=/etc/ssl/private/CAself-key.pem
CA_INFO=/etc/ssl/CAself.info
CA_CERT=/etc/ssl/certs/CAself-cert.pem
certtool --generate-privkey >"${CA_KEY}"
cat <<EOF >"${CA_INFO}"
cn = ${DOMAIN}
ca
cert_signing_key
EOF
certtool \
    --generate-self-signed \
    --load-privkey "${CA_KEY}" \
    --template "${CA_INFO}" \
    --outfile "${CA_CERT}"
chgrp ssl-cert "${CA_KEY}"
chmod 0640 "${CA_KEY}"

# Generate private-key for TLS on the LDAP-service
LDAP_TLS_KEY="/etc/ssl/private/${SERVER}_slapd_key.pem"
LDAP_TLS_INFO="/etc/ssl/${SERVER}.info"
LDAP_TLS_CERT="/etc/ssl/certs/${SERVER}_slapd_cert.pem"
certtool --generate-privkey >"${LDAP_TLS_KEY}"
cat <<EOF >"${LDAP_TLS_INFO}"
organization = ${DOMAIN}
cn = ${SERVER}
tls_www_server
encryption_key
signing_key
EOF
certtool \
    --generate-certificate \
    --load-privkey "${LDAP_TLS_KEY}" \
    --load-ca-certificate "${CA_CERT}" \
    --load-ca-privkey "${CA_KEY}" \
    --template "${LDAP_TLS_INFO}" \
    --outfile "${LDAP_TLS_CERT}"
chgrp ssl-cert "${LDAP_TLS_KEY}"
chmod 0640 "${LDAP_TLS_KEY}"

# Set access to ssl keys for LDAP-daemon (slapd)
adduser openldap ssl-cert

# Generate hash from admin password
LDAP_ADMIN_PW=`pwgen -s 10 1`
echo -n "$LDAP_ADMIN_PW" >ldap-admin-pw.txt
chmod 600 ldap-admin-pw.txt
LDAP_ADMIN_HASH=$(slappasswd -h '{SHA}' -T ldap-admin-pw.txt)

# Create ldifs and load them into LDAP
cat <<EOF >slapd-loglevel.ldif
dn: cn=config
changeType: modify
replace: olcLogLevel
olcLogLevel: stats
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f slapd-loglevel.ldif

cat <<EOF >slapd-tls.ldif
dn: cn=config
changeType: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: ${CA_CERT}
-
add: olcTLSCertificateFile
olcTLSCertificateFile: ${LDAP_TLS_CERT}
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: ${LDAP_TLS_KEY}
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f slapd-tls.ldif

cat <<EOF >slapd-database.ldif
dn: olcDatabase={1}hdb,cn=config
changeType: modify
replace: olcDbConfig
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbConfig: {4}set_flags DB_LOG_AUTOREMOVE
-
replace: olcRootPW
olcRootPW: ${LDAP_ADMIN_HASH}
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f slapd-database.ldif

# Do not listen on the clear-text port (389) only SSL/LDAPS (636)
sed -i 's|^SLAPD_SERVICES.*|SLAPD_SERVICES="ldaps:/// ldapi:///"|' /etc/default/slapd

# Restart LDAP-server
/etc/init.d/slapd restart

# Setup LDAP structure
# Generate random password for kerberos-admin account in LDAP, and a hash.
LDAP_KRBADMIN_PW=$(cat /proc/sys/kernel/random/uuid)
echo -n "$LDAP_KRBADMIN_PW" >ldap-krbadmin-pw.txt
chmod 600 ldap-krbadmin-pw.txt
LDAP_KRBADMIN_HASH=$(slappasswd -h '{SHA}' -T ldap-krbadmin-pw.txt)

cat <<EOF >structure.ldif
dn: cn=krb-admin,${LDAPROOT}
cn: krb-admin
objectClass: organizationalRole
objectClass: simpleSecurityObject
userPassword: ${LDAP_KRBADMIN_HASH}

dn: ou=groups,${LDAPROOT}
objectClass: organizationalUnit
ou: groups

dn: ou=users,${LDAPROOT}
objectClass: organizationalUnit
ou: users
EOF
ldapadd -x -D cn=admin,"${LDAPROOT}" -y ldap-admin-pw.txt -f structure.ldif

# Setup kerberos services, with backend database in LDAP
# Prepare LDAP configuration for use as a MIT-kerberos database backend.
# Convert the schema file installed by "krb5-kdc-ldap" package to 
# openldap's new cn=config
gunzip -c /usr/share/doc/krb5-kdc-ldap/kerberos.schema.gz >krb.schema
echo 'include krb.schema' >slapd.tmp.conf
slaptest -f slapd.tmp.conf -F ./
mv  'cn=config/cn=schema/cn={0}krb.ldif' krb.schema.ldif
sed -i 's/^dn: cn={0}krb/dn: cn=kerberos,cn=schema,cn=config/' krb.schema.ldif
sed -i 's/^cn: {0}krb/cn: kerberos/' krb.schema.ldif
sed -i '/^structuralObjectClass/,$d' krb.schema.ldif
ldapadd -QY EXTERNAL -H ldapi:///  -f krb.schema.ldif

# Add index
cat <<EOF >krbindex.ldif
dn: olcDatabase={1}hdb,cn=config
add: olcDbIndex
olcDbIndex: krbPrincipalName eq,pres,sub
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f krbindex.ldif

# Add some ACL's
cat <<EOF >krbacl.ldif
dn: olcDatabase={1}hdb,cn=config
replace: olcAccess
olcAccess: to attrs=userPassword,shadowLastChange,krbPrincipalKey by dn="cn=krb-admin,${LDAPROOT}" write by anonymous auth by self write by * none
-
add: olcAccess
olcAccess: to dn.base="" by * read
-
add: olcAccess
olcAccess: to * by dn="cn=krb-admin,${LDAPROOT}" write by * read
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f krbacl.ldif

# Setup MIT-kerberos 
cp /etc/krb5.conf /etc/krb5.conf.bak-$(date +%Y%m%d_%H%M)
cat <<EOF >/etc/krb5.conf2
[libdefaults]
        default_realm = ${REALM}
        allow_weak_crypto = true
        default_tgs_enctypes = des-cbc-crc
        default_tkt_enctypes = des-cbc-crc
        permitted_enctypes = des-cbc-crc

        krb4_config = /etc/krb.conf
        krb4_realms = /etc/krb.realms
        kdc_timesync = 1
        ccache_type = 4
        forwardable = true
        proxiable = true

[realms]
        ${REALM} = {
                kdc = ${SERVER}
                admin_server = ${SERVER}
                default_domain = ${DOMAIN}
                database_module = openldap_ldapconf
        }

[domain_realm]
        .${DOMAIN} = ${REALM}

[login]
        krb4_convert = true
        krb4_get_tickets = false

[logging]
     kdc = SYSLOG:INFO:DAEMON
     admin_server = SYSLOG:INFO:DAEMON
     default = SYSLOG:INFO:DAEMON

[dbdefaults]
        ldap_kerberos_container_dn = ${LDAPROOT}

[dbmodules]
        openldap_ldapconf = {
                db_library = kldap
                ldap_kdc_dn = "cn=krb-admin,${LDAPROOT}"
                ldap_kadmind_dn = "cn=krb-admin,${LDAPROOT}"
                ldap_service_password_file = /etc/krb5kdc/service.keyfile
                ldap_servers = ldapi:///
                ldap_conns_per_server = 5
EOF

# Create basic entries in the kerberos LDAP backend
clear
echo "You will now be asked to enter a password (twice)."
echo "You will normally not need to use this regularly, but"
echo "it may become quite important if something ever goes wrong."
echo
echo "So... please think well and store in a safe place."
echo 
kdb5_ldap_util -w "$LDAP_KRBADMIN_PW" \
    -D  "cn=krb-admin,$LDAPROOT" \
    create \
    -subtrees "$LDAPROOT" \
    -r "$REALM" \
    -s \
    -H ldapi:///

# Stash the LDAP-password for the account the kerberos daemons use to
# read and write to LDAP
echo
echo "You will now be asked to enter a password (twice)."
echo "Please copy/paste the following password in there: $LDAP_KRBADMIN_PW"
echo

kdb5_ldap_util -w "$LDAP_KRBADMIN_PW" \
    -D  "cn=krb-admin,$LDAPROOT" \
    stashsrvpw \
    -f /etc/krb5kdc/service.keyfile \
    "cn=krb-admin,$LDAPROOT"

clear
echo "Please take note of the following information"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo
echo "==> LDAP root: ${LDAPROOT}"
echo
echo "==> Kerberos realm: ${REALM}"
echo
echo "==> LDAP super-user account:"
echo "    cn=admin,${LDAPROOT}"
echo "    password: ${LDAP_ADMIN_PW}"
echo
echo "Dont't forget to make a principal with admin permissions in kerberos."
echo "You will need that (together with LDAP super-user) to create accounts."
echo "To do this start kadmin.local (as root) on the server. At the prompt"
echo "enter:  addprinc yourname/admin"
echo
echo "The following TMP-directory contains passwords among other things: "
echo "==> $SETUPDIR"
echo
echo "Please make sure you remove this directory!"
echo

# Setup LDAP structure
# Generate random password for kerberos-admin account in LDAP, and a hash 
# from it.
LDAP_KRBADMIN_PW=$(cat /proc/sys/kernel/random/uuid)
echo -n "$LDAP_KRBADMIN_PW" >ldap-krbadmin-pw.txt
chmod 600 ldap-krbadmin-pw.txt
LDAP_KRBADMIN_HASH=$(slappasswd -h '{SHA}' -T ldap-krbadmin-pw.txt)

cat <<EOF >structure.ldif
dn: cn=krb-admin,${LDAPROOT}
cn: krb-admin
objectClass: organizationalRole
objectClass: simpleSecurityObject
userPassword: ${LDAP_KRBADMIN_HASH}

dn: ou=groups,${LDAPROOT}
objectClass: organizationalUnit
ou: groups

dn: ou=users,${LDAPROOT}
objectClass: organizationalUnit
ou: users
EOF
ldapadd -x -D cn=admin,"${LDAPROOT}" -y ldap-admin-pw.txt -f structure.ldif

# Setup kerberos backend database in LDAP
gunzip -c /usr/share/doc/krb5-kdc-ldap/kerberos.schema.gz >krb.schema
echo 'include krb.schema' >slapd.tmp.conf
slaptest -f slapd.tmp.conf -F ./
mv  'cn=config/cn=schema/cn={0}krb.ldif' krb.schema.ldif
sed -i 's/^dn: cn={0}krb/dn: cn=kerberos,cn=schema,cn=config/' krb.schema.ldif
sed -i 's/^cn: {0}krb/cn: kerberos/' krb.schema.ldif
sed -i '/^structuralObjectClass/,$d' krb.schema.ldif
ldapadd -QY EXTERNAL -H ldapi:///  -f krb.schema.ldif

# Add index
cat <<EOF >krbindex.ldif
dn: olcDatabase={1}hdb,cn=config
add: olcDbIndex
olcDbIndex: krbPrincipalName eq,pres,sub
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f krbindex.ldif

# Add some ACL's
cat <<EOF >krbacl.ldif
dn: olcDatabase={1}hdb,cn=config
replace: olcAccess
olcAccess: to attrs=userPassword,shadowLastChange,krbPrincipalKey by dn="cn=krb-admin,${LDAPROOT}" write by anonymous auth by self write by * none
-
add: olcAccess
olcAccess: to dn.base="" by * read
-
add: olcAccess
olcAccess: to * by dn="cn=krb-admin,${LDAPROOT}" write by * read
EOF
ldapmodify -v -Y EXTERNAL -H ldapi:/// -f krbacl.ldif

# Setup MIT-kerberos 
cp /etc/krb5.conf /etc/krb5.conf.bak-$(date +%Y%m%d_%H%M)
cat <<EOF >/etc/krb5.conf
[libdefaults]
        default_realm = ${REALM}
        allow_weak_crypto = true
        default_tgs_enctypes = des-cbc-crc
        default_tkt_enctypes = des-cbc-crc
        permitted_enctypes = des-cbc-crc

        krb4_config = /etc/krb.conf
        krb4_realms = /etc/krb.realms
        kdc_timesync = 1
        ccache_type = 4
        forwardable = true
        proxiable = true

[realms]
        ${REALM} = {
                kdc = ${SERVER}
                admin_server = ${SERVER}
                default_domain = ${DOMAIN}
                database_module = openldap_ldapconf
        }

[domain_realm]
        .${DOMAIN} = ${REALM}

[login]
        krb4_convert = true
        krb4_get_tickets = false

[logging]
     kdc = SYSLOG:INFO:DAEMON
     admin_server = SYSLOG:INFO:DAEMON
     default = SYSLOG:INFO:DAEMON

[dbdefaults]
        ldap_kerberos_container_dn = ${LDAPROOT}

[dbmodules]
        openldap_ldapconf = {
                db_library = kldap
                ldap_kdc_dn = "cn=krb-admin,${LDAPROOT}"
                ldap_kadmind_dn = "cn=krb-admin,${LDAPROOT}"
                ldap_service_password_file = /etc/krb5kdc/service.keyfile
                ldap_servers = ldapi:///
                ldap_conns_per_server = 5
EOF

# Create basic entries in the kerberos LDAP backend
clear
echo "You will now be asked to enter a password (twice)."
echo "You will normally not need to use this regularly, but"
echo "it may become quite important if something ever goes wrong."
echo
echo "So... please think well and store in a safe place."
echo 
kdb5_ldap_util -w "$LDAP_KRBADMIN_PW" \
    -D  "cn=krb-admin,$LDAPROOT" \
    create \
    -subtrees "$LDAPROOT" \
    -r "$REALM" \
    -s \
    -H ldapi:///

# Stash the LDAP-password for the account the kerberos daemons use to
# read and write to LDAP
echo
echo "You will now be asked to enter a password (twice)."
echo "Please copy/paste the following password in there: $LDAP_KRBADMIN_PW"
echo

kdb5_ldap_util -w "$LDAP_KRBADMIN_PW" \
    -D  "cn=krb-admin,$LDAPROOT" \
    stashsrvpw \
    -f /etc/krb5kdc/service.keyfile \
    "cn=krb-admin,$LDAPROOT"

clear
echo "Please take note of the following information"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo
echo "==> LDAP root: ${LDAPROOT}"
echo
echo "==> Kerberos realm: ${REALM}"
echo
echo "==> LDAP super-user account:"
echo "    cn=admin,${LDAPROOT}"
echo "    password: ${LDAP_ADMIN_PW}"
echo
echo "Dont't forget to make a principal with admin permissions in kerberos."
echo "You will need that (together with LDAP super-user) to create accounts."
echo "To do this start kadmin.local (as root) on the server. At the prompt"
echo "enter:  addprinc yourname/admin"
echo
echo "The following TMP-directory contains passwords among other things: "
echo "==> $SETUPDIR"
echo
echo "Please make sure you remove this directory!"