Repository: owncloud/ocis
Pull request #9656 (2024-07-19 13:22:03)

reuse node id when registering services
we now use the default nodeid when registering services. so all services started in the same binary will receive the same id.

sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [1 New Bugs](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) (required ≤ 0)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)

##   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/light_bulb-16px.png '') Catch issues before they fail your Quality Gate with our IDE extension ![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/sonarlint-16px.png '') [SonarLint](https://www.sonarsource.com/products/sonarlint/features/connected-mode/?referrer=pull-request)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [1 New Bugs](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) (required ≤ 0)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)

##   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/light_bulb-16px.png '') Catch issues before they fail your Quality Gate with our IDE extension ![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/sonarlint-16px.png '') [SonarLint](https://www.sonarsource.com/products/sonarlint/features/connected-mode/?referrer=pull-request)


kobergj: >  however that is also not collision free when two services were called e.g. auth and auth-blarg. then listing auth services would still also list all auth-blarg services.

This is why I used `/`. Any other character would also do. We just need to make sure it isn't used in service names. `-` unfortunately is.
sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [55.2% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_duplicated_lines_density&view=list) (required ≤ 50%)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [48.6% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [35.4% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [20.2% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [20.2% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=9656&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=9656&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [21.3% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=9656&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=9656)



Patch:
diff --git a/changelog/unreleased/fix-natsjskv-registry.md b/changelog/unreleased/fix-natsjskv-registry.md
index bb8838fa504..f4a08600e8e 100644
--- a/changelog/unreleased/fix-natsjskv-registry.md
+++ b/changelog/unreleased/fix-natsjskv-registry.md
@@ -2,6 +2,7 @@ Bugfix: Repair nats-js-kv registry
 
 The registry would always send traffic to only one pod. This is now fixed and load should be spread evenly. Also implements watcher method so the cache can use it.
 
+https://github.com/owncloud/ocis/pull/9656
 https://github.com/owncloud/ocis/pull/9662
 https://github.com/owncloud/ocis/pull/9654
 https://github.com/owncloud/ocis/pull/9620
diff --git a/go.mod b/go.mod
index 5cc41cc4a60..a3026307e37 100644
--- a/go.mod
+++ b/go.mod
@@ -361,7 +361,7 @@ replace github.com/egirna/icap-client => github.com/fschade/icap-client v0.0.0-2
 
 replace github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
 
-replace github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240723073728-b36ea3314b73
+replace github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240724102745-4bc93ffd7ab6
 
 // exclude the v2 line of go-sqlite3 which was released accidentally and prevents pulling in newer versions of go-sqlite3
 // see https://github.com/mattn/go-sqlite3/issues/965 for more details
diff --git a/go.sum b/go.sum
index 6fc2e08da58..e44af375b06 100644
--- a/go.sum
+++ b/go.sum
@@ -1609,8 +1609,8 @@ github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
 github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
-github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240723073728-b36ea3314b73 h1:Cgg5BVWG99INUMX43nD5jhZgNzQJyFA0MvZkctNn0Lw=
-github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240723073728-b36ea3314b73/go.mod h1:pjcozWijkNPbEtX5SIQaxEW/h8VAVZYTLx+70bmB3LY=
+github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240724102745-4bc93ffd7ab6 h1:NNXx1/XWR6Ryud6qNanwrl/JuRx2KdCW1jS2/Cf/TO8=
+github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240724102745-4bc93ffd7ab6/go.mod h1:pjcozWijkNPbEtX5SIQaxEW/h8VAVZYTLx+70bmB3LY=
 github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
diff --git a/ocis-pkg/natsjsregistry/registry.go b/ocis-pkg/natsjsregistry/registry.go
index d9dcd5f9321..b66896f168b 100644
--- a/ocis-pkg/natsjsregistry/registry.go
+++ b/ocis-pkg/natsjsregistry/registry.go
@@ -12,9 +12,9 @@ import (
 	"time"
 
 	natsjskv "github.com/go-micro/plugins/v4/store/nats-js-kv"
-	"github.com/google/uuid"
 	"github.com/nats-io/nats.go"
 	"go-micro.dev/v4/registry"
+	"go-micro.dev/v4/server"
 	"go-micro.dev/v4/store"
 	"go-micro.dev/v4/util/cmd"
 )
@@ -25,7 +25,7 @@ var (
 	_registryUsernameEnv = "MICRO_REGISTRY_AUTH_USERNAME"
 	_registryPasswordEnv = "MICRO_REGISTRY_AUTH_PASSWORD"
 
-	_serviceDelimiter = "/"
+	_serviceDelimiter = "@"
 )
 
 func init() {
@@ -90,18 +90,12 @@ func (n *storeregistry) Register(s *registry.Service, opts ...registry.RegisterO
 		o(&options)
 	}
 
-	unique := uuid.New().String()
-	if s.Metadata == nil {
-		s.Metadata = make(map[string]string)
-	}
-	s.Metadata["uuid"] = unique
-
 	b, err := json.Marshal(s)
 	if err != nil {
 		return err
 	}
 	return n.store.Write(&store.Record{
-		Key:    s.Name + _serviceDelimiter + unique,
+		Key:    s.Name + _serviceDelimiter + server.DefaultId,
 		Value:  b,
 		Expiry: options.TTL,
 	})
@@ -111,13 +105,7 @@ func (n *storeregistry) Register(s *registry.Service, opts ...registry.RegisterO
 func (n *storeregistry) Deregister(s *registry.Service, _ ...registry.DeregisterOption) error {
 	n.lock.RLock()
 	defer n.lock.RUnlock()
-
-	var unique string
-	if s.Metadata != nil {
-		unique = s.Metadata["uuid"]
-	}
-
-	return n.store.Delete(s.Name + _serviceDelimiter + unique)
+	return n.store.Delete(s.Name + _serviceDelimiter + server.DefaultId)
 }
 
 // GetService gets a specific service from the registry
diff --git a/ocis-pkg/natsjsregistry/watcher.go b/ocis-pkg/natsjsregistry/watcher.go
index f5187358f30..0dc59f48db9 100644
--- a/ocis-pkg/natsjsregistry/watcher.go
+++ b/ocis-pkg/natsjsregistry/watcher.go
@@ -1,21 +1,23 @@
 package natsjsregistry
 
 import (
+	"encoding/json"
 	"errors"
 
+	natsjskv "github.com/go-micro/plugins/v4/store/nats-js-kv"
 	"github.com/nats-io/nats.go"
 	"go-micro.dev/v4/registry"
 )
 
 // NatsWatcher is the watcher of the nats interface
 type NatsWatcher interface {
-	WatchAll(bucket string, opts ...nats.WatchOpt) (nats.KeyWatcher, error)
+	WatchAll(bucket string, opts ...nats.WatchOpt) (<-chan *natsjskv.StoreUpdate, func() error, error)
 }
 
 // Watcher is used to keep track of changes in the registry
 type Watcher struct {
-	watch   nats.KeyWatcher
-	updates <-chan nats.KeyValueEntry
+	updates <-chan *natsjskv.StoreUpdate
+	stop    func() error
 	reg     *storeregistry
 }
 
@@ -26,14 +28,14 @@ func NewWatcher(s *storeregistry) (*Watcher, error) {
 		return nil, errors.New("store does not implement watcher interface")
 	}
 
-	watcher, err := w.WatchAll("service-registry")
+	watcher, stop, err := w.WatchAll("service-registry")
 	if err != nil {
 		return nil, err
 	}
 
 	return &Watcher{
-		watch:   watcher,
-		updates: watcher.Updates(),
+		updates: watcher,
+		stop:    stop,
 		reg:     s,
 	}, nil
 }
@@ -45,30 +47,18 @@ func (w *Watcher) Next() (*registry.Result, error) {
 		return nil, errors.New("watcher stopped")
 	}
 
-	service, err := w.reg.getService(kve.Key())
-	if err != nil {
+	var svc *registry.Service
+	if err := json.Unmarshal(kve.Value.Data, svc); err != nil {
 		return nil, err
 	}
 
-	var action string
-	switch kve.Operation() {
-	default:
-		action = "create"
-	case nats.KeyValuePut:
-		action = "create"
-	case nats.KeyValueDelete:
-		action = "delete"
-	case nats.KeyValuePurge:
-		action = "delete"
-	}
-
 	return &registry.Result{
-		Service: service,
-		Action:  action,
+		Service: svc,
+		Action:  kve.Action,
 	}, nil
 }
 
 // Stop stops the watcher
 func (w *Watcher) Stop() {
-	_ = w.watch.Stop()
+	_ = w.stop()
 }
diff --git a/ocis-pkg/registry/service.go b/ocis-pkg/registry/service.go
index da80a891223..65c62e8d262 100644
--- a/ocis-pkg/registry/service.go
+++ b/ocis-pkg/registry/service.go
@@ -7,10 +7,11 @@ import (
 	"strings"
 
 	mRegistry "go-micro.dev/v4/registry"
+	"go-micro.dev/v4/server"
 	"go-micro.dev/v4/util/addr"
 )
 
-func BuildGRPCService(serviceID, uuid, address string, version string) *mRegistry.Service {
+func BuildGRPCService(serviceID, address string, version string) *mRegistry.Service {
 	var host string
 	var port int
 
@@ -28,7 +29,7 @@ func BuildGRPCService(serviceID, uuid, address string, version string) *mRegistr
 	}
 
 	node := &mRegistry.Node{
-		Id:       serviceID + "-" + uuid,
+		Id:       serviceID + "-" + server.DefaultId,
 		Address:  net.JoinHostPort(addr, fmt.Sprint(port)),
 		Metadata: make(map[string]string),
 	}
@@ -46,7 +47,7 @@ func BuildGRPCService(serviceID, uuid, address string, version string) *mRegistr
 	}
 }
 
-func BuildHTTPService(serviceID, uuid, address string, version string) *mRegistry.Service {
+func BuildHTTPService(serviceID, address string, version string) *mRegistry.Service {
 	var host string
 	var port int
 
@@ -64,7 +65,7 @@ func BuildHTTPService(serviceID, uuid, address string, version string) *mRegistr
 	}
 
 	node := &mRegistry.Node{
-		Id:       serviceID + "-" + uuid,
+		Id:       serviceID + "-" + server.DefaultId,
 		Address:  net.JoinHostPort(addr, fmt.Sprint(port)),
 		Metadata: make(map[string]string),
 	}
diff --git a/ocis-pkg/service/grpc/service.go b/ocis-pkg/service/grpc/service.go
index 3364c2194b1..6afe731e2f8 100644
--- a/ocis-pkg/service/grpc/service.go
+++ b/ocis-pkg/service/grpc/service.go
@@ -25,6 +25,7 @@ func NewServiceWithClient(client client.Client, opts ...Option) (Service, error)
 	var mServer server.Server
 	sopts := newOptions(opts...)
 	tlsConfig := &tls.Config{}
+
 	if sopts.TLSEnabled {
 		var cert tls.Certificate
 		var err error
diff --git a/ocis/pkg/command/root.go b/ocis/pkg/command/root.go
index 2edf4a750f5..6dd7136e41e 100644
--- a/ocis/pkg/command/root.go
+++ b/ocis/pkg/command/root.go
@@ -1,7 +1,10 @@
 package command
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/ocis-pkg/clihelper"
 	"github.com/owncloud/ocis/v2/ocis-pkg/config"
@@ -25,5 +28,6 @@ func Execute() error {
 		)
 	}
 
-	return app.Run(os.Args)
+	ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	return app.RunContext(ctx, os.Args)
 }
diff --git a/ocis/pkg/command/server.go b/ocis/pkg/command/server.go
index 108038ce72d..f9c3aed0703 100644
--- a/ocis/pkg/command/server.go
+++ b/ocis/pkg/command/server.go
@@ -21,7 +21,7 @@ func Server(cfg *config.Config) *cli.Command {
 		Action: func(c *cli.Context) error {
 			// Prefer the in-memory registry as the default when running in single-binary mode
 			r := runtime.New(cfg)
-			return r.Start()
+			return r.Start(c.Context)
 		},
 	}
 }
diff --git a/ocis/pkg/runtime/runtime.go b/ocis/pkg/runtime/runtime.go
index 32e6b8e1a91..49ce93c3b7e 100644
--- a/ocis/pkg/runtime/runtime.go
+++ b/ocis/pkg/runtime/runtime.go
@@ -1,6 +1,8 @@
 package runtime
 
 import (
+	"context"
+
 	"github.com/owncloud/ocis/v2/ocis-pkg/config"
 	"github.com/owncloud/ocis/v2/ocis/pkg/runtime/service"
 )
@@ -18,6 +20,6 @@ func New(cfg *config.Config) Runtime {
 }
 
 // Start rpc runtime
-func (r *Runtime) Start() error {
-	return service.Start(service.WithConfig(r.c))
+func (r *Runtime) Start(ctx context.Context) error {
+	return service.Start(ctx, service.WithConfig(r.c))
 }
diff --git a/ocis/pkg/runtime/service/service.go b/ocis/pkg/runtime/service/service.go
index d42604b7e64..311d6f7c1ea 100644
--- a/ocis/pkg/runtime/service/service.go
+++ b/ocis/pkg/runtime/service/service.go
@@ -7,10 +7,8 @@ import (
 	"net/http"
 	"net/rpc"
 	"os"
-	"os/signal"
 	"sort"
 	"strings"
-	"syscall"
 	"time"
 
 	authapp "github.com/owncloud/ocis/v2/services/auth-app/pkg/command"
@@ -96,7 +94,7 @@ type Service struct {
 // calls are done explicitly to loadFromEnv().
 // Since this is the public constructor, options need to be added, at the moment only logging options
 // are supported in order to match the running OwnCloud services structured log.
-func NewService(options ...Option) (*Service, error) {
+func NewService(ctx context.Context, options ...Option) (*Service, error) {
 	opts := NewOptions()
 
 	for _, f := range options {
@@ -109,7 +107,7 @@ func NewService(options ...Option) (*Service, error) {
 		log.Level(opts.Config.Log.Level),
 	)
 
-	globalCtx, cancelGlobal := context.WithCancel(context.Background())
+	globalCtx, cancelGlobal := context.WithCancel(ctx)
 
 	s := &Service{
 		Services:   make([]serviceFuncMap, len(_waitFuncs)),
@@ -352,19 +350,18 @@ func NewService(options ...Option) (*Service, error) {
 
 // Start a rpc service. By default, the package scope Start will run all default services to provide with a working
 // oCIS instance.
-func Start(o ...Option) error {
+func Start(ctx context.Context, o ...Option) error {
 	// Start the runtime. Most likely this was called ONLY by the `ocis server` subcommand, but since we cannot protect
 	// from the caller, the previous statement holds truth.
 
 	// prepare a new rpc Service struct.
-	s, err := NewService(o...)
+	s, err := NewService(ctx, o...)
 	if err != nil {
 		return err
 	}
 
-	// halt listens for interrupt signals and blocks.
-	halt := make(chan os.Signal, 1)
-	signal.Notify(halt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	// get a cancel function to stop the service
+	ctx, cancel := context.WithCancel(ctx)
 
 	// tolerance controls backoff cycles from the supervisor.
 	tolerance := 5
@@ -376,7 +373,7 @@ func Start(o ...Option) error {
 			if e.Type() == suture.EventTypeBackoff {
 				totalBackoff++
 				if totalBackoff == tolerance {
-					halt <- os.Interrupt
+					cancel()
 				}
 			}
 			s.Log.Info().Str("event", e.String()).Msg(fmt.Sprintf("supervisor: %v", e.Map()["supervisor_name"]))
@@ -424,8 +421,8 @@ func Start(o ...Option) error {
 	// https://pkg.go.dev/github.com/thejerf/suture/v4@v4.0.0#Supervisor
 	go s.Supervisor.ServeBackground(s.context)
 
-	// trap will block on halt channel for interruptions.
-	go trap(s, halt)
+	// trap will block on context done channel for interruptions.
+	go trap(s, ctx)
 
 	for i, service := range s.Services {
 		scheduleServiceTokens(s, service)
@@ -508,9 +505,8 @@ func (s *Service) List(_ struct{}, reply *string) error {
 
 // trap blocks on halt channel. When the runtime is interrupted it
 // signals the controller to stop any supervised process.
-func trap(s *Service, halt chan os.Signal) {
-	<-halt
-	s.cancel()
+func trap(s *Service, ctx context.Context) {
+	<-ctx.Done()
 	for sName := range s.serviceToken {
 		for i := range s.serviceToken[sName] {
 			if err := s.Supervisor.Remove(s.serviceToken[sName][i]); err != nil {
diff --git a/services/activitylog/cmd/activitylog/main.go b/services/activitylog/cmd/activitylog/main.go
index d10204f4c88..dae55b4f16f 100644
--- a/services/activitylog/cmd/activitylog/main.go
+++ b/services/activitylog/cmd/activitylog/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/activitylog/pkg/command"
 	"github.com/owncloud/ocis/v2/services/activitylog/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/activitylog/pkg/command/root.go b/services/activitylog/pkg/command/root.go
index 518d6309b36..0874c938902 100644
--- a/services/activitylog/pkg/command/root.go
+++ b/services/activitylog/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/activitylog/pkg/command/server.go b/services/activitylog/pkg/command/server.go
index e6854065c8b..232bc1aa1f7 100644
--- a/services/activitylog/pkg/command/server.go
+++ b/services/activitylog/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/cs3org/reva/v2/pkg/events"
 	"github.com/cs3org/reva/v2/pkg/events/stream"
@@ -61,12 +60,7 @@ func Server(cfg *config.Config) *cli.Command {
 			}
 
 			gr := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 
 			mtrcs := metrics.New()
 			mtrcs.BuildInfo.WithLabelValues(version.GetString()).Set(1)
@@ -145,7 +139,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/antivirus/cmd/antivirus/main.go b/services/antivirus/cmd/antivirus/main.go
index b37a1ca3edf..8f0332ad1db 100644
--- a/services/antivirus/cmd/antivirus/main.go
+++ b/services/antivirus/cmd/antivirus/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/antivirus/pkg/command"
 	"github.com/owncloud/ocis/v2/services/antivirus/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/antivirus/pkg/command/root.go b/services/antivirus/pkg/command/root.go
index 2884482748e..4683d3bc52c 100644
--- a/services/antivirus/pkg/command/root.go
+++ b/services/antivirus/pkg/command/root.go
@@ -25,5 +25,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/antivirus/pkg/command/server.go b/services/antivirus/pkg/command/server.go
index 32e2fd8b44f..0acbd873212 100644
--- a/services/antivirus/pkg/command/server.go
+++ b/services/antivirus/pkg/command/server.go
@@ -29,13 +29,8 @@ func Server(cfg *config.Config) *cli.Command {
 		Action: func(c *cli.Context) error {
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				logger = log.NewLogger(
+				ctx, cancel = context.WithCancel(c.Context)
+				logger      = log.NewLogger(
 					log.Name(cfg.Service.Name),
 					log.Level(cfg.Log.Level),
 					log.Pretty(cfg.Log.Pretty),
diff --git a/services/app-provider/cmd/app-provider/main.go b/services/app-provider/cmd/app-provider/main.go
index c4afd562c2d..1d7474d45b2 100644
--- a/services/app-provider/cmd/app-provider/main.go
+++ b/services/app-provider/cmd/app-provider/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/app-provider/pkg/command"
 	"github.com/owncloud/ocis/v2/services/app-provider/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/app-provider/pkg/command/root.go b/services/app-provider/pkg/command/root.go
index d7bbe2bb4ff..42ac00c4940 100644
--- a/services/app-provider/pkg/command/root.go
+++ b/services/app-provider/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/app-provider/pkg/command/server.go b/services/app-provider/pkg/command/server.go
index 6259e7b8498..450bb2d7abb 100644
--- a/services/app-provider/pkg/command/server.go
+++ b/services/app-provider/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -61,7 +61,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -82,7 +81,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -91,14 +90,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/app-registry/cmd/app-registry/main.go b/services/app-registry/cmd/app-registry/main.go
index 6a9d91f7d68..ddb4faa2952 100644
--- a/services/app-registry/cmd/app-registry/main.go
+++ b/services/app-registry/cmd/app-registry/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/app-registry/pkg/command"
 	"github.com/owncloud/ocis/v2/services/app-registry/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/app-registry/pkg/command/root.go b/services/app-registry/pkg/command/root.go
index 9f20d6051a3..41582af228e 100644
--- a/services/app-registry/pkg/command/root.go
+++ b/services/app-registry/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/app-registry/pkg/command/server.go b/services/app-registry/pkg/command/server.go
index 54bf5241035..b8d1a790bfb 100644
--- a/services/app-registry/pkg/command/server.go
+++ b/services/app-registry/pkg/command/server.go
@@ -37,7 +37,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -60,7 +60,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -77,7 +76,7 @@ func Server(cfg *config.Config) *cli.Command {
 				cancel()
 			})
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -86,14 +85,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/audit/cmd/audit/main.go b/services/audit/cmd/audit/main.go
index f365e874ec3..56413c60b55 100644
--- a/services/audit/cmd/audit/main.go
+++ b/services/audit/cmd/audit/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/audit/pkg/command"
 	"github.com/owncloud/ocis/v2/services/audit/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/audit/pkg/command/root.go b/services/audit/pkg/command/root.go
index abe6054a56a..c52fd880deb 100644
--- a/services/audit/pkg/command/root.go
+++ b/services/audit/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/audit/pkg/command/server.go b/services/audit/pkg/command/server.go
index 6c55e638c1f..93f945e4976 100644
--- a/services/audit/pkg/command/server.go
+++ b/services/audit/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/cs3org/reva/v2/pkg/events"
 	"github.com/cs3org/reva/v2/pkg/events/stream"
@@ -34,12 +33,7 @@ func Server(cfg *config.Config) *cli.Command {
 				gr     = run.Group{}
 				logger = logging.Configure(cfg.Service.Name, cfg.Log)
 
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
+				ctx, cancel = context.WithCancel(c.Context)
 			)
 			defer cancel()
 
@@ -60,7 +54,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Err(err).
 					Msg("Shutting down server")
 				cancel()
-				os.Exit(1)
 			})
 
 			{
diff --git a/services/auth-app/cmd/auth-app/main.go b/services/auth-app/cmd/auth-app/main.go
index 185d6eb9fd9..ada20d1afda 100644
--- a/services/auth-app/cmd/auth-app/main.go
+++ b/services/auth-app/cmd/auth-app/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/auth-app/pkg/command"
 	"github.com/owncloud/ocis/v2/services/auth-app/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/auth-app/pkg/command/root.go b/services/auth-app/pkg/command/root.go
index f1ba83b36ec..a3c2c87df05 100644
--- a/services/auth-app/pkg/command/root.go
+++ b/services/auth-app/pkg/command/root.go
@@ -31,5 +31,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/auth-app/pkg/command/server.go b/services/auth-app/pkg/command/server.go
index afb3b54dc00..323e203c73c 100644
--- a/services/auth-app/pkg/command/server.go
+++ b/services/auth-app/pkg/command/server.go
@@ -31,14 +31,14 @@ func Server(cfg *config.Config) *cli.Command {
 		Before: func(_ *cli.Context) error {
 			return configlog.ReturnFatal(parser.ParseConfig(cfg))
 		},
-		Action: func(_ *cli.Context) error {
+		Action: func(c *cli.Context) error {
 			logger := logging.Configure(cfg.Service.Name, cfg.Log)
 			traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name)
 			if err != nil {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -61,7 +61,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -82,7 +81,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -91,14 +90,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/auth-basic/cmd/auth-basic/main.go b/services/auth-basic/cmd/auth-basic/main.go
index ec5af41edf3..6235d5da74a 100644
--- a/services/auth-basic/cmd/auth-basic/main.go
+++ b/services/auth-basic/cmd/auth-basic/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/auth-basic/pkg/command"
 	"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/auth-basic/pkg/command/root.go b/services/auth-basic/pkg/command/root.go
index cb53a0a6670..46823bc174a 100644
--- a/services/auth-basic/pkg/command/root.go
+++ b/services/auth-basic/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/auth-basic/pkg/command/server.go b/services/auth-basic/pkg/command/server.go
index 3a7aaf312a7..a89ccb5326b 100644
--- a/services/auth-basic/pkg/command/server.go
+++ b/services/auth-basic/pkg/command/server.go
@@ -39,7 +39,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -74,7 +74,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -95,7 +94,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -104,14 +103,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/auth-bearer/cmd/auth-bearer/main.go b/services/auth-bearer/cmd/auth-bearer/main.go
index 8617701cfde..8cab6c04a11 100644
--- a/services/auth-bearer/cmd/auth-bearer/main.go
+++ b/services/auth-bearer/cmd/auth-bearer/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/auth-bearer/pkg/command"
 	"github.com/owncloud/ocis/v2/services/auth-bearer/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/auth-bearer/pkg/command/root.go b/services/auth-bearer/pkg/command/root.go
index c923e706fb2..c22b4f9ae3b 100644
--- a/services/auth-bearer/pkg/command/root.go
+++ b/services/auth-bearer/pkg/command/root.go
@@ -33,7 +33,7 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
 
 // SutureService allows for the accounts command to be embedded and supervised by a suture supervisor tree.
diff --git a/services/auth-bearer/pkg/command/server.go b/services/auth-bearer/pkg/command/server.go
index 5646f639914..1c8e239b3ae 100644
--- a/services/auth-bearer/pkg/command/server.go
+++ b/services/auth-bearer/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -61,7 +61,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -82,7 +81,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -91,14 +90,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/auth-machine/cmd/auth-machine/main.go b/services/auth-machine/cmd/auth-machine/main.go
index 937b0b20cdf..f2b0bdc360d 100644
--- a/services/auth-machine/cmd/auth-machine/main.go
+++ b/services/auth-machine/cmd/auth-machine/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/auth-machine/pkg/command"
 	"github.com/owncloud/ocis/v2/services/auth-machine/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/auth-machine/pkg/command/root.go b/services/auth-machine/pkg/command/root.go
index fe153cd7847..733789b9796 100644
--- a/services/auth-machine/pkg/command/root.go
+++ b/services/auth-machine/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/auth-machine/pkg/command/server.go b/services/auth-machine/pkg/command/server.go
index e19fb45f69b..0a4dcbb59b0 100644
--- a/services/auth-machine/pkg/command/server.go
+++ b/services/auth-machine/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -61,7 +61,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -82,7 +81,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -91,14 +90,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/auth-service/cmd/auth-service/main.go b/services/auth-service/cmd/auth-service/main.go
index bcc7a625ec7..70b2c3d7f91 100644
--- a/services/auth-service/cmd/auth-service/main.go
+++ b/services/auth-service/cmd/auth-service/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/auth-service/pkg/command"
 	"github.com/owncloud/ocis/v2/services/auth-service/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/auth-service/pkg/command/root.go b/services/auth-service/pkg/command/root.go
index 2fd57dd7adb..f37d4584c72 100644
--- a/services/auth-service/pkg/command/root.go
+++ b/services/auth-service/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/auth-service/pkg/command/server.go b/services/auth-service/pkg/command/server.go
index 565f6757476..58ab0dde1d8 100644
--- a/services/auth-service/pkg/command/server.go
+++ b/services/auth-service/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -61,7 +61,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -83,7 +82,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -92,14 +91,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/clientlog/cmd/clientlog/main.go b/services/clientlog/cmd/clientlog/main.go
index ce0d4a4aff9..9c6595c600c 100644
--- a/services/clientlog/cmd/clientlog/main.go
+++ b/services/clientlog/cmd/clientlog/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/clientlog/pkg/command"
 	"github.com/owncloud/ocis/v2/services/clientlog/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/clientlog/pkg/command/root.go b/services/clientlog/pkg/command/root.go
index 389caf1bb21..ca9b26166be 100644
--- a/services/clientlog/pkg/command/root.go
+++ b/services/clientlog/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/clientlog/pkg/command/server.go b/services/clientlog/pkg/command/server.go
index 29cfaf6cf8c..80261be3d32 100644
--- a/services/clientlog/pkg/command/server.go
+++ b/services/clientlog/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/cs3org/reva/v2/pkg/events"
 	"github.com/cs3org/reva/v2/pkg/events/stream"
@@ -62,12 +61,7 @@ func Server(cfg *config.Config) *cli.Command {
 			}
 
 			gr := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 
 			mtrcs := metrics.New()
 			mtrcs.BuildInfo.WithLabelValues(version.GetString()).Set(1)
@@ -118,7 +112,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/collaboration/pkg/command/root.go b/services/collaboration/pkg/command/root.go
index 31fe6db63fd..11035c80078 100644
--- a/services/collaboration/pkg/command/root.go
+++ b/services/collaboration/pkg/command/root.go
@@ -25,5 +25,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/collaboration/pkg/command/server.go b/services/collaboration/pkg/command/server.go
index 5732c55890f..799448d4cf3 100644
--- a/services/collaboration/pkg/command/server.go
+++ b/services/collaboration/pkg/command/server.go
@@ -36,12 +36,7 @@ func Server(cfg *config.Config) *cli.Command {
 			}
 
 			gr := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 			defer cancel()
 
 			// prepare components
diff --git a/services/collaboration/pkg/helpers/registration.go b/services/collaboration/pkg/helpers/registration.go
index c4967dac7d2..321a1947c16 100644
--- a/services/collaboration/pkg/helpers/registration.go
+++ b/services/collaboration/pkg/helpers/registration.go
@@ -8,7 +8,6 @@ import (
 	gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
 	rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
 	"github.com/cs3org/reva/v2/pkg/mime"
-	"github.com/gofrs/uuid"
 	"github.com/owncloud/ocis/v2/ocis-pkg/log"
 	"github.com/owncloud/ocis/v2/ocis-pkg/registry"
 	"github.com/owncloud/ocis/v2/ocis-pkg/version"
@@ -19,7 +18,7 @@ import (
 // There are no explicit requirements for the context, and it will be passed
 // without changes to the underlying RegisterService method.
 func RegisterOcisService(ctx context.Context, cfg *config.Config, logger log.Logger) error {
-	svc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name+"."+cfg.App.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+	svc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name+"."+cfg.App.Name, cfg.GRPC.Addr, version.GetString())
 	return registry.RegisterService(ctx, svc, logger)
 }
 
diff --git a/services/eventhistory/cmd/eventhistory/main.go b/services/eventhistory/cmd/eventhistory/main.go
index d2172949bc6..47eb6483c10 100644
--- a/services/eventhistory/cmd/eventhistory/main.go
+++ b/services/eventhistory/cmd/eventhistory/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/eventhistory/pkg/command"
 	"github.com/owncloud/ocis/v2/services/eventhistory/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/eventhistory/pkg/command/root.go b/services/eventhistory/pkg/command/root.go
index 683c716a30b..a1d27a56363 100644
--- a/services/eventhistory/pkg/command/root.go
+++ b/services/eventhistory/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/eventhistory/pkg/command/server.go b/services/eventhistory/pkg/command/server.go
index 197e07ae8bc..1c9146aa756 100644
--- a/services/eventhistory/pkg/command/server.go
+++ b/services/eventhistory/pkg/command/server.go
@@ -47,13 +47,8 @@ func Server(cfg *config.Config) *cli.Command {
 
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				m = metrics.New()
+				ctx, cancel = context.WithCancel(c.Context)
+				m           = metrics.New()
 			)
 
 			defer cancel()
diff --git a/services/frontend/cmd/frontend/main.go b/services/frontend/cmd/frontend/main.go
index cbdc5dac510..a3e887680f5 100644
--- a/services/frontend/cmd/frontend/main.go
+++ b/services/frontend/cmd/frontend/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/frontend/pkg/command"
 	"github.com/owncloud/ocis/v2/services/frontend/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/frontend/pkg/command/root.go b/services/frontend/pkg/command/root.go
index ab4fd045238..0e906f15ea6 100644
--- a/services/frontend/pkg/command/root.go
+++ b/services/frontend/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/frontend/pkg/command/server.go b/services/frontend/pkg/command/server.go
index a60e81153dc..cd22a4be7f1 100644
--- a/services/frontend/pkg/command/server.go
+++ b/services/frontend/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -65,7 +65,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -86,7 +85,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			httpSvc := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.HTTP.Addr, version.GetString())
+			httpSvc := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, cfg.HTTP.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, httpSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the http service")
 			}
@@ -102,14 +101,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/gateway/cmd/gateway/main.go b/services/gateway/cmd/gateway/main.go
index d22e804011a..766b15bcf99 100644
--- a/services/gateway/cmd/gateway/main.go
+++ b/services/gateway/cmd/gateway/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/gateway/pkg/command"
 	"github.com/owncloud/ocis/v2/services/gateway/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/gateway/pkg/command/root.go b/services/gateway/pkg/command/root.go
index fcf6db18db0..940a43259cf 100644
--- a/services/gateway/pkg/command/root.go
+++ b/services/gateway/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/gateway/pkg/command/server.go b/services/gateway/pkg/command/server.go
index ebbc7f7eb4a..9f556d556e7 100644
--- a/services/gateway/pkg/command/server.go
+++ b/services/gateway/pkg/command/server.go
@@ -37,7 +37,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -51,7 +51,9 @@ func Server(cfg *config.Config) *cli.Command {
 					runtime.WithRegistry(reg),
 					runtime.WithTraceProvider(traceProvider),
 				)
-
+				logger.Info().
+					Str("server", cfg.Service.Name).
+					Msg("reva runtime exited")
 				return nil
 			}, func(err error) {
 				logger.Error().
@@ -60,7 +62,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -74,10 +75,13 @@ func Server(cfg *config.Config) *cli.Command {
 			}
 
 			gr.Add(debugServer.ListenAndServe, func(_ error) {
+				logger.Info().
+					Str("server", cfg.Service.Name).
+					Msg("Shutting down debug erver")
 				cancel()
 			})
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -86,14 +90,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/graph/cmd/graph/main.go b/services/graph/cmd/graph/main.go
index 7844daa6af9..b0d9189e0a0 100644
--- a/services/graph/cmd/graph/main.go
+++ b/services/graph/cmd/graph/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/graph/pkg/command"
 	"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/graph/pkg/command/root.go b/services/graph/pkg/command/root.go
index 5c9fae28940..dd967ffbedd 100644
--- a/services/graph/pkg/command/root.go
+++ b/services/graph/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Usage:    "Serve Graph API for oCIS",
 		Commands: GetCommands(cfg),
 	})
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/graph/pkg/command/server.go b/services/graph/pkg/command/server.go
index 2c547aefeb7..7c10c330ba1 100644
--- a/services/graph/pkg/command/server.go
+++ b/services/graph/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 	"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
@@ -35,12 +34,7 @@ func Server(cfg *config.Config) *cli.Command {
 			}
 
 			gr := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 			mtrcs := metrics.New()
 
 			defer cancel()
@@ -69,7 +63,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/groups/cmd/groups/main.go b/services/groups/cmd/groups/main.go
index 2172fc84505..c1d4afadbef 100644
--- a/services/groups/cmd/groups/main.go
+++ b/services/groups/cmd/groups/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/groups/pkg/command"
 	"github.com/owncloud/ocis/v2/services/groups/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/groups/pkg/command/root.go b/services/groups/pkg/command/root.go
index fdc14e68564..ba2a991b40b 100644
--- a/services/groups/pkg/command/root.go
+++ b/services/groups/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/groups/pkg/command/server.go b/services/groups/pkg/command/server.go
index 6690ebbb118..cd6dffcb6d3 100644
--- a/services/groups/pkg/command/server.go
+++ b/services/groups/pkg/command/server.go
@@ -39,7 +39,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -74,7 +74,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -95,7 +94,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -104,14 +103,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/idm/cmd/idm/main.go b/services/idm/cmd/idm/main.go
index f30202e587d..e61c15349d0 100644
--- a/services/idm/cmd/idm/main.go
+++ b/services/idm/cmd/idm/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/idm/pkg/command"
 	"github.com/owncloud/ocis/v2/services/idm/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/idm/pkg/command/resetpw.go b/services/idm/pkg/command/resetpw.go
index 0fd204c501a..bdc37044864 100644
--- a/services/idm/pkg/command/resetpw.go
+++ b/services/idm/pkg/command/resetpw.go
@@ -40,12 +40,7 @@ func ResetPassword(cfg *config.Config) *cli.Command {
 		},
 		Action: func(c *cli.Context) error {
 			logger := logging.Configure(cfg.Service.Name, cfg.Log)
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 			return resetPassword(ctx, logger, cfg, c.String("user-name"))
diff --git a/services/idm/pkg/command/root.go b/services/idm/pkg/command/root.go
index 85134a4375d..6e6c9c4dc8f 100644
--- a/services/idm/pkg/command/root.go
+++ b/services/idm/pkg/command/root.go
@@ -31,5 +31,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/idm/pkg/command/server.go b/services/idm/pkg/command/server.go
index 048ef8d3b68..3ec90806ac6 100644
--- a/services/idm/pkg/command/server.go
+++ b/services/idm/pkg/command/server.go
@@ -40,12 +40,7 @@ func Server(cfg *config.Config) *cli.Command {
 			var (
 				gr          = run.Group{}
 				logger      = logging.Configure(cfg.Service.Name, cfg.Log)
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
+				ctx, cancel = context.WithCancel(c.Context)
 			)
 
 			defer cancel()
@@ -95,7 +90,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Err(err).
 						Msg("Shutting down server")
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/idp/cmd/idp/main.go b/services/idp/cmd/idp/main.go
index 174283c909a..de20d3a5b3c 100644
--- a/services/idp/cmd/idp/main.go
+++ b/services/idp/cmd/idp/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/idp/pkg/command"
 	"github.com/owncloud/ocis/v2/services/idp/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/idp/pkg/command/root.go b/services/idp/pkg/command/root.go
index 724620d7da3..b6707989cde 100644
--- a/services/idp/pkg/command/root.go
+++ b/services/idp/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/idp/pkg/command/server.go b/services/idp/pkg/command/server.go
index 48f431f5921..02bf30eaa0f 100644
--- a/services/idp/pkg/command/server.go
+++ b/services/idp/pkg/command/server.go
@@ -56,13 +56,8 @@ func Server(cfg *config.Config) *cli.Command {
 			}
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				metrics = metrics.New()
+				ctx, cancel = context.WithCancel(c.Context)
+				metrics     = metrics.New()
 			)
 
 			defer cancel()
@@ -95,7 +90,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/invitations/cmd/invitations/main.go b/services/invitations/cmd/invitations/main.go
index 3290c0b3065..8c9a45aeabc 100644
--- a/services/invitations/cmd/invitations/main.go
+++ b/services/invitations/cmd/invitations/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/invitations/pkg/command"
 	"github.com/owncloud/ocis/v2/services/invitations/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/invitations/pkg/command/root.go b/services/invitations/pkg/command/root.go
index aa8c993ab37..7425baf0d39 100644
--- a/services/invitations/pkg/command/root.go
+++ b/services/invitations/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/invitations/pkg/command/server.go b/services/invitations/pkg/command/server.go
index 01000c7d727..0b2b358cda6 100644
--- a/services/invitations/pkg/command/server.go
+++ b/services/invitations/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 	"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
@@ -37,13 +36,8 @@ func Server(cfg *config.Config) *cli.Command {
 
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				metrics = metrics.New(metrics.Logger(logger))
+				ctx, cancel = context.WithCancel(c.Context)
+				metrics     = metrics.New(metrics.Logger(logger))
 			)
 
 			defer cancel()
@@ -89,7 +83,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/nats/cmd/nats/main.go b/services/nats/cmd/nats/main.go
index 4b5803ac78c..347a2cc3e9e 100644
--- a/services/nats/cmd/nats/main.go
+++ b/services/nats/cmd/nats/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/nats/pkg/command"
 	"github.com/owncloud/ocis/v2/services/nats/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/nats/pkg/command/root.go b/services/nats/pkg/command/root.go
index 067bd39cd57..483d91b63c0 100644
--- a/services/nats/pkg/command/root.go
+++ b/services/nats/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/nats/pkg/command/server.go b/services/nats/pkg/command/server.go
index e118d43312b..983909d8c67 100644
--- a/services/nats/pkg/command/server.go
+++ b/services/nats/pkg/command/server.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"crypto/tls"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 
@@ -33,12 +32,7 @@ func Server(cfg *config.Config) *cli.Command {
 			logger := logging.Configure(cfg.Service.Name, cfg.Log)
 
 			gr := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -114,7 +108,6 @@ func Server(cfg *config.Config) *cli.Command {
 
 				natsServer.Shutdown()
 				cancel()
-				os.Exit(1)
 			})
 
 			return gr.Run()
diff --git a/services/notifications/cmd/notifications/main.go b/services/notifications/cmd/notifications/main.go
index 5d5752af388..73f31b88fc6 100644
--- a/services/notifications/cmd/notifications/main.go
+++ b/services/notifications/cmd/notifications/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/notifications/pkg/command"
 	"github.com/owncloud/ocis/v2/services/notifications/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/notifications/pkg/command/root.go b/services/notifications/pkg/command/root.go
index aa048245a01..2833e622edb 100644
--- a/services/notifications/pkg/command/root.go
+++ b/services/notifications/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/notifications/pkg/command/server.go b/services/notifications/pkg/command/server.go
index 55b3c7ad3c4..0b635a2a2a0 100644
--- a/services/notifications/pkg/command/server.go
+++ b/services/notifications/pkg/command/server.go
@@ -53,13 +53,7 @@ func Server(cfg *config.Config) *cli.Command {
 
 			gr := run.Group{}
 
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
-
+			ctx, cancel := context.WithCancel(c.Context)
 			defer cancel()
 
 			{
diff --git a/services/ocdav/cmd/ocdav/main.go b/services/ocdav/cmd/ocdav/main.go
index 9875027bdb5..5a6d24390f0 100644
--- a/services/ocdav/cmd/ocdav/main.go
+++ b/services/ocdav/cmd/ocdav/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/ocdav/pkg/command"
 	"github.com/owncloud/ocis/v2/services/ocdav/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/ocdav/pkg/command/root.go b/services/ocdav/pkg/command/root.go
index 5b1afc5b301..6dd8518683d 100644
--- a/services/ocdav/pkg/command/root.go
+++ b/services/ocdav/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/ocdav/pkg/command/server.go b/services/ocdav/pkg/command/server.go
index 33bb9b32264..4272419e84d 100644
--- a/services/ocdav/pkg/command/server.go
+++ b/services/ocdav/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/cs3org/reva/v2/pkg/micro/ocdav"
 	"github.com/cs3org/reva/v2/pkg/sharedconf"
@@ -36,7 +35,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -104,7 +103,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Str("server", c.Command.Name).
 					Msg("Shutting down server")
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -127,14 +125,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/ocm/cmd/ocm/main.go b/services/ocm/cmd/ocm/main.go
index 6ac3d5a5773..77a2913ba61 100644
--- a/services/ocm/cmd/ocm/main.go
+++ b/services/ocm/cmd/ocm/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/ocm/pkg/command"
 	"github.com/owncloud/ocis/v2/services/ocm/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/ocm/pkg/command/root.go b/services/ocm/pkg/command/root.go
index 7187fe52735..e524c73bd33 100644
--- a/services/ocm/pkg/command/root.go
+++ b/services/ocm/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/ocm/pkg/command/server.go b/services/ocm/pkg/command/server.go
index 1025d1ce735..6dc234fda9a 100644
--- a/services/ocm/pkg/command/server.go
+++ b/services/ocm/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -62,7 +62,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -83,12 +82,12 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
 
-			httpSvc := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.HTTP.Addr, version.GetString())
+			httpSvc := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, cfg.HTTP.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, httpSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the http service")
 			}
@@ -97,14 +96,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/ocs/cmd/ocs/main.go b/services/ocs/cmd/ocs/main.go
index a2b9021ead9..96de1a08e17 100644
--- a/services/ocs/cmd/ocs/main.go
+++ b/services/ocs/cmd/ocs/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/ocs/pkg/command"
 	"github.com/owncloud/ocis/v2/services/ocs/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/ocs/pkg/command/root.go b/services/ocs/pkg/command/root.go
index 569ff06ab40..1d2d38d8818 100644
--- a/services/ocs/pkg/command/root.go
+++ b/services/ocs/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/ocs/pkg/command/server.go b/services/ocs/pkg/command/server.go
index cdb23116331..1054ea2e280 100644
--- a/services/ocs/pkg/command/server.go
+++ b/services/ocs/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 	"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
@@ -42,13 +41,8 @@ func Server(cfg *config.Config) *cli.Command {
 
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				metrics = metrics.New()
+				ctx, cancel = context.WithCancel(c.Context)
+				metrics     = metrics.New()
 			)
 
 			defer cancel()
@@ -82,7 +76,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/policies/cmd/policies/main.go b/services/policies/cmd/policies/main.go
index db0896e4072..e774e8c4a64 100644
--- a/services/policies/cmd/policies/main.go
+++ b/services/policies/cmd/policies/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/policies/pkg/command"
 	"github.com/owncloud/ocis/v2/services/policies/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/policies/pkg/command/root.go b/services/policies/pkg/command/root.go
index 368ca7657c8..5926061c539 100644
--- a/services/policies/pkg/command/root.go
+++ b/services/policies/pkg/command/root.go
@@ -25,5 +25,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/policies/pkg/command/server.go b/services/policies/pkg/command/server.go
index 6f4729f6911..5719335ae21 100644
--- a/services/policies/pkg/command/server.go
+++ b/services/policies/pkg/command/server.go
@@ -35,13 +35,8 @@ func Server(cfg *config.Config) *cli.Command {
 		Action: func(c *cli.Context) error {
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				logger = log.NewLogger(
+				ctx, cancel = context.WithCancel(c.Context)
+				logger      = log.NewLogger(
 					log.Name(cfg.Service.Name),
 					log.Level(cfg.Log.Level),
 					log.Pretty(cfg.Log.Pretty),
diff --git a/services/postprocessing/cmd/postprocessing/main.go b/services/postprocessing/cmd/postprocessing/main.go
index ddc191e3a39..869d23db024 100644
--- a/services/postprocessing/cmd/postprocessing/main.go
+++ b/services/postprocessing/cmd/postprocessing/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/postprocessing/pkg/command"
 	"github.com/owncloud/ocis/v2/services/postprocessing/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/postprocessing/pkg/command/root.go b/services/postprocessing/pkg/command/root.go
index f4a20863206..1e9796445fb 100644
--- a/services/postprocessing/pkg/command/root.go
+++ b/services/postprocessing/pkg/command/root.go
@@ -31,5 +31,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/postprocessing/pkg/command/server.go b/services/postprocessing/pkg/command/server.go
index f5033c12341..6715a914634 100644
--- a/services/postprocessing/pkg/command/server.go
+++ b/services/postprocessing/pkg/command/server.go
@@ -36,15 +36,9 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 		Action: func(c *cli.Context) error {
 			var (
-				gr     = run.Group{}
-				logger = logging.Configure(cfg.Service.Name, cfg.Log)
-
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
+				gr          = run.Group{}
+				logger      = logging.Configure(cfg.Service.Name, cfg.Log)
+				ctx, cancel = context.WithCancel(c.Context)
 			)
 			defer cancel()
 
@@ -88,7 +82,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Str("server", "http").
 						Msg("Shutting down server")
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/proxy/cmd/proxy/main.go b/services/proxy/cmd/proxy/main.go
index 7db75b5de08..889bc6772ee 100644
--- a/services/proxy/cmd/proxy/main.go
+++ b/services/proxy/cmd/proxy/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/proxy/pkg/command"
 	"github.com/owncloud/ocis/v2/services/proxy/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/proxy/pkg/command/root.go b/services/proxy/pkg/command/root.go
index 65d32b57535..b918424d6d8 100644
--- a/services/proxy/pkg/command/root.go
+++ b/services/proxy/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/proxy/pkg/command/server.go b/services/proxy/pkg/command/server.go
index beb83ae506f..7888a69794d 100644
--- a/services/proxy/pkg/command/server.go
+++ b/services/proxy/pkg/command/server.go
@@ -5,7 +5,6 @@ import (
 	"crypto/tls"
 	"fmt"
 	"net/http"
-	"os"
 	"time"
 
 	gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
@@ -120,12 +119,7 @@ func Server(cfg *config.Config) *cli.Command {
 			m := metrics.New()
 
 			gr := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -221,7 +215,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/search/cmd/search/main.go b/services/search/cmd/search/main.go
index 70103e7bf00..1426e298d38 100644
--- a/services/search/cmd/search/main.go
+++ b/services/search/cmd/search/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/search/pkg/command"
 	"github.com/owncloud/ocis/v2/services/search/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/search/pkg/command/root.go b/services/search/pkg/command/root.go
index e850b3612fa..f0f9d05b713 100644
--- a/services/search/pkg/command/root.go
+++ b/services/search/pkg/command/root.go
@@ -31,5 +31,5 @@ func Execute(cfg *config.Config) error {
 		Usage:    "Serve search API for oCIS",
 		Commands: GetCommands(cfg),
 	})
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/search/pkg/command/server.go b/services/search/pkg/command/server.go
index 4983ab9a83b..1e823e42e4e 100644
--- a/services/search/pkg/command/server.go
+++ b/services/search/pkg/command/server.go
@@ -41,12 +41,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 			defer cancel()
 
 			mtrcs := metrics.New()
diff --git a/services/settings/cmd/settings/main.go b/services/settings/cmd/settings/main.go
index 1e21338dd80..965c6385401 100644
--- a/services/settings/cmd/settings/main.go
+++ b/services/settings/cmd/settings/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/settings/pkg/command"
 	"github.com/owncloud/ocis/v2/services/settings/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/settings/pkg/command/root.go b/services/settings/pkg/command/root.go
index 641cf491c6e..d9679de4107 100644
--- a/services/settings/pkg/command/root.go
+++ b/services/settings/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/settings/pkg/command/server.go b/services/settings/pkg/command/server.go
index bcdb7f247d7..5b11f00a56e 100644
--- a/services/settings/pkg/command/server.go
+++ b/services/settings/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 	"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
@@ -44,12 +43,7 @@ func Server(cfg *config.Config) *cli.Command {
 			}
 
 			servers := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 			defer cancel()
 
 			mtrcs := metrics.New()
@@ -79,7 +73,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Str("server", "http").
 					Msg("shutting down server")
 				cancel()
-				os.Exit(1)
 			})
 
 			// prepare a gRPC server and add it to the group run.
@@ -98,7 +91,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Str("server", "grpc").
 					Msg("shutting down server")
 				cancel()
-				os.Exit(1)
 			})
 
 			// prepare a debug server and add it to the group run.
diff --git a/services/sharing/cmd/sharing/main.go b/services/sharing/cmd/sharing/main.go
index 54e0996e3fd..c059753eb0b 100644
--- a/services/sharing/cmd/sharing/main.go
+++ b/services/sharing/cmd/sharing/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/sharing/pkg/command"
 	"github.com/owncloud/ocis/v2/services/sharing/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/sharing/pkg/command/root.go b/services/sharing/pkg/command/root.go
index fba13bf9050..4330a939b40 100644
--- a/services/sharing/pkg/command/root.go
+++ b/services/sharing/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/sharing/pkg/command/server.go b/services/sharing/pkg/command/server.go
index c0a89bfb974..5fc2bf58c5c 100644
--- a/services/sharing/pkg/command/server.go
+++ b/services/sharing/pkg/command/server.go
@@ -39,7 +39,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -77,7 +77,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -99,7 +98,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -108,14 +107,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/sse/cmd/sse/main.go b/services/sse/cmd/sse/main.go
index 8bd438f1148..4e951b92514 100644
--- a/services/sse/cmd/sse/main.go
+++ b/services/sse/cmd/sse/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/sse/pkg/command"
 	"github.com/owncloud/ocis/v2/services/sse/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/sse/pkg/command/root.go b/services/sse/pkg/command/root.go
index f3a6e4b2769..290cc700112 100644
--- a/services/sse/pkg/command/root.go
+++ b/services/sse/pkg/command/root.go
@@ -26,5 +26,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/sse/pkg/command/server.go b/services/sse/pkg/command/server.go
index ac027d606d2..06491d29062 100644
--- a/services/sse/pkg/command/server.go
+++ b/services/sse/pkg/command/server.go
@@ -37,13 +37,8 @@ func Server(cfg *config.Config) *cli.Command {
 		Action: func(c *cli.Context) error {
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				logger = log.NewLogger(
+				ctx, cancel = context.WithCancel(c.Context)
+				logger      = log.NewLogger(
 					log.Name(cfg.Service.Name),
 					log.Level(cfg.Log.Level),
 					log.Pretty(cfg.Log.Pretty),
diff --git a/services/storage-publiclink/cmd/storage-publiclink/main.go b/services/storage-publiclink/cmd/storage-publiclink/main.go
index 6d2415a0070..2207a7829eb 100644
--- a/services/storage-publiclink/cmd/storage-publiclink/main.go
+++ b/services/storage-publiclink/cmd/storage-publiclink/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/storage-publiclink/pkg/command"
 	"github.com/owncloud/ocis/v2/services/storage-publiclink/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/storage-publiclink/pkg/command/root.go b/services/storage-publiclink/pkg/command/root.go
index 9ca05cc710e..a3822e8b0e1 100644
--- a/services/storage-publiclink/pkg/command/root.go
+++ b/services/storage-publiclink/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/storage-publiclink/pkg/command/server.go b/services/storage-publiclink/pkg/command/server.go
index b0829d4728c..64551f0366e 100644
--- a/services/storage-publiclink/pkg/command/server.go
+++ b/services/storage-publiclink/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -61,7 +61,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -82,7 +81,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -91,14 +90,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/storage-shares/cmd/storage-shares/main.go b/services/storage-shares/cmd/storage-shares/main.go
index 8a8f9336beb..5a292e0ec2f 100644
--- a/services/storage-shares/cmd/storage-shares/main.go
+++ b/services/storage-shares/cmd/storage-shares/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/storage-shares/pkg/command"
 	"github.com/owncloud/ocis/v2/services/storage-shares/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/storage-shares/pkg/command/root.go b/services/storage-shares/pkg/command/root.go
index fd36affa1ef..2295b539da3 100644
--- a/services/storage-shares/pkg/command/root.go
+++ b/services/storage-shares/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/storage-shares/pkg/command/server.go b/services/storage-shares/pkg/command/server.go
index d7c186a1f12..4cc258a84a2 100644
--- a/services/storage-shares/pkg/command/server.go
+++ b/services/storage-shares/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -61,7 +61,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -82,7 +81,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -91,14 +90,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/storage-system/cmd/storage-system/main.go b/services/storage-system/cmd/storage-system/main.go
index d9242ea0571..9f2bdaa45e7 100644
--- a/services/storage-system/cmd/storage-system/main.go
+++ b/services/storage-system/cmd/storage-system/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/storage-system/pkg/command"
 	"github.com/owncloud/ocis/v2/services/storage-system/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/storage-system/pkg/command/root.go b/services/storage-system/pkg/command/root.go
index 92b6e757af6..a9786726f17 100644
--- a/services/storage-system/pkg/command/root.go
+++ b/services/storage-system/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/storage-system/pkg/command/server.go b/services/storage-system/pkg/command/server.go
index 5424a456e9e..369f2a5ad7f 100644
--- a/services/storage-system/pkg/command/server.go
+++ b/services/storage-system/pkg/command/server.go
@@ -38,7 +38,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -61,7 +61,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -82,12 +81,12 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
 
-			httpScv := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.HTTP.Addr, version.GetString())
+			httpScv := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, cfg.HTTP.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, httpScv, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the http service")
 			}
@@ -96,14 +95,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/storage-users/cmd/storage-users/main.go b/services/storage-users/cmd/storage-users/main.go
index c3c7bc7e3f0..62bf86fd007 100644
--- a/services/storage-users/cmd/storage-users/main.go
+++ b/services/storage-users/cmd/storage-users/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/storage-users/pkg/command"
 	"github.com/owncloud/ocis/v2/services/storage-users/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/storage-users/pkg/command/root.go b/services/storage-users/pkg/command/root.go
index 777ec6f2f67..d24d37a6c1c 100644
--- a/services/storage-users/pkg/command/root.go
+++ b/services/storage-users/pkg/command/root.go
@@ -32,5 +32,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/storage-users/pkg/command/server.go b/services/storage-users/pkg/command/server.go
index 8a13bc78e55..c4b41379107 100644
--- a/services/storage-users/pkg/command/server.go
+++ b/services/storage-users/pkg/command/server.go
@@ -40,7 +40,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -63,7 +63,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -93,7 +92,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -128,14 +127,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/store/cmd/store/main.go b/services/store/cmd/store/main.go
index ecf42e81938..4384dfab8c8 100644
--- a/services/store/cmd/store/main.go
+++ b/services/store/cmd/store/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/store/pkg/command"
 	"github.com/owncloud/ocis/v2/services/store/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/store/pkg/command/root.go b/services/store/pkg/command/root.go
index 8e208dba5b2..d105b28f9f8 100644
--- a/services/store/pkg/command/root.go
+++ b/services/store/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/store/pkg/command/server.go b/services/store/pkg/command/server.go
index 854bf0e7bb2..8971d75517d 100644
--- a/services/store/pkg/command/server.go
+++ b/services/store/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 
@@ -35,9 +34,6 @@ func Server(cfg *config.Config) *cli.Command {
 			if err != nil {
 				return err
 			}
-			if err != nil {
-				return err
-			}
 			cfg.GrpcClient, err = ogrpc.NewClient(
 				append(ogrpc.GetClientOptions(cfg.GRPCClientTLS), ogrpc.WithTraceProvider(traceProvider))...,
 			)
@@ -47,13 +43,8 @@ func Server(cfg *config.Config) *cli.Command {
 
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				metrics = metrics.New()
+				ctx, cancel = context.WithCancel(c.Context)
+				metrics     = metrics.New()
 			)
 
 			defer cancel()
@@ -76,7 +67,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/thumbnails/cmd/thumbnails/main.go b/services/thumbnails/cmd/thumbnails/main.go
index f0a86f58bf2..f2e8ce62676 100644
--- a/services/thumbnails/cmd/thumbnails/main.go
+++ b/services/thumbnails/cmd/thumbnails/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/thumbnails/pkg/command"
 	"github.com/owncloud/ocis/v2/services/thumbnails/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/thumbnails/pkg/command/root.go b/services/thumbnails/pkg/command/root.go
index 8ddf1c23d67..2e12c42c3bc 100644
--- a/services/thumbnails/pkg/command/root.go
+++ b/services/thumbnails/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/thumbnails/pkg/command/server.go b/services/thumbnails/pkg/command/server.go
index ba869dae9de..f95cf997815 100644
--- a/services/thumbnails/pkg/command/server.go
+++ b/services/thumbnails/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 	"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
@@ -29,7 +28,7 @@ func Server(cfg *config.Config) *cli.Command {
 		Before: func(_ *cli.Context) error {
 			return configlog.ReturnFatal(parser.ParseConfig(cfg))
 		},
-		Action: func(_ *cli.Context) error {
+		Action: func(c *cli.Context) error {
 			logger := logging.Configure(cfg.Service.Name, cfg.Log)
 
 			traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name)
@@ -43,13 +42,8 @@ func Server(cfg *config.Config) *cli.Command {
 
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				m = metrics.New()
+				ctx, cancel = context.WithCancel(c.Context)
+				m           = metrics.New()
 			)
 
 			defer cancel()
@@ -74,7 +68,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			server, err := debug.Server(
diff --git a/services/userlog/cmd/userlog/main.go b/services/userlog/cmd/userlog/main.go
index efdb7ae4b8d..58d53b06360 100644
--- a/services/userlog/cmd/userlog/main.go
+++ b/services/userlog/cmd/userlog/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/userlog/pkg/command"
 	"github.com/owncloud/ocis/v2/services/userlog/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/userlog/pkg/command/root.go b/services/userlog/pkg/command/root.go
index dd80e5acb61..8b8d1b1a5c7 100644
--- a/services/userlog/pkg/command/root.go
+++ b/services/userlog/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/userlog/pkg/command/server.go b/services/userlog/pkg/command/server.go
index a0d2e996602..71a52ca7fac 100644
--- a/services/userlog/pkg/command/server.go
+++ b/services/userlog/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/cs3org/reva/v2/pkg/events"
 	"github.com/cs3org/reva/v2/pkg/events/stream"
@@ -70,12 +69,7 @@ func Server(cfg *config.Config) *cli.Command {
 			}
 
 			gr := run.Group{}
-			ctx, cancel := func() (context.Context, context.CancelFunc) {
-				if cfg.Context == nil {
-					return context.WithCancel(context.Background())
-				}
-				return context.WithCancel(cfg.Context)
-			}()
+			ctx, cancel := context.WithCancel(c.Context)
 
 			mtrcs := metrics.New()
 			mtrcs.BuildInfo.WithLabelValues(version.GetString()).Set(1)
@@ -146,7 +140,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/users/cmd/user/main.go b/services/users/cmd/user/main.go
index cae358d3c0b..35d221577cc 100644
--- a/services/users/cmd/user/main.go
+++ b/services/users/cmd/user/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/users/pkg/command"
 	"github.com/owncloud/ocis/v2/services/users/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/users/pkg/command/root.go b/services/users/pkg/command/root.go
index e0039b1c390..8952e628aac 100644
--- a/services/users/pkg/command/root.go
+++ b/services/users/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/users/pkg/command/server.go b/services/users/pkg/command/server.go
index 100dea31b7b..92094a627a0 100644
--- a/services/users/pkg/command/server.go
+++ b/services/users/pkg/command/server.go
@@ -39,7 +39,7 @@ func Server(cfg *config.Config) *cli.Command {
 				return err
 			}
 			gr := run.Group{}
-			ctx, cancel := defineContext(cfg)
+			ctx, cancel := context.WithCancel(c.Context)
 
 			defer cancel()
 
@@ -74,7 +74,6 @@ func Server(cfg *config.Config) *cli.Command {
 					Msg("Shutting down server")
 
 				cancel()
-				os.Exit(1)
 			})
 
 			debugServer, err := debug.Server(
@@ -95,7 +94,7 @@ func Server(cfg *config.Config) *cli.Command {
 				sync.Trap(&gr, cancel)
 			}
 
-			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
+			grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Addr, version.GetString())
 			if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
 				logger.Fatal().Err(err).Msg("failed to register the grpc service")
 			}
@@ -104,14 +103,3 @@ func Server(cfg *config.Config) *cli.Command {
 		},
 	}
 }
-
-// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
-// if not, it will create a root context that can be cancelled.
-func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
-	return func() (context.Context, context.CancelFunc) {
-		if cfg.Context == nil {
-			return context.WithCancel(context.Background())
-		}
-		return context.WithCancel(cfg.Context)
-	}()
-}
diff --git a/services/web/cmd/web/main.go b/services/web/cmd/web/main.go
index 9974c37fc9a..2331767f35b 100644
--- a/services/web/cmd/web/main.go
+++ b/services/web/cmd/web/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/web/pkg/command"
 	"github.com/owncloud/ocis/v2/services/web/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/web/pkg/command/root.go b/services/web/pkg/command/root.go
index 91a648c1a2d..6f91fb895f2 100644
--- a/services/web/pkg/command/root.go
+++ b/services/web/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/web/pkg/command/server.go b/services/web/pkg/command/server.go
index a4423d0fe3a..5ba91343195 100644
--- a/services/web/pkg/command/server.go
+++ b/services/web/pkg/command/server.go
@@ -27,7 +27,7 @@ func Server(cfg *config.Config) *cli.Command {
 		Before: func(_ *cli.Context) error {
 			return configlog.ReturnFatal(parser.ParseConfig(cfg))
 		},
-		Action: func(_ *cli.Context) error {
+		Action: func(c *cli.Context) error {
 			logger := logging.Configure(cfg.Service.Name, cfg.Log)
 			traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name)
 			if err != nil {
@@ -49,13 +49,8 @@ func Server(cfg *config.Config) *cli.Command {
 
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				m = metrics.New()
+				ctx, cancel = context.WithCancel(c.Context)
+				m           = metrics.New()
 			)
 
 			defer cancel()
@@ -94,7 +89,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/webdav/cmd/webdav/main.go b/services/webdav/cmd/webdav/main.go
index 84449ec2e3e..444ea77ff83 100644
--- a/services/webdav/cmd/webdav/main.go
+++ b/services/webdav/cmd/webdav/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/webdav/pkg/command"
 	"github.com/owncloud/ocis/v2/services/webdav/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/webdav/pkg/command/root.go b/services/webdav/pkg/command/root.go
index 8a1d46b23ac..e2d6cf9f7fc 100644
--- a/services/webdav/pkg/command/root.go
+++ b/services/webdav/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/webdav/pkg/command/server.go b/services/webdav/pkg/command/server.go
index 88983e1de72..d7ed386242d 100644
--- a/services/webdav/pkg/command/server.go
+++ b/services/webdav/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 	"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
@@ -44,13 +43,8 @@ func Server(cfg *config.Config) *cli.Command {
 
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				metrics = metrics.New()
+				ctx, cancel = context.WithCancel(c.Context)
+				metrics     = metrics.New()
 			)
 
 			defer cancel()
@@ -84,7 +78,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/services/webfinger/cmd/webfinger/main.go b/services/webfinger/cmd/webfinger/main.go
index f370d1c9e9e..112094e8a4d 100644
--- a/services/webfinger/cmd/webfinger/main.go
+++ b/services/webfinger/cmd/webfinger/main.go
@@ -1,14 +1,19 @@
 package main
 
 import (
+	"context"
 	"os"
+	"os/signal"
+	"syscall"
 
 	"github.com/owncloud/ocis/v2/services/webfinger/pkg/command"
 	"github.com/owncloud/ocis/v2/services/webfinger/pkg/config/defaults"
 )
 
 func main() {
-	if err := command.Execute(defaults.DefaultConfig()); err != nil {
+	cfg := defaults.DefaultConfig()
+	cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
+	if err := command.Execute(cfg); err != nil {
 		os.Exit(1)
 	}
 }
diff --git a/services/webfinger/pkg/command/root.go b/services/webfinger/pkg/command/root.go
index 4d553a26559..a6d30c53cfa 100644
--- a/services/webfinger/pkg/command/root.go
+++ b/services/webfinger/pkg/command/root.go
@@ -30,5 +30,5 @@ func Execute(cfg *config.Config) error {
 		Commands: GetCommands(cfg),
 	})
 
-	return app.Run(os.Args)
+	return app.RunContext(cfg.Context, os.Args)
 }
diff --git a/services/webfinger/pkg/command/server.go b/services/webfinger/pkg/command/server.go
index 2d8c4b8e45c..0ba9cbe1298 100644
--- a/services/webfinger/pkg/command/server.go
+++ b/services/webfinger/pkg/command/server.go
@@ -3,7 +3,6 @@ package command
 import (
 	"context"
 	"fmt"
-	"os"
 
 	"github.com/oklog/run"
 	"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
@@ -38,13 +37,8 @@ func Server(cfg *config.Config) *cli.Command {
 
 			var (
 				gr          = run.Group{}
-				ctx, cancel = func() (context.Context, context.CancelFunc) {
-					if cfg.Context == nil {
-						return context.WithCancel(context.Background())
-					}
-					return context.WithCancel(cfg.Context)
-				}()
-				m = metrics.New(metrics.Logger(logger))
+				ctx, cancel = context.WithCancel(c.Context)
+				m           = metrics.New(metrics.Logger(logger))
 			)
 
 			defer cancel()
@@ -97,7 +91,6 @@ func Server(cfg *config.Config) *cli.Command {
 						Msg("Shutting down server")
 
 					cancel()
-					os.Exit(1)
 				})
 			}
 
diff --git a/vendor/github.com/go-micro/plugins/v4/store/nats-js-kv/nats.go b/vendor/github.com/go-micro/plugins/v4/store/nats-js-kv/nats.go
index 4ffba417a9b..280a6da1314 100644
--- a/vendor/github.com/go-micro/plugins/v4/store/nats-js-kv/nats.go
+++ b/vendor/github.com/go-micro/plugins/v4/store/nats-js-kv/nats.go
@@ -335,22 +335,63 @@ func (n *natsStore) String() string {
 	return "NATS JetStream KeyValueStore"
 }
 
+// StoreUpdate is the update type for the store.
+type StoreUpdate struct {
+	Value  KeyValueEnvelope
+	Action string
+}
+
 // WatchAll exposes the watcher interface from the underlying JetStreamContext.
-func (n *natsStore) WatchAll(bucket string, opts ...nats.WatchOpt) (nats.KeyWatcher, error) {
+func (n *natsStore) WatchAll(bucket string, opts ...nats.WatchOpt) (<-chan *StoreUpdate, func() error, error) {
 	if bucket == "" {
-		return nil, errors.New("multi bucket watching is not supported")
+		return nil, nil, errors.New("multi bucket watching is not supported")
 	}
 
 	if err := n.initConn(); err != nil {
-		return nil, err
+		return nil, nil, err
 	}
 
 	b, err := n.js.KeyValue(bucket)
 	if err != nil {
-		return nil, errors.Wrap(err, "Failed to get bucket")
+		return nil, nil, errors.Wrap(err, "Failed to get bucket")
 	}
 
-	return b.WatchAll(opts...)
+	w, err := b.WatchAll(opts...)
+	if err != nil {
+		return nil, nil, errors.Wrap(err, "Failed to watch bucket")
+	}
+
+	ch := make(chan *StoreUpdate)
+	go func() {
+		for u := range w.Updates() {
+			if u == nil {
+				continue
+			}
+
+			var action string
+			switch u.Operation() {
+			default:
+				action = u.Operation().String()
+			case nats.KeyValuePut:
+				action = "create"
+			case nats.KeyValueDelete:
+				action = "delete"
+			case nats.KeyValuePurge:
+				action = "delete"
+			}
+
+			var kv KeyValueEnvelope
+			if err := json.Unmarshal(u.Value(), &kv); err != nil {
+				continue
+			}
+			ch <- &StoreUpdate{
+				Value:  kv,
+				Action: action,
+			}
+		}
+	}()
+
+	return ch, w.Stop, nil
 }
 
 // thread safe way to initialize the connection.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 4b51469baf0..9296c29054d 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -963,7 +963,7 @@ github.com/go-micro/plugins/v4/server/http
 # github.com/go-micro/plugins/v4/store/nats-js v1.2.1-0.20231129143103-d72facc652f0
 ## explicit; go 1.21
 github.com/go-micro/plugins/v4/store/nats-js
-# github.com/go-micro/plugins/v4/store/nats-js-kv v0.0.0-20231226212146-94a49ba3e06e => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240723073728-b36ea3314b73
+# github.com/go-micro/plugins/v4/store/nats-js-kv v0.0.0-20231226212146-94a49ba3e06e => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240724102745-4bc93ffd7ab6
 ## explicit; go 1.21
 github.com/go-micro/plugins/v4/store/nats-js-kv
 # github.com/go-micro/plugins/v4/store/redis v1.2.1
@@ -2422,4 +2422,4 @@ stash.kopano.io/kgol/rndm
 # github.com/studio-b12/gowebdav => github.com/aduffeck/gowebdav v0.0.0-20231215102054-212d4a4374f6
 # github.com/egirna/icap-client => github.com/fschade/icap-client v0.0.0-20240123094924-5af178158eaf
 # github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
-# github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240723073728-b36ea3314b73
+# github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240724102745-4bc93ffd7ab6


Test patch:
diff --git a/services/graph/pkg/service/v0/graph_suite_test.go b/services/graph/pkg/service/v0/graph_suite_test.go
index 70dfcce1450..8446bc9b690 100644
--- a/services/graph/pkg/service/v0/graph_suite_test.go
+++ b/services/graph/pkg/service/v0/graph_suite_test.go
@@ -12,7 +12,7 @@ import (
 
 func init() {
 	r := registry.GetRegistry(registry.Inmemory())
-	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
+	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "")
 	service.Nodes = []*mRegistry.Node{{
 		Address: "any",
 	}}
diff --git a/services/notifications/pkg/service/notification_suite_test.go b/services/notifications/pkg/service/notification_suite_test.go
index 7f282054fb6..e045e439814 100644
--- a/services/notifications/pkg/service/notification_suite_test.go
+++ b/services/notifications/pkg/service/notification_suite_test.go
@@ -12,7 +12,7 @@ import (
 
 func init() {
 	r := registry.GetRegistry(registry.Inmemory())
-	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
+	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "")
 	service.Nodes = []*mRegistry.Node{{
 		Address: "any",
 	}}
diff --git a/services/search/pkg/search/search_suite_test.go b/services/search/pkg/search/search_suite_test.go
index 9422179fc53..ace85d9294c 100644
--- a/services/search/pkg/search/search_suite_test.go
+++ b/services/search/pkg/search/search_suite_test.go
@@ -12,7 +12,7 @@ import (
 
 func init() {
 	r := registry.GetRegistry(registry.Inmemory())
-	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
+	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "")
 	service.Nodes = []*mRegistry.Node{{
 		Address: "any",
 	}}
diff --git a/services/storage-users/pkg/task/task_suite_test.go b/services/storage-users/pkg/task/task_suite_test.go
index ac0c8a44b9d..38372778085 100644
--- a/services/storage-users/pkg/task/task_suite_test.go
+++ b/services/storage-users/pkg/task/task_suite_test.go
@@ -12,7 +12,7 @@ import (
 
 func init() {
 	r := registry.GetRegistry(registry.Inmemory())
-	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
+	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "")
 	service.Nodes = []*mRegistry.Node{{
 		Address: "any",
 	}}
diff --git a/services/userlog/pkg/service/service_suit_test.go b/services/userlog/pkg/service/service_suit_test.go
index 9da9654d4e9..d049672b76a 100644
--- a/services/userlog/pkg/service/service_suit_test.go
+++ b/services/userlog/pkg/service/service_suit_test.go
@@ -12,7 +12,7 @@ import (
 
 func init() {
 	r := registry.GetRegistry(registry.Inmemory())
-	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
+	service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "")
 	service.Nodes = []*mRegistry.Node{{
 		Address: "any",
 	}}