# How to Install Statamic on Ubuntu

A full walk-through for installing, configuring and running Statamic on an Ubuntu server, perfect for production use.

## Prerequisites

To install Statamic on an Ubuntu instance you will need the following:

- An Ubuntu 24.04 VPS with root access enabled or a user with sudo privileges (you can follow our [Digital Ocean](/installing/digital-ocean.md) or [Linode](/installing/linode.md) guides to get yours set up)
- A server with at least 1GB memory
- A valid domain name pointed to your server and SSL certificate in place
- PHP 8.3+

## Update Packages

If this is the first time using `apt` in this session, you should sure package lists and installed packages are up to date.

``` shell
sudo apt-get update
sudo apt-get upgrade
```

## Install PHP & Required Modules

``` shell
sudo apt install php-common php-fpm php-json php-mbstring zip unzip php-zip php-cli php-xml php-tokenizer php-curl php-gd -y
```

## Install Composer

Install Composer with the following command:

``` curl
curl -sS https://getcomposer.org/installer | php
```

Next, you need to move the `composer.phar` file to a globally accessible directory and update its permissions.

``` shell
sudo mv composer.phar /usr/local/bin/composer
sudo chmod +x /usr/local/bin/composer
```

:::tip
Do not run `composer` as root. If you followed the steps for creating a Digital Ocean droplet, you will need to create a new user to run `composer` as.
:::

Now you can check to make sure Composer is installed and configured correctly by running this command:

``` shell
composer
```

## Install Statamic CLI

Next up, let's install the Statamic CLI. To do this, run the following command in your terminal:

``` shell
composer global require statamic/cli
```

Upon installation, you can now use the `statamic new` command to spin up fresh Statamic sites with a CLI setup wizard 🧙‍♂️ to guide you through a variety of settings and options.

Our CLI is essentially a super fancy wrapper around the `composer create-project` command. You can choose to not install it, but only at your own annoyance.

## Install & Configure Nginx

Next, install [Nginx](https://nginx.com) with the following command:

``` shell
sudo apt install nginx -y
```

After the install completes, Nginx will start automatically. You can verify the service by running the following the command:

``` shell
sudo systemctl status nginx
```

## Create a new Statamic Application

Now we'll create a new Statamic application using the `statamic new` command.

First, navigate to the default Nginx root directory:

``` shell
cd /var/www/html
```

Next, run the following install command (you may need to update your [$PATH](/knowledge-base/troubleshooting/command-not-found-statamic.md)):

``` shell
statamic new example.com
```

:::tip
If you run into a TTY error like `TTY mode requires /dev/tty to be read/writable`, you can simulate TTY by calling `script` and using the `--no-interaction` flag.

```
script -q -c "statamic new --no-interaction example.com"
```
:::

## Set Permissions

Once Statamic is installed, you'll need to grant appropriate permissions to the non-root user so Statamic and Laravel can write to the necessary system directories.

``` shell
sudo chmod -R 755 /var/www/example.com
sudo chown -R www-data:www-data /var/www/html/example.com
```

Next, let's set up the minimum recommended config file to serve your site. Create a new file with `sudo vim` (or your command line editor of choice) at `/etc/nginx/sites-available/example.com`, making sure to replace `example.com` everywhere with your desired domain.

```php
server {
    listen 80;
    server_name example.com; // [tl! highlight:1]
    root /var/www/html/example.com/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;

    set $try_location @static;

    if ($request_method != GET) {
        set $try_location @not_static;
    }

    if ($args ~* "live-preview=(.*)") {
        set $try_location @not_static;
    }

    location / {
        try_files $uri $try_location;
    }

    location @static {
        try_files /static${uri}_$args.html $uri $uri/ /index.php?$args;
    }

    location @not_static {
        try_files $uri /index.php?$args;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
```

:::tip
You should ensure that the PHP path matches the version of PHP-FPM you have installed. 

For example: the example config above specifies `fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;`, but if you update all packages, you may end up with a later version.
:::

You can confirm that the configuration doesn’t contain any syntax errors with the following command:

``` shell
sudo nginx -t
```

You should see output similar to this:

``` shell
# Output
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

Symlink the newly created config file and reload Nginx to apply these changes:

``` shell
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo systemctl reload nginx
```

Now visit your IP Address or `https://example.com` (but like the actual domain) if you've pointed your domain's A Record and you should see the Statamic landing page.

<figure>
    <img src="/img/quick-start/installed-6.webp" alt="Statamic Welcome Screen" class="u-hide-in-dark-mode">
    <img src="/img/quick-start/installed-6-dark.webp" balt="Statamic Welcome Screen" class="u-hide-in-light-mode">
    <figcaption>If you see this, you have just won.</figcaption>
</figure>

## Conclusion

That's pretty much it. Time for you to take it from here.

If this is your production server, you'll probably want to add cache expiry headers and so on, but those rules and what you cache to the browser are all up to you.

There are many other variables at play when building your own server. It's unrealistic to think we've covered them all here, or that this article won't get out of date at times as things change.

If you run into issues not covered here, you may want to read through [this discussion](https://github.com/statamic/cms/discussions/10487) where several folks work through many edge cases happening all at once.