DAoC CMS Complete Documentation
A code-aligned guide to installing, operating, extending and troubleshooting DAoC CMS with Dawn of Light or OpenDAoC. It covers the core website, community system, game-data editors, live bridges, Discord integration and production maintenance.
1. What DAoC CMS is
DAoC CMS is an open-source content and administration platform made specifically for Dark Age of Camelot freeshards. It combines a conventional website and community layer with direct access to a supported game database and optional services for actions against the live game world.
A minimal installation can run as a website, account portal and forum. A fully integrated installation can additionally expose Herald and PvE data, edit game content, relay guild chat, display live events, operate an itemshop, administer online players and connect Discord.
Publish and organize
Pages, navigation, FAQ, team page, profiles, search, SEO, themes and translations.
Run the community
Registration, linked game accounts, Spike Forum, messages, notifications, moderation and audit tools.
Manage the shard
Herald, PvE database, RvR map, items, mobs, suits, quests, abilities, characters and server properties.
Reach the game world
AldhranConsole, AldhranBridge, Discord bot, live events, guild chat and terrain support.
Documentation scope
This document describes the repository state identified as 1.0.0-rc2. Paths and setting names are written exactly as they exist in that code line. Custom forks can add or omit fields, so schema-dependent operations should still be tested against a copy of the real database before production use.
2. Quick start
This is the shortest safe route from a clean web directory to a usable CMS. The full setup chapters explain every choice.
- Create an empty MySQL database for the CMS using
utf8mb4. - Clone or extract DAoC CMS into the public web directory.
- Open
/setup/and clear all red requirement and permission checks. - Connect the empty CMS database.
- Select Dawn of Light or OpenDAoC and connect the game database.
- For an existing shard choose Use my existing database. Do not import a public schema over live data.
- Set the site URL, timezone, sender identity and generated secrets.
- Skip optional bridges unless you want live game actions immediately.
- Create the Privilege Level 5 administrator and run all installation phases.
- Download the setup summary, back up
includes/config.php, then deletesetup/.
git clone https://github.com/Darku11/daoc_cms.git
cd daoc_cms
# Open https://your-domain.example/daoc_cms/setup/ in a browser
3. Core concepts
Two logical databases
| Database | Contains | Used by |
|---|---|---|
| CMS database | CMS users, pages, themes, translations, forum, settings, bot configuration, audit logs, AI tasks and CMS-owned suit data. | The PHP application and installer. |
| Game database | Accounts, characters, guilds, mobs, item templates, quests, keeps, relics, zones, properties and other emulator data. | CMS game modules, AldhranConsole and the game server. |
In the current PHP runtime both connections are exposed through the configured PDO environment used by the application. Keep the distinction clear operationally: CMS tables are owned by DAoC CMS; emulator tables remain live game data.
Database data versus live-world state
Reading a character or editing an item template is a database operation. Kicking an online player, teleporting them, broadcasting a message or handing an item to an online inventory is a live-world operation and goes through the Console/Bridge chain.
| Example | Path | Extra component |
|---|---|---|
| Show Herald rankings | PHP → game database | None |
| Edit an item template | ACP → game database | None |
| Kick an online player | CMS → AldhranConsole → AldhranBridge | .NET service + C# script |
| Push a keep capture to the website | CMSLiveEvents.cs → api_events.php | C# script |
| Relay guild chat to Discord | GuildChatBridge.cs → CMS → Discord bot | C# script + bot |
Core selector
The setting game_server_core is either dol or opendaoc. Existing RC1 installations without this setting default to DOL behavior. The selected value changes compatibility mappings and selects the core-specific Mob Editor implementation. It can be changed later in ACP → General Settings → Game Server, but the connected database must match the selected core.
4. Architecture
Repository responsibilities
| Repository | Responsibility | Key paths |
|---|---|---|
| Darku11/daoc_cms | Web application, installer, PHP modules, schema, frontend, ACP, bot process source and downloadable bridge scripts. | modules/, includes/, setup/, assets/js/bot.js |
| Darku11/daoc_cms_utilities | Components that run inside or beside the game server. | AldhranConsole/, AldhranBridge.cs, CMSLiveEvents.cs, GuildChatBridge.cs, TerrainService archive |
Request boundaries
- Frontend requests enter through
index.php?p=<slug>. - ACP requests enter through
acp.php?s=<section>and are checked against the section's minimum privilege. - Shared application bootstrap, sessions, settings, compatibility helpers and plugins are loaded through
includes/db.php. - Theme CSS is assembled from database modules by
style.phpwith theme inheritance and ETag versioning. - Live actions use the hardened client in
includes/console_client.php. - External game scripts post events to
api_events.phpusing the game-server shared secret.
5. Requirements and deployment models
Required for the core CMS
| Requirement | Minimum / expected | Why |
|---|---|---|
| Web server | Apache or another PHP-capable server | Apache rules are supplied in .htaccess; equivalent rules are required elsewhere. |
| PHP | 8.2 or newer | Installer hard requirement. |
| Database | MySQL 8; compatible MariaDB deployments should be tested | CMS schema, triggers/events and game data. |
| PHP extensions | pdo, pdo_mysql, json, curl, zip, fileinfo, zlib | Connections, JSON APIs, HTTP integrations, archives, uploads and compressed OpenDAoC import. |
| Recommended extensions | mbstring, openssl | Unicode handling and cryptographic/TLS support. |
| Git | Current stable client | Recommended installation and update workflow. |
Recommended PHP limits
memory_limit: 128 MB or moreupload_max_filesize: 32 MB or morepost_max_size: 32 MB or more and not smaller than the upload limitmax_execution_time: 60 seconds or more, or unlimited during controlled installation
Optional component requirements
| Feature | Additional requirement |
|---|---|
| Live in-game administration / item delivery | .NET 10 for AldhranConsole and AldhranBridge.cs in the game server scripts folder. |
| Discord bot | Current Node.js LTS, npm dependencies and a Discord application/bot. |
| Discord interaction endpoint | PHP Sodium extension when using Discord's Ed25519 interaction verification. |
| Terrain-dependent editors | TerrainService package and its supporting client library. |
| Scheduled AI work | Configured provider and a task scheduler invoking cron_ai_worker.php. |
| Automated itemshop delivery | A scheduler invoking the webshop worker and a working Console/Bridge chain. |
Deployment profiles
Minimal
Web server + PHP + CMS database + existing game database. Suitable for content, accounts, forum and database-backed public modules.
Integrated
Minimal profile plus AldhranConsole and AldhranBridge for live administration and delivery.
Full
Integrated profile plus Discord bot, CMSLiveEvents, GuildChatBridge, schedulers and optional terrain service.
6. Setup wizard
Open https://your-domain.example/path/setup/. The wizard stores answers in the current PHP session, so keep the tab open until installation finishes.
Step 1 — Welcome
Introduces the installation and starts the ten-step sequence. No system changes occur here.
Step 2 — Requirements
The wizard checks PHP, required and recommended extensions, runtime limits, operating system and web server. Red entries block progress; amber entries are warnings.
Step 3 — Permissions
The web server must be able to create or write uploads/, backups/, plugins/ and includes/config.php (or its parent directory before the file exists). Prefer correct ownership and narrow permissions; do not set the entire website to 777.
Step 4 — CMS database
Create the empty database before opening the wizard. The installer connects to it but does not create the database itself.
CREATE DATABASE `daoc_cms`
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
The test verifies connectivity and the ability to create and drop a temporary table. An existing users table triggers a warning because the final schema phase writes CMS tables.
Step 5 — Game database and server core
Select OpenDAoC or Dawn of Light, enter host, port, database, username and password, then choose one mode:
| Mode | Use when | Risk |
|---|---|---|
| Use my existing database | The shard already exists or its schema was imported separately. | Connection/structure test only. Safest for production. |
| Install public database | Building a brand-new shard from the bundled core-specific schema. | Destructive import; can replace tables. |
| Import my own backup | Intentionally restoring a supplied SQL file. | Destructive import; large files may exceed PHP limits. |
The bundled public files are setup/sql/dol_public.sql and setup/sql/opendaoc_public.sql.gz. Large backups are more reliable through the MySQL command line; after importing them externally, return and select the existing-database mode.
Step 6 — Site configuration and secrets
Configure site name, shard name, absolute base URL without a trailing slash, language, timezone, sender name/address, optional Resend key and optional Discord values. The wizard generates:
- Password pepper — required to validate every CMS password.
- Instance ID — installation identity and session-name component; not a secret.
- Bot bootstrap secret — authorizes the Node bot to retrieve startup configuration.
- Game-server integration secret — written as
ASP_KEYand used as the canonical shared secret for AldhranConsole and game-server scripts.
Step 7 — Optional bridges
Set AldhranConsole host (without http://), HTTP port (default 5100) and AldhranBridge TCP port (default 2000). The wizard exposes downloads for the three C# scripts. Saving this step configures only the CMS; the external services still have to be installed and started.
Step 8 — Administrator
Create the first Privilege Level 5 account. The username is restricted to 3–20 letters, numbers, underscores or hyphens; the password validator requires a strong password. The installed password is peppered and stored as a bcrypt hash.
Step 9 — Installation phases
- Write
includes/config.php. - Verify the CMS database connection.
- Execute
setup/sql/database.sql. - Normalize selected CMS table names to the
cms_scheme. - Create the Super Admin.
- Save initial settings and the migration baseline.
The per-phase endpoint is CSRF-protected, rejects non-POST requests and refuses a second completed run in the same setup session.
Step 10 — Finish and seal
Download daoc-cms-setup-summary.txt before leaving the page. It contains the pepper, instance ID, integration key and bot bootstrap secret, but not database or administrator passwords. The wizard creates install.lock and clears setup secrets from the session.
setup/ after installation. The lock blocks normal reuse, but removing the installer code is the correct production state. If the lock could not be created, deletion is urgent.7. First-run checklist
- Setup summary downloaded and stored outside the web root.
includes/config.phpbacked up securely.setup/removed andinstall.lockpresent.- HTTPS enabled before ordinary logins; secure cookies are enforced by the CMS.
- Super Admin login tested.
- Two-factor authentication enabled for the Super Admin; ACP access requires it at level 5.
- ACP opens and re-authentication succeeds.
- Selected game-server core matches the connected database.
- Herald or another read-only game module can query the game database.
- Maintenance mode reviewed; the fresh schema seeds it as enabled.
- Unused public modules disabled.
- Default pages, privacy text and imprint reviewed for the actual operator.
- Backup paths and a first verified backup configured.
- Secrets excluded from Git and off-server backups protected.
Recommended order
- Secure access and backups.
- Confirm database/core compatibility.
- Set identity, language, modules and legal pages.
- Configure theme and content.
- Add one optional integration at a time and test its health boundary before adding the next.
8. Configuration
includes/config.php
The installer generates this PHP file. It contains credentials and must never be committed, served as text or shared in support screenshots.
| Constant | Purpose | Notes |
|---|---|---|
SITE_URL | Canonical absolute CMS URL. | No trailing slash. Used for links, mail and SEO. |
INSTANCE_ID | Unique installation identity. | Also makes the PHP session cookie name installation-specific. |
ALDRAN_PEPPER / ALDHRAN_PEPPER | Password pepper aliases retained for compatibility. | Back up permanently; never rotate without a password migration. |
ASP_KEY | Installed game-server integration secret and compatibility fallback. | Current installs also persist it in settings.game_server_shared_secret. |
BOT_BOOTSTRAP_SECRET | Authorizes bot startup configuration retrieval. | Separate from both the bot socket secret and Discord token. |
DB_HOST, DB_USER, DB_PASS, DB_NAME | CMS database connection. | Restrict DB account access to the intended host/database. |
RESEND_API_KEY | Optional mail API credential. | Leave empty when unused. |
SMTP_FROM_EMAIL, SMTP_FROM_NAME | Outbound sender identity. | Use a sender/domain authorized by the delivery service. |
SITE_URL: the installer text correctly notes that it is a file constant, not merely an ACP setting. Update the file carefully, clear caches and verify canonical URLs, mail links and callbacks.General settings tabs
| Area | Important setting keys | Behavior |
|---|---|---|
| Identity & presentation | site_name, default_language, active_theme, discord_link | Site name, UI language, theme and community link. |
| Modules | mod_forum, mod_herald, mod_rvr_map, mod_faq, mod_team, mod_register, mod_pve, itemshop_enabled, mod_imprint | Controls public navigation and module availability. |
| Accounts | email_verification_required, admin_approval_required, use_resend_api | Registration activation and mail behavior. |
| Game core | game_server_core | dol or opendaoc; controls compatibility logic. |
| Game address | game_server_ip, game_server_port | Public/status TCP target; default game port is 10300. |
| Live bridge | game_server_console_host, game_server_console_port, game_server_bridge_port, game_server_shared_secret | CMS-to-Console host/port and shared integration secret. |
| Restart | game_server_bat_path | Configured startup path used by the generated watchdog/restart workflow. |
| Maintenance | maintenance_mode, maintenance_text | Blocks normal visitors; access is retained for level 5 administrators. |
Secret separation
| Secret | Authenticates | Never substitute with |
|---|---|---|
| Discord Bot Token | Bot process → Discord | Any CMS or bridge secret |
| Bot bootstrap secret | Bot process → api_bot_config.php | Bot token or socket secret |
| Bot socket secret | CMS ↔ Node bot HMAC/webhook/socket traffic | Game-server shared secret |
| Game-server shared secret | CMS ↔ AldhranConsole ↔ AldhranBridge and C# event scripts | Discord credentials |
9. Roles, standing and ACP access
CMS privilege is stored in users.priv_level. It is related to, but distinct from, the game account's account.PrivLevel. The User Manager can synchronize both where the action explicitly does so.
| Level | Display role | Typical access |
|---|---|---|
| 0 | Guest | Unauthenticated public pages allowed by page/module visibility. |
| 1 | Player | Profile, forum and ordinary authenticated features. |
| 2 | Associate | Support/moderation features where individual modules permit level 2. |
| 3 | GM | ACP dashboard and selected operational/game-data modules. |
| 4 | Admin | Content, settings, integrations, logs and broad administration. |
| 5 | Super Admin | Protected system functions, PHP error log, zones, plugin installation and full privilege assignment. |
Management ceiling
| Operator | May manage targets up to | May assign up to |
|---|---|---|
| Level 3 GM | Level 2 | Level 2 |
| Level 4 Admin | Level 3 | Level 3 |
| Level 5 Super Admin | Level 5 | Level 5 |
The User Manager enforces these limits in both listing/edit checks and assignment validation. An Admin cannot promote another account to level 4 or 5 and cannot manage an existing level 4/5 target. A Super Admin cannot delete or edit their own protected account through the User Manager workflow.
ACP session protection
- ACP entry requires level 3 or higher.
- The ACP has a separate 30-minute re-authentication window.
- Level 5 accounts must enable TOTP before ACP access; re-authentication uses the TOTP code.
- Other staff re-authenticate with their password.
- AJAX actions repeat minimum-privilege and ACP-session checks.
Standing
Standing is a moderation state independent of privilege: Good (0), Warning I (1), Warning II (2), Restricted (3), Suspended (4) and Banned (5). Restricted/unverified accounts are read-only in relevant profile/community workflows. Ban and suspension actions can trigger bot events and game-account synchronization.
10. Frontend modules
| Module | Purpose | Dependency / switch |
|---|---|---|
| Dynamic pages | Published CMS content, scheduled publication, menu categories, privilege visibility and SEO metadata. | Always available through the Content Manager. |
| Registration & verification | Creates linked CMS accounts with password policy, privacy acceptance, optional email verification/admin approval and anti-abuse checks. | mod_register |
| User profiles | Avatar, languages, biography, signature, linked characters, password, TOTP, data export and account deletion. | Authenticated user; game DB for character list. |
| Spike Forum | Boards, threads, posts, polls, attachments, reactions, mentions, tags, prefixes, unread state, subscriptions, reports and search. | mod_forum |
| Private messages | Internal user-to-user messaging with unread counters and sender/receiver deletion state. | Authenticated user. |
| FAQ | Public categorized frequently asked questions. | mod_faq |
| Team | Staff/team presentation based on CMS users and role data. | mod_team |
| Herald | Population, character, guild, leaderboard, keep and relic views. | mod_herald + game DB. |
| PvE database | Bestiary, bosses, items, quests, reward resolution and related game data. | mod_pve + game DB. |
| Itemshop | Browse configured shop items, create purchases and deliver through the live bridge. | itemshop_enabled + Console/Bridge for delivery. |
| RvR map | Realm war display with normalized keep ownership and relic data. | mod_rvr_map + game DB. |
| Search | Site/forum search surfaces with visibility checks. | Available routes; forum search can be disabled separately. |
| Imprint | Operator legal notice page. | mod_imprint |
| RSS / sitemap | Public forum RSS and published public-page XML sitemap. | rss.php, sitemap.php |
Publication visibility
Normal visitors see only pages with status='published', a reached or empty published_at value and a permitted min_priv. Administrators may see additional content in management contexts. The sitemap restricts itself to published, currently visible level-0 pages; the RSS feed excludes protected boards and shadow-banned authors.
11. ACP module reference
Every ACP section has a code-defined minimum level. Plugin sections are merged into the same registry after their hook registration.
| Category / section | Min. | What it manages |
|---|---|---|
| Dashboard | 3 | Operational overview, counters, shortcuts, update widget and plugin dashboard hooks. |
| User Manager | 3 | Search, account standing, CMS/game privilege, verification, profiles, password and account lifecycle within the management ceiling. |
| Content Manager | 4 | Pages, publication state, navigation, templates, metadata, history and media. |
| General Settings | 4 | Identity, modules, game core, bridge, startup path and maintenance. |
| Theme Editor | 4 | Database CSS modules, themes, inheritance, live preview, variables, history, import/export and contrast checks. |
| Translation Editor | 4 | Search, compare, create, edit and remove language variables by context. |
| Forum Admin | 4 | Board structure, reports, settings, prefixes, smilies, forbidden words and maintenance tools. |
| FAQ Manager | 3 | FAQ categories, entries and ordering. |
| Mob Editor | 3 | Core-specific visual spawn, loot, template and patrol-route management. |
| Core Architect | 3 | Economy analysis and simulation. |
| Dataquest Creator | 3 | Visual DataQuest editing and simulation. |
| Item Creator | 3 | Search, create and edit item templates with schema-aware writes. |
| Suit Creator | 3 | Paperdoll gear sets, caps, presets, revisions, item generation and merchant output. |
| Ability Editor | 4 | Spells, spell lines, styles, abilities and NPC templates. |
| Character Editor | 3 | Character lookup and selected game-character fields. |
| Zones Editor | 5 | Zone properties. |
| Global Constants | 3 | Reference values and ID mappings. |
| Ingame Console | 4 | Online status, player actions, broadcasts, restart and restricted raw commands via AldhranConsole. |
| Server Properties | 4 | Game-server properties and rates. |
| Bot & AI Settings | 4 view / 5 save | Discord process, socket, command service and provider configuration. |
| Bot Commands | 4 | Enable state, minimum AuthLevel and user/AuthLevel overrides. |
| AI Suggestions | 4 | Review, accept or reject queued proposals. |
| Admin Log | 4 | Administrative and security audit trail. |
| IP Audit | 4 | Login/device/household patterns and approvals. |
| PHP Error Log | 5 | Application error diagnosis. |
| Cache Manager | 3 | CSS versioning, OPcache reset and browser-cache status. |
| Backup Manager | 4 | Create, verify, annotate, pin, restore and delete archives. |
| Plugin Manager | 5 effective | Install, activate, deactivate and uninstall PHP plugins. |
12. Content and navigation
Page fields
The pages table carries the slug, title, content, status, publication date, menu category and position, parent relationship, language/translation group, template key/data, minimum privilege, meta title/description and optional hero image.
Menu categories
Dynamic menu entries are grouped under stronghold, community and library. none keeps a page out of navigation. Two content prefixes create special links:
[EXT]:https://example.orgcreates an external link with safe new-tab attributes.[MODULE]:heraldcreates a module link and respects the corresponding module switch.
Safe publishing workflow
- Create or edit as draft.
- Set language, menu placement, privilege and metadata.
- Preview rendered content and media.
- Schedule
published_ator publish immediately. - Verify as a logged-out visitor, because ACP visibility can be broader.
History and media tables preserve page revisions and file relationships. Canonical URLs drop tracking, secret and transient query parameters before generating the canonical link.
13. Themes and CSS
Frontend CSS is stored as named modules in aldhran_styles. style.php selects a stack for the current frontend module, resolves the active theme's parent chain and emits active CSS with content-aware ETags.
Editor capabilities
- Load, create and save individual CSS modules.
- Clone a theme or create one with a parent.
- Live preview and palette/CSS-variable editing.
- Validate balanced CSS braces and inspect contrast.
- Export a theme as SQL and import validated theme SQL.
- Retain up to 30 history versions per module/theme and roll back.
- Delete non-default themes after child relationships are resolved.
Theme inheritance
aldhran_themes.parent_slug forms an inheritance chain. Parent modules are loaded first and child modules later, so the active child can override selected CSS without duplicating the full theme.
Cache behavior
The ETag combines active theme, requested module, css_version and the latest update timestamp of loaded style rows. Saving database CSS therefore changes the response identity; the Cache Manager can additionally bump css_version to force broad revalidation.
templates/<active-theme>/<name>.php before falling back to the default template path. Template names are restricted to letters, numbers, underscores and hyphens.14. Translations
Translation rows use lang_code, var_key, var_value and var_context. The runtime loads active languages and resolves strings through t()/cms_t() with replacements and an explicit fallback.
Editor workflow
- Filter by language, context and search text.
- Edit a complete row or perform a quick inline save.
- Create a variable for one language and optionally create the same key for another.
- Compare missing keys between languages.
- Delete an obsolete row deliberately; missing UI strings then use their code fallback where supplied.
Preserve stable variable keys when changing wording. A renamed key is a code change, not merely a translation edit. New modules should use a distinct context and provide an English fallback in code.
15. Spike Forum
Spike is the integrated DAoC CMS forum. It shares users, roles, standing, profiles, notifications and administration with the rest of the platform instead of requiring a separate forum bridge.
Member features
- Categories, boards, privilege-based read/post access and graphical boards.
- Threads with slugs, prefixes, tags, sticky/locked/approval state and subscriptions.
- Rich posts, inline images, separately tracked attachments, smilies and edit history.
- Polls with two or more options, optional multiple choice and optional end time.
- Reactions, mentions, notifications, unread markers and user ignore/block features.
- Search, private messages and post/thread reports.
Forum administration
- Create, order, move and delete categories/boards.
- Move, lock, sticky, approve or delete threads in bulk.
- Merge threads, move individual posts and preview content.
- Process reports with handler notes and status.
- Manage forbidden words, actions/replacements, prefixes and smilies.
- Configure cooldowns, link thresholds, attachments/MIME types, edit history, subscriptions, search, unread markers, tags and other feature switches.
- Clean old read markers and search logs.
Attachment security
The default attachment path is uploads/forum/. Uploads are checked against configured size and MIME allowlists. Inline base64 images are decoded into stored image files; ordinary archives/documents become attachment records. Keep execution disabled in the upload directory at the web-server level.
Public feed
rss.php exposes the latest 20 approved posts from public boards, optionally filtered with ?board=<id>. Protected content and shadow-banned authors are excluded.
16. Dawn of Light and OpenDAoC compatibility
DAoC CMS supports both emulator families. Support does not mean their schemas or runtime APIs are identical; RC2 introduces explicit compatibility boundaries instead of treating OpenDAoC as a byte-for-byte DOL database.
PHP compatibility layer
includes/game_server_compat.php centralizes operations shared by public and ACP modules:
- Core selection and safe default to DOL for older installations.
- UUID-style game object ID generation.
- Schema inspection and case-preserving field filtering before writes.
- Account/character lookup and game privilege resolution.
- Keep ownership across
ClaimedGuildNameversusGuildIDschemas. - Relic identity normalization across
RelicIDand optionalRelic_ID. - Herald population, public-stat privacy, character and guild queries.
- PvE counts, mob/loot resolution, DataQuest reward parsing, item-name and region-label lookup.
Core-specific behavior
| Area | DOL | OpenDAoC |
|---|---|---|
| Mob Editor | acp_mob_editor.php, including DOL fields such as MaxDistance. | acp_mob_editor_opendaoc.php; removes absent MaxDistance, exposes FactionID and avoids a DOL-only default Brain class. |
| Item writes | Physical item-template columns are discovered and unsupported fields are removed before persistence. | |
| Suit merchant pricing | Can use a MerchantItem price column where present. | Uses the referenced ItemTemplate price when MerchantItem has no Price column. |
| Keep claims | Commonly joins keep.GuildID to guild. | Can read keep.ClaimedGuildName directly. |
| Script API differences | Bridge scripts use reflection-based shims for logger creation, player enumeration, release enum placement, command lookup and translation overloads. | |
Switching a running installation
- Back up both databases and the CMS files.
- Point the installation at the intended game database.
- Set
game_server_coreto the matching value. - Clear CSS/OPcache only if code or styles changed; the core selector itself is database-backed.
- Test read-only modules first, then editors on a staging copy.
- Install the matching tested bridge scripts and restart/recompile the game server.
17. Game-data editors
Mob Editor
The Mob Editor is a visual spawn and NPC management environment. It supports zone/region selection, map-based placement, mob creation/editing, templates, loot relationships and patrol routes. The dedicated 2D route editor can associate a route with a selected mob before recording points. A separate OpenDAoC implementation handles core-specific mob fields.
Automatic ground-height or terrain-assisted placement requires the terrain service. Without it, enter a valid Z coordinate or use a known source value.
Item Creator
Searches and edits itemtemplate records. It covers identity, model/slot/type, value/price, quality/condition/durability, bonuses, resists, effects and other fields exposed by the active schema. Writes are filtered against the real table columns so optional fields from another core are not blindly inserted.
Id_nb can alter every merchant, loot table or character inventory that references it. Clone to a new ID unless replacement is intentional.Suit Creator
Builds named equipment sets around a paperdoll. It includes class presets, automatic cap calculations, per-slot item selection, saved revisions, clone/blank generation modes, game-table writes and merchant/export workflows. Saving a suit and writing generated items are separate operations: a CMS-side draft does not alter itemtemplate until the write action is used.
Dataquest Creator
Provides a visual editor and simulator for DataQuest records, including quest text, steps, goals, dialogue and rewards. OpenDAoC serialized per-step XP/money rewards and choice-item encodings are normalized by the compatibility layer when displayed.
Ability Editor
Manages spells, spell lines and their level assignments, combat styles and style spells, abilities, and NPC templates/spells. The editor exposes low-level emulator values such as spell type, target, damage type, timing, range, specialization keys, growth rate and NPC brain/class fields.
Other tools
| Tool | Purpose | Risk profile |
|---|---|---|
| Core Architect | Economy snapshots, wealth analysis and simulation. | Prefer analysis/simulation before applying balancing decisions. |
| Character Editor | Find characters and update selected character fields. | Back up before level, realm, currency or identity changes. |
| Zones Editor | Edit zone properties. | Level 5 only; wrong region/coordinate data affects world behavior. |
| Global Constants | Browse shared constants and ID references used by editors. | Reference-oriented; verify the active client/core version. |
| Server Properties | Edit game-server properties and rates. | Some properties apply only after a server restart. |
Safe editor procedure
- Create a database backup and note the exact table/record identity.
- Use search/read mode to confirm the current record.
- Change the smallest possible field set.
- Verify database persistence.
- Restart or reload scripts only where the game core requires it.
- Test in-game with a non-production object or controlled character.
18. Itemshop
The itemshop is a CMS/game integration, not an external payment processor. shop_system_items defines available game items, category, base price, stock and activation state. Public item views join those definitions with game item templates.
Purchase path
/shop/purchase and DB workAldhranConsole also exposes /shop/cm-listings for consignment merchant offers. The webshop worker retries or finalizes queued delivery work according to the CMS itemshop logic.
Operational rules
- Keep
itemshop_enabledoff until Console status and a test delivery succeed. - Use a restricted game-database user with the rights required by enabled shop features.
- Never expose AldhranConsole directly to customers.
- Test insufficient balance, unavailable stock, offline player and duplicate/retry behavior.
- Audit delivery logs before manually compensating a failed transaction.
19. Herald, PvE database and RvR map
Herald
Displays server population, top characters, individual character records, guilds and members, keeps and relic context. OpenDAoC's public-stat privacy flag is respected by compatibility queries. Avoid bypassing these helpers with new direct queries that would reveal hidden statistics.
PvE database
Provides bestiary and boss views, item search/details, quest lists/details and resolved rewards. Mob loot follows the emulator's mob-name → loot-template → item-template relationships. Region labels and optional schema details are normalized where possible.
RvR map
Reads keep realm ownership, guild claims and relic state from the game database, then normalizes the different DOL/OpenDAoC representations. The JSON/data view should be treated as public game state; do not add staff-only fields to its response without a privilege boundary.
Freshness
These modules query the database when requested; they are not a separate analytics warehouse. “Players online” views that infer activity from LastPlayed use a recency window and are an approximation unless the live Bridge presence endpoint is used.
20. AldhranConsole and AldhranBridge
This is the canonical chain for live administration:
X-Aldhran-SecretAldhranConsole requirements
- .NET 10 SDK to build.
- .NET 10 ASP.NET Core Runtime for a framework-dependent release.
- MySQL/MariaDB connectivity to the game database.
- Network access to AldhranBridge's host/port for live-world actions.
appsettings.json
{
"Console": {
"ListenUrl": "http://127.0.0.1:5100",
"SharedSecret": "REPLACE_WITH_THE_CMS_GAME_SERVER_SECRET",
"DbConnection": "Server=127.0.0.1;Port=3306;Database=GAME_DB;User ID=USER;Password=PASSWORD;",
"BridgeHost": "127.0.0.1",
"BridgePort": 2000,
"BridgeTimeoutSeconds": 8,
"ScriptsPath": ""
}
}
Production values can be supplied as environment variables using double underscores, for example Console__SharedSecret and Console__DbConnection. Legacy ApiSecret, BridgeSecret, DolHost and DolPort keys remain accepted, but current installations should use the canonical keys.
Build and publish
dotnet restore
dotnet build --configuration Release
# Windows framework-dependent publish
dotnet publish --configuration Release --runtime win-x64 --self-contained false --output publish/win-x64
# Linux framework-dependent publish
dotnet publish --configuration Release --runtime linux-x64 --self-contained false --output publish/linux-x64
Run AldhranConsole.exe on Windows or dotnet AldhranConsole.dll on Linux. Keep the published directory together and exclude configured production files, bin/ and obj/ from source releases.
Install AldhranBridge
- Copy the current
AldhranBridge.csto the game server'sscripts/directory. - Replace
CHANGE_ME_BRIDGE_SECRETwith the exact CMS game-server shared secret. - Keep
BRIDGE_PORTsynchronized with the Console configuration (default2000). - Restrict the port by firewall to the AldhranConsole host.
- Restart/recompile scripts and check the server log for
[AldhranBridge] Started on port 2000.
Health tests
curl http://127.0.0.1:5100/health
curl -H "X-Aldhran-Secret: YOUR_SHARED_SECRET" http://127.0.0.1:5100/status
/health proves only that the HTTP process is alive and intentionally exposes no connection details. /status proves the authenticated Console → Bridge round trip.
Capabilities
The bridge handles status and presence, kick, privilege level 0–3, teleport, item delivery, stat changes, heal/revive, freeze/mute, broadcasts, guild chat, scheduled restart and restricted raw commands. shutdown and quit are blocked on both sides of the raw-command boundary.
OpenDAoC script compilation and “Bad IL format”
Use source scripts that are compiled against the target server's own assemblies. The utilities repository includes two PowerShell helpers:
# Diagnose all scripts and print the real CSxxxx source error
.\tools\Test-OpenDAoCScripts.ps1 -ReleasePath "C:\Path\To\OpenDAoC\Release"
# Build lib\GameServerScripts.dll against that exact release
.\tools\Build-OpenDAoCScriptAssembly.ps1 -ReleasePath "C:\Path\To\OpenDAoC\Release"
The diagnostic script deliberately compiles the complete script tree with the installed .NET SDK and the release's own assemblies. This separates a real source/API error from a stale or incompatible precompiled GameServerScripts.dll. Do not distribute one arbitrary precompiled script DLL as universally compatible across different OpenDAoC builds.
21. CMSLiveEvents
CMSLiveEvents.cs subscribes to player-death and keep-capture events and posts them to api_events.php. It is optional and runs inside the game-server script environment.
- Edit
API_URLto the public HTTPS URL ofapi_events.php. - Set
BRIDGE_SECRETto the current game-server shared secret. - Place the file in
scripts/and restart/recompile. - Cause a controlled PvP or keep event and poll
api_events.php?last_id=0.
Authenticated POST requests store ordinary event types/messages in cms_live_events. The public GET path returns up to five newer, escaped events based on last_id. Guild-chat events follow a special relay path and are not stored as ordinary feed events.
22. GuildChatBridge
GuildChatBridge.cs preserves the original /gu behavior while forwarding each successful guild message to the CMS. Because the core suppresses duplicate command registrations, the script replaces the loaded &gu/&guild command entries after scripts load and restores them when unloaded.
Install
- Enable Guild Chat Sync in ACP → Bot & AI Settings. The CMS attempts to add
guild.discord_channel_idif absent. - Configure and start the Discord bot.
- Edit the bridge's
API_URLandBRIDGE_SECRET. - Copy it to
scripts/, restart/recompile and check for script errors. - Link each in-game guild to its Discord channel ID.
- Send
/gu testin game. Confirm the message still reaches guild members and appears in the linked Discord channel.
Outbound game → CMS HTTP work runs asynchronously and intentionally cannot crash the chat command. A failed web request therefore leaves in-game chat working but must be diagnosed from logs and the Discord relay result.
Discord → game
The Node bot listens for Discord messages using GuildMessages and MessageContent, posts a signed guild_chat event to the CMS, and the dispatcher/Console/Bridge chain delivers it to the game guild where configured.
23. Discord bot
The Aldhran DiscordBot is a Node.js process. It is independent of AldhranBridge for startup and ordinary Discord connectivity. Individual commands that perform live game actions still need the corresponding Console/Bridge path.
Required values
| Value | Source | Used by |
|---|---|---|
| Bot Token | Discord Developer Portal → Bot | Node process login to Discord. |
| Public Key | Discord application General Information | bot_interactions.php Ed25519 validation when using the interaction endpoint. |
| Client/Application ID | Discord application | Application identification/invite configuration. |
| Bot Channel ID | Discord channel → Copy ID | Default output channel. |
| Admin Role ID | Discord role → Copy ID | Raises recognized bot command authority to level 4. |
| Bot bootstrap secret | Setup summary / config | Retrieves CMS bot configuration. |
| Socket secret | Generated separately by operator | HMAC signatures for Node bot ↔ CMS traffic. |
Discord application
- Create an application and bot in the Discord Developer Portal.
- Enable Message Content Intent. The bot requests Guilds, GuildMessages and MessageContent; it does not request Presence or Server Members.
- Install it to the target server with application-command support.
- Grant View Channels and Send Messages. Add Manage Channels only for
/createguildchannel. - Do not grant Administrator merely to troubleshoot command registration.
CMS bot settings
Set active state, guild-chat switch, Bot Token, channel/role IDs, reboot delay, socket secret, host, port (default 15000), TLS flag and the path to bot.js. Saving bot settings is restricted to level 5. The Token and socket secret are never redisplayed; leave each input empty to retain the stored value.
Process environment
DAOC_CMS_CONFIG_URL=https://your-domain.example/api_bot_config.php
DAOC_CMS_BOOTSTRAP_SECRET=YOUR_BOT_BOOTSTRAP_SECRET
DAOC_CMS_WEBHOOK_URL=https://your-domain.example/bot_webhook.php
node assets/js/bot.js
The ACP Start Bot action uses the configured script path and supplies the required environment. Manual startup is useful for seeing the exact Node/Discord error in a console.
Registered slash commands
/status, /players, /reboot, /broadcast, /char, /guild, /leaderboard, /aisk and /createguildchannel. Command enable state, minimum AuthLevel, cooldown and per-user/per-level overrides are managed in the Bot Commands ACP section.
Why the bot is online but commands are missing
- Check the Node log for
Slash commands registered globally and for each guild.Being online proves login only, not successful REST registration. - Confirm the bot was installed with the
applications.commandsscope/application-command functionality. - Restart the process after resetting the token or changing the installation.
- Verify that the bot is actually a member of the intended guild when the ready handler loops through guilds.
- Check Discord API errors in the Node console; permissions such as Administrator do not repair a missing installation scope or invalid token.
- Guild registrations should appear quickly; global commands can be cached. Test in the installed guild and restart the Discord client if necessary.
Authentication paths
api_bot_config.php:X-DAOC-CMS-Bootstrapheader and bootstrap secret.bot_webhook.php: raw-body HMAC-SHA256 inX-Webhook-Signature, rate-limited.- Bot socket: HMAC of action + timestamp, maximum 60-second drift, loopback binding in the Node implementation.
bot_interactions.php: Discord Ed25519 signature and timestamp headers.
24. AI providers, tasks and suggestions
The AI subsystem is optional. It supports provider-backed analysis and suggestion workflows; it does not replace operator responsibility. The code supports none, Gemini, LM Studio, Groq, OpenAI and Anthropic configurations.
Configuration
Each provider retains its own encrypted API key, URL and model. Shared controls set active provider, maximum tokens (100–8000) and temperature (0–2), plus module-specific system prompts. Local LM Studio can use a localhost-compatible endpoint.
Workflow
- A module creates a provider request or queued task.
- The response is logged and, for change proposals, stored as a suggestion.
- Staff review the original context and proposal.
- An authorized reviewer accepts or rejects it with an optional note.
- Accepted actions are handled through explicit apply handlers; terminal accepted/rejected suggestions cannot be reverted to pending by the database trigger.
cron_ai_worker.php processes queued work when called by the scheduler. The schema also tracks daily call/task counts, provider keys, logs, tasks and expiry behavior.
/aisk is separately controllable in Bot Commands. Normal Discord features do not require an AI provider.
25. TerrainService and map data
The utilities repository includes a Windows x64 TerrainService package used by tools that need client-derived terrain or ground-height data. It is not part of a basic CMS installation and does not belong in the DOL/OpenDAoC scripts directory.
Use it when
- A map editor requests automatic Z/ground height.
- A placement tool explicitly reports that the terrain endpoint is unavailable.
- The tool documentation mentions the TerrainService or DAoC client library.
Operational guidance
- Run it on a trusted host reachable only by the editor/CMS component that needs it.
- Keep client data/version aligned with the target world data.
- Do not expose a local terrain endpoint publicly without authentication/firewall controls.
- Validate returned coordinates in game before bulk placement.
DaocClientLib remains third-party work and retains its own authorship and licensing; it is not relicensed merely by being used with DAoC CMS.
26. Endpoints and APIs
DAoC CMS has a small set of integration endpoints rather than a general public REST API. Treat each endpoint according to its authentication model. Do not expose a secret-bearing example command in shell history, screenshots or tickets.
CMS endpoints
| Endpoint | Method and purpose | Authentication |
|---|---|---|
api_events.php | POST accepts type and message; guild-chat events also use guild and player. GET ?last_id=N returns up to five newer events. | POST form field secret, checked against the configured game-server secret, bridge secret or legacy ASP_KEY. GET is intentionally public. |
api_bot_config.php | GET supplies the Node bot with its token, loopback socket port/secret and active switches. | X-DAOC-CMS-Bootstrap must equal BOT_BOOTSTRAP_SECRET. |
bot_webhook.php | POST receives JSON events from the Node bot and dispatches them inside the CMS. | X-Webhook-Signature: sha256=<HMAC>, calculated over the raw body with the bot socket secret. The current handler skips verification if that secret is empty, so a production setup must never leave it empty. |
bot_interactions.php | POST handles Discord interaction pings and commands. | Discord X-Signature-Ed25519 and X-Signature-Timestamp, verified with the configured application public key. PHP Sodium is required for this path. |
ajax_status.php, ajax_restart.php, ajax_bot_start.php | Browser actions used by authorized ACP screens. | CMS session, role and request checks; these are not public automation APIs. |
ajax_edit_post.php, ajax_editpost.php, ajax_reports.php | Forum editing and moderation requests. | Logged-in CMS user plus the applicable forum permission and CSRF controls. |
rss.php, sitemap.php, robots.php | Public discovery and syndication resources. | Public; output follows the current content and visibility configuration. |
Live-event examples
# Publish a server event. Use an environment variable or protected secret store in real automation.
curl -X POST "https://cms.example/api_events.php" \
--data-urlencode "secret=REDACTED" \
--data-urlencode "type=keep_capture" \
--data-urlencode "message=Albion captured Caer Benowyc"
# Read events newer than ID 120
curl "https://cms.example/api_events.php?last_id=120"
The GET result has the shape {"ok":true,"events":[...]}. Each event contains id, type, message and time. Clients should retain the highest processed ID and tolerate an empty array.
AldhranConsole HTTP API
The console defaults to http://127.0.0.1:5100. /health is unauthenticated; all other routes require X-Aldhran-Secret. The CMS console client calls route names without the leading slash.
| Method | Route | Purpose |
|---|---|---|
| GET | /health | Process health only; a successful response does not prove the bridge or game server is reachable. |
| GET | /status | Integrated status of console, bridge and game-facing components. |
| POST | /players/online | Returns which names from a supplied list are online; used by webshop delivery. |
| POST | /kick, /privlevel, /teleport, /giveitem, /setstats | Player administration and item delivery. |
| POST | /broadcast, /guildchat, /raw | Messaging and advanced bridge command dispatch. Raw blocks shutdown/quit commands but remains highly privileged. |
| POST | /restart, /heal, /revive, /freeze, /mute | Live server/player operations implemented by the C# bridge. |
| GET | /items/search | Searches compatible item records. |
| GET/POST | /shop/cm-listings, /shop/purchase | Consignment-merchant listing and purchase integration. |
| GET/POST | /world-forge/realms, /world-forge/upload, /world-forge/sync-realm | World Forge realm inspection, upload and synchronization. |
# Process liveness
curl http://127.0.0.1:5100/health
# Integrated status
curl -H "X-Aldhran-Secret: REDACTED" http://127.0.0.1:5100/status
27. Database model
DAoC CMS uses two logical data domains. The CMS database owns website users, content, settings, forum, logs and integration state. The game database remains the authority for accounts, characters, guilds, items, world data and server properties. They may be separate schemas on one server or on different MySQL hosts, provided the CMS credentials have the required access.
Major CMS table families
| Area | Representative tables | Responsibility |
|---|---|---|
| Identity and trust | users, user_known_devices, user_blocks, login_attempts, ip_bans | CMS identity, privilege level, verification, TOTP/device state, blocks and abuse controls. |
| Content | pages, pages_history, pages_media, pages_templates, faq, cms_menu | Published pages, revision history, uploaded media, templates, FAQ and navigation. |
| Localization and appearance | cms_languages, cms_translations, aldhran_themes, aldhran_styles, aldhran_styles_history | Language catalog, translation keys, theme definitions, CSS and style revisions. |
| Spike Forum | spike_categories, spike_boards, spike_threads, spike_posts, spike_attachments, spike_reports, spike_notifications, spike_mentions | Forum hierarchy, posts, attachments, moderation and unread/notification state. |
| Messaging | pm_messages, cms_live_events, cms_gm_tasks | Private messages, public live feed and staff task workflow. |
| Discord and bot | cms_bot_settings, cms_bot_commands, cms_bot_command_permissions, cms_bot_events, bot_debug_logs | Bot secrets/settings, command policy, dispatch queues and diagnostics. |
| AI | cms_ai_settings, cms_ai_provider_keys, cms_ai_tasks, cms_ai_suggestions, cms_ai_logs | Provider configuration, queued jobs, reviewed proposals and usage/error history. |
| Commerce and tools | shop_system_items, webshop_orders, cms_suit_templates, cms_suit_template_items, igc_zone_points | Shop catalog/delivery, reusable equipment suits and coordinate points. |
| Operations | settings, cms_backups, admin_logs, aldhran_logs, sys_error_log, aldhran_plugins, plugin_documentation | Runtime configuration, archive inventory, audits/errors and plugin lifecycle. |
Game schema compatibility
Common game tables include account, dolcharacters, guild, itemtemplate, mob, mobxitemtemplate, merchantitem, dataquest, keeps, relics, zones and server properties. Exact names, identifiers and columns differ between Dawn of Light and OpenDAoC. Use includes/game_server_compat.php or module-specific compatibility helpers instead of duplicating schema assumptions.
- Character, guild and item identifiers can be numeric, textual or UUID-like depending on the core/schema.
- Privacy filters must be applied before exposing Herald or account-linked character data.
- OpenDAoC-specific editor behavior includes different mob fields and optional/default brain behavior.
- Merchant and suit pricing can belong to different tables across supported layouts.
Connection policy
- Use separate MySQL users for the CMS schema and game schema where practical.
- Grant only the operations required by enabled modules. Editors and restore tools require writes; public Herald/PvE pages can operate with reads.
- Use
utf8mb4for the CMS database. - Do not point setup's public-schema import or uploaded-schema option at a populated production game database: those workflows are intended to create/import a schema and can be destructive.
- Take transactionally consistent backups before migrations, restores, bulk edits or compatibility experiments.
Migrations
Fresh setup installs the baseline schema and records migration baseline 20260812000000. Later schema changes live in migrations/. A migration file is named YYYYMMDDHHMMSS_short_description.php and returns a callable. Fresh-install SQL and migrations must converge on the same final schema.
php migrate.php --status
php migrate.php
migrate.php is CLI-only. Run status first, back up both databases, apply once, then run status again. Never mark a migration as complete manually unless you have audited and reproduced its exact effect.
28. Plugins, hooks and extensions
Plugins are PHP classes loaded by the CMS and therefore execute with the web process's access to files, databases and secrets. Install only reviewed source from a trusted origin. The Plugin Manager is a Super Admin operation in the effective implementation.
File and class contract
An upload is limited to 512 KB and its filename must match NamePlugin.php. The class implements PluginInterface and provides the methods below. Start with plugins/ExamplePlugin.php, but replace its demonstration remote asset with a reviewed local asset.
| Method | Purpose |
|---|---|
public static function getMetadata(): array | Returns at least slug, display name, version and descriptive metadata. Dependencies and minimum privilege can also be declared. |
__construct(PDO $db, int $userPriv, int $currentUserId) | Receives the active CMS database connection and current authorization context. |
initialize(): void | Per-request setup. Keep it idempotent and light. |
registerHooks(): void | Registers callbacks through cms_register_hook(). |
render(): string | Returns the plugin's page output where the host router invokes it. |
uninstall(): bool | Removes plugin-owned state when safe and reports success. Do not delete user data silently. |
Allowed hook points
| Hook | Placement / return | Output handling |
|---|---|---|
hook_head | Public page <head> | Raw head markup; asset policy still applies. |
hook_after_header | Immediately after the public header | Script-aware filtering. |
hook_sidebar_nav | End of public sidebar navigation | Purified HTML. |
hook_footer | Public footer before </body> | Purified HTML. |
hook_acp_head | ACP <head> | Raw head markup; use only reviewed local assets. |
hook_acp_sidebar_nav | ACP navigation additions | Purified HTML. |
hook_acp_dashboard_top | Top of ACP dashboard | ACP-card filtering. |
hook_acp_dashboard_modules | Dashboard card grid | ACP-card filtering. |
hook_acp_register_section | Returns ACP section registration data | Structured array. |
hook_acp_register_view | Returns ACP view callable registration | Structured array/callable. |
Minimal pattern
<?php
class StatusNotePlugin implements PluginInterface
{
public static function getMetadata(): array
{
return [
'slug' => 'status_note',
'name' => 'Status Note',
'version' => '1.0.0',
'description' => 'Adds a small status note.',
'dependencies' => [],
'min_priv' => 1,
];
}
public function __construct(private PDO $db, private int $userPriv, private int $currentUserId) {}
public function initialize(): void {}
public function registerHooks(): void
{
cms_register_hook('hook_footer', fn(): string => '<p class="status-note">Shard status updated hourly.</p>');
}
public function render(): string { return ''; }
public function uninstall(): bool { return true; }
}
Extension rules
- Escape dynamic output and use prepared PDO statements.
- Apply CMS authorization and CSRF checks to every state-changing action; metadata
min_privis not a substitute. - Namespace tables, settings, routes, CSS selectors and translation keys with the plugin slug.
- Add schema changes through reversible plugin setup logic or project migrations, with clear uninstall data-retention behavior.
- Use local CSS/JS. The core local-asset policy has no general remote CDN allowlist.
- Never store tokens in the plugin file or return them in rendered HTML.
- Test disabled, enabled, update and uninstall paths on a staging copy before production.
29. Operations, updates and recovery
A reliable installation separates routine content work from privileged maintenance. Define who may deploy code, run migrations, restore data, rotate secrets and operate the live bridge. Keep a written recovery path that still works when the CMS itself is unavailable.
Recommended maintenance cycle
- Announce a maintenance window if game or account data may be affected.
- Enable maintenance mode and verify that authorized staff retain access.
- Back up CMS files, CMS database and game database. Copy the verified archive off the web host.
- Review the target published release notes, PHP/MySQL requirements and migration status.
- Deploy the published release through the same method used for the installation.
- Run
php migrate.php --status, thenphp migrate.phpif pending migrations exist. - Clear the CMS/CSS cache and reset OPcache through the Cache ACP section or the host process.
- Smoke-test login, ACP, content, forum, game-database pages and every enabled integration.
- Disable maintenance mode, monitor error/audit logs and retain the pre-change backup until the release is stable.
Git-based update
git status
git fetch origin
git pull --ff-only origin main
php migrate.php --status
php migrate.php
Do not pull over unexplained local modifications. Commit the customization on a separate branch or recreate it as a maintained plugin/theme. The ACP update widget compares VERSION, local Git revision and published GitHub releases; it is informational and follows the published-release policy.
Backup Manager
The ACP backup feature can archive site files and create dumps of the CMS and game databases. ZIP and 7-Zip workflows are supported when their executables are configured. Database export/import uses the configured mysqldump and mysql paths. Built-in Windows/XAMPP-looking paths are examples, not requirements—set the actual executable paths on the host.
- Add a clear description and optional PIN according to your operational policy.
- Run archive verification and check that both database dumps are present.
- Download or replicate backups to a separate system with restricted access.
- Periodically restore into an isolated environment; an untested archive is not a recovery plan.
- Restore modes can target all data, databases, ACP/CMS data or game data. Resolve the exact selection before confirming because restore overwrites live state.
Schedulers and background work
| Worker | Typical cadence | Responsibility |
|---|---|---|
cron_ai_worker.php | Based on expected task volume | Processes queued AI work and suggestion tasks. Run only when the AI subsystem is intentionally configured. |
includes/cron_webshop_worker.php | Every 30–60 seconds | Checks pending recipients through AldhranConsole and delivers paid items when the player is online. Stops retrying an order after ten failed delivery attempts. |
| Bot process | Continuous service | Runs node assets/js/bot.js; use a service manager with restart limits and protected environment variables. |
| AldhranConsole | Continuous service | Hosts the local HTTP API and maintains access to the game bridge/database. |
# Linux cron example; replace paths and PHP binary
* * * * * /usr/bin/php /var/www/daoc-cms/includes/cron_webshop_worker.php >> /var/log/daoc-webshop.log 2>&1
# Windows Task Scheduler action example
Program: C:\php\php.exe
Arguments: C:\sites\daoc-cms\includes\cron_webshop_worker.php
Cache behavior
The Cache ACP section bumps the CSS asset version and can reset OPcache. Browser responses may retain ETag/cache state for up to 24 hours. After a theme or stylesheet deployment, clear server-side caches first, then hard-refresh one test browser before diagnosing the code as stale.
Logs and retention
- Admin logs: privileged actions and actor context.
- Aldhran logs: bridge/integration activity.
- System error log: captured application errors; PHP also writes to
php_errors.logwhen configured by the CMS bootstrap. - Bot debug/event logs: configuration, socket, webhook and command troubleshooting.
- Web server, PHP, Node, service and game logs: required for failures that occur before CMS logging starts.
IP addresses recorded by CMS audit helpers are anonymized at the last IPv4 octet or final IPv6 component. Some security records are pruned after 30 days and unverified registrations after seven days; external infrastructure logs follow their own retention policy.
Daily health checklist
- Public homepage and login load over HTTPS without warnings.
- CMS and game database connections succeed.
- No unexpected maintenance banner or critical-integrity alert is present.
- Recent error/admin logs contain no unexplained spike.
- AldhranConsole
/healthand authenticated/statusmatch expected state. - Bot process, commands and any guild-chat relay operate in the intended guild.
- Pending webshop orders are not accumulating at the retry limit.
- The latest off-host backup exists and the last restore test is still within policy.
30. Security model and production checklist
DAoC CMS contains layered controls—strict sessions, CSRF validation, role checks, prepared statements, upload validation, rate limits, audit logs and web-server deny rules—but secure deployment still depends on the surrounding host and correct secrets. A feature being reachable only from the ACP does not make its network calls safe by default.
Built-in protections
- Session cookies are HTTP-only, SameSite Strict, Secure and tied to an instance-specific name; strict/only-cookie modes are enabled and the default session lifetime is one hour.
- ACP access begins at privilege level 3. Sensitive level-5 access requires TOTP and privileged operations use recent-authentication controls.
- CSRF tokens protect state-changing browser actions, while integration endpoints use dedicated secrets, HMAC or Ed25519 signatures.
- Core database paths use prepared PDO statements and compatibility-aware helpers.
- Upload paths check extension/MIME and are protected by server rules; directory indexing is disabled by the supplied
.htaccess. - Configuration, database helpers, logs, SQL/YAML files, dependency manifests, migrations, hidden files and backup content are denied by the Apache rules.
- Production PHP error display is disabled while server-side logging remains active.
Required production controls
- Serve the entire site through HTTPS and redirect HTTP before application handling. Secure session cookies will not work correctly on plain HTTP.
- Keep
includes/config.phpoutside backups shared with untrusted parties and deny it at the web server even when not using Apache. - Delete or web-deny
setup/after installation and retaininstall.lock. - Use a dedicated OS account for the web process; grant write access only to required upload, cache, backup, plugin and configuration paths.
- Use strong, unique values for password pepper,
ASP_KEY, Aldhran shared secret, bot bootstrap secret, bot socket secret, database passwords, Discord token and provider keys. - Restrict MySQL to required hosts and use least-privilege accounts; never expose port 3306 to the public internet.
- Bind AldhranConsole and the Node bot socket to loopback when possible. Firewall game bridge and management ports.
- Require TOTP for all Super Admins, keep the group very small and never share administrator accounts.
- Keep backups encrypted/restricted and off-host; they contain credentials, private messages and account/game data.
- Review and patch PHP, web server, MySQL, Node.js, .NET and the operating system on a defined schedule.
Secret inventory and rotation
| Secret | Consumers | Rotation effect |
|---|---|---|
Password pepper / ALDHRAN_PEPPER | CMS password processing | Changing it can invalidate existing password verification. Plan a migration/reset path; do not casually rotate. |
ASP_KEY | Legacy/fallback server integrations | Update every remaining consumer; prefer a feature-specific secret where supported. |
| Game-server/Aldhran shared secret | CMS, AldhranConsole and AldhranBridge/event scripts | Restart/reload components after updating both sides; mismatches return 401 or bridge authentication errors. |
BOT_BOOTSTRAP_SECRET | Node bot startup → api_bot_config.php | Update the bot environment and restart it. |
| Bot socket secret | Node bot, CMS webhooks/socket dispatch | Update ACP state and bot configuration together; confirm webhook signatures afterward. |
| Discord token/public key | Node login / interaction verification | Reset token in Discord, save in ACP and restart. Public key is not confidential but must be authentic. |
| AI/API keys and SMTP key | Optional outbound providers | Rotate at provider, update the encrypted CMS setting, then send a limited test request. |
Reverse proxy and non-Apache servers
The bundled .htaccess protects Apache deployments only. Recreate the deny rules in nginx, IIS or the chosen proxy. Preserve the real client IP only from trusted proxy addresses, set HTTPS forwarding correctly and do not allow direct access to the backend that bypasses TLS or path restrictions.
Incident response
- Contain: enable maintenance mode, restrict ingress or stop affected bot/bridge services.
- Preserve: snapshot relevant logs and database/files before cleanup.
- Scope: identify account, secret, endpoint, host and time range involved.
- Rotate exposed feature secrets and revoke sessions/tokens. Treat a leaked database or config backup as multiple secret exposures.
- Repair from a known-good release or verified backup; apply patches and migrations.
- Validate integrity, privileged accounts, plugins, scheduled tasks and bridge scripts before reopening.
- Document the event and prevention changes without publishing credentials or an exploitable proof before users can patch.
31. Troubleshooting guide
Start with the smallest failing boundary. Record the exact URL/action, timestamp, HTTP status or exception, active core type and recent change. Test from the same host and user context as the failing component; a successful request from an administrator workstation may not prove reachability from PHP, Node or the game process.
| Symptom | Likely causes | Checks and correction |
|---|---|---|
| Setup redirects or reports already installed | install.lock exists or setup is web-denied. | Do not delete the lock on a live installation. For an intentional clean reinstall, back up and recreate an empty target environment first. |
| Requirement/permission check is red | PHP below 8.2, missing PDO/MySQL/JSON/cURL/ZIP/Fileinfo/Zlib, or unwritable required paths. | Compare web-PHP and CLI-PHP versions/modules. Grant the web process minimal write access to the paths named by the installer. |
| CMS database test fails | Host/port/user error, missing create-table rights during test/install, TLS/firewall or wrong MySQL server. | Connect from the web host with the same credentials; verify the empty CMS schema and MySQL 8 compatibility. |
| Login loops or never persists | Site is served over HTTP while cookies are Secure, proxy HTTPS headers are wrong, or hostname/path changed. | Use HTTPS, correct trusted-proxy forwarding and verify the browser receives the instance-specific session cookie. |
| ACP access denied | Privilege below 3, stale session, recent-authentication expired, or level-5 TOTP not complete. | Confirm the user's effective level and reauthenticate. Repair account state through a controlled database procedure only if no valid Super Admin remains. |
| Unknown column/table in Herald, PvE or editor | Wrong game_server_core, custom schema drift or incomplete public schema. | Select DOL/OpenDAoC correctly, compare the failing query with the real schema and extend compatibility helpers rather than hard-coding one fork. |
| C# script fails with CS compiler errors | Source API differs from the target game-server release. | Run Test-OpenDAoCScripts.ps1 against the exact release folder and fix the reported symbol/type incompatibility. |
| Game server reports bad IL / invalid program | Script was compiled against mismatched assemblies or by a different pipeline. | Use Build-OpenDAoCScriptAssembly.ps1 against the exact target release and deploy the resulting compatible assembly/source as required by that core. |
AldhranConsole /health works but CMS commands fail | Health only proves the HTTP process. Secret, BridgeHost/Port, game script or firewall can still fail. | Call authenticated /status, inspect console and game logs, then test TCP reachability to bridge port 2000 (or configured value). |
| AldhranConsole returns 401 | X-Aldhran-Secret differs from SharedSecret. | Compare exact values without posting them publicly; remove surrounding whitespace, update both sides and restart/reload. |
| CMS reports console unreachable / 502 | Wrong host/port, console stopped, loopback used across different machines, or firewall. | From the PHP host, request /health. Use the console host's private address only when services are on separate hosts and secure that route. |
| Discord bot is online but slash commands are absent | Missing application-command installation, registration REST error, wrong guild or stale Discord client cache. | Check Node log for successful global and per-guild registration, reinstall with command support, restart the bot and test in a guild it joined. |
| Discord bot cannot load config | Wrong DAOC_CMS_CONFIG_URL, bootstrap secret, TLS trust or HTTP routing. | Request the URL from the bot host with the header, check 401/404/TLS output, then restart after correction. |
| Bot socket test fails | Node process stopped, host/port mismatch, secret mismatch or port bound only on another host. | Confirm the process is listening on the configured loopback port (default 15000) and that CMS and bot use the same socket secret. |
| Guild chat works in game but not Discord | Guild sync disabled, no discord_channel_id, bot cannot send to channel, or event secret mismatch. | Enable sync, map/create the guild channel, verify channel permission, then inspect api_events.php and bot event logs. |
| Live feed stays empty | C# event script missing/not loaded, endpoint/secret wrong, or browser is polling a different CMS instance. | POST a safe manual event, inspect response/logs and verify INSTANCE_ID/site URL and game script configuration. |
| Webshop order remains pending | Worker not scheduled, player offline, Aldhran presence call fails, item ID invalid or ten-attempt limit reached. | Run the worker once in a console, inspect its log and order fields, verify /players/online and /giveitem with a staging item. |
| Theme/CSS change not visible | CMS CSS version, OPcache, proxy cache or browser ETag cache is stale. | Use ACP Cache, reset OPcache if applicable, purge the trusted proxy cache and hard-refresh. |
| Critical security banner appears | Audit-integrity anomaly or IP-registration threshold triggered. | Do not suppress it first. Preserve logs, review recent administrator/account actions and determine whether it is attack traffic, corruption or a known maintenance effect. |
| Game log shows network error 10060 / UPnP | Game-server port mapping or outbound network timeout. | Diagnose the game server's UPnP/router settings separately. It is not evidence that the CMS HTTP or Aldhran bridge secret is wrong. |
OpenDAoC script diagnostic commands
.\tools\Test-OpenDAoCScripts.ps1 -ReleasePath "C:\Path\To\OpenDAoC\Release"
.\tools\Build-OpenDAoCScriptAssembly.ps1 -ReleasePath "C:\Path\To\OpenDAoC\Release"
The tools compile against the complete source tree and the exact target release assemblies, which distinguishes normal C# compile failures from runtime bad-IL/assembly mismatches.
Evidence to include in a useful bug report
- DAoC CMS version from
VERSIONand Git commit if installed from Git. - Game core (DOL/OpenDAoC), exact release/fork and database schema version.
- PHP, MySQL, web server, operating system and—where relevant—Node/.NET versions.
- Exact reproduction steps, expected result, actual result and timestamp/timezone.
- Sanitized error text and the relevant narrow log window.
- Whether the problem reproduces with custom plugins/theme disabled in a staging copy.
32. Development workflow
The main application repository is github.com/Darku11/daoc_cms. C# bridges, AldhranConsole, terrain package and compatibility tools live in github.com/Darku11/daoc_cms_utilities. Keep changes focused and test every affected boundary.
Local preparation
git clone https://github.com/Darku11/daoc_cms.git
cd daoc_cms
git switch -c fix/short-description
php -v
php -m
Use a disposable CMS database and a copy or purpose-built public game schema. Never develop destructive editors against the only production database. Enable visible errors only in the isolated development environment; production should retain server-side logging.
Project structure
| Path | Responsibility |
|---|---|
index.php, header.php, sidebar.php, footer.php | Public routing and shared layout. |
acp.php | ACP routing, section authorization and view loading. |
includes/ | Database/bootstrap, compatibility, integrations, hooks, AI, bot, templates, errors, update and shared services. |
modules/ | Public and ACP logic/view modules. Preserve separation where a module has explicit _logic and _view files. |
setup/ | Installer, schema sources, configuration writer and downloadable bridge assets. |
migrations/ | Ordered upgrades for installed systems. |
plugins/ | Optional trusted PHP extensions. |
templates/, themes/styles tables | Layout rendering and database-backed appearance. |
tests/ | Automated checks currently included with the project; extend for regressions. |
Change checklist
- Reproduce the issue and write down the affected core/schema.
- Keep SQL prepared and route schema differences through compatibility helpers.
- Add role, recent-auth, TOTP and CSRF checks appropriate to the operation.
- Escape browser output and validate uploaded files/JSON/IDs at the boundary.
- Update both fresh-install schema and a timestamped migration for structural database changes.
- Add/update translations rather than embedding new user-facing strings where the module is localized.
- Test DOL and OpenDAoC for shared game-data logic or clearly mark the feature core-specific.
- Test fresh install, upgrade, maintenance mode and a non-Super-Admin role relevant to the feature.
- Check logs for new warnings and verify no secrets or generated configuration entered the commit.
- Update documentation and release notes for configuration, migration, endpoint or deployment changes.
PHP checks
# Syntax-check tracked PHP files
git ls-files '*.php' | while read -r file; do php -l "$file" || exit 1; done
# Migration state against the development database
php migrate.php --status
The repository includes tests/DeviceCheckTest.php; run it with the compatible test runner available in the development environment. The absence of a broad packaged test suite means linting and a documented manual matrix remain important.
AldhranConsole development
cd AldhranConsole
dotnet restore
dotnet build
dotnet run
The current project targets net10.0, version 2.6.0, and uses MySqlConnector 2.6.1. Configure a development-only appsettings.json; never commit real connection strings or shared secrets.
Pull requests
Small fixes, documentation and translations can be submitted directly. Discuss larger features or architecture first. Describe the reason, testing, core compatibility, database/config changes and operational impact. Contributions are distributed under GPL-3.0-only and must not import incompatible third-party material.
33. License, support and glossary
License
DAoC CMS project-owned source is licensed under the GNU General Public License v3.0 only (GPL-3.0-only). The repository LICENSE contains the controlling terms. Bundled or referenced third-party components, game data, fonts, images and other assets retain their original copyright and license notices; a DAoC CMS SPDX header does not override those terms.
Contributors retain copyright in their own contributions and agree that submitted work is distributed under GPL-3.0-only. Modified redistributions must satisfy the GPL, preserve applicable notices and identify modifications as required by the license. This summary is operational guidance, not a substitute for the license text.
Support and reporting
- GitHub issues for reproducible public defects and enhancement discussions.
- Aldhran community forum for CMS support and bug reports.
- DAoC CMS / Aldhran Discord for community discussion.
Report exploitable security issues privately first; do not open a public issue containing an active exploit, secret or private dataset. Include a safe impact description, affected version and a private reproduction path.
Glossary
| Term | Meaning in this documentation |
|---|---|
| ACP | Administration Control Panel, reached through acp.php. |
| AuthLevel / privilege level | CMS authorization scale from Guest/0 through Super Admin/5. Game-server privileges are related operationally but must not be assumed identical in every core. |
| DOL | Dawn of Light game-server implementation/schema family. |
| OpenDAoC | Supported DOL-derived server implementation with schema/API differences handled by compatibility code. |
| AldhranConsole | .NET HTTP management service used by the CMS and integrations. |
| AldhranBridge | C# game-server script accepting authenticated TCP commands from AldhranConsole. |
| CMSLiveEvents | C# game-server script that publishes selected game events to api_events.php. |
| GuildChatBridge | C# script that preserves guild-command checks and relays eligible guild chat to the CMS/Discord path. |
| Minimal integration | Website/community features with CMS and game database access but without live C#/.NET/Node services. |
| Full integration | CMS plus compatible game schema, live bridge/console, selected C# scripts and optional Discord/worker services. |
| Migration | Ordered, code-owned database change applied by CLI to bring an existing installation forward. |
| Public game schema | A schema/data subset intended for public CMS features; it is not a substitute for understanding the production core's real schema. |
Final production acceptance
- Version and chosen game core are recorded.
- Setup is locked and protected; HTTPS and secure sessions work.
- CMS and game database permissions match enabled features.
- At least two authorized operators can access the ACP, with level-5 TOTP verified.
- Backups are verified off-host and a restore has been tested.
- Every enabled bridge, bot, event, guild-chat and worker path passes its own test.
- Secrets are unique, stored outside source control and covered by a rotation procedure.
- Monitoring/log retention and a maintenance/update owner are defined.
Documentation baseline: DAoC CMS 1.0.0-rc2 and the matching utilities repository state reviewed on 13 August 2026. For later releases, read published release notes and migrations before treating a field, route or default as unchanged.