push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,193 @@
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Lily Foster <lily@lily.flowers>
# Portions of this code are adapted from nixos-cosmic
# https://github.com/lilyinstarlight/nixos-cosmic
{
config,
lib,
pkgs,
utils,
...
}:
let
cfg = config.services.desktopManager.cosmic;
notExcluded = pkg: utils.disablePackageByName pkg config.environment.cosmic.excludePackages;
excludedCorePkgs = lib.lists.intersectLists corePkgs config.environment.cosmic.excludePackages;
# **ONLY ADD PACKAGES WITHOUT WHICH COSMIC CRASHES, NOTHING ELSE**
corePkgs =
with pkgs;
[
cosmic-applets
cosmic-applibrary
cosmic-bg
cosmic-comp
cosmic-files
config.services.displayManager.cosmic-greeter.package
cosmic-idle
cosmic-initial-setup
cosmic-launcher
cosmic-notifications
cosmic-osd
cosmic-panel
cosmic-session
cosmic-settings
cosmic-settings-daemon
cosmic-workspaces-epoch
]
++ lib.optionals cfg.xwayland.enable [
# Why would you want to enable XWayland but exclude the package
# providing XWayland support? Doesn't make sense. Add `xwayland` to the
# `corePkgs` list.
xwayland
];
in
{
meta.maintainers = lib.teams.cosmic.members;
options = {
services.desktopManager.cosmic = {
enable = lib.mkEnableOption "COSMIC desktop environment";
showExcludedPkgsWarning = lib.mkEnableOption "the warning for excluding core packages" // {
default = true;
};
xwayland.enable = lib.mkEnableOption "Xwayland support for the COSMIC compositor" // {
default = true;
};
};
environment.cosmic.excludePackages = lib.mkOption {
description = "List of packages to exclude from the COSMIC environment.";
type = lib.types.listOf lib.types.package;
default = [ ];
example = lib.literalExpression "[ pkgs.cosmic-player ]";
};
};
config = lib.mkIf cfg.enable {
# Environment packages
environment.pathsToLink = [
"/share/backgrounds"
"/share/cosmic"
"/share/cosmic-layouts"
"/share/cosmic-themes"
];
environment.systemPackages = utils.removePackagesByName (
corePkgs
++ (
with pkgs;
[
adwaita-icon-theme
alsa-utils
cosmic-edit
cosmic-icons
cosmic-player
cosmic-randr
cosmic-screenshot
cosmic-term
cosmic-wallpapers
hicolor-icon-theme
playerctl
pop-icon-theme
pop-launcher
xdg-user-dirs
]
++ lib.optionals config.services.flatpak.enable [
# User may have Flatpaks enabled but might not want the `cosmic-store` package.
cosmic-store
]
)
) config.environment.cosmic.excludePackages;
# Distro-wide defaults for graphical sessions
services.graphical-desktop.enable = true;
xdg = {
# Required for cosmic-osd
sounds.enable = true;
icons.fallbackCursorThemes = lib.mkDefault [ "Cosmic" ];
portal = {
enable = true;
extraPortals = with pkgs; [
xdg-desktop-portal-cosmic
xdg-desktop-portal-gtk
];
configPackages = lib.mkDefault [ pkgs.xdg-desktop-portal-cosmic ];
};
};
systemd = {
packages = [ pkgs.cosmic-session ];
user.targets = {
# TODO: remove when upstream has XDG autostart support
cosmic-session = {
wants = [ "xdg-desktop-autostart.target" ];
before = [ "xdg-desktop-autostart.target" ];
};
};
};
fonts.packages = with pkgs; [
fira
noto-fonts
open-sans
];
# Required options for the COSMIC DE
environment.sessionVariables.X11_BASE_RULES_XML = "${config.services.xserver.xkb.dir}/rules/base.xml";
environment.sessionVariables.X11_EXTRA_RULES_XML = "${config.services.xserver.xkb.dir}/rules/base.extras.xml";
programs.dconf.enable = true;
programs.dconf.packages = [ pkgs.cosmic-session ];
security.polkit.enable = true;
security.rtkit.enable = true;
services.accounts-daemon.enable = true;
services.displayManager.sessionPackages = [ pkgs.cosmic-session ];
services.libinput.enable = true;
services.upower.enable = true;
# Required for screen locker
security.pam.services.cosmic-greeter = { };
# geoclue2 stuff
services.geoclue2.enable = true;
# We _do_ use the demo agent in the `cosmic-settings-daemon` package,
# but this option also creates a systemd service that conflicts with the
# `cosmic-settings-daemon` package's geoclue2 agent. Therefore, disable it.
services.geoclue2.enableDemoAgent = false;
# As mentioned above, we do use the demo agent. And it needs to be
# whitelisted, otherwise it doesn't run.
services.geoclue2.whitelistedAgents = [ "geoclue-demo-agent" ]; # whitelist our own geoclue2 agent o
# Good to have defaults
hardware.bluetooth.enable = lib.mkDefault true;
networking.networkmanager.enable = lib.mkDefault true;
services.acpid.enable = lib.mkDefault true;
services.avahi.enable = lib.mkDefault true;
services.gnome.gnome-keyring.enable = lib.mkDefault true;
services.gvfs.enable = lib.mkDefault true;
services.orca.enable = lib.mkDefault (notExcluded pkgs.orca);
services.power-profiles-daemon.enable = lib.mkDefault (
!config.hardware.system76.power-daemon.enable
);
warnings = lib.optionals (cfg.showExcludedPkgsWarning && excludedCorePkgs != [ ]) [
''
The `environment.cosmic.excludePackages` option was used to exclude some
packages from the environment which also includes some packages that the
maintainers of the COSMIC DE deem necessary for the COSMIC DE to start
and initialize. Excluding said packages creates a high probability that
the COSMIC DE will fail to initialize properly, or completely. This is an
unsupported use case. If this was not intentional, please assign an empty
list to the `environment.cosmic.excludePackages` option. If you want to
exclude non-essential packages, please look at the NixOS module for the
COSMIC DE and look for the essential packages in the `corePkgs` list.
You can stop this warning from appearing by setting the option
`services.desktopManager.cosmic.showExcludedPkgsWarning` to `false`.
''
];
};
}

View File

@@ -0,0 +1,177 @@
# GNOME Desktop {#chap-gnome}
GNOME provides a simple, yet full-featured desktop environment with a focus on productivity. Its Mutter compositor supports both Wayland and X server, and the GNOME Shell user interface is fully customizable by extensions.
## Enabling GNOME {#sec-gnome-enable}
All of the core apps, optional apps, games, and core developer tools from GNOME are available.
To enable the GNOME desktop use:
```nix
{
services.desktopManager.gnome.enable = true;
services.displayManager.gdm.enable = true;
}
```
::: {.note}
While it is not strictly necessary to use GDM as the display manager with GNOME, it is recommended, as some features such as screen lock [might not work](#sec-gnome-faq-can-i-use-lightdm-with-gnome) without it.
:::
The default applications used in NixOS are very minimal, inspired by the defaults used in [gnome-build-meta](https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/48.0/elements/core/meta-gnome-core-apps.bst).
### GNOME without the apps {#sec-gnome-without-the-apps}
If youd like to only use the GNOME desktop and not the apps, you can disable them with:
```nix
{ services.gnome.core-apps.enable = false; }
```
and none of them will be installed.
If youd only like to omit a subset of the core utilities, you can use
[](#opt-environment.gnome.excludePackages).
Note that this mechanism can only exclude core utilities, games and core developer tools.
### Disabling GNOME services {#sec-gnome-disabling-services}
It is also possible to disable many of the [core services](https://github.com/NixOS/nixpkgs/blob/b8ec4fd2a4edc4e30d02ba7b1a2cc1358f3db1d5/nixos/modules/services/x11/desktop-managers/gnome.nix#L329-L348). For example, if you do not need indexing files, you can disable TinySPARQL with:
```nix
{
services.gnome.localsearch.enable = false;
services.gnome.tinysparql.enable = false;
}
```
Note, however, that doing so is not supported and might break some applications. Notably, GNOME Music cannot work without TinySPARQL.
### GNOME games {#sec-gnome-games}
You can install all of the GNOME games with:
```nix
{ services.gnome.games.enable = true; }
```
### GNOME core developer tools {#sec-gnome-core-developer-tools}
You can install GNOME core developer tools with:
```nix
{ services.gnome.core-developer-tools.enable = true; }
```
## Enabling GNOME Flashback {#sec-gnome-enable-flashback}
GNOME Flashback provides a desktop environment based on the classic GNOME 2 architecture. You can enable the default GNOME Flashback session, which uses the Metacity window manager, with:
```nix
{ services.desktopManager.gnome.flashback.enableMetacity = true; }
```
It is also possible to create custom sessions that replace Metacity with a different window manager using [](#opt-services.desktopManager.gnome.flashback.customSessions).
The following example uses `xmonad` window manager:
```nix
{
services.desktopManager.gnome.flashback.customSessions = [
{
wmName = "xmonad";
wmLabel = "XMonad";
wmCommand = "${pkgs.haskellPackages.xmonad}/bin/xmonad";
enableGnomePanel = false;
}
];
}
```
## Icons and GTK Themes {#sec-gnome-icons-and-gtk-themes}
Icon themes and GTK themes dont require any special option to install in NixOS.
You can add them to [](#opt-environment.systemPackages) and switch to them with GNOME Tweaks.
If youd like to do this manually in dconf, change the values of the following keys:
```
/org/gnome/desktop/interface/gtk-theme
/org/gnome/desktop/interface/icon-theme
```
in `dconf-editor`
## Shell Extensions {#sec-gnome-shell-extensions}
Most Shell extensions are packaged under the `gnomeExtensions` attribute.
Some packages that include Shell extensions, like `gpaste`, dont have their extension decoupled under this attribute.
You can install them like any other package:
```nix
{
environment.systemPackages = [
pkgs.gnomeExtensions.dash-to-dock
pkgs.gnomeExtensions.gsconnect
pkgs.gnomeExtensions.mpris-indicator-button
];
}
```
Unfortunately, we lack a way for these to be managed in a completely declarative way.
So you have to enable them manually with an Extensions application.
It is possible to use a [GSettings override](#sec-gnome-gsettings-overrides) for this on `org.gnome.shell.enabled-extensions`, but that will only influence the default value.
## GSettings Overrides {#sec-gnome-gsettings-overrides}
Majority of software building on the GNOME platform use GLibs [GSettings](https://developer.gnome.org/gio/unstable/GSettings.html) system to manage runtime configuration. For our purposes, the system consists of XML schemas describing the individual configuration options, stored in the package, and a settings backend, where the values of the settings are stored. On NixOS, like on most Linux distributions, dconf database is used as the backend.
[GSettings vendor overrides](https://developer.gnome.org/gio/unstable/GSettings.html#id-1.4.19.2.9.25) can be used to adjust the default values for settings of the GNOME desktop and apps by replacing the default values specified in the XML schemas. Using overrides will allow you to pre-seed user settings before you even start the session.
::: {.warning}
Overrides really only change the default values for GSettings keys so if you or an application changes the setting value, the value set by the override will be ignored. Until [NixOSs dconf module implements changing values](https://github.com/NixOS/nixpkgs/issues/54150), you will either need to keep that in mind and clear the setting from the backend using `dconf reset` command when that happens, or use the [module from home-manager](https://nix-community.github.io/home-manager/options.html#opt-dconf.settings).
:::
You can override the default GSettings values using the
[](#opt-services.desktopManager.gnome.extraGSettingsOverrides) option.
Take note that whatever packages you want to override GSettings for, you need to add them to
[](#opt-services.desktopManager.gnome.extraGSettingsOverridePackages).
You can use `dconf-editor` tool to explore which GSettings you can set.
### Example {#sec-gnome-gsettings-overrides-example}
```nix
{
services.desktopManager.gnome = {
extraGSettingsOverrides = ''
# Change default background
[org.gnome.desktop.background]
picture-uri='file://${pkgs.nixos-artwork.wallpapers.mosaic-blue.gnomeFilePath}'
# Favorite apps in gnome-shell
[org.gnome.shell]
favorite-apps=['org.gnome.Console.desktop', 'org.gnome.Nautilus.desktop']
'';
extraGSettingsOverridePackages = [
pkgs.gsettings-desktop-schemas # for org.gnome.desktop
pkgs.gnome-shell # for org.gnome.shell
];
};
}
```
## Frequently Asked Questions {#sec-gnome-faq}
### Can I use LightDM with GNOME? {#sec-gnome-faq-can-i-use-lightdm-with-gnome}
Yes you can, and any other display-manager in NixOS.
However, it doesnt work correctly for the Wayland session of GNOME Shell yet, and
wont be able to lock your screen.
See [this issue.](https://github.com/NixOS/nixpkgs/issues/56342)

View File

@@ -0,0 +1,551 @@
{
config,
lib,
pkgs,
utils,
...
}:
let
inherit (lib)
mkOption
types
mkDefault
mkEnableOption
literalExpression
;
cfg = config.services.desktopManager.gnome;
serviceCfg = config.services.gnome;
# Prioritize nautilus by default when opening directories
mimeAppsList = pkgs.writeTextFile {
name = "gnome-mimeapps";
destination = "/share/applications/mimeapps.list";
text = ''
[Default Applications]
inode/directory=nautilus.desktop;org.gnome.Nautilus.desktop
'';
};
defaultFavoriteAppsOverride = ''
[org.gnome.shell]
favorite-apps=[ 'org.gnome.Epiphany.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop' ]
'';
nixos-background-light = pkgs.nixos-artwork.wallpapers.simple-blue;
nixos-background-dark = pkgs.nixos-artwork.wallpapers.simple-dark-gray;
# TODO: Having https://github.com/NixOS/nixpkgs/issues/54150 would supersede this
nixos-gsettings-desktop-schemas = pkgs.gnome.nixos-gsettings-overrides.override {
inherit (cfg) extraGSettingsOverrides extraGSettingsOverridePackages favoriteAppsOverride;
inherit flashbackEnabled nixos-background-dark nixos-background-light;
};
nixos-background-info = pkgs.writeTextFile {
name = "nixos-background-info";
text = ''
<?xml version="1.0"?>
<!DOCTYPE wallpapers SYSTEM "gnome-wp-list.dtd">
<wallpapers>
<wallpaper deleted="false">
<name>Blobs</name>
<filename>${nixos-background-light.gnomeFilePath}</filename>
<filename-dark>${nixos-background-dark.gnomeFilePath}</filename-dark>
<options>zoom</options>
<shade_type>solid</shade_type>
<pcolor>#3a4ba0</pcolor>
<scolor>#2f302f</scolor>
</wallpaper>
</wallpapers>
'';
destination = "/share/gnome-background-properties/nixos.xml";
};
flashbackEnabled = cfg.flashback.enableMetacity || lib.length cfg.flashback.customSessions > 0;
flashbackWms =
lib.optional cfg.flashback.enableMetacity {
wmName = "metacity";
wmLabel = "Metacity";
wmCommand = "${pkgs.metacity}/bin/metacity";
enableGnomePanel = true;
}
++ cfg.flashback.customSessions;
notExcluded =
pkg: mkDefault (utils.disablePackageByName pkg config.environment.gnome.excludePackages);
in
{
meta = {
doc = ./gnome.md;
maintainers = lib.teams.gnome.members;
};
imports = [
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "gnome" "enable" ]
[ "services" "desktopManager" "gnome" "enable" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "gnome" "extraGSettingsOverrides" ]
[ "services" "desktopManager" "gnome" "extraGSettingsOverrides" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "gnome" "extraGSettingsOverridePackages" ]
[ "services" "desktopManager" "gnome" "extraGSettingsOverridePackages" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "gnome" "debug" ]
[ "services" "desktopManager" "gnome" "debug" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "gnome" "sessionPath" ]
[ "services" "desktopManager" "gnome" "sessionPath" ]
)
# flashback options
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "gnome" "flashback" "customSessions" ]
[ "services" "desktopManager" "gnome" "flashback" "customSessions" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "gnome" "flashback" "enableMetacity" ]
[ "services" "desktopManager" "gnome" "flashback" "enableMetacity" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "gnome" "flashback" "panelModulePackages" ]
[ "services" "desktopManager" "gnome" "flashback" "panelModulePackages" ]
)
(lib.mkRenamedOptionModule
[ "services" "gnome" "core-utilities" "enable" ]
[ "services" "gnome" "core-apps" "enable" ]
)
];
options = {
services.gnome = {
core-os-services.enable = mkEnableOption "essential services for GNOME3";
core-shell.enable = mkEnableOption "GNOME Shell services";
core-apps.enable = mkEnableOption "GNOME core apps";
core-developer-tools.enable = mkEnableOption "GNOME core developer tools";
games.enable = mkEnableOption "GNOME games";
};
services.desktopManager.gnome = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable GNOME desktop manager.";
};
sessionPath = mkOption {
default = [ ];
type = types.listOf types.package;
example = literalExpression "[ pkgs.gpaste ]";
description = ''
Additional list of packages to be added to the session search path.
Useful for GNOME Shell extensions or GSettings-conditional autostart.
Note that this should be a last resort; patching the package is preferred (see GPaste).
'';
};
favoriteAppsOverride = mkOption {
internal = true; # this is messy
default = defaultFavoriteAppsOverride;
type = types.lines;
example = literalExpression ''
'''
[org.gnome.shell]
favorite-apps=[ 'firefox.desktop', 'org.gnome.Calendar.desktop' ]
'''
'';
description = "List of desktop files to put as favorite apps into pkgs.gnome-shell. These need to be installed somehow globally.";
};
extraGSettingsOverrides = mkOption {
default = "";
type = types.lines;
description = "Additional gsettings overrides.";
};
extraGSettingsOverridePackages = mkOption {
default = [ ];
type = types.listOf types.path;
description = "List of packages for which gsettings are overridden.";
};
debug = mkEnableOption "pkgs.gnome-session debug messages";
flashback = {
enableMetacity = mkEnableOption "the standard GNOME Flashback session with Metacity";
customSessions = mkOption {
type = types.listOf (
types.submodule {
options = {
wmName = mkOption {
type = types.strMatching "[a-zA-Z0-9_-]+";
description = "A unique identifier for the window manager.";
example = "xmonad";
};
wmLabel = mkOption {
type = types.str;
description = "The name of the window manager to show in the session chooser.";
example = "XMonad";
};
wmCommand = mkOption {
type = types.str;
description = "The executable of the window manager to use.";
example = literalExpression ''"''${pkgs.haskellPackages.xmonad}/bin/xmonad"'';
};
enableGnomePanel = mkOption {
type = types.bool;
default = true;
example = false;
description = "Whether to enable the GNOME panel in this session.";
};
};
}
);
default = [ ];
description = "Other GNOME Flashback sessions to enable.";
};
panelModulePackages = mkOption {
default = [ pkgs.gnome-applets ];
defaultText = literalExpression "[ pkgs.gnome-applets ]";
type = types.listOf types.package;
description = ''
Packages containing modules that should be made available to `pkgs.gnome-panel` (usually for applets).
If you're packaging something to use here, please install the modules in `$out/lib/gnome-panel/modules`.
'';
};
};
};
environment.gnome.excludePackages = mkOption {
default = [ ];
example = literalExpression "[ pkgs.totem ]";
type = types.listOf types.package;
description = "Which packages gnome should exclude from the default environment";
};
};
config = lib.mkMerge [
(lib.mkIf (cfg.enable || flashbackEnabled) {
# Seed our configuration into nixos-generate-config
system.nixos-generate-config.desktopConfiguration = [
''
# Enable the GNOME Desktop Environment.
services.displayManager.gdm.enable = true;
services.desktopManager.gnome.enable = true;
''
];
services.gnome.core-os-services.enable = true;
services.gnome.core-shell.enable = true;
services.gnome.core-apps.enable = mkDefault true;
services.displayManager.sessionPackages = [ pkgs.gnome-session.sessions ];
environment.extraInit = ''
${lib.concatMapStrings (p: ''
if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
fi
if [ -d "${p}/lib/girepository-1.0" ]; then
export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
fi
'') cfg.sessionPath}
'';
environment.systemPackages = cfg.sessionPath;
environment.sessionVariables.GNOME_SESSION_DEBUG = lib.mkIf cfg.debug "1";
# Override GSettings schemas
environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
})
(lib.mkIf flashbackEnabled {
services.displayManager.sessionPackages =
let
wmNames = map (wm: wm.wmName) flashbackWms;
namesAreUnique = lib.unique wmNames == wmNames;
in
assert (lib.assertMsg namesAreUnique "Flashback WM names must be unique.");
map (
wm:
pkgs.gnome-flashback.mkSessionForWm {
inherit (wm) wmName wmLabel wmCommand;
}
) flashbackWms;
security.pam.services.gnome-flashback = {
enableGnomeKeyring = true;
};
systemd.packages = [
pkgs.gnome-flashback
]
++ map pkgs.gnome-flashback.mkSystemdTargetForWm flashbackWms;
environment.systemPackages = [
pkgs.gnome-flashback
(pkgs.gnome-panel-with-modules.override {
panelModulePackages = cfg.flashback.panelModulePackages;
})
]
# For /share/applications/${wmName}.desktop
++ (map (
wm: pkgs.gnome-flashback.mkWmApplication { inherit (wm) wmName wmLabel wmCommand; }
) flashbackWms)
# For /share/pkgs.gnome-session/sessions/gnome-flashback-${wmName}.session
++ (map (
wm: pkgs.gnome-flashback.mkGnomeSession { inherit (wm) wmName wmLabel enableGnomePanel; }
) flashbackWms);
})
(lib.mkIf serviceCfg.core-os-services.enable {
hardware.bluetooth.enable = mkDefault true;
programs.dconf.enable = true;
security.polkit.enable = true;
security.rtkit.enable = mkDefault true;
services.accounts-daemon.enable = true;
services.dleyna.enable = mkDefault true;
services.power-profiles-daemon.enable = mkDefault true;
services.gnome.at-spi2-core.enable = true;
services.gnome.evolution-data-server.enable = true;
services.gnome.gnome-keyring.enable = true;
services.gnome.gcr-ssh-agent.enable = mkDefault true;
services.gnome.gnome-online-accounts.enable = mkDefault true;
services.gnome.localsearch.enable = mkDefault true;
services.gnome.tinysparql.enable = mkDefault true;
services.hardware.bolt.enable = mkDefault true;
# TODO: Enable once #177946 is resolved
# services.packagekit.enable = mkDefault true;
services.udisks2.enable = true;
services.upower.enable = config.powerManagement.enable;
services.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
# Explicitly enabled since GNOME will be severely broken without these.
xdg.mime.enable = true;
xdg.icons.enable = true;
xdg.portal.enable = true;
xdg.portal.extraPortals = [
pkgs.xdg-desktop-portal-gnome
pkgs.xdg-desktop-portal-gtk
];
xdg.portal.configPackages = mkDefault [ pkgs.gnome-session ];
networking.networkmanager.enable = mkDefault true;
services.xserver.updateDbusEnvironment = true;
# gnome has a custom alert theme but it still
# inherits from the freedesktop theme.
environment.systemPackages = with pkgs; [
sound-theme-freedesktop
];
# Needed for themes and backgrounds
environment.pathsToLink = [
"/share" # TODO: https://github.com/NixOS/nixpkgs/issues/47173
];
})
(lib.mkIf serviceCfg.core-shell.enable {
services.desktopManager.gnome.sessionPath = [
pkgs.gnome-shell
];
services.colord.enable = mkDefault true;
services.gnome.glib-networking.enable = true;
services.gnome.gnome-browser-connector.enable = mkDefault true;
services.gnome.gnome-initial-setup.enable = mkDefault true;
services.gnome.gnome-remote-desktop.enable = mkDefault true;
services.gnome.gnome-settings-daemon.enable = true;
services.gnome.gnome-user-share.enable = mkDefault true;
services.gnome.rygel.enable = mkDefault true;
services.gvfs.enable = true;
services.system-config-printer.enable = (lib.mkIf config.services.printing.enable (mkDefault true));
systemd.packages = [
pkgs.gnome-session
pkgs.gnome-shell
];
services.udev.packages = [
# Force enable KMS modifiers for devices that require them.
# https://gitlab.gnome.org/GNOME/pkgs.mutter/-/merge_requests/1443
pkgs.mutter
];
services.avahi.enable = mkDefault true;
services.geoclue2.enable = mkDefault true;
services.geoclue2.enableDemoAgent = false; # GNOME has its own geoclue agent
services.geoclue2.appConfig.gnome-datetime-panel = {
isAllowed = true;
isSystem = true;
};
services.geoclue2.appConfig.gnome-color-panel = {
isAllowed = true;
isSystem = true;
};
services.geoclue2.appConfig."org.gnome.Shell" = {
isAllowed = true;
isSystem = true;
};
services.orca.enable = notExcluded pkgs.orca;
fonts.packages = utils.removePackagesByName [
pkgs.adwaita-fonts
] config.environment.gnome.excludePackages;
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/gnome-48/elements/core/meta-gnome-core-shell.bst
environment.systemPackages =
let
mandatoryPackages = [
pkgs.gnome-shell
];
optionalPackages = [
pkgs.adwaita-icon-theme
nixos-background-info
pkgs.gnome-backgrounds
pkgs.gnome-bluetooth
pkgs.gnome-color-manager
pkgs.gnome-control-center
pkgs.gnome-tour # GNOME Shell detects the .desktop file on first log-in.
pkgs.gnome-user-docs
pkgs.glib # for gsettings program
pkgs.gnome-menus
pkgs.gtk3.out # for gtk-launch program
pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
pkgs.xdg-user-dirs-gtk # Used to create the default bookmarks
];
in
mandatoryPackages
++ utils.removePackagesByName optionalPackages config.environment.gnome.excludePackages;
})
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-48/elements/core/meta-gnome-core-apps.bst
(lib.mkIf serviceCfg.core-apps.enable {
environment.systemPackages = utils.removePackagesByName (
[
pkgs.baobab
pkgs.decibels
pkgs.epiphany
pkgs.gnome-text-editor
pkgs.gnome-calculator
pkgs.gnome-calendar
pkgs.gnome-characters
pkgs.gnome-clocks
pkgs.gnome-console
pkgs.gnome-contacts
pkgs.gnome-font-viewer
pkgs.gnome-logs
pkgs.gnome-maps
pkgs.gnome-music
pkgs.gnome-system-monitor
pkgs.gnome-weather
pkgs.loupe
pkgs.nautilus
pkgs.gnome-connections
pkgs.simple-scan
pkgs.snapshot
pkgs.totem
pkgs.yelp
]
++ lib.optionals config.services.flatpak.enable [
# Since PackageKit Nix support is not there yet,
# only install gnome-software if flatpak is enabled.
pkgs.gnome-software
]
) config.environment.gnome.excludePackages;
# Enable default program modules
# Since some of these have a corresponding package, we only
# enable that program module if the package hasn't been excluded
# through `environment.gnome.excludePackages`
programs.evince.enable = notExcluded pkgs.evince;
programs.file-roller.enable = notExcluded pkgs.file-roller;
programs.geary.enable = notExcluded pkgs.geary;
programs.gnome-disks.enable = notExcluded pkgs.gnome-disk-utility;
programs.seahorse.enable = notExcluded pkgs.seahorse;
services.gnome.sushi.enable = notExcluded pkgs.sushi;
# VTE shell integration for gnome-console
programs.bash.vteIntegration = mkDefault true;
programs.zsh.vteIntegration = mkDefault true;
# Let nautilus find extensions
# TODO: Create nautilus-with-extensions package
environment.sessionVariables.NAUTILUS_4_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-4";
# Override default mimeapps for nautilus
environment.sessionVariables.XDG_DATA_DIRS = [ "${mimeAppsList}/share" ];
environment.pathsToLink = [
"/share/nautilus-python/extensions"
];
})
(lib.mkIf serviceCfg.games.enable {
environment.systemPackages = utils.removePackagesByName [
pkgs.aisleriot
pkgs.atomix
pkgs.five-or-more
pkgs.four-in-a-row
pkgs.gnome-2048
pkgs.gnome-chess
pkgs.gnome-klotski
pkgs.gnome-mahjongg
pkgs.gnome-mines
pkgs.gnome-nibbles
pkgs.gnome-robots
pkgs.gnome-sudoku
pkgs.gnome-taquin
pkgs.gnome-tetravex
pkgs.hitori
pkgs.iagno
pkgs.lightsoff
pkgs.quadrapassel
pkgs.swell-foop
pkgs.tali
] config.environment.gnome.excludePackages;
})
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-48/elements/core/meta-gnome-core-developer-tools.bst
(lib.mkIf serviceCfg.core-developer-tools.enable {
environment.systemPackages = utils.removePackagesByName [
pkgs.dconf-editor
pkgs.devhelp
pkgs.d-spy
pkgs.gnome-builder
# boxes would make sense in this option, however
# it doesn't function well enough to be included
# in default configurations.
# https://github.com/NixOS/nixpkgs/issues/60908
# pkgs.gnome-boxes
pkgs.sysprof
] config.environment.gnome.excludePackages;
services.sysprof.enable = notExcluded pkgs.sysprof;
})
];
}

View File

@@ -0,0 +1,296 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.desktopManager.lomiri;
in
{
options.services.desktopManager.lomiri = {
enable = lib.mkEnableOption ''
the Lomiri graphical shell (formerly known as Unity8)
'';
basics = lib.mkOption {
internal = true;
description = ''
Enable basic things for getting Lomiri working.
'';
type = lib.types.bool;
default = config.services.xserver.displayManager.lightdm.greeters.lomiri.enable || cfg.enable;
};
};
config = lib.mkMerge [
# Basics for getting Lomiri to work
(lib.mkIf cfg.basics {
environment = {
# To override the default keyboard layout in Lomiri
etc.${pkgs.lomiri.lomiri.passthru.etcLayoutsFile}.text =
lib.strings.replaceStrings
[ "," ]
[
"\n"
]
config.services.xserver.xkb.layout;
pathsToLink = [
# Data
"/share/locale" # TODO LUITK hardcoded default locale path, fix individual apps to not rely on it
"/share/wallpapers"
];
systemPackages = with pkgs.lomiri; [
lomiri-wallpapers # default + additional wallpaper
suru-icon-theme # basic indicator icons
];
};
# Override GSettings defaults
programs.dconf = {
enable = true;
profiles.user.databases = [
{
settings = {
"com/lomiri/shell/launcher" = {
logo-picture-uri = "file://${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake-white.svg";
home-button-background-color = "#5277C3";
};
};
lockAll = true;
}
];
};
fonts.packages = with pkgs; [
ubuntu-classic # Ubuntu is default font
];
# Xwayland is partly hardcoded in Mir so it can't really be fully turned off, and it must be on PATH for X11 apps *and Lomiri's web browser* to work.
# Until Mir/Lomiri can be properly used without it, force it on so everything behaves as expected.
programs.xwayland.enable = lib.mkForce true;
services.ayatana-indicators = {
enable = true;
packages = (
with pkgs;
[
ayatana-indicator-session # Controls for shutting down etc
]
++ (with lomiri; [
lomiri-indicator-datetime # Clock
])
);
};
})
# Full Lomiri DE
(lib.mkIf cfg.enable {
# We need the basic setup as well
services.desktopManager.lomiri.basics = true;
environment = {
systemPackages =
(with pkgs; [
glib # XDG MIME-related tools identify it as GNOME, add gio for MIME identification to work
libayatana-common
ubports-click
])
++ (with pkgs.lomiri; [
hfd-service
libusermetrics
lomiri
lomiri-calculator-app
lomiri-calendar-app
lomiri-camera-app
lomiri-clock-app
lomiri-content-hub
lomiri-docviewer-app
lomiri-download-manager
lomiri-filemanager-app
lomiri-gallery-app
lomiri-history-service
lomiri-mediaplayer-app
lomiri-music-app
lomiri-polkit-agent
lomiri-schemas # exposes some required dbus interfaces
lomiri-session # wrappers to properly launch the session
lomiri-sounds
lomiri-system-settings
lomiri-telephony-service
lomiri-terminal-app
lomiri-thumbnailer
lomiri-url-dispatcher
mediascanner2 # TODO possibly needs to be kicked off by graphical-session.target
# Qt5 qtwebengine is not secure: https://github.com/NixOS/nixpkgs/pull/435067
# morph-browser
# Adding another browser that is known-working until Morph Browser can migrate to Qt6
pkgs.epiphany
qtmir # not having its desktop file for Xwayland available causes any X11 application to crash the session
teleports
]);
};
hardware = {
bluetooth.enable = lib.mkDefault true;
};
networking.networkmanager.enable = lib.mkDefault true;
systemd.packages = with pkgs.lomiri; [
hfd-service
lomiri-download-manager
];
services.dbus.packages = with pkgs.lomiri; [
hfd-service
libusermetrics
lomiri-download-manager
];
services.accounts-daemon.enable = true;
services.udisks2.enable = true;
services.upower.enable = true;
services.geoclue2.enable = true;
services.telepathy.enable = true;
services.ayatana-indicators = {
enable = true;
packages =
(
with pkgs;
[
ayatana-indicator-display
ayatana-indicator-messages
ayatana-indicator-power
]
++ lib.optionals config.hardware.bluetooth.enable [ ayatana-indicator-bluetooth ]
++ lib.optionals (config.services.pulseaudio.enable || config.services.pipewire.pulse.enable) [
ayatana-indicator-sound
]
)
++ (
with pkgs.lomiri;
[ lomiri-telephony-service ]
++ lib.optionals config.networking.networkmanager.enable [ lomiri-indicator-network ]
);
};
services.gnome.evolution-data-server = {
enable = true;
plugins = [
# TODO: lomiri.address-book-service
];
};
services.displayManager = {
defaultSession = lib.mkDefault "lomiri";
sessionPackages = with pkgs.lomiri; [ lomiri-session ];
};
services.xserver = {
enable = lib.mkDefault true;
displayManager.lightdm = {
enable = lib.mkDefault true;
greeters.lomiri.enable = lib.mkDefault true;
};
};
environment.pathsToLink = [
# Configs for inter-app data exchange system
"/share/lomiri-content-hub/peers"
# Configs for inter-app URL requests
"/share/lomiri-url-dispatcher/urls"
# Splash screens & other images for desktop apps launched via lomiri-app-launch
"/share/lomiri-app-launch"
# TODO Try to get maliit stuff working
"/share/maliit/plugins"
# At least the network indicator is still under the unity name, due to leftover Unity-isms
"/share/unity"
# Data
"/share/sounds"
];
systemd.user.services =
let
lomiriService = "lomiri.service";
lomiriServiceNames = [
lomiriService
"lomiri-full-greeter.service"
"lomiri-full-shell.service"
"lomiri-greeter.service"
"lomiri-shell.service"
];
in
{
# Unconditionally run service that collects system-installed URL handlers before LUD
# TODO also run user-installed one?
"lomiri-url-dispatcher-update-system-dir" = {
description = "Lomiri URL dispatcher system directory updater";
wantedBy = [ "lomiri-url-dispatcher.service" ];
before = [ "lomiri-url-dispatcher.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.lomiri.lomiri-url-dispatcher}/libexec/lomiri-url-dispatcher/lomiri-update-directory /run/current-system/sw/share/lomiri-url-dispatcher/urls/";
};
};
"lomiri-polkit-agent" = {
description = "Lomiri Polkit agent";
wantedBy = [ lomiriService ];
after = [ lomiriService ];
partOf = [ lomiriService ];
serviceConfig = {
Type = "simple";
Restart = "always";
ExecStart = "${pkgs.lomiri.lomiri-polkit-agent}/libexec/lomiri-polkit-agent/policykit-agent";
};
};
"mediascanner-2.0" = {
description = "Media Scanner";
wantedBy = lomiriServiceNames;
before = lomiriServiceNames;
partOf = lomiriServiceNames;
serviceConfig = {
Type = "dbus";
BusName = "com.lomiri.MediaScanner2.Daemon";
Restart = "on-failure";
ExecStart = "${lib.getExe pkgs.lomiri.mediascanner2}";
};
};
};
systemd.services = {
"dbus-com.lomiri.UserMetrics" = {
serviceConfig = {
Type = "dbus";
BusName = "com.lomiri.UserMetrics";
User = "usermetrics";
StandardOutput = "syslog";
SyslogIdentifier = "com.lomiri.UserMetrics";
ExecStart = "${pkgs.lomiri.libusermetrics}/libexec/libusermetrics/usermetricsservice";
}
// lib.optionalAttrs (!config.security.apparmor.enable) {
# Due to https://gitlab.com/ubports/development/core/libusermetrics/-/issues/8, auth must be disabled when not using AppArmor, lest the next database usage breaks
Environment = "USERMETRICS_NO_AUTH=1";
};
};
};
users.users.usermetrics = {
group = "usermetrics";
home = "/var/lib/usermetrics";
createHome = true;
isSystemUser = true;
};
users.groups.usermetrics = { };
})
];
meta.maintainers = lib.teams.lomiri.members;
}

View File

@@ -0,0 +1,72 @@
# Pantheon Desktop {#chap-pantheon}
Pantheon is the desktop environment created for the elementary OS distribution. It is written from scratch in Vala, utilizing GNOME technologies with GTK and Granite.
## Enabling Pantheon {#sec-pantheon-enable}
All of Pantheon is working in NixOS and the applications should be available, aside from a few [exceptions](https://github.com/NixOS/nixpkgs/issues/58161). To enable Pantheon, set
```nix
{ services.desktopManager.pantheon.enable = true; }
```
This automatically enables LightDM and Pantheon's LightDM greeter. If you'd like to disable this, set
```nix
{
services.xserver.displayManager.lightdm.greeters.pantheon.enable = false;
services.xserver.displayManager.lightdm.enable = false;
}
```
but please be aware using Pantheon without LightDM as a display manager will break screenlocking from the UI. The NixOS module for Pantheon installs all of Pantheon's default applications. If you'd like to not install Pantheon's apps, set
```nix
{ services.pantheon.apps.enable = false; }
```
You can also use [](#opt-environment.pantheon.excludePackages) to remove any other app (like `elementary-mail`).
## Wingpanel and Switchboard plugins {#sec-pantheon-wingpanel-switchboard}
Wingpanel and Switchboard work differently than they do in other distributions, as far as using plugins. You cannot install a plugin globally (like with {option}`environment.systemPackages`) to start using it. You should instead be using the following options:
- [](#opt-services.desktopManager.pantheon.extraWingpanelIndicators)
- [](#opt-services.desktopManager.pantheon.extraSwitchboardPlugs)
to configure the programs with plugs or indicators.
The difference in NixOS is both these programs are patched to load plugins from a directory that is the value of an environment variable. All of which is controlled in Nix. If you need to configure the particular packages manually you can override the packages like:
```nix
wingpanel-with-indicators.override {
indicators = [ pkgs.some-special-indicator ];
}
```
```nix
switchboard-with-plugs.override { plugs = [ pkgs.some-special-plug ]; }
```
please note that, like how the NixOS options describe these as extra plugins, this would only add to the default plugins included with the programs. If for some reason you'd like to configure which plugins to use exactly, both packages have an argument for this:
```nix
wingpanel-with-indicators.override {
useDefaultIndicators = false;
indicators = specialListOfIndicators;
}
```
```nix
switchboard-with-plugs.override {
useDefaultPlugs = false;
plugs = specialListOfPlugs;
}
```
this could be most useful for testing a particular plug-in in isolation.
## FAQ {#sec-pantheon-faq}
[I have switched from a different desktop and Pantheons theming looks messed up.]{#sec-pantheon-faq-messed-up-theme}
: Open Switchboard and go to: Administration → About → Restore Default Settings → Restore Settings. This will reset any dconf settings to their Pantheon defaults. Note this could reset certain GNOME specific preferences if that desktop was used prior.
[I cannot enable both GNOME and Pantheon.]{#sec-pantheon-faq-gnome-and-pantheon}
: This is a known [issue](https://github.com/NixOS/nixpkgs/issues/64611) and there is no known workaround.
[Does AppCenter work, or is it available?]{#sec-pantheon-faq-appcenter}
: AppCenter is available and the Flatpak backend should work so you can install some Flatpak applications using it. However, due to missing appstream metadata, the Packagekit backend does not function currently. See this [issue](https://github.com/NixOS/nixpkgs/issues/15932).
If you are using Pantheon, AppCenter should be installed by default if you have [Flatpak support](#module-services-flatpak) enabled. If you also wish to add the `appcenter` Flatpak remote:
```ShellSession
$ flatpak remote-add --if-not-exists appcenter https://flatpak.elementary.io/repo.flatpakrepo
```

View File

@@ -0,0 +1,360 @@
{
config,
lib,
utils,
pkgs,
...
}:
with lib;
let
cfg = config.services.desktopManager.pantheon;
serviceCfg = config.services.pantheon;
nixos-gsettings-desktop-schemas = pkgs.pantheon.elementary-gsettings-schemas.override {
extraGSettingsOverridePackages = cfg.extraGSettingsOverridePackages;
extraGSettingsOverrides = cfg.extraGSettingsOverrides;
};
notExcluded = pkg: utils.disablePackageByName pkg config.environment.pantheon.excludePackages;
in
{
meta = {
doc = ./pantheon.md;
maintainers = teams.pantheon.members;
};
imports = [
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "pantheon" ]
[ "services" "desktopManager" "pantheon" ]
)
];
options = {
services.pantheon = {
contractor = {
enable = mkEnableOption "contractor, a desktop-wide extension service used by Pantheon";
};
apps.enable = mkEnableOption "Pantheon default applications";
};
services.desktopManager.pantheon = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the pantheon desktop manager";
};
sessionPath = mkOption {
default = [ ];
type = types.listOf types.package;
example = literalExpression "[ pkgs.gpaste ]";
description = ''
Additional list of packages to be added to the session search path.
Useful for GSettings-conditional autostart.
Note that this should be a last resort; patching the package is preferred (see GPaste).
'';
};
extraWingpanelIndicators = mkOption {
default = null;
type = with types; nullOr (listOf package);
description = "Indicators to add to Wingpanel.";
};
extraSwitchboardPlugs = mkOption {
default = null;
type = with types; nullOr (listOf package);
description = "Plugs to add to Switchboard.";
};
extraGSettingsOverrides = mkOption {
default = "";
type = types.lines;
description = "Additional gsettings overrides.";
};
extraGSettingsOverridePackages = mkOption {
default = [ ];
type = types.listOf types.path;
description = "List of packages for which gsettings are overridden.";
};
debug = mkEnableOption "gnome-session debug messages";
};
environment.pantheon.excludePackages = mkOption {
default = [ ];
example = literalExpression "[ pkgs.pantheon.elementary-camera ]";
type = types.listOf types.package;
description = "Which packages pantheon should exclude from the default environment";
};
};
config = mkMerge [
(mkIf cfg.enable {
services.desktopManager.pantheon.sessionPath = utils.removePackagesByName [
pkgs.pantheon.pantheon-agent-geoclue2
] config.environment.pantheon.excludePackages;
services.displayManager.sessionPackages = [ pkgs.pantheon.elementary-session-settings ];
# Ensure lightdm is used when Pantheon is enabled
# Without it screen locking will be nonfunctional because of the use of lightlocker
warnings = optional (config.services.xserver.displayManager.lightdm.enable != true) ''
Using Pantheon without LightDM as a displayManager will break screenlocking from the UI.
'';
services.xserver.displayManager.lightdm.greeters.pantheon.enable = mkDefault true;
# Without this, elementary LightDM greeter will pre-select non-existent `default` session
# https://github.com/elementary/greeter/issues/368
services.displayManager.defaultSession = mkDefault "pantheon-wayland";
programs.dconf.profiles.user.databases = [
{
settings."io/elementary/greeter" = {
last-session-type = "pantheon-wayland";
};
}
];
environment.extraInit = ''
${concatMapStrings (p: ''
if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
fi
if [ -d "${p}/lib/girepository-1.0" ]; then
export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
fi
'') cfg.sessionPath}
'';
# Default services
hardware.bluetooth.enable = mkDefault true;
security.polkit.enable = true;
services.accounts-daemon.enable = true;
services.colord.enable = mkDefault true;
services.fwupd.enable = mkDefault true;
# TODO: Enable once #177946 is resolved
# services.packagekit.enable = mkDefault true;
services.power-profiles-daemon.enable = mkDefault true;
services.touchegg.enable = mkDefault true;
services.touchegg.package = pkgs.pantheon.touchegg;
services.tumbler.enable = mkDefault true;
services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
services.dbus.packages = with pkgs.pantheon; [
switchboard-plug-power
elementary-default-settings # accountsservice extensions
];
services.pantheon.apps.enable = mkDefault true;
services.pantheon.contractor.enable = mkDefault true;
services.gnome.at-spi2-core.enable = true;
services.gnome.evolution-data-server.enable = true;
services.gnome.glib-networking.enable = true;
services.gnome.gnome-keyring.enable = true;
services.gnome.gcr-ssh-agent.enable = mkDefault true;
services.gvfs.enable = true;
services.gnome.rygel.enable = mkDefault true;
services.udisks2.enable = true;
services.upower.enable = config.powerManagement.enable;
services.libinput.enable = mkDefault true;
services.switcherooControl.enable = mkDefault true;
services.zeitgeist.enable = mkDefault true;
services.geoclue2.enable = mkDefault true;
# pantheon has pantheon-agent-geoclue2
services.geoclue2.enableDemoAgent = false;
services.geoclue2.appConfig."io.elementary.desktop.agent-geoclue2" = {
isAllowed = true;
isSystem = true;
};
services.udev.packages = [
pkgs.pantheon.gnome-settings-daemon
# Force enable KMS modifiers for devices that require them.
# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1443
pkgs.pantheon.mutter
];
services.orca.enable = mkDefault (notExcluded pkgs.orca);
systemd.packages = with pkgs; [
gnome-session
pantheon.gala
pantheon.gnome-settings-daemon
pantheon.elementary-session-settings
];
programs.dconf.enable = true;
networking.networkmanager.enable = mkDefault true;
systemd.user.targets."gnome-session-x11-services".wants = [
"org.gnome.SettingsDaemon.XSettings.service"
];
systemd.user.targets."gnome-session-x11-services-ready".wants = [
"org.gnome.SettingsDaemon.XSettings.service"
];
# Global environment
environment.systemPackages =
(with pkgs.pantheon; [
elementary-bluetooth-daemon
elementary-session-settings
elementary-settings-daemon
gala
gnome-settings-daemon
(switchboard-with-plugs.override {
plugs = cfg.extraSwitchboardPlugs;
})
(wingpanel-with-indicators.override {
indicators = cfg.extraWingpanelIndicators;
})
])
++ utils.removePackagesByName (
(with pkgs; [
desktop-file-utils
glib # for gsettings program
gnome-menus
adwaita-icon-theme
gtk3.out # for gtk-launch program
onboard
sound-theme-freedesktop
xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
])
++ (with pkgs.pantheon; [
# Artwork
elementary-gtk-theme
elementary-icon-theme
elementary-sound-theme
elementary-wallpapers
# Desktop
elementary-default-settings
elementary-dock
elementary-shortcut-overlay
# Services
elementary-capnet-assist
elementary-notifications
pantheon-agent-geoclue2
pantheon-agent-polkit
])
) config.environment.pantheon.excludePackages;
# Settings from elementary-default-settings
# GTK4 will try both $XDG_CONFIG_DIRS/gtk-4.0 and ${gtk4}/etc/gtk-4.0, but not /etc/gtk-4.0.
environment.etc."xdg/gtk-4.0/settings.ini".source =
"${pkgs.pantheon.elementary-default-settings}/etc/gtk-4.0/settings.ini";
xdg.mime.enable = true;
xdg.icons.enable = true;
xdg.portal.enable = true;
xdg.portal.extraPortals = [
pkgs.xdg-desktop-portal-gtk
]
++ (with pkgs.pantheon; [
elementary-files
elementary-settings-daemon
xdg-desktop-portal-pantheon
]);
xdg.portal.configPackages = mkDefault [ pkgs.pantheon.elementary-default-settings ];
# Override GSettings schemas
environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
environment.sessionVariables.GNOME_SESSION_DEBUG = mkIf cfg.debug "1";
environment.pathsToLink = [
# FIXME: modules should link subdirs of `/share` rather than relying on this
"/share"
];
# Otherwise you can't store NetworkManager Secrets with
# "Store the password only for this user"
programs.nm-applet.enable = true;
# Pantheon has its own network indicator
programs.nm-applet.indicator = false;
# Shell integration for VTE terminals
programs.bash.vteIntegration = mkDefault true;
programs.zsh.vteIntegration = mkDefault true;
# Default Fonts
fonts.packages = with pkgs; [
inter
open-dyslexic
open-sans
roboto-mono
];
fonts.fontconfig.defaultFonts = {
monospace = [ "Roboto Mono" ];
sansSerif = [ "Inter" ];
};
})
(mkIf serviceCfg.apps.enable {
programs.evince.enable = mkDefault (notExcluded pkgs.evince);
programs.file-roller.enable = mkDefault (notExcluded pkgs.file-roller);
environment.systemPackages = utils.removePackagesByName (
[
pkgs.gnome-font-viewer
]
++ (
with pkgs.pantheon;
[
elementary-calculator
elementary-calendar
elementary-camera
elementary-code
elementary-files
elementary-mail
elementary-maps
elementary-music
elementary-photos
elementary-screenshot
elementary-tasks
elementary-terminal
elementary-videos
epiphany
]
++ lib.optionals config.services.flatpak.enable [
# Only install appcenter if flatpak is enabled before
# https://github.com/NixOS/nixpkgs/issues/15932 is resolved.
appcenter
sideload
]
)
) config.environment.pantheon.excludePackages;
# needed by screenshot
fonts.packages = [
pkgs.pantheon.elementary-redacted-script
];
})
(mkIf serviceCfg.contractor.enable {
environment.systemPackages = with pkgs.pantheon; [
contractor
file-roller-contract
];
environment.pathsToLink = [
"/share/contractor"
];
})
];
}

View File

@@ -0,0 +1,391 @@
{
config,
lib,
pkgs,
utils,
...
}:
let
cfg = config.services.desktopManager.plasma6;
inherit (pkgs) kdePackages;
inherit (lib)
literalExpression
mkDefault
mkIf
mkOption
mkPackageOption
types
;
activationScript = ''
# will be rebuilt automatically
rm -fv "$HOME/.cache/ksycoca"*
'';
in
{
options = {
services.desktopManager.plasma6 = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the Plasma 6 (KDE 6) desktop environment.";
};
enableQt5Integration = mkOption {
type = types.bool;
default = true;
description = "Enable Qt 5 integration (theming, etc). Disable for a pure Qt 6 system.";
};
notoPackage = mkPackageOption pkgs "Noto fonts - used for UI by default" {
default = [ "noto-fonts" ];
example = "noto-fonts-lgc-plus";
};
};
environment.plasma6.excludePackages = mkOption {
description = "List of default packages to exclude from the configuration";
type = types.listOf types.package;
default = [ ];
example = literalExpression "[ pkgs.kdePackages.elisa ]";
};
};
imports = [
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "plasma6" "enable" ]
[ "services" "desktopManager" "plasma6" "enable" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "plasma6" "enableQt5Integration" ]
[ "services" "desktopManager" "plasma6" "enableQt5Integration" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "plasma6" "notoPackage" ]
[ "services" "desktopManager" "plasma6" "notoPackage" ]
)
];
config = mkIf cfg.enable {
qt.enable = true;
programs.xwayland.enable = true;
environment.systemPackages =
with kdePackages;
let
requiredPackages = [
qtwayland # Hack? To make everything run on Wayland
qtsvg # Needed to render SVG icons
# Frameworks with globally loadable bits
frameworkintegration # provides Qt plugin
kauth # provides helper service
kcoreaddons # provides extra mime type info
kded # provides helper service
kfilemetadata # provides Qt plugins
kguiaddons # provides geo URL handlers
kiconthemes # provides Qt plugins
kimageformats # provides Qt plugins
qtimageformats # provides optional image formats such as .webp and .avif
kio # provides helper service + a bunch of other stuff
kio-admin # managing files as admin
kio-extras # stuff for MTP, AFC, etc
kio-fuse # fuse interface for KIO
kpackage # provides kpackagetool tool
kservice # provides kbuildsycoca6 tool
kunifiedpush # provides a background service and a KCM
kwallet # provides helper service
kwallet-pam # provides helper service
kwalletmanager # provides KCMs and stuff
plasma-activities # provides plasma-activities-cli tool
solid # provides solid-hardware6 tool
phonon-vlc # provides Phonon plugin
# Core Plasma parts
kwin
kscreen
libkscreen
kscreenlocker
kactivitymanagerd
kde-cli-tools
kglobalacceld # keyboard shortcut daemon
kwrited # wall message proxy, not to be confused with kwrite
baloo # system indexer
milou # search engine atop baloo
kdegraphics-thumbnailers # pdf etc thumbnailer
polkit-kde-agent-1 # polkit auth ui
plasma-desktop
plasma-workspace
drkonqi # crash handler
kde-inotify-survey # warns the user on low inotifywatch limits
# Application integration
libplasma # provides Kirigami platform theme
plasma-integration # provides Qt platform theme
kde-gtk-config # syncs KDE settings to GTK
# Artwork + themes
breeze
breeze-icons
breeze-gtk
ocean-sound-theme
pkgs.hicolor-icon-theme # fallback icons
qqc2-breeze-style
qqc2-desktop-style
# misc Plasma extras
kdeplasma-addons
pkgs.xdg-user-dirs # recommended upstream
# Plasma utilities
kmenuedit
kinfocenter
plasma-systemmonitor
ksystemstats
libksysguard
systemsettings
kcmutils
];
optionalPackages = [
aurorae
plasma-browser-integration
plasma-workspace-wallpapers
konsole
kwin-x11
(lib.getBin qttools) # Expose qdbus in PATH
ark
elisa
gwenview
okular
kate
ktexteditor # provides elevated actions for kate
khelpcenter
dolphin
baloo-widgets # baloo information in Dolphin
dolphin-plugins
spectacle
ffmpegthumbs
krdp
xwaylandvideobridge # exposes Wayland windows to X11 screen capture
]
++ lib.optionals config.hardware.sensor.iio.enable [
# This is required for autorotation in Plasma 6
qtsensors
]
++ lib.optionals config.services.flatpak.enable [
# Since PackageKit Nix support is not there yet,
# only install discover if flatpak is enabled.
discover
];
in
requiredPackages
++ utils.removePackagesByName optionalPackages config.environment.plasma6.excludePackages
++ lib.optionals config.services.desktopManager.plasma6.enableQt5Integration [
breeze.qt5
plasma-integration.qt5
kwayland-integration
(
# Only symlink the KIO plugins, so we don't accidentally pull any services
# like KCMs or kcookiejar
let
kioPluginPath = "${pkgs.plasma5Packages.qtbase.qtPluginPrefix}/kf5/kio";
inherit (pkgs.plasma5Packages) kio;
in
pkgs.runCommand "kio5-plugins-only" { } ''
mkdir -p $out/${kioPluginPath}
ln -s ${kio}/${kioPluginPath}/* $out/${kioPluginPath}
''
)
kio-extras-kf5
]
# Optional and hardware support features
++ lib.optionals config.hardware.bluetooth.enable [
bluedevil
bluez-qt
pkgs.openobex
pkgs.obexftp
]
++ lib.optional config.networking.networkmanager.enable plasma-nm
++ lib.optional config.services.pulseaudio.enable plasma-pa
++ lib.optional config.services.pipewire.pulse.enable plasma-pa
++ lib.optional config.powerManagement.enable powerdevil
++ lib.optional config.services.printing.enable print-manager
++ lib.optional config.services.colord.enable colord-kde
++ lib.optional config.services.hardware.bolt.enable plasma-thunderbolt
++ lib.optional config.services.samba.enable kdenetwork-filesharing
++ lib.optional config.services.xserver.wacom.enable wacomtablet
++ lib.optional config.services.flatpak.enable flatpak-kcm;
environment.pathsToLink = [
# FIXME: modules should link subdirs of `/share` rather than relying on this
"/share"
"/libexec" # for drkonqi
];
environment.etc."X11/xkb".source = config.services.xserver.xkb.dir;
# Add ~/.config/kdedefaults to XDG_CONFIG_DIRS for shells, since Plasma sets that.
# FIXME: maybe we should append to XDG_CONFIG_DIRS in /etc/set-environment instead?
environment.sessionVariables.XDG_CONFIG_DIRS = [ "$HOME/.config/kdedefaults" ];
# Needed for things that depend on other store.kde.org packages to install correctly,
# notably Plasma look-and-feel packages (a.k.a. Global Themes)
#
# FIXME: this is annoyingly impure and should really be fixed at source level somehow,
# but kpackage is a library so we can't just wrap the one thing invoking it and be done.
# This also means things won't work for people not on Plasma, but at least this way it
# works for SOME people.
environment.sessionVariables.KPACKAGE_DEP_RESOLVERS_PATH = "${kdePackages.frameworkintegration.out}/libexec/kf6/kpackagehandlers";
# Enable GTK applications to load SVG icons
programs.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
fonts.packages = [
cfg.notoPackage
pkgs.hack-font
];
fonts.fontconfig.defaultFonts = {
monospace = [
"Hack"
"Noto Sans Mono"
];
sansSerif = [ "Noto Sans" ];
serif = [ "Noto Serif" ];
};
programs.gnupg.agent.pinentryPackage = mkDefault pkgs.pinentry-qt;
programs.kde-pim.enable = mkDefault true;
programs.ssh.askPassword = mkDefault "${kdePackages.ksshaskpass.out}/bin/ksshaskpass";
# Enable helpful DBus services.
services.accounts-daemon.enable = true;
# when changing an account picture the accounts-daemon reads a temporary file containing the image which systemsettings5 may place under /tmp
systemd.services.accounts-daemon.serviceConfig.PrivateTmp = false;
services.power-profiles-daemon.enable = mkDefault true;
services.system-config-printer.enable = mkIf config.services.printing.enable (mkDefault true);
services.udisks2.enable = true;
services.upower.enable = config.powerManagement.enable;
services.libinput.enable = mkDefault true;
# Extra UDEV rules used by Solid
services.udev.packages = [
# libmtp has "bin", "dev", "out" outputs. UDEV rules file is in "out".
pkgs.libmtp.out
pkgs.media-player-info
];
# Set up Dr. Konqi as crash handler
systemd.packages = [ kdePackages.drkonqi ];
systemd.services."drkonqi-coredump-processor@".wantedBy = [ "systemd-coredump@.service" ];
xdg.icons.enable = true;
xdg.icons.fallbackCursorThemes = mkDefault [ "breeze_cursors" ];
xdg.portal.enable = true;
xdg.portal.extraPortals = [
kdePackages.kwallet
kdePackages.xdg-desktop-portal-kde
pkgs.xdg-desktop-portal-gtk
];
xdg.portal.configPackages = mkDefault [ kdePackages.plasma-workspace ];
services.pipewire.enable = mkDefault true;
# Enable screen reader by default
services.orca.enable = mkDefault true;
services.displayManager = {
sessionPackages = [ kdePackages.plasma-workspace ];
defaultSession = mkDefault "plasma";
};
services.displayManager.sddm = {
package = kdePackages.sddm;
theme = mkDefault "breeze";
wayland = mkDefault {
enable = true;
compositor = "kwin";
};
extraPackages = with kdePackages; [
breeze-icons
kirigami
libplasma
plasma5support
qtsvg
qtvirtualkeyboard
];
};
security.pam.services = {
login.kwallet = {
enable = true;
package = kdePackages.kwallet-pam;
};
kde = {
allowNullPassword = true;
kwallet = {
enable = true;
package = kdePackages.kwallet-pam;
};
};
kde-fingerprint = lib.mkIf config.services.fprintd.enable { fprintAuth = true; };
kde-smartcard = lib.mkIf config.security.pam.p11.enable { p11Auth = true; };
};
security.wrappers = {
kwin_wayland = {
owner = "root";
group = "root";
capabilities = "cap_sys_nice+ep";
source = "${lib.getBin pkgs.kdePackages.kwin}/bin/kwin_wayland";
};
ksystemstats_intel_helper = {
owner = "root";
group = "root";
capabilities = "cap_perfmon+ep";
source = "${pkgs.kdePackages.ksystemstats}/libexec/ksystemstats_intel_helper";
};
ksgrd_network_helper = {
owner = "root";
group = "root";
capabilities = "cap_net_raw+ep";
source = "${pkgs.kdePackages.libksysguard}/libexec/ksysguard/ksgrd_network_helper";
};
};
# Upstream recommends allowing set-timezone and set-ntp so that the KCM and
# the automatic timezone logic work without user interruption.
# However, on NixOS NTP cannot be overwritten via dbus, and timezone
# can only be set if `time.timeZone` is set to `null`. So, we only allow
# set-timezone, and we only allow it when the timezone can actually be set.
security.polkit.extraConfig = lib.mkIf (config.time.timeZone != null) ''
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.timedate1.set-timezone" && subject.active) {
return polkit.Result.YES;
}
});
'';
programs.dconf.enable = true;
programs.firefox.nativeMessagingHosts.packages = [ kdePackages.plasma-browser-integration ];
programs.chromium = {
enablePlasmaBrowserIntegration = true;
plasmaBrowserIntegrationPackage = pkgs.kdePackages.plasma-browser-integration;
};
programs.kdeconnect.package = kdePackages.kdeconnect-kde;
programs.partition-manager.package = kdePackages.partitionmanager;
# FIXME: ugly hack. See #292632 for details.
system.userActivationScripts.rebuildSycoca = activationScript;
systemd.user.services.nixos-rebuild-sycoca = {
description = "Rebuild KDE system configuration cache";
wantedBy = [ "graphical-session-pre.target" ];
serviceConfig.Type = "oneshot";
script = activationScript;
};
};
}