Skip to content

Instantly share code, notes, and snippets.

@boxofrox
Last active November 12, 2019 20:55
Show Gist options
  • Save boxofrox/eeb9cba5b25d4caad7b47a26039b1b61 to your computer and use it in GitHub Desktop.
Save boxofrox/eeb9cba5b25d4caad7b47a26039b1b61 to your computer and use it in GitHub Desktop.
Print file limits for systemd services.
result
*.qcow2

Setup

  1. Create a working folder. E.g mkdir test.
  2. Copy default.nix into working folder.
  3. Copy vmtest.nix into working folder.

Build a VM

sudo nixos-rebuild build-vm --fast -I nixos-config=./vmtest.nix

Run the vm

./result/bin/run-test-nixos-vm

File limits

Inside the VM, print the guest OS file limits with print-file-limits.

Then check the journal log for the print-file-limits service with journal -u print-file-limits.service --no-pager -e.

Gist

https://gist.github.com/boxofrox/eeb9cba5b25d4caad7b47a26039b1b61

{ lib, pkgs, ... }:
with lib;
let
buildScript = pkgs.writeText "test-builder.sh" ''
export PATH="$coreutils/bin:$gcc/bin"
mkdir -p $out/bin
gcc -o $out/bin/print-file-limits $src
'';
src = pkgs.writeText "print-file-limits.c" ''
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
int main () {
struct rlimit limit;
getrlimit(RLIMIT_NOFILE, &limit);
printf(
"RLIMIT_NOFILE soft(%lld) hard(%lld)",
(long long) limit.rlim_cur,
(long long) limit.rlim_max
);
}
'';
package = pkgs.stdenv.mkDerivation {
name = "print-file-limits";
version = "0.0.1";
inherit src;
inherit (pkgs) gcc coreutils;
builder = "${pkgs.bash}/bin/bash";
args = [ buildScript ];
system = builtins.currentSystem;
};
in {
config = {
systemd.services."print-file-limits" = {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${package}/bin/print-file-limits";
LimitNOFILE = "128000:1000000";
};
};
environment.systemPackages = [ package ];
};
}

Without adjusting file-max, logLimits, and service limits in vmtest.nix

[vm@test-nixos:~]$ print-file-limits
RLIMIT_NOFILE soft(1024) hard(524288)

[vm@test-nixos:~]$ journalctl -u print-file-limits --no-pager -e
-- Logs begin at Tue 2019-11-12 17:00:52 UTC, end at Tue 2019-11-12 17:23:53 UTC. --
Nov 12 17:23:32 test-nixos systemd[1]: Starting print-file-limits.service...
Nov 12 17:23:32 test-nixos print-file-limits[549]: RLIMIT_NOFILE soft(1024) hard(524288)
Nov 12 17:23:32 test-nixos systemd[1]: print-file-limits.service: Succeeded.
Nov 12 17:23:32 test-nixos systemd[1]: Started print-file-limits.service.

Note that soft and hard limits match between service and user process.

After adjusting file-max and logLimits in vmtest.nix

[vm@test-nixos:~]$ print-file-limits
RLIMIT_NOFILE soft(8192) hard(8192)
[vm@test-nixos:~]$ journalctl -u print-file-limits.service --no-pager -e
-- Logs begin at Tue 2019-11-12 17:00:52 UTC, end at Tue 2019-11-12 17:31:30 UTC. --
Nov 12 17:30:36 test-nixos systemd[1]: Starting print-file-limits.service...
Nov 12 17:30:36 test-nixos print-file-limits[548]: RLIMIT_NOFILE soft(1024) hard(524288)
Nov 12 17:30:36 test-nixos systemd[1]: print-file-limits.service: Succeeded.
Nov 12 17:30:36 test-nixos systemd[1]: Started print-file-limits.service.

Note that soft and hard limits don't match between service and user process. This confirms that file-max and logLimits do not affect service file limits.

After adjusting file-max, logLimits, and service limits in vmtest.nix

[vm@test-nixos:~]$ cat /etc/systemd/system.conf
[Manager]
DefaultCPUAccounting=yes
DefaultBlockIOAccounting=yes
DefaultIOAccounting=yes
DefaultBlockIOAccounting=yes
DefaultIPAccounting=yes

DefaultLimitCORE=infinity
DefaultLimitNOFILE=128K:512K


[vm@test-nixos:~]$ print-file-limits
RLIMIT_NOFILE soft(8192) hard(8192)
[vm@test-nixos:~]$ journalctl -u print-file-limits.service --no-pager -e
-- Logs begin at Tue 2019-11-12 17:00:52 UTC, end at Tue 2019-11-12 17:59:18 UTC. --
Nov 12 17:57:56 test-nixos systemd[1]: Starting print-file-limits.service...
Nov 12 17:57:56 test-nixos print-file-limits[542]: RLIMIT_NOFILE soft(1024) hard(524288)
Nov 12 17:57:56 test-nixos systemd[1]: print-file-limits.service: Succeeded.
Nov 12 17:57:56 test-nixos systemd[1]: Started print-file-limits.service.

Despite setting DefaultLimitNOFILE, the RLIMIT for print-file-limits.service did not change. Not sure what is required here.

Change service limit to local option. Also bump service hard limit to 1M.

[vm@test-nixos:~]$ journalctl -u print-file-limits.service --no-pager -e
-- Logs begin at Tue 2019-11-12 17:00:52 UTC, end at Tue 2019-11-12 18:41:56 UTC. --
Nov 12 18:41:35 test-nixos print-file-limits[555]: RLIMIT_NOFILE soft(1024) hard(524288)

[vm@test-nixos:~]$ grep NOFILE /etc/systemd/system/print-file-limits.service
LimitNOFILE=125K:1M

[vm@test-nixos:~]$ cat /etc/systemd/system.conf
[Manager]
DefaultCPUAccounting=yes
DefaultBlockIOAccounting=yes
DefaultIOAccounting=yes
DefaultBlockIOAccounting=yes
DefaultIPAccounting=yes

DefaultLimitCORE=infinity

Still no change in RLIMITS reported by print-file-limits.service.

Remove units from service hard limit.

diff --git a/default.nix b/default.nix
index 46732a2..646275c 100644
--- a/default.nix
+++ b/default.nix
@@ -47,7 +47,7 @@ in {
       serviceConfig = {
         Type = "oneshot";
         ExecStart = "${package}/bin/print-file-limits";
-        LimitNOFILE = "128K:1M";
+        LimitNOFILE = "128000:1000000";
       };
     };
 
[vm@test-nixos:~]$ journalctl -u print-file-limits.service -n 5 --no-pager
-- Logs begin at Tue 2019-11-12 17:00:52 UTC, end at Tue 2019-11-12 20:36:04 UTC. --
Nov 12 20:35:43 test-nixos print-file-limits[518]: RLIMIT_NOFILE soft(125000) hard(1000000)

RLIMITS for print-file-limits.service now reflect the settings in the service file.

{ pkgs, ...}:
{
imports = [ ./default.nix ];
fileSystems."/".label = "vmdisk";
networking.hostName = "test-nixos";
users.extraUsers.vm = {
password = "vm";
shell = "${pkgs.bash}/bin/bash";
group = "wheel";
};
security.sudo = {
enable = true;
wheelNeedsPassword = false;
};
virtualisation = {
graphics = false;
cores = 2;
};
# Adjust file-max.
boot.kernel.sysctl = {
"fs.file-max" = 2097152;
};
# Adjust logLimits.
security.pam.loginLimits = [
{ domain = "*"; item = "nofile"; type = "soft"; value = "8192"; }
{ domain = "*"; item = "nofile"; type = "hard"; value = "8192"; }
];
# Adjust systemd service limits. Using per-service limit in default.nix.
/*
systemd.extraConfig = ''
DefaultLimitNOFILE=128K:1M
'';
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment