Setting up a Server for Craft

Craft’s system requirements are simple to satisfy in local development with tools like DDEV. When it comes time to share your project with the world, though, you’ll need to find a host that meets its requirements, or provision a VPS yourself.

If you’re eager to show off progress on a new Craft project, consider signing up for a free seven-day trial of Craft Cloud! Your code, content, and configuration are all portable between hosts.

Components of a Server #

Every Craft project relies on three main services:

  1. HTTP server — A process that connects to the outside world, marshaling requests and responses from/to clients;
  2. PHP Interpreter — The program that reads and executes the PHP scripts that make up your Craft application;
  3. Database — A specialized storage engine for Craft’s content;

Some hosting solutions package all three into the same physical machine. Others delegate the responsibilities to multiple servers to provide better scalability.

Additionally—and depending on your overall architecture—you’ll need a place to store uploaded files.

Initial Setup #

Some servers will require zero setup or maintenance. Examples of this kind of hosting include:

  • All Arcustech plans;
  • Many “shared” hosting providers;
  • Some PaaS or Docker-in-production options;
  • Craft Cloud and Servd;

For hosts that sell exclusively virtual or dedicated servers (like Vultr, Linode, or Digital Ocean), you may need to install some or all of the required software. This process typically begins by provisioning a server with a popular Linux distribution, and using the default credentials to log in via SSH.

We strongly advise against using FTP to manage files on your server. Review our Hosting 101 guide for some other tips on how to identify hosts that work well with Craft!

Provisioning Services #

If you are new to configuring hosting resources, a provisioning service like Laravel Forge, Ploi, or ServerPilot can dramatically simplify the setup and ongoing maintenance by…

  • Communicating directly with the underlying server providers via APIs;
  • Performing one-time setup tasks like creating management and application users and hardening security;
  • Installing software, services, and configuration files;
  • Setting up a working directory and public web root for your site;

These services also typically have built-in tools for deployment, long-running process or daemons, CRON tasks, backups, logging, monitoring, and more.

Manual Installation #

The specifics of installation will differ based on your host, region, operating system preference, and appetite for experimentation!

Digital Ocean has a number of guides that cover common suites of software:

  • LAMP — “Linux, Apache, MySQL, PHP,” the most popular combination for running Craft.
  • LEMP — “Linux, nginx, MySQL, PHP,” or a variation of the above that uses nginx instead of Apache, and PHP’s “FastCGI Process Manager.”

Both of these technology stacks are available as 1-Click Apps, or via Linode’s Marketplace and StackScripts. Both hosts also support the cloud-init specification, allowing you to define reproducible server configuration as code.

No matter who ultimately configures the server (you or an automated tool), the process will look something like this:

  • Create a virtual server with your provider;
  • Log in via SSH and perform initial setup and security-hardening steps by creating a non-root user (with sudo capabilities), configuring the SSH daemon, and enabling firewall rules;
  • Install required software: Apache or nginx, PHP (and any extensions that aren’t bundled with it), MySQL or Postgres, Git;
  • Configure one or more “hosts” that point to a public web root (Apache calls these VirtualHosts, nginx uses server directives);

If your host offers it, you can reach for a “managed” database so that you are not responsible for installing, securing, and tuning MySQL or Postgres.

To validate your setup before deploying an entire Craft project to it, take a look at our server-check tool.

HTTP Server Configuration #

Both Apache and nginx should be configured to use the web/ subdirectory of your project as the public web root. You should never expose the entire project folder to the internet!

Apache #

Apache uses the VirtualHost directive to map incoming requests to directories and services.

The .htaccess file in a new Craft installation is often used in conjunction with the DocumentRoot and AllowOverrides directives to allow the application code to route requests. For single-tenant servers, it can be helpful to disable overrides and insert the default .htaccess rules directly into the VirtualHost configuration block.

Installing the libapache2-mod-php package typically enables automatic hand-off to the PHP interpreter, when a request is routed to a script. If your scripts are not being executed, you may need to manually run a2enmod php

nginx #

The equivalent feature in nginx is called a server, which is often combined with one or more location)s to “rewrite” requests with the PHP back-end (as Apache does, with .htaccess):

server {
    # Declare the domain this server should respond to:
    server_name mydomain.com;
    # Disable disclosure of nginx:
    server_tokens off;
    # Set your public document root:
    root "/var/www/mydomain.com/web";
    # Add index.php to the list of allowed “index” files:
    index index.html index.htm index.php;
    # Set the appropriate Content-Type header:
    charset utf-8;

    # Global route handler:
    location / {
        # Try the exact URI, then a directory (applying the `index` directive, above), then the root `index.php`:
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Was a PHP script directly accessed (or rewritten internally)?
    location ~ \.php$ {
        try_files $fastcgi_script_name =404;

        # Replace with your PHP version’s socket or host:
        fastcgi_pass 127.0.0.1:9000;

        # Load default params (include name may be different by distribution):
        include fastcgi_params;

        # Set additional params that Craft expects:
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_param QUERY_STRING $args;

        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    }
}

Additional directives may be necessary to perform redirection, enforce SSL, or

Project Files #

At this point, you can introduce your project code, import a database backup, and upload your assets!

Review our Deployment Best Practices article, or read about the Craft workflow for more information about integrating code changes into live environments.

Configuration #

The .env file from your local project is a good blueprint for the variables you’ll need to define on the server—but many of the values are apt to need updates:

# (Optional) Generate a new “app ID”:
CRAFT_APP_ID="..."

# Replace the DDEV/development URL:
PRIMARY_SITE_URL="https://your-live-domain.com/"

# Replace database connection info:
CRAFT_DB_SERVER=""
CRAFT_DB_PORT=""
CRAFT_DB_DATABASE=""
CRAFT_DB_USER=""
CRAFT_DB_PASSWORD=""

CRAFT_DB_DRIVER should stay the same. The other database connection settings must match what you provided when installing MySQL or Postgres (or whatever was provided by the host, if you’re using a managed database).

Additionally, you should remove or disable any developer settings like CRAFT_DEV_MODE, CRAFT_ALLOW_ADMIN_CHANGES, and CRAFT_DISALLOW_ROBOTS (when you’re ready to launch).

Craft 5.5.0 added support for HTTP basic authentication at the application layer, which you can use to protect your site from prying eyes.

Database #

You can capture a database backup from your local environment by running ddev craft db/backup. If you already have your code on the remote server, upload and restore the backup with php craft db/restore /path/to/backup.sql. Otherwise, you can use your database’s command-line client (mysql or pg_restore) to directly import data.

Uploads #

When using a single server, you can often store uploaded assets directly on-disk.

If you suspect the server’s available disk space might eventually be exhausted (say, for a media-heavy project, or one that accepts uploads from front-end users), you may want to consider a remote filesystem.

This is also important on servers with ephemeral storage (like Craft Cloud), and load-balanced setups, where subsequent requests may not be served by the same underlying instance. Centralizing uploaded files makes them accessible to all instances, and keeps those requests away from your compute power, instead serving them from a CDN or edge cache.

Logs #

When something goes wrong with your site, you’ll need to know where to look for logs. By default, Craft writes out files to the storage/logs/ directory at the root of your project, separated by the application “mode” (web, console, and queue) and split into days.

Some hosts (in particular, those that use ephemeral, container-based infrastructure) may “drain” logs from stdout to a proprietary reader.

DNS #

Your host will likely provide you with an IPv4 or IPv6 address for your new server. This must be added as an A record for your domain, and the server must be configured to acknowledge requests from that address (and, if necessary, map it to the correct web directory).

www- and non-www URLs #

An additional record for the www “subdomain” may be required, even if you want to issue a server-level redirect to strip it from URLs.

SSL #

Some hosts will automatically handle SSL for you. Others may require that you install a certificate yourself, or use a tool like LetsEncrypt to automatically issue and renew certificates.

Services like Cloudflare can also provide SSL via their Zero Trust platform and Tunnel product.

Maintenance #

Keeping your server up-to-date is essential for security and performance. This means regularly installing operating system patches, package updates, and running Craft updates.

Updating Craft is always your responsibility! Shared hosting providers and provisioning tools tend to handle low-level software patches, automatically—but they will never touch your application files.

Periodically review the PHP versions available via your host or package manager. You may only be able to select minor versions (i.e. 8.4 and 8.3), so that the host is able to apply security patches.

Security #

The best thing you can do for your sites and servers is keep them up to date. When creating your server, always use the latest long-term support or LTS release of your favorite distribution, and set expectations for periodic maintenance.

Access to your servers—including the provider accounts you or your clients use to manage them—should be carefully guarded. You should never need to use password authentication for SSH, or enable insecure FTP. When setting up automation tools for deployment, create a unique key-pair for that service.

Files can be copied to the server using secure tools like scp or rsync, and many database administration tools support tunneling—so there’s no need to open ports for additional services. When provisioning a managed database, consider blocking all connections except those originating from your server’s IP address.

Tools like fail2ban can alleviate some malicious traffic, but a WAF provider like Cloudflare will often provide better protection and insight.

Applies to Craft CMS 5, Craft CMS 4, and Craft CMS 3.