diff --git a/pkg/cluster/certs.go b/pkg/cluster/certs.go
index 8e18bf4358e133c6f9e070f4e82120295625c858..8ec91d671c29417e9d6a7ea048ec0c980ce9fc71 100644
--- a/pkg/cluster/certs.go
+++ b/pkg/cluster/certs.go
@@ -8,7 +8,7 @@ import (
 func (c *Cluster) initCerts() {
 	// Prepare the cluster PKI
 	if c.node.Role == Master {
-		ca, err := pki.NewClusterPKI("pki")
+		ca, err := pki.NewClusterCA("pki")
 		if err != nil {
 			logrus.Fatal("could not initialize pki: ", err)
 		}
diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go
index 89c3d68017a62ef04b1d217e73ce1156f26e65cb..8a7af7321c89de7adb3c5eb85162fb929a767871 100644
--- a/pkg/cluster/cluster.go
+++ b/pkg/cluster/cluster.go
@@ -3,8 +3,8 @@
 package cluster
 
 import (
-	"forge.tedomum.net/acides/hepto/hepto/pkg/sml"
 	"forge.tedomum.net/acides/hepto/hepto/pkg/pki"
+	"forge.tedomum.net/acides/hepto/hepto/pkg/sml"
 	"forge.tedomum.net/acides/hepto/hepto/pkg/wg"
 	"github.com/sirupsen/logrus"
 )
@@ -17,7 +17,7 @@ type Cluster struct {
 	node        *NodeSettings
 	certs       *pki.NodeCerts
 	masterCerts *pki.MasterCerts
-	pki         *pki.ClusterPKI
+	pki         *pki.ClusterCA
 	services    *ClusterServices
 }
 
@@ -27,7 +27,7 @@ func New(settings *ClusterSettings, node *NodeSettings) *Cluster {
 		node:       node,
 		networking: NewClusterNetworking(settings.Name, node.Name),
 		ml:         sml.New[HeptoMeta, HeptoState](node.Name, node.IP, node.Port, node.Anchors, settings.Key),
-		pki:        &pki.ClusterPKI{},
+		pki:        &pki.ClusterCA{},
 		services:   NewClusterServices(),
 	}
 }
diff --git a/pkg/cluster/meta.go b/pkg/cluster/meta.go
index 13c268b9e4c60258acc3bd11fd8bdc1ba8b5b745..04ae143b50356cb73ce3f50dcf3de87b2e503b43 100644
--- a/pkg/cluster/meta.go
+++ b/pkg/cluster/meta.go
@@ -2,10 +2,8 @@ package cluster
 
 import (
 	"encoding/json"
-	"fmt"
-	"strings"
 
-  "forge.tedomum.net/acides/hepto/hepto/pkg/pki"
+	"forge.tedomum.net/acides/hepto/hepto/pkg/pki"
 )
 
 // Represents a node metadata
@@ -19,7 +17,7 @@ type HeptoMeta struct {
 // Represents the cluster state
 type HeptoState struct {
 	// Cluster CAs public certificates
-	PKI *pki.ClusterPKI `json:"ca"`
+	PKI *pki.ClusterCA `json:"ca"`
 	// Certificate per node, this should only
 	// be updated by the node itself
 	Certificates map[string]*pki.NodeCerts `json:"nodes"`
@@ -46,21 +44,7 @@ func (s *HeptoState) Decode(b []byte) error {
 }
 
 func (s *HeptoState) String() string {
-	var res string
-	if s.PKI != nil {
-		var ca []string
-		if s.PKI.API != nil {
-			ca = append(ca, "api")
-		}
-		if s.PKI.Kubelet != nil {
-			ca = append(ca, "kubelet")
-		}
-		if s.PKI.Services != nil {
-			ca = append(ca, "services")
-		}
-		res += fmt.Sprintf("ca{%s}", strings.Join(ca, ", "))
-	}
-	return res
+	return "state"
 }
 
 func (s *HeptoState) Merge(b []byte) (bool, error) {
diff --git a/pkg/cluster/services.go b/pkg/cluster/services.go
index 50a54dd48756958499db7a9718514123b281438e..d5e5f917afb5f1def1e32815d55590e6f5228547 100644
--- a/pkg/cluster/services.go
+++ b/pkg/cluster/services.go
@@ -42,10 +42,11 @@ func (s *ClusterServices) Update(c *Cluster) {
 		s.startK8sMaster(c.networking, c.pki, c.masterCerts)
 		s.started = true
 	} else if c.node.Role == Node {
-		if c.pki.Services == nil || c.pki.Services.Cert == nil {
+		// Bail if certificates are not ready yet
+		if c.pki.TLS == nil || c.pki.TLS.Cert == nil {
 			return
 		}
-		if c.certs.API.Cert == nil || c.certs.Service.Cert == nil {
+		if c.certs.TLS.Cert == nil || c.certs.API.Cert == nil {
 			return
 		}
 		logrus.Debug("looking for master node...")
@@ -68,12 +69,12 @@ func (s *ClusterServices) startEtcd() {
 	go s.watch(service)
 }
 
-func (s *ClusterServices) startK8sMaster(net *ClusterNetworking, ca *pki.ClusterPKI, certs *pki.MasterCerts) {
+func (s *ClusterServices) startK8sMaster(net *ClusterNetworking, ca *pki.ClusterCA, certs *pki.MasterCerts) {
 	api, err := wrappers.APIServer(s.ctx, []string{
 		"--bind-address", net.NodeAddress.IP.String(),
 		"--service-cluster-ip-range", net.ServiceNet.String(),
-		"--tls-cert-file", certs.Service.CertPath(),
-		"--tls-private-key-file", certs.Service.KeyPath(),
+		"--tls-cert-file", certs.TLS.CertPath(),
+		"--tls-private-key-file", certs.TLS.KeyPath(),
 		"--client-ca-file", ca.API.CertPath(),
 		"--kubelet-certificate-authority", ca.Kubelet.CertPath(),
 		"--kubelet-client-certificate", certs.Kubelet.CertPath(),
@@ -90,9 +91,9 @@ func (s *ClusterServices) startK8sMaster(net *ClusterNetworking, ca *pki.Cluster
 	}
 	cmConfig := KubeConfig{
 		URL:        fmt.Sprintf("https://[%s]:6443", net.NodeAddress.IP.String()),
-		CACert:     ca.Services.CertPath(),
-		ClientCert: certs.ControllersClient.CertPath(),
-		ClientKey:  certs.ControllersClient.KeyPath(),
+		CACert:     ca.TLS.CertPath(),
+		ClientCert: certs.ControllersAPI.CertPath(),
+		ClientKey:  certs.ControllersAPI.KeyPath(),
 	}
 	cmConfigPath := "/cm.yaml"
 	err = cmConfig.Write(cmConfigPath)
@@ -101,8 +102,8 @@ func (s *ClusterServices) startK8sMaster(net *ClusterNetworking, ca *pki.Cluster
 	}
 	cm, err := wrappers.ControllerManager(s.ctx, []string{
 		"--kubeconfig", cmConfigPath,
-		"--tls-cert-file", certs.Controllers.CertPath(),
-		"--tls-private-key-file", certs.Controllers.KeyPath(),
+		"--tls-cert-file", certs.ControllersTLS.CertPath(),
+		"--tls-private-key-file", certs.ControllersTLS.KeyPath(),
 		"--service-account-private-key-file", certs.Tokens.KeyPath(),
 		"--use-service-account-credentials",
 	})
@@ -111,9 +112,9 @@ func (s *ClusterServices) startK8sMaster(net *ClusterNetworking, ca *pki.Cluster
 	}
 	schedulerConfig := KubeConfig{
 		URL:        fmt.Sprintf("https://[%s]:6443", net.NodeAddress.IP.String()),
-		CACert:     ca.Services.CertPath(),
-		ClientCert: certs.SchedulerClient.CertPath(),
-		ClientKey:  certs.SchedulerClient.KeyPath(),
+		CACert:     ca.API.CertPath(),
+		ClientCert: certs.SchedulerAPI.CertPath(),
+		ClientKey:  certs.SchedulerAPI.KeyPath(),
 	}
 	schedulerConfigPath := "/scheduler.yaml"
 	err = schedulerConfig.Write(schedulerConfigPath)
@@ -131,10 +132,10 @@ func (s *ClusterServices) startK8sMaster(net *ClusterNetworking, ca *pki.Cluster
 	go s.watch(scheduler)
 }
 
-func (s *ClusterServices) startK8sNode(master net.IP, ca *pki.ClusterPKI, certs *pki.NodeCerts) {
+func (s *ClusterServices) startK8sNode(master net.IP, ca *pki.ClusterCA, certs *pki.NodeCerts) {
 	kubeletKubeConfig := KubeConfig{
 		URL:        fmt.Sprintf("https://[%s]:6443", master.String()),
-		CACert:     ca.Services.CertPath(),
+		CACert:     ca.TLS.CertPath(),
 		ClientCert: certs.API.CertPath(),
 		ClientKey:  certs.API.KeyPath(),
 	}
@@ -142,8 +143,8 @@ func (s *ClusterServices) startK8sNode(master net.IP, ca *pki.ClusterPKI, certs
 	kubeletKubeConfig.Write(kubeletKubeConfigPath)
 	kubeletConfig := KubeletConfig{
 		CACert:  ca.Kubelet.CertPath(),
-		TLSCert: certs.Service.CertPath(),
-		TLSKey:  certs.Service.KeyPath(),
+		TLSCert: certs.TLS.CertPath(),
+		TLSKey:  certs.TLS.KeyPath(),
 	}
 	kubeletConfigPath := "/kubelet.yaml"
 	kubeletConfig.Write(kubeletConfigPath)
diff --git a/pkg/pekahi/pki.go b/pkg/pekahi/pki.go
index c9e5dfad41fe6b9db0ea01ac190f3724e573d6e8..b28213b74a5739a305476d6eecf69953caece2a7 100644
--- a/pkg/pekahi/pki.go
+++ b/pkg/pekahi/pki.go
@@ -1,17 +1,26 @@
 package pekahi
 
 import (
+	"crypto/x509"
+	"os"
 	"path/filepath"
 )
 
-type PKI struct {
-	*Certificate
+type FileBundle struct {
 	Path string
 }
 
-func GetCertificate(path string) (*Certificate, error) {
+func NewFileBundle(path string) (*FileBundle, error) {
+	err := os.MkdirAll(path, 0755)
+	if err != nil {
+		return nil, err
+	}
+	return &FileBundle{path}, nil
+}
+
+func (b *FileBundle) GetCertificate(name string) (*Certificate, error) {
 	c := &Certificate{
-		IO: FileIO{path},
+		IO: FileIO{filepath.Join(b.Path, name)},
 	}
 	err := c.Load()
 	if err != nil {
@@ -24,23 +33,26 @@ func GetCertificate(path string) (*Certificate, error) {
 	return c, nil
 }
 
-func GetPKI(path string) (*PKI, error) {
-	c, err := GetCertificate(path)
+func (b *FileBundle) GetCertOrCSR(name string, template *x509.Certificate) (*Certificate, error) {
+	c, err := b.GetCertificate(name)
 	if err != nil {
 		return nil, err
 	}
-	err = c.SelfSign(NewCATemplate())
+	err = c.MakeCSR(template)
 	if err != nil {
 		return nil, err
 	}
-	return &PKI{
-		c,
-		path,
-	}, nil
+	return c, nil
 }
 
-func (p *PKI) GetCertificate(name string) *Certificate {
-	return &Certificate{
-		IO: FileIO{filepath.Join(p.Path, name)},
+func (b *FileBundle) GetCA(name string) (*Certificate, error) {
+	c, err := b.GetCertificate(name)
+	if err != nil {
+		return nil, err
 	}
+	err = c.SelfSign(NewCATemplate())
+	if err != nil {
+		return nil, err
+	}
+	return c, nil
 }
diff --git a/pkg/pki/ca.go b/pkg/pki/ca.go
index f79e8db75d1a0800b90f7cd4cc26557719c02740..4fe3116744e0d90b4ae6945d5da9f23124c4243b 100644
--- a/pkg/pki/ca.go
+++ b/pkg/pki/ca.go
@@ -1,56 +1,43 @@
 package pki
 
 import (
-	"os"
-	"path/filepath"
-
 	"forge.tedomum.net/acides/hepto/hepto/pkg/pekahi"
 )
 
-// Cluster PKI is made of three different PKIs
-type ClusterPKI struct {
+// Cluster PKI is made of three different CAs
+type ClusterCA struct {
 	// Signs services exposed over the cluster
-	Services *pekahi.PKI `json:"services"`
+	TLS *pekahi.Certificate `json:"tls"`
 	// Signs kubelet client certificates (master)
-	Kubelet *pekahi.PKI `json:"kubelet"`
+	Kubelet *pekahi.Certificate `json:"kubelet"`
 	// Signs apiserver client certificates (nodes and controller)
-	API *pekahi.PKI `json:"api"`
+	API *pekahi.Certificate `json:"api"`
 }
 
-func NewClusterPKI(path string) (*ClusterPKI, error) {
-	err := os.MkdirAll(path, 0755)
+func NewClusterCA(path string) (*ClusterCA, error) {
+	bundle, err := pekahi.NewFileBundle(path)
 	if err != nil {
 		return nil, err
 	}
-	servicesCA, err := pekahi.GetPKI(filepath.Join(path, "services"))
+	tlsCA, err := bundle.GetCA("tls")
 	if err != nil {
 		return nil, err
 	}
-	kubeletCA, err := pekahi.GetPKI(filepath.Join(path, "kubelet"))
+	kubeletCA, err := bundle.GetCA("kubelet")
 	if err != nil {
 		return nil, err
 	}
-	apiserverCA, err := pekahi.GetPKI(filepath.Join(path, "api"))
+	apiserverCA, err := bundle.GetCA("api")
 	if err != nil {
 		return nil, err
 	}
-	return &ClusterPKI{servicesCA, kubeletCA, apiserverCA}, nil
+	return &ClusterCA{tlsCA, kubeletCA, apiserverCA}, nil
 }
 
 // Merge PKI
-func (n *ClusterPKI) Merge(other *ClusterPKI) bool {
-	change := false
-	if n.API == nil && other.API != nil {
-		n.API = other.API
-		change = true
-	}
-	if n.Services == nil && other.Services != nil {
-		n.Services = other.Services
-		change = true
-	}
-	if n.Kubelet == nil && other.Kubelet != nil {
-		n.Kubelet = other.Kubelet
-		change = true
-	}
+func (n *ClusterCA) Merge(remote *ClusterCA) bool {
+	change := mergeCert(n.TLS, remote.TLS)
+	change = change || mergeCert(n.Kubelet, remote.Kubelet)
+	change = change || mergeCert(n.API, remote.API)
 	return change
 }
diff --git a/pkg/pki/master.go b/pkg/pki/master.go
index abf027b601234e5625677121218298461a575500..acebc86092d3bbab4ca8d318c7739e68daebb743 100644
--- a/pkg/pki/master.go
+++ b/pkg/pki/master.go
@@ -2,8 +2,6 @@ package pki
 
 import (
 	"net"
-	"os"
-	"path/filepath"
 
 	"forge.tedomum.net/acides/hepto/hepto/pkg/pekahi"
 )
@@ -11,88 +9,78 @@ import (
 // Master certs
 type MasterCerts struct {
 	// Certificate for exposing the apiserver
-	Service *pekahi.Certificate
+	TLS *pekahi.Certificate
 	// Certificate for signing tokens
 	Tokens *pekahi.Certificate
 	// Certificate for authenticating against kubelets
 	Kubelet *pekahi.Certificate
 	// Service certificate for the controller manager
-	Controllers *pekahi.Certificate
+	ControllersTLS *pekahi.Certificate
 	// API client certificate for the controller manager
-	ControllersClient *pekahi.Certificate
+	ControllersAPI *pekahi.Certificate
 	// API client certificate for the scheduler
-	SchedulerClient *pekahi.Certificate
+	SchedulerAPI *pekahi.Certificate
 }
 
 func NewMasterCerts(path string, ip net.IP) (*MasterCerts, error) {
-	err := os.MkdirAll(path, 0755)
+	bundle, err := pekahi.NewFileBundle(path)
 	if err != nil {
 		return nil, err
 	}
-	// Service certificate
-	serviceCert, err := pekahi.GetCertificate(filepath.Join(path, "service"))
-	if err != nil {
-		return nil, err
-	}
-	err = serviceCert.MakeCSR(pekahi.NewServerTemplate([]string{"apiserver"}, []net.IP{ip}))
+	// TLS certificate
+	tlsCert, err := bundle.GetCertOrCSR("tls",
+		pekahi.NewServerTemplate([]string{"apiserver"}, []net.IP{ip}),
+	)
 	if err != nil {
 		return nil, err
 	}
 	// Tokens key
-	tokenKey, err := pekahi.GetCertificate(filepath.Join(path, "tokens"))
+	tokenKey, err := bundle.GetCertificate("tokens")
 	if err != nil {
 		return nil, err
 	}
 	// Kubelet certificate
-	kubeletClientCert, err := pekahi.GetCertificate(filepath.Join(path, "kubelet"))
-	if err != nil {
-		return nil, err
-	}
-	err = kubeletClientCert.MakeCSR(pekahi.NewClientTemplate("apiserver", ""))
+	kubeletCert, err := bundle.GetCertOrCSR("kubelet",
+		pekahi.NewClientTemplate("apiserver", ""),
+	)
 	if err != nil {
 		return nil, err
 	}
 	// Controller manager certificate
-	controllersCert, err := pekahi.GetCertificate(filepath.Join(path, "kubelet"))
-	if err != nil {
-		return nil, err
-	}
-	err = controllersCert.MakeCSR(pekahi.NewServerTemplate([]string{"controllers"}, []net.IP{ip}))
+	controllersTLSCert, err := bundle.GetCertOrCSR("controllers-tls",
+		pekahi.NewServerTemplate([]string{"controllers"}, []net.IP{ip}),
+	)
 	if err != nil {
 		return nil, err
 	}
 	// Controller manager API client certificate
-	controllersClientCert, err := pekahi.GetCertificate(filepath.Join(path, "controllers-client"))
-	if err != nil {
-		return nil, err
-	}
-	err = controllersClientCert.MakeCSR(pekahi.NewClientTemplate("system:kube-controller-manager", ""))
+	controllersAPICert, err := bundle.GetCertOrCSR("controllers-api",
+		pekahi.NewClientTemplate("system:kube-controller-manager", ""),
+	)
 	if err != nil {
 		return nil, err
 	}
 	// Scheduler API client certificate
-	schedulerClientCert, err := pekahi.GetCertificate(filepath.Join(path, "scheduler-client"))
-	if err != nil {
-		return nil, err
-	}
-	err = schedulerClientCert.MakeCSR(pekahi.NewClientTemplate("system:kube-scheduler", ""))
+	schedulerAPICert, err := bundle.GetCertOrCSR("scheduler-api",
+		pekahi.NewClientTemplate("system:kube-scheduler", ""),
+	)
 	if err != nil {
 		return nil, err
 	}
 	return &MasterCerts{
-		Service:           serviceCert,
-		Tokens:            tokenKey,
-		Kubelet:           kubeletClientCert,
-		Controllers:       controllersCert,
-		ControllersClient: controllersClientCert,
-		SchedulerClient:   schedulerClientCert,
+		TLS:            tlsCert,
+		Tokens:         tokenKey,
+		Kubelet:        kubeletCert,
+		ControllersTLS: controllersTLSCert,
+		ControllersAPI: controllersAPICert,
+		SchedulerAPI:   schedulerAPICert,
 	}, nil
 }
 
-func (p *ClusterPKI) SignMasterCerts(m *MasterCerts) {
-	signCert(p.Services, m.Service, pekahi.NewServerTemplate(m.Service.CSR.DNSNames, m.Service.CSR.IPAddresses))
-	signCert(p.Kubelet, m.Kubelet, pekahi.NewClientTemplate(m.Kubelet.CSR.Subject.CommonName, ""))
-	signCert(p.Services, m.Controllers, pekahi.NewServerTemplate(m.Controllers.CSR.DNSNames, m.Controllers.CSR.IPAddresses))
-	signCert(p.API, m.ControllersClient, pekahi.NewClientTemplate(m.ControllersClient.CSR.Subject.CommonName, ""))
-	signCert(p.API, m.SchedulerClient, pekahi.NewClientTemplate(m.SchedulerClient.CSR.Subject.CommonName, ""))
+func (ca *ClusterCA) SignMasterCerts(m *MasterCerts) {
+	signCert(ca.TLS, m.TLS, pekahi.NewServerTemplate(m.TLS.CSR.DNSNames, m.TLS.CSR.IPAddresses))
+	signCert(ca.Kubelet, m.Kubelet, pekahi.NewClientTemplate(m.Kubelet.CSR.Subject.CommonName, ""))
+	signCert(ca.TLS, m.ControllersTLS, pekahi.NewServerTemplate(m.ControllersTLS.CSR.DNSNames, m.ControllersTLS.CSR.IPAddresses))
+	signCert(ca.API, m.ControllersAPI, pekahi.NewClientTemplate(m.ControllersAPI.CSR.Subject.CommonName, ""))
+	signCert(ca.API, m.SchedulerAPI, pekahi.NewClientTemplate(m.SchedulerAPI.CSR.Subject.CommonName, ""))
 }
diff --git a/pkg/pki/node.go b/pkg/pki/node.go
index ba2e9e053566596054362edef71b6cbe2edbd2d6..e84cae3fc9cdb827fbeebb567e6565f91538129d 100644
--- a/pkg/pki/node.go
+++ b/pkg/pki/node.go
@@ -2,8 +2,6 @@ package pki
 
 import (
 	"net"
-	"os"
-	"path/filepath"
 
 	"forge.tedomum.net/acides/hepto/hepto/pkg/pekahi"
 )
@@ -11,48 +9,44 @@ import (
 // Node certs
 type NodeCerts struct {
 	// Certificate for exposing the kubelet service
-	Service *pekahi.Certificate `json:"service"`
+	TLS *pekahi.Certificate `json:"tls"`
 	// Node certificate for accessing the apiserver
 	API *pekahi.Certificate `json:"api"`
 }
 
 func NewNodeCerts(path string, nodeName string) (*NodeCerts, error) {
-	err := os.MkdirAll(path, 0755)
+	bundle, err := pekahi.NewFileBundle(path)
 	if err != nil {
 		return nil, err
 	}
 	// Service certificate
-	serviceCert, err := pekahi.GetCertificate(filepath.Join(path, "service"))
-	if err != nil {
-		return nil, err
-	}
-	err = serviceCert.MakeCSR(pekahi.NewServerTemplate([]string{nodeName}, []net.IP{}))
+	tlsCert, err := bundle.GetCertOrCSR("tls",
+		pekahi.NewServerTemplate([]string{nodeName}, []net.IP{}),
+	)
 	if err != nil {
 		return nil, err
 	}
 	// API certificate
-	apiClientCert, err := pekahi.GetCertificate(filepath.Join(path, "api"))
-	if err != nil {
-		return nil, err
-	}
-	err = apiClientCert.MakeCSR(pekahi.NewClientTemplate("system:nodes:"+nodeName, "system:nodes"))
+	apiCert, err := bundle.GetCertOrCSR("api",
+		pekahi.NewClientTemplate("system:nodes:"+nodeName, "system:nodes"),
+	)
 	if err != nil {
 		return nil, err
 	}
 	return &NodeCerts{
-		Service: serviceCert,
-		API:     apiClientCert,
+		TLS: tlsCert,
+		API: apiCert,
 	}, nil
 }
 
 // Merge node certificates
 func (n *NodeCerts) Merge(other *NodeCerts) bool {
-	change := mergeCert(n.Service, other.Service)
+	change := mergeCert(n.TLS, other.TLS)
 	change = change || mergeCert(n.API, other.API)
 	return change
 }
 
-func (p *ClusterPKI) SignNodeCerts(name string, n *NodeCerts) {
-	signCert(p.Services, n.Service, pekahi.NewServerTemplate([]string{name}, []net.IP{}))
-	signCert(p.API, n.API, pekahi.NewClientTemplate("system:node:"+name, "system:nodes"))
+func (ca *ClusterCA) SignNodeCerts(name string, n *NodeCerts) {
+	signCert(ca.TLS, n.TLS, pekahi.NewServerTemplate([]string{name}, []net.IP{}))
+	signCert(ca.API, n.API, pekahi.NewClientTemplate("system:node:"+name, "system:nodes"))
 }
diff --git a/pkg/pki/utils.go b/pkg/pki/utils.go
index dcd9814073acafffd7723fef4bfd026199a6360d..f36ed29a8db54bb4893e38ae05933bf61b255a98 100644
--- a/pkg/pki/utils.go
+++ b/pkg/pki/utils.go
@@ -10,6 +10,15 @@ import (
 // Merge a single node or master certificate
 func mergeCert(local *pekahi.Certificate, remote *pekahi.Certificate) bool {
 	change := false
+	// Do not merge nothing
+	if remote == nil {
+		return change
+	}
+	// Create local certificate if required
+	if local == nil && remote != nil {
+		*local = pekahi.Certificate{}
+		change = true
+	}
 	// Import CSR to master for signing
 	if local.CSR == nil && remote.CSR != nil {
 		local.CSR = remote.CSR
@@ -24,10 +33,10 @@ func mergeCert(local *pekahi.Certificate, remote *pekahi.Certificate) bool {
 	return change
 }
 
-func signCert(p *pekahi.PKI, c *pekahi.Certificate, template *x509.Certificate) {
+func signCert(ca *pekahi.Certificate, c *pekahi.Certificate, template *x509.Certificate) {
 	if c.CSR != nil && c.Cert == nil {
 		logrus.Info("signing certificate ", c.CSR.Subject.String())
-		err := p.Sign(c, template)
+		err := ca.Sign(c, template)
 		if err != nil {
 			logrus.Warnf("cannot sign certificate for %s: %s", c.CSR.Subject.String(), err)
 		}