diff --git a/Panel/CHANGELOG.md b/Panel/CHANGELOG.md
index e696b3e7..bd6962af 100644
--- a/Panel/CHANGELOG.md
+++ b/Panel/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 2026-05-13
+- **Root Apache vhost template for split Panel/Website layout:** Added `SITES_AVAILABLE_EXAMPLE.conf` at repo root with ready-to-copy `sites-available` examples for both `Panel/` and `Website/`, covering HTTP→HTTPS redirects, SSL vhosts, example domains/paths, required Apache modules, Certbot (`--apache` and `--webroot`) commands, and verification/reload steps.
+- **Per-site Apache examples for direct deployment:** Added `examples/apache/panel.example.com.conf` and `examples/apache/website.example.com.conf` so each site can be copied directly into `/etc/apache2/sites-available/` with minimal edits.
+- **Apache install helper script:** Added `examples/apache/install-sites-available.sh` to copy vhost examples into `sites-available`, optionally run `a2enmod`, `a2ensite`, `apache2ctl configtest`, and reload Apache in one flow.
+
## 2026-05-09
- **Billing OS-variant rollback + exact-service provisioning:** Removed storefront canonical Linux/Windows deduping and order-time OS service auto-switching so each enabled `billing_services` row is sold as its own variant. Checkout/provision now preserve the exact selected `service_id`/`home_cfg_id`/XML, enforce location OS compatibility without silent swapping, log selected XML context in provisioning traces, and show “Server installation is in progress.” instead of immediate executable-missing wording while update installs are active. Also replaced deprecated `utf8_encode()` usage in `modules/gamemanager/view_server_log.php` for PHP 8.3 compatibility.
- **Mandatory provisioning trace log + existing-home install retry:** Added visible fail-closed trace logging to `modules/billing/logs/provisioning_trace.log`, threaded detailed per-order provisioning results into checkout success flows, and changed billing provisioning so `Active` orders with an existing `home_id` only skip when the install is already complete. Incomplete existing homes now keep allocating missing IP/mod data and re-use `gamemanager_trigger_update_install()` with traced inputs/outputs instead of silently requiring a manual Game Monitor update.
diff --git a/SITES_AVAILABLE_EXAMPLE.conf b/SITES_AVAILABLE_EXAMPLE.conf
new file mode 100644
index 00000000..6bd08972
--- /dev/null
+++ b/SITES_AVAILABLE_EXAMPLE.conf
@@ -0,0 +1,138 @@
+# GameServerPanel (GSP) Apache vhost examples
+#
+# Copy these into real files under /etc/apache2/sites-available/, for example:
+# /etc/apache2/sites-available/panel.example.com.conf
+# /etc/apache2/sites-available/website.example.com.conf
+#
+# Example deployment paths:
+# Panel -> /var/www/gsp/Panel
+# Website -> /var/www/gsp/Website
+#
+# Required Apache modules:
+# sudo a2enmod ssl rewrite headers
+# sudo systemctl reload apache2
+#
+# Initial activation (HTTP first):
+# sudo a2ensite panel.example.com.conf website.example.com.conf
+# sudo apache2ctl configtest
+# sudo systemctl reload apache2
+#
+# Certbot (Apache plugin):
+# sudo certbot --apache -d panel.example.com -d www.panel.example.com
+# sudo certbot --apache -d gsp.example.com -d www.gsp.example.com
+#
+# Certbot dry run / renewal test:
+# sudo certbot renew --dry-run
+#
+# Notes:
+# - Replace all example domains and paths.
+# - Keep all user-facing website routes root-relative in Website/.
+# - If you use Cloudflare or another proxy, ensure TLS mode and DNS records are correct.
+
+######################################################################
+# PANEL SITE (Panel/)
+######################################################################
+
+# HTTP: allow ACME challenge, redirect everything else to HTTPS
+
+ ServerName panel.example.com
+ ServerAlias www.panel.example.com
+ DocumentRoot /var/www/gsp/Panel
+
+
+ Options FollowSymLinks
+ AllowOverride All
+ Require all granted
+
+
+ RewriteEngine On
+ RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
+ RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+ ErrorLog ${APACHE_LOG_DIR}/panel_example_error.log
+ CustomLog ${APACHE_LOG_DIR}/panel_example_access.log combined
+
+
+# HTTPS: panel site with Let's Encrypt cert paths
+
+ ServerName panel.example.com
+ ServerAlias www.panel.example.com
+ DocumentRoot /var/www/gsp/Panel
+
+
+ Options FollowSymLinks
+ AllowOverride All
+ Require all granted
+
+
+ SSLEngine on
+ SSLCertificateFile /etc/letsencrypt/live/panel.example.com/fullchain.pem
+ SSLCertificateKeyFile /etc/letsencrypt/live/panel.example.com/privkey.pem
+
+ Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
+
+ ErrorLog ${APACHE_LOG_DIR}/panel_example_ssl_error.log
+ CustomLog ${APACHE_LOG_DIR}/panel_example_ssl_access.log combined
+
+
+######################################################################
+# WEBSITE SITE (Website/ standalone storefront)
+######################################################################
+
+# HTTP: allow ACME challenge, redirect everything else to HTTPS
+
+ ServerName gsp.example.com
+ ServerAlias www.gsp.example.com
+ DocumentRoot /var/www/gsp/Website
+
+
+ Options FollowSymLinks
+ AllowOverride All
+ Require all granted
+
+
+ RewriteEngine On
+ RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
+ RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+ ErrorLog ${APACHE_LOG_DIR}/website_example_error.log
+ CustomLog ${APACHE_LOG_DIR}/website_example_access.log combined
+
+
+# HTTPS: website site with Let's Encrypt cert paths
+
+ ServerName gsp.example.com
+ ServerAlias www.gsp.example.com
+ DocumentRoot /var/www/gsp/Website
+
+
+ Options FollowSymLinks
+ AllowOverride All
+ Require all granted
+
+
+ SSLEngine on
+ SSLCertificateFile /etc/letsencrypt/live/gsp.example.com/fullchain.pem
+ SSLCertificateKeyFile /etc/letsencrypt/live/gsp.example.com/privkey.pem
+
+ Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
+
+ ErrorLog ${APACHE_LOG_DIR}/website_example_ssl_error.log
+ CustomLog ${APACHE_LOG_DIR}/website_example_ssl_access.log combined
+
+
+######################################################################
+# Optional webroot-based Certbot alternative (instead of --apache):
+#
+# sudo certbot certonly --webroot \
+# -w /var/www/gsp/Panel \
+# -d panel.example.com -d www.panel.example.com
+#
+# sudo certbot certonly --webroot \
+# -w /var/www/gsp/Website \
+# -d gsp.example.com -d www.gsp.example.com
+#
+# Then verify and reload:
+# sudo apache2ctl configtest
+# sudo systemctl reload apache2
+######################################################################
diff --git a/examples/apache/install-sites-available.sh b/examples/apache/install-sites-available.sh
new file mode 100644
index 00000000..34693ab9
--- /dev/null
+++ b/examples/apache/install-sites-available.sh
@@ -0,0 +1,218 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Installs example Apache vhost configs for GSP Panel + Website.
+#
+# Usage (run as root or with sudo):
+# sudo ./install-sites-available.sh \
+# --source-dir /path/to/repo/examples/apache \
+# --dest-dir /etc/apache2/sites-available \
+# --panel-conf panel.example.com.conf \
+# --website-conf website.example.com.conf \
+# --enable-mods \
+# --enable-sites \
+# --reload
+#
+# Defaults are suitable for Debian/Ubuntu Apache layout.
+
+SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+DEST_DIR="/etc/apache2/sites-available"
+PANEL_CONF="panel.example.com.conf"
+WEBSITE_CONF="website.example.com.conf"
+ENABLE_MODS=0
+ENABLE_SITES=0
+RELOAD=0
+FORCE=0
+RUN_CERTBOT=0
+PANEL_DOMAINS=""
+WEBSITE_DOMAINS=""
+
+print_help() {
+ cat <<'EOF'
+Install GSP example Apache vhost files.
+
+Options:
+ --source-dir Directory containing *.conf files.
+ --dest-dir Apache sites-available directory.
+ --panel-conf Panel conf filename in source-dir.
+ --website-conf Website conf filename in source-dir.
+ --enable-mods Run: a2enmod ssl rewrite headers
+ --enable-sites Run: a2ensite
+ --reload Run apache2ctl configtest and reload apache2
+ --run-certbot Run certbot --apache for provided domains
+ --panel-domains Comma-separated domains for panel certbot run
+ --website-domains Comma-separated domains for website certbot run
+ --force Overwrite destination files if they exist
+ -h, --help Show this help text
+
+Examples:
+ sudo ./install-sites-available.sh --enable-mods --enable-sites --reload
+ sudo ./install-sites-available.sh --force --enable-sites --reload
+ sudo ./install-sites-available.sh --enable-mods --enable-sites --run-certbot \
+ --panel-domains panel.example.com,www.panel.example.com \
+ --website-domains gsp.example.com,www.gsp.example.com --reload
+EOF
+}
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --source-dir)
+ SOURCE_DIR="$2"
+ shift 2
+ ;;
+ --dest-dir)
+ DEST_DIR="$2"
+ shift 2
+ ;;
+ --panel-conf)
+ PANEL_CONF="$2"
+ shift 2
+ ;;
+ --website-conf)
+ WEBSITE_CONF="$2"
+ shift 2
+ ;;
+ --enable-mods)
+ ENABLE_MODS=1
+ shift
+ ;;
+ --enable-sites)
+ ENABLE_SITES=1
+ shift
+ ;;
+ --reload)
+ RELOAD=1
+ shift
+ ;;
+ --run-certbot)
+ RUN_CERTBOT=1
+ shift
+ ;;
+ --panel-domains)
+ PANEL_DOMAINS="$2"
+ shift 2
+ ;;
+ --website-domains)
+ WEBSITE_DOMAINS="$2"
+ shift 2
+ ;;
+ --force)
+ FORCE=1
+ shift
+ ;;
+ -h|--help)
+ print_help
+ exit 0
+ ;;
+ *)
+ echo "Unknown option: $1" >&2
+ print_help
+ exit 1
+ ;;
+ esac
+done
+
+if [[ $EUID -ne 0 ]]; then
+ echo "Run this script as root (or via sudo)." >&2
+ exit 1
+fi
+
+PANEL_SRC="$SOURCE_DIR/$PANEL_CONF"
+WEBSITE_SRC="$SOURCE_DIR/$WEBSITE_CONF"
+PANEL_DST="$DEST_DIR/$PANEL_CONF"
+WEBSITE_DST="$DEST_DIR/$WEBSITE_CONF"
+
+if [[ ! -f "$PANEL_SRC" ]]; then
+ echo "Panel conf not found: $PANEL_SRC" >&2
+ exit 1
+fi
+if [[ ! -f "$WEBSITE_SRC" ]]; then
+ echo "Website conf not found: $WEBSITE_SRC" >&2
+ exit 1
+fi
+if [[ ! -d "$DEST_DIR" ]]; then
+ echo "Destination directory does not exist: $DEST_DIR" >&2
+ exit 1
+fi
+
+if [[ "$RUN_CERTBOT" -eq 1 ]]; then
+ if [[ -z "$PANEL_DOMAINS" || -z "$WEBSITE_DOMAINS" ]]; then
+ echo "--run-certbot requires both --panel-domains and --website-domains" >&2
+ exit 1
+ fi
+ if ! command -v certbot >/dev/null 2>&1; then
+ echo "certbot not found in PATH. Install certbot first." >&2
+ exit 1
+ fi
+fi
+
+copy_file() {
+ local src="$1"
+ local dst="$2"
+
+ if [[ -f "$dst" && "$FORCE" -ne 1 ]]; then
+ echo "Skipping existing file: $dst (use --force to overwrite)"
+ return
+ fi
+
+ install -m 0644 "$src" "$dst"
+ echo "Installed: $dst"
+}
+
+copy_file "$PANEL_SRC" "$PANEL_DST"
+copy_file "$WEBSITE_SRC" "$WEBSITE_DST"
+
+build_domain_args() {
+ local list="$1"
+ local normalized
+ local domain
+ normalized="${list//,/ }"
+ for domain in $normalized; do
+ if [[ -n "$domain" ]]; then
+ printf '%s\n' "-d" "$domain"
+ fi
+ done
+}
+
+if [[ "$ENABLE_MODS" -eq 1 ]]; then
+ echo "Enabling Apache modules: ssl rewrite headers"
+ a2enmod ssl rewrite headers
+fi
+
+if [[ "$ENABLE_SITES" -eq 1 ]]; then
+ echo "Enabling Apache sites: $PANEL_CONF $WEBSITE_CONF"
+ a2ensite "$PANEL_CONF" "$WEBSITE_CONF"
+fi
+
+if [[ "$RELOAD" -eq 1 ]]; then
+ echo "Validating Apache config"
+ apache2ctl configtest
+ echo "Reloading Apache"
+ systemctl reload apache2
+fi
+
+if [[ "$RUN_CERTBOT" -eq 1 ]]; then
+ echo "Running Certbot for panel domains: $PANEL_DOMAINS"
+ mapfile -t panel_domain_args < <(build_domain_args "$PANEL_DOMAINS")
+ certbot --apache "${panel_domain_args[@]}"
+
+ echo "Running Certbot for website domains: $WEBSITE_DOMAINS"
+ mapfile -t website_domain_args < <(build_domain_args "$WEBSITE_DOMAINS")
+ certbot --apache "${website_domain_args[@]}"
+
+ echo "Re-validating Apache config after Certbot changes"
+ apache2ctl configtest
+ echo "Reloading Apache after Certbot changes"
+ systemctl reload apache2
+fi
+
+echo "Done."
+echo "Next steps:"
+echo " 1) Edit ServerName/ServerAlias/DocumentRoot values in $PANEL_DST and $WEBSITE_DST"
+if [[ "$RUN_CERTBOT" -eq 1 ]]; then
+ echo " 2) Certbot has been run for the supplied domains."
+else
+ echo " 2) Run Certbot for real domains, e.g.:"
+ echo " certbot --apache -d panel.example.com -d www.panel.example.com"
+ echo " certbot --apache -d gsp.example.com -d www.gsp.example.com"
+fi
diff --git a/examples/apache/panel.example.com.conf b/examples/apache/panel.example.com.conf
new file mode 100644
index 00000000..e9a9c24a
--- /dev/null
+++ b/examples/apache/panel.example.com.conf
@@ -0,0 +1,60 @@
+# Apache vhost example for GSP Panel
+# Copy to: /etc/apache2/sites-available/panel.example.com.conf
+#
+# Enable modules once:
+# sudo a2enmod ssl rewrite headers
+#
+# Enable site:
+# sudo a2ensite panel.example.com.conf
+# sudo apache2ctl configtest
+# sudo systemctl reload apache2
+#
+# Issue certificate (Apache plugin):
+# sudo certbot --apache -d panel.example.com -d www.panel.example.com
+#
+# Alternative webroot issuance:
+# sudo certbot certonly --webroot -w /var/www/gsp/Panel \
+# -d panel.example.com -d www.panel.example.com
+#
+# Renewal test:
+# sudo certbot renew --dry-run
+
+
+ ServerName panel.example.com
+ ServerAlias www.panel.example.com
+ DocumentRoot /var/www/html/Panel
+
+
+ Options FollowSymLinks
+ AllowOverride All
+ Require all granted
+
+
+ RewriteEngine On
+ RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
+ RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+ ErrorLog ${APACHE_LOG_DIR}/panel_example_error.log
+ CustomLog ${APACHE_LOG_DIR}/panel_example_access.log combined
+
+
+
+ ServerName panel.example.com
+ ServerAlias www.panel.example.com
+ DocumentRoot /var/www/html/Panel
+
+
+ Options FollowSymLinks
+ AllowOverride All
+ Require all granted
+
+
+ SSLEngine on
+ SSLCertificateFile /etc/letsencrypt/live/panel.example.com/fullchain.pem
+ SSLCertificateKeyFile /etc/letsencrypt/live/panel.example.com/privkey.pem
+
+ Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
+
+ ErrorLog ${APACHE_LOG_DIR}/panel_example_ssl_error.log
+ CustomLog ${APACHE_LOG_DIR}/panel_example_ssl_access.log combined
+
diff --git a/examples/apache/website.example.com.conf b/examples/apache/website.example.com.conf
new file mode 100644
index 00000000..6adc5fa3
--- /dev/null
+++ b/examples/apache/website.example.com.conf
@@ -0,0 +1,60 @@
+# Apache vhost example for GSP Website storefront
+# Copy to: /etc/apache2/sites-available/website.example.com.conf
+#
+# Enable modules once:
+# sudo a2enmod ssl rewrite headers
+#
+# Enable site:
+# sudo a2ensite website.example.com.conf
+# sudo apache2ctl configtest
+# sudo systemctl reload apache2
+#
+# Issue certificate (Apache plugin):
+# sudo certbot --apache -d gsp.example.com -d www.gsp.example.com
+#
+# Alternative webroot issuance:
+# sudo certbot certonly --webroot -w /var/www/gsp/Website \
+# -d gsp.example.com -d www.gsp.example.com
+#
+# Renewal test:
+# sudo certbot renew --dry-run
+
+
+ ServerName gsp.example.com
+ ServerAlias www.gsp.example.com
+ DocumentRoot /var/www/html/Website
+
+
+ Options FollowSymLinks
+ AllowOverride All
+ Require all granted
+
+
+ RewriteEngine On
+ RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
+ RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+
+ ErrorLog ${APACHE_LOG_DIR}/website_example_error.log
+ CustomLog ${APACHE_LOG_DIR}/website_example_access.log combined
+
+
+
+ ServerName gsp.example.com
+ ServerAlias www.gsp.example.com
+ DocumentRoot /var/www/html/Website
+
+
+ Options FollowSymLinks
+ AllowOverride All
+ Require all granted
+
+
+ SSLEngine on
+ SSLCertificateFile /etc/letsencrypt/live/gsp.example.com/fullchain.pem
+ SSLCertificateKeyFile /etc/letsencrypt/live/gsp.example.com/privkey.pem
+
+ Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
+
+ ErrorLog ${APACHE_LOG_DIR}/website_example_ssl_error.log
+ CustomLog ${APACHE_LOG_DIR}/website_example_ssl_access.log combined
+