Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Three documentation trees, split by genre and audience:
- Prefer `(( ))` over numeric operators inside `[[ ]]` (e.g., `(( count < 50 ))`, not `[[ $count -lt 50 ]]`)
- Prefer a full `if`/`else` conditional for simple two-path control flow; don't rely on `exec` or `exit` in one branch to make following statements unreachable
- For strings/paths with spaces, quote them instead of escaping spaces with `\ ` (e.g., `"$APP_DIR/Disk Usage.desktop"`, not `$APP_DIR/Disk\ Usage.desktop`)
- Shebangs must use `#!/bin/bash` consistently (never `#!/usr/bin/env bash`)
- Shebangs must use `#!/bin/bash` consistently (never `#!/usr/bin/env bash`). A security-sensitive entrypoint may use the exact `#!/bin/bash -p` form only when it must suppress `BASH_ENV` and exported-function startup injection before its first command; that exception must be explained at the boundary and covered by a regression that rejects an ordinary Bash launch with a decoy `-p` argument.
- Scripts under `install/` and `migrations/` may be sourced and intentionally omit shebangs

# Command Naming
Expand Down
115 changes: 91 additions & 24 deletions bin/omarchy-install-dev-env
Original file line number Diff line number Diff line change
@@ -1,27 +1,68 @@
#!/bin/bash
#!/bin/bash -p

# omarchy:summary=Install a supported development environment
# omarchy:name=dev-env
# omarchy:args=<ruby|node|bun|deno|go|laravel|symfony|php|python|elixir|phoenix|rust|java|zig|ocaml|dotnet|clojure|scala>
# omarchy:examples=omarchy install dev-env ruby | omarchy install dev-env node
# omarchy:requires-sudo=true

if [[ -z $1 ]]; then
if [[ $- != *p* ]]; then
echo "Refusing an unsafe Bash startup for development-environment installation." >&2
exit 126
fi

source "${BASH_SOURCE[0]%/*}/omarchy-install-security-functions" || exit 126

omarchy_security_require_privileged_bash_startup || {
echo "Refusing an unsafe Bash startup for development-environment installation." >&2
exit 126
}

set -euo pipefail

environment=${1:-}

usage() {
echo "Usage: omarchy-install-dev-env <ruby|node|bun|deno|go|laravel|symfony|php|python|elixir|phoenix|rust|java|zig|ocaml|dotnet|clojure|scala>" >&2
}

case "$environment" in
ruby | node | bun | deno | go | laravel | symfony | php | python | elixir | phoenix | rust | java | zig | ocaml | dotnet | clojure | scala) ;;
*)
usage
exit 1
fi
;;
esac

install_php() {
omarchy-pkg-add php composer php-sqlite xdebug
# These mixed installers intentionally invalidate the calling terminal's sudo
# timestamp, including one that predated this command. sudo cannot selectively
# distinguish a timestamp refreshed by this workflow from an older one. The
# explicit contract prevents any home-owned tool manager, downloaded backend,
# language hook, or remote script below from inheriting silent root authority.
finish_privileged_phase() {
omarchy_install_security_finish_privileged_phase \
"Could not invalidate cached sudo authorization; refusing to run user-owned installer code."
}

# Install Path for Composer
if [[ :$PATH: != *:$HOME/.config/composer/vendor/bin:* ]]; then
echo 'export PATH="$HOME/.config/composer/vendor/bin:$PATH"' >>"$HOME/.bashrc"
source "$HOME/.bashrc"
echo "Added Composer global bin directory to PATH."
else
echo "Composer global bin directory already in PATH."
fi
install_packages() {
OMARCHY_SUDO_NO_UPDATE=1 /usr/bin/omarchy-pkg-add "$@"
}

omarchy_security_install_sudo_cleanup_traps

finish_privileged_phase
case "$environment" in
ruby|php|laravel|symfony|clojure)
omarchy_security_sudo_supports_no_update || {
echo "This sudo does not support --no-update; refusing a mixed-trust installer." >&2
exit 1
}
;;
esac
echo "Security note: this installer clears cached sudo authorization before running user-level tooling."

install_php() {
install_packages php composer php-sqlite xdebug

# Enable some extensions
local php_ini_path="/etc/php/php.ini"
Expand All @@ -34,26 +75,45 @@ install_php() {
"pdo_mysql"
)

# Enable Xdebug
sudo sed -i \
-e 's/^;zend_extension=xdebug.so/zend_extension=xdebug.so/' \
-e 's/^;xdebug.mode=debug/xdebug.mode=debug/' \
/etc/php/conf.d/xdebug.ini

# Keep the trusted configuration phase to one command-scoped authorization.
# sudo --no-update deliberately cannot reuse or publish a timestamp, so one
# sed process avoids prompting once per extension without opening a reusable
# credential window.
local -a sed_expressions=(
-e 's/^;zend_extension=xdebug.so/zend_extension=xdebug.so/'
-e 's/^;xdebug.mode=debug/xdebug.mode=debug/'
)
local ext
for ext in "${extensions_to_enable[@]}"; do
sudo sed -i "s/^;extension=${ext}/extension=${ext}/" "$php_ini_path"
sed_expressions+=(-e "s/^;extension=${ext}/extension=${ext}/")
done

/usr/bin/sudo -N -- /usr/bin/sed -i "${sed_expressions[@]}" \
/etc/php/conf.d/xdebug.ini "$php_ini_path"
}

configure_composer_path() {
# This touches user-owned shell configuration only after the caller has
# finished and revoked the privileged phase. Never source the file here.
if [[ :$PATH: != *:$HOME/.config/composer/vendor/bin:* ]]; then
echo 'export PATH="$HOME/.config/composer/vendor/bin:$PATH"' >>"$HOME/.bashrc"
export PATH="$HOME/.config/composer/vendor/bin:$PATH"
echo "Added Composer global bin directory to PATH."
else
echo "Composer global bin directory already in PATH."
fi
}

install_node() {
echo -e "Installing Node.js...\n"
mise use --global node
}

case "$1" in
case "$environment" in
ruby)
echo -e "Installing Ruby on Rails...\n"
omarchy-pkg-add libyaml
install_packages libyaml
finish_privileged_phase
mise settings add ruby.compile false
mise settings add idiomatic_version_file_enable_tools ruby
mise use --global ruby@latest
Expand All @@ -79,18 +139,24 @@ go)
php)
echo -e "Installing PHP...\n"
install_php
finish_privileged_phase
configure_composer_path
;;
laravel)
echo -e "Installing PHP and Laravel...\n"
install_php
finish_privileged_phase
configure_composer_path
install_node
composer global require laravel/installer
echo -e "\nYou can now run: laravel new myproject"
;;
symfony)
echo -e "Installing PHP and Symfony...\n"
install_php
omarchy-pkg-add symfony-cli
install_packages symfony-cli
finish_privileged_phase
configure_composer_path
echo -e "\nYou can now run: symfony new --webapp myproject"
;;
python)
Expand Down Expand Up @@ -143,7 +209,8 @@ dotnet)
;;
clojure)
echo -e "Installing Clojure...\n"
omarchy-pkg-add rlwrap
install_packages rlwrap
finish_privileged_phase
mise use --global clojure@latest
;;
scala)
Expand Down
26 changes: 23 additions & 3 deletions bin/omarchy-install-font
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
#!/bin/bash
#!/bin/bash -p

# omarchy:summary=Install a Nerd Font package and switch the system to it
# omarchy:args=<display-name> <package> <family>
# omarchy:examples=omarchy install font 'Cascadia Mono' ttf-cascadia-mono-nerd 'CaskaydiaMono Nerd Font'

if [[ $- != *p* ]]; then
echo "Refusing an unsafe Bash startup for font installation." >&2
exit 126
fi

source "${BASH_SOURCE[0]%/*}/omarchy-install-security-functions" || exit 126

if ! omarchy_security_require_privileged_bash_startup; then
echo "Refusing an unsafe Bash startup for font installation." >&2
exit 126
fi

set -e

omarchy_install_security_sanitize_bash_startup_environment "$0" "$@"

name="${1-}"
package="${2-}"
family="${3-}"
Expand All @@ -17,5 +33,9 @@ printf -v install_message '%q' "Installing ${name}..."
printf -v package_arg '%q' "$package"
printf -v family_arg '%q' "$family"

exec omarchy-launch-floating-terminal-with-presentation \
"echo ${install_message}; omarchy-pkg-add ${package_arg} && sleep 2 && omarchy-font-set ${family_arg}"
omarchy_install_security_prepare_cold_command_scoped_sudo \
"Could not invalidate cached sudo authorization." \
"This sudo does not support --no-update; refusing a mixed-trust font install."

exec /usr/bin/omarchy-launch-floating-terminal-with-presentation \
"echo ${install_message}; trap '/usr/bin/sudo -k >/dev/null 2>&1 || true' EXIT; /usr/bin/sudo -k && OMARCHY_SUDO_NO_UPDATE=1 /usr/bin/omarchy-pkg-add ${package_arg} && /usr/bin/sudo -k && /usr/bin/sleep 2 && /usr/bin/omarchy-font-set ${family_arg}"
39 changes: 35 additions & 4 deletions bin/omarchy-install-gaming-battlenet
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
#!/bin/bash
#!/bin/bash -p

# omarchy:summary=Install Battle.net standalone via umu-launcher + GE-Proton (no Steam, no Lutris, no Heroic).
# omarchy:requires-sudo=true

set -e
if [[ $- != *p* ]]; then
echo "Refusing an unsafe Bash startup for Battle.net installation." >&2
exit 126
fi

source "${BASH_SOURCE[0]%/*}/omarchy-install-security-functions" || exit 126

omarchy_security_require_privileged_bash_startup || {
echo "Refusing an unsafe Bash startup for Battle.net installation." >&2
exit 126
}

set -euo pipefail

# This mixed installer intentionally invalidates the calling terminal's sudo
# timestamp, including one that predates this command. sudo cannot identify
# which package helper refreshed a shared timestamp, and downloaded vendor code
# must never inherit silent root access.
finish_privileged_phase() {
omarchy_install_security_finish_privileged_phase \
"Could not invalidate cached sudo authorization; refusing to run Battle.net installer code."
}

omarchy_security_install_sudo_cleanup_traps

finish_privileged_phase
omarchy_security_sudo_supports_no_update || {
echo "This sudo does not support --no-update; refusing a mixed-trust installer." >&2
exit 1
}
echo "Security note: this installer clears cached sudo authorization before running downloaded vendor code."

PREFIX="$HOME/Games/battlenet"
LAUNCHER="$PREFIX/drive_c/Program Files (x86)/Battle.net/Battle.net Launcher.exe"
INSTALLER_URL="https://downloader.battle.net/download/getInstallerForGame?os=win&gameProgram=BATTLENET_APP&version=Live"

echo "Installing Battle.net..."

omarchy-pkg-add umu-launcher
omarchy-install-gaming-gpu-lib32
OMARCHY_SUDO_NO_UPDATE=1 /usr/bin/omarchy-pkg-add umu-launcher
OMARCHY_SUDO_NO_UPDATE=1 /usr/bin/omarchy-install-gaming-gpu-lib32
finish_privileged_phase

# Detect a half-finished prefix from a closed/crashed previous run and offer
# to wipe it before trying again. Battle.net's installer isn't idempotent.
Expand Down
62 changes: 54 additions & 8 deletions bin/omarchy-install-gaming-geforce-now
Original file line number Diff line number Diff line change
@@ -1,19 +1,65 @@
#!/bin/bash
#!/bin/bash -p

# omarchy:summary=Install and launch Geforce Now.
# omarchy:group=install
# omarchy:name=gaming geforce-now

set -e
if [[ $- != *p* ]]; then
echo "Refusing an unsafe Bash startup for GeForce NOW installation." >&2
exit 126
fi

source "${BASH_SOURCE[0]%/*}/omarchy-install-security-functions" || exit 126

omarchy_security_require_privileged_bash_startup || {
echo "Refusing an unsafe Bash startup for GeForce NOW installation." >&2
exit 126
}

set -euo pipefail

installer=""

cleanup() {
local status=$?
if [[ -n $installer ]] && ! /usr/bin/rm -f -- "$installer"; then
(( status != 0 )) || status=1
fi
omarchy_security_exit_with_revoked_sudo "$status"
}

trap cleanup EXIT
omarchy_security_install_signal_exit_traps

# This command deliberately invalidates even a sudo timestamp that predated
# the workflow. sudo cannot identify which command refreshed a shared terminal
# timestamp, and downloaded vendor code must never inherit silent root access.
omarchy_install_security_prepare_cold_command_scoped_sudo \
"Could not invalidate cached sudo authorization; refusing to continue." \
"This sudo does not support --no-update; refusing a mixed-trust installer."
echo "Security note: this installer clears cached sudo authorization before running downloaded vendor code."

echo "Installing GeForce NOW..."
omarchy-pkg-add flatpak
cd /tmp
OMARCHY_SUDO_NO_UPDATE=1 /usr/bin/omarchy-pkg-add flatpak

if ! omarchy_security_revoke_sudo_timestamp; then
echo "Could not invalidate cached sudo authorization; refusing to run the downloaded installer." >&2
exit 1
fi

installer=$(/usr/bin/mktemp -- /tmp/omarchy-geforce-now.XXXXXXXX.bin)
owner=$(/usr/bin/stat -c '%u' -- "$installer")
mode=$(/usr/bin/stat -c '%a' -- "$installer")
links=$(/usr/bin/stat -c '%h' -- "$installer")
if [[ -L $installer || ! -f $installer || $owner != "$(/usr/bin/id -u)" || $mode != 600 || $links != 1 ]]; then
echo "Could not create a private GeForce NOW installer file." >&2
exit 1
fi

# Download and run GeForce NOW
curl -LO https://international.download.nvidia.com/GFNLinux/GeForceNOWSetup.bin
chmod +x GeForceNOWSetup.bin
./GeForceNOWSetup.bin
/usr/bin/curl --fail --location --output "$installer" \
https://international.download.nvidia.com/GFNLinux/GeForceNOWSetup.bin
/usr/bin/chmod 0700 -- "$installer"
(cd /tmp && exec "$installer")

# Ensure a separate browser process not started by GFN is available.
# If not, it seems like GFN has a tendency to hang on login.
Expand Down
24 changes: 18 additions & 6 deletions bin/omarchy-install-gaming-gpu-lib32
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
#!/bin/bash
#!/bin/bash -p

# omarchy:summary=Install lib32 graphics drivers (Vulkan + NVIDIA) for any detected GPUs.
# omarchy:group=install
# omarchy:name=gaming gpu-lib32
# omarchy:requires-sudo=true

set -e
if [[ $- != *p* ]]; then
echo "Refusing an unsafe Bash startup for graphics-driver installation." >&2
exit 126
fi

source "${BASH_SOURCE[0]%/*}/omarchy-security-functions" || exit 126

omarchy_security_require_privileged_bash_startup || {
echo "Refusing an unsafe Bash startup for graphics-driver installation." >&2
exit 126
}

set -euo pipefail

echo "Installing lib32 graphics drivers..."

Expand All @@ -16,15 +28,15 @@ declare -A VULKAN_DRIVERS=(
[AMD]=lib32-vulkan-radeon
)
for vendor in "${!VULKAN_DRIVERS[@]}"; do
if lspci | grep -iE "(VGA|Display).*$vendor" >/dev/null; then
if /usr/bin/lspci | /usr/bin/grep -iE "(VGA|Display).*$vendor" >/dev/null; then
PACKAGES+=("${VULKAN_DRIVERS[$vendor]}")
fi
done

if omarchy-hw-nvidia-gsp; then
if /usr/bin/omarchy-hw-nvidia-gsp; then
PACKAGES+=(lib32-nvidia-utils)
elif omarchy-hw-nvidia-without-gsp; then
elif /usr/bin/omarchy-hw-nvidia-without-gsp; then
PACKAGES+=(lib32-nvidia-580xx-utils)
fi

(( ${#PACKAGES[@]} > 0 )) && omarchy-pkg-add "${PACKAGES[@]}"
(( ${#PACKAGES[@]} == 0 )) || /usr/bin/omarchy-pkg-add "${PACKAGES[@]}"
Loading