Everything needed to deploy Outline to Azure Container Apps. The Bicep template automatically creates all required resources including PostgreSQL, Redis, and Azure File Storage.
-
Install Azure CLI (if not already installed)
# macOS brew install azure-cli # Linux curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash # Windows # Download from https://aka.ms/InstallAzureCLI
-
Login to Azure
az login az account set --subscription "your-subscription-id"
-
Generate Secrets
# Generate SECRET_KEY openssl rand -hex 32 # Generate UTILS_SECRET openssl rand -hex 32
-
Update Parameters
- Edit
azuredeploy.parameters.json - Update
secretKeyandutilsSecretwith generated values - Update
postgresAdminPasswordwith a strong password - Update
azureClientIdandazureClientSecretwith your Azure AD app credentials - Note: You can leave
outlineUrlas the placeholder for now - we'll update it after deployment with the actual FQDN
- Edit
-
Deploy
cd Azure chmod +x deploy.sh ./deploy.sh -
Update Configuration After Deployment
- The script will show your Container App FQDN (e.g.,
outline-app.xyz123.azurecontainerapps.io) - Update the
outlineUrlin the Container App (see Post-Deployment section below) - Add Azure AD redirect URI:
https://your-fqdn.azurecontainerapps.io/auth/azure.callback - Go to Azure Portal → Azure AD → App registrations → Your app → Authentication
- The script will show your Container App FQDN (e.g.,
- Azure CLI installed and configured
- Azure Subscription with permissions to create:
- Resource Groups
- Container Apps
- PostgreSQL Flexible Servers
- Redis Caches
- Storage Accounts
- Log Analytics Workspaces
- Azure AD App Registration with:
- Client ID
- Client Secret
- Redirect URI (configured after deployment)
The Bicep template automatically creates:
-
Azure Database for PostgreSQL Flexible Server
- Database:
outline - Auto-configured with SSL
- Firewall rule for Azure services
- Database:
-
Azure Cache for Redis
- SSL/TLS only
- Auto-configured connection
-
Azure Storage Account
- Azure File Share (for volume mounts - default)
- Blob container (for S3-compatible storage - alternative)
-
Container Apps Environment
- Managed environment with logging
-
Container App
- Running Outline
- Auto-scaling configured
- Volume mount for persistent storage
-
Log Analytics Workspace
- For monitoring and logs
Edit azuredeploy.parameters.json and update these required values:
Required:
secretKey: Generated withopenssl rand -hex 32utilsSecret: Generated withopenssl rand -hex 32postgresAdminPassword: Strong password for PostgreSQLazureClientId: Your Azure AD Client IDazureClientSecret: Your Azure AD Client Secret
Can be updated after deployment:
outlineUrl: Your public domain URL. You can use a placeholder initially (e.g.,https://outline.yourdomain.com) and update it after deployment with the actual Container App FQDN or your custom domain
Optional (have defaults):
useVolumeMount:true(uses Azure File Storage volume mounts - recommended)fileShareName:outline-files(name of the Azure File Share)useAzureStorage:true(uses Azure Storage, set tofalsefor external S3)- Resource names (auto-generated if left empty)
cd Azure
chmod +x deploy.sh
./deploy.shThe script will:
- Check Azure CLI installation
- Verify you're logged in
- Create resource group
- Deploy all infrastructure
- Show your Container App FQDN
# Create resource group
az group create --name outline-rg --location centralus
# Deploy infrastructure
az deployment group create \
--resource-group outline-rg \
--template-file main.bicep \
--parameters @azuredeploy.parameters.jsonAfter deployment, you'll get a FQDN. Update your Azure AD app registration:
- Go to Azure Portal → Azure Active Directory → App registrations
- Find your app (by Client ID)
- Go to Authentication
- Add redirect URI:
https://your-container-app-fqdn.azurecontainerapps.io/auth/azure.callback - Save
After deployment, you'll get a Container App FQDN. Update the outlineUrl environment variable:
# Get your Container App FQDN
FQDN=$(az containerapp show \
--name outline-app \
--resource-group outline-rg \
--query "properties.configuration.ingress.fqdn" \
--output tsv)
# Update the URL (use the FQDN or your custom domain)
az containerapp update \
--name outline-app \
--resource-group outline-rg \
--set-env-vars "URL=https://${FQDN}"Or if using a custom domain:
az containerapp update \
--name outline-app \
--resource-group outline-rg \
--set-env-vars "URL=https://outline.yourdomain.com"Visit your Container App FQDN (shown after deployment) and sign in with Azure AD!
# Create Container App Environment
az containerapp env create \
--name outline-env \
--resource-group outline-rg \
--location eastus
# Create Container App
az containerapp create \
--name outline-app \
--resource-group outline-rg \
--environment outline-env \
--image docker.getoutline.com/outlinewiki/outline:latest \
--target-port 3000 \
--ingress external \
--env-vars \
NODE_ENV=production \
URL=https://your-domain.com \
PORT=3000 \
--secrets \
secret-key="your-secret-key" \
database-url="your-database-url" \
redis-url="your-redis-url" \
--cpu 1.0 \
--memory 2Gi \
--min-replicas 1 \
--max-replicas 10The template is configured to use Azure File Storage as volume mounts by default. This is the simplest and most Azure-native approach.
How it works:
- Azure File Share is created automatically
- Mounted at
/var/lib/outline/datain the container - Outline uses local storage (
FILE_STORAGE=local) - Files persist across restarts and are shared across replicas
Configuration:
useVolumeMount=true(default)fileShareName=outline-files(default)- No additional setup required!
If you prefer S3-compatible storage:
-
External S3 Service:
- Set
useAzureStorage=falsein parameters - Provide
awsAccessKeyId,awsSecretAccessKey,s3BucketName,awsRegion - Works immediately
- Set
-
MinIO Gateway (Azure-native S3):
- Set
useVolumeMount=falsein parameters - Deploy MinIO Container App separately
- Set
The deployment is configured with:
- Min replicas: 1
- Max replicas: 10
- Auto-scaling: Based on HTTP concurrent requests (100 requests per replica)
You can adjust these in the main.bicep file or update after deployment:
az containerapp update \
--name outline-app \
--resource-group outline-rg \
--min-replicas 2 \
--max-replicas 20Logs are automatically sent to Azure Log Analytics. You can view them in:
- Azure Portal → Container Apps → outline-app → Log stream
- Azure Portal → Log Analytics workspaces → outline-logs
- Check logs:
az containerapp logs show --name outline-app --resource-group outline-rg --follow - Verify all secrets are correctly set
- Check database connectivity from Azure
- Verify PostgreSQL firewall allows Azure services
- Check connection string format
- Ensure SSL is properly configured (
sslmode=require)
- Verify Azure AD redirect URI matches your Container App FQDN
- Check Azure AD app registration settings
- Verify client ID and secret are correct
- Use Consumption plan for Container Apps (pay per use)
- Consider using Azure Database for PostgreSQL Flexible Server with burstable tier for development
- Use Basic tier for Azure Cache for Redis for development
# Get Container App URL
az containerapp show \
--name outline-app \
--resource-group outline-rg \
--query "properties.configuration.ingress.fqdn" \
--output tsv
# View logs
az containerapp logs show \
--name outline-app \
--resource-group outline-rg \
--follow- Go to Azure Portal → Container Apps → outline-app → Custom domains
- Add your custom domain
- Configure DNS records as shown
- SSL certificate is automatically managed by Azure
To update environment variables or secrets:
# Update a single environment variable
az containerapp update \
--name outline-app \
--resource-group outline-rg \
--set-env-vars "KEY=VALUE"
# Update multiple environment variables
az containerapp update \
--name outline-app \
--resource-group outline-rg \
--set-env-vars "KEY1=VALUE1" "KEY2=VALUE2"
# Update the URL (important for Outline to generate correct links)
az containerapp update \
--name outline-app \
--resource-group outline-rg \
--set-env-vars "URL=https://your-actual-domain.com"Important: The URL environment variable tells Outline what domain it's running on. This is used for generating links, email notifications, and OAuth redirects. Make sure to update it after deployment with your actual Container App FQDN or custom domain.
- ✅ Deploy the infrastructure (done!)
- ✅ Update Azure AD redirect URI
- ✅ Access your Outline instance
- Configure custom domain (optional)
- Set up additional authentication providers (optional)
For more information: