- AlmaLinux 8, 9 (Request Tracker 4.4)
- AlmaLinux 10 (Request Tracker 5)
The RT major version follows the platform: EL8/9 install RT 4.4, EL10 installs
RT 5. The cookbook adjusts automatically — notably, extensions that RT 5 merged
into core (RT::Extension::REST2, RT::Authen::Token) are skipped from the
plugins list on EL10 (loading them as plugins makes RT 5 fail to start).
By default this cookbook serves RT over plain HTTP only. TLS is expected to be
terminated by an upstream HAProxy (or similar) reverse proxy that forwards to
this backend over HTTP. Apache is configured with osl-apache::mod_remoteip
so the real client IP is recovered from the X-Forwarded-For header.
To terminate TLS on the RT host instead, set ssl-certificate to the id of an
item in the certificates data bag. The cookbook then installs it with
certificate_manage, listens on 443 and redirects port 80 to HTTPS. Requests
for internal-domain are not redirected, because rt-mailgate and the rt CLI
post to http://<internal-domain>.
osl-apache reads its listen attribute while recipes compile. So the resource
sets listen, and the workers-per-cpu limits, when it is declared, not when
it converges. It includes osl-apache, osl-apache::mod_remoteip and
osl-apache::mod_perl at the same point, so Apache is installed before the
resource's action runs. Declare it before any recipe in the run list that
includes osl-apache. If osl-apache has already been loaded without the ports this site
needs, the resource raises an error at compile time. A wrapper that can't change
the order can set node['osl-apache']['listen'] itself first.
The list of trusted proxies defaults to OSUOSL's load balancers. For other deployments, override it on the node:
node.default['osl-apache']['mod_remoteip']['trusted_proxy'] = %w(10.0.0.1)RT's SELinux policy ships in the OSL request-tracker-selinux RPM, which this
cookbook installs alongside request-tracker:
- the
request_trackermodule /opt/rt/varlabelledhttpd_sys_rw_content_t- the
httpd_can_sendmailandhttpd_can_network_connect_dbbooleans
The cookbook sets no policy of its own. The kitchen suites converge with
osl-selinux enforcing and fail on any httpd_t or procmail_t denial.
osl-rt is resource-first: declare the osl_request_tracker
resource. The resource name is the site's fqdn; the rest of the configuration
lives in the request-tracker data bag (selected with data_bag). Do NOT
put configuration in node attributes.
# Deploy RT for requests.openpowerfoundation.org, reading the rest of the
# config from request-tracker/requests.
osl_request_tracker 'requests.openpowerfoundation.org' do
data_bag 'requests'
end| Name | Type | Description | Default |
|---|---|---|---|
db-username |
String | The username of the DB user | nil |
db-password |
String | The password of the DB user | nil |
root-password |
String | The password used for the root account on RT | nil |
fqdn |
String | Set by the osl_request_tracker resource name, not the data bag (any fqdn key here is ignored). The site's web/host domain. |
resource name |
mail-domain |
String | The public email domain for queue addresses, when it differs from the host fqdn (e.g. example.org while the site is support.example.org). Queue mail at either domain is delivered to RT; other addresses at mail-domain aren't local and go out through the relay. |
fqdn |
web-port |
Integer | Sets RT's $WebPort. Needed when TLS terminates upstream (e.g. HAProxy) and RT serves plain HTTP: set 443 so RT treats itself as HTTPS, otherwise it assumes http://<fqdn>:80 and rejects HTTPS form posts with a "possible cross-site request forgery" error. |
RT default (80) |
web-base-url |
String | Sets RT's $WebBaseURL explicitly. Only needed when the public URL isn't derivable from fqdn + web-port (a different public host, a WebPath prefix, etc.); otherwise RT derives it. |
derived |
user |
String | The user account that is responsible for being the default email | support |
failed-email |
String | Address that mail RT fails to process is forwarded to | root |
logo |
Hash | Optional custom branding. url is fetched into RT's static images dir and $LogoURL is set to the served path; link/alt set $LogoLinkURL/$LogoAltText. Assumes the default (empty) WebPath; override $LogoURL via extra-config otherwise. |
nil |
internal-domain |
String | A workaround required needs a non-sublevel domain name to access the site internally | rtlocal |
db.type |
String | The database engine, passed to RT as $DatabaseType. Use mysql for MySQL/MariaDB or Pg for PostgreSQL. With Pg the cookbook installs the perl-DBD-Pg driver and the psql client (used by the one-time DB guards) instead of the MariaDB client. |
mysql |
db.host |
String | The hostname of the DB server | localhost |
db.name |
String | The DB name on the DB server | rt |
db-upgrade |
String | Opt-in: the RT version the database is currently at (e.g. "4.4.7"), passed as --upgrade-from to apply pending schema upgrades (after importing a DB or an RT package upgrade). The "proceed?" prompt is auto-confirmed, so back up first. See docs/migration.md. |
unset |
queues |
Hash | The queues and emails available for RT. The key is the pretty print, and the value is a email-valid name. | {'Support Example': nil} Any nil-valued key will be ignored. |
spam-exempt |
Array | Queue emails whose mail is never diverted to .Spam/ by procmail's X-Spam-Status rule. Abuse-type queues need this: their reports quote the very spam they report, so they tag as spam by nature but must still be ticketed. |
the queues emails intersected with abuse/postmaster |
plugins |
Array | A list of plugins to add to the RT site. On EL10/RT 5, extensions merged into core (RT::Extension::REST2, RT::Authen::Token) are automatically skipped. |
[] |
lifecycles |
Hash | Any custom lifecycles to make available in RT. Arbitrary lifecycles (including an approvals lifecycle) are emitted verbatim, so add them here rather than in code. |
{} Provides default lifecycle. |
extra-config |
Hash | Raw RT config options emitted verbatim into RT_SiteConfig.pm. Keys must be valid RT names (e.g. $Timezone, $DefaultQueue, $ParseNewMessageForTicketCcs). String values are quoted; numbers/literals are emitted as-is; keys beginning with % are treated as Perl literals (e.g. %FullTextSearch). Do not set _Plugins/_Lifecycles here — use plugins/lifecycles. The cookbook also sets %ReferrerComponents so a link to /Search/Bulk.html that carries only a search (Query and Rows) opens without RT's "possible cross-site request forgery" warning, even from a page that sends no Referer; a link that also carries an update or display options (Format, OrderBy) is still checked. A %ReferrerComponents here replaces it. |
{} |
ssl-certificate |
String | Opt-in: serve TLS on the RT host with this item from the certificates data bag (installed as <id>.pem, <id>.key and <id>-bundle.crt under /etc/pki/tls). Apache listens on 443 and port 80 redirects to HTTPS, except for internal-domain. Set web-port to 443 as well. |
unset (HTTP only) |
workers-per-cpu |
Integer | Opt-in: cap Apache prefork workers at this many per CPU core. It is never fewer than 5 and never more than osl-apache's memory-based limit. Every worker is a full RT interpreter, so on a CPU-bound host more workers only add contention. 3 is a good start. |
unset (osl-apache sizes by memory) |
clean-sessions |
String | Age for a daily rt-clean-sessions --older <age> --skip-user cron (/etc/cron.d/rt-clean-sessions, 03:15, as apache), in RT's <NUM>[H|D|M|Y] format. RT never expires sessions itself. --skip-user keeps users logged in on more than one browser. Set false to remove the cron. |
30D |
fulltext-index |
Boolean | Opt-in: sets %FullTextSearch to Indexed => 1 with RT's default index table (AttachmentsIndex, plus the ContentIndex column on Pg), and adds a rt-fulltext-indexer --quiet cron every 10 minutes. The index must exist first: run /opt/rt/sbin/rt-setup-fulltext-index --dba <db-username> once, off-peak and inside tmux or screen, before turning this on. --dba is needed because the script otherwise connects as RT's default admin user (root, or postgres on Pg); it prompts for that user's password, so keep the password off the command line. On MySQL, answer mysql for the index type and keep the default table name, which this key expects. Ignore the %FullTextSearch block it prints at the end, since this key sets it. It tokenizes every attachment and drops any existing index table, so never rerun it on a live index. On MySQL, RT 4.4 can't index attachments containing 4-byte UTF-8 characters such as emoji, because it connects as utf8mb3; the indexer warns and skips them, so content search can't find them. RT 5 uses utf8mb4. RT checks for the table only when it starts: if httpd started while the table was missing, full-text search stays off until httpd restarts. Restart httpd after the converge that turns this on. A %FullTextSearch in extra-config overrides this setting. |
false |
spam-digest |
Array | Addresses that get a daily, headers-only digest of the mail procmail filed into .Spam and .AutoReply under the user's ~/Mail in the last 24 hours, newest first, at most 200 per folder. The digest lists the date, file name, From, X-Original-To, Subject and the spam score (or why the message was filed), and never reads a message body. /usr/local/sbin/rt-spam-digest sends it as postmaster@<node fqdn> from the rt-spam-digest service, run as user. The rt-spam-digest.timer fires at 06:00 Pacific, within 5 minutes, and the times in the digest are Pacific. Runs are kept 24 hours apart, so no message is missed; on the two DST change days the gap is 23 or 25 hours, so the 23-hour day can list an hour of mail twice and the 25-hour day can miss an hour. The digest is mailed even when there is nothing to report, so a day with no digest means it is broken. The Lab's daily triage (spamwatch.py) parses the body. Run rt-spam-digest --stdout --fqdn <name> as user to print it instead. Set false to remove the timer, service and script. |
["ramereth@osuosl.org"] |
{
"db": {
"type": "mysql",
"host": "localhost",
"name": "rt"
},
"mail-domain": "example.org",
"user": "support",
"failed-email": "systems@example.org",
"logo": {
"url": "https://example.org/img/logo.png",
"link": "https://support.example.org/",
"alt": "Example Support"
},
"queues": {
"Support": "support",
"Frontend Team": "frontend",
"Backend Team": "backend",
"DevOps Team": "devops",
"Marketing Team": "advertising",
"The Board Of Directors": "board"
},
"plugins": ["RT::Extension::REST2", "RT::Authen::Token"],
"extra-config": {
"$Timezone": "US/Pacific",
"$DefaultQueue": "Support",
"$ParseNewMessageForTicketCcs": 1,
"%FullTextSearch": "Enable => 1, Indexed => 1"
},
"lifecycles": {
"new-wave": {
"initial": ["order in"],
"active": ["order work", "order delayed"],
"inactive": ["order up"]
"transitions": {
"": ["order in"],
"order in": ["order work"],
"order work": ["order delayed", "order up"],
"order delayed": ["order work"]
},
"rights": {
"* => order in": "ResetOrder"
}
}
}
}The recipe is safe to converge against an already-populated database: schema
init, the root password, and existing queues are all guarded by the actual
database state, so an imported instance is never re-initialized or clobbered. The
opt-in db-upgrade key applies pending schema upgrades after an import or package
upgrade. See docs/migration.md for the full details, the
migration Test Kitchen suite, and how to generate the seed dump.
Deploys an RT web service on the node (Apache + RT, the database schema, procmail,
and a osl_postfix_server 'default' mail server). The resource name is the site's
fqdn; the rest of the config comes from a request-tracker data bag item (see
Data Bag Attributes).
| Property | Type | Description | Default |
|---|---|---|---|
fqdn |
String | The site's fqdn (the resource name). Authoritative — overrides any fqdn in the data bag. |
resource name |
data_bag |
String | Name of the item in the request-tracker data bag holding the rest of the config. |
default |
osl_request_tracker 'requests.openpowerfoundation.org' do
data_bag 'requests'
endTo converge against request-tracker RPMs built in rpms/request-tracker
before they're published, run make repo there, then set OSL_RT_LOCAL_REPO
for kitchen with the openstack driver:
OSL_RT_LOCAL_REPO=1 kitchen test two-domain-almalinux-9A pre_converge hook in kitchen.openstack.yml rsyncs
REPO/<release> (from ~/git/osl/rpms/request-tracker, or OSL_RT_REPO) to
the instance. It then installs its request-tracker-local.repo, whose
priority=1 wins over the published repo. Without a build it prints a note and
the published RPMs are used. Start from fresh instances, because the resource
installs RT but never upgrades it.
- Fork the repository on Github
- Create a named feature branch (like
username/add_component_x) - Write tests for your change
- Write your change
- Run the tests, ensuring they all pass
- Submit a Pull Request using Github
- Author:: Oregon State University chef@osuosl.org
Copyright:: 2023, Oregon State University
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.