I am trying to figure out what the optimal configuration is for my virtual host files, but I'm having some issues with it.
Currently I have 2 domains: domain1.com and domain2.com
I have 1 server at IP 000.000.000.001 which actually hosts all the needed files. In these files you have an API (api.domain1.com) and the actual website.
domain1.com is using the nameservers of Digital Ocean and uses the following DNS records:
A # 000.000.000.001
CNAME * domain1.com.
For SEO purposes I want to redirect all requests which are not being made to the api subdomain to forward to www.domain1.com.
However, I also ONLY want users to be able to browse my site (and API) through a SSL connection, I don't want users being able to use it through HTTP so I try to redirect all those requests to use HTTPS. The certificates are provided by LetsEncrypt!. Their automated install made changes to my virtual hosts files and currently I have 4 of them:
api.domain1.com.conf
<VirtualHost *:80>
ServerName api.domain1.com
DocumentRoot /var/www/api.domain1.com/web
RewriteEngine on
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [L,QSA,R=permanent]
</VirtualHost>
api.domain1.com-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName api.domain1.com
DocumentRoot /var/www/api.domain1.com/web
ExpiresActive On
/* ... */
<Directory /var/www/api.domain1.com/web>
AllowOverride None
Order Allow,Deny
Allow from All
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
</IfModule>
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLCertificateFile /etc/letsencrypt/live/domain1.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain1.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateChainFile /etc/letsencrypt/live/domain1.com/chain.pem
</VirtualHost>
</IfModule>
domain1.com.conf
<VirtualHost *:80>
ServerName domain1.com
Redirect 301 / https://www.domain1.com
</VirtualHost>
domain1.com-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName www.domain1.com
DocumentRoot /var/www/domain1.com
ExpiresActive On
/* ... */
RewriteEngine On
RewriteCond %{HTTP_HOST} ^https://domain1.com
RewriteRule ^/(.*)$ https://www.domain1.com/$1 [L,R=301]
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
ErrorDocument 404 /404.html
SSLCertificateFile /etc/letsencrypt/live/domain1.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain1.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateChainFile /etc/letsencrypt/live/domain1.com/chain.pem
</VirtualHost>
</IfModule>
When I try to visit the site, the following things happen:
http://test.domain1.com --> https://test.domain1.com FAIL
http://domain1.com --> https://www.domain1.com SUCCESS
http://www.domain1.com --> https://www.domain1.com SUCCESS
https://domain1.com --> https://domain1.com FAIL
https://www.domain1.com --> https://www.domain1.com SUCCESS
As you can see, the first and fourth entry fails. They both return a 404 Not Found to my visitors which is unacceptable to me. The first one even shows a SSL warning (I don't think that LetsEncrypt! supports wildcards so I think this warning cannot be prevented?)
What is causing my test. not redirecting to www.?
What is causing my fourth entry to end up serving a 404?
Now I also want my second domain (domain2.com) to point to this server/files. This domain is hosted at a different location (I got it from a friend) and is using different nameservers. I cannot simply change the nameservers (I think?) because this second domain has email hosting linked to it which uses the nameservers of this other provider. Momentarily, this domain also has its own web server (but this will go away in the future) hosted at 000.000.000.002. Right now, it uses a
<meta http-equiv="refresh" content="0; url=https://www.domain1.com" />
tag in its index.html file to redirect to the right server, in the future this will have to be done in the DNS records though.
How should I do this?
So to summarise:
I thought the CNAME * is a catch-all for all subdomains?
What did I do wrong in the virtual hosts file? Something is causing that fourth redirect to fail.
How should I handle my second domain pointing at my first IP?
Is there another way to only allow HTTPS connections? (This should also be forced on the API virtual host). I've heard of HSTS, should I implement this?
Some SEO tests also pointed out that I need a IP redirect to further improve my SEO results. They give this as an example:
RewriteCond %{HTTP_HOST} ^000\.000\.000\.001
RewriteRule (.*) http://www.domain1.com/$1 [R=301,L]
Should I also implement this for SEO purposes? Should I also implement this for my other IP address?
So many questions...
Of course, if you have any other suggestions, please share your opinion!
Lots of questions there! Let's try to work through them:
Not sure what you are asking here, and not an expert in CNAMES but would have thought you'd need '*.domain1.com' at least instead of just '*'
For both you fails you do not explicitly note your alternative server names in either ServerName nor ServerAlias. In this case it will default to the first server found in the config. Is this the api.domain.com one? If so that might explain the 404 as the SERVER_NAME will (by default) be the client supplied one so the api.domain1.com:80 settings will just redirect to the https version of what they sent (which is what appears to be happening), which will then also look at the api.domain1.com:443 config and not find the name. You would need to either add the alternative names to ServerAlias setting of your main domain1.com config, or move that config to be first so it becomes the default and the api one is only used when the api.domain1.com name is explicitly used.
As you appear to want to redirect this straight to your new site I would update the DNS to point to your new IP address, to save you paying for two servers (in terms of money and time to administer). This can be done on the existing DNS nameserver to keep the e-mail though obviously would be nicer to consolidate on one. In the meantime implement a proper 301 redirect in the server config as the meta redirect is not as strong a signal to search engines and you do seem to care about SEO.
The main way is to redirect http to https. HSTS is primarily a security feature which automatically redirects http to https before the browser makes the request. This is useful as the default is http (e.g. typing www.example.com in the browser address bar will, by default, send you to http://www.example.com rather than https://www.example.com), and this can be intercepted to prevent an upgrade to https (which is more difficult to then intercept). It has some downsides though: Not all browsers support it, you need to visit the website at least once to load the HSTS setting (though some browsers allow pre-loading of this), and the setting will expire if the site is not visited in the maxAge time (again assuming it's not preloaded). So it should not be used as a replacement to redirects but more as an enforcement of it for browsers that support HSTS. Blogged about it here if you want to read more on HSTS.
I would also say you have several different methods of redirecting (api:80 has Rewrite, domain1:80 has Redirect, domain1:443 has Rewrite - but with a very restrictive and incorrect RewriteCond). Personally I prefer to use one method as it's less confusing but that's a personal matter (Redirect is also slightly faster but Rewrite gives you more power so I prefer that one). So I tend to have config like this:
<VirtualHost *:80>
#This is the first host so is the default.
#So although I've specified a ServerName and ServerAlias anything else not specified elsewhere will also end up here.
ServerName www.domain1.com
ServerAlias domain1.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
#Redirect everything to https:
RewriteEngine on
RewriteRule ^(.*)$ https://www.domain1.com$1 [R=301,L]
</VirtualHost>
<VirtualHost *:80>
ServerName api.domain1.com
ErrorLog ${APACHE_LOG_DIR}/api.error.log
CustomLog ${APACHE_LOG_DIR}/api.access.log combined
#Redirect everything to https:
RewriteEngine on
RewriteRule ^(.*)$ https://api.domain1.com$1 [R=301,L]
</VirtualHost>
and then for the 443 I would have this:
<VirtualHost *:443>
#This is the first host so is the default.
#So although I've specified a ServerName and ServerAlias anything else not specified elsewhere will also end up here.
ServerName www.domain1.com
ServerAlias domain1.com
ErrorLog ${APACHE_LOG_DIR}/ssl.error.log
CustomLog ${APACHE_LOG_DIR}/ssl.access.log combined
#Redirect everything which is not already on the real www domain name to that:
RewriteEngine on
RewriteCond %{HTTP_HOST} !www.domain1.com
RewriteRule ^(.*)$ https://www.domain1.com$1 [R=301,L]
#all your other 443 config for www.domain1.com
</VirtualHost>
<VirtualHost *:443>
ServerName api.domain1.com
ErrorLog ${APACHE_LOG_DIR}/ssl.api.error.log
CustomLog ${APACHE_LOG_DIR}/ssl.api.access.log combined
#all your other 443 config for api.domain1.com
</VirtualHost>
Note that I've added different log files for each vhost so it's more obvious which vhost is being hit.
Note also that I redirect anything which is not www.domain1.com rather than your version which only redirected if people typed domain1.com (and which I'm not sure would be used as suspect api.domain1.com config came first).
This will also take care of anyone accessing your website by IP address, or any other name as it will always be redirect to your real www.domain1.com server name. This is easy for http requests, but for https requests they may indeed get a cert error if your cert does not include the servername used.
LetsEncrypt do not support wildcards, but they do allow multiple names on a cert so you can easily get a cert for domain1.com and www.domain1.com and you should as this is generally considered best practice. You could also add any other domains you think might be used. For you api.domain1.com domain you could also add to this same cert, or get a separate cert for that since you have separate config for that (your config above is not clear on which you are doing for that since it looks like same config but not sure if that's a typo or not).
For SEO purposes it is indeed best to only serve your site under one URL and use redirects to enforce that URL and above config will do this. This is to prevent Google thinking you have duplicate content if you server the same content under www.domain1.com/page1.html and https://www.domain1.com/page1.html and https://domain1.com/page1.html and http://000.000.000.001/page1.html ...etc.
A lot covered there but hopefully points you in the right direction.
Related
Hoping somebody will be able to help me to understand how the following would work as well as why it would need to be done if that's okay?
I've got two domains.
domain-one.co.uk - this is the main domain and holds an SSL cert
domain-one-uk.com - this is another domain our client owns, it's not secure and they want it to redirect to the first domain.
Is this simply going to be a case of adding a 301 rule in the htaccess file in the public folder or do I need to do anything with the DNS settings?
I added the following but it didn't seem to work
RewriteCond %{HTTP_HOST} ^www\.domain\-one\-uk\.com$
RewriteRule ^$ https://www.domain-one.co.uk/? [L,R=301]
Would appreciate any help and teaching anyone can provide.
Thank you
If there is no existing URLs to redirect and this is only a domain redirect, i'd go for a basic 301 redirect in the .htaccess on the insecure server, which will redirect anything that arrives there to the new domain :
Redirect 301 / https://secure-domain.net/
If the insecure server used to have content that is also available on the secure server (with the same URLs, besides the protocol and domain), then you indeed need to use RewriteRules, eg. :
RewriteEngine On
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
In your case, the missing "RewriteEngine On" certainly caused the redirect not to work.
The RewriteCond that checks the current domain name is only needed if this htaccess is used by both domains (ie. they are handled by the same server, using the same directory).
I have the following issue and can't find a solution. Also I am not sure if this does work at all.
I have two domains. domain.de and domain.com
The german site has the domain domain.de. As soon as the domain domain.com is being used the redirect shall be to domain.com/en/. In other words. Only if the domain.com is used it shall be redirected to domain.com/en/.
But at the same time there are other URLs. e.g. domain.com/en/about-us/ .. or domain.com/it/bieno/. They all should not be affected.
Is it possible to redirect only the domain domain.com to domain.com/en/ and at the same time all other URLs would still be working?
It is a TYPO3 9.x installation btw. Perhaps I can solve this in TYPO3?
Eric
If you're using Apache (or a different webserver which supports this) you can use mod_rewrite to achieve this by adding the following to your .htaccess (replacing the domains of course):
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
Rewriterule ^/?$ https://example.com/en/ [L,R=301]
The RewriteCond checks if the domain is example.com or www.example.com. If you only need it to work for example.com, you can remove (www\.)?. ^/?$ checks if the requested path is / or empty.
If you use the default .htaccess for TYPO3, you don't need RewriteEngine On, but you will need to add this somewhere after the existing RewriteEngine On and before RewriteRule ^.*$ %{ENV:CWD}index.php [QSA,L]. I'd add it right after RewriteEngine On.
I have checked out the posts and made the appropriate changes to the configuration files to make zend framework 2 to work on my local environment. Everything goes fine but the redirection of the page on specifying the vhost name doesnot work appropriately. It displays me the home page of the MAMP server with the directory listing.
Here is what I have done till now:
httpd.conf
<VirtualHost *:80>
ServerName newportalcopper.localhost
DocumentRoot /Applications/MAMP/htdocs/NewPortalCopper/public
SetEnv APPLICATION_ENV "development"
<Directory /Applications/MAMP/htdocs/NewPortalCopper/public>
DirectoryIndex index.php
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
etc/hosts
127.0.0.1 newportalcopper.localhost localhost
Can some one tell me what i am doing wrong that this particular thing is not working.
Thanks for viewing the post guys and the help specified. At the end i was able to sort the problem out.
The main issue was the port number in case of MAMP. It was required to be 8888 instead of 80. This specifically solved my problem.
Currently users, going to our www URL get SSL errors, ie "the certificate for this website is invalid". This is because we only have one cert, which is configured for the non-WWW URL: mysite.co
We want requests for either
http://www.mysite.co
https://www.mysite.co
to go to
https://mysite.co
The reverse is acceptable, since our motivation is to minimize costs by paying for only one cert, either www or without www. I did read another post, saying SSL negotiation happens before any response from the server (in our case redirection), so visitors will receive a warning when using a domain that is not in our common name. However, I modified DNS to include a CNAME so that all www.mysite.co traffic redirects to mysite.co and we still see the error in Firefox and Safari
We use Ubuntu with the following mod_rewrite
1) in /etc/apache2/sites-available/mysite-ssl
<VirtualHost *:443>
RewriteEngine on
RewriteCond %{HTTP_HOST} www.mysite.com [NC]
RewriteRule ^(.*)$ https://mysite.com/$1 [R=permanent,L,NC]
ServerAdmin admin#mysite
ServerName mysite
ServerAlias www.mysite
... other stuff ...
</VirtualHost>
2) in /etc/apache2/sites-available/mysite
<VirtualHost *:80>
RewriteEngine on
ReWriteCond %{SERVER_PORT} !^443$
RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R,L]
</VirtualHost>
Interestingly, Chrome says everything fine when going to WWW.mysite.co (both http and https)
However BOTH Firefox and Safari complain of a hostname mismatch (cannot verify identity)
So after more reading & research, the above rules work for redirecting traffic from www.site.co to site.co
However, the only way to have two or more URL's secured with one SSL Certificate is to purchase either:
a Wildcard SSL Certificate, which covers *.site.co .. these do not need to be defined at purchase time
an SSL Cert with one or more Subject Alternative Names (SANs) that cover www.site.co .. mail.site.co .. etc. These need to be defined when you purchase the Cert, specifying each SAN
I'm using Ubuntu Server with Apache2 to host my websites.
I have two domains, www.test.com and www.domain.com (not real names)
Inside of my sites-available I have the default that is pointed to my www.test.com domain and then I have a created one for www.domain.com inside that I have:
<VirtualHost *:80>
ServerName www.domain.com
ServerAlias domain.com
DocumentRoot /var/www/domainfolder
<Directory />
Options +FollowSymLinks
AllowOverride all
</Directory>
</VirtualHost>
Now the website works, I can navigate to it and use it but since I'm using it for wordpress when ever I click on say Admin CP it will try to navigate to www.domain.com/domainfolder/admin-cp/ I'm just not sure why it's trying to access the folder it's stored in?
Using .htaccess just gives me an internal server error because it's always going down a directory, here is the code:
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_URI} !(.*)folder
RewriteRule ^(.*)$ domainfolder/$1 [L]
They would need separate addresses in Virtual hosts to use separate directories.
Given example.com and folders one, two, and three
You need to choose
1. example.com (one), example.com/two and example.com/three
or example.com (one), two.example.com and three.example.com
example.com (one), two.com and three.com
Given
DocumentRoot /www/subdomain/sub1
ServerName www.sub1.domain.tld
ServerPath /sub1/
RewriteEngine On
RewriteRule ^(/sub1/.*) /www/subdomain$1
Do you have a rule similar to the highlighted section above, rewrites are how you get the pretty address you are looking for.
Also, make sure apache mod_rewrite is enabled.