JustToThePoint English Website Version
JustToThePoint en español

NixOS: Services, GNOME Desktop, User Accounts, and Flatpak Configuration

“I refuse to answer without my lawyer or even worse, without knowing the answer”, Apocalypse, Anawim, #justtothepoint.

Complex Numbers

NixOS is a unique, innovative, and powerful Linux distribution that leverages the Nix package manager. Unlike traditional Linux distributions that update packages and system configurations in-place, NixOS uses a purely functional and declarative approach to define the system state, reducing the risk of system breakage.

NixOS is a Linux distribution that uses the Nix package manager to handle packages and system configuration in a purely functional manner. This approach ensures that builds are reproducible and that the system state can be reliably replicated or rolled back.

  1. Immutable Design: It uses a configuration file (usually /etc/nixos/configuration.nix) to define the entire system state, including installed packages, services, and system settings. This makes the system “immutable” in the sense that you don’t manually modify system files. Instead, you declare what you want, and NixOS builds the system from that declaration.
  2. Atomic Updates: When you run nixos-rebuild switch, the system builds a new generation of the environment. If the build is successful, you can switch to this new environment atomically. This means that either the entire update is applied, or nothing changes at all, preventing partial updates that could leave the system in an inconsistent state: sudo nixos-rebuild switch, build and switch to the new generation. If anything goes wrong, you can easily roll back to a previous generation: sudo nix-env ‐‐rollback This rollback is seamless because each generation is stored separately.

    sudo nix-env ‐‐rollback is a command used to revert your system to the previous configuration. It’s a powerful tool for undoing unintended changes or recovering from failed package installations. Before rolling back, consider if there’s a more targeted solution, like uninstalling specific packages or reverting configuration files.

  3. Purely Functional System Configuration: NixOS uses a functional paradigm for configuration. This means that changes are expressed as pure functions from a configuration to a system state, ensuring reproducible builds and easy rollback.

NixOS

Services and Desktop Environment

NixOS leverages a declarative approach to system configuration, making it incredibly flexible and powerful. By defining your desired system state in the configuration.nix file, you can easily manage desktop environments and services, install and manage packages, and configure system-wide settings like time zones, locales, and keyboard layouts.

Services and desktop environments are enabled and configured via the configuration.nix file. Instead of manually editing multiple system files, you declare your desired desktop environment (GNOME, KDE Plasma, XFCE, i3, etc.) and services, and then NixOS will ensure they are set up correctly after a rebuild.

A service is a computer program that runs in the background, performing specific tasks without direct user interaction. They are essential for the smooth functioning of the system and provide various functionalities, such as: network services (SSH, FTP, HTTP, etc.) for remote access and communication; time synchronization and system management (NTP, systemd-timesyncd); PipeWire and PulseAudio for audio and multimedia; synchronization and backup services (rsync, Nextcloud, etc.); inter-process communication (D-Bus); automated task scheduling (Cron).

services = {
  xserver = {
  # XServer Settings: Configures the display server and desktop environments.
    enable = true; # Enables the X11 Window system
    displayManager.gdm.enable = true; # Uses GDM as the graphical login manager (common in GNOME desktop environments).
    # GDM provides the login screen and handles user sessions for the GNOME desktop environment.
    desktopManager.gnome.enable = true; # Enables the GNOME desktop environment

    # Enable the i3 window manager with gaps
  	windowManager.i3 = {
    			enable = true;
    			package = pkgs.i3-gaps;
  	};
  	# Keep your screen active
  	displayManager.sessionCommands = ''
    			# Disable DPMS (Display Power Management Signaling)
    			${pkgs.xorg.xset}/bin/xset -dpms
    			# Disable screen saver
    			${pkgs.xorg.xset}/bin/xset s off
  	'';
  };

  # A cleaner alternative (only i3) with sddm
  xserver = {
    enable = true;  # Enables the X server, which is necessary for graphical environments.

    windowManager.i3 = {
        enable = true;  # Enables the i3 window manager, a popular tiling window manager known for its stability and efficiency.
        package = pkgs.i3-gaps;  # Specifies the package to be used for i3, i3-gaps adds gaps between windows.
    };
};

  flatpak.enable = true;  # Enables Flatpak, a system for building, distributing, and running sandboxed desktop applications.

  displayManager.sddm.enable = true;  # Enables the SDDM for managing user sessions and logins.
  # It is a modern display manager aiming to be fast, simple, and beautiful.

  displayManager.autoLogin = {
    enable = true;  # Enables automatic login for the specified user.
    user = "YOUR-USERNAME";  # Specifies the username for automatic login.
  };

Enabling both GNOME and i3 allows you to choose between a full desktop environment and a lightweight window manager.

In case something goes seriously wrong with your graphical session, you can press Ctrl+Alt+F1 (or F2 through F6) to switch to a different virtual console. These consoles provide a text-based login shell, allowing you to troubleshoot the system and fix issues without relying on the graphical environment.

User Accounts

NixOS user management is also declarative. Instead of manually adding users (useradd) or editing /etc/passwd, you define user accounts in configuration.nix.

users.users.nmaximo7 = { # Defines a user account.
  #Remember to set a password for the user using: sudo passwd nmaximo7
  description = "nmaximo7"; # Description for the user
  isNormalUser = true;  # Indicates this is a regular (non-system) user
  shell = "${pkgs.zsh}/bin/zsh"; # Sets Zsh as the default shell
  openssh.authorizedKeys.keys = [
  	"< INSERT PUBLIC KEY >" # A public SSH key for passwordless login.
    # Typically, you copy and paste the content: cat .ssh/id_ed25519.pub.
  ];
  extraGroups = [ "networkmanager" "wheel" "docker" "audio" "input" ];
  # Adds the user to several groups:
  # "wheel" grants sudo access (allowing administrative tasks)
  # "networkmanager" grants permissions to control network interfaces
  # "docker" allows the user to run Docker containers without sudo
  # "audio" and "input" are useful for granting permissions to audio devices
  # and input devices, needed by certain programs and status bars (e.g., polybar).

  packages = with pkgs; [
    # You can list user-specific packages here
    # which will be installed specifically for this use
  ];
};

GNOME Configuration

GNOME Extensions are small, modular JavaScript plugins that modify, enhance, or add functionality to the GNOME desktop environment. Edit your configuration.nix:

  packages = with pkgs; [
      # Dash to Panel is an icon taskbar for Gnome Shell so that the application launchers and system tray are combined into a single panel.
      gnomeExtensions.dash-to-panel      # Taskbar panel combining launcher and tray
      gnomeExtensions.forge              # Tiling window manager for GNOME
      gnomeExtensions.auto-move-windows  # Automatic workspace placement
      gnome-shell-extensions             # Official GNOME extension pack
      gnomeExtensions.appindicator       # System tray icon support
  ];

  # PolicyKit (polkit) is an authorization system that allows non-privileged processes to perform privileged operations.
  # It acts as a gatekeeper for system-level actions.
  # GNOME's remote desktop features normally prompt for authentication each session. This rule:
  # Grant a specific user permission (nmaximo7) to use Remote Desktop features without being prompted for a password.
  # RemoteDesktop portals (both Flatpak and Mutter) are secure communication bridges that allow apps to request system resources.
  # Security.polkit.extraConfig tells NixOS to add a custom rule to PolicyKit (polkit), the system service that controls system-wide privileges
  security.polkit.extraConfig = ''
	  polkit.addRule(function(action, subject) {
	    if ((action.id == "org.freedesktop.portal.RemoteDesktop" ||
		 action.id == "org.gnome.Mutter.RemoteDesktop") &&
		subject.user == "nmaximo7") {
        # It instructs the system to automatically authorize the request rather than asking for authentication
	      return polkit.Result.YES;
	    }
	  });
  '';

  # This configuration line forces the GNOME Display Manager (GDM) to use Xorg instead of Wayland.
  # Better compatibility: Many GNOME extensions work more reliably with Xorg
  # Screen sharing: Some remote desktop and screen capture tools work better with Xorg
  # Input handling: Certain applications have better input support
  services.xserver.displayManager.gdm.wayland = false;

  # dconf is the configuration storage system for GNOME and GTK applications.
  # It functions like a registry for GNOME settings.
  programs.dconf.enable = true;
home-manager.users.nmaximo7 = { pkgs, ... }:
  {
    [...]
    dconf.settings = {
    # Disable automatic screen lock
    "org/gnome/desktop/session" = {
      idle-delay = 0; # Never consider the session idle
    };

    "org/gnome/desktop/screensaver" = {
      lock-enabled = false;  # Disable screen lock
    };

    "org/gnome/settings-daemon/plugins/power" = {
      sleep-inactive-ac-type = "nothing";
      sleep-inactive-battery-type = "nothing";
    };
    # ── Enable extensions ──────────────────────────────────────
    "org/gnome/shell" = {
      disable-user-extensions = false; # Allow user-installed extensions
      enabled-extensions = [
        "apps-menu@gnome-shell-extensions.gcampax.github.com"
        "dash-to-panel@jderose9.github.com"
        "forge@jmmaranan.com"
        "auto-move-windows@gnome-shell-extensions.gcampax.github.com"
        "appindicatorsupport@rgcjonas.gmail.com"
      ];
    };

    # ── Auto Move Windows ──────────────────────────────────────
    # Automatically places application windows on specific workspaces
    "org/gnome/shell/extensions/auto-move-windows" = {
      # Format: "application.desktop:workspace_number"
      application-list = [
        "code.desktop:2"            # VS Code → Workspace 2
        "google-chrome.desktop:1"   # Chrome  → Workspace 1
        "org.gnome.Console.desktop:3"  # kgx → Workspace 3
      ];
    };

    # Forge Keybindings Management
    # Window tiling: Automatically arranges windows in a grid
    # Forge's default keybindings conflict with GNOME's terminal launcher (Return)
    "org/gnome/shell/extensions/forge/keybindings" = {
        window-toggle-float = [ "f" ];   # New binding, it was Return/
        window-swap = [ ];          # Clear default Return
        window-move = [ ];          # Clear default Shift>Return
        window-focus = [ ];         # Clear default Return
        window-split = [ ];         # Clear default binding
     };

    # ── Dash to Panel (single bottom panel, combined launcher + tray) ─
    "org/gnome/shell/extensions/dash-to-panel" = {
      panel-positions       = "{\"0\":\"BOTTOM\"}";  # BOTTOM, TOP, LEFT, RIGHT. Position on primary monitor
      # 0 Primary monitor, "BOTTOM": Place panel at bottom
      panel-sizes           = "{\"0\":48}"; # Height in pixels
      panel-element-positions = builtins.toJSON {
        "0" = [
          { element = "showAppsButton";   visible = true;  position = "stackedTL"; }
          { element = "activitiesButton"; visible = false; position = "stackedTL"; }
          { element = "leftBox";          visible = true;  position = "stackedTL"; }
          { element = "taskbar";          visible = true;  position = "stackedTL"; }
          # Shows running applications
          { element = "centerBox";        visible = true;  position = "stackedBR"; }
          { element = "rightBox";         visible = true;  position = "stackedBR"; }
          { element = "systemMenu";       visible = true;  position = "stackedBR"; }
          # systemMenu: Volume, network, power controls
          { element = "dateMenu";         visible = true;  position = "stackedBR"; }
          # dateMenu: Calendar and time display
          { element = "desktopButton";    visible = true;  position = "stackedBR"; }
        ];
      };
      dot-style-focused    = "DOTS"; # Style for active window
      dot-style-unfocused  = "DOTS"; # Style for inactive windows
      show-favorites       = true; # Show pinned apps
      group-apps = true; # Group windows from
      show-tooltip         = true; # Show tooltips on hover
      hide-overview-on-startup = true; # Skip the activities overview on boot
    };

    # ── Forge (tiling) ─────────────────────────────────────────
    "org/gnome/shell/extensions/forge" = {
      tiling-mode-enabled = true; # Automatically arranges windows in a grid
      stacked-tiling-mode-enabled = false; # Alternative layout similar to i3
      float-always-on-top-enabled = true; # Some applications (dialogs, calculators) work better when floating
    };

    # ── Number of workspaces ───────────────────────────────────
    "org/gnome/desktop/wm/preferences" = {
      num-workspaces = 4;
      workspace-names = [ "Web" "Code" "Terminal" "Misc" ];
    };

    # ── Window manager keybindings ─────────────────────────────
    "org/gnome/desktop/wm/keybindings" = {
      # Close window: Super + Q
      close = [ "q" ];

      # Move window to workspace N: Super + Shift + N
      move-to-workspace-1 = [ "1" ];
      move-to-workspace-2 = [ "2" ];
      move-to-workspace-3 = [ "3" ];
      move-to-workspace-4 = [ "4" ];

      # Switch to workspace N: Super + N
      switch-to-workspace-1 = [ "1" ];
      switch-to-workspace-2 = [ "2" ];
      switch-to-workspace-3 = [ "3" ];
      switch-to-workspace-4 = [ "4" ];

      # Move/resize with keyboard (optional)
      maximize              = [ "Up" ];
      unmaximize            = [ "Down" ];
      toggle-fullscreen     = [ "f" ];
      switch-applications   = [];
      switch-windows        = [ "Tab" ];
    };

    # ── Custom keybindings  ────────────────────
    # 1. Register custom keybinding paths in the main media-keys setting
    "org/gnome/settings-daemon/plugins/media-keys" = {
      custom-keybindings = [
        "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/"
        "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/"
        "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/"
      ];
    };

    # 2. Define each binding with name, command, and shortcut
    # Custom keybinding 0: Super + Enter → kgx
    "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0" = {
      name    = "Terminal";
      command = "kgx";           # change to kitty, alacritty, etc. as needed
      binding = "Return";
    };

    # Custom keybinding 1: example extra — file manager on Super + E
    "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1" = {
      name    = "Files";
      command = "nautilus";
      binding = "e";
    };

    # A GNOME custom shortcut to shut down your system
    "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2" = {
      name = "Shutdown";
      command = "systemctl poweroff";
      binding = "D";
    };

    # ── Mutter (compositor) tweaks ─────────────────────────────
    "org/gnome/mutter" = {
      dynamic-workspaces    = false; # Fixed number of workspaces
      workspaces-only-on-primary = true; # Only show workspaces on main monitor
      edge-tiling = true;  # Enable snapping windows to edges
      # Allows dragging windows to screen edges to tile them
	 };

     # Remote Desktop Portal Silence
	   # The polkit rule alone isn't enough to silence all prompts.
     # Disabling the RDP (Remote Desktop Protocol) daemon prevents GNOME from attempting to start it, which would trigger the authentication prompt.
     "org/gnome/desktop/remote-desktop/rdp" = {
        enable = false;  # We don't need RDP; keeps the daemon quiet
     };
  }; # End dconf.settings

  [...]
  # Autostart Applications
  # We copy our custom desktop file to ~/.config/autostart/, which GNOME reads on login to auto-start applications.
  home.file.".config/autostart/code.desktop".source = "/home/${username}/dotfiles/autostart/code.desktop";
  home.file.".config/autostart/chrome.desktop".source = "/home/${username}/dotfiles/autostart/chrome.desktop";
  home.file.".config/autostart/kgx.desktop".source = "/home/${username}/dotfiles/autostart/kgx.desktop";
[Desktop Entry]
Type=Application  # This is an application (not Link or Directory)
Name=Visual Studio Code # Display name
Exec=code --folder-uri vscode-remote://ssh-remote+myserver/mnt/data/justtothepoint
# code: The VS Code executable
# --folder-uri vscode-remote://...: Opens a remote SSH connection to the Arch server (myserver)
# The path /mnt/data/justtothepoint is the remote directory to open
X-GNOME-Autostart-enabled=true
Bitcoin donation

JustToThePoint Copyright © 2011 - 2026 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun. Social Issues, Join us.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.