Post

Install Xibo on Debian

I have installed Xibo CMS on Debian Bullseye using Apache2 as the web server and enforcing TLS using this configuration. I have completed this using the autogenerated self-signed certificates for TLS (not trusted). You will need to follow another guide for creating public-signed certificates. I recommend using Let’s Encrypt with their certbot.

This guide is now updated for installing Xibo CMS 4.0.10.

  • The MariaDB version installed here is not currently supported by Xibo.
  • A local install of QuickChart is not covered in this guide but recommended.
  • This guide previously used Ubuntu for the OS.

Install Requirements

All of the requirements can be installed using apt.

1
sudo apt install apache2 cron libapache2-mod-{xsendfile,php8.2} mariadb-server mariadb-client nftables php8.2-{cli,gd,mysql,zip,soap,curl,simplexml,mbstring,zmq} wget

Install Xibo CMS

When I am configuring server software outside of a package manager I always place it under the /srv folder. I will be installing Xibo under /srv/xibo-cms.

1
2
3
sudo mkdir /srv/xibo-cms
cd /srv/xibo-cms
sudo wget https://github.com/xibosignage/xibo-cms/releases/download/4.0.10/xibo-cms-4.0.10.tar.gz

This extracts the contents of the archive without placing it into a folder

1
2
sudo tar -xvzf xibo-cms-4.0.10.tar.gz --strip-components=1
sudo rm xibo-cms-4.0.10.tar.gz

The apache2 user ‘www-data’ needs to be set as owner of all the extracted items.

1
sudo chown -R www-data: /srv/xibo-cms

This deletes the existing /var/www directory and creates a symlink to /srv/xibo-cms.

1
2
sudo rm -r /var/www
sudo ln -s /srv/xibo-cms /var/www

Configure Apache2

This enables the necessary apache2 modules and creates a site configuration using vim.

1
2
sudo a2enmod rewrite ssl session headers
sudo vim /etc/apache2/sites-available/xibo-cms.conf

xibo-cms.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<VirtualHost *:80>
    DocumentRoot "/var/www/web"
    ServerName xibo.domain.com
    XSendFile on
    XSendFilePath /var/www/library
    <Directory "/var/www/web">
        AllowOverride All
        Options Indexes FollowSymLinks MultiViews
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    DocumentRoot "/var/www/web"
    ServerName xibo.domain.com
    XSendFile on
    XSendFilePath /var/www/library
    SSLEngine on
    SSLCertificateFile "/etc/ssl/certs/ssl-cert-snakeoil.pem"
    SSLCertificateKeyFile "/etc/ssl/private/ssl-cert-snakeoil.key"
    <Directory "/var/www/web">
        AllowOverride All
        Options Indexes FollowSymLinks MultiViews
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

This disables the default site and enables the newly created xibo-cms site configuration.

1
2
sudo a2dissite 000-default.conf
sudo a2ensite xibo-cms.conf

Configure MariaDB

This configures a root password for MariaDB. Make sure to change MY_NEW_PASSWORD to your password of choice. First enter mariadb/mysql console by runinng sudo mysql, then run these SQL commands.

1
2
3
ALTER USER 'root'@'localhost' IDENTIFIED BY 'MY_NEW_PASSWORD';
FLUSH PRIVILEGES;
quit;

Configure PHP

PHP configuration needs to be modified to allow upload of larger files and a few other parts I pulled from Xibo’s Dockerfile.

1
sudo vim /etc/php/8.2/apache2/php.ini

You need to modify the file to change the following settings

1
2
3
4
5
6
7
8
9
10
11
12
13
allow_url_fopen = Off
error_reporting = E_ERROR | E_WARNING | E_PARSE
expose_php = Off
max_execution_time = 300
memory_limit = 256M
post_max_size = 2G
session.cookie_secure = Off
session.cookie_httponly = On
session.cookie_samesite = Lax
session.gc_divisor = 100
session.gc_maxlifetime = 1440
session.gc_probability = 1
upload_max_filesize = 2G

And also for cli.

1
sudo vim /etc/php/8.2/cli/php.ini
1
2
3
4
5
6
7
8
allow_url_fopen = Off
error_reporting = E_ERROR | E_WARNING | E_PARSE
expose_php = Off
max_execution_time = 0
memory_limit = 256M
session.gc_divisor = 100
session.gc_probability = 1
upload_max_filesize = 2G

You can do all this quickly with sed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sed -i "s/allow_url_fopen = .*$/allow_url_fopen = Off/" /etc/php/8.2/apache2/php.ini
sed -i "s/error_reporting = .*$/error_reporting = E_ERROR | E_WARNING | E_PARSE/" /etc/php/8.2/apache2/php.ini
sed -i "s/expose_php = .*$/expose_php = Off/" /etc/php/8.2/apache2/php.ini
sed -i 's/max_execution_time = .*$/max_execution_time = 300/g' /etc/php/8.2/apache2/php.ini
sed -i 's/memory_limit = .*$/memory_limit = 256M/g' /etc/php/8.2/apache2/php.ini
sed -i 's/post_max_size = .*$/post_max_size = 2G/g' /etc/php/8.2/apache2/php.ini
sed -i 's/session.cookie_secure = .*$/session.cookie_secure = Off/g' /etc/php/8.2/apache2/php.ini
sed -i 's/session.cookie_httponly = .*$/session.cookie_httponly = On/g' /etc/php/8.2/apache2/php.ini
sed -i 's/session.cookie_samesite = .*$/session.cookie_samesite = Lax/g' /etc/php/8.2/apache2/php.ini
sed -i "s/session.gc_divisor = .*$/session.gc_divisor = 100/" /etc/php/8.2/apache2/php.ini
sed -i "s/session.gc_maxlifetime = .*$/session.gc_maxlifetime = 1440/" /etc/php/8.2/apache2/php.ini
sed -i "s/session.gc_probability = .*$/session.gc_probability = 1/" /etc/php/8.2/apache2/php.ini
sed -i 's/upload_max_filesize = .*$/upload_max_filesize = 2G/g' /etc/php/8.2/apache2/php.ini
sed -i "s/allow_url_fopen = .*$/allow_url_fopen = Off/" /etc/php/8.2/cli/php.ini
sed -i "s/error_reporting = .*$/error_reporting = E_ERROR | E_WARNING | E_PARSE/" /etc/php/8.2/cli/php.ini
sed -i "s/expose_php = .*$/expose_php = Off/" /etc/php/8.2/cli/php.ini
sed -i 's/max_execution_time = .*$/max_execution_time = 0/g' /etc/php/8.2/cli/php.ini
sed -i 's/memory_limit = .*$/memory_limit = 256M/g' /etc/php/8.2/cli/php.ini
sed -i "s/session.gc_divisor = .*$/session.gc_divisor = 100/" /etc/php/8.2/cli/php.ini
sed -i "s/session.gc_probability = .*$/session.gc_probability = 1/" /etc/php/8.2/cli/php.ini
sed -i 's/upload_max_filesize = .*$/upload_max_filesize = 2G/g' /etc/php/8.2/cli/php.ini

Configure XMR

Create XMR Configuration File

1
sudo vim /srv/xibo-cms/vendor/xibosignage/xibo-xmr/bin/config.json

Enter the following information and change the pubOn IP address to the public IP of the server. You can view this by running the command “ip address”

1
2
3
4
5
{
    "listenOn": "tcp://127.0.0.1:50001",
    "pubOn": ["tcp://192.168.1.1:9505"],
    "debug": false
}

Set www-data as the owner of the file.

1
sudo chown www-data: /srv/xibo-cms/vendor/xibosignage/xibo-xmr/bin/config.json

Create XMR service

1
sudo vim /etc/systemd/system/xibo-xmr.service

There is an issue with this because it is using php8 by default and you receive the error PHP Fatal error: Unparenthesized `a ? b : c ? d : e` is not supported. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)` in phar:///srv/xibo-cms/vendor/xibosignage/xibo-xmr/bin/xmr.phar/index.php on line 204. To Resolve this I have forced it to use php8.2 in the ExecStart command.

Enter the following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=Xibo XMR
After=network.target

[Service]
User=www-data
Group=www-data
ExecStart=/usr/bin/php8.2 /srv/xibo-cms/vendor/bin/xmr.phar
Restart=always
KillMode=process
RestartSec=1

[Install]
WantedBy=multi-user.target

Start the service

1
2
3
sudo systemctl daemon-reload
sudo systemctl enable xibo-xmr.service
sudo systemctl start xibo-xmr.service

Check the status of the xibo-xmr service to confirm it is working.

1
sudo systemctl status xibo-xmr.service

Configure XTR

1
sudo crontab -u www-data -e

Select the editor you prefer and then enter the following line.

1
* * * * * /usr/bin/php8.2 /srv/xibo-xmr/bin/xtr.php

Configure Firewall

I have used nftables to configure this. It was installed at the start with apt. I have used the simple ruleset for a server from nftables.org’s wiki.

1
sudo vim /etc/nftables.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
flush ruleset                                                                    
                                                                                 
table inet firewall {

    chain inbound_ipv4 {
        # accepting ping (icmp-echo-request) for diagnostic purposes.
        # However, it also lets probes discover this host is alive.
        # This sample accepts them within a certain rate limit:
        #
        # icmp type echo-request limit rate 5/second accept
    }

    chain inbound_ipv6 {
        # accept neighbour discovery otherwise connectivity breaks
        #
        icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept

        # accepting ping (icmpv6-echo-request) for diagnostic purposes.
        # However, it also lets probes discover this host is alive.
        # This sample accepts them within a certain rate limit:
        #
        # icmpv6 type echo-request limit rate 5/second accept
    }

    chain inbound {

        # By default, drop all traffic unless it meets a filter
        # criteria specified by the rules that follow below.
        type filter hook input priority 0; policy drop;

        # Allow traffic from established and related packets, drop invalid
        ct state vmap { established : accept, related : accept, invalid : drop }

        # Allow loopback traffic.
        iifname lo accept

        # Jump to chain according to layer 3 protocol using a verdict map
        meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 }

        # Allow SSH on port TCP/22 and allow HTTP(S) TCP/80 and TCP/443
        # for IPv4 and IPv6.
        tcp dport { 22, 80, 443, 9505 } accept

        # Uncomment to enable logging of denied inbound traffic
        # log prefix "[nftables] Inbound Denied: " counter drop
    }

    chain forward {
        # Drop everything (assumes this device is not a router)
        type filter hook forward priority 0; policy drop;
    }

    # no need to define output chain, default policy is accept if undefined.
}

Restart nftables service to apply.

1
sudo systemctl restart nftables.service

Complete Installation

1
sudo systemctl restart apache2

You can now browse to the server at the location you configured in the xibo-cms.conf. You will need to point it at the database and use the password you created earlier. You can use most defaults as you go through the rest of the configuration.

Upgrading

Backup

The simplest thing to do is to stop apache2 and xibo-xmr service, moving the /srv/xibo-cms directory, and backing up the database.

1
2
3
sudo systemctl stop apache2 xibo-xmr
sudo mv /srv/xibo-cms /srv/xibo-cms.backup
sudo mysqldump xibo-cms > xibo-cms.sql

Create xibo-cms directory and change to it. Download the new version, in this example 4.0.8 extract it and copy back the necessary files. You will also need to delete the install/index.php file to stop a warning from appearing.

Installation

1
2
3
4
5
6
7
8
9
sudo mkdir /srv/xibo-cms
cd /srv/xibo-cms
sudo wget https://github.com/xibosignage/xibo-cms/releases/download/4.0.10/xibo-cms-4.0.10.tar.gz
sudo tar -xvzf xibo-cms-4.0.10.tar.gz --strip-components=1
sudo cp /srv/xibo-cms.backup/web/settings.php web/
sudo cp -r /srv/xibo-cms.backup/library .
sudo cp /srv/xibo-cms.backup/vendor/xibosignage/xibo-xmr/bin/config.json vendor/xibosignage/xibo-xmr/bin/
sudo chown -R www-data:www-data /srv/xibo-cms
sudo rm web/install/index.php

If upgrading between versions i.e. 3.x.x to 4.x.x, you will need to upgrade the database with this command which must be run from /srv/xibo-cms directory.

1
vendor/bin/phinx migrate -c phinx.php

Start up the services again.

1
sudo systemctl start apache2 xibo-xmr

After you have logged back in you may see no Layouts. Press Shift+F5 to clear cache on your browser and reload the page.

This post is licensed under CC BY 4.0 by the author.