Serve http (port 80) and https (port 443) on same VirtualHost

138,378

Solution 1

You can't do this in one virtual host, because Apache needs to know which one's going to talk SSL and which one isn't (sidenote: nginx doesn't have this problem, you can tell it which listen directives relate to SSL; one of the many reasons I love it).

The way I manage this in Apache is to put all my non-SSL-related configuration into a separate file, and then have the two vhosts configured next to each other, each including the site-specific configuration file inside the vhost stanza, like this:

<VirtualHost 192.0.2.12:80>
    Include /etc/apache2/sites/example.com
</VirtualHost>

<VirtualHost 192.0.2.12:443>
    SSLEngine On
    # etc
    Include /etc/apache2/sites/example.com
</VirtualHost>

Solution 2

It seems like an issue in Apache vHost, but it does the job without having to repeat configuration.

SSLCertificateFile /srv/.ssl/self/server.crt
SSLCertificateKeyFile /srv/.ssl/self/server.pem

# REQUIRED
<VirtualHost *:80>
    DocumentRoot /srv/www/badhost
</VirtualHost>

<VirtualHost *:80 *:443>
    SSLEngine On
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /srv/www/example.www
</VirtualHost>
Share:
138,378
kron
Author by

kron

Updated on September 18, 2022

Comments

  • kron
    kron over 1 year

    I need to setup my VirtualHost on Apache to serve on both http and https (using standard ports)

    If I enable the SSL Engine (as per below) - I get an error when on port 80.

    The reason is, parts of the site need to be SSL but other parts don't. How can I go about serving both http + https on the site?

    Here is my virtual host file....

    NameVirtualHost *
    
    <VirtualHost *>
            ServerAdmin webmaster@localhost
            ServerName mysite.co.uk
            DocumentRoot /var/www/mysite/public
            <Directory />
                    Options FollowSymLinks
                    AllowOverride None
            </Directory>
            <Directory /var/www/mysite/public>
                    Options Indexes FollowSymLinks MultiViews
                    AllowOverride All
                    Order allow,deny
                    allow from all
            </Directory>
    
            ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
            <Directory "/usr/lib/cgi-bin">
                    AllowOverride None
                    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                    Order allow,deny
                    Allow from all
            </Directory>
    
            ErrorLog /var/log/apache2/error.log
    
            # Possible values include: debug, info, notice, warn, error, crit,
            # alert, emerg.
            LogLevel warn
    
            CustomLog /var/log/apache2/access.log combined
            ServerSignature On
    
        Alias /doc/ "/usr/share/doc/"
        <Directory "/usr/share/doc/">
            Options Indexes MultiViews FollowSymLinks
            AllowOverride None
            Order deny,allow
            Deny from all
            Allow from 127.0.0.0/255.0.0.0 ::1/128
        </Directory>
    
         #SSL STUFF...
          SSLEngine on
          SSLCertificateFile /etc/apache2/crts/mysite.crt
          SSLCertificateKeyFile /etc/apache2/crts/mysite.key
          SSLCertificateChainFile /etc/apache2/crts/DigiCertCA.crt
    
    
    </VirtualHost>
    
  • user77376
    user77376 about 8 years
    That's really weird, but exists!
  • Daniel Beardsmore
    Daniel Beardsmore over 7 years
    This worked as well as you might expect from such a kludge — almost, but not quite! I found that Apache 2.4.10 sets the SERVER_PORT environment variable to 443 instead of using the port on which the request came in (80 or 443 depending). <IMAGINARY_PARAGRAPH_BREAK> Pity, as I was hoping to be able to use this, as I really wanted to keep one file per virtual host. <IMAGINARY_PARAGRAPH_BREAK> Also, you will need a ServerName directive inside the top <VirtualHost> otherwise it will gobble up requests by mistake. Set it to ServerName badhost.bad or something.
  • Ulrich Schwarz
    Ulrich Schwarz over 7 years
    @DanielBeardsmore: I've just tested this with 2.4.18 from RH Software collections, and that seems to be due to the default of UseCanonicalPhysicalPort Off. If you set that to on, you seem to get the actual port used. (Funnily enough, I had to leave off the SSLEngine On in my doubly-used vhost and got port 80 as the default.)
  • Ulrich Schwarz
    Ulrich Schwarz over 7 years
    @DanielBeardsmore: FWIW, %{HTTPS} will also be set correctly, but %{REQUEST_SCHEME} isn't (always http). I'd feel silly putting in a feature request for a UseCanonicalRequestScheme directive, though.