Devilbox: How to add subdomains?

Created on 8 Nov 2017  路  30Comments  路  Source: cytopia/devilbox

Hi,

I'm sorry, I'm not sure how can I use devilbox along with WP multisite? To be more precise, I would like to use subdomains. So, maybe this is the main question - how to add subdomains ?
Thanks!

documentation question

Most helpful comment

Hi @mrpsiho @mavimedia

I just double checked it locally and it seems to work fine.
The steps I did are as follows:

.env file

HTTPD_TEMPLATE_DIR=.devilbox
TLD_SUFFIX=loc
HOST_PATH_HTTPD_DATADIR=./data/www

/etc/hosts:

127.0.0.1    cytopia.loc
127.0.0.1    t1.cytopia.loc
127.0.0.1    t2.cytopia.loc

Projects:

# One project only (one vhost)
$ ls -lap ./data/www
total 12
drwxr-xr-x 3 cytopia cytopia 4096 Nov 11 15:40 ./
drwxr-xr-x 6 cytopia cytopia 4096 Sep 26 16:38 ../
drwxr-xr-x 4 cytopia cytopia 4096 Nov 11 15:36 cytopia/

# Note the .devilbox folder for configuration
ls -lap ./data/www/cytopia/
total 16
drwxr-xr-x 4 cytopia cytopia 4096 Nov 11 15:36 ./
drwxr-xr-x 3 cytopia cytopia 4096 Nov 11 15:40 ../
drwxr-xr-x 2 cytopia cytopia 4096 Nov 11 15:40 .devilbox/
drwxr-xr-x 2 cytopia cytopia 4096 Nov 11 15:36 htdocs/

Now download the nginx.yml template (in case of using nginx):

cd ./data/www/cytopia/.devilbox
wget https://raw.githubusercontent.com/devilbox/vhost-gen/master/etc/templates/nginx.yml

Note, keep the whole file as it is and do not remove any sections from it.

Now I have simply added a line below server_name, to get multiple server names:

./data/www/cytopia/.devilbox/nginx.yml

This line was added server_name *.__VHOST_NAME__;

---

# Nginx vHost Template defintion for vhost-gen.py
#
# The 'feature' section contains optional features that can be enabled via
# conf.yml and will then be replaced into the main vhost ('structure' section)
# into their corresponding position:
#
#    __XDOMAIN_REQ__
#    __PHP_FPM__
#    __ALIASES__
#    __DENIES__
#    __STATUS__
#
# The features itself also contain variables to be adjusted in conf.yml
# and will then be replaced in their corresponding feature section
# before being replaced into the vhost section (if enabled):
#
# PHP-FPM:
#    __PHP_ADDR__
#    __PHP_PORT__
# XDomain:
#    __REGEX__
# Alias:
#    __REGEX__
#    __PATH__
# Deny:
#    __REGEX__
# Status:
#    __REGEX__
#
# Variables to be replaced directly in the vhost configuration can also be set
# in conf.yml and include:
#    __VHOST_NAME__
#    __DOCUMENT_ROOT__
#    __INDEX__
#    __ACCESS_LOG__
#    __ERROR_LOG__
#    __PHP_ADDR__
#    __PHP_PORT__
#


###
### Basic vHost skeleton
###
vhost: |
  server {
      listen       __PORT____DEFAULT_VHOST__;
      server_name  __VHOST_NAME__;
      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__
  }


###
### vHost Type (normal or reverse proxy)
###
vhost_type:
  # Normal vHost (-p)
  docroot: |
    # Define the vhost to serve files
    root         "__DOCUMENT_ROOT__";
    index        __INDEX__;

  # Reverse Proxy (-r)
  rproxy: |
    # Define the vhost to reverse proxy
    location __LOCATION__ {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass __PROXY_PROTO__://__PROXY_ADDR__:__PROXY_PORT__;
    }


###
### Optional features to be enabled in vHost
###
features:

  # PHP-FPM will not be applied to a reverse proxy!
  php_fpm: |
    # PHP-FPM Definition
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php?$ {
        try_files $uri = 404;
        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_split_path_info ^(.+\.php)(.*)$;

        fastcgi_pass __PHP_ADDR__:__PHP_PORT__;

        fastcgi_index index.php;
        fastcgi_intercept_errors on;
    }

  alias: |
    # Alias Definition
    location ~ __ALIAS__ {
        root  __PATH__;
    __XDOMAIN_REQ__
    }

  deny: |
    # Deny Definition
    location ~ __REGEX__ {
        deny all;
    }

  server_status: |
    # Status Page
    location ~ __REGEX__ {
        stub_status on;
        access_log off;
    }

  xdomain_request: |
    # Allow cross domain request from these hosts
    if ( $http_origin ~* (__REGEX__) ) {
        add_header "Access-Control-Allow-Origin" "$http_origin";
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Max-Age' 0;
        return 200;
    }

Now in order to apply the changes, you will either have to restart the devilbox, or simply rename the cytopia project directory to something else and then back to cytopia, then the httpd container will re-apply the changes.

Result

Now there is one vhost called http://cytopia.loc as well as unlimited vhosts for all subdomains of http:*.cytopia.loc

As I have already added new DNS entries via /etc/hosts above, I can simply go to http://t1.cytopia.loc which is the same vhost/project as http://cytopia.loc

All 30 comments

Hi @mrpsiho

As an example. When your TLD_SUFFIX is set to com.

If you create a project directory named my-wordpress/, your site is reachable by the servername: http://my-wordpress.com.

If you create a project directory named www.my-wordpress/, your site is reachable by the servername: http://www.my-wordpress.com.

If you create a project directory named api.my-wordpress/, your site is reachable by the servername: http://api.my-wordpress.com.

Does this answer your question?

No, sorry. Such tactic is pretty good, but it doesn't solve my case. So, the main question was 'How to use WP multisite with type 'subdomains' as the chosen method of adding network sites?'

Sorry, I'm not that good with DevOps stuff. I guess, this is what I need https://codex.wordpress.org/Configuring_Wildcard_Subdomains , but I don't know how/whether it is possible with devilbox. Please, suggest.

So you want to set up a wildcard Hostname for one project? E.g.: *.my-wordpress.dev

I think so.

Yes this is possible now, as every web server is base on vhost-gen.

So far I am lacking a bit of documentation, but some has already been documented here:
https://github.com/cytopia/devilbox/blob/master/docs/Configure.md#433-customize-the-vhost-configuration.

Basically saying: Each of your vhosts (project dirs) can have a completely custom web server configuration.

Please read the above documentation for how to achieve it.
Let me know the parts you don't understand and I will extend the documentation so its bullet proof.

@mrpsiho I fixed above vhost-gen link.

Ok, thanks!

So, since I use nginx, the only file I need is nginx.yml unde 'devilbox' folder next to htdocs folder of my project, right?

Then, I tried to add the second 'server' section below the original one, this is how it looks like:

server {
        listen       __PORT____DEFAULT_VHOST__;
        server_name ~^(.*)\.__VHOST_NAME__$ ;

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

        client_max_body_size 10m;

    __VHOST_DOCROOT__
    __VHOST_RPROXY__
    __PHP_FPM__
    __ALIASES__
    __DENIES__
    __SERVER_STATUS__
        # Custom directives
    __CUSTOM__
    }

But it doesn't work for me. Could you give me a hint what's wrong?

Your template is invalid. Not correct yaml. You need to use the whole template and just modify the sections.

Copy this file: https://github.com/devilbox/vhost-gen/blob/master/etc/templates/nginx.yml

No, actually I'm already using this whole document. I cited just a part that I added below the first 'server' block.

I thought maybe just editing the first block is enough, so I tried this:

server {
      listen       __PORT____DEFAULT_VHOST__;
      server_name  __VHOST_NAME__ *.__VHOST_NAME__;

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

      client_max_body_size 10m;

  __VHOST_DOCROOT__
  __VHOST_RPROXY__
  __PHP_FPM__
  __ALIASES__
  __DENIES__
  __SERVER_STATUS__
      # Custom directives
  __CUSTOM__
  }

But it also doesn't work((

I am on the go, but will reply back latest by tomorrow with something you can work on.

Thanks! I will wait.

Hi Cytopia, great work!

I'm also interested in changing vhost settings of projects. I couldn't get it running, too.

Best regards!

Hi @mrpsiho @mavimedia

I just double checked it locally and it seems to work fine.
The steps I did are as follows:

.env file

HTTPD_TEMPLATE_DIR=.devilbox
TLD_SUFFIX=loc
HOST_PATH_HTTPD_DATADIR=./data/www

/etc/hosts:

127.0.0.1    cytopia.loc
127.0.0.1    t1.cytopia.loc
127.0.0.1    t2.cytopia.loc

Projects:

# One project only (one vhost)
$ ls -lap ./data/www
total 12
drwxr-xr-x 3 cytopia cytopia 4096 Nov 11 15:40 ./
drwxr-xr-x 6 cytopia cytopia 4096 Sep 26 16:38 ../
drwxr-xr-x 4 cytopia cytopia 4096 Nov 11 15:36 cytopia/

# Note the .devilbox folder for configuration
ls -lap ./data/www/cytopia/
total 16
drwxr-xr-x 4 cytopia cytopia 4096 Nov 11 15:36 ./
drwxr-xr-x 3 cytopia cytopia 4096 Nov 11 15:40 ../
drwxr-xr-x 2 cytopia cytopia 4096 Nov 11 15:40 .devilbox/
drwxr-xr-x 2 cytopia cytopia 4096 Nov 11 15:36 htdocs/

Now download the nginx.yml template (in case of using nginx):

cd ./data/www/cytopia/.devilbox
wget https://raw.githubusercontent.com/devilbox/vhost-gen/master/etc/templates/nginx.yml

Note, keep the whole file as it is and do not remove any sections from it.

Now I have simply added a line below server_name, to get multiple server names:

./data/www/cytopia/.devilbox/nginx.yml

This line was added server_name *.__VHOST_NAME__;

---

# Nginx vHost Template defintion for vhost-gen.py
#
# The 'feature' section contains optional features that can be enabled via
# conf.yml and will then be replaced into the main vhost ('structure' section)
# into their corresponding position:
#
#    __XDOMAIN_REQ__
#    __PHP_FPM__
#    __ALIASES__
#    __DENIES__
#    __STATUS__
#
# The features itself also contain variables to be adjusted in conf.yml
# and will then be replaced in their corresponding feature section
# before being replaced into the vhost section (if enabled):
#
# PHP-FPM:
#    __PHP_ADDR__
#    __PHP_PORT__
# XDomain:
#    __REGEX__
# Alias:
#    __REGEX__
#    __PATH__
# Deny:
#    __REGEX__
# Status:
#    __REGEX__
#
# Variables to be replaced directly in the vhost configuration can also be set
# in conf.yml and include:
#    __VHOST_NAME__
#    __DOCUMENT_ROOT__
#    __INDEX__
#    __ACCESS_LOG__
#    __ERROR_LOG__
#    __PHP_ADDR__
#    __PHP_PORT__
#


###
### Basic vHost skeleton
###
vhost: |
  server {
      listen       __PORT____DEFAULT_VHOST__;
      server_name  __VHOST_NAME__;
      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__
  }


###
### vHost Type (normal or reverse proxy)
###
vhost_type:
  # Normal vHost (-p)
  docroot: |
    # Define the vhost to serve files
    root         "__DOCUMENT_ROOT__";
    index        __INDEX__;

  # Reverse Proxy (-r)
  rproxy: |
    # Define the vhost to reverse proxy
    location __LOCATION__ {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass __PROXY_PROTO__://__PROXY_ADDR__:__PROXY_PORT__;
    }


###
### Optional features to be enabled in vHost
###
features:

  # PHP-FPM will not be applied to a reverse proxy!
  php_fpm: |
    # PHP-FPM Definition
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php?$ {
        try_files $uri = 404;
        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_split_path_info ^(.+\.php)(.*)$;

        fastcgi_pass __PHP_ADDR__:__PHP_PORT__;

        fastcgi_index index.php;
        fastcgi_intercept_errors on;
    }

  alias: |
    # Alias Definition
    location ~ __ALIAS__ {
        root  __PATH__;
    __XDOMAIN_REQ__
    }

  deny: |
    # Deny Definition
    location ~ __REGEX__ {
        deny all;
    }

  server_status: |
    # Status Page
    location ~ __REGEX__ {
        stub_status on;
        access_log off;
    }

  xdomain_request: |
    # Allow cross domain request from these hosts
    if ( $http_origin ~* (__REGEX__) ) {
        add_header "Access-Control-Allow-Origin" "$http_origin";
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Max-Age' 0;
        return 200;
    }

Now in order to apply the changes, you will either have to restart the devilbox, or simply rename the cytopia project directory to something else and then back to cytopia, then the httpd container will re-apply the changes.

Result

Now there is one vhost called http://cytopia.loc as well as unlimited vhosts for all subdomains of http:*.cytopia.loc

As I have already added new DNS entries via /etc/hosts above, I can simply go to http://t1.cytopia.loc which is the same vhost/project as http://cytopia.loc

Please let me know if it works out for you or at what steps you still have struggle.

Ok, I did the same and whenever I try to reach my subdomain, it shows me the content of localhost (devilbox info page). I'm using Devilbox v0.12 (2017-10-10). Is it the correct version?

@mrpsiho can you check how the vhost actually looks inside the httpd container:

$ docker-compose exec httpd bash
httpd> /etc/httpd/vhost.d
httpd> cat <vhost-name>.conf

And paste the output here along with your nginx.yml

this is what it actually looks like:

server {
    listen       80;
    server_name  moomoo.loc;

    access_log   "/var/log/nginx-stable/moomoo-access.log" combined;
    error_log    "/var/log/nginx-stable/moomoo-error.log" warn;

    # Define the vhost to serve files
    root         "/shared/httpd/moomoo/htdocs";
    index        index.php;


    # PHP-FPM Definition
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php?$ {
        try_files $uri = 404;
        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_split_path_info ^(.+\.php)(.*)$;

        fastcgi_pass php:9000;

        fastcgi_index index.php;
        fastcgi_intercept_errors on;
    }

    # Alias Definition
    location ~ /devilbox-api/ {
        root  /var/www/default/api;
        # Allow cross domain request from these hosts
        if ( $http_origin ~* (http(s)?://(.*)$) ) {
            add_header "Access-Control-Allow-Origin" "$http_origin";
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
            add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
            add_header 'Access-Control-Max-Age' 0;
            return 200;
        }
    }

    # Deny Definition
    location ~ /\.git {
        deny all;
    }

    # Deny Definition
    location ~ /\.ht.* {
        deny all;
    }


    # Custom directives

}

and this is the content of nginx.yml

---

# Nginx vHost Template defintion for vhost-gen.py
#
# The 'feature' section contains optional features that can be enabled via
# conf.yml and will then be replaced into the main vhost ('structure' section)
# into their corresponding position:
#
#    __XDOMAIN_REQ__
#    __PHP_FPM__
#    __ALIASES__
#    __DENIES__
#    __STATUS__
#
# The features itself also contain variables to be adjusted in conf.yml
# and will then be replaced in their corresponding feature section
# before being replaced into the vhost section (if enabled):
#
# PHP-FPM:
#    __PHP_ADDR__
#    __PHP_PORT__
# XDomain:
#    __REGEX__
# Alias:
#    __REGEX__
#    __PATH__
# Deny:
#    __REGEX__
# Status:
#    __REGEX__
#
# Variables to be replaced directly in the vhost configuration can also be set
# in conf.yml and include:
#    __VHOST_NAME__
#    __DOCUMENT_ROOT__
#    __INDEX__
#    __ACCESS_LOG__
#    __ERROR_LOG__
#    __PHP_ADDR__
#    __PHP_PORT__
#


###
### Basic vHost skeleton
###
vhost: |
  server {
      listen       __PORT____DEFAULT_VHOST__;
      server_name  __VHOST_NAME__;
      server_name  *.__VHOST_NAME__;
      server_name  builderius.loc;
      server_name  *.builderius.loc;

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

  __VHOST_DOCROOT__
  __VHOST_RPROXY__
  __PHP_FPM__
  __ALIASES__
  __DENIES__
  __SERVER_STATUS__
      # Custom directives
  __CUSTOM__
  }


###
### vHost Type (normal or reverse proxy)
###
vhost_type:
  # Normal vHost (-p)
  docroot: |
    # Define the vhost to serve files
    root         "__DOCUMENT_ROOT__";
    index        __INDEX__;

  # Reverse Proxy (-r)
  rproxy: |
    # Define the vhost to reverse proxy
    location __LOCATION__ {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass __PROXY_PROTO__://__PROXY_ADDR__:__PROXY_PORT__;
    }


###
### Optional features to be enabled in vHost
###
features:

  # PHP-FPM will not be applied to a reverse proxy!
  php_fpm: |
    # PHP-FPM Definition
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php?$ {
        try_files $uri = 404;
        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_split_path_info ^(.+\.php)(.*)$;

        fastcgi_pass __PHP_ADDR__:__PHP_PORT__;

        fastcgi_index index.php;
        fastcgi_intercept_errors on;
    }

  alias: |
    # Alias Definition
    location ~ __ALIAS__ {
        root  __PATH__;
    __XDOMAIN_REQ__
    }

  deny: |
    # Deny Definition
    location ~ __REGEX__ {
        deny all;
    }

  server_status: |
    # Status Page
    location ~ __REGEX__ {
        stub_status on;
        access_log off;
    }

  xdomain_request: |
    # Allow cross domain request from these hosts
    if ( $http_origin ~* (__REGEX__) ) {
        add_header "Access-Control-Allow-Origin" "$http_origin";
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Max-Age' 0;
        return 200;
    }

P.S. Yep, I also try to use a different domain for my multisite installation

Omg! I must use '.devilbox' folder name? Not just 'devilbox'? Maybe this is the reason...

Yes ;-p

You can however change this by altering: HTTPD_TEMPLATE_DIR=.devilbox to HTTPD_TEMPLATE_DIR=devilbox

Haha, omg. I just wasn't attentive enough(((

Yes, it works. I confirm this!
Just in case - WP multisite edition also works! :)

Thanks a lot! Devilbox is must have for developers!))

Good to hear. I will keep this open until @mavimedia issue has also been resolved and until better documentation has been added.

It works for me too. Thanks.

I'm using Apache 2.4. I have made with ServerAlias *.__VHOST_NAME__ directive.

Is it possible to override the global vhost templates?

@mavimedia could you add a new issue for this topic please

The whole thing is going to be documented with new documentation setup: https://github.com/cytopia/devilbox/issues/157

Is this still valid for latest version? I'm following docs but conf file remains the same

@timersys is still valid and nothing has changed. If it doesn't work for you please create a separate ticket with full steps to reproduce, so we can solve your issue quickly.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jonatanaxe picture jonatanaxe  路  5Comments

sustained picture sustained  路  6Comments

Venorcis picture Venorcis  路  6Comments

Novitsh picture Novitsh  路  6Comments

msyhr picture msyhr  路  7Comments