diff --git a/bin/dbus/configurationmanager-introspec.xml b/bin/dbus/configurationmanager-introspec.xml
index 431023769b9a647acab1b2da6a392b653c3e00f7..50f4a6108b4180bc5d388df8d0df4e51f6dcf28e 100644
--- a/bin/dbus/configurationmanager-introspec.xml
+++ b/bin/dbus/configurationmanager-introspec.xml
@@ -193,6 +193,54 @@
            </arg>
        </method>
 
+        <method name="importAccounts" tp:name-for-bindings="importAccounts">
+            <tp:docstring>
+              Import previously exported accounts
+            </tp:docstring>
+           <arg type="s" name="path" direction="in">
+               <tp:docstring>
+                    Path of the file to import
+               </tp:docstring>
+           </arg>
+           <arg type="s" name="password" direction="in">
+               <tp:docstring>
+                    Decryption password
+               </tp:docstring>
+           </arg>
+           <arg type="i" direction="out">
+               <tp:docstring>
+                    <p>Return code, 0 for success.</p>
+               </tp:docstring>
+           </arg>
+        </method>
+
+        <method name="exportAccounts" tp:name-for-bindings="exportAccounts">
+            <tp:docstring>
+              Export account configuration to an encrypted file.
+            </tp:docstring>
+           <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="VectorString"/>
+           <arg type="as" name="accountIDs" direction="in">
+               <tp:docstring>
+                   A list of account IDs
+               </tp:docstring>
+           </arg>
+           <arg type="s" name="filepath" direction="in">
+               <tp:docstring>
+                    Where to export the account
+               </tp:docstring>
+           </arg>
+           <arg type="s" name="password" direction="in">
+               <tp:docstring>
+                    File encryption password
+               </tp:docstring>
+           </arg>
+           <arg type="i" direction="out">
+               <tp:docstring>
+                    <p>Return code, 0 for success.</p>
+               </tp:docstring>
+           </arg>
+        </method>
+
        <method name="registerAllAccounts" tp:name-for-bindings="registerAllAccounts">
            <tp:docstring>
                 Send account registration (REGISTER) for all accounts, even if they are not enabled.
diff --git a/bin/dbus/dbusconfigurationmanager.cpp b/bin/dbus/dbusconfigurationmanager.cpp
index 9cd02e5f2044998d07feaaf147062dc6ecf26d72..bb3cfa37820dd19718c47db1b7084acb04472c1a 100644
--- a/bin/dbus/dbusconfigurationmanager.cpp
+++ b/bin/dbus/dbusconfigurationmanager.cpp
@@ -527,3 +527,15 @@ DBusConfigurationManager::getVolume(const std::string& device) -> decltype(DRing
 {
     return DRing::getVolume(device);
 }
+
+auto
+DBusConfigurationManager::exportAccounts(const std::vector<std::string>& accountIDs, const std::string& filepath, const std::string& password) -> decltype(DRing::exportAccounts(accountIDs, filepath, password))
+{
+    return DRing::exportAccounts(accountIDs, filepath, password);
+}
+
+auto
+DBusConfigurationManager::importAccounts(const std::string& archivePath, const std::string& password) -> decltype(DRing::importAccounts(archivePath, password))
+{
+    return DRing::importAccounts(archivePath, password);
+}
diff --git a/bin/dbus/dbusconfigurationmanager.h b/bin/dbus/dbusconfigurationmanager.h
index 931ebdf593b519d63918af1fe02bb3529acf0dd7..e40eaf20872b8d97dae6fe1f7f81f94d84b1a0f7 100644
--- a/bin/dbus/dbusconfigurationmanager.h
+++ b/bin/dbus/dbusconfigurationmanager.h
@@ -137,6 +137,8 @@ class DBusConfigurationManager :
         bool acceptTrustRequest(const std::string& accountId, const std::string& from);
         bool discardTrustRequest(const std::string& accountId, const std::string& from);
         void sendTrustRequest(const std::string& accountId, const std::string& to, const std::vector<uint8_t>& payload);
+        int exportAccounts(const std::vector<std::string>& accountIDs, const std::string& filepath, const std::string& password);
+        int importAccounts(const std::string& archivePath, const std::string& password);
 };
 
 #endif // __RING_DBUSCONFIGURATIONMANAGER_H__
diff --git a/configure.ac b/configure.ac
index f55779c00669eb02b53731b86ef3316748048b6b..951db4bdef2fbd79d24dd57ccb63cd1c07fd56f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -157,6 +157,7 @@ AC_TYPE_SIZE_T
 AC_HEADER_TIME
 AC_C_VOLATILE
 AC_CHECK_TYPES([ptrdiff_t])
+AC_CHECK_LIB(zlib, zlib)
 
 PKG_PROG_PKG_CONFIG()
 
@@ -236,7 +237,7 @@ AS_IF([test -n "${CONTRIB_DIR}"], [
         export PKG_CONFIG_PATH_CUSTOM
   ])
   export PKG_CONFIG_PATH="${CONTRIB_DIR}/lib/pkgconfig:${CONTRIB_DIR}/lib64/pkgconfig:$PKG_CONFIG_PATH"
-  LDFLAGS="${LDFLAGS} -L${CONTRIB_DIR}/lib"
+  LDFLAGS="${LDFLAGS} -L${CONTRIB_DIR}/lib -lz"
 
   AS_IF([test "${SYS}" = "darwin"], [
     export LD_LIBRARY_PATH="${CONTRIB_DIR}/lib:$LD_LIBRARY_PATH"
diff --git a/contrib/src/opendht/rules.mak b/contrib/src/opendht/rules.mak
index 4281f262c772b775c4dc6d99d3b9689134385831..b05b627fe8edf5a1e2f236572e209708db88cf6b 100644
--- a/contrib/src/opendht/rules.mak
+++ b/contrib/src/opendht/rules.mak
@@ -1,5 +1,5 @@
 # OPENDHT
-OPENDHT_VERSION := 281b62dfd529a226e94d0da19e01acf07871a797
+OPENDHT_VERSION := 8ae95f1284f3c00c41832ef4d76196481543f59e
 OPENDHT_URL := https://github.com/savoirfairelinux/opendht/archive/$(OPENDHT_VERSION).tar.gz
 
 PKGS += opendht
diff --git a/src/Makefile.am b/src/Makefile.am
index 52b19cd417b41e3a9c8d933e3577c79e0361e82d..43dc74404ec618bcc5a0a5e12c40d1c9e6aa7afe 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -116,6 +116,7 @@ libring_la_SOURCES = \
 		account.cpp \
 		logger.cpp \
 		fileutils.cpp \
+		archiver.cpp \
 		threadloop.cpp \
 		ip_utils.h \
 		ip_utils.cpp \
@@ -137,6 +138,7 @@ libring_la_SOURCES = \
 		call.h \
 		logger.h \
 		fileutils.h \
+		archiver.h \
 		noncopyable.h \
 		utf8_utils.h \
 		ring_types.h \
diff --git a/src/archiver.cpp b/src/archiver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f242f4f7630772b6ce8b1f8b091d09e32e7e3075
--- /dev/null
+++ b/src/archiver.cpp
@@ -0,0 +1,280 @@
+/*
+ *  Copyright (C) 2016 Savoir-faire Linux Inc.
+ *
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+#include "archiver.h"
+
+#include <json/json.h>
+
+#include "client/ring_signal.h"
+#include "account_const.h"
+#include "configurationmanager_interface.h"
+
+#include "manager.h"
+#include "fileutils.h"
+#include "logger.h"
+
+#include <opendht/crypto.h>
+
+#include <fstream>
+#include <sys/stat.h>
+
+namespace ring {
+
+Archiver&
+Archiver::instance()
+{
+    // Meyers singleton
+    static Archiver instance_;
+    return instance_;
+}
+
+Archiver::Archiver()
+{
+
+}
+
+int
+Archiver::exportAccounts(std::vector<std::string> accountIDs,
+                        std::string filepath,
+                        std::string password)
+{
+    if (filepath.empty() || !accountIDs.size()) {
+        RING_ERR("Missing arguments");
+        return EINVAL;
+    }
+
+    std::size_t found = filepath.find_last_of(DIR_SEPARATOR_STR);
+    auto toDir = filepath.substr(0,found);
+    auto filename = filepath.substr(found+1);
+
+    if (!fileutils::isDirectory(toDir)) {
+        RING_ERR("%s is not a directory", toDir.c_str());
+        return ENOTDIR;
+    }
+
+    // Add
+    Json::Value root;
+    Json::Value array;
+
+    for (size_t i = 0; i < accountIDs.size(); ++i) {
+        auto detailsMap = Manager::instance().getAccountDetails(accountIDs[i]);
+        if (detailsMap.empty()) {
+            RING_WARN("Can't export account %s", accountIDs[i].c_str());
+            continue;
+        }
+
+        auto jsonAccount = accountToJsonValue(detailsMap);
+        array.append(jsonAccount);
+    }
+    root["accounts"] = array;
+    Json::FastWriter fastWriter;
+    std::string output = fastWriter.write(root);
+
+    // Compress
+    std::vector<uint8_t> compressed;
+    try {
+        compressed = compress(output);
+    } catch (const std::runtime_error& ex) {
+        RING_ERR("Export failed: %s", ex.what());
+        return 1;
+    }
+
+    // Encrypt using provided password
+    auto encrypted = dht::crypto::aesEncrypt(compressed, password);
+
+    // Write
+    try {
+        fileutils::saveFile(toDir + DIR_SEPARATOR_STR + filename, encrypted);
+    } catch (const std::runtime_error& ex) {
+        RING_ERR("Export failed: %s", ex.what());
+        return EIO;
+    }
+    return 0;
+}
+
+Json::Value
+Archiver::accountToJsonValue(std::map<std::string, std::string> details) {
+    Json::Value root;
+    std::map<std::string, std::string>::iterator iter;
+    for (iter = details.begin(); iter != details.end(); ++iter) {
+
+        if (iter->first.compare(DRing::Account::ConfProperties::Ringtone::PATH) == 0) {
+            // Ringtone path is not exportable
+        } else if (iter->first.compare(DRing::Account::ConfProperties::TLS::CA_LIST_FILE) == 0 ||
+                iter->first.compare(DRing::Account::ConfProperties::TLS::CERTIFICATE_FILE) == 0 ||
+                iter->first.compare(DRing::Account::ConfProperties::TLS::PRIVATE_KEY_FILE) == 0) {
+            // replace paths by the files content
+            std::ifstream ifs(iter->second);
+            std::string fileContent((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
+            root[iter->first] = fileContent;
+
+        } else
+            root[iter->first] = iter->second;
+    }
+
+    return root;
+}
+
+int
+Archiver::importAccounts(std::string archivePath, std::string password)
+{
+    if (archivePath.empty()) {
+        RING_ERR("Missing arguments");
+        return EINVAL;
+    }
+
+    // Read file
+    std::vector<uint8_t> file;
+    try {
+        file = fileutils::loadFile(archivePath);
+    } catch (const std::exception& ex) {
+        RING_ERR("Read failed: %s", ex.what());
+        return ENOENT;
+    }
+
+    // Decrypt
+    try {
+        file = dht::crypto::aesDecrypt(file, password);
+    } catch (const std::exception& ex) {
+        RING_ERR("Decryption failed: %s", ex.what());
+        return EPERM;
+    }
+
+    // Decompress
+    try {
+        file = decompress(file);
+    } catch (const std::exception& ex) {
+        RING_ERR("Decompression failed: %s", ex.what());
+        return ERANGE;
+    }
+
+    try {
+        // Decode string
+        std::string decoded {file.begin(), file.end()};
+
+        // Add
+        Json::Value root;
+        Json::Reader reader;
+        if (!reader.parse(decoded.c_str(),root)) {
+            RING_ERR("Failed to parse %s", reader.getFormattedErrorMessages().c_str());
+            return ERANGE;
+        }
+
+        auto& accounts = root["accounts"];
+        for (int i = 0, n = accounts.size(); i < n; ++i) {
+            // Generate a new account id
+            auto accountId = ring::Manager::instance().getNewAccountId();
+            auto details = jsonValueToAccount(accounts[i], accountId);
+            ring::Manager::instance().addAccount(details, accountId);
+        }
+    } catch (const std::exception& ex) {
+        RING_ERR("Import failed: %s", ex.what());
+        return ERANGE;
+    }
+    return 0;
+}
+
+std::map<std::string, std::string>
+Archiver::jsonValueToAccount(Json::Value& value, const std::string& accountId) {
+    auto idPath_ = fileutils::get_data_dir() + DIR_SEPARATOR_STR + accountId;
+    fileutils::check_dir(idPath_.c_str(), 0700);
+    auto detailsMap = DRing::getAccountTemplate(value[DRing::Account::ConfProperties::TYPE].asString());
+
+    for( Json::ValueIterator itr = value.begin() ; itr != value.end() ; itr++ ) {
+        if (itr->asString().empty())
+            continue;
+        if (itr.key().asString().compare(DRing::Account::ConfProperties::TLS::CA_LIST_FILE) == 0) {
+            std::string fileContent(itr->asString());
+            fileutils::saveFile(idPath_ + DIR_SEPARATOR_STR "ca.key", {fileContent.begin(), fileContent.end()}, 0600);
+
+        } else if (itr.key().asString().compare(DRing::Account::ConfProperties::TLS::PRIVATE_KEY_FILE) == 0) {
+            std::string fileContent(itr->asString());
+            fileutils::saveFile(idPath_ + DIR_SEPARATOR_STR "dht.key", {fileContent.begin(), fileContent.end()}, 0600);
+
+        } else if (itr.key().asString().compare(DRing::Account::ConfProperties::TLS::CERTIFICATE_FILE) == 0) {
+            std::string fileContent(itr->asString());
+            fileutils::saveFile(idPath_ + DIR_SEPARATOR_STR "dht.crt", {fileContent.begin(), fileContent.end()}, 0600);
+        } else
+            detailsMap[itr.key().asString()] = itr->asString();
+    }
+
+    return detailsMap;
+}
+
+std::vector<uint8_t>
+Archiver::compress(const std::string& str, int compressionlevel)
+{
+    auto destSize = compressBound(str.size());
+    std::vector<uint8_t> outbuffer(destSize);
+    int ret = ::compress(reinterpret_cast<Bytef*>(outbuffer.data()), &destSize, (Bytef*)str.data(), str.size());
+
+    if (ret != Z_OK) {
+        std::ostringstream oss;
+        oss << "Exception during zlib compression: (" << ret << ") ";
+        throw(std::runtime_error(oss.str()));
+    }
+
+    return outbuffer;
+}
+
+std::vector<uint8_t>
+Archiver::decompress(const std::vector<uint8_t>& str)
+{
+    z_stream zs; // z_stream is zlib's control structure
+    memset(&zs, 0, sizeof(zs));
+
+    if (inflateInit(&zs) != Z_OK)
+        throw(std::runtime_error("inflateInit failed while decompressing."));
+
+    zs.next_in = (Bytef*)str.data();
+    zs.avail_in = str.size();
+
+    int ret;
+    std::vector<uint8_t> out;
+
+    // get the decompressed bytes blockwise using repeated calls to inflate
+    do {
+        std::array<uint8_t, 32768> outbuffer;
+        zs.next_out = reinterpret_cast<Bytef*>(outbuffer.data());
+        zs.avail_out = outbuffer.size();
+
+        ret = inflate(&zs, 0);
+        if (ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
+            break;
+
+        if (out.size() < zs.total_out) {
+            // append the block to the output string
+            out.insert(out.end(), outbuffer.begin(), outbuffer.begin() + zs.total_out - out.size());
+        }
+    } while (ret == Z_OK);
+
+    inflateEnd(&zs);
+
+    // an error occurred that was not EOF
+    if (ret != Z_STREAM_END) {
+        std::ostringstream oss;
+        oss << "Exception during zlib decompression: (" << ret << ") " << zs.msg;
+        throw(std::runtime_error(oss.str()));
+    }
+
+    return out;
+}
+
+} // namespace ring
diff --git a/src/archiver.h b/src/archiver.h
new file mode 100644
index 0000000000000000000000000000000000000000..6513e37cc5833614db402456bb7e1c09172054b8
--- /dev/null
+++ b/src/archiver.h
@@ -0,0 +1,83 @@
+/*
+ *  Copyright (C) 2016 Savoir-faire Linux Inc.
+ *
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+#pragma once
+
+#include "noncopyable.h"
+
+#include <string>
+#include <vector>
+#include <map>
+#include <zlib.h>
+
+namespace Json {
+class Value;
+};
+
+namespace ring {
+
+/**
+ * Archiver is used to generate/read encrypted archives
+ */
+class Archiver {
+public:
+    static Archiver& instance();
+
+    Archiver();
+
+    /**
+     * Create a protected archive containing a list of accounts
+     * @param accountIDs The accounts to exports
+     * @param filepath The filepath where to put the resulting archive
+     * @param password The mandatory password to set on the archive
+     * @returns 0 for OK, error code otherwise
+     */
+    int exportAccounts(std::vector<std::string> accountIDs,
+                        std::string filepath,
+                        std::string password);
+
+    /**
+     * Read a protected archive and add accounts found in it
+     * Warning: this function must be called from a registered pjsip thread
+     * @param archivePath The path to the archive file
+     * @param password The password to read the archive
+     * @returns 0 for OK, error code otherwise
+     */
+    int importAccounts(std::string archivePath, std::string password);
+
+    /**
+     * Compress a STL string using zlib with given compression level and return
+     * the binary data.
+     */
+    std::vector<uint8_t> compress(const std::string& str, int compressionlevel = Z_BEST_COMPRESSION);
+
+    /**
+     * Decompress an STL string using zlib and return the original data.
+     */
+    std::vector<uint8_t> decompress(const std::vector<uint8_t>& dat);
+
+private:
+    NON_COPYABLE(Archiver);
+
+    static Json::Value accountToJsonValue(std::map<std::string, std::string> details);
+    static std::map<std::string, std::string> jsonValueToAccount(Json::Value& value, const std::string& accountId);
+};
+
+} // namespace ring
diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp
index d8fb9441afdff80bf41771a4ae27139d7ef5ab48..e4737e65297d42fed5b8b1eef1d87cac2ac0d3f4 100644
--- a/src/client/configurationmanager.cpp
+++ b/src/client/configurationmanager.cpp
@@ -34,6 +34,7 @@
 #endif
 #include "logger.h"
 #include "fileutils.h"
+#include "archiver.h"
 #include "ip_utils.h"
 #include "sip/sipaccount.h"
 #include "ringdht/ringaccount.h"
@@ -320,6 +321,21 @@ sendTrustRequest(const std::string& accountId, const std::string& to, const std:
         acc->sendTrustRequest(to, payload);
 }
 
+/*
+ * Import/Export accounts
+ */
+int
+exportAccounts(std::vector<std::string> accountIDs, std::string filepath, std::string password)
+{
+    return ring::Archiver::instance().exportAccounts(accountIDs, filepath, password);
+}
+
+int
+importAccounts(std::string archivePath, std::string password)
+{
+    return ring::Archiver::instance().importAccounts(archivePath, password);
+}
+
 ///This function is used as a base for new accounts for clients that support it
 std::map<std::string, std::string>
 getAccountTemplate(const std::string& accountType)
diff --git a/src/dring/configurationmanager_interface.h b/src/dring/configurationmanager_interface.h
index 8836b81717cb5b7b8c9a0dbca096c09a587247e8..56b3370be0153a9b552f2f3e5bbb6906dae533dc 100644
--- a/src/dring/configurationmanager_interface.h
+++ b/src/dring/configurationmanager_interface.h
@@ -150,6 +150,12 @@ bool discardTrustRequest(const std::string& accountId, const std::string& from);
 
 void sendTrustRequest(const std::string& accountId, const std::string& to, const std::vector<uint8_t>& payload = {});
 
+/*
+ * Import/Export accounts
+ */
+int exportAccounts(std::vector<std::string> accountIDs, std::string filepath, std::string password);
+int importAccounts(std::string archivePath, std::string password);
+
 struct AudioSignal {
         struct DeviceEvent {
                 constexpr static const char* name = "audioDeviceEvent";
diff --git a/src/manager.cpp b/src/manager.cpp
index 54a91831073e3011e6993bdebf9909189dc7ea4c..4a3b82c4f7618799c6f4d791385b2108e59c76e3 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -2433,9 +2433,8 @@ Manager::setAccountDetails(const std::string& accountID,
 }
 
 std::string
-Manager::addAccount(const std::map<std::string, std::string>& details)
+Manager::getNewAccountId()
 {
-    /** @todo Deal with both the accountMap_ and the Configuration */
     std::string newAccountID;
     static std::uniform_int_distribution<uint64_t> rand_acc_id;
 
@@ -2448,8 +2447,16 @@ Manager::addAccount(const std::map<std::string, std::string>& details)
     } while (std::find(accountList.begin(), accountList.end(), newAccountID)
              != accountList.end());
 
-    // Get the type
+    return newAccountID;
+}
 
+std::string
+Manager::addAccount(const std::map<std::string, std::string>& details, const std::string& accountId)
+{
+    /** @todo Deal with both the accountMap_ and the Configuration */
+    auto newAccountID = accountId.empty() ? getNewAccountId() : accountId;
+
+    // Get the type
     const char* accountType;
     if (details.find(Conf::CONFIG_ACCOUNT_TYPE) != details.end())
         accountType = (*details.find(Conf::CONFIG_ACCOUNT_TYPE)).second.c_str();
diff --git a/src/manager.h b/src/manager.h
index 476e239ef21be8c5786506476264473578ec4c63..eb3edcd4e23f901b6800ed92533837686edcea41 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -499,12 +499,20 @@ class Manager {
 
         void setAccountActive(const std::string& accountID, bool active);
 
+        /**
+         * Return a new random accountid that is not present in the list
+         * @return A brand new accountid
+         */
+        std::string getNewAccountId();
+
         /**
          * Add a new account, and give it a new account ID automatically
          * @param details The new account parameters
+         * @param accountId optionnal predetermined accountid to use
          * @return The account Id given to the new account
          */
-        std::string addAccount(const std::map<std::string, std::string> &details);
+        std::string addAccount(const std::map<std::string, std::string> &details,
+                               const std::string& accountId = {});
 
         /**
          * Delete an existing account, unregister VoIPLink associated, and
diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index 15658d2bb503376a6eccc89d800cdfd5d6612202..2515e7ce5432a4c72a6d90e930c5e552e65b4fd5 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -425,7 +425,7 @@ void RingAccount::unserialize(const YAML::Node &node)
     using yaml_utils::parseValue;
 
     SIPAccountBase::unserialize(node);
-    parseValue(node, Conf::DHT_PORT_KEY, dhtPort_);
+
     parseValue(node, Conf::DHT_ALLOW_PEERS_FROM_HISTORY, allowPeersFromHistory_);
     parseValue(node, Conf::DHT_ALLOW_PEERS_FROM_CONTACT, allowPeersFromContact_);
     parseValue(node, Conf::DHT_ALLOW_PEERS_FROM_TRUSTED, allowPeersFromTrusted_);
@@ -1251,6 +1251,9 @@ RingAccount::loadDhParams(const std::string path)
 void
 RingAccount::generateDhParams()
 {
+    //make sure cachePath_ is writable
+    fileutils::check_dir(cachePath_.c_str(), 0700);
+
     std::packaged_task<decltype(loadDhParams)> task(loadDhParams);
     dhParams_ = task.get_future();
     std::thread task_td(std::move(task), cachePath_ + DIR_SEPARATOR_STR "dhParams");