Skip to main content
Version: 12.0

Installing the Server

Overview​

DeskAlerts 12 is delivered for on-premises use as a set of Docker images that run on a Linux host with Docker Compose. The stack contains the DeskAlerts application services, an nginx reverse proxy that publishes them on port 443, and — optionally — Microsoft SQL Server 2022 and RabbitMQ. The package is self-contained: the server needs no access to Docker Hub, npm, or the public internet, so it can be installed on an isolated network.

This page takes a system administrator from a clean Linux server to the first sign-in, one step at a time: each step says what it does and gives the commands to run. The commands are written for Ubuntu Server 24.04 LTS and were run in this order on a clean server. On other distributions only the Docker installation (Step 3) differs.

info

According to DeskAlerts distribution policy, server packages are not published for public download. Request the package for the current version from the DeskAlerts Support team.


Before You Begin​

You needDetails
A Linux serverx86_64, 4 vCPU, 16 GB RAM, and 50 GB SSD at minimum (8 vCPU, 32 GB, 100 GB recommended) — see System Requirements
An account with sudoThe commands run as a regular user; sudo is used where root is required
The server nameThe final host name, for example alerts.company.local, with a DNS record that points to the server
The packagedeskalerts-docker-images-<VERSION>.tar.gz and its SHA-256 checksum from DeskAlerts Support
A TLS certificateFor the server name, in PEM format (fullchain.pem, privkey.pem) — see Step 11
A databaseThe in-stack SQL Server container from the package, or an external SQL Server 2019+ with a login for DeskAlerts
The license fileThe .txt license issued for this server

The examples use version 12.1.0.3 and the server name alerts.company.local. Replace both with your values everywhere on this page. Every command after Step 6 is run from the package folder unless the step says otherwise.


What You Receive​

The package is a tar.gz archive named after the version, for example deskalerts-docker-images-12.1.0.3.tar.gz (about 3 GB). Unpacked, it looks like this:

deskalerts-docker-images-12.1.0.3/
├── README.txt
├── QUICKSTART.txt
├── MANIFEST.txt
├── CHECKSUMS.sha256
├── images/
│ ├── deskalerts-app.tar.gz # all DeskAlerts services
│ ├── mssql-2022.tar.gz # in-stack SQL Server
│ └── rabbitmq-4.1.tar.gz # in-stack RabbitMQ
├── deploy/
│ ├── compose.yml # DeskAlerts services and nginx
│ ├── compose.mssql.yml # overlay: SQL Server 2022 container
│ ├── compose.rabbitmq.yml # overlay: RabbitMQ container
│ └── .env.example # configuration template
├── scripts/
│ ├── import-images.sh # loads the images into Docker
│ ├── init-env.sh # creates deploy/.env and generates the secrets
│ ├── prepare-data-dirs.sh # creates the data folders on the host
│ ├── start.sh / stop.sh # starts and stops the stack
│ └── verify.sh # checks the running stack
└── docs/
└── ON_PREM_DOCKER_DEPLOYMENT_ADMIN.md

MANIFEST.txt lists the version, the images in the package, and whether it contains the in-stack SQL Server and RabbitMQ. The SSO Gateway MSI for Active Directory SSO is delivered separately — see SSO Gateway and Companion.


Step 1. Check the Server​

Confirm the operating system, the number of CPUs, the memory, and the free disk space:

grep PRETTY_NAME /etc/os-release
nproc
free -h
df -h /opt /var/lib

The images take about 14 GB once loaded into Docker, and the archive with its unpacked copy takes another 6 GB during the installation. Keep at least 25 GB free on the file system that holds /opt and /var/lib/docker before you start.


Step 2. Check the Server Name​

The DeskAlerts services call the server by its own URL, so the server name must resolve on the server itself — not only on the workstations:

getent hosts alerts.company.local

The output must show the IP address of this server. If the DNS record does not exist yet, add the name to /etc/hosts until it does:

echo "192.168.10.20 alerts.company.local" | sudo tee -a /etc/hosts

Step 3. Install Docker​

Install Docker Engine with the Docker Compose plugin. Choose the variant that matches your network.

With internet access​

Add the Docker repository and install the packages (the official procedure for Ubuntu):

sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

For other distributions follow the Docker Engine installation guide.

Without internet access​

On a machine with internet access, download these five packages for your Ubuntu release from https://download.docker.com/linux/ubuntu/dists/<codename>/pool/stable/amd64/ (noble for 24.04): containerd.io, docker-ce, docker-ce-cli, docker-buildx-plugin, docker-compose-plugin. Copy them to the server into one folder, for example ~/docker-offline, and install them together:

cd ~/docker-offline
sudo apt-get install -y --no-install-recommends ./*.deb

Important: Keep --no-install-recommends. Without it apt also tries to download the recommended packages (pigz, docker-ce-rootless-extras) from the internet and the whole installation stops with Temporary failure resolving. Docker does not need them.

Start Docker and allow your account to use it​

Enable the Docker service at boot, add your account to the docker group, and apply the group to the current session:

sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
newgrp docker

Check the result:

docker version --format '{{.Server.Version}}'
docker compose version

Both commands must print a version number. If docker version reports permission denied, sign out and sign in again so that the new group membership applies.


Step 4. Limit the Size of the Container Logs​

Docker keeps the console output of every container in a file that grows without limit by default, and the DeskAlerts services write a lot of output. Set a size limit for all containers before the stack is created:

echo '{ "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "5" } }' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker

The limit applies to containers created after the restart. The DeskAlerts file logs are kept separately — see Logs and Diagnostics.

Note: If /etc/docker/daemon.json already exists, add the log-driver and log-opts keys to it instead of overwriting the file.


Step 5. Copy the Package to the Server​

Copy the archive to the server, for example with scp from the computer where you downloaded it:

scp deskalerts-docker-images-12.1.0.3.tar.gz admin@alerts.company.local:/tmp/

On the server, compare the checksum of the archive with the value you received from DeskAlerts Support:

sha256sum /tmp/deskalerts-docker-images-12.1.0.3.tar.gz

Step 6. Unpack the Package​

Create the working folder, move the archive into it, and unpack it:

sudo mkdir -p /opt/deskalerts
sudo chown "$USER":"$USER" /opt/deskalerts
mv /tmp/deskalerts-docker-images-12.1.0.3.tar.gz /opt/deskalerts/
cd /opt/deskalerts
tar -xzf deskalerts-docker-images-12.1.0.3.tar.gz

Go to the package folder and check every file against the list of checksums:

cd /opt/deskalerts/deskalerts-docker-images-12.1.0.3
sha256sum --quiet -c CHECKSUMS.sha256 && echo "All files OK"

The output must end with All files OK. Read MANIFEST.txt to confirm the version and the included images:

cat MANIFEST.txt

Step 7. Load the Docker Images​

Load all images from the images/ folder into Docker:

bash scripts/import-images.sh

The script takes several minutes (about 4.5 minutes on 4 vCPU). Check that every DeskAlerts image carries the version of the package:

docker images --format '{{.Repository}}:{{.Tag}}' | sort

Expected: eleven deskalerts/*:12.1.0.3 images (ai, auth, connection, db-manager, main, nginx, pwa, reports, settings, smtp, workflows), plus alpine:3.20, mcr.microsoft.com/mssql/server:2022-latest, and rabbitmq:4.1-management.

Once the images are loaded, the archive is no longer needed on this server. Keep a copy elsewhere and delete it here to free 3 GB:

rm /opt/deskalerts/deskalerts-docker-images-12.1.0.3.tar.gz

Step 8. Create the Configuration File​

All settings of the stack are in one file, deploy/.env. Create it from the template:

bash scripts/init-env.sh

The script copies deploy/.env.example to deploy/.env, restricts the file to its owner, and generates the secrets that must be unique for every installation: the token-signing keys, the Settings API key, the SSO internal secret, the AI encryption key, and the RabbitMQ password with its connection strings.

Warning: Run init-env.sh only on a new installation, and never with --force-secrets on a server that already has DeskAlerts data. A new AI encryption key makes the stored AI provider keys unreadable, a new SSO secret breaks Active Directory SSO, and a new RabbitMQ password locks the services out of the existing broker.


Step 9. Set the Server URL and the Data Folder​

Go to the deploy folder:

cd /opt/deskalerts/deskalerts-docker-images-12.1.0.3/deploy

Set the public URL of the server. It must be the https:// address users will open, with the host name from the TLS certificate:

sed -i 's|^DESKALERTS_SERVER_URL=.*|DESKALERTS_SERVER_URL=https://alerts.company.local|' .env

Set the host folder for media and uploads. The template contains a Windows path (C:/media) that does not work on Linux:

sed -i 's|^DESKALERTS_MS_MOUNT_FOLDER_SOURCE=.*|DESKALERTS_MS_MOUNT_FOLDER_SOURCE=/opt/deskalerts/data/media|' .env

Step 10. Configure the Database​

Choose one of the two variants.

Variant A: SQL Server in the stack​

The package runs SQL Server 2022 as a container and keeps its data in a folder on the host.

Enter the password for the SQL Server sa account. Use at least 12 characters with upper-case letters, lower-case letters, and digits; avoid symbols, which need quoting in .env. The password is not echoed and does not end up in the shell history:

read -rs -p "SQL Server sa password: " DA_DB_PASS; echo

Write the password to .env in both forms — plain for the SQL Server container and Base64-encoded for the DeskAlerts services:

sed -i "s|^DESKALERTS_DB_PASSWORD_RAW=.*|DESKALERTS_DB_PASSWORD_RAW=${DA_DB_PASS}|" .env
sed -i "s|^DESKALERTS_DB_PASSWORD_64=.*|DESKALERTS_DB_PASSWORD_64=$(printf '%s' "$DA_DB_PASS" | base64 -w0)|" .env
unset DA_DB_PASS

Enable the host folder for the database files (the line is commented out in the template):

sed -i 's|^# *DESKALERTS_DB_MOUNT_FOLDER=.*|DESKALERTS_DB_MOUNT_FOLDER=/opt/deskalerts/data/mssql|' .env

Keep DESKALERTS_DB_SERVER=mssql, DESKALERTS_DB_USER=sa, and DESKALERTS_DB_NAME=DeskAlerts from the template.

Variant B: External SQL Server​

Prepare a SQL Server login for DeskAlerts with SQL Server authentication. The dbcreator server role is enough: the database is created by the installation and the login becomes its owner. The SQL Server must accept connections on port 1433 from this server.

Set the SQL Server host, the login, and the database name:

sed -i 's|^DESKALERTS_DB_SERVER=.*|DESKALERTS_DB_SERVER=sql01.company.local|' .env
sed -i 's|^DESKALERTS_DB_USER=.*|DESKALERTS_DB_USER=deskalerts|' .env
sed -i 's|^DESKALERTS_DB_NAME=.*|DESKALERTS_DB_NAME=DeskAlerts|' .env

Enter the password of the login and write it Base64-encoded:

read -rs -p "SQL login password: " DA_DB_PASS; echo
sed -i "s|^DESKALERTS_DB_PASSWORD_64=.*|DESKALERTS_DB_PASSWORD_64=$(printf '%s' "$DA_DB_PASS" | base64 -w0)|" .env
unset DA_DB_PASS

Comment out the plain password line. It is used only by the in-stack SQL Server, but start.sh refuses to start while it still holds the placeholder from the template:

sed -i 's|^DESKALERTS_DB_PASSWORD_RAW=|# DESKALERTS_DB_PASSWORD_RAW=|' .env

For Azure SQL Database also set DESKALERTS_DB_AZURE_SQL=true.

Check the values​

Print the values you have set, without the passwords:

grep -E '^(DESKALERTS_VERSION|DESKALERTS_SERVER_URL|DESKALERTS_DB_SERVER|DESKALERTS_DB_USER|DESKALERTS_DB_NAME|DESKALERTS_DB_MOUNT_FOLDER|DESKALERTS_MS_MOUNT_FOLDER_SOURCE|DESKALERTS_DB_DROP_DATABASE)=' .env

DESKALERTS_DB_DROP_DATABASE must stay false. The optional settings — SMTP, Active Directory SSO — can be added to .env now or later; see Optional Settings in .env.


Step 11. Install the TLS Certificate​

Without a certificate of its own, nginx generates a self-signed certificate on start. That is enough to open the portal for a test, but agents and browsers will not trust it. For production, install a certificate for the server name from your corporate CA or Let's Encrypt.

Create the certificate folders on the host:

sudo mkdir -p /opt/deskalerts/ssl/live/alerts.company.local /opt/deskalerts/ssl/archive/alerts.company.local

Copy the certificate with its intermediate chain as fullchain.pem and the unencrypted private key as privkey.pem into the live folder and protect the key:

sudo cp fullchain.pem privkey.pem /opt/deskalerts/ssl/live/alerts.company.local/
sudo chmod 600 /opt/deskalerts/ssl/live/alerts.company.local/privkey.pem

A certificate exported from Windows as a .pfx file is converted to these two files with OpenSSL — see HTTPS and Certificates.

Open deploy/compose.yml:

nano /opt/deskalerts/deskalerts-docker-images-12.1.0.3/deploy/compose.yml

Find the nginx: service and add a volumes: section directly above its ports: line, with the same indentation as ports::

volumes:
- type: bind
source: /opt/deskalerts/ssl/live/alerts.company.local
target: /opt/letsencrypt/live/alerts.company.local
- type: bind
source: /opt/deskalerts/ssl/archive/alerts.company.local
target: /opt/letsencrypt/archive/alerts.company.local
ports:
- "443:443"

Save a copy of the edited file next to the certificates:

cp /opt/deskalerts/deskalerts-docker-images-12.1.0.3/deploy/compose.yml /opt/deskalerts/ssl/compose.yml.custom

Important: An update brings a new compose.yml without this section. Add it again in every new package folder before the first start — otherwise nginx silently falls back to a self-signed certificate and the agents stop connecting.


Step 12. Create the Data Folders​

Create the folders for media, uploads, directory-synchronization logs, and the in-stack database, with the owners the containers expect:

cd /opt/deskalerts/deskalerts-docker-images-12.1.0.3
bash scripts/prepare-data-dirs.sh

The script reads the paths from deploy/.env and stops with a clear message if a path is still the Windows path from the template.


Step 13. Start the Stack​

Start the stack with the overlays your deployment uses:

In-stack SQL Server and RabbitMQ (Variant A):

bash scripts/start.sh --mssql --rabbitmq

External SQL Server and in-stack RabbitMQ (Variant B):

bash scripts/start.sh --rabbitmq

start.sh checks that all images are loaded, writes the chosen overlays to deploy/.env (COMPOSE_FILE), and starts the containers in a fixed order:

  1. logs-init prepares the shared log volume and db-manager creates or upgrades the database; both exit with code 0.
  2. main, auth, connection, workflows, settings, smtp, reports, and ai start after both have finished.
  3. nginx starts when the services it proxies are healthy.

The first start takes from under a minute to several minutes, depending on the hardware and the database. The script ends with Stack is up.

Later start.sh, stop.sh, and verify.sh calls need no flags: they reuse the overlays saved in .env. Pass the flags again only to change the set of overlays.


Step 14. Verify the Installation​

Run the check script:

bash scripts/verify.sh

The script lists the containers and checks the login page, /auth/health, and /api/health. Expected result:

OK https://alerts.company.local/
OK https://alerts.company.local/auth/health
OK https://alerts.company.local/api/health

✅ Verification passed. Open https://alerts.company.local/ and change the admin password.

In the container list, db-manager and logs-init must have exited with code 0, and every other container must be Up … (healthy). Confirm that the database step succeeded:

docker logs deskalerts-db-manager-1 2>&1 | tail -3

The last line must be Database setup completed successfully!.

Check which certificate nginx uses:

docker logs deskalerts-nginx-1 2>&1 | grep -E 'Using SSL|self-signed'

With your certificate installed the output names /opt/letsencrypt/live/alerts.company.local/fullchain.pem. A line about a self-signed certificate means the mount from Step 11 is missing or the files are not named fullchain.pem and privkey.pem.


Step 15. Restrict Network Access​

Users and agents need only TCP 443. The stack also publishes, on all interfaces of the server, the ports of the individual services (40004–40012) and — with the in-stack database — SQL Server on 1433. List them:

sudo ss -ltnp | grep docker-proxy

Allow only port 443 to this server in the network firewall in front of it. Docker inserts its own firewall rules for published ports, so a host firewall such as ufw does not block them.


Step 16. Sign In and Change the Administrator Password​

Open https://alerts.company.local/ in a browser on a workstation. The login page shows the version in its top-right corner.

Login page of a new server

Sign in with the built-in account admin and the password admin. The portal opens the Dashboard without asking for a new password, so change it yourself right away:

  1. Click admin at the bottom of the left menu and choose Profile settings.
  2. In the Security section, click Change password. Enter admin in Current password, the new strong password in New password and Confirm new password, and click Update password.
  3. Sign out and sign in again with the new password. Store it safely.

The Change password dialog of Profile settings

Until the license is uploaded the left menu shows only some sections (Dashboard, Create alert, Alerts, Audience explorer, Shared assets, Settings); the others appear with the licensed modules. The password policy for all portal accounts is set under Settings → Users & access → Web-portal password policy.

Note: A browser that still holds a session for the same URL from an earlier installation can show the portal shell without a sign-in; the server refuses its requests. Sign out, or clear the site data in the browser, after reinstalling a server.


Step 17. Upload the License​

  1. Open Settings → License.
  2. Scroll down to Activate new license and drag the .txt license file onto the upload area, or click Browse files and select it.

The Activate new license area at the bottom of Settings → License

  1. Check the License summary at the top of the page: the status must be Active, with your organization name, the number of web-portal users and recipients, and the expiration date. The licensed modules are listed below the summary.

License summary of an activated server

If the portal shows Failed to apply license, reload the page and check the License summary before you upload the file again: in version 12.1.0.3 the message can appear although the license was applied.


Step 18. Check Automatic Start After a Reboot​

The containers come back with the Docker service. Make sure it is enabled at boot and test a reboot before the server goes into production:

systemctl is-enabled docker
sudo reboot

After the server is back, wait one or two minutes and run the check again:

cd /opt/deskalerts/deskalerts-docker-images-12.1.0.3
bash scripts/verify.sh

A few services may restart once while SQL Server is still starting; the result counts only when verify.sh passes.


Step 19. Back Up the Configuration​

deploy/.env holds the generated secrets that the database depends on. Without it the installation cannot be updated or restored with the existing data. Copy it, together with the customized compose.yml, to a protected location outside the server:

mkdir -p ~/deskalerts-config
cp /opt/deskalerts/deskalerts-docker-images-12.1.0.3/deploy/.env ~/deskalerts-config/env-12.1.0.3
cp /opt/deskalerts/deskalerts-docker-images-12.1.0.3/deploy/compose.yml ~/deskalerts-config/compose-12.1.0.3.yml
chmod 600 ~/deskalerts-config/*

Then set up regular backups of the database and the media folder — see Database and Backup.


Optional Settings in .env​

Edit deploy/.env with nano and restart the stack with bash scripts/start.sh to apply a change.

SMTP​

DESKALERTS_SMTP_SERVER=smtp.company.local
DESKALERTS_SMTP_PORT=587
DESKALERTS_SMTP_SSL=true
DESKALERTS_SMTP_AUTH=true
DESKALERTS_SMTP_USER=alerts@company.local
DESKALERTS_SMTP_PASSWORD=...

The SMTP server can also be set later in the portal under Settings → Delivery channels → SMTP server (emails) — see Auxiliary Delivery Channels.

Active Directory SSO​

  1. Install the SSO Gateway MSI on a domain-joined Windows Server (see SSO Gateway and Companion).
  2. Point the stack at the gateway:
DESKALERTS_SSO_GATEWAY_URL=http://<sso-host>:58009
  1. Enter the value of DESKALERTS_SSO_INTERNAL_SECRET from .env as the Internal secret (INTERNAL_SECRET) of the gateway MSI. Both must be identical.

AI features​

AI features are not configured in .env. After the installation, open Settings → Integrations → AI integrations, turn the feature on, and enter the provider key. The server needs outbound HTTPS to the provider; on an isolated network leave AI off — the rest of the product works without it. See AI Providers.


Troubleshooting the Installation​

SymptomLikely causeAction
apt-get install ./*.deb stops with Temporary failure resolvingapt tries to download recommended packagesAdd --no-install-recommends (Step 3)
prepare-data-dirs.sh refuses C:/mediaThe media path from the template was not changedSet DESKALERTS_MS_MOUNT_FOLDER_SOURCE (Step 9)
start.sh: DESKALERTS_DB_PASSWORD_64 / _RAW still hold the .env.example placeholderA password line still has the template value; with an external SQL Server, usually DESKALERTS_DB_PASSWORD_RAWSet the passwords, or comment out DESKALERTS_DB_PASSWORD_RAW for an external SQL Server (Step 10)
start.sh: DESKALERTS_VERSION / DESKALERTS_DB_VERSION does not match the package.env was copied from another versionSet both to the values in deploy/.env.example of this package
db-manager exited with a non-zero codeWrong database password, SQL Server unreachable, or the login cannot create the databasedocker logs deskalerts-db-manager-1; check the DESKALERTS_DB_* values and port 1433
pull access denied or Compose tries to download an imageAn image is not loaded (often a full disk during the import)Free disk space and run bash scripts/import-images.sh again
/api/health returns DegradedThe services cannot log in to RabbitMQ — the password in .env differs from the existing broker volumeRestore the .env the broker was created with
502 from nginxA service is still startingWait for the health checks; docker ps
Browser or agent rejects the certificatenginx uses the self-signed certificateStep 11; check with docker logs deskalerts-nginx-1 (Step 14)
Failed to apply licenseKnown message in 12.1.0.3; the license is often applied anywayReload Settings → License and check the summary (Step 17)

/api/health reports the state of the services, not of the database: it can show Healthy while SQL Server is unreachable. When the portal misbehaves, check the database container or server directly. More symptoms and fixes are listed in Services and Health.


Initial Configuration in the Portal​

StepWhere
Connect the directory and import the audienceSettings → Users & access → IAM sync (AD/EntraID) — see Users & Access
Decide which devices may registerSettings → Users & access → Audience access level — see Audience and Identity
Configure SSO for administratorsSettings → Users & access → SSO settings — for Active Directory SSO see SSO Gateway and Companion
Configure email, SMS, TeamsSettings → Delivery channels — see Auxiliary Delivery Channels
Create web-portal roles and usersSettings → Users & access → Web-portal roles, Web-portal users
Set defaults for new alertsSettings → Alerts → New popup and ticker defaults
Install the first agentsThe Desktop agent section

  • docs/ON_PREM_DOCKER_DEPLOYMENT_ADMIN.md — the deployment guide shipped in the package
  • Preparing the Server, HTTPS and Certificates
  • Updating the Server, Database and Backup, Logs and Diagnostics