How to Set Up and Install Strapi for Production on Ubuntu 22.04

How to Set Up and Install Strapi for Production on Ubuntu 22.04


Strapi is an opensource, headless Content Management System (CMS), built with the JavaScript programming language. Like other headless CMS’, Strapi doesn’t come with a frontend out of the box. Instead, it relies on an API that allows you to architect your content structure. Additionally, Strapi offers a variety of ways to build out your website, integrating with popular frameworks like React and Next.js. Furthermore, you can choose how to consume an API using either a REST API or GraphQL.

In this tutorial, you will install Strapi and set up a production environment to begin creating content. While Strapi runs SQLite in its development mode, you will configure it to use PostgreSQL. You’ll also serve your Strapi application behind an Nginx reverse proxy, and use the PM2 process manager to ensure stable uptime. Finally, you will secure your Nginx connection using Let’s Encrypt.


To follow this tutorial, you will need:

With Node.js version 16, Nginx, and Postgres installed on your server, you’re ready to proceed with the tutorial.

Step 1 — Setting Up Your Postgres Database

A database is required for any Strapi project. Currently, it supports MySQL, MariaDB, SQlite, and PostgreSQL. You can check the minimum version requirements within their official documentation. Furthermore, Strapi expects a fresh database. This means you can’t use an existing database to link to for your Strapi instance.

First, create a database:

  1. sudo -i -u postgres createdb strapi-db

Then create a user for your database:

  1. sudo -i -u postgres createuser --interactive
Enter name of role to add: sammy Shall the new role be a superuser? (y/n) y

By default, in PostgreSQL, you authenticate as database users using the Identification Protocol or ident authentication method. This involves PostgreSQL taking the client’s Ubuntu username and using it as the database username. This allows for greater security in many cases, but it can also cause issues when you’d like an outside program, such as Strapi, to connect to one of your databases. To resolve this, set a password for this PostgreSQL role to allow Strapi to connect to your database.

From your terminal, open the PostgreSQL prompt:

  1. sudo -u postgres psql

From the PostgreSQL prompt, update the user profile to have a strong password of your choosing:

  1. ALTER USER sammy PASSWORD 'postgres_password';

Exit out of your PostgreSQL user by entering \q in your terminal:

  1. \q

With your database and user credentials created, you’re ready to install Strapi.

Step 2 — Installing Strapi on Your Server

To install Strapi on your server, enter the following command:

  1. npx create-strapi-app@latest my-project

Confirm with y to proceed with the installation.

After confirming yes, you’ll access an interactive installation. Choose the following options while making sure your Database name, Username, and Password are changed appropriately:

? Choose your installation type Custom (manual settings) ? Choose your preferred language JavaScript ? Choose your default database client postgres ? Database name: strapi-db ? Host: ? Port: 5432 ? Username: sammy ? Password: postgres_password ? Enable SSL connection: No

The SSL connection is not enabled because it will be configured and obtained with a Let’s Encrypt certificate later in the tutorial. Strapi will begin installation after you make your selections.

Once the installation is complete, you’re ready to build your Strapi project.

First, make sure that you’re in the my-project directory:

  1. cd my-project

Next, run the following command:

  1. NODE_ENV=production npm run build
> my-project@0.1.0 build > strapi build Building your admin UI with production configuration... ✔ Webpack Compiled successfully in 35.44s Admin UI built successfully

This command will build your Strapi project, including the Strapi admin UI.

You can now test your Strapi server. Run the following command to start your Strapi server directly:

  1. node /home/sammy/my-project/node_modules/.bin/strapi start
[2022-11-21 13:54:24.671] info: The Users & Permissions plugin automatically generated a jwt secret and stored it in .env under the name JWT_SECRET. Project information ┌────────────────────┬──────────────────────────────────────────────────┐ │ Time │ Mon Nov 21 2022 13:54:24 GMT+0000 (Coordinated … │ │ Launched in │ 1603 ms │ │ Environment │ development │ │ Process PID │ 4743 │ │ Version │ 4.5.4 (node v16.18.1) │ │ Edition │ Community │ └────────────────────┴──────────────────────────────────────────────────┘ Actions available One more thing... Create your first administrator 💻 by going to the administration panel at: ┌─────────────────────────────┐ │ http://localhost:1337/admin │ └─────────────────────────────┘

If you followed the prerequisites, you set up Nginx as a reverse proxy to Strapi’s default address of http://localhost:1337. Navigate to http://your_domain in your browser to view the default Strapi landing page:

Strapi landing page after initial 'build' and ‘start’ command.
Your Strapi landing page after running the build and start commands.

This command with the default configuration is currently using Strapi’s development mode. It also relies on a process that is tied to a command in your terminal and isn’t suitable for production. In the next step, you will add production settings to a process manager called PM2.

Exit your server by pressing CTRL+c.

With Strapi installed, you’re ready to set up PM2 to run your server in the background as a service.

Step 3 — Installing and Configuring PM2

Instead of starting the server manually, you can rely on PM2 to manage this process. For more details about PM2 and configuring a production ready Node.js application, review our guide. PM2 helps to keep your server up and running without having to start it up manually, ensuring uptime.

First, make sure you’re in the top directory:

  1. cd ~

Next, install PM2 with the following command:

  1. sudo npm install pm2@latest -g

Then, create a configuration file for PM2 with your preferred text editor. nano is used in this example:

  1. sudo nano ecosystem.config.js

Add the following content to this file, while making sure to change the project directory name and path, along with your database name, user, and password:

module.exports = {
  apps: [
      name: 'strapi',
      cwd: '/home/sammy/my-project',
      script: 'npm',
      args: 'start',
      env: {
        NODE_ENV: 'production',
        DATABASE_HOST: 'localhost',
        DATABASE_PORT: '5432',
        DATABASE_NAME: 'strapi-db',
        DATABASE_USERNAME: 'sammy',
        DATABASE_PASSWORD: 'postgres_password',

After editing the PM2 configuration, exit the file. If you’re using nano, press CTRL+x, then y, and ENTER.

Run your Strapi instance in the background with the following command:

  1. pm2 start ecosystem.config.js
[PM2][WARN] Applications strapi not running, starting... [PM2] App [strapi] launched (1 instances) ┌─────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ ├─────┼───────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ │ 0 │ strapi │ default │ N/A │ fork │ 22608 │ 0s │ 0 │ online │ 0% │ 30.3mb │ sammy │ disabled │ └─────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘

Applications that are running under PM2 restart automatically if the application crashes or is killed. You can launch your Strapi instance at startup by running the following subcommand:

  1. pm2 startup
[PM2] Init System found: systemd [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

This generates and configures a startup script to launch PM2 and its managed processes when the server boots.

Next, copy and execute the command given to you in the output, using your username in place of sammy:

  1. sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Then, save the PM2 process list:

  1. pm2 save

You now have the PM2 service running on your server. If you navigate back to http://your_domain, notice that Strapi is now running in production mode:

Strapi production landing page indicator

With PM2 running your server in the background, you can finish up securing your Strapi instance.

Step 4 — Securing Strapi with Let’s Encrypt

As you may have noticed when you navigated to your domain to view the Strapi landing page, the URL, as indicated with http:// instead of https://, is an unsecure connection.

Secure your Strapi instance with Let’s Encrypt by entering the following command:

  1. sudo snap install --classic certbot

Link the certbot command from the snap install directory to your path so you can run it by writing certbot:

  1. sudo ln -s /snap/bin/certbot /usr/bin/certbot

Next, allow HTTPS traffic and the Nginx Full profile:

  1. sudo ufw allow 'Nginx Full'

Delete the redundant Nginx HTTP profile allowance:

  1. sudo ufw delete allow 'Nginx HTTP'

Then use the Nginx plugin to obtain the certificate by inserting your domain address:

  1. sudo certbot --nginx -d your_domain -d www.your_domain

When running the command, you are prompted to enter an email address and agree to the terms of service. You can opt in or out of an email list as well. After doing so, you are greeted with a message telling you the process was successful and where your certificates are stored:

. . . Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem Key is saved at: /etc/letsencrypt/live/your_domain/privkey.pem This certificate expires on 2023-02-05. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background. Deploying certificate Successfully deployed certificate for your_domain to /etc/nginx/sites-enabled/your_domain Successfully deployed certificate for www.your_domain /etc/nginx/sites-enabled/your_domain Congratulations! You have successfully enabled HTTPS on https://your_domain and https://www.your_domain . . .

Navigate to http://your_domain. You are automatically redirected to an HTTPS version of your site. Notice too, that Strapi is running in production mode:

Strapi production landing page indicator

You can now navigate to https://your_domain/admin to create your Strapi administrator account:

Strapi sign up landing page

After entering in your new credentials, you can enter the administrative dashboard:

Strapi's dashboard

From the dashboard, you can start creating content on Strapi.


In this tutorial, you set up a production environment for Strapi using a PostgreSQL database. You also served your Strapi application behind an Nginx reverse proxy and used the PM2 process manager to keep your server up and running.

After setting up your Strapi server, you can start creating content using the Strapi administrative dashboard. You can learn more about setting up and configuring your Strapi application from Strapi’s official documentation.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Tony Tran


Default avatar
Kong Yang


Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

🚨 I need your help, unfortunately this is not working for me

I followed multiple tutorials but these are the ones that helped the most:

Server Setup Ubuntu Firewall essentials Mysql Install NGINX Config

All of those to be ready to do this one that’s the most important Strapi Install on Ubuntu

I added my domain api.inkker.com as an A Record It’s such a simple setup I have strapi running on port 3000, here is my nginx config at /etc/nginx/sites-available/api.inkker.com

server {
    listen 80;
    listen [::]:80;

    server_name api.inkker.com;

    location / {
        include proxy_params;

I allowed the ports on the firewall

root@inkker-server:/etc/nginx/sites-available# ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
80                         ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)
80 (v6)                    ALLOW       Anywhere (v6)

I reloaded nginx as I should and created the symlink and this is what I get in the browser:

![image alt text](

image alt text
Error page

Somehow I see it is loading the favicon, but the app just does not load and I don’t get why, I’ve been doing this for days now and I appreciate the help.

Could it be that you missed to do npm install first before building?

Ok but how do i edit my content types? This leaves me in a pickle. Deno the best next step but gonna try split this into dev on local and prod on remote and then link them with git… Unless i can run dev on remote on another port…

Thanks for this awesome guide! I still had a question: How would it be possible to deploy from development to production? I could use git, but would updating the files cause PM2 to reload Strapi?

This comment has been deleted

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Featured on Community

    Get our biweekly newsletter

    Sign up for Infrastructure as a Newsletter.

    Hollie's Hub for Good

    Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

    Become a contributor

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    Welcome to the developer cloud

    DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

    Learn more
    DigitalOcean Cloud Control Panel