diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index 4bbf622..0785b04 100644
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -309,6 +309,10 @@ static int conf_process(conf_t *conf)
 		strncat(dest, dbext, strlen(dbext));
 		zone->ixfr_db = dest;
 	}
+	
+	/* Update UID and GID. */
+	if (conf->uid < 0) conf->uid = getuid();
+	if (conf->gid < 0) conf->gid = getgid();
 
 	return ret;
 }
diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
index 97412dd..be8840a 100644
--- a/src/knot/ctl/knotc_main.c
+++ b/src/knot/ctl/knotc_main.c
@@ -722,6 +722,9 @@ int main(int argc, char **argv)
 		log_levels_add(LOGT_STDOUT, LOG_ANY,
 		               LOG_MASK(LOG_INFO)|LOG_MASK(LOG_DEBUG));
 	}
+	
+	/* Alter privileges. */
+	proc_update_privileges(conf()->uid, conf()->gid);
 
 	// Fetch PID
 	char* pidfile = pid_filename();
diff --git a/src/knot/ctl/process.c b/src/knot/ctl/process.c
index bb61804..8864cd0 100644
--- a/src/knot/ctl/process.c
+++ b/src/knot/ctl/process.c
@@ -21,6 +21,8 @@
 #include <errno.h>
 #include <string.h>
 #include <signal.h>
+#include <grp.h>
+#include <unistd.h>
 
 #include "knot/common.h"
 #include "knot/ctl/process.h"
@@ -113,6 +115,7 @@ int pid_write(const char* fn)
 int pid_remove(const char* fn)
 {
 	if (unlink(fn) < 0) {
+		perror("unlink");
 		return KNOTD_EINVAL;
 	}
 
@@ -124,3 +127,45 @@ int pid_running(pid_t pid)
 	return kill(pid, 0) == 0;
 }
 
+void proc_update_privileges(int uid, int gid)
+{
+#ifdef HAVE_SETGROUPS
+	/* Drop supplementary groups. */
+	if (uid != getuid() || gid != getgid()) {
+		if (setgroups(0, NULL) < 0) {
+			log_server_warning("Failed to drop supplementary groups"
+			                   " for uid '%d' (%s).\n",
+			                   getuid(), strerror(errno));
+		}
+	}
+#endif
+	
+	/* Watch uid/gid. */
+	if (gid != getgid()) {
+		log_server_info("Changing group id to '%d'.\n", gid);
+		if (setregid(gid, gid) < 0) {
+			log_server_error("Failed to change gid to '%d'.\n",
+			                 gid);
+		}
+	}
+	if (uid != getuid()) {
+		log_server_info("Changing user id to '%d'.\n", uid);
+		if (setreuid(uid, uid) < 0) {
+			log_server_error("Failed to change uid to '%d'.\n",
+			                 uid);
+		}
+	}
+	
+	/* Check storage writeability. */
+	char *lfile = strcdup(conf()->storage, "/knot.lock");
+	assert(lfile != NULL);
+	FILE* fp = fopen(lfile, "w");
+	if (fp == NULL) {
+		log_server_warning("Storage directory '%s' is not writeable.\n",
+		                   conf()->storage);
+	} else {
+		fclose(fp);
+		unlink(lfile);
+	}
+	free(lfile);
+}
diff --git a/src/knot/ctl/process.h b/src/knot/ctl/process.h
index d8f2f4c..a387add 100644
--- a/src/knot/ctl/process.h
+++ b/src/knot/ctl/process.h
@@ -83,6 +83,15 @@ int pid_remove(const char* fn);
  */
 int pid_running(pid_t pid);
 
+/*!
+ * \brief Update process privileges to new UID/GID.
+ *
+ * \param uid New user ID.
+ * \param gid New group ID.
+ *
+ */
+void proc_update_privileges(int uid, int gid);
+
 #endif // _KNOTD_PROCESS_H_
 
 /*! @} */
diff --git a/src/knot/main.c b/src/knot/main.c
index 99ee1cf..a62230a 100644
--- a/src/knot/main.c
+++ b/src/knot/main.c
@@ -20,6 +20,7 @@
 #include <unistd.h>
 #include <getopt.h>
 #include <limits.h>
+
 #ifdef HAVE_CAP_NG_H
 #include <cap-ng.h>
 #endif /* HAVE_CAP_NG_H */
@@ -161,7 +162,6 @@ int main(int argc, char **argv)
 	conf_read_lock();
 	conf_add_hook(conf(), CONF_LOG, log_conf_hook, 0);
 	conf_add_hook(conf(), CONF_ALL, server_conf_hook, server);
-	conf_add_hook(conf(), CONF_ALL, zones_ns_conf_hook, server->nameserver);
 	conf_read_unlock();
 
 	// Find implicit configuration file
@@ -242,21 +242,28 @@ int main(int argc, char **argv)
 	}
 	log_server_info("\n");
 
-	// Create server instance
-	char* pidfile = pid_filename();
+	/* Alter privileges. */
+	proc_update_privileges(conf()->uid, conf()->gid);
+	
+	/* Load zones and add hook. */
+	zones_ns_conf_hook(conf(), server->nameserver);
+	conf_add_hook(conf(), CONF_ALL, zones_ns_conf_hook, server->nameserver);
 
 	// Run server
 	int res = 0;
+	int has_pid = 0;
+	char* pidfile = pid_filename();
 	log_server_info("Starting server...\n");
 	if ((server_start(server)) == KNOTD_EOK) {
 
 		// Save PID
-		int has_pid = 1;
+		has_pid = 1;
 		int rc = pid_write(pidfile);
 		if (rc < 0) {
 			has_pid = 0;
 			log_server_warning("Failed to create "
-					   "PID file '%s'.\n", pidfile);
+					   "PID file '%s' (%s).\n",
+					   pidfile, strerror(errno));
 		}
 
 		// Change directory if daemonized
@@ -370,7 +377,7 @@ int main(int argc, char **argv)
 	server_destroy(&server);
 
 	// Remove PID file
-	if (pid_remove(pidfile) < 0) {
+	if (has_pid && pid_remove(pidfile) < 0) {
 		log_server_warning("Failed to remove PID file.\n");
 	}
 
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
index 5611a0c..5df7fe1 100644
--- a/src/knot/server/server.c
+++ b/src/knot/server/server.c
@@ -22,8 +22,6 @@
 #include <errno.h>
 #include <openssl/evp.h>
 #include <assert.h>
-#include <grp.h>
-
 
 #include "common/prng.h"
 #include "knot/common.h"
@@ -743,51 +741,9 @@ int server_conf_hook(const struct conf_t *conf, void *data)
 			                 "configured interfaces.\n");
 		}
 	}
-	
-	/* Lock configuration. */
-	conf_read_lock();
-	int priv_failed = 0;
-	
-#ifdef HAVE_SETGROUPS
-	/* Drop supplementary groups. */
-	if (conf->gid > -1 || conf->uid > -1) {
-		ret = setgroups(0, NULL);
-		
-		/* Collect results. */
-		if (ret < 0) {
-			log_server_error("Failed to set supplementary groups "
-			                 "for uid '%d' (%s).\n",
-			                 getuid(), strerror(errno));
-			priv_failed = 1;
-		}
-	}
-#endif
-	
-	/* Watch uid/gid. */
-	if (conf->gid > -1 && conf->gid != getgid()) {
-		log_server_info("Changing group id to '%d'.\n", conf->gid);
-		if (setregid(conf->gid, conf->gid) < 0) {
-			log_server_error("Failed to change gid to '%d'.\n",
-			                 conf->gid);
-			priv_failed = 1;
-		}
-	}
-	if (conf->uid > -1 && conf->uid != getuid()) {
-		log_server_info("Changing user id to '%d'.\n", conf->uid);
-		if (setreuid(conf->uid, conf->uid) < 0) {
-			log_server_error("Failed to change uid to '%d'.\n",
-			                 conf->uid);
-			priv_failed = 1;
-		}
-	}
-
-	if (priv_failed) {
-		ret = KNOTD_EACCES;
-	}
 
 	/* Exit if the server is not running. */
 	if (ret != KNOTD_EOK || !(server->state & ServerRunning)) {
-		conf_read_unlock();
 		return KNOTD_ENOTRUNNING;
 	}
 
@@ -807,9 +763,6 @@ int server_conf_hook(const struct conf_t *conf, void *data)
 		}
 	}
 
-	/* Unlock config. */
-	conf_read_unlock();
-
 	return ret;
 }
 
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
index c4415d4..3c39004 100644
--- a/src/zcompile/zcompile.c
+++ b/src/zcompile/zcompile.c
@@ -570,7 +570,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
 	}
 
 	if (!knot_dname_is_fqdn(dname)) {
-		fprintf(stderr, "Error: given zone origin is not FQDN.\n");
+		log_zone_error("Error: given zone origin is not FQDN.\n");
 		knot_dname_release(dname);
 		return KNOTDZCOMPILE_EINVAL;
 	}
@@ -660,8 +660,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
 
 	if (found_orphans != parser->rrsig_orphan_count) {
 		/*! \todo This might be desired behaviour. */
-		fprintf(stderr,
-		        "There are unassigned RRSIGs in the zone!\n");
+		log_zone_error("There are unassigned RRSIGs in the zone!\n");
 		parser->errors++;
 	}
 
