Skip to content

Commit ce6e5f0

Browse files
committed
nixos/oncall: init
1 parent 4a57097 commit ce6e5f0

File tree

3 files changed

+206
-0
lines changed

3 files changed

+206
-0
lines changed

nixos/doc/manual/release-notes/rl-2505.section.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262

6363
- [vwifi](https://github.com/Raizo62/vwifi), a Wi-Fi simulator daemon leveraging the `mac80211_hwsim` and `vhost_vsock` kernel modules for efficient simulation of multi-node Wi-Fi networks. Available as {option}`services.vwifi`.
6464

65+
- [Oncall](https://oncall.tools), a web-based calendar tool designed for scheduling and managing on-call shifts. Available as [services.oncall](options.html#opt-services.oncall).
66+
6567
- [Homer](https://homer-demo.netlify.app/), a very simple static homepage for your server. Available as [services.homer](options.html#opt-services.homer).
6668

6769
- [Ghidra](https://ghidra-sre.org/), a software reverse engineering (SRE) suite of tools. Available as [programs.ghidra](options.html#opt-programs.ghidra).

nixos/modules/module-list.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,7 @@
16081608
./services/web-apps/nostr-rs-relay.nix
16091609
./services/web-apps/ocis.nix
16101610
./services/web-apps/olivetin.nix
1611+
./services/web-apps/oncall.nix
16111612
./services/web-apps/onlyoffice.nix
16121613
./services/web-apps/open-web-calendar.nix
16131614
./services/web-apps/openvscode-server.nix
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
{
2+
config,
3+
lib,
4+
pkgs,
5+
...
6+
}:
7+
let
8+
9+
cfg = config.services.oncall;
10+
settingsFormat = pkgs.formats.yaml { };
11+
configFile = settingsFormat.generate "oncall_extra_settings.yaml" cfg.settings;
12+
13+
in
14+
{
15+
options.services.oncall = {
16+
17+
enable = lib.mkEnableOption "Oncall web app";
18+
19+
package = lib.mkPackageOption pkgs "oncall" { };
20+
21+
database.createLocally = lib.mkEnableOption "Create the database and database user locally." // {
22+
default = true;
23+
};
24+
25+
settings = lib.mkOption {
26+
type = lib.types.submodule {
27+
freeformType = settingsFormat.type;
28+
options = {
29+
oncall_host = lib.mkOption {
30+
type = lib.types.str;
31+
default = "localhost";
32+
description = "FQDN for the Oncall instance.";
33+
};
34+
db.conn = {
35+
kwargs = {
36+
user = lib.mkOption {
37+
type = lib.types.str;
38+
default = "oncall";
39+
description = "Database user.";
40+
};
41+
host = lib.mkOption {
42+
type = lib.types.str;
43+
default = "localhost";
44+
description = "Database host.";
45+
};
46+
database = lib.mkOption {
47+
type = lib.types.str;
48+
default = "oncall";
49+
description = "Database name.";
50+
};
51+
};
52+
str = lib.mkOption {
53+
type = lib.types.str;
54+
default = "%(scheme)s://%(user)s@%(host)s:%(port)s/%(database)s?charset=%(charset)s&unix_socket=/run/mysqld/mysqld.sock";
55+
description = ''
56+
Database connection scheme. The default specifies the
57+
connection through a local socket.
58+
'';
59+
};
60+
require_auth = lib.mkOption {
61+
type = lib.types.bool;
62+
default = true;
63+
description = ''
64+
Whether authentication is required to access the web app.
65+
'';
66+
};
67+
};
68+
};
69+
};
70+
default = { };
71+
description = ''
72+
Extra configuration options to append or override.
73+
For available and default option values see
74+
[upstream configuration file](https://github.com/linkedin/oncall/blob/master/configs/config.yaml)
75+
and the administration part in the
76+
[offical documentation](https://oncall.tools/docs/admin_guide.html).
77+
'';
78+
};
79+
80+
secretFile = lib.mkOption {
81+
type = lib.types.pathWith {
82+
inStore = false;
83+
absolute = true;
84+
};
85+
example = "/run/keys/oncall-dbpassword";
86+
description = ''
87+
A YAML file containing secrets such as database or user passwords.
88+
Some variables that can be considered secrets are:
89+
90+
- db.conn.kwargs.password:
91+
Password used to authenticate to the database.
92+
93+
- session.encrypt_key:
94+
Key for encrypting/signing session cookies.
95+
Change to random long values in production.
96+
97+
- session.sign_key:
98+
Key for encrypting/signing session cookies.
99+
Change to random long values in production.
100+
'';
101+
};
102+
103+
};
104+
105+
config = lib.mkIf cfg.enable {
106+
107+
# Disable debug, only needed for development
108+
services.oncall.settings = lib.mkMerge [
109+
({
110+
debug = lib.mkDefault false;
111+
auth.debug = lib.mkDefault false;
112+
})
113+
];
114+
115+
services.uwsgi = {
116+
enable = true;
117+
plugins = [ "python3" ];
118+
user = "oncall";
119+
instance = {
120+
type = "emperor";
121+
vassals = {
122+
oncall = {
123+
type = "normal";
124+
env = [
125+
"PYTHONPATH=${pkgs.oncall.pythonPath}"
126+
(
127+
"ONCALL_EXTRA_CONFIG="
128+
+ (lib.concatStringsSep "," (
129+
[ configFile ] ++ lib.optional (cfg.secretFile != null) cfg.secretFile
130+
))
131+
)
132+
"STATIC_ROOT=/var/lib/oncall"
133+
];
134+
module = "oncall.app:get_wsgi_app()";
135+
socket = "${config.services.uwsgi.runDir}/oncall.sock";
136+
socketGroup = "nginx";
137+
immediate-gid = "nginx";
138+
chmod-socket = "770";
139+
pyargv = "${pkgs.oncall}/share/configs/config.yaml";
140+
buffer-size = 32768;
141+
};
142+
};
143+
};
144+
};
145+
146+
services.nginx = {
147+
enable = lib.mkDefault true;
148+
virtualHosts."${cfg.settings.oncall_host}".locations = {
149+
"/".extraConfig = "uwsgi_pass unix://${config.services.uwsgi.runDir}/oncall.sock;";
150+
};
151+
};
152+
153+
services.mysql = lib.mkIf cfg.database.createLocally {
154+
enable = true;
155+
package = lib.mkDefault pkgs.mariadb;
156+
ensureDatabases = [ cfg.settings.db.conn.kwargs.database ];
157+
ensureUsers = [
158+
{
159+
name = cfg.settings.db.conn.kwargs.user;
160+
ensurePermissions = {
161+
"${cfg.settings.db.conn.kwargs.database}.*" = "ALL PRIVILEGES";
162+
};
163+
}
164+
];
165+
};
166+
167+
users.users.oncall = {
168+
group = "nginx";
169+
isSystemUser = true;
170+
};
171+
172+
systemd = {
173+
services = {
174+
uwsgi.serviceConfig.StateDirectory = "oncall";
175+
oncall-setup-database = lib.mkIf cfg.database.createLocally {
176+
description = "Set up Oncall database";
177+
serviceConfig = {
178+
Type = "oneshot";
179+
RemainAfterExit = true;
180+
};
181+
requiredBy = [ "uwsgi.service" ];
182+
after = [ "mysql.service" ];
183+
script =
184+
let
185+
mysql = "${lib.getExe' config.services.mysql.package "mysql"}";
186+
in
187+
''
188+
if [ ! -f /var/lib/oncall/.dbexists ]; then
189+
# Load database schema provided with package
190+
${mysql} ${cfg.settings.db.conn.kwargs.database} < ${cfg.package}/share/db/schema.v0.sql
191+
${mysql} ${cfg.settings.db.conn.kwargs.database} < ${cfg.package}/share/db/schema-update.v0-1602184489.sql
192+
touch /var/lib/oncall/.dbexists
193+
fi
194+
'';
195+
};
196+
};
197+
};
198+
199+
};
200+
201+
meta.maintainers = with lib.maintainers; [ onny ];
202+
203+
}

0 commit comments

Comments
 (0)