DigitalOcean Droplets
This is a step-by-step guide for deploying a Strapi project to a DigitalOcean Droplet. Alternatively, you can also choose to deploy to DigitalOcean's Platform-as-a-Service (PaaS) called App Platform if database-related requirements and budget better fit with your use case.
This guide covers hosting the database on a DigitalOcean Droplet. Another option is to host the database externally as a service using DigitalOcean Managed Databases.
- You have created a Strapi project with a local PostgreSQL database.
- You have read through the general deployment configuration section.
- You have created a DigitalOcean account. You can use this referral link.
When creating your Strapi project, don't use the --quickstart flag as the quick start installation uses SQLite, which is not desired for remote hosting.
You can also use Strapi Cloud to quickly deploy and host your project.
Create a "Droplet"
DigitalOcean calls a virtual private server, a Droplet. Create a new Droplet to host your Strapi project:
- Log in to your DigitalOcean account.
- Select the Create dropdown near the top right, then select Droplets.
- Choose a Region and Datacenter closest to your users' location.
- Select Ubuntu 22.04 (LTS) x64 as the image from the OS tab.
- Choose an appropriate droplet size and pricing plan, depending on your needs. Strapi requires at least 2GB of RAM to build and deploy the admin interface.
- Choose SSH Key.
- In a terminal instance on your computer, run the following command:
pbcopy < ~/.ssh/id_rsa.pub. The command copies the existing SSH public key on your development computer to the clipboard. - Back on the DigitalOcean website, paste your public SSH key into the New SSH Key field. Name this SSH key and click on Save.
- (optional) Select additional options as required, for example IPv6.
- (optional) Choose a Hostname or leave as-is.
- Click the Create Droplet button at the bottom right.
DigitalOcean will create your Droplet and indicate the progress with a loading bar. Once complete, proceed to setting up a production server and installing Node.js.
Additional instructions on creating and using SSH Keys can be found on the official DigitalOcean documentation.
Setup production server and install Node.js
The following next steps will help you to set up a production server and a non-root user for managing the server.
Setting up a production server
Follow the official DigitalOcean documentation for initial server set-up using Ubuntu 22.04.
Installing and configuring Node.js and npm
Now the server has been set up, install Node using a personal package archive (PPA), as described in the official DigitalOcean documentation.
After installing Node (which also installs npm by default), you will manually change npm's default directory. The following steps are based on how to resolve access permissions from the official Node documentation:
- Create a
.npm-globaldirectory and set the path to this directory fornode_modulesby running the following commands:mkdir ~/.npm-global
npm config set prefix '~/.npm-global' - Create (or modify) a
~/.profilefile by running the following command:sudo nano ~/.profile - Paste the following lines into the first 2 lines of the open
~/.profilefile:Then press# set PATH so global node modules install without permission issues
export PATH=~/.npm-global/bin:$PATHCtrl+Xto exit,yto save andEnterto accept. - Update your system variables by running the following command:
source ~/.profile
You are now ready to install and configure Git versioning on your server.
Install and configure Git versioning on your server
A convenient way to maintain your Strapi application and update it during and after initial development is to use Git. In order to use Git, you will need to have it installed on your Droplet.
Droplets should have Git installed by default. Check if Git is installed by running the following command:
git --version
If the terminal returns git version followed by some version number (e.g., git version 2.x.x), Git is already installed, and you can proceed to installing the database for your project.
If Git is not installed:
- Install Git by following the DigitalOcean documentation on how to install Git on Ubuntu 22.04.
- Configure Git by setting up the username and email as described in the DigitalOcean documentation.
Install the database for your project
Install PostgreSQL on Ubuntu 22.04 by following the DigitalOcean documentation through to "Step 4 - Creating a New Database". Once done, PostgreSQL is installed and a user and a database are created.
To connect to a PostgreSQL database with Strapi, the database:
- either needs to have a password,
- or specifically states there is no password by declaring an empty string (
'') as the password.
To connect to the PostgreSQL database with Strapi:
(optional) If you have switched away from the
postgres@user, run the following:sudo -u postgres psql
[sudo] password for your-name: # this auth prompt appears
psql (14.8 (Ubuntu 14.8-0ubuntu0.22.04.1)) # shell response after password
Type "help" for help.Run the following commands to alter the user you created and add a password, replacing
your-nameand'your-password'by your own values:psql
# Enter SQL command below including quotation marks and semicolon.
postgres=# ALTER USER your-name PASSWORD 'your-password';
ALTER ROLE # shell response after SQL command
# Then quit with the \q command as we don't want to alter role.
postgres=# \q
exit(optional) The
pgpackage is automatically installed locally if you chosePostgreSQLas the initial database choice when you first set up Strapi. If your Strapi project uses SQLite, install thepgdependency package. On your development machine, run the following command in your Strapi project folder:npm install pg --save
Note the database name, username and password for later use.
Configure for local development
- You must have
gitinstalled and set-up locally. - Git should be initialized for your previously created Strapi project.
Replace the content of the
config/database.jswith the following:- JavaScript
- TypeScript
path: ./config/database.js
module.exports = ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('DATABASE_HOST', '127.0.0.1'),
port: env.int('DATABASE_PORT', 5432),
database: env('DATABASE_NAME', 'strapidb'),
user: env('DATABASE_USERNAME', ''),
password: env('DATABASE_PASSWORD', ''),
ssl: env.bool("DATABASE_SSL", false) && {
rejectUnauthorized:env.bool('DATABASE_SSL_SELF', false),
},
},
debug: false,
},
});path: ./config/database.ts
export default ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('DATABASE_HOST', '127.0.0.1'),
port: env.int('DATABASE_PORT', 5432),
database: env('DATABASE_NAME', 'strapidb'),
user: env('DATABASE_USERNAME', ''),
password: env('DATABASE_PASSWORD', ''),
ssl: env.bool("DATABASE_SSL", false) && {
rejectUnauthorized:env.bool('DATABASE_SSL_SELF', false),
},
},
debug: false,
},
});Push these changes to Github by running the following commands:
git add .
git commit -m "Configured production/database.json"
git push
Deploy from GitHub
You will now deploy your Strapi project to your Droplet by cloning it from GitHub.
From your terminal, logged in as the non-root user to your Droplet, run the following commands, replacing
your-handleandyour-projectwith your GitHub username and project's name:cd ~
git clone https://github.com/your-handle/your-project.git(optional) If using password-based authentication instead of a SSH key:
You will be prompted to enter
your-handleand a password when attempting to clone. This is actually a personal access token (PAT) as passwords have been deprecated.In order to overcome an issue with webhooks later on, run the following commands, replacing
your-handle,your-pat, andyour-projectwith the appropriate values:cd ~/your-project
git remote add origin https://your-handle:your-pat@github.com/your-handle/your-project.git
# If response is "fatal: remote origin already exists.", then run:
git remote set-url origin https://your-handle:your-pat@github.com/your-handle/your-project.git
Navigate to your project's folder, which is the root folder for Strapi, and install the npm packages for your project by running the following commands, replacing
your-projectby your project's name on GitHub:cd your-project
npm installBuild Strapi's admin panel by running the following command:
NODE_ENV=production npm run buildAs Strapi uses port 1337 by default, you must configure your
ufwfirewall to allow access to this port for testing and installation purposes, by running the following commands:cd ~
sudo ufw allow 1337/tcp
sudo ufw enablePress
yto answer yes to theCommand may disrupt existing ssh connections. Proceed with operation (y|n)?message.
Your Strapi project is now installed on your DigitalOcean Droplet. Before being able to create your first user, you must install and configure Nginx and pm2, configure the ecosystem.config.js file and environment variables, and setup webhooks.
Install and configure Nginx web server
Follow the guide on the official DigitalOcean documentation to install and configure Nginx, keeping in mind the following specificities:
You can add a domain name or use a subdomain name for your Strapi project.
References to
your_domainin "Step 5 – Setting Up Server Blocks" should include the TLD, (e.g.example.com).The location field in "Step 5 – Setting Up Server Blocks", specified as
try_files $uri $uri/ =404;, must be replaced with the following:proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
Close the port to outside traffic by running the following commands:
cd ~
sudo ufw deny 1337
Install and configure pm2
pm2 allows you to keep your Strapi project alive and to reload it without downtime.
Ensure you are logged in as a non-root user and install pm2 globally by running the following command:
npm install pm2@latest -g
Configure the ecosystem.config.js and .env files
The ecosystem.config.js manages the database connection variables that Strapi needs to connect to your database. ecosystem.config.js is also used by pm2 to restart your project whenever any changes are made to files within the Strapi file system itself, such as when an update arrives from GitHub. You can read more about the ecosystem.config.js file in the official pm2 documentation.
Create the
ecosystem.config.jsfile with the command below and open it. We'll use thenanoeditor:cd ~
pm2 init
sudo nano ecosystem.config.jsReplace the boilerplate content in the file with the following:
module.exports = {
apps: [
{
name: 'strapi-app',
cwd: '/home/your-name/your-project', // must have absolute path
script: 'npm',
args: 'start',
env: {
NODE_ENV: 'production',
},
},
],
};Go to
your-projectfolder to create and open a.envfile:cd ~/your-project
sudo nano .envCopy the contents of the local
.envfile for the Strapi application to the one currently open innano. Replace the database name and credentials with the ones specified during database setup.HOST=0.0.0.0
PORT=1337
APP_KEYS=your-app-keys # auto-generated
API_TOKEN_SALT=your-api-token-salt # auto-generated
ADMIN_JWT_SECRET=your-admin-jwt-secret # auto-generated
TRANSFER_TOKEN_SALT=your-transfer-token-salt # auto-generated
# Database
DATABASE_CLIENT=postgres
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
DATABASE_NAME=your-database-name # specified during database setup
DATABASE_USERNAME=your-database-username # specified during database setup
DATABASE_PASSWORD=your-database-password # specified during database setup
DATABASE_SSL=false
JWT_SECRET=your-jwt-secret # auto-generatedRun the following commands to start
pm2:cd ~
pm2 start ecosystem.config.js
pm2 is now set-up to use an ecosystem.config.js to manage restarting your application upon changes. This is a recommended best practice.
Configure .env to launch Strapi on system startup
The following steps are modified from the DigitalOcean documentation for setting up PM2:
Generate a startup script to launch PM2 by running:
$ cd ~
$ pm2 startup systemd
# Shell output
[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 your-name --hp /home/your-nameCopy the generated command from above and paste to the terminal:
$ sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u your-name --hp /home/your-name
# Shell output
[PM2] Init System found: systemd
Platform systemd
# ...
[PM2] [v] Command successfully executed.
+---------------------------------------+
[PM2] Freeze a process list on reboot via:
$ pm2 save
[PM2] Remove init script via:
$ pm2 unstartup systemdSave the new PM2 process list and environment:
pm2 save
# Shell output
[PM2] Saving current process list...
[PM2] Successfully saved in /home/your-name/.pm2/dump.pm2
You can test to see if the script above works whenever your system reboots with the sudo reboot command. Login again with your non-root user and run pm2 list and systemctl status pm2-your-name to verify everything is working. You can also check logs with pm2 logs strapi-app --lines 20.
The Strapi production server should now be available at the domain that was specified during Nginx setup. The login screen is available at the /admin endpoint to that same domain.
Set up a webhook on DigitalOcean/GitHub
Providing that your project is set up on GitHub, you must configure your Strapi project repository there with a webhook.
More information can be found on webhooks in general in the GitHub documentation and DigitalOcean documentation.
Go to
your-projecton GitHub and set up a webhook by following step 1 from the DigitalOcean article. Make note of what was entered foryour-webhook-secretfor later.Create a webhook script on your server. The following commands create a new file called
webhook.jswhich will hold 2 variables:cd ~
mkdir NodeWebhooks
cd NodeWebhooks
sudo nano webhook.jsIn the open
nanoeditor, paste the following script, ensuring to update the values for thesecretandrepovariables at the top of the file. Then save and exit.var secret = 'your-webhook-secret'; // created in GitHub earlier
var repo = '~/your-project';
const http = require('http');
const crypto = require('crypto');
const exec = require('child_process').exec;
const PM2_CMD = 'cd ~ && pm2 startOrRestart ecosystem.config.js';
http
.createServer(function(req, res) {
req.on('data', function(chunk) {
let sig =
'sha1=' +
crypto
.createHmac('sha1', secret)
.update(chunk.toString())
.digest('hex');
if (req.headers['x-hub-signature'] == sig) {
exec(`cd ${repo} && git pull && NODE_ENV=production npm run build && ${PM2_CMD}`, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
}
});
res.end();
})
.listen(8080);👀 InfoThe script above declares a variable called
PM2_CMDwhich is used after pulling from GitHub to update your project. The script first changes to the home directory and then runs the variablePM2_CMDaspm2 restart strapi.Allow the port to communicate with outside web traffic for port 8080 by running the following scripts:
sudo ufw allow 8080/tcp
sudo ufw enablePress
yto accept theCommand may disrupt existing ssh connections. Proceed with operation (y|n)?message.Earlier you setup
pm2to start the services foryour-projectwhenever the Droplet reboots or is started. You will now do the same for thewebhook.jsscript.Install the webhook as a
systemdservice. First runecho $PATHand copy the output for use in the next step.echo $PATH
# Shell output
/home/your-name/.npm-global/bin:/home/your-name/bin:/home/your-name/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binCreate a
webhook.servicefile:sudo nano /etc/systemd/system/webhook.servicePaste the configuration details below into the open
nanoeditor. Make sure to replaceyour-namein both places with your username. Following that, paste the path that was outputted to the shell above in place ofyour-path, then save and exit:[Unit]
Description=Github webhook
After=network.target
[Service]
Environment=PATH=your-path
Type=simple
User=your-name
ExecStart=/usr/bin/node /home/your-name/NodeWebhooks/webhook.js
Restart=on-failure
[Install]
WantedBy=multi-user.targetEnable and start the new service so it starts when the system boots:
sudo systemctl enable webhook.service
sudo systemctl start webhookCheck the status of the webhook:
sudo systemctl status webhook(optional) Test your webhook as shown in the DigitalOcean documentation except using the
node webhook.jscommand sincenodejsis depreciated. Sometimes GitHub will show a successful recent delivery even if there is an authentication failure. The most reliable way is to push code changes to the GitHub repository and then runsudo systemctl status webhookagain to see if the latest commit SHA has been registered.
Further steps to take
- To install SSL, you will need to install and run Certbot by Let's Encrypt.
- Set-up Nginx with HTTP/2 Support for Ubuntu 22.04.
🥳 Your Strapi project has been installed on a DigitalOcean Droplet using Ubuntu 22.04.