-
Notifications
You must be signed in to change notification settings - Fork 15
About Configuration Data
The index of this documentation is at Iains Documentation Skunkworks.
NGC takes configuration data from two possible sources:
- Text files in the local filesystem. They are in the INI file format.
- XML streams from the net.
Configuration data is a collection of sections. Within each section is a list of properties. A property has a name and a value.
Sections are used to group logically related properties together, so the main configuration has sections like "Startup" and "Network" and so on.
Properties are key-value pairs. A property name is often just the name of a property, especially when the relevant section is assumed, or otherwise known.
Note: If two properties in two different sections have the same name, they are not the same property! The "port" property in section "A" is a different property from the "port" property in section "B".
The order of sections is irrelevant.
The order of properties in sections is largely irrelevant. For the most part, the server code simply refers to sections and proerties within them by name. But (and this is a big but) the order of properties in some sections is important. An example is the [ServiceList]
section in the main server configuration. The service plugins are loaded in the order the properties appear in the section. Some services assume that other services have already been loaded, and will fail to load if these prerequisites have not been loaded and started.
Any property that begins with Include-
is an include directive. Because all properties in a section must have unique names, you need to tack something on to the name if you're having more than one include in a section.
The property value is the configuration source. It is either a pathname or an URL. Relative pathnames are relative to the pwd. See pwd explanation. URLs must have either http:
or https:
as the scheme.
Local files are expected to be in the INI format. URLs are expected to point to network resources that serve up XML.
The pathname can include wildcards, so one include directive can refer to multiple INI files.
Data can be included from both INI files and XML streams. XML sources can be included from INI files, and vice versa. For example, a central config can be provided by a server on the network, and that data can include INI files, allowing each client machine to have its own config file(s).
The configuration sources are loaded one by one. The first source loaded is the main server configuration (which could be Robust.ini
or OpenSim.ini
or something specified by a command line switch).
After each source is loaded:
- Its data is merged into the server's internal configuration. Any preexisting properties are replaced by the ones from the new source.
- The whole configuration is scanned for include directives. For each directive found, the source (or sources) it refers to is (are) added to a list of sources-to-be-loaded if it is (they are) not already in the list.
- The next source in that list is loaded, and around we go.
Once all sources in that list have been loaded, inclusion is done.
Basically this is like adding the files to a FIFO queue as they are encountered in the configuraion. Each file is added only once, so there can be no circular dependencies. If file A depends on B which depends on A, when B is read, A has already been loaded, so it is not loaded again.
NOTE: The contents of the included file are not inserted at the point of the include directive! This means that if you have properties after the insertion point that conflict with the included file, they may or may not override the included file. The included file may override those properties if it is included later.
This can be very surprising to people used to various systems that do file inclusions, like the C preprocessor, M4, etc, etc.
The library used by NGC (called Nini) supports macros. Macros are ways to substitute text, provided by a property elsewhere in the configuration. A macro invocation is a property name, inside curly braces, preceded by a dollar sign. This property name could either be a naked name, in which case it refers to a property in this section, or it could be a section name and a property name separated by a pipe character, in which case it refers to a property in the named section.
Warning: As of this writing (June 5, 2025) if you have a macro that refers to a property in this section (no section name plus pipe), for example
${PrivatePort}
, in a section that does not define that property, the server will crash (tinkle).
This macro facility is the reason for the [Const]
section in the main ini files (Robust.ini and OpenSim.ini). This section is never referenced in the code, but it is used in macros throughout the rest of the configuration for things that are used repeatedly like, say, the private TCP/UDP port you have chosen for your server/grid on the main base URL.
For example:
[Const]
BaseHostname = "127.0.0.1"
[SomeOtherSection]
; This macro invocation refers to the BaseHostname property in the Const section:
BaseURL = "http://${Const|BaseHostname}"
In this example, the macro refers to the property earlier, and that property's value is substituted for the macro invocation. So the value of BaseURL
becomes "http://127.0.0.1"
.
- First, the main configuration source is loaded.
- Includes are processed one at a time and the contents merged into the internal configuration data.
- Macros are then expanded.
- Finally command line switches are merged into the configuration, overriding anything in the loaded sources.
Note: Because macros are processed after includes, they cannot be used in include directives.
Files in the local filesystem are expected to be in the INI file format. This venerable configuration file format dates back into the mists of time, discovered in the depths of Colossal Cave in a room near the battery vending machine, shortly after Don Woods caused the removal of the lunch room.
URLs point to network resources that are expected to provide an XML stream. This is an ad-hoc schema that is essentially an XML-ification of the INI file format.
Sections are started by the section name between square brackets on a line by itself. The start of another section (or the end of the file) ends the current section.
Properties are the property name and the property value, separated by an equals sign.
Comments are lines that start with a semicolon.
Example:
; This is a comment
; The following is a section header
[Startup]
; The following is a property
console = "rest"
This data is an ad-hoc XML schema. There is no XML declaration. So there is no <?xml version="1.0" ?>
line at the top of the file.
The root element is <Nini>
.
Sections are in <Section>
elements. The value of the Name
attribute is the section name. All sections are direct children of the <Nini>
element. There is no nesting of sections.
Properties are in <Key>
elements. The value of the Name
is the property name. The value of the Value
attribute is the property value. All <Key>
elements are children of a <Section>
element. There are no free-floating properties, all have to belong to a section.
Comments are standard XML comments.
Example (equivalent to the INI example above):
<!-- comment -->
<Nini>
<Section Name="Startup">
<Key Name="console" Value="rest" />
</Section>
</Nini>