Deployment guide

Azuriom

Overview

Azuriom is an open-source content management system written specifically for game server communities. It is developed by the Azuriom team and published at azuriom.com. It gives a Minecraft, FiveM, Rust, ARK, Garry's Mod or Counter-Strike community a real website instead of a forum thread: a news feed with comments and likes, unlimited custom pages, a player account system with roles and permissions, live game server status, and an administration dashboard that a community manager can run without touching a configuration file.

This SecureAnyCloud image deploys Azuriom 1.2.12 on Ubuntu 24.04 on Azure. It installs Azuriom from the official upstream release archive, serves it with nginx and PHP 8.3 FPM, and stores the site data in MariaDB from Ubuntu 24.04. All three are wired together, and unattended security upgrades keep the server patched on your running VM.

What you get:

  • Azuriom 1.2.12 served by nginx and PHP 8.3 FPM, with the Laravel public/ directory as the only web root
  • MariaDB (mariadb.service) holding the site data, bound to loopback
  • One appliance, three services. nginx and php8.3-fpm serve the site on port 80, and mariadb holds every post, page, account and setting. MariaDB is bound to 127.0.0.1:3306 and PHP FPM listens on a Unix socket, so neither is ever exposed to the network. Port 80 is the only reachable surface.
  • A Laravel deployment done properly. Azuriom is a Laravel application, and the document root is the framework's public/ directory and nothing above it. The application source, its vendored dependencies, the database migrations and above all .env, which holds this VM's application key and database password, live outside any URL the web server can address. Only the framework front controller is permitted to execute PHP, so a file placed anywhere else in the web root is refused rather than run.
  • No administrator account in the image. Rather than shipping a default login and rotating it, this image ships no account, no .env, no application key and no database schema at all. On the first boot of every VM, a one-shot service generates a unique Laravel APP_KEY, a unique database password and a unique administrator password. It creates the database schema and the single administrator account with a bcrypt password hash. It then proves that the new password signs in through the real login form and that admin/admin, a blank password and other common guesses do not. Only then does it write /root/azuriom-credentials.txt (mode 0600, root-only).
  • A per-instance application key. APP_KEY is Laravel's session, cookie and encryption signing material. If it were baked into the image, every customer of that image would share it, and anyone holding the image could forge a signed session for anyone else's site. Here it is generated on your VM, for your VM. It also closes Azuriom's own setup wizard: upstream opens the /install/* routes only while APP_KEY is empty, so once first boot has written a real key, the wizard is permanently shut and a passing visitor cannot use it to seize your site.
  • No unprovisioned site is ever served. nginx and php8.3-fpm are each gated on a bootstrap marker that first boot writes only after every credential is in place. Until that marker exists, systemd skips those units entirely, so there is no window in which a half-provisioned site, or the setup wizard, is reachable. The units are still enabled, so the site comes straight back after a reboot.
  • A news system with comments, likes and attachments, unlimited custom pages with a rich editor, and a navigation editor
  • A player account system with registration, email verification, two-factor authentication, password reset, roles and fine-grained permissions
  • Live game server status and player counts, an action log of administrative changes, image and file management, and multi-language support
  • A per-instance application key, database password and administrator password generated on first boot and documented in /root/azuriom-credentials.txt (0600)
  • Azuriom core only. No third-party theme or plugin is bundled, so no unverified extension licence travels in the image. The theme and extension marketplace is available from the dashboard when you want it

Prerequisites

Before you deploy, you need:

  • An active Azure subscription, an SSH public key, and a VNet with a subnet in the target region
  • A subscription to the Azuriom listing on Azure Marketplace
  • Network security group (NSG) rules that allow TCP 22 (administration) and TCP 80 (the website) from the networks that need them
  • A registered domain, plus access to your DNS provider, if you want the community to reach the site by name rather than by IP address
1

Deploy from the Azure Portal

Search the Azure Marketplace for Azuriom, select the SecureAnyCloud publisher, and click Create. Choose Standard_B2s or larger.

Configure the network security group to allow TCP 80 for the website from the internet, or from your own networks while you set it up. Allow TCP 22 for administration from your administrative networks only.

The database and the PHP runtime stay on loopback and are never exposed.

2

Deploy from the Azure CLI

RG="community-prod"; LOCATION="eastus"; VM_NAME="azuriom" IMAGE_URN="sac1647283583153:azuriom-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:azuriom-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1002
3

First boot and your credentials

On first boot, the image generates this VM's application key, database password and administrator password. It creates the database schema and the single administrator account, opens the bootstrap gate and starts the web server. It then verifies that the new credentials work and that the common defaults are rejected, and writes /root/azuriom-credentials.txt. This completes within a minute or two.

SSH in as azureuser and read the details:

sudo cat /root/azuriom-credentials.txt

The file is mode 0600 and owned by root, so only a privileged user can read it. It contains the site URL, the administrator username, email address and password, and the database name, user and password.

4

Confirm the appliance is running

Run the following commands. All three services should report active. ss confirms that the site listens on port 80 while MariaDB is bound to loopback only, and the response headers carry no server version banner.

systemctl is-active mariadb.service php8.3-fpm.service nginx.service php -r 'echo "PHP ".PHP_VERSION."\n";' mysql --version nginx -v ss -tlnp | grep -E ':(80|3306) ' | sed 's/users:.*//' | sort curl -sI http://127.0.0.1/ | head -4
5

Sign in to your site

Browse to http://<your-vm-public-ip>/. The Azuriom community home page opens with the stock theme.

Click Login, or go straight to http://<your-vm-public-ip>/user/login. Sign in with the username admin and the password from the credentials file.

Once signed in, open http://<your-vm-public-ip>/admin for the administration dashboard. It shows counts of users, posts, pages and images, plus recent and active user charts. The navigation for settings, content, users and extensions runs down the left, and the sidebar header reports the game the site is configured for and the Azuriom version.

You can prove the same sign-in from the command line. The following commands use the per-instance password from the credentials file to complete a real login through the form, then check that common default passwords are refused:

sudo /usr/local/sbin/azuriom-login-check.sh admin '<AZURIOM_ADMIN_PASSWORD>' && echo "per-VM password: ACCEPTED (correct)"
sudo /usr/local/sbin/azuriom-login-check.sh admin 'admin' || echo "admin/admin: REJECTED (correct)"
sudo /usr/local/sbin/azuriom-login-check.sh admin '' || echo "blank password: REJECTED (correct)"
6

Change the administrator password

Set your own password as soon as you sign in. Click your avatar at the top right of the site and choose Profile, or browse to /profile. In the Change password form, enter the per-instance password from the credentials file as the current password, then choose a new one.

Azuriom stores passwords as bcrypt hashes, so the new password is never recoverable from the database. Once you change it, the copy in /root/azuriom-credentials.txt is stale. Keep the file for the database password, or remove the administrator password line from it.

7

Make the site your own

Open Settings in the admin sidebar. The General page sets the site name, description, keywords, timezone, default language and the copyright line in the footer. Set the site name first, because it appears in the navigation bar, the browser title and every email the site sends.

The Navbar page builds your navigation. Add links to pages, categories, posts or external URLs, and drag them into the order and nesting you want.

The Theme page lists the installed themes and lets you install more from the Azuriom marketplace without leaving the dashboard. The stock theme is fully usable and is what the screenshots in this guide show.

Under Content, use Pages for static content such as rules, staff lists or a vote page, and Images for the media library that the editor draws on.

8

Publish your first news post

Open Content > Posts > Create to start the post editor. Give the post a title and a short description. The slug fills itself in from the title. Write the body in the rich text editor.

The Published at field controls when the post appears, and the pin switch keeps an announcement at the top of the news list.

Click Save, then open the public site. The post appears in the News section of the home page as a card with its title, an excerpt of the body and a Read more button. This is the core of what Azuriom does: it turns what you write in the dashboard into the community's public website.

The Read more button takes any visitor, signed in or not, to the post's own page, with the full body, a like button and the comment thread.

You can confirm from the command line that a published post is public, with no session or cookie involved:

curl -s -o /dev/null -w 'public home page: HTTP %{http_code}\n' http://127.0.0.1/ POSTS="$(curl -s http://127.0.0.1/ | grep -c 'Read more' || true)" echo "published posts visible to an anonymous visitor: ${POSTS}"

A freshly deployed instance reports 0 here because nothing is published yet. After you publish a post, it reports the number of posts on the home page.

9

Add your game server

Open Settings > Servers > Add to register a game server so the site can show its status and player count. Choose the server type, give it a name, and enter the host and query port. Azuriom pings the server and renders the result in the theme, so visitors can see at a glance whether the server is up and how busy it is.

The AZURIOM_GAME value in /var/www/azuriom/.env sets the game the site is built around. This image sets it to Minecraft offline mode. To build the site around a different game, install that game's extension from Extensions in the dashboard and follow its instructions.

After any manual change to .env, clear the cached configuration:

sudo -u www-data php /var/www/azuriom/artisan optimize:clear
10

Configure mail so registration and password reset work

A fresh instance has no mail transport configured, so account verification and password reset emails are written to the application log rather than sent.

Open Settings > Mail in the dashboard and enter your SMTP host, port, encryption, username and password. Then send the test message from that page.

Mail settings are stored in the database, so you do not need to edit any file on disk. To configure the transport in the environment file instead, edit the MAIL_ values in /var/www/azuriom/.env and clear the cache as in the previous step.

Keep the file's ownership and permissions as they are. It is root:www-data mode 0640 on purpose, because it holds this VM's application key.

11

Open registration to your community

Registration is enabled by default so that players can create accounts. Open Settings > General to control whether new registrations are accepted.

Open Users > Roles to define what each role can do. Create the roles you need (member, moderator, staff) and grant each one only the permissions it should have. Users > Bans handles moderation.

Two-factor authentication is available to every account from Profile > 2FA. Enable it on your administrator account once you have set your own password.

12

Use your own domain and add TLS

Point an A record for your domain at the VM's public IP address. Then set the site address so that links and emails use the name rather than the IP:

sudo sed -i 's|^APP_URL=.*|APP_URL="https://<your-domain>"|' /var/www/azuriom/.env
sudo -u www-data php /var/www/azuriom/artisan optimize:clear

Next, obtain a certificate. Certbot's nginx plugin edits the existing site in place and leaves the allowlist intact:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain> --redirect --agree-tos -m admin@<your-domain> --non-interactive

The dashboard shows a warning while the site is served over plain HTTP. The warning clears once the certificate is in place and HTTP redirects to HTTPS.

13

How the security model works

Two mechanisms do the work, and you can verify both on your own VM.

The bootstrap gate. nginx and php8.3-fpm each carry a systemd drop-in with ConditionPathExists pointing at a marker. First boot writes that marker only after the application key, the database password and the administrator account all exist. Until then, systemd skips the unit. It does not start and fail; it does not start at all. An unprovisioned site is therefore never reachable. Both units remain enabled, so the site returns after a reboot.

grep -h ConditionPathExists /etc/systemd/system/nginx.service.d/sac-bootstrap-gate.conf /etc/systemd/system/php8.3-fpm.service.d/sac-bootstrap-gate.conf ls -l /var/lib/sac/data/ systemctl is-enabled php8.3-fpm.service nginx.service azuriom-firstboot.service

The web root and the closed installer. Only public/ is served, so .env, config/, vendor/, artisan and the logs are not addressable at all. Azuriom's setup wizard is shut because a real application key exists. Only the framework front controller may execute PHP, so a .php file anywhere else in the web root is refused rather than run:

grep -E '^\s+root ' /etc/nginx/sites-available/azuriom stat -c '%n mode %a owner %U:%G' /var/www/azuriom/.env for p in /.env /config/app.php /vendor/autoload.php /artisan /install /install/database /assets/anything.php; do printf '%-28s HTTP %s\n' "$p" "$(curl -s -o /dev/null -w '%{http_code}' -m 10 http://127.0.0.1$p)" done curl -s -o /dev/null -w 'the site itself: HTTP %{http_code}\n' http://127.0.0.1/
14

Back up your site

Everything you create lives in two places: the database, and the uploaded files under storage/app/public. Back up both. Also back up .env if you want an exact restore of the same instance.

sudo mysqldump --single-transaction --routines azuriom > /var/backups/azuriom-$(date +%F).sql
sudo tar czf /var/backups/azuriom-files-$(date +%F).tar.gz -C /var/www/azuriom storage/app/public

To restore on a new instance, copy the files back, import the SQL dump into the azuriom database, and then clear the cache.

Keep .env out of any backup you share, because it carries this VM's application key and database password.

15

Keeping Azuriom up to date

Open Settings > Updates in the dashboard to check for new Azuriom releases and apply them in place. Unattended upgrades, which are enabled in the image, keep the OS itself patched:

systemctl is-enabled unattended-upgrades.service grep -h . /etc/apt/apt.conf.d/20auto-upgrades

Troubleshooting

The site returns nothing and nginx is not running. Check whether first boot completed. If the marker is absent, the gate is doing its job, and the real problem is in first boot:

systemctl status azuriom-firstboot.service --no-pager | tail -20 ls -l /var/lib/sac/data/

A 500 error after editing .env. Laravel reads .env on every request, so a malformed line breaks every page. Check the application log and clear the cache:

sudo tail -20 /var/www/azuriom/storage/logs/laravel.log 2>/dev/null || echo "no application log yet"
sudo -u www-data php /var/www/azuriom/artisan optimize:clear

Password reset emails never arrive. Mail is unconfigured on a fresh instance by design. Configure SMTP as in Step 10.

Permission errors when installing a theme or plugin. The extension directories are owned by the web user on purpose, and the rest of the application is deliberately read-only to it. If a manual file copy has changed that, restore the ownership:

sudo chown -R www-data:www-data /var/www/azuriom/storage /var/www/azuriom/bootstrap/cache /var/www/azuriom/plugins /var/www/azuriom/resources/themes

Support

SecureAnyCloud provides 24/7 technical support for this image by email at sales@secureanycloud.com and via live chat, with a one-hour average response time for critical issues.

We help with domain and TLS certificate setup, mail delivery, themes and extensions, game server integration, roles and permissions, backup and restore, performance tuning and Azuriom version upgrades.

Azuriom is free software licensed under the GNU General Public License version 3 or later, with an additional term that permits the "Powered by Azuriom" attribution requirement on public pages. The upstream project's own documentation is at azuriom.com/docs.

All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch Azuriom 1.2.12 Game CMS 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