diff --git a/examples/extension_service/Dockerfile b/examples/extension_service/Dockerfile
index 9bb9a152b3343d3a48b5f07b511b528e2739955e..2c8ed85c1fe89a8792e59cd2999fe8ebb2f54d0a 100644
--- a/examples/extension_service/Dockerfile
+++ b/examples/extension_service/Dockerfile
@@ -11,7 +11,7 @@ ARG PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
 ENV PIP_EXTRA_INDEX_URL=$PIP_EXTRA_INDEX_URL
 
 COPY . /home/${USER}/app
-RUN pip install perxis==0.0.16
+RUN pip install perxis==0.0.17
 
 ENV PYTHONPATH="/home/perx/app"
 ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
diff --git a/examples/extension_service/Dockerfile.local b/examples/extension_service/Dockerfile.local
index 994d988a029b2c54363a269a7e55d0daff2f4da4..d8d0d31766a83b0069c695242665804a78e52890 100644
--- a/examples/extension_service/Dockerfile.local
+++ b/examples/extension_service/Dockerfile.local
@@ -11,7 +11,7 @@ ARG PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
 ENV PIP_EXTRA_INDEX_URL=$PIP_EXTRA_INDEX_URL
 
 COPY . /home/${USER}/app
-RUN pip install perxis==0.0.16
+RUN pip install perxis==0.0.17
 RUN pip install 'watchdog[watchmedo]'
 
 ENV PYTHONPATH="/home/perx/app"
diff --git a/examples/extension_service/server.py b/examples/extension_service/server.py
index a4fb49cb79244b3f3bb8a01ef739f4a8e3361ad8..64bc3cf5ef3cb3bf21ed8d0175855932bbfb9ff5 100644
--- a/examples/extension_service/server.py
+++ b/examples/extension_service/server.py
@@ -18,7 +18,6 @@ def main():
     interceptor = header_adder_interceptor(
         'x-perxis-access', 'system'
     )
-
     with grpc.insecure_channel("extension-manager:9030") as extensions_manager_channel:
         intercept_channel_extensions_manager_channel = grpc.intercept_channel(extensions_manager_channel, interceptor)
 
diff --git a/examples/extension_service/servicer.py b/examples/extension_service/servicer.py
index 12a84558f9aa622886e3ab11320e14175925eb15..d1d22675902fdb6168dbad0b6b33f2e6e075c419 100644
--- a/examples/extension_service/servicer.py
+++ b/examples/extension_service/servicer.py
@@ -15,7 +15,7 @@ class Servicer(ExtensionService):
     roles = [
         roles_pb2.Role(
             id="demo-role",
-            description="Описание к роли",
+            description="Описание к ролииии",
             rules=[
                 common_pb2.Rule(
                     collection_id="dealers_cities",
diff --git a/perxis/extensions/extension_setup.py b/perxis/extensions/extension_setup.py
index a439803d2b04bfe4596014c5e3337fbb808f3bc0..9622223b097a4559ec6ddc9d7beea86148c919d6 100644
--- a/perxis/extensions/extension_setup.py
+++ b/perxis/extensions/extension_setup.py
@@ -81,43 +81,62 @@ class ExtensionSetup:
 
         return errors_list
 
-    def __update_roles(self, space_id: str) -> list[str]:
+    def __update_roles(self, space_id: str, env_id: str) -> list[str]:
         errors_list = []
 
         for local_role in self.roles:
             try:
-                cloned_role = copy.deepcopy(local_role)
-                cloned_role.space_id = space_id
-
-                # Полностью замещать данные роли тем что имеется в расширении
-                # TODO: нужно ли мержить права чтобы не терять изменения?
-                self.roles_service.Update.with_call(
-                    roles_pb2.UpdateRequest(
-                        role=cloned_role
+                get_response, state = self.roles_service.Get.with_call(
+                    roles_pb2.GetRequest(
+                        space_id=space_id,
+                        role_id=local_role.id
                     )
                 )
+
+                role = get_response.role
             except grpc.RpcError as e:
-                errors_list.append(f"Не удалось обновить роль {local_role.id}, {e.details()}")
+                if "not found" not in e.details():
+                    errors_list.append(f"Не удалось получить роль {local_role.id}, {e.details()}")
+                    continue
 
-        return errors_list
+                role = None
 
-    def __create_roles(self, space_id: str) -> list[str]:
-        errors_list = []
+            cloned_role = copy.deepcopy(local_role)
+            cloned_role.space_id = space_id
 
-        for local_role in self.roles:
-            try:
-                cloned_role = copy.deepcopy(local_role)
-                cloned_role.space_id = space_id
+            if role:
+                if not role.environments:
+                    role.environments[:] = [env_id]
+                elif env_id not in role.environments:
+                    role.environments.append(env_id)
 
-                response, _ = self.roles_service.Create.with_call(
-                    roles_pb2.CreateRequest(
-                        role=cloned_role
-                    ),
-                )
-            except grpc.RpcError as e:
-                # На этапе install считается что ролей __нет__. При install с указанием force роли предварительно
-                # удаляются
-                errors_list.append(f"Не удалось создать роль {local_role.id}, {e.details()}")
+                cloned_role.environments[:] = role.environments
+
+                try:
+                    self.roles_service.Update.with_call(
+                        roles_pb2.UpdateRequest(
+                            role=cloned_role
+                        )
+                    )
+                except grpc.RpcError as e:
+                    errors_list.append(f"Не удалось обновить роль {local_role.id}, {e.details()}")
+            else:
+                if env_id not in cloned_role.environments:
+                    cloned_role.environments.append(env_id)
+
+                try:
+                    cloned_role = copy.deepcopy(local_role)
+                    cloned_role.space_id = space_id
+
+                    response, _ = self.roles_service.Create.with_call(
+                        roles_pb2.CreateRequest(
+                            role=cloned_role
+                        ),
+                    )
+                except grpc.RpcError as e:
+                    # На этапе install считается что ролей __нет__. При install с указанием force роли предварительно
+                    # удаляются
+                    errors_list.append(f"Не удалось создать роль {local_role.id}, {e.details()}")
 
         return errors_list
 
@@ -169,51 +188,47 @@ class ExtensionSetup:
 
                 client = get_response.client
             except grpc.RpcError as e:
-                errors_list.append(f"Не удалось получить клиент {local_client.id}, {e.details()}")
+                if "not found" not in e.details():
+                    errors_list.append(f"Не удалось получить клиент {local_client.id}, {e.details()}")
+                    continue
 
-                continue
+                client = None
 
-            try:
-                # Нужно чтобы у клиента каждый раз не слетали данные токенов при переустановке
-                # свойства oauth, api_key и tls должны браться из __созданного__ клиента
-                new_client = clients_pb2.Client(
-                    id=local_client.id,
-                    space_id=space_id,
-                    name=local_client.name,
-                    description=local_client.description,
-                    disabled=client.disabled,
-                    role_id=local_client.role_id,
-                    oauth=client.oauth,
-                    api_key=client.api_key,
-                    tls=client.tls
-                )
-
-                self.clients_service.Update.with_call(
-                    clients_pb2.UpdateRequest(
-                        client=new_client
+            if client:
+                try:
+                    # Нужно чтобы у клиента каждый раз не слетали данные токенов при переустановке
+                    # свойства oauth, api_key и tls должны браться из __созданного__ клиента
+                    new_client = clients_pb2.Client(
+                        id=local_client.id,
+                        space_id=space_id,
+                        name=local_client.name,
+                        description=local_client.description,
+                        disabled=client.disabled,
+                        role_id=local_client.role_id,
+                        oauth=client.oauth or local_client.oauth,
+                        api_key=client.api_key or local_client.api_key,
+                        tls=client.tls
                     )
-                )
-            except grpc.RpcError as e:
-                errors_list.append(f"Не удалось обновить клиент {local_client.id}, {e.details()}")
-
-        return errors_list
-
-    def __create_clients(self, space_id: str) -> list[str]:
-        errors_list = []
 
-        for local_client in self.clients:
-            try:
-                cloned_client = copy.deepcopy(local_client)
-                cloned_client.space_id = space_id
+                    self.clients_service.Update.with_call(
+                        clients_pb2.UpdateRequest(
+                            client=new_client
+                        )
+                    )
+                except grpc.RpcError as e:
+                    errors_list.append(f"Не удалось обновить клиент {local_client.id}, {e.details()}")
+            else:
+                try:
+                    cloned_client = copy.deepcopy(local_client)
+                    cloned_client.space_id = space_id
 
-                response, _ = self.clients_service.Create.with_call(
-                    clients_pb2.CreateRequest(
-                        client=cloned_client
-                    ),
-                )
-            except grpc.RpcError as e:
-                # Как и с ролями считается что при install записей быть не должно в любом случае т.к. force всё удаляет
-                errors_list.append(f"Не удалось создать клиент {local_client.id}, {e.details()}")
+                    response, _ = self.clients_service.Create.with_call(
+                        clients_pb2.CreateRequest(
+                            client=cloned_client
+                        ),
+                    )
+                except grpc.RpcError as e:
+                    errors_list.append(f"Не удалось создать клиент {local_client.id}, {e.details()}")
 
         return errors_list
 
@@ -398,8 +413,8 @@ class ExtensionSetup:
             errors += self.__remove_roles(space_id)
 
         errors += self.__update_collections(space_id, env_id)
-        errors += self.__create_roles(space_id)
-        errors += self.__create_clients(space_id)
+        errors += self.__update_roles(space_id, env_id)
+        errors += self.__update_clients(space_id)
 
         return errors
 
@@ -407,19 +422,14 @@ class ExtensionSetup:
         errors = []
 
         # В случае обновление расширения с флагом force нужно предварительно удалить все сущности.
-        # Фактически это переустановка а не удаление
         if use_force:
             errors += self.__remove_clients(space_id)
             errors += self.__remove_roles(space_id)
             errors += self.__remove_collections(space_id, env_id)
 
-            errors += self.__update_collections(space_id, env_id)
-            errors += self.__create_roles(space_id)
-            errors += self.__create_clients(space_id)
-        else:
-            errors += self.__update_collections(space_id, env_id)
-            errors += self.__update_roles(space_id)
-            errors += self.__update_clients(space_id)
+        errors += self.__update_collections(space_id, env_id)
+        errors += self.__update_roles(space_id, env_id)
+        errors += self.__update_clients(space_id)
 
         return errors