.. include:: /_includes/all.rst

.. _vhost_gen_example_add_sub_domains:

************************
Example: add sub domains
************************

This tutorial gives you a brief overview how to serve your project under one subdomain via
the project directory name as well as how to serve one project with multiple subdomains with
a customized virtual host config via ``vhost-gen``.


**Table of Contents**

.. contents:: :local:


Simple sub domains for one project
==================================

When you just want to serve your project under different sub domains, you simply name your project
directory by the name of it. See the following examples how you build up your project URL.

+----------------+----------------+---------------------------------+
| Project dir    | ``TLD_SUFFIX`` | Project URL                     |
+================+================+=================================+
| my-test        | ``loc``        | ``http://my-test.loc``          |
+----------------+----------------+---------------------------------+
| www.my-test    | ``loc``        | ``http://www.my-test.loc``      |
+----------------+----------------+---------------------------------+
| t1.www.my-test | ``loc``        | ``http://t1.www.my-test.loc``   |
+----------------+----------------+---------------------------------+
| my-test        | ``local``      | ``http://my-test.local``        |
+----------------+----------------+---------------------------------+
| www.my-test    | ``local``      | ``http://www.my-test.local``    |
+----------------+----------------+---------------------------------+
| t2.www.my-test | ``local``      | ``http://t2.www.my-test.local`` |
+----------------+----------------+---------------------------------+

Whatever name you want to have in front of the ``TLD_SUFFIX`` is actually just the directory you
create. Generically, it looks like this:

+----------------+----------------+-------------------------------+
| Project dir    | ``TLD_SUFFIX`` | Project URL                   |
+================+================+===============================+
| <dir-name>     | ``<tld>``      | ``http://<dir-name>.<tld>``   |
+----------------+----------------+-------------------------------+

.. important::
   The project directories must be real directories and not symlinks!
   See example below for how to set it up.


Example
-------

Prerequisite
^^^^^^^^^^^^

Let's assume the following settings.

+-------------------------------+--------------------------------------+
| Variable                      | Value                                |
+===============================+======================================+
| :ref:`env_tld_suffix`         | ``loc``                              |
+-------------------------------+--------------------------------------+
| :ref:`env_httpd_docroot_dir`  | ``htdocs``                           |
+-------------------------------+--------------------------------------+
| Project name / directory      | ``my-test``                          |
+-------------------------------+--------------------------------------+
| Sub domain 1 / directory      | ``api.my-test``                      |
+-------------------------------+--------------------------------------+
| Sub domain 2 / directory      | ``www.my-test``                      |
+-------------------------------+--------------------------------------+

* Project which holds the data is ``my-test``
* Web root of ``my-test`` is in ``my-test/FRAMEWORK/public``
* Same project should be available under ``api.my-test`` and ``www.my-test``

Directory structure
^^^^^^^^^^^^^^^^^^^

.. code-block:: bash

   host> tree -L 2
   .
   ├── my-test
   │   ├── FRAMEWORK
   │   └── htdocs -> FRAMEWORK/public
   ├── api.my-test
   │   └── htdocs -> ../my-test/FRAMEWORK/public
   └── www.my-test
       └── htdocs -> ../my-test/FRAMEWORK/public

* ``my-test``, ``api.my-test`` and ``www.my-test`` must be **normal directories** (not symlinks).
* The *framework data* resided in ``my-test``.
* Each projects ``htdocs`` directory is a symlink pointing to the web root of the *framework* in ``my-test``

With this structure you will have three domains available pointing to the same project:

* http://my-test.loc
* http://api.my-test.loc
* http://www.my-test.loc


Complex sub domains for one project
===================================

When you want to have more complex sub domains for one project (such as in the
case of Wordpress multi-sites), you will need to customize your virtual host config for this
project and make the web server allow to serve your files by different server names.

Each web server virtual host is auto-generated by a tool called |ext_lnk_project_vhost_gen|.
``vhost-gen`` allows you to overwrite its
default generation process via templates. Those templates can be added to each project, giving
you the option to customize the virtual host of this specific project.

..
   note::
   :ref:`customize_all_virtual_hosts_globally` and :ref:`customize_specific_virtual_host`

.. note::
   :ref:`vhost_gen_virtual_host_templates`
     Ensure you have read and understand how to customize virtual hosts globally with ``vhost-gen``.
   :ref:`vhost_gen_customize_all_virtual_hosts_globally`
     Ensure you have read and understand how to customize virtual hosts globally with ``vhost-gen``.
   :ref:`vhost_gen_customize_specific_virtual_host`
     Ensure you have read and understand how to customize your virtual host with ``vhost-gen``.
   :ref:`env_httpd_template_dir`
     Ensure you know what this variable does inside your ``.env`` file.

.. important::
   When adjusting vhost-gen templates for a project you have to do **one** of the following:

   * Restart the devilbox
   * Or rename your project directory to some other name and then rename it back to its original name.

   More information here: :ref:`custom_vhost_apply_vhost_gen_changes`

.. warning::
   Pay close attention that you do not use TAB (``\t``) characters for indenting the vhost-gen
   yaml files. Some editors might automatically indent using TABs, so ensure they are replaced
   with spaces. If TAB characters are present, those files become invalid and won't work.
   https://github.com/cytopia/devilbox/issues/142

   You can use the bundled ``yamllint`` binary inside the container to validate your config.

   **See also:**

   * :ref:`work_inside_the_php_container`
   * :ref:`available_tools`


Prerequisite
------------

Let's assume the following settings.

+-------------------------------+--------------------------------------+
| Variable                      | Value                                |
+===============================+======================================+
| Devilbox path                 | ``/home/user/devilbox``              |
+-------------------------------+--------------------------------------+
| :ref:`env_httpd_template_dir` | ``.devilbox``                        |
+-------------------------------+--------------------------------------+
| :ref:`env_httpd_datadir`      | ``./data/www``                       |
+-------------------------------+--------------------------------------+
| :ref:`env_tld_suffix`         | ``loc``                              |
+-------------------------------+--------------------------------------+
| Project name/directory        | ``project-1`` (Ensure it exist)      |
+-------------------------------+--------------------------------------+

Ensure that the default ``vhost-gen`` templates have been copied to your projects template directory:

.. code-block:: bash

   # Navigate to the Devilbox directory
   host> cd ./home/user/devilbox

   # Create template directory in your project
   host> mkdir ./data/www/project-1/.devilbox

   # Copy vhost-gen templates
   host> cp cfg/vhost-gen/*.yml ./data/www/project-1/.devilbox

By having done all prerequisite, your project should be available under http://my-project-1.loc

Now you are all set and we can dive into the actual configuration.


.. _tutorial_adding_sub_domains_apache_22:

Apache 2.2
----------

Adding ``www`` sub domain
^^^^^^^^^^^^^^^^^^^^^^^^^

Let's also make this project available under http://www.my-project-1.loc

Step 1: Add DNS entry
"""""""""""""""""""""

The first step would be to add an additional DNS entry for ``www.my-project-1.loc``.
See here how to do that for Linux, MacOS or Windows:
:ref:`getting_started_create_your_first_project_dns_entry`

DNS is in place, however when you visit http://www.my-project-1.loc, you will end up seeing the
Devilbox intranet, because this is the default host when no match has been found.

Step 2: Adjust apache22.yml
"""""""""""""""""""""""""""

Next you will have to adjust the Apache 2.2 vhost configuration template. The current default
template looks similar to the one shown below (**Note:** Only the ``vhost:`` sub section is shown
here).

.. code-block:: yaml
   :caption: /home/user/devilbox/data/www/project-1/.devilbox/apache22.yml
   :emphasize-lines: 3

   vhost: |
     <VirtualHost __DEFAULT_VHOST__:__PORT__>
         ServerName   __VHOST_NAME__

         CustomLog  "__ACCESS_LOG__" combined
         ErrorLog   "__ERROR_LOG__"

     __VHOST_DOCROOT__
     __VHOST_RPROXY__
     __PHP_FPM__
     __ALIASES__
     __DENIES__
     __SERVER_STATUS__
         # Custom directives
     __CUSTOM__
     </VirtualHost>

All you will have to do, is to add a``ServerAlias`` directive:

.. code-block:: yaml
   :caption: /home/user/devilbox/data/www/project-1/.devilbox/apache22.yml
   :emphasize-lines: 3,4

   vhost: |
     <VirtualHost __DEFAULT_VHOST__:__PORT__>
         ServerName   __VHOST_NAME__
         ServerAlias  www.__VHOST_NAME__

         CustomLog  "__ACCESS_LOG__" combined
         ErrorLog   "__ERROR_LOG__"

     __VHOST_DOCROOT__
     __VHOST_RPROXY__
     __PHP_FPM__
     __ALIASES__
     __DENIES__
     __SERVER_STATUS__
         # Custom directives
     __CUSTOM__
     </VirtualHost>

Step 3: Apply new changes
"""""""""""""""""""""""""

The **last step** is to actually to apply those changes. This is equal for all web servers.
Go to :ref:`tutorial_adding_sub_domains_apply_changes` and follow the steps.

Afterwards you can go and visit http://www.my-project-1.loc and you should see the same page as if you
visit http://my-project-1.loc


Adding catch-all sub domain
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Let's also make this project available under any sub domain.

Step 1: Add DNS entry
"""""""""""""""""""""

The first step would be to add DNS entries for all sub domains you require.
See here how to do that for Linux, MacOS or Windows:
:ref:`getting_started_create_your_first_project_dns_entry`

This however is not really convenient. If you have basically infinite sub domains (via catch-all),
you should consider using Auto-DNS instead: :ref:`setup_auto_dns`.

Step 2: Adjust apache22.yml
"""""""""""""""""""""""""""

Next you will have to adjust the Apache 2.2 vhost configuration template. The current default
template looks similar to the one shown below (**Note:** Only the ``vhost:`` sub section is shown
here).

.. code-block:: yaml
   :caption: /home/user/devilbox/data/www/project-1/.devilbox/apache22.yml
   :emphasize-lines: 3

   vhost: |
     <VirtualHost __DEFAULT_VHOST__:__PORT__>
         ServerName   __VHOST_NAME__

         CustomLog  "__ACCESS_LOG__" combined
         ErrorLog   "__ERROR_LOG__"

     __VHOST_DOCROOT__
     __VHOST_RPROXY__
     __PHP_FPM__
     __ALIASES__
     __DENIES__
     __SERVER_STATUS__
         # Custom directives
     __CUSTOM__
     </VirtualHost>

All you will have to do, is to add a ``ServerAlias`` directive which does catch-all:

.. code-block:: yaml
   :caption: /home/user/devilbox/data/www/project-1/.devilbox/apache22.yml
   :emphasize-lines: 3,4

   vhost: |
     <VirtualHost __DEFAULT_VHOST__:__PORT__>
         ServerName   __VHOST_NAME__
         ServerAlias  *.__VHOST_NAME__

         CustomLog  "__ACCESS_LOG__" combined
         ErrorLog   "__ERROR_LOG__"

     __VHOST_DOCROOT__
     __VHOST_RPROXY__
     __PHP_FPM__
     __ALIASES__
     __DENIES__
     __SERVER_STATUS__
         # Custom directives
     __CUSTOM__
     </VirtualHost>

Step 3: Apply new changes
"""""""""""""""""""""""""

The **last step** is to actually to apply those changes. This is equal for all web servers.
Go to :ref:`tutorial_adding_sub_domains_apply_changes` and follow the steps.


Apache 2.4
----------

The procedure for Apache 2.4 is exactly the same as for Apache 2.2, even the syntax is identical.
The only difference is that you need to adjust ``apache24.yml`` instead of ``apache22.yml``.

Just go up one section: :ref:`tutorial_adding_sub_domains_apache_22`


Nginx
-----

The procedure for Nginx is also exactly the same as for Apache 2.4, however the syntax of its
``nginx.yml`` file is slightly different, that's why the whole tutorial will be repeated here
fitted for Nginx.


Adding ``www`` sub domain
^^^^^^^^^^^^^^^^^^^^^^^^^

Let's also make this project available under http://www.my-project-1.loc

Step 1: Add DNS entry
"""""""""""""""""""""

The first step would be to add an additional DNS entry for ``www.my-project-1.loc``.
See here how to do that for Linux, MacOS or Windows:
:ref:`getting_started_create_your_first_project_dns_entry`

DNS is in place, however when you visit http://www.my-project-1.loc, you will end up seeing the
Devilbox intranet, because this is the default host when no match has been found.

Step 2: Adjust nginx.yml
"""""""""""""""""""""""""""

Next you will have to adjust the Nginx vhost configuration template. The current default
template looks similar to the one shown below (**Note:** Only the ``vhost:`` sub section is shown
here).

.. code-block:: yaml
   :caption: /home/user/devilbox/data/www/project-1/.devilbox/nginx.yml
   :emphasize-lines: 4

   vhost: |
     server {
         listen       __PORT____DEFAULT_VHOST__;
         server_name  __VHOST_NAME__;

         access_log   "__ACCESS_LOG__" combined;
         error_log    "__ERROR_LOG__" warn;

     __VHOST_DOCROOT__
     __VHOST_RPROXY__
     __PHP_FPM__
     __ALIASES__
     __DENIES__
     __SERVER_STATUS__
         # Custom directives
     __CUSTOM__
     }

All you will have to do, is to extend the ``server_name`` directive:

.. code-block:: yaml
   :caption: /home/user/devilbox/data/www/project-1/.devilbox/nginx.yml
   :emphasize-lines: 4

   vhost: |
     server {
         listen       __PORT____DEFAULT_VHOST__;
         server_name  __VHOST_NAME__ www.__VHOST_NAME__;

         access_log   "__ACCESS_LOG__" combined;
         error_log    "__ERROR_LOG__" warn;

     __VHOST_DOCROOT__
     __VHOST_RPROXY__
     __PHP_FPM__
     __ALIASES__
     __DENIES__
     __SERVER_STATUS__
         # Custom directives
     __CUSTOM__
     }


Step 3: Apply new changes
"""""""""""""""""""""""""

The **last step** is to actually to apply those changes. This is equal for all web servers.
Go to :ref:`tutorial_adding_sub_domains_apply_changes` and follow the steps.

Afterwards you can go and visit http://www.my-project-1.loc and you should see the same page as if you
visit http://my-project-1.loc


Adding catch-all sub domain
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Let's also make this project available under any sub domain.

Step 1: Add DNS entry
"""""""""""""""""""""

The first step would be to add DNS entries for all sub domains you require.
See here how to do that for Linux, MacOS or Windows:
:ref:`getting_started_create_your_first_project_dns_entry`

This however is not really convenient. If you have basically infinite sub domains (via catch-all),
you should consider using Auto-DNS instead: :ref:`setup_auto_dns`.


Step 2: Adjust nginx.yml
"""""""""""""""""""""""""""

Next you will have to adjust the Nginx vhost configuration template. The current default
template looks similar to the one shown below (**Note:** Only the ``vhost:`` sub section is shown
here).

.. code-block:: yaml
   :caption: /home/user/devilbox/data/www/project-1/.devilbox/nginx.yml
   :emphasize-lines: 4

   vhost: |
     server {
         listen       __PORT____DEFAULT_VHOST__;
         server_name  __VHOST_NAME__;

         access_log   "__ACCESS_LOG__" combined;
         error_log    "__ERROR_LOG__" warn;

     __VHOST_DOCROOT__
     __VHOST_RPROXY__
     __PHP_FPM__
     __ALIASES__
     __DENIES__
     __SERVER_STATUS__
         # Custom directives
     __CUSTOM__
     }

All you will have to do, is to extend the ``server_name`` directive with a catch-all:

.. code-block:: yaml
   :caption: /home/user/devilbox/data/www/project-1/.devilbox/nginx.yml
   :emphasize-lines: 4

   vhost: |
     server {
         listen       __PORT____DEFAULT_VHOST__;
         server_name  __VHOST_NAME__ *.__VHOST_NAME__;

         access_log   "__ACCESS_LOG__" combined;
         error_log    "__ERROR_LOG__" warn;

     __VHOST_DOCROOT__
     __VHOST_RPROXY__
     __PHP_FPM__
     __ALIASES__
     __DENIES__
     __SERVER_STATUS__
         # Custom directives
     __CUSTOM__
     }

Step 3: Apply new changes
"""""""""""""""""""""""""

The **last step** is to actually to apply those changes. This is equal for all web servers.
Go to :ref:`tutorial_adding_sub_domains_apply_changes` and follow the steps.


.. _tutorial_adding_sub_domains_apply_changes:

Apply changes
-------------

After having edited your vhost-gen template files, you still need to apply these changes.
This can be achieved in two ways:

1. Restart the Devilbox
2. Rename your project directory back and forth

Let's cover the second step

.. code-block:: bash

   # Navigate to the data directory
   host> /home/user/devilbox/data/www

   # Rename your project to something else
   host> mv project-1 project-1.tmp

   # Rename your project to its original name
   host> mv project-1.tmp project-1

If you want to understand what is going on right now, check the docker logs for the web server.

.. code-block:: bash

   # Navigate to the devilbox directory
   host> /home/user/devilbox

   # Check docker logs
   host> docker-compose logs httpd

   httpd_1  | vhostgen: [2018-03-18 11:46:52] Adding: project-1.tmp.loc
   httpd_1  | watcherd: [2018-03-18 11:46:52] [OK]  ADD: succeeded: /shared/httpd/project-1.tmp
   httpd_1  | watcherd: [2018-03-18 11:46:52] [OK]  DEL: succeeded: /shared/httpd/project-1
   httpd_1  | watcherd: [2018-03-18 11:46:52] [OK]  TRIGGER succeeded: /usr/local/apache2/bin/httpd -k restart

   httpd_1  | vhostgen: [2018-03-18 11:46:52] Adding: project-1loc
   httpd_1  | watcherd: [2018-03-18 11:46:52] [OK]  ADD: succeeded: /shared/httpd/project-1
   httpd_1  | watcherd: [2018-03-18 11:46:52] [OK]  DEL: succeeded: /shared/httpd/project-1.tmp
   httpd_1  | watcherd: [2018-03-18 11:46:52] [OK]  TRIGGER succeeded: /usr/local/apache2/bin/httpd -k restart

**What happened?**

The directory changes have been noticed and a new virtual host has been created. This time however
your new vhost-gen template has been read and the changes have applied.


Checklist
---------

1. Template files are copied from ``cfg/vhost-gen/*`` to your project template dir (as
   specified in ``.env`` via ``HTTPD_TEMPLATE_DIR``)
2. Ensure the vhost-gen yaml files are valid (No tab characters)
3. When templates are edited, the Devilbox is either restarted or the project directory is renamed
   to something else and then renamed back to its original name
