diff --git a/src/backoffice/forms.py b/src/backoffice/forms.py
index 610e321d045dc8589faf9f05b2318f1d728e44aa..e4f3d7c6355c56d56a4f0778bdde827fa989ebd3 100644
--- a/src/backoffice/forms.py
+++ b/src/backoffice/forms.py
@@ -6,7 +6,7 @@ from django.core.exceptions import ValidationError
 from django.contrib.auth.forms import UserCreationForm
 from django.utils.translation import gettext_lazy as _
 
-from core.integrations import BigBlueButton, IntegrationError, WorkAdventure
+from core.integrations import BigBlueButton, Hangar, IntegrationError, WorkAdventure
 from core.models import Application, Assembly, AssemblyMember, Event, PlatformUser, Room, RoomLink
 
 
@@ -224,6 +224,38 @@ class AssemblyCreateRoomBigBlueButtonForm(AssemblyCreateRoomForm):
         return room
 
 
+class AssemblyCreateRoomHangarForm(AssemblyCreateRoomForm):
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.fields['name'].initial = self.assembly.slug
+        self.fields['name'].disabled = True
+
+    def clean(self, *args, **kwargs):
+        cleaned_data = super().clean(*args, **kwargs)
+
+        if not Hangar.can_create_for_assembly(self.assembly):
+            raise ValidationError(_('Room-new-hangar__unavailable'))
+
+        return cleaned_data
+
+    def create_room(self, request):
+        room = self.assembly.rooms.create(
+            conference=self.assembly.conference,
+            room_type=Room.RoomType.HANGAR,
+            backend_status=Room.BackendStatus.NEW,
+            **self.cleaned_data,
+        )
+        room.save()
+        self.room_id = room.id
+
+        if not self.create_room_on_backend(request, Hangar, room):
+            room.delete()
+            room = None
+            self.room_id = None
+
+        return room
+
+
 class CreateAssemblyEventForm(forms.ModelForm):
     class Meta:
         model = Event
@@ -262,6 +294,8 @@ class EditAssemblyRoomForm(forms.ModelForm):
             self.fields['backend_status'] = forms.CharField(initial=self.instance.get_backend_status_display(), disabled=True)
         if self.instance.room_type in Room.TYPES_WITH_CAPACITY:
             self.fields['capacity'] = forms.IntegerField(initial=self.instance.capacity)
+        if self.instance.room_type in [Room.RoomType.HANGAR]:
+            self.fields['name'].disabled = True
 
     def save(self, commit=False):
         obj = super().save(commit)
diff --git a/src/backoffice/locale/de/LC_MESSAGES/django.po b/src/backoffice/locale/de/LC_MESSAGES/django.po
index 4fbfdd9c61340ab2a09f4797c78d4d9b2016ecba..888f387e9d1a970cbf0a3f4a99c497412615a55b 100644
--- a/src/backoffice/locale/de/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/de/LC_MESSAGES/django.po
@@ -39,6 +39,9 @@ msgstr "Pfad zu einem Git-Repository mit den Kartendaten. Die angegebene URL mus
 msgid "Room-single_workadventure_only"
 msgstr "Es ist derzeit nur ein WorkAdventure-Raum möglich."
 
+msgid "Room-new-hangar__unavailable"
+msgstr "nur eine Ablage pro Assembly"
+
 msgid "Event__schedule_start__placeholder"
 msgstr "'dd.mm.YYYY HH:MM' oder 'YYYY-mm-dd HH:MM'"
 
@@ -336,12 +339,15 @@ msgstr "Schöner Raum und auch so hübsch dekoriert. Wirklich in Schutt und Asch
 msgid "Project__remove__confirm"
 msgstr "Nettes Projekt. Alle Spuren davon (zumindest auf dieser Konferenz) verwischen?"
 
-msgid "Room__remove__notpossible"
-msgstr "Hier könnte der Raum gelöscht werden, jedoch sind noch Veranstaltungen vorhanden. Lösche zuerst auch diese Veranstaltungen oder entferne die Zuordnung zu diesem Raum."
-
 msgid "Project__remove__notpossible"
 msgstr "Hier solltest du das Projekt löschen können aber scheinbar hat das Management etwas dagegen - unklar weswegen. Bitte wende dich an den Support."
 
+msgid "Hangar__remove__notpossible"
+msgstr "Hangar entfernen benötigt manuelle Interaktion, bitte kontaktiere den Support."
+
+msgid "Room__remove__notpossible"
+msgstr "Hier könnte der Raum gelöscht werden, jedoch sind noch Veranstaltungen vorhanden. Lösche zuerst auch diese Veranstaltungen oder entferne die Zuordnung zu diesem Raum."
+
 msgid "nav_activetab_srmarker"
 msgstr "(ausgewählt)"
 
@@ -441,6 +447,15 @@ msgstr "Anlegen"
 msgid "Room-new-bbb__unavailable"
 msgstr "BBB nicht verfügbar."
 
+msgid "Room-new-hangar"
+msgstr "Hangar beziehen"
+
+msgid "Room-new-hangar__help"
+msgstr "Dateiablage für Assembly-Inhalte erstellen."
+
+msgid "Room-new-hangar__create"
+msgstr "Anlegen"
+
 msgid "Room-new-lecturehall"
 msgstr "Vorlesungsraum"
 
@@ -606,6 +621,9 @@ msgstr "Bezug zur Assembly '{linked_name}' wurde vermerkt."
 msgid "assemblyedit_removedlink"
 msgstr "Bezug zur Assembly '{linked_name}' wurde entfernt."
 
+msgid "Room-new-hangar__legal_hint"
+msgstr "Du bestätigst, dass ihr ausschließlich nur solche Inhalte ablegt/veröffentlicht, für die ihr auch die nötigen Lizenzen/Rechte habt. Zuwiderhandlungen können ggf. straf- bzw. zivilrechtliche Folgen haben!"
+
 msgid "updated"
 msgstr "Eintrag aktualisiert"
 
@@ -642,6 +660,9 @@ msgstr "404 Benutzer nicht gefunden: "
 msgid "removed"
 msgstr "entfernt"
 
+msgid "internal_error_please_retry"
+msgstr "Mist. Irgendwas ist schief gelaufen, der Techniker ist informiert! Bitte probiere die Aktion erneut - wenn das Problem bestehen bleibt melde dich bei uns."
+
 msgid "RoomLink__created"
 msgstr "Link hinzugefügt: {name}"
 
diff --git a/src/backoffice/locale/en/LC_MESSAGES/django.po b/src/backoffice/locale/en/LC_MESSAGES/django.po
index 411510ee5821850398b735ae2769310515bc365a..8ab10ac7f18dfa5e02fcbe0169d839cdcbce4502 100644
--- a/src/backoffice/locale/en/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/en/LC_MESSAGES/django.po
@@ -39,6 +39,9 @@ msgstr "Link to a Git repository containing the map configuration. The given URL
 msgid "Room-single_workadventure_only"
 msgstr "Only a single WorkAdventure room is currently supported."
 
+msgid "Room-new-hangar__unavailable"
+msgstr "only one per assembly"
+
 msgid "Event__schedule_start__placeholder"
 msgstr "YYYY-mm-dd HH:MM"
 
@@ -337,12 +340,15 @@ msgstr "Nice room. So much wow. Do you really want to burn it down?"
 msgid "Project__remove__confirm"
 msgstr "You are about to leave no public traces of this project (at least on this conference). Sure?"
 
-msgid "Room__remove__notpossible"
-msgstr "Here you could remove the room if it hadn't at least one event assigned to it. Please delete all events associated with this room first (or remove the association)."
-
 msgid "Project__remove__notpossible"
 msgstr "Here you should be able to remove the project but management says 'no'. We don't know why either, please contact support."
 
+msgid "Hangar__remove__notpossible"
+msgstr "Hangar removal needs manual interaction, please contact support."
+
+msgid "Room__remove__notpossible"
+msgstr "Here you could remove the room if it hadn't at least one event assigned to it. Please delete all events associated with this room first (or remove the association)."
+
 msgid "nav_activetab_srmarker"
 msgstr "(current)"
 
@@ -442,6 +448,15 @@ msgstr "create"
 msgid "Room-new-bbb__unavailable"
 msgstr "BBB not available"
 
+msgid "Room-new-hangar"
+msgstr "Hangar"
+
+msgid "Room-new-hangar__help"
+msgstr "Configure a file storage for your assembly."
+
+msgid "Room-new-hangar__create"
+msgstr "create"
+
 msgid "Room-new-lecturehall"
 msgstr "lecture hall"
 
@@ -565,7 +580,6 @@ msgstr "Reset password"
 msgid "registration_reset_password_done"
 msgstr "Passwor reset initiated."
 
-
 msgid "registration_reset_password_mailsent"
 msgstr "An email with a password reset link has been sent to the given e-mail address. Please check your inbox and open the link sent to you in order to reset your password."
 
@@ -608,6 +622,9 @@ msgstr "Association with assembly '{linked_name}' has been saved."
 msgid "assemblyedit_removedlink"
 msgstr "Association with assembly '{linked_name}' has been deleted."
 
+msgid "Room-new-hangar__legal_hint"
+msgstr "You acknowledge that you will only store/publish content to which you own the necessary rights/licenses. Any violation might be liable to prosecution!"
+
 msgid "updated"
 msgstr "Entry has been updated."
 
@@ -644,6 +661,9 @@ msgstr "404 User Not Found: "
 msgid "removed"
 msgstr "removed"
 
+msgid "internal_error_please_retry"
+msgstr "D'oh. Something's gone wrong, the issue has been logged. Please retry your action and if the issue persists contact us."
+
 msgid "RoomLink__created"
 msgstr "added link: {name}"
 
diff --git a/src/backoffice/templates/backoffice/assembly_room.html b/src/backoffice/templates/backoffice/assembly_room.html
index 2760fbdff08ddf2cacdd3a48c9d7b1693d27aed6..be33b0e7a7037b7f09406737341ab9c0c7415b55 100644
--- a/src/backoffice/templates/backoffice/assembly_room.html
+++ b/src/backoffice/templates/backoffice/assembly_room.html
@@ -25,6 +25,8 @@
         {% if room.name %}{% if room.room_type != 'project' %}{{ room.get_room_type_display }} {% trans 'Room' %}{% else %}{% trans 'Project' %}{% endif %} "{{ room.name }}"{% else %}<span class="badge badge-secondary">{% trans 'Room-new' %}</span>{% endif %}
       </div>
       <div class="card-body">
+          {% if legal_warning %}<div class="alert alert-warning">{{ legal_warning }}</div>{% endif %}
+
           {% bootstrap_form form %}
       </div>
 {% if can_manage %}
@@ -101,7 +103,7 @@
           <button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('{% if room.room_type != 'project' %}{% trans 'Room__remove__confirm' %}{% else %}{% trans 'Project__remove__confirm' %}{% endif %}')">{% if room.room_type != 'project' %}{% trans 'Room__remove' %}{% else %}{% trans 'Project__remove' %}{% endif %}: {{ room.name }}</button>
         </form>
         {% else %}
-        <p>{% if room.room_type != 'project' %}{% trans 'Room__remove__notpossible' %}{% else %}{% trans 'Project__remove__notpossible' %}{% endif %}</p>
+        <p>{% if room.room_type == 'project' %}{% trans 'Project__remove__notpossible' %}{% elif room.room_type == 'hangar' %}{% trans 'Hangar__remove__notpossible' %}{% else %}{% trans 'Room__remove__notpossible' %}{% endif %}</p>
         {% endif %}
       </div>
     </div>
diff --git a/src/backoffice/templates/backoffice/room-new.html b/src/backoffice/templates/backoffice/room-new.html
index 760ce74263e20f2b58f85635b4afdda9c05d986b..73585ddf0e2846a8720cbec5c20d1b43539100f4 100644
--- a/src/backoffice/templates/backoffice/room-new.html
+++ b/src/backoffice/templates/backoffice/room-new.html
@@ -52,6 +52,20 @@ room++ | {{ assembly.name }} | {{ conference.name }}
         </div>
       </div>
 
+      {# Hangar #}
+      <div class="card">
+        <div class="card-body {% if rooms_available.hangar %}border-primary{% else %}border-default{% endif %}">
+          <h5 class="card-title {% if rooms_available.hangar %}text-primary{% else %}text-default{% endif %}">{% trans 'Room-new-hangar' %}</h5>
+          <p class="card-text">{% trans 'Room-new-hangar__help' %}</p>
+        </div>
+        <div class="card-footer">
+          {% if rooms_available.hangar %}
+          <a class="btn btn-sm btn-primary" href="{% url 'backoffice:assembly-create-room' assembly=assembly.id %}?type=hangar">{% trans 'Room-new-hangar__create' %}</a>
+          {% else %}
+          <span class="text-muted" style="font-size: 90%;">{% trans 'Room-new-hangar__unavailable' %}
+          {% endif %}
+        </div>
+      </div>
     </div>{# /card-deck, open a new row #}
     <div class="card-deck mt-4">
 
@@ -114,6 +128,7 @@ room++ | {{ assembly.name }} | {{ conference.name }}
       <div class="card-body">
         <form action="{% url 'backoffice:assembly-create-room' assembly=assembly.id %}" method="POST">{% csrf_token %}
           <input type="hidden" name="type" value="{{ room_type }}">
+          {% if legal_warning %}<div class="alert alert-warning">{{ legal_warning }}</div>{% endif %}
 
           {% bootstrap_form form %}
 
diff --git a/src/backoffice/views/assemblies.py b/src/backoffice/views/assemblies.py
index 3f071346ab769cd8d432b2de31f56472eb5a414c..278026ce64f13298cf48002c8aa5394a500be24f 100644
--- a/src/backoffice/views/assemblies.py
+++ b/src/backoffice/views/assemblies.py
@@ -21,11 +21,11 @@ from core.models.rooms import Room, RoomLink
 from core.models.sso import Application
 from core.models.tags import ConferenceTag
 from core.models.users import PlatformUser
-from core.integrations import BigBlueButton, IntegrationError, WorkAdventure
+from core.integrations import BigBlueButton, Hangar, IntegrationError, WorkAdventure
 
 from ..forms import \
     AssemblyAddApplicationForm, AssemblyAddMemberForm, \
-    AssemblyCreateForm, AssemblyCreateRoomGenericForm, AssemblyCreateRoomBigBlueButtonForm, AssemblyCreateRoomWorkAdventureForm, \
+    AssemblyCreateForm, AssemblyCreateRoomGenericForm, AssemblyCreateRoomBigBlueButtonForm, AssemblyCreateRoomWorkAdventureForm, AssemblyCreateRoomHangarForm, \
     AssemblyEditForm, \
     CreateAssemblyRoomLinkForm, \
     EditAssemblyRoomForm, EditAssemblyRoomWorkAdventureForm, \
@@ -295,6 +295,11 @@ class AssemblyRoomView(AssemblyMixin, UpdateView):
         ctx['createform'] = self.create_roomlink_form or CreateAssemblyRoomLinkForm()
         ctx['supports_links'] = self.object.room_type in Room.TYPES_WITH_LINKS
         ctx['can_delete'] = not Event.objects.filter(conference=self.conference, room=self.object).exists()
+
+        if self.object.room_type == Room.RoomType.HANGAR:
+            ctx['legal_warning'] = _('Room-new-hangar__legal_hint')
+            ctx['can_delete'] = False
+
         return ctx
 
     def get_object(self, *args, **kwargs):
@@ -604,6 +609,10 @@ class BadgeView(AssemblyMixin, UpdateView):
         return reverse('backoffice:assembly-badges', kwargs={'assembly': self.assembly.id})
 
 
+class RoomNotAvailableError(Exception):
+    pass
+
+
 class CreateRoomView(AssemblyMixin, FormView):
     assembly_url_param = 'assembly'
     template_name = 'backoffice/room-new.html'
@@ -611,28 +620,43 @@ class CreateRoomView(AssemblyMixin, FormView):
 
     def dispatch(self, *args, **kwargs):
         self.room_type = (self.request.POST if self.request.method != 'GET' else self.request.GET).get('type', None)
-        return super().dispatch(*args, **kwargs)
+        try:
+            return super().dispatch(*args, **kwargs)
+        except RoomNotAvailableError:
+            return redirect('backoffice:assembly-create-room', assembly=self.assembly.id)
 
     def get_form(self, *args, **kwargs):
+        if self.room_type is None:
+            return None
+
         if self.room_type == Room.RoomType.BIGBLUEBUTTON:
             if BigBlueButton is None or not BigBlueButton.can_create_for_assembly(self.assembly):
                 messages.error(self.request, 'BBB not available')
-                return redirect('backoffice:assembly-create-room', assembly=self.assembly.id)
+                raise RoomNotAvailableError()
 
             return AssemblyCreateRoomBigBlueButtonForm(self.request.POST, assembly=self.assembly)
 
         if self.room_type == Room.RoomType.WORKADVENTURE:
             if WorkAdventure is None or not WorkAdventure.can_create_for_assembly(self.assembly):
                 messages.error(self.request, 'WA not available')
-                return redirect('backoffice:assembly-create-room', assembly=self.assembly.id)
+                raise RoomNotAvailableError()
 
             return AssemblyCreateRoomWorkAdventureForm(self.request.POST, assembly=self.assembly)
 
-        if self.room_type:
+        if self.room_type == Room.RoomType.HANGAR:
+            if Hangar is None or not Hangar.can_create_for_assembly(self.assembly):
+                messages.error(self.request, 'Hangar not available')
+                raise RoomNotAvailableError()
+
+            return AssemblyCreateRoomHangarForm(self.request.POST, assembly=self.assembly)
+
+        if self.room_type in Room.RoomType.values:
             return AssemblyCreateRoomGenericForm(self.request.POST, assembly=self.assembly, initial={'room_type': self.room_type})
 
         else:
-            return None
+            logger.warning('Unexpected room_type "%s" upon creating new room for %s.', self.room_type, self.assembly)
+            messages.warning(self.request, _('internal_error_please_retry'))
+            raise RoomNotAvailableError()
 
     def get_context_data(self, *args, **kwargs):
         ctx = super().get_context_data(*args, **kwargs)
@@ -643,8 +667,12 @@ class CreateRoomView(AssemblyMixin, FormView):
             rooms_available.update({
                 'workadventure': WorkAdventure is not None and WorkAdventure.can_create_for_assembly(self.assembly),
                 'bbb': BigBlueButton is not None and BigBlueButton.can_create_for_assembly(self.assembly),
+                'hangar': Hangar is not None and Hangar.can_create_for_assembly(self.assembly),
             })
 
+        elif self.room_type == Room.RoomType.HANGAR:
+            ctx['legal_warning'] = _('Room-new-hangar__legal_hint')
+
         return ctx
 
     def form_valid(self, form):
diff --git a/src/core/integrations/__init__.py b/src/core/integrations/__init__.py
index 20f1b1bac6a82eae26ba929b152399557b14be9f..8ded4750e683cc544adbdef7582db2ef484f20e8 100644
--- a/src/core/integrations/__init__.py
+++ b/src/core/integrations/__init__.py
@@ -1,5 +1,6 @@
 from django.conf import settings
 from .bigbluebutton import BigBlueButtonIntegration
+from .rc3hangar import HangarIntegration
 from .error import IntegrationError
 from .workadventure import WorkAdventureIntegration
 
@@ -7,11 +8,18 @@ if settings.BIGBLUEBUTTON_API_URL is not None:
     BigBlueButton = BigBlueButtonIntegration(settings.BIGBLUEBUTTON_API_URL, settings.BIGBLUEBUTTON_API_TOKEN, settings.BIGBLUEBUTTON_END_MEETING_CALLBACK)
 else:
     BigBlueButton = None  # type: BigBlueButtonIntegration
+
+if settings.HANGAR_URL is not None:
+    Hangar = HangarIntegration(settings.HANGAR_URL)
+else:
+    Hangar = None
+
 WorkAdventure = WorkAdventureIntegration()
 
 
 __all__ = [
     'BigBlueButton',
+    'Hangar',
     'IntegrationError',
     'WorkAdventure',
 ]
diff --git a/src/core/integrations/rc3hangar.py b/src/core/integrations/rc3hangar.py
new file mode 100644
index 0000000000000000000000000000000000000000..655103297df7462109a55c4c959ab15b3724d37c
--- /dev/null
+++ b/src/core/integrations/rc3hangar.py
@@ -0,0 +1,46 @@
+from core.models.assemblies import Assembly
+from core.models.rooms import Room
+from core.models.users import PlatformUser
+
+
+class HangarIntegration:
+    def __init__(self, url):
+        self._url = url
+
+    def is_available(self):
+        return self._url is not None
+
+    def can_create_for_assembly(self, assembly: Assembly):
+        assert assembly is not None
+
+        # limit to one instance per assembly
+        existing = assembly.rooms.filter(room_type=Room.RoomType.HANGAR).exists()
+        return not existing
+
+    def create_room(self, room: Room):
+        assert room is not None and room.room_type == Room.RoomType.HANGAR and room.backend_status == Room.BackendStatus.NEW
+
+        # status is managed externally
+        pass
+
+    def remove_room(self, room: Room):
+        assert room is not None and room.room_type == Room.RoomType.HANGAR
+
+        # cannot be done here, trigger "contact technician" message
+        return False
+
+    def room_status(self, room: Room):
+        assert room is not None and room.room_type == Room.RoomType.HANGAR
+
+        return room.backend_status
+
+    def join_room(self, room: Room, user: PlatformUser):
+        assert room is not None and room.room_type == Room.RoomType.HANGAR
+        assert user is not None
+
+        url = self._url.format(
+            assembly_slug=room.assembly_slug,
+            room_id=room.id,
+            username=user.username,
+        )
+        return url
diff --git a/src/core/locale/de/LC_MESSAGES/django.po b/src/core/locale/de/LC_MESSAGES/django.po
index 8db02a507ba653bc69d7e0a4c11aa9f770d9a67e..2ba3b3a1edabb4f68915231c26f8c4d831f7e54e 100644
--- a/src/core/locale/de/LC_MESSAGES/django.po
+++ b/src/core/locale/de/LC_MESSAGES/django.po
@@ -771,6 +771,9 @@ msgstr "BigBlueButton"
 msgid "Room__type-workadventure"
 msgstr "WorkAdventure"
 
+msgid "Room__type-hangar"
+msgstr "Hangar"
+
 msgid "Room__type-other"
 msgstr "andere"
 
diff --git a/src/core/locale/en/LC_MESSAGES/django.po b/src/core/locale/en/LC_MESSAGES/django.po
index da07eb5f8d825d3163343d08b83ff8e3bc5c4c14..d415042cbe8c753fec3705d942da123539d03f66 100644
--- a/src/core/locale/en/LC_MESSAGES/django.po
+++ b/src/core/locale/en/LC_MESSAGES/django.po
@@ -771,6 +771,9 @@ msgstr "BigBlueButton"
 msgid "Room__type-workadventure"
 msgstr "WorkAdventure"
 
+msgid "Room__type-hangar"
+msgstr "hangar"
+
 msgid "Room__type-other"
 msgstr "other"
 
diff --git a/src/core/management/commands/hangar_creation.py b/src/core/management/commands/hangar_creation.py
new file mode 100644
index 0000000000000000000000000000000000000000..cf5256c107ce85af2acc4ee7f2615a37dfeeaaae
--- /dev/null
+++ b/src/core/management/commands/hangar_creation.py
@@ -0,0 +1,63 @@
+import logging
+import subprocess
+
+from django.conf import settings
+from django.core.management.base import BaseCommand, CommandError
+from django.utils import timezone
+
+from core.models.rooms import Room
+
+
+def create_hangar(room: Room):
+    username = room.assembly.slug
+    cmd = ['ssh', settings.HANGAR_HOST, settings.HANGAR_CMD, username]
+
+    result = subprocess.run(cmd, capture_output=True, timeout=42, encoding='utf-8', stderr=subprocess.STDOUT)
+    if result.returncode == 0:
+        password = result.stdout
+        room.backend_link = settings.BACKEND_URL.format(username=username, password=password)
+        room.backend_status = Room.BackendStatus.ACTIVE
+
+        all_contacts = room.assembly.get_all_managing_contacts()
+        room.backend_data = {
+            'timestamp': timezone.now(),
+            'contacts': all_contacts,
+        }
+        room.save()
+
+    else:
+        room.backend_data = {
+            'timestamp': timezone.now(),
+            '_error': result.stdout,
+        }
+        room.backend_status = Room.BackendStatus.ERROR
+        room.save()
+
+        raise Exception('Backend creation failed.')
+
+
+class Command(BaseCommand):
+    def handle(self, *args, **options):
+        for x in ['URL', 'BACKEND_URL', 'HOST', 'CMD']:
+            if not hasattr(settings, 'HANGAR_' + x) or getattr(settings, 'HANGAR_' + x) in [None, '']:
+                raise CommandError(f'No HANGAR_{x} configured.')
+
+        if settings.HANGAR_BACKEND_URL is None or settings.HANGAR_BACKEND_URL == '':
+            raise CommandError('No HANGAR_BACKEND_URL configured.')
+
+        rooms = Room.objects.filter(room_type=Room.RoomType.HANGAR, backend_status=Room.BackendStatus.NEW)
+        for room in rooms:
+            room.backend_status = Room.BackendStatus.SETUP
+            room.save()
+
+            try:
+                create_hangar(room)
+
+            except Exception as err:
+                logging.error('Got error on creating hangar for %s: %s', room, err)
+                room.backend_status = Room.BackendStatus.ERROR
+                room.backend_data = {
+                    'timestamp': timezone.now(),
+                    '_exception': str(err),
+                }
+                room.save()
diff --git a/src/core/migrations/0001_initial.py b/src/core/migrations/0001_initial.py
index a07fd132c390383d4348ce4a9f06c3ca0b6ef7d3..fa4518b36821816d522e10439d4ea7e6c924068d 100644
--- a/src/core/migrations/0001_initial.py
+++ b/src/core/migrations/0001_initial.py
@@ -119,7 +119,7 @@ class Migration(migrations.Migration):
             fields=[
                 ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                 ('name', models.CharField(max_length=200)),
-                ('room_type', models.CharField(choices=[('lecturehall', 'Room__type-lecturehall'), ('stage', 'Room__type-stage'), ('workshop', 'Room__type-workshop'), ('outside', 'Room__type-outside'), ('online', 'Room__type-online'), ('project', 'Room__type-project'), ('bbb', 'Room__type-bbb'), ('workadventure', 'Room__type-workadventure'), ('other', 'Room__type-other')], help_text='Room__type__help', max_length=20, verbose_name='Room__type')),
+                ('room_type', models.CharField(choices=[('lecturehall', 'Room__type-lecturehall'), ('stage', 'Room__type-stage'), ('workshop', 'Room__type-workshop'), ('outside', 'Room__type-outside'), ('online', 'Room__type-online'), ('project', 'Room__type-project'), ('bbb', 'Room__type-bbb'), ('workadventure', 'Room__type-workadventure'), ('hangar', 'Room__type-hangar'), ('other', 'Room__type-other')], help_text='Room__type__help', max_length=20, verbose_name='Room__type')),
                 ('capacity', models.PositiveIntegerField(blank=True, help_text='Room__capacity__help', null=True, verbose_name='Room__capacity')),
                 ('conference', core.fields.ConferenceReference(help_text='Conference__reference_help', on_delete=django.db.models.deletion.CASCADE, related_name='rooms', to='core.conference', verbose_name='Conference__reference')),
             ],
diff --git a/src/core/models/assemblies.py b/src/core/models/assemblies.py
index 69cadfbd62940390a4d396c928f2d02c9b51394e..fcbf599818e3f3ba1c7902f88884e55c3effa898 100644
--- a/src/core/models/assemblies.py
+++ b/src/core/models/assemblies.py
@@ -297,6 +297,12 @@ class Assembly(TaggedItemMixin, models.Model):
     def sorted_tags(self):
         return sorted(t['slug'] for t in self.tags)
 
+    def get_all_managing_contacts(self):
+        result = {}
+        for member in self.members.filter(role__in=AssemblyMember.MANAGEMENT_ROLES):
+            result[member.member.username] = member.member.get_verified_contacts()
+        return result
+
     def create_technical_user_if_necessary(self):
         if self.technical_user is not None:
             return self.technical_user
diff --git a/src/core/models/rooms.py b/src/core/models/rooms.py
index 4e5d5c3fd9a9ad258e7747f5c17e703ac07e8445..3df44acb4eabc05867bd5c9b0086418b080b3dc1 100644
--- a/src/core/models/rooms.py
+++ b/src/core/models/rooms.py
@@ -57,9 +57,10 @@ class Room(models.Model):
         PROJECT = 'project', _('Room__type-project')
         BIGBLUEBUTTON = 'bbb', _('Room__type-bbb')
         WORKADVENTURE = 'workadventure', _('Room__type-workadventure')
+        HANGAR = 'hangar', _('Room__type-hangar')
         OTHER = 'other', _('Room__type-other')
 
-    BACKEND_ROOMTYPES = [RoomType.BIGBLUEBUTTON, RoomType.WORKADVENTURE]
+    BACKEND_ROOMTYPES = [RoomType.BIGBLUEBUTTON, RoomType.WORKADVENTURE, RoomType.HANGAR]
     TYPES_WITH_CAPACITY = [RoomType.LECTURE_HALL, RoomType.STAGE, RoomType.WORKSHOP]
     TYPES_WITH_LINKS = [RoomType.PROJECT, RoomType.LECTURE_HALL, RoomType.STAGE, RoomType.WORKSHOP, RoomType.OUTSIDE, RoomType.ONLINE, RoomType.OTHER]
 
diff --git a/src/rc3platform/settings/base.py b/src/rc3platform/settings/base.py
index 4711ef80478f7526688f64860bfee35eee8cc18e..4ef40a5bd8ac6d4c3c6a8be1a05980e8c602bfcf 100644
--- a/src/rc3platform/settings/base.py
+++ b/src/rc3platform/settings/base.py
@@ -217,5 +217,8 @@ BIGBLUEBUTTON_API_TOKEN = None
 BIGBLUEBUTTON_END_MEETING_CALLBACK = None  # url bbb will call to notify us of ending meetings
 # BIGBLUEBUTTON_END_MEETING_CALLBACK = 'https://rc3.world/api/bbb_meeting_end'
 
+# Hangar
+HANGAR_URL = None
+
 # Workadventure
 WORKADVENTURE_URL_SCHEME = 'http://play.{assembly_slug}.localhost:8080/?u={username}'