Headache free multiple accounts subdomains and private domains in web applications.
Our goal is to give our users the ability to use subdomains and private domains with zero hassle and with complete automation.
We have a web application that lets the user define a private subdomain like so:
account1.app-domain.com
account2.app-domain.com
account3.app-domain.com
app-domain.com is the main aplication domain.
To achieve this you do something like this:
Configure Wildcard Subdomains in your DNS zone file and in your web server virtual host.
| Name | Data | Type |
| *.app-domain.com | app-domain.com | CNAME |
| app-domain.com | 123.45.678.910 | A |
Apache virtual host:
ServerName *.ap-domain.com
In your application, find and load the account from the database via the subdomain field.
Rails routes file:
match '', to: homepage#show', constraints: lambda { |r| r.subdomain.present? && r.subdomain != 'www' }
So far so good
Next you want to allow the user to use his own private domain (with or without "WWW" prefix) like so:
WWW.USER1-PRIVATE-DOMAIN.COM
(with "WWW" prefix) will load
ACCOUNT1.APP-DOMAIN.COM
USER1-PRIVATE-DOMAIN.COM
(without "WWW" prefix) will load
ACCOUNT1.APP-DOMAIN.COM
WWW.USER2-PRIVATE-DOMAIN.COM
(with "WWW" prefix) will load
ACCOUNT2.APP-DOMAIN.COM
USER2-PRIVATE-DOMAIN.COM
(without "WWW" prefix) will load
ACCOUNT2.APP-DOMAIN.COM
and so on
To achieve this you do something like this:
On the server virtual host:
ServerName *.ap-domain.com ServerAlias www.user1-private-domain.com ServerAlias user1-private-domain.com ServerAlias www.user2-private-domain.com ServerAlias user2-private-domain.com ServerAlias www.user3-private-domain.com ServerAlias user3-private-domain.com
And so on
For each users private domain DNS zone:
| Name | Data | Type |
| user1-private-domain.com | 123.45.678.910 | A |
| www | user1-private-domain.com | CNAME |
Isn't it great?
Well not at all…
Problem
If you have 3 users then everything is fine, But what if you have 1000 users and you want everything to handle itself automatically?
Another problem
what if you decide to upgrade your server one day and you change the IP Address? Are you going to contact 1000 users to change their DNS zone file?
The solution is very simple and easy to achieve,You will not need to deal with settings at all, this functionality will be completely automatic.
Step 1:
Make your app the default site on the server so that a domain that is not listed in any of the virtual hosts on the server will end up pointing to the default site => Our application.
This will eliminate the need to update our virtual host with ServerAlias for every private domain. Whatever private domains coming our servers way will all point to our app.
Apache default site is the first configuration virtual host file in “sites-enabled” directory ordered by its name, so go to “sites-available” directory, disable (sudo a2dissite) the application, change the name of the conf file to 00000-myapp.conf and enable (sudo a2ensite) right back again. make sure the new name is the first when ordered by name. You will need to restart apache for the changes to take effect.
Step 2:
Initially instruct your users to configure their DNS zone like so:
| Name | Data | Type |
| www | app-domain.com | CNAME |
We point the subdomain to the application domain rather then to the private domain A record, Now you can change your servers IP Address Daily and all 1000 private domains (with www prefix) will always point to the right IP.
One more big headache elimination to go...
How do we make sure that the users private domain without www prefix will point to the right IP?
In the DNS zone we have an A record that points to the current app IP. But if we change the app IP someday all domains without www prefix will be lost.
Last step:
Buy a small 5$ VPS and install apache, Configure apache to redirect whatever domain (that does not have the www prefix) to the same domain but with the www prefix like so:
http://domain.com => 301 redirect to http://www.domain.com
Apache (default site) virtual host:
ServerAdmin erez@qcm.co.il
ServerName 133.22.666.444
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
We use mod_rewrite to achieve this
RewriteEngine on # The RewriteEngine directive enables the runtime rewriting engin
RewriteCond %{HTTP_HOST} !^www\. [NC]
# Check if the domain have www prefix in it? if yes proceed
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# Redirect to the domain, Add “http://www.” in the beginning with status 301 moved permanently
Ones this server is up and running forever the user will set his DNS zone with an A record like so:
| Name | Data | Type |
| user1-private-domain.com | 133.22.666.444 | A |
Where 133.22.666.444 is the IP of the redirecting server.
Now when we go to a private domain like user1-private-domain.com without www prefix, we will always be redirected to www.user1-private-domain.com and to the right server IP and the right app on the server.
2 downsides:
- redirects will not work for https requests.
- the redirect will cost us time => the time it takes to redirect.
Well, nobody is perfect :)
Hope this helps somebody.