A storage module to use Azure Blob Storage as key/certificate storage backend for your Certmagic-enabled HTTPS server.
Inspired by grafana/certmagic-gcs.
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.
In this section, we create a Caddy config using our Azure Blob Storage backend.
-
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
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!"
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 and omit
connection_string
:$ export AZURE_STORAGE_ACCOUNT="myaccount" $ export AZURE_STORAGE_KEY="......" # 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.
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
The tests support multiple authentication methods, mirroring the behavior of the real module:
-
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 ./...
-
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 ./...
-
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.
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 ./...
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. 🙏
This module is distributed under AGPL-3.0-only.