Modular post-install automation script for openSUSE Tumbleweed (zypper, Snapper tuning, entry point opensuse-setup-modular.sh)
Find a file
Avraam Fyraridis b5f1a1bcdc fix(gpu): scope the kernel-module install message to avoid overclaiming
"Installing NVIDIA open kernel module from default openSUSE repos
(EU-signed, no US repo)" was technically correct but printed first in
the branch, easy to misread as a claim about the whole NVIDIA setup.
Scope it explicitly to the kernel driver and flag that the GL/Vulkan/
CUDA userspace remains proprietary regardless.
2026-08-01 11:48:24 +03:00
config chore: mark scripts/configs executable 2026-08-01 11:36:53 +03:00
docs Standalone cutover: MIT relicense, Qt6 GUI pivot, containerized dev stack 2026-07-23 19:42:06 +03:00
gui Standalone cutover: MIT relicense, Qt6 GUI pivot, containerized dev stack 2026-07-23 19:42:06 +03:00
lib fix(gpu): scope the kernel-module install message to avoid overclaiming 2026-08-01 11:48:24 +03:00
modules chore: mark scripts/configs executable 2026-08-01 11:36:53 +03:00
.gitignore chore: mark scripts/configs executable 2026-08-01 11:36:53 +03:00
CHANGELOG.md docs: document NVIDIA userspace runtime-check fix in README and CHANGELOG 2026-08-01 11:33:26 +03:00
LICENSE chore: mark scripts/configs executable 2026-08-01 11:36:53 +03:00
opensuse-setup-modular.sh fix(report): correct factual errors in the summary, and the stdbuf/_dbx_enter bug 2026-07-25 16:26:07 +03:00
PORTING.md Standalone cutover: MIT relicense, Qt6 GUI pivot, containerized dev stack 2026-07-23 19:42:06 +03:00
README.md docs: document NVIDIA userspace runtime-check fix in README and CHANGELOG 2026-08-01 11:33:26 +03:00
test-phase1.sh Standalone cutover: MIT relicense, Qt6 GUI pivot, containerized dev stack 2026-07-23 19:42:06 +03:00
test-phase2.sh Standalone cutover: MIT relicense, Qt6 GUI pivot, containerized dev stack 2026-07-23 19:42:06 +03:00

openSUSE Tumbleweed Post-Installation Setup

A modular post-installation script for openSUSE Tumbleweed. Sets up multimedia codecs, development toolchains, GPU drivers, databases, and system optimizations — with an emphasis on sourcing everything from official openSUSE repositories rather than third-party ones.

Status: working, actively used. Every major feature listed under "Verified" below has been run end-to-end on real hardware, not just tested in a VM.

Warning

This script modifies system configuration, installs packages, and (if enabled) installs GPU kernel modules. Take a Btrfs snapshot before your first run (sudo snapper create -d pre-setup) and read the flags below. Start with the minimal profile.

Quick start

git clone ssh://git@git.truediff.dev:2222/truediff/openSUSE-Tumbleweed-Script.git
cd openSUSE-Tumbleweed-Script
chmod +x opensuse-setup-modular.sh

# Safe first run: core system only, no GPU drivers, no dev tools
./opensuse-setup-modular.sh minimal --auto

Profiles

Profile Contents
minimal Base system, multimedia codecs (Packman), essential CLI utilities, shell config, system optimizations. No dev tools, no GPU drivers, no gaming.
complete Everything: dev toolchains, PostgreSQL, data science, gaming utilities, GPU drivers, SCX scheduler.

Run with --auto (unattended) or --interactive (prompts).

What it does (14 steps)

System checks → GPU detection → zypper tuning → repositories (Packman via an EU mirror) → zypper dup → base system → multimedia → core packages → GPU drivers → PostgreSQL → data science → gaming → shell → optimizations (including Snapper tuning).

Configuration

Every feature is a flag. Precedence is environment variable > profile > defaults, so you can override anything on the command line:

INSTALL_GPU_DRIVERS=false INSTALL_GAMING=false \
  ./opensuse-setup-modular.sh complete --auto

Key flags (see config/defaults.conf for the full list and comments):

Flag Default Purpose
INSTALL_GPU_DRIVERS true Install vendor GPU drivers. Set false for a lower-risk first pass.
INSTALL_GPU_HYBRID_SWITCHING true supergfxctl/switcheroo-control on hybrid laptops. false still gives working PRIME render-offload.
INSTALL_GPU_NVIDIA_MIGRATE_OPEN false If a proprietary NVIDIA driver is already installed, auto-migrate to the open module (destructive: removes all nvidia packages first). Default is to detect, skip, and print manual steps.
INSTALL_DEV_MODE containers containers = toolchains in a distrobox; baremetal = installed on the host.
INSTALL_POSTGRESQL_MODE native native = system package; quadlet = rootless podman container, version-pinned.

Design notes

Containerized dev toolchains (default). On a rolling release, a host Python/Node/Go upgrade can break every venv and project on the machine. Dev toolchains therefore live in a distrobox container that only changes when you recreate it. This also keeps the host smaller, which means smaller Btrfs snapshot deltas. See docs/CONTAINERS-DECISION.md for the full reasoning, including why the gaming stack deliberately stays on bare metal.

Snapper tuning. Btrfs qgroup accounting makes snapshot cleanup slow enough to stall I/O on some systems. The script disables quota accounting, clears QGROUP, bounds snapshot counts, and disables timeline snapshots — while keeping rollback and pre/post-zypper snapshots intact.

NVIDIA. Uses the open kernel module (nvidia-open-driver-G06-signed-kmp-default, Turing/RTX 20-series and newer) from the default openSUSE repositories. No third-party NVIDIA repository is added. The -signed variant normally loads under Secure Boot without manual MOK enrollment.

The kernel module alone does not give you rendering: the GL/EGL/Vulkan/CUDA userspace (nvidia-gl-G06, nvidia-video-G06, nvidia-compute-G06, nvidia-compute-utils-G06 for nvidia-smi) is a separate set of packages, always closed-source regardless of the open/proprietary kmp choice. The script checks at runtime (zypper info) whether these resolve from a repo you already have enabled (e.g. the official repo-non-free from openSUSE-repos-*-NVIDIA, commonly added by the Tumbleweed installer itself when it detects an NVIDIA GPU) and installs them automatically if so; otherwise it prints manual steps rather than adding NVIDIA's own repo for you. Without either, the open module loads but every app — including games — silently renders on the integrated GPU instead.

Package sourcing. Official openSUSE repos wherever possible; Packman via an EU mirror for multimedia; container images from registry.opensuse.org and registry.suse.com. Where the only source for something is an individual's personal OBS project (e.g. the NVIDIA VA-API bridge), the script prints instructions rather than silently adding that repository.

Verified on real hardware

Tested end-to-end on a hybrid Intel + NVIDIA laptop (RTX 4070 mobile, Tumbleweed snapshot 20260718, kernel 7.1):

  • minimal profile, full 14 steps
  • Snapper qgroup tuning (quotas confirmed off)
  • Containerized dev stack (distrobox, gcc 15.3.0 inside the container)
  • NVIDIA open kernel module (/proc/driver/nvidia/version confirms the open module); nvidia-smi live via the proprietary→open migration path (pre-existing driver detected, full package set installed as part of the documented migration)
  • Optimus PRIME render-offload
  • PostgreSQL quadlet (PG 17.10, connection verified)

2026-08-01 finding: on the default clean-install path (no pre-existing proprietary driver — the common case), the userspace packages were previously skipped unconditionally, so nvidia-smi was NOT live and everything, including games, silently rendered on the integrated GPU instead of NVIDIA. Fixed by checking package availability at runtime (see NVIDIA design note above); verified end-to-end on the same real hardware after the fix — nvidia-smi live, PRIME offload confirmed via glxinfo.

Not yet execution-tested: the AMD GPU branch, the destructive proprietary→open NVIDIA migration path on this codebase revision (it was verified pre-port; not re-run since), and the complete profile as a single end-to-end run. Treat those as reviewed-but-unproven.

Repository layout

opensuse-setup-modular.sh   Orchestrator (the 14 steps)
lib/                        common helpers, GPU, repositories, system checks
modules/                    One file per feature area
config/                     defaults.conf + profiles/
docs/                       INTERFACE.md (GUI contract), CONTAINERS-DECISION.md
gui/                        askpass helper + notes for a future GUI front-end
test-phase1.sh              Syntax/structure checks
test-phase2.sh              Dry-run package-resolution checks
PORTING.md                  Engineering log: every bug found and why it happened

Contributing / debugging

PORTING.md is the detailed engineering log — 17 rounds of bugs found on real hardware, each with the root cause written down. If something breaks, read it first; the failure mode is often already documented there.

Before opening a PR: run test-phase1.sh (syntax) and, on a Tumbleweed machine, test-phase2.sh (dry-run package resolution).

License

MIT — see LICENSE.