How to Install UVdesk Helpdesk System on Ubuntu 20.04 LTS

Updated on May 4, 2022
How to Install UVdesk Helpdesk System on Ubuntu 20.04 LTS header image


UVdesk is an open-source helpdesk system designed to offer multi-channel customer service. With the help of UVdesk, you can respond to support tickets from various online platforms in one single place.

This article explains how to install UVdesk Open Source 1.1.0 on an Ubuntu 20.04 LTS cloud server instance at Vultr.


Before you begin, you need to:

  • Deploy an Ubuntu 20.04 LTS server instance at Vultr with at least 4 GB of memory. And this article uses as an example IPv4 address for the server instance.
  • Prepare a domain name, such as, for accessing the UVdesk helpdesk system.

1. Set Up DNS Records

If you are hosting the apex domain name at Vultr, set up DNS records as follows to bind,, and to the UVdesk server's IPv4 address

|table|100| |thead| |tr| |th|20|Type| |th|20|Name| |th|20|Data| |th|20|TTL(seconds)| |th|20|Priority| |tbody| |tr| |td|A| |td| | |td|| |td|300| |td| | |tr| |td|A| |td|www| |td|| |td|300| |td| | |tr| |td|A| |td|helpdesk| |td|| |td|300| |td| | |tr| |td|MX| |td| | |td|| |td|300| |td|10| |tr| |td|NS| |td| | |td|| |td|300| |td| | |tr| |td|NS| |td| | |td|| |td|300| |td| |

To learn more about managing DNS through Vultr, see the introduction to Vultr DNS.

Instructions on setting up DNS records on other platforms may vary.

2. Prepare the System

Open your favorite terminal program on your desktop machine, such as PuTTY on Windows or iTerm2 on macOS, and log in to the UVdesk server instance as root with the initial password you found on the Server Details page.

After logging in, perform the tasks listed in this section to prepare the system.

Check if any swap space is in use on the system:

# swapon -s

If the system has swap allocated, skip to the next task. Otherwise, create a swap file of 2GB to smooth system operations:

# fallocate -l 2g /swap
# chmod 600 /swap
# mkswap /swap
# swapon /swap
# echo '/swap    none swap defaults 0 0' | tee -a /etc/fstab
# free -m

Change the system-provided password of the root user to a private and strong one, such as r00tyHvM%2kaz8E3:

# echo 'root:r00tyHvM%2kaz8E3' | chpasswd && history -d -1

Add a non-root user with sudo privileges, such as uvdesk, and also set up a strong password for it, such as sud04QeXb$x#6&Cw:

# useradd -ms /bin/bash uvdesk
# echo 'uvdesk:sud04QeXb$x#6&Cw' | chpasswd && history -d -1
# echo 'uvdesk    ALL=(ALL)   NOPASSWD: ALL' | tee -a /etc/sudoers.d/designated
# chmod 0440 /etc/sudoers.d/designated

Create UFW firewall rules to allow only traffic on 22(SSH), 80(HTTP), and 443(HTTPS) ports:

# ufw default deny
# ufw allow 22
# ufw allow 80
# ufw allow 443
# ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y:key_enter:
# ufw status verbose

Update the system, and reboot the server instance to apply all updates:

# apt update
# apt upgrade -y
# apt autoremove -y
# shutdown -r now

After the server instance gets up and running again, log in as the newly created sudo user uvdesk to move on.

3. Install MariaDB 10.7

UVdesk Open Source 1.1.0 requires a Relational Database Management System (RDBMS), and this article prefers MariaDB 10.7, the latest stable release of MariaDB.

Set up the MariaDB 10.7 Advanced Package Tool (APT) repository:

$ sudo apt-get install software-properties-common dirmngr apt-transport-https -y
$ sudo apt-key adv --fetch-keys ''
$ sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el,s390x] focal main'

Install MariaDB 10.7 server:

$ sudo apt update
$ sudo apt install mariadb-server -y

Start the MariaDB service and make it automatically start on boot:

$ sudo systemctl start mariadb.service
$ sudo systemctl enable mariadb.service

Run an official script to secure the installation of MariaDB 10.7 server:

$ sudo mariadb-secure-installation

Reply to questions as follows to enhance the security of the MariaDB 10.7 installation:

Enter current password for root (enter for none): :key_enter:
Switch to unix_socket authentication [Y/n] n:key_enter:
Change the root password? [Y/n] n:key_enter:
Remove anonymous users? [Y/n] y:key_enter:
Disallow root login remotely? [Y/n] y:key_enter:
Remove test database and access to it? [Y/n] y:key_enter:
Reload privilege tables now? [Y/n] y:key_enter:

Find possible locations of the MariaDB configuration files:

$ mysql --help | grep "Default options" -A 1
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf

Create a global MariaDB configuration file at the first location:

$ sudo nano /etc/my.cnf

Populate the file as follows to set utf8mb4 as the default character set for MariaDB 10.7:

default-character-set = utf8mb4

default-character-set = utf8mb4

character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

Press Ctrl+O, Enter, and Ctrl+X to save the configuration file and quit.

Restart the MariaDB service to load new settings:

$ sudo systemctl restart mariadb.service

4. Install PHP 8.0

Create a third-party PHP Personal Package Archives (PPA) repository:

$ LC_ALL=C.UTF-8 sudo add-apt-repository ppa:ondrej/php -y
$ sudo apt update
$ sudo apt upgrade -y

Install required PHP 8.0 packages for UVdesk, including the FastCGI Process Manager (FPM) extension for working with Nginx:

$ sudo apt install php8.0 php8.0-bcmath php8.0-common php8.0-curl php8.0-fpm php8.0-gd php8.0-imap php8.0-intl php8.0-ldap php8.0-mailparse php8.0-mbstring php8.0-mysql php8.0-mongodb php8.0-opcache php8.0-soap php8.0-tidy php8.0-xml php8.0-zip -y
$ php -v
PHP 8.0.17 (cli) (built: Mar 20 2022 17:04:09) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.17, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.17, Copyright (c), by Zend Technologies

Set up the proper timezone according to the location of your server instance:

$ sudo sed -i 's#;date.timezone =#date.timezone = America/Los_Angeles#' /etc/php/8.0/fpm/php.ini
$ sudo sed -i 's#;date.timezone =#date.timezone = America/Los_Angeles#' /etc/php/8.0/cli/php.ini

For other timezones, refer to the PHP Timezones List page.

Increase the memory limit for PHP-FPM 8.0 from 128MB to 1GB:

$ sudo sed -i 's/memory_limit = 128M/memory_limit = 1G/' /etc/php/8.0/fpm/php.ini

Increase execution time to 60 seconds for both PHP-FPM and PHP-CLI:

$ sudo sed -i 's/max_execution_time = 30/max_execution_time = 60/' /etc/php/8.0/fpm/php.ini
$ sudo sed -i 's/max_execution_time = 30/max_execution_time = 60/' /etc/php/8.0/cli/php.ini

Change PHP-FPM 8.0 settings to make it work with Nginx:

$ sudo sed -i 's/user = www-data/user = nginx/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/group = www-data/group = nginx/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/listen.owner = www-data/listen.owner = nginx/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/ = www-data/ = nginx/' /etc/php/8.0/fpm/pool.d/www.conf

Start the PHP-FPM 8.0 service and make it automatically start on boot:

$ sudo systemctl start php8.0-fpm.service
$ sudo systemctl enable php8.0-fpm.service

5. Install Nginx 1.21.6

UVdesk Open Source 1.1.0 needs to work with a web server, such as Apache or Nginx. This article prefers the latest mainline release of Nginx, which is Nginx 1.21.6 for now.

Install dependencies for installing Nginx:

$ sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring -y

Import the official Nginx GPG signing key:

$ curl | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

Identify the GPG signing key stored in the downloaded file:

$ gpg --dry-run --quiet --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg

Make sure that the output contains the full fingerprint 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62. Otherwise, delete the downloaded file and re-do the import.

Set up the mainline Nginx APT repository:

$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

Set up repository pinning to prefer official Nginx mainline packages to distribution-provided ones:

$ echo -e "Package: *\nPin: origin\nPin: release o=nginx\nPin-Priority: 900\n" \
    | sudo tee /etc/apt/preferences.d/99nginx

Install the mainline version of Nginx, which is Nginx 1.21.6 for now:

$ sudo apt update
$ sudo apt install nginx -y

Confirm the installation of Nginx:

$ nginx -V
nginx version: nginx/1.21.6
built by gcc 9.3.0 (Ubuntu 9.3.0-10ubuntu2)
built with OpenSSL 1.1.1f  31 Mar 2020
TLS SNI support enabled

Start the Nginx service and make it automatically start on boot:

$ sudo systemctl start nginx.service
$ sudo systemctl enable nginx.service

6. Get a Let's Encrypt Certificate

Valid TLS certificates are indispensable for enabling HTTPS access to a website. If you don't have any valid TLS certificate yet, follow instructions below to get free Let's Encrypt certificates for,, and

Update the snapd program:

$ sudo snap install core; sudo snap refresh core

Remove any existing Certbot programs installed from other sources to avoid possible conflicts:

$ sudo apt-get remove certbot
$ sudo sed -i '/certbot-auto/d' /etc/crontab
$ sudo rm -f /usr/local/bin/cert-bot
$ sudo rm -rf /opt/

Install Certbot using the snapd program:

$ sudo snap install --classic certbot

Create a symbolic link in the /usr/bin directory pointing to the newly installed Certbot program:

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Get Let's Encrypt certificates for,, and through Certbot and its Nginx plugin:

$ sudo certbot certonly --nginx --email --agree-tos --no-eff-email -d -d -d

The Certbot program has set up automatic certificate renewals by default to prevent the Let's Encrypt TLS certificates from expiring in 90 days. Use the commands listed below to confirm these renewals are on schedule:

$ sudo certbot renew --dry-run
$ sudo systemctl list-timers | grep snap.certbot.renew.service

7. Install Composer 2.3.3

UVdesk uses Composer to manage dependencies. Use the following commands to install Composer 2.3.3, the latest stable release of Composer for now:

$ cd
$ php -r "copy('', 'composer-setup.php');"
$ php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"
$ sudo mv composer.phar /usr/local/bin/composer
$ composer -V
Composer version 2.3.3 2022-04-01 22:15:35

Notice: The instructions listed above are only for installing Composer 2.3.3. Always check for the proper instructions for installing a newer version of Composer on the official Composer Download page.

8. Install UVdesk 1.1.0

Create a MariaDB Database for UVdesk

Log in to the MariaDB shell as root:

$ sudo mysql -u root

In the MariaDB shell, create a database named uvdesk, a database user named uvdesk, and the database user's password uv8jTm9LHtez0MKn:

MariaDB [(none)]> CREATE DATABASE uvdesk CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
MariaDB [(none)]> CREATE USER 'uvdesk'@'localhost' IDENTIFIED BY 'uv8jTm9LHtez0MKn';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON uvdesk.* TO 'uvdesk'@'localhost' IDENTIFIED BY 'uv8jTm9LHtez0MKn' WITH GRANT OPTION;
MariaDB [(none)]> EXIT;

Configure Nginx to Host UVdesk

Create required directories for hosting the UVdesk site:

$ sudo mkdir /etc/nginx/{sites-available,sites-enabled,modules-enabled}
$ sudo mkdir /var/www/
$ sudo chown uvdesk:uvdesk /var/www/

Back up preset Nginx configuration files:

$ sudo mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
$ sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak

Generate a 2048-bit Diffie-Hellman parameters file to increase SSL security:

$ sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048

Create the main Nginx configuration file:

$ sudo nano /etc/nginx/nginx.conf

Populate the file with:

user                 nginx;
pid                  /run/;
worker_processes     auto;
worker_rlimit_nofile 65535;

# Load modules
include              /etc/nginx/modules-enabled/*.conf;

events {
    multi_accept       on;
    worker_connections 65535;

http {
    charset                utf-8;
    sendfile               on;
    tcp_nopush             on;
    tcp_nodelay            on;
    server_tokens          off;
    log_not_found          off;
    types_hash_max_size    2048;
    types_hash_bucket_size 64;
    client_max_body_size   16M;

    # MIME
    include                mime.types;
    default_type           application/octet-stream;

    # Logging
    access_log             /var/log/nginx/access.log;
    error_log              /var/log/nginx/error.log warn;

    # SSL
    ssl_session_timeout    1d;
    ssl_session_cache      shared:SSL:10m;
    ssl_session_tickets    off;

    # Diffie-Hellman parameter for DHE ciphersuites
    ssl_dhparam            /etc/nginx/dhparam.pem;

    # Mozilla Intermediate configuration
    ssl_protocols          TLSv1.2 TLSv1.3;

    # OCSP Stapling
    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver      valid=60s;
    resolver_timeout       2s;

    # Load configurations
    include                /etc/nginx/conf.d/*.conf;
    include                /etc/nginx/sites-enabled/*;

Press Ctrl+O, Enter, and Ctrl+X to save and quit.

Create the Nginx configuration file for

$ sudo nano /etc/nginx/sites-available/

Populate the file with:

server {
    listen                  443 ssl http2;
    listen                  [::]:443 ssl http2;
    server_name   ;
    set                     $base /var/www/;
    root                    $base/public;

    # SSL
    ssl_certificate         /etc/letsencrypt/live/;
    ssl_certificate_key     /etc/letsencrypt/live/;
    ssl_trusted_certificate /etc/letsencrypt/live/;

    # . files
    location ~ /\.(?!well-known) {
        deny all;

    # index.php
    index                   index.php;

    # index.php fallback
    location / {
        try_files $uri $uri/ /index.php?$query_string;

    # favicon.ico
    location = /favicon.ico {
        log_not_found off;
        access_log    off;

    # robots.txt
    location = /robots.txt {
        log_not_found off;
        access_log    off;

    # assets, media
    location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
        expires    7d;
        access_log off;

    # svg, fonts
    location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
        add_header Access-Control-Allow-Origin "*";
        expires    7d;
        access_log off;

    # gzip
    gzip            on;
    gzip_vary       on;
    gzip_proxied    any;
    gzip_comp_level 6;
    gzip_types      text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

    # handle .php
    location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php-fpm.sock;
    # 404
    try_files                     $fastcgi_script_name =404;

    # default fastcgi_params
    include                       fastcgi_params;

    # fastcgi settings
    fastcgi_index                 index.php;
    fastcgi_buffers               8 16k;
    fastcgi_buffer_size           32k;

    # fastcgi params
    fastcgi_param DOCUMENT_ROOT   $realpath_root;
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    fastcgi_param PHP_ADMIN_VALUE "open_basedir=$base/:/usr/lib/php/:/tmp/";

# Redirect HTTP to HTTPS
server {
    listen      80;
    listen      [::]:80;

    location / {
        return 301$request_uri;

# Disallow direct access to the server's IPv4 and IPv6 addresses
server {
    listen      80 default_server;
    listen      [::]:80 default_server;
    server_name "";
    return 444;

Press Ctrl+O, Enter, and Ctrl+X to save and quit.

Create a symbolic link to enable the configuration file for

$ sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

Test newly created Nginx configurations and restart the Nginx service:

$ sudo nginx -t
$ sudo systemctl restart nginx.service

Point your favorite web browser to to verify URL redirects you setup earlier. If all goes well, it should switch to

Install UVdesk 1.1.0

Use Composer to install dependencies for UVdesk:

$ cd /var/www
$ composer clear-cache
$ composer create-project uvdesk/community-skeleton

During the installation, reply to questions as follows:

WARNING  doctrine/doctrine-bundle (>=2.4): From
Do you want to include Docker configuration from recipes? (defaults to y): y:key_enter:
WARNING  google/recaptcha (>=1.1): From
The recipe for this package comes from the "contrib" repository, which is open to community contributions.
Do you want to execute this recipe? (defaults to n): y:key_enter:

Install the acl utility:

$ sudo apt install acl

Grant permissions on specific directories and files for both the command line user uvdesk and the Nginx user nginx:

$ sudo setfacl -dR -m u:nginx:rwX -m u:uvdesk:rwX /var/www/
$ sudo setfacl -R -m u:nginx:rwX -m u:uvdesk:rwX /var/www/
$ sudo setfacl -dR -m u:nginx:rwX -m u:uvdesk:rwX /var/www/
$ sudo setfacl -R -m u:nginx:rwX -m u:uvdesk:rwX /var/www/
$ sudo setfacl -dR -m u:nginx:rwX -m u:uvdesk:rwX /var/www/
$ sudo setfacl -R -m u:nginx:rwX -m u:uvdesk:rwX /var/www/
$ sudo setfacl -m u:nginx:rwX -m u:uvdesk:rwX /var/www/

Restart the Nginx service:

$ sudo systemctl restart nginx.service

Point your favorite web browser to again to start the UVdesk web installation wizard.

  1. On the Welcome page, click the LET'S BEGIN button.
  2. On the System Requirements page, make sure the system meets all requirements and click the PROCEED button.
  3. On the Database Configuration page, input database user credentials as follows, and click the PROCEED button:
    • Server:
    • Port: 3306
    • Username: uvdesk
    • Password: uv8jTm9LHtez0MKn
    • Database: uvdesk
  4. On the Create Super Admin Account page, input the administrator's credentials and click the PROCEED button:
    • Name: John Doe
    • Email:
    • Password: admin4Est@7sfz8G
    • Confirm Password: admin4Est@7sfz8G
  5. On the Website Configuration page, input member and customer panel prefixes, and click the PROCEED button:
    • Member Panel Prefix: member
    • Customer Panel Prefix: customer
  6. On the last page, click the INSTALL NOW button to begin the installation.

Notice: If the installation fails because of an SQL error "SQLSTATE[42S02]: Base table or view not found: 1146 Table 'uvdesk.uv_support_role' doesn't exist," use commands listed below to fix the problem:

$ cd /var/www/
$ php bin/console doctrine:migrations:diff
$ php bin/console doctrine:migrations:migrate
$ php bin/console c:c
$ sudo shutdown -r now

Then refresh the UVdesk web installation wizard page to perform the installation again.

Next Steps

Having the UVdesk helpdesk system installed, log in as the administrator you created earlier from UVdesk Support Center, and then set up a mailbox to send and receive emails from UVdesk.

More Information