cookbook 'limits', '~> 3.1.0'
limits (11) Versions 3.1.0 Follow11
Configures limits for the pam_limits module
cookbook 'limits', '~> 3.1.0', :supermarket
knife supermarket install limits
knife supermarket download limits
Limits Cookbook
This cookbook is used to configure limits for the pam_limits module.
By default, the configuration file is located at
/etc/security/limits.conf. It can also configure limits in any
arbitrary path such as files in the directory /etc/security/limits.d.
It is available on the Chef Supermarket or GitHub.
Requirements
Chef Infra Client 18 or newer and older than 20, or the equivalent Cinc
Client release. No gems or other cookbooks are required.
Any platform whose pam_limits reads /etc/security/limits.conf and
/etc/security/limits.d, which in practice means Linux. The cookbook
declares support for CentOS, Debian, Fedora, RedHat, Rocky and Ubuntu, and
is tested on Debian 13, Fedora 43, Rocky Linux 9, Rocky Linux 10 and
Ubuntu 24.04.
Usage
This cookbook does not provide any recipes. Instead, it should be
added as a dependency of another cookbook. This will make the custom
resources provided by the limits cookbook available to be used in
another cookbook's recipes.
Here is an example of managing the system's limit.conf file, adding two
limits, managing a limits.d file, deleting any manually-added limits,
and adding one limit:
# System limits.conf example limits_file '/etc/security/limits.conf' do action :create end limit 'example-1' do domain '*' type 'hard' item 'nofile' value 512 end limit 'example-2' do domain '@student' type 'soft' item 'nproc' value 20 end # Separate limits.d example limits_file '/etc/security/limits.d/001_vader.conf' do action [:create, :purge] end limit 'example-3' do path '/etc/security/limits.d/001_vader.conf' domain 'vader' type 'hard' item 'nofile' value 1000 end
Custom Resource: limits_file
This resource is used to manage a limits file. It is not required in
order to use the limit resource, but it is required to purge limits
that were not set via Chef. It can also be used without any limit
resources to just maintain the formatting of a limits file.
| Property | Type | Default | Required |
|---|---|---|---|
path |
String | (name property) | No |
owner |
String, Integer | root |
No |
group |
String, Integer | root |
No |
mode |
String, Integer | 0644 |
No |
backup |
Integer, FalseClass | false |
No |
Backups
backup is the number of copies Chef keeps when this resource changes
the file, or false to keep none. It is worth knowing which writes that
covers, because it is fewer than it looks.
The create action renders the file from what is already on disk, so it
changes the file on the first converge, when it reformats, and rarely
again: on later runs it reads the file, renders the same bytes, and has
nothing to write. The purge action changes the file every time it
removes a limit. So in practice backup is a purge feature, which is
also the action where a copy of the previous file is worth the most.
Writes made by the limit resource are never backed up, and that resource
has no backup property. It rewrites the whole file once per limit, so
twenty limits on one path is twenty writes in one run. Backups assume a
resource that writes a file once; keeping them here would leave nineteen
snapshots of half-applied state and push the one useful pre-run copy out
of the retention window. Point a limits_file at the path if you want the
file's writes backed up.
Action: create (default)
This action will create the desired limits file. The file will be
formatted to a known style. Any comments not attached to limits or lines
that are not limits will be removed from the file. Existing limits and
attached comments will remain. File owner, group, and mode will be
maintained by Chef.
Action: purge
This action will remove any limits in the limits file that were not
configured via Chef. This is useful if you want to ensure that a limits
file is completely managed by Chef and any manually-added limits are
removed.
A limit counts as configured via Chef when a limit resource declaring
it appears anywhere in the run with the same path, whichever recipe
declared it. The resource collection is what is consulted, not the file,
so it makes no difference whether that limit has converged yet or
converges at all: a limit declared with action :nothing is left alone
on the runs where nothing notifies it, rather than being removed and
written back the next time it fires.
When it removes something it rewrites the file through Chef, so backup
is honored. Owner, group, and mode are maintained the same way the
create action maintains them, on every run rather than only on one that
finds something to remove: otherwise the run that corrected a file's
permissions would be the same run that left nothing to purge, and a file
changed by hand afterwards would stay changed.
The content of a file with nothing to purge is left alone rather than
reformatted, since this action was not asked to create anything, and a
path with no file on it is left alone entirely rather than given an empty
one.
Action: delete
This action will delete the desired limits file.
Examples
limits_file '/etc/security/limits.conf' do action :create end limits_file '/etc/security/limits.d/001_vader.conf' do action [:create, :purge] end limits_file '/etc/security/limits.d/002_anakin.conf' do action :delete end
Custom Resource: limit
This resource is used to manage a specific limit in a limits file. The
limits_file resource is not required to be used in conjunction with
this resource, but they do complement each other.
| Property | Type | Default | Required |
|---|---|---|---|
path |
String | /etc/security/limits.conf |
No |
domain |
String | none | Yes |
type |
String | none | Yes |
item |
String | none | Yes |
value |
Integer, String | none | Yes |
comment |
String | none | No |
type and item are checked against the tables below and the run fails
on anything else.
comment is the comment's own text. The # that opens every comment
line in a limits file is written for you, so a comment carrying one of
its own keeps it: comment '#4127 see the ticket' is written as
# #4127 see the ticket. A multi-line comment is written one # per
line, and trailing whitespace is dropped from each of them.
The file is written through Chef's file resource, the same as
limits_file writes it. A change replaces the file in one step, so
pam_limits reads either the previous file or the new one, never a
partial one. The write is not reported on its own, because this resource
is declared once per limit rather than once per file and the limit's own
change is already reported. One consequence is worth knowing:
the file is replaced rather than written over, so POSIX ACLs set with
setfacl are not carried across. That is equally true of every other
file Chef manages.
It sets no owner, group, mode or backup: those belong to limits_file. A
path managed only by limit resources keeps whatever permissions it
already had, or takes the run's umask if the file is new, and is never
backed up.
More documentation on domain, type, item, and value can be found at the
limits.conf man page.
Valid types
| Type | Meaning |
|---|---|
soft |
The limit in force, which a user may raise up to the hard limit |
hard |
The ceiling the soft limit cannot be raised past |
- |
Sets both the soft and the hard limit at once |
Valid items
| Item | Meaning |
|---|---|
as |
Address space limit (KB) |
chroot |
Change root to directory |
core |
Maximum core file size (KB) |
cpu |
Maximum CPU time (minutes) |
data |
Maximum data size (KB) |
fsize |
Maximum file size (KB) |
locks |
Maximum number of file locks |
maxlogins |
Maximum number of logins for this user |
maxsyslogins |
Maximum number of logins on the system |
memlock |
Maximum locked-in-memory address space (KB) |
msgqueue |
Maximum memory used by POSIX message queues (bytes) |
nice |
Maximum nice priority allowed to raise to |
nofile |
Maximum number of open file descriptors |
nonewprivs |
0 or 1; 1 disables acquiring new privileges |
nproc |
Maximum number of processes |
priority |
The priority to run the user's processes with |
rss |
Maximum resident set size (KB), ignored since Linux 2.4.30 |
rtprio |
Maximum realtime priority for non-privileged processes |
rttime |
Timeout for real-time tasks (microseconds) |
sigpending |
Maximum number of pending signals |
stack |
Maximum stack size (KB) |
Three of these are not available everywhere, and the resource does not
check: pam_limits logs an unknown item and skips the line, so setting
one writes a limit a newer module will honor rather than failing the run.
Which pam_limits is installed on a node is the operator's business.
| Item | Available in |
|---|---|
chroot |
Debian and Ubuntu only. A distribution patch rather than an upstream item, so it is absent from the man page |
nonewprivs |
Linux-PAM 1.5.0 and newer, released November 2020 |
rttime |
Linux-PAM 1.7.1 and newer, released June 2025, so still ahead of most distributions |
A value is a number, or one of -1, unlimited and infinity for no
limit, which the man page allows for every item except priority,
nice and nonewprivs. The resource does not check a value against its
item. No field may be empty or contain whitespace or a #, because
pam_limits splits a line on whitespace and ends it at a #, so such a
limit could not be read back from the file it was written to.
That includes a group whose name has a space in it, which pam_limits
has no way to name: there is no quoting or escaping in limits.conf, so
@domain users is read as the domain @domain followed by a type of
users. Groups like this usually come from a directory service. On a
node that resolves them through SSSD, the override_space option in
sssd.conf replaces the space with another character, and the group can
then be named that way, as @domain_users.
Action: create (default)
This action will create the desired limit inside the limits file. This
will also have the affect of reformatting the limits file. Any comments
not attached to limits or lines that are not limits will be removed from
the file. Existing limits and attached comments will remain.
If the limit already exists in the file, any out-of-sync properties will
be updated. A limit is identified by the combination of domain, type,
and item.
Action: delete
This action will delete the desired limit inside the limits file. A
limit is identified by the combination of domain, type, and item.
Examples
limit 'create example' do domain 'ftp' type 'hard' item 'nproc' value 0 action :create end limit 'delete example' do path '/etc/security/limits.d/001_vader.conf' domain 'vader' type 'hard' item 'nofile' action :delete end
Dependent cookbooks
This cookbook has no specified dependencies.
Contingent cookbooks
limits cookbook CHANGELOG
v3.1.0
Input that was silently mishandled is now refused. A limit whose domain
or value carries whitespace or a # cannot be written to a limits file
and read back, so it was either dropped on the next read or returned
with a different value, and the resource never settled. Such a limit now
fails property validation instead. One shape of it was still enforced:
pam_limits reads a value only up to the end of its leading number, so a
value such as 10, 10 20 or 10#20 reached pam as 10 while the
resource reported a change on every run. A recipe carrying one now fails
until the value is corrected. Nothing valid is refused: limits.conf has
no line continuation, its first three fields are separated by
whitespace, and a # ends the line wherever it falls, so a field
carrying either character cannot describe a limit in the first place.
A limits file written with CRLF line endings also no longer loses
limits. Such a file parsed as only those of its limits that carried an
inline comment, and the rest were dropped the next time the file was
written.
A comment no longer keeps a limit converging forever. Chef coerces both
the comment a recipe asks for and the comment read back off disk on their
way into the same property, so whatever that coercion does it has to do
twice and give the same answer. It did not: trailing whitespace was kept
where the file dropped it, and a leading # was taken off, then taken
off again on the second pass.
The comment property now holds the comment's own text. The # that
opens every comment line in a limits file belongs to the file and is
written for you, so a comment carrying one of its own keeps it.
comment '#4127 see the ticket' is written as # #4127 see the ticket,
where before it was quietly written as # 4127 see the ticket. A recipe
that spelled the # out, as comment '# note', writes # # note now
and rewrites such a file once on the first run after upgrading.
- Reject a
domainorvaluethat cannot survive being written to a limits file and read back, in thelimitresource as a property validation failure and inLimits::Entryfor anything reaching the library another way. A limit with no value is untouched, since that is how a lookup and the delete action name a limit without saying what it should be - Keep a file path inside the header comment that opens a managed file. A newline in a filename is legal on Linux and pam_limits reads such a file like any other, but the header was built by hand, so the name could end the comment and leave a line behind that read back as a limit nobody declared
- Normalize a
commentto the form it is written in, stripping trailing whitespace from each of its lines. The property kept its own, but every line is written stripped, so the comment a limit was asked for and the comment read back off disk never compared equal and the limit converged on every run - Read a comment's
#as syntax only when reading a file. Taking one off is nowLimits::Helpers.unformat_comment, used byLimits::Fileand nowhere else, which leaves the coercion thecommentproperty applies as nothing but an rstrip, and applying an rstrip twice changes nothing. Before, the property took a#off whatever a recipe gave it andLimits::Entrytook another off on the way to the file, so## warningwas written as# warning, and#1 prioritywas written as# 1 priorityand never noticed, because a wrong comment still settles - Read a
#line with nothing after it, directly above a limit, as no comment at all. It was read as an empty comment, which thecommentproperty refuses, so anylimiton the line below it failed the converge, and it was written back as a blank line, so the file took a second rewrite to settle - Read a comment line indented in front of its
#as the comment after the#. The indentation kept the#from being recognized, so a hand-edited# notewas rewritten as# # note. It is now rewritten as# note, once, on the first run after upgrading - Coerce a value to an Integer only when the whole string is a number.
The match was anchored to line boundaries rather than to the ends of
the string, so a value carrying a newline could be read as a number on
one of its lines and coerced as a whole, turning
foo\n10into 0 - Keep the limits in a file written with CRLF line endings. A line ends
at a
\n, so a\rin front of one stopped the line matching, except where an inline comment consumed it. A CRLF file therefore parsed as some of its limits and not others, and the rest were dropped the next time the file was written. The endings are normalized on read and the file is rewritten with\n - Rewrite the file through Chef when purging, rather than writing it
directly once per removed limit. Each deletion rendered and replaced
the whole file, so an interrupted run left some unmanaged limits gone
and the rest still there,
backupwas ignored by the one action that deletes configuration somebody else wrote, and the run showed no content diff. A file managed by:purgealone now takes the resource's owner, group and mode, where before it kept whatever it already had. Those are applied on every run rather than only on one that finds something to remove, since the run that corrects them is otherwise the same run that leaves nothing to purge, and a file changed by hand afterwards would stay that way. The content is still rewritten only when there is something to remove, and a path with no file on it is still left alone rather than given an empty one. Purge now replaces the file in one step as well - Replace the file in one step when a limit changes, rather than
truncating it and writing it again. The file was rewritten with
File.write, which truncates the destination and only then renders what it was handed, so a failure while rendering left an empty file where the limits had been, and a client killed partway through left a prefix of one that pam reads without complaint. It is now written through Chef'sfileresource, run rather than declared against an event dispatcher nobody is subscribed to, so a file written once per limit does not report itself once per limit. One consequence of replacing the file rather than writing over it: POSIX ACLs set withsetfaclare not carried across, which is true of every other file Chef manages - Accept the
nonewprivsandrttimeitems, the two the limits.conf man page documents that this cookbook did not. Neither is available on every platform and the resource does not check: pam_limits logs an unknown item and skips the line, so writing one is honored by a newer module rather than failing the run - Document the valid types and items in the README with a description
for each, along with a Requirements section. They were reachable only
by opening
libraries/constants.rb, which a reader on Supermarket cannot do - Test against Rocky Linux 10 as well as Rocky Linux 9, which covers the EL10 client packages rather than only the EL9 ones
- Ship
CHANGELOG.mdin the published cookbook, so that Supermarket renders it as the Changelog tab on the cookbook page. Along with the README it is one of only two files Supermarket reads out of the tarball
v3.0.0
The minimum supported Chef Infra Client is now 18. Nodes running an
older client will fail the chef_version metadata constraint. Pin to
~> 2.4 to stay on a release that supports Chef Infra Client 12
through 17.
- Move development and testing from Chef Workstation to Cinc Workstation 26.2.4
- Test Kitchen selects Cinc via
product_name: cinc, which derives both the image (cincproject/cinc) and the client binary (/opt/cinc/bin/cinc-client) - Remove the Chef 19 Habitat image workaround and its hardcoded client path, as Cinc 19 ships as an omnibus package
- Drop the Chef Infra Client 17 test suite, as
cincproject/cinc:17is published for amd64 only - Raise the minimum supported Chef Infra Client to 18
- Test Kitchen suites track major versions instead of exact pins
- Replace CentOS Stream 10 with Rocky Linux 9 and Ubuntu 25.10 with Ubuntu 24.04 LTS for Test Kitchen
- Add Rocky Linux to the list of supported platforms
- Add GitHub Actions CI with separate lint, unit, and integration
stages. The integration matrix is derived from
kitchen list --json, so each suite and platform combination runs in parallel - Check on every pull request that a bumped version is not already tagged and that it is the newest entry in this changelog
- Tag the commit and publish a GitHub release automatically when a version bump merges to main, taking the release notes from the matching section of this changelog
- Drop release dates from this changelog, as the tag and the GitHub release already record when a version shipped
- Share the cookbook to Chef Supermarket after a release is tagged, behind a GitHub environment that requires a human to approve the deployment. Publishing after tagging is what lets Supermarket's version tag quality metric find the tag it looks for
- Run the test jobs weekly, so that upstream drift in the dokken base images is caught without waiting for someone to push
- Add a CI status badge to the README
- Remove the unused
default_source :supermarketfrom the Policyfile - Correct
chefignoreso that the workflow directory, an undottedkitchen.local.yml, andchefignoreitself are kept out of the published cookbook artifact - Ignore the undotted
kitchen.local.yml, matching the undottedkitchen.ymlalready in use - Cookstyle-recommended fixes
v2.4.1
- Repackage previous version without macOS-related issues. Root-cause
was using the BSD flavor of
tarwhich was including macOS extended attributes. Changing to the GNU flavor oftardoes not include these extended attributes.
v2.4.0
- Add support for Chef Infra Client 19
- Update Chef Workstation to 25.13.7
- Refactor platform and suites for Test Kitchen
- Update platform versions for Test Kitchen
- Update Chef Infra Client versions for Test Kitchen
v2.3.0
- Add support for Chef Infra Client 18
- Update Chef Workstation to 22.10.1013
- Update platform versions for Test Kitchen
- Update Chef Infra Client versions for Test Kitchen
- Move to policy files for Test Kitchen
- Cookstyle-recommended fixes
v2.2.0
- Add support for Chef 17
- Update Chef Workstation to 20.12.205
- Cookstyle-recommended fixes
- Test kitchen will test more platforms
- Test kitchen will perform two converges and ensure idempotency
- Add TESTING.md file
v2.1.1
- Chef 16.2.x had a backwards-incompatible change related to custom resources. This version supports the new style while maintaining backwards-compatibility.
- Update Chef Workstation to 20.6.62
v2.1.0
- Add support for Chef 16.x
- Update Chef Workstation to 0.18.3
v2.0.0
This cookbook has been completely refactored. It is not backwards
compatible. Please see the README.md for usage details. The code has
been uplifted to the latest best practices. The LWRP and definition was
removed in favor of the new custom resource syntax introduced in Chef
12.
- Add
limitcustom resource for managing individual limits - Add
limits_filecustom resource for managing a limits file - Remove attributes in favor of default values in custom resources
- Remove
set_limitdefinition andlimits_configLWRP - Replace ChefDK with Chef Workstation
- Replace RuboCop with Cookstyle
- Replace Serverspec with InSpec
- Replace Vagrant with Dokken
- Test support on Chef 12-15
v1.0.0
This cookbook has changed to be an LWRP-only usage. No longer will
limits be able to be specified using attributes. Please see the
README.md for usage details.
- Development and testing using ChefDK
- Add ChefSpec tests
- Add Serverspec tests
- Change license from Apache to MIT
v0.2.0
- Initial release of limits
Collaborator Number Metric
3.1.0 failed this metric
Failure: Cookbook has 0 collaborators. A cookbook must have at least 2 collaborators to pass this metric.
Cookstyle Metric
3.1.0 passed this metric
No Binaries Metric
3.1.0 passed this metric
Testing File Metric
3.1.0 passed this metric
Version Tag Metric
3.1.0 passed this metric
3.1.0 failed this metric
3.1.0 passed this metric
No Binaries Metric
3.1.0 passed this metric
Testing File Metric
3.1.0 passed this metric
Version Tag Metric
3.1.0 passed this metric
3.1.0 passed this metric
3.1.0 passed this metric
Version Tag Metric
3.1.0 passed this metric
3.1.0 passed this metric