How Craft Determines the Site URL
Craft can typically infer the requested URL and the requested site based on your server’s configuration. In some rare cases, you may need to explicitly set the CRAFT_WEB_URL
bootstrap variable. Complete URLs are not stored in the database, which means launching a site (or changing domains) is only ever a matter of adjusting config and clearing caches.
The most stable and secure way to set URLs for your sites is using environment variables.
Site Settings #
When you create a new project, Craft looks for (or sets) a PRIMARY_SITE_URL
variable in your .env
file. Our recommended local development environment DDEV automatically populates this variable with the project’s hostname, like https://my-project.ddev.site
. A reference to that variable is then stored in project config, and is visible to administrators by navigating to Settings → Sites → Default (or whatever the name of your primary site is).
When it comes time to deploy, all you need to do is replace that URL in the live .env
file:
PRIMARY_SITE_URL="https://my-domain.com"
Multi-site URLs #
Craft also uses the hostname and path to determine which site a request will be handled by. Sites are differentiated by domains, subdomains, and paths—so it’s important that each of them is defined consistently, across requests. Ambiguous settings for multiple sites may cause a request to be served in the wrong context.
For this reason, we recommend using environment variables to define each site’s Base URL. You don’t need a separate variable for every site—but at least one for each hostname you expect the installation to be accessible from. Let’s look at an example:
GLOBAL_SITE_URL="https://acme-labs.com"
CORPORATE_SITE_URL="https://corp.acme-labs.com"
B2B_SITE_URL="https://b2b.acme-labs.com"
We can then create variations on these URLs to make content available in different languages:
Site | Language | Base URL |
---|---|---|
Global | English | https://acme-labs.com |
Spanish | https://acme-labs.com/es | |
Chinese | https://acme-labs.com/cn | |
Corporate | English | https://corp.acme-labs.com |
Spanish | https://corp.acme-labs.com/es | |
Chinese | https://corp.acme-labs.com/cn | |
Distributors | English | https://b2b.acme-labs.com. |
Spanish | https://b2b.acme-labs.com/es | |
Chinese | https://b2b.acme-labs.com/cn |
In this table, the Spanish corporate site (https://corp.acme-labs.com/es
) might have a Base URL setting of $CORPORATE_SITE_URL/es
.
The @web
Alias #
Craft defines a number of aliases corresponding to commonly-accessed paths and URLs.
@web
is intended to reflect the current hostname, and in most cases is determined automatically. For multi-site projects that use different domains or subdomains, this means that @web
may evaluate to different hostnames or URLs, depending on which site was requested. It will only include a path if the index.php
file serving the request is located in a folder beneath the web root.
Do not use @web
in a site’s Base URL setting! This can make it impossible for Craft to determine which site to serve.
Instead, define an environment variable for each domain you intend to use:
PRIMARY_SITE_URL="https://my-domain.com"
FRANCHISE_SITE_URL="https://franchising.my-domain.com"
# ...
The same holds true for local filesystems—they must have stable URLs that do not depend on which site was requested.
If you wish to use an alias as part of a site’s Base URL, define an alias specific to the project and set it to an environment variable:
use craft\config\GeneralConfig;
return GeneralConfig::create()
// ...
->aliases([
'@primaryBaseUrl' => App::env('PRIMARY_SITE_URL'),
'@franchisingBaseUrl' => App::env('FRANCHISING_SITE_URL'),
])
;
In the earlier examples, your sites’ Base URL settings might have values like @primaryBaseUrl
(English), or @primaryBaseUrl/es
(Spanish).
As of Craft 5.5.0, you may use environment variables at the beginning of many project config settings—so $PRIMARY_SITE_URL/en
is a valid base URL!
Control Panel URLs #
The control panel should only be accessible from a single domain. Use the baseCpUrl
config setting to lock this to a particular URL and help avoid license errors. This can also be set with the CRAFT_BASE_CP_URL
environment variable.
CRAFT_WEB_URL
#
If Craft can’t figure out what URL it’s being accessed from, you may need to explicitly set the CRAFT_WEB_URL
bootstrap variable. This is exceedingly rare, and usually reflects a broader server configuration issue, resulting in ubiquitous $_SERVER
values and headers being hidden or overritten.
Visting Utilities → PHP Info in the control panel should display values for both $_SERVER['HTTP_HOST']
and $_SERVER['SERVER_NAME']
. If these are missing or inaccurate, consult with your host.