diff --git a/config/config_custom.php.dist b/config/config_custom.php.dist
new file mode 100644
index 0000000000000000000000000000000000000000..1fe05628fde107d3556cd92e2586e98c10aa8794
--- /dev/null
+++ b/config/config_custom.php.dist
@@ -0,0 +1,135 @@
+<?php
+/*
+ * CUSTOM SETTINGS
+ * 
+ * Settings here override defaults from config_defaults.php
+ * 
+ */
+return [
+
+    'lang' => 'en-en', // for available languages see ./config/lang/*.json
+
+    'auth' => [
+        // force using a given user ... for development only
+        'forceuser' => 'admin',
+
+        // use a real login
+        'ldap' => [
+            'server'       => 'ldaps://ldap.example.com',
+            'port'         => 636,
+            'DnLdapUser' => 'cn=lookupuser,dc=department,dc=example.com',
+            'PwLdapUser' => 'lookupuser_password_here',
+            'DnUserNode'   => 'ou=People,dc=department,dc=example.com',
+            'DnAppNode'    => 'cn=CI Web-GUI Users,ou=Application Access,dc=department,dc=example.com',
+            'debugLevel'   => 0,
+        ]
+    ],
+
+    // ----------------------------------------------------------------------    
+
+    'phases' => [
+        "preview" => [],
+        "stage" => [],
+        "live" => [
+            // prevent immediate installation after build or accept
+            "deploytimes" => ['/(Mon|Tue|Wed|Thu)\ 14\:/'],
+        ],
+    ],
+    'showdebug' => [
+        'ip'=> ['127.0.0.1'],
+    ],
+
+    'projectgroups' => array(
+        'aae'=>'AAE',
+        'aum'=>'AUM',
+        'eosce'=>'EOSCE',
+        'iml'=>'IML Services and websites',
+        'measured'=>'Measured',
+        'medsurf'=>'Medsurf',
+    ),
+
+    // ----------------------------------------------------------------------
+    // build settings
+    // ----------------------------------------------------------------------
+    'versionsToKeep' => 10, // for cleanup: keep n unused versions
+    'builtsToKeep' => 3,
+    'build' => array(
+        'env' => 'export RVMSCRIPT="/usr/local/rvm/scripts/rvm";',
+        'hooks' => array(
+            'build-postclone' => 'hooks/onbuild-postclone',
+            'build-precompress' => 'hooks/onbuild',
+        ),
+    ),
+
+    // ----------------------------------------------------------------------
+    // rsync of archives
+    // ----------------------------------------------------------------------
+    'mirrorPackages' => array(
+        /*
+
+        // (1)
+        // sync to a puppet master puppet to extract archive and generate templates
+        'puppet' => array(
+            'type' => 'rsync',
+            'runas' => '', // www-data, // nur fuer commandline
+            'target' => 'copy-deployment@puppetmaster.example.com:/share/ciserver',
+        ),
+
+        // (2)
+        // sync to a software package server like https://os-docs.iml.unibe.ch/ci-pkg/
+        'package-server' => array(
+            'type' => 'rsync',
+            'runas' => '', // www-data, // nur fuer commandline
+            'target' => 'copy-deployment@software.example.com:/var/www/data-ciserver',
+        ),
+        */
+    ),
+
+    // ----------------------------------------------------------------------    
+    // plugins
+    // existing subkeys = enabled plugins
+    // ----------------------------------------------------------------------    
+    'plugins'=>[
+
+        'rollout'=>[
+            'default'=>[],
+            'ssh'=>[
+                'user'=>'imldeployment',
+                'privatekey'=>'',
+                'addkeycommand'=>'/usr/bin/ssh-keygen -R %s; /usr/bin/ssh-keyscan -t rsa %s >> /home/www-data/.ssh/known_hosts',
+                'testcommand'=>'sudo puppet --version',
+                'command'=>'/usr/local/bin/puppetrun.sh',
+            ],
+            'awx'=>[
+                'url'=>'https://awx.sys.iml.unibe.ch/api/v2', // no ending "/"
+                'user'=>'api-ci',
+                'password'=>'awRSbdB2rkViaBXBKOvtr11DEoZJSqHceih1hEE4awrjIO1wuArKu85WmetsRp63',
+                'jobtemplate'=>'36',
+                'tags'=>'rollout',
+                // 'ignore-ssl-error'=>false,
+            ],
+        ],
+    ],
+    
+    // ----------------------------------------------------------------------    
+    // notifications to messengers ...
+    // ----------------------------------------------------------------------    
+
+    // notifications to messengers ...
+    'messenger'=>array(
+        'slack'=>array(
+            'presets'=>array(
+                'https://hooks.slack.com/services/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'=>array(
+                    'label'=>'#medsurf-heartbeat',
+                    'user'=>'[CI-WebGUI]',
+                ),
+                'https://hooks.slack.com/services/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'=>array(
+                    'label'=>'#msrd-analyzer-hrtbeat',
+                    'user'=>'[CI-WebGUI]',
+                ),
+            ),
+        ),
+    ),
+    // ----------------------------------------------------------------------    
+
+];
\ No newline at end of file
diff --git a/config/config_defaults.php b/config/config_defaults.php
new file mode 100644
index 0000000000000000000000000000000000000000..e500f6e0aff3a5b02f41e9c88d087b80422ef2a5
--- /dev/null
+++ b/config/config_defaults.php
@@ -0,0 +1,168 @@
+<?php
+/*
+ * DEFAULT CONFIG SETTINGS
+ * 
+ * Do not change this file. For custom settings use the config_custom.php
+ * and override wanted keys.
+ * 
+ */
+return [
+
+    // ----------------------------------------------------------------------    
+
+    'workDir' => '/var/imldeployment',
+    'tmpDir' => '/var/tmp/imldeployment',
+
+    // ----------------------------------------------------------------------    
+
+    'phases' => [
+        "preview" => [
+            'css' => [
+                'bgdark' => 'background:#393E50;  color:#f8f8f8;',
+                'bglight' => 'background:#eee; color:#333; background:rgba(210,210,210,0.3); ',
+                'bgbutton' => 'background:#393E50; color:#fcfcfc; border: 1px solid rgba(0,0,0,0.15);',
+            ],
+        ],
+        "stage" => [
+            'css' => [
+                'bgdark' => 'background:#3F88C5; color:#f8f8f8;',
+                'bglight' => 'background:#f0f4f8; color:#333; background:rgba(200,210,220,0.3); ',
+                'bgbutton' => 'background:#3F88C5; color:#fcfcfc; border: 1px solid rgba(0,0,0,0.15);',
+            ],
+        ],
+        "live" => [
+            'css' => [
+                'bgdark' => 'background:#44BBA4; color:#f8f8f8;',
+                'bglight' => 'background:#f4f8f0; color:#333; background:rgba(210,220,200,0.3); ',
+                'bgbutton' => 'background:#44BBA4; color:#fcfcfc; border: 1px solid rgba(0,0,0,0.15);',
+            ],
+            // prevent immediate installation after build or accept
+            "deploytimes" => ['/(Mon|Tue|Wed|Thu)\ 14\:/'],
+        ],
+    ],
+
+    'auth' => [
+        // force using a given user ... for development only
+        'forceuser' => 'admin',
+
+        // use a real login
+        'ldap' => [
+            'server'       => 'ldaps://ldap.example.com',
+            'port'         => 636,
+            'DnLdapUser' => 'cn=lookupuser,dc=department,dc=example.com',
+            'PwLdapUser' => 'lookupuser_password_here',
+            'DnUserNode'   => 'ou=People,dc=department,dc=example.com',
+            'DnAppNode'    => 'cn=CI Web-GUI Users,ou=Application Access,dc=department,dc=example.com',
+            'debugLevel'   => 0,
+        ]
+    ],
+
+    'lang' => 'en-en', // for available languages see ./config/lang/*.json
+
+    'showdebug' => [
+        'ip'=> ['127.0.0.1'],
+    ],
+    'projectgroups' => [
+        'teamA'=>'Team A: Services',
+        'teamB'=>'Team B: Website',
+    ],
+    
+    // ----------------------------------------------------------------------
+    // build settings
+    // ----------------------------------------------------------------------
+    'versionsToKeep' => 10, // for cleanup: keep n unused versions
+    'builtsToKeep' => 3,
+    'build' => array(
+        'env' => 'export RVMSCRIPT="/usr/local/rvm/scripts/rvm";',
+        'hooks' => array(
+            'build-postclone' => 'hooks/onbuild-postclone',
+            'build-precompress' => 'hooks/onbuild',
+        ),
+    ),
+
+    // ----------------------------------------------------------------------
+    // sync of archives
+    // ----------------------------------------------------------------------
+    'mirrorPackages' => array(
+        /*
+
+        // (1)
+        // sync to a puppet master puppet to extract archive and generate templates
+        'puppet' => array(
+            'type' => 'rsync',
+            'runas' => '', // www-data, // nur fuer commandline
+            'target' => 'copy-deployment@puppetmaster.example.com:/share/ciserver',
+        ),
+
+        // (2)
+        // sync to a software package server like https://os-docs.iml.unibe.ch/ci-pkg/
+        'package-server' => array(
+            'type' => 'rsync',
+            'runas' => '', // apache httpd user is default, e.g. www-data
+            'target' => 'copy-deployment@software.example.com:/var/www/data-ciserver',
+        ),
+        */
+    ),
+
+    // ----------------------------------------------------------------------    
+    // plugins
+    // existing subkeys = enabled plugins
+    // ----------------------------------------------------------------------    
+    'plugins'=>[
+        'rollout'=>[
+            'default'=>[],
+            /*
+            'ssh'=>[
+                'user'=>'deployment',
+                'privatekey'=>'',
+                'addkeycommand'=>'/usr/bin/ssh-keygen -R %s; /usr/bin/ssh-keyscan -t rsa %s >> /home/www-data/.ssh/known_hosts',
+                'testcommand'=>'sudo puppet --version',
+                'command'=>'/usr/local/bin/puppetrun.sh',
+            ],
+            'awx'=>[
+                'url'=>'https://awx.example.com/api/v2', // no ending "/"
+                'user'=>'ciserver',
+                'password'=>'ciserver',
+                'jobtemplate'=>'36',
+                'tags'=>'rollout',
+            ],
+            */
+        ],
+    ],
+    
+    // ----------------------------------------------------------------------    
+    // notifications to messengers ...
+    // ----------------------------------------------------------------------    
+    'messenger'=>[
+        'slack'=>[
+            'presets'=>[],
+        ],
+        'email'=>[
+            'from'=>'noreply@ciserver.example.com',
+        ]
+    ],
+
+    // ----------------------------------------------------------------------    
+    // TODO: functionality to be removed?!
+    // ----------------------------------------------------------------------    
+
+    'foreman' => array(
+        'api'=>'https://foreman.example.com/', // with ending "/"
+        'user'=>'ci-server',
+        'password'=>'ciserver_password_here',
+        'ignore-ssl-error'=>true,
+        // 'varname-replace'=>'ci-replacement',
+    ),
+
+    // where to store project data
+    'projects' => array(
+        'json' => array(
+            'active'       => true,
+        ),
+        'ldap' => array(
+            'active'       => false,
+        ),
+    ),
+    // ----------------------------------------------------------------------    
+
+];
\ No newline at end of file
diff --git a/config/inc_projects_config.php b/config/inc_projects_config.php
new file mode 100644
index 0000000000000000000000000000000000000000..8344d4400b1b31031718b8df86d0809899ffc711
--- /dev/null
+++ b/config/inc_projects_config.php
@@ -0,0 +1,20 @@
+<?php
+$aConfig = array_replace_recursive(
+    include('config_defaults.php'),
+    include('config_custom.php')
+)
+;
+
+// ----------------------------------------------------------------------
+// generate some vars
+// ----------------------------------------------------------------------
+
+$aConfig = array_merge($aConfig, array(
+    'appRootDir' => dirname(dirname(__FILE__)),
+    'configDir' => dirname(__FILE__),
+    'dataDir' => $aConfig['workDir'] . '/data',    // to write data: ssh keys, projects, database
+    'buildDir' => $aConfig['workDir'] . '/build',
+    'buildDefaultsDir' => $aConfig['workDir'] . '/defaults',
+    'packageDir' => $aConfig['workDir'] . '/packages',
+    'archiveDir' => $aConfig['workDir'] . '/packages/_files',
+));
diff --git a/config/inc_user2roles.php.dist b/config/inc_user2roles.php.dist
new file mode 100644
index 0000000000000000000000000000000000000000..133af67ae858e0b804a997d439b3f97112abf068
--- /dev/null
+++ b/config/inc_user2roles.php.dist
@@ -0,0 +1,22 @@
+<?php
+/*
+ * IML DEPLOYMENT GUI
+ * LIST OF ROLES AND ASSIGNED USERS
+ * 
+ * A user can be assigned to multiple groups
+ * 
+ * see permissions per role in inc_roles.php
+ * 
+ * Remarks: 
+ * - Non authenticated users are member in "all"
+ * - Every user logged in is member of "authenticated"
+ */
+return [
+    "developer" => [],
+    "projectmanager" => [],
+    "admin" => [
+        'admin',
+        'anotheradminuser',
+    ],
+    
+];
diff --git a/hooks/templates/inc_projects_config.php.erb b/hooks/templates/inc_projects_config.php.erb
deleted file mode 100644
index 051b02b4b51c43272dd2f3925e6737717161db60..0000000000000000000000000000000000000000
--- a/hooks/templates/inc_projects_config.php.erb
+++ /dev/null
@@ -1,208 +0,0 @@
-<?php
-
-// ----------------------------------------------------------------------
-// fetch status infos von den einzelnen Phasen
-// ----------------------------------------------------------------------
-
-$aConfig = array(
-    // Basispfad:
-    'workDir' => '/var/imldeployment',
-    'tmpDir' => '/var/tmp/imldeployment',
-    'versionsToKeep' => 5, // for cleanup: keep n unused versions
-    'builtsToKeep' => 3,
-    'build' => array(
-        'env' => 'export RVMSCRIPT="/usr/local/rvm/scripts/rvm";',
-        'hooks' => array(
-            'build-postclone' => 'hooks/onbuild-postclone',
-            'build-precompress' => 'hooks/onbuild',
-        ),
-    ),
-    'lang' => 'de', // for available languages see ./config/lang/*.json
-
-    // rsync of archives
-    'mirrorPackages' => array(),
-    
-    // task#4574
-    // plugins
-    'plugins'=>array(
-
-        // enabled build plugins
-        'build'=>array(
-        ),
-        // enabled rollout plugins
-        'rollout'=>array(
-            'default'=>array(),
-            'ssh'=>array(
-                'user'=>'<%= @replace["rollout-ssh-user"] %>',
-                'privatekey'=>'',
-                'addkeycommand'=>'/usr/bin/ssh-keygen -R %s; /usr/bin/ssh-keyscan -t rsa %s >> /home/www-data/.ssh/known_hosts',
-                'testcommand'=>'sudo puppet --version',
-                // 'command'=>'sudo puppet agent -t --detailed-exitcodes ; rc=$?; if [ $rc -eq 2 ]; then rc=0; fi ; exit $rc',
-                'command'=>'/usr/local/bin/puppetrun.sh',
-            ),
-            'awx'=>array(
-                'url'=>'<%= @replace["rollout-awx-url"] %>', // no ending "/"
-                'user'=>'<%= @replace["rollout-awx-user"] %>',
-                'password'=>'<%= @replace["rollout-awx-password"] %>',
-                'jobtemplate'=>'36', // 36 = iml wrapper playbook
-                'tags'=>'rollout',
-                // 'ignore-ssl-error'=>false,
-            ),
-            /*
-            'foreman'=>array(
-                'api'=>'https://foreman.one.iml.unibe.ch/', // with ending "/"
-                'user'=>'ci-server',
-                'password'=>'A2h0MUVcnfRN_KLYMpymgjsHv0wu8qiY',
-                'ignore-ssl-error'=>true,
-            ),
-             * 
-             */
-        ),
-    ),
-    'installPackages' => array(
-        'user' => 'imldeployment',
-        
-        // command to update ssh hostkey in known_hosts file
-        // %s is name of the server (2x)
-        'addkeycommand' => '/usr/bin/ssh-keygen -R %s; /usr/bin/ssh-keyscan -t rsa %s >> /home/www-data/.ssh/known_hosts',
-        
-        // command to verify if puppet host is correct
-        'testcommand' => 'sudo puppet --version',
-        
-        // puppet agent liefert 0 oder 2 zurueck, wenn OK
-        // http://docs.puppetlabs.com/references/3.4.0/man/apply.html
-        // 'command' => 'sudo puppet agent -t --detailed-exitcodes ; rc=$?; if [ $rc -eq 2 ]; then rc=0; fi ; exit $rc',
-        // task#38890 replace direct puppet call with a shell script
-        'command' => '/usr/local/bin/puppetrun.sh',
-    ),
-    'phases' => array(
-        "preview" => array(
-            'css' => array(
-                'bgdark' => 'background:#393E50;  color:#f8f8f8;',
-                'bglight' => 'background:#eee; color:#333; background:rgba(210,210,210,0.3); ',
-                'bgbutton' => 'background:#393E50; color:#fcfcfc; border: 1px solid rgba(0,0,0,0.15);',
-            ),
-        ),
-        "stage" => array(
-            'css' => array(
-                'bgdark' => 'background:#3F88C5; color:#f8f8f8;',
-                'bglight' => 'background:#f0f4f8; color:#333; background:rgba(200,210,220,0.3); ',
-                'bgbutton' => 'background:#3F88C5; color:#fcfcfc; border: 1px solid rgba(0,0,0,0.15);',
-            ),
-        ),
-        "live" => array(
-            'css' => array(
-                'bgdark' => 'background:#44BBA4; color:#f8f8f8;',
-                'bglight' => 'background:#f4f8f0; color:#333; background:rgba(210,220,200,0.3); ',
-                'bgbutton' => 'background:#44BBA4; color:#fcfcfc; border: 1px solid rgba(0,0,0,0.15);',
-            ),
-            // wenn deploytimes existiert, dann wird nach dem Deploy das Paket 
-            // in einer Queue zurueckgehalten
-            "deploytimes" => array('/(Mon|Tue|Wed|Thu)\ 14\:/'),
-        ),
-    ),
-    'showdebug' => array(
-        'ip'=>array(),
-    ),
-    
-    // generate template in hook/templates
-    'auth' => array(
-        'ldap' => array(
-            'server'       => '<%= @replace["ldap-url"] %>',
-            'port'         => 636,
-            'DnLdapUser' => '<%= @replace["ldap-user"] %>',
-            'PwLdapUser' => '<%= @replace["ldap-password"] %>',
-            'DnUserNode'   => '<%= @replace["ldap-dn-user"] %>',
-            'DnAppNode'    => '<%= @replace["ldap-cn-apps"] %><%= @replace["ldap-dn-apps"] %>',
-            'debugLevel'   => 0,
-        )
-    ),
-    'foreman' => array(
-        'api'=>'<%= @replace["foreman-url"] %>', // with ending "/"
-        'user'=>'<%= @replace["foreman-user"] %>',
-        'password'=>'<%= @replace["foreman-password"] %>',
-        'ignore-ssl-error'=><%= @replace["ignore-ssl-error"] %>,
-        // 'varname-replace'=>'ci-replacement',
-    ),
-
-    'projectgroups' => array(<%= @replace["projectgroups"] %>),
-
-    // where to store project data
-    'projects' => array(
-        'json' => array(
-            'active'       => true,
-        ),
-        'ldap' => array(
-            'active'       => false,
-        ),
-    ),
-    // notifications to messengers ...
-    'messenger'=>array(<%= @replace["messenger"] %>),    
-);
-
-// ----------------------------------------------------------------------
-// override for local development
-// ----------------------------------------------------------------------
-
-// unsafe ... 
-// make a check that fits your environemnt
-// php_uname("n") can send a short hostname (without domain)
-$bProd=!!strpos(__DIR__, '/ci.iml.unibe.ch/');
-
-switch (php_uname("n")) {
-    case "USER":
-    case "AAE49":
-    case "dev.ci.iml.unibe.ch":
-        $aConfig['workDir'] = "D:\imldeployment";
-        break;
-
-    case "ci.iml.unibe.ch":
-    case "ci":
-
-        if ($bProd){
-            // synch der Pakete nur auf dem Livesystem
-            $aConfig['mirrorPackages'] = array(
-                'puppet' => array(
-                    'type' => 'rsync',
-                    'runas' => '', // www-data, // nur fuer commandline
-                    'target' => 'ladmin@calcium.iml.unibe.ch:/share/imldeployment',
-                ),
-                'puppet.one' => array(
-                    'type' => 'rsync',
-                    'runas' => '', // www-data, // nur fuer commandline
-                    'target' => 'copy-deployment@puppet.one.iml.unibe.ch:/var/shared/imldeployment',
-                ),
-                'pkg-server' => array(
-                    'type' => 'rsync',
-                    'runas' => '', // www-data, // nur fuer commandline
-                    'target' => 'copy-deployment@software.shared.se.iml.unibe.ch:/var/shared/imldeployment',
-                ),
-            );
-        }
-        break;
-
-    default:
-        break;
-}
-if (!array_key_exists('tmpDir', $aConfig) || !$aConfig["tmpDir"]){
-    $aConfig["tmpDir"] = (getenv("temp") ? getenv("temp") : "/var/tmp") . '/imldeployment';
-}
-
-// ----------------------------------------------------------------------
-// TODO: include custom settings that were saved in the GUI
-// ----------------------------------------------------------------------
-
-
-// ----------------------------------------------------------------------
-// generate some vars
-// ----------------------------------------------------------------------
-
-$aConfig = array_merge($aConfig, array(
-    'appRootDir' => dirname(dirname(__FILE__)),
-    'configDir' => dirname(__FILE__),
-    'dataDir' => $aConfig['workDir'] . '/data',    // to write data: ssh keys, projects, database
-    'buildDir' => $aConfig['workDir'] . '/build',
-    'buildDefaultsDir' => $aConfig['workDir'] . '/defaults',
-    'packageDir' => $aConfig['workDir'] . '/packages',
-    'archiveDir' => $aConfig['workDir'] . '/packages/_files',
-        ));
diff --git a/hooks/templates/inc_user2roles.php.erb b/hooks/templates/inc_user2roles.php.erb
index a42b5862a2ae4f3c5682b3ac55453c1578a5fcd2..0ad69f461a3ccad8cbf480519b59a52472e569f0 100644
--- a/hooks/templates/inc_user2roles.php.erb
+++ b/hooks/templates/inc_user2roles.php.erb
@@ -1,15 +1,24 @@
 <?php
 /*
+ * TARGET: config/inc_user2roles.php
+ * ----------------------------------------------------------------------
+ *
  * IML DEPLOYMENT GUI
- * USERS and assigned roles
+ * LIST OF ROLES AND ASSIGNED USERS
  * 
- * remark: Every user logged in is member of "authenticated"
+ * A user can be assigned to multiple groups
+ * 
+ * see permissions per role in inc_roles.php
+ * 
+ * Remarks: 
+ * - Non authenticated users are member in "all"
+ * - Every user logged in is member of "authenticated"
  */
+return [
+    // "authenticated" => [],
+    // "developer" => [],
+    // "projectmanager" => [],
 
-return array(
-    // "authenticated" => array(),
-    // "developer" => array(),
-    // "projectmanager" => array(),
-    "admin" => array(<%= @replace["adminusers"] %>),
+    "admin" => [<%= @replace["adminusers"] %>],
     
-);
+];