Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/default_profiles
diff options
context:
space:
mode:
Diffstat (limited to 'archinstall/default_profiles')
-rw-r--r--archinstall/default_profiles/__init__.py0
-rw-r--r--archinstall/default_profiles/applications/__init__.py0
-rw-r--r--archinstall/default_profiles/applications/pipewire.py40
-rw-r--r--archinstall/default_profiles/custom.py218
-rw-r--r--archinstall/default_profiles/desktop.py87
-rw-r--r--archinstall/default_profiles/desktops/__init__.py0
-rw-r--r--archinstall/default_profiles/desktops/awesome.py36
-rw-r--r--archinstall/default_profiles/desktops/bspwm.py30
-rw-r--r--archinstall/default_profiles/desktops/budgie.py30
-rw-r--r--archinstall/default_profiles/desktops/cinnamon.py31
-rw-r--r--archinstall/default_profiles/desktops/cutefish.py31
-rw-r--r--archinstall/default_profiles/desktops/deepin.py28
-rw-r--r--archinstall/default_profiles/desktops/enlightenment.py27
-rw-r--r--archinstall/default_profiles/desktops/gnome.py27
-rw-r--r--archinstall/default_profiles/desktops/i3.py33
-rw-r--r--archinstall/default_profiles/desktops/kde.py32
-rw-r--r--archinstall/default_profiles/desktops/lxqt.py35
-rw-r--r--archinstall/default_profiles/desktops/mate.py27
-rw-r--r--archinstall/default_profiles/desktops/qtile.py27
-rw-r--r--archinstall/default_profiles/desktops/sway.py66
-rw-r--r--archinstall/default_profiles/desktops/xfce4.py30
-rw-r--r--archinstall/default_profiles/minimal.py15
-rw-r--r--archinstall/default_profiles/profile.py206
-rw-r--r--archinstall/default_profiles/server.py57
-rw-r--r--archinstall/default_profiles/servers/__init__.py0
-rw-r--r--archinstall/default_profiles/servers/cockpit.py19
-rw-r--r--archinstall/default_profiles/servers/docker.py33
-rw-r--r--archinstall/default_profiles/servers/httpd.py19
-rw-r--r--archinstall/default_profiles/servers/lighttpd.py19
-rw-r--r--archinstall/default_profiles/servers/mariadb.py25
-rw-r--r--archinstall/default_profiles/servers/nginx.py19
-rw-r--r--archinstall/default_profiles/servers/postgresql.py26
-rw-r--r--archinstall/default_profiles/servers/sshd.py19
-rw-r--r--archinstall/default_profiles/servers/tomcat.py19
-rw-r--r--archinstall/default_profiles/tailored.py21
-rw-r--r--archinstall/default_profiles/xorg.py21
36 files changed, 1353 insertions, 0 deletions
diff --git a/archinstall/default_profiles/__init__.py b/archinstall/default_profiles/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/archinstall/default_profiles/__init__.py
diff --git a/archinstall/default_profiles/applications/__init__.py b/archinstall/default_profiles/applications/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/archinstall/default_profiles/applications/__init__.py
diff --git a/archinstall/default_profiles/applications/pipewire.py b/archinstall/default_profiles/applications/pipewire.py
new file mode 100644
index 00000000..5d2e5ea3
--- /dev/null
+++ b/archinstall/default_profiles/applications/pipewire.py
@@ -0,0 +1,40 @@
+from typing import List, Union, Any, TYPE_CHECKING
+
+import archinstall
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+from archinstall.lib.models import User
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+class PipewireProfile(Profile):
+ def __init__(self):
+ super().__init__('Pipewire', ProfileType.Application)
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ 'pipewire',
+ 'pipewire-alsa',
+ 'pipewire-jack',
+ 'pipewire-pulse',
+ 'gst-plugin-pipewire',
+ 'libpulse',
+ 'wireplumber'
+ ]
+
+ def _enable_pipewire_for_all(self, install_session: 'Installer'):
+ users: Union[User, List[User]] = archinstall.arguments.get('!users', None)
+ if not isinstance(users, list):
+ users = [users]
+
+ for user in users:
+ install_session.arch_chroot('systemctl enable --user pipewire-pulse.service', run_as=user.username)
+
+ def install(self, install_session: 'Installer'):
+ super().install(install_session)
+ install_session.add_additional_packages(self.packages)
+ self._enable_pipewire_for_all(install_session)
diff --git a/archinstall/default_profiles/custom.py b/archinstall/default_profiles/custom.py
new file mode 100644
index 00000000..f7e100ed
--- /dev/null
+++ b/archinstall/default_profiles/custom.py
@@ -0,0 +1,218 @@
+from typing import List, Dict, Optional, TYPE_CHECKING, Any
+
+from ..lib import menu
+from archinstall.lib.output import log, FormattedOutput
+from archinstall.lib.profile.profiles_handler import profile_handler
+from archinstall.default_profiles.profile import Profile, ProfileType, SelectResult, ProfileInfo, TProfile
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+class CustomProfileList(menu.ListManager):
+ def __init__(self, prompt: str, profiles: List[TProfile]):
+ self._actions = [
+ str(_('Add profile')),
+ str(_('Edit profile')),
+ str(_('Delete profile'))
+ ]
+ super().__init__(prompt, profiles, [self._actions[0]], self._actions[1:])
+
+ def reformat(self, data: List[TProfile]) -> Dict[str, Optional[TProfile]]:
+ table = FormattedOutput.as_table(data)
+ rows = table.split('\n')
+
+ # these are the header rows of the table and do not map to any profile obviously
+ # we're adding 2 spaces as prefix because the menu selector '> ' will be put before
+ # the selectable rows so the header has to be aligned
+ display_data: Dict[str, Optional[TProfile]] = {f' {rows[0]}': None, f' {rows[1]}': None}
+
+ for row, profile in zip(rows[2:], data):
+ row = row.replace('|', '\\|')
+ display_data[row] = profile
+
+ return display_data
+
+ def selected_action_display(self, profile: TProfile) -> str:
+ return profile.name
+
+ def handle_action(
+ self,
+ action: str,
+ entry: Optional['CustomTypeProfile'],
+ data: List['CustomTypeProfile']
+ ) -> List['CustomTypeProfile']:
+ if action == self._actions[0]: # add
+ new_profile = self._add_profile()
+ if new_profile is not None:
+ # in case a profile with the same name as an existing profile
+ # was created we'll replace the existing one
+ data = [d for d in data if d.name != new_profile.name]
+ data += [new_profile]
+ elif entry is not None:
+ if action == self._actions[1]: # edit
+ new_profile = self._add_profile(entry)
+ if new_profile is not None:
+ # we'll remove the original profile and add the modified version
+ data = [d for d in data if d.name != entry.name and d.name != new_profile.name]
+ data += [new_profile]
+ elif action == self._actions[2]: # delete
+ data = [d for d in data if d != entry]
+
+ return data
+
+ def _is_new_profile_name(self, name: str) -> bool:
+ existing_profile = profile_handler.get_profile_by_name(name)
+ if existing_profile is not None and existing_profile.profile_type != ProfileType.CustomType:
+ return False
+ return True
+
+ def _add_profile(self, editing: Optional['CustomTypeProfile'] = None) -> Optional['CustomTypeProfile']:
+ name_prompt = '\n\n' + str(_('Profile name: '))
+
+ while True:
+ profile_name = menu.TextInput(name_prompt, editing.name if editing else '').run().strip()
+
+ if not profile_name:
+ return None
+
+ if not self._is_new_profile_name(profile_name):
+ error_prompt = str(_("The profile name you entered is already in use. Try again"))
+ print(error_prompt)
+ else:
+ break
+
+ packages_prompt = str(_('Packages to be install with this profile (space separated, leave blank to skip): '))
+ edit_packages = ' '.join(editing.packages) if editing else ''
+ packages = menu.TextInput(packages_prompt, edit_packages).run().strip()
+
+ services_prompt = str(_('Services to be enabled with this profile (space separated, leave blank to skip): '))
+ edit_services = ' '.join(editing.services) if editing else ''
+ services = menu.TextInput(services_prompt, edit_services).run().strip()
+
+ choice = menu.Menu(
+ str(_('Should this profile be enabled for installation?')),
+ menu.Menu.yes_no(),
+ skip=False,
+ default_option=menu.Menu.no(),
+ clear_screen=False,
+ show_search_hint=False
+ ).run()
+
+ enable_profile = True if choice.value == menu.Menu.yes() else False
+
+ profile = CustomTypeProfile(
+ profile_name,
+ enabled=enable_profile,
+ packages=packages.split(' '),
+ services=services.split(' ')
+ )
+
+ return profile
+
+
+# TODO
+# Still needs some ironing out
+class CustomProfile():
+ def __init__(self):
+ super().__init__(
+ 'Custom',
+ ProfileType.Custom,
+ description=str(_('Create your own'))
+ )
+
+ def json(self) -> Dict[str, Any]:
+ data: Dict[str, Any] = {'main': self.name, 'gfx_driver': self.gfx_driver, 'custom': []}
+
+ for profile in self._current_selection:
+ data['custom'].append({
+ 'name': profile.name,
+ 'packages': profile.packages,
+ 'services': profile.services,
+ 'enabled': profile.custom_enabled
+ })
+
+ return data
+
+ def do_on_select(self) -> SelectResult:
+ custom_profile_list = CustomProfileList('', profile_handler.get_custom_profiles())
+ custom_profiles = custom_profile_list.run()
+
+ # we'll first remove existing custom default_profiles with
+ # the same name and then add the new ones this
+ # will avoid errors of default_profiles with duplicate naming
+ profile_handler.remove_custom_profiles(custom_profiles)
+ profile_handler.add_custom_profiles(custom_profiles)
+
+ self.set_current_selection(custom_profiles)
+
+ if custom_profile_list.is_last_choice_cancel():
+ return SelectResult.SameSelection
+
+ enabled_profiles = [p for p in self._current_selection if p.custom_enabled]
+ # in case we only created inactive default_profiles we wanna store them but
+ # we want to reset the original setting
+ if not enabled_profiles:
+ return SelectResult.ResetCurrent
+
+ return SelectResult.NewSelection
+
+ def post_install(self, install_session: 'Installer'):
+ for profile in self._current_selection:
+ profile.post_install(install_session)
+
+ def install(self, install_session: 'Installer'):
+ driver_packages = self.gfx_driver_packages()
+ install_session.add_additional_packages(driver_packages)
+
+ for profile in self._current_selection:
+ if profile.custom_enabled:
+ log(f'Installing custom profile {profile.name}...')
+
+ install_session.add_additional_packages(profile.packages)
+ install_session.enable_service(profile.services)
+
+ profile.install(install_session)
+
+ def info(self) -> Optional[ProfileInfo]:
+ enabled_profiles = [p for p in self._current_selection if p.custom_enabled]
+ if enabled_profiles:
+ details = ', '.join([p.name for p in enabled_profiles])
+ gfx_driver = self.gfx_driver
+ return ProfileInfo(self.name, details, gfx_driver)
+
+ return None
+
+ def reset(self):
+ for profile in self._current_selection:
+ profile.set_enabled(False)
+
+ self.gfx_driver = None
+
+
+class CustomTypeProfile(Profile):
+ def __init__(
+ self,
+ name: str,
+ enabled: bool = False,
+ packages: List[str] = [],
+ services: List[str] = []
+ ):
+ super().__init__(
+ name,
+ ProfileType.CustomType,
+ packages=packages,
+ services=services,
+ support_gfx_driver=True
+ )
+
+ self.custom_enabled = enabled
+
+ def json(self) -> Dict[str, Any]:
+ return {
+ 'name': self.name,
+ 'packages': self.packages,
+ 'services': self.services,
+ 'enabled': self.custom_enabled
+ }
diff --git a/archinstall/default_profiles/desktop.py b/archinstall/default_profiles/desktop.py
new file mode 100644
index 00000000..2351bd08
--- /dev/null
+++ b/archinstall/default_profiles/desktop.py
@@ -0,0 +1,87 @@
+from typing import Any, TYPE_CHECKING, List, Optional, Dict
+
+from archinstall.lib import menu
+from archinstall.lib.output import log
+from archinstall.lib.profile.profiles_handler import profile_handler
+from archinstall.default_profiles.profile import Profile, ProfileType, SelectResult, GreeterType
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+class DesktopProfile(Profile):
+ def __init__(self, current_selection: List[Profile] = []):
+ super().__init__(
+ 'Desktop',
+ ProfileType.Desktop,
+ description=str(_('Provides a selection of desktop environments and tiling window managers, e.g. gnome, kde, sway')),
+ current_selection=current_selection,
+ support_greeter=True
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ 'nano',
+ 'vim',
+ 'openssh',
+ 'htop',
+ 'wget',
+ 'iwd',
+ 'wireless_tools',
+ 'wpa_supplicant',
+ 'smartmontools',
+ 'xdg-utils'
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ combined_greeters: Dict[GreeterType, int] = {}
+ for profile in self.current_selection:
+ if profile.default_greeter_type:
+ combined_greeters.setdefault(profile.default_greeter_type, 0)
+ combined_greeters[profile.default_greeter_type] += 1
+
+ if len(combined_greeters) >= 1:
+ return list(combined_greeters)[0]
+
+ return None
+
+ def _do_on_select_profiles(self):
+ for profile in self.current_selection:
+ profile.do_on_select()
+
+ def do_on_select(self) -> SelectResult:
+ choice = profile_handler.select_profile(
+ profile_handler.get_desktop_profiles(),
+ self._current_selection,
+ title=str(_('Select your desired desktop environment')),
+ multi=True
+ )
+
+ match choice.type_:
+ case menu.MenuSelectionType.Selection:
+ self.set_current_selection(choice.value) # type: ignore
+ self._do_on_select_profiles()
+ return SelectResult.NewSelection
+ case menu.MenuSelectionType.Skip:
+ return SelectResult.SameSelection
+ case menu.MenuSelectionType.Reset:
+ return SelectResult.ResetCurrent
+
+ def post_install(self, install_session: 'Installer'):
+ for profile in self._current_selection:
+ profile.post_install(install_session)
+
+ def install(self, install_session: 'Installer'):
+ # Install common packages for all desktop environments
+ install_session.add_additional_packages(self.packages)
+
+ for profile in self._current_selection:
+ log(f'Installing profile {profile.name}...')
+
+ install_session.add_additional_packages(profile.packages)
+ install_session.enable_service(profile.services)
+
+ profile.install(install_session)
diff --git a/archinstall/default_profiles/desktops/__init__.py b/archinstall/default_profiles/desktops/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/archinstall/default_profiles/desktops/__init__.py
diff --git a/archinstall/default_profiles/desktops/awesome.py b/archinstall/default_profiles/desktops/awesome.py
new file mode 100644
index 00000000..bb481914
--- /dev/null
+++ b/archinstall/default_profiles/desktops/awesome.py
@@ -0,0 +1,36 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+class AwesomeProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Awesome', ProfileType.WindowMgr, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return ['alacritty']
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
+
+ def install(self, install_session: 'Installer'):
+ super().install(install_session)
+
+ # TODO: Copy a full configuration to ~/.config/awesome/rc.lua instead.
+ with open(f"{install_session.target}/etc/xdg/awesome/rc.lua", 'r') as fh:
+ awesome_lua = fh.read()
+
+ # Replace xterm with alacritty for a smoother experience.
+ awesome_lua = awesome_lua.replace('"xterm"', '"alacritty"')
+
+ with open(f"{install_session.target}/etc/xdg/awesome/rc.lua", 'w') as fh:
+ fh.write(awesome_lua)
+
+ # TODO: Configure the right-click-menu to contain the above packages that were installed. (as a user config)
diff --git a/archinstall/default_profiles/desktops/bspwm.py b/archinstall/default_profiles/desktops/bspwm.py
new file mode 100644
index 00000000..f3bc982d
--- /dev/null
+++ b/archinstall/default_profiles/desktops/bspwm.py
@@ -0,0 +1,30 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class BspwmProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Bspwm', ProfileType.WindowMgr, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ 'bspwm',
+ 'sxhkd',
+ 'dmenu',
+ 'xdo',
+ 'rxvt-unicode'
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/budgie.py b/archinstall/default_profiles/desktops/budgie.py
new file mode 100644
index 00000000..32bd718d
--- /dev/null
+++ b/archinstall/default_profiles/desktops/budgie.py
@@ -0,0 +1,30 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class BudgieProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Budgie', ProfileType.DesktopEnv, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "arc-gtk-theme",
+ "budgie",
+ "mate-terminal",
+ "nemo",
+ "papirus-icon-theme",
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/cinnamon.py b/archinstall/default_profiles/desktops/cinnamon.py
new file mode 100644
index 00000000..22fd0d9d
--- /dev/null
+++ b/archinstall/default_profiles/desktops/cinnamon.py
@@ -0,0 +1,31 @@
+from typing import Optional, List, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class CinnamonProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Cinnamon', ProfileType.DesktopEnv, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "cinnamon",
+ "system-config-printer",
+ "gnome-keyring",
+ "gnome-terminal",
+ "blueberry",
+ "metacity"
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/cutefish.py b/archinstall/default_profiles/desktops/cutefish.py
new file mode 100644
index 00000000..6f88c47a
--- /dev/null
+++ b/archinstall/default_profiles/desktops/cutefish.py
@@ -0,0 +1,31 @@
+from typing import Optional, List, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+class CutefishProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Cutefish', ProfileType.DesktopEnv, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "cutefish",
+ "noto-fonts"
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Sddm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
+
+ def install(self, install_session: 'Installer'):
+ super().install(install_session)
diff --git a/archinstall/default_profiles/desktops/deepin.py b/archinstall/default_profiles/desktops/deepin.py
new file mode 100644
index 00000000..054c8fdf
--- /dev/null
+++ b/archinstall/default_profiles/desktops/deepin.py
@@ -0,0 +1,28 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class DeepinProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Deepin', ProfileType.DesktopEnv, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "deepin",
+ "deepin-terminal",
+ "deepin-editor"
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/enlightenment.py b/archinstall/default_profiles/desktops/enlightenment.py
new file mode 100644
index 00000000..164f64fe
--- /dev/null
+++ b/archinstall/default_profiles/desktops/enlightenment.py
@@ -0,0 +1,27 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class EnlighenmentProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Enlightenment', ProfileType.WindowMgr, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "enlightenment",
+ "terminology"
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/gnome.py b/archinstall/default_profiles/desktops/gnome.py
new file mode 100644
index 00000000..3cbd49bd
--- /dev/null
+++ b/archinstall/default_profiles/desktops/gnome.py
@@ -0,0 +1,27 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class GnomeProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Gnome', ProfileType.DesktopEnv, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ 'gnome',
+ 'gnome-tweaks'
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Gdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/i3.py b/archinstall/default_profiles/desktops/i3.py
new file mode 100644
index 00000000..7c6f24ca
--- /dev/null
+++ b/archinstall/default_profiles/desktops/i3.py
@@ -0,0 +1,33 @@
+from typing import Optional, List, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class I3wmProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('i3-wm', ProfileType.WindowMgr, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ 'i3-wm',
+ 'i3lock',
+ 'i3status',
+ 'i3blocks',
+ 'xterm',
+ 'lightdm-gtk-greeter',
+ 'lightdm',
+ 'dmenu',
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/kde.py b/archinstall/default_profiles/desktops/kde.py
new file mode 100644
index 00000000..cd02e069
--- /dev/null
+++ b/archinstall/default_profiles/desktops/kde.py
@@ -0,0 +1,32 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class KdeProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Kde', ProfileType.DesktopEnv, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "plasma-meta",
+ "konsole",
+ "kwrite",
+ "dolphin",
+ "ark",
+ "plasma-wayland-session",
+ "egl-wayland"
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Sddm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/lxqt.py b/archinstall/default_profiles/desktops/lxqt.py
new file mode 100644
index 00000000..146e168e
--- /dev/null
+++ b/archinstall/default_profiles/desktops/lxqt.py
@@ -0,0 +1,35 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class LxqtProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Lxqt', ProfileType.DesktopEnv, description='')
+
+ # NOTE: SDDM is the only officially supported greeter for LXQt, so unlike other DEs, lightdm is not used here.
+ # LXQt works with lightdm, but since this is not supported, we will not default to this.
+ # https://github.com/lxqt/lxqt/issues/795
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "lxqt",
+ "breeze-icons",
+ "oxygen-icons",
+ "xdg-utils",
+ "ttf-freefont",
+ "leafpad",
+ "slock",
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Sddm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/mate.py b/archinstall/default_profiles/desktops/mate.py
new file mode 100644
index 00000000..0ddaaaab
--- /dev/null
+++ b/archinstall/default_profiles/desktops/mate.py
@@ -0,0 +1,27 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class MateProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Mate', ProfileType.DesktopEnv, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "mate",
+ "mate-extra"
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/qtile.py b/archinstall/default_profiles/desktops/qtile.py
new file mode 100644
index 00000000..66c6fa1b
--- /dev/null
+++ b/archinstall/default_profiles/desktops/qtile.py
@@ -0,0 +1,27 @@
+from typing import Optional, List, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class QtileProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('Qtile', ProfileType.WindowMgr, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ 'qtile',
+ 'alacritty'
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/desktops/sway.py b/archinstall/default_profiles/desktops/sway.py
new file mode 100644
index 00000000..519f5bbb
--- /dev/null
+++ b/archinstall/default_profiles/desktops/sway.py
@@ -0,0 +1,66 @@
+from typing import List, Optional, TYPE_CHECKING, Any
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+from archinstall.lib.menu import Menu
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+class SwayProfile(XorgProfile):
+ def __init__(self):
+ super().__init__(
+ 'Sway',
+ ProfileType.WindowMgr,
+ description=''
+ )
+ self._control_preference = []
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "sway",
+ "swaybg",
+ "swaylock",
+ "swayidle",
+ "waybar",
+ "dmenu",
+ "brightnessctl",
+ "grim",
+ "slurp",
+ "pavucontrol",
+ "foot",
+ "xorg-xwayland"
+ ] + self._control_preference
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ @property
+ def services(self) -> List[str]:
+ if "seatd" in self._control_preference:
+ return ['seatd']
+ elif "polkit" in self._control_preference:
+ return ['polkit']
+
+ return []
+
+ def _get_system_privelege_control_preference(self):
+ # need to activate seat service and add to seat group
+ title = str(_('Sway needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)'))
+ title += str(_('\n\nChoose an option to give Sway access to your hardware'))
+ choice = Menu(title, ["polkit", "seatd"], skip=False).run()
+ self._control_preference = [choice.value]
+
+ def do_on_select(self):
+ self._get_system_privelege_control_preference()
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
+
+ def install(self, install_session: 'Installer'):
+ super().install(install_session)
diff --git a/archinstall/default_profiles/desktops/xfce4.py b/archinstall/default_profiles/desktops/xfce4.py
new file mode 100644
index 00000000..bd6c3038
--- /dev/null
+++ b/archinstall/default_profiles/desktops/xfce4.py
@@ -0,0 +1,30 @@
+from typing import List, Optional, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType, GreeterType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class Xfce4Profile(XorgProfile):
+ def __init__(self):
+ super().__init__('Xfce4', ProfileType.DesktopEnv, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return [
+ "xfce4",
+ "xfce4-goodies",
+ "pavucontrol",
+ "gvfs",
+ "xarchiver"
+ ]
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ return GreeterType.Lightdm
+
+ def preview_text(self) -> Optional[str]:
+ text = str(_('Environment type: {}')).format(self.profile_type.value)
+ return text + '\n' + self.packages_text()
diff --git a/archinstall/default_profiles/minimal.py b/archinstall/default_profiles/minimal.py
new file mode 100644
index 00000000..f78708e9
--- /dev/null
+++ b/archinstall/default_profiles/minimal.py
@@ -0,0 +1,15 @@
+from typing import Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class MinimalProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'Minimal',
+ ProfileType.Minimal,
+ description=str(_('A very basic installation that allows you to customize Arch Linux as you see fit.'))
+ )
diff --git a/archinstall/default_profiles/profile.py b/archinstall/default_profiles/profile.py
new file mode 100644
index 00000000..c7d6b3dc
--- /dev/null
+++ b/archinstall/default_profiles/profile.py
@@ -0,0 +1,206 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+from enum import Enum, auto
+from typing import List, Optional, Any, Dict, TYPE_CHECKING, TypeVar
+
+from archinstall.lib.output import FormattedOutput
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+TProfile = TypeVar('TProfile', bound='Profile')
+
+
+class ProfileType(Enum):
+ # top level default_profiles
+ Server = 'Server'
+ Desktop = 'Desktop'
+ Xorg = 'Xorg'
+ Minimal = 'Minimal'
+ Custom = 'Custom'
+ # detailed selection default_profiles
+ ServerType = 'ServerType'
+ WindowMgr = 'Window Manager'
+ DesktopEnv = 'Desktop Environment'
+ CustomType = 'CustomType'
+ # special things
+ Tailored = 'Tailored'
+ Application = 'Application'
+
+
+class GreeterType(Enum):
+ Lightdm = 'lightdm'
+ Sddm = 'sddm'
+ Gdm = 'gdm'
+
+
+class SelectResult(Enum):
+ NewSelection = auto()
+ SameSelection = auto()
+ ResetCurrent = auto()
+
+
+@dataclass
+class ProfileInfo:
+ name: str
+ details: Optional[str]
+ gfx_driver: Optional[str] = None
+ greeter: Optional[str] = None
+
+ @property
+ def absolute_name(self) -> str:
+ if self.details is not None:
+ return self.details
+ return self.name
+
+
+class Profile:
+ def __init__(
+ self,
+ name: str,
+ profile_type: ProfileType,
+ description: str = '',
+ current_selection: List[TProfile] = [],
+ packages: List[str] = [],
+ services: List[str] = [],
+ support_gfx_driver: bool = False,
+ support_greeter: bool = False
+ ):
+ self.name = name
+ self.description = description
+ self.profile_type = profile_type
+ self._support_gfx_driver = support_gfx_driver
+ self._support_greeter = support_greeter
+
+ # self.gfx_driver: Optional[str] = None
+
+ self._current_selection = current_selection
+ self._packages = packages
+ self._services = services
+
+ # Only used for custom default_profiles
+ self.custom_enabled = False
+
+ @property
+ def current_selection(self) -> List[TProfile]:
+ return self._current_selection
+
+ @property
+ def packages(self) -> List[str]:
+ """
+ Returns a list of packages that should be installed when
+ this profile is among the choosen ones
+ """
+ return self._packages
+
+ @property
+ def services(self) -> List[str]:
+ """
+ Returns a list of services that should be enabled when
+ this profile is among the chosen ones
+ """
+ return self._services
+
+ @property
+ def default_greeter_type(self) -> Optional[GreeterType]:
+ """
+ Setting a default greeter type for a desktop profile
+ """
+ return None
+
+ def install(self, install_session: 'Installer'):
+ """
+ Performs installation steps when this profile was selected
+ """
+
+ def post_install(self, install_session: 'Installer'):
+ """
+ Hook that will be called when the installation process is
+ finished and custom installation steps for specific default_profiles
+ are needed
+ """
+
+ def json(self) -> Dict:
+ """
+ Returns a json representation of the profile
+ """
+ return {}
+
+ def do_on_select(self) -> SelectResult:
+ """
+ Hook that will be called when a profile is selected
+ """
+ return SelectResult.NewSelection
+
+ def current_selection_names(self) -> List[str]:
+ if self._current_selection:
+ return [s.name for s in self._current_selection]
+ return []
+
+ def reset(self):
+ self.set_current_selection([])
+
+ def set_current_selection(self, current_selection: List[TProfile]):
+ self._current_selection = current_selection
+
+ def is_top_level_profile(self) -> bool:
+ top_levels = [ProfileType.Desktop, ProfileType.Server, ProfileType.Xorg, ProfileType.Minimal, ProfileType.Custom]
+ return self.profile_type in top_levels
+
+ def is_desktop_profile(self) -> bool:
+ return self.profile_type == ProfileType.Desktop
+
+ def is_server_type_profile(self) -> bool:
+ return self.profile_type == ProfileType.ServerType
+
+ def is_desktop_type_profile(self) -> bool:
+ return self.profile_type == ProfileType.DesktopEnv or self.profile_type == ProfileType.WindowMgr
+
+ def is_xorg_type_profile(self) -> bool:
+ return self.profile_type == ProfileType.Xorg
+
+ def is_tailored(self) -> bool:
+ return self.profile_type == ProfileType.Tailored
+
+ def is_custom_type_profile(self) -> bool:
+ return self.profile_type == ProfileType.CustomType
+
+ def is_graphic_driver_supported(self) -> bool:
+ if not self._current_selection:
+ return self._support_gfx_driver
+ else:
+ if any([p._support_gfx_driver for p in self._current_selection]):
+ return True
+ return False
+
+ def is_greeter_supported(self) -> bool:
+ return self._support_greeter
+
+ def preview_text(self) -> Optional[str]:
+ """
+ Used for preview text in profiles_bck. If a description is set for a
+ profile it will automatically display that one in the preivew.
+ If no preview or a different text should be displayed just
+ """
+ if self.description:
+ return self.description
+ return None
+
+ def packages_text(self) -> str:
+ text = str(_('Installed packages')) + ':\n'
+
+ nr_packages = len(self.packages)
+ if nr_packages <= 5:
+ col = 1
+ elif nr_packages <= 10:
+ col = 2
+ elif nr_packages <= 15:
+ col = 3
+ else:
+ col = 4
+
+ text += FormattedOutput.as_columns(self.packages, col)
+ return text
diff --git a/archinstall/default_profiles/server.py b/archinstall/default_profiles/server.py
new file mode 100644
index 00000000..e240b3ef
--- /dev/null
+++ b/archinstall/default_profiles/server.py
@@ -0,0 +1,57 @@
+import logging
+from typing import Any, TYPE_CHECKING, List
+
+from archinstall.lib.output import log
+from archinstall.lib.menu import MenuSelectionType
+from archinstall.lib.profile.profiles_handler import profile_handler
+from archinstall.default_profiles.profile import ProfileType, Profile, SelectResult, TProfile
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+class ServerProfile(Profile):
+ def __init__(self, current_value: List[TProfile] = []):
+ super().__init__(
+ 'Server',
+ ProfileType.Server,
+ description=str(_('Provides a selection of various server packages to install and enable, e.g. httpd, nginx, mariadb')),
+ current_selection=current_value
+ )
+
+ def do_on_select(self) -> SelectResult:
+ available_servers = profile_handler.get_server_profiles()
+
+ choice = profile_handler.select_profile(
+ available_servers,
+ self._current_selection,
+ title=str(_('Choose which servers to install, if none then a minimal installation will be done')),
+ multi=True
+ )
+
+ match choice.type_:
+ case MenuSelectionType.Selection:
+ self.set_current_selection(choice.value) # type: ignore
+ return SelectResult.NewSelection
+ case MenuSelectionType.Skip:
+ return SelectResult.SameSelection
+ case MenuSelectionType.Reset:
+ return SelectResult.ResetCurrent
+
+ def post_install(self, install_session: 'Installer'):
+ for profile in self._current_selection:
+ profile.post_install(install_session)
+
+ def install(self, install_session: 'Installer'):
+ server_info = self.current_selection_names()
+ details = ', '.join(server_info)
+ log(f'Now installing the selected servers: {details}', level=logging.INFO)
+
+ for server in self._current_selection:
+ log(f'Installing {server.name}...', level=logging.INFO)
+ install_session.add_additional_packages(server.packages)
+ install_session.enable_service(server.services)
+ server.install(install_session)
+
+ log('If your selections included multiple servers with the same port, you may have to reconfigure them.', fg="yellow", level=logging.INFO)
diff --git a/archinstall/default_profiles/servers/__init__.py b/archinstall/default_profiles/servers/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/archinstall/default_profiles/servers/__init__.py
diff --git a/archinstall/default_profiles/servers/cockpit.py b/archinstall/default_profiles/servers/cockpit.py
new file mode 100644
index 00000000..8cac0976
--- /dev/null
+++ b/archinstall/default_profiles/servers/cockpit.py
@@ -0,0 +1,19 @@
+from typing import List
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+
+class CockpitProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'Cockpit',
+ ProfileType.ServerType
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['cockpit', 'udisks2', 'packagekit']
+
+ @property
+ def services(self) -> List[str]:
+ return ['cockpit.socket']
diff --git a/archinstall/default_profiles/servers/docker.py b/archinstall/default_profiles/servers/docker.py
new file mode 100644
index 00000000..e6e17831
--- /dev/null
+++ b/archinstall/default_profiles/servers/docker.py
@@ -0,0 +1,33 @@
+from typing import List, Union, TYPE_CHECKING
+
+import archinstall
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+from archinstall.lib.models import User
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+
+
+class DockerProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'Docker',
+ ProfileType.ServerType
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['docker']
+
+ @property
+ def services(self) -> List[str]:
+ return ['docker']
+
+ def post_install(self, install_session: 'Installer'):
+ users: Union[User, List[User]] = archinstall.arguments.get('!users', None)
+ if not isinstance(users, list):
+ users = [users]
+
+ for user in users:
+ install_session.arch_chroot(f'usermod -a -G docker {user.username}')
diff --git a/archinstall/default_profiles/servers/httpd.py b/archinstall/default_profiles/servers/httpd.py
new file mode 100644
index 00000000..595ce84f
--- /dev/null
+++ b/archinstall/default_profiles/servers/httpd.py
@@ -0,0 +1,19 @@
+from typing import List
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+
+class HttpdProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'httpd',
+ ProfileType.ServerType
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['apache']
+
+ @property
+ def services(self) -> List[str]:
+ return ['httpd']
diff --git a/archinstall/default_profiles/servers/lighttpd.py b/archinstall/default_profiles/servers/lighttpd.py
new file mode 100644
index 00000000..00aa5564
--- /dev/null
+++ b/archinstall/default_profiles/servers/lighttpd.py
@@ -0,0 +1,19 @@
+from typing import List
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+
+class LighttpdProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'Lighttpd',
+ ProfileType.ServerType
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['lighttpd']
+
+ @property
+ def services(self) -> List[str]:
+ return ['lighttpd']
diff --git a/archinstall/default_profiles/servers/mariadb.py b/archinstall/default_profiles/servers/mariadb.py
new file mode 100644
index 00000000..4506f1bc
--- /dev/null
+++ b/archinstall/default_profiles/servers/mariadb.py
@@ -0,0 +1,25 @@
+from typing import List, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+
+
+class MariadbProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'Mariadb',
+ ProfileType.ServerType
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['mariadb']
+
+ @property
+ def services(self) -> List[str]:
+ return ['mariadb']
+
+ def post_install(self, install_session: 'Installer'):
+ install_session.arch_chroot('mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql')
diff --git a/archinstall/default_profiles/servers/nginx.py b/archinstall/default_profiles/servers/nginx.py
new file mode 100644
index 00000000..6038616c
--- /dev/null
+++ b/archinstall/default_profiles/servers/nginx.py
@@ -0,0 +1,19 @@
+from typing import List
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+
+class NginxProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'Nginx',
+ ProfileType.ServerType
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['nginx']
+
+ @property
+ def services(self) -> List[str]:
+ return ['nginx']
diff --git a/archinstall/default_profiles/servers/postgresql.py b/archinstall/default_profiles/servers/postgresql.py
new file mode 100644
index 00000000..dba722ce
--- /dev/null
+++ b/archinstall/default_profiles/servers/postgresql.py
@@ -0,0 +1,26 @@
+from typing import List, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+
+
+class PostgresqlProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'Postgresql',
+ ProfileType.ServerType,
+ ''
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['postgresql']
+
+ @property
+ def services(self) -> List[str]:
+ return ['postgresql']
+
+ def post_install(self, install_session: 'Installer'):
+ install_session.arch_chroot("initdb -D /var/lib/postgres/data", run_as='postgres')
diff --git a/archinstall/default_profiles/servers/sshd.py b/archinstall/default_profiles/servers/sshd.py
new file mode 100644
index 00000000..7f855b1a
--- /dev/null
+++ b/archinstall/default_profiles/servers/sshd.py
@@ -0,0 +1,19 @@
+from typing import List
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+
+class SshdProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'sshd',
+ ProfileType.ServerType
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['openssh']
+
+ @property
+ def services(self) -> List[str]:
+ return ['sshd']
diff --git a/archinstall/default_profiles/servers/tomcat.py b/archinstall/default_profiles/servers/tomcat.py
new file mode 100644
index 00000000..9bd8837b
--- /dev/null
+++ b/archinstall/default_profiles/servers/tomcat.py
@@ -0,0 +1,19 @@
+from typing import List
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+
+class TomcatProfile(Profile):
+ def __init__(self):
+ super().__init__(
+ 'Tomcat',
+ ProfileType.ServerType
+ )
+
+ @property
+ def packages(self) -> List[str]:
+ return ['tomcat10']
+
+ @property
+ def services(self) -> List[str]:
+ return ['tomcat10']
diff --git a/archinstall/default_profiles/tailored.py b/archinstall/default_profiles/tailored.py
new file mode 100644
index 00000000..62666249
--- /dev/null
+++ b/archinstall/default_profiles/tailored.py
@@ -0,0 +1,21 @@
+from typing import List, Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import ProfileType
+from archinstall.default_profiles.xorg import XorgProfile
+
+if TYPE_CHECKING:
+ from archinstall.lib.installer import Installer
+ _: Any
+
+
+class TailoredProfile(XorgProfile):
+ def __init__(self):
+ super().__init__('52-54-00-12-34-56', ProfileType.Tailored, description='')
+
+ @property
+ def packages(self) -> List[str]:
+ return ['nano', 'wget', 'git']
+
+ def install(self, install_session: 'Installer'):
+ super().install(install_session)
+ # do whatever you like here :)
diff --git a/archinstall/default_profiles/xorg.py b/archinstall/default_profiles/xorg.py
new file mode 100644
index 00000000..553421a4
--- /dev/null
+++ b/archinstall/default_profiles/xorg.py
@@ -0,0 +1,21 @@
+from typing import Any, TYPE_CHECKING
+
+from archinstall.default_profiles.profile import Profile, ProfileType
+
+if TYPE_CHECKING:
+ _: Any
+
+
+class XorgProfile(Profile):
+ def __init__(
+ self,
+ name: str = 'Xorg',
+ profile_type: ProfileType = ProfileType.Xorg,
+ description: str = str(_('Installs a minimal system as well as xorg and graphics drivers.')),
+ ):
+ super().__init__(
+ name,
+ profile_type,
+ description=description,
+ support_gfx_driver=True
+ )