Deployment guide

FreeScout

Videos

Overview: FreeScout on Ubuntu 24.04 on Azure: overview (watch on YouTube)

Launch and log in: FreeScout on Ubuntu 24.04 on Azure: launch and log in (watch on YouTube)

Deep Dive: FreeScout on Ubuntu 24.04 on Azure: deep dive (watch on YouTube)

Overview

FreeScout is a free, open source, self-hosted help desk and shared mailbox. It is a lightweight alternative to Zendesk and Help Scout. It turns incoming email into a shared inbox of conversations that your team can assign, reply to and work on together with internal notes, saved replies and tags. You can extend it with modules.

The SecureAnyCloud image delivers FreeScout fully installed and configured on Ubuntu 24.04. It is a Laravel application on PHP 8.3 with OPcache, served by nginx over HTTPS with php-fpm and backed by MariaDB. The database schema is already migrated and the admin account already exists, so you land directly on the sign-in page with nothing to configure.

FreeScout is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). The complete, unmodified upstream source is shipped on the image under /var/www/freescout. SecureAnyCloud is not affiliated with, endorsed by, or sponsored by the FreeScout project, and "FreeScout" is a trademark of its respective owner. This image repackages the upstream open source release with SecureAnyCloud's provisioning and support.

What you get:

  • FreeScout 1.8.230 (AGPL-3.0), served from /var/www/freescout/public
  • nginx (TLS on :443, with :80 redirected to HTTPS and a plain /healthz liveness endpoint), PHP 8.3 (php8.3-fpm with OPcache, including the imap extension for mailbox fetching) and MariaDB, all from Ubuntu 24.04 main/universe
  • A per-VM self-signed TLS certificate generated on first boot, so the interface loads in a secure context
  • Per-VM administrator password, MariaDB password and Laravel APP_KEY, all generated at first boot and written to a root-only file. No default or shared login ships in the image.
  • The Laravel scheduler, which runs every minute through a systemd timer and drives background jobs and email fetching
  • nginx.service, php8.3-fpm.service and mariadb.service as systemd units, enabled and active
  • 24/7 SecureAnyCloud support

Prerequisites

Before you deploy, make sure you have:

  • An active Azure subscription
  • An SSH key pair
  • A VNet and subnet in the target region
  • NSG inbound rules that allow 22/tcp from your management network, and 443/tcp (HTTPS) plus 80/tcp (which redirects to HTTPS) from your users

Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point. Scale up for larger teams or heavier mail volume.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for FreeScout by SecureAnyCloud, and select Create.

On Basics, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTPS (443). Then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:freescout-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name freescout \
  --image sac1647283583153:freescout-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Open HTTPS, and HTTP (which redirects), to reach the web interface:

az vm open-port --resource-group <your-rg> --name freescout --port 443 --priority 900
az vm open-port --resource-group <your-rg> --name freescout --port 80 --priority 910

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

Confirm that the three services behind FreeScout all report active. The plain HTTP port answers a lightweight /healthz liveness check and redirects everything else to HTTPS. The interface answers over TLS.

systemctl is-active nginx php8.3-fpm mariadb curl -s -o /dev/null -w 'healthz -> %{http_code}\n' http://127.0.0.1/healthz curl -s -o /dev/null -w 'http redirect -> %{http_code}\n' http://127.0.0.1/ curl -ks -o /dev/null -w 'https app -> %{http_code}\n' https://127.0.0.1/login

Expected: three lines of active, then healthz -> 200, http redirect -> 301 and https app -> 200 (the FreeScout sign-in page over TLS).

Step 5 - Retrieve your administrator password

On the first boot of every VM, a one-shot service (freescout-firstboot.service) generates credentials that are unique to that VM. These are a fresh Laravel application key, a fresh MariaDB password and a fresh administrator password. The service also generates a per-VM self-signed TLS certificate and sets the VM's own address as the application URL. No shared or default credentials ship in the image.

sudo cat /root/freescout-credentials.txt

The file (mode 0600, root only) contains the administrator email (freescout.admin.user, which is admin@sac.local), the administrator password (freescout.admin.pass), the sign-in URL and the database credentials. FreeScout signs in by email address. After you sign in, change the admin email to your own from Manage -> Users.

You can prove the login round trip from the VM's own shell. The commands read the per-VM credentials, fetch a CSRF token and post a real sign-in. A successful FreeScout login answers HTTP 302 away from the login page. The commands also confirm that a wrong password is rejected back to the login page:

USER=$(sudo grep '^freescout.admin.user=' /root/freescout-credentials.txt | cut -d= -f2-)
PASS=$(sudo grep '^freescout.admin.pass=' /root/freescout-credentials.txt | cut -d= -f2-)
CJ=$(mktemp)
TOK=$(curl -ks -c "$CJ" https://127.0.0.1/login | grep -oE 'name="_token" value="[^"]+"' | head -1 | sed 's/.*value="//;s/"//')
curl -ks -o /dev/null -w 'good login -> %{redirect_url}\n' -b "$CJ" -c "$CJ" \
  -d "_token=$TOK" --data-urlencode "email=$USER" --data-urlencode "password=$PASS" https://127.0.0.1/login
BAD=$(mktemp)
BTOK=$(curl -ks -c "$BAD" https://127.0.0.1/login | grep -oE 'name="_token" value="[^"]+"' | head -1 | sed 's/.*value="//;s/"//')
curl -ks -o /dev/null -w 'wrong pass -> %{redirect_url}\n' -b "$BAD" -c "$BAD" \
  -d "_token=$BTOK" --data-urlencode "email=$USER" --data-urlencode "password=wrong-99" https://127.0.0.1/login rm -f "$CJ" "$BAD"

Expected: good login -> https://127.0.0.1/home (signed in) and wrong pass -> https://127.0.0.1/login (bounced back and rejected).

Step 6 - Sign in

Browse to https://<vm-public-ip>/ and sign in with the email admin@sac.local and the password from the credentials file.

Because the image ships a per-VM self-signed certificate, your browser shows a one-time certificate warning on the first visit. Click through it, or install your own domain certificate into /etc/nginx/ssl/freescout.crt and /etc/nginx/ssl/freescout.key.

After you sign in, you land on the FreeScout dashboard. It lists your mailboxes and the conversations waiting in them.

Step 7 - Create a mailbox and work conversations

A mailbox is a shared inbox that your whole team works from. Choose Manage -> Mailboxes -> Create Mailbox, or open the pre-created Support mailbox that ships with the image. Give the mailbox a name and the email address that will receive customer mail. Then add the Connection Settings for your mail provider: IMAP to fetch incoming mail and SMTP to send replies.

Inside a mailbox, every email becomes a conversation. You can assign it to an agent, reply to it, tag it, add private internal notes to it, or resolve it. To start a conversation yourself, select New Conversation, pick the customer, add a subject and body, and send. This is the core FreeScout workflow: a shared, collaborative inbox where nothing falls through the cracks.

Step 8 - Confirm the version and the stack

grep "'version'" /var/www/freescout/config/app.php | head -1 php -v | head -1 df -h /

Expected: 'version' => '1.8.230', PHP 8.3, and the OS disk that holds the application tree (/var/www/freescout) and the MariaDB datadir (/var/lib/mysql). If you need more room for attachments or the database, resize the OS disk from the Azure portal.

First-boot service and security model

A one-shot freescout-firstboot.service runs After=mariadb.service and Before=nginx.service, so the per-VM credentials and TLS certificate are in place before the first page is served. The service rotates the MariaDB password and edits .env in lock-step, so the application never loses its database connection. It regenerates the Laravel APP_KEY, sets a per-VM administrator password and writes the credentials file at mode 0600 (root only). It then drops a sentinel so that it runs exactly once.

systemctl status freescout-firstboot.service --no-pager | head -6 sudo stat -c '%a %U:%G %n' /root/freescout-credentials.txt

Administration from the CLI

Run admin tasks with Laravel's artisan as the www-data user. For example, list the available commands or clear the cache:

sudo -u www-data php /var/www/freescout/artisan list | grep freescout
sudo -u www-data php /var/www/freescout/artisan freescout:clear-cache

The Laravel scheduler runs background jobs such as fetching new email and sending notifications. It runs every minute through the freescout-scheduler.timer systemd timer, so there is no crontab entry to add.

Serving FreeScout on your own domain

FreeScout protects against host-header attacks. It only answers requests whose host matches APP_URL or is listed in APP_TRUSTED_HOSTS. The image pre-trusts the loopback address and the VM's own IP addresses.

To serve FreeScout on your own domain, point a DNS record at the VM. Then set both values in /var/www/freescout/.env and clear the cache:

APP_URL=https://help.example.com APP_TRUSTED_HOSTS=127.0.0.1,localhost,help.example.com
sudo -u www-data php /var/www/freescout/artisan freescout:clear-cache

For a browser-trusted certificate, install one from your CA (for example Let's Encrypt) in place of the shipped self-signed pair:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d help.example.com

Backup and maintenance

FreeScout's data lives in the MariaDB database and in the uploaded files under /var/www/freescout/storage. Back up the database with mariadb-dump, and snapshot the OS disk from the Azure portal for a full point-in-time copy:

sudo mariadb-dump --single-transaction freescout | gzip > /var/backups/freescout-$(date +%F).sql.gz

Keep the OS current with sudo apt-get update && sudo apt-get upgrade. The image ships with unattended security updates enabled. Review FreeScout's own update notes before you move between versions.

Support

This image is backed by 24/7 SecureAnyCloud support for deployment, upgrades, mailbox and IMAP/SMTP configuration, module installation, LDAP and SAML single sign-on, performance tuning and database administration. Email sales@secureanycloud.com or use the live chat in the support portal. Critical issues receive a one-hour average response.

Deploy on Azure

Launch FreeScout on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure