diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp
index 8ab53d3b87..4ca2439996 100644
--- a/assignment-client/src/assets/AssetServer.cpp
+++ b/assignment-client/src/assets/AssetServer.cpp
@@ -45,25 +45,67 @@ AssetServer::AssetServer(ReceivedMessage& message) :
 }
 
 void AssetServer::run() {
+
+    qDebug() << "Waiting for connection to domain to request settings from domain-server.";
+
+    // wait until we have the domain-server settings, otherwise we bail
+    DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
+    connect(&domainHandler, &DomainHandler::settingsReceived, this, &AssetServer::completeSetup);
+    connect(&domainHandler, &DomainHandler::settingsReceiveFail, this, &AssetServer::domainSettingsRequestFailed);
+
     ThreadedAssignment::commonInit(ASSET_SERVER_LOGGING_TARGET_NAME, NodeType::AssetServer);
+}
 
+void AssetServer::completeSetup() {
     auto nodeList = DependencyManager::get<NodeList>();
-    nodeList->addNodeTypeToInterestSet(NodeType::Agent);
 
-    const QString RESOURCES_PATH = "assets";
+    auto& domainHandler = nodeList->getDomainHandler();
+    const QJsonObject& settingsObject = domainHandler.getSettingsObject();
 
-    _resourcesDirectory = QDir(ServerPathUtils::getDataDirectory()).filePath(RESOURCES_PATH);
+    static const QString ASSET_SERVER_SETTINGS_KEY = "asset_server";
+
+    if (!settingsObject.contains(ASSET_SERVER_SETTINGS_KEY)) {
+        qCritical() << "Received settings from the domain-server with no asset-server section. Stopping assignment.";
+        setFinished(true);
+        return;
+    }
+
+    auto assetServerObject = settingsObject[ASSET_SERVER_SETTINGS_KEY].toObject();
+
+    // get the path to the asset folder from the domain server settings
+    static const QString ASSETS_PATH_OPTION = "assets_path";
+    auto assetsJSONValue = assetServerObject[ASSETS_PATH_OPTION];
+
+    if (!assetsJSONValue.isString()) {
+        qCritical() << "Received an assets path from the domain-server that could not be parsed. Stopping assignment.";
+        setFinished(true);
+        return;
+    }
+
+    auto assetsPathString = assetsJSONValue.toString();
+    QDir assetsPath { assetsPathString };
+    QString absoluteFilePath = assetsPath.absolutePath();
+
+    if (assetsPath.isRelative()) {
+        // if the domain settings passed us a relative path, make an absolute path that is relative to the
+        // default data directory
+        absoluteFilePath = ServerPathUtils::getDataFilePath("assets/" + assetsPathString);
+    }
+
+    _resourcesDirectory = QDir(absoluteFilePath);
 
     qDebug() << "Creating resources directory";
     _resourcesDirectory.mkpath(".");
 
-    bool noExistingAssets = !_resourcesDirectory.exists() \
-        || _resourcesDirectory.entryList(QDir::Files).size() == 0;
+    bool noExistingAssets = !_resourcesDirectory.exists() || _resourcesDirectory.entryList(QDir::Files).size() == 0;
 
     if (noExistingAssets) {
-        qDebug() << "Asset resources directory not found, searching for existing asset resources";
+        qDebug() << "Asset resources directory empty, searching for existing asset resources to migrate";
         QString oldDataDirectory = QCoreApplication::applicationDirPath();
-        auto oldResourcesDirectory = QDir(oldDataDirectory).filePath("resources/" + RESOURCES_PATH);
+
+        const QString OLD_RESOURCES_PATH = "assets";
+
+        auto oldResourcesDirectory = QDir(oldDataDirectory).filePath("resources/" + OLD_RESOURCES_PATH);
 
 
         if (QDir(oldResourcesDirectory).exists()) {
@@ -111,10 +153,12 @@ void AssetServer::run() {
             auto hexHash = hash.toHex();
 
             qDebug() << "\tMoving " << filename << " to " << hexHash;
-
+            
             file.rename(_resourcesDirectory.absoluteFilePath(hexHash) + "." + fileInfo.suffix());
         }
     }
+
+    nodeList->addNodeTypeToInterestSet(NodeType::Agent);
 }
 
 void AssetServer::handleAssetGetInfo(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h
index fe83ce92a6..7d6e26af08 100644
--- a/assignment-client/src/assets/AssetServer.h
+++ b/assignment-client/src/assets/AssetServer.h
@@ -29,6 +29,8 @@ public slots:
     void run();
 
 private slots:
+    void completeSetup();
+
     void handleAssetGetInfo(QSharedPointer<ReceivedMessage> packet, SharedNodePointer senderNode);
     void handleAssetGet(QSharedPointer<ReceivedMessage> packet, SharedNodePointer senderNode);
     void handleAssetUpload(QSharedPointer<ReceivedMessage> packetList, SharedNodePointer senderNode);
diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json
index 891c586a6a..014d9f3767 100644
--- a/domain-server/resources/describe-settings.json
+++ b/domain-server/resources/describe-settings.json
@@ -168,7 +168,7 @@
     },
     {
       "name": "asset_server",
-      "label": "Asset Server",
+      "label": "Asset Server (ATP)",
       "assignment-types": [3],
       "settings": [
         {
@@ -178,6 +178,14 @@
           "help": "Assigns an asset-server in your domain to serve files to clients via the ATP protocol (over UDP)",
           "default": true,
           "advanced": true
+        },
+        {
+          "name": "assets_path",
+          "type": "string",
+          "label": "Assets Path",
+          "help": "The path to the directory assets are stored in.<br/>If this path is relative, it will be relative to the application data directory.<br/>If you change this path you will need to manually copy any existing assets from the previous directory.",
+          "default": "",
+          "advanced": true
         }
       ]
     },
@@ -377,7 +385,7 @@
         {
           "name": "persistFilePath",
           "label": "Entities File Path",
-          "help": "The path to the file entities are stored in. If this path is relative it will be relative to the application data directory. The filename must end in .json.gz.",
+          "help": "The path to the file entities are stored in.<br/>If this path is relative it will be relative to the application data directory.<br/>The filename must end in .json.gz.",
           "placeholder": "models.json.gz",
           "default": "models.json.gz",
           "advanced": true
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index 9e3b69854f..9e13c8e6fa 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -120,6 +120,14 @@ DomainServer::~DomainServer() {
     DependencyManager::destroy<LimitedNodeList>();
 }
 
+void DomainServer::queuedQuit(QString quitMessage, int exitCode) {
+    if (!quitMessage.isEmpty()) {
+        qCritical() << qPrintable(quitMessage);
+    }
+
+    QCoreApplication::exit(exitCode);
+}
+
 void DomainServer::aboutToQuit() {
 
     // clear the log handler so that Qt doesn't call the destructor on LogHandler
@@ -164,8 +172,11 @@ bool DomainServer::optionallyReadX509KeyAndCertificate() {
         qDebug() << "TCP server listening for HTTPS connections on" << DOMAIN_SERVER_HTTPS_PORT;
 
     } else if (!certPath.isEmpty() || !keyPath.isEmpty()) {
-        qDebug() << "Missing certificate or private key. domain-server will now quit.";
-        QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
+        static const QString MISSING_CERT_ERROR_MSG = "Missing certificate or private key. domain-server will now quit.";
+        static const int MISSING_CERT_ERROR_CODE = 3;
+
+        QMetaObject::invokeMethod(this, "queuedQuit", Qt::QueuedConnection,
+                                  Q_ARG(QString, MISSING_CERT_ERROR_MSG), Q_ARG(int, MISSING_CERT_ERROR_CODE));
         return false;
     }
 
@@ -199,8 +210,10 @@ bool DomainServer::optionallySetupOAuth() {
             || _hostname.isEmpty()
             || _oauthClientID.isEmpty()
             || _oauthClientSecret.isEmpty()) {
-            qDebug() << "Missing OAuth provider URL, hostname, client ID, or client secret. domain-server will now quit.";
-            QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
+            static const QString MISSING_OAUTH_INFO_MSG = "Missing OAuth provider URL, hostname, client ID, or client secret. domain-server will now quit.";
+            static const int MISSING_OAUTH_INFO_ERROR_CODE = 4;
+            QMetaObject::invokeMethod(this, "queuedQuit", Qt::QueuedConnection,
+                                      Q_ARG(QString, MISSING_OAUTH_INFO_MSG), Q_ARG(int, MISSING_OAUTH_INFO_ERROR_CODE));
             return false;
         } else {
             qDebug() << "OAuth will be used to identify clients using provider at" << _oauthProviderURL.toString();
@@ -404,9 +417,13 @@ bool DomainServer::resetAccountManagerAccessToken() {
         return true;
 
     } else {
-        qDebug() << "Missing OAuth provider URL, but a domain-server feature was required that requires authentication." <<
-            "domain-server will now quit.";
-        QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
+        static const QString MISSING_OAUTH_PROVIDER_MSG =
+            QString("Missing OAuth provider URL, but a domain-server feature was required that requires authentication.") +
+            QString("domain-server will now quit.");
+        static const int MISSING_OAUTH_PROVIDER_ERROR_CODE = 5;
+        QMetaObject::invokeMethod(this, "queuedQuit", Qt::QueuedConnection,
+                                  Q_ARG(QString, MISSING_OAUTH_PROVIDER_MSG),
+                                  Q_ARG(int, MISSING_OAUTH_PROVIDER_ERROR_CODE));
 
         return false;
     }
@@ -517,11 +534,6 @@ void DomainServer::setupICEHeartbeatForFullNetworking() {
     }
 }
 
-void DomainServer::loginFailed() {
-    qDebug() << "Login to data server has failed. domain-server will now quit";
-    QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
-}
-
 void DomainServer::parseAssignmentConfigs(QSet<Assignment::Type>& excludedTypes) {
     // check for configs from the command line, these take precedence
     const QString ASSIGNMENT_CONFIG_REGEX_STRING = "config-([\\d]+)";
diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h
index afdd7bd26e..326ca3e1a8 100644
--- a/domain-server/src/DomainServer.h
+++ b/domain-server/src/DomainServer.h
@@ -65,7 +65,6 @@ public slots:
 private slots:
     void aboutToQuit();
 
-    void loginFailed();
     void setupPendingAssignmentCredits();
     void sendPendingTransactionsToServer();
 
@@ -77,6 +76,8 @@ private slots:
 
     void handleTempDomainSuccess(QNetworkReply& requestReply);
     void handleTempDomainError(QNetworkReply& requestReply);
+
+    void queuedQuit(QString quitMessage, int exitCode);
     
 private:
     void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp
index 98bb63241e..49ae03ccd4 100644
--- a/domain-server/src/DomainServerSettingsManager.cpp
+++ b/domain-server/src/DomainServerSettingsManager.cpp
@@ -62,9 +62,14 @@ DomainServerSettingsManager::DomainServerSettingsManager() :
         }
     }
 
-    qCritical() << "Did not find settings decription in JSON at" << SETTINGS_DESCRIPTION_RELATIVE_PATH
-            << "- Unable to continue. domain-server will quit.";
-    QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
+    static const QString MISSING_SETTINGS_DESC_MSG =
+        QString("Did not find settings decription in JSON at %1 - Unable to continue. domain-server will quit.")
+        .arg(SETTINGS_DESCRIPTION_RELATIVE_PATH);
+    static const int MISSING_SETTINGS_DESC_ERROR_CODE = 6;
+
+    QMetaObject::invokeMethod(QCoreApplication::instance(), "queuedQuit", Qt::QueuedConnection,
+                              Q_ARG(QString, MISSING_SETTINGS_DESC_MSG),
+                              Q_ARG(int, MISSING_SETTINGS_DESC_ERROR_CODE));
 }
 
 void DomainServerSettingsManager::processSettingsRequestPacket(QSharedPointer<ReceivedMessage> message) {