I originally contributed the following as a guide for the official Strapi docs, but as they are working on v4 of Strapi at the moment, I figured it would still be good to include somewhere, so here it is on my blog! As a result, the layout of the content won't be my normal blog style, it's more documtation-esq, but it should still do the job.
If you're new to Strapi, Strapi is a headless CMS that you would host somewhere and use their API to pull the content into an application, be it a SPA in your favourite JavaScript framework, a mobile app, or something else.
These guides are tested against the v3 release of Strapi, as v4 is in beta at the time of writing. It's likely that much of the content covered here will be applicable for v4, the only thing I expect to change is how to use the file upload provider, I'm unsure if the existing plugin will work with v4.
Azure Install Requirements
- You must have an Azure account before doing these steps.
Table of Contents
- Create resources using the portal
- Create using the Azure CLI
- Create Azure Resource Manager template
- Storing files and images with Azure Storage
Required Resources
There are three resources in Azure that are required to run Strapi in a PaaS model, AppService to host the Strapi web application, Storage to store images/uploaded assets, and a database, Azure has managed MySQL and Postgres to choose from (for this tutorial, we'll use MySQL, but the steps are the same for MySQL).
Creating Resources via the Azure Portal
In this section we'll use the Azure Portal to create the required resources to host Strapi.
Navigate to the Azure Portal
Click Create a resource and search for Resource group from the provided search box
Provide a name for your Resource Group,
my-strapi-app
, and select a regionClick Review + create then Create
Navigate to the Resource Group once it's created, click Create resources
and search for Web AppEnsure the Subscription and Resource Group are correct, then provide the following configuration for the app:
- _Name_ - `my-strapi-app`
- _Publish_ - `Code`
- _Runtime stack_ - `Node 14 LTS`
- _Operating System_ - `Linux`
- _Region_ - Select an appropriate region
Use the App Service Plan to select the appropriate Sku and size for the level of scale your app will need (refer to the Azure docs for more information on the various Sku and sizes)
Click Review + create then Create
Navigate back to the Resource Group and click Create then search for Storage account and click Create
Ensure the Subscription and Resource Group are correct, then provide the following configuration for the storage account:
- _Name_ - `my-strapi-app`
- _Region_ - Select an appropriate region
- _Performance_ - `Standard`
- _Redundancy_ - Select the appropriate level of redundancy for your files
Click Review + create then Create
Navigate back to the Resource Group and click Create then search for Azure Database for MySQL and click Create
Select Single server for the service type
Ensure the Subscription and Resource Group are correct, then provide the following configuration for the storage account:
- _Name_ - `my-strapi-db`
- _Data source_ - `None` (unless you're wanting to import from a backup)
- _Location_ - Select an appropriate region
- _Version_ - `5.7`
- _Compute + storage_ - Select an appropriate scale for your requirements (Basic is adequate for many Strapi workloads)
- Enter a username and password for the Administrator account, click Review + create then Create
Configuring the Resources
Once all the resources are created, you will need to get the connection information for the MySQL and Storage account to the Web App, as well as configure the resources for use.
Configure the Storage Account
- Navigate to the Storage Account resource, then Data storage - Containers
- Create a new Container, provide a Name,
strapi-uploads
, and set Public access level toBlob
, then click Create - Navigate to Security + networking - Access keys, copy the Storage account name and key1
- Navigate to the Web App you created and go to Settings - Configuration
- Create new application settings for the Storage account, storage account key and container name (these will become the environment variables available to Strapi) and click Save
Configure MySQL
- Navigate to the MySQL resource then Settings - Connection security
- Set
Allow access to Azure services
toYes
and click Save - Navigate to Overview and copy Server name and Server admin login name
- Open the Azure Cloud Shell and log into the
mysql
cli:
- `mysql --host <server> --user <username> -p`
- Create a database for Strapi to use
CREATE DATABASE strapi;
then close the Cloud Shell- Optional - create a separate non server admin user (see this doc for guidance)
- Navigate to the Web App you created and go to Settings - Configuration
- Create new application settings for the Database host, username and password (these will become the environment variables available to Strapi) and click Save
Creating Resources via the Azure CLI
In this section, we'll use the Azure CLI to create the required resources. This will assume you have some familiarity with the Azure CLI and how to find the right values.
-
Create a new Resource Group
rgName=my-strapi-app location=westus az group create --name $rgName --location $location
-
Create a new Linux App Service Plan (ensure you change the
number-of-workers
andsku
to meet your scale requirements)
appPlanName=strapi-app-service-plan az appservice plan create --resource-group $rgName --name $appPlanName --is-linux --number-of-workers 4 --sku S1 --location $location
-
Create a Web App running Node.js 14
webAppName=my-strapi-app az webapp create --resource-group $rgName --name $webAppName --plan $appPlanName --runtime "node|10.14"
-
Create a Storage Account
saName=mystrapiapp az storage account create --resource-group $rgName --name $saName --location $location # Get the access key saKey=$(az storage account keys list --account-name $saName --query "[?keyName=='key1'].value" --output tsv) # Add a container to the storage account container=strapi-uploads az storage container create --name $container --public-access blob --access-key $saKey --account-name $saName
-
Create a MySQL database
serverName=my-strapi-db dbName=strapi username=strapi password=... # Create the server az mysql server create --resource-group $rgName --name $serverName --location $location --admin-user $username --admin-password $password --version 5.7 --sku-name B_Gen5_1 # Create the database az mysql db create --resource-group $rgName --name $dbName --server-name $serverName # Allow Azure resources through the firewall az mysql server firewall-rule create --resource-group $rgName --server-name $serverName --name AllowAllAzureIps --start-ip-range 0.0.0.0 --end-ip-range 0.0.0.0
-
Add configuration values to the Web App
az webapp config appsettings set --resource-group $rgName --name $webAppName --setting STORAGE_ACCOUNT=$saName az webapp config appsettings set --resource-group $rgName --name $webAppName --setting STORAGE_ACCOUNT_KEY=$saKey az webapp config appsettings set --resource-group $rgName --name $webAppName --setting STORAGE_ACCOUNT_CONTAINER=$container az webapp config appsettings set --resource-group $rgName --name $webAppName --setting DATABASE_HOST=$serverName.mysql.database.azure.com az webapp config appsettings set --resource-group $rgName --name $webAppName --setting DATABASE_USERNAME=$username@$serverName az webapp config appsettings set --resource-group $rgName --name $webAppName --setting DATABASE_PASSWORD=$password
Deploy with an Azure Resource Manager template
To deploy using an Azure Resource Manager template, use the botton below, or upload this template as a custom deployment in Azure.
Storing files and images
As AppService is a PaaS hosting model, an upload provider will be required to save the uploaded assets to Azure Storage. Check out https://github.com/jakeFeldman/strapi-provider-upload-azure-storage for more details on using Azure Storage as an upload provider.
Local development
For local development, you can either use the standard Strapi file/image upload provider (which stored on the local disk), or the Azurite emulator.
Deploying and running Strapi
Azure AppService can be deployed to using CI/CD pipelines or via FTPS, refer to the Azure docs on how to do this for your preferred manner.
To start the Node.js application, AppService will run the npm start
command. As there is no guarantee that the symlinks created by npm install
were preserved (in the case of an upload from a CI/CD pipeline) it is recommended that the npm start
command directly references the Keystone entry point:
"scripts": {
"start": "node node_modules/strapi/bin/strapi.js start"
}
Conclusion
This has been a look at how we can use the different PaaS features of Azure to host Strapi, and the different ways in which you can setup those resources. I prefer to use the Resource Manager template myself, and then configure GitHub Actions as the CI/CD pipeline so that deployments all happen smoothly in the future.
Hopefully this makes it easier for you to also get your Strapi sites running in Azure, and once Strapi 4 is out, I'll get some updated content on the differences that you need to be aware of when hosting in Azure.