alt text

I saw a mention of iTop on Mastodon, and not having heard of it before, I thought I would give installing it a go and see how it compares to the various ticketing solutions I have used at work. As I had an under used Odroid C2 which is just running a base install of Arch Linux, that was the target I chose for the install. As usual I wanted to do as much of the install and configuration via Salt as possible. This post documents the experience, and what I came up with.

LAMP Stack

Like many web applications, iTop runs on top of the Lamp stack. Despite the ubiquity of this base requirement and many a Salt tutorial focused on installing LAMP, I have not as yet come up with Salt state files of my own to do this. I also have never installed LAMP on Arch before, so I am really starting from scratch.

Apache

I decided to start out simply following the guidance on installing Apache provided on the Arch Linux Wiki. I figured additional adjustments required to support iTop would make themselves clear as I progressed or failed to progress.

To install Apache and associated dependencies, su -c 'pacman -S apache' seemed to suffice. Once insalled, su -c 'systemctl enable --now httpd' was all it took to get the web running and set to run on restarts of the device.

Easy to do manually, but now I need to replicate those Salt state file because automation and future use. This is what I came up with to install software Apache if it is missing and make sure service is running now and in the future.

File system layout for Apache state

app_apache
└── init.sls

init.sls file for Apache

# Installs Apache Web Server 
# Created: 2021-12-27
# Modified 

# Make sure apache is installed
apache_inst:
  pkg.installed:
    - name: 
    - refresh: False

# Make sure service is enabled and started.
apache_service:
  service.running:
    - name: httpd.service
    - enable: True

Apache Arch Notes:

  • Main apache config file is /etc/httpd/conf/httpd.conf
  • ServerAdmin should be updated from ServerAdmin you@example.com
  • Document root for webserver is DocumentRoot "/srv/http"
  • Server signature should be turned off, ServerSignature Off
  • Server tokens should be surpressed, ServerTokens Prod
  • Check Apache configuration file, apachectl configtest
  • Apache runs as httpd.service on Arch, as user and group http.

Apache Fast CGI Interface Module

After some research I decided to use the Fast CGI module (mod_fcgid) in order to increase CGI performance. Additional Apache and PHP configuration is needed to take advanage of this module, as follows.

  • Install the module.
    • su -c 'pacman -S mod_fcgid' is sufficent to install the module.
  • Create a fcgid-bin directory in the document root of the web server to house wrappers needed for applications to use module.
    • su -c 'mkdir /srv/http/fcgid-bin' is the command I used.
  • Modify Apache configuration file/etc/httpd/conf/httpd.conf:
    • Remove leading # to uncomment the loading of the actions module, should look like this: LoadModule actions_module modules/mod_actions.so
    • The FCGID module needs to be loaded after the unixd module on which it dependends. I placed this within the existing <IfModule unixd_module> block, where I tucked the needed LoadModule fcgid_module modules/mod_fcgid.so entry in right above the closing </IfModule>.
      The block wound up looking like this:
<IfModule unixd_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User http
Group http
LoadModule fcgid_module modules/mod_fcgid.so
</IfModule>
  • Ensure that the inclusion of the MPM module configuration is uncommented (no leading #), and looks like this:
    Include conf/extra/httpd-mpm.conf

  • Restart Apache to enable changes made in /etc/httpd/conf/httpd.conf.

    • su -c 'systemctl restart httpd.service

This is the Salt solution I came up with to do the same.

File system layout for app_apache_mod_fcgid

app_apache_mod_fcgid/
└── init.sls

init.sls file for mod_fcgid

# Installs Apache fast CGI mod  
# Created: 2021-12-27
# Modified 

# Make sure apache fast CGI mod is installed
#
include:
  - app_apache

mod_fcgid_inst:
  pkg.installed:
    - name: 
    - refresh: False

# Make directory
/srv/http/fcgid-bin:
  file.directory:
    - user: http
    - group: http
    - dir_mod: 755

# Modify /etc/httpd/conf/httpd.conf
# Loading of the actions module
actions_enable:
  file.replace:
    - name: /etc/httpd/conf/httpd.conf
    - pattern: #LoadModule actions_module modules/mod_actions.so
    - repl: LoadModule actions_module modules/mod_actions.so
    - count: 1
    - backup: .bak_actions
    - bufsize: file

# Load FCGID module
fcgid_module:
  # load as part of IfModule unixd block
  file.blockreplace:
    - name: /etc/httpd/conf/httpd.conf
    - marker_start: "<IfModule unixd_module>"
    - marker_end: "</IfModule>"
    - content: |
        #
        # If you wish httpd to run as a different user or group, you must run
        # httpd as root initially and it will switch.
        #
        # User/Group: The name (or #number) of the user/group to run httpd as.
        # It is usually good practice to create a dedicated user and group for
        # running httpd, as with most system services.
        #
        User http
        Group http
        LoadModule fcgid_module modules/mod_fcgid.so
    - show_changes: True

# Enable MPM configuration
mpm_enable:
  file.replace:
    - name: /etc/httpd/conf/httpd.conf
    - pattern: #Include conf/extra/httpd-mpm.conf
    - repl: Include conf/extra/httpd-mpm.conf
    - count: 1
    - backup: .bak_mpm
    - bufsize: file

# Restart Apache

# Make sure service is enabled and restarted if changes.
fcgid_apache_service:
  service.running:
    - name: httpd.service
    - enable: True
    - watch:
      - file: '/etc/httpd/conf/httpd.conf'

PHP

By virtue of being a rolling release, Arch defaults to installing the current version of PHP in the 8.x familly. Since iTop does not support PHP 8.x yet, I need to make sure PHP 7.x is installed. There are multiple ways to optimize PHP for use with Apache. Above, I opted to make use of apache2-mpm-worker and mod_fcgid, so I need to also install and configure PHP to make use of thos modules.

pacman -S php7 is enough to get PHP v7 installed manually. The following is an equivalent Salt state that does the same.

File system layout for app_php7

app_php7/
└── init.sls

init.sls file for app_php7

# Installs PHP 7 
# Created: 2021-12-27
# Modified 

# Make sure php7 is installed
php7_inst:
  pkg.installed:
    - name: 
    - refresh: False

PHP CGI Optimization

In a similar manner su -c 'pacman -S mod_fcgid php7-cgi' takes care of installation of the php-cgi optimization wrapper. A bit of configuration required to get the PHP optimization wrapper set up and working. Again most of the guidance was found here on the Arch Linux Wiki

  • Create symlink for the PHP wrapper:
su -c 'ln -s /usr/bin/php-cgi /srv/http/fcgid-bin/php-fcgid-wrapper'
  • Create /etc/httpd/conf/extra/php-fcgid.conf with the following content:
# Required modules: fcgid_module

<IfModule fcgid_module>
    AddHandler php-fcgid .php
    AddType application/x-httpd-php .php
    Action php-fcgid /fcgid-bin/php-fcgid-wrapper
    ScriptAlias /fcgid-bin/ /srv/http/fcgid-bin/
    SocketPath /var/run/httpd/fcgidsock
    SharememPath /var/run/httpd/fcgid_shm
        # If you don't allow bigger requests many applications may fail (such as WordPress login)
        FcgidMaxRequestLen 536870912
        # Path to php.ini – defaults to /etc/phpX/cgi
        DefaultInitEnv PHPRC=/etc/php7/
        # Number of PHP childs that will be launched. Leave undefined to let PHP decide.
        #DefaultInitEnv PHP_FCGI_CHILDREN 3
        # Maximum requests before a process is stopped and a new one is launched
        #DefaultInitEnv PHP_FCGI_MAX_REQUESTS 5000
    <Location /fcgid-bin/>
        SetHandler fcgid-script
        Options +ExecCGI
    </Location>
</IfModule>
  • Append inclusion of FCGID configuration for PHP by appending the following line to the end of the file: Include conf/extra/php-fcgid.conf
    • Restart httpd.service.
      su -c systemctl restart httpd

Here is the Salt solution to do all of the above I came up with:

File system structure for php7-cgi

/srv/salt/app_php7_php7-cgi/
├── files
│   └── php-fcgid.conf
└── init.sls

init.sls for php7-cgi

# Installs php-cgi  
# Created: 2021-12-27
# Modified 
# Notes: Based off of guidance here: 
  # https://wiki.archlinux.org/title/Apache_HTTP_Server

# Make sure apache php-cgi wrapper is installed
#
include:
  - app_apache_mod_fcgid
  - app_php7

php-cgi_inst:
  pkg.installed:
    - name: 
    - refresh: False

# Create symbolic link
/srv/http/fcgid-bin/php-fcgid-wrapper:
  file.symlink:
    - target: /usr/bin/php-cgi7

# Copy php-fcgid.conf file
/etc/httpd/conf/extra/php-fcgid.conf:
  file.managed:
    - source:
      - salt://app_php7_php7-cgi/files/php-fcgid.conf

# Include php-cgi configuration
fcgid_conf:
  file.replace:
    - name: /etc/httpd/conf/httpd.conf
    - pattern: #Include conf/extra/php-fcgid.conf
    - repl: Include conf/extra/php-fcgid.conf
    - count: 1
    - append_if_not_found: True
    - show_changes: True
    - backup: bak3
    - bufsize: file

# Restart Apache

# Make sure service is enabled and restarted if changes.
restart_apache_service:
  service.running:
    - name: httpd.service
    - enable: True
    - watch:
      - file: '/etc/httpd/conf/httpd.conf'
      - file: '/etc/httpd/conf/extra/php-fcgid.conf'

php-fcgid.conf

# Required modules: fcgid_module

<IfModule fcgid_module>
    AddHandler php-fcgid .php
    AddType application/x-httpd-php .php
    Action php-fcgid /fcgid-bin/php-fcgid-wrapper
    ScriptAlias /fcgid-bin/ /srv/http/fcgid-bin/
    SocketPath /var/run/httpd/fcgidsock
    SharememPath /var/run/httpd/fcgid_shm
        # If you don't allow bigger requests many applications may fail (such as WordPress login)
        FcgidMaxRequestLen 536870912
        # Path to php.ini – defaults to /etc/phpX/cgi
        DefaultInitEnv PHPRC=/etc/php7/
        # Number of PHP childs that will be launched. Leave undefined to let PHP decide.
        #DefaultInitEnv PHP_FCGI_CHILDREN 3
        # Maximum requests before a process is stopped and a new one is launched
        #DefaultInitEnv PHP_FCGI_MAX_REQUESTS 5000
        #Increased default IO timeout from 40 seconds to 2 minutes
        FcgidIOTimeout 120
    <Location /fcgid-bin/>
        SetHandler fcgid-script
        Options +ExecCGI
    </Location>
</IfModule>

MariaDB

While ultimately I intend to run the database for iTop off an existing database server I did go through the steps of installing MariaDB locally so that I could create a Salt state file to do the needful in the future. While the steps are fairly straight forward, install the software, initialize the database server, set the service running and then to restart, I ran in to an hardware related setting that kept causing the software to crash during database initialization. After some searching on the world wide web, I found an Odroid C2 specific setting to change, and when I did chane it things began working as expected. I will note the setting in the Opportunities section below, and did create a state file to fix, I am not going to include it in my Salt state file for MariaDB, as it is unlikely something that I will run into again.

As should be expected, I for the most part stuck with the installation guidance for MariaDB on the Arch Wiki.

Install the Software
  • su -c 'pacman -S mariadb'
Initialize the Database Server for Use
  • su -c 'mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql'
Enable and Start Service
  • su -c 'systemctl enable --now mariadb.service'

Finally, here is the Salt state I came up with to do the installation and activation:

File system layout for app_mariadb

/srv/salt/app_mariadb/
└── init.sls

init.sls file for Mariadb

# Installs Maria DB Server 
# Created: 2021-12-28
# Modified 
# Notes: Arch guidance - https://wiki.archlinux.org/title/MariaDB
#
# Make sure mariadb is installed
inst_mariadb:
  pkg.installed:
    - name: 
    - refresh: False

init_mariadb:
  cmd.run:
    - name: mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
    - onchanges:
      - pkg: inst_mariadb

# Make sure service is enabled and started.
  service.running:
    - name: mariadb.service
    - enable: True
    - reload: True
    - provider: systemd

iTop

With with the needed support staxk in place (Apache, MariaDB and PHP) and working, all that remains is to install iTop. For the installation I relied heavilly on the documentation from iTop. For purposes of this document, I am installing iTop version 2.7.5-1 which I downloaded as a zipped archive file from SourceForge.

iTop Prerequisites

In addition to the prerequisites noted in the iTop documentation, I identified a couple of additional requirements that resulted from deciding to make use of an unused machine with little more installed than the base operating system. For example the iTop software I am using is distributed as a Zip archive, and the server had no Unzip utility installed. The PHP install outlined above is also pretty bare bones and it did not surprise me that I wound up having to enable some additional PHP modules to support iTop.

Unzip

Instalation of unzip utility is straight forward, just a su -c 'pacman -S unzip'. The state file to install iTop has an include stanza which calls the state file to install unzip and other dependencies from their own individual install state files. This is the approach I took for the rest of the prerequisites as well. Ultimately the Apache, MariaDB and PHP installations could be treated in the same manner where each of the state files is ‘included’ into the iTop state file.

File System Layout for app_unzip

/srv/salt/app_unzip/
└── init.sls

init.sls file for unzip

# Installs unzip software
# Created: 2021-12-29
# Modified:
  # Tested on Arch ARM Linux 

# Install unzip
{% if (grains['os'] == 'Arch ARM') %}
inst_unzip:
  pkg.installed:
    - name: {{ pillar['unzip'] }}
    - refresh: False
{% endif %}

Graphviz

Since iTop makes use of Graphviz as a run-time dependency, I opted to include the state file to install as part of the iTop statefile like was done for Unzip. su -c 'pacman -S graphviz' did the trick for this host.

File System Layout for app_graphviz

/srv/salt/app_graphviz/
└── init.sls

init.sls file for graphviz

# Installs graphviz software
# Created: 2021-12-29
# Modified:
  # Tested on Arch ARM Linux 

# Install graphviz
{% if (grains['os'] == 'Arch ARM') %}
inst_graphviz:
  pkg.installed:
    - name: {{ pillar['graphviz'] }}
    - refresh: False
{% endif %}

Additional PHP Modules for iTop

When running the iTop wizard the first time it raised errors for missing PHP modules GD, MYSQLI, ICONV, SOAP, LDAP and the ability to save sessions.

File system layout for php7-gd, php7-mysqli, php7-iconv, php7-soap, php7-ldap and php7-session_save_

/srv/salt/app_php7_php7-gd/
└── init.sls
/srv/salt/app_php7_php7-mysqli/
└── init.sls
/srv/salt/app_php7_php7-iconv/
└── init.sls
/srv/salt/app_php7_php7-soap/
└── init.sls
/srv/salt/app_php7_php7-ldap
└── init.sls
/srv/salt/app_php7_php7-session-save/
└── init.sls

init.sls for GD

# Installs php-gd
# Created: 2021-12-27
# Modified  

# Make sure apache php-gd extension is installed
#
include:
  - app_php7

php7-gd_inst:
  pkg.installed:
    - name: 
    - refresh: False

gd_enable:
  file.replace:
    - name: /etc/php7/php.ini
    - pattern: ;extension=gd
    - repl: extension=gd
    - count: 1
    - backup: .bak
    - bufsize: file

# Restart Apache
# Make sure service is enabled and restarted if changes.
gd_restart_apache_service:
  service.running:
    - name: httpd.service
    - enable: True
    - watch:
      - file: '/etc/php7/php.ini'

init.sls for MYSQLI

# Enables php-mysqli
# Created: 2021-12-27
# Modified  

# Make sure php7-mysqli extension is enabled
#
include:
  - app_php7

php7-mysqli_enable:
  file.replace:
    - name: /etc/php7/php.ini
    - pattern: ;extension=mysqli
    - repl: extension=mysqli
    - count: 1
    - backup: .bak_mysqli
    - bufsize: file

php7-pdo_mysql_enable:
  file.replace:
    - name: /etc/php7/php.ini
    - pattern: ;extension=pdo_mysql
    - repl: extension=pdo_mysql
    - count: 1
    - backup: .bak_pdo
    - bufsize: file

# Restart Apache
# Make sure service is enabled and restarted if changes.
mysqli_restart_apache_service:
  service.running:
    - name: httpd.service
    - enable: True
    - watch:
      - file: '/etc/php7/php.ini'

init.sls for ICONV

# Enables php-iconv
# Created: 2021-12-27
# Modified  

# Make sure php-iconv extension is enabled

include:
  - app_php7

iconv_enable:
  file.replace:
    - name: /etc/php7/php.ini
    - pattern: ;extension=iconv
    - repl: extension=iconv
    - count: 1
    - backup: .bak_iconv
    - bufsize: file

# Restart Apache
# Make sure service is enabled and restarted if changes.
iconv_restart_apache_service:
  service.running:
    - name: httpd.service
    - enable: True
    - watch:
      - file: '/etc/php7/php.ini'

init.sls for SOAP

# Enables php7-soap extension
# Created: 2021-12-27
# Modified  

# Make sure php-soap extension is enabled
#
include:
  - app_php7

soap_enable:
  file.replace:
    - name: /etc/php7/php.ini
    - pattern: ;extension=soap
    - repl: extension=soap
    - count: 1
    - backup: .bak_soap
    - bufsize: file

# Restart Apache
# Make sure service is enabled and restarted if changes.
soap_restart_apache_service:
  service.running:
    - name: httpd.service
    - enable: True
    - watch:
      - file: '/etc/php7/php.ini'

init.sls for LDAP

# Enables php7-ldap extension
# Created: 2021-12-27
# Modified  

# Make sure php-ldap extension is enabled
#
include:
  - app_php7

ldap_enable:
  file.replace:
    - name: /etc/php7/php.ini
    - pattern: ;extension=ldap
    - repl: extension=ldap
    - count: 1
    - backup: .bak_ldap
    - bufsize: file

# Restart Apache
# Make sure service is enabled and restarted if changes.
ldap_restart_apache_service:
  service.running:
    - name: httpd.service
    - enable: True
    - watch:
      - file: '/etc/php7/php.ini'

init.sls for save_sessions

# Enables php7-session saving to /tmp file system
# Created: 2021-12-27
# Modified  

# Make sure php7 session saving is enabled
#
include:
  - app_php7

session_save_enable:
  file.replace:
    - name: /etc/php7/php.ini
    - pattern: ;session.save_path = "/tmp"
    - repl: session.save_path = "/tmp"
    - count: 1
    - backup: .bak_session
    - bufsize: file

# Restart Apache
# Make sure service is enabled and restarted if changes.
session_restart_apache_service:
  service.running:
    - name: httpd.service
    - enable: True
    - watch:
      - file: '/etc/php7/php.ini'

Putting every thing together, this is the Salt state file I came up with to install the iTop software:

File System Layout for app_itop

/srv/salt/app_itop
├── files
│   └── iTop-2.7.5-1-7770.zip
└── init.sls

init.sls file for itop

# Installs iTop as a CMDB 
# Created: 2021-12-27
# Modified

# Install iTop
include: 
  # iTop dependencies
  - app_graphviz
  - app_unzip
  - app_php7
  - app_apache
  - app_mariadb
  - app_php7_php7-cgi
  - app_php7_php7-gd
  - app_php7_php7-iconv
  - app_php7_php7-mysqli
  - app_php7_php7-soap
  - app_php7_php7-ldap
  - app_php7_php7-session-save

iTop_inst:
  # expand iTOP archive in web server document root
  archive.extracted:
    - name: /srv/http
    - source: salt://app_itop/files/iTop-2.7.5-1-7770.zip
    - user: http
    - group: http
    - keep_source: False
    - archive_format: zip
    - enforce_toplevel: False
    - if_missing: /srv/http/itop

  file.rename:
    # Rename 'web' folder to 'itop' in webserver document root
    - name: /srv/http/itop
    - source: /srv/http/web

/srv/http/INSTALL:
   # Remove unnecessary file from wbserver document root
   file.absent

/srv/http/README:
   # Remove unnecessary file from wbserver document root
   file.absent

/srv/http/LICENSE:
   # Remove unnecessary file from wbserver document root
   file.absent

With the above I was successfully able to automatically install the iTop software and all supporting dependencies on the Arch based Odroid C2 by simply issuing the single command su -c 'salt bob-c2 state.apply app_iftop'. Issuing that command and then waiting a few minutes is all it takes to install iTop and all of the dependencies on which it relies.

There are a few more steps to complete before the application can be configured and made available for use.

iTop Database and Database User

I created the database and database user for iTop to use with the forllowing commands. I should tuck these commands into a Salt state, but have not done so as yet, simply executing them directly through the mysql commnad line interface.

User Create / Acces Grant
CREATE DATABASE iTop;
CREATE USER 'iTop'@'localhost' IDENTIFIED BY 'SekretPasswerd';
GRANT ALL PRIVILEGES ON iTop.* TO 'iTop'@'localhost';
FLUSH PRIVILEGES;
QUIT;

iTop Wizard

With the software installes, and database user and database created, all thet remains is to visit the index page of of the iTop software in a web browser and complete the first time use wizard to complete initial configuration. For me, this was a matter of browsing to http://bob-c2/itop/index.php.

Initial Landing Page

alt text

Install or Upgrade Choice

alt text

iTop License Acceptance Dialog

alt text

iTop Database Configuration Dialog

alt text

Administrator Account Setup Dialog

alt text

Miscellaneous Parameters Setting Dialog

alt text

Configuration Management Options Dialog

alt text

Service Management Options Dialog

alt text

Tickets Management Options Dialog

alt text

Change Management Options Dialog

alt text

Additional ITIL Tickets Dialog

alt text

Ready to Install Dialog

alt text

Installation in Progress

alt text

Installation Done Dialog

alt text

Welcome to iTop Dialog

alt text

Opportunities / Lessons Learned

  • A new version 3.0.0 of iTop should soon be out of Beta, so there will be a chance to revisit and perhaps improve things as a result of upgrading.
  • php-fcgid.conf
    • Had to increase the fcgid IO timeout from default of 40s to 2 minutes in order to get iTop to install.
          #Increased default IO timeout from 40 seconds to 2 minutes
	  FcgidIOTimeout 120
    
  • /boot/boot.ini
    • Had alter mesontime setting from default of “1” to “0” in ordert to get MariaDB initializaed on the Odroid C2 hardware. This will diminish video performance, but is not an issue for me as I am running the device headless. A reboot is necessary for the change to take effect, so needs to be done before MariaDB is initialized as part of the install process.
      • setenv mesontimer “0”
      • Here is a Salt file to apply this fix.
# Fixes /boot/boot.ini on C2 to allow Mariadb to work
# Created: 2021-12-29
# Modified
# Notes: Odroid guidance - https://forum.odroid.com/viewtopic.php?t=40016
#         setenv mesontimer "0"

fixboot:
  file.replace:
    - name: /boot/boot.ini
    - repl: setenv mesontimer "0"
    - pattern:  setenv mesontimer "1"
    - ignore_if_missing: True

Reboot if changed:
  module.run:
    - system.reboot:
    - onchanges:
      - fixboot 

References