diff --git a/README_CONFIGURATION.md b/README_CONFIGURATION.md
new file mode 100644
index 0000000000000000000000000000000000000000..d1ad263fbaaf1fdd1587b596096902db6a972126
--- /dev/null
+++ b/README_CONFIGURATION.md
@@ -0,0 +1,15 @@
+# Server Configuration
+
+The server configuration is a list of key-value pairs. A configuration file may contain empty lines, comment lines, and key-value lines.
+Comment lines begin with a hash (`#`). Key-value lines must have the format `KEY_NAME=VALUE` or `KEY_NAME = VALUE`.
+
+The server default configuration is located at `./conf/core/server.conf`.
+
+The default configuration can be overriden by
+
+1. the file ./conf/ext/server.conf
+2. any file in ./conf/ext/server.conf.d/
+3. environment variables with the prefix `CAOSDB_CONFIG_`
+
+in this order.
+
diff --git a/README_SETUP.md b/README_SETUP.md
index 8f8329cc76ef5508444707c830ee6747b9154f9a..e14b1833732e5d63e3217dbf736485c5188af3c0 100644
--- a/README_SETUP.md
+++ b/README_SETUP.md
@@ -27,7 +27,7 @@ On Debian, the required packages can be installed with:
 After a fresh clone of the repository, this is what you need to setup the server:
 
 1. It is recommended to run the unit tests with `make test`
-2. Copy `conf/core/server.conf.template` to `conf/ext/server.conf` and change it
+2. Copy `conf/core/server.conf` to `conf/ext/server.conf` and change it
    appropriately:
     * Setup for MySQL back-end: Assuming that the mysql back-end is installed,
       specify the fields `MYSQL_USER_NAME`, `MYSQL_USER_PASSWORD`,
@@ -38,6 +38,7 @@ After a fresh clone of the repository, this is what you need to setup the server
     * Select a path for the file system and set the fields `FILE_SYSTEM_ROOT`,
       `DROP_OFF_BOX`, and `TMP_FILES`.
     * Maybe set another `SESSION_TIMEOUT_MS`.
+    * See also [README_CONFIGURATION.md](README_CONFIGURATION.md)
 3. Copy `conf/core/usersources.ini.template` to `conf/ext/usersources.ini`.
     * Define the users/groups who you want to include/exclude.
     * Assign at least one user the `administration` role.
diff --git a/conf/core/server.conf b/conf/core/server.conf
new file mode 100644
index 0000000000000000000000000000000000000000..fd0f38929545e2fc3213919bf340b5a520603fc1
--- /dev/null
+++ b/conf/core/server.conf
@@ -0,0 +1,62 @@
+SERVER_OWNER=
+SERVER_NAME=CaosDB Server
+SERVER_SIDE_SCRIPTING_BIN_DIR=./scripting/bin/
+SERVER_SIDE_SCRIPTING_WORKING_DIR=./scripting/working/
+FILE_SYSTEM_ROOT=./CaosDBFileSystem/FileSystemRoot/
+DROP_OFF_BOX=./CaosDBFileSystem/DropOffBox/
+TMP_FILES=./CaosDBFileSystem/TMP/
+CHOWN_SCRIPT=./misc/chown_script/caosdb_chown_dropoffbox
+USER_SOURCES_INI_FILE=./conf/ext/usersources.ini
+NEW_USER_DEFAULT_ACTIVITY=INACTIVE
+AUTH_OPTIONAL=FALSE
+
+MYSQL_HOST=localhost
+MYSQL_PORT=3306
+MYSQL_DATABASE_NAME=caosdb
+MYSQL_USER_NAME=caosdb
+MYSQL_USER_PASSWORD=caosdb
+
+MYSQL_SCHEMA_VERSION=v2.1.0
+
+CONTEXT_ROOT=
+
+SERVER_PORT_HTTPS=443
+SERVER_PORT_HTTP=80
+
+HTTPS_ENABLED_PROTOCOLS=TLSv1.2 TLSv1.1 TLSv1
+HTTPS_DISABLED_PROTOCOLS=SSLv3 SSLv2Hello
+HTTPS_ENABLED_CIPHER_SUITES=TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_AES_256_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDH_RSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_RC4_128_SHA TLS_ECDHE_RSA_WITH_RC4_128_SHA TLS_ECDH_ECDSA_WITH_RC4_128_SHA TLS_ECDH_RSA_WITH_RC4_128_SHA TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+HTTPS_DISABLED_CIPHER_SUITES=SSL_RSA_WITH_RC4_128_MD5 SSL_RSA_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_RC4_128_SHA TLS_DHE_RSA_WITH_AES_256_CBC_SHA TLS_DHE_DSS_WITH_AES_256_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
+
+INITIAL_CONNECTIONS=1
+
+MAX_CONNECTIONS=10
+
+# 10 min
+SESSION_TIMEOUT_MS=600000 
+# 7days
+ACTIVATION_TIMEOUT_MS=604800000
+
+MAIL_HANDLER_CLASS=caosdb.server.utils.mail.ToFileHandler
+MAIL_TO_FILE_HANDLER_LOC=./
+
+ADMIN_NAME=CaosDB Admin
+ADMIN_EMAIL=
+BUGTRACKER_URI=
+
+TRANSACTION_BENCHMARK_ENABLED=true
+CACHE_CONF_LOC=./conf/core/cache.ccf
+
+RULES_CACHE_CAPACITY=100
+SPARSE_ENTITY_CACHE_CAPACITY=1000
+PROPERTIES_CACHE_CAPACITY=1000
+PARENTS_CACHE_CAPACITY=1000
+USER_ACCOUNT_CACHE_CAPACITY=100
+GROUP_CACHE_CAPACITY=100
+
+INSERT_FILES_IN_DIR_ALLOWED_DIRS=
+
+SUDO_PASSWORD=
+QUERY_FILTER_ENTITIES_WITHOUT_RETRIEVE_PERMISSIONS=TRUE
+
+CHECK_ENTITY_ACL_ROLES_MODE=MUST
diff --git a/conf/core/server.conf.template b/conf/core/server.conf.template
deleted file mode 100644
index 253f577f3c55c86f1daebc98470358f9329b5d78..0000000000000000000000000000000000000000
--- a/conf/core/server.conf.template
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# ** header v3.0
-# This file is a part of the CaosDB Project.
-#
-# Copyright (C) 2018 Research Group Biomedical Physics,
-# Max-Planck-Institute for Dynamics and Self-Organization Göttingen
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# ** end header
-#
-
-# MySQL
-MYSQL_USER_NAME = {mysql-user-name}
-MYSQL_USER_PASSWORD = {mysql-user-password}
-MYSQL_DATABASE_NAME = {mysql-database_name}
-MYSQL_HOST = {mysql-host}
-
-
-
-# (HTTP will be redirected to HTTP)
-SERVER_PORT_HTTP = {server-port-http}
-SERVER_PORT_HTTPS = {server-port-https}
-
-# about certificates needed for HTTPS auth
-CERTIFICATES_KEY_PASSWORD = {certificates-key-password}
-CERTIFICATES_KEY_STORE_PATH = {certificates-key-store-path}
-CERTIFICATES_KEY_STORE_PASSWORD = {certificates-key-store-password}
-
-
-# Location of the internal file storage
-FILE_SYSTEM_ROOT = {file-system-root}
-DROP_OFF_BOX = {drop-off-box}
-TMP_FILES = {tmp-files}
-
-SESSION_TIMEOUT_MS = 43200000
diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java
index 2aa6ad3a5b6d89aa74bc10d2654327f5919aca45..52c7ad24d81438e9d95cc4f69c599be12cb00cea 100644
--- a/src/main/java/caosdb/server/CaosDBServer.java
+++ b/src/main/java/caosdb/server/CaosDBServer.java
@@ -64,6 +64,7 @@ import caosdb.server.utils.FileUtils;
 import caosdb.server.utils.Initialization;
 import caosdb.server.utils.NullPrintStream;
 import caosdb.server.utils.Utils;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Properties;
@@ -127,6 +128,15 @@ public class CaosDBServer extends Application {
   public static void main(final String[] args) {
     logger.fine("SERVER_START");
 
+    try {
+      logger.fine("read config files.");
+      SERVER_PROPERTIES = ServerProperties.initServerProperties();
+    } catch (IOException e1) {
+      e1.printStackTrace();
+      System.err.println("Could not read config files.");
+      System.exit(1);
+    }
+
     boolean startGui = true;
 
     for (final String s : args) {
@@ -702,16 +712,10 @@ public class CaosDBServer extends Application {
    * @param value, the new value.
    */
   public static void setProperty(String key, String value) {
-    if (SERVER_PROPERTIES == null) {
-      SERVER_PROPERTIES = ServerProperties.initServerProperties();
-    }
     SERVER_PROPERTIES.setProperty(key, value);
   }
 
   public static Properties getServerProperties() {
-    if (SERVER_PROPERTIES == null) {
-      SERVER_PROPERTIES = ServerProperties.initServerProperties();
-    }
     return SERVER_PROPERTIES;
   }
 }
diff --git a/src/main/java/caosdb/server/FileSystem.java b/src/main/java/caosdb/server/FileSystem.java
index 3a1259a9422be35d7db9824b9f2a54c0c96a5e60..38476573d95582e6c6e9af928709feae620a03d7 100644
--- a/src/main/java/caosdb/server/FileSystem.java
+++ b/src/main/java/caosdb/server/FileSystem.java
@@ -42,7 +42,6 @@ import org.apache.commons.fileupload.FileItemStream;
 
 public class FileSystem {
   private static String filesystem = null;
-  private static Boolean userfolders = null;
   private static String dropOffBox = null;
   private static String tmpdir = null;
 
@@ -95,19 +94,11 @@ public class FileSystem {
 
   private static void init() {
     filesystem = CaosDBServer.getServerProperty(ServerProperties.KEY_FILE_SYSTEM_ROOT);
-    userfolders = new Boolean(CaosDBServer.getServerProperty(ServerProperties.KEY_USER_FOLDERS));
     dropOffBox = CaosDBServer.getServerProperty(ServerProperties.KEY_DROP_OFF_BOX);
     tmpdir = CaosDBServer.getServerProperty(ServerProperties.KEY_TMP_FILES);
     check();
   }
 
-  public static boolean isUserfolders() throws IOException {
-    if (userfolders == null) {
-      init();
-    }
-    return userfolders;
-  }
-
   private FileSystem() {}
 
   /**
diff --git a/src/main/java/caosdb/server/ServerProperties.java b/src/main/java/caosdb/server/ServerProperties.java
index 1cd6078e7e0be9f061f7f985f2b11015f7c594dc..6dc25483ef3a9a77db97e4799bd32033ca83f807 100644
--- a/src/main/java/caosdb/server/ServerProperties.java
+++ b/src/main/java/caosdb/server/ServerProperties.java
@@ -26,11 +26,18 @@ import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ServerProperties extends Properties {
 
   private static final long serialVersionUID = 1L;
+  private static Logger logger = LoggerFactory.getLogger(ServerProperties.class.getName());
 
   public static final String KEY_FILE_SYSTEM_ROOT = "FILE_SYSTEM_ROOT";
   public static final String KEY_DROP_OFF_BOX = "DROP_OFF_BOX";
@@ -44,7 +51,7 @@ public class ServerProperties extends Properties {
   public static final String KEY_MYSQL_DATABASE_NAME = "MYSQL_DATABASE_NAME";
   public static final String KEY_MYSQL_USER_NAME = "MYSQL_USER_NAME";
   public static final String KEY_MYSQL_USER_PASSWORD = "MYSQL_USER_PASSWORD";
-  public static final String KEY_MYSQL_SCHEMA_VERSION = "SQL_SCHEMA_VERSION";
+  public static final String KEY_MYSQL_SCHEMA_VERSION = "MYSQL_SCHEMA_VERSION";
 
   public static final String KEY_BASE_PATH = "BASE_PATH";
   public static final String KEY_FILE_POLICY = "FILE_POLICY";
@@ -57,8 +64,8 @@ public class ServerProperties extends Properties {
 
   public static final String KEY_HTTPS_ENABLED_PROTOCOLS = "HTTPS_ENABLED_PROTOCOLS";
   public static final String KEY_HTTPS_DISABLED_PROTOCOLS = "HTTPS_DISABLED_PROTOCOLS";
-  public static final String KEY_HTTPS_ENABLED_CIPHER_SUITES = "HTTPS_ENABLES_CIPHER_SUITES";
-  public static final String KEY_HTTPS_DISABLED_CIPHER_SUITES = "HTTPS_DISABLES_CIPHER_SUITES";
+  public static final String KEY_HTTPS_ENABLED_CIPHER_SUITES = "HTTPS_ENABLED_CIPHER_SUITES";
+  public static final String KEY_HTTPS_DISABLED_CIPHER_SUITES = "HTTPS_DISABLED_CIPHER_SUITES";
 
   public static final String KEY_CERTIFICATES_KEY_STORE_PATH = "CERTIFICATES_KEY_STORE_PATH";
   public static final String KEY_CERTIFICATES_KEY_STORE_PASSWORD =
@@ -69,8 +76,6 @@ public class ServerProperties extends Properties {
 
   public static final String KEY_MAX_CONNECTIONS = "MAX_CONNECTIONS";
 
-  public static final String KEY_ITEMS_PER_PAGE = "ITEMS_PER_PAGE";
-
   public static final String KEY_MAIL_HANDLER_CLASS = "MAIL_HANDLER_CLASS";
   public static final String KEY_MAIL_TO_FILE_HANDLER_LOC = "MAIL_TO_FILE_HANDLER_LOC";
 
@@ -78,8 +83,6 @@ public class ServerProperties extends Properties {
   public static final String KEY_ADMIN_EMAIL = "ADMIN_EMAIL";
   public static final String KEY_BUGTRACKER_URI = "BUGTRACKER_URI";
 
-  public static final String KEY_UNITS_FILE = "UNITS_FILE";
-
   public static final String KEY_SESSION_TIMEOUT_MS = "SESSION_TIMEOUT_MS";
   public static final String KEY_ACTIVATION_TIMEOUT_MS = "ACTIVATION_TIMEOUT_MS";
 
@@ -124,103 +127,56 @@ public class ServerProperties extends Properties {
   public static final String KEY_CHECK_ENTITY_ACL_ROLES_MODE = "CHECK_ENTITY_ACL_ROLES_MODE";
 
   /**
-   * This init_server_properties method reads the config file which contains key-value-pairs for
-   * such variables like the user name of the database, the port the server will be listening on
-   * etc.
+   * Read the config files and initialize the server properties.
+   *
+   * @throws IOException
    */
-  public static Properties initServerProperties() {
+  public static Properties initServerProperties() throws IOException {
     final Properties serverProperties = new Properties();
     final String basepath = System.getProperty("user.dir");
-    serverProperties.setProperty(KEY_SERVER_OWNER, "");
-    serverProperties.setProperty(KEY_SERVER_NAME, "CaosDB Server");
-    serverProperties.setProperty(KEY_SERVER_SIDE_SCRIPTING_BIN_DIR, basepath + "/scripting/bin/");
-    serverProperties.setProperty(
-        KEY_SERVER_SIDE_SCRIPTING_WORKING_DIR, basepath + "/scripting/working/");
-    serverProperties.setProperty(KEY_FILE_SYSTEM_ROOT, "CaosDBFileSystem/FileSystemRoot/");
-    serverProperties.setProperty(KEY_DROP_OFF_BOX, "CaosDBFileSystem/DropOffBox/");
-    serverProperties.setProperty(KEY_TMP_FILES, "CaosDBFileSystem/TMP/");
-    serverProperties.setProperty(KEY_CHOWN_SCRIPT, "misc/chown_script/caosdb_chown_dropoffbox");
-    serverProperties.setProperty(KEY_USER_SOURCES_INI_FILE, basepath + "/conf/ext/usersources.ini");
-    serverProperties.setProperty(KEY_USER_FOLDERS, "FALSE");
-    serverProperties.setProperty(KEY_NEW_USER_DEFAULT_ACTIVITY, "INACTIVE");
-    serverProperties.setProperty(KEY_AUTH_OPTIONAL, "FALSE");
-
-    serverProperties.setProperty(KEY_MYSQL_HOST, "localhost");
-    serverProperties.setProperty(KEY_MYSQL_PORT, "3306");
-    serverProperties.setProperty(KEY_MYSQL_DATABASE_NAME, "db_2_0");
-    serverProperties.setProperty(KEY_MYSQL_USER_NAME, "CaosDB");
-    serverProperties.setProperty(KEY_MYSQL_USER_PASSWORD, "CaosDB");
-
-    serverProperties.setProperty(KEY_MYSQL_SCHEMA_VERSION, "v2.1.0");
-
-    serverProperties.setProperty(KEY_BASE_PATH, basepath);
-    serverProperties.setProperty(KEY_CONTEXT_ROOT, "");
-    serverProperties.setProperty(KEY_POLICY_COMPONENT, "enabled");
-
-    serverProperties.setProperty(KEY_SERVER_PORT_HTTPS, "0");
-    serverProperties.setProperty(KEY_SERVER_PORT_HTTP, "0");
-
-    serverProperties.setProperty(KEY_HTTPS_ENABLED_PROTOCOLS, "TLSv1.2 TLSv1.1 TLSv1");
-    serverProperties.setProperty(KEY_HTTPS_DISABLED_PROTOCOLS, "SSLv3 SSLv2Hello");
-    serverProperties.setProperty(
-        KEY_HTTPS_ENABLED_CIPHER_SUITES,
-        "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_AES_256_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDH_RSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_RC4_128_SHA TLS_ECDHE_RSA_WITH_RC4_128_SHA TLS_ECDH_ECDSA_WITH_RC4_128_SHA TLS_ECDH_RSA_WITH_RC4_128_SHA TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
-    serverProperties.setProperty(
-        KEY_HTTPS_DISABLED_CIPHER_SUITES,
-        "SSL_RSA_WITH_RC4_128_MD5 SSL_RSA_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_RC4_128_SHA TLS_DHE_RSA_WITH_AES_256_CBC_SHA TLS_DHE_DSS_WITH_AES_256_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA");
-
-    serverProperties.setProperty(KEY_INITIAL_CONNECTIONS, "1");
-
-    serverProperties.setProperty(KEY_MAX_CONNECTIONS, "10");
-
-    serverProperties.setProperty(KEY_ITEMS_PER_PAGE, "100");
-
-    serverProperties.setProperty(KEY_SESSION_TIMEOUT_MS, "600000"); // 10 min
-    serverProperties.setProperty(KEY_ACTIVATION_TIMEOUT_MS, "604800000"); // 7days
-
-    serverProperties.setProperty(KEY_MAIL_HANDLER_CLASS, "caosdb.server.utils.mail.ToFileHandler");
-    serverProperties.setProperty(KEY_MAIL_TO_FILE_HANDLER_LOC, "./");
-
-    serverProperties.setProperty(KEY_ADMIN_NAME, "CaosDB Admin");
-    serverProperties.setProperty(KEY_ADMIN_EMAIL, "");
-    serverProperties.setProperty(KEY_BUGTRACKER_URI, "");
-
-    serverProperties.setProperty(KEY_UNITS_FILE, basepath + "/src/main/java/caosdb/unit/si.units");
-
-    serverProperties.setProperty(KEY_TRANSACTION_BENCHMARK_ENABLED, "true");
-    serverProperties.setProperty(KEY_CACHE_CONF_LOC, "conf/core/cache.ccf");
-
-    serverProperties.setProperty(KEY_RULES_CACHE_CAPACITY, "100");
-    serverProperties.setProperty(KEY_SPARSE_ENTITY_CACHE_CAPACITY, "1000");
-    serverProperties.setProperty(KEY_PROPERTIES_CACHE_CAPACITY, "1000");
-    serverProperties.setProperty(KEY_PARENTS_CACHE_CAPACITY, "1000");
-    serverProperties.setProperty(KEY_USER_ACCOUNT_CACHE_CAPACITY, "100");
-    serverProperties.setProperty(KEY_GROUP_CACHE_CAPACITY, "100");
-
-    serverProperties.setProperty(KEY_INSERT_FILES_IN_DIR_ALLOWED_DIRS, "");
-
-    serverProperties.setProperty(KEY_SUDO_PASSWORD, "");
-    serverProperties.setProperty(KEY_QUERY_FILTER_ENTITIES_WITHOUT_RETRIEVE_PERMISSIONS, "TRUE");
-
-    serverProperties.setProperty(KEY_CHECK_ENTITY_ACL_ROLES_MODE, "MUST");
-
-    try {
-      final File confFile = new File(basepath + "/conf/ext/server.conf");
-      if (confFile.exists()) {
-        final BufferedInputStream sp_in = new BufferedInputStream(new FileInputStream(confFile));
-        serverProperties.load(sp_in);
-        sp_in.close();
-      } else {
-        System.out.println("No config file found. Will use standard configuration.");
+
+    // load standard config
+    loadConfigFile(serverProperties, new File(basepath + "/conf/core/server.conf"));
+
+    // load ext/server.conf
+    loadConfigFile(serverProperties, new File(basepath + "/conf/ext/server.conf"));
+
+    // load ext/server.conf.d/ (ordering is determined by system collation)
+    File confDir = new File(basepath + "/conf/ext/server.conf.d");
+    if (confDir.exists() && confDir.isDirectory()) {
+      String[] confFiles = confDir.list();
+      Arrays.sort(confFiles, Comparator.naturalOrder());
+      for (String confFile : confFiles) {
+        loadConfigFile(serverProperties, new File(confDir, confFile));
       }
+    }
 
-    } catch (final IOException e) {
-      System.out.println("Failed to read config file. Will use standard configuration.");
+    // load env vars
+    for (java.util.Map.Entry<String, String> envvar : System.getenv().entrySet()) {
+      if (envvar.getKey().startsWith("CAOSDB_CONFIG_") && envvar.getKey().length() > 14) {
+        serverProperties.setProperty(envvar.getKey().substring(14), envvar.getValue());
+      }
     }
-    // this is due to the userfolders must have a users name...
-    if (serverProperties.getProperty(KEY_USER_FOLDERS).equalsIgnoreCase("TRUE")) {
-      serverProperties.setProperty(KEY_POLICY_COMPONENT, "enabled");
+
+    // log configuration alphabetically
+    if (logger.isInfoEnabled()) {
+      ArrayList<String> names = new ArrayList<>(serverProperties.stringPropertyNames());
+      Collections.sort(names);
+      for (String name : names) {
+        String val = name.contains("PASSW") ? "****" : serverProperties.getProperty(name);
+        logger.info(name + "=" + val);
+      }
     }
     return serverProperties;
   }
+
+  private static void loadConfigFile(Properties serverProperties, File confFile)
+      throws IOException {
+    if (confFile.exists() && confFile.isFile()) {
+      logger.info("Reading configuration from " + confFile.getAbsolutePath());
+      final BufferedInputStream sp_in = new BufferedInputStream(new FileInputStream(confFile));
+      serverProperties.load(sp_in);
+      sp_in.close();
+    }
+  }
 }