Tutorial: Strapi (v4.x) on Azure - Web and Static Apps with Github CD/CI and PostgreSQL server
Introduction
The Azure ecosystem is not the same as it has been a few year ago, they’re pushing hard to make all the opensource tools, specially NodeJS based ones, to be easy to integrate into their ecosystem. Strapi (Node based Headless CMS) is one of the tools I’ve been trying to integrate fully into Azure, and it took me a while to finally understand how it’s done. I want to share this knowledge with you.
Requisites
- Azure account — to create Web and Static Web Apps and a PostgreSQL server
- Github account — you’ll be using Github workflows to build and deploy Strapi
- Node — version >=10.16.0 <=14.x.x
- Yarn — you can use npm if you prefer
- Git — so we can create/manage local/remote git repositories
Goal
- Create an Azure Web App for the server-side of Strapi with CI/CD
- Create an Azure Static Web App for the Strapi Admin Panel with CI/CD
- Make sure Strapi Admin Panel connects to Strapi
Steps
- Create a local Strapi project
- Setup the Github repo
- Prepare for Azure integration
- Create an Azure Web App
- Create an Azure Static Web App
- Update the Github workflow for the Azure Web App
- Update the Github workflow for the Azure Static Web App
- Create an Azure Database for PostgreSQL
- Create a remote database for Strapi
- Add database configurations to the Strapi Web App
- Add production configuration to Strapi project
1. Create a Strapi project
So, let’s create our Strapi project by running:
yarn create strapi-app strapi-on-azure --quickstartThis will create a quick Strapi project with all the relevant dependencies and, by default, it’ll use Sqlite3 as the database.
If you haven’t tried Strapi feel free to create a local admin user through the Strapi Admin Panel. You can find all the resources you need in strapi.io/resource-center.
2. Setup the Github repo
At this point, I’d recommend initialising a git repo inside the newly created project folder and sync it with your Github repository.
git add .
git -m commit "Initial strapi project"
git remote add origin git@github.com:<your-username>/strapi-on-azure.git
git push --set-upstream origin masterNow you’re ready to make the relevant changes.
3. Prepare project for Azure integration
First we’ll have to create a JavaScript file in the root of our project that will be the entry point for our Strapi app, i.e. node server. I called mine server.js.
/* ./server.js */const strapi = require('@strapi/strapi')
strapi().start()
After this, edit your package.json file and update the start script so it looks like this:
“start”: “NODE_ENV=production node server.js”,Commit and push your code:
git add .
git commit -m "Start script updated"
git push4. Create an Azure Web App
Log into your Azure account and create a new Web App.
Fill the relevant fields. You might need to create a new Resource Group and/or a new App Service Plan
Make sure you select the correct spec for your Web App. Strapi recommends 2 GB of memory but it should work fine with 1.75 GB because we’ll be running the server side Strapi only. Click on Apply.
Once you’re happy with your spec click the Next: Deployment button. On the next screen we are going to enable Continuous Development.
You’ll have to authorise Azure to access your Github account.
Now you can choose you can choose your Strapi project from the Github repo and the relevant branch. In our case we select the master branch. In a production scenario you’ll probably want to have a production branch.
Azure will generate a Github workflow configuration file (that we’ll be changing below). If you inspect the file (by clicking the Preview file button) you’ll be able to understand, roughly, what’s going to happen every time you push changes to the master branch.
Let’s ignore, the next two steps, i.e. Monitoring and Tags by pressing the Next button twice.
On the last step you configuration will be validated, and if there’s nothing amiss you can now create the Web App by pressing the Create button.
Once the resource is created the Continuous Development task will kick in. Unfortunately, the provided workflow template is not sufficient to make the build and deploy work. We’ll get to that later.
You can see the workflow running under you Github repo and the Actions tab.
I recommend you stop this build and deploy job by pressing the three dots, at the end of the running workflow, and select Cancel run. Otherwise, you’ll end up having to clean your Github storage.
One thing that I found useful was to use a Github workflow to clean my artifacts storage every day for the Strapi Web App builds. There’s a good article to help you with that.
Next step will be to create the Static Web App.
5. Create an Azure Static Web App
Under Create a resource we need to search for static web app and select it from the dropdown.
Click on Create.
Fill all the required fields, and choose Github under your Deployment details.
Under Build details for the Build process select Custom. Then for the Output location write build. Click on Review + create button.
And finally click on Create.
6. Update the Github workflow for the Azure Web App
Next step is to change the Build and deploy workflow for our Azure Web App, i.e. Strapi. You can do that buy selecting the View workflow file for a specific run (as shown below). Alternatively, you can just git fetch and git rebase to get the new workflow in your local project — you’ll see it under .github/workflows.
Now click on the edit icon.
The final workflow should look like the one below. Make sure you DON’T edit the line that starts with publish-profile — we want to keep the secret that was generated for you.
name: Build and deploy Strapi to Azure Web App - strapi-on-azureon:
push:
branches:
- master
workflow_dispatch:jobs:
build:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v2- name: Set up Node.js version
uses: actions/setup-node@v1
with:
node-version: '14.x'- name: npm install, build, and test
run: |
npm install
npm run test --if-present
- name: 'Tar files'
run: tar -cf node-app.tar .- name: Upload artifact for deployment job
uses: actions/upload-artifact@v2
with:
name: node-app
path: node-app.tardeploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'Production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}steps:
- name: Download artifact from build job
uses: actions/download-artifact@v2
with:
name: node-app
- name: 'Untar files'
run: 'tar -xf node-app.tar'- name: 'Deploy to Azure Web App'
id: deploy-to-webapp
uses: azure/webapps-deploy@v2
with:
app-name: 'strapi-on-azure'
slot-name: 'Production'
publish-profile: ${{ secrets.<auto generated azure secret name> }}
package: .
Finally, commit the changes.
Now, we’ll have to tweak the Static Web App build and deploy workflow too.
7. Update the Github workflow for the Static Azure Web App
Select View workflow file for the Actions tab in Github.
Now edit the file and add the following line
app_build_command: "NODE_ENV=production yarn build"Right before the line
app_location: "/" # App source code pathCommit your changes.
8. Create an Azure Database for PostgreSQL
For the sake of this tutorial I was hoping to use Sqlite3 as the database, but unfortunately I wasn’t able to have it running in a Azure Web App (Linux), yet. Therefore, I’ve decided to connect our Strapi Web App to an Azure PostgreSQL server because I thought it would be a valid option for those who want to use Strapi in production.
Click on Create.
Then Create a Flexible server — this will allow you to start with a Development server and scale it up later when you need more CPU cores or memory.
Fill in the form. For the purpose of this article, we’re going to create a Development database. Also, make sure you remember the user name and password, you’ll need it for the Strapi Web App configurations — so Strapi can connect to the Postgres server, obviously.
Make sure you allow public access from Azure service within Azure to this service. In a later stage you might just specify a range of IP addresses that you can get from the Networking section of your Azure Web App.
Review your choices and press Create.
9. Create a remote database for Strapi
Connecting to remote postgres server. The first time we connect we need to specify the default database name, i.e. postgres
psql "host=strapi-on-azure.postgres.database.azure.com port=5432 dbname=postgres user=malhao password=YourPassword123 sslmode=require"After connecting to the database you’ll have to create the database for Strapi to use.
create database strapi_on_azure;We can check if the database was created by listing all existing databases:
postgres=> \lAfter that we disconnect from our database.
postgres=> \q10. Add database configurations to the Strapi Web App
Now, let’s add the database configurations to our Strapi Web App. Go to Settings > Configurations section and click on Advanced edit.
The final Settings file should look something like this:
[
{
"name": "DATABASE_HOST",
"value": "strapi-on-azure.postgres.database.azure.com",
"slotSetting": false
},
{
"name": "DATABASE_NAME",
"value": "strapi_on_azure",
"slotSetting": false
},
{
"name": "DATABASE_PASSWORD",
"value": "YourDatabasePassword",
"slotSetting": false
},
{
"name": "DATABASE_PORT",
"value": "5432",
"slotSetting": false
},
{
"name": "DATABASE_SSL",
"value": "true",
"slotSetting": false
},
{
"name": "DATABASE_USERNAME",
"value": "malhao",
"slotSetting": false
},
{
"name": "WEBSITE_HTTPLOGGING_RETENTION_DAYS",
"value": "30",
"slotSetting": false
}
]Finally save your changes.
11. Add production configuration to Strapi project
Now we need to create the server configuration in our Strapi project.
/* ./config/env/production/server.js */module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
url: 'https://strapi-on-azure.azurewebsites.net',
});
And the admin panel configuration. There’s no need to set the full path to your front-end (i.e. https://witty-sky-061465203.azurestaticapps.net). “/” will suffice.
module.exports = ({ env }) => ({
auth: {
secret: env('ADMIN_JWT_SECRET'),
},
url: '/',
serveAdminPanel: false
});In order to use the PostgrSQL server we’ll have to install the pq node package.
yarn add pgAnd add the configuration file.
/* ./config/env/production/database.js */module.exports = ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('DATABASE_HOST'),
port: env.int('DATABASE_PORT'),
database: env('DATABASE_NAME'),
user: env('DATABASE_USERNAME'),
password: env('DATABASE_PASSWORD'),
ssl: env.bool('DATABASE_SSL', false),
},
},
});
Now, commit and push your code. Go make yourself a cuppa, you deserve it if you came this far.
Once the builds finish open your Static Web App URL. In my case: https://witty-sky-061465203.azurestaticapps.net
If everything went according to plan, you should be able to create your admin credentials and login into the admin portal for the very first time.
Hurrah! It’s all done.
The next step is probably to configure an email provider. With previous Strapi instances I’ve used SendGrid and I’m still happy with it — make sure you always have a whitelisted IP address so you can login into your account. Otherwise, you’ll have to raise a customer support ticket — happened to me.
