Azure Blob client and Active Storage adapter to replace the now abandoned azure-storage-blob
An Active Storage is supplied, but the gem is Rails agnostic and can be used in any Ruby project.
To migrate from azure-storage-blob to azure-blob:
- Replace
azure-storage-blob
in your Gemfile withazure-blob
- Run
bundle install
- Change the
AzureStorage
service toAzureBlob
in your Active Storage config (config/storage.yml
) - Restart or deploy the app.
Example config:
microsoft:
service: AzureBlob
storage_account_name: account_name
storage_access_key: SECRET_KEY
container: container_name
AzureBlob supports managed identities on :
- Azure VM
- App Service
- Azure Functions (Untested but should work)
- Azure Containers (Untested but should work)
AKS support will likely require more work. Contributions are welcome.
To authenticate through managed identities instead of a shared key, omit storage_access_key
from your storage.yml
file and pass in the identity principal_id
.
ActiveStorage config example:
prod:
service: AzureBlob
container: container_name
storage_account_name: account_name
principal_id: 71b34410-4c50-451d-b456-95ead1b18cce
To use Azurite, pass the storage_blob_host
config key with the Azurite URL (http://127.0.0.1:10000/devstoreaccount1
by default)
and the Azurite credentials (devstoreaccount1
and Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==
by default).
Example:
dev:
service: AzureBlob
container: container_name
storage_account_name: devstoreaccount1
storage_access_key: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
storage_blob_host: http://127.0.0.1:10000/devstoreaccount1
You'll have to create the container before you can start uploading files. You can do so using Azure CLI, Azure Storage Explorer, or by running:
bin/rails runner "ActiveStorage::Blob.service.client.tap{|client| client.create_container unless client.get_container_properties.present?}.tap { |client| puts 'done!' if client.get_container_properties.present?}"
Make sure that config.active_storage.service = :dev
is set to your azurite configuration.
Container names can't have any special characters, or you'll get an error.
Instantiate a client with your account name, an access key and the container name:
client = AzureBlob::Client.new(
account_name: @account_name,
access_key: @access_key,
container: @container,
)
path = "some/new/file"
# Upload
client.create_block_blob(path, "Hello world!")
# Download
client.get_blob(path) #=> "Hello world!"
# Delete
client.delete_blob(path)
For the full list of methods: https://www.rubydoc.info/gems/azure-blob/AzureBlob/Client
The client is configured to raise an error early for missing credentials, causing it to crash before becoming healthy. This behavior can sometimes be undesirable, such as during assets precompilation.
To enable lazy loading and ignore missing credentials, set the lazy
option:
AzureBlob::Client.new(account_name: nil, access_key: nil, container: nil, lazy: true)
or add lazy: true
to your config/storage.yml
for Active Storage.
A dev environment is supplied through Nix with devenv.
- Install devenv.
- Enter the dev environment by cd into the repo and running
devenv shell
(ordirenv allow
if you are a direnv user). - Log into azure CLI with
az login
terraform init
terraform apply
This will generate the necessary infrastructure on azure.- Generate devenv.local.nix with your private key and container information:
generate-env-file
- If you are using direnv, the environment will reload automatically. If not, exit the shell and reopen it by hitting and running
devenv shell
again.
To test with Entra ID, the AZURE_ACCESS_KEY
environment variable must be unset and the code must be ran or proxied through a VPS with the proper roles.
For cost saving, the terraform variable create_vm
and create_app_service
are false by default.
To create the VPS and App service, Create a var file var.tfvars
containing:
create_vm = true
create_app_service = true
and re-apply terraform: terraform apply -var-file=var.tfvars
.
This will create the VPS and required managed identities.
bin/rake test_azure_vm
and bin/rake test_app_service
will establish a VPN connection to the VM or App service container and run the test suite. You might be prompted for a sudo password when the VPN starts (sshuttle).
After you are done, run terraform again without the var file (terraform apply
) to destroy the VPS and App service application.
Some tests copied over from Rails don't clean after themselves. A rake task is provided to empty your containers and keep cost low: bin/rake flush_test_container
If you prefer not using devenv/nix:
Ensure your version of Ruby fit the minimum version in azure-blob.gemspec
and setup those Env variables:
AZURE_ACCOUNT_NAME
AZURE_ACCESS_KEY
AZURE_PRIVATE_CONTAINER
AZURE_PUBLIC_CONTAINER
The gem is available as open source under the terms of the MIT License.