Deploy on an Azure Linux VM#
This page takes you from an empty Azure subscription to a working Reportworq server reachable over HTTPS at your own web address. Every step is a command you can copy and paste, and every command is explained, so you do not need prior Linux experience to follow it.
Allow about 45 minutes, most of which is waiting for downloads.
If you have not chosen a deployment shape yet, read Deployment topology first. This page covers the Linux tarball on a virtual machine you control. It is the right choice when you want to decide for yourself when the Reportworq version changes, and when you want to import a Reportworq 5 repository, neither of which the container deployment offers.
What you will build#
A single Linux virtual machine running two pieces of software:
- Reportworq, listening on port 8080 on the machine's internal loopback address only, so it is never reachable directly from the internet.
- Caddy, a small web server that sits in front of Reportworq. It obtains and renews a free, publicly trusted TLS certificate automatically, accepts HTTPS traffic on port 443, and passes each request through to Reportworq.
Alongside the machine you will attach a separate data disk, mounted at /var/lib/reportworq, which holds the Reportworq repository. The repository is the only durable state in the whole deployment, so keeping it on its own disk is what makes backup, restore and rebuild straightforward.
Only three ports are open to the internet: 22 for your own administrative access, 80 so the certificate can be issued and so browsers are redirected, and 443 for users.
Before you start#
- An Azure subscription, and permission to create a resource group, a virtual network, a public IP address and a virtual machine.
- The Azure CLI installed and signed in. Run
az login, thenaz account set --subscription <your-subscription-id>. - Your Reportworq license key.
- A web address you can point at the server. The steps below create a free Azure address of the form
<label>.<region>.cloudapp.azure.com, which is enough to obtain a certificate. If you would rather use your own domain, see Use your own domain name. - An SSH key pair. If you do not have one, run
ssh-keygen -t ed25519and accept the defaults.
HTTPS is not optional in practice. The Excel add-in and every Microsoft 365 feature, including Entra sign-in, SharePoint, Microsoft 365 email and Teams distribution, require it, and over plain HTTP they fail quietly. Unlike a fresh Windows install, a Linux server does not create a certificate for itself, so setting up HTTPS is a step in this runbook rather than an afterthought.
Step 1: Choose your settings#
Run these lines in your local terminal. Everything that follows reuses them, so set them once and keep the terminal window open.
RG=rg-reportworq
LOC=eastus2
VM=vm-reportworq-01
DNSLABEL=contoso-reportworq
ADMIN=rwadmin
MYIP=$(curl -s https://ifconfig.me)
What each one is:
| Setting | What it means |
|---|---|
RG |
The resource group name. A resource group is a folder that holds everything you create here, so deleting it removes the whole deployment. |
LOC |
The Azure region. Choose the one closest to your users and to your data sources. |
VM |
The name of the virtual machine. Choose this deliberately and do not change it later, see the note on license activation. |
DNSLABEL |
The first part of the free Azure web address. This example produces contoso-reportworq.eastus2.cloudapp.azure.com. It must be unique within the region. |
ADMIN |
The administrative user name you will use to sign in to the server over SSH. |
MYIP |
Your current public IP address, looked up automatically. It is used to restrict SSH access to you. |
Step 2: Create the resource group and the firewall rules#
An Azure network security group is the firewall in front of the machine. Create it with exactly three inbound rules.
az group create -n "$RG" -l "$LOC"
az network nsg create -g "$RG" -n nsg-reportworq
az network nsg rule create -g "$RG" --nsg-name nsg-reportworq -n allow-ssh \
--priority 100 --access Allow --protocol Tcp --direction Inbound \
--source-address-prefixes "$MYIP" --destination-port-ranges 22
az network nsg rule create -g "$RG" --nsg-name nsg-reportworq -n allow-http \
--priority 110 --access Allow --protocol Tcp --direction Inbound \
--source-address-prefixes Internet --destination-port-ranges 80
az network nsg rule create -g "$RG" --nsg-name nsg-reportworq -n allow-https \
--priority 120 --access Allow --protocol Tcp --direction Inbound \
--source-address-prefixes Internet --destination-port-ranges 443
- Port 22 is administrative access. It is limited to your own IP address. If your IP address changes, update the rule. Organizations that prefer not to expose SSH at all can use Azure Bastion instead and skip this rule.
- Port 80 is needed twice: once so the certificate authority can verify that you control the address, and afterwards so that anyone typing
http://is redirected tohttps://. - Port 443 is the only port your users need. If your users all come from known office networks, narrow
--source-address-prefixesto those ranges.
Do not open ports 8080 or 8081. Port 8080 is Reportworq itself, which is reached through the proxy on the machine's internal address. Port 8081 is the Real-time Event Hub, and on a single server it is an internal endpoint that never leaves the machine. The guidance elsewhere to open both ports applies to a multi-server cluster, where worker nodes contact the web server across the network, and not to a single machine, see Deployment topology.
Step 3: Create the virtual machine and its data disk#
The published requirement is 4 cores, 32 GB of RAM and 10 GB of disk, plus roughly 2 GB of RAM for each job that runs at the same time. Reportworq runs 4 jobs at once by default. Size against your busiest moment, not your average, because peak memory tracks the number of jobs in flight, see System requirements.
| Workload | Virtual machine size | Cores and memory |
|---|---|---|
| Pilot or trial | Standard_D4ds_v5 |
4 cores, 16 GB. Below the stated minimum. Fine to prove the install, not a production footprint. |
| Production baseline | Standard_E4ads_v7 |
4 cores, 32 GB. Meets the published minimum. |
| Higher concurrency | Standard_E8ads_v7 |
8 cores, 64 GB. Choose this when you raise parallel job execution above about 8. |
| Large workbooks, heavy Excel | Standard_E16ads_v7 |
16 cores, 128 GB. |
Choose a size whose name contains a d, such as E4ads_v7. Those sizes include a fast local temporary disk that Reportworq uses as scratch space while rendering, at no extra cost. No graphics card and no display adapter is required.
az vm create -g "$RG" -n "$VM" \
--image Ubuntu2404 \
--size Standard_E4ads_v7 \
--admin-username "$ADMIN" \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--public-ip-address-dns-name "$DNSLABEL" \
--public-ip-sku Standard \
--nsg nsg-reportworq \
--os-disk-size-gb 128 \
--os-disk-delete-option Delete
Then attach the data disk that will hold the repository:
az vm disk attach -g "$RG" --vm-name "$VM" -n disk-reportworq-repo \
--new --size-gb 512 --sku Premium_LRS --lun 0
Why a separate managed disk, and not Azure Files. Parts of the Reportworq repository are SQLite databases, which hold job execution history, write-back history, and the audit logs. SQLite needs reliable file locking, which a network file share emulates imperfectly, and a fast, low-latency disk, because job execution writes many small files. A managed disk gives you both, and its snapshots are instant, which makes them your backup and your upgrade rollback. A file share is the right answer only when several machines must share one repository, which means a load-balanced cluster.
512 GB is a comfortable production start. The repository grows with your content, run history, generated output and logs. You can grow a managed disk later without recreating it.
Now connect to the server. Every command from here to Step 11 runs on the server, not on your local machine.
ssh "$ADMIN@${DNSLABEL}.${LOC}.cloudapp.azure.com"
Step 4: Prepare the data disk#
A new Azure disk arrives blank. These commands give it a filesystem and attach it to the folder Reportworq will use. Do this before installing Reportworq, so the repository lands on the disk from the start and nothing has to be moved later.
sudo apt-get update
sudo apt-get install -y parted xfsprogs
DEV=/dev/disk/azure/scsi1/lun0
sudo parted "$DEV" --script mklabel gpt mkpart primary xfs 0% 100%
sudo partprobe "$DEV"
sudo mkfs.xfs "${DEV}-part1"
sudo mkdir -p /var/lib/reportworq
UUID=$(sudo blkid -s UUID -o value "${DEV}-part1")
echo "UUID=$UUID /var/lib/reportworq xfs defaults,nofail 0 2" | sudo tee -a /etc/fstab
sudo mount -a
df -h /var/lib/reportworq
The last command should report a filesystem of roughly 512 GB mounted on /var/lib/reportworq. If it does not, stop and resolve that before continuing.
Two details in the /etc/fstab line matter more than they look:
- The disk is identified by its UUID, a permanent identifier, rather than by a name such as
/dev/sdc. Azure does not guarantee those names stay the same across restarts and resizes. nofailtells the server to start even if the disk is missing. Without it, a disk problem stops the machine from starting at all, and you cannot connect to fix it.
Step 5: Install the operating system prerequisites#
Reportworq ships with everything it needs to run except three things the operating system must provide.
sudo apt-get install -y \
libicu-dev \
fontconfig libfontconfig1 libfreetype6 libgomp1 \
fonts-liberation fonts-dejavu-core fonts-noto-core
| What | Why it is required |
|---|---|
libicu-dev |
International text support. Without it Reportworq stops immediately at startup with the message "Couldn't find a valid ICU package installed on the system." |
fontconfig, libfontconfig1, libfreetype6, libgomp1 |
The graphics libraries used to render images and charts into Excel, PDF and PowerPoint output. |
| The font packages | Not optional. A new Linux server has almost no fonts installed, and report output renders blank or as rows of boxes without them. |
If your reports must look identical to output produced on Windows, install your organization's own fonts here as well. You can also manage fonts as workspace files instead, see Server configuration.
Step 6: Download and install Reportworq#
First, see which versions are available. This command lists every published version and the files each one contains:
curl -s https://quelock.reportworq.com/details/all/RW6
Then download and install the one you want. Replace 6.0.1.1 with your chosen version and AAA-BBB-CCC-DDD with your license key.
RWVER=6.0.1.1
cd /tmp
curl -fL -o "reportworq-${RWVER}-linux-x64.tar.gz" \
"https://quelock.reportworq.com/download/all/RW6/${RWVER}/reportworq-${RWVER}-linux-x64.tar.gz?licenseKey=AAA-BBB-CCC-DDD"
tar -xzf "reportworq-${RWVER}-linux-x64.tar.gz"
cd "reportworq-${RWVER}-linux-x64"
sudo ./install.sh
The download is about 485 MB. Make sure you take the file ending in -linux-x64.tar.gz. Each release also publishes a container image whose name ends in .tar.gz, and the two are not interchangeable.
The installer is safe to run more than once, which is also how you upgrade later. It creates a restricted reportworq user account for the service to run under, and lays out these locations:
| What | Where |
|---|---|
| Program files | /opt/reportworq/lib/app |
| Repository, your only durable data | /var/lib/reportworq/repository, on the disk you mounted |
| Logs | /var/log/reportworq |
| Configuration | /etc/reportworq/reportworq.env |
A first install deliberately leaves Reportworq stopped, so that you can set the configuration before it starts for the first time. That is the next step.
Step 7: Configure and start Reportworq#
Open the configuration file:
sudo nano /etc/reportworq/reportworq.env
Make it read as follows. nano is a simple text editor: edit the text, then press Ctrl+O and Enter to save, and Ctrl+X to exit.
RW_PORT=8080
RW_REPOSITORY_PATH=/var/lib/reportworq/repository
RW_BEHIND_REVERSE_PROXY=true
RW_BEHIND_REVERSE_PROXY=true is the line people most often miss, and leaving it out causes failures that are hard to diagnose. It tells Reportworq that something in front of it is handling HTTPS, so that the web addresses Reportworq generates for itself, including Microsoft sign-in redirects and Excel add-in callbacks, begin with https:// rather than http://. Without it those integrations break while everything else appears to work.
Keep this setting in the file. It is read at each startup and is not written into Reportworq's own settings, so removing the line reverts the behavior the next time the service restarts.
Now start Reportworq and check it came up:
sudo systemctl start reportworq
systemctl status reportworq
curl -I http://localhost:8080
systemctl status should report active (running), and the curl command should return a response from the web server rather than a connection error. To watch the startup messages in detail, run journalctl -u reportworq -f and press Ctrl+C to stop watching.
Step 8: Install Caddy#
Caddy is the web server that will handle HTTPS. Install it from its official package repository:
sudo apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt-get update && sudo apt-get install -y caddy
Step 9: Configure HTTPS#
Edit Caddy's configuration file:
sudo nano /etc/caddy/Caddyfile
Replace its entire contents with the following, changing the first line to your own web address:
contoso-reportworq.eastus2.cloudapp.azure.com {
encode zstd gzip
reverse_proxy 127.0.0.1:8080 {
transport http {
read_timeout 30m
write_timeout 30m
}
}
request_body {
max_size 512MB
}
}
What each part does:
| Line | Purpose |
|---|---|
| The web address on the first line | Tells Caddy which address to serve, and which address to request a certificate for. |
encode zstd gzip |
Compresses responses, which makes the interface noticeably faster over slow links. |
reverse_proxy 127.0.0.1:8080 |
Passes each request through to Reportworq on the machine's internal address. |
read_timeout and write_timeout |
The Reportworq interface and the Excel add-in hold long-lived connections. The default timeouts are short enough to cut them. |
request_body max_size |
Source workbooks and report output can be large. The default limit is too small for them. |
The first line must be your web address, never an IP address. This is the single most common way to get this step wrong. An IP address cannot legally be used in the part of the TLS handshake that tells the server which site is being requested, so a configuration keyed on an IP address matches nothing on port 443 and the browser gets a failed connection, while port 80 still redirects into it. Caddy also quietly issues itself an untrusted certificate for an IP address instead of requesting a real one.
Check the configuration, then apply it:
caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
Caddy now contacts a certificate authority, proves it controls the address over port 80, and installs the certificate. This normally takes a few seconds. Confirm it worked from your own machine, not from the server:
curl -I https://contoso-reportworq.eastus2.cloudapp.azure.com
A 200 response means HTTPS is working. If it fails, see Troubleshooting.
From here on, Caddy renews the certificate automatically before it expires, and redirects anyone who arrives over plain HTTP.
Use your own domain name#
To serve Reportworq at an address in your own domain, such as reportworq.contoso.com, create a DNS A record for that name in your DNS provider pointing at the machine's public IP address. Find the IP address with:
az vm show -g "$RG" -n "$VM" -d --query publicIps -o tsv
Wait until the name resolves, then put that name on the first line of the Caddyfile instead of the Azure address and reload Caddy. Because the certificate is issued against whatever name the Caddyfile carries, it is worth getting the final address right before you hand the server to users.
Step 10: Check what you built#
From your own machine:
curl -sI https://contoso-reportworq.eastus2.cloudapp.azure.com | head -5
curl -sI http://contoso-reportworq.eastus2.cloudapp.azure.com | head -5
The first should return HTTP/1.1 200 OK. The second should return 308 Permanent Redirect to the https:// address, which is Caddy sending plain HTTP visitors to the secure address.
Step 11: Finish setup and activate the license#
Browse to your address. An empty repository opens the first-run wizard: Welcome, Repository, License, Users, Finish. See First-run setup for the wizard in detail.
- Repository. Already correct at
/var/lib/reportworq/repository. This step is also where a server joins an existing cluster, using Add a load balancer to an existing web app. - License. Enter your key and activate. Online activation needs outbound HTTPS from the server to the licensing service, and each activation uses one seat. If outbound access is restricted, use Manual activation, which gives you a request code to exchange on an internet-connected machine, see Install Reportworq.
- Users. Create the first administrator account.
To confirm the reverse proxy is configured correctly, open Settings > Configuration > Web Server after signing in. The SSL Certificate switch shows as on and cannot be changed, with the text "HTTPS is terminated by the reverse proxy - no certificate is configured on this instance." That message is confirmation that RW_BEHIND_REVERSE_PROXY took effect.
Outbound access the server needs: the licensing service and version downloads at quelock.reportworq.com; Microsoft Graph and Microsoft sign-in for Microsoft 365 distribution and Entra sign-in; your mail server for email distribution; and your own IBM Planning Analytics, database and other data source endpoints. Add these to your outbound rules if your network denies outbound traffic by default.
One caution specific to virtual machines. License activation is tied to the machine name. Resizing, stopping, deallocating and restarting the machine are all safe, because the name does not change. Rebuilding the machine under a different name invalidates the activation. Release the license seat before you decommission a server, and keep the same name if you rebuild one.
Day-to-day operations#
systemctl status reportworq
sudo systemctl restart reportworq
journalctl -u reportworq -f
sudo tail -f /var/log/reportworq/*.log
For Caddy, the equivalents are sudo systemctl reload caddy to apply a configuration change without dropping connections, and journalctl -u caddy -f to watch its log.
- Concurrency. Settings > Configuration > Performance > Execution > Parallel Job Execution accepts 1 to 50 and defaults to 4. This is the setting that keeps peak memory predictable, so allow about 2 GB of RAM for each concurrent job and raise it only alongside memory, see Server configuration.
- Resizing the machine. Deallocate it, run
az vm resize, then start it. The data disk and the machine name survive, so the license does too. - Growing the data disk. Run
az disk update --size-gb <new size>, restart the machine, then runsudo xfs_growfs /var/lib/reportworq. - Retention. Run history, logs and generated output grow steadily. Configure retention rather than waiting for the disk to fill, see Retention.
Upgrading#
Two paths work on Linux, and both preserve your repository, logs and configuration. Take a disk snapshot before either one:
az snapshot create -g "$RG" -n snap-repo-$(date +%Y%m%d-%H%M) \
--source disk-reportworq-repo
In the product, at Settings > Update Reportworq, is the normal path. Pick a version and Reportworq downloads it, installs it alongside the current one, backs up the repository and restarts into it. For a server without internet access, Update from a patch file accepts a tarball you supply. See Update Reportworq.
From the tarball is the right choice when you want the exact files in your hands, for example for a server without internet access or a scripted rollout across several machines. Repeat Step 6 with the new version number. The installer stops the service, replaces the program files and starts it again.
Two things to know before you upgrade:
- The in-product backup is not a substitute for a snapshot. Reportworq's own backup is written inside the repository, so it protects you against a bad upgrade but not against losing the disk. The snapshot is what protects the disk.
- Read the release notes for repository changes. An upgrade can change the repository in ways that make going back to an earlier version unsafe. If you need to downgrade, contact Reportworq support rather than reverting the files and hoping.
If a newly installed version will not start, remove it and restart. Reportworq automatically falls back to the previous version, and then to the originally installed one, so a failed upgrade cannot leave the server unable to start:
sudo rm -rf /opt/reportworq/Versions/v<version>
sudo systemctl restart reportworq
Each installed version is a full copy of the application, about 1 GB, and they are stored on the operating system disk rather than the data disk. Remove versions you no longer need from the Update Reportworq screen.
Backups#
| What | How | How often |
|---|---|---|
| The repository, your only durable data | Azure Backup on the machine, or a snapshot policy on the data disk | Daily, and before every upgrade |
Startup settings, /opt/reportworq/settings.json |
Include the operating system disk in the backup, or copy the file aside | When it changes |
Service configuration, /etc/reportworq/reportworq.env |
The same | When it changes |
| Reportworq's own backup | Settings > Configuration > Web Server > Backup | Before upgrades, remembering it lives inside the repository |
Everything that matters is on the data disk. Rebuilding a server is: create a new machine, install the prerequisites, install the tarball, attach the restored disk at /var/lib/reportworq, keep the same machine name, and start.
Troubleshooting#
| Symptom | Cause | What to do |
|---|---|---|
| Reports render blank or as boxes | No fonts installed | Install the font packages from Step 5 and restart Reportworq |
| Reportworq stops immediately, log says "Couldn't find a valid ICU package" | libicu-dev missing |
sudo apt-get install -y libicu-dev |
The browser cannot connect over HTTPS, but http:// redirects to it |
The Caddyfile names an IP address instead of a web address | Put the web address on the first line and reload Caddy. Check certificate activity with journalctl -u caddy | grep acme |
| The certificate is never issued | Port 80 is closed, or the address does not resolve to this machine | Confirm the allow-http rule exists, and that the address resolves to the machine's public IP |
| The Excel add-in or Microsoft 365 sign-in fails silently | RW_BEHIND_REVERSE_PROXY is not set, so Reportworq builds http:// addresses |
Add it to /etc/reportworq/reportworq.env and restart Reportworq |
| A tarball upgrade appears to do nothing | A version installed in the product outranks the one you unpacked | Re-run install.sh, which clears them |
| The operating system disk is filling up | Each installed version is about 1 GB | Remove old versions from the Update Reportworq screen |
| The license is invalid after a rebuild | Activation is tied to the machine name | Keep the machine name, and release the seat before decommissioning |
| The machine will not start after a disk change | An /etc/fstab entry without nofail |
Mount by UUID with nofail, as in Step 4 |
| Jobs cannot reach a network file share | Reportworq runs as the restricted reportworq user |
Mount the share with a user and group matching that account |
Notes and limits#
- This runbook builds a single server. To add throughput you add worker servers against the same repository rather than more web servers, at which point the repository must move to a share every server can reach. See Deployment topology.
- Linux is at feature parity with Windows. The only difference worth remembering is the default port: 8080 on Linux, 8600 on Windows.
- If your organization requires encryption all the way to the application, with no unencrypted traffic even inside the machine, you can give Reportworq the certificate directly instead of using Caddy, see Server configuration. That path makes certificate renewal your responsibility, so the proxy is the lower-maintenance choice.
Going deeper. For the choice between Windows, Linux and containers, see Deployment topology. For the sizing figures behind Step 3, see System requirements. For the license model and how seats are counted, see Licensing and entitlements. For moving an existing instance onto this server, see Migrate to a new server.
Feedback on this page
Comments, questions, requests, or something missing or unclear? Email us - the page you are on is filled in for you.
Email feedback on this pageOr write to support@reportworq.com directly.