Recently I've re-written my blog in its entirety. Having first built it in 2014, it was time to give it a refresh. In this post I want to talk about my journey deploying Directus to Microsoft Azure.
The reason I chose Directus was threefold:
- Open source — full transparency and an active community
- Self-hosting friendly — not locked into their cloud offering
- Attach to existing databases — this was the killer feature for me since I already had a SQL Server database with all my posts, meaning zero data migration
Deploying to Azure was trickier than expected. Here's what I learned.
Spinning Up the Docker Image in Azure
Azure Web Apps supports Docker containers, which makes deploying Directus straightforward in theory. In practice, there were a few gotchas.
Creating the Web App
- In the Azure Portal, create a new Web App
- Under Publish, select Container (this is currently in preview)
- Choose Linux as the operating system
- Select an appropriate App Service Plan (B1 works fine for a personal blog)
Choosing the Right Image Version
This is where I lost some time. Not all Directus versions run smoothly on Azure Web Apps. After some trial and error, I found that version 10.11.0 worked reliably:
image: directus/directus:10.11.0
Later versions like 10.12.x caused startup issues on Azure's container runtime. If you're hitting problems, try pinning to 10.11.0 first.
Essential Environment Variables
At minimum, you'll need these environment variables configured in your App's Environment Variables section:
KEY=<random-uuid>
SECRET=<random-string>
ADMIN_EMAIL=your@email.com # To Access the Directus Admin Panel
ADMIN_PASSWORD=<strong-password> # To Access the Directus Admin Panel
DB_CLIENT=mssql
DB_HOST=<your-db-server>.database.windows.net
DB_PORT=1433
DB_DATABASE=<database-name>
DB_USER=<username>
DB_PASSWORD=<password>
DB_ENCRYPT=true
The DB_ENCRYPT=true is essential for Azure SQL Database connections.
Configuring Azure Storage
By default, Directus stores uploaded files locally. This doesn't work well on Azure Web Apps since the filesystem isn't persistent across container restarts. You need to configure Azure Blob Storage.
Setting Up Storage
- Create a new Storage Account in the same resource group as your Web App
- Create a container (I called mine
blogstorage) - Set the access level based on your needs:
- Blob (anonymous read) — recommended for public blogs. Images are served directly from Azure Storage, bypassing Directus for better performance
- Private — Directus proxies all requests through
/assets/<id>. More control, but adds latency
Granting Access
The cleanest approach is using managed identity:
- In your Web App, enable System assigned managed identity
- In your Storage Account, go to Access Control (IAM)
- Add a role assignment: give your Web App the Storage Blob Data Contributor role
Configuring Directus
Add these environment variables to your Web App:
STORAGE_LOCATIONS=azure
STORAGE_AZURE_DRIVER=azure
STORAGE_AZURE_CONTAINER_NAME=blogstorage
STORAGE_AZURE_ACCOUNT_NAME=<your-storage-account>
STORAGE_AZURE_ACCOUNT_KEY=<your-access-key>
If using managed identity instead of access keys, you can use:
STORAGE_AZURE_ENDPOINT=https://<account>.blob.core.windows.net
And omit the account key entirely.
Assigning a Custom Subdomain (Optional)
I wanted Directus accessible at it's own subdomain rather than the default *.azurewebsites.net URL.
DNS Configuration
- In your DNS provider, create a CNAME record:
- Name:
directus - Value:
<your-app-name>.azurewebsites.net
- Name:
Azure Configuration
- In your Web App, go to Custom domains
- Click Add custom domain
- Enter your subdomain
- Azure will verify the CNAME record exists
- Once verified, add an App Service Managed Certificate for free HTTPS
Update CORS Settings
Don't forget to update your Directus configuration with the following environment variables:
CORS_ENABLED=true
CORS_ORIGIN=https://domain.com,https://sub.domain.com
Gotchas & Lessons Learned
A few things that caught me out:
- Version matters — not all Directus Docker images run on Azure. Version 10.11.0 was stable for me
- Filesystem is ephemeral — configure Azure Storage from day one, not after you've uploaded content
- Cold starts — the free/shared tiers have aggressive cold starts. B1 or higher keeps the container warm
- Database firewall — ensure your Azure SQL Database allows connections from Azure services
- HTTPS redirect — enable "HTTPS Only" in your Web App settings once your custom domain is configured
Wrapping Up
Self-hosting Directus on Azure is entirely viable for a personal blog or small project. The combination of Azure Web Apps for the container, Azure SQL Database for persistence, and Azure Blob Storage for uploads gives you a fully managed setup with minimal maintenance overhead.
The ability to connect Directus to my existing database meant I could rebuild my frontend completely while keeping all my content intact — exactly what I needed for a 2026 refresh of a 2014 blog.