Alternative ATProto PDS implementation
1param webAppName string 2param location string = resourceGroup().location // Location for all resources 3 4param sku string = 'B1' // The SKU of App Service Plan 5param dockerContainerName string = '${webAppName}:latest' 6param repositoryUrl string = 'https://github.com/DrChat/bluepds' 7param branch string = 'main' 8param customDomain string 9 10@description('Redeploy hostnames without SSL binding. Just specify `true` if this is the first time you\'re deploying the app.') 11param redeployHostnamesHack bool = false 12 13var acrName = toLower('${webAppName}${uniqueString(resourceGroup().id)}') 14var aspName = toLower('${webAppName}-asp') 15var webName = toLower('${webAppName}${uniqueString(resourceGroup().id)}') 16var sanName = toLower('${webAppName}${uniqueString(resourceGroup().id)}') 17 18// resource appInsights 'Microsoft.OperationalInsights/workspaces@2023-09-01' = { 19// name: '${webAppName}-ai' 20// location: location 21// properties: { 22// publicNetworkAccessForIngestion: 'Enabled' 23// workspaceCapping: { 24// dailyQuotaGb: 1 25// } 26// sku: { 27// name: 'Standalone' 28// } 29// } 30// } 31 32// resource appServicePlanDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { 33// name: appServicePlan.name 34// scope: appServicePlan 35// properties: { 36// workspaceId: appInsights.id 37// metrics: [ 38// { 39// category: 'AllMetrics' 40// enabled: true 41// } 42// ] 43// } 44// } 45 46resource appServicePlan 'Microsoft.Web/serverfarms@2020-06-01' = { 47 name: aspName 48 location: location 49 properties: { 50 reserved: true 51 } 52 sku: { 53 name: sku 54 } 55 kind: 'linux' 56} 57 58resource acrResource 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = { 59 name: acrName 60 location: location 61 sku: { 62 name: 'Basic' 63 } 64 properties: { 65 adminUserEnabled: false 66 } 67} 68 69resource appStorage 'Microsoft.Storage/storageAccounts@2023-05-01' = { 70 name: sanName 71 location: location 72 kind: 'StorageV2' 73 sku: { 74 name: 'Standard_LRS' 75 } 76} 77 78resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2023-05-01' = { 79 name: '${appStorage.name}/default/data' 80 properties: {} 81} 82 83resource appService 'Microsoft.Web/sites@2020-06-01' = { 84 name: webName 85 location: location 86 identity: { 87 type: 'SystemAssigned' 88 } 89 properties: { 90 httpsOnly: true 91 serverFarmId: appServicePlan.id 92 siteConfig: { 93 // Sigh. This took _far_ too long to figure out. 94 // We must authenticate to ACR, as no credentials are set up by default 95 // (the Az CLI will implicitly set them up in the background) 96 acrUseManagedIdentityCreds: true 97 appSettings: [ 98 { 99 name: 'BLUEPDS_HOST_NAME' 100 value: empty(customDomain) ? '${webName}.azurewebsites.net' : customDomain 101 } 102 { 103 name: 'BLUEPDS_TEST' 104 value: 'false' 105 } 106 { 107 name: 'WEBSITES_PORT' 108 value: '8000' 109 } 110 ] 111 linuxFxVersion: 'DOCKER|${acrName}.azurecr.io/${dockerContainerName}' 112 } 113 } 114} 115 116resource hostNameBinding 'Microsoft.Web/sites/hostNameBindings@2024-04-01' = if (redeployHostnamesHack) { 117 name: customDomain 118 parent: appService 119 properties: { 120 siteName: appService.name 121 hostNameType: 'Verified' 122 sslState: 'Disabled' 123 } 124} 125 126// This stupidity is required because Azure requires a circular dependency in order to define a custom hostname with SSL. 127// https://stackoverflow.com/questions/73077972/how-to-deploy-app-service-with-managed-ssl-certificate-using-arm 128module certificateBindings './deploymentBindingHack.bicep' = { 129 name: '${deployment().name}-ssl' 130 params: { 131 appServicePlanResourceId: appServicePlan.id 132 customHostnames: [customDomain] 133 location: location 134 webAppName: appService.name 135 } 136 dependsOn: [hostNameBinding] 137} 138 139resource appServiceStorageConfig 'Microsoft.Web/sites/config@2024-04-01' = { 140 name: 'azurestorageaccounts' 141 parent: appService 142 properties: { 143 data: { 144 type: 'AzureFiles' 145 shareName: 'data' 146 mountPath: '/app/data' 147 accountName: appStorage.name 148 // WTF? Where's the ability to mount storage via managed identity? 149 accessKey: appStorage.listKeys().keys[0].value 150 } 151 } 152} 153 154@description('This is the built-in AcrPull role. See https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#acrpull') 155resource acrPullRoleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { 156 scope: subscription() 157 name: '7f951dda-4ed3-4680-a7ca-43fe172d538d' 158} 159 160resource appServiceAcrPull 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 161 name: guid(resourceGroup().id, acrResource.id, appService.id, 'AssignAcrPullToAS') 162 scope: acrResource 163 properties: { 164 description: 'Assign AcrPull role to AS' 165 principalId: appService.identity.principalId 166 principalType: 'ServicePrincipal' 167 roleDefinitionId: acrPullRoleDefinition.id 168 } 169} 170 171resource srcControls 'Microsoft.Web/sites/sourcecontrols@2021-01-01' = { 172 name: 'web' 173 parent: appService 174 properties: { 175 repoUrl: repositoryUrl 176 branch: branch 177 isManualIntegration: true 178 } 179} 180 181output acr string = acrResource.name 182output domain string = appService.properties.hostNames[0]