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
|
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
|
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.
|
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": [
|
"sec-userborn": [
|
||||||
"index.html#sec-userborn"
|
"index.html#sec-userborn"
|
||||||
],
|
],
|
||||||
|
"sec-restrict-usage-time": [
|
||||||
|
"index.html#sec-restrict-usage-time"
|
||||||
|
],
|
||||||
"ch-file-systems": [
|
"ch-file-systems": [
|
||||||
"index.html#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).
|
- [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).
|
- [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).
|
- [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/sslmate-agent.nix
|
||||||
./services/security/step-ca.nix
|
./services/security/step-ca.nix
|
||||||
./services/security/tang.nix
|
./services/security/tang.nix
|
||||||
|
./services/security/timekpr.nix
|
||||||
./services/security/tor.nix
|
./services/security/tor.nix
|
||||||
./services/security/torify.nix
|
./services/security/torify.nix
|
||||||
./services/security/torsocks.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