├── .gitignore ├── LICENSE ├── docs ├── DOCS.md ├── README.md ├── logo.svg └── screenshots │ ├── bootsplash.png │ ├── desktop_apps.png │ ├── desktop_overview.jpg │ ├── fastfetch.png │ ├── installer.png │ ├── manager_dashboard.png │ ├── manager_menu.png │ └── starship.png └── installer.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore temp dir 2 | .tmp.* 3 | 4 | # Ignore gum binary 5 | gum 6 | 7 | # Ignore installer files 8 | installer.conf 9 | installer.conf.old 10 | installer.conf.new 11 | installer.log 12 | installer.log.old 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /docs/DOCS.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 | Arch OS Docs 5 |

6 | 7 | # Contents 8 | 9 | 1. [Recommendation](#recommendation) 10 | 2. [Advanced Installation](#advanced-installation) 11 | 3. [Features](#features) 12 | 4. [Technical Information](#technical-information) 13 | 5. [Rescue & Recovery](#rescue--recovery) 14 | 6. [Troubleshooting](#troubleshooting) 15 | 7. [Development](#development) 16 | 8. [Credits](#credits) 17 | 18 | ## Recommendation 19 | 20 |

21 | 22 | For a robust & stable Arch OS experience, install as few additional packages from the official [Arch Repository](https://archlinux.org/packages) or [AUR](https://aur.archlinux.org) as possible. Instead, use [Flatpak](https://flathub.org) or [GNOME Software](https://apps.gnome.org). Furthermore change system files only if absolutely necessary and perform regular package upgrades. 23 | 24 | - Arch OS System Manager: **`arch-os`** 25 | - System information: **`fetch`** 26 | - Update system: **`paru -Syu`** 27 | - Search package: **`paru -Ss `** 28 | - Install package: **`paru -S `** 29 | - List installed packages: **`paru -Qe`** 30 | - Show package info: **`paru -Qi `** 31 | - Remove package: **`paru -Rsn `** 32 | 33 | **Note:** See `~/.aliases` for useful command aliases 34 | 35 | ### GNOME Shortcuts 36 | 37 | **Note:** Only available with default installation preset (desktop). 38 | 39 | - Close Window: **`Super + q`** 40 | - Hide Window: **`Super + h`** 41 | - Toggle Desktop: **`Super + d`** 42 | - Toggle Fullscreen: **`Super + F11`** 43 | 44 | ### Additional Packages (optional) 45 | 46 | **Note:** The target of the respective URL is also the recommended way to install the package. 47 | 48 | - Install [Pika Backup](https://flathub.org/apps/details/org.gnome.World.PikaBackup) for backup and restore home files 49 | - Install [Extension Manager](https://flathub.org/apps/com.mattjakeman.ExtensionManager) for manage GNOME Extensions 50 | - Install [webapp-manager](https://aur.archlinux.org/packages/webapp-manager) for easy creation of web-apps for any website 51 | - Install [preload](https://wiki.archlinux.org/title/Preload) on older machines (start the service after installation: `sudo systemctl enable preload`) 52 | - Install [mutter-performance](https://aur.archlinux.org/packages/mutter-performance) (great on older Intel Graphics with Wayland) 53 | - Install [downgrade](https://aur.archlinux.org/packages/downgrade) when you need to downgrade a package 54 | - Install [EasyEffects](https://flathub.org/de/apps/com.github.wwmm.easyeffects) for Dolby Atmos 55 | - Install [folder-color-nautilus](https://aur.archlinux.org/packages/folder-color-nautilus) for setting colorful folders 56 | - Install [Flatseal](https://flathub.org/apps/com.github.tchx84.Flatseal) to manage Flatpak Permissions 57 | - Install [Warehouse](https://flathub.org/apps/io.github.flattool.Warehouse) to Manage Flatpak Packages 58 | - Install [LocalSend](https://flathub.org/de/apps/org.localsend.localsend_app) to simply share files in same network 59 | - Install [Monitorets](https://flathub.org/de/apps/io.github.jorchube.monitorets) as sticky system monitor 60 | - Install [MissionCenter](https://flathub.org/de/apps/io.missioncenter.MissionCenter) as system monitor 61 | - Install [Parabolic](https://flathub.org/de/apps/org.nickvision.tubeconverter) as download manager 62 | - Install [Amberol](https://archlinux.org/packages/extra/x86_64/amberol/) or [Gapless](https://flathub.org/apps/com.github.neithern.g4music) as music player 63 | - Install [noisetorch](https://aur.archlinux.org/packages/noisetorch) for microphone noise suppression 64 | - Install [AddWater](https://flathub.org/apps/dev.qwery.AddWater) for Firefox GNOME Theme 65 | - Install [MenuLibre](https://aur.archlinux.org/packages/menulibre) as desktop app editor 66 | - Install [File Roller](https://archlinux.org/packages/extra/x86_64/file-roller/) as archive helper tool 67 | - Install [GNOME Firmware](https://archlinux.org/packages/extra/x86_64/gnome-firmware/) to update firmware of the local hardware 68 | - Install [seahorse](https://archlinux.org/packages/extra/x86_64/seahorse/) as keyring editor (login password can be set to empty) 69 | - Install [dconf-editor](https://archlinux.org/packages/extra/x86_64/dconf-editor/) as graphical tool for `gsettings` and `dconf` 70 | - Install [GNOME Tweaks](https://archlinux.org/packages/extra/x86_64/gnome-tweaks/) as graphical tool for advanced GNOME settings 71 | - Install [Refine](https://flathub.org/apps/page.tesk.Refine) as replacement for GNOME Tweaks 72 | - Install [Ferdium](https://flathub.org/apps/org.ferdium.Ferdium) for all web services at one place 73 | - Install [Alpaca](https://flathub.org/apps/com.jeffser.Alpaca) for local AI support 74 | - Install [Ignition](https://flathub.org/apps/io.github.flattool.Ignition) to manage GNOME autostart files 75 | - Install [Papers](https://flathub.org/apps/org.gnome.Papers) as elegant document viewer for GNOME 76 | - Install [GDM Settings](https://flathub.org/apps/io.github.realmazharhussain.GdmSettings) GDM Login Manager Settings 77 | 78 | ### Theming (optional) 79 | 80 | - Desktop Font: [inter-font](https://archlinux.org/packages/extra/any/inter-font/), [adwaita-fonts](https://archlinux.org/packages/extra/any/adwaita-fonts/) 81 | - Desktop Theme: [adw-gtk3](https://github.com/lassekongo83/adw-gtk3) 82 | - Icon Theme: [tela-icon-theme](https://github.com/vinceliuice/Tela-icon-theme), [tela-circle-icon-theme](https://github.com/vinceliuice/Tela-circle-icon-theme) 83 | - Cursor Theme: [bibata-cursor](https://aur.archlinux.org/packages/bibata-cursor-theme-bin), [nordzy-cursors](https://github.com/alvatip/Nordzy-cursors) 84 | - Firefox Theme: [AddWater](https://flathub.org/apps/dev.qwery.AddWater), [firefox-gnome-theme](https://github.com/rafaelmardojai/firefox-gnome-theme) 85 | - GNOME GTK3 Theme Variant: [adw-gtk3-colorizer](https://extensions.gnome.org/extension/8084/adw-gtk3-colorizer/) 86 | 87 | ### GNOME Extensions (optional) 88 | 89 | - [archlinux-updates-indicator](https://extensions.gnome.org/extension/1010/archlinux-updates-indicator/) 90 | - [app-indicator-support](https://extensions.gnome.org/extension/615/appindicator-support/) 91 | - [weather-oclock](https://extensions.gnome.org/extension/5470/weather-oclock/) 92 | - [just-perfection](https://extensions.gnome.org/extension/3843/just-perfection/) 93 | - [dash-to-panel](https://extensions.gnome.org/extension/1160/dash-to-panel/) 94 | - [dash-to-dock](https://extensions.gnome.org/extension/307/dash-to-dock/) 95 | - [caffeine](https://extensions.gnome.org/extension/517/caffeine/) 96 | - [tiling-assistant](https://extensions.gnome.org/extension/3733/tiling-assistant/) 97 | - [happy-appy-hotkey](https://extensions.gnome.org/extension/6057/happy-appy-hotkey/) 98 | - [app-hider](https://extensions.gnome.org/extension/5895/app-hider/) 99 | - [hide-minimized](https://extensions.gnome.org/extension/2639/hide-minimized/) 100 | - [blur-my-shell](https://extensions.gnome.org/extension/3193/blur-my-shell/) 101 | - [open-bar](https://extensions.gnome.org/extension/6580/open-bar/) 102 | - [vitals](https://extensions.gnome.org/extension/1460/vitals/) 103 | - [system-monitor](https://extensions.gnome.org/extension/6807/system-monitor/) 104 | - [fullscreen-to-empty-workspace](https://extensions.gnome.org/extension/7559/fullscreen-to-empty-workspace/) (open fullscreen apps on new workspace) 105 | - [disable-unredirect-fullscreen](https://extensions.gnome.org/extension/1873/disable-unredirect-fullscreen-windows/) (fix some issues) 106 | - [window-calls](https://extensions.gnome.org/extension/4724/window-calls/) (alternative to wmctrl in wayland) 107 | - [lilypad](https://extensions.gnome.org/extension/7266/lilypad/) 108 | 109 | ### Office Support 110 | 111 | - [LibreOffice](https://archlinux.org/packages/extra/x86_64/libreoffice-fresh/) 112 | - [OnlyOffice](https://flathub.org/apps/org.onlyoffice.desktopeditors) 113 | - [Drawing](https://flathub.org/apps/com.github.maoschanz.drawing) 114 | - [BoxySVG](https://flathub.org/apps/com.boxy_svg.BoxySVG) 115 | 116 | ### Realtime Streaming to other PC, TV or Smart Device 117 | 118 | - Streaming Server: [Sunshine](https://docs.lizardbyte.dev/projects/sunshine/latest/index.html) 119 | - Streaming Client: [Moonlight](https://moonlight-stream.org) 120 | - Discord: [Vesktop](https://flathub.org/apps/dev.vencord.Vesktop) (incl. Wayland Screen Sharing) 121 | - All-In-One Game Collection Manager (TV/Desktop): [RetroDECK](https://retrodeck.readthedocs.io/en/latest/wiki_experiments/desktop-launch/desktop-launch/) 122 | 123 | #### Install Sunshine (Streaming Server) 124 | 125 | 1. Add [LizardByte Repository](https://github.com/LizardByte/pacman-repo) to Pacman config: `sudo nano /etc/pacman.conf` 126 | 127 | ``` 128 | [lizardbyte] 129 | SigLevel = Optional 130 | Server = https://github.com/LizardByte/pacman-repo/releases/latest/download 131 | ``` 132 | 133 | 2. Install Sunshine: `sudo pacman -Syyu lizardbyte/sunshine` 134 | 3. Start Sunshine Desktop Application (see system tray) 135 | 4. Open local Sunshine Web Interface: https://localhost:47990 and set username and password 136 | 5. Simply start streaming with [Moonlight](https://moonlight-stream.org) 137 | 138 | Source: [LizardByte Docs](https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html#archlinux) 139 | 140 | ### For Developer 141 | 142 | For sandboxed CLI tools or test environment you can try [Distrobox](https://distrobox.it/) or [Toolbox](https://containertoolbx.org) and as container runtime use [Podman](https://podman.io) or [Docker](https://www.docker.com). 143 | 144 | #### Useful Tools 145 | 146 | - [GNOME Boxes](https://archlinux.org/packages/extra/x86_64/gnome-boxes/) 147 | - [Podman Desktop](https://flathub.org/apps/io.podman_desktop.PodmanDesktop) 148 | - [Pods](https://flathub.org/apps/com.github.marhkb.Pods) 149 | - [BoxBuddy](https://flathub.org/apps/io.github.dvlv.boxbuddyrs) 150 | 151 | ### For Gamer 152 | 153 | For native **Microsoft Windows Gaming** install [Qemu](https://wiki.archlinux.org/title/QEMU) and enable GPU Passthrough. Then you can use an emulated Microsoft Windows with native GPU access. For quick installation, have a look to this project: [quickpassthrough](https://github.com/HikariKnight/quickpassthrough) 154 | 155 | **Note:** Use [gamemode](https://wiki.archlinux.org/title/Gamemode) when playing games from Linux with: `gamemoderun ` 156 | 157 | #### Gaming Meta Package 158 | 159 | You can install install [AUR/lutris-wine-meta](https://aur.archlinux.org/packages/lutris-wine-meta) and [AUR/arch-gaming-meta](https://aur.archlinux.org/packages/arch-gaming-meta) package to install some useful apps and libraries for gaming: 160 | 161 | ``` 162 | paru -S lutris-wine-meta # Recommended from lutris maintainers 163 | paru -S arch-gaming-meta # Has a lot of depenencies 164 | ``` 165 | 166 | #### Steam 167 | 168 | Install prefered Steam version: 169 | 170 | - Average between performance and compatibility (recommended): `paru -S steam` 171 | - Best performance: `paru -S steam-native` 172 | - Best compatibility: `flatpak install com.valvesoftware.Steam` 173 | - Install and apply GNOME Theme: [AdwSteamGtk](https://flathub.org/apps/io.github.Foldex.AdwSteamGtk) 174 | 175 | #### Other Gaming Tools 176 | 177 | - [Lutris](https://archlinux.org/packages/extra/any/lutris/) 178 | - [Bottles](https://aur.archlinux.org/packages/bottles) 179 | - [RetroDeck](https://flathub.org/apps/net.retrodeck.retrodeck) 180 | - [Cartridges](https://flathub.org/de/apps/page.kramo.Cartridges) 181 | - [ScummVM](https://flathub.org/apps/org.scummvm.ScummVM) 182 | - [Wine](https://archlinux.org/packages/multilib/x86_64/wine/), [Winetricks](https://archlinux.org/packages/multilib/x86_64/winetricks/) 183 | - [Proton](https://aur.archlinux.org/packages/proton-ge-custom-bin), [Protontricks](https://aur.archlinux.org/packages/protontricks) 184 | - [Gamescope](https://archlinux.org/packages/extra/x86_64/gamescope/) 185 | - [MangoHud](https://archlinux.org/packages/extra/x86_64/mangohud/) 186 | - [ProtonPlus](https://flathub.org/apps/com.vysp3r.ProtonPlus) 187 | - [Haguichi](https://flathub.org/apps/com.github.ztefn.haguichi), [logmein-hamachi](https://aur.archlinux.org/packages/logmein-hamachi]) 188 | 189 | ### For Audiophiles 190 | 191 | For advanced Pipewire audio configuration, check out the official [Arch Wiki](https://wiki.archlinux.org/title/PipeWire). 192 | 193 | May check out these projects: 194 | 195 | - [AutoEq](https://github.com/jaakkopasanen/AutoEq) 196 | - [EasyEffects Presents](https://github.com/wwmm/easyeffects/wiki/Community-presets) 197 | 198 | ## Advanced Installation 199 | 200 | The `installer.conf` with all properties (except `ARCH_OS_PASSWORD` for better security) will automatically generated on first start of the installer and be updated on every setup change. If the file exists on startup, the values will set as preset for the installer properties. This file provides some additional properties to customize your Arch OS installation (see [Example](#example-installerconf)). 201 | 202 | **Note:** The `installer.conf` & `installer.log` will copied to the new user's home directory during installation. This files can be saved for reuse or simply deleted. 203 | 204 | ### Example: `installer.conf` 205 | 206 | ``` 207 | ARCH_OS_HOSTNAME='arch-os' # Hostname 208 | ARCH_OS_USERNAME='tux' # User 209 | ARCH_OS_DISK='/dev/sda' # Disk 210 | ARCH_OS_BOOT_PARTITION='/dev/sda1' # Boot partition 211 | ARCH_OS_ROOT_PARTITION='/dev/sda2' # Root partition 212 | ARCH_OS_FILESYSTEM='btrfs' # Filesystem | Available: btrfs, ext4 213 | ARCH_OS_BOOTLOADER='grub' # Bootloader | Available: grub, systemd 214 | ARCH_OS_SNAPPER_ENABLED='true' # BTRFS Snapper enabled | Disable: false 215 | ARCH_OS_ENCRYPTION_ENABLED='true' # Disk encryption | Disable: false 216 | ARCH_OS_TIMEZONE='Europe/Berlin' # Timezone | Show available: ls /usr/share/zoneinfo/** | Example: Europe/Berlin 217 | ARCH_OS_LOCALE_LANG='de_DE' # Locale | Show available: ls /usr/share/i18n/locales | Example: de_DE 218 | ARCH_OS_LOCALE_GEN_LIST=('de_DE.UTF-8 UTF-8' 'de_DE ISO-8859-1' 'de_DE@euro ISO-8859-15' 'en_US.UTF-8 UTF-8') # Locale List | Show available: cat /etc/locale.gen 219 | ARCH_OS_REFLECTOR_COUNTRY='Germany' # Country used by reflector | Default: null | Example: Germany,France 220 | ARCH_OS_VCONSOLE_KEYMAP='de-latin1-nodeadkeys' # Console keymap | Show available: localectl list-keymaps | Example: de-latin1-nodeadkeys 221 | ARCH_OS_VCONSOLE_FONT='' # Console font | Default: null | Show available: find /usr/share/kbd/consolefonts/*.psfu.gz | Example: eurlatgr 222 | ARCH_OS_KERNEL='linux-zen' # Kernel | Default: linux-zen | Recommended: linux, linux-lts linux-zen, linux-hardened 223 | ARCH_OS_MICROCODE='intel-ucode' # Microcode | Disable: none | Available: intel-ucode, amd-ucode 224 | ARCH_OS_CORE_TWEAKS_ENABLED='true' # Arch OS Core Tweaks | Disable: false 225 | ARCH_OS_MULTILIB_ENABLED='true' # MultiLib 32 Bit Support | Disable: false 226 | ARCH_OS_AUR_HELPER='paru' # AUR Helper | Default: paru | Disable: none | Recommended: paru, yay, trizen, pikaur 227 | ARCH_OS_BOOTSPLASH_ENABLED='true' # Bootsplash | Disable: false 228 | ARCH_OS_HOUSEKEEPING_ENABLED='true' # Housekeeping | Disable: false 229 | ARCH_OS_MANAGER_ENABLED='true' # Arch OS Manager | Disable: false 230 | ARCH_OS_SHELL_ENHANCEMENT_ENABLED='true' # Shell Enhancement | Disable: false 231 | ARCH_OS_SHELL_ENHANCEMENT_FISH_ENABLED='true' # Enable fish shell | Default: true | Disable: false 232 | ARCH_OS_DESKTOP_ENABLED='true' # Arch OS Desktop (caution: if disabled, only a minimal tty will be provied)| Disable: false 233 | ARCH_OS_DESKTOP_GRAPHICS_DRIVER='amd' # Graphics Driver | Disable: none | Available: mesa, intel_i915, nvidia, amd, ati 234 | ARCH_OS_DESKTOP_EXTRAS_ENABLED='true' # Enable desktop extra packages (caution: if disabled, only core + gnome + git packages will be installed) | Disable: false 235 | ARCH_OS_DESKTOP_SLIM_ENABLED='true' # Enable Sim Desktop (only GNOME Core Apps) | Default: false 236 | ARCH_OS_DESKTOP_KEYBOARD_MODEL='pc105' # X11 keyboard model | Default: pc105 | Show available: localectl list-x11-keymap-models 237 | ARCH_OS_DESKTOP_KEYBOARD_LAYOUT='de' # X11 keyboard layout | Show available: localectl list-x11-keymap-layouts | Example: de 238 | ARCH_OS_DESKTOP_KEYBOARD_VARIANT='nodeadkeys' # X11 keyboard variant | Default: null | Show available: localectl list-x11-keymap-variants | Example: nodeadkeys 239 | ARCH_OS_SAMBA_SHARE_ENABLED='true' # Enable Samba public (anonymous) & home share (user) | Disable: false 240 | ARCH_OS_VM_SUPPORT_ENABLED='true' # VM Support | Default: true | Disable: false 241 | ARCH_OS_ECN_ENABLED='true' # Disable ECN support for legacy routers | Default: true | Disable: false 242 | ``` 243 | 244 | ### Minimal Installation 245 | 246 | Set these properties to install Arch OS Core only with minimal packages & configurations. This is the same as preset `core`: 247 | 248 | ``` 249 | ARCH_OS_CORE_TWEAKS_ENABLED='false' 250 | ARCH_OS_BOOTSPLASH_ENABLED='false' 251 | ARCH_OS_DESKTOP_ENABLED='false' 252 | ARCH_OS_MULTILIB_ENABLED='false' 253 | ARCH_OS_HOUSEKEEPING_ENABLED='false' 254 | ARCH_OS_SHELL_ENHANCEMENT_ENABLED='false' 255 | ARCH_OS_AUR_HELPER='none' 256 | ``` 257 | 258 | If you want to disable VM support add `ARCH_OS_VM_SUPPORT_ENABLED='false'` 259 | 260 | **Note:** You will only be provided with a minimal tty after installation. 261 | 262 | ## Features 263 | 264 | Each feature can be activated/deactivated during installation. Further information can be found in the individual feature headings. 265 | 266 | ### Core Tweaks 267 | 268 | Enable this feature with `ARCH_OS_CORE_TWEAKS_ENABLED='true'`: 269 | 270 | - `vm.max_map_count` is set to `1048576` for compatibility of some apps/games (default) 271 | - `quiet splash vt.global_cursor_default=0` is set to kernel parameters for silent boot 272 | - Pacman parallel downloads is set to `5` 273 | - Pacman colors and eyecandy is enabled 274 | - Sudo password feedback is enabled 275 | - Debug packages are disabled in `/etc/makepkg.conf` 276 | - Watchdog is disabled with kernel arg `nowatchdog` and blacklist: `/etc/modprobe.d/blacklist-watchdog.conf` 277 | 278 | Disable this featuree with `ARCH_OS_CORE_TWEAKS_ENABLED='false'` 279 | 280 | ### Housekeeping 281 | 282 | This feature will install and configure: 283 | 284 | | Package | Service | Config | Description | 285 | | -------------- | -------------------- | --------------------------------- | ---------------------------------------------------------------------- | 286 | | reflector | reflector.service | /etc/xdg/reflector/reflector.conf | Rank & update the mirrorlist on every boot | 287 | | pacman-contrib | paccache.timer | none | Weekly clear the pacman cache | 288 | | pkgfile | pkgfile-update.timer | none | Missing command suggestion and daily database update | 289 | | smartmontools | smartd | none | Monitor storage devices | 290 | | irqbalance | irqbalance.service | none | Distribute hardware interrupts across processors on a multicore system | 291 | 292 | Disable this feature with `ARCH_OS_HOUSEKEEPING_ENABLED='false'` 293 | 294 | ### Shell Enhancement 295 | 296 |

297 | 298 | If the property `ARCH_OS_SHELL_ENHANCEMENT_ENABLED` is set to `true`, the following packages are installed and preconfigured (for root & user). To keep `bash` as default shell, set `ARCH_OS_SHELL_ENHANCEMENT_FISH_ENABLED='false'`. 299 | 300 | Package Dependencies: 301 | 302 | ``` 303 | fish git starship eza bat zoxide fd fzf fastfetch mc btop nano man-db bash-completion nano-syntax-highlighting ttf-firacode-nerd ttf-nerd-fonts-symbols 304 | ``` 305 | 306 | **Promt Theme [➜ Arch OS Starship Theme](https://github.com/murkl/starship-theme-arch-os)** 307 | 308 | - `fish` is set as default shell 309 | - `starship` is set as fancy default promt see `~/.config/fish/config.fish` 310 | - `ls` is replaced with colorful `eza` see `~/.aliases` 311 | - `man` is replaced with colorful `bat` see `~/.config/fish/config.fish` 312 | - `nano` is set as default editor 313 | - `fastfetch` is preconfigured as system info 314 | 315 | #### Useful Terminal commands 316 | 317 | - `help` open fish help in browser 318 | - `history` open command history 319 | - `fish` open fish shell (default) 320 | - `bash` switch to bash shell (go back to fish with `q`) 321 | - `fetch` show system info 322 | - `btop` show system manager 323 | - `logs` show system logs 324 | - `mc` open file manager 325 | - `fd` Alternative search 326 | - `z` Alternative cd (zoxide) 327 | - `ll` list files in dir 328 | - `la` list all files (+ hidden files) in dir 329 | - `lt` tree files in dir 330 | - `.` go back 331 | - `c` clear screen 332 | - `q` exit 333 | - `open ` open file in GNOME app 334 | 335 | **Note:** See `~/.aliases` for all command aliases 336 | 337 | #### Useful Terminal keyboard shortcuts 338 | 339 | - Use `Tab` to autocomplete command 340 | - Use `Arrows` to navigate 341 | - Use `Ctrl + r` to search in command history 342 | - Use `Alt + s` to run previous command as `sudo` (Bash: `sudo !!`) 343 | - Use `Alt + .` to paste the last parameter from previous command (Bash: `ESC .`) 344 | 345 | #### Configuration 346 | 347 | This config files are created or modified during the Arch OS installation. 348 | 349 | ``` 350 | # Aliases 351 | ~/.aliases 352 | 353 | # Bash config 354 | ~/.bashrc 355 | 356 | # Fish config 357 | ~/.config/fish/config.fish 358 | 359 | # Starship config 360 | ~/.config/starship.toml 361 | 362 | # Fastfetch config 363 | ~/.config/fastfetch/config.jsonc 364 | 365 | # Midnight Commander config 366 | ~/.config/mc/ini 367 | 368 | # Btop config 369 | ~/.config/btop/btop.conf 370 | 371 | # Nano config 372 | /etc/nanorc 373 | 374 | # Environment config 375 | /etc/environment 376 | 377 | # Open Fish web config 378 | fish_config 379 | ``` 380 | 381 | ### Arch OS Manager 382 | 383 | **GitHub Project ➜ [github.com/murkl/arch-os-manager](https://github.com/murkl/arch-os-manager)** 384 | 385 |

386 | 387 | Install **➜ [archlinux-updates-indicator](https://extensions.gnome.org/extension/1010/)** and set this in extension options to integrate [Arch OS Manager](https://github.com/murkl/arch-os-manager): 388 | 389 | - Check command: `/usr/bin/arch-os check` 390 | - Update command: `arch-os --kitty upgrade` 391 | - Package Manager (optional): `arch-os --kitty` 392 | 393 | ### Install Graphics Driver (manually) 394 | 395 | Set the property `ARCH_OS_DESKTOP_GRAPHICS_DRIVER='none'` and install your graphics driver manually: 396 | 397 | - [OpenGL](https://wiki.archlinux.org/title/OpenGL) 398 | - [Intel HD](https://wiki.archlinux.org/title/Intel_graphics#Installation) 399 | - [NVIDIA](https://wiki.archlinux.org/title/NVIDIA#Installation) 400 | - [NVIDIA Optimus](https://wiki.archlinux.org/title/NVIDIA_Optimus#Available_methods) 401 | - [AMD](https://wiki.archlinux.org/title/AMDGPU#Installation) 402 | - [ATI Legacy](https://wiki.archlinux.org/title/ATI#Installation) 403 | 404 | #### Tools 405 | 406 | - [AMD LACT](https://archlinux.org/packages/extra/x86_64/lact-libadwaita/): Overclocking Tool 407 | 408 | ### VM Support 409 | 410 | If the installation is executed in a VM (autodetected), the corresponding packages are installed. 411 | 412 | Supported VMs: 413 | 414 | - kvm 415 | - vmware 416 | - oracle 417 | - microsoft 418 | 419 | Disable this feature with `ARCH_OS_VM_SUPPORT_ENABLED='false'` 420 | 421 | ## Technical Information 422 | 423 | Here are some technical information regarding the Arch OS Core installation. 424 | 425 | ### Partitions layout 426 | 427 | The partitions layout is seperated in two partitions: 428 | 429 | 1. **FAT32** partition (1 GiB), mounted at `/boot` as ESP 430 | 2. **EXT4/BTRFS** partition (rest of disk) optional with **LUKS2 encrypted container**, mounted at `/` as root 431 | 432 | | Partition | Label | Size | Mount | Filesystem | 433 | | --------- | ------------------------ | ------------ | ----- | ------------------------------- | 434 | | 1 | BOOT | 1 GiB | /boot | FAT32 | 435 | | 2 | ROOT / BTRFS / cryptroot | Rest of disk | / | EXT4/BTRFS + Encryption (LUKS2) | 436 | 437 | #### BTRFS 438 | 439 | Great GUI for managing Snapshots: [AUR/btrfs-assistant](https://aur.archlinux.org/packages/btrfs-assistant) 440 | 441 | | Subvolume | Mountpoint | Description | Snapper Config | 442 | | ---------- | ----------- | -------------------------------------- | ------------------------- | 443 | | @ | / | Mount point for root | /etc/snapper/configs/root | 444 | | @home | /home | Mount point for home | x | 445 | | @snapshots | /.snapshots | Read-only snapshots created by snapper | x | 446 | 447 | **Note:** If `btrfs` as filesystem and `grub` as bootloader is selected, _OverlayFS_ is used and lets you overlay a writable layer on top of a read-only Btrfs snapshot, so changes are temporary and the original data stays untouched. It is enabled by adding `grub-btrfs-overlayfs` to the `HOOKS` array in `/etc/mkinitcpio.conf`. 448 | 449 | | Package | Service/Timer | Description | 450 | | ----------- | --------------------------- | -------------------------------------------------------------------- | 451 | | grub-btrfs | grub-btrfsd.service | Automatically updates GRUB menu entries when Btrfs snapshots change. | 452 | | btrfs-progs | btrfs-scrub@-.timer | Schedules regular Btrfs scrub for the root filesystem. | 453 | | btrfs-progs | btrfs-scrub@home.timer | Schedules regular Btrfs scrub for the /home subvolume. | 454 | | btrfs-progs | btrfs-scrub@snapshots.timer | Schedules regular Btrfs scrub for the /snapshots subvolume. | 455 | | snapper | snapper-boot.timer | Automatically creates a Btrfs snapshot at every system boot. | 456 | | snapper | snapper-timeline.timer | Automatically creates periodic Btrfs snapshots. | 457 | | snapper | snapper-cleanup.timer | Cleans up old Btrfs snapshots based on retention policy. | 458 | 459 | This packages are installed: 460 | 461 | ``` 462 | base-devel btrfs-progs efibootmgr inotify-tools grub grub-btrfs snapper snap-pac 463 | ``` 464 | 465 | **Note:** By installing `snap-pac`, a Pacman hook is created that automatically generates Btrfs snapshots before and after each package transaction. 466 | 467 | ### Swap 468 | 469 | As default, `zram-generator` is used to create swap with enhanced config. 470 | 471 | You can edit the zram-generator default configuration in `/etc/systemd/zram-generator.conf` and to modify the enhanced kernel parameter in `/etc/sysctl.d/99-vm-zram-parameters.conf` 472 | 473 | ### Packages 474 | 475 | This packages will be installed during Arch OS Core Installation (~150 packages in total): 476 | 477 | ``` 478 | base base-devel linux-firmware zram-generator networkmanager [kernel_pkg] [microcode_pkg] 479 | ``` 480 | 481 | ### Services 482 | 483 | This services will be enabled during Arch OS Core Installation: 484 | 485 | ``` 486 | NetworkManager fstrim.timer systemd-zram-setup@zram0.service systemd-oomd.service systemd-boot-update.service systemd-timesyncd.service 487 | ``` 488 | 489 | ### Configuration 490 | 491 | This configuration will be set during Arch OS Core Installation: 492 | 493 | - Bootloader timeout is set to `0` 494 | - User is added to group `wheel` to use `sudo` 495 | 496 | **Note:** The password (`ARCH_OS_PASSWORD`) is used for encryption (optional), root and user login and can be changed afterwards with `passwd` if necessary. 497 | 498 | ## Rescue & Recovery 499 | 500 | If you need to rescue your Arch OS in case of a crash, **boot from an Arch ISO device** and start the included recovery mode: 501 | 502 | ``` 503 | curl -Ls bit.ly/arch-os | RECOVERY=true bash 504 | ``` 505 | 506 | ### BTRFS Rollback - manually 507 | 508 | ``` 509 | btrfs subvolume list /mnt/recovery # List BTRFS snapshots 510 | btrfs subvolume delete --recursive /mnt/recovery/@ 511 | btrfs subvolume snapshot /mnt/recovery/@snapshots//snapshot /mnt/recovery/@ 512 | ``` 513 | 514 | ### EXT4 Recovery - manually 515 | 516 | Follow these instructions to do this manually. 517 | 518 | #### 1. Disk Information 519 | 520 | - Show disk info: `lsblk` 521 | 522 | _**Example**_ 523 | 524 | - _Example Disk: `/dev/sda`_ 525 | - _Example Boot: `/dev/sda1`_ 526 | - _Example Root: `/dev/sda2`_ 527 | 528 | #### 2. Mount 529 | 530 | **Note:** _You may have to replace the example `/dev/sda` with your own disk_ 531 | 532 | - Create mount dir: `mkdir -p /mnt/boot` 533 | - a) Mount root partition (disk encryption enabled): 534 | - `cryptsetup open /dev/sda2 cryptroot` 535 | - `mount /dev/mapper/cryptroot /mnt` 536 | - b) Mount root partition (disk encryption disabled): 537 | - `mount /dev/sda2 /mnt` 538 | - Mount boot partition: `mount /dev/sda1 /mnt/boot` 539 | 540 | #### 3. Chroot 541 | 542 | - Enter chroot: `arch-chroot /mnt` 543 | - _Fix your Arch OS..._ 544 | - Exit: `exit` 545 | 546 | ## Troubleshooting 547 | 548 | If an error occurs, see created `installer.log` for more details. 549 | 550 | ### Installation failed 551 | 552 | If you encounter problems with a server during Arch OS installation (`error: failed retrieving file` or related errors), remove this server from `/etc/pacman.d/mirrorlist` (Arch ISO) and run Arch OS Installer again. 553 | 554 | #### Example 555 | 556 | ``` 557 | # From booted Arch ISO: 558 | nano /etc/pacman.d/mirrorlist 559 | ``` 560 | 561 | ``` 562 | .... 563 | # Disable this server 564 | # Server = https://archlinux.thaller.ws/$repo/os/$arch 565 | Server = https://london.mirror.pkgbuild.com/$repo/os/$arch 566 | Server = https://mirror.ubrco.de/archlinux/$repo/os/$arch 567 | Server = https://mirror.f4st.host/archlinux/$repo/os/$arch 568 | .... 569 | ``` 570 | 571 | ### Device is busy 572 | 573 | Try terminate all processes with: 574 | 575 | ``` 576 | fuser -km /mnt 577 | ``` 578 | 579 | ### Legacy Routers (ECN disabled) 580 | 581 | Set `ARCH_OS_ECN_ENABLED="false"` in Arch OS `installer.conf`. 582 | 583 | ### Downgrade a package 584 | 585 | ``` 586 | paru -S downgrade 587 | sudo downgrade my_package_name 588 | ``` 589 | 590 | ### Reset Pacman Keyring & Update 591 | 592 | ``` 593 | sudo rm -rf /etc/pacman.d/gnupg 594 | sudo pacman-key --init 595 | sudo pacman-key --populate 596 | 597 | # Do update 598 | sudo pacman -Sy archlinux-keyring && paru -Su 599 | ``` 600 | 601 | ### Reset Pacman/AUR cache 602 | 603 | ``` 604 | paru -Scc 605 | ``` 606 | 607 | ## Development 608 | 609 | Create new pull request branches only from [main branch](https://github.com/murkl/arch-os/tree/main)! The [dev branch](https://github.com/murkl/arch-os/tree/dev) will be deleted after each merge into main. 610 | 611 | The Arch OS [dev branch](https://github.com/murkl/arch-os/tree/dev) can be broken, use only for testing! 612 | 613 | ``` 614 | curl -Ls bit.ly/arch-os-dev | bash 615 | ``` 616 | 617 | ### Parameter 618 | 619 | ``` 620 | # Set password: 621 | ARCH_OS_PASSWORD=mySecret123 ./installer.sh 622 | 623 | # Force install: 624 | FORCE=true ./installer.sh 625 | 626 | # Custom gum: 627 | GUM=/usr/bin/gum ./installer.sh 628 | 629 | # Debug simulator: 630 | DEBUG=true ./installer.sh 631 | 632 | # Start recovery mode: 633 | RECOVERY=true ./installer.sh 634 | ``` 635 | 636 | ## Credits 637 | 638 | Many thanks for these projects and the people behind them! 639 | 640 | - Arch Linux 641 | - GNOME 642 | - Gum by charm 643 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Arch OS

4 |

5 | 6 |
7 | 8 |

Boot from official Arch ISO and run

9 | 10 | **`curl -Ls bit.ly/arch-os | bash`** 11 | 12 |

13 | 14 | [➜ Step by Step Installation Guide](#arch-os-installation) 15 | 16 |

17 | 18 |

19 | 20 |

21 | 22 | [➜ More Screenshots](#screenshots) 23 | 24 |

25 | 26 |

Optimized for Gaming, Emulation, Audio & Development

27 | 28 |

29 | This project aims to provide a mostly automized, minimal and robust Arch Linux base (minimal tty core or desktop), along with an easy-to-use and fast properties-file-based installer with error handling. Install a minimal Arch Linux core with optional features such as GNOME Desktop with Graphics Driver, Automatic Housekeeping, Zen Kernel, Fancy Shell Enhancement, preinstalled Paru as AUR Helper, enabled MultiLib, Bootsplash, System Manager and some more...

30 | 31 | ## More Information 32 | 33 |

34 | 35 | 36 |

37 | 38 | **[➜ Arch OS Documentation](DOCS.md)**
39 | ➜ t.me/archos_community 40 | 41 |

100% shellcheck approved

42 | 43 |
44 | 45 | ## Core Features 46 | 47 | - [Minimal Arch Linux](DOCS.md#minimal-installation) (~150 packages) 48 | - [Zen Kernel](DOCS.md#advanced-installation) (configurable) 49 | - [Swap](DOCS.md#swap) with zram-generator (zstd) 50 | - [Sole OS](DOCS.md#partitions-layout) 51 | - BTRFS Snapshot Support (Snapper, OverlayFS) 52 | - All-in-One password (encryption, root & user) 53 | - Multilingual Support 54 | - Filesystem btrfs or ext4 55 | - Bootloader: grub or systemd (auto updated) 56 | - Silent Boot (optional) 57 | - Systemd OOM (out-of-memory killer) 58 | - Pacman parallel downloads & eyecandy (optional) 59 | - Network Manager 60 | - SSD Support (fstrim) 61 | - Microcode Support (Intel & AMD) 62 | - Disabled Watchdog (optional) 63 | - UEFI only supported 64 | - [More Information...](DOCS.md#technical-information) 65 | 66 | ## Desktop Features 67 | 68 | - [GNOME Desktop Environment](DOCS.md#recommendation) (optional with additional packages) 69 | - [Arch OS Slim Version](DOCS.md#example-installerconf) (GNOME Core Apps only) 70 | - [Graphics Driver](DOCS.md#install-graphics-driver-manually) (Mesa, Intel i915, NVIDIA, AMD, ATI) 71 | - [Pipewire Audio](DOCS.md#for-audiophiles) (Dolby Atmos supported) 72 | - Flatpak Support + Auto Update (GNOME Software) 73 | - Samba, Networking Protocol Libs, Git, Utils & Codecs included 74 | - GNOME Power Profiles Support (tuned-ppd) 75 | - VPN Support 76 | - Basic Fonts 77 | - Wayland optimized (no Xorg pre-installed) 78 | - Auto GNOME Login enabled 79 | - Printer Support (cups) 80 | - SSH Agent (gcr) 81 | - Gamemode preinstalled 82 | - No Xorg included 83 | 84 | ## Additional Features 85 | 86 | - [Arch OS Core Tweaks](DOCS.md#core-tweaks) 87 | - [Arch OS Bootsplash](https://github.com/murkl/plymouth-theme-arch-os) 88 | - [Arch OS System Manager](DOCS.md#arch-os-manager) 89 | - [Arch OS Shell Enhancement](DOCS.md#shell-enhancement) 90 | - [Arch OS Starship Theme](https://github.com/murkl/starship-theme-arch-os) 91 | - [Arch OS Automatic Housekeeping](DOCS.md#housekeeping) 92 | - [AUR Helper](DOCS.md#advanced-installation) (configurable) 93 | - [VM Support](DOCS.md#vm-support) (optional) 94 | - 32 Bit Support (Multilib) 95 | - Disk Encryption (LUKS2) 96 | 97 | ## Arch OS Installation 98 | 99 | To install Arch OS, an internet connection is required, as many packages will be downloaded during the installation process. 100 | 101 | ### 1. Prepare bootable USB Device 102 | 103 | - Download latest Arch Linux ISO from **[archlinux.org](https://www.archlinux.org/download)** or **[archlinux.de](https://www.archlinux.de/download)** 104 | - Use **[Ventoy](https://www.ventoy.net/en/download.html)** or your prefered iso writer tool to create a bootable USB device 105 | - Alternatively (Linux only): **[➜ Arch OS Creator](https://github.com/murkl/arch-os-creator)** 106 | 107 | ### 2. Configure BIOS / UEFI Settings 108 | 109 | - Disable Secure Boot 110 | - Set Boot Mode to UEFI 111 | 112 | ### 3. Boot from USB Device 113 | 114 | - Load prefered keyboard layout (optional): `loadkeys de` 115 | - Connect to WLAN (optional): `iwctl station wlan0 connect 'SSID'` 116 | 117 | #### 3.1. Run Arch OS Installer 118 | 119 | ``` 120 | curl -Ls bit.ly/arch-os | bash 121 | ``` 122 | 123 | **Note:** _Cancel the Arch OS Installer with `Ctrl + c`. The properties will be restored upon the next execution._ 124 | 125 | **[➜ See Advanced Installation](DOCS.md#advanced-installation)** 126 | 127 | ## System Maintenance 128 | 129 |

130 | 131 | After installing Arch OS with the default properties preset, most maintenance tasks are performed automatically. However, the following steps must be executed manually on a regular basis: 132 | 133 | - Regularly upgrade your system packages (Pacman/AUR & Flatpak) 134 | - Regularly read the **[Arch Linux News](https://www.archlinux.org/news)** (preferably before upgrading your system) 135 | - Regularly check & merge new configurations with `pacdiff` (preferably after each system upgrade) 136 | - Consult the **[Arch Linux Wiki](https://wiki.archlinux.org)** (if you need help) 137 | 138 | To streamline this process, you can use the preinstalled **[➜ Arch OS System Manager](https://github.com/murkl/arch-os-manager)** 139 | 140 |
141 | 142 |

Screenshots

143 | 144 |
145 |

Desktop Demo

146 |

Bootsplash Demo

147 |

Starship Demo

148 |

Fetch Demo

149 |

Desktop Core Apps Demo

150 |

System Manager Demo

151 |
152 | 153 |
154 | -------------------------------------------------------------------------------- /docs/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/screenshots/bootsplash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/murkl/arch-os/41dd2d053eb8f150abb4c047d689258a7b73e37f/docs/screenshots/bootsplash.png -------------------------------------------------------------------------------- /docs/screenshots/desktop_apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/murkl/arch-os/41dd2d053eb8f150abb4c047d689258a7b73e37f/docs/screenshots/desktop_apps.png -------------------------------------------------------------------------------- /docs/screenshots/desktop_overview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/murkl/arch-os/41dd2d053eb8f150abb4c047d689258a7b73e37f/docs/screenshots/desktop_overview.jpg -------------------------------------------------------------------------------- /docs/screenshots/fastfetch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/murkl/arch-os/41dd2d053eb8f150abb4c047d689258a7b73e37f/docs/screenshots/fastfetch.png -------------------------------------------------------------------------------- /docs/screenshots/installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/murkl/arch-os/41dd2d053eb8f150abb4c047d689258a7b73e37f/docs/screenshots/installer.png -------------------------------------------------------------------------------- /docs/screenshots/manager_dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/murkl/arch-os/41dd2d053eb8f150abb4c047d689258a7b73e37f/docs/screenshots/manager_dashboard.png -------------------------------------------------------------------------------- /docs/screenshots/manager_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/murkl/arch-os/41dd2d053eb8f150abb4c047d689258a7b73e37f/docs/screenshots/manager_menu.png -------------------------------------------------------------------------------- /docs/screenshots/starship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/murkl/arch-os/41dd2d053eb8f150abb4c047d689258a7b73e37f/docs/screenshots/starship.png -------------------------------------------------------------------------------- /installer.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # shellcheck disable=SC1090 3 | 4 | ######################################################### 5 | # ARCH OS INSTALLER | Automated Arch Linux Installer TUI 6 | ######################################################### 7 | 8 | # SOURCE: https://github.com/murkl/arch-os 9 | # AUTOR: murkl 10 | # ORIGIN: Germany 11 | # LICENCE: GPL 2.0 12 | 13 | # CONFIG 14 | set -o pipefail # A pipeline error results in the error status of the entire pipeline 15 | set -e # Terminate if any command exits with a non-zero 16 | set -E # ERR trap inherited by shell functions (errtrace) 17 | 18 | # ENVIRONMENT 19 | : "${DEBUG:=false}" # DEBUG=true ./installer.sh 20 | : "${FORCE:=false}" # FORCE=true ./installer.sh 21 | : "${GUM:=./gum}" # GUM=/usr/bin/gum ./installer.sh 22 | : "${RECOVERY:=false}" # RECOVERY=true ./installer.sh 23 | 24 | # SCRIPT 25 | VERSION='1.8.6' 26 | 27 | # GUM 28 | GUM_VERSION="0.13.0" 29 | 30 | # ENVIRONMENT 31 | SCRIPT_CONFIG="./installer.conf" 32 | SCRIPT_LOG="./installer.log" 33 | 34 | # INIT 35 | INIT_FILENAME="initialize" 36 | 37 | # TEMP 38 | SCRIPT_TMP_DIR="$(mktemp -d "./.tmp.XXXXX")" 39 | ERROR_MSG="${SCRIPT_TMP_DIR}/installer.err" 40 | PROCESS_LOG="${SCRIPT_TMP_DIR}/process.log" 41 | PROCESS_RET="${SCRIPT_TMP_DIR}/process.ret" 42 | 43 | # COLORS 44 | COLOR_BLACK=0 # #000000 45 | COLOR_RED=9 # #ff0000 46 | COLOR_GREEN=10 # #00ff00 47 | COLOR_YELLOW=11 # #ffff00 48 | COLOR_BLUE=12 # #0000ff 49 | COLOR_PURPLE=13 # #ff00ff 50 | COLOR_CYAN=14 # #00ffff 51 | COLOR_WHITE=15 # #ffffff 52 | 53 | COLOR_FOREGROUND="${COLOR_BLUE}" 54 | COLOR_BACKGROUND="${COLOR_WHITE}" 55 | 56 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 57 | # MAIN 58 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 59 | 60 | main() { 61 | 62 | # Clear logfile 63 | [ -f "$SCRIPT_LOG" ] && mv -f "$SCRIPT_LOG" "${SCRIPT_LOG}.old" 64 | 65 | # Check gum binary or download 66 | gum_init 67 | 68 | # Traps (error & exit) 69 | trap 'trap_exit' EXIT 70 | trap 'trap_error ${FUNCNAME} ${LINENO}' ERR 71 | 72 | # Print version to logfile 73 | log_info "Arch OS ${VERSION}" 74 | 75 | # Start recovery 76 | [[ "$RECOVERY" = "true" ]] && { 77 | start_recovery 78 | exit $? # Exit after recovery 79 | } 80 | 81 | # --------------------------------------------------------------------------------------------------- 82 | 83 | # Loop properties step to update screen if user edit properties 84 | while (true); do 85 | 86 | print_header "Arch OS Installer" # Show landig page 87 | gum_white 'Please make sure you have:' && echo 88 | gum_white '• Backed up your important data' 89 | gum_white '• A stable internet connection' 90 | gum_white '• Secure Boot disabled' 91 | gum_white '• Boot Mode set to UEFI' 92 | 93 | # Ask for load & remove existing config file 94 | if [ "$FORCE" = "false" ] && [ -f "$SCRIPT_CONFIG" ] && ! gum_confirm "Load existing installer.conf?"; then 95 | gum_confirm "Remove existing installer.conf?" || trap_gum_exit # If not want remove config > exit script 96 | echo && gum_title "Properties File" 97 | mv -f "$SCRIPT_CONFIG" "${SCRIPT_CONFIG}.old" && gum_info "installer.conf was moved to installer.conf.old" 98 | gum_warn "Please restart Arch OS Installer..." 99 | echo && exit 0 100 | fi 101 | 102 | echo # Print new line 103 | 104 | # Source installer.conf if exists or select preset 105 | until properties_preset_source; do :; done 106 | 107 | # Selectors 108 | echo && gum_title "Core Setup" 109 | until select_username; do :; done 110 | until select_password; do :; done 111 | until select_timezone; do :; done 112 | until select_language; do :; done 113 | until select_keyboard; do :; done 114 | until select_filesystem; do :; done 115 | until select_bootloader; do :; done 116 | until select_disk; do :; done 117 | echo && gum_title "Desktop Setup" 118 | until select_enable_desktop_environment; do :; done 119 | until select_enable_desktop_driver; do :; done 120 | until select_enable_desktop_slim; do :; done 121 | until select_enable_desktop_keyboard; do :; done 122 | echo && gum_title "Feature Setup" 123 | until select_enable_encryption; do :; done 124 | until select_enable_core_tweaks; do :; done 125 | until select_enable_bootsplash; do :; done 126 | until select_enable_multilib; do :; done 127 | until select_enable_aur; do :; done 128 | until select_enable_housekeeping; do :; done 129 | until select_enable_shell_enhancement; do :; done 130 | until select_enable_manager; do :; done 131 | 132 | # Print success 133 | echo && gum_title "Properties" 134 | 135 | # Open Advanced Properties? 136 | if [ "$FORCE" = "false" ] && gum_confirm --negative="Skip" "Open Advanced Setup Editor?"; then 137 | local header_txt="• Advanced Setup | Save with CTRL + D or ESC and cancel with CTRL + C" 138 | if gum_write --show-line-numbers --prompt "" --height=12 --width=180 --char-limit=0 --header="${header_txt}" --value="$(cat "$SCRIPT_CONFIG")" >"${SCRIPT_CONFIG}.new"; then 139 | mv "${SCRIPT_CONFIG}.new" "${SCRIPT_CONFIG}" && properties_source 140 | gum_info "Properties successfully saved" 141 | gum_confirm "Change Password?" && until select_password --change && properties_source; do :; done 142 | echo && ! gum_spin --title="Reload Properties in 3 seconds..." -- sleep 3 && trap_gum_exit 143 | continue # Restart properties step to refresh properties screen 144 | else 145 | rm -f "${SCRIPT_CONFIG}.new" # Remove tmp properties 146 | gum_warn "Advanced Setup canceled" 147 | fi 148 | fi 149 | 150 | # Finish 151 | gum_info "Successfully initialized" 152 | 153 | ###################################################### 154 | break # Exit properties step and continue installation 155 | ###################################################### 156 | done 157 | 158 | # --------------------------------------------------------------------------------------------------- 159 | 160 | # Start installation in 5 seconds? 161 | if [ "$FORCE" = "false" ]; then 162 | gum_confirm "Start Arch OS Installation?" || trap_gum_exit 163 | fi 164 | local spin_title="Arch OS Installation starts in 5 seconds. Press CTRL + C to cancel..." 165 | echo && ! gum_spin --title="$spin_title" -- sleep 5 && trap_gum_exit # CTRL + C pressed 166 | gum_title "Arch OS Installation" 167 | 168 | SECONDS=0 # Messure execution time of installation 169 | 170 | # Executors 171 | exec_init_installation 172 | exec_prepare_disk 173 | exec_pacstrap_core 174 | exec_enable_multilib 175 | exec_install_aur_helper 176 | exec_install_bootsplash 177 | exec_install_housekeeping 178 | exec_install_shell_enhancement 179 | exec_install_desktop 180 | exec_install_graphics_driver 181 | exec_install_archos_manager 182 | exec_install_vm_support 183 | exec_finalize_arch_os 184 | 185 | # Calc installation duration 186 | duration=$SECONDS # This is set before install starts 187 | duration_min="$((duration / 60))" 188 | duration_sec="$((duration % 60))" 189 | 190 | # Print duration time info 191 | local finish_txt="Installation successful in ${duration_min} minutes and ${duration_sec} seconds" 192 | echo && gum_green --bold "$finish_txt" 193 | log_info "$finish_txt" 194 | 195 | # Copy installer files to users home 196 | if [ "$DEBUG" = "false" ]; then 197 | cp -f "$SCRIPT_CONFIG" "/mnt/home/${ARCH_OS_USERNAME}/installer.conf" 198 | sed -i "1i\# Arch OS Version: ${VERSION}" "/mnt/home/${ARCH_OS_USERNAME}/installer.conf" 199 | cp -f "$SCRIPT_LOG" "/mnt/home/${ARCH_OS_USERNAME}/installer.log" 200 | arch-chroot /mnt chown -R "$ARCH_OS_USERNAME":"$ARCH_OS_USERNAME" "/home/${ARCH_OS_USERNAME}/installer.conf" 201 | arch-chroot /mnt chown -R "$ARCH_OS_USERNAME":"$ARCH_OS_USERNAME" "/home/${ARCH_OS_USERNAME}/installer.log" 202 | fi 203 | 204 | wait # Wait for sub processes 205 | 206 | # --------------------------------------------------------------------------------------------------- 207 | 208 | # Show reboot & unmount promt 209 | local do_reboot do_unmount do_chroot 210 | 211 | # Default values 212 | do_reboot="false" 213 | do_chroot="false" 214 | do_unmount="false" 215 | 216 | # Force values 217 | if [ "$FORCE" = "true" ]; then 218 | do_reboot="false" 219 | do_chroot="false" 220 | do_unmount="true" 221 | fi 222 | 223 | # Reboot promt 224 | [ "$FORCE" = "false" ] && gum_confirm "Reboot to Arch OS now?" && do_reboot="true" && do_unmount="true" 225 | 226 | # Unmount 227 | [ "$FORCE" = "false" ] && [ "$do_reboot" = "false" ] && gum_confirm "Unmount Arch OS from /mnt?" && do_unmount="true" 228 | [ "$do_unmount" = "true" ] && echo && gum_warn "Unmounting Arch OS from /mnt..." 229 | if [ "$DEBUG" = "false" ] && [ "$do_unmount" = "true" ]; then 230 | swapoff -a 231 | umount -A -R /mnt 232 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ] && cryptsetup close cryptroot 233 | fi 234 | 235 | # Do reboot 236 | [ "$FORCE" = "false" ] && [ "$do_reboot" = "true" ] && gum_warn "Rebooting to Arch OS..." && [ "$DEBUG" = "false" ] && reboot 237 | 238 | # Chroot 239 | [ "$FORCE" = "false" ] && [ "$do_unmount" = "false" ] && gum_confirm "Chroot to new Arch OS?" && do_chroot="true" 240 | if [ "$do_chroot" = "true" ] && echo && gum_warn "Chrooting Arch OS at /mnt..."; then 241 | gum_warn "!! YOUR ARE NOW ON YOUR NEW ARCH OS SYSTEM !!" 242 | gum_warn ">> Leave with command 'exit'" 243 | if [ "$DEBUG" = "false" ]; then 244 | arch-chroot /mnt /dev/null 272 | umount -A -R "$recovery_mount_dir" &>/dev/null 273 | umount -l -A -R "$recovery_mount_dir" &>/dev/null 274 | cryptsetup close "$recovery_crypt_label" &>/dev/null 275 | umount -A -R /mnt &>/dev/null 276 | umount -l -A -R /mnt &>/dev/null 277 | cryptsetup close cryptroot &>/dev/null 278 | set -e 279 | } 280 | 281 | # Select disk 282 | mapfile -t items < <(lsblk -I 8,259,254 -d -o KNAME,SIZE -n) 283 | # size: $(lsblk -d -n -o SIZE "/dev/${item}") 284 | options=() && for item in "${items[@]}"; do options+=("/dev/${item}"); done 285 | user_input=$(gum_choose --header "+ Select Arch OS Disk" "${options[@]}") || exit 130 286 | gum_title "Recovery" 287 | [ -z "$user_input" ] && gum_fail "Disk is empty" && exit 1 # Check if new value is null 288 | user_input=$(echo "$user_input" | awk -F' ' '{print $1}') # Remove size from input 289 | [ ! -e "$user_input" ] && gum_fail "Disk does not exists" && exit 130 290 | 291 | [[ "$user_input" = "/dev/nvm"* ]] && recovery_boot_partition="${user_input}p1" || recovery_boot_partition="${user_input}1" 292 | [[ "$user_input" = "/dev/nvm"* ]] && recovery_root_partition="${user_input}p2" || recovery_root_partition="${user_input}2" 293 | 294 | # Check encryption 295 | #if lsblk -ndo FSTYPE "$recovery_root_partition" 2>/dev/null | grep -q "crypto_LUKS"; then 296 | if lsblk -no fstype "${recovery_root_partition}" 2>/dev/null | grep -qw crypto_LUKS || false; then 297 | recovery_encryption_enabled="true" 298 | mount_target="/dev/mapper/${recovery_crypt_label}" 299 | gum_warn "The disk $recovery_root_partition is encrypted with LUKS" 300 | else 301 | recovery_encryption_enabled="false" 302 | mount_target="$recovery_root_partition" 303 | gum_info "The disk $recovery_root_partition is not encrypted" 304 | fi 305 | 306 | # Check archiso 307 | [ "$(cat /proc/sys/kernel/hostname)" != "archiso" ] && gum_fail "You must execute the Recovery from Arch ISO!" && exit 130 308 | 309 | # Make sure everything is unmounted 310 | recovery_unmount 311 | 312 | # Create mount dir 313 | mkdir -p "$recovery_mount_dir" 314 | 315 | # Env 316 | local mount_fs_btrfs 317 | local mount_fs_ext4 318 | 319 | # Mount encrypted disk 320 | if [ "$recovery_encryption_enabled" = "true" ]; then 321 | 322 | # Encryption password 323 | recovery_encryption_password=$(gum_input --password --header "+ Enter Encryption Password" /dev/null || { 327 | gum_fail "Wrong encryption password" 328 | exit 130 329 | } 330 | 331 | mount_fs_btrfs=$(lsblk -no fstype "${mount_target}" 2>/dev/null | grep -qw btrfs && echo true || echo false) 332 | mount_fs_ext4=$(lsblk -no fstype "${mount_target}" 2>/dev/null | grep -qw ext4 && echo true || echo false) 333 | 334 | # EXT4: Mount encrypted disk 335 | if $mount_fs_ext4; then 336 | gum_info "Mounting EXT4: /root" 337 | mount "${mount_target}" "$recovery_mount_dir" 338 | fi 339 | 340 | # BTRFS: Mount encrypted disk 341 | if $mount_fs_btrfs; then 342 | gum_info "Mounting BTRFS: @, @home & @snapshots" 343 | local mount_opts="defaults,noatime,compress=zstd" 344 | mount --mkdir -t btrfs -o ${mount_opts},subvolid=5 "${mount_target}" "${recovery_mount_dir}" 345 | mount --mkdir -t btrfs -o ${mount_opts},subvol=@home "${mount_target}" "${recovery_mount_dir}/home" 346 | mount --mkdir -t btrfs -o ${mount_opts},subvol=@snapshots "${mount_target}" "${recovery_mount_dir}/.snapshots" 347 | fi 348 | 349 | # TODO 350 | if false; then 351 | gum_info "Mounting BTRFS: @, @home & @snapshots" 352 | mount "$recovery_root_partition" "$recovery_mount_dir" 353 | fi 354 | 355 | else 356 | 357 | mount_fs_btrfs=$(lsblk -no fstype "${mount_target}" 2>/dev/null | grep -qw btrfs && echo true || echo false) 358 | mount_fs_ext4=$(lsblk -no fstype "${mount_target}" 2>/dev/null | grep -qw ext4 && echo true || echo false) 359 | 360 | # EXT4: Mount unencrypted disk 361 | if $mount_fs_ext4; then 362 | gum_info "Mounting EXT4: /root" 363 | mount "$recovery_root_partition" "$recovery_mount_dir" 364 | fi 365 | 366 | # BTRFS: Mount unencrypted disk 367 | if $mount_fs_btrfs; then 368 | gum_info "Mounting BTRFS: @, @home & @snapshots" 369 | local mount_opts="defaults,noatime,compress=zstd" 370 | mount --mkdir -t btrfs -o ${mount_opts},subvolid=5 "${mount_target}" "${recovery_mount_dir}" 371 | mount --mkdir -t btrfs -o ${mount_opts},subvol=@home "${mount_target}" "${recovery_mount_dir}/home" 372 | mount --mkdir -t btrfs -o ${mount_opts},subvol=@snapshots "${mount_target}" "${recovery_mount_dir}/.snapshots" 373 | fi 374 | 375 | # TODO 376 | if false; then 377 | gum_info "Mounting BTRFS: @, @home & @snapshots" 378 | mount "$recovery_root_partition" "$recovery_mount_dir" 379 | fi 380 | fi 381 | 382 | # Check if ext4 OR btrfs found 383 | if ! $mount_fs_btrfs && ! $mount_fs_ext4; then 384 | gum_fail "ERROR: Filesystem not found. Only BTRFS & EXT4 supported." 385 | exit 130 386 | fi 387 | 388 | # Check if ext4 AND btrfs found 389 | if $mount_fs_btrfs && $mount_fs_ext4; then 390 | gum_fail "ERROR: BTRFS and EXT4 are found at the same device." 391 | exit 130 392 | fi 393 | 394 | # Mount boot 395 | gum_info "Mounting EFI: /boot" 396 | mkdir -p "$recovery_mount_dir/boot" 397 | mount "$recovery_boot_partition" "${recovery_mount_dir}/boot" 398 | 399 | # Chroot (ext4) 400 | if $mount_fs_ext4; then 401 | gum_green "!! YOUR ARE NOW ON YOUR RECOVERY SYSTEM !!" 402 | gum_yellow ">> Leave with command 'exit'" 403 | arch-chroot "$recovery_mount_dir" > Exit Recovery" 406 | fi 407 | 408 | # BTRFS Rollback 409 | if $mount_fs_btrfs; then 410 | 411 | # Input & info 412 | echo && gum_title "BTRFS Rollback" 413 | local snapshots snapshot_input 414 | #snapshots=$(btrfs subvolume list "$recovery_mount_dir" | awk '$NF ~ /^@snapshots\/[0-9]+\/snapshot$/ {print $NF}') 415 | snapshots=$(btrfs subvolume list -o "${recovery_mount_dir}/.snapshots" | awk '{print $NF}') 416 | [ -z "$snapshots" ] && gum_fail "No Snapshot found in @snapshots" && exit 130 417 | snapshot_input=$(echo "$snapshots" | gum_filter --header "+ Select Snapshot") || exit 130 418 | gum_info "Snapshot: ${snapshot_input}" 419 | gum_confirm "Confirm Rollback to @" || exit 130 420 | 421 | # Rollback 422 | btrfs subvolume delete --recursive "${recovery_mount_dir}/@" 423 | btrfs subvolume snapshot "${recovery_mount_dir}/${snapshot_input}" "${recovery_mount_dir}/@" 424 | rm -f "${recovery_mount_dir}/mnt/var/lib/pacman/db.lck" 425 | gum_info "Snapshot ${snapshot_input} is set to @ after next reboot" 426 | gum_green "Rollback successfully finished" 427 | fi 428 | } 429 | 430 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 431 | # PROPERTIES 432 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 433 | 434 | properties_source() { 435 | [ ! -f "$SCRIPT_CONFIG" ] && return 1 436 | set -a # Load properties file and auto export variables 437 | source "$SCRIPT_CONFIG" 438 | set +a 439 | return 0 440 | } 441 | 442 | properties_generate() { 443 | { # Write properties to installer.conf 444 | echo "ARCH_OS_HOSTNAME='${ARCH_OS_HOSTNAME}' # Hostname" 445 | echo "ARCH_OS_USERNAME='${ARCH_OS_USERNAME}' # User" 446 | echo "ARCH_OS_DISK='${ARCH_OS_DISK}' # Disk" 447 | echo "ARCH_OS_BOOT_PARTITION='${ARCH_OS_BOOT_PARTITION}' # Boot partition" 448 | echo "ARCH_OS_ROOT_PARTITION='${ARCH_OS_ROOT_PARTITION}' # Root partition" 449 | echo "ARCH_OS_FILESYSTEM='${ARCH_OS_FILESYSTEM}' # Filesystem | Available: btrfs, ext4" 450 | echo "ARCH_OS_BOOTLOADER='${ARCH_OS_BOOTLOADER}' # Bootloader | Available: grub, systemd" 451 | echo "ARCH_OS_SNAPPER_ENABLED='${ARCH_OS_SNAPPER_ENABLED}' # BTRFS Snapper enabled | Disable: false" 452 | echo "ARCH_OS_ENCRYPTION_ENABLED='${ARCH_OS_ENCRYPTION_ENABLED}' # Disk encryption | Disable: false" 453 | echo "ARCH_OS_TIMEZONE='${ARCH_OS_TIMEZONE}' # Timezone | Show available: ls /usr/share/zoneinfo/** | Example: Europe/Berlin" 454 | echo "ARCH_OS_LOCALE_LANG='${ARCH_OS_LOCALE_LANG}' # Locale | Show available: ls /usr/share/i18n/locales | Example: de_DE" 455 | echo "ARCH_OS_LOCALE_GEN_LIST=(${ARCH_OS_LOCALE_GEN_LIST[*]@Q}) # Locale List | Show available: cat /etc/locale.gen" 456 | echo "ARCH_OS_REFLECTOR_COUNTRY='${ARCH_OS_REFLECTOR_COUNTRY}' # Country used by reflector | Default: null | Example: Germany,France" 457 | echo "ARCH_OS_VCONSOLE_KEYMAP='${ARCH_OS_VCONSOLE_KEYMAP}' # Console keymap | Show available: localectl list-keymaps | Example: de-latin1-nodeadkeys" 458 | echo "ARCH_OS_VCONSOLE_FONT='${ARCH_OS_VCONSOLE_FONT}' # Console font | Default: null | Show available: find /usr/share/kbd/consolefonts/*.psfu.gz | Example: eurlatgr" 459 | echo "ARCH_OS_KERNEL='${ARCH_OS_KERNEL}' # Kernel | Default: linux-zen | Recommended: linux, linux-lts linux-zen, linux-hardened" 460 | echo "ARCH_OS_MICROCODE='${ARCH_OS_MICROCODE}' # Microcode | Disable: none | Available: intel-ucode, amd-ucode" 461 | echo "ARCH_OS_CORE_TWEAKS_ENABLED='${ARCH_OS_CORE_TWEAKS_ENABLED}' # Arch OS Core Tweaks | Disable: false" 462 | echo "ARCH_OS_MULTILIB_ENABLED='${ARCH_OS_MULTILIB_ENABLED}' # MultiLib 32 Bit Support | Disable: false" 463 | echo "ARCH_OS_AUR_HELPER='${ARCH_OS_AUR_HELPER}' # AUR Helper | Default: paru | Disable: none | Recommended: paru, yay, trizen, pikaur" 464 | echo "ARCH_OS_BOOTSPLASH_ENABLED='${ARCH_OS_BOOTSPLASH_ENABLED}' # Bootsplash | Disable: false" 465 | echo "ARCH_OS_HOUSEKEEPING_ENABLED='${ARCH_OS_HOUSEKEEPING_ENABLED}' # Housekeeping | Disable: false" 466 | echo "ARCH_OS_MANAGER_ENABLED='${ARCH_OS_MANAGER_ENABLED}' # Arch OS Manager | Disable: false" 467 | echo "ARCH_OS_SHELL_ENHANCEMENT_ENABLED='${ARCH_OS_SHELL_ENHANCEMENT_ENABLED}' # Shell Enhancement | Disable: false" 468 | echo "ARCH_OS_SHELL_ENHANCEMENT_FISH_ENABLED='${ARCH_OS_SHELL_ENHANCEMENT_FISH_ENABLED}' # Enable fish shell | Default: true | Disable: false" 469 | echo "ARCH_OS_DESKTOP_ENABLED='${ARCH_OS_DESKTOP_ENABLED}' # Arch OS Desktop (caution: if disabled, only a minimal tty will be provied)| Disable: false" 470 | echo "ARCH_OS_DESKTOP_GRAPHICS_DRIVER='${ARCH_OS_DESKTOP_GRAPHICS_DRIVER}' # Graphics Driver | Disable: none | Available: mesa, intel_i915, nvidia, amd, ati" 471 | echo "ARCH_OS_DESKTOP_EXTRAS_ENABLED='${ARCH_OS_DESKTOP_EXTRAS_ENABLED}' # Enable desktop extra packages (caution: if disabled, only core + gnome + git packages will be installed) | Disable: false" 472 | echo "ARCH_OS_DESKTOP_SLIM_ENABLED='${ARCH_OS_DESKTOP_SLIM_ENABLED}' # Enable Sim Desktop (only GNOME Core Apps) | Default: false" 473 | echo "ARCH_OS_DESKTOP_KEYBOARD_MODEL='${ARCH_OS_DESKTOP_KEYBOARD_MODEL}' # X11 keyboard model | Default: pc105 | Show available: localectl list-x11-keymap-models" 474 | echo "ARCH_OS_DESKTOP_KEYBOARD_LAYOUT='${ARCH_OS_DESKTOP_KEYBOARD_LAYOUT}' # X11 keyboard layout | Show available: localectl list-x11-keymap-layouts | Example: de" 475 | echo "ARCH_OS_DESKTOP_KEYBOARD_VARIANT='${ARCH_OS_DESKTOP_KEYBOARD_VARIANT}' # X11 keyboard variant | Default: null | Show available: localectl list-x11-keymap-variants | Example: nodeadkeys" 476 | echo "ARCH_OS_SAMBA_SHARE_ENABLED='${ARCH_OS_SAMBA_SHARE_ENABLED}' # Enable Samba public (anonymous) & home share (user) | Disable: false" 477 | echo "ARCH_OS_VM_SUPPORT_ENABLED='${ARCH_OS_VM_SUPPORT_ENABLED}' # VM Support | Default: true | Disable: false" 478 | echo "ARCH_OS_ECN_ENABLED='${ARCH_OS_ECN_ENABLED}' # Disable ECN support for legacy routers | Default: true | Disable: false" 479 | } >"$SCRIPT_CONFIG" # Write properties to file 480 | } 481 | 482 | properties_preset_source() { 483 | 484 | # Default presets 485 | [ -z "$ARCH_OS_HOSTNAME" ] && ARCH_OS_HOSTNAME="arch-os" 486 | [ -z "$ARCH_OS_KERNEL" ] && ARCH_OS_KERNEL="linux-zen" 487 | [ -z "$ARCH_OS_SNAPPER_ENABLED" ] && ARCH_OS_SNAPPER_ENABLED='true' 488 | [ -z "$ARCH_OS_SHELL_ENHANCEMENT_FISH_ENABLED" ] && ARCH_OS_SHELL_ENHANCEMENT_FISH_ENABLED="true" 489 | [ -z "$ARCH_OS_DESKTOP_EXTRAS_ENABLED" ] && ARCH_OS_DESKTOP_EXTRAS_ENABLED='true' 490 | [ -z "$ARCH_OS_DESKTOP_KEYBOARD_MODEL" ] && ARCH_OS_DESKTOP_KEYBOARD_MODEL="pc105" 491 | [ -z "$ARCH_OS_SAMBA_SHARE_ENABLED" ] && ARCH_OS_SAMBA_SHARE_ENABLED="true" 492 | [ -z "$ARCH_OS_ECN_ENABLED" ] && ARCH_OS_ECN_ENABLED="true" 493 | [ -z "$ARCH_OS_VM_SUPPORT_ENABLED" ] && ARCH_OS_VM_SUPPORT_ENABLED="true" 494 | 495 | # Set microcode 496 | [ -z "$ARCH_OS_MICROCODE" ] && grep -E "GenuineIntel" &>/dev/null <<<"$(lscpu)" && ARCH_OS_MICROCODE="intel-ucode" 497 | [ -z "$ARCH_OS_MICROCODE" ] && grep -E "AuthenticAMD" &>/dev/null <<<"$(lscpu)" && ARCH_OS_MICROCODE="amd-ucode" 498 | 499 | # Load properties or select preset 500 | if [ -f "$SCRIPT_CONFIG" ]; then 501 | properties_source 502 | gum join "$(gum_green --bold "• ")" "$(gum_white "Setup preset loaded from: ")" "$(gum_white --bold "installer.conf")" 503 | else 504 | # Select preset 505 | local preset options 506 | options=("desktop - GNOME Desktop Environment (default)" "core - Minimal Arch Linux TTY Environment" "none - No pre-selection") 507 | preset=$(gum_choose --header "+ Choose Setup Preset" "${options[@]}") || trap_gum_exit_confirm 508 | [ -z "$preset" ] && return 1 # Check if new value is null 509 | preset="$(echo "$preset" | awk '{print $1}')" 510 | 511 | # Core preset 512 | if [[ $preset == core* ]]; then 513 | ARCH_OS_SNAPPER_ENABLED='false' 514 | ARCH_OS_DESKTOP_ENABLED='false' 515 | ARCH_OS_MULTILIB_ENABLED='false' 516 | ARCH_OS_HOUSEKEEPING_ENABLED='false' 517 | ARCH_OS_SHELL_ENHANCEMENT_ENABLED='false' 518 | ARCH_OS_BOOTSPLASH_ENABLED='false' 519 | ARCH_OS_MANAGER_ENABLED='false' 520 | ARCH_OS_DESKTOP_GRAPHICS_DRIVER="none" 521 | ARCH_OS_AUR_HELPER='none' 522 | fi 523 | 524 | # Desktop preset 525 | if [[ $preset == desktop* ]]; then 526 | ARCH_OS_SNAPPER_ENABLED='true' 527 | ARCH_OS_DESKTOP_EXTRAS_ENABLED='true' 528 | ARCH_OS_SAMBA_SHARE_ENABLED='true' 529 | ARCH_OS_CORE_TWEAKS_ENABLED="true" 530 | ARCH_OS_BOOTSPLASH_ENABLED='true' 531 | ARCH_OS_DESKTOP_ENABLED='true' 532 | ARCH_OS_MULTILIB_ENABLED='true' 533 | ARCH_OS_HOUSEKEEPING_ENABLED='true' 534 | ARCH_OS_SHELL_ENHANCEMENT_ENABLED='true' 535 | ARCH_OS_MANAGER_ENABLED='true' 536 | ARCH_OS_AUR_HELPER='paru' 537 | fi 538 | 539 | # Write properties 540 | properties_source 541 | gum join "$(gum_green --bold "• ")" "$(gum_white "Setup preset loaded for: ")" "$(gum_white --bold "$preset")" 542 | fi 543 | return 0 544 | } 545 | 546 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 547 | # SELECTORS 548 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 549 | 550 | select_username() { 551 | if [ -z "$ARCH_OS_USERNAME" ]; then 552 | local user_input 553 | user_input=$(gum_input --header "+ Enter Username") || trap_gum_exit_confirm 554 | [ -z "$user_input" ] && return 1 # Check if new value is null 555 | ARCH_OS_USERNAME="$user_input" && properties_generate # Set value and generate properties file 556 | fi 557 | gum_property "Username" "$ARCH_OS_USERNAME" 558 | return 0 559 | } 560 | 561 | # --------------------------------------------------------------------------------------------------- 562 | 563 | select_password() { # --change 564 | if [ "$1" = "--change" ] || [ -z "$ARCH_OS_PASSWORD" ]; then 565 | local user_password user_password_check 566 | user_password=$(gum_input --password --header "+ Enter Password") || trap_gum_exit_confirm 567 | [ -z "$user_password" ] && return 1 # Check if new value is null 568 | user_password_check=$(gum_input --password --header "+ Enter Password again") || trap_gum_exit_confirm 569 | [ -z "$user_password_check" ] && return 1 # Check if new value is null 570 | if [ "$user_password" != "$user_password_check" ]; then 571 | gum_confirm --affirmative="Ok" --negative="" "The passwords are not identical" 572 | return 1 573 | fi 574 | ARCH_OS_PASSWORD="$user_password" && properties_generate # Set value and generate properties file 575 | fi 576 | [ "$1" = "--change" ] && gum_info "Password successfully changed" 577 | [ "$1" != "--change" ] && gum_property "Password" "*******" 578 | return 0 579 | } 580 | 581 | # --------------------------------------------------------------------------------------------------- 582 | 583 | select_timezone() { 584 | if [ -z "$ARCH_OS_TIMEZONE" ]; then 585 | local tz_auto user_input 586 | tz_auto="$(curl -s http://ip-api.com/line?fields=timezone)" 587 | user_input=$(gum_input --header "+ Enter Timezone (auto-detected)" --value "$tz_auto") || trap_gum_exit_confirm 588 | [ -z "$user_input" ] && return 1 # Check if new value is null 589 | if [ ! -f "/usr/share/zoneinfo/${user_input}" ]; then 590 | gum_confirm --affirmative="Ok" --negative="" "Timezone '${user_input}' is not supported" 591 | return 1 592 | fi 593 | ARCH_OS_TIMEZONE="$user_input" && properties_generate # Set property and generate properties file 594 | fi 595 | gum_property "Timezone" "$ARCH_OS_TIMEZONE" 596 | return 0 597 | } 598 | 599 | # --------------------------------------------------------------------------------------------------- 600 | 601 | # shellcheck disable=SC2001 602 | select_language() { 603 | if [ -z "$ARCH_OS_LOCALE_LANG" ] || [ -z "${ARCH_OS_LOCALE_GEN_LIST[*]}" ]; then 604 | local user_input items options filter 605 | # Fetch available options (list all from /usr/share/i18n/locales and check if entry exists in /etc/locale.gen) 606 | mapfile -t items < <(basename -a /usr/share/i18n/locales/* | grep -v "@") # Create array without @ files 607 | # Add only available locales (!!! intense command !!!) 608 | options=() && for item in "${items[@]}"; do grep -q -e "^$item" -e "^#$item" /etc/locale.gen && options+=("$item"); done 609 | # shellcheck disable=SC2002 610 | [ -r /root/.zsh_history ] && filter=$(cat /root/.zsh_history | grep 'loadkeys' | head -n 2 | tail -n 1 | cut -d';' -f2 | cut -d' ' -f2 | cut -d'-' -f1) 611 | # Select locale 612 | user_input=$(gum_filter --value="$filter" --header "+ Choose Language" "${options[@]}") || trap_gum_exit_confirm 613 | [ -z "$user_input" ] && return 1 # Check if new value is null 614 | ARCH_OS_LOCALE_LANG="$user_input" # Set property 615 | # Set locale.gen properties (auto generate ARCH_OS_LOCALE_GEN_LIST) 616 | ARCH_OS_LOCALE_GEN_LIST=() && while read -r locale_entry; do 617 | ARCH_OS_LOCALE_GEN_LIST+=("$locale_entry") 618 | # Remove leading # from matched lang in /etc/locale.gen and add entry to array 619 | done < <(sed "/^#${ARCH_OS_LOCALE_LANG}/s/^#//" /etc/locale.gen | grep "$ARCH_OS_LOCALE_LANG") 620 | # Add en_US fallback (every language) if not already exists in list 621 | [[ "${ARCH_OS_LOCALE_GEN_LIST[*]}" != *'en_US.UTF-8 UTF-8'* ]] && ARCH_OS_LOCALE_GEN_LIST+=('en_US.UTF-8 UTF-8') 622 | properties_generate # Generate properties file (for ARCH_OS_LOCALE_LANG & ARCH_OS_LOCALE_GEN_LIST) 623 | fi 624 | gum_property "Language" "$ARCH_OS_LOCALE_LANG" 625 | return 0 626 | } 627 | 628 | # --------------------------------------------------------------------------------------------------- 629 | 630 | select_keyboard() { 631 | if [ -z "$ARCH_OS_VCONSOLE_KEYMAP" ]; then 632 | local user_input items options filter 633 | mapfile -t items < <(command localectl list-keymaps) 634 | options=() && for item in "${items[@]}"; do options+=("$item"); done 635 | # shellcheck disable=SC2002 636 | [ -r /root/.zsh_history ] && filter=$(cat /root/.zsh_history | grep 'loadkeys' | head -n 2 | tail -n 1 | cut -d';' -f2 | cut -d' ' -f2 | cut -d'-' -f1) 637 | user_input=$(gum_filter --value="$filter" --header "+ Choose Keyboard" "${options[@]}") || trap_gum_exit_confirm 638 | [ -z "$user_input" ] && return 1 # Check if new value is null 639 | ARCH_OS_VCONSOLE_KEYMAP="$user_input" && properties_generate # Set value and generate properties file 640 | fi 641 | gum_property "Keyboard" "$ARCH_OS_VCONSOLE_KEYMAP" 642 | return 0 643 | } 644 | 645 | # --------------------------------------------------------------------------------------------------- 646 | 647 | select_disk() { 648 | if [ -z "$ARCH_OS_DISK" ] || [ -z "$ARCH_OS_BOOT_PARTITION" ] || [ -z "$ARCH_OS_ROOT_PARTITION" ]; then 649 | local user_input items options 650 | mapfile -t items < <(lsblk -I 8,259,254 -d -o KNAME,SIZE -n) 651 | # size: $(lsblk -d -n -o SIZE "/dev/${item}") 652 | options=() && for item in "${items[@]}"; do options+=("/dev/${item}"); done 653 | user_input=$(gum_choose --header "+ Choose Disk" "${options[@]}") || trap_gum_exit_confirm 654 | [ -z "$user_input" ] && return 1 # Check if new value is null 655 | user_input=$(echo "$user_input" | awk -F' ' '{print $1}') # Remove size from input 656 | [ ! -e "$user_input" ] && log_fail "Disk does not exists" && return 1 657 | ARCH_OS_DISK="$user_input" # Set property 658 | [[ "$ARCH_OS_DISK" = "/dev/nvm"* ]] && ARCH_OS_BOOT_PARTITION="${ARCH_OS_DISK}p1" || ARCH_OS_BOOT_PARTITION="${ARCH_OS_DISK}1" 659 | [[ "$ARCH_OS_DISK" = "/dev/nvm"* ]] && ARCH_OS_ROOT_PARTITION="${ARCH_OS_DISK}p2" || ARCH_OS_ROOT_PARTITION="${ARCH_OS_DISK}2" 660 | properties_generate # Generate properties file 661 | fi 662 | gum_property "Disk" "$ARCH_OS_DISK" 663 | return 0 664 | } 665 | 666 | # --------------------------------------------------------------------------------------------------- 667 | 668 | select_filesystem() { 669 | if [ -z "$ARCH_OS_FILESYSTEM" ]; then 670 | local user_input options 671 | options=("btrfs" "ext4") 672 | user_input=$(gum_choose --header "+ Choose Filesystem (snapshot support: btrfs)" "${options[@]}") || trap_gum_exit_confirm 673 | [ -z "$user_input" ] && return 1 # Check if new value is null 674 | ARCH_OS_FILESYSTEM="$user_input" && properties_generate # Set value and generate properties file 675 | fi 676 | gum_property "Filesystem" "${ARCH_OS_FILESYSTEM}" 677 | return 0 678 | } 679 | 680 | # --------------------------------------------------------------------------------------------------- 681 | 682 | select_bootloader() { 683 | if [ -z "$ARCH_OS_BOOTLOADER" ]; then 684 | local user_input options 685 | options=("grub" "systemd") 686 | user_input=$(gum_choose --header "+ Choose Bootloader (snapshot menu: grub)" "${options[@]}") || trap_gum_exit_confirm 687 | [ -z "$user_input" ] && return 1 # Check if new value is null 688 | ARCH_OS_BOOTLOADER="$user_input" && properties_generate # Set value and generate properties file 689 | fi 690 | gum_property "Bootloader" "${ARCH_OS_BOOTLOADER}" 691 | return 0 692 | } 693 | 694 | # --------------------------------------------------------------------------------------------------- 695 | 696 | select_enable_encryption() { 697 | if [ -z "$ARCH_OS_ENCRYPTION_ENABLED" ]; then 698 | gum_confirm "Enable Disk Encryption?" 699 | local user_confirm=$? 700 | [ $user_confirm = 130 ] && { 701 | trap_gum_exit_confirm 702 | return 1 703 | } 704 | local user_input 705 | [ $user_confirm = 1 ] && user_input="false" 706 | [ $user_confirm = 0 ] && user_input="true" 707 | ARCH_OS_ENCRYPTION_ENABLED="$user_input" && properties_generate # Set value and generate properties file 708 | fi 709 | gum_property "Disk Encryption" "$ARCH_OS_ENCRYPTION_ENABLED" 710 | return 0 711 | } 712 | 713 | # --------------------------------------------------------------------------------------------------- 714 | 715 | select_enable_core_tweaks() { 716 | if [ -z "$ARCH_OS_CORE_TWEAKS_ENABLED" ]; then 717 | gum_confirm "Enable Core Tweaks?" 718 | local user_confirm=$? 719 | [ $user_confirm = 130 ] && { 720 | trap_gum_exit_confirm 721 | return 1 722 | } 723 | local user_input 724 | [ $user_confirm = 1 ] && user_input="false" 725 | [ $user_confirm = 0 ] && user_input="true" 726 | ARCH_OS_CORE_TWEAKS_ENABLED="$user_input" && properties_generate # Set value and generate properties file 727 | fi 728 | gum_property "Core Tweaks" "$ARCH_OS_CORE_TWEAKS_ENABLED" 729 | return 0 730 | } 731 | 732 | # --------------------------------------------------------------------------------------------------- 733 | 734 | select_enable_bootsplash() { 735 | if [ -z "$ARCH_OS_BOOTSPLASH_ENABLED" ]; then 736 | gum_confirm "Enable Bootsplash?" 737 | local user_confirm=$? 738 | [ $user_confirm = 130 ] && { 739 | trap_gum_exit_confirm 740 | return 1 741 | } 742 | local user_input 743 | [ $user_confirm = 1 ] && user_input="false" 744 | [ $user_confirm = 0 ] && user_input="true" 745 | ARCH_OS_BOOTSPLASH_ENABLED="$user_input" && properties_generate # Set value and generate properties file 746 | fi 747 | gum_property "Bootsplash" "$ARCH_OS_BOOTSPLASH_ENABLED" 748 | return 0 749 | } 750 | 751 | # --------------------------------------------------------------------------------------------------- 752 | 753 | select_enable_desktop_environment() { 754 | if [ -z "$ARCH_OS_DESKTOP_ENABLED" ]; then 755 | local user_input 756 | gum_confirm "Enable GNOME Desktop Environment?" 757 | local user_confirm=$? 758 | [ $user_confirm = 130 ] && { 759 | trap_gum_exit_confirm 760 | return 1 761 | } 762 | [ $user_confirm = 1 ] && user_input="false" 763 | [ $user_confirm = 0 ] && user_input="true" 764 | ARCH_OS_DESKTOP_ENABLED="$user_input" && properties_generate # Set value and generate properties file 765 | fi 766 | gum_property "Desktop Environment" "$ARCH_OS_DESKTOP_ENABLED" 767 | return 0 768 | } 769 | 770 | # --------------------------------------------------------------------------------------------------- 771 | 772 | select_enable_desktop_slim() { 773 | if [ "$ARCH_OS_DESKTOP_ENABLED" = "true" ]; then 774 | if [ -z "$ARCH_OS_DESKTOP_SLIM_ENABLED" ]; then 775 | local user_input 776 | gum_confirm "Enable Desktop Slim Mode? (GNOME Core Apps only)" --affirmative="No (default)" --negative="Yes" 777 | local user_confirm=$? 778 | [ $user_confirm = 130 ] && { 779 | trap_gum_exit_confirm 780 | return 1 781 | } 782 | [ $user_confirm = 1 ] && user_input="true" 783 | [ $user_confirm = 0 ] && user_input="false" 784 | ARCH_OS_DESKTOP_SLIM_ENABLED="$user_input" && properties_generate # Set value and generate properties file 785 | fi 786 | gum_property "Desktop Slim Mode" "$ARCH_OS_DESKTOP_SLIM_ENABLED" 787 | fi 788 | return 0 789 | } 790 | 791 | # --------------------------------------------------------------------------------------------------- 792 | 793 | select_enable_desktop_keyboard() { 794 | if [ "$ARCH_OS_DESKTOP_ENABLED" = "true" ]; then 795 | if [ -z "$ARCH_OS_DESKTOP_KEYBOARD_LAYOUT" ]; then 796 | local user_input user_input2 797 | user_input=$(gum_input --header "+ Enter Desktop Keyboard Layout" --placeholder "e.g. 'us' or 'de'...") || trap_gum_exit_confirm 798 | [ -z "$user_input" ] && return 1 # Check if new value is null 799 | ARCH_OS_DESKTOP_KEYBOARD_LAYOUT="$user_input" 800 | gum_property "Desktop Keyboard" "$ARCH_OS_DESKTOP_KEYBOARD_LAYOUT" 801 | user_input2=$(gum_input --header "+ Enter Desktop Keyboard Variant (optional)" --placeholder "e.g. 'nodeadkeys' or leave empty...") || trap_gum_exit_confirm 802 | ARCH_OS_DESKTOP_KEYBOARD_VARIANT="$user_input2" 803 | properties_generate 804 | else 805 | gum_property "Desktop Keyboard" "$ARCH_OS_DESKTOP_KEYBOARD_LAYOUT" 806 | fi 807 | [ -n "$ARCH_OS_DESKTOP_KEYBOARD_VARIANT" ] && gum_property "Desktop Keyboard Variant" "$ARCH_OS_DESKTOP_KEYBOARD_VARIANT" 808 | fi 809 | return 0 810 | } 811 | 812 | # --------------------------------------------------------------------------------------------------- 813 | 814 | select_enable_desktop_driver() { 815 | if [ "$ARCH_OS_DESKTOP_ENABLED" = "true" ]; then 816 | if [ -z "$ARCH_OS_DESKTOP_GRAPHICS_DRIVER" ] || [ "$ARCH_OS_DESKTOP_GRAPHICS_DRIVER" = "none" ]; then 817 | local user_input options 818 | options=("mesa" "intel_i915" "nvidia" "amd" "ati") 819 | user_input=$(gum_choose --header "+ Choose Desktop Graphics Driver (default: mesa)" "${options[@]}") || trap_gum_exit_confirm 820 | [ -z "$user_input" ] && return 1 # Check if new value is null 821 | ARCH_OS_DESKTOP_GRAPHICS_DRIVER="$user_input" && properties_generate # Set value and generate properties file 822 | fi 823 | gum_property "Desktop Graphics Driver" "$ARCH_OS_DESKTOP_GRAPHICS_DRIVER" 824 | fi 825 | return 0 826 | } 827 | 828 | # --------------------------------------------------------------------------------------------------- 829 | 830 | select_enable_aur() { 831 | if [ -z "$ARCH_OS_AUR_HELPER" ]; then 832 | local user_input options 833 | options=("paru" "paru-bin" "paru-git" "none") 834 | user_input=$(gum_choose --header "+ Choose AUR Helper (default: paru)" "${options[@]}") || trap_gum_exit_confirm 835 | [ -z "$user_input" ] && return 1 # Check if new value is null 836 | ARCH_OS_AUR_HELPER="$user_input" && properties_generate # Set value and generate properties file 837 | fi 838 | gum_property "AUR Helper" "$ARCH_OS_AUR_HELPER" 839 | return 0 840 | } 841 | 842 | # --------------------------------------------------------------------------------------------------- 843 | 844 | select_enable_multilib() { 845 | if [ -z "$ARCH_OS_MULTILIB_ENABLED" ]; then 846 | gum_confirm "Enable 32 Bit Support?" 847 | local user_confirm=$? 848 | [ $user_confirm = 130 ] && { 849 | trap_gum_exit_confirm 850 | return 1 851 | } 852 | local user_input 853 | [ $user_confirm = 1 ] && user_input="false" 854 | [ $user_confirm = 0 ] && user_input="true" 855 | ARCH_OS_MULTILIB_ENABLED="$user_input" && properties_generate # Set value and generate properties file 856 | fi 857 | gum_property "32 Bit Support" "$ARCH_OS_MULTILIB_ENABLED" 858 | return 0 859 | } 860 | 861 | # --------------------------------------------------------------------------------------------------- 862 | 863 | select_enable_housekeeping() { 864 | if [ -z "$ARCH_OS_HOUSEKEEPING_ENABLED" ]; then 865 | gum_confirm "Enable Housekeeping?" 866 | local user_confirm=$? 867 | [ $user_confirm = 130 ] && { 868 | trap_gum_exit_confirm 869 | return 1 870 | } 871 | local user_input 872 | [ $user_confirm = 1 ] && user_input="false" 873 | [ $user_confirm = 0 ] && user_input="true" 874 | ARCH_OS_HOUSEKEEPING_ENABLED="$user_input" && properties_generate # Set value and generate properties file 875 | fi 876 | gum_property "Housekeeping" "$ARCH_OS_HOUSEKEEPING_ENABLED" 877 | return 0 878 | } 879 | 880 | # --------------------------------------------------------------------------------------------------- 881 | 882 | select_enable_shell_enhancement() { 883 | if [ -z "$ARCH_OS_SHELL_ENHANCEMENT_ENABLED" ]; then 884 | gum_confirm "Enable Shell Enhancement?" 885 | local user_confirm=$? 886 | [ $user_confirm = 130 ] && { 887 | trap_gum_exit_confirm 888 | return 1 889 | } 890 | local user_input 891 | [ $user_confirm = 1 ] && user_input="false" 892 | [ $user_confirm = 0 ] && user_input="true" 893 | ARCH_OS_SHELL_ENHANCEMENT_ENABLED="$user_input" && properties_generate # Set value and generate properties file 894 | fi 895 | gum_property "Shell Enhancement" "$ARCH_OS_SHELL_ENHANCEMENT_ENABLED" 896 | return 0 897 | } 898 | 899 | # --------------------------------------------------------------------------------------------------- 900 | 901 | select_enable_manager() { 902 | if [ -z "$ARCH_OS_MANAGER_ENABLED" ]; then 903 | gum_confirm "Enable Arch OS Manager?" 904 | local user_confirm=$? 905 | [ $user_confirm = 130 ] && { 906 | trap_gum_exit_confirm 907 | return 1 908 | } 909 | local user_input 910 | [ $user_confirm = 1 ] && user_input="false" 911 | [ $user_confirm = 0 ] && user_input="true" 912 | ARCH_OS_MANAGER_ENABLED="$user_input" && properties_generate # Set value and generate properties file 913 | fi 914 | gum_property "Arch OS Manager" "$ARCH_OS_MANAGER_ENABLED" 915 | return 0 916 | } 917 | 918 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 919 | # EXECUTORS (SUB PROCESSES) 920 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 921 | 922 | exec_init_installation() { 923 | local process_name="Initialize Installation" 924 | process_init "$process_name" 925 | ( 926 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 927 | # Check installation prerequisites 928 | [ ! -d /sys/firmware/efi ] && log_fail "BIOS not supported! Please set your boot mode to UEFI." && exit 1 929 | log_info "UEFI detected" 930 | bootctl status | grep "Secure Boot" | grep -q "disabled" || { log_fail "You must disable Secure Boot in UEFI to continue installation" && exit 1; } 931 | log_info "Secure Boot: disabled" 932 | [ "$(cat /proc/sys/kernel/hostname)" != "archiso" ] && log_fail "You must execute the Installer from Arch ISO!" && exit 1 933 | log_info "Arch ISO detected" 934 | log_info "Waiting for Reflector from Arch ISO..." 935 | # This mirrorlist will copied to new Arch system during installation 936 | while timeout 180 tail --pid=$(pgrep reflector) -f /dev/null &>/dev/null; do sleep 1; done 937 | pgrep reflector &>/dev/null && log_fail "Reflector timeout after 180 seconds" && exit 1 938 | rm -f /var/lib/pacman/db.lck # Remove pacman lock file if exists 939 | timedatectl set-ntp true # Set time 940 | # Make sure everything is unmounted before start install 941 | swapoff -a || true 942 | umount -R /mnt/recovery || true 943 | if [[ "$(umount -f -A -R /mnt 2>&1)" == *"target is busy"* ]]; then 944 | # If umount is busy execute fuser 945 | fuser -km /mnt || true 946 | umount -f -A -R /mnt || true 947 | fi 948 | wait # Wait for sub process 949 | cryptsetup close cryptroot || true 950 | cryptsetup close cryptrecovery || true 951 | vgchange -an || true 952 | # Temporarily disable ECN (prevent traffic problems with some old routers) 953 | [ "$ARCH_OS_ECN_ENABLED" = "false" ] && sysctl net.ipv4.tcp_ecn=0 954 | pacman -Sy --noconfirm archlinux-keyring # Update keyring 955 | process_return 0 956 | ) &>"$PROCESS_LOG" & 957 | process_capture $! "$process_name" 958 | } 959 | 960 | # --------------------------------------------------------------------------------------------------- 961 | 962 | exec_prepare_disk() { 963 | local process_name="Prepare Disk" 964 | process_init "$process_name" 965 | ( 966 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 967 | 968 | # Wipe and create partitions 969 | wipefs -af "$ARCH_OS_DISK" # Remove All Filesystem Signatures 970 | sgdisk --zap-all "$ARCH_OS_DISK" # Remove the Partition Table 971 | sgdisk -o "$ARCH_OS_DISK" # Create new GPT partition table 972 | sgdisk -n 1:0:+1G -t 1:ef00 -c 1:boot --align-end "$ARCH_OS_DISK" # Create partition /boot efi partition: 1 GiB 973 | sgdisk -n 2:0:0 -t 2:8300 -c 2:root --align-end "$ARCH_OS_DISK" # Create partition / partition: Rest of space 974 | partprobe "$ARCH_OS_DISK" # Reload partition table 975 | 976 | # Disk encryption 977 | if [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ]; then 978 | log_info "Enable Disk Encryption for ${ARCH_OS_ROOT_PARTITION}" 979 | echo -n "$ARCH_OS_PASSWORD" | cryptsetup luksFormat "$ARCH_OS_ROOT_PARTITION" 980 | echo -n "$ARCH_OS_PASSWORD" | cryptsetup open "$ARCH_OS_ROOT_PARTITION" cryptroot 981 | fi 982 | 983 | # Format /boot partition 984 | mkfs.fat -F 32 -n BOOT "$ARCH_OS_BOOT_PARTITION" 985 | 986 | # EXT4 987 | if [ "$ARCH_OS_FILESYSTEM" = "ext4" ]; then 988 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ] && mkfs.ext4 -F -L ROOT /dev/mapper/cryptroot 989 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "false" ] && mkfs.ext4 -F -L ROOT "$ARCH_OS_ROOT_PARTITION" 990 | 991 | # Mount disk to /mnt 992 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ] && mount -v /dev/mapper/cryptroot /mnt 993 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "false" ] && mount -v "$ARCH_OS_ROOT_PARTITION" /mnt 994 | 995 | # Mount /boot 996 | #mount -v --mkdir LABEL=BOOT /mnt/boot 997 | mount -v --mkdir "$ARCH_OS_BOOT_PARTITION" /mnt/boot 998 | fi 999 | 1000 | # BTRFS 1001 | if [ "$ARCH_OS_FILESYSTEM" = "btrfs" ]; then 1002 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ] && mkfs.btrfs -f -L BTRFS /dev/mapper/cryptroot 1003 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "false" ] && mkfs.btrfs -f -L BTRFS "$ARCH_OS_ROOT_PARTITION" 1004 | 1005 | # Mount disk to /mnt 1006 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ] && mount -v /dev/mapper/cryptroot /mnt 1007 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "false" ] && mount -v "$ARCH_OS_ROOT_PARTITION" /mnt 1008 | 1009 | # Create subvolumes 1010 | btrfs subvolume create /mnt/@ 1011 | btrfs subvolume create /mnt/@home 1012 | btrfs subvolume create /mnt/@snapshots 1013 | #local btrfs_root_id 1014 | #btrfs_root_id="$(btrfs subvolume list /mnt | awk '$NF == "@" {print $2}')" 1015 | #btrfs subvolume set-default "${btrfs_root_id}" /mnt # Set @ as default 1016 | umount -R /mnt 1017 | 1018 | # Mount subvolumes 1019 | local mount_target 1020 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "false" ] && mount_target="$ARCH_OS_ROOT_PARTITION" 1021 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ] && mount_target="/dev/mapper/cryptroot" 1022 | 1023 | local mount_opts="defaults,noatime,compress=zstd" 1024 | mount --mkdir -t btrfs -o ${mount_opts},subvol=@ "${mount_target}" /mnt 1025 | mount --mkdir -t btrfs -o ${mount_opts},subvol=@home "${mount_target}" /mnt/home 1026 | mount --mkdir -t btrfs -o ${mount_opts},subvol=@snapshots "${mount_target}" /mnt/.snapshots 1027 | 1028 | # Mount /boot 1029 | #mount -v --mkdir LABEL=BOOT /mnt/boot 1030 | mount -v --mkdir "$ARCH_OS_BOOT_PARTITION" /mnt/boot 1031 | fi 1032 | 1033 | # Return 1034 | process_return 0 1035 | ) &>"$PROCESS_LOG" & 1036 | process_capture $! "$process_name" 1037 | } 1038 | 1039 | # --------------------------------------------------------------------------------------------------- 1040 | 1041 | exec_pacstrap_core() { 1042 | local process_name="Pacstrap Arch OS Core" 1043 | process_init "$process_name" 1044 | ( 1045 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1046 | 1047 | # Core packages 1048 | local packages=("$ARCH_OS_KERNEL" base base-devel linux-firmware zram-generator networkmanager) 1049 | 1050 | # Add microcode package 1051 | [ -n "$ARCH_OS_MICROCODE" ] && [ "$ARCH_OS_MICROCODE" != "none" ] && packages+=("$ARCH_OS_MICROCODE") 1052 | 1053 | # Add filesystem packages 1054 | [ "$ARCH_OS_FILESYSTEM" = "btrfs" ] && packages+=(btrfs-progs efibootmgr inotify-tools) 1055 | 1056 | # Add grub packages 1057 | [ "$ARCH_OS_BOOTLOADER" = "grub" ] && packages+=(grub grub-btrfs) 1058 | 1059 | # Add snapper packages 1060 | [ "$ARCH_OS_FILESYSTEM" = "btrfs" ] && [ "$ARCH_OS_SNAPPER_ENABLED" = "true" ] && packages+=(snapper) 1061 | 1062 | # Install core packages and initialize an empty pacman keyring in the target 1063 | pacstrap -K /mnt "${packages[@]}" 1064 | 1065 | # Generate /etc/fstab 1066 | genfstab -U /mnt >>/mnt/etc/fstab 1067 | 1068 | # Set timezone & system clock 1069 | arch-chroot /mnt ln -sf "/usr/share/zoneinfo/${ARCH_OS_TIMEZONE}" /etc/localtime 1070 | arch-chroot /mnt hwclock --systohc # Set hardware clock from system clock 1071 | 1072 | { # Create swap (zram-generator with zstd compression) 1073 | # https://wiki.archlinux.org/title/Zram#Using_zram-generator 1074 | echo '[zram0]' 1075 | echo 'zram-size = min(ram / 2, 8192)' 1076 | echo 'compression-algorithm = zstd' 1077 | } >/mnt/etc/systemd/zram-generator.conf 1078 | 1079 | { # Optimize swap on zram (https://wiki.archlinux.org/title/Zram#Optimizing_swap_on_zram) 1080 | echo 'vm.swappiness = 180' 1081 | echo 'vm.watermark_boost_factor = 0' 1082 | echo 'vm.watermark_scale_factor = 125' 1083 | echo 'vm.page-cluster = 0' 1084 | } >/mnt/etc/sysctl.d/99-vm-zram-parameters.conf 1085 | 1086 | # Set console keymap in /etc/vconsole.conf 1087 | echo "KEYMAP=$ARCH_OS_VCONSOLE_KEYMAP" >/mnt/etc/vconsole.conf 1088 | [ -n "$ARCH_OS_VCONSOLE_FONT" ] && echo "FONT=$ARCH_OS_VCONSOLE_FONT" >>/mnt/etc/vconsole.conf 1089 | 1090 | # Set & Generate Locale 1091 | echo "LANG=${ARCH_OS_LOCALE_LANG}.UTF-8" >/mnt/etc/locale.conf 1092 | for ((i = 0; i < ${#ARCH_OS_LOCALE_GEN_LIST[@]}; i++)); do sed -i "s/^#${ARCH_OS_LOCALE_GEN_LIST[$i]}/${ARCH_OS_LOCALE_GEN_LIST[$i]}/g" "/mnt/etc/locale.gen"; done 1093 | arch-chroot /mnt locale-gen 1094 | 1095 | # Set hostname & hosts 1096 | echo "$ARCH_OS_HOSTNAME" >/mnt/etc/hostname 1097 | { 1098 | echo '# ' 1099 | echo '127.0.0.1 localhost.localdomain localhost' 1100 | echo '::1 localhost.localdomain localhost' 1101 | } >/mnt/etc/hosts 1102 | 1103 | # Create initial ramdisk from /etc/mkinitcpio.conf 1104 | # https://wiki.archlinux.org/title/Mkinitcpio#Common_hooks 1105 | # https://wiki.archlinux.org/title/Microcode#mkinitcpio 1106 | local btrfs_hook 1107 | [ "$ARCH_OS_FILESYSTEM" = "btrfs" ] && [ "$ARCH_OS_BOOTLOADER" = "grub" ] && btrfs_hook=' grub-btrfs-overlayfs' 1108 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ] && sed -i "s/^HOOKS=(.*)$/HOOKS=(base systemd keyboard autodetect microcode modconf sd-vconsole block sd-encrypt filesystems fsck${btrfs_hook})/" /mnt/etc/mkinitcpio.conf 1109 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "false" ] && sed -i "s/^HOOKS=(.*)$/HOOKS=(base systemd keyboard autodetect microcode modconf sd-vconsole block filesystems fsck${btrfs_hook})/" /mnt/etc/mkinitcpio.conf 1110 | arch-chroot /mnt mkinitcpio -P 1111 | 1112 | # KERNEL PARAMETER 1113 | # Zswap should be disabled when using zram (https://github.com/archlinux/archinstall/issues/881) 1114 | # Silent boot: https://wiki.archlinux.org/title/Silent_boot 1115 | local kernel_args=('rw' 'init=/usr/lib/systemd/systemd' 'zswap.enabled=0') 1116 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "true" ] && kernel_args+=("rd.luks.name=$(blkid -s UUID -o value "${ARCH_OS_ROOT_PARTITION}")=cryptroot" "root=/dev/mapper/cryptroot") 1117 | [ "$ARCH_OS_ENCRYPTION_ENABLED" = "false" ] && kernel_args+=("root=PARTUUID=$(lsblk -dno PARTUUID "${ARCH_OS_ROOT_PARTITION}")") 1118 | [ "$ARCH_OS_FILESYSTEM" = "btrfs" ] && kernel_args+=('rootflags=subvol=@' 'rootfstype=btrfs') 1119 | [ "$ARCH_OS_CORE_TWEAKS_ENABLED" = "true" ] && kernel_args+=('nowatchdog') 1120 | [ "$ARCH_OS_BOOTSPLASH_ENABLED" = "true" ] || [ "$ARCH_OS_CORE_TWEAKS_ENABLED" = "true" ] && kernel_args+=('quiet' 'splash' 'vt.global_cursor_default=0' 'loglevel=3' 'rd.udev.log_level=3' 'systemd.show_status=auto') 1121 | 1122 | # SYSTEMD-BOOT INSTALLATION 1123 | if [ "$ARCH_OS_BOOTLOADER" = "systemd" ]; then 1124 | 1125 | # Install Bootloader to /boot (systemdboot) 1126 | arch-chroot /mnt bootctl --esp-path=/boot install 1127 | 1128 | { # Create Bootloader config 1129 | echo 'default main.conf' 1130 | echo 'console-mode auto' 1131 | echo 'timeout 0' 1132 | echo 'editor yes' 1133 | } >/mnt/boot/loader/loader.conf 1134 | 1135 | { # Create default boot entry 1136 | echo 'title Arch OS' 1137 | echo "linux /vmlinuz-${ARCH_OS_KERNEL}" 1138 | echo "initrd /initramfs-${ARCH_OS_KERNEL}.img" 1139 | echo "options ${kernel_args[*]}" 1140 | } >/mnt/boot/loader/entries/main.conf 1141 | 1142 | { # Create fallback boot entry 1143 | echo 'title Arch OS (Fallback)' 1144 | echo "linux /vmlinuz-${ARCH_OS_KERNEL}" 1145 | echo "initrd /initramfs-${ARCH_OS_KERNEL}-fallback.img" 1146 | echo "options ${kernel_args[*]}" 1147 | } >/mnt/boot/loader/entries/main-fallback.conf 1148 | 1149 | # Enable service: Auto bootloader update 1150 | arch-chroot /mnt systemctl enable systemd-boot-update.service 1151 | fi 1152 | 1153 | # ------------------------------------------------------------------ 1154 | 1155 | # GRUB INSTALLATION 1156 | if [ "$ARCH_OS_BOOTLOADER" = "grub" ]; then 1157 | 1158 | # Add kernel args to /etc/default/grub 1159 | sed -i "\,^GRUB_CMDLINE_LINUX=\"\",s,\",&${kernel_args[*]}," /mnt/etc/default/grub 1160 | 1161 | # Installing GRUB 1162 | arch-chroot /mnt grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB 1163 | 1164 | # Creating grub config file 1165 | sed -i "s/^GRUB_TIMEOUT=.*$/GRUB_TIMEOUT=3/" /mnt/etc/default/grub 1166 | sed -i "s/^GRUB_TIMEOUT_STYLE=.*$/GRUB_TIMEOUT_STYLE=menu/" /mnt/etc/default/grub 1167 | arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg 1168 | 1169 | # Enable btrfs update service 1170 | [ "$ARCH_OS_FILESYSTEM" = "btrfs" ] && arch-chroot /mnt systemctl enable grub-btrfsd.service 1171 | fi 1172 | 1173 | # Create new user 1174 | arch-chroot /mnt useradd -m -G wheel -s /bin/bash "$ARCH_OS_USERNAME" 1175 | 1176 | # Create user dirs 1177 | mkdir -p "/mnt/home/${ARCH_OS_USERNAME}/.config" 1178 | mkdir -p "/mnt/home/${ARCH_OS_USERNAME}/.local/share" 1179 | arch-chroot /mnt chown -R "$ARCH_OS_USERNAME":"$ARCH_OS_USERNAME" "/home/${ARCH_OS_USERNAME}" 1180 | 1181 | # Allow users in group wheel to use sudo 1182 | sed -i 's^# %wheel ALL=(ALL:ALL) ALL^%wheel ALL=(ALL:ALL) ALL^g' /mnt/etc/sudoers 1183 | 1184 | # Change passwords 1185 | printf "%s\n%s" "${ARCH_OS_PASSWORD}" "${ARCH_OS_PASSWORD}" | arch-chroot /mnt passwd 1186 | printf "%s\n%s" "${ARCH_OS_PASSWORD}" "${ARCH_OS_PASSWORD}" | arch-chroot /mnt passwd "$ARCH_OS_USERNAME" 1187 | 1188 | # Enable services 1189 | arch-chroot /mnt systemctl enable NetworkManager # Network Manager 1190 | arch-chroot /mnt systemctl enable fstrim.timer # SSD support 1191 | arch-chroot /mnt systemctl enable systemd-zram-setup@zram0.service # Swap (zram-generator) 1192 | arch-chroot /mnt systemctl enable systemd-oomd.service # Out of memory killer (swap is required) 1193 | arch-chroot /mnt systemctl enable systemd-timesyncd.service # Sync time from internet after boot 1194 | 1195 | if [ "$ARCH_OS_FILESYSTEM" = "btrfs" ]; then 1196 | # Btrfs scrub timer 1197 | arch-chroot /mnt systemctl enable btrfs-scrub@-.timer 1198 | arch-chroot /mnt systemctl enable btrfs-scrub@home.timer 1199 | arch-chroot /mnt systemctl enable btrfs-scrub@snapshots.timer 1200 | fi 1201 | 1202 | if [ "$ARCH_OS_FILESYSTEM" = "btrfs" ] && [ "$ARCH_OS_SNAPPER_ENABLED" = "true" ]; then 1203 | 1204 | # Create snapper config 1205 | arch-chroot /mnt umount /.snapshots 1206 | arch-chroot /mnt rm -r /.snapshots 1207 | arch-chroot /mnt snapper --no-dbus -c root create-config / 1208 | arch-chroot /mnt btrfs subvolume delete /.snapshots 1209 | arch-chroot /mnt mkdir /.snapshots 1210 | arch-chroot /mnt mount -a 1211 | arch-chroot /mnt chmod 750 /.snapshots 1212 | arch-chroot /mnt sudo chown :wheel /.snapshots 1213 | 1214 | # Modify snapper config 1215 | # https://www.dwarmstrong.org/btrfs-snapshots-rollbacks/ 1216 | # /etc/snapper/configs/root 1217 | 1218 | # Enable snapper services 1219 | arch-chroot /mnt systemctl enable snapper-timeline.timer 1220 | arch-chroot /mnt systemctl enable snapper-cleanup.timer 1221 | arch-chroot /mnt systemctl enable snapper-boot.timer 1222 | fi 1223 | 1224 | # Make some Arch OS tweaks 1225 | if [ "$ARCH_OS_CORE_TWEAKS_ENABLED" = "true" ]; then 1226 | 1227 | # Add password feedback 1228 | echo -e "\n## Enable sudo password feedback\nDefaults pwfeedback" >>/mnt/etc/sudoers 1229 | 1230 | # Configure pacman parrallel downloads, colors, eyecandy 1231 | sed -i 's/^#ParallelDownloads/ParallelDownloads/' /mnt/etc/pacman.conf 1232 | sed -i 's/^#Color/Color\nILoveCandy/' /mnt/etc/pacman.conf 1233 | 1234 | # Disable watchdog modules 1235 | mkdir -p /mnt/etc/modprobe.d/ 1236 | echo 'blacklist sp5100_tco' >>/mnt/etc/modprobe.d/blacklist-watchdog.conf 1237 | echo 'blacklist iTCO_wdt' >>/mnt/etc/modprobe.d/blacklist-watchdog.conf 1238 | 1239 | # Disable debug packages when using makepkg 1240 | sed -i '/OPTIONS=.*!debug/!s/\(OPTIONS=.*\)debug/\1!debug/' /mnt/etc/makepkg.conf 1241 | 1242 | # Set max VMAs (need for some apps/games) 1243 | #echo vm.max_map_count=1048576 >/mnt/etc/sysctl.d/vm.max_map_count.conf 1244 | 1245 | # Reduce shutdown timeout 1246 | #sed -i "s/^\s*#\s*DefaultTimeoutStopSec=.*/DefaultTimeoutStopSec=10s/" /mnt/etc/systemd/system.conf 1247 | fi 1248 | 1249 | # Return 1250 | process_return 0 1251 | ) &>"$PROCESS_LOG" & 1252 | process_capture $! "$process_name" 1253 | } 1254 | 1255 | # --------------------------------------------------------------------------------------------------- 1256 | 1257 | exec_install_desktop() { 1258 | local process_name="GNOME Desktop" 1259 | if [ "$ARCH_OS_DESKTOP_ENABLED" = "true" ]; then 1260 | process_init "$process_name" 1261 | ( 1262 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1263 | 1264 | local packages=() 1265 | 1266 | # GNOME base packages 1267 | packages+=(gnome git) 1268 | 1269 | # GNOME desktop extras 1270 | if [ "$ARCH_OS_DESKTOP_EXTRAS_ENABLED" = "true" ]; then 1271 | 1272 | # GNOME base extras (buggy: power-profiles-daemon) 1273 | packages+=(gnome-browser-connector gnome-themes-extra tuned-ppd rygel cups gnome-epub-thumbnailer) 1274 | 1275 | # GNOME wayland screensharing, flatpak & pipewire support 1276 | packages+=(xdg-utils xdg-desktop-portal xdg-desktop-portal-gtk xdg-desktop-portal-gnome flatpak-xdg-utils) 1277 | 1278 | # Audio (Pipewire replacements + session manager): https://wiki.archlinux.org/title/PipeWire#Installation 1279 | packages+=(pipewire pipewire-alsa pipewire-pulse pipewire-jack wireplumber) 1280 | [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ] && packages+=(lib32-pipewire lib32-pipewire-jack) 1281 | 1282 | # Disabled because hardware-specific 1283 | #packages+=(sof-firmware) # Need for intel i5 audio 1284 | 1285 | # Networking & Access 1286 | packages+=(samba rsync gvfs gvfs-mtp gvfs-smb gvfs-nfs gvfs-afc gvfs-goa gvfs-gphoto2 gvfs-google gvfs-dnssd gvfs-wsdd) 1287 | packages+=(modemmanager network-manager-sstp networkmanager-l2tp networkmanager-vpnc networkmanager-pptp networkmanager-openvpn networkmanager-openconnect networkmanager-strongswan) 1288 | 1289 | # Kernel headers 1290 | packages+=("${ARCH_OS_KERNEL}-headers") 1291 | 1292 | # Utils (https://wiki.archlinux.org/title/File_systems) 1293 | packages+=(base-devel archlinux-contrib pacutils fwupd bash-completion dhcp net-tools inetutils nfs-utils e2fsprogs f2fs-tools udftools dosfstools ntfs-3g exfat-utils btrfs-progs xfsprogs p7zip zip unzip unrar tar wget curl) 1294 | packages+=(nautilus-image-converter) 1295 | 1296 | # Runtimes, Builder & Helper 1297 | packages+=(gdb python go rust nodejs npm lua cmake jq zenity gum fzf) 1298 | 1299 | # Certificates 1300 | packages+=(ca-certificates) 1301 | 1302 | # Codecs (https://wiki.archlinux.org/title/Codecs_and_containers) 1303 | packages+=(ffmpeg ffmpegthumbnailer gstreamer gst-libav gst-plugin-pipewire gst-plugins-good gst-plugins-bad gst-plugins-ugly libdvdcss libheif webp-pixbuf-loader opus speex libvpx libwebp) 1304 | packages+=(a52dec faac faad2 flac jasper lame libdca libdv libmad libmpeg2 libtheora libvorbis libxv wavpack x264 xvidcore libdvdnav libdvdread openh264) 1305 | [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ] && packages+=(lib32-gstreamer lib32-gst-plugins-good lib32-libvpx lib32-libwebp) 1306 | 1307 | # Optimization 1308 | packages+=(gamemode sdl_image) 1309 | [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ] && packages+=(lib32-gamemode lib32-sdl_image) 1310 | 1311 | # Fonts 1312 | packages+=(ttf-firacode-nerd ttf-nerd-fonts-symbols ttf-font-awesome noto-fonts noto-fonts-emoji ttf-liberation ttf-dejavu adobe-source-sans-fonts adobe-source-serif-fonts) 1313 | 1314 | # Theming 1315 | packages+=(adw-gtk-theme tela-circle-icon-theme-standard) 1316 | fi 1317 | 1318 | # Installing packages together (preventing conflicts e.g.: jack2 and piepwire-jack) 1319 | chroot_pacman_install "${packages[@]}" 1320 | 1321 | # Force remove gnome packages 1322 | if [ "$ARCH_OS_DESKTOP_SLIM_ENABLED" = "true" ]; then 1323 | chroot_pacman_remove gnome-calendar || true 1324 | chroot_pacman_remove gnome-maps || true 1325 | chroot_pacman_remove gnome-contacts || true 1326 | chroot_pacman_remove gnome-font-viewer || true 1327 | chroot_pacman_remove gnome-characters || true 1328 | chroot_pacman_remove gnome-clocks || true 1329 | chroot_pacman_remove gnome-connections || true 1330 | chroot_pacman_remove gnome-music || true 1331 | chroot_pacman_remove gnome-weather || true 1332 | chroot_pacman_remove gnome-calculator || true 1333 | chroot_pacman_remove gnome-logs || true 1334 | chroot_pacman_remove gnome-text-editor || true 1335 | chroot_pacman_remove gnome-disk-utility || true 1336 | chroot_pacman_remove simple-scan || true 1337 | chroot_pacman_remove baobab || true 1338 | chroot_pacman_remove totem || true 1339 | chroot_pacman_remove snapshot || true 1340 | chroot_pacman_remove epiphany || true 1341 | chroot_pacman_remove loupe || true 1342 | chroot_pacman_remove decibels || true 1343 | #chroot_pacman_remove evince || true # Need for sushi 1344 | fi 1345 | 1346 | # Add user to other useful groups (https://wiki.archlinux.org/title/Users_and_groups#User_groups) 1347 | arch-chroot /mnt groupadd -f plugdev 1348 | arch-chroot /mnt usermod -aG adm,audio,video,optical,input,tty,plugdev "$ARCH_OS_USERNAME" 1349 | 1350 | # Add user to gamemode group 1351 | [ "$ARCH_OS_DESKTOP_EXTRAS_ENABLED" = "true" ] && arch-chroot /mnt gpasswd -a "$ARCH_OS_USERNAME" gamemode 1352 | 1353 | # Enable GNOME auto login 1354 | mkdir -p /mnt/etc/gdm 1355 | # grep -qrnw /mnt/etc/gdm/custom.conf -e "AutomaticLoginEnable" || sed -i "s/^\[security\]/AutomaticLoginEnable=True\nAutomaticLogin=${ARCH_OS_USERNAME}\n\n\[security\]/g" /mnt/etc/gdm/custom.conf 1356 | { 1357 | echo "[daemon]" 1358 | echo "WaylandEnable=True" 1359 | echo "" 1360 | echo "AutomaticLoginEnable=True" 1361 | echo "AutomaticLogin=${ARCH_OS_USERNAME}" 1362 | echo "" 1363 | echo "[debug]" 1364 | echo "Enable=False" 1365 | } >/mnt/etc/gdm/custom.conf 1366 | 1367 | # Set git-credential-libsecret in ~/.gitconfig 1368 | arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- git config --global credential.helper /usr/lib/git-core/git-credential-libsecret 1369 | 1370 | # GnuPG integration (https://wiki.archlinux.org/title/GNOME/Keyring#GnuPG_integration) 1371 | mkdir -p "/mnt/home/${ARCH_OS_USERNAME}/.gnupg" 1372 | echo 'pinentry-program /usr/bin/pinentry-gnome3' >"/mnt/home/${ARCH_OS_USERNAME}/.gnupg/gpg-agent.conf" 1373 | 1374 | # Set environment 1375 | mkdir -p "/mnt/home/${ARCH_OS_USERNAME}/.config/environment.d/" 1376 | # shellcheck disable=SC2016 1377 | { 1378 | echo '# SSH AGENT' 1379 | echo 'SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/gcr/ssh' # Set gcr sock (https://wiki.archlinux.org/title/GNOME/Keyring#Setup_gcr) 1380 | echo '' 1381 | echo '# PATH' 1382 | echo 'PATH="${PATH}:${HOME}/.local/bin"' 1383 | echo '' 1384 | echo '# XDG' 1385 | echo 'XDG_CONFIG_HOME="${HOME}/.config"' 1386 | echo 'XDG_DATA_HOME="${HOME}/.local/share"' 1387 | echo 'XDG_STATE_HOME="${HOME}/.local/state"' 1388 | echo 'XDG_CACHE_HOME="${HOME}/.cache" ' 1389 | } >"/mnt/home/${ARCH_OS_USERNAME}/.config/environment.d/00-arch.conf" 1390 | 1391 | # shellcheck disable=SC2016 1392 | { 1393 | echo '# Workaround for Flatpak aliases' 1394 | echo 'PATH="${PATH}:/var/lib/flatpak/exports/bin"' 1395 | } >"/mnt/home/${ARCH_OS_USERNAME}/.config/environment.d/99-flatpak.conf" 1396 | 1397 | # Samba 1398 | if [ "$ARCH_OS_DESKTOP_EXTRAS_ENABLED" = "true" ]; then 1399 | 1400 | # Create samba config 1401 | mkdir -p "/mnt/etc/samba/" 1402 | { 1403 | echo '[global]' 1404 | echo ' workgroup = WORKGROUP' 1405 | echo ' server string = Samba Server' 1406 | echo ' server role = standalone server' 1407 | echo ' security = user' 1408 | echo ' map to guest = Bad User' 1409 | echo ' log file = /var/log/samba/%m.log' 1410 | echo ' max log size = 50' 1411 | echo ' client min protocol = SMB2' 1412 | echo ' server min protocol = SMB2' 1413 | if [ "$ARCH_OS_SAMBA_SHARE_ENABLED" = "true" ]; then 1414 | echo 1415 | echo '[homes]' 1416 | echo ' comment = Home Directory' 1417 | echo ' browseable = yes' 1418 | echo ' read only = no' 1419 | echo ' create mask = 0700' 1420 | echo ' directory mask = 0700' 1421 | echo ' valid users = %S' 1422 | echo 1423 | echo '[public]' 1424 | echo ' comment = Public Share' 1425 | echo ' path = /srv/samba/public' 1426 | echo ' browseable = yes' 1427 | echo ' guest ok = yes' 1428 | echo ' read only = no' 1429 | echo ' writable = yes' 1430 | echo ' create mask = 0777' 1431 | echo ' directory mask = 0777' 1432 | echo ' force user = nobody' 1433 | echo ' force group = users' 1434 | fi 1435 | } >/mnt/etc/samba/smb.conf 1436 | 1437 | # Test samba config 1438 | arch-chroot /mnt testparm -s /etc/samba/smb.conf 1439 | 1440 | if [ "$ARCH_OS_SAMBA_SHARE_ENABLED" = "true" ]; then 1441 | 1442 | # Create samba public dir 1443 | arch-chroot /mnt mkdir -p /srv/samba/public 1444 | arch-chroot /mnt chmod 777 /srv/samba/public 1445 | arch-chroot /mnt chown -R nobody:users /srv/samba/public 1446 | 1447 | # Add user as samba user with same password (different user db) 1448 | ( 1449 | echo "$ARCH_OS_PASSWORD" 1450 | echo "$ARCH_OS_PASSWORD" 1451 | ) | arch-chroot /mnt smbpasswd -s -a "$ARCH_OS_USERNAME" 1452 | fi 1453 | 1454 | # Start samba services 1455 | arch-chroot /mnt systemctl enable smb.service 1456 | 1457 | # https://wiki.archlinux.org/title/Samba#Windows_1709_or_up_does_not_discover_the_samba_server_in_Network_view 1458 | arch-chroot /mnt systemctl enable wsdd.service 1459 | 1460 | # Disabled (master browser issues) > may needed for old windows clients 1461 | #arch-chroot /mnt systemctl enable nmb.service 1462 | fi 1463 | 1464 | # Set X11 keyboard layout in /etc/X11/xorg.conf.d/00-keyboard.conf 1465 | mkdir -p /mnt/etc/X11/xorg.conf.d/ 1466 | { 1467 | echo 'Section "InputClass"' 1468 | echo ' Identifier "system-keyboard"' 1469 | echo ' MatchIsKeyboard "yes"' 1470 | echo ' Option "XkbLayout" "'"${ARCH_OS_DESKTOP_KEYBOARD_LAYOUT}"'"' 1471 | echo ' Option "XkbModel" "'"${ARCH_OS_DESKTOP_KEYBOARD_MODEL}"'"' 1472 | echo ' Option "XkbVariant" "'"${ARCH_OS_DESKTOP_KEYBOARD_VARIANT}"'"' 1473 | echo 'EndSection' 1474 | } >/mnt/etc/X11/xorg.conf.d/00-keyboard.conf 1475 | 1476 | # Enable Arch OS Desktop services 1477 | arch-chroot /mnt systemctl enable gdm.service # GNOME 1478 | arch-chroot /mnt systemctl enable bluetooth.service # Bluetooth 1479 | arch-chroot /mnt systemctl enable avahi-daemon # Network browsing service 1480 | arch-chroot /mnt systemctl enable gpm.service # TTY Mouse Support 1481 | 1482 | # Extra services 1483 | if [ "$ARCH_OS_DESKTOP_EXTRAS_ENABLED" = "true" ]; then 1484 | arch-chroot /mnt systemctl enable tuned # Power daemon 1485 | arch-chroot /mnt systemctl enable tuned-ppd # Power daemon 1486 | arch-chroot /mnt systemctl enable cups.socket # Printer 1487 | fi 1488 | 1489 | # User services (Not working: Failed to connect to user scope bus via local transport: Permission denied) 1490 | # arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- systemctl enable --user pipewire.service # Pipewire 1491 | # arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- systemctl enable --user pipewire-pulse.service # Pipewire 1492 | # arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- systemctl enable --user wireplumber.service # Pipewire 1493 | # arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- systemctl enable --user gcr-ssh-agent.socket # GCR ssh-agent 1494 | 1495 | # Workaround: Manual creation of user service symlinks 1496 | arch-chroot /mnt mkdir -p "/home/${ARCH_OS_USERNAME}/.config/systemd/user/default.target.wants" 1497 | arch-chroot /mnt ln -s "/usr/lib/systemd/user/pipewire.service" "/home/${ARCH_OS_USERNAME}/.config/systemd/user/default.target.wants/pipewire.service" 1498 | arch-chroot /mnt ln -s "/usr/lib/systemd/user/pipewire-pulse.service" "/home/${ARCH_OS_USERNAME}/.config/systemd/user/default.target.wants/pipewire-pulse.service" 1499 | arch-chroot /mnt mkdir -p "/home/${ARCH_OS_USERNAME}/.config/systemd/user/sockets.target.wants" 1500 | arch-chroot /mnt ln -s "/usr/lib/systemd/user/pipewire.socket" "/home/${ARCH_OS_USERNAME}/.config/systemd/user/sockets.target.wants/pipewire.socket" 1501 | arch-chroot /mnt ln -s "/usr/lib/systemd/user/pipewire-pulse.socket" "/home/${ARCH_OS_USERNAME}/.config/systemd/user/sockets.target.wants/pipewire-pulse.socket" 1502 | arch-chroot /mnt ln -s "/usr/lib/systemd/user/gcr-ssh-agent.socket" "/home/${ARCH_OS_USERNAME}/.config/systemd/user/sockets.target.wants/gcr-ssh-agent.socket" 1503 | arch-chroot /mnt mkdir -p "/home/${ARCH_OS_USERNAME}/.config/systemd/user/pipewire.service.wants" 1504 | arch-chroot /mnt ln -s "/usr/lib/systemd/user/wireplumber.service" "/home/${ARCH_OS_USERNAME}/.config/systemd/user/pipewire-session-manager.service" 1505 | arch-chroot /mnt ln -s "/usr/lib/systemd/user/wireplumber.service" "/home/${ARCH_OS_USERNAME}/.config/systemd/user/pipewire.service.wants/wireplumber.service" 1506 | arch-chroot /mnt chown -R "$ARCH_OS_USERNAME":"$ARCH_OS_USERNAME" "/home/${ARCH_OS_USERNAME}/.config/systemd/" 1507 | 1508 | # Enhance PAM (fix keyring issue for relogin): add try_first_pass 1509 | sed -i 's/auth\s\+optional\s\+pam_gnome_keyring\.so$/& try_first_pass/' /mnt/etc/pam.d/gdm-password /mnt/etc/pam.d/gdm-autologin 1510 | 1511 | # Create users applications dir 1512 | mkdir -p "/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications" 1513 | 1514 | # Create UEFI Boot desktop entry 1515 | # { 1516 | # echo '[Desktop Entry]' 1517 | # echo 'Name=Reboot to UEFI' 1518 | # echo 'Icon=system-reboot' 1519 | # echo 'Exec=systemctl reboot --firmware-setup' 1520 | # echo 'Type=Application' 1521 | # echo 'Terminal=false' 1522 | # } >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/systemctl-reboot-firmware.desktop" 1523 | 1524 | # Hide aplications desktop icons 1525 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/bssh.desktop" 1526 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/bvnc.desktop" 1527 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/avahi-discover.desktop" 1528 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/qv4l2.desktop" 1529 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/qvidcap.desktop" 1530 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/lstopo.desktop" 1531 | 1532 | # Hide aplications (extra) desktop icons 1533 | if [ "$ARCH_OS_DESKTOP_EXTRAS_ENABLED" = "true" ]; then 1534 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/stoken-gui.desktop" # networkmanager-openconnect 1535 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/stoken-gui-small.desktop" # networkmanager-openconnect 1536 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/cups.desktop" 1537 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/tuned-gui.desktop" 1538 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/cmake-gui.desktop" 1539 | fi 1540 | 1541 | # Hide Shell Enhancement apps 1542 | if [ "$ARCH_OS_SHELL_ENHANCEMENT_ENABLED" = "true" ]; then 1543 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/fish.desktop" 1544 | echo -e '[Desktop Entry]\nType=Application\nHidden=true' >"/mnt/home/${ARCH_OS_USERNAME}/.local/share/applications/btop.desktop" 1545 | fi 1546 | 1547 | # Set Flatpak theme access 1548 | arch-chroot /mnt flatpak override --filesystem=xdg-config/gtk-3.0 1549 | arch-chroot /mnt flatpak override --filesystem=xdg-config/gtk-4.0 1550 | 1551 | # Add Init script 1552 | if [ "$ARCH_OS_DESKTOP_EXTRAS_ENABLED" = "true" ]; then 1553 | { 1554 | echo "# exec_install_desktop | Favorite apps" 1555 | echo "gsettings set org.gnome.shell favorite-apps \"['org.gnome.Console.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop', 'org.gnome.Settings.desktop']\"" 1556 | echo "# exec_install_desktop | Reset app-folders" 1557 | echo "dconf reset -f /org/gnome/desktop/app-folders/" 1558 | echo "# exec_install_desktop | Theming settings" 1559 | echo "gsettings set org.gnome.desktop.interface gtk-theme 'adw-gtk3'" 1560 | echo "gsettings set org.gnome.desktop.interface icon-theme 'Tela-circle'" 1561 | echo "gsettings set org.gnome.desktop.interface accent-color 'slate'" 1562 | echo "# exec_install_desktop | Font settings" 1563 | echo "gsettings set org.gnome.desktop.interface font-hinting 'slight'" 1564 | echo "gsettings set org.gnome.desktop.interface font-antialiasing 'rgba'" 1565 | echo "gsettings set org.gnome.desktop.interface monospace-font-name 'FiraCode Nerd Font 11'" 1566 | echo "# exec_install_desktop | Show all input sources" 1567 | echo "gsettings set org.gnome.desktop.input-sources show-all-sources true" 1568 | echo "# exec_install_desktop | Mutter settings" 1569 | echo "gsettings set org.gnome.mutter center-new-windows true" 1570 | echo "# exec_install_desktop | File chooser settings" 1571 | echo "gsettings set org.gtk.Settings.FileChooser sort-directories-first true" 1572 | echo "gsettings set org.gtk.gtk4.Settings.FileChooser sort-directories-first true" 1573 | echo "# exec_install_desktop | Keybinding settings" 1574 | echo "gsettings set org.gnome.desktop.wm.keybindings close \"['q']\"" 1575 | echo "gsettings set org.gnome.desktop.wm.keybindings minimize \"['h']\"" 1576 | echo "gsettings set org.gnome.desktop.wm.keybindings show-desktop \"['d']\"" 1577 | echo "gsettings set org.gnome.desktop.wm.keybindings toggle-fullscreen \"['F11']\"" 1578 | } >>"/mnt/home/${ARCH_OS_USERNAME}/${INIT_FILENAME}.sh" 1579 | fi 1580 | 1581 | # Set correct permissions 1582 | arch-chroot /mnt chown -R "$ARCH_OS_USERNAME":"$ARCH_OS_USERNAME" "/home/${ARCH_OS_USERNAME}" 1583 | 1584 | # Return 1585 | process_return 0 1586 | ) &>"$PROCESS_LOG" & 1587 | process_capture $! "$process_name" 1588 | fi 1589 | } 1590 | 1591 | # --------------------------------------------------------------------------------------------------- 1592 | 1593 | exec_install_graphics_driver() { 1594 | local process_name="Desktop Driver" 1595 | if [ -n "$ARCH_OS_DESKTOP_GRAPHICS_DRIVER" ] && [ "$ARCH_OS_DESKTOP_GRAPHICS_DRIVER" != "none" ]; then 1596 | process_init "$process_name" 1597 | ( 1598 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1599 | case "${ARCH_OS_DESKTOP_GRAPHICS_DRIVER}" in 1600 | "mesa") # https://wiki.archlinux.org/title/OpenGL#Installation 1601 | local packages=(mesa mesa-utils vkd3d vulkan-tools) 1602 | [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ] && packages+=(lib32-mesa lib32-mesa-utils lib32-vkd3d) 1603 | chroot_pacman_install "${packages[@]}" 1604 | ;; 1605 | "intel_i915") # https://wiki.archlinux.org/title/Intel_graphics#Installation 1606 | local packages=(vulkan-intel vkd3d libva-intel-driver vulkan-tools) 1607 | [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ] && packages+=(lib32-vulkan-intel lib32-vkd3d lib32-libva-intel-driver) 1608 | chroot_pacman_install "${packages[@]}" 1609 | sed -i "s/^MODULES=(.*)/MODULES=(i915)/g" /mnt/etc/mkinitcpio.conf 1610 | arch-chroot /mnt mkinitcpio -P 1611 | ;; 1612 | "nvidia") # https://wiki.archlinux.org/title/NVIDIA#Installation 1613 | local packages=("${ARCH_OS_KERNEL}-headers" nvidia-dkms nvidia-settings nvidia-utils opencl-nvidia vkd3d vulkan-tools) 1614 | [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ] && packages+=(lib32-nvidia-utils lib32-opencl-nvidia lib32-vkd3d) 1615 | chroot_pacman_install "${packages[@]}" 1616 | # https://wiki.archlinux.org/title/NVIDIA#DRM_kernel_mode_setting 1617 | # Alternative (slow boot, bios logo twice, but correct plymouth resolution): 1618 | #sed -i "s/systemd zswap.enabled=0/systemd nvidia_drm.modeset=1 nvidia_drm.fbdev=1 zswap.enabled=0/g" /mnt/boot/loader/entries/main.conf 1619 | mkdir -p /mnt/etc/modprobe.d/ && echo -e 'options nvidia_drm modeset=1 fbdev=1' >/mnt/etc/modprobe.d/nvidia.conf 1620 | sed -i "s/^MODULES=(.*)/MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)/g" /mnt/etc/mkinitcpio.conf 1621 | # https://wiki.archlinux.org/title/NVIDIA#pacman_hook 1622 | mkdir -p /mnt/etc/pacman.d/hooks/ 1623 | { 1624 | echo "[Trigger]" 1625 | echo "Operation=Install" 1626 | echo "Operation=Upgrade" 1627 | echo "Operation=Remove" 1628 | echo "Type=Package" 1629 | echo "Target=nvidia" 1630 | echo "Target=${ARCH_OS_KERNEL}" 1631 | echo "# Change the linux part above if a different kernel is used" 1632 | echo "" 1633 | echo "[Action]" 1634 | echo "Description=Update NVIDIA module in initcpio" 1635 | echo "Depends=mkinitcpio" 1636 | echo "When=PostTransaction" 1637 | echo "NeedsTargets" 1638 | echo "Exec=/bin/sh -c 'while read -r trg; do case \$trg in linux*) exit 0; esac; done; /usr/bin/mkinitcpio -P'" 1639 | } >/mnt/etc/pacman.d/hooks/nvidia.hook 1640 | # Enable Wayland Support (https://wiki.archlinux.org/title/GDM#Wayland_and_the_proprietary_NVIDIA_driver) 1641 | [ ! -f /mnt/etc/udev/rules.d/61-gdm.rules ] && mkdir -p /mnt/etc/udev/rules.d/ && ln -s /dev/null /mnt/etc/udev/rules.d/61-gdm.rules 1642 | # Rebuild initial ram disk 1643 | arch-chroot /mnt mkinitcpio -P 1644 | ;; 1645 | "amd") # https://wiki.archlinux.org/title/AMDGPU#Installation 1646 | # Deprecated: libva-mesa-driver lib32-libva-mesa-driver mesa-vdpau lib32-mesa-vdpau 1647 | local packages=(mesa mesa-utils xf86-video-amdgpu vulkan-radeon vkd3d vulkan-tools) 1648 | [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ] && packages+=(lib32-mesa lib32-vulkan-radeon lib32-vkd3d) 1649 | chroot_pacman_install "${packages[@]}" 1650 | # Must be discussed: https://wiki.archlinux.org/title/AMDGPU#Disable_loading_radeon_completely_at_boot 1651 | sed -i "s/^MODULES=(.*)/MODULES=(amdgpu)/g" /mnt/etc/mkinitcpio.conf 1652 | arch-chroot /mnt mkinitcpio -P 1653 | ;; 1654 | "ati") # https://wiki.archlinux.org/title/ATI#Installation 1655 | # Deprecated: libva-mesa-driver lib32-libva-mesa-driver mesa-vdpau lib32-mesa-vdpau 1656 | local packages=(mesa mesa-utils xf86-video-ati vkd3d vulkan-tools) 1657 | [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ] && packages+=(lib32-mesa lib32-vkd3d) 1658 | chroot_pacman_install "${packages[@]}" 1659 | sed -i "s/^MODULES=(.*)/MODULES=(radeon)/g" /mnt/etc/mkinitcpio.conf 1660 | arch-chroot /mnt mkinitcpio -P 1661 | ;; 1662 | esac 1663 | process_return 0 1664 | ) &>"$PROCESS_LOG" & 1665 | process_capture $! "$process_name" 1666 | fi 1667 | } 1668 | 1669 | # --------------------------------------------------------------------------------------------------- 1670 | 1671 | exec_enable_multilib() { 1672 | local process_name="Enable Multilib" 1673 | if [ "$ARCH_OS_MULTILIB_ENABLED" = "true" ]; then 1674 | process_init "$process_name" 1675 | ( 1676 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1677 | sed -i '/\[multilib\]/,/Include/s/^#//' /mnt/etc/pacman.conf 1678 | arch-chroot /mnt pacman -Syyu --noconfirm 1679 | process_return 0 1680 | ) &>"$PROCESS_LOG" & 1681 | process_capture $! "$process_name" 1682 | fi 1683 | } 1684 | 1685 | # --------------------------------------------------------------------------------------------------- 1686 | 1687 | exec_install_bootsplash() { 1688 | local process_name="Bootsplash" 1689 | if [ "$ARCH_OS_BOOTSPLASH_ENABLED" = "true" ]; then 1690 | process_init "$process_name" 1691 | ( 1692 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1693 | chroot_pacman_install plymouth git base-devel # Install packages 1694 | sed -i "s/base systemd keyboard/base systemd plymouth keyboard/g" /mnt/etc/mkinitcpio.conf # Configure mkinitcpio 1695 | chroot_aur_install plymouth-theme-arch-os # Install Arch OS plymouth theme from AUR 1696 | arch-chroot /mnt plymouth-set-default-theme -R arch-os # Set Theme & rebuild initram disk 1697 | process_return 0 # Return 1698 | ) &>"$PROCESS_LOG" & 1699 | process_capture $! "$process_name" 1700 | fi 1701 | } 1702 | 1703 | # --------------------------------------------------------------------------------------------------- 1704 | 1705 | exec_install_aur_helper() { 1706 | local process_name="AUR Helper" 1707 | if [ -n "$ARCH_OS_AUR_HELPER" ] && [ "$ARCH_OS_AUR_HELPER" != "none" ]; then 1708 | process_init "$process_name" 1709 | ( 1710 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1711 | chroot_pacman_install git base-devel # Install packages 1712 | chroot_aur_install "$ARCH_OS_AUR_HELPER" # Install AUR helper 1713 | # Paru config 1714 | if [ "$ARCH_OS_AUR_HELPER" = "paru" ] || [ "$ARCH_OS_AUR_HELPER" = "paru-bin" ] || [ "$ARCH_OS_AUR_HELPER" = "paru-git" ]; then 1715 | sed -i 's/^#BottomUp/BottomUp/g' /mnt/etc/paru.conf 1716 | sed -i 's/^#SudoLoop/SudoLoop/g' /mnt/etc/paru.conf 1717 | fi 1718 | process_return 0 # Return 1719 | ) &>"$PROCESS_LOG" & 1720 | process_capture $! "$process_name" 1721 | fi 1722 | } 1723 | 1724 | # --------------------------------------------------------------------------------------------------- 1725 | 1726 | exec_install_housekeeping() { 1727 | local process_name="Housekeeping" 1728 | if [ "$ARCH_OS_HOUSEKEEPING_ENABLED" = "true" ]; then 1729 | process_init "$process_name" 1730 | ( 1731 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1732 | chroot_pacman_install pacman-contrib reflector pkgfile smartmontools irqbalance # Install Base packages 1733 | { # Configure reflector service 1734 | echo "# Reflector config for the systemd service" 1735 | echo "--save /etc/pacman.d/mirrorlist" 1736 | [ -n "$ARCH_OS_REFLECTOR_COUNTRY" ] && echo "--country ${ARCH_OS_REFLECTOR_COUNTRY}" 1737 | #echo "--completion-percent 95" 1738 | echo "--protocol https" 1739 | echo "--age 12" 1740 | echo "--latest 10" 1741 | echo "--sort rate" 1742 | } >/mnt/etc/xdg/reflector/reflector.conf 1743 | # Enable services 1744 | arch-chroot /mnt systemctl enable reflector.service # Rank mirrors after boot (reflector) 1745 | arch-chroot /mnt systemctl enable paccache.timer # Discard cached/unused packages weekly (pacman-contrib) 1746 | arch-chroot /mnt systemctl enable pkgfile-update.timer # Pkgfile update timer (pkgfile) 1747 | arch-chroot /mnt systemctl enable smartd # SMART check service (smartmontools) 1748 | arch-chroot /mnt systemctl enable irqbalance.service # IRQ balancing daemon (irqbalance) 1749 | process_return 0 # Return 1750 | ) &>"$PROCESS_LOG" & 1751 | process_capture $! "$process_name" 1752 | fi 1753 | } 1754 | 1755 | # --------------------------------------------------------------------------------------------------- 1756 | 1757 | exec_install_archos_manager() { 1758 | local process_name="Arch OS Manager" 1759 | if [ "$ARCH_OS_MANAGER_ENABLED" = "true" ]; then 1760 | process_init "$process_name" 1761 | ( 1762 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1763 | chroot_pacman_install git base-devel pacman-contrib # Install dependencies 1764 | chroot_aur_install arch-os-manager # Install archos-manager 1765 | 1766 | # { 1767 | # echo "# exec_install_archos_manager | Initialize" 1768 | # echo "/usr/bin/arch-os --init &> /dev/null" 1769 | # } >>"/mnt/home/${ARCH_OS_USERNAME}/${INIT_FILENAME}.sh" 1770 | 1771 | # Init manager 1772 | arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- /usr/bin/arch-os --init 1773 | 1774 | process_return 0 # Return 1775 | ) &>"$PROCESS_LOG" & 1776 | process_capture $! "$process_name" 1777 | fi 1778 | } 1779 | 1780 | # --------------------------------------------------------------------------------------------------- 1781 | 1782 | exec_install_shell_enhancement() { 1783 | local process_name="Shell Enhancement" 1784 | if [ "$ARCH_OS_SHELL_ENHANCEMENT_ENABLED" = "true" ]; then 1785 | process_init "$process_name" 1786 | ( 1787 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 1788 | 1789 | # Install packages 1790 | local packages=(git starship eza bat zoxide fd fzf fastfetch mc btop nano man-db bash-completion nano-syntax-highlighting ttf-firacode-nerd ttf-nerd-fonts-symbols) 1791 | chroot_pacman_install "${packages[@]}" 1792 | 1793 | # Create fastfetch config dirs 1794 | mkdir -p "/mnt/root/.config/fastfetch" "/mnt/home/${ARCH_OS_USERNAME}/.config/fastfetch" 1795 | 1796 | # Install & set fish for root & user 1797 | if [ "$ARCH_OS_SHELL_ENHANCEMENT_FISH_ENABLED" = "true" ]; then 1798 | chroot_pacman_install fish 1799 | mkdir -p "/mnt/root/.config/fish" "/mnt/home/${ARCH_OS_USERNAME}/.config/fish" # Create fish config dirs 1800 | # shellcheck disable=SC2016 1801 | { # Create fish config for root & user 1802 | echo 'if status is-interactive' 1803 | echo ' # Commands to run in interactive sessions can go here' 1804 | echo 'end' 1805 | echo '' 1806 | echo '# Disable welcome message' 1807 | echo 'set fish_greeting' 1808 | echo '' 1809 | echo '# Colorize man pages (bat)' 1810 | echo 'command -v bat &>/dev/null && export MANPAGER="sh -c \"col -bx | bat -l man -p\""' 1811 | echo 'command -v bat &>/dev/null && export MANROFFOPT="-c"' 1812 | echo '' 1813 | echo '# Source user aliases' 1814 | echo 'test -f "$HOME/.aliases" && source "$HOME/.aliases"' 1815 | echo '' 1816 | echo '# Init zoxide' 1817 | echo 'command -v zoxide &>/dev/null && zoxide init fish | source' 1818 | echo '' 1819 | echo '# Init starship promt (except tty)' 1820 | echo 'if not tty | string match -q "/dev/tty*"' 1821 | echo ' and command -v starship >/dev/null' 1822 | echo ' starship init fish | source' 1823 | echo 'end' 1824 | } | tee "/mnt/root/.config/fish/config.fish" "/mnt/home/${ARCH_OS_USERNAME}/.config/fish/config.fish" >/dev/null 1825 | #arch-chroot /mnt chsh -s /usr/bin/fish 1826 | #arch-chroot /mnt chsh -s /usr/bin/fish "$ARCH_OS_USERNAME" 1827 | fi 1828 | 1829 | { # Create aliases for root & user 1830 | echo '# ls / eza' 1831 | echo 'alias ls="ls -h --color=always --group-directories-first"' 1832 | echo 'command -v eza &>/dev/null && alias ls="eza -h --color=always --group-directories-first"' 1833 | echo 'alias ll="ls -l"' 1834 | echo 'alias la="ls -la"' 1835 | echo 'alias lt="ls -Tal"' 1836 | echo -e '\n# Colorize' 1837 | echo 'alias diff="diff --color=auto"' 1838 | echo 'alias grep="grep --color=auto"' 1839 | echo 'alias ip="ip -color=auto"' 1840 | echo -e '\n# Wrapper' 1841 | echo 'alias logs="systemctl --failed; echo; journalctl -p 3 -b"' 1842 | echo 'alias q="exit"' 1843 | echo 'alias c="clear"' 1844 | echo 'command -v fastfetch &>/dev/null && alias fetch="fastfetch"' 1845 | echo 'command -v meld &>/dev/null && alias pacnew="sudo DIFFPROG=meld pacdiff"' 1846 | echo 'command -v xdg-open &>/dev/null && alias open="xdg-open"' 1847 | echo 'alias myip="curl ipv4.icanhazip.com"' 1848 | echo -e '\n# Change dir' 1849 | echo 'alias .="cd .."' 1850 | echo 'alias ..="cd ../.."' 1851 | echo 'alias ...="cd ../../.."' 1852 | echo -e '\n# Packages' 1853 | local pkg_manager='pacman' && [ -n "$ARCH_OS_AUR_HELPER" ] && [ "$ARCH_OS_AUR_HELPER" != "none" ] && pkg_manager="$ARCH_OS_AUR_HELPER" 1854 | if [ "$pkg_manager" = "pacman" ]; then 1855 | echo "alias paci='sudo ${pkg_manager} -S' # Install package" 1856 | echo "alias pacu='sudo ${pkg_manager} -Syu' # System upgrade" 1857 | else 1858 | echo "alias paci='${pkg_manager} -S' # Install package" 1859 | echo "alias pacu='${pkg_manager} -Syu' # System upgrade" 1860 | fi 1861 | echo "alias pacs='${pkg_manager} -Ss' # Search package in database" 1862 | echo "alias pacr='${pkg_manager} -Rns' # Remove package" 1863 | echo "alias pacrc='${pkg_manager} -Scc' # Clear Cache" 1864 | echo "alias pacl='${pkg_manager} -Qe' # List all installed packages" 1865 | echo "alias pacla='${pkg_manager} -Qm' # List installed AUR packages" 1866 | echo "alias pacls='${pkg_manager} -Qs' # Search installed packages" 1867 | echo "alias pacli='${pkg_manager} -Qi' # Show package info" 1868 | } | tee "/mnt/root/.aliases" "/mnt/home/${ARCH_OS_USERNAME}/.aliases" >/dev/null 1869 | 1870 | # shellcheck disable=SC2016 1871 | { # Create bash config for root & user 1872 | echo '# If not running interactively, do not do anything' 1873 | echo '[[ $- != *i* ]] && return' 1874 | echo '' 1875 | echo ' # Export systemd environment vars from ~/.config/environment.d/* (tty only)' 1876 | echo '[[ ${SHLVL} == 1 ]] && [ -z "${DISPLAY}" ] && export $(/usr/lib/systemd/user-environment-generators/30-systemd-environment-d-generator | xargs)' 1877 | echo '' 1878 | echo '# Source aliases' 1879 | echo 'source "${HOME}/.aliases"' 1880 | echo '' 1881 | echo '# Plugin: pkgfile (command not found)' 1882 | echo '[ -f /usr/share/doc/pkgfile/command-not-found.bash ] && source /usr/share/doc/pkgfile/command-not-found.bash' 1883 | echo '' 1884 | echo '# Options' 1885 | echo 'shopt -s autocd # Auto cd' 1886 | echo 'shopt -s cdspell # Correct cd typos' 1887 | echo 'shopt -s checkwinsize # Update windows size on command' 1888 | echo 'shopt -s histappend # Append History instead of overwriting file' 1889 | echo 'shopt -s cmdhist # Bash attempts to save all lines of a multiple-line command in the same history entry' 1890 | echo 'shopt -s extglob # Extended pattern' 1891 | echo 'shopt -s no_empty_cmd_completion # No empty completion' 1892 | echo 'shopt -s expand_aliases # Expand aliases' 1893 | echo '' 1894 | echo '# Ignore upper and lowercase when TAB completion' 1895 | echo 'bind "set completion-ignore-case on"' 1896 | echo '' 1897 | echo '# Colorize man pages (bat)' 1898 | echo 'command -v bat &>/dev/null && export MANPAGER="sh -c \"col -bx | bat -l man -p\""' 1899 | echo 'command -v bat &>/dev/null && export MANROFFOPT="-c"' 1900 | echo '' 1901 | echo '# History' 1902 | echo 'export HISTSIZE=1000 # History will save N commands' 1903 | echo 'export HISTFILESIZE=${HISTSIZE} # History will remember N commands' 1904 | echo 'export HISTCONTROL=ignoredups:erasedups # Ingore duplicates and spaces (ignoreboth)' 1905 | echo 'export HISTTIMEFORMAT="%F %T " # Add date to history' 1906 | echo '' 1907 | echo '# History ignore list' 1908 | echo 'export HISTIGNORE="&:ls:ll:la:cd:exit:clear:history:q:c"' 1909 | echo '' 1910 | echo '# Start fish shell - no tty (https://wiki.archlinux.org/title/Fish#Modify_.bashrc_to_drop_into_fish)' 1911 | echo 'if [[ ! $(tty) =~ /dev/tty[0-9]* ]] && command -v fish &>/dev/null && [[ $(ps --no-header --pid=$PPID --format=comm) != "fish" && -z ${BASH_EXECUTION_STRING} && ${SHLVL} == 1 ]]; then' 1912 | echo ' shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""' 1913 | echo ' exec fish $LOGIN_OPTION' 1914 | echo ' return' 1915 | echo 'fi' 1916 | echo '' 1917 | echo '# Init starship (no tty)' 1918 | echo '[[ ! $(tty) =~ /dev/tty[0-9]* ]] && command -v starship &>/dev/null && eval "$(starship init bash)"' 1919 | echo '' 1920 | echo '# Init zoxide' 1921 | echo 'command -v zoxide &>/dev/null && eval "$(zoxide init bash)"' 1922 | } | tee "/mnt/root/.bashrc" "/mnt/home/${ARCH_OS_USERNAME}/.bashrc" >/dev/null 1923 | 1924 | # Download Arch OS starship theme 1925 | mkdir -p "/mnt/home/${ARCH_OS_USERNAME}/.config/" 1926 | curl -Lf https://raw.githubusercontent.com/murkl/starship-theme-arch-os/refs/heads/main/starship.toml >"/mnt/home/${ARCH_OS_USERNAME}/.config/starship.toml" 1927 | if [ ! -s "/mnt/home/${ARCH_OS_USERNAME}/.config/starship.toml" ]; then 1928 | # Theme fallback 1929 | arch-chroot /mnt /usr/bin/starship preset pure-preset -o "/home/${ARCH_OS_USERNAME}/.config/starship.toml" 1930 | fi 1931 | cp "/mnt/home/${ARCH_OS_USERNAME}/.config/starship.toml" "/mnt/root/.config/starship.toml" 1932 | arch-chroot /mnt chown -R "$ARCH_OS_USERNAME":"$ARCH_OS_USERNAME" "/home/${ARCH_OS_USERNAME}/.config/" 1933 | 1934 | # shellcheck disable=SC2028,SC2016 1935 | { # Create fastfetch config for root & user 1936 | echo '{' 1937 | echo ' "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",' 1938 | echo ' "logo": {' 1939 | echo ' "source": "arch2",' 1940 | echo ' "type": "auto",' 1941 | echo ' "color": {' 1942 | echo ' "1": "white",' 1943 | echo ' "2": "white"' 1944 | echo ' },' 1945 | echo ' "padding": {' 1946 | echo ' "top": 0,' 1947 | echo ' "left": 4,' 1948 | echo ' "right": 8' 1949 | echo ' }' 1950 | echo ' },' 1951 | echo ' "display": {' 1952 | echo ' "key": {' 1953 | echo ' "width": 20' 1954 | echo ' },' 1955 | echo ' "separator": " → ",' 1956 | echo ' "color": {' 1957 | echo ' "keys": "default",' 1958 | echo ' "separator": "magenta"' 1959 | echo ' }' 1960 | echo ' },' 1961 | echo ' "modules": [' 1962 | echo ' "break",' 1963 | echo ' {' 1964 | echo ' "key": "Distro ",' 1965 | echo ' "type": "os",' 1966 | echo ' "format": "Arch OS"' 1967 | echo ' },' 1968 | echo ' {' 1969 | echo ' "key": "Kernel ",' 1970 | echo ' "type": "kernel"' 1971 | echo ' },' 1972 | echo ' {' 1973 | echo ' "key": "CPU ",' 1974 | echo ' "type": "cpu",' 1975 | echo ' "temp": true' 1976 | echo ' },' 1977 | echo ' {' 1978 | echo ' "key": "GPU ",' 1979 | echo ' "type": "gpu",' 1980 | echo ' "temp": true' 1981 | echo ' },' 1982 | echo ' "break",' 1983 | echo ' {' 1984 | echo ' "key": "Desktop ",' 1985 | echo ' "type": "de"' 1986 | echo ' },' 1987 | echo ' {' 1988 | echo ' "key": "Manager ",' 1989 | echo ' "type": "wm"' 1990 | echo ' },' 1991 | echo ' {' 1992 | echo ' "key": "Shell ",' 1993 | echo ' "type": "shell"' 1994 | echo ' },' 1995 | echo ' {' 1996 | echo ' "key": "Terminal ",' 1997 | echo ' "type": "terminal"' 1998 | echo ' },' 1999 | echo ' "break",' 2000 | echo ' {' 2001 | echo ' "key": "Disk ",' 2002 | echo ' "type": "disk"' 2003 | echo ' },' 2004 | echo ' {' 2005 | echo ' "key": "Memory ",' 2006 | echo ' "type": "memory"' 2007 | echo ' },' 2008 | echo ' {' 2009 | echo ' "key": "Network ",' 2010 | echo ' "type": "localip"' 2011 | echo ' },' 2012 | echo ' {' 2013 | echo ' "key": "Uptime ",' 2014 | echo ' "type": "uptime"' 2015 | echo ' },' 2016 | echo ' "break",' 2017 | echo ' {' 2018 | echo ' "key": "Packages ",' 2019 | echo ' "type": "packages"' 2020 | echo ' },' 2021 | echo ' "break",' 2022 | echo ' {' 2023 | echo ' "type": "custom",' 2024 | echo ' "format": "{#red}● {#green}● {#yellow}● {#blue}● {#magenta}● {#cyan}● {#white}● {#default}●"' 2025 | echo ' }' 2026 | echo ' ]' 2027 | echo '}' 2028 | } | tee "/mnt/root/.config/fastfetch/config.jsonc" "/mnt/home/${ARCH_OS_USERNAME}/.config/fastfetch/config.jsonc" >/dev/null 2029 | 2030 | { # Set nano environment 2031 | echo 'EDITOR=nano' 2032 | echo 'VISUAL=nano' 2033 | } >/mnt/etc/environment 2034 | 2035 | # Set Nano colors 2036 | sed -i "s/^# set linenumbers/set linenumbers/" /mnt/etc/nanorc 2037 | sed -i "s/^# set minibar/set minibar/" /mnt/etc/nanorc 2038 | sed -i 's;^# include /usr/share/nano/\*\.nanorc;include /usr/share/nano/*.nanorc\ninclude /usr/share/nano/extra/*.nanorc\ninclude /usr/share/nano-syntax-highlighting/*.nanorc;g' /mnt/etc/nanorc 2039 | 2040 | { # Add init script 2041 | echo "# exec_install_shell_enhancement | Set default monospace font" 2042 | echo "gsettings set org.gnome.desktop.interface monospace-font-name 'FiraCode Nerd Font 11'" 2043 | if [ "$ARCH_OS_SHELL_ENHANCEMENT_FISH_ENABLED" = "true" ]; then 2044 | echo "# exec_install_shell_enhancement | Set fish theme" 2045 | echo "fish -c 'fish_config theme choose Nord && echo y | fish_config theme save'" 2046 | fi 2047 | } >>"/mnt/home/${ARCH_OS_USERNAME}/${INIT_FILENAME}.sh" 2048 | 2049 | # Set correct permissions 2050 | arch-chroot /mnt chown -R "$ARCH_OS_USERNAME":"$ARCH_OS_USERNAME" "/home/${ARCH_OS_USERNAME}" 2051 | 2052 | # Finished 2053 | process_return 0 2054 | ) &>"$PROCESS_LOG" & 2055 | process_capture $! "$process_name" 2056 | fi 2057 | } 2058 | 2059 | # --------------------------------------------------------------------------------------------------- 2060 | 2061 | exec_install_vm_support() { 2062 | local process_name="VM Support" 2063 | if [ "$ARCH_OS_VM_SUPPORT_ENABLED" = "true" ]; then 2064 | process_init "$process_name" 2065 | ( 2066 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 2067 | case $(systemd-detect-virt || true) in 2068 | kvm) 2069 | log_info "KVM detected" 2070 | chroot_pacman_install spice spice-vdagent spice-protocol spice-gtk qemu-guest-agent 2071 | arch-chroot /mnt systemctl enable qemu-guest-agent 2072 | ;; 2073 | vmware) 2074 | log_info "VMWare Workstation/ESXi detected" 2075 | chroot_pacman_install open-vm-tools 2076 | arch-chroot /mnt systemctl enable vmtoolsd 2077 | arch-chroot /mnt systemctl enable vmware-vmblock-fuse 2078 | ;; 2079 | oracle) 2080 | log_info "VirtualBox detected" 2081 | chroot_pacman_install virtualbox-guest-utils 2082 | arch-chroot /mnt systemctl enable vboxservice 2083 | ;; 2084 | microsoft) 2085 | log_info "Hyper-V detected" 2086 | chroot_pacman_install hyperv 2087 | arch-chroot /mnt systemctl enable hv_fcopy_daemon 2088 | arch-chroot /mnt systemctl enable hv_kvp_daemon 2089 | arch-chroot /mnt systemctl enable hv_vss_daemon 2090 | ;; 2091 | *) log_info "No VM detected" ;; # Do nothing 2092 | esac 2093 | process_return 0 # Return 2094 | ) &>"$PROCESS_LOG" & 2095 | process_capture $! "$process_name" 2096 | fi 2097 | } 2098 | 2099 | # --------------------------------------------------------------------------------------------------- 2100 | 2101 | # shellcheck disable=SC2016 2102 | exec_finalize_arch_os() { 2103 | local process_name="Finalize Arch OS" 2104 | process_init "$process_name" 2105 | ( 2106 | [ "$DEBUG" = "true" ] && sleep 1 && process_return 0 # If debug mode then return 2107 | 2108 | # Add init script 2109 | if [ -s "/mnt/home/${ARCH_OS_USERNAME}/${INIT_FILENAME}.sh" ]; then 2110 | mkdir -p "/mnt/home/${ARCH_OS_USERNAME}/.arch-os/system" 2111 | mkdir -p "/mnt/home/${ARCH_OS_USERNAME}/.config/autostart" 2112 | mv "/mnt/home/${ARCH_OS_USERNAME}/${INIT_FILENAME}.sh" "/mnt/home/${ARCH_OS_USERNAME}/.arch-os/system/${INIT_FILENAME}.sh" 2113 | # Add version env 2114 | sed -i "1i\ARCH_OS_VERSION=${VERSION}" "/mnt/home/${ARCH_OS_USERNAME}/.arch-os/system/${INIT_FILENAME}.sh" 2115 | # Add shebang 2116 | sed -i '1i\#!/usr/bin/env bash' "/mnt/home/${ARCH_OS_USERNAME}/.arch-os/system/${INIT_FILENAME}.sh" 2117 | # Add autostart-remove 2118 | { 2119 | echo "# exec_finalize_arch_os | Remove autostart init files" 2120 | echo "rm -f /home/${ARCH_OS_USERNAME}/.config/autostart/${INIT_FILENAME}.desktop" 2121 | } >>"/mnt/home/${ARCH_OS_USERNAME}/.arch-os/system/${INIT_FILENAME}.sh" 2122 | # Print initialized info 2123 | { 2124 | echo "# exec_finalize_arch_os | Print initialized info" 2125 | echo "echo \"\$(date '+%Y-%m-%d %H:%M:%S') | Arch OS \${ARCH_OS_VERSION} | Initialized\"" 2126 | } >>"/mnt/home/${ARCH_OS_USERNAME}/.arch-os/system/${INIT_FILENAME}.sh" 2127 | arch-chroot /mnt chmod +x "/home/${ARCH_OS_USERNAME}/.arch-os/system/${INIT_FILENAME}.sh" 2128 | { 2129 | echo "[Desktop Entry]" 2130 | echo "Type=Application" 2131 | echo "Name=Arch OS Initialize" 2132 | echo "Icon=preferences-system" 2133 | echo "Exec=bash -c '/home/${ARCH_OS_USERNAME}/.arch-os/system/${INIT_FILENAME}.sh > /home/${ARCH_OS_USERNAME}/.arch-os/system/${INIT_FILENAME}.log'" 2134 | } >"/mnt/home/${ARCH_OS_USERNAME}/.config/autostart/${INIT_FILENAME}.desktop" 2135 | fi 2136 | 2137 | # Set correct home permissions 2138 | arch-chroot /mnt chown -R "$ARCH_OS_USERNAME":"$ARCH_OS_USERNAME" "/home/${ARCH_OS_USERNAME}" 2139 | 2140 | # Remove orphans and force return true 2141 | arch-chroot /mnt bash -c 'pacman -Qtd &>/dev/null && pacman -Rns --noconfirm $(pacman -Qtdq) || true' 2142 | 2143 | # Install snapper pacman hook 2144 | [ "$ARCH_OS_FILESYSTEM" = "btrfs" ] && [ "$ARCH_OS_SNAPPER_ENABLED" = "true" ] && chroot_pacman_install snap-pac 2145 | 2146 | # Add pacman btrfs hook (need to place on the end of script) 2147 | if [ "$ARCH_OS_FILESYSTEM" = "btrfs" ] && [ "$ARCH_OS_SNAPPER_ENABLED" = "false" ]; then 2148 | # Create pacman hook (auto create snapshot on pre-transaction) 2149 | mkdir -p /mnt/etc/pacman.d/hooks/ 2150 | # shellcheck disable=SC2016 2151 | { 2152 | echo '[Trigger]' 2153 | echo 'Operation = Install' 2154 | echo 'Operation = Upgrade' 2155 | echo 'Operation = Remove' 2156 | echo 'Type = Package' 2157 | echo 'Target = *' 2158 | echo '' 2159 | echo '[Action]' 2160 | echo 'Description = Creating BTRFS snapshot' 2161 | echo 'When = PreTransaction' 2162 | #echo 'Exec = /usr/bin/btrfs subvolume snapshot -r / /.snapshots/$(date +%Y-%m-%d_%H-%M-%S)' 2163 | echo 'Exec = /bin/sh -c '\''/usr/bin/btrfs subvolume snapshot -r / /.snapshots/"$(date "+%Y-%m-%d_%H-%M-%S")"'\''' 2164 | } >/mnt/etc/pacman.d/hooks/50-btrfs-snapshot.hook 2165 | fi 2166 | 2167 | process_return 0 # Return 2168 | ) &>"$PROCESS_LOG" & 2169 | process_capture $! "$process_name" 2170 | } 2171 | 2172 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2173 | # CHROOT HELPER 2174 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2175 | 2176 | chroot_pacman_install() { 2177 | local packages=("$@") 2178 | local pacman_failed="true" 2179 | # Retry installing packages 5 times (in case of connection issues) 2180 | for ((i = 1; i < 6; i++)); do 2181 | # Print log if greather than first try 2182 | [ "$i" -gt 1 ] && log_warn "${i}. Retry Pacman installation..." 2183 | # Try installing packages 2184 | # if ! arch-chroot /mnt bash -c "yes | LC_ALL=en_US.UTF-8 pacman -S --needed --disable-download-timeout ${packages[*]}"; then 2185 | if ! arch-chroot /mnt pacman -S --noconfirm --needed --disable-download-timeout "${packages[@]}"; then 2186 | sleep 10 && continue # Wait 10 seconds & try again 2187 | else 2188 | pacman_failed="false" && break # Success: break loop 2189 | fi 2190 | done 2191 | # Result 2192 | [ "$pacman_failed" = "true" ] && return 1 # Failed after 5 retries 2193 | [ "$pacman_failed" = "false" ] && return 0 # Success 2194 | } 2195 | 2196 | chroot_aur_install() { 2197 | 2198 | # Vars 2199 | local repo repo_url repo_tmp_dir aur_failed 2200 | repo="$1" && repo_url="https://aur.archlinux.org/${repo}.git" 2201 | 2202 | # Disable sudo needs no password rights 2203 | sed -i 's/^# %wheel ALL=(ALL:ALL) NOPASSWD: ALL/%wheel ALL=(ALL:ALL) NOPASSWD: ALL/' /mnt/etc/sudoers 2204 | 2205 | # Temp dir 2206 | repo_tmp_dir=$(mktemp -u "/home/${ARCH_OS_USERNAME}/.tmp-aur-${repo}.XXXX") 2207 | 2208 | # Retry installing AUR 5 times (in case of connection issues) 2209 | aur_failed="true" 2210 | for ((i = 1; i < 6; i++)); do 2211 | 2212 | # Print log if greather than first try 2213 | [ "$i" -gt 1 ] && log_warn "${i}. Retry AUR installation..." 2214 | 2215 | # Try cloning AUR repo 2216 | ! arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- bash -c "rm -rf ${repo_tmp_dir}; git clone ${repo_url} ${repo_tmp_dir}" && sleep 10 && continue 2217 | 2218 | # Add '!debug' option to PKGBUILD 2219 | arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- bash -c "cd ${repo_tmp_dir} && echo -e \"\noptions=('!debug')\" >>PKGBUILD" 2220 | 2221 | # Try installing AUR 2222 | if ! arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- bash -c "cd ${repo_tmp_dir} && makepkg -si --noconfirm --needed"; then 2223 | sleep 10 && continue # Wait 10 seconds & try again 2224 | else 2225 | aur_failed="false" && break # Success: break loop 2226 | fi 2227 | done 2228 | 2229 | # Remove tmp dir 2230 | arch-chroot /mnt /usr/bin/runuser -u "$ARCH_OS_USERNAME" -- rm -rf "$repo_tmp_dir" 2231 | 2232 | # Enable sudo needs no password rights 2233 | sed -i 's/^%wheel ALL=(ALL:ALL) NOPASSWD: ALL/# %wheel ALL=(ALL:ALL) NOPASSWD: ALL/' /mnt/etc/sudoers 2234 | 2235 | # Result 2236 | [ "$aur_failed" = "true" ] && return 1 # Failed after 5 retries 2237 | [ "$aur_failed" = "false" ] && return 0 # Success 2238 | } 2239 | 2240 | chroot_pacman_remove() { arch-chroot /mnt pacman -Rn --noconfirm "$@" || return 1; } 2241 | 2242 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2243 | # TRAP FUNCTIONS 2244 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2245 | 2246 | # shellcheck disable=SC2317 2247 | trap_error() { 2248 | # If process calls this trap, write error to file to use in exit trap 2249 | echo "Command '${BASH_COMMAND}' failed with exit code $? in function '${1}' (line ${2})" >"$ERROR_MSG" 2250 | } 2251 | 2252 | # shellcheck disable=SC2317 2253 | trap_exit() { 2254 | local result_code="$?" 2255 | 2256 | # Read error msg from file (written in error trap) 2257 | local error && [ -f "$ERROR_MSG" ] && error="$(<"$ERROR_MSG")" && rm -f "$ERROR_MSG" 2258 | 2259 | # Cleanup 2260 | unset ARCH_OS_PASSWORD 2261 | rm -rf "$SCRIPT_TMP_DIR" 2262 | 2263 | # When ctrl + c pressed exit without other stuff below 2264 | [ "$result_code" = "130" ] && gum_warn "Exit..." && { 2265 | exit 1 2266 | } 2267 | 2268 | # Check if failed and print error 2269 | if [ "$result_code" -gt "0" ]; then 2270 | [ -n "$error" ] && gum_fail "$error" # Print error message (if exists) 2271 | [ -z "$error" ] && gum_fail "An Error occurred" # Otherwise pint default error message 2272 | gum_warn "See ${SCRIPT_LOG} for more information..." 2273 | gum_confirm "Show Logs?" && gum pager --show-line-numbers <"$SCRIPT_LOG" # Ask for show logs? 2274 | fi 2275 | 2276 | exit "$result_code" # Exit installer.sh 2277 | } 2278 | 2279 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2280 | # PROCESS FUNCTIONS 2281 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2282 | 2283 | process_init() { 2284 | [ -f "$PROCESS_RET" ] && gum_fail "${PROCESS_RET} already exists" && exit 1 2285 | echo 1 >"$PROCESS_RET" # Init result with 1 2286 | log_proc "${1}..." # Log starting 2287 | } 2288 | 2289 | process_capture() { 2290 | local pid="$1" # Set process pid 2291 | local process_name="$2" # Set process name 2292 | local user_canceled="false" # Will set to true if user press ctrl + c 2293 | 2294 | # Show gum spinner until pid is not exists anymore and set user_canceled to true on failure 2295 | gum_spin --title "${process_name}..." -- bash -c "while kill -0 $pid &> /dev/null; do sleep 1; done" || user_canceled="true" 2296 | cat "$PROCESS_LOG" >>"$SCRIPT_LOG" # Write process log to logfile 2297 | 2298 | # When user press ctrl + c while process is running 2299 | if [ "$user_canceled" = "true" ]; then 2300 | kill -0 "$pid" &>/dev/null && pkill -P "$pid" &>/dev/null # Kill process if running 2301 | gum_fail "Process with PID ${pid} was killed by user" && trap_gum_exit # Exit with 130 2302 | fi 2303 | 2304 | # Handle error while executing process 2305 | [ ! -f "$PROCESS_RET" ] && gum_fail "${PROCESS_RET} not found (do not init process?)" && exit 1 2306 | [ "$(<"$PROCESS_RET")" != "0" ] && gum_fail "${process_name} failed" && exit 1 # If process failed (result code 0 was not write in the end) 2307 | 2308 | # Finish 2309 | rm -f "$PROCESS_RET" # Remove process result file 2310 | gum_proc "${process_name}" "success" # Print process success 2311 | } 2312 | 2313 | process_return() { 2314 | # 1. Write from sub process 0 to file when succeed (at the end of the script part) 2315 | # 2. Rread from parent process after sub process finished (0=success 1=failed) 2316 | echo "$1" >"$PROCESS_RET" 2317 | exit "$1" 2318 | } 2319 | 2320 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2321 | # HELPER FUNCTIONS 2322 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2323 | 2324 | print_header() { 2325 | local title="$1" 2326 | clear && gum_foreground ' 2327 | █████ ██████ ██████ ██ ██ ██████ ███████ 2328 | ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 2329 | ███████ ██████ ██ ███████ ██ ██ ███████ 2330 | ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 2331 | ██ ██ ██ ██ ██████ ██ ██ ██████ ███████' 2332 | local header_version=" v. ${VERSION}" 2333 | [ "$DEBUG" = "true" ] && header_version=" d. ${VERSION}" 2334 | gum_white --margin "1 0" --align left --bold "Welcome to ${title} ${header_version}" 2335 | [ "$FORCE" = "true" ] && gum_red --bold "CAUTION: Force mode enabled. Cancel with: Ctrl + c" && echo 2336 | return 0 2337 | } 2338 | 2339 | print_filled_space() { 2340 | local total="$1" && local text="$2" && local length="${#text}" 2341 | [ "$length" -ge "$total" ] && echo "$text" && return 0 2342 | local padding=$((total - length)) && printf '%s%*s\n' "$text" "$padding" "" 2343 | } 2344 | 2345 | gum_init() { 2346 | if [ ! -x ./gum ]; then 2347 | clear && echo "Loading Arch OS Installer..." # Loading 2348 | local gum_url gum_path # Prepare URL with version os and arch 2349 | # https://github.com/charmbracelet/gum/releases 2350 | gum_url="https://github.com/charmbracelet/gum/releases/download/v${GUM_VERSION}/gum_${GUM_VERSION}_$(uname -s)_$(uname -m).tar.gz" 2351 | if ! curl -Lsf "$gum_url" >"${SCRIPT_TMP_DIR}/gum.tar.gz"; then echo "Error downloading ${gum_url}" && exit 1; fi 2352 | if ! tar -xf "${SCRIPT_TMP_DIR}/gum.tar.gz" --directory "$SCRIPT_TMP_DIR"; then echo "Error extracting ${SCRIPT_TMP_DIR}/gum.tar.gz" && exit 1; fi 2353 | gum_path=$(find "${SCRIPT_TMP_DIR}" -type f -executable -name "gum" -print -quit) 2354 | [ -z "$gum_path" ] && echo "Error: 'gum' binary not found in '${SCRIPT_TMP_DIR}'" && exit 1 2355 | if ! mv "$gum_path" ./gum; then echo "Error moving ${gum_path} to ./gum" && exit 1; fi 2356 | if ! chmod +x ./gum; then echo "Error chmod +x ./gum" && exit 1; fi 2357 | fi 2358 | } 2359 | 2360 | gum() { 2361 | if [ -n "$GUM" ] && [ -x "$GUM" ]; then 2362 | "$GUM" "$@" 2363 | else 2364 | echo "Error: GUM='${GUM}' is not found or executable" >&2 2365 | exit 1 2366 | fi 2367 | } 2368 | 2369 | trap_gum_exit() { exit 130; } 2370 | trap_gum_exit_confirm() { gum_confirm "Exit Installation?" && trap_gum_exit; } 2371 | 2372 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2373 | # GUM WRAPPER 2374 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2375 | 2376 | # Gum colors (https://github.com/muesli/termenv?tab=readme-ov-file#color-chart) 2377 | gum_foreground() { gum_style --foreground "$COLOR_FOREGROUND" "${@}"; } 2378 | gum_background() { gum_style --foreground "$COLOR_BACKGROUND" "${@}"; } 2379 | gum_white() { gum_style --foreground "$COLOR_WHITE" "${@}"; } 2380 | gum_black() { gum_style --foreground "$COLOR_BLACK" "${@}"; } 2381 | gum_red() { gum_style --foreground "$COLOR_RED" "${@}"; } 2382 | gum_green() { gum_style --foreground "$COLOR_GREEN" "${@}"; } 2383 | gum_blue() { gum_style --foreground "$COLOR_BLUE" "${@}"; } 2384 | gum_yellow() { gum_style --foreground "$COLOR_YELLOW" "${@}"; } 2385 | gum_cyan() { gum_style --foreground "$COLOR_CYAN" "${@}"; } 2386 | gum_purple() { gum_style --foreground "$COLOR_PURPLE" "${@}"; } 2387 | 2388 | # Gum prints 2389 | gum_title() { log_head "${*}" && gum join "$(gum_foreground --bold "+ ")" "$(gum_foreground --bold "${*}")"; } 2390 | gum_info() { log_info "$*" && gum join "$(gum_green --bold "• ")" "$(gum_white "${*}")"; } 2391 | gum_warn() { log_warn "$*" && gum join "$(gum_yellow --bold "• ")" "$(gum_white "${*}")"; } 2392 | gum_fail() { log_fail "$*" && gum join "$(gum_red --bold "• ")" "$(gum_white "${*}")"; } 2393 | 2394 | # Gum wrapper 2395 | gum_style() { gum style "${@}"; } 2396 | gum_confirm() { gum confirm --prompt.foreground "$COLOR_FOREGROUND" --selected.background "$COLOR_FOREGROUND" --selected.foreground "$COLOR_BACKGROUND" --unselected.foreground "$COLOR_FOREGROUND" "${@}"; } 2397 | gum_input() { gum input --placeholder "..." --prompt "> " --cursor.foreground "$COLOR_FOREGROUND" --prompt.foreground "$COLOR_FOREGROUND" --header.foreground "$COLOR_FOREGROUND" "${@}"; } 2398 | gum_choose() { gum choose --cursor "> " --header.foreground "$COLOR_FOREGROUND" --cursor.foreground "$COLOR_FOREGROUND" "${@}"; } 2399 | gum_filter() { gum filter --prompt "> " --indicator ">" --placeholder "Type to filter..." --height 8 --header.foreground "$COLOR_FOREGROUND" --indicator.foreground "$COLOR_FOREGROUND" --match.foreground "$COLOR_FOREGROUND" "${@}"; } 2400 | gum_write() { gum write --prompt "> " --show-cursor-line --char-limit 0 --cursor.foreground "$COLOR_FOREGROUND" --header.foreground "$COLOR_FOREGROUND" "${@}"; } 2401 | gum_spin() { gum spin --spinner line --title.foreground "$COLOR_FOREGROUND" --spinner.foreground "$COLOR_FOREGROUND" "${@}"; } 2402 | 2403 | # Gum key & value 2404 | gum_proc() { log_proc "$*" && gum join "$(gum_green --bold "• ")" "$(gum_white --bold "$(print_filled_space 24 "${1}")")" "$(gum_white " > ")" "$(gum_green "${2}")"; } 2405 | gum_property() { log_prop "$*" && gum join "$(gum_green --bold "• ")" "$(gum_white "$(print_filled_space 24 "${1}")")" "$(gum_green --bold " > ")" "$(gum_white --bold "${2}")"; } 2406 | 2407 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2408 | # LOGGING WRAPPER 2409 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2410 | 2411 | write_log() { echo -e "$(date '+%Y-%m-%d %H:%M:%S') | arch-os | ${*}" >>"$SCRIPT_LOG"; } 2412 | log_info() { write_log "INFO | ${*}"; } 2413 | log_warn() { write_log "WARN | ${*}"; } 2414 | log_fail() { write_log "FAIL | ${*}"; } 2415 | log_head() { write_log "HEAD | ${*}"; } 2416 | log_proc() { write_log "PROC | ${*}"; } 2417 | log_prop() { write_log "PROP | ${*}"; } 2418 | 2419 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2420 | # START MAIN 2421 | # //////////////////////////////////////////////////////////////////////////////////////////////////// 2422 | 2423 | main "$@" 2424 | --------------------------------------------------------------------------------