Flarum is the lightest of the three mainstream open-source forum platforms. It is a PHP application built on Laravel components with a Mithril frontend, it uses Composer for both installation and extension management, and it runs comfortably on a 1 GB VPS alongside other services. If you have deployed any modern PHP app behind nginx and PHP-FPM, none of this will surprise you.
This guide covers a production Flarum install on a RamNode KVM VPS with nginx, PHP-FPM, MariaDB, Let's Encrypt, an external SMTP relay, and a working backup and upgrade process.
1. Version decision: 1.8 or 2.0
Read this before you type anything, because it determines your PHP version.
Flarum 2.0 has been in development for roughly three years and is currently in its release-candidate series (rc.4 as of mid-2026). The Flarum team describes the API as stable and confirms that real forums are running 2.0 in production, but it has not shipped a final stable tag. Flarum 2.0 requires PHP 8.3 or higher.
Flarum 1.8.x is the last stable release line. It runs on PHP 8.2 and 8.3.
| Flarum 1.8.x | Flarum 2.0 RC | |
|---|---|---|
| Stability | Final stable | Release candidate |
| PHP | 8.2 or 8.3 | 8.3+ |
| Extension ecosystem | Complete | Most major extensions ported, some gaps |
| Upgrade path | Will need a 2.0 migration eventually | Already there |
Recommendation: if this is a forum you are handing to a client or a community that will be annoyed by breakage, install 1.8.x. If it is your own project and you would rather do the 2.0 migration now instead of later, install the RC. Ubuntu 24.04 ships PHP 8.3 natively, so either choice works without a third-party PPA.
Note one 2.0 gotcha up front: Flarum 2.0 treats MySQL and MariaDB as distinct drivers. If you use MariaDB, your config.php driver value must be mariadb, not mysql. Setting it wrong produces a scattered set of query failures that look like anything except a driver mismatch. 2.0 rc.3 added detection for this, but know it exists.
2. Choose the right RamNode instance
Flarum is genuinely cheap to run.
| Community size | RAM | vCPU | Disk |
|---|---|---|---|
| Small forum, under 100 active users | 1 GB | 1 | 20 GB |
| Under 500 active users | 2 GB | 2 | 40 GB |
| Larger, or with Redis and queue workers | 4 GB | 2 to 4 | 60 GB+ |
Pick Ubuntu 24.04 LTS x86_64 on a KVM plan. Flarum will happily share a 2 GB box with other small PHP sites, which is the main reason to pick it over Discourse.
3. Prerequisites
- A domain or subdomain with an A record on your RamNode IPv4 (and AAAA if you are using IPv6). Propagate it before you request certificates.
- An external SMTP relay. Same constraint as every other app you host here.
- SSH access as a sudo user.
The SMTP situation on RamNode
RamNode does not permit mail services on its VPS platform and outbound port 25 is not available to you. Flarum needs email for registration confirmation, password resets, and notification digests. Configure it against a transactional provider over port 587 or 465.
Options: Postmark, SendGrid, Mailgun, Amazon SES, Brevo, Scaleway TEM.
Unlike Discourse, Flarum will install and let you click around without working mail. That is a trap. Registration will break for every user who is not you, and you will find out about it from an angry Discord message. Configure SMTP in the admin panel before you announce the forum, and set SPF, DKIM, and DMARC at your DNS provider.
4. Base server preparation
apt update && apt upgrade -y
hostnamectl set-hostname forum.example.com
timedatectl set-timezone UTCReboot if the kernel changed.
Create a deploy user if you are still on root:
adduser deploy
usermod -aG sudo deploy
rsync --archive --chown=deploy:deploy ~/.ssh /home/deploySwap
On a 1 GB plan, composer create-project will pull hundreds of packages and can spike hard. Add swap.
fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
echo 'vm.swappiness=10' >> /etc/sysctl.d/99-flarum.conf
sysctl --systemFirewall
apt install -y ufw
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enableAutomatic security updates and fail2ban
apt install -y unattended-upgrades fail2ban
dpkg-reconfigure -plow unattended-upgrades
systemctl enable --now fail2ban5. Install the stack
nginx, PHP 8.3, MariaDB
Ubuntu 24.04's default PHP is 8.3, which satisfies both Flarum 1.8 and 2.0. No PPA needed.
apt install -y nginx mariadb-server \
php8.3-fpm php8.3-cli php8.3-common \
php8.3-curl php8.3-dom php8.3-gd php8.3-mbstring \
php8.3-mysql php8.3-tokenizer php8.3-zip php8.3-xml \
php8.3-intl php8.3-opcache \
git unzip curlThe extension list maps directly to Flarum's requirements: curl, dom, fileinfo, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip, session. fileinfo, json, openssl, and session are compiled into the Ubuntu PHP build. Verify:
php -m | grep -E '^(curl|dom|fileinfo|gd|json|mbstring|openssl|pdo_mysql|tokenizer|zip|session)#x27;
php -vComposer 2
curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
composer --versionConfirm it reports 2.x. Flarum requires Composer 2 and will not work with 1.x.
Secure MariaDB
mariadb-secure-installationAnswer: no unix_socket change if you want a root password, set a root password, remove anonymous users, disallow remote root, remove test database, reload privileges.
Create the database and user:
mariadb -u root -pCREATE DATABASE flarum CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'flarum'@'localhost' IDENTIFIED BY 'use-a-long-random-password-here';
GRANT ALL PRIVILEGES ON flarum.* TO 'flarum'@'localhost';
FLUSH PRIVILEGES;
EXIT;Confirm MariaDB only listens locally. In /etc/mysql/mariadb.conf.d/50-server.cnf:
bind-address = 127.0.0.1systemctl restart mariadb
ss -lntp | grep 33066. Install Flarum
Create the install directory and hand it to the deploy user.
mkdir -p /var/www/flarum
chown -R deploy:www-data /var/www/flarum
cd /var/www/flarumAs the deploy user (not root, and not www-data):
su - deploy
cd /var/www/flarumFor Flarum 1.8.x stable
composer create-project flarum/flarum:^1.8 .For Flarum 2.0 RC
composer create-project flarum/flarum:^2.0.0 --stability=RC .If you need a third-party extension that only publishes beta releases against 2.0, use --stability=beta instead. Once 2.0 goes stable, set "minimum-stability": "stable" in your composer.json so Composer stops pulling pre-release packages.
The install pulls a lot of packages. On a 1 GB plan this is where swap matters.
Permissions
The web server user needs write access to three places: the root install directory (for config.php), storage/, and public/assets/.
sudo chown -R deploy:www-data /var/www/flarum
sudo find /var/www/flarum -type d -exec chmod 2775 {} \;
sudo find /var/www/flarum -type f -exec chmod 0664 {} \;
sudo chmod -R 775 /var/www/flarum/storage /var/www/flarum/public/assetsNever use 777. If you hit a permissions warning during install, the fix is ownership, not a wider mode.
Add your deploy user to the web group so you can run composer and php flarum without sudo:
sudo usermod -aG www-data deployLog out and back in for the group change to apply.
7. nginx configuration
The webroot is public/, not the install root. This is the single most common Flarum misconfiguration and it will expose config.php if you get it wrong.
Flarum ships a .nginx.conf file in the install root. Include it rather than copying its contents, so upstream changes flow through on upgrade.
/etc/nginx/sites-available/flarum:
server {
listen 80;
listen [::]:80;
server_name forum.example.com;
root /var/www/flarum/public;
index index.php;
client_max_body_size 32M;
include /var/www/flarum/.nginx.conf;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_read_timeout 120;
}
access_log /var/log/nginx/flarum.access.log;
error_log /var/log/nginx/flarum.error.log;
}Enable it:
ln -s /etc/nginx/sites-available/flarum /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginxPHP-FPM pool tuning
On a 1 GB plan, the default pm.max_children will let PHP-FPM cheerfully OOM the box under load. Edit /etc/php/8.3/fpm/pool.d/www.conf:
pm = dynamic
pm.max_children = 8
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 500Rule of thumb: a Flarum PHP-FPM child uses 40 to 60 MB. Multiply your max_children by 60 MB and make sure the result leaves headroom for MariaDB and nginx.
Bump PHP limits in /etc/php/8.3/fpm/php.ini:
memory_limit = 256M
upload_max_filesize = 32M
post_max_size = 32M
max_execution_time = 60
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
opcache.validate_timestamps = 1
opcache.revalidate_freq = 2systemctl restart php8.3-fpm8. TLS with Let's Encrypt
apt install -y certbot python3-certbot-nginx
certbot --nginx -d forum.example.com --agree-tos -m you@example.com --redirectCertbot rewrites your server block to add 443 and the redirect. Renewal runs from a systemd timer:
systemctl status certbot.timer
certbot renew --dry-runIf you are behind Cloudflare, use DNS-only mode for the initial issuance, then enable the proxy and set SSL mode to Full (strict).
9. Run the installer
Browse to https://forum.example.com. Flarum's web installer asks for:
- Forum title
- Database host:
127.0.0.1 - Database name:
flarum - Database user:
flarum - Database password: the one you set
- Table prefix: leave blank unless you are sharing a database
- Admin username, email, password
Submit. Flarum writes config.php in the install root and runs migrations.
If you chose 2.0 with MariaDB
After install, open /var/www/flarum/config.php and confirm the driver:
'database' => array (
'driver' => 'mariadb',
'host' => '127.0.0.1',
...
),If it says mysql and you are running MariaDB, change it. This matters only on 2.x.
Lock down config.php
chmod 640 /var/www/flarum/config.php
chown deploy:www-data /var/www/flarum/config.phpVerify it is not web-reachable:
curl -I https://forum.example.com/config.phpYou want a 404. If you get a 200 or a 403 from PHP, your webroot is wrong. Fix it before you go further.
10. Configure email
Admin panel, Email. Fill in:
Driver: SMTP
Host: smtp.postmarkapp.com
Port: 587
Encryption: tls
Username: <provider token>
Password: <provider token>
From address: forum@example.comSave, then use the "Send test mail" control. If it fails, check storage/logs/flarum.log.
Set up a cron entry so scheduled tasks (digests, cleanup) actually run:
crontab -e -u deploy* * * * * cd /var/www/flarum && /usr/bin/php flarum schedule:run >> /dev/null 2>&111. Extensions
Flarum's extension model is Composer packages. Install from the CLI:
cd /var/www/flarum
composer require fof/upload:"*"
php flarum cache:clearThen enable it in the admin panel under Extensions.
Worth installing on a real forum:
fof/uploadfor proper file and image handlingfof/oauthif you want social loginflarum/tags(bundled) for category structurefof/best-answerif you are running a support forumfof/redisif you have Redis available and want a real cache and session driverfof/sitemapfor search visibility
Two things to know about 2.0 extension migration:
blomstra/database-queueandblomstra/fontawesomeare gone. That functionality is now in core.blomstra/flarum-redisbecomesfof/redis, andblomstra/horizonbecomesfof/horizon.
The Extension Manager extension (flarum/extension-manager) lets you install extensions from the admin UI without SSH. It is convenient. It also means your production forum runs Composer from a web request. On a small RamNode plan, that is a real timeout and memory risk. Prefer the CLI.
12. Backups
Flarum has no built-in backup system. You build one. Three things need backing up: the database, public/assets/ (avatars, logos, uploads), and config.php plus composer.json and composer.lock.
/usr/local/bin/flarum-backup.sh:
#!/bin/bash
set -euo pipefail
FLARUM_DIR=/var/www/flarum
BACKUP_DIR=/srv/backups/flarum
STAMP=$(date +%Y%m%d-%H%M%S)
KEEP_DAYS=14
mkdir -p "$BACKUP_DIR"
# Database
mariadb-dump --single-transaction --quick --default-character-set=utf8mb4 \
-u flarum -p"$FLARUM_DB_PASS" flarum | gzip > "$BACKUP_DIR/db-$STAMP.sql.gz"
# Assets and config
tar czf "$BACKUP_DIR/files-$STAMP.tar.gz" \
-C "$FLARUM_DIR" public/assets config.php composer.json composer.lock
# Retention
find "$BACKUP_DIR" -type f -mtime +$KEEP_DAYS -deletePut the DB password in a root-only environment file rather than in the script:
echo 'FLARUM_DB_PASS=your-password' > /root/.flarum-backup.env
chmod 600 /root/.flarum-backup.envAnd source it from cron:
15 3 * * * . /root/.flarum-backup.env && /usr/local/bin/flarum-backup.sh >> /var/log/flarum-backup.log 2>&1Then get the backups off the box. A RamNode VPS is a single node. Backups that live on the same disk as the thing they are backing up are not backups.
rsync -az --delete /srv/backups/flarum/ user@backup-host:/srv/backups/flarum/Restore
gunzip < db-20260716-030001.sql.gz | mariadb -u flarum -p flarum
tar xzf files-20260716-030001.tar.gz -C /var/www/flarum
cd /var/www/flarum && php flarum cache:clear13. Upgrades
Minor updates within a release line
cd /var/www/flarum
composer update --prefer-dist --no-plugins --no-dev -a --with-all-dependencies
php flarum migrate
php flarum cache:clearBack up first. Every time.
1.8 to 2.0
The order here is not negotiable. Do it on a staging copy first.
- Get your 1.x install fully current, including all extensions:
shell
composer update --prefer-dist --no-plugins --no-dev -a --with-all-dependencies - Confirm PHP is 8.3 or higher and Composer is 2.x.
- Find extensions with no 2.0 release. Run
composer why-not flarum/core 2.0.0and remove (not disable) anything blocking. Replace superseded packages per section 11. - Edit
composer.json: set every extension version string to*, including bundled ones likeflarum/tagsandflarum/mentions. Setflarum/coreto^2.0, never to*and never to a pinned minor. - Add
"minimum-stability": "beta"until 2.0 ships stable, then change it back tostable. - If you use MariaDB, change the driver in
config.phptomariadb. - Disable third-party extensions in the admin dashboard. Not required, but it makes debugging tractable.
- Run the update, migrate, clear cache, restart PHP-FPM and opcache.
If the update command fails, composer why-not flarum/core 2.0.0 tells you exactly what is blocking. That is nearly always an unported extension.
14. Troubleshooting
White screen after install. Check storage/logs/flarum.log and /var/log/nginx/flarum.error.log. Nine times out of ten it is permissions on storage/.
"The requested URL was not found" on every page except the homepage. URL rewriting is not working. Confirm include /var/www/flarum/.nginx.conf; is in your server block and that the file exists.
config.php is readable from the web. Your root is pointing at the install directory instead of public/. Fix immediately and rotate the database password, because it was exposed.
Assets do not load after an update. php flarum cache:clear, then confirm public/assets is writable by www-data.
Random query failures on 2.0. Driver mismatch. config.php says mysql, your server is MariaDB.
PHP-FPM 502s under modest load. pm.max_children too high, box swapped, workers got killed. Lower it. Check dmesg | grep -i oom.
Emails silently not sending. Check storage/logs/flarum.log. Confirm you are on 587 or 465 with a real provider, because port 25 is not a route available to you on RamNode.
15. Where Flarum fits
Flarum is the right choice when you want a clean, fast, modern-looking forum that runs on a small box and does not demand a dedicated server. The extension ecosystem is smaller than Discourse's and the moderation tooling is less sophisticated. If you need trust levels, sophisticated spam handling, and a mature plugin catalog, Discourse is worth its heavier footprint. If you want real-time interaction and a Node stack, NodeBB sits in between. Both have companion guides.
Quick reference
Install root: /var/www/flarum
Webroot: /var/www/flarum/public
Config: /var/www/flarum/config.php
Logs: /var/www/flarum/storage/logs/flarum.log
nginx include: /var/www/flarum/.nginx.conf
PHP-FPM socket: /run/php/php8.3-fpm.sock
php flarum cache:clear
php flarum migrate
php flarum info
php flarum schedule:run