diff --git a/src/account.cpp b/src/account.cpp
index 244d470591ac8a4c69dcca161792bbae98f7aca2..4ca0850c32e695268faad1488353ffbb77b33351 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -42,6 +42,7 @@ using random_device = dht::crypto::random_device;
 #include "client/ring_signal.h"
 #include "account_schema.h"
 #include "string_utils.h"
+#include "fileutils.h"
 #include "config/yamlparser.h"
 #include "system_codec_container.h"
 #include "ice_transport.h"
@@ -410,6 +411,14 @@ Account::parseString(const std::map<std::string, std::string>& details,
     s = iter->second;
 }
 
+void
+Account::parsePath(const std::map<std::string, std::string>& details,
+                   const char *key, std::string &s, const std::string& base)
+{
+    find_iter();
+    s = fileutils::getCleanPath(base, iter->second);
+}
+
 void
 Account::parseBool(const std::map<std::string, std::string>& details,
                    const char* key, bool &b)
diff --git a/src/account.h b/src/account.h
index f0d4375d5def66a4fb68d0e604e6252f240851f3..7ee94b5ef7a235ab2e1089c38d135218d0306744 100644
--- a/src/account.h
+++ b/src/account.h
@@ -326,6 +326,7 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
     protected:
         static void parseString(const std::map<std::string, std::string> &details, const char *key, std::string &s);
         static void parseBool(const std::map<std::string, std::string> &details, const char *key, bool &b);
+        static void parsePath(const std::map<std::string, std::string> &details, const char *key, std::string &s, const std::string& base);
 
         template<class T>
         static inline void
diff --git a/src/config/yamlparser.cpp b/src/config/yamlparser.cpp
index 1aac3d7caad50233ce347b37740caedb926596cc..17160ba24d9211191fae6b4d9f5a364461ed2567 100644
--- a/src/config/yamlparser.cpp
+++ b/src/config/yamlparser.cpp
@@ -19,13 +19,22 @@
  */
 
 #include "yamlparser.h"
+#include "fileutils.h"
 
-namespace ring {
+namespace ring { namespace yaml_utils {
+
+void
+parsePath(const YAML::Node &node, const char *key, std::string& path, const std::string& base)
+{
+    std::string val;
+    parseValue(node, key, val);
+    path = fileutils::getCleanPath(base, val);
+}
 
 // FIXME: Maybe think of something more clever, this is due to yaml-cpp's poor
 // handling of empty values for nested collections.
 std::vector<std::map<std::string, std::string>>
-yaml_utils::parseVectorMap(const YAML::Node &node, const std::initializer_list<std::string> &keys)
+parseVectorMap(const YAML::Node &node, const std::initializer_list<std::string> &keys)
 {
     std::vector<std::map<std::string, std::string>> result;
     for (const auto &n : node) {
@@ -38,4 +47,4 @@ yaml_utils::parseVectorMap(const YAML::Node &node, const std::initializer_list<s
     return result;
 }
 
-} // namespace ring
+}} // namespace ring::yaml_utils
diff --git a/src/config/yamlparser.h b/src/config/yamlparser.h
index a1234ec7527eb1f69bb1077cb876497a3d884fac..eaab6be237ff91487aae5fa42ce84a85751e7bfc 100644
--- a/src/config/yamlparser.h
+++ b/src/config/yamlparser.h
@@ -18,8 +18,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
  */
 
-#ifndef __YAMLPARSER_H__
-#define __YAMLPARSER_H__
+#pragma once
 
 #include <yaml-cpp/yaml.h>
 
@@ -33,9 +32,9 @@ void parseValue(const YAML::Node &node, const char *key, T &value)
     value = node[key].as<T>(value);
 }
 
+void parsePath(const YAML::Node &node, const char *key, std::string& path, const std::string& base);
+
 std::vector<std::map<std::string, std::string>>
 parseVectorMap(const YAML::Node &node, const std::initializer_list<std::string> &keys);
 
 }} // namespace ring::yaml_utils
-
-#endif
diff --git a/src/fileutils.cpp b/src/fileutils.cpp
index bd040d5a7020112f96a01fa540080143dc21cb44..5e87286f130012edd9a6f4c6ace0969fb5d1914a 100644
--- a/src/fileutils.cpp
+++ b/src/fileutils.cpp
@@ -299,12 +299,30 @@ bool isPathRelative(const std::string& path)
 #endif
 }
 
+std::string
+getCleanPath(const std::string& base, const std::string& path)
+{
+    if (base.empty() or path.size() < base.size())
+        return path;
+    auto base_sep = base + DIR_SEPARATOR_STR;
+    if (path.compare(0, base_sep.size(), base_sep) == 0)
+        return path.substr(base_sep.size());
+    else
+        return path;
+}
+
+std::string
+getFullPath(const std::string& base, const std::string& path)
+{
+    bool isRelative {not base.empty() and isPathRelative(path)};
+    return isRelative ? base + DIR_SEPARATOR_STR + path : path;
+}
+
 std::vector<uint8_t>
 loadFile(const std::string& path, const std::string& default_dir)
 {
-    bool isRelative {not default_dir.empty() and isPathRelative(path)};
     std::vector<uint8_t> buffer;
-    std::ifstream file(isRelative ? default_dir + DIR_SEPARATOR_STR + path : path, std::ios::binary);
+    std::ifstream file(getFullPath(default_dir, path), std::ios::binary);
     if (!file)
         throw std::runtime_error("Can't read file: "+path);
     file.seekg(0, std::ios::end);
diff --git a/src/fileutils.h b/src/fileutils.h
index 5d3d3c64f353d7e1fd43c1a2c908e90799d082e1..10e65c28d90a13d9b3d6589b849c0df9d97f6c42 100644
--- a/src/fileutils.h
+++ b/src/fileutils.h
@@ -59,8 +59,8 @@ namespace ring { namespace fileutils {
 
     /**
      * Check directory existance and create it with given mode if it doesn't.
-     * @path path to check, relative or absolute
-     * @dir last directory creation mode
+     * @param path to check, relative or absolute
+     * @param dir last directory creation mode
      * @param parents default mode for all created directories except the last
      */
     bool check_dir(const char *path, mode_t dir=0755, mode_t parents=0755);
@@ -71,6 +71,16 @@ namespace ring { namespace fileutils {
     bool recursive_mkdir(const std::string& path, mode_t mode=0755);
 
     bool isPathRelative(const std::string& path);
+    /**
+     * If path is contained in base, return the suffix, otherwise return the full path.
+     * @param base must not finish with DIR_SEPARATOR_STR, can be empty
+     * @param path the path
+     */
+    std::string getCleanPath(const std::string& base, const std::string& path);
+    /**
+     * If path is relative, it is appended to base.
+     */
+    std::string getFullPath(const std::string& base, const std::string& path);
 
     bool isFile(const std::string& path);
     bool isDirectory(const std::string& path);
diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index 49005d43cd459c6d5a20e18dc0ca8640d942165c..cfdd69c642c9e33df4352a2ce69675de489d7bb2 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -695,8 +695,17 @@ void RingAccount::serialize(YAML::Emitter &out)
 void RingAccount::unserialize(const YAML::Node &node)
 {
     using yaml_utils::parseValue;
+    using yaml_utils::parsePath;
 
     SIPAccountBase::unserialize(node);
+
+    // get tls submap
+    const auto &tlsMap = node[Conf::TLS_KEY];
+    parsePath(tlsMap, Conf::CERTIFICATE_KEY, tlsCertificateFile_, idPath_);
+    parsePath(tlsMap, Conf::CALIST_KEY, tlsCaListFile_, idPath_);
+    parseValue(tlsMap, Conf::TLS_PASSWORD_KEY, tlsPassword_);
+    parsePath(tlsMap, Conf::PRIVATE_KEY_KEY, tlsPrivateKeyFile_, idPath_);
+
     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_);
@@ -707,7 +716,7 @@ void RingAccount::unserialize(const YAML::Node &node)
     }
 
     try {
-        parseValue(node, DRing::Account::ConfProperties::ARCHIVE_PATH, archivePath_);
+        parsePath(node, DRing::Account::ConfProperties::ARCHIVE_PATH, archivePath_, idPath_);
     } catch (const std::exception& e) {
         RING_WARN("can't read archive path: %s", e.what());
     }
@@ -753,7 +762,7 @@ RingAccount::createRingDevice(const dht::crypto::Identity& id)
     fileutils::check_dir(idPath_.c_str(), 0700);
 
     // save the chain including CA
-    std::tie(tlsPrivateKeyFile_, tlsCertificateFile_) = saveIdentity(dev_id, idPath_ + DIR_SEPARATOR_STR "ring_device");
+    std::tie(tlsPrivateKeyFile_, tlsCertificateFile_) = saveIdentity(dev_id, idPath_, "ring_device");
     tlsPassword_ = {};
     identity_ = dev_id;
     ringDeviceId_ = dev_id.first->getPublicKey().getId().toString();
@@ -877,13 +886,13 @@ RingAccount::useIdentity(const dht::crypto::Identity& identity)
 }
 
 dht::crypto::Identity
-RingAccount::loadIdentity(const std::string& crt_path, const std::string& key_path, const std::string& key_pwd)
+RingAccount::loadIdentity(const std::string& crt_path, const std::string& key_path, const std::string& key_pwd) const
 {
     RING_DBG("Loading identity: %s %s", crt_path.c_str(), key_path.c_str());
     dht::crypto::Identity id;
     try {
-        dht::crypto::Certificate dht_cert(fileutils::loadFile(crt_path));
-        dht::crypto::PrivateKey  dht_key(fileutils::loadFile(key_path), key_pwd);
+        dht::crypto::Certificate dht_cert(fileutils::loadFile(crt_path, idPath_));
+        dht::crypto::PrivateKey  dht_key(fileutils::loadFile(key_path, idPath_), key_pwd);
         auto crt_id = dht_cert.getId();
         if (crt_id != dht_key.getPublicKey().getId())
             return {};
@@ -916,7 +925,7 @@ RingAccount::readArchive(const std::string& pwd) const
 
     // Read file
     try {
-        data = fileutils::loadFile(archivePath_);
+        data = fileutils::loadFile(archivePath_, idPath_);
     } catch (const std::exception& e) {
         RING_ERR("[Account %s] archive loading error: %s", getAccountID().c_str(), e.what());
         throw;
@@ -1063,8 +1072,8 @@ RingAccount::saveArchive(const ArchiveContent& archive_content, const std::strin
     // Write
     try {
         if (archivePath_.empty())
-            archivePath_ = idPath_ + DIR_SEPARATOR_STR "export.gz";
-        fileutils::saveFile(archivePath_, encrypted);
+            archivePath_ = "export.gz";
+        fileutils::saveFile(fileutils::getFullPath(idPath_, archivePath_), encrypted);
     } catch (const std::runtime_error& ex) {
         RING_ERR("Export failed: %s", ex.what());
         return;
@@ -1177,14 +1186,14 @@ RingAccount::revokeDevice(const std::string& password, const std::string& device
 }
 
 std::pair<std::string, std::string>
-RingAccount::saveIdentity(const dht::crypto::Identity id, const std::string& path) const
+RingAccount::saveIdentity(const dht::crypto::Identity id, const std::string& path, const std::string& name)
 {
-    auto paths = std::make_pair(path + ".key", path + ".crt");
+    auto names = std::make_pair(name + ".key", name + ".crt");
     if (id.first)
-        fileutils::saveFile(paths.first, id.first->serialize(), 0600);
+        fileutils::saveFile(path + DIR_SEPARATOR_STR + names.first, id.first->serialize(), 0600);
     if (id.second)
-        fileutils::saveFile(paths.second, id.second->getPacked(), 0600);
-    return paths;
+        fileutils::saveFile(path + DIR_SEPARATOR_STR + names.second, id.second->getPacked(), 0600);
+    return names;
 }
 
 void
@@ -1404,7 +1413,7 @@ RingAccount::migrateAccount(const std::string& pwd)
     }
 
     if (updateCertificates(archive, identity_)) {
-        std::tie(tlsPrivateKeyFile_, tlsCertificateFile_) = saveIdentity(identity_, idPath_ + DIR_SEPARATOR_STR "ring_device");
+        std::tie(tlsPrivateKeyFile_, tlsCertificateFile_) = saveIdentity(identity_, idPath_, "ring_device");
         saveArchive(archive, pwd);
         setRegistrationState(RegistrationState::UNREGISTERED);
         Migration::setState(accountID_, Migration::State::SUCCESS);
@@ -1420,14 +1429,7 @@ RingAccount::loadAccount(const std::string& archive_password, const std::string&
 
     RING_DBG("[Account %s] loading Ring account", getAccountID().c_str());
     try {
-#if TARGET_OS_IPHONE
-        const auto certPath = idPath_ + DIR_SEPARATOR_STR + tlsCertificateFile_;
-        const auto keyPath = idPath_ + DIR_SEPARATOR_STR + tlsPrivateKeyFile_;
-#else
-        const auto& certPath = tlsCertificateFile_;
-        const auto& keyPath = tlsPrivateKeyFile_;
-#endif
-        auto id = loadIdentity(certPath, keyPath, tlsPassword_);
+        auto id = loadIdentity(tlsCertificateFile_, tlsPrivateKeyFile_, tlsPassword_);
         bool hasValidId = useIdentity(id);
         bool needMigration = hasValidId and needsMigration(id);
         bool hasArchive = not archivePath_.empty() and fileutils::isFile(archivePath_);
@@ -1483,9 +1485,16 @@ RingAccount::loadAccount(const std::string& archive_password, const std::string&
 }
 
 void
-RingAccount::setAccountDetails(const std::map<std::string, std::string> &details)
+RingAccount::setAccountDetails(const std::map<std::string, std::string>& details)
 {
     SIPAccountBase::setAccountDetails(details);
+
+    // TLS
+    parsePath(details, Conf::CONFIG_TLS_CA_LIST_FILE, tlsCaListFile_, idPath_);
+    parsePath(details, Conf::CONFIG_TLS_CERTIFICATE_FILE, tlsCertificateFile_, idPath_);
+    parsePath(details, Conf::CONFIG_TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile_, idPath_);
+    parseString(details, Conf::CONFIG_TLS_PASSWORD, tlsPassword_);
+
     if (hostname_.empty())
         hostname_ = DHT_DEFAULT_BOOTSTRAP;
     parseInt(details, Conf::CONFIG_DHT_PORT, dhtPort_);
@@ -1502,7 +1511,7 @@ RingAccount::setAccountDetails(const std::map<std::string, std::string> &details
     parseString(details, DRing::Account::ConfProperties::ARCHIVE_PASSWORD, archive_password);
     parseString(details, DRing::Account::ConfProperties::ARCHIVE_PIN,      archive_pin);
     std::transform(archive_pin.begin(), archive_pin.end(), archive_pin.begin(), ::toupper);
-    parseString(details, DRing::Account::ConfProperties::ARCHIVE_PATH,     archivePath_);
+    parsePath(details, DRing::Account::ConfProperties::ARCHIVE_PATH,     archivePath_, idPath_);
     parseString(details, DRing::Account::ConfProperties::RING_DEVICE_NAME, ringDeviceName_);
 
 #if HAVE_RINGNS
@@ -1530,6 +1539,10 @@ RingAccount::getAccountDetails() const
     a.emplace(Conf::CONFIG_SRTP_ENABLE,       isSrtpEnabled() ? TRUE_STR : FALSE_STR);
     a.emplace(Conf::CONFIG_SRTP_RTP_FALLBACK, getSrtpFallback() ? TRUE_STR : FALSE_STR);
 
+    a.emplace(Conf::CONFIG_TLS_CA_LIST_FILE,        fileutils::getFullPath(idPath_, tlsCaListFile_));
+    a.emplace(Conf::CONFIG_TLS_CERTIFICATE_FILE,    fileutils::getFullPath(idPath_, tlsCertificateFile_));
+    a.emplace(Conf::CONFIG_TLS_PRIVATE_KEY_FILE,    fileutils::getFullPath(idPath_, tlsPrivateKeyFile_));
+    a.emplace(Conf::CONFIG_TLS_PASSWORD,            tlsPassword_);
     a.emplace(Conf::CONFIG_TLS_METHOD,                     "Automatic");
     a.emplace(Conf::CONFIG_TLS_CIPHERS,                    "");
     a.emplace(Conf::CONFIG_TLS_SERVER_NAME,                "");
diff --git a/src/ringdht/ringaccount.h b/src/ringdht/ringaccount.h
index e1882754de5e681c4dff5cdc4679ea00f0a94bc5..3024c7fa6fee3576f48b337cfdacbc5d69ce5e2e 100644
--- a/src/ringdht/ringaccount.h
+++ b/src/ringdht/ringaccount.h
@@ -499,7 +499,7 @@ class RingAccount : public SIPAccountBase {
         static ArchiveContent loadArchive(const std::vector<uint8_t>& data);
         std::vector<std::pair<sockaddr_storage, socklen_t>> loadBootstrap() const;
 
-        std::pair<std::string, std::string> saveIdentity(const dht::crypto::Identity id, const std::string& path) const;
+        static std::pair<std::string, std::string> saveIdentity(const dht::crypto::Identity id, const std::string& path, const std::string& name);
         void saveNodes(const std::vector<dht::NodeExport>&) const;
         void saveValues(const std::vector<dht::ValuesExport>&) const;
 
@@ -525,7 +525,7 @@ class RingAccount : public SIPAccountBase {
          * and certPath_ a valid certificate file, load and returns them.
          * Otherwise, generate a new identity and returns it.
          */
-        static dht::crypto::Identity loadIdentity(const std::string& crt_path, const std::string& key_path, const std::string& key_pwd);
+        dht::crypto::Identity loadIdentity(const std::string& crt_path, const std::string& key_path, const std::string& key_pwd) const;
         std::vector<dht::NodeExport> loadNodes() const;
         std::vector<dht::ValuesExport> loadValues() const;
 
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index da6a6fa4e331195b6962ea0a0444d7d9fadb3a08..1bafebdd9279c39d56c39edffa41aa17c865837b 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -499,7 +499,10 @@ void SIPAccount::unserialize(const YAML::Node &node)
 
     // get tls submap
     const auto &tlsMap = node[Conf::TLS_KEY];
-
+    parseValue(tlsMap, Conf::CERTIFICATE_KEY, tlsCertificateFile_);
+    parseValue(tlsMap, Conf::CALIST_KEY, tlsCaListFile_);
+    parseValue(tlsMap, Conf::TLS_PASSWORD_KEY, tlsPassword_);
+    parseValue(tlsMap, Conf::PRIVATE_KEY_KEY, tlsPrivateKeyFile_);
     parseValue(tlsMap, Conf::TLS_ENABLE_KEY, tlsEnable_);
     parseValue(tlsMap, Conf::TLS_PORT_KEY, tlsListenerPort_);
     parseValue(tlsMap, Conf::CIPHERS_KEY, tlsCiphers_);
@@ -530,6 +533,12 @@ void SIPAccount::setAccountDetails(const std::map<std::string, std::string> &det
 
     parseInt(details, Conf::CONFIG_LOCAL_PORT, localPort_);
 
+    // TLS
+    parseString(details, Conf::CONFIG_TLS_CA_LIST_FILE, tlsCaListFile_);
+    parseString(details, Conf::CONFIG_TLS_CERTIFICATE_FILE, tlsCertificateFile_);
+    parseString(details, Conf::CONFIG_TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile_);
+    parseString(details, Conf::CONFIG_TLS_PASSWORD, tlsPassword_);
+
     // SIP specific account settings
     parseString(details, Conf::CONFIG_ACCOUNT_ROUTESET, serviceRoute_);
 
diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp
index 098995d53fbc39762254ffa14d8bcff05e446e61..823558b14a462bb4c5c6d36d6a7d6478fe4f71e6 100644
--- a/src/sip/sipaccountbase.cpp
+++ b/src/sip/sipaccountbase.cpp
@@ -196,13 +196,6 @@ void SIPAccountBase::unserialize(const YAML::Node &node)
 
     parseValue(node, Conf::DTMF_TYPE_KEY, dtmfType_);
 
-    // get tls submap
-    const auto &tlsMap = node[Conf::TLS_KEY];
-    parseValue(tlsMap, Conf::CERTIFICATE_KEY, tlsCertificateFile_);
-    parseValue(tlsMap, Conf::CALIST_KEY, tlsCaListFile_);
-    parseValue(tlsMap, Conf::TLS_PASSWORD_KEY, tlsPassword_);
-    parseValue(tlsMap, Conf::PRIVATE_KEY_KEY, tlsPrivateKeyFile_);
-
     unserializeRange(node, Conf::AUDIO_PORT_MIN_KEY, Conf::AUDIO_PORT_MAX_KEY, audioPortRange_);
     unserializeRange(node, Conf::VIDEO_PORT_MIN_KEY, Conf::VIDEO_PORT_MAX_KEY, videoPortRange_);
 
@@ -245,12 +238,6 @@ void SIPAccountBase::setAccountDetails(const std::map<std::string, std::string>
     updateRange(tmpMin, tmpMax, videoPortRange_);
 #endif
 
-    // TLS
-    parseString(details, Conf::CONFIG_TLS_CA_LIST_FILE, tlsCaListFile_);
-    parseString(details, Conf::CONFIG_TLS_CERTIFICATE_FILE, tlsCertificateFile_);
-    parseString(details, Conf::CONFIG_TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile_);
-    parseString(details, Conf::CONFIG_TLS_PASSWORD, tlsPassword_);
-
     // ICE - STUN
     parseBool(details, Conf::CONFIG_STUN_ENABLE, stunEnabled_);
     parseString(details, Conf::CONFIG_STUN_SERVER, stunServer_);
@@ -288,11 +275,6 @@ SIPAccountBase::getAccountDetails() const
     a.emplace(Conf::CONFIG_TURN_SERVER_PWD, turnServerPwd_);
     a.emplace(Conf::CONFIG_TURN_SERVER_REALM, turnServerRealm_);
 
-    a.emplace(Conf::CONFIG_TLS_CA_LIST_FILE,        tlsCaListFile_);
-    a.emplace(Conf::CONFIG_TLS_CERTIFICATE_FILE,    tlsCertificateFile_);
-    a.emplace(Conf::CONFIG_TLS_PRIVATE_KEY_FILE,    tlsPrivateKeyFile_);
-    a.emplace(Conf::CONFIG_TLS_PASSWORD,            tlsPassword_);
-
     return a;
 }