diff --git a/machines/common/all/users.nix b/machines/common/all/users.nix index 22e02637f..e3d11f7c4 100644 --- a/machines/common/all/users.nix +++ b/machines/common/all/users.nix @@ -15,7 +15,7 @@ # XXX colin: this is what the installer has, but is it necessary? # group = "users"; extraGroups = [ "wheel" "nixbuild" "networkmanager" ]; - initialHashedPassword = ""; + initialPassword = lib.mkDefault ""; # shell = pkgs.bashInteractive; # XXX colin: create ssh key for THIS user by logging in and running: # ssh-keygen -t ed25519 diff --git a/machines/moby/default.nix b/machines/moby/default.nix index abc656406..d29c593d0 100644 --- a/machines/moby/default.nix +++ b/machines/moby/default.nix @@ -2,9 +2,18 @@ { imports = [ ./../common/all - ./../common/gnome.nix + #./../common/gnome.nix + # TODO: remove this phosh.nix file. + # phosh service support was added to nixpkgs on 2022/05/07: https://github.com/NixOS/nixpkgs/pull/153940 + # it may be possible to import this via /... path ? + # or find a more recent nixpkgs which builds with mobile-nixos. that PR indicates people have done so. + ./phosh.nix + ./gui-phosh.nix ]; + # XXX colin: phosh doesn't work well with passwordless login + users.users.colin.initialPassword = "147147"; + home-manager.users.colin = import ./../../helpers/home-manager-gen-colin.nix { inherit pkgs lib; system = "aarch64-linux"; diff --git a/machines/moby/gui-phosh.nix b/machines/moby/gui-phosh.nix new file mode 100644 index 000000000..b547f9099 --- /dev/null +++ b/machines/moby/gui-phosh.nix @@ -0,0 +1,8 @@ +{ ... }: +{ + services.xserver.desktopManager.phosh = { + enable = true; + user = "colin"; + group = "users"; + }; +} diff --git a/machines/moby/phosh.nix b/machines/moby/phosh.nix new file mode 100644 index 000000000..85bcdf762 --- /dev/null +++ b/machines/moby/phosh.nix @@ -0,0 +1,218 @@ +# inline of this: https://github.com/NixOS/nixpkgs/blob/nixpkgs-unstable/nixos/modules/services/x11/desktop-managers/phosh.nix +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.xserver.desktopManager.phosh; + + # Based on https://source.puri.sm/Librem5/librem5-base/-/blob/4596c1056dd75ac7f043aede07887990fd46f572/default/sm.puri.OSK0.desktop + oskItem = pkgs.makeDesktopItem { + name = "sm.puri.OSK0"; + desktopName = "On-screen keyboard"; + exec = "${pkgs.squeekboard}/bin/squeekboard"; + # categories = [ "GNOME" "Core" ]; + # onlyShowIn = [ "GNOME" ]; + noDisplay = true; + # extraConfig = { + # X-GNOME-Autostart-Phase = "Panel"; + # X-GNOME-Provides = "inputmethod"; + # X-GNOME-Autostart-Notify = "true"; + # X-GNOME-AutoRestart = "true"; + # }; + }; + + phocConfigType = types.submodule { + options = { + xwayland = mkOption { + description = '' + Whether to enable XWayland support. + + To start XWayland immediately, use `immediate`. + ''; + type = types.enum [ "true" "false" "immediate" ]; + default = "false"; + }; + cursorTheme = mkOption { + description = '' + Cursor theme to use in Phosh. + ''; + type = types.str; + default = "default"; + }; + outputs = mkOption { + description = '' + Output configurations. + ''; + type = types.attrsOf phocOutputType; + default = { + DSI-1 = { + scale = 2; + }; + }; + }; + }; + }; + + phocOutputType = types.submodule { + options = { + modeline = mkOption { + description = '' + One or more modelines. + ''; + type = types.either types.str (types.listOf types.str); + default = []; + example = [ + "87.25 720 776 848 976 1440 1443 1453 1493 -hsync +vsync" + "65.13 768 816 896 1024 1024 1025 1028 1060 -HSync +VSync" + ]; + }; + mode = mkOption { + description = '' + Default video mode. + ''; + type = types.nullOr types.str; + default = null; + example = "768x1024"; + }; + scale = mkOption { + description = '' + Display scaling factor. + ''; + type = types.nullOr types.ints.unsigned; + default = null; + example = 2; + }; + rotate = mkOption { + description = '' + Screen transformation. + ''; + type = types.enum [ + "90" "180" "270" "flipped" "flipped-90" "flipped-180" "flipped-270" null + ]; + default = null; + }; + }; + }; + + optionalKV = k: v: if v == null then "" else "${k} = ${builtins.toString v}"; + + renderPhocOutput = name: output: let + modelines = if builtins.isList output.modeline + then output.modeline + else [ output.modeline ]; + renderModeline = l: "modeline = ${l}"; + in '' + [output:${name}] + ${concatStringsSep "\n" (map renderModeline modelines)} + ${optionalKV "mode" output.mode} + ${optionalKV "scale" output.scale} + ${optionalKV "rotate" output.rotate} + ''; + + renderPhocConfig = phoc: let + outputs = mapAttrsToList renderPhocOutput phoc.outputs; + in '' + [core] + xwayland = ${phoc.xwayland} + ${concatStringsSep "\n" outputs} + [cursor] + theme = ${phoc.cursorTheme} + ''; +in + +{ + options = { + services.xserver.desktopManager.phosh = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable the Phone Shell."; + }; + + package = mkOption { + type = types.package; + default = pkgs.phosh; + defaultText = literalExpression "pkgs.phosh"; + example = literalExpression "pkgs.phosh"; + description = '' + Package that should be used for Phosh. + ''; + }; + + user = mkOption { + description = "The user to run the Phosh service."; + type = types.str; + example = "alice"; + }; + + group = mkOption { + description = "The group to run the Phosh service."; + type = types.str; + example = "users"; + }; + + phocConfig = mkOption { + description = '' + Configurations for the Phoc compositor. + ''; + type = types.oneOf [ types.lines types.path phocConfigType ]; + default = {}; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.defaultUnit = "graphical.target"; + # Inspired by https://gitlab.gnome.org/World/Phosh/phosh/-/blob/main/data/phosh.service + systemd.services.phosh = { + wantedBy = [ "graphical.target" ]; + serviceConfig = { + ExecStart = "${cfg.package}/bin/phosh"; + User = cfg.user; + Group = cfg.group; + PAMName = "login"; + WorkingDirectory = "~"; + Restart = "always"; + + TTYPath = "/dev/tty7"; + TTYReset = "yes"; + TTYVHangup = "yes"; + TTYVTDisallocate = "yes"; + + # Fail to start if not controlling the tty. + StandardInput = "tty-fail"; + StandardOutput = "journal"; + StandardError = "journal"; + + # Log this user with utmp, letting it show up with commands 'w' and 'who'. + UtmpIdentifier = "tty7"; + UtmpMode = "user"; + }; + }; + + environment.systemPackages = [ + pkgs.phoc + cfg.package + pkgs.squeekboard + oskItem + ]; + + systemd.packages = [ cfg.package ]; + + programs.feedbackd.enable = true; + + security.pam.services.phosh = {}; + + hardware.opengl.enable = mkDefault true; + + services.gnome.core-shell.enable = true; + services.gnome.core-os-services.enable = true; + services.xserver.displayManager.sessionPackages = [ cfg.package ]; + + environment.etc."phosh/phoc.ini".source = + if builtins.isPath cfg.phocConfig then cfg.phocConfig + else if builtins.isString cfg.phocConfig then pkgs.writeText "phoc.ini" cfg.phocConfig + else pkgs.writeText "phoc.ini" (renderPhocConfig cfg.phocConfig); + }; +}