Certmagic Storage Backend for Azure Blob Storage
A storage module to use Azure Blob Storage as key/certificate storage backend for your Certmagic-enabled HTTPS server.
Inspired by grafana/certmagic-gcs.
Usage
Azure Storage Account
Recommendations to enhance security:
- Enable infrastructure encryption during storage account creation for double encryption at rest.
- Use customer-managed keys for storage service encryption and leverage Key Vault key rotation policy.
- Apply least privilege RBAC controls - grant only the minimum required permissions (e.g.,
Storage Blob Data Contributor for the container).
- Use managed identity authentication where possible and disable storage account key access.
- Apply storage account network restrictions - configure firewalls, virtual networks, or private endpoints to limit access.
- Enable blob versioning and soft delete to protect against accidental deletion or corruption of certificates.
- Monitor access with Azure Storage Analytics and set up alerts for unusual access patterns.
Caddy
In this section, we create a Caddy config using our Azure Blob Storage backend.
Getting started
-
Set up Azure Storage Account
- Create an Azure Storage Account
- Create a blob container (e.g.,
caddy-data)
- The module will create the container if it doesn't exist and has enough permissions
- Get your connection string or configure authentication
-
Create a Caddyfile
{
storage azureblob {
account_name YOUR_STORAGE_ACCOUNT
container_name caddy-data
connection_string "YOUR_STORAGE_CONNECTION_STRING"
}
}
localhost
respond "Hello Caddy with Azure Blob Storage!"
-
Alternative: Using Managed Identity (recommended for Azure VMs)
{
storage azureblob {
account_name myaccount
container_name caddy-data
# connection_string omitted - will use managed identity
}
}
localhost
respond "Hello Caddy with Azure Blob Storage!"
-
Start Caddy
xcaddy run
-
Check that it works
curl https://localhost
Azure Storage Emulator (for development)
For local development, you can use Azurite (Azure Storage Emulator):
-
Start Azurite
If using VSCode the simplest way to use Azurite is the Azurite extension
-
Use development connection string
{
storage azureblob {
account_name YOUR_AZURITE_ACCOUNT
container_name caddy-data
connection_string "YOUR_AZURITE_CONNECTION_STRING"
}
}
localhost
respond "Hello Caddy with Azurite!"
Authentication Methods
This module supports several Azure authentication methods:
-
Connection String (Simple)
{
storage azureblob {
account_name YOUR_STORAGE_ACCOUNT
container_name caddy-data
connection_string "YOUR_STORAGE_CONNECTION_STRING"
}
}
-
Managed Identity (Recommended for Azure VMs)
{
storage azureblob {
account_name YOUR_STORAGE_ACCOUNT
container_name caddy-data
}
}
-
Environment Variables
Set these environment variables:
$ export AZURE_STORAGE_ACCOUNT="myaccount"
$ export AZURE_STORAGE_CONNECTION_STRING="......"
# Or for managed identity:
$ export AZURE_CLIENT_ID="......" # Optional: for user assigned identity
The AZURE_CLIENT_ID variable is optional and can be used to supply the client id for a user assigned managed identity. If omitted it will use a system assigned identity by default.
Configuration Options
| Parameter |
Description |
Required |
account_name |
Azure Storage Account name |
Yes |
container_name |
Blob container name for storing certificates |
Yes |
connection_string |
Azure Storage connection string |
No* |
*When connection_string is omitted, the module will attempt to use:
- Azure Managed Identity (if running on Azure)
- Environment variables (
AZURE_STORAGE_ACCOUNT, AZURE_STORAGE_CONNECTION_STRING)
- Azure CLI credentials
- Default Azure credential chain
Running Tests
The tests support multiple authentication methods, mirroring the behavior of the real module:
Local Development with Azurite (Recommended)
-
Install and start Azurite (Azure Storage Emulator)
-
Configure connection string:
cp .env.example .env
# Edit .env and uncomment the AZURE_STORAGE_CONNECTION_STRING line
# Use the default Azurite connection string provided in the file
-
Run tests:
go test ./...
Testing with Real Azure Storage
Option 1: Using Connection String
-
Create .env file:
cp .env.example .env
-
Edit .env with your real Azure Storage credentials:
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=YOUR_ACCOUNT;AccountKey=YOUR_KEY;EndpointSuffix=core.windows.net
AZURE_STORAGE_ACCOUNT=YOUR_ACCOUNT
-
Run tests:
go test ./...
Option 2: Using Azure CLI (No Connection String Required)
-
Login to Azure CLI:
az login
-
Set only the account name:
echo "AZURE_STORAGE_ACCOUNT=your-account-name" > .env
# Note: No AZURE_STORAGE_CONNECTION_STRING needed!
-
Run tests:
go test ./...
Tests will automatically use your Azure CLI credentials.
Option 3: Manual Environment Variables
With Connection String:
# Windows (PowerShell)
$env:AZURE_STORAGE_CONNECTION_STRING = "DefaultEndpointsProtocol=https;AccountName=..."
$env:AZURE_STORAGE_ACCOUNT = "your-account-name"
go test ./...
# Linux/macOS
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=..."
export AZURE_STORAGE_ACCOUNT="your-account-name"
go test ./...
With Azure CLI (after az login):
# Windows (PowerShell)
$env:AZURE_STORAGE_ACCOUNT = "your-account-name"
go test ./...
# Linux/macOS
export AZURE_STORAGE_ACCOUNT="your-account-name"
go test ./...
Acknowledgments
This module was created by adapting the excellent grafana/certmagic-gcs Google Cloud Storage implementation for Azure Blob Storage. Their Google Cloud Storage implementation was an invaluable reference for understanding the CertMagic storage interface and building a robust storage backend. 🙏
License
This module is distributed under AGPL-3.0-only.