···262262 mfi = 238;
263263 caddy = 239;
264264 taskd = 240;
265265+ factorio = 241;
265266266267 # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
267268···495496 #mfi = 238; # unused
496497 caddy = 239;
497498 taskd = 240;
499499+ factorio = 241;
498500499501 # When adding a gid, make sure it doesn't match an existing
500502 # uid. Users and groups with the same name should have equal
···11+{ config, lib, pkgs, ... }:
22+33+with lib;
44+55+let
66+ cfg = config.services.factorio;
77+ name = "Factorio";
88+ stateDir = "/var/lib/factorio";
99+ configFile = pkgs.writeText "factorio.conf" ''
1010+ use-system-read-write-data-directories=true
1111+ [path]
1212+ read-data=${pkgs.factorio-headless}/share/factorio/data
1313+ write-data=${stateDir}
1414+ '';
1515+in
1616+{
1717+ options = {
1818+ services.factorio = {
1919+ enable = mkEnableOption name;
2020+ port = mkOption {
2121+ type = types.int;
2222+ default = 34197;
2323+ description = ''
2424+ The port to which the service should bind.
2525+2626+ This option will also open up the UDP port in the firewall configuration.
2727+ '';
2828+ };
2929+ saveName = mkOption {
3030+ type = types.string;
3131+ default = "default";
3232+ description = ''
3333+ The name of the savegame that will be used by the server.
3434+3535+ When not present in ${stateDir}/saves, it will be generated before starting the service.
3636+ '';
3737+ };
3838+ # TODO Add more individual settings as nixos-options?
3939+ # TODO XXX The server tries to copy a newly created config file over the old one
4040+ # on shutdown, but fails, because it's in the nix store. When is this needed?
4141+ # Can an admin set options in-game and expect to have them persisted?
4242+ configFile = mkOption {
4343+ type = types.path;
4444+ default = configFile;
4545+ defaultText = "configFile";
4646+ description = ''
4747+ The server's configuration file.
4848+4949+ The default file generated by this module contains lines essential to
5050+ the server's operation. Use its contents as a basis for any
5151+ customizations.
5252+ '';
5353+ };
5454+ };
5555+ };
5656+5757+ config = mkIf cfg.enable {
5858+ users = {
5959+ users.factorio = {
6060+ uid = config.ids.uids.factorio;
6161+ description = "Factorio server user";
6262+ group = "factorio";
6363+ home = stateDir;
6464+ createHome = true;
6565+ };
6666+6767+ groups.factorio = {
6868+ gid = config.ids.gids.factorio;
6969+ };
7070+ };
7171+7272+ systemd.services.factorio = {
7373+ description = "Factorio headless server";
7474+ wantedBy = [ "multi-user.target" ];
7575+ after = [ "network.target" ];
7676+7777+ preStart = ''
7878+ test -e ${stateDir}/saves/${cfg.saveName}.zip || ${pkgs.factorio-headless}/bin/factorio \
7979+ --config=${cfg.configFile} \
8080+ --create=${cfg.saveName}
8181+ '';
8282+8383+ serviceConfig = {
8484+ User = "factorio";
8585+ Group = "factorio";
8686+ Restart = "always";
8787+ KillSignal = "SIGINT";
8888+ WorkingDirectory = stateDir;
8989+ PrivateTmp = true;
9090+ UMask = "0007";
9191+ ExecStart = toString [
9292+ "${pkgs.factorio-headless}/bin/factorio"
9393+ "--config=${cfg.configFile}"
9494+ "--port=${toString cfg.port}"
9595+ "--start-server=${cfg.saveName}"
9696+ ];
9797+ };
9898+ };
9999+100100+ networking.firewall.allowedUDPPorts = [ cfg.port ];
101101+ };
102102+}
+80-50
pkgs/games/factorio/default.nix
···44# Begin download parameters
55, username ? ""
66, password ? ""
77+, releaseType
78}:
891010+assert releaseType == "alpha" || releaseType == "headless";
1111+1212+with stdenv.lib;
913let
1010- version = "0.12.28";
1414+ version = "0.12.29";
1515+ isHeadless = releaseType == "headless";
1616+1717+ arch = if stdenv.system == "x86_64-linux" then {
1818+ inUrl = "linux64";
1919+ inTar = "x64";
2020+ } else if stdenv.system == "i686-linux" then {
2121+ inUrl = "linux32";
2222+ inTar = "i386";
2323+ } else abort "Unsupported platform";
11241212- fetch = callPackage ./fetch.nix { username = username; password = password; };
1313- arch = if stdenv.system == "x86_64-linux" then "x64"
1414- else if stdenv.system == "i686-linux" then "x32"
1515- else abort "Unsupported platform";
2525+ authenticatedFetch = callPackage ./fetch.nix { inherit username password; };
16261717- variants = {
2727+ fetch = rec {
2828+ url = "https://www.factorio.com/get-download/${version}/${releaseType}/${arch.inUrl}";
2929+ name = "factorio_${releaseType}_${arch.inTar}-${version}.tar.gz"; # TODO take this from 302 redirection somehow? fetchurl doesn't help.
1830 x64 = {
1919- url = "https://www.factorio.com/get-download/${version}/alpha/linux64";
2020- sha256 = "01si5n9hb2h0c5q8k3hr3nphsakp9kki84qyp70dgddwqsn8wfjl";
3131+ headless = fetchurl { inherit name url; sha256 = "1hr5dhpfagknjjd47qw3fa3ap8ikjc9hvxavrg4mpslbr0iqww8v"; };
3232+ alpha = authenticatedFetch { inherit url; sha256 = "0vngfrjjib99k6czhg32rikfi36i3p3adx4mxc1z8bi5n70dbwqb"; };
2133 };
2222-2323- x32 = {
2424- url = "https://www.factorio.com/get-download/${version}/alpha/linux32";
2525- sha256 = "13h013ixyhv4rpvh0jv5jry3mrwv65v57nqn16bjh3hr8ip70lkq";
3434+ i386 = {
3535+ headless = abort "Factorio 32-bit headless binaries are not available for download.";
3636+ alpha = authenticatedFetch { inherit url; sha256 = "10135rd9103x79i89p6fh5ssmw612012yyx3yyhb3nzl554zqzbm"; };
2637 };
2738 };
3939+4040+ configBaseCfg = ''
4141+ use-system-read-write-data-directories=false
4242+ [path]
4343+ read-data=$out/share/factorio/data/
4444+ '';
4545+4646+ updateConfigSh = ''
4747+ #! $SHELL
4848+ if [[ -e ~/.factorio/config.cfg ]]; then
4949+ # Config file exists, but may have wrong path.
5050+ # Try to edit it. I'm sure this is perfectly safe and will never go wrong.
5151+ sed -i 's|^read-data=.*|read-data=$out/share/factorio/data/|' ~/.factorio/config.cfg
5252+ else
5353+ # Config file does not exist. Phew.
5454+ install -D $out/share/factorio/config-base.cfg ~/.factorio/config.cfg
5555+ fi
5656+ '';
5757+2858in
29593060stdenv.mkDerivation rec {
3131- name = "factorio-${version}";
6161+ name = "factorio-${releaseType}-${version}";
32623333- src = fetch variants.${arch};
6363+ src = fetch.${arch.inTar}.${releaseType};
34643535- libPath = stdenv.lib.makeLibraryPath [
3636- alsaLib
3737- libX11
3838- libXcursor
3939- libXinerama
4040- libXrandr
4141- libXi
4242- mesa_noglu
4343- ];
6565+ libPath = stdenv.lib.makeLibraryPath (
6666+ optionals (! isHeadless) [
6767+ alsaLib
6868+ libX11
6969+ libXcursor
7070+ libXinerama
7171+ libXrandr
7272+ libXi
7373+ mesa_noglu
7474+ ]
7575+ );
44764577 buildInputs = [ makeWrapper ];
46787979+ dontBuild = true;
8080+8181+ # TODO detangle headless/normal mode wrapping, libs, etc. test all urls 32/64/headless/gfx
4782 installPhase = ''
4883 mkdir -p $out/{bin,share/factorio}
4949- cp -a bin/${arch}/factorio $out/bin/factorio.${arch}
5050- cp -a doc-html data $out/share/factorio/
5151-5252- # Fortunately, Factorio already supports system-wide installs.
5353- # Unfortunately it's a bit inconvenient to set the paths.
5454- cat > $out/share/factorio/config-base.cfg <<EOF
5555-use-system-read-write-data-directories=false
5656-[path]
5757-read-data=$out/share/factorio/data/
5858-EOF
5959-6060- cat > $out/share/factorio/update-config.sh <<EOF
6161-if [[ -e ~/.factorio/config.cfg ]]; then
6262- # Config file exists, but may have wrong path.
6363- # Try to edit it. I'm sure this is perfectly safe and will never go wrong.
6464- sed -i 's|^read-data=.*|read-data=$out/share/factorio/data/|' ~/.factorio/config.cfg
6565-else
6666- # Config file does not exist. Phew.
6767- install -D $out/share/factorio/config-base.cfg ~/.factorio/config.cfg
6868-fi
6969-EOF
7070- chmod a+x $out/share/factorio/update-config.sh
7171-8484+ cp -a data $out/share/factorio
8585+ cp -a bin/${arch.inTar}/factorio $out/bin/factorio
7286 patchelf \
7387 --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
7474- $out/bin/factorio.${arch}
8888+ $out/bin/factorio
75897676- makeWrapper $out/bin/factorio.${arch} $out/bin/factorio \
9090+ '' + optionalString (! isHeadless) (''
9191+ mv $out/bin/factorio $out/bin/factorio.${arch.inTar}
9292+ makeWrapper $out/bin/factorio.${arch.inTar} $out/bin/factorio \
7793 --prefix LD_LIBRARY_PATH : /run/opengl-driver/lib:$libPath \
7894 --run "$out/share/factorio/update-config.sh" \
7995 --add-flags "-c \$HOME/.factorio/config.cfg"
8080- '';
9696+ # Fortunately, Factorio already supports system-wide installs.
9797+ # Unfortunately it's a bit inconvenient to set the paths.
9898+ install -m0644 <(cat << EOF
9999+ '' + configBaseCfg + ''
100100+ EOF
101101+ ) $out/share/factorio/config-base.cfg
102102+103103+ install -m0755 <(cat << EOF
104104+ '' + updateConfigSh + ''
105105+ EOF
106106+ ) $out/share/factorio/update-config.sh
107107+ cp -a doc-html $out/share/factorio
108108+ '');
109109+110110+ preferLocalBuild = true;
8111182112 meta = {
83113 description = "A game in which you build and maintain factories";
···95125 '';
96126 homepage = https://www.factorio.com/;
97127 license = stdenv.lib.licenses.unfree;
9898- maintainers = [ stdenv.lib.maintainers.Baughn ];
128128+ maintainers = with stdenv.maintainers; [ Baughn elitak ];
99129 platforms = [ "i686-linux" "x86_64-linux" ];
100130 };
101131}