This commit is contained in:
kalmenn 2025-07-07 13:52:45 +02:00
parent 6fbd9b2a6c
commit 919efdf2a4
Signed by: kalmenn
GPG key ID: F500055C44BC3834
6 changed files with 162 additions and 59 deletions

View file

@ -2,7 +2,7 @@
description = "Nixos modules for the pterodactyl game server panel"; description = "Nixos modules for the pterodactyl game server panel";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; nixpkgs.url = github:nixos/nixpkgs?ref=nixos-unstable;
}; };
outputs = { self, nixpkgs }: { outputs = { self, nixpkgs }: {
@ -11,9 +11,14 @@
); );
packages = nixpkgs.lib.genAttrs [ "x86_64-linux" ] ( packages = nixpkgs.lib.genAttrs [ "x86_64-linux" ] (
system: nixpkgs.lib.genAttrs [ "pterodactyl" "php" "wings" ] ( system: let
package: import ./packages/${package}.nix { pkgs = import nixpkgs { inherit system; }; }; pkgs = import nixpkgs { inherit system; };
) in rec {
}); wings = import ./packages/wings.nix { inherit pkgs; };
pterodactyl = import ./packages/pterodactyl.nix { inherit pkgs; };
php = import ./packages/php.nix { inherit pkgs; };
composer = import ./packages/composer.nix { inherit pkgs php; };
}
);
}; };
} }

View file

@ -2,20 +2,36 @@
{ lib, config, pkgs, ... }: { lib, config, pkgs, ... }:
let let
cfg = config.services.pterodactyl; thisConfig = config.services.pterodactyl;
flakePkgs = flake.outputs.packages.${pkgs.system};
defaultUser = "pterodactyl"; defaultUser = "pterodactyl";
in { in {
options.services.pterodactyl = { options.services.pterodactyl = {
enable = lib.mkEnableOption "Enable the pterodacytl game server panel"; enable = lib.mkEnableOption "Enable the pterodacytl game server panel";
proxy = { pkg = lib.mkOption {
enable = lib.mkEnableOption "Automatically configure Nginx to serve the panel"; type = lib.types.package;
serverName = lib.mkOption { description = "The package in which to source the php files used by pterodactyl";
default = flake.outputs.packages.${pkgs.system}.pterodactyl;
};
dataDir = lib.mkOption {
type = lib.types.str;
description = "The directory in which to store stateful data";
default = "/var/lib/pterodactyl";
};
server = {
enable = lib.mkEnableOption ''
Automatically configure Nginx to serve the panel
If you need more control over the nginx proxy, for now you must leave this option disabled
and write your own nginx configuration. Feel free to copy ours as a starting point.
'';
name = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = "The canonical domain on which the panel will be hosted"; description = "The canonical domain name on which the panel will be hosted";
default = "localhost"; default = "localhost";
example = "pterodactyl.example.com"; example = "pterodactyl.example.com";
}; };
@ -27,27 +43,64 @@ in {
}; };
}; };
user = lib.mkOption { php = {
type = lib.types.str; socket = lib.mkOption {
description = '' type = lib.types.path;
The user that owns the files managed by the panel. description = "The location of the unix socket used by php-fpm";
If you change this, make sure their files are accessible by your www user default = config.services.phpfpm.pools.pterodactyl.socket;
(probably "nginx"). };
'';
default = defaultUser;
example = defaultUser;
};
pkg = lib.mkOption { user = lib.mkOption {
type = lib.types.package; type = lib.types.str;
description = "The package in which to source the php files used by pterodactyl"; description = ''
default = flakePkgs.pterodactyl; The user that the php-fpm processes will run under. See also the `group` option.
};
dataDir = lib.mkOption { If you change this, make sure the unix socket is accessible by your www user
type = lib.types.str; (probably "nginx").
description = "The directory in which to store stateful data"; '';
default = "/var/lib/pterodactyl"; default = defaultUser;
};
group = lib.mkOption {
type = lib.types.str;
description = ''
The group that the php-fpm processes will run under. See also the `user` option.
If you change this, make sure the unix socket is accessible by your www user
(probably "nginx").
'';
default = defaultUser;
};
home = lib.mkOption {
type = lib.types.path;
description = ''
Where Pterodactyl stores its stateful data is hardcoded to be right next to its php
scripts. But since we'd like to store the latter in the nix store and the nix store is
immutable, we have to find a workaround.
So, the directory pointed to by this option will be where we instruct php to find its
scripts and data. And the actual files will be simlinked to from this directory, so we can
actually store them in a different location.
'';
default = "/var/lib/pterodactyl/";
};
manageHome = lib.mkOption {
type = lib.types.bool;
description = ''
Whether or not to automatically create the symlinks
See services.pterodactyl.php.home for details.
'';
default = true;
};
pkg = lib.mkOption {
type = lib.types.package;
description = "The php package to use";
default = flake.outputs.packages.${pkgs.system}.php;
};
}; };
redis = { redis = {
@ -67,29 +120,37 @@ in {
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf thisConfig.enable {
users = lib.mkIf (cfg.user == defaultUser) { users = {
users.${cfg.user} = { users = {
isSystemUser = true; ${thisConfig.php.user} = lib.mkIf (thisConfig.php.user == defaultUser) {
createHome = true; isSystemUser = true;
home = cfg.dataDir; createHome = true;
group = cfg.user; home = thisConfig.php.home;
group = thisConfig.php.group;
};
${config.services.nginx.user} = lib.mkIf (thisConfig.php.group == defaultUser) {
extraGroups = [ thisConfig.php.group ];
};
}; };
groups.${cfg.user} = { }; groups = {
${thisConfig.php.group} = lib.mkIf (thisConfig.php.group == defaultUser) {};
users.${config.services.nginx.user}.extraGroups = [ cfg.user ]; };
}; };
services.redis.servers.${cfg.redis.name} = lib.mkIf cfg.redis.configureLocally { services.redis.servers.${thisConfig.redis.name} = lib.mkIf cfg.redis.configureLocally {
enable = true; enable = true;
port = cfg.redis.port; port = thisConfig.redis.port;
}; };
services.nginx = lib.mkIf cfg.proxy.enable { services.nginx = lib.mkIf thisConfig.server.enable {
enable = true; enable = true;
virtualHosts."${cfg.serverName}" = { virtualHosts."pterodactyl" = {
serverName = thisConfig.server.name;
root = "${config.services.pterodactyl.pkg}/public"; root = "${config.services.pterodactyl.pkg}/public";
extraConfig = '' extraConfig = ''
@ -101,7 +162,7 @@ in {
include ${pkgs.nginx}/conf/fastcgi_params; include ${pkgs.nginx}/conf/fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${config.services.phpfpm.pools.pterodactyl.socket}; fastcgi_pass unix:${thisConfig.php.socket};
fastcgi_index index.php; fastcgi_index index.php;
@ -127,7 +188,7 @@ in {
}; };
services.phpfpm.pools.pterodactyl = { services.phpfpm.pools.pterodactyl = {
user = cfg.user; user = thisConfig.php.user;
settings = { settings = {
"listen.owner" = config.services.nginx.user; "listen.owner" = config.services.nginx.user;
"pm" = "dynamic"; "pm" = "dynamic";
@ -145,17 +206,49 @@ in {
}; };
}; };
systemd.tmpfiles.settings."10-pterodactyl" = lib.mkIf thisConfig.php.manageHome {
"${thisConfig.php.home}/app" = { "L" = { argument = "${thisConfig.pkg}/app"; }; };
"${thisConfig.php.home}/config" = { "L" = { argument = "${thisConfig.pkg}/config"; }; };
"${thisConfig.php.home}/database" = { "L" = { argument = "${thisConfig.pkg}/database"; }; };
"${thisConfig.php.home}/public" = { "L" = { argument = "${thisConfig.pkg}/public"; }; };
"${thisConfig.php.home}/resources" = { "L" = { argument = "${thisConfig.pkg}/resources"; }; };
"${thisConfig.php.home}/routes" = { "L" = { argument = "${thisConfig.pkg}/routes"; }; };
"${thisConfig.php.home}/tests" = { "L" = { argument = "${thisConfig.pkg}/tests"; }; };
"${thisConfig.php.home}/artisan" = { "L" = { argument = "${thisConfig.pkg}/artisan"; }; };
"${thisConfig.php.home}/compser.json" = { "L" = { argument = "${thisConfig.pkg}/compser.json"; }; };
"${thisConfig.php.home}/compser.lock" = { "L" = { argument = "${thisConfig.pkg}/composer.lock"; }; };
"${thisConfig.php.home}/bootstrap/app.php" = {
"L" = { argument = "${thisConfig.pkg}/bootstrap/app.php"; };
};
"${thisConfig.php.home}/bootstrap/tests.php" = {
"L" = { argument = "${thisConfig.pkg}/bootstrap/tests.php"; };
};
"${thisConfig.php.home}/bootstrap/cache" = {
"L" = { argument = "${thisConfig.dataDir}/cache"; };
};
"${thisConfig.php.home}/storage" = { "L" = { argument = "${thisConfig.dataDir}/storage"; }; };
"${thisConfig.dataDir}/storage" = {
"d" = { user = thisConfig.php.user; group = thisConfig.php.group; mode = "750"; };
};
"${thisConfig.dataDir}/cache" = {
"d" = { user = thisConfig.php.user; group = thisConfig.php.group; mode = "750"; };
};
};
systemd.services.pteroq = { systemd.services.pteroq = {
enable = true; enable = true;
description = "Pterodactyl Queue Worker"; description = "Pterodactyl Queue Worker";
after = [ "redis-${cfg.redis.name}.service" ]; after = [ "redis-${thisConfig.redis.name}.service" ];
unitConfig = { StartLimitInterval = 180; }; unitConfig = { StartLimitInterval = 180; };
serviceConfig = { serviceConfig = {
User = cfg.user; User = thisConfig.php.user;
Group = cfg.user; Group = thisConfig.php.group;
Restart = "always"; Restart = "always";
ExecStart = ExecStart =
"${flakePkgs.php}/bin/php ${cfg.pkg}/artisan queue:work --queue=high,standard,low --sleep=3 --tries=3"; "${thisConfig.php.pkg}/bin/php ${thisConfig.php.home}/artisan queue:work --queue=high,standard,low --sleep=3 --tries=3";
StartLimitBurst = 30; StartLimitBurst = 30;
RestartSec = "5s"; RestartSec = "5s";
}; };

5
packages/composer.nix Normal file
View file

@ -0,0 +1,5 @@
{ pkgs ? import <nixpkgs>, php ? null }:
let
php = if php == null then pkgs.php else php;
in php.packages.composer.override {php = phpWithExtensions;};

View file

@ -1,12 +1,12 @@
{ pkgs }: { pkgs ? import <nixpkgs> }:
pkgs.php83.buildEnv { pkgs.php83.buildEnv {
extensions = { enabled, all, }: enabled ++ (with all; [ extensions = { enabled, all, }: enabled ++ (with all; [
redis redis
# xdebug xdebug
]); ]);
# extraConfig = '' extraConfig = ''
# xdebug.mode=debug xdebug.mode=debug
# ''; '';
} }

View file

@ -1,9 +1,9 @@
{ pkgs }: { pkgs ? import <nixpkgs> }:
let let
version = "1.11.11"; version = "1.11.11";
in pkgs.fetchzip { in pkgs.fetchzip {
url = "https://github.com/pterodactyl/panel/releases/download/v${ version }/panel.tar.gz"; url = https://github.com/pterodactyl/panel/releases/download/v${version}/panel.tar.gz;
hash = "sha256-0nOHtReVUVXYQY/glS4x0gkbhetoXSWg4rRwOJlkcM8="; hash = "sha256-0nOHtReVUVXYQY/glS4x0gkbhetoXSWg4rRwOJlkcM8=";
stripRoot = false; stripRoot = false;
} }

View file

@ -1,4 +1,4 @@
{ pkgs }: { pkgs ? import <nixpkgs> }:
let let
version = "1.11.13"; version = "1.11.13";