Compare commits

...

19 Commits

Author SHA1 Message Date
xenia 8d63e56204 WIP: update satisfactory dedicated server 2025-09-01 22:47:30 -04:00
xenia 3b71438ff4 update nixpkgs/lix 2025-08-31 17:44:41 -04:00
xenia 49a730f641 update nixpkgs 2025-08-03 16:19:57 -04:00
xenia de53bfd455 oops 2025-07-07 21:36:44 -04:00
xenia f71602bcff update nixpkgs and lix 2025-07-07 21:19:57 -04:00
xenia 1557fcbf00 rollback lix 2025-06-28 20:36:18 -04:00
xenia b157a5ca31 update to lix 2.92.2 2025-06-24 22:34:42 -04:00
xenia 83be7c5296 whoops 2025-06-22 18:21:43 -04:00
xenia d181eac6a3 pkgs: fix zbasefind 2025-06-18 23:34:47 -04:00
xenia c1bd5b32d6 pkgs: add moloch(-dragon) 2025-06-11 01:12:10 -04:00
xenia 76cbd04361 templates: beamer: use new style texlive syntax 2025-06-10 00:08:55 -04:00
xenia 6933e33e80 templates: update gitignore 2025-06-09 23:03:47 -04:00
xenia 9c6a46b398 templates: update beamer 2025-06-09 22:16:51 -04:00
xenia b33745acb8 templates: update beamer template 2025-06-09 22:16:04 -04:00
xenia 71af6415d2 templates: update beamer template 2025-06-09 22:03:56 -04:00
xenia 37050f846b templates: add beamer template 2025-06-09 21:19:03 -04:00
xenia 6223d67e8f flake: add `apps` to mkFlake transformed keys 2025-06-09 21:03:14 -04:00
xenia 8674b22d5c flake: rework the nixpkgs init code 2025-06-06 00:24:49 -04:00
xenia 946bbc1522 update nixpkgs to 25.05 2025-05-29 15:13:56 -04:00
17 changed files with 903 additions and 107 deletions

View File

@ -1,52 +1,37 @@
{
"nodes": {
"lix": {
"flake": false,
"locked": {
"lastModified": 1737234286,
"narHash": "sha256-CCKIAE84dzkrnlxJCKFyffAxP3yfsOAbdvydUGqq24g=",
"rev": "2837da71ec1588c1187d2e554719b15904a46c8b",
"type": "tarball",
"url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/2837da71ec1588c1187d2e554719b15904a46c8b.tar.gz?rev=2837da71ec1588c1187d2e554719b15904a46c8b"
},
"original": {
"type": "tarball",
"url": "https://git.lix.systems/lix-project/lix/archive/2.92.0.tar.gz"
}
},
"lix-module": {
"flake": false,
"locked": {
"lastModified": 1742943028,
"narHash": "sha256-fprwZKE1uMzO9tiWWOrmLWBW3GPkMayQfb0xOvVFIno=",
"rev": "868d97695bab9d21f6070b03957bcace249fbe3c",
"lastModified": 1756125859,
"narHash": "sha256-6a+PWILmqHCs9B5eIBLg6HSZ8jYweZpgOWO8FlyVwYI=",
"rev": "d3292125035b04df00d01549a26e948631fabe1e",
"type": "tarball",
"url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/868d97695bab9d21f6070b03957bcace249fbe3c.tar.gz?rev=868d97695bab9d21f6070b03957bcace249fbe3c"
"url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/d3292125035b04df00d01549a26e948631fabe1e.tar.gz?rev=d3292125035b04df00d01549a26e948631fabe1e"
},
"original": {
"type": "tarball",
"url": "https://git.lix.systems/lix-project/nixos-module/archive/2.92.0-3.tar.gz"
"url": "https://git.lix.systems/lix-project/nixos-module/archive/2.93.3-2.tar.gz"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1748370509,
"narHash": "sha256-QlL8slIgc16W5UaI3w7xHQEP+Qmv/6vSNTpoZrrSlbk=",
"lastModified": 1756617294,
"narHash": "sha256-aGnd4AHIYCWQKChAkHPpX+YYCt7pA6y2LFFA/s8q0wQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4faa5f5321320e49a78ae7848582f684d64783e9",
"rev": "b4c2c57c31e68544982226d07e4719a2d86302a8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"lix": "lix",
"lix-module": "lix-module",
"nixpkgs": "nixpkgs"
}

110
flake.nix
View File

@ -2,26 +2,25 @@
description = "dragnpkgs together with nixpkgs and lix";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
lix-module = {
url = "https://git.lix.systems/lix-project/nixos-module/archive/2.92.0-3.tar.gz";
flake = false;
};
lix = {
url = "https://git.lix.systems/lix-project/lix/archive/2.92.0.tar.gz";
url = "https://git.lix.systems/lix-project/nixos-module/archive/2.93.3-2.tar.gz";
flake = false;
};
};
outputs = { self, nixpkgs, lix, lix-module }:
outputs = { self, nixpkgs, lix-module }:
let
overlays = [
(import ./overlay.nix)
(import "${lix-module}/overlay.nix" { inherit lix; })
(import "${lix-module}/overlay.nix" { lix = null; })
];
forAllSystems = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed;
libVersionInfoOverlay = import "${nixpkgs}/lib/flake-version-info.nix" nixpkgs;
# this is taken from upstream. if upstream changes, the code here needs to be updated to match
addLibVersionInfo = lib: lib.extend libVersionInfoOverlay;
lib-base = addLibVersionInfo (import "${nixpkgs}/lib");
in {
# we don't just use nix.registry.whatever.flake = self
# the reason for this is to be able to handle a flake.lock containing an entry for this
@ -29,21 +28,54 @@
# self reference in the registry to be downloadable by URL in case it makes it into a
# flake.lock
meta.registry-entry = {
from = { id = "dragnpkgs-unstable"; type = "indirect"; };
from = { id = "dragnpkgs"; type = "indirect"; };
to = {
type = "git";
url = "https://git.lain.faith/haskal/dragnpkgs.git";
ref = "main";
ref = "nixos-25.05";
} // self.lib.filterAttrs
(n: _: n == "lastModified" || n == "rev" || n == "revCount" || n == "narHash")
self;
};
# the nix path entry for self
meta.path-entry = "dragnpkgs-unstable=flake:dragnpkgs-unstable";
meta.path-entry = "dragnpkgs=flake:dragnpkgs";
lib = nixpkgs.lib.extend (final: prev: {
licenses = prev.licenses // { fyptl = import ./lib/licenses/fyptl.nix; };
lib = (lib-base.extend (import ./lib/overlay.nix)).extend (final: prev: {
# initializes regular upstream nixpkgs with the given arguments
nixpkgs-custom = { system, ... } @ args: (
(import "${nixpkgs}" args).extend (final: prev: {
lib = addLibVersionInfo prev.lib;
})
);
# initializes dragnpkgs with its overlays and default config using the given arguments
dragnpkgs-custom = { system, ... } @ args: let
unsafeConf = if builtins.hasAttr "extraBuiltins" builtins then (
let conf = builtins.extraBuiltins; in
if builtins.isAttrs conf then conf else {}
) else {};
possiblyCommitCrimes =
if
builtins.hasAttr "dragnpkgs" unsafeConf &&
builtins.isAttrs unsafeConf.dragnpkgs &&
builtins.hasAttr "possiblyCommitCrimes" unsafeConf.dragnpkgs &&
builtins.isBool unsafeConf.dragnpkgs.possiblyCommitCrimes
then
unsafeConf.dragnpkgs.possiblyCommitCrimes
else
false;
in
final.nixpkgs-custom (args // {
overlays = overlays ++ (args.overlays or []);
config = (args.config or {}) // {
allowlistedLicenses = (final.optionals
possiblyCommitCrimes
[ final.licenses.fyptl ]) ++ (args.config.allowlistedLicenses or []);
};
});
nixos = import "${nixpkgs}/nixos/lib" { lib = final; };
nixosSystem = args:
import "${nixpkgs}/nixos/lib/eval-config.nix" (
@ -122,17 +154,17 @@
};
};
config.nix.registry.dragnpkgs-unstable =
config.nix.registry.dragnpkgs =
lib.mkIf config.dragnpkgs.setFlakeRegistry self.meta.registry-entry;
config.nix.registry.nixpkgs = lib.mkIf config.dragnpkgs.setNixpkgsFlakeAlias {
from = { id = "nixpkgs"; type = "indirect"; };
to = { id = "dragnpkgs-unstable"; type = "indirect"; };
to = { id = "dragnpkgs"; type = "indirect"; };
};
config.nix.registry.templates = lib.mkIf config.dragnpkgs.setTemplatesFlakeAlias {
from = { id = "templates"; type = "indirect"; };
to = { id = "dragnpkgs-unstable"; type = "indirect"; };
to = { id = "dragnpkgs"; type = "indirect"; };
};
config.nix.nixPath = lib.mkIf config.dragnpkgs.setNixPath [
@ -153,8 +185,8 @@
lib.mkForce "/etc/nix/extra-builtins.nix"
);
config.environment.etc."nix/extra-builtins.nix".text =
lib.mkIf config.dragnpkgs.possiblyCommitCrimes (
config.environment.etc = lib.mkIf config.dragnpkgs.possiblyCommitCrimes {
"nix/extra-builtins.nix".text =
let
possiblyCommitCrimes =
lib.boolToString config.dragnpkgs.possiblyCommitCrimes;
@ -164,7 +196,8 @@
possiblyCommitCrimes = ${possiblyCommitCrimes};
};
}
'');
'';
};
})
(import ./module.nix)
@ -184,7 +217,8 @@
));
in
builtins.mapAttrs (name: value:
if name == "packages" || name == "legacyPackages" || name == "devShells" then
if name == "packages" || name == "legacyPackages" || name == "devShells" ||
name == "apps" then
rewritePerSystem value
else
value
@ -192,41 +226,19 @@
});
legacyPackages = forAllSystems (system:
let
unsafeConf = if builtins.hasAttr "extraBuiltins" builtins then (
let conf = builtins.extraBuiltins; in
if builtins.isAttrs conf then conf else {}
) else {};
possiblyCommitCrimes =
if
builtins.hasAttr "dragnpkgs" unsafeConf &&
builtins.isAttrs unsafeConf.dragnpkgs &&
builtins.hasAttr "possiblyCommitCrimes" unsafeConf.dragnpkgs &&
builtins.isBool unsafeConf.dragnpkgs.possiblyCommitCrimes
then
unsafeConf.dragnpkgs.possiblyCommitCrimes
else
false;
in
nixpkgs.legacyPackages.${system}.appendOverlays (overlays ++
[(final: prev: {
stdenv = prev.stdenv.override {
config = prev.config // {
allowlistedLicenses = final.lib.optionals
possiblyCommitCrimes
[ final.lib.licenses.fyptl ];
};
};
})])
self.lib.dragnpkgs-custom { inherit system; }
);
nixosModules = nixpkgs.nixosModules;
templates = {
default = {
path = ./templates/default;
description = "A very basic flake (with dragnpkgs)";
};
beamer = {
path = ./templates/beamer;
description = "A very basic presentation with Beamer";
};
};
defaultTemplate = self.templates.default;

3
lib/overlay.nix Normal file
View File

@ -0,0 +1,3 @@
final: prev: {
licenses = prev.licenses // { fyptl = import ./licenses/fyptl.nix; };
}

View File

@ -1,14 +1,15 @@
{ ... }: {
imports = [
./modules/ghidra-server
./modules/regdom
./modules/machine-info
./modules/satisfactory-dedicated-server
./modules/regdom
];
# set some nix settings defaults
config.nix.settings = {
repl-overlays = [ ./repl-overlay.nix ];
experimental-features = "nix-command flakes repl-flake pipe-operator";
experimental-features = "nix-command flakes pipe-operator";
temp-dir = "/var/tmp";
# we're disabling the default flake registry because i don't like it

View File

@ -0,0 +1,421 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.satisfactory;
in {
options.services.satisfactory = with lib; {
enable = mkEnableOption "satisfactory";
package = mkPackageOption pkgs "satisfactory-dedicated-server" {};
directory = mkOption {
description = ''
Directory where Satisfactory Dedicated Server data will be stored
'';
default = "/var/lib/satisfactory";
type = types.str;
example = literalExpression "\"/data/games/satisfactory\"";
};
user = mkOption {
description = "User account under which Satisfactory Dedicated Server runs.";
default = "satisfactory";
type = types.str;
example = literalExpression "\"satisfactory2\"";
};
group = mkOption {
description = "Group under which Satisfactory Dedicated Server runs.";
default = "satisfactory";
type = types.str;
example = literalExpression "\"satisfactory2\"";
};
useACMEHost = mkOption {
description = ''
If set, the server will use the ACME-provided TLS certificate for the given host.
Note that this module does not actually provision the specified certificate; you must
use additional config (e.g., `services.nginx.virtualHosts.<name>.enableACME = true`) to
provision the certificate using a supported ACME method.
'';
default = null;
type = types.nullOr types.str;
example = literalExpression "\"myserver.example\"";
};
port = mkOption {
description = ''
Server port number (TCP/UDP)
This corresponds to the `-Port` command line option.
'';
default = 7777;
type = types.port;
example = literalExpression "7778";
};
reliablePort = mkOption {
description = ''
Server reliable port number
This corresponds to the `-ReliablePort` command line option.
'';
default = 8888;
type = types.port;
example = literalExpression "8889";
};
externalReliablePort = mkOption {
description = ''
Server reliable port number as seen outside NAT.
This corresponds to the `-ExternalReliablePort` command line option.
'';
default = null;
type = types.nullOr types.port;
example = literalExpression "12345";
};
disableSeasonalEvents = mkOption {
description = ''
Whether to run the server with seasonal events disabled.
This corresponds to the `-DisableSeasonalEvents` command line option.
'';
default = false;
type = types.bool;
example = literalExpression "true";
};
extraIniOptions = mkOption {
description = ''
Run the server with additional ini configuration values.
This is a nested attribute set of values.
- The top level attribute specifies the ini file containing the value to set (i.e., the
first component of the `-ini` command line option), for example `Game` or `Engine`.
- The secondary level attribute specifies the ini file category, without brackets,
for example `/Script/Engine.GameSession`.
- The final level attribute specifies the option name to set, for example
`MaxPlayers`. The value of the attribute is the value to set on the command line.
This corresponds to the `-ini` command line option.
'';
default = {};
type = with types; attrsOf (attrsOf (attrsOf str));
example = literalExpression ''
{
Game."/Script/Engine.GameSession".MaxPlayers = "8";
}
'';
};
initialSettings = mkOption {
description = ''
Settings to apply to the server via the server API on the first run.
'';
type = types.submodule {
options = {
serverName = mkOption {
description = ''
The name of the server.
If this is provided, `adminPasswordFile` must also be set.
'';
type = with types; nullOr str;
default = null;
example = literalExpression "\"My Dedicated Server\"";
};
adminPasswordFile = mkOption {
description = ''
Path to a file containing the initial admin password.
If this is provided, `serverName` must also be set.
'';
type = with types; nullOr path;
default = null;
example = literalExpression "\"/var/lib/secrets/admin-password.txt\"";
};
clientPasswordFile = mkOption {
description = ''
Path to a file containing the initial client password. If not set, the server will
not be configured with a client password and will be accessible to any client.
'';
type = with types; nullOr path;
default = null;
example = literalExpression "\"/var/lib/secrets/client-password.txt\"";
};
};
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = with cfg.initialSettings; (serverName == null) == (adminPasswordFile == null);
message = ''
When either of services.satisfactory.initialSettings.serverName or
services.satisfactory.initialSettings.adminPasswordFile are set, the other must also be
set. The dedicated server API requires configuring both options simultaneously.
'';
}
{
assertion = with cfg.initialSettings; (clientPasswordFile == null) || (serverName != null);
message = ''
Option services.satisfactory.initialSettings.clientPasswordFile is set, but there are
no options set for the initial server claim data (i.e., serverName and adminPasswordFile).
Setting a client password is not possible without executing a server claim.
'';
}
];
users.users."${cfg.user}" = {
isSystemUser = true;
home = cfg.directory;
group = cfg.group;
createHome = false;
};
users.groups."${cfg.group}" = {};
systemd.tmpfiles.settings."satisfactory" = let
default = {
inherit (cfg) user group;
mode = "0755";
};
in {
"${cfg.directory}".d = default;
"${cfg.directory}/saves".d = default;
"${cfg.directory}/settings".d = default;
};
systemd.services = let
base_url = "https://127.0.0.1:${builtins.toString cfg.port}/api/v1/";
binary = "${cfg.directory}/server/Engine/Binaries/Linux/FactoryServer-Linux-Shipping";
ini_list = lib.flatten (
lib.mapAttrsToList (filename: fileOpts:
lib.mapAttrsToList (section: sectionOpts:
lib.mapAttrsToList (key: value:
" -ini:${filename}:[${section}]:${key}=${value}"
) sectionOpts
) fileOpts
) cfg.extraIniOptions
);
ini_args = lib.concatStringsSep " " ini_list;
port = with builtins;
"-Port=${toString cfg.port} -ReliablePort=${toString cfg.reliablePort}";
extport =
if cfg.externalReliablePort == null then
""
else
" -ExternalReliablePort=${builtins.toString cfg.externalReliablePort}";
seasonalEvts =
if cfg.disableSeasonalEvents then
" -DisableSeasonalEvents"
else
"";
args = "${port}${extport}${seasonalEvts}${ini_args}";
server_command = "${binary} FactoryGame ${args}";
doSetup = cfg.initialSettings.serverName != null;
commonConfig = {
after = ["network.target"] ++ lib.optionals (cfg.useACMEHost != null) [
"acme-finished-${cfg.useACMEHost}.target"
];
environment = {
"LD_LIBRARY_PATH" = "${cfg.directory}/server/linux64";
};
unitConfig = {
RequiresMountsFor = cfg.directory;
};
serviceConfig = {
Nice = "-5";
User = cfg.user;
Group = cfg.user;
WorkingDirectory = cfg.directory;
StandardOutput = "journal";
LoadCredential = lib.mkIf (cfg.useACMEHost != null) (let
certDir = config.security.acme.certs.${cfg.useACMEHost}.directory;
in [
"cert_chain.pem:${certDir}/fullchain.pem"
"private_key.pem:${certDir}/key.pem"
]);
ProtectSystem = true;
ProtectHome = true;
NoNewPrivileges = true;
# virtualize the file system to synthesize what is read only with what is dedicated server
# game state
PrivateTmp = true;
TemporaryFileSystem = [
"${cfg.directory}:ro"
];
BindReadOnlyPaths = [
"${cfg.package}:${cfg.directory}/server"
];
BindPaths = [
"${cfg.directory}/saves:${cfg.directory}/.config/Epic"
"/var/tmp:${cfg.directory}/server/FactoryGame/Intermediate"
"${cfg.directory}/settings:${cfg.directory}/server/FactoryGame/Saved"
] ++ lib.optionals (cfg.useACMEHost != null) [
"%d:${cfg.directory}/server/FactoryGame/Certificates"
];
Restart = "on-failure";
RestartSec = 60;
SuccessExitStatus = 143;
};
};
in {
"satisfactory" = lib.mkMerge [
commonConfig
{
description = "Satisfactory Dedicated Server";
wantedBy = [ "multi-user.target" ];
requires = lib.optionals doSetup ["satisfactory-first-time-setup.service"];
after = lib.optionals doSetup ["satisfactory-first-time-setup.service"];
serviceConfig = {
ExecStart = server_command;
};
}
];
"satisfactory-first-time-setup" = lib.mkIf doSetup (lib.mkMerge [
commonConfig
{
description = "Satisfactory Dedicated Server first-time setup";
path = with pkgs; [
curl
jq
];
unitConfig = {
ConditionPathExists =
"!${cfg.directory}/saves/FactoryGame/Saved/SaveGames/ServerSettings.${builtins.toString cfg.port}.sav";
};
serviceConfig = {
Type = "oneshot";
# isolate satisfactory during configuration
PrivateNetwork = true;
LoadCredential =
(lib.optionals (cfg.initialSettings.adminPasswordFile != null) [
"admin_password.txt:${cfg.initialSettings.adminPasswordFile}"
]) ++ (lib.optionals (cfg.initialSettings.clientPasswordFile != null) [
"client_password.txt:${cfg.initialSettings.clientPasswordFile}"
]);
};
script = ''
set -euo pipefail
set -m
echo Starting server...
${server_command} &
server_pid=$!
server_status=""
for i in {1..5}; do
server_status="$(curl -SsLk -XPOST -H "Content-Type: application/json" \
--data '{"function":"HealthCheck","data":{"clientCustomData":""}}' \
"${base_url}" | jq -r '.data.health' || true)"
if [ "$server_status" == "healthy" ]; then
break
fi
sleep 5
done
if [ "$server_status" != "healthy"; then
echo Server did not report healthy status in time
exit 1
fi
token="$(curl -SsLk -XPOST -H "Content-Type: application/json" \
--data '{"function":"PasswordlessLogin","data":{"MinimumPrivilegeLevel":"InitialAdmin"}}' \
"${base_url}" | jq -r '.data.authenticationToken')"
if [ "$token" == "null" ]; then
echo Server authentication failed
exit 2
fi
echo Executing server claim...
data="$(jq -n \
--arg "serverName" "${cfg.initialSettings.serverName}" \
--rawfile "password" "$CREDENTIALS_DIRECTORY/admin_password.txt" \
'{} |.function="ClaimServer" | .data.ServerName=$serverName | .data.AdminPassword=($password|rtrimstr("\n"))')"
new_token="$(curl -SsLk -XPOST -H "Content-Type: application/json" \
-H "Authorization: Bearer $token" \
--data "$data" \
"${base_url}" | jq -r '.data.authenticationToken')"
if [ "$new_token" == "null" ]; then
echo Server claim failed
exit 2
fi
token="$new_token"
if [ -f "$CREDENTIALS_DIRECTORY/client_password.txt" ]; then
echo Setting client password...
data="$(jq -n \
--rawfile "password" "$CREDENTIALS_DIRECTORY/client_password.txt" \
'{} |.function="SetClientPassword" | .data.Password=($password|rtrimstr("\n"))')"
result="$(curl -SsLk -XPOST -H "Content-Type: application/json" \
-H "Authorization: Bearer $token" \
--data "$data" \
"${base_url}" | jq -r '.data')"
if [ "$result" != "" ]; then
echo "Password set failed: $result"
exit 4
fi
fi
echo Setup complete
echo Stopping server...
kill -SIGTERM $server_pid
wait $server_pid
'';
}
]);
"satisfactory-restart-certs" = lib.mkIf (cfg.useACMEHost != null) {
description = "Restart Satisfactory Dedicated Server after cert provisioning";
wantedBy = ["acme-finished-${cfg.useACMEHost}.target"];
path = [config.systemd.package];
script = ''
systemctl try-restart satisfactory.service
'';
serviceConfig = {
Type = "simple";
};
};
};
};
}

View File

@ -1,7 +1,5 @@
final: prev: {
lib = prev.lib.extend (lfinal: lprev: {
licenses = lprev.licenses // { fyptl = import ./lib/licenses/fyptl.nix; };
});
lib = prev.lib.extend (import ./lib/overlay.nix);
fetchFromSteam = prev.callPackage ./lib/fetchsteam {};
fetchb4 = prev.callPackage ./lib/fetchb4 {};
@ -38,7 +36,10 @@ final: prev: {
feedvalidator = final.python312Packages.feedvalidator;
megacom = final.python312Packages.megacom;
# temporary upgrade so we can actually download satisfactory
depotdownloader = prev.callPackage ./pkgs/temp/depotdownloader {};
outer-wilds-text-adventure = prev.callPackage ./pkgs/games/outer-wilds-text-adventure {};
satisfactory-dedicated-server = prev.callPackage ./pkgs/games/satisfactory-dedicated-server {};
mkNginxServer = prev.callPackage ./lib/dev-nginx {};
@ -58,4 +59,8 @@ final: prev: {
pympress = prev.pympress.overrideDerivation (oldAttrs: {
patches = [ ./pkgs/python/pympress/0001-Fix-KDE-window-icon.patch ];
});
texliveDragonPackages = {
moloch = prev.callPackage ./pkgs/tex/moloch {};
};
}

View File

@ -7,32 +7,30 @@
}:
let
appId = "1690800";
buildId = "15636842";
buildId = "19234106";
steamworks_sdk = fetchFromSteam {
name = "steamworks-sdk";
inherit appId;
depot = {
depotId = "1006";
manifestId = "7138471031118904166";
manifestId = "5587033981095108078";
};
hash = "sha256-OtPI1kAx6+9G09IEr2kYchyvxlPl3rzx/ai/xEVG4oM=";
hash = "sha256-CjrVpq5ztL6wTWIa63a/4xHM35DzgDR/O6qVf1YV5xw=";
};
server_dist = fetchFromSteam {
name = "satisfactory-dedicated-server";
inherit appId;
depot = {
depotId = "1690802";
manifestId = "1910179703516567959";
manifestId = "5693629351763493998";
};
hash = "sha256-TxPegZFAwiAzuHgw9xLGr5sAP7KAVMMfPFYL7TRX1O0=";
hash = "sha256-0svLwO4JYKIPwoNCRfT9+pocZ0n1QpSEqP41DdUhEac=";
};
in stdenv.mkDerivation {
pname = "satisfactory-dedicated-server";
version = "build-${buildId}";
src = server_dist;
buildInputs = [ steamworks_sdk ];
propagatedBuildInputs = [ SDL2 ];
dontConfigure = true;
dontBuild = true;
@ -44,6 +42,7 @@ in stdenv.mkDerivation {
mkdir -p $out/FactoryGame/Intermediate
mkdir -p $out/FactoryGame/Saved
mkdir -p $out/FactoryGame/Certificates
rm $out/FactoryServer.sh
'';
@ -58,10 +57,12 @@ in stdenv.mkDerivation {
chmod +x $out/Engine/Binaries/Linux/FactoryServer-Linux-Shipping
patchelf --add-needed ${SDL2}/lib/libSDL2-2.0.so.0 \
patchelf \
--add-needed ${SDL2}/lib/libSDL2-2.0.so.0 \
$out/linux64/steamclient.so
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
patchelf \
--set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
--add-needed $out/linux64/steamclient.so \
$out/Engine/Binaries/Linux/FactoryServer-Linux-Shipping
'';

View File

@ -1,14 +1,14 @@
From 10a24d7831f51549d8c05193a0fbc329cc327fbe Mon Sep 17 00:00:00 2001
From d9e022548aff94e90914baa921ddb4cd939c0e5c Mon Sep 17 00:00:00 2001
From: xenia <xenia@awoo.systems>
Date: Sat, 21 Dec 2024 15:33:10 -0500
Subject: [PATCH] implement lix support
---
CMakeLists.txt | 27 -------------
extra-builtins.cc | 87 ++++++++++++++++-------------------------
meson.build | 18 +++++++++
CMakeLists.txt | 27 ------------
extra-builtins.cc | 91 ++++++++++++++++-------------------------
meson.build | 18 ++++++++
nix-plugins-config.h.in | 3 --
4 files changed, 51 insertions(+), 84 deletions(-)
4 files changed, 53 insertions(+), 86 deletions(-)
delete mode 100644 CMakeLists.txt
create mode 100644 meson.build
delete mode 100644 nix-plugins-config.h.in
@ -47,7 +47,7 @@ index 9674fe8..0000000
-
-install(TARGETS nix-extra-builtins DESTINATION lib/nix/plugins)
diff --git a/extra-builtins.cc b/extra-builtins.cc
index 3a0f90e..f2978f8 100644
index 3a0f90e..95aef5e 100644
--- a/extra-builtins.cc
+++ b/extra-builtins.cc
@@ -1,12 +1,8 @@
@ -68,8 +68,12 @@ index 3a0f90e..f2978f8 100644
using namespace nix;
@@ -24,39 +20,38 @@ static GlobalConfig::Register rp(&extraBuiltinsSettings);
static void extraBuiltins(EvalState & state, const PosIdx pos,
@@ -21,42 +17,41 @@ static ExtraBuiltinsSettings extraBuiltinsSettings;
static GlobalConfig::Register rp(&extraBuiltinsSettings);
-static void extraBuiltins(EvalState & state, const PosIdx pos,
+static void extraBuiltins(EvalState & state,
Value ** _args, Value & v)
{
- static auto extraBuiltinsFile = state.rootPath(CanonPath(extraBuiltinsSettings.extraBuiltinsFile.to_string()));
@ -130,8 +134,9 @@ index 3a0f90e..f2978f8 100644
+ Value* arg = state.ctx.mem.allocValue();
+ arg->mkAttrs(attrs);
v.mkApp(fun, arg);
state.forceValue(v, pos);
- state.forceValue(v, pos);
- } catch (FileNotFound &) {
+ state.forceValue(v, noPos);
+ } catch (SysError &) {
v.mkNull();
}
@ -190,5 +195,5 @@ index 459fea8..0000000
-#define NIX_CFLAGS_OTHER "@NIX_CFLAGS_OTHER@"
-#define BOOST_INCLUDE_DIR "@BOOST_INCLUDE_DIR@"
--
2.47.2
2.49.0

View File

@ -7,6 +7,7 @@
pkg-config,
lix,
capnproto,
boost182,
}: stdenv.mkDerivation {
name = "lix-plugins";
@ -30,6 +31,7 @@
buildInputs = [
lix
boost182
capnproto
];
meta = {

View File

@ -12,7 +12,7 @@ rustPlatform.buildRustPackage rec {
hash = "sha256-orvXNhM1WKlJ6j5Nuap0kZarydcujoEmF+OrdX7iFmA=";
};
cargoHash = "sha256-7/SP+drJWg2c4bsd3d4ge8E9BJZykbWfjgC2lSJhqas=";
cargoHash = "sha256-m8lXHfj6W/qltK+WrT0rE0gDNvvhghcXkeiX3Slx9X8=";
meta = {
description = "A firmware base address search tool";

View File

@ -0,0 +1,39 @@
{
lib,
buildDotnetModule,
fetchFromGitHub,
dotnetCorePackages,
}:
buildDotnetModule rec {
pname = "depotdownloader";
version = "3.4.0";
src = fetchFromGitHub {
owner = "SteamRE";
repo = "DepotDownloader";
rev = "DepotDownloader_${version}";
hash = "sha256-zduNWIQi+ItNSh9RfRfY0giIw/tMQIMRh9woUzQ5pJw=";
};
projectFile = "DepotDownloader.sln";
nugetDeps = ./deps.json;
dotnet-sdk = dotnetCorePackages.sdk_9_0;
dotnet-runtime = dotnetCorePackages.runtime_9_0;
passthru.updateScript = ./update.sh;
meta = {
description = "Steam depot downloader utilizing the SteamKit2 library";
changelog = "https://github.com/SteamRE/DepotDownloader/releases/tag/DepotDownloader_${version}";
license = lib.licenses.gpl2Only;
maintainers = [ lib.maintainers.babbaj ];
platforms = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
mainProgram = "DepotDownloader";
};
}

View File

@ -0,0 +1,72 @@
[
{
"pname": "Microsoft.NETCore.Platforms",
"version": "5.0.0",
"hash": "sha256-LIcg1StDcQLPOABp4JRXIs837d7z0ia6+++3SF3jl1c="
},
{
"pname": "Microsoft.Win32.Registry",
"version": "5.0.0",
"hash": "sha256-9kylPGfKZc58yFqNKa77stomcoNnMeERXozWJzDcUIA="
},
{
"pname": "Microsoft.Windows.CsWin32",
"version": "0.3.183",
"hash": "sha256-bn0rHYoVLRTqiZqkkp6u3PMKtg0NNxA2F++1e/+3Jhw="
},
{
"pname": "Microsoft.Windows.SDK.Win32Docs",
"version": "0.1.42-alpha",
"hash": "sha256-6DvzmNzrGVfWmNJNqooj+Ya+7bAQlyeg7pmyKaUlIws="
},
{
"pname": "Microsoft.Windows.SDK.Win32Metadata",
"version": "61.0.15-preview",
"hash": "sha256-OB60ThIv8e7AMGaRRzJ8dWme5HjN+Q0HoUDquP2ejTg="
},
{
"pname": "Microsoft.Windows.WDK.Win32Metadata",
"version": "0.12.8-experimental",
"hash": "sha256-YaN6JlgnpIooLYu3NdFVHwoqFwZYTeePtekXCfTiLTo="
},
{
"pname": "protobuf-net",
"version": "3.2.52",
"hash": "sha256-phXeroBt5KbHYkApkkMa0mRCVkDY+dtOOXXNY+i50Ek="
},
{
"pname": "protobuf-net.Core",
"version": "3.2.52",
"hash": "sha256-/9Jj26tuSKeYJb9udwew5i5EVvaoeNu/vBCKS0VhSQQ="
},
{
"pname": "QRCoder",
"version": "1.6.0",
"hash": "sha256-2Ev/6d7PH6K4dVYQQHlZ+ZggkCnDtrlaGygs65mDo28="
},
{
"pname": "SteamKit2",
"version": "3.2.0",
"hash": "sha256-hB/36fP9kf+1mIx+hTELUMHe8ZkmSKxOK41ZzOaBa3E="
},
{
"pname": "System.IO.Hashing",
"version": "9.0.4",
"hash": "sha256-rbcQzEncB3VuUZIcsE1tq30suf5rvRE4HkE+0lR/skU="
},
{
"pname": "System.Security.AccessControl",
"version": "5.0.0",
"hash": "sha256-ueSG+Yn82evxyGBnE49N4D+ngODDXgornlBtQ3Omw54="
},
{
"pname": "System.Security.Principal.Windows",
"version": "5.0.0",
"hash": "sha256-CBOQwl9veFkrKK2oU8JFFEiKIh/p+aJO+q9Tc2Q/89Y="
},
{
"pname": "ZstdSharp.Port",
"version": "0.8.5",
"hash": "sha256-+UQFeU64md0LlSf9nMXif6hHnfYEKm+WRyYd0Vo2QvI="
}
]

View File

@ -0,0 +1,94 @@
{
fetchFromGitea,
writeShellScript,
writableTmpDirAsHomeHook,
stdenvNoCC,
texlivePackages,
texliveBasic,
}:
let
texEnv = texliveBasic.withPackages (ps: with ps; [
# l3build
beamer
biblatex
enumitem
fileinfo
hypdoc
hyperref
listings
metalogo
parskip
pgf
pgfopts
setspace
xurl
microtype
latexmk
]);
in stdenvNoCC.mkDerivation rec {
pname = "moloch";
version = "1.0.2-DEV-xenia";
outputs = [
"tex"
"texdoc"
];
passthru.tlDeps = with texlivePackages; [ latex ];
src = fetchFromGitea {
domain = "git.lain.faith";
owner = "haskal";
repo = "${pname}-dragon";
rev = "v${version}";
hash = "sha256-eMlhJj4a2HTDhDzkS9KR+d76lt81iH7x//WZOA39tno=";
};
dontConfigure = true;
nativeBuildInputs = [
texEnv
# multiple-outputs.sh fails if $out is not defined
(writeShellScript "force-tex-output.sh" ''
out="''${tex-}"
'')
writableTmpDirAsHomeHook # Need a writable $HOME for latexmk
];
# we just build manually, but moloch's own method of building is using l3build
# i have no idea how to get that working, so for now just do it normal style
buildPhase = ''
runHook preBuild
# Generate the style files
cd src
latex beamertheme${pname}.ins
# Generate the documentation
cp ../doc/${pname}.tex .
latexmk -pdf ${pname}.tex
cd ..
runHook postBuild
'';
installPhase = ''
runHook preInstall
path="$tex/tex/latex/${pname}"
mkdir -p "$path"
cp src/*.{cls,def,clo,sty} "$path/"
path="$texdoc/doc/tex/latex/${pname}"
mkdir -p "$path"
cp src/${pname}.pdf "$path/"
runHook postInstall
'';
}

1
templates/beamer/.envrc Normal file
View File

@ -0,0 +1 @@
use flake

16
templates/beamer/.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
/my-beamer-presentation.pdf
*.aux
*.fdb_latexmk
*.fls
*.log
*.nav
*.out
*.snm
*.synctex.gz
*.toc
result
result-tex
.direnv

View File

@ -0,0 +1,46 @@
{
description = "A very basic presentation with Beamer";
outputs = { self, dragnpkgs } @ inputs: dragnpkgs.lib.mkFlake {
# Define a texlive environment to use
packages.texlive-custom = { texliveMedium, texliveDragonPackages }:
texliveMedium.withPackages (ps: with ps; [
fontawesome5
texliveDragonPackages.moloch
]);
# Package definition for building the PDF
packages.default = { system, stdenvNoCC }: stdenvNoCC.mkDerivation rec {
pname = "my-beamer-presentation";
name = "${pname}.pdf";
nativeBuildInputs = [
self.packages.${system}.texlive-custom
];
src = self;
buildPhase = ''
latexmk -pdf ${pname}.tex
'';
installPhase = ''
cp ${pname}.pdf $out
'';
};
# Runnable package (ie `nix run`) to start the presentation
apps.default = { lib, system, writeShellScript, pympress }: {
type = "app";
program = "${writeShellScript "start-presentation" ''
exec ${lib.getExe pympress} ${self.packages.${system}.default}
''}";
};
# Devshell definition to expose the texlive environment to eg nvim
devShells.default = { mkShell, system }: mkShell {
packages = [ self.packages.${system}.texlive-custom ];
};
};
}

View File

@ -0,0 +1,93 @@
\documentclass[aspectratio=169]{beamer}
\usepackage[english]{babel}
\usepackage{fontawesome5}
\usepackage{tikz}
\usetikzlibrary{arrows,calc,fit,positioning}
\usetheme{moloch}
\usefonttheme[onlymath]{serif}
% this can be commented out to produce a slide deck with no notes
\setbeameroption{show notes}
% useful tikz styles from previous slide decks
\tikzset{%
icon/.value required,
icon/.style={%
node contents={\faIcon{#1}},
icon size=normal,
},
icon size/.is choice,
icon size/.default=normal,
icon size/normal/.style={%
font={\fontsize{20.74}{20.74}\selectfont}
},
icon size/small/.style={%
font={\fontsize{12}{12}\selectfont}
},
rounded box/.style={%
inner sep=0.3em,
draw,
rounded corners,
line width=0.1em
},
sequence diagram/.style={%
font=\small,
line width=1pt,
sequence/.style={%
every to/.style={%
to path={(\tikztostart) -- (\tikztostart -| \tikztotarget) \tikztonodes} % chktex 1 chktex 8
},
->/.style={-stealth,every node/.style={above}},
<-/.style={stealth-,every node/.style={below}},
},
note/.style={%
color=example text.fg,
},
},
}
\title{My Beamer Presentation}
\subtitle{(From the template)}
\author{You}
\institute{Institute of Swag Nix Templates}
\date{Now}
\begin{document}
\maketitle
\section{My Section}
\subsection{My Subsection}
\begin{frame}
\frametitle{Some Slide Title}
Sample text
\end{frame}
\begin{frame}
\frametitle{Some Other Slide Title}
Sample text 2
\end{frame}
\appendix
\begin{frame}[standout]
Backup Slides
\end{frame}
\begin{frame}
\frametitle{Backup slide 1}
Some backup slide content
\end{frame}
\end{document}