diff --git a/src/fedfsd/main.c b/src/fedfsd/main.c
index 31718e8..eb7ab48 100644
--- a/src/fedfsd/main.c
+++ b/src/fedfsd/main.c
@@ -212,9 +212,6 @@ int main(int argc, char **argv)
 		}
 	}
 
-	if (!nsdb_create_basedir())
-		exit(EXIT_FAILURE);
-
 	if (!fedfsd_drop_privileges(uid, gid))
 		exit(EXIT_FAILURE);
 
diff --git a/src/include/nsdb.h b/src/include/nsdb.h
index 9c8383b..2ba1b7a 100644
--- a/src/include/nsdb.h
+++ b/src/include/nsdb.h
@@ -115,7 +115,6 @@ struct fedfs_fsl {
  * Locate the cert store
  */
 _Bool		 nsdb_set_parentdir(const char *parentdir);
-_Bool		 nsdb_create_basedir(void);
 _Bool		 nsdb_is_default_parentdir(void);
 _Bool		 nsdb_init_database(void);
 
diff --git a/src/libnsdb/nsdb.c b/src/libnsdb/nsdb.c
index c81f228..dec2091 100644
--- a/src/libnsdb/nsdb.c
+++ b/src/libnsdb/nsdb.c
@@ -157,50 +157,6 @@ nsdb_set_parentdir(const char *parentdir)
 }
 
 /**
- * Create parent directory
- *
- * @return true if fedfsd directory exists
- *
- * Warning: this function must be called as root, and is usually
- * invoked before the process has set its umask.
- */
-_Bool
-nsdb_create_basedir(void)
-{
-	struct passwd *pw;
-	_Bool retval;
-
-	retval = false;
-	if (mkdir(fedfs_base_dirname, FEDFS_BASE_DIRMODE) == -1) {
-		if (errno == EEXIST) {
-			xlog(D_CALL, "FedFS base directory exists");
-			retval = true;
-			goto out;
-		}
-		xlog(L_ERROR, "Failed to create base dir: %m");
-		goto out;
-	}
-
-	pw = getpwnam(FEDFS_USER);
-	if (pw == NULL) {
-		xlog(L_ERROR, "Failed to find %s", FEDFS_USER);
-		rmdir(fedfs_base_dirname);
-		goto out;
-	}
-
-	if (chown(fedfs_base_dirname, pw->pw_uid, pw->pw_gid) == -1) {
-		xlog(L_ERROR, "Failed to chown base dir: %m");
-		rmdir(fedfs_base_dirname);
-		goto out;
-	}
-
-	retval = true;
-
-out:
-	return retval;
-}
-
-/**
  * Predicate: Does parent directory refer to default FedFS state directory?
  *
  * @return true if active fedfsd directory is same as default
@@ -241,6 +197,10 @@ nsdb_create_tables(sqlite3 *db)
  * Ensure database file and tables exist
  *
  * @return true if successful
+ *
+ * This must be called with capabilities that allow the base
+ * directory and database to be created.  This is typically
+ * "cap_dac_override=ep".
  */
 _Bool
 nsdb_init_database(void)
@@ -253,6 +213,16 @@ nsdb_init_database(void)
 	xlog(D_CALL, "%s: Initializing database", __func__);
 
 	retval = false;
+
+	if (mkdir(fedfs_base_dirname, FEDFS_BASE_DIRMODE) == -1) {
+		if (errno != EEXIST) {
+			xlog(L_ERROR, "Failed to create base dir: %m");
+			goto out;
+		}
+		xlog(D_GENERAL, "%s: Base dir %s exists",
+			__func__, fedfs_base_dirname);
+	}
+
 	db = fedfs_open_db(fedfs_db_filename,
 				SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
 	if (db == NULL)
diff --git a/src/nsdbparams/Makefile.am b/src/nsdbparams/Makefile.am
index ddc3cd9..6205e32 100644
--- a/src/nsdbparams/Makefile.am
+++ b/src/nsdbparams/Makefile.am
@@ -27,7 +27,7 @@ noinst_HEADERS		= nsdbparams.h
 sbin_PROGRAMS		= nsdbparams
 nsdbparams_SOURCES	= delete.c list.c main.c show.c update.c
 LDADD			= $(LIBLDAP) $(LIBLBER) \
-			  $(LIBSQLITE3) $(LIBIDN) $(LIBUUID) \
+			  $(LIBSQLITE3) $(LIBIDN) $(LIBUUID) $(LIBCAP) \
 			  $(top_builddir)/src/libnsdb/libnsdb.a \
 			  $(top_builddir)/src/libjunction/libjunction.a \
 			  $(top_builddir)/src/libpath/libpath.a \
diff --git a/src/nsdbparams/delete.c b/src/nsdbparams/delete.c
index 37f30b1..6b86e3d 100644
--- a/src/nsdbparams/delete.c
+++ b/src/nsdbparams/delete.c
@@ -199,9 +199,6 @@ nsdbparams_delete(const char *progname, int argc, char **argv)
 	}
 	nsdbname = argv[optind];
 
-	if (!nsdb_create_basedir())
-		return EXIT_FAILURE;
-
 	if (!nsdbparams_drop_privileges(uid, gid))
 		return EXIT_FAILURE;
 
diff --git a/src/nsdbparams/list.c b/src/nsdbparams/list.c
index e79b896..f877604 100644
--- a/src/nsdbparams/list.c
+++ b/src/nsdbparams/list.c
@@ -177,9 +177,6 @@ nsdbparams_list(const char *progname, int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	if (!nsdb_create_basedir())
-		return EXIT_FAILURE;
-
 	if (!nsdbparams_drop_privileges(uid, gid))
 		return EXIT_FAILURE;
 
diff --git a/src/nsdbparams/main.c b/src/nsdbparams/main.c
index 91b0372..6e96c1c 100644
--- a/src/nsdbparams/main.c
+++ b/src/nsdbparams/main.c
@@ -47,6 +47,11 @@
 #include "nsdbparams.h"
 
 /**
+ * Capabilies that nsdbparams should retain, in text format.
+ */
+#define NSDBPARAMS_CAPABILITIES "cap_dac_override=ep"
+
+/**
  * Display program synopsis
  *
  * @param progname NUL-terminated C string containing name of program
@@ -69,6 +74,52 @@ nsdbparams_usage(const char *progname)
 }
 
 /**
+ * Clear all capabilities but a certain few.
+ *
+ * @return true if successful
+ *
+ * This permits callers to create directories anywhere, but all other
+ * capabilities are dropped.
+ */
+static _Bool
+nsdbparams_clear_capabilities(void)
+{
+	cap_t caps;
+	char *text;
+
+	caps = cap_from_text(NSDBPARAMS_CAPABILITIES);
+	if (caps == NULL) {
+		xlog(L_ERROR, "Failed to allocate capability: %m");
+		return false;
+	}
+
+	if (cap_set_proc(caps) == -1) {
+		xlog(L_ERROR, "Failed to set capability flags: %m");
+		(void)cap_free(caps);
+		return false;
+	}
+
+	(void)cap_free(caps);
+
+	caps = cap_get_proc();
+	if (caps == NULL)
+		goto out;
+
+	text = cap_to_text(caps, NULL);
+	if (text == NULL)
+		goto out_free;
+
+	xlog(D_CALL, "Process capabilities: %s", text);
+	(void)cap_free(text);
+
+out_free:
+	(void)cap_free(caps);
+
+out:
+	return true;
+}
+
+/**
  * Drop root privileges
  *
  * @param uid run as this effective uid
@@ -80,6 +131,8 @@ nsdbparams_usage(const char *progname)
 _Bool
 nsdbparams_drop_privileges(const uid_t uid, const gid_t gid)
 {
+	_Bool result;
+
 	(void)umask(S_IWGRP | S_IWOTH);
 
 	/*
@@ -109,10 +162,11 @@ nsdbparams_drop_privileges(const uid_t uid, const gid_t gid)
 		return false;
 	}
 
+	result = nsdbparams_clear_capabilities();
+
 	xlog(D_CALL, "%s: Effective UID, GID: %u, %u",
 			__func__, geteuid(), getegid());
-
-	return true;
+	return result;
 }
 
 /**
diff --git a/src/nsdbparams/show.c b/src/nsdbparams/show.c
index ba52521..d95f61c 100644
--- a/src/nsdbparams/show.c
+++ b/src/nsdbparams/show.c
@@ -189,9 +189,6 @@ nsdbparams_show(const char *progname, int argc, char **argv)
 		}
 	}
 
-	if (!nsdb_create_basedir())
-		return EXIT_FAILURE;
-
 	if (!nsdbparams_drop_privileges(uid, gid))
 		return EXIT_FAILURE;
 
diff --git a/src/nsdbparams/update.c b/src/nsdbparams/update.c
index bde2151..d073552 100644
--- a/src/nsdbparams/update.c
+++ b/src/nsdbparams/update.c
@@ -333,9 +333,6 @@ nsdbparams_update(const char *progname, int argc, char **argv)
 		goto out;
 	}
 
-	if (!nsdb_create_basedir())
-		goto out;
-
 	if (!nsdbparams_drop_privileges(uid, gid))
 		goto out;
 
