A colleague had setup something along these lines at work. It’s a good idea and I couldn’t figure out any blog post or docs mentioning such a use case, so thought I’d write something up.
What we wanted to do was have URL redirection. That’s to say if someone visits https://rakhesh.com I want it to forward to https://rakhesh.net. Simple stuff, and I think the recently announced Azure Front Door can be used for the same now. Of course when he setup redirection this wasn’t available so he had to resort to other means. What he did was setup an App Service and modify its web.config
file to do IIS redirects. While I knew of App Services and knew you could modify the web.config
setting via Application Settings I hadn’t realized you can entirely replace it.
In fact, before jumping into web.config
I should probably first mention that IIS has a URL Rewrite extension and while that is something you usually install manually it is present by default in App Service. Here’s an example web.config
that redirects all requests to Google:
1 2 3 4 5 6 7 8 9 10 11 12 |
<configuration> <system.webServer> <rewrite> <rules> <rule name="Rewrite to google.com"> <match url="^(.*)$" /> <action type="Redirect" url="https://www.google.com" /> </rule> </rules> </rewrite> </system.webServer> </configuration> |
So what one needs to do to setup a redirection service is create an App Service and somehow replace its web.config
with one similar to the above that does the redirection for you. The App Service should use IIS so we’ll go with one of the .NET ones.
It’s probably easiest to create an App Service via the Portal so feel free to do it that way. Below is a rough sketch of the steps via CLI:
1 2 3 4 5 6 7 8 |
# create a resource group az group create --name $apprg --location $location # create app service plan az appservice plan create --resource-group $apprg --name $planname --location $location --sku "S1" # create webapp az webapp create --resource-group $apprg --plan $planname --name $appname --runtime "aspnet|V4.8" --deployment-local-git |
Replace all the $
variables accordingly of course.
One thing I did above, which you’ll have to do manually if creating this from the portal, is to set the deployment type as local Git. Again, it doesn’t have to be local Git – you can use any other deployment method to push the web.config
, or you can totally skip this and edit the web.config
file manually (I’ll show how in a bit). But that’s what the --deployment-local-git
switch in the last command above stands for.
In my case I ended up with an App Service with the following URL: https://rak-362143-wa.azurewebsites.net. Let’s say the domain I want to actually redirect is az.rakhesh.com
so what I’ll do now is 1) create a CNAME entry in DNS pointing az.rakhesh.com to rak-362143-wa.azurewebsites.net, and 2) add az.rakhesh.com as a custom domain to the App Service. Again, you can do the latter via the portal but here’s how to do it via the CLI:
1 |
az webapp config hostname add --webapp-name $appname --resource-group $apprg --hostname "az.rakhesh.com" |
Assuming no errors, we are good to proceed.
(Just to add: at this point only http://az.rakhesh.com will work. To get https working I’ll have to add a cert – skipping that for now).
Now onto the web.config
.
I’ll go into how to modify the web.config
file directly on the App Service – i.e. not via Git like I setup above. For this we can make use of something called Kudu. This is the engine that runs on an App Service and does the actual building of your code when you push it to an App Service. Turns out for every App Service like https://rak-362143-wa.azurewebsites.net you can go to a URL like https://rak-362143-wa.scm.azurewebsites.net that takes you to its Kudu page. On this page if you click on Debug Console > PowerShell
> and in the file manager that opens if you click on the site > wwwroot
folder you can then click the +
icon to create a new web.config
file.
Then click on the pencil icon next to the file, paste the web.config
text I had above and Save it. And that’s it! At this point if I go to http://az.rakhesh.com it will redirect me to Google. :)
Instead of creating and editing the file via Kudu it is also possible to create a file locally and push via Git. This is why I enabled local Git deployment above. What this does is that the App Service now has a Git repo associated to it with a username password combo, and one can push to this Git repo to make any changes to the App Service.
If you want to try this delete the web.config
file created above and read on…
The quickest way to see the Git repo details in the Portal is to go to the Deployment Center and see Local Git/FTPS credentials. Or to get these via the portal you can do the following:
1 2 3 4 5 6 7 8 |
# output the username, password etc. for git gituser=`az webapp deployment list-publishing-credentials --name $appname --resource-group $apprg | jq -r '.publishingUserName'` gitpass=`az webapp deployment list-publishing-credentials --name $appname --resource-group $apprg | jq -r '.publishingPassword'` gitrepo=`az webapp deployment source config-local-git --name $appname --resource-group $apprg | jq -r '.url' | sed "s/None/$gituser/g"` echo "Clone from $gitrepo; the password is $gitpass" |
After this change to some directory and clone $gitrepo
. Enter the password when prompted:
1 2 3 4 |
$ git clone $gitrepo Cloning into 'rak-362143-wa'... Password for 'https://$rak-362143-wa@rak-362143-wa.scm.azurewebsites.net': warning: You appear to have cloned an empty repository. |
Next change to the folder that was created and create a folder called FolderToDeploy
in that (I didn’t do this initially and figured I had to do this from the error messages). Create web.config
in here with the same info as earlier. And do a git add .
and git commit -m "initial commit"
and git push
as usual. In my case it threw the following error :)
1 2 3 4 5 6 7 8 9 10 |
Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to 6 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (4/4), 1.05 KiB | 1.05 MiB/s, done. Total 4 (delta 0), reused 0 (delta 0), pack-reused 0 remote: The current deployment branch is 'master', but nothing has been pushed to it remote: Error - Changes committed to remote repository but deployment to website failed. To https://rak-362143-wa.scm.azurewebsites.net/rak-362143-wa.git * [new branch] main -> main |
This bummed me for a while until I realized that locally my Git repo branch was called main
while in Azure it was master
. So I made a new branch locally called master
, set the upstream, and pushed again. This time it worked! (Note: if you are following along, don’t do this yet. Read on for one more issue I encountered, fix it, and then push).
1 2 3 4 5 |
# create a new local branch git checkout -b master # push the current branch and set the remote as upstream git push --set-upstream origin master |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 remote: Updating branch 'master'. remote: Updating submodules. remote: Preparing deployment for commit id '387ad970b1'. remote: Generating deployment script. remote: Generating deployment script for Web Site remote: Running deployment command... remote: Handling Basic Web Site deployment. remote: Creating app_offline.htm remote: KuduSync.NET from: 'D:\home\site\repository' to: 'D:\home\site\wwwroot' remote: Deleting file: 'hostingstart.html' remote: Copying file: 'FolderToDeploy\web.config' remote: Deleting app_offline.htm remote: Finished successfully. remote: Running post deployment command(s)... remote: Triggering recycle (preview mode disabled). remote: Deployment successful. To https://rak-362143-wa.scm.azurewebsites.net/rak-362143-wa.git * [new branch] master -> master Branch 'master' set up to track remote branch 'master' from 'origin'. |
Sweet!
Unfortunately this too does not work. :D What happens is the web.config
has been copied to a folder called FolderToDeploy
but that’s of no use to us as we want it to be in the root of wwwroot
. The trick to get it to copy over as I want is in this article. What I have to do is set the following in the Application Settings of the app:
1 |
SCM_SCRIPT_GENERATOR_ARGS=--basic -p FolderToDeploy |
I can do that via the CLI as follows:
1 |
az webapp config appsettings set --resource-group $apprg --name $appname --settings SCM_SCRIPT_GENERATOR_ARGS="--basic -p FolderToDeploy" |
Now I can push the config again. This time you’ll see it removes the FolderToDeploy
after the code is pushed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
[master 5a6191c] changes 1 file changed, 1 insertion(+), 1 deletion(-) Enumerating objects: 7, done. Counting objects: 100% (7/7), done. Delta compression using up to 6 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (4/4), 981 bytes | 981.00 KiB/s, done. Total 4 (delta 1), reused 0 (delta 0), pack-reused 0 remote: Updating branch 'master'. remote: Updating submodules. remote: Preparing deployment for commit id '5a6191c539'. remote: Generating deployment script. remote: The site directory path: .\FolderToDeploy remote: Generating deployment script for Web Site remote: Running deployment command... remote: Handling Basic Web Site deployment. remote: Creating app_offline.htm remote: KuduSync.NET from: 'D:\home\site\repository\FolderToDeploy' to: 'D:\home\site\wwwroot' remote: Deleting file: 'FolderToDeploy\web.config' remote: Deleting directory: 'FolderToDeploy' remote: Copying file: 'web.config' remote: Deleting app_offline.htm remote: Finished successfully. remote: Running post deployment command(s)... remote: Triggering recycle (preview mode disabled). remote: Deployment successful. To https://rak-362143-wa.scm.azurewebsites.net/rak-362143-wa.git 387ad97..5a6191c master -> master |
Now if I go to http://az.rakhesh.com/ it will redirect as expected!