Web & search stack internals
The web-serving half of BOA: how Provision turns an Aegir site node into an
Nginx vhost + a settings.php, where the edge-map wall that fronts every
request is declared, and how the Barracuda installer lays down the Solr search
backends those vhosts talk to. Two languages meet here — the vhost/settings
generator is Drush 8 / PHP 5.6-floor PHP inside the Provision fork, the Solr
installer is Barracuda-side bash inside boa-private — and a change on either
side has to survive the other's assumptions. If you touch server.tpl.php, a
settings template, or solr.sh.inc, this is the wiring your change lands in.
The render pipeline in one pass
Every Nginx config file BOA writes goes through the same Provision_Config
machinery, driven by the nginx service class
(Provision_Service_http_nginx, http/Provision/Service/http/nginx.php:3).
init_server() registers which config classes render at server vs site scope
(nginx.php:23-25,39-40), and save_server()/verify_server_cmd() probe the
running box — nginx -V feature flags, socket-vs-port PHP-FPM mode, the
/data/conf/global.inc BOA-mode marker — and stash the results as server
properties the templates read (nginx.php:44-160). Each registered class is a
Provision_Config subclass whose write() runs the fixed cycle in the base
(Provision/Config.php:195): process() populates $this->data, load_template()
resolves the .tpl.php (through the provision_config_load_templates[_alter]
hooks, Config.php:117-160), and render_template() eval('?>' . $template)s
it with $this and $data in scope (Config.php:169-186) before
file_put_contents writes the file — then Provision_Config_Http::write()
->sync()s it to the target server (http/Provision/Config/Http.php:10-13).
The three server/site classes and what they emit:
| Class | Template | Renders to | Contains |
|---|---|---|---|
Provision_Config_Nginx_Server (Nginx/Server.php) |
server.tpl.php |
<config_path>/nginx.conf (Http/Server.php:21-24) |
the http-block edge maps + limit_*_zones |
Provision_Config_Nginx_Inc_Server (Nginx/Inc/Server.php) |
Inc/vhost_include.tpl.php |
<include_path>/nginx_vhost_common.conf (Http/Inc/Server.php:41-44) |
the per-request guard chain every vhost includes |
Provision_Config_Nginx_Site (Nginx/Site.php) |
vhost.tpl.php (vhost_disabled.tpl.php when down) |
<http_vhostd_path>/<uri> (Http/Site.php:13-19,37-39) |
the site server block, DB creds, include nginx_vhost_common.conf |
The SSL variants (Nginx/Ssl/*, registered by nginx/ssl.php) render the
quic-enabled listeners; the subdir feature adds Provision_Config_Nginx_Subdir
_SubdirVhostonly whenprovision_hosting_feature_enabled('subdirs')(nginx.php:37-41). All of them extend the same base, so the pipeline above is invariant — only the template andfilename()change.
Both server-scope classes also splice in drush_command_invoke_all('provision_nginx_server_config', …) / _vhost_config output (Nginx/Server.php,
Nginx/Site.php), the extension seam documented on the
Aegir backend APIs topic — that is how a hosting_* module
injects config without editing a template.
Where the four leaves sit
Aegir site node ──(verify task)──▶ Provision http service
│
┌────────────────────────────────────┼───────────────────────────────┐
│ server.tpl.php (once per server) │ vhost.tpl.php / vhost_ssl │ settings template
│ http { ... maps + geo + zones } │ (once per site) │ (once per site)
│ $is_banned, $is_cms_probe, │ server { listen; server_name;│ settings.php:
│ $is_ai_*, $cache_uid, │ fastcgi_param db_* creds; │ literal db creds,
│ $boa_i18n_* ... │ include nginx_vhost_common }│ global.inc chain,
│ ↓ [1 edge maps] │ ↓ [2 vhost generator] │ local.settings.php
│ Inc/vhost_include.tpl.php │ │ ↓ [3 settings wiring]
│ guard chain: if ($is_*) return 444│ │
└────────────────────────────────────┴───────────────────────────────┘
│
php-fpm ──▶ Drupal ──▶ Search API / Solr
↑ [4 Solr installer: solr.sh.inc]
- [1] Edge maps are declared in
server.tpl.php(http scope, once per server) and enforced invhost_include.tpl.php(per request, in every vhost). Splitting declaration from enforcement is deliberate: a map is a cheap constant-time lookup, so the guard chain is a flat list ofif ($is_x) return 444;with no per-request regex. - [2] The vhost generator is
vhost.tpl.php/Ssl/vhost_ssl.tpl.phpplus theProvision_Config_Nginx_*classes that render them — the per-site server block, the DB-credfastcgi_paraminjection, and theincludethat pulls in the shared guard chain. - [3] settings.php wiring is the Drupal-side companion: BOA writes the DB
creds literally into
settings.php(BOA turns Aegir's$_SERVERdb-cloaking off —cloaked_db_creds()returns FALSE), plus the three-levelglobal.inc→ platform →local.settings.phpinclude chain. - [4] The Solr installer is Barracuda-side bash —
solr.sh.inclays down the Solr 4/7/9 backends and their JVM/service wiring that Search-API vhost traffic ultimately reaches.
Hold that picture; each leaf zooms into one box.
Pages in this topic
- Vhost generator (Provision Nginx config classes) —
the
Provision_Configrender cycle end to end: the nginx service class (nginx.php) and itsinit_server/save_server/verify_server_cmdfeature probing, the server/inc/site class split and theirfilename()targets, theeval-based template render, the disabled-vhost template swap (Http/Site.php:37-39), the subdir generator's per-aliaswrite()loop (Nginx/Subdir.php), thenginx_vhost_common.conflegacy symlinks (Http/Inc/Server.php:14-37), and thepost.doperator-override drop points the rendered vhostincludes. Note for accuracy: the per-site rendered SSL listener islisten {ip}:{port} quic;withoutreuseport(Ssl/vhost_ssl.tpl.php:64-66) —reuseportbelongs only to the wildcard master listener, not the per-site vhost. - Edge map mechanics (server.tpl.php) — the full http-block
map/geo catalogue and the two-stage declare-then-enforce idiom: the
geo $remote_addr $is_bannedban wall (server.tpl.php:473), the$is_cms_probeforeign-CMS whole-segment probe map (server.tpl.php:458), the AI-crawler class maps and theirlimit_req_zonerate keys (server.tpl.php:314-424,109-111), the$cache_uidsession map (server.tpl.php:889) that authoritatively decides anon-vs-authenticated, the$boa_i18n_guard/$boa_i18n_path/$boa_is_anon→$boa_i18n_anon_keychain and itslimit_conn boa_i18n_anoncap (server.tpl.php:924-955,120), and why every one of these is amapeven when it looks like a constant (songinx -tnever sees an undefined variable). Enforcement of each lives in the guard chain (vhost_include.tpl.php:183-211,return 444). - settings.php wiring (Drupal settings templates) —
Provision_Config_Drupal_Settings(Config/Drupal/Settings.php) and the per-major template selection (provision_drupal_settings_{6..11}.tpl.php,Settings.php:18-68): the$this->cloakedDB-credential switch that on BOA resolves FALSE (the nginx service'scloaked_db_creds()returns FALSE,nginx.php:17-19), so the template writes literal creds via itselsebranch (settings_7.tpl.php:95-117) — not the stock-Aegir$_SERVERcloak branch — theutf8mb4/hash-salt/db_typemysqli→mysql normalisation, theprovision_drupal_configextension hook feeding$extra_config, and the fixed include cascade/data/conf/global{,-N}.inc→ platformsettings.php/platform.settings.php→ per-sitelocal.settings.php(settings_7.tpl.php:200-224), the last of which Provision creates blank and locks to0440(Settings.php:95-114). - Solr installer (solr.sh.inc) — the Barracuda-side
search backend layer:
_if_install_upgrade_solr(solr.sh.inc:447), invoked fromBARRACUDA.sh.txt:578when/root/.deny.java.cnfis absent, and its three version ladders — Solr 4 on Jetty 9 (_if_solr_four, port 8099), Solr 7 (_if_solr_seven, port 9077), Solr 9 (_if_solr_nine, port 9099) — each gated on anSRntoken in_XTRAS_LIST, an existing data dir, or a hosted-sys marker (solr.sh.inc:454-477). Covers the pinned versions inBARRACUDA.sh.txt(_SOLR_4_VRN/_SOLR_7_VRN/_SOLR_9_VRN/_JETTY_9_VRN,:135-137,65), the_get_dev_archmirror fetch, theinstall_solr_service.shinvocation, the per-version-file idempotency guards (solr-<VRN>-version.txt), the JDK-pinned/etc/default/solrN.in.shrewrite (Java 11/17/21 by_OS_CODE), the_UP_JDKrestart path, and wheremanage_solr_config.shfits for core config sync.
Adjacent developing topics
- Aegir backend APIs — the
provision_nginx_server_config/provision_nginx_vhost_config/provision_drupal_confighooks these templates invoke, and the Provision template-alter chain ahosting_*extension uses to add config without patching a.tpl.php. - Install & staged-setup internals — how the
Provision codebase (and the Solr backends) get onto a box in the first place:
the staged
AegirSetup*engine and the/opt/tmp/make_localbuild tree. - Monitor & abuse-guard internals (code) — the
scan_nginxscorer that reads the access log these vhosts write and reacts to the444s the guard chain and the$boa_i18n_anoncap emit; the ban decisions it makes land back in the$is_bannedgeo declared here.
Reference
- Variables and
Commands — the consolidated
_VARand CLI tables, including the_SOLR_*/_JETTY_*/_XTRAS_LISTknobs the installer reads. The Nginxmapvariables ($is_banned,$is_cms_probe,$boa_i18n_*,$cache_uid, …) are deployed-vhost contract surface: add, never rename or remove. - Discontinued features — retired search/web pieces (older Solr/Jetty generations, superseded template mechanics) land there; check it before documenting anything found only in old trees or logs.