How to develop locally on Platform.sh with a tethered connection

Goal

Run a project on a local web server that connects to an application’s services with an SSH tunnel.

Assumptions

This guide uses the Platform.sh CLI to connect to a project’s services, and assumes that it and Git are already installed. The guide also assumes that an SSH key is configured on the project account.

Problems

The local machine must be configured with the appropriate PHP extensions. From a local project, an SSH tunnel is required to connect to Platform.sh services and expose those relationships in a local environment variable.

Steps

1. Check pcntl and posix

Tunneling to the project’s services using the CLI requires the PHP extensions pcntl and posix. Check to make sure they are present, and install if the following output is not received:

$ php -m | grep -E 'posix|pcntl'
pcntl
posix

2. Download local project copy

List the projects on the account to find the project-ID:

$ platform projects
Your projects are: 
+--------------+------------------------------------------+-------------------------------------------------+
| ID           | Title                                    | URL                                             |
+--------------+------------------------------------------+-------------------------------------------------+
| <project-ID> | Platform Project                         | https://eu.platform.sh//#/projects/<project-ID> |
+--------------+------------------------------------------+-------------------------------------------------+

Download the project.

$ platform get <project-ID>
Directory [repo]: repo
Environment [master]: dev
Downloading project Platform Project (<project-ID>)
  Cloning into 'my-project/repo'...
  remote: counting objects: 461, done.        
  Receiving objects: 100% (461/461), 1.41 MiB | 249.00 KiB/s, done.
  Resolving deltas: 100% (225/225), done.
    
The project Platform Project (<project-ID>) was successfully downloaded to: repo

3. Open an SSH tunnel to the project.

$ platform tunnel:open
SSH tunnel opened on port 30000 to relationship: elasticsearch
SSH tunnel opened on port 30001 to relationship: rabbitmq
SSH tunnel opened on port 30002 to relationship: postgresql

Check to make sure that the tunnels are visible.

$ platform tunnel:list
+-------+--------------+-------------+-----+---------------+
| Port  | Project      | Environment | App | Relationship  |
+-------+--------------+-------------+-----+---------------+
| 30000 | <project-ID> | dev         | app | elasticsearch |
| 30001 | <project-ID> | dev         | app | rabbitmq      |
| 30002 | <project-ID> | dev         | app | postgresql    |
+-------+--------------+-------------+-----+---------------+

If the tunnels are not visible here, check /Users/<user>/.platformsh/tunnels.log to see if the SSH key was configured incorrectly.

4. Export PLATFORM_RELATIONSHIPS

Create a JSON encoded PLATFORM_RELATIONSHIPS environment variable to mimic the relationships array that will be visible to the application.

export PLATFORM_RELATIONSHIPS="$(platform tunnel:info --encode)"

5. Build

Build the application. If a service is required locally but missing, the CLI will prompt for its installation.

$ cd repo
$ platform build

6. Run the application

Now the project has been built and can be run locally. For a Django application:

$ python manage.py runserver    

7. Close the tunnel.

$ platform tunnel:close    
Close tunnel to relationship elasticsearch on <project-ID>-dev--app? [Y/n] y    
Closed tunnel to elasticsearch on <project-ID>-dev--app    
Close tunnel to relationship rabbitmq on <project-ID>-dev--app? [Y/n] y    
Closed tunnel to rabbitmq on <project-ID>-dev--app    
Close tunnel to relationship postgresql on <project-ID>-dev--app? [Y/n] y    
Closed tunnel to postgresql on <project-ID>-dev--app     

Conclusion

Once PHP extensions are properly configured and SSH tunnels are opened to a Platform.sh project’s services, an application can be built for local development.

The CLI is used here to connect to PostgreSQL, ElasticSearch and RabbitMQ, but the commands are not specific to those services or to the language used in the application.

Additional information regarding local development best practices can be found in the Platform.sh documentation.