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.
nginxandphp8.3-fpmserve the site on port 80, andmariadbholds every post, page, account and setting. MariaDB is bound to127.0.0.1:3306and 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 LaravelAPP_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 thatadmin/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_KEYis 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 whileAPP_KEYis 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.
nginxandphp8.3-fpmare 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
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.
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 1002First 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.txtThe 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.
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 -4Sign 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)"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.
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.
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.
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:clearConfigure 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.
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.
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:clearNext, 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-interactiveThe 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.
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.serviceThe 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/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/publicTo 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.
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-upgradesTroubleshooting
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:clearPassword 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/themesSupport
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