# Staging and Production on same VPS

**URL:** https://discourse.roots.io/t/staging-and-production-on-same-vps/2440
**Category:** bedrock
**Created:** 2014-10-27T12:51:19Z
**Posts:** 36
**Showing post:** 23 of 36

## Post 23 by @fullyint — 2015-07-15T20:17:49Z

**The quick fix approach**  
@tobyl It sounds like you’re running the `server.yml` playbook separately, once for `group_vars/staging`, then again for `group_vars/production`. You could possibly make that work if you change the “[site key](https://github.com/roots/trellis/blob/d12b4b261f88913d0c8b57756c1c9aa2232a0c63/group_vars/staging#L4)” in your `group_vars/staging` to something different, like `staging.example.com`. That way, when [trellis creates nginx conf files using that site key name](https://github.com/roots/trellis/blob/d12b4b261f88913d0c8b57756c1c9aa2232a0c63/roles/wordpress-setup/tasks/nginx.yml#L18), you’ll in fact have two separate conf files.

You could do that, but then you’d have to always run `server.yml` twice (once per environment). Some minor adjustments to Trellis would enable a single run of `server.yml` to handle both staging and production.

**A better approach**  
Trellis uses Ansible’s ability to run playbooks on a group of hosts or servers. Trellis groups servers by environment. However, it sounds like you’d like to group your environments within a server. Here’s one way you could adjust Trellis, grouping your staging and production sites under the domain name of the production site: “[example.com](http://example.com)”.

- **Inventory.**
  - Save a copy of `hosts/production` as `hosts/my-inventory-name`, e.g., `hosts/example.com`. Ansible always uses an inventory file. Trellis happens to have different inventory files for different hosts, so it groups the inventory files in a `hosts` directory.
  - Edit your new `hosts/example.com` inventory file. Add your server IP under `[web]` and change `[production:children]` to `[example.com:children]`.

- **Group variables.**
  - Save a copy of `group_vars/production` as `group_vars/my-group-name`, e.g., `group_vars/example.com`
  - Copy the content of `wordpress_sites` from `group_vars/staging` and append it onto the `wordpress_sites` in `group_vars/example.com`. (see example below)
  - Rename the site keys within `wordpress_sites`, e.g., to `production` and `staging` (see example below). You could name them `example.com` and `staging.example.com`, but you’ll see later why that might make for funny-looking commands.

Your `wordpress_sites` in `group_vars/example.com` should now look about like this:

```
wordpress_sites:
  production:
    site_hosts:
      - example.com
    ⋮
    env:
      wp_home: http://example.com
      wp_siteurl: http://example.com/wp
      wp_env: production
      ⋮
  staging:
    site_hosts:
      - staging.example.com
    ⋮
    env:
      wp_home: http://staging.example.com
      wp_siteurl: http://staging.example.com/wp
      wp_env: staging
      ⋮
```

You’ll notice that this is just an implementation of what @swalkinshaw suggested [above](https://discourse.roots.io/t/staging-and-production-on-same-vps/2440/5).

**Provisioning**  
You only need to run `server.yml` once:

```
# ansible-playbook -i hosts/my-inventory-name server.yml
ansible-playbook -i hosts/example.com server.yml
```

**Deployment**  
Deploy the production and staging sites separately:

```
# Production
# ./deploy.sh my-inventory-name my-site-key
./deploy.sh example.com production

# Staging
# ./deploy.sh my-inventory-name my-site-key
./deploy.sh example.com staging
```

To see if it worked, you can of course navigate to [example.com](http://example.com) and [staging.example.com](http://staging.example.com). Also run…

```
ssh web@example.com "ls /srv/www"
# production staging
ssh web@example.com "ls /etc/nginx/sites-enabled"
# no-default.conf production.conf staging.conf
```

**Site key names**  
If you had named your site keys (in `wordpress_sites`) to `example.com` and `staging.example.com` (instead of `production` and `staging`), then the deploy commands would still work, but would look a little funny:

```
# Production
# ./deploy.sh my-inventory-name my-site-key
./deploy.sh example.com example.com

# Staging
# ./deploy.sh my-inventory-name my-site-key
./deploy.sh example.com staging.example.com
```

**Development.** Note that this grouping of environments includes only staging and production. To include `development`, with its differences such as `display_errors = On` in `php.ini`, you’d have to do a little more customization.

**Consider using separate servers for staging and production.** Quoting from above:

> [@fullyint](#):
>
> But for an extra $5/mo at DO, I enjoy having a separate server for staging so I can blow it up, reprovision, and go nuts with it all the time, while leaving my production server untouched. It’s totally worth it to me. I’d recommend separate servers if you’re doing that kind of work with staging.
> 
> Of course, there are plenty of use cases in which you wouldn’t need staging on a separate server. In such cases, on the occasion you need to be able to test server setup without disturbing your production site, you could just spin up a temporary disposable testing staging server on the side.

---

_[View the full topic](https://discourse.roots.io/t/staging-and-production-on-same-vps/2440)._
