nixos/timekpr: init at 0.5.8
Co-authored-by: Matt Sturgeon <matt@sturgeon.me.uk>
This commit is contained in:
@@ -152,3 +152,16 @@ original files are by default stored in `/var/lib/nixos`.
|
||||
Userborn implements immutable users by re-mounting the password files
|
||||
read-only. This means that unlike when using the Perl script, trying to add a
|
||||
new user (e.g. via `useradd`) will fail right away.
|
||||
|
||||
## Restrict usage time {#sec-restrict-usage-time}
|
||||
|
||||
[Timekpr-nExT](https://mjasnik.gitlab.io/timekpr-next/) is a screen time managing application that helps optimizing time spent at computer for your subordinates, children or even for yourself.
|
||||
|
||||
You can enable it via:
|
||||
|
||||
```nix
|
||||
{ services.timekpr.enable = true; }
|
||||
```
|
||||
|
||||
This will install the `timekpr` package and start the `timekpr` service.
|
||||
You can then use the `timekpra` application to configure time limits for users.
|
||||
|
||||
@@ -335,6 +335,9 @@
|
||||
"sec-userborn": [
|
||||
"index.html#sec-userborn"
|
||||
],
|
||||
"sec-restrict-usage-time": [
|
||||
"index.html#sec-restrict-usage-time"
|
||||
],
|
||||
"ch-file-systems": [
|
||||
"index.html#ch-file-systems"
|
||||
],
|
||||
|
||||
@@ -80,6 +80,8 @@
|
||||
|
||||
- [mautrix-discord](https://github.com/mautrix/discord), a Matrix-Discord puppeting/relay bridge. Available as [services.mautrix-discord](#opt-services.mautrix-discord.enable).
|
||||
|
||||
- [Timekpr-nExT](https://mjasnik.gitlab.io/timekpr-next/), a time managing application that helps optimizing time spent at computer for your subordinates, children or even for yourself. Available as [](#opt-services.timekpr.enable).
|
||||
|
||||
- [SuiteNumérique Meet](https://github.com/suitenumerique/meet) is an open source alternative to Google Meet and Zoom powered by LiveKit: HD video calls, screen sharing, and chat features. Built with Django and React. Available as [services.lasuite-meet](#opt-services.lasuite-meet.enable).
|
||||
|
||||
- [lemurs](https://github.com/coastalwhite/lemurs), a customizable TUI display/login manager. Available at [services.displayManager.lemurs](#opt-services.displayManager.lemurs.enable).
|
||||
|
||||
@@ -1468,6 +1468,7 @@
|
||||
./services/security/sslmate-agent.nix
|
||||
./services/security/step-ca.nix
|
||||
./services/security/tang.nix
|
||||
./services/security/timekpr.nix
|
||||
./services/security/tor.nix
|
||||
./services/security/torify.nix
|
||||
./services/security/torsocks.nix
|
||||
|
||||
65
nixos/modules/services/security/timekpr.nix
Normal file
65
nixos/modules/services/security/timekpr.nix
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.timekpr;
|
||||
targetBaseDir = "/var/lib/timekpr";
|
||||
daemonUser = "root";
|
||||
daemonGroup = "root";
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.timekpr = {
|
||||
package = lib.mkPackageOption pkgs "timekpr" { };
|
||||
enable = lib.mkEnableOption "Timekpr-nExT, a screen time managing application that helps optimizing time spent at computer for your subordinates, children or even for yourself";
|
||||
adminUsers = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"alice"
|
||||
"bob"
|
||||
];
|
||||
description = ''
|
||||
All listed users will become part of the `timekpr` group so they can manage timekpr settings without requiring sudo.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.groups.timekpr = {
|
||||
gid = 2000;
|
||||
members = cfg.adminUsers;
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
# Add timekpr to system packages so that polkit can find it
|
||||
cfg.package
|
||||
];
|
||||
services.dbus.enable = true;
|
||||
services.dbus.packages = [
|
||||
cfg.package
|
||||
];
|
||||
environment.etc."timekpr" = {
|
||||
source = "${cfg.package}/etc/timekpr";
|
||||
};
|
||||
systemd.packages = [
|
||||
cfg.package
|
||||
];
|
||||
systemd.services.timekpr = {
|
||||
enable = true;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
security.polkit.enable = true;
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${targetBaseDir} 0755 ${daemonUser} ${daemonGroup} -"
|
||||
"d ${targetBaseDir}/config 0755 ${daemonUser} ${daemonGroup} -"
|
||||
"d ${targetBaseDir}/work 0755 ${daemonUser} ${daemonGroup} -"
|
||||
];
|
||||
};
|
||||
|
||||
meta.maintainers = [ lib.maintainers.atry ];
|
||||
}
|
||||
17
nixos/tests/timekpr.nix
Normal file
17
nixos/tests/timekpr.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{ pkgs, lib, ... }:
|
||||
{
|
||||
name = "timekpr";
|
||||
meta.maintainers = [ lib.maintainers.atry ];
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, lib, ... }:
|
||||
{
|
||||
services.timekpr.enable = true;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_file("/etc/timekpr/timekpr.conf")
|
||||
machine.wait_for_unit("timekpr.service")
|
||||
'';
|
||||
}
|
||||
150
pkgs/by-name/ti/timekpr/package.nix
Normal file
150
pkgs/by-name/ti/timekpr/package.nix
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
fetchgit,
|
||||
gitUpdater,
|
||||
glib,
|
||||
gobject-introspection,
|
||||
gtk3,
|
||||
lib,
|
||||
python3Packages,
|
||||
sound-theme-freedesktop,
|
||||
stdenv,
|
||||
wrapGAppsHook4,
|
||||
}:
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "timekpr";
|
||||
version = "0.5.8";
|
||||
|
||||
src = fetchgit {
|
||||
url = "https://git.launchpad.net/timekpr-next";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-Y0jAKl553HjoP59wJnKBKq4Ogko1cs8uazW2dy7AlBo=";
|
||||
};
|
||||
|
||||
buildInputs = [
|
||||
glib
|
||||
gtk3
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
gobject-introspection
|
||||
wrapGAppsHook4
|
||||
];
|
||||
|
||||
pyproject = true;
|
||||
|
||||
build-system = with python3Packages; [
|
||||
setuptools
|
||||
];
|
||||
|
||||
dependencies = with python3Packages; [
|
||||
dbus-python
|
||||
pygobject3
|
||||
psutil
|
||||
];
|
||||
|
||||
# Generate setup.py because the upstream repository does not include it
|
||||
SETUP_PY = ''
|
||||
from setuptools import setup, find_namespace_packages
|
||||
|
||||
package_dir={"timekpr": "."}
|
||||
setup(
|
||||
name="timekpr-next",
|
||||
version="${version}",
|
||||
package_dir=package_dir,
|
||||
packages=[
|
||||
f"{package_prefix}.{package_suffix}"
|
||||
for package_prefix, where in package_dir.items()
|
||||
for package_suffix in find_namespace_packages(where=where)
|
||||
],
|
||||
install_requires=[
|
||||
${lib.concatMapStringsSep ", " (dependency: "'${dependency.pname}'") dependencies}
|
||||
],
|
||||
)
|
||||
'';
|
||||
|
||||
postPatch = ''
|
||||
shopt -s globstar extglob nullglob
|
||||
|
||||
substituteInPlace bin/* **/*.py resource/server/systemd/timekpr.service \
|
||||
--replace-quiet /usr/lib/python3/dist-packages "$out"/${lib.escapeShellArg python3Packages.python.sitePackages}
|
||||
|
||||
substituteInPlace **/*.desktop **/*.policy **/*.service \
|
||||
--replace-fail /usr/bin/timekpr "$out"/bin/timekpr
|
||||
|
||||
substituteInPlace common/constants/constants.py \
|
||||
--replace-fail /usr/share/sounds/freedesktop ${lib.escapeShellArg sound-theme-freedesktop}/share/sounds/freedesktop \
|
||||
--replace-fail /usr/share/timekpr "$out"/share/timekpr \
|
||||
--replace-fail /usr/share/locale "$out"/share/locale
|
||||
|
||||
substituteInPlace resource/server/timekpr.conf \
|
||||
--replace-fail /usr/share/timekpr "$out"/share/timekpr \
|
||||
|
||||
# The original file name `timekpra` is renamed to `..timekpra-wrapped-wrapped` because `makeCWrapper` was used multiple times.
|
||||
substituteInPlace client/admin/adminprocessor.py \
|
||||
--replace-fail '"/timekpra" in ' '"/..timekpra-wrapped-wrapped" in '
|
||||
|
||||
printf %s "$SETUP_PY" > setup.py
|
||||
'';
|
||||
|
||||
# We need to manually inject $PYTHONPATH here, because `buildPythonApplication` does not recognize timekpr's executables as Python scripts, and therefore it does not automatically inject $PYTHONPATH into them.
|
||||
postFixup = ''
|
||||
for executable in $out/bin/*
|
||||
do
|
||||
wrapProgram "$executable" --prefix PYTHONPATH : "$PYTHONPATH"
|
||||
done
|
||||
'';
|
||||
|
||||
preInstall = ''
|
||||
while IFS= read -r line
|
||||
do
|
||||
# Trim leading/trailing whitespace
|
||||
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
|
||||
# Skip empty lines and comments
|
||||
if [[ -z "$line" || "$line" =~ ^# ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Separate source and destination
|
||||
# This assumes the destination is the last field and source path doesn't contain problematic spaces
|
||||
# More robust parsing might be needed if source paths have spaces.
|
||||
source_path=$(echo "$line" | awk '{ $NF=""; print $0 }' | sed 's/[[:space:]]*$//')
|
||||
dest_path=$(echo "$line" | awk '{ print $NF }')
|
||||
|
||||
# Check destination path prefix and map to $out/*
|
||||
case "$dest_path" in
|
||||
usr/share/*)
|
||||
# Remove "usr/" prefix and prepend "$out/"
|
||||
install -D --mode=444 "$source_path" --target-directory="$out/''${dest_path#usr/}"
|
||||
;;
|
||||
usr/bin/*)
|
||||
# Remove "usr/" prefix and prepend "$out/"
|
||||
install -D --mode=555 "$source_path" --target-directory="$out/''${dest_path#usr/}"
|
||||
;;
|
||||
etc/*|lib/*|var/*)
|
||||
# Prepend "$out/"
|
||||
install -D --mode=444 "$source_path" --target-directory="$out/$dest_path"
|
||||
;;
|
||||
usr/lib/python3/dist-packages/*)
|
||||
# Skip this line if the destination is a Python module
|
||||
# because it will be handled by the Python build process
|
||||
continue
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown destination prefix: '$dest_path'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done < debian/install
|
||||
'';
|
||||
|
||||
passthru.updateScript = gitUpdater { rev-prefix = "v"; };
|
||||
|
||||
meta = {
|
||||
description = "Manages and restricts user screen time by enforcing time limits";
|
||||
homepage = "https://mjasnik.gitlab.io/timekpr-next/";
|
||||
license = lib.licenses.gpl3;
|
||||
maintainers = [ lib.maintainers.atry ];
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user