From 35ae448a9549f03505449812e5e2faaf07c57d9f Mon Sep 17 00:00:00 2001 From: rccyx Date: Sat, 20 Jun 2026 23:42:08 +0100 Subject: [PATCH 01/10] nix: add package and flake outputs --- default.nix | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 32 ++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 default.nix create mode 100644 flake.nix diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..89fbe2e --- /dev/null +++ b/default.nix @@ -0,0 +1,56 @@ +{ + lib, + stdenvNoCC, + qt6, +}: + +stdenvNoCC.mkDerivation { + pname = "thyx"; + version = "1.0.0"; + + src = ./.; + + dontBuild = true; + dontConfigure = true; + + installPhase = '' + runHook preInstall + + theme_dir="$out/share/sddm/themes/thyx" + font_dir="$out/share/fonts/truetype/thyx" + license_dir="$out/share/licenses/thyx" + + mkdir -p "$theme_dir" "$font_dir" "$license_dir" + + install -Dm0644 metadata.desktop "$theme_dir/metadata.desktop" + install -Dm0644 theme.conf "$theme_dir/theme.conf" + + cp -r backgrounds "$theme_dir/backgrounds" + cp -r icons "$theme_dir/icons" + cp -r presets "$theme_dir/presets" + cp -r src "$theme_dir/src" + + install -Dm0644 fonts/*.ttf -t "$font_dir" + install -Dm0644 LICENSE "$license_dir/LICENSE" + install -Dm0644 fonts/OFL.txt "$license_dir/OFL.txt" + + runHook postInstall + ''; + + passthru = { + sddmThemeName = "thyx"; + qtQmlPackages = with qt6; [ + qtdeclarative + qtmultimedia + qt5compat + qtsvg + ]; + }; + + meta = { + description = "Thyx SDDM theme"; + homepage = "https://github.com/rccyx/thyx"; + license = lib.licenses.mit; + platforms = lib.platforms.linux; + }; +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..a0e06c4 --- /dev/null +++ b/flake.nix @@ -0,0 +1,32 @@ +{ + description = "Thyx SDDM theme"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = { self, nixpkgs }: + let + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; + + forAllSystems = nixpkgs.lib.genAttrs systems; + in + { + packages = forAllSystems (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + default = pkgs.callPackage ./default.nix { }; + thyx = self.packages.${system}.default; + }); + + nixosModules = { + default = import ./module.nix; + thyx = self.nixosModules.default; + }; + }; +} From 7098df21c65fe48712d278c568ae4070b0e771a1 Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 02:04:28 +0100 Subject: [PATCH 02/10] add nix sddm module --- module.nix | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 module.nix diff --git a/module.nix b/module.nix new file mode 100644 index 0000000..110d4f5 --- /dev/null +++ b/module.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.displayManager.sddm.thyx; + package = cfg.package; + themeName = package.passthru.sddmThemeName or "thyx"; + qtQmlPackages = package.passthru.qtQmlPackages or (with pkgs.qt6; [ + qtdeclarative + qtmultimedia + qt5compat + qtsvg + ]); +in +{ + options.services.displayManager.sddm.thyx = { + enable = lib.mkEnableOption "Thyx SDDM theme"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.callPackage ./default.nix { }; + defaultText = lib.literalExpression "pkgs.callPackage ./default.nix { }"; + description = "Thyx SDDM theme package."; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ package ]; + + fonts.packages = [ package ]; + + services.displayManager.sddm = { + enable = true; + theme = themeName; + extraPackages = [ package ] ++ qtQmlPackages; + }; + }; +} From f214a316a1f61879823b5e6483d7fc6d2938ca6e Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 02:18:29 +0100 Subject: [PATCH 03/10] add nix docs --- README.md | 30 +++++++++++++++++------------- docs/nix.md | 32 ++++++++++++++++++++++++++++++++ scripts/install | 1 + 3 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 docs/nix.md diff --git a/README.md b/README.md index 9d953db..28bd821 100644 --- a/README.md +++ b/README.md @@ -95,19 +95,7 @@ Want a fast mental model of what this is, what SDDM is, and how recovery works? ## Installation -Clone the repo, then run the installer from the repo root. - -```bash -./scripts/install -``` - -For non interactive installs, pass `--yes`. - -```bash -./scripts/install --yes -``` - -The installer will install and setup everything for the following (through the manifests in [`scripts/data`](./scripts/data/)): +The installer is atomic and idempotent and will auto setup everything with one command for the following: - **Arch** @@ -131,6 +119,22 @@ The installer will install and setup everything for the following (through the m - **Gentoo** - **Alpine Edge** +Simply run: + +```bash +git clone https://github.com/rccyx/thyx && cd thyx +bash ./scripts/install +``` + +For non interactive installs, pass `--yes`. + +```bash +bash ./scripts/install --yes +``` + +> [!IMPORTANT] +> Using NixOS? read [docs/nix.md](./docs/nix.md). Don't run those commands: + The installer is local, explicit, and idempotent. It validates the theme tree, installs missing runtime packages, checks required commands, stages the install atomically, writes the SDDM theme selection, and keeps the current session alive. During setup, it prints the exact plan, asks for confirmation and sudo, installs end to end, and logs the run. diff --git a/docs/nix.md b/docs/nix.md new file mode 100644 index 0000000..97b20d1 --- /dev/null +++ b/docs/nix.md @@ -0,0 +1,32 @@ +# NixOS + +Use the theme as a flake: + +```nix +{ + inputs = { + thyx.url = "github:rccyx/thyx"; + }; + + outputs = { nixpkgs, thyx, ... }: { + nixosConfigurations.host = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + + modules = [ + thyx.nixosModules.default + + { + services.displayManager.sddm.thyx.enable = true; + services.displayManager.sddm.wayland.enable = true; + } + ]; + }; + }; +} +``` + +Then rebuild. + +```bash +sudo nixos-rebuild switch --flake .#host +``` diff --git a/scripts/install b/scripts/install index 23209a9..f7f0fe8 100755 --- a/scripts/install +++ b/scripts/install @@ -103,6 +103,7 @@ main() { _thyx_parse_args "$@" _thyx_setup_log _thyx_validate_repo_tree "${THYX_REPO_DIR}" + [ "$(_thyx_os_field ID || true)" != "nixos" ] || _thyx_die "NixOS install is declarative; use docs/nix.md. The uninstaller is not supported on NixOS." _thyx_prepare_runtime_manifest "${script_dir}" >/dev/null _thyx_print_install_plan From ea07b054af18a27d5852ec7fa8820920ebbc7735 Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 12:28:10 +0100 Subject: [PATCH 04/10] update flake --- flake.nix | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index a0e06c4..fb138b8 100644 --- a/flake.nix +++ b/flake.nix @@ -24,9 +24,41 @@ thyx = self.packages.${system}.default; }); + checks = forAllSystems (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + package = self.packages.${system}.default; + + moduleEval = nixpkgs.lib.nixosSystem { + inherit system; + + modules = [ + self.nixosModules.default + + { + services.displayManager.sddm.thyx.enable = true; + services.displayManager.sddm.wayland.enable = true; + } + ]; + }; + in + { + package = package; + + nixos-module = pkgs.runCommand "thyx-nixos-module-check" { } '' + test "${moduleEval.config.services.displayManager.sddm.theme}" = "thyx" + test -e "${package}/share/sddm/themes/thyx/metadata.desktop" + test -e "${package}/share/sddm/themes/thyx/theme.conf" + test -e "${package}/share/sddm/themes/thyx/src/Main.qml" + test -e "${package}/share/fonts/truetype/thyx/PlusJakartaSans-VariableFont_wght.ttf" + + touch "$out" + ''; + }); + nixosModules = { default = import ./module.nix; thyx = self.nixosModules.default; }; }; -} +} \ No newline at end of file From 9e5917806489075e261bdbd23397083df1d3594c Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 12:36:29 +0100 Subject: [PATCH 05/10] test nix in ci --- .github/workflows/ci.yml | 7 ++- .github/workflows/on-workflow-call-nix.yml | 56 +++++++++++++++++++++ flake.nix | 57 ++++++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/on-workflow-call-nix.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 411dad1..6fefe43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,12 @@ jobs: if: needs.changes.outputs.non_docs == 'true' uses: ./.github/workflows/on-workflow-call-lint.yml - smoke-test: + nix-smoke: + needs: changes + if: needs.changes.outputs.non_docs == 'true' + uses: ./.github/workflows/on-workflow-call-nix.yml + + distro-smoke: needs: - shellcheck - format diff --git a/.github/workflows/on-workflow-call-nix.yml b/.github/workflows/on-workflow-call-nix.yml new file mode 100644 index 0000000..590dece --- /dev/null +++ b/.github/workflows/on-workflow-call-nix.yml @@ -0,0 +1,56 @@ +name: nix + +on: + workflow_call: + +permissions: + contents: read + +jobs: + nix: + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: install nix + uses: cachix/install-nix-action@v31 + with: + github_access_token: ${{ github.token }} + enable_kvm: true + extra_nix_config: | + system-features = nixos-test benchmark big-parallel kvm + + - name: flake check + run: nix flake check --print-build-logs + + - name: build package + run: nix build .#thyx --print-build-logs + + - name: nixos vm smoke + run: nix build .#checks.x86_64-linux.nixos-vm --print-build-logs + + - name: verify package layout + run: | + set -euo pipefail + + nix build .#thyx --print-build-logs + + out="$(readlink -f result)" + + test -f "${out}/share/sddm/themes/thyx/metadata.desktop" + test -f "${out}/share/sddm/themes/thyx/theme.conf" + test -f "${out}/share/sddm/themes/thyx/src/Main.qml" + + test -d "${out}/share/sddm/themes/thyx/backgrounds" + test -d "${out}/share/sddm/themes/thyx/icons" + test -d "${out}/share/sddm/themes/thyx/presets" + test -d "${out}/share/sddm/themes/thyx/src" + + test -f "${out}/share/fonts/truetype/thyx/PlusJakartaSans-VariableFont_wght.ttf" + test -f "${out}/share/fonts/truetype/thyx/PlusJakartaSans-Italic-VariableFont_wght.ttf" diff --git a/flake.nix b/flake.nix index fb138b8..014ca38 100644 --- a/flake.nix +++ b/flake.nix @@ -54,6 +54,63 @@ touch "$out" ''; + + nixos-vm = pkgs.testers.runNixOSTest { + name = "thyx-nixos-smoke"; + + nodes.machine = { pkgs, ... }: { + imports = [ + self.nixosModules.default + ]; + + services.displayManager.sddm.thyx.enable = true; + services.displayManager.sddm.wayland.enable = true; + + environment.systemPackages = with pkgs; [ + dbus + xvfb-run + ]; + + system.stateVersion = "25.11"; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + + machine.succeed("test -f /run/current-system/sw/share/sddm/themes/thyx/metadata.desktop") + machine.succeed("test -f /run/current-system/sw/share/sddm/themes/thyx/theme.conf") + machine.succeed("test -f /run/current-system/sw/share/sddm/themes/thyx/src/Main.qml") + machine.succeed("test -f /run/current-system/sw/share/sddm/themes/thyx/backgrounds/cinder.mp4") + machine.succeed("test -f /run/current-system/sw/share/sddm/themes/thyx/presets/cinder.conf") + + machine.succeed("test -f /run/current-system/sw/share/fonts/truetype/thyx/PlusJakartaSans-VariableFont_wght.ttf") + machine.succeed("test -f /run/current-system/sw/share/fonts/truetype/thyx/PlusJakartaSans-Italic-VariableFont_wght.ttf") + + machine.succeed("grep -q '^Current=thyx$' /etc/sddm.conf.d/00-nixos.conf") + machine.succeed("grep -q '^ThemeDir=/run/current-system/sw/share/sddm/themes$' /etc/sddm.conf.d/00-nixos.conf") + + machine.succeed("command -v sddm") + machine.succeed("command -v sddm-greeter-qt6 || command -v sddm-greeter") + + machine.succeed(""" + set -euo pipefail + + greeter="$(command -v sddm-greeter-qt6 || command -v sddm-greeter)" + + set +e + xvfb-run -a -s "-screen 0 1280x720x24" \ + timeout 8s \ + dbus-run-session -- \ + env QT_QPA_PLATFORM=xcb \ + "$greeter" --test-mode --theme /run/current-system/sw/share/sddm/themes/thyx + + code="$?" + set -e + + [ "$code" -eq 0 ] || [ "$code" -eq 124 ] + """) + ''; + }; }); nixosModules = { From 4d5f91d7ce8c61756cdd2f31539337465d1fbbd9 Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 12:38:52 +0100 Subject: [PATCH 06/10] ci: isolate nix --- .github/workflows/ci.yml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fefe43..e4e057b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,29 +17,29 @@ jobs: changes: uses: ./.github/workflows/on-workflow-call-check-changes.yml - shellcheck: - needs: changes - if: needs.changes.outputs.non_docs == 'true' - uses: ./.github/workflows/on-workflow-call-shell-check.yml + # shellcheck: + # needs: changes + # if: needs.changes.outputs.non_docs == 'true' + # uses: ./.github/workflows/on-workflow-call-shell-check.yml - format: - needs: changes - if: needs.changes.outputs.non_docs == 'true' - uses: ./.github/workflows/on-workflow-call-format.yml + # format: + # needs: changes + # if: needs.changes.outputs.non_docs == 'true' + # uses: ./.github/workflows/on-workflow-call-format.yml - lint: - needs: changes - if: needs.changes.outputs.non_docs == 'true' - uses: ./.github/workflows/on-workflow-call-lint.yml + # lint: + # needs: changes + # if: needs.changes.outputs.non_docs == 'true' + # uses: ./.github/workflows/on-workflow-call-lint.yml nix-smoke: needs: changes if: needs.changes.outputs.non_docs == 'true' uses: ./.github/workflows/on-workflow-call-nix.yml - distro-smoke: - needs: - - shellcheck - - format - - lint - uses: ./.github/workflows/on-workflow-call-distro-smoke.yml + # distro-smoke: + # needs: + # - shellcheck + # - format + # - lint + # uses: ./.github/workflows/on-workflow-call-distro-smoke.yml From 755742916281d2bc765ec838449f4e31e49a3072 Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 12:48:08 +0100 Subject: [PATCH 07/10] remove the redundat font check --- flake.nix | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/flake.nix b/flake.nix index 014ca38..506bb59 100644 --- a/flake.nix +++ b/flake.nix @@ -50,7 +50,10 @@ test -e "${package}/share/sddm/themes/thyx/metadata.desktop" test -e "${package}/share/sddm/themes/thyx/theme.conf" test -e "${package}/share/sddm/themes/thyx/src/Main.qml" + test -e "${package}/share/sddm/themes/thyx/backgrounds/cinder.mp4" + test -e "${package}/share/sddm/themes/thyx/presets/cinder.conf" test -e "${package}/share/fonts/truetype/thyx/PlusJakartaSans-VariableFont_wght.ttf" + test -e "${package}/share/fonts/truetype/thyx/PlusJakartaSans-Italic-VariableFont_wght.ttf" touch "$out" ''; @@ -58,7 +61,7 @@ nixos-vm = pkgs.testers.runNixOSTest { name = "thyx-nixos-smoke"; - nodes.machine = { pkgs, ... }: { + nodes.machine = { ... }: { imports = [ self.nixosModules.default ]; @@ -66,11 +69,6 @@ services.displayManager.sddm.thyx.enable = true; services.displayManager.sddm.wayland.enable = true; - environment.systemPackages = with pkgs; [ - dbus - xvfb-run - ]; - system.stateVersion = "25.11"; }; @@ -83,32 +81,15 @@ machine.succeed("test -f /run/current-system/sw/share/sddm/themes/thyx/backgrounds/cinder.mp4") machine.succeed("test -f /run/current-system/sw/share/sddm/themes/thyx/presets/cinder.conf") - machine.succeed("test -f /run/current-system/sw/share/fonts/truetype/thyx/PlusJakartaSans-VariableFont_wght.ttf") - machine.succeed("test -f /run/current-system/sw/share/fonts/truetype/thyx/PlusJakartaSans-Italic-VariableFont_wght.ttf") - machine.succeed("grep -q '^Current=thyx$' /etc/sddm.conf.d/00-nixos.conf") machine.succeed("grep -q '^ThemeDir=/run/current-system/sw/share/sddm/themes$' /etc/sddm.conf.d/00-nixos.conf") machine.succeed("command -v sddm") machine.succeed("command -v sddm-greeter-qt6 || command -v sddm-greeter") - machine.succeed(""" - set -euo pipefail - - greeter="$(command -v sddm-greeter-qt6 || command -v sddm-greeter)" - - set +e - xvfb-run -a -s "-screen 0 1280x720x24" \ - timeout 8s \ - dbus-run-session -- \ - env QT_QPA_PLATFORM=xcb \ - "$greeter" --test-mode --theme /run/current-system/sw/share/sddm/themes/thyx - - code="$?" - set -e - - [ "$code" -eq 0 ] || [ "$code" -eq 124 ] - """) + machine.wait_until_succeeds("systemctl is-active display-manager.service") + machine.wait_until_succeeds("journalctl -b --no-pager | grep -F 'Loading theme configuration from \"/run/current-system/sw/share/sddm/themes/thyx/theme.conf\"'") + machine.wait_until_succeeds("journalctl -b --no-pager | grep -F 'Loading file:///run/current-system/sw/share/sddm/themes/thyx/src/Main.qml'") ''; }; }); From 1e82c5ef58fedd2b6be1971ad4326b23d223353c Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 12:51:26 +0100 Subject: [PATCH 08/10] ci: run with nix now --- .github/workflows/ci.yml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4e057b..6fefe43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,29 +17,29 @@ jobs: changes: uses: ./.github/workflows/on-workflow-call-check-changes.yml - # shellcheck: - # needs: changes - # if: needs.changes.outputs.non_docs == 'true' - # uses: ./.github/workflows/on-workflow-call-shell-check.yml + shellcheck: + needs: changes + if: needs.changes.outputs.non_docs == 'true' + uses: ./.github/workflows/on-workflow-call-shell-check.yml - # format: - # needs: changes - # if: needs.changes.outputs.non_docs == 'true' - # uses: ./.github/workflows/on-workflow-call-format.yml + format: + needs: changes + if: needs.changes.outputs.non_docs == 'true' + uses: ./.github/workflows/on-workflow-call-format.yml - # lint: - # needs: changes - # if: needs.changes.outputs.non_docs == 'true' - # uses: ./.github/workflows/on-workflow-call-lint.yml + lint: + needs: changes + if: needs.changes.outputs.non_docs == 'true' + uses: ./.github/workflows/on-workflow-call-lint.yml nix-smoke: needs: changes if: needs.changes.outputs.non_docs == 'true' uses: ./.github/workflows/on-workflow-call-nix.yml - # distro-smoke: - # needs: - # - shellcheck - # - format - # - lint - # uses: ./.github/workflows/on-workflow-call-distro-smoke.yml + distro-smoke: + needs: + - shellcheck + - format + - lint + uses: ./.github/workflows/on-workflow-call-distro-smoke.yml From b439a25318625bbc7db74812f8745ba1c1f4c53d Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 13:07:45 +0100 Subject: [PATCH 09/10] run nix & distros in parallel --- .github/workflows/ci.yml | 6 ++++-- README.md | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fefe43..71fa13b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,8 +33,10 @@ jobs: uses: ./.github/workflows/on-workflow-call-lint.yml nix-smoke: - needs: changes - if: needs.changes.outputs.non_docs == 'true' + needs: + - shellcheck + - format + - lint uses: ./.github/workflows/on-workflow-call-nix.yml distro-smoke: diff --git a/README.md b/README.md index 28bd821..5ecac13 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ bash ./scripts/install --yes ``` > [!IMPORTANT] -> Using NixOS? read [docs/nix.md](./docs/nix.md). Don't run those commands: +> Using NixOS? It's supported, just read [docs/nix.md](./docs/nix.md). Don't run those commands: The installer is local, explicit, and idempotent. It validates the theme tree, installs missing runtime packages, checks required commands, stages the install atomically, writes the SDDM theme selection, and keeps the current session alive. From a63cdd1121eeb39598527269193e0a613d059488 Mon Sep 17 00:00:00 2001 From: rccyx Date: Sun, 21 Jun 2026 13:16:56 +0100 Subject: [PATCH 10/10] nix lock file --- flake.lock | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 flake.lock diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..0ee7307 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1781577229, + "narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "567a49d1913ce81ac6e9582e3553dd90a955875f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +}