diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index 2b1e9169e5f6..671a959cdde1 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -20,7 +20,7 @@ in
imports = [
./none.nix ./xterm.nix ./xfce.nix ./plasma5.nix ./lumina.nix
./lxqt.nix ./enlightenment.nix ./gnome3.nix ./kodi.nix ./maxx.nix
- ./mate.nix ./pantheon.nix
+ ./mate.nix ./pantheon.nix ./surf-display.nix
];
options = {
diff --git a/nixos/modules/services/x11/desktop-managers/surf-display.nix b/nixos/modules/services/x11/desktop-managers/surf-display.nix
new file mode 100644
index 000000000000..232bbf5c55d4
--- /dev/null
+++ b/nixos/modules/services/x11/desktop-managers/surf-display.nix
@@ -0,0 +1,127 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.desktopManager.surf-display;
+
+ surfDisplayConf = ''
+ # Surf Kiosk Display: Wrap around surf browser and turn your
+ # system into a browser screen in KIOSK-mode.
+
+ # default download URI for all display screens if not configured individually
+ DEFAULT_WWW_URI="${cfg.defaultWwwUri}"
+
+ # Enforce fixed resolution for all displays (default: not set):
+ #DEFAULT_RESOLUTION="1920x1080"
+
+ # HTTP proxy URL, if needed (default: not set).
+ #HTTP_PROXY_URL="http://webcache:3128"
+
+ # Setting for internal inactivity timer to restart surf-display
+ # if the user goes inactive/idle.
+ INACTIVITY_INTERVAL="${builtins.toString cfg.inactivityInterval}"
+
+ # log to syslog instead of .xsession-errors
+ LOG_TO_SYSLOG="yes"
+
+ # Launch pulseaudio daemon if not already running.
+ WITH_PULSEAUDIO="yes"
+
+ # screensaver settings, see "man 1 xset" for possible options
+ SCREENSAVER_SETTINGS="${cfg.screensaverSettings}"
+
+ # disable right and middle pointer device click in browser sessions while keeping
+ # scrolling wheels' functionality intact... (consider "pointer" subcommand on
+ # xmodmap man page for details).
+ POINTER_BUTTON_MAP="${cfg.pointerButtonMap}"
+
+ # Hide idle mouse pointer.
+ HIDE_IDLE_POINTER="${cfg.hideIdlePointer}"
+
+ ${cfg.extraConfig}
+ '';
+
+in {
+ options = {
+ services.xserver.desktopManager.surf-display = {
+ enable = mkEnableOption "surf-display as a kiosk browser session";
+
+ defaultWwwUri = mkOption {
+ type = types.string;
+ default = "${pkgs.surf-display}/share/surf-display/empty-page.html";
+ example = "https://www.example.com/";
+ description = "Default URI to display.";
+ };
+
+ inactivityInterval = mkOption {
+ type = types.int;
+ default = 300;
+ example = "0";
+ description = ''
+ Setting for internal inactivity timer to restart surf-display if the
+ user goes inactive/idle to get a fresh session for the next user of
+ the kiosk.
+
+ If this value is set to zero, the whole feature of restarting due to
+ inactivity is disabled.
+ '';
+ };
+
+ screensaverSettings = mkOption {
+ type = types.string;
+ default = "";
+ description = ''
+ Screensaver settings, see man 1 xset for possible options.
+ '';
+ };
+
+ pointerButtonMap = mkOption {
+ type = types.string;
+ default = "1 0 0 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0";
+ description = ''
+ Disable right and middle pointer device click in browser sessions
+ while keeping scrolling wheels' functionality intact. See pointer
+ subcommand on man xmodmap for details.
+ '';
+ };
+
+ hideIdlePointer = mkOption {
+ type = types.string;
+ default = "yes";
+ example = "no";
+ description = "Hide idle mouse pointer.";
+ };
+
+ extraConfig = mkOption {
+ type = types.string;
+ default = "";
+ example = ''
+ # Enforce fixed resolution for all displays (default: not set):
+ DEFAULT_RESOLUTION="1920x1080"
+
+ # HTTP proxy URL, if needed (default: not set).
+ HTTP_PROXY_URL="http://webcache:3128"
+
+ # Configure individual display screens with host specific parameters:
+ DISPLAYS['display-host-0']="www_uri=https://www.displayserver.comany.net/display-1/index.html"
+ DISPLAYS['display-host-1']="www_uri=https://www.displayserver.comany.net/display-2/index.html"
+ DISPLAYS['display-host-2']="www_uri=https://www.displayserver.comany.net/display-3/index.html|res=1920x1280"
+ DISPLAYS['display-host-3']="www_uri=https://www.displayserver.comany.net/display-4/index.html"|res=1280x1024"
+ DISPLAYS['display-host-local-file']="www_uri=file:///usr/share/doc/surf-display/empty-page.html"
+ '';
+ description = ''
+ Extra configuration options to append to /etc/default/surf-display.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.displayManager.extraSessionFilePackages = [
+ pkgs.surf-display
+ ];
+
+ environment.etc."default/surf-display".text = surfDisplayConf;
+ };
+}
diff --git a/pkgs/desktops/surf-display/default.nix b/pkgs/desktops/surf-display/default.nix
new file mode 100644
index 000000000000..f3554fe0b40a
--- /dev/null
+++ b/pkgs/desktops/surf-display/default.nix
@@ -0,0 +1,53 @@
+{ stdenv, fetchgit, makeWrapper
+, surf, wmctrl, matchbox, xdotool, unclutter
+, xorg, pulseaudio, xprintidle-ng }:
+
+stdenv.mkDerivation rec {
+ pname = "surf-display";
+ version = "unstable-2019-04-15";
+
+ src = fetchgit {
+ url = "https://code.it-zukunft-schule.de/cgit/surf-display";
+ rev = "972d6c4b7c4503dbb63fa6c92cdc24d1e32064a4";
+ sha256 = "03c68gg4kfmkri1gn5b7m1g8vh9ciawhajb29c17kkc7mn388hjm";
+ };
+
+ nativeBuildInputs = [ makeWrapper ];
+
+ buildInputs = [
+ surf
+ wmctrl
+ matchbox
+ pulseaudio
+ xprintidle-ng
+ xdotool
+ xorg.xmodmap
+ xorg.xkbutils
+ unclutter
+ ];
+
+ patches = [ ./pdf-makefile.patch ];
+
+ buildFlags = [ "man" ];
+
+ postFixup = ''
+ substituteInPlace $out/share/xsessions/surf-display.desktop \
+ --replace surf-display $out/bin/surf-display
+
+ substituteInPlace $out/bin/surf-display --replace /usr/share $out/share
+
+ patchShebangs $out/bin/surf-display
+ wrapProgram $out/bin/surf-display \
+ --prefix PATH ':' ${stdenv.lib.makeBinPath buildInputs}
+ '';
+
+ makeFlags = [ "PREFIX=${placeholder ''out''}" ];
+
+ meta = with stdenv.lib; {
+ description = "Kiosk browser session manager based on the surf browser";
+ homepage = "https://code.it-zukunft-schule.de/cgit/surf-display/";
+ maintainers = with maintainers; [ etu ];
+ license = licenses.gpl2;
+ platforms = platforms.linux;
+ };
+}
diff --git a/pkgs/desktops/surf-display/pdf-makefile.patch b/pkgs/desktops/surf-display/pdf-makefile.patch
new file mode 100644
index 000000000000..9c2541052c0e
--- /dev/null
+++ b/pkgs/desktops/surf-display/pdf-makefile.patch
@@ -0,0 +1,24 @@
+diff --git a/Makefile b/Makefile
+index 1081d64..499160c 100644
+--- a/Makefile
++++ b/Makefile
+@@ -13,19 +13,10 @@ man::
+ gzip -9 -c -n data/surf-display.1 > data/surf-display.1.gz
+
+ install:
+- if [ ! -e data/surf-display.pdf.gz ]; then \
+- echo "Run 'make build' first, before running 'sudo make install'."; \
+- exit -1; \
+- fi
+-
+ # script
+ mkdir -p $(DESTDIR)$(PREFIX)/bin/
+ install -m 0755 bin/surf-display $(DESTDIR)$(PREFIX)/bin/
+
+- # LaTeX Beamer PDF: Impressive HowTo
+- mkdir -p $(DESTDIR)$(PREFIX)/share/doc/surf-display/
+- install -m 0644 data/*.pdf.gz $(DESTDIR)$(PREFIX)/share/doc/surf-display/
+-
+ # man page
+ mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1
+ install -m 0644 data/*.1.gz $(DESTDIR)$(PREFIX)/share/man/man1/
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 9d022733584c..f2b89a411d62 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -20557,6 +20557,8 @@ in
surf = callPackage ../applications/networking/browsers/surf { gtk = gtk2; };
+ surf-display = callPackages ../desktops/surf-display { };
+
sunvox = callPackage ../applications/audio/sunvox { };
swh_lv2 = callPackage ../applications/audio/swh-lv2 { };