eg25-control: port to s6 (hopefully)
This commit is contained in:
parent
4c0ae75b00
commit
19115dfb65
|
@ -64,6 +64,5 @@
|
||||||
"dialout" # TODO: figure out if dialout is required. that's for /dev/ttyUSB1, but geoclue probably doesn't read that?
|
"dialout" # TODO: figure out if dialout is required. that's for /dev/ttyUSB1, but geoclue probably doesn't read that?
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.services.eg25-control.enable = true;
|
|
||||||
sane.programs.where-am-i.enableFor.user.colin = true;
|
sane.programs.where-am-i.enableFor.user.colin = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
./dino.nix
|
./dino.nix
|
||||||
./dissent.nix
|
./dissent.nix
|
||||||
./dtrx.nix
|
./dtrx.nix
|
||||||
|
./eg25-control.nix
|
||||||
./element-desktop.nix
|
./element-desktop.nix
|
||||||
./engrampa.nix
|
./engrampa.nix
|
||||||
./epiphany.nix
|
./epiphany.nix
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.eg25-control;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.eg25-control = {
|
||||||
|
services.eg25-control-powered = {
|
||||||
|
description = "eg25-control-powered: power to the Qualcomm eg25 modem used by PinePhone";
|
||||||
|
startCommand = "eg25-control --power-on --verbose";
|
||||||
|
cleanupCommand = "eg25-control --power-off --verbose";
|
||||||
|
# depends = [ "ModemManager" ]
|
||||||
|
};
|
||||||
|
|
||||||
|
services.eg25-control-gps = {
|
||||||
|
# TODO: separate almanac upload from GPS enablement
|
||||||
|
# - don't want to re-upload the almanac everytime the GPS is toggled
|
||||||
|
# - want to upload almanac even when GPS *isn't* enabled, if we have internet connection.
|
||||||
|
description = "eg25-control-gps: background GPS tracking";
|
||||||
|
startCommand = "eg25-control --enable-gps --dump-debug-info --verbose";
|
||||||
|
cleanupCommand = "eg25-control --disable-gps --dump-debug-info --verbose";
|
||||||
|
depends = [ "eg25-control-powered" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: port to s6
|
||||||
|
systemd.services.eg25-control-freshen-agps = lib.mkIf cfg.enabled {
|
||||||
|
description = "keep assisted-GPS data fresh";
|
||||||
|
serviceConfig = {
|
||||||
|
# XXX: this can have a race condition with eg25-control-gps
|
||||||
|
# - eg25-control-gps initiates DL of new/<agps>
|
||||||
|
# - eg25-control-gps tests new/<agps>: it works
|
||||||
|
# - eg25-control-freshen-agps initiates DL of new/<agps>
|
||||||
|
# - eg25-control-gps: moves new/<agps> into cache/
|
||||||
|
# - but it moved the result (possibly incomplete) of eg25-control-freshen-agps, incorrectly
|
||||||
|
# in practice, i don't expect much issue from this.
|
||||||
|
ExecStart = "${cfg.package}/bin/eg25-control --ensure-agps-cache --verbose";
|
||||||
|
Restart = "no";
|
||||||
|
|
||||||
|
User = "eg25-control";
|
||||||
|
WorkingDirectory = "/var/lib/eg25-control";
|
||||||
|
StateDirectory = "eg25-control";
|
||||||
|
};
|
||||||
|
startAt = "hourly"; # this is a bit more than necessary, but idk systemd calendar syntax
|
||||||
|
after = [ "network-online.target" "nss-lookup.target" ];
|
||||||
|
requires = [ "network-online.target" ];
|
||||||
|
# wantedBy = [ "network-online.target" ]; # auto-start immediately after boot
|
||||||
|
};
|
||||||
|
users = lib.mkIf cfg.enabled {
|
||||||
|
groups.eg25-control = {};
|
||||||
|
users.eg25-control = {
|
||||||
|
group = "eg25-control";
|
||||||
|
isSystemUser = true;
|
||||||
|
home = "/var/lib/eg25-control";
|
||||||
|
extraGroups = [
|
||||||
|
"dialout" # required to read /dev/ttyUSB1
|
||||||
|
"networkmanager" # required to authenticate with mmcli
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
sane.persist.sys.byStore.plaintext = lib.mkIf cfg.enabled [
|
||||||
|
# to persist agps data, i think.
|
||||||
|
{ user = "eg25-control"; group = "eg25-control"; path = "/var/lib/eg25-control"; }
|
||||||
|
];
|
||||||
|
}
|
|
@ -9,8 +9,8 @@ let
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
gps = serviceButton "systemd" "eg25-control-gps" ""; # GPS services; other icons: gps, ⌖, 🛰, 🌎,
|
gps = serviceButton "s6" "eg25-control-gps" ""; # GPS services; other icons: gps, ⌖, 🛰, 🌎,
|
||||||
cell-modem = serviceButton "systemd" "eg25-control-powered" ""; # icons: 5g, 📡, 📱, ᯤ, ⚡, , 🌐, 📶, 🗼, , , ,
|
cell-modem = serviceButton "s6" "eg25-control-powered" ""; # icons: 5g, 📡, 📱, ᯤ, ⚡, , 🌐, 📶, 🗼, , , ,
|
||||||
vpn = serviceButton "systemd" "wg-quick-vpn-servo" "vpn::hn";
|
vpn = serviceButton "systemd" "wg-quick-vpn-servo" "vpn::hn";
|
||||||
|
|
||||||
gnome-calls = serviceButton "s6" "gnome-calls" "SIP";
|
gnome-calls = serviceButton "s6" "gnome-calls" "SIP";
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
imports = [
|
imports = [
|
||||||
./clightning.nix
|
./clightning.nix
|
||||||
./dyn-dns.nix
|
./dyn-dns.nix
|
||||||
./eg25-control.nix
|
|
||||||
./eg25-manager.nix
|
./eg25-manager.nix
|
||||||
./kiwix-serve.nix
|
./kiwix-serve.nix
|
||||||
./mautrix-signal.nix
|
./mautrix-signal.nix
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.sane.services.eg25-control;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.sane.services.eg25-control = with lib; {
|
|
||||||
enable = mkEnableOption "Quectel EG25 modem configuration scripts. alternative to eg25-manager";
|
|
||||||
package = mkOption {
|
|
||||||
type = types.package;
|
|
||||||
default = pkgs.eg25-control;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
users.groups.eg25-control = {};
|
|
||||||
users.users.eg25-control = {
|
|
||||||
group = "eg25-control";
|
|
||||||
isSystemUser = true;
|
|
||||||
home = "/var/lib/eg25-control";
|
|
||||||
extraGroups = [
|
|
||||||
"dialout" # required to read /dev/ttyUSB1
|
|
||||||
"networkmanager" # required to authenticate with mmcli
|
|
||||||
];
|
|
||||||
};
|
|
||||||
sane.persist.sys.byStore.plaintext = [
|
|
||||||
{ user = "eg25-control"; group = "eg25-control"; path = "/var/lib/eg25-control"; }
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.services.eg25-control-powered = {
|
|
||||||
description = "power to the Qualcomm eg25 modem used by PinePhone";
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
ExecStart = "${cfg.package}/bin/eg25-control --power-on --verbose";
|
|
||||||
ExecStop = "${cfg.package}/bin/eg25-control --power-off --verbose";
|
|
||||||
Restart = "on-failure";
|
|
||||||
RestartSec = "60s";
|
|
||||||
TimeoutSec = "60s";
|
|
||||||
|
|
||||||
# XXX /sys/class/modem-power/modem-power/device/powered is writable only by root
|
|
||||||
# User = "eg25-control";
|
|
||||||
# WorkingDirectory = "/var/lib/eg25-control";
|
|
||||||
# StateDirectory = "eg25-control";
|
|
||||||
};
|
|
||||||
after = [ "ModemManager.service" ];
|
|
||||||
wants = [ "ModemManager.service" ];
|
|
||||||
# wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
systemd.services.eg25-control-gps = {
|
|
||||||
# TODO: separate almanac upload from GPS enablement
|
|
||||||
# - don't want to re-upload the almanac everytime the GPS is toggled
|
|
||||||
# - want to upload almanac even when GPS *isn't* enabled, if we have internet connection.
|
|
||||||
description = "background GPS tracking";
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "simple";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
ExecStart = "${cfg.package}/bin/eg25-control --enable-gps --dump-debug-info --verbose";
|
|
||||||
ExecStop = "${cfg.package}/bin/eg25-control --disable-gps --dump-debug-info --verbose";
|
|
||||||
Restart = "on-failure";
|
|
||||||
RestartSec = "60s";
|
|
||||||
|
|
||||||
User = "eg25-control";
|
|
||||||
WorkingDirectory = "/var/lib/eg25-control";
|
|
||||||
StateDirectory = "eg25-control";
|
|
||||||
};
|
|
||||||
after = [ "eg25-control-powered.service" ];
|
|
||||||
requires = [ "eg25-control-powered.service" ];
|
|
||||||
# wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.eg25-control-freshen-agps = {
|
|
||||||
description = "keep assisted-GPS data fresh";
|
|
||||||
serviceConfig = {
|
|
||||||
# XXX: this can have a race condition with eg25-control-gps
|
|
||||||
# - eg25-control-gps initiates DL of new/<agps>
|
|
||||||
# - eg25-control-gps tests new/<agps>: it works
|
|
||||||
# - eg25-control-freshen-agps initiates DL of new/<agps>
|
|
||||||
# - eg25-control-gps: moves new/<agps> into cache/
|
|
||||||
# - but it moved the result (possibly incomplete) of eg25-control-freshen-agps, incorrectly
|
|
||||||
# in practice, i don't expect much issue from this.
|
|
||||||
ExecStart = "${cfg.package}/bin/eg25-control --ensure-agps-cache --verbose";
|
|
||||||
Restart = "no";
|
|
||||||
|
|
||||||
User = "eg25-control";
|
|
||||||
WorkingDirectory = "/var/lib/eg25-control";
|
|
||||||
StateDirectory = "eg25-control";
|
|
||||||
};
|
|
||||||
startAt = "hourly"; # this is a bit more than necessary, but idk systemd calendar syntax
|
|
||||||
after = [ "network-online.target" "nss-lookup.target" ];
|
|
||||||
requires = [ "network-online.target" ];
|
|
||||||
# wantedBy = [ "network-online.target" ]; # auto-start immediately after boot
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -49,6 +49,15 @@ let
|
||||||
restart of the service (if applicable) is blocked on this command.
|
restart of the service (if applicable) is blocked on this command.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
startCommand = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
command which is run to start the service.
|
||||||
|
this command is expected to exit once the service is up, contrary to the normal `command` argument.
|
||||||
|
mutually exclusive to `command`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
readiness.waitCommand = mkOption {
|
readiness.waitCommand = mkOption {
|
||||||
type = types.nullOr (types.coercedTo types.package toString types.str);
|
type = types.nullOr (types.coercedTo types.package toString types.str);
|
||||||
default = null;
|
default = null;
|
||||||
|
|
|
@ -62,10 +62,13 @@ let
|
||||||
# }
|
# }
|
||||||
fsToDerivation = fs: fsItemToDerivation "/" { dir = fs; };
|
fsToDerivation = fs: fsItemToDerivation "/" { dir = fs; };
|
||||||
|
|
||||||
# infers the service type from the arguments and creates an attrset usable by `fsToDerivation`.
|
# infers some service settings from the arguments and creates an attrset usable by `fsToDerivation`.
|
||||||
# also configures the service for logging, if applicable.
|
# also configures the service for logging, if applicable.
|
||||||
serviceToFs = { name, check, contents, depends, finish, run }: let
|
# type can be:
|
||||||
type = if run != null then "longrun" else "bundle";
|
# - "longrun"
|
||||||
|
# - "bundle"
|
||||||
|
# - "oneshot"?
|
||||||
|
serviceToFs = { name, check, contents, depends, finish, run, type }: let
|
||||||
logger = serviceToFs' {
|
logger = serviceToFs' {
|
||||||
name = "logger:${name}";
|
name = "logger:${name}";
|
||||||
consumerFor = name;
|
consumerFor = name;
|
||||||
|
@ -75,8 +78,8 @@ let
|
||||||
in (serviceToFs' {
|
in (serviceToFs' {
|
||||||
inherit name check depends finish run type;
|
inherit name check depends finish run type;
|
||||||
contents = maybe (type == "bundle") contents;
|
contents = maybe (type == "bundle") contents;
|
||||||
producerFor = maybe (type == "longrun") "logger:${name}";
|
producerFor = maybe (type != "bundle") "logger:${name}";
|
||||||
}) // (lib.optionalAttrs (type == "longrun") logger);
|
}) // (lib.optionalAttrs (type != "bundle") logger);
|
||||||
|
|
||||||
serviceToFs'= {
|
serviceToFs'= {
|
||||||
name,
|
name,
|
||||||
|
@ -221,7 +224,7 @@ let
|
||||||
|
|
||||||
# transform the `user.services` attrset into a s6 services list.
|
# transform the `user.services` attrset into a s6 services list.
|
||||||
s6SvcsFromConfigServices = services: lib.mapAttrsToList
|
s6SvcsFromConfigServices = services: lib.mapAttrsToList
|
||||||
(name: service: {
|
(name: service: rec {
|
||||||
inherit name;
|
inherit name;
|
||||||
check = service.readiness.waitCommand;
|
check = service.readiness.waitCommand;
|
||||||
contents = builtins.attrNames (
|
contents = builtins.attrNames (
|
||||||
|
@ -231,7 +234,13 @@ let
|
||||||
lib.filterAttrs (_: cfg: lib.elem name cfg.dependencyOf) services
|
lib.filterAttrs (_: cfg: lib.elem name cfg.dependencyOf) services
|
||||||
);
|
);
|
||||||
finish = service.cleanupCommand;
|
finish = service.cleanupCommand;
|
||||||
run = service.command;
|
inherit (if service.startCommand != null then
|
||||||
|
{ type="oneshot"; run = service.startCommand; }
|
||||||
|
else if service.command != null then
|
||||||
|
{ type="longshot"; run = service.command; }
|
||||||
|
else
|
||||||
|
{ type="bundle"; run = null; }
|
||||||
|
) type run;
|
||||||
})
|
})
|
||||||
services
|
services
|
||||||
;
|
;
|
||||||
|
|
Loading…
Reference in New Issue