Introduction
============
Azure App Service provides you an easy and quick way to deploy your web applications. In this post, I will detail how to map multiple domains for multiple sites in single Windows or Linux Web App. Basically they are leveraging the Web Server like IIS or Nginx to rewrite requests to separate sub-directories like D:\home\site\wwwroot\siteA in Windows or /home/site/wwwroot/sg in Linux.
Preparation
============
- Web App (Windows/Linux)
- Custom domains
Topology diagram
============
How to
============
- Firstly, we can bind domains to the web app by adding custom domain from Portal. After binding, we can see them listed like as below:
Note: As mentioned on the wizard, Azure must verify that you are the owner of this domain name. So you should create a CNAME/A record and TXT record in a public DNS provider that match your domain to the the Web app public URL.
Windows
- For Windows Web App, we can go ahead to "Advanced Tools" and choose Go
- Then we navigate to D:\home\site\wwwroot, and create two direcotries, for example "a" and "b", and create web.config file if it does not exist by clicking the button near "wwwroot":
- In each directory, you can put your separate websites. As an sample, I put an index.html in each of them.
- Then click the edit button to open the web.config file.
- Pasting below content into it and update the domain names and paths accordingly, then save. They are used to set the redirection rules, note that there is no need to set Virtual applications and directories.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="a.cominaco.com" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^a\.cominaco\.com$" />
<add input="{PATH_INFO}" pattern="^/a/" negate="true" />
</conditions>
<action type="Rewrite" url="\a\{R:0}" />
</rule>
<rule name="b.cominaco.com" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^b\.cominaco\.com$" />
<add input="{PATH_INFO}" pattern="^/b/" negate="true" />
</conditions>
<action type="Rewrite" url="\b\{R:0}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
- All done. It would take effect without restarting.
Linux
- For Linux Web App, it is important to know that most official docker images do not support changing configuration of web server, hence it will not work. In this demo, we will use WordPress for Linux as an example as it supports customizing nginx.conf.
- Suppose we already bind the custom domains and set two sites in /home/site/wwwroot and /home/site/wwwroot/sg
- Go to SSH console from portal
- Open the config file using 'vim /etc/nginx/conf.d/default.conf' and update the file like as below, please change the server_name and root directory accordingly.
upstream php {
server unix:/var/run/php/php-fpm.sock;
#server 127.0.0.1:9000;
}
server {
listen 80;
server_name sg.cominaco.com;
root /home/site/wwwroot/sg;
## This should be in your http block and if it is, it's not needed here.
index index.php;
if ($request_uri ~* "/(cart|checkout|my-account)/*$") {
set $skip_cache 1;
}
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~* \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi.conf;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass php;
fastcgi_read_timeout 300;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache off;
fastcgi_cache_valid 60m;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
server {
listen 80;
## Your website name goes here.
server_name main.cominaco.com;
root /home/site/wwwroot;
## This should be in your http block and if it is, it's not needed here.
index index.php;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Add locations of phpmyadmin here.
# Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html
sendfile off;
set $skip_cache 0;
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache uris containing the following segments
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
# Don't cache WooCommerce URLs
# Cart widgets are still a problem: https://github.com/emcniece/docker-wordpress/issues/3
if ($request_uri ~* "/(cart|checkout|my-account)/*$") {
set $skip_cache 1;
}
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~* \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi.conf;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass php;
fastcgi_read_timeout 300;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache off;
fastcgi_cache_valid 60m;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
- Then run "nginx -s reload" to load the configuration.
- All done! you can now check the results, here are the results in this demo: http://main.cominaco.com/, http://sg.cominaco.com/
Thanks for reading this post. I hope you enjoyed it. Please feel free to write your comments and views about the same over here.
Posted at https://sl.advdat.com/3CjGXrr