Skip to content

Commit c8e9779

Browse files
author
Firebleudark
committed
v5.0.0: Simple post-install + GUI; English docs; cleanup
0 parents  commit c8e9779

File tree

8 files changed

+1434
-0
lines changed

8 files changed

+1434
-0
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Changelog
2+
3+
## v5.0.0 — Simple Post-install + GUI wrapper
4+
5+
- Rewrite focused on a single, readable Bash script: `v5/simple-postinstall.sh`.
6+
- Robust preflight checks: distro (Arch), sudo, network, pacman sync, NTP, pacman GPG keys.
7+
- Profiles: `minimal`, `gaming`, `kde` (non-interactive with `--yes`).
8+
- GPU drivers: AMD/Intel (Mesa/Vulkan), NVIDIA open-source `nouveau` by default with opt-in proprietary.
9+
- System setup: multilib, Flatpak + Flathub, PipeWire/WirePlumber, NetworkManager, CUPS, virtualization (qemu/libvirt/virt-manager), TLP, UFW, useful services.
10+
- Categories: Base, Dev, Media, Browsers, Communication, Office/Fonts, Gaming.
11+
- Source priority policy: repo > AUR (paru auto-install if needed) > Flatpak.
12+
- Tkinter GUI: `gui/app.py` (subtle dark theme), profiles exposed, extras toggles, preflight button, live logs.
13+
- Repository cleanup: removed legacy GUI and complex scaffolding; simplified doc in English.
14+
15+
### Notes
16+
- Requires Python `tk` for GUI. CLI does not need Python.
17+
- A reboot is recommended after switching NVIDIA drivers.

LICENSE

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Autoinstallpackages — Simple Arch Post-install
2+
3+
Simple, readable Arch Linux post-install tool. It performs essential preflight checks, installs drivers, configures core services, and offers app categories. Three ready-to-use profiles: minimal, gaming, and full KDE.
4+
5+
## Features
6+
- Preflight: distro check (Arch), sudo validation, network reachability, pacman database sync, NTP sync, pacman GPG keys.
7+
- GPU drivers: AMD/Intel (Mesa/Vulkan), NVIDIA (nouveau by default; proprietary optional).
8+
- System setup: multilib, Flatpak + Flathub, PipeWire/WirePlumber, NetworkManager, printing (CUPS), virtualization (qemu/libvirt/virt-manager), laptop (TLP), firewall (UFW), useful services (fstrim + optional Bluetooth).
9+
- App categories: Base, Dev, Media, Browsers, Communication, Office/Fonts, Gaming.
10+
- Source priority: repo > AUR (paru auto if needed) > Flatpak.
11+
- GUI wrapper: optional Tkinter app with subtle dark theme and direct controls.
12+
13+
## Requirements
14+
- Arch Linux (or derivative with pacman).
15+
- Internet access; sudo privileges.
16+
- For GUI: Python 3 and Tk (package `tk`).
17+
- Tools used: `pciutils` (lspci), `curl`, `ping` (optional), `systemd` (timedatectl), `git` and `base-devel` (for AUR helper install when needed), `flatpak` (if chosen).
18+
19+
## Profiles
20+
- minimal: open-source GPU drivers, Base utils, audio, network, firewall; no multilib/Flatpak/KDE.
21+
- gaming: multilib + Flatpak, GPU drivers, Base + Gaming (Steam, Gamemode, MangoHUD) + gaming extras (Lutris, Heroic, Bottles, PrismLauncher, ProtonUp-Qt), audio/network, services.
22+
- kde: full KDE Plasma + KDE Apps + SDDM, Base utils, audio/network, services.
23+
24+
## Source Priority Policy
25+
When installing a specific app, the tool tries in this order:
26+
1) Official Arch repo via pacman
27+
2) AUR via `paru` (or `yay`) — if no helper is present, it offers to install `paru` automatically
28+
3) Flatpak from Flathub
29+
30+
## CLI Usage
31+
```bash
32+
# Interactive
33+
bash v5/simple-postinstall.sh
34+
35+
# Non-interactive profiles
36+
bash v5/simple-postinstall.sh --profile minimal --yes
37+
bash v5/simple-postinstall.sh --profile gaming --yes
38+
bash v5/simple-postinstall.sh --profile kde --yes
39+
40+
# Dry-run (no changes)
41+
bash v5/simple-postinstall.sh --dry-run
42+
43+
# Skip AUR entirely
44+
bash v5/simple-postinstall.sh --skip-aur
45+
46+
# Preflight only (report and exit)
47+
bash v5/simple-postinstall.sh --check
48+
49+
# Extras toggles (non-interactive)
50+
bash v5/simple-postinstall.sh --yes --profile minimal \
51+
--gaming-extras --install-chromium --install-chrome --install-spotify
52+
```
53+
54+
## GUI Usage
55+
```bash
56+
python3 gui/app.py
57+
```
58+
- Select a profile (Minimal, Gaming, KDE) and optional extras.
59+
- Preflight button runs non-intrusive checks.
60+
- Install button runs the Bash script with your selection.
61+
62+
## Notes on NVIDIA Drivers
63+
- The default path for NVIDIA is open-source `nouveau` (removes proprietary `nvidia*` if present and installs `xf86-video-nouveau` + `mesa`, and `vulkan-nouveau` when available).
64+
- You can opt-in to proprietary drivers during the prompt.
65+
- A reboot is recommended after switching drivers.
66+
67+
## Safety & Idempotency
68+
- Most operations are idempotent (safe to re-run).
69+
- The script prompts before major changes (unless `--yes`).
70+
- Preflight tries to auto-fix safe items (NTP, pacman keys) when reasonable.
71+
72+
## License
73+
[GPLv3](LICENSE)

VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5.0.0
11.7 KB
Binary file not shown.

gui/__pycache__/app.pyc

11.6 KB
Binary file not shown.

gui/app.py

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#!/usr/bin/env python3
2+
# Simple Tkinter GUI wrapper for the Bash post-install script.
3+
# - Subtle dark theme, minimal controls
4+
# - Profiles exposed: minimal, gaming, KDE
5+
# - Extras toggles: gaming extras, Chromium, Google Chrome, Spotify
6+
# - Preflight button runs non-intrusive checks
7+
import os
8+
import sys
9+
import threading
10+
import subprocess
11+
import queue
12+
import tkinter as tk
13+
from tkinter import ttk, messagebox
14+
15+
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16+
SCRIPT = os.path.join(ROOT, 'v5', 'simple-postinstall.sh')
17+
18+
19+
class App(tk.Tk):
20+
def __init__(self):
21+
super().__init__()
22+
self.title('Autoinstall Post-Install (Arch)')
23+
self.geometry('900x600')
24+
self._setup_theme()
25+
self._build_ui()
26+
self.proc = None
27+
self.q = queue.Queue()
28+
29+
def _setup_theme(self):
30+
style = ttk.Style(self)
31+
try:
32+
style.theme_use('clam')
33+
except Exception:
34+
pass
35+
# Subtle palette
36+
self.configure(bg='#111418')
37+
style.configure('.', background='#111418', foreground='#D6D7D9')
38+
style.configure('TButton', background='#1a1f24', foreground='#E6E7E8')
39+
style.map('TButton', background=[('active', '#232a31')])
40+
style.configure('TCheckbutton', background='#111418', foreground='#D6D7D9')
41+
style.configure('TRadiobutton', background='#111418', foreground='#D6D7D9')
42+
style.configure('TFrame', background='#111418')
43+
style.configure('TLabel', background='#111418', foreground='#D6D7D9')
44+
style.configure('TNotebook', background='#111418')
45+
style.configure('TNotebook.Tab', background='#1a1f24', foreground='#D6D7D9')
46+
47+
def _build_ui(self):
48+
container = ttk.Frame(self)
49+
container.pack(fill='both', expand=True, padx=12, pady=12)
50+
51+
# Top controls
52+
top = ttk.Frame(container)
53+
top.pack(fill='x', pady=(0, 8))
54+
55+
self.profile = tk.StringVar(value='minimal')
56+
ttk.Label(top, text='Profile:').pack(side='left')
57+
for val, txt in [('minimal', 'Minimal'), ('gaming', 'Gaming'), ('kde', 'KDE')]:
58+
ttk.Radiobutton(top, text=txt, value=val, variable=self.profile).pack(side='left', padx=6)
59+
60+
ttk.Separator(container).pack(fill='x', pady=6)
61+
62+
# Extras
63+
ex = ttk.Frame(container)
64+
ex.pack(fill='x')
65+
ttk.Label(ex, text='Extras:').grid(row=0, column=0, sticky='w')
66+
self.var_gaming = tk.BooleanVar(value=False)
67+
self.var_chromium = tk.BooleanVar(value=False)
68+
self.var_chrome = tk.BooleanVar(value=False)
69+
self.var_spotify = tk.BooleanVar(value=False)
70+
ttk.Checkbutton(ex, text='Gaming extras (Lutris, Heroic, Bottles, Prism, ProtonUp)', variable=self.var_gaming).grid(row=1, column=0, sticky='w')
71+
ttk.Checkbutton(ex, text='Chromium (repo)', variable=self.var_chromium).grid(row=2, column=0, sticky='w')
72+
ttk.Checkbutton(ex, text='Google Chrome (AUR/Flatpak)', variable=self.var_chrome).grid(row=3, column=0, sticky='w')
73+
ttk.Checkbutton(ex, text='Spotify (AUR/Flatpak)', variable=self.var_spotify).grid(row=4, column=0, sticky='w')
74+
75+
# Buttons
76+
btns = ttk.Frame(container)
77+
btns.pack(fill='x', pady=8)
78+
ttk.Button(btns, text='Preflight', command=self.run_check).pack(side='left')
79+
self.btn_install = ttk.Button(btns, text='Install', command=self.run_install)
80+
self.btn_install.pack(side='left', padx=8)
81+
self.progress = ttk.Progressbar(btns, mode='indeterminate')
82+
self.progress.pack(side='right', fill='x', expand=True)
83+
84+
# Log area
85+
logf = ttk.Frame(container)
86+
logf.pack(fill='both', expand=True)
87+
self.txt = tk.Text(logf, bg='#0f1317', fg='#D6D7D9', insertbackground='#D6D7D9')
88+
self.txt.pack(fill='both', expand=True)
89+
self.txt.tag_config('ok', foreground='#7bd88f')
90+
self.txt.tag_config('warn', foreground='#ffcc66')
91+
self.txt.tag_config('err', foreground='#ff6e6e')
92+
93+
self.after(100, self._poll_queue)
94+
95+
def append(self, s, tag=None):
96+
self.txt.insert('end', s + '\n', tag)
97+
self.txt.see('end')
98+
99+
def run_check(self):
100+
if not os.path.exists(SCRIPT):
101+
messagebox.showerror('Error', f'Script not found: {SCRIPT}')
102+
return
103+
self._run_async(["bash", SCRIPT, "--check"], title='Preflight…')
104+
105+
def run_install(self):
106+
if not os.path.exists(SCRIPT):
107+
messagebox.showerror('Error', f'Script not found: {SCRIPT}')
108+
return
109+
profile = self.profile.get()
110+
args = ["bash", SCRIPT, "--yes", "--profile", profile]
111+
if self.var_gaming.get():
112+
args.append("--gaming-extras")
113+
# Ensure gaming extras are installed when profile is "gaming"
114+
if profile == 'gaming' and "--gaming-extras" not in args:
115+
args.append("--gaming-extras")
116+
if self.var_chromium.get():
117+
args.append("--install-chromium")
118+
if self.var_chrome.get():
119+
args.append("--install-chrome")
120+
if self.var_spotify.get():
121+
args.append("--install-spotify")
122+
self._run_async(args, title='Installing…')
123+
124+
def _run_async(self, args, title='Exécution…'):
125+
if self.proc and self.proc.poll() is None:
126+
messagebox.showwarning('Running', 'An execution is already in progress.')
127+
return
128+
self.append('=' * 60)
129+
self.append(title)
130+
self.progress.start(10)
131+
self.btn_install.state(['disabled'])
132+
def worker():
133+
try:
134+
self.proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1)
135+
for line in self.proc.stdout:
136+
self.q.put(line.rstrip('\n'))
137+
rc = self.proc.wait()
138+
self.q.put(f"[exit {rc}]")
139+
except Exception as e:
140+
self.q.put(f"[error] {e}")
141+
threading.Thread(target=worker, daemon=True).start()
142+
143+
def _poll_queue(self):
144+
try:
145+
while True:
146+
line = self.q.get_nowait()
147+
tag = None
148+
if 'FAIL' in line or 'error' in line.lower():
149+
tag = 'err'
150+
elif 'OK' in line or 'done' in line.lower():
151+
tag = 'ok'
152+
elif 'warn' in line.lower():
153+
tag = 'warn'
154+
self.append(line, tag)
155+
except queue.Empty:
156+
pass
157+
finally:
158+
if self.proc and self.proc.poll() is not None:
159+
self.progress.stop()
160+
self.btn_install.state(['!disabled'])
161+
self.after(100, self._poll_queue)
162+
163+
164+
def main():
165+
app = App()
166+
app.mainloop()
167+
168+
169+
if __name__ == '__main__':
170+
main()

0 commit comments

Comments
 (0)