mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-12 05:16:25 +03:00
Merge master into staging-next
This commit is contained in:
commit
60fbf92c10
116 changed files with 2548 additions and 828 deletions
|
@ -103,6 +103,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
|||
|
||||
- [Monado](https://monado.freedesktop.org/), an open source XR runtime. Available as [services.monado](#opt-services.monado.enable).
|
||||
|
||||
- [Pretix](https://pretix.eu/about/en/), an open source ticketing software for events. Available as [services.pretix]($opt-services-pretix.enable).
|
||||
|
||||
- [Clevis](https://github.com/latchset/clevis), a pluggable framework for automated decryption, used to unlock encrypted devices in initrd. Available as [boot.initrd.clevis.enable](#opt-boot.initrd.clevis.enable).
|
||||
|
||||
- [armagetronad](https://wiki.armagetronad.org), a mid-2000s 3D lightcycle game widely played at iD Tech Camps. You can define multiple servers using `services.armagetronad.<server>.enable`.
|
||||
|
@ -320,7 +322,12 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
|||
|
||||
- `addDriverRunpath` has been added to facilitate the deprecation of the old `addOpenGLRunpath` setuphook. This change is motivated by the evolution of the setuphook to include all hardware acceleration.
|
||||
|
||||
- Cinnamon has been updated to 6.0. Please beware that the [Wayland session](https://blog.linuxmint.com/?p=4591) is still experimental in this release.
|
||||
- Cinnamon has been updated to 6.0. Please beware that the [Wayland session](https://blog.linuxmint.com/?p=4591) is still experimental in this release and could potentially [affect Xorg sessions](https://blog.linuxmint.com/?p=4639). We suggest a reboot when switching between sessions.
|
||||
|
||||
- MATE has been updated to 1.28.
|
||||
- To properly support panel plugins built with Wayland (in-process) support, we are introducing `services.xserver.desktopManager.mate.extraPanelApplets` option, please use that for installing panel applets.
|
||||
- Similarly, please use `services.xserver.desktopManager.mate.extraCajaExtensions` option for installing Caja extensions.
|
||||
- To use the Wayland session, enable `services.xserver.desktopManager.mate.enableWaylandSession`. This is opt-in for now as it is in early stage and introduces a new set of Wayfire closure. Due to [known issues with LightDM](https://github.com/canonical/lightdm/issues/63), we suggest using SDDM for display manager.
|
||||
|
||||
- New `boot.loader.systemd-boot.xbootldrMountPoint` allows setting up a separate [XBOOTLDR partition](https://uapi-group.org/specifications/specs/boot_loader_specification/) to store boot files. Useful on systems with a small EFI System partition that cannot be easily repartitioned.
|
||||
|
||||
|
@ -347,6 +354,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
|||
|
||||
- [Lilypond](https://lilypond.org/index.html) and [Denemo](https://www.denemo.org) are now compiled with Guile 3.0.
|
||||
|
||||
- The EC2 image module now enables the [Amazon SSM Agent](https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html) by default.
|
||||
|
||||
- The following options of the Nextcloud module were moved into [`services.nextcloud.settings`](#opt-services.nextcloud.settings) and renamed to match the name from Nextcloud's `config.php`:
|
||||
- `logLevel` -> [`loglevel`](#opt-services.nextcloud.settings.loglevel),
|
||||
- `logType` -> [`log_type`](#opt-services.nextcloud.settings.log_type),
|
||||
|
|
|
@ -30,7 +30,10 @@ in
|
|||
ipu6-drivers
|
||||
];
|
||||
|
||||
hardware.firmware = [ pkgs.ipu6-camera-bins ];
|
||||
hardware.firmware = with pkgs; [
|
||||
ipu6-camera-bins
|
||||
ivsc-firmware
|
||||
];
|
||||
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM=="intel-ipu6-psys", MODE="0660", GROUP="video"
|
||||
|
|
|
@ -1358,6 +1358,7 @@
|
|||
./services/web-apps/plausible.nix
|
||||
./services/web-apps/powerdns-admin.nix
|
||||
./services/web-apps/pretalx.nix
|
||||
./services/web-apps/pretix.nix
|
||||
./services/web-apps/prosody-filer.nix
|
||||
./services/web-apps/rimgo.nix
|
||||
./services/web-apps/sftpgo.nix
|
||||
|
|
|
@ -600,6 +600,7 @@ in
|
|||
description = "Ensure that NetworkManager declarative profiles are created";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
before = [ "network-online.target" ];
|
||||
after = [ "NetworkManager.service" ];
|
||||
script = let
|
||||
path = id: "/run/NetworkManager/system-connections/${id}.nmconnection";
|
||||
in ''
|
||||
|
@ -609,9 +610,7 @@ in
|
|||
${pkgs.envsubst}/bin/envsubst -i ${ini.generate (lib.escapeShellArg profile.n) profile.v} > ${path (lib.escapeShellArg profile.n)}
|
||||
'') (lib.mapAttrsToList (n: v: { inherit n v; }) cfg.ensureProfiles.profiles)
|
||||
+ ''
|
||||
if systemctl is-active --quiet NetworkManager; then
|
||||
${pkgs.networkmanager}/bin/nmcli connection reload
|
||||
fi
|
||||
${pkgs.networkmanager}/bin/nmcli connection reload
|
||||
'';
|
||||
serviceConfig = {
|
||||
EnvironmentFile = cfg.ensureProfiles.environmentFiles;
|
||||
|
|
|
@ -1,99 +1,122 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.komga;
|
||||
|
||||
in {
|
||||
inherit (lib) mkOption mkEnableOption maintainers;
|
||||
inherit (lib.types) port str bool;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.komga = {
|
||||
enable = mkEnableOption (lib.mdDoc "Komga, a free and open source comics/mangas media server");
|
||||
enable = mkEnableOption "Komga, a free and open source comics/mangas media server";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
type = port;
|
||||
default = 8080;
|
||||
description = lib.mdDoc ''
|
||||
The port that Komga will listen on.
|
||||
'';
|
||||
description = "The port that Komga will listen on.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
type = str;
|
||||
default = "komga";
|
||||
description = lib.mdDoc ''
|
||||
User account under which Komga runs.
|
||||
'';
|
||||
description = "User account under which Komga runs.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
type = str;
|
||||
default = "komga";
|
||||
description = lib.mdDoc ''
|
||||
Group under which Komga runs.
|
||||
'';
|
||||
description = "Group under which Komga runs.";
|
||||
};
|
||||
|
||||
stateDir = mkOption {
|
||||
type = types.str;
|
||||
type = str;
|
||||
default = "/var/lib/komga";
|
||||
description = lib.mdDoc ''
|
||||
State and configuration directory Komga will use.
|
||||
'';
|
||||
description = "State and configuration directory Komga will use.";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
type = bool;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Whether to open the firewall for the port in {option}`services.komga.port`.
|
||||
'';
|
||||
description = "Whether to open the firewall for the port in {option}`services.komga.port`.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config =
|
||||
let
|
||||
inherit (lib) mkIf getExe;
|
||||
in
|
||||
mkIf cfg.enable {
|
||||
|
||||
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
|
||||
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
|
||||
|
||||
users.groups = mkIf (cfg.group == "komga") {
|
||||
komga = {};
|
||||
};
|
||||
users.groups = mkIf (cfg.group == "komga") { komga = { }; };
|
||||
|
||||
users.users = mkIf (cfg.user == "komga") {
|
||||
komga = {
|
||||
group = cfg.group;
|
||||
home = cfg.stateDir;
|
||||
description = "Komga Daemon user";
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.komga = {
|
||||
environment = {
|
||||
SERVER_PORT = builtins.toString cfg.port;
|
||||
KOMGA_CONFIGDIR = cfg.stateDir;
|
||||
users.users = mkIf (cfg.user == "komga") {
|
||||
komga = {
|
||||
group = cfg.group;
|
||||
home = cfg.stateDir;
|
||||
description = "Komga Daemon user";
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
|
||||
description = "Komga is a free and open source comics/mangas media server";
|
||||
systemd.services.komga = {
|
||||
environment = {
|
||||
SERVER_PORT = builtins.toString cfg.port;
|
||||
KOMGA_CONFIGDIR = cfg.stateDir;
|
||||
};
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
description = "Komga is a free and open source comics/mangas media server";
|
||||
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
ExecStart = "${pkgs.komga}/bin/komga";
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
|
||||
StateDirectory = mkIf (cfg.stateDir == "/var/lib/komga") "komga";
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
ExecStart = getExe pkgs.komga;
|
||||
|
||||
StateDirectory = mkIf (cfg.stateDir == "/var/lib/komga") "komga";
|
||||
|
||||
RemoveIPC = true;
|
||||
NoNewPrivileges = true;
|
||||
CapabilityBoundingSet = "";
|
||||
SystemCallFilter = [ "@system-service" ];
|
||||
ProtectSystem = "full";
|
||||
PrivateTmp = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectClock = true;
|
||||
ProcSubset = "pid";
|
||||
PrivateUsers = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelTunables = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
];
|
||||
LockPersonality = true;
|
||||
RestrictNamespaces = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelModules = true;
|
||||
SystemCallArchitectures = "native";
|
||||
RestrictSUIDSGID = true;
|
||||
RestrictRealtime = true;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ govanify ];
|
||||
}
|
||||
|
|
579
nixos/modules/services/web-apps/pretix.nix
Normal file
579
nixos/modules/services/web-apps/pretix.nix
Normal file
|
@ -0,0 +1,579 @@
|
|||
{ config
|
||||
, lib
|
||||
, pkgs
|
||||
, utils
|
||||
, ...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
concatMapStringsSep
|
||||
escapeShellArgs
|
||||
filter
|
||||
filterAttrs
|
||||
getExe
|
||||
getExe'
|
||||
isAttrs
|
||||
isList
|
||||
literalExpression
|
||||
mapAttrs
|
||||
mkDefault
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
optionals
|
||||
optionalString
|
||||
recursiveUpdate
|
||||
types
|
||||
;
|
||||
|
||||
filterRecursiveNull = o:
|
||||
if isAttrs o then
|
||||
mapAttrs (_: v: filterRecursiveNull v) (filterAttrs (_: v: v != null) o)
|
||||
else if isList o then
|
||||
map filterRecursiveNull (filter (v: v != null) o)
|
||||
else
|
||||
o;
|
||||
|
||||
cfg = config.services.pretix;
|
||||
format = pkgs.formats.ini { };
|
||||
|
||||
configFile = format.generate "pretix.cfg" (filterRecursiveNull cfg.settings);
|
||||
|
||||
finalPackage = cfg.package.override {
|
||||
inherit (cfg) plugins;
|
||||
};
|
||||
|
||||
pythonEnv = cfg.package.python.buildEnv.override {
|
||||
extraLibs = with cfg.package.python.pkgs; [
|
||||
(toPythonModule finalPackage)
|
||||
gunicorn
|
||||
]
|
||||
++ lib.optionals (cfg.settings.memcached.location != null)
|
||||
cfg.package.optional-dependencies.memcached
|
||||
;
|
||||
};
|
||||
|
||||
withRedis = cfg.settings.redis.location != null;
|
||||
in
|
||||
{
|
||||
meta = with lib; {
|
||||
maintainers = with maintainers; [ hexa ];
|
||||
};
|
||||
|
||||
options.services.pretix = {
|
||||
enable = mkEnableOption "pretix";
|
||||
|
||||
package = mkPackageOption pkgs "pretix" { };
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "pretix";
|
||||
description = ''
|
||||
Group under which pretix should run.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "pretix";
|
||||
description = ''
|
||||
User under which pretix should run.
|
||||
'';
|
||||
};
|
||||
|
||||
environmentFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/run/keys/pretix-secrets.env";
|
||||
description = ''
|
||||
Environment file to pass secret configuration values.
|
||||
|
||||
Each line must follow the `PRETIX_SECTION_KEY=value` pattern.
|
||||
'';
|
||||
};
|
||||
|
||||
plugins = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
example = literalExpression ''
|
||||
with config.services.pretix.package.plugins; [
|
||||
passbook
|
||||
pages
|
||||
];
|
||||
'';
|
||||
description = ''
|
||||
Pretix plugins to install into the Python environment.
|
||||
'';
|
||||
};
|
||||
|
||||
gunicorn.extraArgs = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [
|
||||
"--name=pretix"
|
||||
];
|
||||
example = [
|
||||
"--name=pretix"
|
||||
"--workers=4"
|
||||
"--max-requests=1200"
|
||||
"--max-requests-jitter=50"
|
||||
"--log-level=info"
|
||||
];
|
||||
description = ''
|
||||
Extra arguments to pass to gunicorn.
|
||||
See <https://docs.pretix.eu/en/latest/admin/installation/manual_smallscale.html#start-pretix-as-a-service> for details.
|
||||
'';
|
||||
apply = escapeShellArgs;
|
||||
};
|
||||
|
||||
celery = {
|
||||
extraArgs = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Extra arguments to pass to celery.
|
||||
|
||||
See <https://docs.celeryq.dev/en/stable/reference/cli.html#celery-worker> for more info.
|
||||
'';
|
||||
apply = utils.escapeSystemdExecArgs;
|
||||
};
|
||||
};
|
||||
|
||||
nginx = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether to set up an nginx virtual host.
|
||||
'';
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
example = "talks.example.com";
|
||||
description = ''
|
||||
The domain name under which to set up the virtual host.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
database.createLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether to automatically set up the database on the local DBMS instance.
|
||||
|
||||
Only supported for PostgreSQL. Not required for sqlite.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = format.type;
|
||||
options = {
|
||||
pretix = {
|
||||
instance_name = mkOption {
|
||||
type = types.str;
|
||||
example = "tickets.example.com";
|
||||
description = ''
|
||||
The name of this installation.
|
||||
'';
|
||||
};
|
||||
|
||||
url = mkOption {
|
||||
type = types.str;
|
||||
example = "https://tickets.example.com";
|
||||
description = ''
|
||||
The installation’s full URL, without a trailing slash.
|
||||
'';
|
||||
};
|
||||
|
||||
cachedir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/cache/pretix";
|
||||
description = ''
|
||||
Directory for storing temporary files.
|
||||
'';
|
||||
};
|
||||
|
||||
datadir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/pretix";
|
||||
description = ''
|
||||
Directory for storing user uploads and similar data.
|
||||
'';
|
||||
};
|
||||
|
||||
logdir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/log/pretix";
|
||||
description = ''
|
||||
Directory for storing log files.
|
||||
'';
|
||||
};
|
||||
|
||||
currency = mkOption {
|
||||
type = types.str;
|
||||
default = "EUR";
|
||||
example = "USD";
|
||||
description = ''
|
||||
Default currency for events in its ISO 4217 three-letter code.
|
||||
'';
|
||||
};
|
||||
|
||||
registration = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to allow registration of new admin users.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
database = {
|
||||
backend = mkOption {
|
||||
type = types.enum [
|
||||
"sqlite3"
|
||||
"postgresql"
|
||||
];
|
||||
default = "postgresql";
|
||||
description = ''
|
||||
Database backend to use.
|
||||
|
||||
Only postgresql is recommended for production setups.
|
||||
'';
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = with types; nullOr types.path;
|
||||
default = if cfg.settings.database.backend == "postgresql" then "/run/postgresql" else null;
|
||||
defaultText = literalExpression ''
|
||||
if config.services.pretix.settings..database.backend == "postgresql" then "/run/postgresql"
|
||||
else null
|
||||
'';
|
||||
description = ''
|
||||
Database host or socket path.
|
||||
'';
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "pretix";
|
||||
description = ''
|
||||
Database name.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "pretix";
|
||||
description = ''
|
||||
Database username.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
mail = {
|
||||
from = mkOption {
|
||||
type = types.str;
|
||||
example = "tickets@example.com";
|
||||
description = ''
|
||||
E-Mail address used in the `FROM` header of outgoing mails.
|
||||
'';
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
example = "mail.example.com";
|
||||
description = ''
|
||||
Hostname of the SMTP server use for mail delivery.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 25;
|
||||
example = 587;
|
||||
description = ''
|
||||
Port of the SMTP server to use for mail delivery.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
celery = {
|
||||
backend = mkOption {
|
||||
type = types.str;
|
||||
default = "redis+socket://${config.services.redis.servers.pretix.unixSocket}?virtual_host=1";
|
||||
defaultText = literalExpression ''
|
||||
optionalString config.services.pretix.celery.enable "redis+socket://''${config.services.redis.servers.pretix.unixSocket}?virtual_host=1"
|
||||
'';
|
||||
description = ''
|
||||
URI to the celery backend used for the asynchronous job queue.
|
||||
'';
|
||||
};
|
||||
|
||||
broker = mkOption {
|
||||
type = types.str;
|
||||
default = "redis+socket://${config.services.redis.servers.pretix.unixSocket}?virtual_host=2";
|
||||
defaultText = literalExpression ''
|
||||
optionalString config.services.pretix.celery.enable "redis+socket://''${config.services.redis.servers.pretix.unixSocket}?virtual_host=2"
|
||||
'';
|
||||
description = ''
|
||||
URI to the celery broker used for the asynchronous job queue.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
redis = {
|
||||
location = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = "unix://${config.services.redis.servers.pretix.unixSocket}?db=0";
|
||||
defaultText = literalExpression ''
|
||||
"unix://''${config.services.redis.servers.pretix.unixSocket}?db=0"
|
||||
'';
|
||||
description = ''
|
||||
URI to the redis server, used to speed up locking, caching and session storage.
|
||||
'';
|
||||
};
|
||||
|
||||
sessions = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether to use redis as the session storage.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
memcached = {
|
||||
location = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "127.0.0.1:11211";
|
||||
description = ''
|
||||
The `host:port` combination or the path to the UNIX socket of a memcached instance.
|
||||
|
||||
Can be used instead of Redis for caching.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
tools = {
|
||||
pdftk = mkOption {
|
||||
type = types.path;
|
||||
default = getExe pkgs.pdftk;
|
||||
defaultText = literalExpression ''
|
||||
lib.getExe pkgs.pdftk
|
||||
'';
|
||||
description = ''
|
||||
Path to the pdftk executable.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
pretix configuration as a Nix attribute set. All settings can also be passed
|
||||
from the environment.
|
||||
|
||||
See <https://docs.pretix.eu/en/latest/admin/config.html> for possible options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# https://docs.pretix.eu/en/latest/admin/installation/index.html
|
||||
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeScriptBin "pretix-manage" ''
|
||||
cd ${cfg.settings.pretix.datadir}
|
||||
sudo=exec
|
||||
if [[ "$USER" != ${cfg.user} ]]; then
|
||||
sudo='exec /run/wrappers/bin/sudo -u ${cfg.user} ${optionalString withRedis "-g redis-pretix"} --preserve-env=PRETIX_CONFIG_FILE'
|
||||
fi
|
||||
export PRETIX_CONFIG_FILE=${configFile}
|
||||
$sudo ${getExe' pythonEnv "pretix-manage"} "$@"
|
||||
'')
|
||||
];
|
||||
|
||||
services = {
|
||||
nginx = mkIf cfg.nginx.enable {
|
||||
enable = true;
|
||||
recommendedGzipSettings = mkDefault true;
|
||||
recommendedOptimisation = mkDefault true;
|
||||
recommendedProxySettings = mkDefault true;
|
||||
recommendedTlsSettings = mkDefault true;
|
||||
upstreams.pretix.servers."unix:/run/pretix/pretix.sock" = { };
|
||||
virtualHosts.${cfg.nginx.domain} = {
|
||||
# https://docs.pretix.eu/en/latest/admin/installation/manual_smallscale.html#ssl
|
||||
extraConfig = ''
|
||||
more_set_headers Referrer-Policy same-origin;
|
||||
more_set_headers X-Content-Type-Options nosniff;
|
||||
'';
|
||||
locations = {
|
||||
"/".proxyPass = "http://pretix";
|
||||
"/media/" = {
|
||||
alias = "${cfg.settings.pretix.datadir}/media/";
|
||||
extraConfig = ''
|
||||
access_log off;
|
||||
expires 7d;
|
||||
'';
|
||||
};
|
||||
"^~ /media/(cachedfiles|invoices)" = {
|
||||
extraConfig = ''
|
||||
deny all;
|
||||
return 404;
|
||||
'';
|
||||
};
|
||||
"/static/" = {
|
||||
alias = "${finalPackage}/${cfg.package.python.sitePackages}/pretix/static.dist/";
|
||||
extraConfig = ''
|
||||
access_log off;
|
||||
more_set_headers Cache-Control "public";
|
||||
expires 365d;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
postgresql = mkIf (cfg.database.createLocally && cfg.settings.database.backend == "postgresql") {
|
||||
enable = true;
|
||||
ensureUsers = [ {
|
||||
name = cfg.settings.database.user;
|
||||
ensureDBOwnership = true;
|
||||
} ];
|
||||
ensureDatabases = [ cfg.settings.database.name ];
|
||||
};
|
||||
|
||||
redis.servers.pretix.enable = withRedis;
|
||||
};
|
||||
|
||||
systemd.services = let
|
||||
commonUnitConfig = {
|
||||
environment.PRETIX_CONFIG_FILE = configFile;
|
||||
serviceConfig = {
|
||||
User = "pretix";
|
||||
Group = "pretix";
|
||||
EnvironmentFile = optionals (cfg.environmentFile != null) [
|
||||
cfg.environmentFile
|
||||
];
|
||||
StateDirectory = [
|
||||
"pretix"
|
||||
];
|
||||
CacheDirectory = "pretix";
|
||||
LogsDirectory = "pretix";
|
||||
WorkingDirectory = cfg.settings.pretix.datadir;
|
||||
SupplementaryGroups = optionals withRedis [
|
||||
"redis-pretix"
|
||||
];
|
||||
AmbientCapabilities = "";
|
||||
CapabilityBoundingSet = [ "" ];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"@chown"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
};
|
||||
in {
|
||||
pretix-web = recursiveUpdate commonUnitConfig {
|
||||
description = "pretix web service";
|
||||
after = [
|
||||
"network.target"
|
||||
"redis-pretix.service"
|
||||
"postgresql.service"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
preStart = ''
|
||||
versionFile="${cfg.settings.pretix.datadir}/.version"
|
||||
version=$(cat "$versionFile" 2>/dev/null || echo 0)
|
||||
|
||||
pluginsFile="${cfg.settings.pretix.datadir}/.plugins"
|
||||
plugins=$(cat "$pluginsFile" 2>/dev/null || echo "")
|
||||
configuredPlugins="${concatMapStringsSep "|" (package: package.name) cfg.plugins}"
|
||||
|
||||
if [[ $version != ${cfg.package.version} || $plugins != $configuredPlugins ]]; then
|
||||
${getExe' pythonEnv "pretix-manage"} migrate
|
||||
|
||||
echo "${cfg.package.version}" > "$versionFile"
|
||||
echo "$configuredPlugins" > "$pluginsFile"
|
||||
fi
|
||||
'';
|
||||
serviceConfig = {
|
||||
ExecStart = "${getExe' pythonEnv "gunicorn"} --bind unix:/run/pretix/pretix.sock ${cfg.gunicorn.extraArgs} pretix.wsgi";
|
||||
RuntimeDirectory = "pretix";
|
||||
};
|
||||
};
|
||||
|
||||
pretix-periodic = recursiveUpdate commonUnitConfig {
|
||||
description = "pretix periodic task runner";
|
||||
# every 15 minutes
|
||||
startAt = [ "*:3,18,33,48" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${getExe' pythonEnv "pretix-manage"} runperiodic";
|
||||
};
|
||||
};
|
||||
|
||||
pretix-worker = recursiveUpdate commonUnitConfig {
|
||||
description = "pretix asynchronous job runner";
|
||||
after = [
|
||||
"network.target"
|
||||
"redis-pretix.service"
|
||||
"postgresql.service"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig.ExecStart = "${getExe' pythonEnv "celery"} -A pretix.celery_app worker ${cfg.celery.extraArgs}";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.sockets.pretix-web.socketConfig = {
|
||||
ListenStream = "/run/pretix/pretix.sock";
|
||||
SocketUser = "nginx";
|
||||
};
|
||||
|
||||
users = {
|
||||
groups."${cfg.group}" = {};
|
||||
users."${cfg.user}" = {
|
||||
isSystemUser = true;
|
||||
createHome = true;
|
||||
home = cfg.settings.pretix.datadir;
|
||||
inherit (cfg) group;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -20,6 +20,22 @@ in
|
|||
};
|
||||
|
||||
debug = mkEnableOption (lib.mdDoc "mate-session debug messages");
|
||||
|
||||
extraPanelApplets = mkOption {
|
||||
default = [ ];
|
||||
example = literalExpression "with pkgs.mate; [ mate-applets ]";
|
||||
type = types.listOf types.package;
|
||||
description = lib.mdDoc "Extra applets to add to mate-panel.";
|
||||
};
|
||||
|
||||
extraCajaExtensions = mkOption {
|
||||
default = [ ];
|
||||
example = lib.literalExpression "with pkgs.mate; [ caja-extensions ]";
|
||||
type = types.listOf types.package;
|
||||
description = lib.mdDoc "Extra extensions to add to caja.";
|
||||
};
|
||||
|
||||
enableWaylandSession = mkEnableOption (lib.mdDoc "MATE Wayland session");
|
||||
};
|
||||
|
||||
environment.mate.excludePackages = mkOption {
|
||||
|
@ -31,55 +47,63 @@ in
|
|||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = mkMerge [
|
||||
(mkIf (cfg.enable || cfg.enableWaylandSession) {
|
||||
services.xserver.displayManager.sessionPackages = [
|
||||
pkgs.mate.mate-session-manager
|
||||
];
|
||||
|
||||
services.xserver.displayManager.sessionPackages = [
|
||||
pkgs.mate.mate-session-manager
|
||||
];
|
||||
# Debugging
|
||||
environment.sessionVariables.MATE_SESSION_DEBUG = mkIf cfg.debug "1";
|
||||
|
||||
# Let caja find extensions
|
||||
environment.sessionVariables.CAJA_EXTENSION_DIRS = [ "${config.system.path}/lib/caja/extensions-2.0" ];
|
||||
environment.systemPackages = utils.removePackagesByName
|
||||
(pkgs.mate.basePackages ++
|
||||
pkgs.mate.extraPackages ++
|
||||
[
|
||||
(pkgs.mate.caja-with-extensions.override {
|
||||
extensions = cfg.extraCajaExtensions;
|
||||
})
|
||||
(pkgs.mate.mate-panel-with-applets.override {
|
||||
applets = cfg.extraPanelApplets;
|
||||
})
|
||||
pkgs.desktop-file-utils
|
||||
pkgs.glib
|
||||
pkgs.gtk3.out
|
||||
pkgs.shared-mime-info
|
||||
pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
|
||||
pkgs.yelp # for 'Contents' in 'Help' menus
|
||||
])
|
||||
config.environment.mate.excludePackages;
|
||||
|
||||
# Let mate-panel find applets
|
||||
environment.sessionVariables."MATE_PANEL_APPLETS_DIR" = "${config.system.path}/share/mate-panel/applets";
|
||||
environment.sessionVariables."MATE_PANEL_EXTRA_MODULES" = "${config.system.path}/lib/mate-panel/applets";
|
||||
programs.dconf.enable = true;
|
||||
# Shell integration for VTE terminals
|
||||
programs.bash.vteIntegration = mkDefault true;
|
||||
programs.zsh.vteIntegration = mkDefault true;
|
||||
|
||||
# Debugging
|
||||
environment.sessionVariables.MATE_SESSION_DEBUG = mkIf cfg.debug "1";
|
||||
# Mate uses this for printing
|
||||
programs.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
|
||||
|
||||
environment.systemPackages = utils.removePackagesByName
|
||||
(pkgs.mate.basePackages ++
|
||||
pkgs.mate.extraPackages ++
|
||||
[
|
||||
pkgs.desktop-file-utils
|
||||
pkgs.glib
|
||||
pkgs.gtk3.out
|
||||
pkgs.shared-mime-info
|
||||
pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
|
||||
pkgs.yelp # for 'Contents' in 'Help' menus
|
||||
])
|
||||
config.environment.mate.excludePackages;
|
||||
services.gnome.at-spi2-core.enable = true;
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
services.udev.packages = [ pkgs.mate.mate-settings-daemon ];
|
||||
services.gvfs.enable = true;
|
||||
services.upower.enable = config.powerManagement.enable;
|
||||
services.xserver.libinput.enable = mkDefault true;
|
||||
|
||||
programs.dconf.enable = true;
|
||||
# Shell integration for VTE terminals
|
||||
programs.bash.vteIntegration = mkDefault true;
|
||||
programs.zsh.vteIntegration = mkDefault true;
|
||||
security.pam.services.mate-screensaver.unixAuth = true;
|
||||
|
||||
# Mate uses this for printing
|
||||
programs.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
|
||||
xdg.portal.configPackages = mkDefault [ pkgs.mate.mate-desktop ];
|
||||
|
||||
services.gnome.at-spi2-core.enable = true;
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
services.udev.packages = [ pkgs.mate.mate-settings-daemon ];
|
||||
services.gvfs.enable = true;
|
||||
services.upower.enable = config.powerManagement.enable;
|
||||
services.xserver.libinput.enable = mkDefault true;
|
||||
environment.pathsToLink = [ "/share" ];
|
||||
})
|
||||
(mkIf cfg.enableWaylandSession {
|
||||
programs.wayfire.enable = true;
|
||||
programs.wayfire.plugins = [ pkgs.wayfirePlugins.firedecor ];
|
||||
|
||||
security.pam.services.mate-screensaver.unixAuth = true;
|
||||
|
||||
xdg.portal.configPackages = mkDefault [ pkgs.mate.mate-desktop ];
|
||||
|
||||
environment.pathsToLink = [ "/share" ];
|
||||
};
|
||||
environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${pkgs.mate.mate-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
|
||||
|
||||
environment.systemPackages = [ pkgs.mate.mate-wayland-session ];
|
||||
services.xserver.displayManager.sessionPackages = [ pkgs.mate.mate-wayland-session ];
|
||||
})
|
||||
];
|
||||
}
|
||||
|
|
|
@ -79,6 +79,10 @@ in
|
|||
serviceConfig.StandardOutput = "journal+console";
|
||||
};
|
||||
|
||||
# Amazon-issued AMIs include the SSM Agent by default, so we do the same.
|
||||
# https://docs.aws.amazon.com/systems-manager/latest/userguide/ami-preinstalled-agent.html
|
||||
services.amazon-ssm-agent.enable = true;
|
||||
|
||||
# Allow root logins only using the SSH key that the user specified
|
||||
# at instance creation time.
|
||||
services.openssh.enable = true;
|
||||
|
|
|
@ -513,6 +513,7 @@ in {
|
|||
mastodon = discoverTests (import ./web-apps/mastodon { inherit handleTestOn; });
|
||||
pixelfed = discoverTests (import ./web-apps/pixelfed { inherit handleTestOn; });
|
||||
mate = handleTest ./mate.nix {};
|
||||
mate-wayland = handleTest ./mate-wayland.nix {};
|
||||
matter-server = handleTest ./matter-server.nix {};
|
||||
matomo = handleTest ./matomo.nix {};
|
||||
matrix-appservice-irc = handleTest ./matrix/appservice-irc.nix {};
|
||||
|
@ -729,6 +730,7 @@ in {
|
|||
pppd = handleTest ./pppd.nix {};
|
||||
predictable-interface-names = handleTest ./predictable-interface-names.nix {};
|
||||
pretalx = runTest ./web-apps/pretalx.nix;
|
||||
pretix = runTest ./web-apps/pretix.nix;
|
||||
printing-socket = handleTest ./printing.nix { socket = true; };
|
||||
printing-service = handleTest ./printing.nix { socket = false; };
|
||||
privoxy = handleTest ./privoxy.nix {};
|
||||
|
|
63
nixos/tests/mate-wayland.nix
Normal file
63
nixos/tests/mate-wayland.nix
Normal file
|
@ -0,0 +1,63 @@
|
|||
import ./make-test-python.nix ({ pkgs, lib, ... }: {
|
||||
name = "mate-wayland";
|
||||
|
||||
meta.maintainers = lib.teams.mate.members;
|
||||
|
||||
nodes.machine = { ... }: {
|
||||
imports = [
|
||||
./common/user-account.nix
|
||||
];
|
||||
|
||||
services.xserver.enable = true;
|
||||
services.xserver.displayManager = {
|
||||
sddm.enable = true; # https://github.com/canonical/lightdm/issues/63
|
||||
sddm.wayland.enable = true;
|
||||
defaultSession = "MATE";
|
||||
autoLogin = {
|
||||
enable = true;
|
||||
user = "alice";
|
||||
};
|
||||
};
|
||||
services.xserver.desktopManager.mate.enableWaylandSession = true;
|
||||
|
||||
hardware.pulseaudio.enable = true;
|
||||
|
||||
# Need to switch to a different GPU driver than the default one (-vga std) so that wayfire can launch:
|
||||
virtualisation.qemu.options = [ "-vga none -device virtio-gpu-pci" ];
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
|
||||
testScript = { nodes, ... }:
|
||||
let
|
||||
user = nodes.machine.users.users.alice;
|
||||
in
|
||||
''
|
||||
machine.wait_for_unit("display-manager.service")
|
||||
|
||||
with subtest("Wait for Wayland server"):
|
||||
machine.wait_for_file("/run/user/${toString user.uid}/wayland-1")
|
||||
|
||||
with subtest("Check if MATE session components actually start"):
|
||||
for i in ["wayfire", "mate-panel", "mate-wayland.sh", "mate-wayland-components.sh"]:
|
||||
machine.wait_until_succeeds(f"pgrep -f {i}")
|
||||
machine.wait_for_text('(Applications|Places|System)')
|
||||
# It is expected that this applet doesn't work in Wayland
|
||||
machine.wait_for_text('WorkspaceSwitcherApplet')
|
||||
|
||||
with subtest("Check if various environment variables are set"):
|
||||
cmd = "xargs --null --max-args=1 echo < /proc/$(pgrep -xf mate-panel)/environ"
|
||||
machine.succeed(f"{cmd} | grep 'XDG_SESSION_TYPE' | grep 'wayland'")
|
||||
machine.succeed(f"{cmd} | grep 'XDG_SESSION_DESKTOP' | grep 'MATE'")
|
||||
machine.succeed(f"{cmd} | grep 'MATE_PANEL_APPLETS_DIR' | grep '${pkgs.mate.mate-panel-with-applets.pname}'")
|
||||
|
||||
with subtest("Check if Wayfire config is properly configured"):
|
||||
for i in ["button_style = mate", "firedecor", "mate-wayland-components.sh"]:
|
||||
machine.wait_until_succeeds(f"cat /home/${user.name}/.config/mate/wayfire.ini | grep '{i}'")
|
||||
|
||||
with subtest("Check if Wayfire has ever coredumped"):
|
||||
machine.fail("coredumpctl --json=short | grep wayfire")
|
||||
machine.sleep(10)
|
||||
machine.screenshot("screen")
|
||||
'';
|
||||
})
|
|
@ -54,6 +54,15 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
|
|||
machine.wait_for_text('(Applications|Places|System)')
|
||||
machine.wait_for_text('(Computer|Home|Trash)')
|
||||
|
||||
with subtest("Check if various environment variables are set"):
|
||||
machine.succeed("xargs --null --max-args=1 echo < /proc/$(pgrep -xf marco)/environ | grep 'XDG_CURRENT_DESKTOP' | grep 'MATE'")
|
||||
# From mate-panel-with-applets packaging
|
||||
machine.succeed("xargs --null --max-args=1 echo < /proc/$(pgrep -xf mate-panel)/environ | grep 'MATE_PANEL_APPLETS_DIR' | grep '${pkgs.mate.mate-panel-with-applets.pname}'")
|
||||
|
||||
with subtest("Check if applets are built with in-process support"):
|
||||
# This is needed for Wayland support
|
||||
machine.fail("pgrep -fa clock-applet")
|
||||
|
||||
with subtest("Lock the screen"):
|
||||
machine.wait_until_succeeds("su - ${user.name} -c '${env} mate-screensaver-command -q' | grep 'The screensaver is inactive'")
|
||||
machine.succeed("su - ${user.name} -c '${env} mate-screensaver-command -l >&2 &'")
|
||||
|
|
47
nixos/tests/web-apps/pretix.nix
Normal file
47
nixos/tests/web-apps/pretix.nix
Normal file
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
name = "pretix";
|
||||
meta.maintainers = with lib.maintainers; [ hexa ];
|
||||
|
||||
nodes = {
|
||||
pretix = {
|
||||
networking.extraHosts = ''
|
||||
127.0.0.1 tickets.local
|
||||
'';
|
||||
|
||||
services.pretix = {
|
||||
enable = true;
|
||||
nginx.domain = "tickets.local";
|
||||
plugins = with pkgs.pretix.plugins; [
|
||||
passbook
|
||||
pages
|
||||
];
|
||||
settings = {
|
||||
pretix = {
|
||||
instance_name = "NixOS Test";
|
||||
url = "http://tickets.local";
|
||||
};
|
||||
mail.from = "hello@tickets.local";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
pretix.wait_for_unit("pretix-web.service")
|
||||
pretix.wait_for_unit("pretix-worker.service")
|
||||
|
||||
pretix.wait_until_succeeds("curl -q --fail http://tickets.local")
|
||||
|
||||
pretix.succeed("pretix-manage --help")
|
||||
|
||||
pretix.log(pretix.succeed("systemd-analyze security pretix-web.service"))
|
||||
'';
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue