FAQ
- Enterprise Installation
- Enterprise Scalability
- Policy Distribution
- Manual Execution
- Agent Email Reports
- Policy Writing
Enterprise Installation and Configuration
What steps should I take after installing CFEngine Enterprise
There are general steps to be taken outlined in Post-Installation Configuration.
In addition to this, Enterprise 3.6 uses the local mail relay, and it is assumed that the server where CFEngine Enterprise is installed on has proper mail setup.
The default FROM email for all emails sent from the Mission Portal is currently admin@organization.com. This can be changed on the CFEngine Hub in /var/cfengine/httpd/htdocs/application/config/appsettings.php:$config['appemail']
.
Can I use an existing PostgreSQL installation
No. Although CFEngine keeps its assumptions about Postgres to a bare minimum, CFEngine should use a dedicated PostgreSQL database instance to ensure there is no conflict with an existing installation.
Do I need experience with PostgreSQL
PostgreSQL is highly configurable and you should have some in-house expertise to properly configure your database installation. The defaults are well tuned for common cases but you may find optimizations depending on your hardware and OS.
What is the system user for the CFEngine dedicated PostgreSQL database and Apache server
Starting with CFEngine 3.6 there will be a system user called cfpostgres
for running the dedicated CFEngine PostgreSQL database
installation.
Similarly there will be a cfapache
system user for the Apache web server.
What are the requirements for installing CFEngine Enterprise
General Information
Users and Permissions
- CFEngine Enterprise makes an attempt to create the local users
cfapache
andcfpostgres
, as well as groupcfapache
when installing 3.6. The server must allow creation of these users and groups.
Enterprise Scalability
Is it normal to have many cf-hub processes running
- Yes, it is expected to have ~ 50 cf-hub processes running on your hub
Policy Distribution
I have added new files in masterfiles but my remote clients are not getting updates
Check that the files you expect to be distributed have matching leaf_name
pattern. If newly bootstrapped clients get those files but existing clients don't, this is certainly the problem, because bootstrapping and failsafe operation ignore leaf_name
and copy everything.
In CFEngine 3.6 masterfiles policy framework this is configurable with
input_name_patterns
in the update_def
bundle in def.cf
. See The Policy Framework for more information.
I have updated some non policy files and changes are not distributed to clients
cf_promises_validated
gates client updates. This file is only updated on the
policy server when new policy is validated. Edits to non policy files do not
trigger an update of cf_promises_validated
. You can use a separate promise to
ensure those files are continually distributed, instead of only on policy
updates.
For details see cf_promises_validated and cfe_internal_update_policy
My policy server has changed its IP address and new bootstraps don't work!
(thanks to Dan Langille in https://groups.google.com/forum/#!topic/help-cfengine/jcdIh12_lNI)
Symptom:
After the policy server was restarted with the new IP address, clients would not connect:
error: Not authorized to trust public key of server '192.168.14.113' (trustkey = false)
error: Authentication dialogue with '192.168.14.113' failed
Bootstrapping the clients also fails:
[root@dev /var/cfengine] /var/cfengine/bin/cf-agent --bootstrap 192.168.14.113
2014-06-23T13:57:07-0400 notice: R: This autonomous node assumes the role of voluntary client
2014-06-23T13:57:07-0400 notice: R: Failed to copy policy from policy server at 192.168.14.113:/var/cfengine/masterfiles
Please check
* cf-serverd is running on 192.168.14.113
* network connectivity to 192.168.14.113 on port 5308
* masterfiles 'body server control' - in particular allowconnects, trustkeysfrom and skipverify
* masterfiles 'bundle server' -> access: -> masterfiles -> admit/deny
It is often useful to restart cf-serverd in verbose mode (cf-serverd -v) on 192.168.14.113 to diagnose connection issues.
When updating masterfiles, wait (usually 5 minutes) for files to propagate to inputs on 192.168.14.113 before retrying.
2014-06-23T13:57:07-0400 notice: R: Did not start the scheduler
2014-06-23T13:57:07-0400 error: Bootstrapping failed, no input file at '/var/cfengine/inputs/promises.cf' after bootstrap
Solution:
Assuming that 661df12c960af9afdde093e0cb339b4d
is the MD5 hostkey and 192.168.14.113
is the new IP address:
cd /var/cfengine/ppkeys && mv -i root-MD5=661df12c960af9afdde093e0cb339b4d.pub root-192.168.14.113.pub
Manual Execution
How do I run a standalone policy file
The --file
or -f
option to cf-agent
specifys the policy file. The -K
or --no-lock
flag and the -I
or --inform
options are commonly used in combination with the -f
option to ensure that
all promises are skipped because of locking and for the agent to produce
informational output like successful repairs.
cf-agent -KIf ./my_standalone_policy.cf
In 3.6.1 and later, a standalone policy file may choose not to
specify a bundlesequence
. In that case, the bundlesequence
defaults to main
so you'll need a bundle called main
.
You can avoid that requirement by using the -b BUNDLENAME
flag which
specifies an explicit bundlesequence
, see below.
Why do I get Undefined body when I try to run my policy
cf-promises -f ./large-files.cf
:
./large-files.cf:14:0: error: Undefined body tidy with type delete
./large-files.cf:16:0: error: Undefined body recurse with type depth_search
The above errors indicate that the tidy
and recurse
bodies are not able
to be found by CFEngine. This is because they are not found in the file or in
one of the files it includes. Either define the body within the same policy
file or include the file that defines the body using inputs in either body
common control or body file
control.
Example: Add stdlib via body common control
body common control
{
bundlesequence => { "file_remover" };
inputs => { "$(sys.libdir)/stdlib.cf" };
}
Example: Add stdlib via body file control Body file control allows you to build modular policy. Body file control inputs are typically relative to the policy file itself.
bundle file_remover_control
{
vars:
"inputs" slist => { "$(this.promise_dir)/$(sys.local_libdir)/stdlib.cf" };
}
body file control
{
inputs => { @(file_remover_control.inputs) };
}
This policy will work correctly whether it's included by another
policy file or not. Note the body file
control
option is new since
CFEngine 3.6, so you should not use if your policy could be seen by
3.5 or earlier CFEngine clients.
How do I run a specific bundle
A specific bundle can be activated by passing the -b
or --bundlesequence
options to cf-agent
. This may be used to activate a specific bundle within a
large policy set or to run a standalone policy that does not include a body
common control
.
cf-agent -b my_bundle
If you want to activate multiple bundles in a sequence simply separate them with commas (no spaces between).
cf-agent --bundlesequence bundle1,bundle2
How do I define a class for a single run
You can use the --define
or -D
options of cf-agent
.
cf-agent -D my_class
And if you want to define multiple, simply separate them with commas (no spaces between).
cf-agent --define my_class,my_other_class
Multiple -D
flags are not supported, you have to put all the classes in one comma-separated list.
Showing Classes and variables with cf-promsies
cf-promises --show-classes
and cf-promises --show-vars
will only show
classes and variables found on a first pass through the policy, since
cf-promises
does not evaluate agent promises.
Agent Email Reports
How do I set the email where agent reports are sent
The agent report email functionality is configured in body executor control
https://github.com/cfengine/masterfiles/blob/master/controls/cf_execd.cf. It
defaults to root@$(def.domain)
which is configured in bundle common def
https://github.com/cfengine/masterfiles/blob/master/def.cf.
For details see domain.
How do I disable agent email output
You can simply remove or comment out the settings.
In 3.6.x there is a convenience class cfengine_internal_agent_email
avaiable
in bundle common def
to switch on/off agent email.
For details see cfengine_internal_agent_email.
Mustache Templating
How can I pass a data variable to template_data?
Currently you cannot pass a data variable directly to
template_data
, instead you must use one of the data-producing functions for
example mergedata
(), readjson
(), or parsejson
(). Please see the
Functions by Return Type table for a list
of all data-producing functions.
Note you can use mergedata
() directly on a single data container,
e.g. template_data => mergedata(mycontainer)
to satisfy the syntactic quirk above.
Can I render a Mustache template into a string?
Not directly, you could render a file and read that into a string, but you would need to be cautious of CF_BUFSIZE.
How do I render a section only if a given class is defined?
In this Mustache example the word 'Enterprise' will only be rendered if the class 'enterprise' is defined.
This template should not be passed a data container; it uses the datastate()
of the CFEngine system. That's where classes.enterprise
and vars.sys.cf_version
came from.
Version: CFEngine Enterprise
How do I iterate over a list?
This template should not be passed a data container; it uses the datastate()
of the CFEngine system. That's where vars.mon.listening_tcp4_ports
came from.
{{#vars.mon.listening_tcp4_ports}}
* {{.}}
{{/vars.mon.listening_tcp4_ports}}
How do I ensure that a local user is locked?
To ensure that a local user exists but is locked (for example a service
account) simply specify policy => "locked"
.
bundle agent service_accounts
{
vars:
"users" slist => { "apache", "libuuid" };
users:
!windows::
"$(users)"
policy => "locked";
}
Policy Writing
Common questions asked about policy writing.
How do I pass a data type variable
Data type variables also known as "data containers" are passed using the same syntax as passing a list.
bundle agent example
{
vars:
# First you must have a data type variable, define it inline or read from a
# file using `readjson()`.
"data" data => parsejson('[ { "x": 1 }, { "y": 2 } ]');
methods:
"use data"
usebundle => use_data(@(data));
}
bundle agent use_data(dc)
{
vars:
# Use the data
# Get its keys, or its index
"dc_index" slist => getindices(dc);
classes:
"have_x" expression => isvariable("dc[$(dc_index)][x]");
"have_z" expression => isvariable("dc[$(dc_index)][z]");
reports:
"CFEngine version '$(sys.cf_version)'";
have_x::
"Index '$(dc_index)' has key for x";
have_z::
"Index '$(dc_index)' has key for z";
}
$ cf-agent -Kf ./example.cf -b example
R: CFEngine version '3.6.4'
R: Index '0' has key for x
R: Index '1' has key for x