If you run a small business or manage a homelab that fields requests from real people, you've probably lived the shared-inbox nightmare. Someone replies-all, a customer question gets buried under newsletter signups, and nobody actually owns the ticket. A proper help desk fixes that, but Zendesk and Help Scout start billing per agent almost immediately. That's where FreeScout comes in.

FreeScout is a free, open-source help desk application that looks and behaves a lot like Help Scout, minus the monthly invoice. Because it's just a PHP application with a MySQL database, it runs comfortably in a small Proxmox VE LXC container, no dedicated VM required. This guide walks through the entire setup, from creating the container to logging into your first support mailbox.

What You Will Learn

  • What FreeScout actually is and how it compares to a shared email inbox
  • Why an LXC container is a good fit for this particular app
  • How to size and create the container in Proxmox VE
  • How to install PHP, MariaDB, Nginx, and Composer on Debian 12
  • How to download, configure, and run the FreeScout installer
  • What each install command actually does
  • Common errors during setup and how to fix them
  • Backup and update habits worth adopting from day one

What Is This Feature?

FreeScout is a self-hosted help desk built on the Laravel PHP framework. Instead of a support email landing in someone's personal inbox, it lands in a shared mailbox inside FreeScout, gets turned into a ticket (called a conversation), and can be assigned, tagged, and replied to by your team without anyone stepping on each other's replies. Customers never see FreeScout itself; they just get email replies that look like they came from your support address.

Before we go further, a quick word on the container technology we're using. LXC stands for Linux Containers. Unlike a full virtual machine, an LXC container shares the host's Linux kernel instead of running its own, which makes it start faster and use noticeably less RAM and disk. For an app like FreeScout, which is really just a web server, a PHP process, and a database, that's a perfect match. You don't need the overhead of a full VM to run something this lightweight.

You'll also see references to a few supporting pieces along the way. MariaDB is the open-source database FreeScout stores tickets, users, and settings in — it's a drop-in replacement for MySQL and is what Debian ships by default. Nginx is the web server that receives browser requests and hands PHP files off to be processed. Composer is PHP's package manager; it downloads all the code libraries FreeScout depends on so you don't have to grab them by hand.

Why Would You Use It?

The honest answer is cost and control. A five-person support team on a paid help desk platform can run well over a hundred dollars a month, forever. FreeScout has no per-agent fee — you can add as many mailboxes and users as your server can handle. Everything lives on hardware you own, which matters if you're dealing with customer data you'd rather not hand to a third party.

It's also just a good homelab project. You get real experience running a production-style PHP/Laravel application: web server config, cron jobs, database permissions, the works. That's transferable knowledge, unlike clicking through a SaaS onboarding wizard.

I'll be upfront about the tradeoff, though. You're now responsible for backups, updates, and uptime. If your Proxmox host goes down, so does your support inbox. That's a fair trade for a homelab or a small business watching costs, but it's worth knowing going in.

Prerequisites

Before starting, make sure you have the following:

  • A working Proxmox VE 8.x or 9.x host with free CPU, RAM, and storage
  • The debian-12-standard LXC template already downloaded (Datacenter → node → local → CT Templates)
  • At least 2 CPU cores, 2 GB of RAM, and 8 GB of disk space free for the container
  • Basic comfort typing commands over SSH — nothing advanced, but you shouldn't be seeing a terminal for the first time
  • A domain name or internal hostname you plan to point at this container (optional, but recommended if agents will access it remotely)
  • An email account you're willing to connect as the support mailbox, with IMAP and SMTP access enabled

Step-by-Step Tutorial

1. Create the LXC container

In the Proxmox web UI, click Create CT in the top-right corner. On the General tab, give it a hostname like freescout and set a root password. On the Template tab, pick the debian-12-standard template you downloaded earlier.

On Disk, set at least 8 GB — FreeScout itself is small, but ticket attachments and log files add up over time. On CPU, 2 cores is plenty to start. On Memory, set 2048 MB; you can drop this to 1024 MB later if it's overkill for your ticket volume, but the install process is more comfortable with headroom. Leave the container unprivileged unless you have a specific reason not to.

On Network, assign a static IP if your homelab uses one, or leave it on DHCP with a reservation set on your router. Finish the wizard and start the container.

2. Update the system and install base packages

Open the container's console (or SSH in) and run:

apt update && apt upgrade -y
apt install -y curl unzip git cron sudo

This refreshes the package lists, applies any pending security updates, and pulls in a handful of tools we'll need shortly: curl for downloading files, git for pulling the FreeScout source, and cron for the scheduled task Laravel apps rely on.

3. Install PHP and required extensions

Debian 12 ships PHP 8.2 by default, which comfortably meets FreeScout's minimum of PHP 8.1. Install it along with the extensions FreeScout needs:

apt install -y php8.2-fpm php8.2-mysql php8.2-mbstring php8.2-xml \
php8.2-curl php8.2-zip php8.2-gd php8.2-bcmath php8.2-imap php8.2-intl

Each of these matters: php-imap lets FreeScout talk to your support mailbox over IMAP, php-gd handles image thumbnails for attachments, and php-bcmath and php-intl are used internally by Laravel for precise number handling and locale formatting.

4. Install and configure MariaDB

apt install -y mariadb-server mariadb-client
mysql_secure_installation

Walk through the prompts — set a root password, remove anonymous users, disable remote root login, and drop the test database. Then create a dedicated database and user for FreeScout:

mysql -u root -p
CREATE DATABASE freescout CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'freescout'@'localhost' IDENTIFIED BY 'choose-a-strong-password';
GRANT ALL PRIVILEGES ON freescout.* TO 'freescout'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Write that password down. You'll enter it into the FreeScout web installer in a few minutes.

5. Install Composer

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

Composer isn't in Debian's default repos in a version recent enough for FreeScout, so we grab it directly from the official installer script instead.

6. Download FreeScout

cd /var/www
git clone https://github.com/freescout-helpdesk/freescout.git
cd freescout
composer install --no-dev --optimize-autoloader

Cloning via git, rather than downloading a zip, makes future updates a simple git pull. The composer install step downloads every PHP library FreeScout depends on — expect this to take a minute or two on a 2-core container.

7. Set folder permissions

chown -R www-data:www-data /var/www/freescout
chmod -R 755 /var/www/freescout/storage /var/www/freescout/bootstrap/cache

Laravel-based apps write logs, cached views, and session data into the storage and bootstrap/cache folders. If the web server user can't write to them, you'll get a blank white screen instead of the app.

8. Configure Nginx

Install Nginx and create a server block:

apt install -y nginx
nano /etc/nginx/sites-available/freescout

Paste in a config pointing the document root at the public folder (not the project root — this matters for security) and passing PHP files to php8.2-fpm's socket. Then enable the site and reload:

ln -s /etc/nginx/sites-available/freescout /etc/nginx/sites-enabled/
rm /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx

9. Run the web installer

Open a browser and go to http://<container-ip>/install. FreeScout's setup wizard checks your PHP extensions, asks for the database credentials you created earlier, and walks you through creating your first admin account. When it finishes, it writes the configuration into a .env file automatically — you never edit that by hand during initial setup.

10. Set up the scheduler cron job

FreeScout relies on Laravel's task scheduler for things like sending queued notification emails. Add this as the www-data user:

crontab -u www-data -e

Then add this single line:

* * * * * php /var/www/freescout/artisan schedule:run >> /dev/null 2>&1

That's it — one line, runs every minute, does nothing visible when everything's healthy.

11. Connect your support mailbox

Log into FreeScout, go to Manage → Mailboxes → New Mailbox, and enter your support email address along with its IMAP and SMTP settings. FreeScout will periodically check that inbox and pull new messages in as tickets. Test this with a real email before telling your team it's live.

Commands Explained

CommandWhat it does
apt install php8.2-fpm ...Installs the PHP runtime and the specific extensions FreeScout requires to function
mysql_secure_installationLocks down a fresh MariaDB install — removes default and anonymous access
composer install --no-devDownloads FreeScout's PHP dependencies, skipping developer-only tools you don't need in production
chown -R www-data:www-dataGives the web server process ownership of the app files so it can read and write where needed
nginx -tTests your Nginx config for syntax errors before you reload the live service
crontab -u www-data -eEdits the scheduled task list that runs as the same user as the web server, which the scheduler needs

Common Errors

A blank white page after installing usually means a permissions problem — the storage or bootstrap/cache folder isn't writable by www-data. Re-run the chown and chmod commands from step 7.

A 502 Bad Gateway error from Nginx almost always means the PHP-FPM socket path in your server block doesn't match the actual socket file. Check /etc/php/8.2/fpm/pool.d/www.conf for the listen directive and make sure your Nginx config references the same path.

A database access denied error during the web installer means the database username, password, or host you entered doesn't match what you created in step 4. Double-check for typos, especially trailing spaces copied from a password manager.

If the installer complains about a missing PHP extension even after you installed it, restart php8.2-fpm — it doesn't pick up newly installed extensions on its own.

Troubleshooting

Start with the application log at /var/www/freescout/storage/logs/laravel.log. Almost every runtime error, from failed mailbox connections to broken email templates, gets written there with a full stack trace.

If pages load but look broken (missing styles, JavaScript errors), clear Laravel's cached config and views:

cd /var/www/freescout
php artisan config:clear
php artisan cache:clear
php artisan view:clear

For mailbox connection failures, test the IMAP credentials outside FreeScout first — most email providers require an app-specific password rather than your normal login, especially Gmail and Outlook accounts with two-factor authentication enabled.

If Nginx itself won't start, check journalctl -u nginx -n 50 for the actual failure reason rather than guessing.

Best Practices

Put this container behind a reverse proxy with a real TLS certificate before agents log in remotely — FreeScout handles sensitive customer conversations, and HTTP-only access on a home network is asking for trouble the moment you forward a port.

Back up the MySQL database separately from your Proxmox-level backups. A vzdump backup captures the whole container, which is useful, but a scheduled mysqldump gives you a lightweight, restorable copy of just the ticket data that's easy to move between servers if you ever migrate.

Take a snapshot before every FreeScout update. Updates are a simple git pull plus a composer install and migration run, but Laravel migrations aren't always reversible cleanly, and a snapshot gives you an instant undo button.

Don't run the queue worker on a sync driver forever if your ticket volume grows — it's fine for a small team, but a proper queue worker as a systemd service keeps outgoing email from blocking page loads once you're processing dozens of tickets a day.

Frequently Asked Questions

Is FreeScout really free to use?

The core application is free and open-source under the AGPL license. Some official modules, like advanced reporting or certain integrations, are paid add-ons, but the base help desk — mailboxes, tickets, multiple agents — costs nothing.

Do I need a full VM instead of an LXC container?

No. FreeScout is a standard PHP web app with no special kernel requirements, which makes it a good fit for LXC. Save the VMs for workloads that genuinely need kernel isolation or a different OS entirely.

Can I use my existing Gmail address as the support mailbox?

Yes, with an app-specific password if you have 2-step verification enabled on the Google account. Plain IMAP with your normal password won't work on most Google Workspace or Gmail accounts anymore.

How many support agents can this handle?

There's no license-based agent limit. Realistically, the 2 CPU / 2 GB RAM container in this guide comfortably handles a handful of agents and moderate ticket volume; scale up the container resources if you outgrow it.

Can I move this installation to another server later?

Yes. Export the MySQL database, copy the /var/www/freescout folder (or re-clone from git and restore your .env), and point the new server's DNS or reverse proxy at it.

Conclusion

You now have a working, self-hosted help desk running in a lightweight LXC container instead of a bloated VM. It took installing a handful of standard Linux packages, running one web-based wizard, and setting a single cron job — nothing exotic. From here, the natural next steps are locking down access with a reverse proxy and TLS certificate, and setting up a recurring database backup so a bad update never costs you your ticket history. Once your support mailbox is connected and your first ticket comes in, you'll wonder why you tolerated a shared inbox for as long as you did.