diff --git a/.gitignore b/.gitignore
index 0f9665549e88d781bd0d0e461368608177536b3a..4c21651c3266e977c2fc612e86d13b8bf2662a5f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,5 +8,7 @@ cmd/bitmask-connect/bitmask-connect
 locales/*/out.gotext.json
 tools/transifex/transifex
 
+branding/assets/default
+
 .*.swp
 *.exe
diff --git a/Makefile b/Makefile
index 8fba67203b5e4373563063138362786f68cee304..9f11a76e6989dc18aefc0d310731aa7f2406eb30 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,9 @@
 
 TAGS ?= gtk_3_18
 
+PROVIDER ?= $(shell grep ^'provider =' branding/config/vendor.conf | cut -d '=' -f 2 | tr -d "[:space:]")
+DEFAULT_PROVIDER = branding/assets/default/
+
 all: icon locales get build
 
 get:
@@ -11,6 +14,15 @@ get:
 generate:
 	go generate cmd/bitmask-vpn/main.go
 
+relink_default:
+ifneq (,$(wildcard ${DEFAULT_PROVIDER}))
+	cd branding/assets && unlink default
+endif
+	cd branding/assets && ln -s ${PROVIDER} default
+
+prepare: generate relink_default
+	branding/scripts/check-ca-crt.py ${PROVIDER} branding/config/vendor.conf
+
 build: $(foreach path,$(wildcard cmd/*),build_$(patsubst cmd/%,%,$(path)))
 
 build_%:
diff --git a/branding/README.txt b/branding/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..36015243733a629731b0c3a3d6363bd4710a482a
--- /dev/null
+++ b/branding/README.txt
@@ -0,0 +1,21 @@
+Branding for BitmaskVPN
+================================================================================
+
+This folder contains everything that is needed to generate a customized built of
+BitmaskVPN for your provider.
+
+
+Configure
+--------------------------------------------------------------------------------
+
+- Edit the file at 'branding/config/vendor.conf'. Add all the needed variables.
+- Copy your provider CA certificate to 'branding/config/<provider>-ca.crt'
+- Make sure that the folder 'branding/assets/<provider>' exists. Copy there all the needed assets.
+
+Build
+--------------------------------------------------------------------------------
+
+Run:
+
+PROVIDER=example.org make generate
+make build
diff --git a/branding/assets/default b/branding/assets/default
deleted file mode 120000
index f0a0a645f1f5edec052d8ee623d5695a7de17da1..0000000000000000000000000000000000000000
--- a/branding/assets/default
+++ /dev/null
@@ -1 +0,0 @@
-riseup
\ No newline at end of file
diff --git a/branding/check-ca-crt.py b/branding/check-ca-crt.py
deleted file mode 100755
index 646246784addf8f42cdba2c0b20e6a629199e60b..0000000000000000000000000000000000000000
--- a/branding/check-ca-crt.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python3
-import re
-import sys
-import urllib.request
-
-SCRIPT_NAME = 'check-ca-crt.py'
-
-USAGE = '''Check that the stored provider CA matches the one announced online.
-Usage: {name} <provider> <uri>
-
-Example: {name} riseup black.riseup.net'''.format(name=SCRIPT_NAME)
-
-
-def getLocalCert(provider):
-    sanitized = re.sub(r'[^\w\s-]', '', provider).strip().lower()
-    with open('config/{provider}-ca.crt'.format(provider=sanitized)) as crt:
-        return crt.read().strip()
-
-
-def getRemoteCert(uri):
-    fp = urllib.request.urlopen('https://' + uri + '/ca.crt')
-    remote_cert = fp.read().decode('utf-8').strip()
-    fp.close()
-    return remote_cert
-
-
-if __name__ == '__main__':
-
-    if len(sys.argv) != 3:
-        print('[!] Not enough arguments')
-        print(USAGE)
-        sys.exit(1)
-
-    provider = sys.argv[1]
-    uri = sys.argv[2]
-
-    local = getLocalCert(provider)
-    remote = getRemoteCert(uri)
-
-    try:
-        assert local == remote
-    except AssertionError:
-        print('[!] ERROR: remote and local CA certs do not match')
-        sys.exit(1)
-    else:
-        print('OK')
diff --git a/branding/config.go.tmpl b/branding/config.go.tmpl
deleted file mode 100644
index c3a9a330ae1ddc1ca029ccb8a0a85c28a9d39648..0000000000000000000000000000000000000000
--- a/branding/config.go.tmpl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-   DO NOT EDIT --------------------------------------------------
-
-   This file has been automatically generated by `go generate`.
-   Any changes will be overriden.
-
-   DO NOT EDIT --------------------------------------------------
-*/
-
-package config
-
-/* All these constants are defined in the vendor.conf file
-*/
-const (
-	Provider        = "$providerURL"
-	ApplicationName = "$applicationName"
-	BinaryName      = "$binaryName"
-	DonateURL       = "$donateURL"
-	HelpURL         = "$helpURL"
-	TosURL          = "$tosURL"
-	APIURL          = "$apiURL"
-	GeolocationAPI  = "$geolocationAPI"
-)
-
-/*
-
-CaCert : a string containing a representation of the provider CA, used to
-        sign the webapp and openvpn certificates. should be placed in
-        config/[provider]-ca.crt
-
-*/
-var CaCert = []byte(`$caCertString`)
diff --git a/branding/config/calyx-ca.crt b/branding/config/calyx-ca.crt
new file mode 100644
index 0000000000000000000000000000000000000000..2923144fee077f6bbf2a206b5262e551f42bb8b0
--- /dev/null
+++ b/branding/config/calyx-ca.crt
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQ0FADBEMQ4wDAYDVQQKDAVjYWx5
+eDEaMBgGA1UECwwRaHR0cHM6Ly9jYWx5eC5uZXQxFjAUBgNVBAMMDWNhbHl4IFJv
+b3QgQ0EwHhcNMTMwNzAyMDAwMDAwWhcNMjMwNzAyMDAwMDAwWjBEMQ4wDAYDVQQK
+DAVjYWx5eDEaMBgGA1UECwwRaHR0cHM6Ly9jYWx5eC5uZXQxFjAUBgNVBAMMDWNh
+bHl4IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDupdnx
+Bgat537XOqrZOulE/RvjoXB1S07sy9/MMtksXFoQuWJZRCSTp1Jaqg3H/e9o1nct
+LQO91+izfJe07TUyajFl7CfllYgMeyKTYcT85dFwNX4pcIHZr8UpmO0MpGBoR4W1
+8cPa3vxAG0CsyUmrASJVyhRouk4qazRosM5RwBxTdMzCK7L3SwqPQoxlY9YmRJlD
+XYZlK5VMJd0dj9XxhMeFs5n43R0bsDENryrExSbuxoNfnUoQg3wffKk+Z0gW7YgW
+ivPsbObqOgXUuBEU0xr9xMNBpU33ffLIsccrHq1EKp8zGfCOcww6v7+zEadUkVLo
+6j/rRhYYgRw9lijZG1rMuV/mTGnUqbjHsdoz5mzkFFWeTSqo44lvhveUyCcwRNmi
+2sjS77l0fCTzfreufffFoOEcRVMRfsnJdu/xPeARoXILEx8nQ421mSn6spOZlDQr
+Tt0T0BAWt+VNc+m0IGSW3SwS7r5MUyQ/M5GrbQBGi5W2SzPriKZ79YTOwPVmXKLZ
+vJoEuKRDkEPJLBAhcD5oSQljOm/Wp/hjmRH4HnI1y4XMshWlDsyRDB1Au5yrsfwN
+noFVSskEcbXlZfNgml4lktLBqz+qwsw+voq6Ak7ROKbc0ii5s8+iNMbAtIK7GcFF
+kuKKIyRmmGlDim/SDhlNdWo7Ah4Akde7zfWufwIDAQABo2AwXjAdBgNVHQ4EFgQU
+AY8+K4ZupAQ+L9ttFJG3vaLBq5gwDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMB
+Af8wHwYDVR0jBBgwFoAUAY8+K4ZupAQ+L9ttFJG3vaLBq5gwDQYJKoZIhvcNAQEN
+BQADggIBAOpXi5o3g/2o2rPa53iG7Zgcy8RpePGgZk6xknGYWeLamEqSh+XWQZ2w
+2kQP54bf8HfPj3ugJBWsVtYAs/ltJwzeBfYDrwEJd1N8tw2IRuGlQOWiTAVVLBj4
+Zs+dikSuMoA399f/7BlUIEpVLUiV/emTtbkjFnDeKEV9zql6ypR0BtR8Knf8ALvL
+YfMsWLvTe4rXeypzxIaE2pn8ttcXLYAX0ml2MofTi5xcDhMn1vznKIvs82xhncQx
+I1MJMWqPHNHgJUJpA+y1IFh5LPbpag9PKQ0yQ9sM+/dyGumF2jElsMw71flh/Txr
+2dEv8+FNV1pPK26XJZBK24rNWFs30eAFfH9EQCwVla174I4PDoWqsIR7vtQMObDt
+Bq34R3TjjJJIt2sCSlYLooWwiK7Q+d/SgYqA+MSDmmwhzm86ToK6cwbCsvuw1AxR
+X6VIs4U8wOotgljzX/CSpKqlxcqZjhnAuelZ1+KiN8RHKPj7AzSLYOv/YwTjLTIq
+EOxquoNR58uDa5pBG22a7xWbSaKosn/mEl8SrUr6klzzc8Vh09IMoxrw74uLdAg2
+1jnrhm7qg91Ttb0aXiqbV+Kg/qQzojdewnnoBFnv4jaQ3y8zDCfMhsBtWlWz4Knb
+Zqga1WyRm3Gj1j6IV0oOincYMrw5YA7bgXpwop/Lo/mmliMA14ps
+-----END CERTIFICATE-----
diff --git a/branding/config/vendor.conf b/branding/config/vendor.conf
index ee5aa3643ece67a52f7419f757fcd9f59680d807..12fca4e51e540998a3a22afe48826f802ad9519c 100644
--- a/branding/config/vendor.conf
+++ b/branding/config/vendor.conf
@@ -8,17 +8,31 @@ provider = riseup
 name                = Riseup
 applicationName     = RiseupVPN
 binaryName          = riseup-vpn 
+
 providerURL         = riseup.net
+apiURL              = https://api.black.riseup.net/
+caURL               = https://black.riseup.net/ca.crt
+
 tosURL              = https://riseup.net/tos
 helpURL             = https://riseup.net/support
-donateURL           = https://riseup.net/donate
-apiURL              = https://api.black.riseup.net/
+
 geolocationAPI      = https://api.black.riseup.net:9001/json
 
+askForDonations     = true
+donateURL           = https://riseup.net/donate
+
 
 [calyx]
 
 name                = Calyx
 applicationName     = CalyxVPN
 binaryName          = calyx-vpn
-apiURL              = https://calyx.org
+providerURL         = https://calyx.net
+tosURL              = https://calyx.net/tos
+helpURL             = https://calyx.net/support
+apiURL              = https://api.calyx.net:4430/
+caURL               = https://calyx.net/ca.crt
+geolocationAPI      = https://api.black.riseup.net:9001/json
+
+askForDonations     = true
+donateURL           = http://example.org
diff --git a/branding/scripts/check-ca-crt.py b/branding/scripts/check-ca-crt.py
index 646246784addf8f42cdba2c0b20e6a629199e60b..431d05957f6fd4bc2a6d65a61768b33b501809a9 100755
--- a/branding/scripts/check-ca-crt.py
+++ b/branding/scripts/check-ca-crt.py
@@ -1,29 +1,37 @@
 #!/usr/bin/env python3
 import re
 import sys
+import configparser
 import urllib.request
 
 SCRIPT_NAME = 'check-ca-crt.py'
 
 USAGE = '''Check that the stored provider CA matches the one announced online.
-Usage: {name} <provider> <uri>
+Usage: {name} <provider> <config>
 
-Example: {name} riseup black.riseup.net'''.format(name=SCRIPT_NAME)
+Example: {name} riseup branding/config/vendor.conf'''.format(name=SCRIPT_NAME)
 
 
 def getLocalCert(provider):
     sanitized = re.sub(r'[^\w\s-]', '', provider).strip().lower()
-    with open('config/{provider}-ca.crt'.format(provider=sanitized)) as crt:
+    with open('branding/config/'
+              '{provider}-ca.crt'.format(provider=sanitized)) as crt:
         return crt.read().strip()
 
 
 def getRemoteCert(uri):
-    fp = urllib.request.urlopen('https://' + uri + '/ca.crt')
+    fp = urllib.request.urlopen(uri)
     remote_cert = fp.read().decode('utf-8').strip()
     fp.close()
     return remote_cert
 
 
+def getUriForProvider(provider, configfile):
+    c = configparser.ConfigParser()
+    c.read(configfile)
+    return c[provider]['caURL']
+
+
 if __name__ == '__main__':
 
     if len(sys.argv) != 3:
@@ -32,7 +40,13 @@ if __name__ == '__main__':
         sys.exit(1)
 
     provider = sys.argv[1]
-    uri = sys.argv[2]
+    config = sys.argv[2]
+
+    try:
+        uri = getUriForProvider(provider, config)
+    except IndexError:
+        print('[!] Misconfigured provider')
+        sys.exit(1)
 
     local = getLocalCert(provider)
     remote = getRemoteCert(uri)
@@ -43,4 +57,4 @@ if __name__ == '__main__':
         print('[!] ERROR: remote and local CA certs do not match')
         sys.exit(1)
     else:
-        print('OK')
+        print('OK: local CA matches what provider announces')
diff --git a/branding/scripts/vendorize.py b/branding/scripts/vendorize.py
index 46cc1e69ab6f4f04562a60cc96d12757b16017cd..c600967429f2083e6f9deafecc8ba78e9387718a 100755
--- a/branding/scripts/vendorize.py
+++ b/branding/scripts/vendorize.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 
+import datetime
 import os
 import sys
 
@@ -12,11 +13,20 @@ CONFIGFILE = 'config/vendor.conf'
 SCRIPT_NAME = 'vendorize'
 
 
-def getProviderData(config):
-    default = config['default']['provider']
-    print("[+] Configured provider:", default)
+def getDefaultProvider(config):
+    provider = os.environ.get('PROVIDER')
+    if provider:
+        print('[+] Got provider {} from environemnt'.format(provider))
+    else:
+        print('[+] Using default provider from config file')
+        provider = config['default']['provider']
+    return provider
+
 
-    c = config[default]
+def getProviderData(provider, config):
+    print("[+] Configured provider:", provider)
+
+    c = config[provider]
     d = dict()
 
     keys = ('name', 'applicationName', 'binaryName',
@@ -26,6 +36,9 @@ def getProviderData(config):
     for value in keys:
         d[value] = c.get(value)
 
+    d['timeStamp'] = '{:%Y-%m-%d %H:%M:%S}'.format(
+        datetime.datetime.now())
+
     return d
 
 
@@ -90,7 +103,8 @@ if __name__ == "__main__":
     config = configparser.ConfigParser()
     config.read(configfile)
 
-    data = getProviderData(config)
+    provider = getDefaultProvider(config)
+    data = getProviderData(provider, config)
     addCaData(data, configfile)
     writeOutput(data, infile, outfile)
 
diff --git a/branding/template/config.go b/branding/template/config.go
index c3a9a330ae1ddc1ca029ccb8a0a85c28a9d39648..67908c06dee24d2ee3c84be3fc7295995a51f6ec 100644
--- a/branding/template/config.go
+++ b/branding/template/config.go
@@ -1,16 +1,11 @@
-/*
-   DO NOT EDIT --------------------------------------------------
-
-   This file has been automatically generated by `go generate`.
-   Any changes will be overriden.
-
-   DO NOT EDIT --------------------------------------------------
-*/
+// Code generated by go generate; DO NOT EDIT.
+// This file was generated by vendorize.py
+// At $timeStamp
 
 package config
 
 /* All these constants are defined in the vendor.conf file
-*/
+ */
 const (
 	Provider        = "$providerURL"
 	ApplicationName = "$applicationName"
diff --git a/branding/vendorize.py b/branding/vendorize.py
deleted file mode 100755
index 46cc1e69ab6f4f04562a60cc96d12757b16017cd..0000000000000000000000000000000000000000
--- a/branding/vendorize.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import sys
-
-from string import Template
-import configparser
-
-OUTFILE = 'config.go'
-INFILE = 'config.go.tmpl'
-CONFIGFILE = 'config/vendor.conf'
-SCRIPT_NAME = 'vendorize'
-
-
-def getProviderData(config):
-    default = config['default']['provider']
-    print("[+] Configured provider:", default)
-
-    c = config[default]
-    d = dict()
-
-    keys = ('name', 'applicationName', 'binaryName',
-            'providerURL', 'tosURL', 'helpURL',
-            'donateURL', 'apiURL', 'geolocationAPI', 'caCertString')
-
-    for value in keys:
-        d[value] = c.get(value)
-
-    return d
-
-
-def addCaData(data, configfile):
-    provider = data.get('name').lower()
-    folder, f = os.path.split(configfile)
-    caFile = os.path.join(folder, provider + '-ca.crt')
-    if not os.path.isfile(caFile):
-        bail('[!] Cannot find CA file in {path}'.format(path=caFile))
-    with open(caFile) as ca:
-        data['caCertString'] = ca.read().strip()
-
-
-def writeOutput(data, infile, outfile):
-
-    with open(infile) as infile:
-        s = Template(infile.read())
-
-    with open(outfile, 'w') as outf:
-        outf.write(s.substitute(data))
-
-
-def bail(msg=None):
-    if not msg:
-        print('Usage: {scriptname}.py <template> <config> <output>'.format(
-            scriptname=SCRIPT_NAME))
-    else:
-        print(msg)
-    sys.exit(1)
-
-
-if __name__ == "__main__":
-    infile = outfile = ""
-
-    if len(sys.argv) > 4:
-        bail()
-
-    elif len(sys.argv) == 1:
-        infile = INFILE
-        outfile = OUTFILE
-        configfile = CONFIGFILE
-    else:
-        try:
-            infile = sys.argv[1]
-            configfile = sys.argv[2]
-            outfile = sys.argv[3]
-        except IndexError:
-            bail()
-
-    if not os.path.isfile(infile):
-        bail('[!] Cannot find template in {path}'.format(
-            path=os.path.abspath(infile)))
-    elif not os.path.isfile(configfile):
-        bail('[!] Cannot find config in {path}'.format(
-            path=os.path.abspath(configfile)))
-    else:
-        print('[+] Using {path} as template'.format(
-            path=os.path.abspath(infile)))
-        print('[+] Using {path} as config'.format(
-            path=os.path.abspath(configfile)))
-
-    config = configparser.ConfigParser()
-    config.read(configfile)
-
-    data = getProviderData(config)
-    addCaData(data, configfile)
-    writeOutput(data, infile, outfile)
-
-    print('[+] Wrote configuration for {provider} to {outf}'.format(
-        provider=data.get('name'),
-        outf=os.path.abspath(outfile)))
diff --git a/cmd/bitmask-vpn/main.go b/cmd/bitmask-vpn/main.go
index fa1daf3a8b222e8329659195c67feef011a7d8f2..25dcb4834353d080f5de196e1a1e62e0d38de1bf 100644
--- a/cmd/bitmask-vpn/main.go
+++ b/cmd/bitmask-vpn/main.go
@@ -15,7 +15,7 @@
 
 package main
 
-//go:generate ../../branding/vendorize.py ../../branding/config.go.tmpl ../../branding/config/vendor.conf ../../pkg/config/config.go
+//go:generate ../../branding/scripts/vendorize.py ../../branding/template/config.go ../../branding/config/vendor.conf ../../pkg/config/config.go
 
 import (
 	"flag"
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 29f724a7a458da3047ddb912e6cfb6ce0ec8403a..eabdbefdf90fed736be2d1bcf8ae2498343a521d 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -1,16 +1,11 @@
-/*
-   DO NOT EDIT --------------------------------------------------
-
-   This file has been automatically generated by `go generate`.
-   Any changes will be overriden.
-
-   DO NOT EDIT --------------------------------------------------
-*/
+// Code generated by go generate; DO NOT EDIT.
+// This file was generated by vendorize.py
+// At 2019-07-02 18:39:16
 
 package config
 
 /* All these constants are defined in the vendor.conf file
-*/
+ */
 const (
 	Provider        = "riseup.net"
 	ApplicationName = "RiseupVPN"
@@ -26,7 +21,7 @@ const (
 
 CaCert : a string containing a representation of the provider CA, used to
         sign the webapp and openvpn certificates. should be placed in
-        config/[provider]/ca.crt
+        config/[provider]-ca.crt
 
 */
 var CaCert = []byte(`-----BEGIN CERTIFICATE-----