-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·1257 lines (1148 loc) · 45.1 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·1257 lines (1148 loc) · 45.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env bash
# ==================================================
# KoolDots (2026)
# Project URL: https://github.com/LinuxBeginnings
# License: GNU GPLv3
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
# https://github.com/LinuxBeginnings
clear
# Set some colors for output messages
OK="$(tput setaf 2)[OK]$(tput sgr0)"
ERROR="$(tput setaf 1)[ERROR]$(tput sgr0)"
NOTE="$(tput setaf 3)[NOTE]$(tput sgr0)"
INFO="$(tput setaf 4)[INFO]$(tput sgr0)"
WARN="$(tput setaf 1)[WARN]$(tput sgr0)"
CAT="$(tput setaf 6)[ACTION]$(tput sgr0)"
MAGENTA="$(tput setaf 5)"
ORANGE="$(tput setaf 214)"
WARNING="$(tput setaf 1)"
YELLOW="$(tput setaf 3)"
GREEN="$(tput setaf 2)"
BLUE="$(tput setaf 4)"
SKY_BLUE="$(tput setaf 6)"
RESET="$(tput sgr0)"
# Set a high-contrast whiptail theme unless the user already provided one
if [ -z "${NEWT_COLORS:-}" ]; then
export NEWT_COLORS='
root=white,black
border=white,black
window=white,black
shadow=black,black
title=yellow,black
button=black,lightgray
actbutton=black,cyan
compactbutton=white,black
textbox=white,black
acttextbox=white,black
entry=white,black
label=white,black
listbox=white,black
actlistbox=black,cyan
checkbox=white,black
actcheckbox=black,cyan
'
fi
# Function to print colorful text
print_color() {
printf "%b%s%b\n" "$1" "$2" "$RESET"
}
print_help() {
cat <<EOF
KooL Debian-Hyprland installer
Usage: ${0##*/} [OPTIONS]
Options:
--build-trixie Force trixie compatibility mode
--no-trixie Disable trixie compatibility mode
--mode <source|debian|auto> Select Hyprland install method
--packages Alias for --mode debian
--source Alias for --mode source
--preset <file> Load preset file with options
--force-reinstall Force APT re-installs where applicable
--tty Use simple TTY prompts instead of whiptail dialogs
-h, --help Show this help and exit
Notes:
--tty is a fallback for remote/CI or when terminals cannot render whiptail.
XDG-Desktop-Portal-Hyprland (screen sharing) is installed by default.
EOF
}
# Fast-path help so users can inspect options without entering prompts
for arg in "$@"; do
case "$arg" in
-h | --help)
print_help
exit 0
;;
esac
done
# ---------------- APT source checks (deb-src, non-free, non-free-firmware) ----------------
_detect_codename() {
local c
if [ -r /etc/os-release ]; then
# shellcheck disable=SC1091
. /etc/os-release 2>/dev/null || true
c="${DEBIAN_CODENAME:-${VERSION_CODENAME:-}}"
fi
if [ -z "$c" ]; then c=$(lsb_release -c -s 2>/dev/null || true); fi
if [ -z "$c" ]; then c="trixie"; fi
echo "$c"
}
_has_deb_src_enabled() {
if sudo grep -RhsE '^[[:space:]]*deb-src[[:space:]]' /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null | grep -q .; then
return 0
fi
if sudo grep -RhsE '^[[:space:]]*Types:[[:space:]].*\bdeb-src\b' /etc/apt/sources.list.d/*.sources 2>/dev/null | grep -q .; then
return 0
fi
return 1
}
_has_component_enabled() {
# $1: component (e.g., non-free, non-free-firmware)
local comp="$1"
if sudo grep -RhsE "^[[:space:]]*deb(-src)?[[:space:]].*\b${comp}(\s|$)" /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null | grep -q .; then
return 0
fi
if sudo grep -RhsE "^[[:space:]]*Components:[[:space:]].*\b${comp}(\s|$)" /etc/apt/sources.list.d/*.sources 2>/dev/null | grep -q .; then
return 0
fi
return 1
}
# Unconditionally uncomment deb-src lines across all APT list files
_uncomment_deb_src_everywhere() {
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*.list; do
[ -f "$f" ] || continue
sudo sed -i -E 's/^[[:space:]]*#([[:space:]]*deb-src[[:space:]])/\1/' "$f" 2>/dev/null || true
done
for f in /etc/apt/sources.list.d/*.sources; do
[ -f "$f" ] || continue
sudo sed -i -E '/^[[:space:]]*Types:[[:space:]]/ { /\bdeb-src\b/! s/(Types:.*)/\1 deb-src/ }' "$f" 2>/dev/null || true
done
}
_enable_deb_src_conservatively() {
# Always attempt to uncomment existing deb-src entries first (no prompts)
_uncomment_deb_src_everywhere
if ! _has_deb_src_enabled; then
# If still none present, duplicate active deb lines into deb-src lines in the main list
local f=/etc/apt/sources.list
if [ -f "$f" ]; then
local tmp
tmp=$(mktemp)
sudo awk '
BEGIN { added=0 }
/^[[:space:]]*deb[[:space:]]/ && $0 !~ /^[[:space:]]*#/ {
line=$0; sub(/^[[:space:]]*deb/, "deb-src", line); print $0; print line; added=1; next
}
{ print $0 }
END { if (added==0) {} }
' "$f" >"$tmp" && sudo cp "$tmp" "$f" && rm -f "$tmp"
fi
fi
}
_write_nonfree_overlay_sources() {
# Create/refresh a small overlay sources file enabling ONLY missing components.
# This prevents duplicate APT targets when some components are already present elsewhere.
local c suite upd sec file comps=""
c=$(_detect_codename)
suite="$c"
upd="${c}-updates"
sec="${c}-security"
file="/etc/apt/sources.list.d/99-debian-nonfree.list"
# Determine which components are actually missing globally
if ! _has_component_enabled non-free; then comps+=" non-free"; fi
if ! _has_component_enabled non-free-firmware; then comps+=" non-free-firmware"; fi
comps=$(echo "$comps" | sed 's/^ *//')
# If no components are missing, remove existing overlay (if any) and return
if [ -z "$comps" ]; then
sudo rm -f "$file" 2>/dev/null || true
return 0
fi
# Build overlay content with ONLY the missing components
sudo bash -c "cat > '$file' <<EOF
# Added by Debian-Hyprland installer to enable missing components only.
# Safe overlay: does not modify existing sources.list; remove if undesired.
deb http://deb.debian.org/debian ${suite} ${comps}
# Add deb-src for missing components as well (sources)
deb-src http://deb.debian.org/debian ${suite} ${comps}
EOF"
# For non-sid suites, add updates and security pockets using only missing comps
if [ "$c" != "sid" ]; then
sudo bash -c "cat >> '$file' <<EOF
deb http://deb.debian.org/debian ${upd} ${comps}
deb-src http://deb.debian.org/debian ${upd} ${comps}
deb http://security.debian.org/debian-security ${sec} ${comps}
deb-src http://security.debian.org/debian-security ${sec} ${comps}
EOF"
fi
}
verify_and_offer_fix_apt_sources() {
# Unconditionally ensure deb-src is uncommented/enabled
_enable_deb_src_conservatively
# Write minimal overlay for missing non-free components (or remove overlay if not needed)
_write_nonfree_overlay_sources
# Report status after applying fixes
local msg=""
if _has_deb_src_enabled; then
msg+="\n - deb-src: ${GREEN}ENABLED${RESET}"
else
msg+="\n - deb-src: ${YELLOW}MISSING${RESET}"
fi
if _has_component_enabled non-free; then
msg+="\n - non-free: ${GREEN}ENABLED${RESET}"
else
msg+="\n - non-free: ${YELLOW}MISSING${RESET}"
fi
if _has_component_enabled non-free-firmware; then
msg+="\n - non-free-firmware: ${GREEN}ENABLED${RESET}"
else
msg+="\n - non-free-firmware: ${YELLOW}MISSING${RESET}"
fi
echo -e "${INFO} APT sources status (post-fix):${msg}"
}
detect_suite() {
local c
c=$(_detect_codename)
case "$c" in
trixie | forky | sid)
echo "$c"
;;
*)
echo "$c"
;;
esac
}
ensure_trixie_backports_repo() {
local suite="$1"
[ "$suite" = "trixie" ] || return 0
local file="/etc/apt/sources.list.d/99-debian-trixie-backports.list"
local desired="deb http://deb.debian.org/debian trixie-backports main contrib non-free non-free-firmware"
if sudo grep -RhsE '^[[:space:]]*deb[[:space:]]+http://deb\.debian\.org/debian/?[[:space:]]+trixie-backports([[:space:]]|$)' /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null | grep -q .; then
# If we previously created an overlay but backports exists elsewhere, remove overlay to avoid duplicate targets.
if sudo test -f "$file"; then
sudo rm -f "$file" 2>/dev/null || true
fi
return 0
fi
if sudo grep -RhsE '^[[:space:]]*Suites:[[:space:]].*\btrixie-backports\b' /etc/apt/sources.list.d/*.sources 2>/dev/null | grep -q .; then
if sudo test -f "$file"; then
sudo rm -f "$file" 2>/dev/null || true
fi
return 0
fi
echo "${INFO} Enabling Debian trixie-backports repository for Hyprland packages..." | tee -a "$LOG"
sudo bash -c "cat > '$file' <<EOF
# Added by Debian-Hyprland installer for Hyprland package mode on trixie
deb http://deb.debian.org/debian trixie-backports main contrib non-free non-free-firmware
deb-src http://deb.debian.org/debian trixie-backports main contrib non-free non-free-firmware
EOF"
}
debian_hypr_required_packages=(
hyprland
xdg-desktop-portal-hyprland
hypridle
hyprlock
hyprpicker
hyprpolkitagent
)
debian_hypr_optional_packages=(
hyprpaper
hyprland-protocols
hyprland-guiutils
hyprland-qtutils
qml6-module-org-hyprland-style
hyprwayland-scanner
hyprcursor-util
hyprlauncher
hyprland-backgrounds
)
package_available_for_suite() {
local pkg="$1"
local suite="$2"
if [ "$suite" = "trixie" ]; then
apt-cache madison "$pkg" 2>/dev/null | grep -q "trixie-backports" ||
apt-cache policy "$pkg" 2>/dev/null | grep -q "trixie-backports"
else
apt-cache policy "$pkg" 2>/dev/null | awk '/Candidate:/ {print $2}' | grep -vq "(none)"
fi
}
verify_debian_hypr_packages() {
local suite="$1"
local missing=()
local pkg
for pkg in "${debian_hypr_required_packages[@]}"; do
if ! package_available_for_suite "$pkg" "$suite"; then
missing+=("$pkg")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
echo "${WARN} Missing required Debian Hyprland packages for suite '$suite': ${missing[*]}" | tee -a "$LOG"
return 1
fi
return 0
}
select_hypr_install_mode() {
local suite="$1"
local requested="$2"
local resolved="$requested"
if [ "$resolved" = "auto" ]; then
case "$suite" in
trixie | forky | sid)
resolved="debian"
;;
*)
resolved="source"
;;
esac
fi
echo "$resolved"
}
install_debian_hyprland_stack() {
local suite="$1"
local install_list=()
local pkg
for pkg in "${debian_hypr_required_packages[@]}"; do
install_list+=("$pkg")
done
for pkg in "${debian_hypr_optional_packages[@]}"; do
if package_available_for_suite "$pkg" "$suite"; then
install_list+=("$pkg")
fi
done
echo "${INFO} Installing Hyprland from Debian packages: ${install_list[*]}" | tee -a "$LOG"
if [ "$suite" = "trixie" ]; then
sudo apt-get install -y -t trixie-backports "${install_list[@]}"
else
sudo apt-get install -y "${install_list[@]}"
fi
}
# Warning: End of Life Support
printf "\n%.0s" {1..2}
print_color $YELLOW "
█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
KooL's Debian - Hyprland October 2025 Update
Most Hyprland packages are built from Source
NOTICE
█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█
All Hyprland and associated packages set to install using this script are downloaded and built from source (github)
However, do note that it is downloaded from each individual releases. You can set versions by editing the scripts
located install-scripts directory.
These packages are NOT updated automatically.
See the HOWTO documentation on how to get next release of Hyprland installed
BE WARNED!!!!! Installation will take longer!!
█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
NOTE:
Hyprland and Dependencies versions
█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█
Thank you!
"
printf "\n%.0s" {1..2}
# Prompt user to continue or exit
read -rp "Do you want to continue with the installation? [y/N]: " confirm
case "$confirm" in
[yY][eE][sS] | [yY])
echo -e "${OK} Continuing with installation..."
;;
*)
echo -e "${NOTE} You chose not to continue. Exiting..."
exit 1
;;
esac
# Create Directory for Install Logs
if [ ! -d Install-Logs ]; then
mkdir Install-Logs
fi
# Set the name of the log file to include the current date and time
LOG="Install-Logs/01-Hyprland-Install-Scripts-$(date +%d-%H%M%S).log"
# Check if running as root. If root, script will exit
if [[ $EUID -eq 0 ]]; then
echo "${ERROR} This script should ${WARNING}NOT${RESET} be executed as root!! Exiting......." | tee -a "$LOG"
printf "\n%.0s" {1..2}
exit 1
fi
# Function to check if the system is Ubuntu
is_ubuntu() {
# Check for 'Ubuntu' in /etc/os-release
if grep -q 'Ubuntu' /etc/os-release; then
return 0
fi
return 1
}
# Check if the system is Ubuntu
if is_ubuntu; then
echo "${WARN}This script is ${WARNING}NOT intended for Ubuntu / Ubuntu Based${RESET}. Refer to ${YELLOW}README for the correct link for Ubuntu-Hyprland project${RESET}" | tee -a "$LOG"
exit 1
fi
# Debian Trixie compatibility mode
# Some Hypr* components need source-level shims on Debian 13 (trixie) toolchains.
# Default: auto-detect via /etc/os-release
# Overrides:
# --build-trixie / --no-trixie
# HYPR_BUILD_TRIXIE=1|0 (env)
TRIXIE_MODE="auto"
PRESET_FILE=""
HYPR_INSTALL_MODE="auto"
# Parse a small set of supported CLI args (order-independent)
# NOTE: install.sh historically used "$1"/"$2" for --preset; this keeps that working.
args=("$@")
FORCE_REINSTALL=0
TTY_MODE=0
for ((i = 0; i < ${#args[@]}; i++)); do
case "${args[$i]}" in
--build-trixie)
TRIXIE_MODE="on"
;;
--no-trixie)
TRIXIE_MODE="off"
;;
--force-reinstall)
FORCE_REINSTALL=1
;;
--mode)
if [ $((i + 1)) -lt ${#args[@]} ]; then
HYPR_INSTALL_MODE="${args[$((i + 1))]}"
fi
;;
--packages)
HYPR_INSTALL_MODE="debian"
;;
--source)
HYPR_INSTALL_MODE="source"
;;
--tty)
TTY_MODE=1
;;
-h | --help)
print_help
exit 0
;;
--preset)
if [ $((i + 1)) -lt ${#args[@]} ]; then
PRESET_FILE="${args[$((i + 1))]}"
fi
;;
esac
done
# If env explicitly sets HYPR_BUILD_TRIXIE, honor it.
if [ -n "${HYPR_BUILD_TRIXIE+x}" ]; then
if [ "${HYPR_BUILD_TRIXIE}" = "1" ]; then
TRIXIE_MODE="on"
elif [ "${HYPR_BUILD_TRIXIE}" = "0" ]; then
TRIXIE_MODE="off"
fi
fi
# Resolve auto-detection
if [ "$TRIXIE_MODE" = "auto" ]; then
HYPR_BUILD_TRIXIE=0
if [ -f /etc/os-release ]; then
# shellcheck disable=SC1091
. /etc/os-release || true
if [ "${ID:-}" = "debian" ] && [ "${VERSION_CODENAME:-}" = "trixie" ]; then
HYPR_BUILD_TRIXIE=1
fi
fi
elif [ "$TRIXIE_MODE" = "on" ]; then
HYPR_BUILD_TRIXIE=1
else
HYPR_BUILD_TRIXIE=0
fi
export HYPR_BUILD_TRIXIE
# Install whiptail unless running in --tty mode
if [ "$TTY_MODE" -ne 1 ] && ! command -v whiptail >/dev/null; then
echo "${NOTE} - whiptail is not installed. Installing..." | tee -a "$LOG"
sudo apt install -y whiptail
printf "\n%.0s" {1..1}
fi
printf "\n%.0s" {1..2}
echo -e "\e[35m
╦╔═┌─┐┌─┐╦ ╦ ╦┬ ┬┌─┐┬─┐┬ ┌─┐┌┐┌┌┬┐
╠╩╗│ ││ │║ ╠═╣└┬┘├─┘├┬┘│ ├─┤│││ ││ July 2025
╩ ╩└─┘└─┘╩═╝ ╩ ╩ ┴ ┴ ┴└─┴─┘┴ ┴┘└┘─┴┘ Debian Trixie / SiD
\e[0m"
printf "\n%.0s" {1..1}
DEBIAN_SUITE="$(detect_suite)"
if [ "$HYPR_INSTALL_MODE" = "auto" ]; then
if [ "$TTY_MODE" -eq 1 ]; then
echo "Select Hyprland install method:"
echo " s) Build from source (Recommended)"
echo " d) Debian packages"
read -r -p "Choose [s/d] (default s): " _mode
case "${_mode,,}" in
d | debian) HYPR_INSTALL_MODE="debian" ;;
s | source | "" | *) HYPR_INSTALL_MODE="source" ;;
esac
else
choice=$(whiptail --title "Hyprland install method" --menu "Select installation source" 15 70 5 \
s "Build from source (Recommended)" \
d "Debian packages" 3>&1 1>&2 2>&3) || true
case "$choice" in
d) HYPR_INSTALL_MODE="debian" ;;
s | *) HYPR_INSTALL_MODE="source" ;;
esac
fi
fi
HYPR_INSTALL_MODE="$(select_hypr_install_mode "$DEBIAN_SUITE" "$HYPR_INSTALL_MODE")"
case "$HYPR_INSTALL_MODE" in
source | debian) ;;
*)
echo "${ERROR} Invalid --mode value '$HYPR_INSTALL_MODE'. Use: source, debian, auto." | tee -a "$LOG"
exit 1
;;
esac
# Function to remove Hyprland-related Debian packages
purge_deb_hyprland_packages() {
echo "${INFO} Checking for Hyprland Debian packages..." | tee -a "$LOG"
local hyprland_packages=(
hyprland hyprland-plugins hyprland-session
hyprland-protocols hyprland-guiutils hyprland-qt-support hyprland-qtutils qml6-module-org-hyprland-style
hyprutils libhyprutils0 libhyprutils-dev
hyprlang libhyprlang0 libhyprlang-dev
hyprgraphics libhyprgraphics0 libhyprgraphics-dev
hyprcursor libhyprcursor0 libhyprcursor-dev
hyprwayland-scanner
hyprtoolkit
hyprwire hyprwire-protocols libhyprwire0 libhyprwire-dev
aquamarine libaquamarine0 libaquamarine-dev
hypridle hyprlock hyprpicker hyprpaper hyprsunset hyprlauncher hyprsysteminfo
hyprpolkitagent hyprpm hyprctl
xdg-desktop-portal-hyprland
)
echo "${INFO} Removing any previously installed .deb packages..." | tee -a "$LOG"
local pkg
for pkg in "${hyprland_packages[@]}"; do
if dpkg -s "$pkg" >/dev/null 2>&1; then
echo "${NOTE} Purging package: $pkg" | tee -a "$LOG"
sudo apt-get purge -y "$pkg" 2>&1 | grep -E "(Setting up|Removing|Purging)" | tee -a "$LOG" || true
fi
done
sudo apt-get autoremove -y >/dev/null 2>&1 || true
}
remove_source_hyprland_artifacts() {
echo "${INFO} Checking for source-installed Hyprland artifacts..." | tee -a "$LOG"
local hyprland_binaries=(
"/usr/local/bin/Hyprland"
"/usr/local/bin/hyprland"
"/usr/local/bin/start-hyprland"
"/usr/local/bin/hyprctl"
"/usr/local/bin/hyprpm"
"/usr/local/share/wayland-sessions/hyprland.desktop"
"/usr/local/share/wayland-sessions/hyprland-uwsm.desktop"
"/usr/local/lib/pkgconfig/hyprtoolkit.pc"
"/usr/local/share/pkgconfig/hyprtoolkit.pc"
)
local binary
for binary in "${hyprland_binaries[@]}"; do
if [ -e "$binary" ]; then
echo "${NOTE} Removing source artifact: $binary" | tee -a "$LOG"
sudo rm -f "$binary"
fi
done
# Remove empty local wayland sessions directory (if now unused)
sudo rmdir /usr/local/share/wayland-sessions 2>/dev/null || true
# Remove development files from /usr/local
if [ -d "/usr/local/include/hyprland" ] || [ -d "/usr/local/include/hyprtoolkit" ] || [ -d "/usr/local/lib/libhypr" ] || [ -d "/usr/local/lib/cmake/hyprtoolkit" ]; then
echo "${INFO} Removing development files from /usr/local..." | tee -a "$LOG"
sudo rm -rf /usr/local/include/hyprland* 2>/dev/null || true
sudo rm -rf /usr/local/include/hyprtoolkit* 2>/dev/null || true
sudo rm -rf /usr/local/lib/libhypr* 2>/dev/null || true
sudo rm -rf /usr/local/lib/libaquamarine* 2>/dev/null || true
sudo rm -rf /usr/local/lib/libypr* 2>/dev/null || true
sudo rm -rf /usr/local/lib/cmake/hyprtoolkit 2>/dev/null || true
sudo ldconfig 2>/dev/null || true
fi
echo "${OK} Cleanup completed" | tee -a "$LOG"
}
clean_existing_hyprland() {
purge_deb_hyprland_packages
remove_source_hyprland_artifacts
}
# Welcome / proceed (TTY or whiptail)
if [ "$TTY_MODE" -eq 1 ]; then
echo "========================================"
echo "KooL Debian-Hyprland Trixie+ Install Script"
echo "========================================"
echo "ATTENTION: Run a full system update and reboot first (recommended)."
echo "NOTE: On VMs, enable 3D acceleration or Hyprland may not start."
echo
if [ "$HYPR_INSTALL_MODE" = "debian" ]; then
echo "Build method: DEBIAN PACKAGES (suite: $DEBIAN_SUITE)"
if [ "$DEBIAN_SUITE" = "trixie" ]; then
echo "Trixie mode will enable trixie-backports for Hyprland."
fi
else
echo "Build method: FROM SOURCE"
echo "IMPORTANT: Ensure deb-src is enabled in APT sources."
fi
read -r -p "Proceed with installation? [y/N]: " _ans
case "${_ans,,}" in
y | yes) : ;;
*)
echo "${NOTE} You chose not to continue. Exiting..." | tee -a "$LOG"
exit 1
;;
esac
else
# Welcome message using whiptail (for displaying information)
whiptail --title "KooL Debian-Hyprland Trixie+ (2025) Install Script" \
--msgbox "Welcome to KooL Debian-Hyprland Trixie+ (2025) Install Script!!!\n\n\
ATTENTION: Run a full system update and Reboot first !!! (Highly Recommended)\n\n\
NOTE: If you are installing on a VM, ensure to enable 3D acceleration otherwise Hyprland may NOT start!" \
15 80
if [ "$HYPR_INSTALL_MODE" = "debian" ]; then
proceed_msg="Build method: DEBIAN PACKAGES (suite: $DEBIAN_SUITE)\n\nFor Debian trixie this will enable trixie-backports and install Hyprland from packages.\n\nShall we proceed?"
else
proceed_msg="Build method: FROM SOURCE\n\nVERY IMPORTANT!!!\nYou must be able to install from source by uncommenting or adding deb-src to APT sources else script may fail.\n\nShall we proceed?"
fi
if ! whiptail --title "Proceed with Installation?" --yesno "$proceed_msg" 15 60; then
echo -e "\n"
echo "❌ ${INFO} You 🫵 chose ${YELLOW}NOT${RESET} to proceed. ${YELLOW}Exiting...${RESET}" | tee -a "$LOG"
echo -e "\n"
exit 1
fi
fi
echo "👌 ${OK} 🇵🇭 ${MAGENTA}KooL..${RESET} ${SKY_BLUE}lets continue with the installation...${RESET}" | tee -a "$LOG"
sleep 1
printf "\n%.0s" {1..1}
# install pciutils if detected not installed. Necessary for detecting GPU
if ! dpkg -l | grep -w pciutils >/dev/null; then
echo "pciutils is not installed. Installing..." | tee -a "$LOG"
sudo apt install -y pciutils
printf "\n%.0s" {1..1}
fi
# Path to the install-scripts directory
script_directory=install-scripts
# Function to execute a script if it exists and make it executable
execute_script() {
local script="$1"
shift || true
local script_path="$script_directory/$script"
local args=("$@")
if [ -f "$script_path" ]; then
chmod +x "$script_path"
if [ -x "$script_path" ]; then
# Pass flags via env so sub-scripts can react without CLI churn
if [ "${HYPR_BUILD_TRIXIE:-0}" = "1" ]; then
HYPR_BUILD_TRIXIE=1 HYPR_FORCE_REINSTALL=${FORCE_REINSTALL:-0} HYPR_INSTALL_MODE="${HYPR_INSTALL_MODE:-}" DEBIAN_SUITE="${DEBIAN_SUITE:-}" bash "$script_path" --build-trixie "${args[@]}"
return $?
else
HYPR_BUILD_TRIXIE=0 HYPR_FORCE_REINSTALL=${FORCE_REINSTALL:-0} HYPR_INSTALL_MODE="${HYPR_INSTALL_MODE:-}" DEBIAN_SUITE="${DEBIAN_SUITE:-}" bash "$script_path" "${args[@]}"
return $?
fi
else
echo "Failed to make script '$script' executable." | tee -a "$LOG"
return 1
fi
else
echo "Script '$script' not found in '$script_directory'." | tee -a "$LOG"
return 1
fi
}
# Load centralized Hyprland stack tags if present and export for child scripts
if [ -f "./hypr-tags.env" ]; then
# shellcheck disable=SC1091
source "./hypr-tags.env"
# If core tags are set to auto/latest, refresh to resolve concrete versions
if [ "${HYPRUTILS_TAG:-}" = "auto" ] || [ "${HYPRUTILS_TAG:-}" = "latest" ] || [ -z "${HYPRUTILS_TAG:-}" ] ||
[ "${HYPRLANG_TAG:-}" = "auto" ] || [ "${HYPRLANG_TAG:-}" = "latest" ] || [ -z "${HYPRLANG_TAG:-}" ]; then
if [ -f ./refresh-hypr-tags.sh ]; then
chmod +x ./refresh-hypr-tags.sh || true
./refresh-hypr-tags.sh
# reload after refresh
# shellcheck disable=SC1091
source "./hypr-tags.env"
fi
fi
# Export all *_TAG variables and WAYLAND_PROTOCOLS_TAG for child scripts
while IFS='=' read -r _k _v; do
[ -z "${_k:-}" ] && continue
case "$_k" in
*"_TAG" | WAYLAND_PROTOCOLS_TAG)
export "$_k"
;;
esac
done <"./hypr-tags.env"
fi
#################
## Default values for the options (will be overwritten by preset file if available)
gtk_themes="OFF"
bluetooth="OFF"
thunar="OFF"
ags="OFF"
quickshell="OFF"
sddm="OFF"
sddm_theme="OFF"
xdph="OFF"
zsh="OFF"
pokemon="OFF"
rog="OFF"
dots="OFF"
input_group="OFF"
nvidia="OFF"
# Function to load preset file
load_preset() {
if [ -f "$1" ]; then
echo "✅ Loading preset: $1"
source "$1"
else
echo "⚠️ Preset file not found: $1. Using default values."
fi
}
# Check if --preset argument is passed (order-independent)
if [ -n "${PRESET_FILE:-}" ]; then
load_preset "$PRESET_FILE"
fi
# List of services to check for active login managers
services=("gdm.service" "gdm3.service" "lightdm.service" "lxdm.service")
# Function to check if any login services are active
check_services_running() {
active_services=() # Array to store active services
for svc in "${services[@]}"; do
if systemctl is-active --quiet "$svc"; then
active_services+=("$svc")
fi
done
if [ ${#active_services[@]} -gt 0 ]; then
return 0
else
return 1
fi
}
if check_services_running; then
active_list=$(printf "%s\n" "${active_services[@]}")
if [ "$TTY_MODE" -eq 1 ]; then
echo "${WARN} Active non-SDDM login manager(s) detected:"
echo "$active_list"
echo "NOTE: SDDM and SDDM theme options will be hidden."
else
# Display the active login manager(s) in the whiptail message box
whiptail --title "Active non-SDDM login manager(s) detected" \
--msgbox "The following login manager(s) are active:\n\n$active_list\n\nIf you want to install SDDM and SDDM theme, stop and disable first the active services above, and reboot before running this script\nRefer to README on switching to SDDM if you really want SDDM\n\nNOTE: Your option to install SDDM and SDDM theme has now been removed\n\n- Ja " 28 80
fi
fi
# Check if NVIDIA GPU is detected
nvidia_detected=false
if lspci | grep -i "nvidia" &>/dev/null; then
nvidia_detected=true
whiptail --title "NVIDIA GPU Detected" --msgbox "NVIDIA GPU detected in your system.\n\nNOTE: The script will install nvidia-dkms, nvidia-utils, and nvidia-settings if you choose to configure." 12 60
fi
# Initialize the options array for whiptail checklist
options_command=(
whiptail --title "Select Options" --checklist "Choose options to install or configure\nNOTE: 'SPACEBAR' to select & 'TAB' key to change selection" 28 85 20
)
# Add NVIDIA options if detected
if [ "$nvidia_detected" == "true" ]; then
options_command+=(
"nvidia" "Do you want script to configure NVIDIA GPU?" "OFF"
)
fi
# Check if user is already in the 'input' group
input_group_detected=false
if ! groups "$(whoami)" | grep -q '\binput\b'; then
input_group_detected=true
whiptail --title "Input Group" --msgbox "You are not currently in the input group.\n\nAdding you to the input group might be necessary for the Waybar keyboard-state functionality." 12 60
fi
# Add 'input_group' option if user is not in input group
if [ "$input_group_detected" == "true" ]; then
options_command+=(
"input_group" "Add your USER to input group for some waybar functionality?" "OFF"
)
fi
# Conditionally add SDDM and SDDM theme options if no active login manager is found
if ! check_services_running; then
options_command+=(
"sddm" "Install & configure SDDM login manager?" "OFF"
"sddm_theme" "Download & Install Additional SDDM theme?" "OFF"
)
fi
# Add the remaining static options (XDPH now installed by default; removed from menu)
options_command+=(
"gtk_themes" "Install GTK themes (required for Dark/Light function)" "OFF"
"bluetooth" "Do you want script to configure Bluetooth?" "OFF"
"thunar" "Do you want Thunar file manager to be installed?" "OFF"
"ags" "Install AGS v1 for Desktop-Like Overview" "OFF"
"quickshell" "Install Quickshell (QtQuick-based shell toolkit)?" "OFF"
"zsh" "Install zsh shell with Oh-My-Zsh?" "OFF"
"pokemon" "Add Pokemon color scripts to your terminal?" "OFF"
"rog" "Are you installing on Asus ROG laptops?" "OFF"
"dots" "Download and install pre-configured KooL Hyprland dotfiles?" "OFF"
)
# Capture the selected options before the while loop starts
if [ "$TTY_MODE" -eq 1 ]; then
# Build a simple list of available keys
available_opts=()
if [ "$nvidia_detected" == "true" ]; then available_opts+=(nvidia); fi
if [ "$input_group_detected" == "true" ]; then available_opts+=(input_group); fi
if ! check_services_running; then available_opts+=(sddm sddm_theme); fi
available_opts+=(gtk_themes bluetooth thunar ags quickshell zsh pokemon rog dots)
while true; do
echo "Available options (space-separated):"
printf ' %s\n' "${available_opts[@]}"
read -r -p "Enter options to install/configure: " selected_options
selected_options=$(echo "$selected_options" | tr -d '"' | tr -s ' ')
if [ -z "$selected_options" ]; then
echo "${WARN} No options selected. Please enter at least one."
continue
fi
IFS=' ' read -r -a options <<<"$selected_options"
echo "You selected: ${options[*]}"
read -r -p "Proceed with these choices? [y/N]: " yn
case "${yn,,}" in
y | yes) break ;;
*) echo "Returning to selection..." ;;
esac
done
else
while true; do
selected_options=$("${options_command[@]}" 3>&1 1>&2 2>&3)
if [ $? -ne 0 ]; then
echo -e "\n"
echo "❌ ${INFO} You 🫵 cancelled the selection. ${YELLOW}Goodbye!${RESET}" | tee -a "$LOG"
exit 0
fi
if [ -z "$selected_options" ]; then
whiptail --title "Warning" --msgbox "No options were selected. Please select at least one option." 10 60
continue
fi
selected_options=$(echo "$selected_options" | tr -d '"' | tr -s ' ')
IFS=' ' read -r -a options <<<"$selected_options"
dots_selected="OFF"
for option in "${options[@]}"; do
if [[ "$option" == "dots" ]]; then
dots_selected="ON"
break
fi
done
if [[ "$dots_selected" == "OFF" ]]; then
if ! whiptail --title "KooL Hyprland Dot Files" --yesno \
"You have not selected to install the pre-configured KooLDots Hyprland dotfiles.\n\nKindly NOTE that if you proceed without dotfiles, and this is a *new* install, not an *upgrade*, Hyprland will start with default vanilla Hyprland configuration and I won't be able to give you support.\n\nWould you like to continue install without KooL Hyprland Dots or return to choices/options?" \
--yes-button "Continue" --no-button "Return" 15 90; then
echo "🔙 Returning to options..." | tee -a "$LOG"
continue
else
echo "${INFO} ⚠️ Continuing WITHOUT the dotfiles installation..." | tee -a "$LOG"
printf "\n%.0s" {1..1}
fi
fi
confirm_message="You have selected the following options:\n\n"
for option in "${options[@]}"; do
confirm_message+=" - $option\n"
done
confirm_message+="\nAre you happy with these choices?"
if ! whiptail --title "Confirm Your Choices" --yesno "$(printf "%s" "$confirm_message")" 25 80; then
echo -e "\n"
echo "❌ ${SKY_BLUE}You're not 🫵 happy${RESET}. ${YELLOW}Returning to options...${RESET}" | tee -a "$LOG"
continue
fi
echo "👌 ${OK} You confirmed your choices. Proceeding with ${SKY_BLUE}KooL 🇵🇭 Hyprland Installation...${RESET}" | tee -a "$LOG"
break
done
fi
printf "\n%.0s" {1..1}
# Verify APT sources before updating (deb-src + non-free components)
echo "${INFO} Verifying APT sources (deb-src, non-free, non-free-firmware)..." | tee -a "$LOG"
verify_and_offer_fix_apt_sources
if [ "$DEBIAN_SUITE" = "trixie" ]; then
ensure_trixie_backports_repo "$DEBIAN_SUITE"
fi
echo "${INFO} Running a ${SKY_BLUE}full system update...${RESET}" | tee -a "$LOG"
sudo apt update
sleep 1
if [ "$HYPR_INSTALL_MODE" = "debian" ]; then
if ! verify_debian_hypr_packages "$DEBIAN_SUITE"; then
echo "${WARN} Falling back to source install mode because required Debian packages are unavailable." | tee -a "$LOG"
HYPR_INSTALL_MODE="source"
fi
fi
if [ "$HYPR_INSTALL_MODE" = "debian" ]; then
remove_source_hyprland_artifacts
execute_script "02-pre-cleanup.sh"
echo "${INFO} Installing ${SKY_BLUE}necessary fonts...${RESET}" | tee -a "$LOG"
sleep 1
execute_script "fonts.sh" || {
echo "${ERROR:-[ERROR]} Fonts installation failed" | tee -a "$LOG"
exit 1
}
echo "${INFO} Installing ${SKY_BLUE}KooL Hyprland packages from Debian repositories...${RESET}" | tee -a "$LOG"
sleep 1
install_debian_hyprland_stack "$DEBIAN_SUITE"
echo "${INFO} Installing ${SKY_BLUE}KooL Hyprland runtime/support packages...${RESET}" | tee -a "$LOG"
sleep 1
execute_script "01-hypr-pkgs.sh" || {
echo "${ERROR:-[ERROR]} Hyprland packages installation failed" | tee -a "$LOG"
exit 1
}
sleep 1
execute_script "wallust.sh"
sleep 1
execute_script "swww.sh"
sudo ldconfig 2>/dev/null || true
else
# Remove any Debian-provided Hyprland stack packages before source builds
clean_existing_hyprland
# execute pre clean up
execute_script "02-pre-cleanup.sh"
echo "${INFO} Installing ${SKY_BLUE}necessary dependencies...${RESET}" | tee -a "$LOG"
sleep 1
execute_script "00-dependencies.sh" || {
echo "${ERROR:-[ERROR]} Dependencies installation failed" | tee -a "$LOG"
exit 1
}
echo "${INFO} Installing ${SKY_BLUE}necessary fonts...${RESET}" | tee -a "$LOG"
sleep 1
execute_script "fonts.sh" || {
echo "${ERROR:-[ERROR]} Fonts installation failed" | tee -a "$LOG"
exit 1
}
# Build from source
# Optional: refresh tags before building the Hyprland stack
# Set FETCH_LATEST=1 to opt-in (default is no-refresh to honor pinned tags)
if [ "${FETCH_LATEST:-0}" = "1" ] && [ -f ./refresh-hypr-tags.sh ]; then
chmod +x ./refresh-hypr-tags.sh || true
./refresh-hypr-tags.sh
fi
echo "${INFO} Installing ${SKY_BLUE}KooL Hyprland packages from source...${RESET}" | tee -a "$LOG"
sleep 1
execute_script "01-hypr-pkgs.sh" || {
echo "${ERROR:-[ERROR]} Hyprland packages installation failed" | tee -a "$LOG"
exit 1
}
sleep 1
execute_script "hyprutils.sh"