diff --git a/scripts/register.sh b/scripts/register.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ed75a36260d64d486324a7cabe0a11a74f18996b
--- /dev/null
+++ b/scripts/register.sh
@@ -0,0 +1,325 @@
+#!/usr/bin/env bash
+# Register a user for IndiePaaS
+#
+# This file:
+#  - Registers the domain name to NameCheap
+#  - Generates the TLS certificate associated
+#  - Configures the DNS
+#  - Configures the mail forwarding
+#
+# Version 0.0.1 
+#
+# Authors:
+#  - Pierre Ozoux (pierre-o.fr)
+#
+# Usage:
+#  LOG_LEVEL=7 ./register.sh -n example.org -d
+#
+# Licensed under AGPLv3
+
+
+### Configuration
+#####################################################################
+
+# Environment variables and their defaults
+LOG_LEVEL="${LOG_LEVEL:-6}" # 7 = debug -> 0 = emergency
+
+# Commandline options. This defines the usage page, and is used to parse cli
+# opts & defaults from. The parsing is unforgiving so be precise in your syntax
+read -r -d '' usage <<-'EOF'
+  -n   [arg] Domain name to process. Required.
+  -d         Enables debug mode
+  -h         This page
+EOF
+
+### Functions
+#####################################################################
+
+function contains () {
+  local n=$#
+  local value=${!n}
+  for ((i=1;i < $#;i++)) {
+    if [ "${!i}" == "${value}" ]; then
+      echo "y"
+      return 0
+    fi
+  }
+  echo "n"
+  return 1
+}
+
+function TLD () {
+  echo ${arg_n} | cut -d. -f2,3
+}
+
+function SLD () {
+  echo ${arg_n} | cut -d. -f1
+}
+
+function call_API () {
+  output=$(curl -s "https://api.$NAMECHEAP_URL/xml.response\?ApiUser=${NAMECHEAP_API_USER}&ApiKey=${NAMECHEAP_API_KEY}&UserName=${NAMECHEAP_API_USER}&ClientIp=${IP}$1")
+
+  if [ -z $(echo ${output} | grep 'Status="OK"') ]; then
+    error "API call failed. Please read the output"
+    echo ${output}
+    exit 1
+  else
+    info "API call is a success."
+  fi
+
+}
+
+function create_domain_name () {
+
+  not_supported_extensions=("us" "eu" "nu" "asia" "ca" "co.uk" "me.uk" "org.uk" "com.au" "net.au" "org.au" "es" "nom.es" "com.es" "org.es" "de" "fr" "")
+  if [ $(contains "${not_supported_extensions[@]}" "$(TLD)") == "y" ]; then
+    error "Extension .${extension} is not yet supported.."
+    exit 1
+  fi 
+
+  info "Buying Domain name."
+  arguments="&Command=namecheap.domains.create\
+&DomainName=${arg_n}\
+&Years=1\
+&AuxBillingFirstName=${FirstName}\
+&AuxBillingLastName=${LastName}\
+&AuxBillingAddress1=${Address}\
+&AuxBillingCity=${City}\
+&AuxBillingPostalCode=${PostalCode}\
+&AuxBillingCountry=${Country}\
+&AuxBillingPhone=${Phone}\
+&AuxBillingEmailAddress=${EmailAddress}\
+&AuxBillingStateProvince=${City}\
+&TechFirstName=${FirstName}\
+&TechLastName=${LastName}\
+&TechAddress1=${Address}\
+&TechCity=${City}\
+&TechPostalCode=${PostalCode}\
+&TechCountry=${Country}\
+&TechPhone=${Phone}\
+&TechEmailAddress=${EmailAddress}\
+&TechStateProvince=${City}\
+&AdminFirstName=${FirstName}\
+&AdminLastName=${LastName}\
+&AdminAddress1=${Address}\
+&AdminCity=${City}\
+&AdminPostalCode=${PostalCode}\
+&AdminCountry=${Country}\
+&AdminPhone=${Phone}\
+&AdminEmailAddress=${EmailAddress}\
+&AdminStateProvince=${City}\
+&RegistrantFirstName=${FirstName}\
+&RegistrantLastName=${LastName}\
+&RegistrantAddress1=${Address}\
+&RegistrantCity=${City}\
+&RegistrantPostalCode=${PostalCode}\
+&RegistrantCountry=${Country}\
+&RegistrantPhone=${Phone}\
+&RegistrantEmailAddress=${EmailAddress}\
+&RegistrantStateProvince=${City}"
+
+  call_API ${arguments}
+
+  info "Changing email forwarding."
+  arguments="&Command=namecheap.domains.dns.setEmailForwarding\
+&DomainName=${arg_n}\
+&mailbox1=hostmaster\
+&ForwardTo1=${EmailAddress}"
+
+  call_API ${arguments}
+}
+
+function generate_certificate () {
+
+  TLS_FOLDER=/data/import/${arg_n}/TLS
+
+  info "Creating import folder."
+  mkdir -p ${TLS_FOLDER}/CSR
+  
+  info "Generating the key."
+  openssl genrsa -out ${TLS_FOLDER}//CSR/${arg_n}.key 4096
+
+  info "Creating the request."
+  openssl req -new \
+    -key ${TLS_FOLDER}/CSR/${arg_n}.key \
+    -out ${TLS_FOLDER}/CSR/${arg_n}.csr \
+    -subj "/C=${CountryCode}/ST=${City}/L=${City}/O=${arg_n}/OU=/CN=${arg_n}/emailAddress=${EmailAddress}"
+
+  info "Here is your CSR, paste it in your Certificate authority interface."
+  echo ""
+  cat ${TLS_FOLDER}/CSR/${arg_n}.csr
+
+  echo ""
+  info "You should have received a certificate"
+  info "Please paste your certificate now"
+  IFS= read -d '' -n 1 certificate
+  while IFS= read -d '' -n 1 -t 2 c
+  do
+    certificate+=$c
+  done
+
+  if [ "${arg_d}" = "1" ]; then
+    echo ${certificate}
+  fi
+
+  echo ${certificate} > ${TLS_FOLDER}/CSR/${arg_n}.cert
+
+  info "Concat certificate, CA and key into pem file"
+  cat ${TLS_FOLDER}/CSR/${arg_n}.cert /data/indiehosters/scripts/sub.class2.server.ca.pem ${TLS_FOLDER}/CSR/${arg_n}.key > ${TLS_FOLDER}/${arg_n}.pem
+}
+
+function configure_dns () {
+  info "Configuring DNS."
+  arguments="&Command=namecheap.domains.dns.setHosts\
+&DomainName=${arg_n}\
+&SLD=$(SLD)\
+&TLD=$(TLD)\
+&HostName1=@\
+&RecordType1=A\
+&Address1=${IP}\
+&HostName2=www\
+&RecordType2=CNAME\
+&Address2=${arg_n}\
+&HostName3=mail\
+&RecordType3=A\
+&Address3=${IP}\
+&HostName4=@\
+&RecordType4=MX\
+&Address4=mail.${arg_n}\
+&MXPref4=10"
+
+  call_API ${arguments}
+
+}
+
+function _fmt ()      {
+  local color_ok="\x1b[32m"
+  local color_bad="\x1b[31m"
+
+  local color="${color_bad}"
+  if [ "${1}" = "debug" ] || [ "${1}" = "info" ] || [ "${1}" = "notice" ]; then
+    color="${color_ok}"
+  fi
+
+  local color_reset="\x1b[0m"
+  if [[ "${TERM}" != "xterm"* ]] || [ -t 1 ]; then
+    # Don't use colors on pipes or non-recognized terminals
+    color=""; color_reset=""
+  fi
+  echo -e "$(date -u +"%Y-%m-%d %H:%M:%S UTC") ${color}$(printf "[%9s]" ${1})${color_reset}";
+}
+function emergency () {                             echo "$(_fmt emergency) ${@}" 1>&2 || true; exit 1; }
+function alert ()     { [ "${LOG_LEVEL}" -ge 1 ] && echo "$(_fmt alert) ${@}" 1>&2 || true; }
+function critical ()  { [ "${LOG_LEVEL}" -ge 2 ] && echo "$(_fmt critical) ${@}" 1>&2 || true; }
+function error ()     { [ "${LOG_LEVEL}" -ge 3 ] && echo "$(_fmt error) ${@}" 1>&2 || true; }
+function warning ()   { [ "${LOG_LEVEL}" -ge 4 ] && echo "$(_fmt warning) ${@}" 1>&2 || true; }
+function notice ()    { [ "${LOG_LEVEL}" -ge 5 ] && echo "$(_fmt notice) ${@}" 1>&2 || true; }
+function info ()      { [ "${LOG_LEVEL}" -ge 6 ] && echo "$(_fmt info) ${@}" 1>&2 || true; }
+function debug ()     { [ "${LOG_LEVEL}" -ge 7 ] && echo "$(_fmt debug) ${@}" 1>&2 || true; }
+
+function help () {
+  echo "" 1>&2
+  echo " ${@}" 1>&2
+  echo "" 1>&2
+  echo "  ${usage}" 1>&2
+  echo "" 1>&2
+  exit 1
+}
+
+function cleanup_before_exit () {
+  info "Cleaning up. Done"
+}
+trap cleanup_before_exit EXIT
+
+### Parse commandline options
+#####################################################################
+
+# Translate usage string -> getopts arguments, and set $arg_<flag> defaults
+while read line; do
+  opt="$(echo "${line}" |awk '{print $1}' |sed -e 's#^-##')"
+  if ! echo "${line}" |egrep '\[.*\]' >/dev/null 2>&1; then
+    init="0" # it's a flag. init with 0
+  else
+    opt="${opt}:" # add : if opt has arg
+    init=""  # it has an arg. init with ""
+  fi
+  opts="${opts}${opt}"
+
+  varname="arg_${opt:0:1}"
+  if ! echo "${line}" |egrep '\. Default=' >/dev/null 2>&1; then
+    eval "${varname}=\"${init}\""
+  else
+    match="$(echo "${line}" |sed 's#^.*Default=\(\)#\1#g')"
+    eval "${varname}=\"${match}\""
+  fi
+done <<< "${usage}"
+
+# Reset in case getopts has been used previously in the shell.
+OPTIND=1
+
+# Overwrite $arg_<flag> defaults with the actual CLI options
+while getopts "${opts}" opt; do
+  line="$(echo "${usage}" |grep "\-${opt}")"
+
+
+  [ "${opt}" = "?" ] && help "Invalid use of script: ${@} "
+  varname="arg_${opt:0:1}"
+  default="${!varname}"
+
+  value="${OPTARG}"
+  if [ -z "${OPTARG}" ] && [ "${default}" = "0" ]; then
+    value="1"
+  fi
+
+  eval "${varname}=\"${value}\""
+  debug "cli arg ${varname} = ($default) -> ${!varname}"
+done
+
+shift $((OPTIND-1))
+
+[ "$1" = "--" ] && shift
+
+
+### Switches (like -d for debugmdoe, -h for showing helppage)
+#####################################################################
+
+# debug mode
+if [ "${arg_d}" = "1" ]; then
+  set -o xtrace
+  LOG_LEVEL="7"
+fi
+
+# help mode
+if [ "${arg_h}" = "1" ]; then
+  # Help exists with code 1
+  help "Help using ${0}"
+fi
+
+
+### Validation (decide what's required for running your script and error out)
+#####################################################################
+
+[ -z "${arg_n}" ]     && help      "Setting a domain name with -n is required"
+[ -z "${LOG_LEVEL}" ] && emergency "Cannot continue without LOG_LEVEL. "
+
+
+### Runtime
+#####################################################################
+
+# Exit on error. Append ||true if you expect an error.
+# set -e is safer than #!/bin/bash -e because that is neutralised if
+# someone runs your script like `bash yourscript.sh`
+set -o errexit
+set -o nounset
+
+# Bash will remember & return the highest exitcode in a chain of pipes.
+# This way you can catch the error in case mysqldump fails in `mysqldump |gzip`
+set -o pipefail
+
+if [[ "${OSTYPE}" == "darwin"* ]]; then
+  info "You are on OSX"
+fi
+
+create_domain_name
+generate_certificate
+configure_dns
diff --git a/scripts/sub.class2.server.ca.pem b/scripts/sub.class2.server.ca.pem
new file mode 100644
index 0000000000000000000000000000000000000000..6621e684aec68ed7c4d6374b5b9a42a9fe99020d
--- /dev/null
+++ b/scripts/sub.class2.server.ca.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIBGzANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NzA5WhcNMTcxMDI0MjA1NzA5WjCB
+jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
+IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
+YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4k85L6GMmoWtCA4IPlfyiAEh
+G5SpbOK426oZGEY6UqH1D/RujOqWjJaHeRNAUS8i8gyLhw9l33F0NENVsTUJm9m8
+H/rrQtCXQHK3Q5Y9upadXVACHJuRjZzArNe7LxfXyz6CnXPrB0KSss1ks3RVG7RL
+hiEs93iHMuAW5Nq9TJXqpAp+tgoNLorPVavD5d1Bik7mb2VsskDPF125w2oLJxGE
+d2H2wnztwI14FBiZgZl1Y7foU9O6YekO+qIw80aiuckfbIBaQKwn7UhHM7BUxkYa
+8zVhwQIpkFR+ZE3EMFICgtffziFuGJHXuKuMJxe18KMBL47SLoc6PbQpZ4rEAwID
+AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFBHbI0X9VMxqcW+EigPXvvcBLyaGMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
+L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
+YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
+dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
+c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
+BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
+BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
+LnBkZjANBgkqhkiG9w0BAQsFAAOCAgEAbQjxXHkqUPtUY+u8NEFcuKMDITfjvGkl
+LgrTuBW63grW+2AuDAZRo/066eNHs6QV4i5e4ujwPSR2dgggY7mOIIBmiDm2QRjF
+5CROq6zDlIdqlsFZICkuONDNFpFjaPtZRTmuK1n6gywQgCNSIrbzjPcwR/jL/wow
+bfwC9yGme1EeZRqvWy/HzFWacs7UMmWlRk6DTmpfPOPMJo5AxyTZCiCYQQeksV7x
+UAeY0kWa+y/FV+eerOPUl6yy4jRHTk7tCySxrciZwYbd6YNLmeIQoUAdRC3CH3nT
+B2/JYxltcgyGHMiPU3TtafZgLs8fvncv+wIF1YAF/OGqg8qmzoJ3ghM4upGdTMIu
+8vADdmuLC/+dnbzknxX6QEGlWA8zojLUxVhGNfIFoizu/V/DyvSvYuxzzIkPECK5
+gDoMoBTTMI/wnxXwulNPtfgF7/5AtDhA4GNAfB2SddxiNQAF7XkUHtMZ9ff3W6Xk
+FldOG+NlLFqsDBG/KLckyFK36gq+FqNFCbmtmtXBGB5L1fDIeYzcMKG6hFQxhHS0
+oqpdHhp2nWBfLlOnTNqIZNJzOH37OJE6Olk45LNFJtSrqIAZyCCfM6bQgoQvZuIa
+xs9SIp+63ZMk9TxEaQj/KteaOyfaPXI9778U7JElMTz3Bls62mslV2I1C/A73Zyq
+JZWQZ8NU4ds=
+-----END CERTIFICATE-----