How we run redirection.io on SymfonyCloud

Lately, we have been playing with SymfonyCloud for the needs of one of our client’s projects. As the General Availability of the service has been announced earlier this week, we believe it is the right time to explain how we managed to get redirection.io's agent running on SymfonyCloud.

Wait, what is redirection.io?

redirection.io is a production tool to setup SEO optimizations in websites. It logs all the traffic and suggests to create redirection rules, meta tags override, etc., in order to avoid SEO mistakes and HTTP errors. When you rebuild a large website, URLs can change, and redirection.io helps mitigate the usual “post migration traffic and ranking drop”.

From a technical point of view, redirection.io is mainly an agent to run on your infrastructure, to apply redirections and SEO override rules. There are several connectors between your Web traffic and the agent – we maintain nginx and Apache native modules, a PHP client, a Symfony bundle, etc. The solution is build to be a “best-in-class” in terms of performance, flexibility and resiliency.

And SymfonyCloud?

SymfonyCloud is a PaaS – it provides a managed hosting environment, which automates infrastructure management, website deployments, and reduces the hosting maintenance tasks.

By default, SymfonyCloud provides many services (Emails, PostgreSQL, MariaDB, Redis, Elasticsearch, Varnish, etc.) that one can simply configure in seconds using a simple YAML syntax. For instance, should you want to enable Elasticsearch in your platform, you just have to configure the service and to link it in your application configuration:

# in .symfony/services.yaml
my_project_elasticsearch:
    type: elasticsearch:6.5
    disk: 512
    configuration:
        plugins:
            - analysis-icu

Make the service “visible” from the application:

# in .symfony.cloud.yaml
relationships:
    elasticsearch: "my_project_elasticsearch:elasticsearch"

Sure, you are bound to the versions, configuration directives, plugins, extensions, etc., that SymfonyCloud chooses to propose. This can be seen as a bit restrictive if you expected to use the latest unstable plugin for Elasticsearch, but such an approach really streamlines the way you manage application infrastructures. You will never have to worry about upgrades or even scalability… “Code your infrastructure” has never been so true!

Unfortunately, SymfonyCloud does not (yet?) propose a ready-to-use “redirection.io” service, so we will have to setup redirectionio’s agent by ourself.

Use redirection.io in a SymfonyCloud-managed project

Setup redirection.io’s agent in the SymfonyCloud infrastructure

Luckily, redirectionio-agent is simply a binary with no extra dependency. You won’t need a database, a specific library or something else – just run the binary and you’re done.

Running redirectionio-agent on SymfonyCloud as part of your project’s infrastructure is just like running one more application, as explained in the “Multiple applications” cookbook. Simply create a redirectionio directory, with some files in it, which is enough to start an agent “application”:

redirectionio
├─ .symfony.cloud.yaml
├─ redirectionio-agent
└─ redirectionio-agent.yaml

redirectionio-agent is redirection.io’s agent binary, which can be obtained from the “manual install” archive:

$ wget https://packages.redirection.io/dist/redirectionio-agent-latest_any_amd64.tar.gz
$ tar xzvf redirectionio-agent-latest_any_amd64.tar.gz

The binary can be found in ./redirection-agent/redirectionio-agent.

redirectionio-agent.yaml is the agent’s configuration, as defined in redirection.io’s configuration reference:

# Name of this instance, mandatory for logging
instance_name: "My project on SymfonyCloud"

# Interface listening. "" for all interfaces (not advised)
# /run/redirectionio.sock or 127.0.0.1:10301
listen: 0.0.0.0:10301
    
# Directory where the rules will be persisted
datadir: /tmp/var/lib/redirectionio

.symfony.cloud.yaml contains the “agent” application configuration:

name: redirectionio-agent

type: php:7.3 # there's no "empty" type, so simply pick one of the available types

build:
    flavor: none

web:
    commands:
        start: |
            set -x -e
            exec ./redirectionio-agent -config-file /app/redirectionio-agent.yaml
disk: 128

Commit, deploy, and you should have a working redirection-agent service.

Link the Symfony app to the agent

Now the agent is setup, let’s make our Symfony app talk with it.

First, we have to declare a relationship between both applications. In your Symfony app .symfony.cloud.yaml file, add a relationships section:

relationships:
    redirectionio_agent: "redirectionio-agent:http"

This tells the Symfony app that the application named redirectionio-agent is related to the Symfony application using the alias redirectionio_agent.

The redirection.io team has published a Symfony bundle to hook in the Request and Response, call the agent and process redirections. This bundle can of course be installed using Composer:

$ composer require redirectionio/proxy-symfony

Once installed, simply edit the config/packages/redirectionio.yaml file:

# see https://github.com/redirectionio/proxy-symfony
redirection_io:
    project_key: "WRITE YOUR PROJECT KEY HERE"
    connections:
        my_agent: "tcp://%env(REDIRECTIONIO_AGENT_HOST)%:10301"

You can get a redirection.io project key by creating a project on redirection.io. The REDIRECTIONIO_AGENT_HOST environment variable above is automatically available as it is derived from the name of the “redirectionio_agent” relationship.

We are all set! Simply commit the changes and deploy the application using the symfony cli tool:

$ symfony deploy


(a bunch of things happen)


Redeploying environment master
  Environment configuration
    symfony-demo (type: php:7.3, size: S, disk: 2048)
    redirectionio-agent (type: php:7.3, size: S, disk: 128)

  Environment routes
    http://master-1234567-abcdefghijklm.eu.s5y.io/ redirects to https://master-1234567-abcdefghijklm.eu.s5y.io/
    https://master-1234567-abcdefghijklm.eu.s5y.io/ is served by application `symfony-demo`

Now, we can create a rule in redirection.io’s manager:

Screencapture of redirection.io's rules list

Hooray, the redirection works when loading the /redirection.io-test URL, and our agent is detected as a running instance:

Screencapture of redirection.io's instances screen

Manage multiple environments

On the “instances” screen above, one can regret that all our environments will use the same instance name. Hence, we won’t be able to differentiate our testing environments and the production.

This can however be mitigated by changing the instance_name value in the redirectionio-agent configuration, using the SymfonyCloud SYMFONY_ENVIRONMENT environment variable.

Change the content of the file redirectionio-agent.yaml:

# Name of this instance, mandatory for logging
instance_name: "${SYMFONY_ENVIRONMENT}_cloud"

# Interface listening. "" for all interfaces (not advised)
# /run/redirectionio.sock or 127.0.0.1:10301
# Default value: 127.0.0.1:10301
listen: 0.0.0.0:10301

Also change the .symfony.cloud.yaml of the “agent” application:

name: redirectionio-agent

type: php:7.3 # there's no "empty" type, so simply pick one of the available types

build:
    flavor: none

web:
    commands:
        start: |
            set -x -e
            sed -e "s/\${SYMFONY_ENVIRONMENT}/${SYMFONY_ENVIRONMENT}/g" ./redirectionio-agent.yaml > /tmp/redirectionio-agent-runtime.yaml
            mkdir -p /tmp/var/lib
            exec ./redirectionio-agent -config-file /tmp/redirectionio-agent-runtime.yaml
disk: 128

As the filesystem is read-only, the configuration file is written at the application startup in /tmp. Of course, we could also use a mount to have persistent storage – this would even be a better idea for redirectionio-agent’s datadir, which holds a cache of your redirection rules for faster startups.

Protect the secrets

We can be a bit disappointed, at this stage, to store the redirection.io project key directly in config/packages/redirectionio.yaml (which will end up in the git repository). Instead of this, change the content of this file to use a REDIRECTIONIO_KEY environment variable:

# see https://github.com/redirectionio/proxy-symfony
redirection_io:
    project_key: "%env(REDIRECTIONIO_KEY)%"
    connections:
        my_agent: "tcp://%env(REDIRECTIONIO_AGENT_HOST)%:10301"

And define this environment variable using the symfony binary:

$ symfony var:set REDIRECTIONIO_KEY="set your key here" --hide-at-runtime

Commit, redeploy, and you’re done! ✨

As a conclusion…

We are thrilled to use SymfonyCloud for deploying Web platforms! It gives us a structured and fast way to get an hosting environment “which works and is maintained”. We strongly believe that it is a perfect fit for many reasonable business projects, when there’s no need for an in-house devops and sysadmins team.

Of course, there are still some features that could be improved, and we feel that the paint is still fresh on some aspects, but we have been really surprised by the ease of deployment that SymfonyCloud offers. This comes at the price of some missing flexibility (no, you won’t have a root account, you can just use supported services versions, etc.) but, if those bounds are convenient for your project, the price for a 24/24 managed infrastructure is unbeatable.

We are absolutely delighted to see how simple the installation of redirection.io on SymfonyCloud is: in five minutes, we have setup an integration that runs like clockwork! With no additional impact on performance, we now have a convenient way to monitor our site traffic, fix SEO errors in seconds and focus on the quality of the user experience.

blog comments powered by Disqus