RedirectionioAgentService¶
redirection.io agent (v3) running as a reverse proxy in front of your applications, so it works with any of them — FrankenPHP, PHP-FPM, Go, Rust, … — with no module to install in the application image.
Traffic flows router -> agent -> application: the domain is declared on the
agent instead of on the application, which therefore does not call
withDomain(). One agent handles as many domains as needed, each with its own
project key.
Configuration¶
$app = (new SymfonyService('app'))->withDirectory(__DIR__ . '/app');
$api = (new RustService('api'))->withVersion('1.90')->withDirectory(__DIR__ . '/api');
$event->addService($app);
$event->addService($api);
$event->addService(
(new RedirectionioAgentService())
->withProjectKey('default-project-key') // Used by the domains registered without an explicit key
->withInstanceName('dev')
// ->addReverseProxy(string $domain, ServiceInterface|string $target, ?string $projectKey = null, int $port = 80)
->addReverseProxy('app.project.test', $app)
->addReverseProxy('legacy.project.test', $app, 'another-project-key')
->addReverseProxy('api.project.test', $api, port: 8080)
);
$target accepts a service instance or a plain service name. The port is the
one the target listens on inside the Docker network.
The Host header your application receives¶
The agent decides what Host to forward from the address it forwards to: an
IP address keeps the one of the original request, a host name replaces it with
itself. Every target here is a compose service reached by name, so left alone
the agent would hand your application Host: app — which Symfony rejects as an
untrusted host, and which makes every absolute URL it generates wrong.
preserve_host is therefore written on every forward, and your application sees
the domain the visitor asked for. Turn it off if you want the agent's own
behaviour back:
->withPreserveHost(false) // for every domain
->addReverseProxy('legacy.project.test', $app, preserveHost: false) // for one
Debugging¶
(new RedirectionioAgentService())->withDebug()
Raises the agent log level, and lets it accept a certificate it cannot verify
when calling its API — which is exactly what a self-hosted
withApiHost() served by the local
router hands it. The agent image ships the public CA bundle only, and runs on
scratch, so there is nowhere to add the local one.
Development only, as the name says.
Test mode and traffic logs¶
(new RedirectionioAgentService())
->withTestMode() // instance.test_mode
->withLogging(false) // instance.logging
Both write the matching key of the instance section of the generated
agent.yml, and neither is written unless you call it — the agent keeps its own
default otherwise.
Applying a configuration change¶
The generated agent.yml is shipped as a compose config, and the agent reads it
once, on boot. Compose does not recreate a container when only the content of a
config changed, so the plugin stamps a digest of it in a
castor.config.redirectionio-agent label: the container definition changes with
the configuration, and castor docker:up is enough — no --force-recreate.
Pointing the agent at a self-hosted API¶
The agent talks to the redirection.io SaaS by default. A self-hosted instance — or the very project this agent runs in — is declared with:
(new RedirectionioAgentService())
->withApiHost('https://api.myproject.test/app_dev.php')
->withApiTimeout(120) // seconds, only written along with a host
which writes the api section of the generated agent.yml. Both are absent by
default, and the agent then uses its own defaults.
A URL like https://api.myproject.test resolves from inside the agent
container: the plugin makes the project's own domains reachable, see router and
HTTPS.
Generated configuration¶
The agent configuration is generated from those calls and shipped to the
container as an inline compose config, visible in compose.generated.yaml under
configs: — there is no agent.yml to maintain by hand:
configs:
redirectionio-agent:
content: |
instance:
name: dev
persist: false
reverse_proxy:
listen:
- 'tcp://0.0.0.0:80'
trusted_proxies:
forwarded: true
x_forwarded_for: true
x_forwarded_host: true
x_forwarded_proto: true
virtual_hosts:
-
domains:
- app.project.test
forward:
address: 'app:80'
tls: false
agent:
project_key: default-project-key
The router terminates TLS and sets the X-Forwarded-* headers, which the agent
is configured to trust, so your application still sees the original host and
scheme.
Containers¶
redirectionio-agent— the agent, routed by the router for every registered domain and forwarding to the target services