installer: create namespaces with kube client
diff --git a/core/installer/Makefile b/core/installer/Makefile
index 1bc4e06..9c14dd1 100644
--- a/core/installer/Makefile
+++ b/core/installer/Makefile
@@ -11,19 +11,19 @@
 	go build -o pcloud cmd/*.go
 
 bootstrap:
-	./pcloud bootstrap --kubeconfig=../../priv/kubeconfig --charts-dir=../../charts --admin-pub-key=/Users/lekva/.ssh/id_rsa.pub --soft-serve-ip=192.168.0.211 --storage-dir=/pcloud-storage/longhorn
+	./pcloud --kubeconfig=../../priv/kubeconfig bootstrap --charts-dir=../../charts --admin-pub-key=/Users/lekva/.ssh/id_rsa.pub --soft-serve-ip=192.168.0.211 --storage-dir=/pcloud-storage/longhorn
 
 create_env:
-	./pcloud create-env --admin-priv-key=/Users/lekva/.ssh/id_rsa --name=lekva --ip=192.168.0.211 --admin-username=gio
+	./pcloud --kubeconfig=../../priv/kubeconfig create-env --admin-priv-key=/Users/lekva/.ssh/id_rsa --name=lekva --ip=192.168.0.211 --admin-username=gio
 
 rpuppy:
-	./pcloud install --ssh-key=/Users/lekva/.ssh/id_rsa --app=rpuppy --repo-addr=ssh://localhost:2222/lekva
+	./pcloud --kubeconfig=../../priv/kubeconfig install --ssh-key=/Users/lekva/.ssh/id_rsa --app=rpuppy --repo-addr=ssh://localhost:2222/lekva
 
 appmanager:
-	./pcloud appmanager --ssh-key=/Users/lekva/.ssh/id_rsa --repo-addr=ssh://192.168.0.211/lekva --port=9090
+	./pcloud --kubeconfig=../../priv/kubeconfig appmanager --ssh-key=/Users/lekva/.ssh/id_rsa --repo-addr=ssh://192.168.0.211/qwe --port=9090
 
 welc:
-	./pcloud welcome --ssh-key=/Users/lekva/.ssh/id_rsa --repo-addr=ssh://192.168.0.211/lekva --port=9090
+	./pcloud --kubeconfig=../../priv/kubeconfig welcome --ssh-key=/Users/lekva/.ssh/id_rsa --repo-addr=ssh://192.168.0.211/lekva --port=9090
 
 
 
diff --git a/core/installer/app.go b/core/installer/app.go
index 2b94770..8d79c58 100644
--- a/core/installer/app.go
+++ b/core/installer/app.go
@@ -13,10 +13,11 @@
 var valuesTmpls embed.FS
 
 type App struct {
-	Name      string
-	Templates []*template.Template
-	Schema    string
-	Readme    *template.Template
+	Name       string
+	Namespaces []string
+	Templates  []*template.Template
+	Schema     string
+	Readme     *template.Template
 }
 
 type AppRepository interface {
@@ -87,6 +88,7 @@
 	}
 	return App{
 		"ingress-private",
+		[]string{"ingress-private"},
 		[]*template.Template{
 			tmpls.Lookup("ingress-private.yaml"),
 		},
@@ -102,6 +104,7 @@
 	}
 	return App{
 		"certificate-issuer-private",
+		[]string{},
 		[]*template.Template{
 			tmpls.Lookup("certificate-issuer-private.yaml"),
 		},
@@ -117,6 +120,7 @@
 	}
 	return App{
 		"certificate-issuer-public",
+		[]string{},
 		[]*template.Template{
 			tmpls.Lookup("certificate-issuer-public.yaml"),
 		},
@@ -132,6 +136,7 @@
 	}
 	return App{
 		"core-auth",
+		[]string{"core-auth"},
 		[]*template.Template{
 			tmpls.Lookup("core-auth-storage.yaml"),
 			tmpls.Lookup("core-auth.yaml"),
@@ -148,6 +153,7 @@
 	}
 	return App{
 		"vaultwarden",
+		[]string{"app-vaultwarden"},
 		[]*template.Template{
 			tmpls.Lookup("vaultwarden.yaml"),
 		},
@@ -163,6 +169,7 @@
 	}
 	return App{
 		"matrix",
+		[]string{"app-matrix"},
 		[]*template.Template{
 			tmpls.Lookup("matrix-storage.yaml"),
 			tmpls.Lookup("matrix.yaml"),
@@ -179,6 +186,7 @@
 	}
 	return App{
 		"pihole",
+		[]string{"app-pihole"},
 		[]*template.Template{
 			tmpls.Lookup("pihole.yaml"),
 		},
@@ -194,6 +202,7 @@
 	}
 	return App{
 		"maddy",
+		[]string{"app-maddy"},
 		[]*template.Template{
 			tmpls.Lookup("maddy.yaml"),
 		},
@@ -209,6 +218,7 @@
 	}
 	return App{
 		"qbittorrent",
+		[]string{"app-qbittorrent"},
 		[]*template.Template{
 			tmpls.Lookup("qbittorrent.yaml"),
 		},
@@ -224,6 +234,7 @@
 	}
 	return App{
 		"jellyfin",
+		[]string{"app-jellyfin"},
 		[]*template.Template{
 			tmpls.Lookup("jellyfin.yaml"),
 		},
@@ -239,6 +250,7 @@
 	}
 	return App{
 		"rpuppy",
+		[]string{"app-rpuppy"},
 		[]*template.Template{
 			tmpls.Lookup("rpuppy.yaml"),
 		},
@@ -254,6 +266,7 @@
 	}
 	return App{
 		"headscale",
+		[]string{"app-headscale"},
 		[]*template.Template{
 			tmpls.Lookup("headscale.yaml"),
 		},
@@ -269,6 +282,7 @@
 	}
 	return App{
 		"tailscale-proxy",
+		[]string{"tailscale-proxy"},
 		[]*template.Template{
 			tmpls.Lookup("tailscale-proxy.yaml"),
 		},
@@ -284,6 +298,7 @@
 	}
 	return App{
 		"metallb-config-env",
+		[]string{"metallb-config"},
 		[]*template.Template{
 			tmpls.Lookup("metallb-config-env.yaml"),
 		},
@@ -299,6 +314,7 @@
 	}
 	return App{
 		"env-manager",
+		[]string{"env-manager"},
 		[]*template.Template{
 			tmpls.Lookup("env-manager.yaml"),
 		},
@@ -314,6 +330,7 @@
 	}
 	return App{
 		"welcome",
+		[]string{"app-welcome"},
 		[]*template.Template{
 			tmpls.Lookup("welcome.yaml"),
 		},
@@ -329,6 +346,7 @@
 	}
 	return App{
 		"ingress-public",
+		[]string{"ingress-public"},
 		[]*template.Template{
 			tmpls.Lookup("ingress-public.yaml"),
 		},
@@ -344,6 +362,7 @@
 	}
 	return App{
 		"cert-manager",
+		[]string{"cert-manager"},
 		[]*template.Template{
 			tmpls.Lookup("cert-manager.yaml"),
 		},
@@ -359,6 +378,7 @@
 	}
 	return App{
 		"cert-manager-webhook-gandi",
+		[]string{},
 		[]*template.Template{
 			tmpls.Lookup("cert-manager-webhook-gandi.yaml"),
 		},
@@ -374,6 +394,7 @@
 	}
 	return App{
 		"cert-manager-webhook-gandi-role",
+		[]string{},
 		[]*template.Template{
 			tmpls.Lookup("cert-manager-webhook-gandi-role.yaml"),
 		},
@@ -389,6 +410,7 @@
 	}
 	return App{
 		"csi-driver-smb",
+		[]string{"csi-driver-smb"},
 		[]*template.Template{
 			tmpls.Lookup("csi-driver-smb.yaml"),
 		},
@@ -404,6 +426,7 @@
 	}
 	return App{
 		"resource-renderer-controller",
+		[]string{"rr-controller"},
 		[]*template.Template{
 			tmpls.Lookup("resource-renderer-controller.yaml"),
 		},
@@ -419,6 +442,7 @@
 	}
 	return App{
 		"headscale-controller",
+		[]string{"headscale-controller"},
 		[]*template.Template{
 			tmpls.Lookup("headscale-controller.yaml"),
 		},
diff --git a/core/installer/app_manager.go b/core/installer/app_manager.go
index 5c1822a..d2feccc 100644
--- a/core/installer/app_manager.go
+++ b/core/installer/app_manager.go
@@ -12,26 +12,19 @@
 const kustomizationFileName = "kustomization.yaml"
 
 type AppManager struct {
-	repoIO RepoIO
+	repoIO    RepoIO
+	nsCreator NamespaceCreator
 }
 
-func NewAppManager(repoIO RepoIO) (*AppManager, error) {
+func NewAppManager(repoIO RepoIO, nsCreator NamespaceCreator) (*AppManager, error) {
 	return &AppManager{
 		repoIO,
+		nsCreator,
 	}, nil
 }
 
 func (m *AppManager) Config() (Config, error) {
-	configF, err := m.repoIO.Reader(configFileName)
-	if err != nil {
-		return Config{}, err
-	}
-	defer configF.Close()
-	config, err := ReadConfig(configF)
-	if err != nil {
-		return Config{}, err
-	}
-	return config, nil
+	return m.repoIO.ReadConfig()
 }
 
 func (m *AppManager) AppConfig(name string) (map[string]any, error) {
@@ -49,11 +42,24 @@
 	return cfg, err
 }
 
-func (m *AppManager) Install(app App, config map[string]any) error {
+func (m *AppManager) Install(app App, ns NamespaceGenerator, config map[string]any) error {
 	// if err := m.repoIO.Fetch(); err != nil {
 	// 	return err
 	// }
-	globalConfig, err := m.Config()
+	namespaces := make([]string, len(app.Namespaces))
+	for i, n := range app.Namespaces {
+		var err error
+		namespaces[i], err = ns.Generate(n)
+		if err != nil {
+			return err
+		}
+	}
+	for _, n := range namespaces {
+		if err := m.nsCreator.Create(n); err != nil {
+			return err
+		}
+	}
+	globalConfig, err := m.repoIO.ReadConfig()
 	if err != nil {
 		return err
 	}
@@ -61,5 +67,10 @@
 		"Global": globalConfig.Values,
 		"Values": config,
 	}
+	if len(namespaces) > 0 {
+		all["Release"] = map[string]any{
+			"Namespace": namespaces[0],
+		}
+	}
 	return m.repoIO.InstallApp(app, "apps", all)
 }
diff --git a/core/installer/cmd/app_manager.go b/core/installer/cmd/app_manager.go
index 73e2311..cff270e 100644
--- a/core/installer/cmd/app_manager.go
+++ b/core/installer/cmd/app_manager.go
@@ -68,7 +68,14 @@
 	if err != nil {
 		return err
 	}
-	m, err := installer.NewAppManager(installer.NewRepoIO(repo, signer))
+	kube, err := installer.NewOutOfClusterNamespaceCreator(rootFlags.kubeConfig)
+	if err != nil {
+		return err
+	}
+	m, err := installer.NewAppManager(
+		installer.NewRepoIO(repo, signer),
+		kube,
+	)
 	if err != nil {
 		return err
 	}
@@ -173,7 +180,7 @@
 	}
 	var resp rendered
 	resp.Readme = readme.String()
-	for _, tmpl := range a.Templates {
+	for _, tmpl := range a.Templates { // TODO(giolekva): deduplicate with Install
 		var f bytes.Buffer
 		if err := tmpl.Execute(&f, all); err != nil {
 			fmt.Printf("%+v\n", all)
@@ -207,7 +214,15 @@
 	if err != nil {
 		return err
 	}
-	if err := s.m.Install(*a, values); err != nil {
+	config, err := s.m.Config()
+	if err != nil {
+		return err
+	}
+	nsGen := installer.NewCombine(
+		installer.NewPrefixGenerator(config.Values.Id+"-"),
+		installer.NewRandomSuffixGenerator(3),
+	)
+	if err := s.m.Install(*a, nsGen, values); err != nil {
 		return err
 	}
 	return c.String(http.StatusOK, "Installed")
diff --git a/core/installer/cmd/bootstrap.go b/core/installer/cmd/bootstrap.go
index 135b6b4..ffff0ba 100644
--- a/core/installer/cmd/bootstrap.go
+++ b/core/installer/cmd/bootstrap.go
@@ -86,11 +86,11 @@
 	if err := installLonghorn(); err != nil {
 		return err
 	}
-	time.Sleep(5 * time.Minute) // TODO(giolekva): implement proper wait
+	time.Sleep(2 * time.Minute) // TODO(giolekva): implement proper wait
 	if err := installSoftServe(bootstrapJobKeys.Public); err != nil {
 		return err
 	}
-	time.Sleep(2 * time.Minute) // TODO(giolekva): implement proper wait
+	time.Sleep(1 * time.Minute) // TODO(giolekva): implement proper wait
 	ss, err := soft.NewClient(bootstrapFlags.softServeIP, 22, []byte(bootstrapJobKeys.Private), log.Default())
 	if err != nil {
 		return err
@@ -113,16 +113,20 @@
 	global := map[string]any{
 		"PCloudEnvName": bootstrapFlags.pcloudEnvName,
 	}
-	if err := installInfrastructureServices(repoIO, global); err != nil {
+	nsCreator, err := newNSCreator()
+	if err != nil {
 		return err
 	}
-	if err := installEnvManager(ss, repoIO, global); err != nil {
+	nsGen := installer.NewPrefixGenerator("pcloud-")
+	if err := installInfrastructureServices(repoIO, nsGen, nsCreator, global); err != nil {
+		return err
+	}
+	if err := installEnvManager(ss, repoIO, nsGen, nsCreator, global); err != nil {
 		return err
 	}
 	if ss.RemovePublicKey("admin", bootstrapJobKeys.Public); err != nil {
 		return err
 	}
-
 	return nil
 }
 
@@ -372,16 +376,33 @@
 	return nil
 }
 
-func installInfrastructureServices(repo installer.RepoIO, global map[string]any) error {
-	values := map[string]any{
-		"Global": global,
-	}
+func installInfrastructureServices(repo installer.RepoIO, nsGen installer.NamespaceGenerator, nsCreator installer.NamespaceCreator, global map[string]any) error {
 	appRepo := installer.NewInMemoryAppRepository(installer.CreateAllApps())
 	install := func(name string) error {
 		app, err := appRepo.Find(name)
 		if err != nil {
 			return err
 		}
+		namespaces := make([]string, len(app.Namespaces))
+		for i, n := range app.Namespaces {
+			namespaces[i], err = nsGen.Generate(n)
+			if err != nil {
+				return err
+			}
+		}
+		for _, n := range namespaces {
+			if err := nsCreator.Create(n); err != nil {
+				return err
+			}
+		}
+		values := map[string]any{
+			"Global": global,
+		}
+		if len(namespaces) > 0 {
+			values["Release"] = map[string]any{
+				"Namespace": namespaces[0],
+			}
+		}
 		return repo.InstallApp(*app, "infrastructure", values)
 	}
 	appsToInstall := []string{
@@ -445,7 +466,7 @@
 	return nil
 }
 
-func installEnvManager(ss *soft.Client, repo installer.RepoIO, global map[string]any) error {
+func installEnvManager(ss *soft.Client, repo installer.RepoIO, nsGen installer.NamespaceGenerator, nsCreator installer.NamespaceCreator, global map[string]any) error {
 	keys, err := installer.NewSSHKeyPair()
 	if err != nil {
 		return err
@@ -458,16 +479,31 @@
 		return err
 	}
 	appRepo := installer.NewInMemoryAppRepository(installer.CreateAllApps())
-	envManager, err := appRepo.Find("env-manager")
+	app, err := appRepo.Find("env-manager")
 	if err != nil {
 		return err
 	}
-	return repo.InstallApp(*envManager, "infrastructure", map[string]any{
+	namespaces := make([]string, len(app.Namespaces))
+	for i, n := range app.Namespaces {
+		namespaces[i], err = nsGen.Generate(n)
+		if err != nil {
+			return err
+		}
+	}
+	for _, n := range namespaces {
+		if err := nsCreator.Create(n); err != nil {
+			return err
+		}
+	}
+	return repo.InstallApp(*app, "infrastructure", map[string]any{
 		"Global": global,
 		"Values": map[string]any{
 			"RepoIP":        bootstrapFlags.softServeIP,
 			"SSHPrivateKey": keys.Private,
 		},
+		"Release": map[string]any{
+			"Namespace": namespaces[0],
+		},
 	})
 }
 
diff --git a/core/installer/cmd/env_manager.go b/core/installer/cmd/env_manager.go
index 647850d..a74369d 100644
--- a/core/installer/cmd/env_manager.go
+++ b/core/installer/cmd/env_manager.go
@@ -64,10 +64,15 @@
 		return err
 	}
 	repoIO := installer.NewRepoIO(repo, ss.Signer)
+	nsCreator, err := newNSCreator()
+	if err != nil {
+		return err
+	}
 	s := welcome.NewEnvServer(
 		envManagerFlags.port,
 		ss,
 		repoIO,
+		nsCreator,
 	)
 	s.Start()
 	return nil
diff --git a/core/installer/cmd/kube.go b/core/installer/cmd/kube.go
new file mode 100644
index 0000000..995aec3
--- /dev/null
+++ b/core/installer/cmd/kube.go
@@ -0,0 +1,13 @@
+package main
+
+import (
+	"github.com/giolekva/pcloud/core/installer"
+)
+
+func newNSCreator() (installer.NamespaceCreator, error) {
+	if rootFlags.kubeConfig != "" {
+		return installer.NewOutOfClusterNamespaceCreator(rootFlags.kubeConfig)
+	} else {
+		return installer.NewInClusterNamespaceCreator()
+	}
+}
diff --git a/core/installer/cmd/welcome.go b/core/installer/cmd/welcome.go
index 3b834b0..6d2d7e0 100644
--- a/core/installer/cmd/welcome.go
+++ b/core/installer/cmd/welcome.go
@@ -63,9 +63,14 @@
 		InsecureSkipTLS: true,
 		Progress:        os.Stdout,
 	})
+	nsCreator, err := newNSCreator()
+	if err != nil {
+		return err
+	}
 	s := welcome.NewServer(
 		welcomeFlags.port,
 		installer.NewRepoIO(repo, auth.Signer),
+		nsCreator,
 	)
 	s.Start()
 	return nil
diff --git a/core/installer/kube.go b/core/installer/kube.go
new file mode 100644
index 0000000..bf22f40
--- /dev/null
+++ b/core/installer/kube.go
@@ -0,0 +1,58 @@
+package installer
+
+import (
+	"context"
+	"fmt"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/rest"
+	"k8s.io/client-go/tools/clientcmd"
+)
+
+type NamespaceCreator interface {
+	Create(name string) error
+}
+
+type realNamespaceCreator struct {
+	clientset *kubernetes.Clientset
+}
+
+func NewOutOfClusterNamespaceCreator(kubeconfig string) (NamespaceCreator, error) {
+	config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
+	if err != nil {
+		return nil, err
+	}
+	clientset, err := kubernetes.NewForConfig(config)
+	if err != nil {
+		return nil, err
+	}
+	return &realNamespaceCreator{clientset}, nil
+}
+
+func NewInClusterNamespaceCreator() (NamespaceCreator, error) {
+	config, err := rest.InClusterConfig()
+	if err != nil {
+		panic(err.Error())
+	}
+	clientset, err := kubernetes.NewForConfig(config)
+	if err != nil {
+		return nil, err
+	}
+	return &realNamespaceCreator{clientset}, nil
+}
+
+func (n *realNamespaceCreator) Create(name string) error {
+	_, err := n.clientset.CoreV1().Namespaces().Create(context.Background(), &corev1.Namespace{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       " ",
+			APIVersion: "",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Name: name,
+		},
+	}, metav1.CreateOptions{})
+	fmt.Printf("++++ Created ns: %s %+v\n", name, err)
+	return err
+}
diff --git a/core/installer/namespace.go b/core/installer/namespace.go
new file mode 100644
index 0000000..87cd8c4
--- /dev/null
+++ b/core/installer/namespace.go
@@ -0,0 +1,64 @@
+package installer
+
+import (
+	"crypto/rand"
+	"fmt"
+)
+
+type NamespaceGenerator interface {
+	Generate(name string) (string, error)
+}
+
+type prefixGenerator struct {
+	prefix string
+}
+
+func NewPrefixGenerator(prefix string) NamespaceGenerator {
+	return &prefixGenerator{prefix}
+}
+
+func (g *prefixGenerator) Generate(name string) (string, error) {
+	return g.prefix + name, nil
+}
+
+type randomSuffixGenerator struct {
+	len int
+}
+
+func NewRandomSuffixGenerator(len int) NamespaceGenerator {
+	return &randomSuffixGenerator{len}
+}
+
+var letters = []rune("abcdefghijklmnopqrstuvwxyz")
+
+func (g randomSuffixGenerator) Generate(name string) (string, error) {
+	r := make([]byte, g.len)
+	if _, err := rand.Read(r); err != nil {
+		return "", err
+	}
+	ret := make([]rune, g.len)
+	for i, v := range r {
+		ret[i] += letters[v%26]
+	}
+	return fmt.Sprintf("%s-%s", name, string(ret)), nil
+}
+
+type combineGenerator struct {
+	ns []NamespaceGenerator
+}
+
+func NewCombine(ns ...NamespaceGenerator) NamespaceGenerator {
+	return &combineGenerator{ns}
+}
+
+func (g *combineGenerator) Generate(name string) (string, error) {
+	cur := name
+	var err error
+	for _, i := range g.ns {
+		cur, err = i.Generate(cur)
+		if err != nil {
+			return "", err
+		}
+	}
+	return cur, nil
+}
diff --git a/core/installer/repoio.go b/core/installer/repoio.go
index 97bf9b6..4574fee 100644
--- a/core/installer/repoio.go
+++ b/core/installer/repoio.go
@@ -20,6 +20,7 @@
 
 type RepoIO interface {
 	Fetch() error
+	ReadConfig() (Config, error)
 	ReadKustomization(path string) (*Kustomization, error)
 	WriteKustomization(path string, kust Kustomization) error
 	WriteYaml(path string, data any) error
@@ -55,6 +56,15 @@
 	return err
 }
 
+func (r *repoIO) ReadConfig() (Config, error) {
+	configF, err := r.Reader(configFileName)
+	if err != nil {
+		return Config{}, err
+	}
+	defer configF.Close()
+	return ReadConfig(configF)
+}
+
 func (r *repoIO) ReadKustomization(path string) (*Kustomization, error) {
 	inp, err := r.Reader(path)
 	if err != nil {
diff --git a/core/installer/values-tmpl/cert-manager-webhook-gandi-role.yaml b/core/installer/values-tmpl/cert-manager-webhook-gandi-role.yaml
index f0f9b93..ef0b383 100644
--- a/core/installer/values-tmpl/cert-manager-webhook-gandi-role.yaml
+++ b/core/installer/values-tmpl/cert-manager-webhook-gandi-role.yaml
@@ -2,12 +2,11 @@
 kind: HelmRelease
 metadata:
   name: cert-manager-webhook-gandi-role
-  namespace: {{ .Global.PCloudEnvName }}
+  namespace: {{ .Global.PCloudEnvName }}-cert-manager
 spec:
-  targetNamespace: {{ .Global.PCloudEnvName }}-cert-manager
   dependsOn:
     - name: cert-manager
-      namespace: {{ .Global.PCloudEnvName }}
+      namespace: {{ .Global.PCloudEnvName }}-cert-manager
   chart:
     spec:
       chart: charts/cert-manager-webhook-gandi-role
diff --git a/core/installer/values-tmpl/cert-manager-webhook-gandi.yaml b/core/installer/values-tmpl/cert-manager-webhook-gandi.yaml
index fdcc030..bbadd91 100644
--- a/core/installer/values-tmpl/cert-manager-webhook-gandi.yaml
+++ b/core/installer/values-tmpl/cert-manager-webhook-gandi.yaml
@@ -2,12 +2,11 @@
 kind: HelmRelease
 metadata:
   name: cert-manager-webhook-gandi
-  namespace: {{ .Global.PCloudEnvName }}
+  namespace: {{ .Global.PCloudEnvName }}-cert-manager
 spec:
-  targetNamespace: {{ .Global.PCloudEnvName }}-cert-manager
   dependsOn:
     - name: cert-manager
-      namespace: {{ .Global.PCloudEnvName }}
+      namespace: {{ .Global.PCloudEnvName }}-cert-manager # TODO(giolekva): derivative
   chart:
     spec:
       chart: charts/cert-manager-webhook-gandi
diff --git a/core/installer/values-tmpl/cert-manager.yaml b/core/installer/values-tmpl/cert-manager.yaml
index db00d34..c5bb9ac 100644
--- a/core/installer/values-tmpl/cert-manager.yaml
+++ b/core/installer/values-tmpl/cert-manager.yaml
@@ -1,35 +1,12 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-cert-manager
-  namespace: {{ .Global.PCloudEnvName }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: {{ .Global.PCloudEnvName }}
-        namespace: {{ .Global.PCloudEnvName }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: ""
-    namespacePrefix: {{ .Global.PCloudEnvName }}-
-    namespaces:
-    - cert-manager
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: cert-manager
-  namespace: {{ .Global.PCloudEnvName }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.PCloudEnvName }}-cert-manager
   dependsOn:
-    - name: namespaces-cert-manager
-      namespace: {{ .Global.PCloudEnvName }}
     - name: ingress-public
-      namespace: {{ .Global.PCloudEnvName }}
+      namespace: {{ .Global.PCloudEnvName }}-ingress-public # TODO(giolekva): derivative
   chart:
     spec:
       chart: charts/cert-manager
diff --git a/core/installer/values-tmpl/certificate-issuer-private.yaml b/core/installer/values-tmpl/certificate-issuer-private.yaml
index a9cc706..09209d0 100644
--- a/core/installer/values-tmpl/certificate-issuer-private.yaml
+++ b/core/installer/values-tmpl/certificate-issuer-private.yaml
@@ -2,12 +2,11 @@
 kind: HelmRelease
 metadata:
   name: certificate-issuer-private
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Global.Id }}-ingress-private
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}ingress-private
   dependsOn:
   - name: ingress-private
-    namespace: {{ .Global.Id }}
+    namespace: {{ .Global.Id }}-ingress-private
   chart:
     spec:
       chart: charts/certificate-issuer-private
diff --git a/core/installer/values-tmpl/certificate-issuer-public.yaml b/core/installer/values-tmpl/certificate-issuer-public.yaml
index 907954a..5755f0f 100644
--- a/core/installer/values-tmpl/certificate-issuer-public.yaml
+++ b/core/installer/values-tmpl/certificate-issuer-public.yaml
@@ -2,13 +2,12 @@
 kind: HelmRelease
 metadata:
   name: certificate-issuer-public
-  namespace: {{ .Global.Id }}
-spec:
   # TODO(giolekva): is there better namespace for this?
-  targetNamespace: {{ .Global.NamespacePrefix }}ingress-private
+  namespace: {{ .Global.Id }}-ingress-private
+spec:
   dependsOn:
   - name: ingress-private
-    namespace: {{ .Global.Id }}
+    namespace: {{ .Global.Id }}-ingress-private
   chart:
     spec:
       chart: charts/certificate-issuer-public
diff --git a/core/installer/values-tmpl/core-auth-storage.yaml b/core/installer/values-tmpl/core-auth-storage.yaml
index 9040b62..368b433 100644
--- a/core/installer/values-tmpl/core-auth-storage.yaml
+++ b/core/installer/values-tmpl/core-auth-storage.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-core-auth
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - core-auth
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: core-auth-storage
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}core-auth
-  dependsOn:
-    - name: namespaces-core-auth
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: charts/postgresql
diff --git a/core/installer/values-tmpl/core-auth.yaml b/core/installer/values-tmpl/core-auth.yaml
index 856fb4c..7a1b7a1 100644
--- a/core/installer/values-tmpl/core-auth.yaml
+++ b/core/installer/values-tmpl/core-auth.yaml
@@ -2,14 +2,13 @@
 kind: HelmRelease
 metadata:
   name: core-auth
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}core-auth
   dependsOn:
   - name: core-auth-storage
-    namespace: {{ .Global.Id }}
-  - name: ingress-private
-    namespace: {{ .Global.Id }}
+    namespace: {{ .Release.Namespace }}
+  - name: ingress-private # TODO(giolekva): is this needed?
+    namespace: {{ .Global.Id }}-ingress-private
   chart:
     spec:
       chart: charts/auth
@@ -76,7 +75,7 @@
           enabled: false
         config:
           version: v0.7.1-alpha.1
-          dsn: postgres://kratos:kratos@postgres.lekva-core-auth.svc:5432/kratos?sslmode=disable&max_conns=20&max_idle_conns=4
+          dsn: postgres://kratos:kratos@postgres.{{ .Globa.Id }}-core-auth.svc:5432/kratos?sslmode=disable&max_conns=20&max_idle_conns=4
           serve:
             public:
               base_url: https://accounts.{{ .Global.Domain }}
@@ -247,7 +246,7 @@
           enabled: true
         config:
           version: v1.10.6
-          dsn: postgres://hydra:hydra@postgres.lekva-core-auth.svc:5432/hydra?sslmode=disable&max_conns=20&max_idle_conns=4
+          dsn: postgres://hydra:hydra@postgres.{{ .Globa.Id }}-core-auth.svc:5432/hydra?sslmode=disable&max_conns=20&max_idle_conns=4
           serve:
             cookies:
               same_site_mode: None
@@ -299,4 +298,4 @@
       ingressClassName: {{ .Global.PCloudEnvName }}-ingress-public
       domain: {{ .Global.Domain }}
       internalDomain: p.{{ .Global.Domain }}
-      hydra: hydra-admin.lekva-core-auth.svc.cluster.local
+      hydra: hydra-admin.{{ .Globa.Id }}-core-auth.svc.cluster.local
diff --git a/core/installer/values-tmpl/csi-driver-smb.yaml b/core/installer/values-tmpl/csi-driver-smb.yaml
index 9a2cf36..9297d0f 100644
--- a/core/installer/values-tmpl/csi-driver-smb.yaml
+++ b/core/installer/values-tmpl/csi-driver-smb.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-csi-driver-smb
-  namespace: {{ .Global.PCloudEnvName }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: {{ .Global.PCloudEnvName }}
-        namespace: {{ .Global.PCloudEnvName }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: ""
-    namespacePrefix: {{ .Global.PCloudEnvName }}-
-    namespaces:
-    - csi-driver-smb
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: csi-driver-smb
-  namespace: {{ .Global.PCloudEnvName }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.PCloudEnvName }}-csi-driver-smb
-  dependsOn:
-    - name: namespaces-csi-driver-smb
-      namespace: {{ .Global.PCloudEnvName }}
   chart:
     spec:
       chart: charts/csi-driver-smb
diff --git a/core/installer/values-tmpl/env-manager.yaml b/core/installer/values-tmpl/env-manager.yaml
index 691693b..b64ce09 100644
--- a/core/installer/values-tmpl/env-manager.yaml
+++ b/core/installer/values-tmpl/env-manager.yaml
@@ -2,7 +2,7 @@
 kind: HelmRelease
 metadata:
   name: env-manager
-  namespace: {{ .Global.PCloudEnvName }}
+  namespace: {{ .Release.Namespace }}
 spec:
   chart:
     spec:
diff --git a/core/installer/values-tmpl/headscale-controller.yaml b/core/installer/values-tmpl/headscale-controller.yaml
index 3285f58..f799d9b 100644
--- a/core/installer/values-tmpl/headscale-controller.yaml
+++ b/core/installer/values-tmpl/headscale-controller.yaml
@@ -1,32 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-headscale-controller
-  namespace: {{ .Global.PCloudEnvName }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.PCloudEnvName }}
-  interval: 1m0s
-  values:
-    namespacePrefix: {{ .Global.PCloudEnvName }}-
-    namespaces:
-    - headscale-controller
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: headscale-controller
-  namespace: {{ .Global.PCloudEnvName }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.PCloudEnvName }}-headscale-controller
-  dependsOn:
-    - name: namespaces-headscale-controller
-      namespace: {{ .Global.PCloudEnvName }}
   chart:
     spec:
       chart: charts/headscale-controller
diff --git a/core/installer/values-tmpl/headscale.yaml b/core/installer/values-tmpl/headscale.yaml
index 8c16b86..c3894c2 100644
--- a/core/installer/values-tmpl/headscale.yaml
+++ b/core/installer/values-tmpl/headscale.yaml
@@ -1,35 +1,12 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-headscale
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - app-headscale
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: headscale
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}app-headscale
   dependsOn:
-    - name: namespaces-headscale
-      namespace: {{ .Global.Id }}
     - name: core-auth
-      namespace: {{ .Global.Id }}
+      namespace: {{ .Global.NamespacePrefix }}core-auth
   chart:
     spec:
       chart: charts/headscale
diff --git a/core/installer/values-tmpl/ingress-private.yaml b/core/installer/values-tmpl/ingress-private.yaml
index 0874b72..e1870af 100644
--- a/core/installer/values-tmpl/ingress-private.yaml
+++ b/core/installer/values-tmpl/ingress-private.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-ingress-private
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - ingress-private
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: ingress-private
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}ingress-private
-  dependsOn:
-    - name: namespaces-ingress-private
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: charts/ingress-nginx
diff --git a/core/installer/values-tmpl/ingress-public.yaml b/core/installer/values-tmpl/ingress-public.yaml
index 80a5efd..67ac1b2 100644
--- a/core/installer/values-tmpl/ingress-public.yaml
+++ b/core/installer/values-tmpl/ingress-public.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-ingress-public
-  namespace: {{ .Global.PCloudEnvName }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: {{ .Global.PCloudEnvName }}
-        namespace: {{ .Global.PCloudEnvName }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: ""
-    namespacePrefix: {{ .Global.PCloudEnvName }}-
-    namespaces:
-    - ingress-public
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: ingress-public
-  namespace: {{ .Global.PCloudEnvName }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.PCloudEnvName }}-ingress-public
-  dependsOn:
-    - name: namespaces-ingress-public
-      namespace: {{ .Global.PCloudEnvName }}
   chart:
     spec:
       chart: charts/ingress-nginx
diff --git a/core/installer/values-tmpl/jellyfin.yaml b/core/installer/values-tmpl/jellyfin.yaml
index 2ef63ee..d486072 100644
--- a/core/installer/values-tmpl/jellyfin.yaml
+++ b/core/installer/values-tmpl/jellyfin.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-jellyfin
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - app-jellyfin
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: jellyfin
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}app-jellyfin
-  dependsOn:
-    - name: namespaces-jellyfin
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: charts/jellyfin
diff --git a/core/installer/values-tmpl/maddy.yaml b/core/installer/values-tmpl/maddy.yaml
index c7d8dd7..31a96e1 100644
--- a/core/installer/values-tmpl/maddy.yaml
+++ b/core/installer/values-tmpl/maddy.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-maddy
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - app-maddy
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: maddy
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}app-maddy
-  dependsOn:
-    - name: namespaces-maddy
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: charts/maddy
diff --git a/core/installer/values-tmpl/matrix-storage.yaml b/core/installer/values-tmpl/matrix-storage.yaml
index 87f1657..47ee9c0 100644
--- a/core/installer/values-tmpl/matrix-storage.yaml
+++ b/core/installer/values-tmpl/matrix-storage.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-matrix
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - app-matrix
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: matrix-storage
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}app-matrix
-  dependsOn:
-    - name: namespaces-matrix
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: postgresql
diff --git a/core/installer/values-tmpl/matrix.yaml b/core/installer/values-tmpl/matrix.yaml
index ecc36fe..d3e3a03 100644
--- a/core/installer/values-tmpl/matrix.yaml
+++ b/core/installer/values-tmpl/matrix.yaml
@@ -2,12 +2,11 @@
 kind: HelmRelease
 metadata:
   name: matrix
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}app-matrix
   dependsOn:
   - name: matrix-storage
-    namespace: {{ .Global.Id }}
+    namespace: {{ .Release.Namespace }}
   chart:
     spec:
       chart: charts/matrix
diff --git a/core/installer/values-tmpl/metallb-config-env.yaml b/core/installer/values-tmpl/metallb-config-env.yaml
index 39907e4..defa5ec 100644
--- a/core/installer/values-tmpl/metallb-config-env.yaml
+++ b/core/installer/values-tmpl/metallb-config-env.yaml
@@ -1,8 +1,8 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: meteallb-config-env # TODO(giolekva): typo metea
-  namespace: {{ .Global.Id }}
+  name: metallb-config-env
+  namespace: {{ .Release.Namespace }}
 spec:
   chart:
     spec:
diff --git a/core/installer/values-tmpl/pihole.yaml b/core/installer/values-tmpl/pihole.yaml
index 51e3d97..5b9d963 100644
--- a/core/installer/values-tmpl/pihole.yaml
+++ b/core/installer/values-tmpl/pihole.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-pihole
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - app-pihole
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: pihole
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}app-pihole
-  dependsOn:
-    - name: namespaces-pihole
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: charts/pihole
diff --git a/core/installer/values-tmpl/qbittorrent.yaml b/core/installer/values-tmpl/qbittorrent.yaml
index 346a933..0597595 100644
--- a/core/installer/values-tmpl/qbittorrent.yaml
+++ b/core/installer/values-tmpl/qbittorrent.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-qbittorrent
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - app-qbittorrent
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: qbittorrent
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  namespace: {{ .Global.NamespacePrefix }}app-qbittorrent
-  dependsOn:
-    - name: namespaces-qbittorrent
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: charts/qbittorrent
diff --git a/core/installer/values-tmpl/resource-renderer-controller.yaml b/core/installer/values-tmpl/resource-renderer-controller.yaml
index 72cf68b..7ffa9d0 100644
--- a/core/installer/values-tmpl/resource-renderer-controller.yaml
+++ b/core/installer/values-tmpl/resource-renderer-controller.yaml
@@ -1,32 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-rr-controller
-  namespace: {{ .Global.PCloudEnvName }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.PCloudEnvName }}
-  interval: 1m0s
-  values:
-    namespacePrefix: {{ .Global.PCloudEnvName }}-
-    namespaces:
-    - rr-controller
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: rr-controller
-  namespace: {{ .Global.PCloudEnvName }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.PCloudEnvName }}-rr-controller
-  dependsOn:
-    - name: namespaces-rr-controller
-      namespace: {{ .Global.PCloudEnvName }}
   chart:
     spec:
       chart: charts/resource-renderer-controller
diff --git a/core/installer/values-tmpl/tailscale-proxy.yaml b/core/installer/values-tmpl/tailscale-proxy.yaml
index 9664e51..5ceae75 100644
--- a/core/installer/values-tmpl/tailscale-proxy.yaml
+++ b/core/installer/values-tmpl/tailscale-proxy.yaml
@@ -1,35 +1,12 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-tailscale-proxy
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - tailscale-proxy
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: tailscale-proxy
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}tailscale-proxy
   dependsOn:
-    - name: namespaces-tailscale-proxy
-      namespace: {{ .Global.Id }}
     - name: headscale
-      namespace: {{ .Global.Id }}
+      namespace: {{ .Global.NamespacePrefix }}app-headscale
   chart:
     spec:
       chart: charts/tailscale
diff --git a/core/installer/values-tmpl/vaultwarden.yaml b/core/installer/values-tmpl/vaultwarden.yaml
index 71046d4..4419776 100644
--- a/core/installer/values-tmpl/vaultwarden.yaml
+++ b/core/installer/values-tmpl/vaultwarden.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-vaultwarden
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - app-vaultwarden
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: vaultwarden
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}app-vaultwarden
-  dependsOn:
-    - name: namespaces-vaultwarden
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: charts/vaultwarden
diff --git a/core/installer/values-tmpl/vpn-mesh-config.yaml b/core/installer/values-tmpl/vpn-mesh-config.yaml
index d42e1c8..2604eeb 100644
--- a/core/installer/values-tmpl/vpn-mesh-config.yaml
+++ b/core/installer/values-tmpl/vpn-mesh-config.yaml
@@ -2,7 +2,7 @@
 kind: HelmRelease
 metadata:
   name: vpn-mesh-config
-  namespace: {{ .Values.NamespacePrefix }}ingress-private
+  namespace: {{ .Release.NamespacePrefix }}ingress-private
 spec:
   chart:
     spec:
diff --git a/core/installer/values-tmpl/welcome.yaml b/core/installer/values-tmpl/welcome.yaml
index 9f4c298..93556e3 100644
--- a/core/installer/values-tmpl/welcome.yaml
+++ b/core/installer/values-tmpl/welcome.yaml
@@ -1,33 +1,9 @@
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
-  name: namespaces-welcome
-  namespace: {{ .Global.Id }}
-spec:
-  chart:
-    spec:
-      chart: charts/namespaces
-      sourceRef:
-        kind: GitRepository
-        name: pcloud
-        namespace: {{ .Global.Id }}
-  interval: 1m0s
-  values:
-    pcloudInstanceId: {{ .Global.Id }}
-    namespacePrefix: {{ .Global.NamespacePrefix }}
-    namespaces:
-    - app-welcome
----
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
   name: welcome
-  namespace: {{ .Global.Id }}
+  namespace: {{ .Release.Namespace }}
 spec:
-  targetNamespace: {{ .Global.NamespacePrefix }}app-welcome
-  dependsOn:
-    - name: namespaces-welcome
-      namespace: {{ .Global.Id }}
   chart:
     spec:
       chart: charts/welcome
@@ -41,5 +17,5 @@
     sshPrivateKey: {{ .Values.SSHPrivateKey | b64enc }}
     ingress:
       className: {{ .Global.PCloudEnvName }}-ingress-public
-      domain: {{ .Global.Domain }}
+      domain: welcome.{{ .Global.Domain }}
       certificateIssuer: {{ .Global.Id }}-public
diff --git a/core/installer/welcome/env.go b/core/installer/welcome/env.go
index e871830..67e51d9 100644
--- a/core/installer/welcome/env.go
+++ b/core/installer/welcome/env.go
@@ -23,16 +23,18 @@
 var createEnvFormHtml string
 
 type EnvServer struct {
-	port int
-	ss   *soft.Client
-	repo installer.RepoIO
+	port      int
+	ss        *soft.Client
+	repo      installer.RepoIO
+	nsCreator installer.NamespaceCreator
 }
 
-func NewEnvServer(port int, ss *soft.Client, repo installer.RepoIO) *EnvServer {
+func NewEnvServer(port int, ss *soft.Client, repo installer.RepoIO, nsCreator installer.NamespaceCreator) *EnvServer {
 	return &EnvServer{
 		port,
 		ss,
 		repo,
+		nsCreator,
 	}
 }
 
@@ -99,7 +101,7 @@
 		if repo == nil {
 			return err
 		}
-		if err := initNewEnv(s.ss, installer.NewRepoIO(repo, s.ss.Signer), req); err != nil {
+		if err := initNewEnv(s.ss, installer.NewRepoIO(repo, s.ss.Signer), s.nsCreator, req); err != nil {
 			return err
 		}
 	}
@@ -124,8 +126,8 @@
 	return c.String(http.StatusOK, "OK")
 }
 
-func initNewEnv(ss *soft.Client, r installer.RepoIO, req createEnvReq) error {
-	appManager, err := installer.NewAppManager(r)
+func initNewEnv(ss *soft.Client, r installer.RepoIO, nsCreator installer.NamespaceCreator, req createEnvReq) error {
+	appManager, err := installer.NewAppManager(r, nsCreator)
 	if err != nil {
 		return err
 	}
@@ -152,18 +154,18 @@
 			return err
 		}
 		defer out.Close()
-		_, err = out.Write([]byte(`
+		_, err = out.Write([]byte(fmt.Sprintf(`
 apiVersion: source.toolkit.fluxcd.io/v1beta2
 kind: GitRepository
 metadata:
   name: pcloud
-  namespace: lekva
+  namespace: %s
 spec:
   interval: 1m0s
   url: https://github.com/giolekva/pcloud
   ref:
     branch: main
-`))
+`, req.Name)))
 		if err != nil {
 			return err
 		}
@@ -178,12 +180,13 @@
 		return err
 	}
 	r.CommitAndPush("initialize config")
+	nsGen := installer.NewPrefixGenerator(req.Name + "-")
 	{
 		app, err := appsRepo.Find("metallb-config-env")
 		if err != nil {
 			return err
 		}
-		if err := appManager.Install(*app, map[string]any{
+		if err := appManager.Install(*app, nsGen, map[string]any{
 			"IngressPrivate": "10.1.0.1",
 			"Headscale":      "10.1.0.2",
 			"SoftServe":      "10.1.0.3",
@@ -200,7 +203,7 @@
 		if err != nil {
 			return err
 		}
-		if err := appManager.Install(*app, map[string]any{}); err != nil {
+		if err := appManager.Install(*app, nsGen, map[string]any{}); err != nil {
 			return err
 		}
 	}
@@ -209,7 +212,7 @@
 		if err != nil {
 			return err
 		}
-		if err := appManager.Install(*app, map[string]any{}); err != nil {
+		if err := appManager.Install(*app, nsGen, map[string]any{}); err != nil {
 			return err
 		}
 	}
@@ -218,7 +221,7 @@
 		if err != nil {
 			return err
 		}
-		if err := appManager.Install(*app, map[string]any{
+		if err := appManager.Install(*app, nsGen, map[string]any{
 			"Subdomain": "test", // TODO(giolekva): make core-auth chart actually use this
 		}); err != nil {
 			return err
@@ -229,7 +232,7 @@
 		if err != nil {
 			return err
 		}
-		if err := appManager.Install(*app, map[string]any{
+		if err := appManager.Install(*app, nsGen, map[string]any{
 			"Subdomain": "headscale",
 		}); err != nil {
 			return err
@@ -251,7 +254,7 @@
 		if err != nil {
 			return err
 		}
-		if err := appManager.Install(*app, map[string]any{
+		if err := appManager.Install(*app, nsGen, map[string]any{
 			"RepoAddr":      ss.GetRepoAddress(req.Name),
 			"SSHPrivateKey": keys.Private,
 		}); err != nil {
diff --git a/core/installer/welcome/welcome.go b/core/installer/welcome/welcome.go
index 04e08f5..d34580f 100644
--- a/core/installer/welcome/welcome.go
+++ b/core/installer/welcome/welcome.go
@@ -20,14 +20,16 @@
 var staticAssets embed.FS
 
 type Server struct {
-	port int
-	repo installer.RepoIO
+	port      int
+	repo      installer.RepoIO
+	nsCreator installer.NamespaceCreator
 }
 
-func NewServer(port int, repo installer.RepoIO) *Server {
+func NewServer(port int, repo installer.RepoIO, nsCreator installer.NamespaceCreator) *Server {
 	return &Server{
 		port,
 		repo,
+		nsCreator,
 	}
 }
 
@@ -86,7 +88,15 @@
 	}
 	// TODO(giolekva): accounts-ui create user req
 	{
-		appManager, err := installer.NewAppManager(s.repo)
+		config, err := s.repo.ReadConfig()
+		if err != nil {
+			return err
+		}
+		if err != nil {
+			return err
+		}
+		nsGen := installer.NewPrefixGenerator(config.Values.Id + "-")
+		appManager, err := installer.NewAppManager(s.repo, s.nsCreator)
 		if err != nil {
 			return err
 		}
@@ -96,7 +106,7 @@
 			if err != nil {
 				return err
 			}
-			if err := appManager.Install(*app, map[string]any{
+			if err := appManager.Install(*app, nsGen, map[string]any{
 				"GandiAPIToken": req.GandiAPIToken,
 			}); err != nil {
 				return err
@@ -107,7 +117,7 @@
 			if err != nil {
 				return err
 			}
-			if err := appManager.Install(*app, map[string]any{
+			if err := appManager.Install(*app, nsGen, map[string]any{
 				"Username": req.Username,
 				"IPSubnet": "10.1.0.0/24", // TODO(giolekva): this should be taken from the config generated during new env creation
 			}); err != nil {