ruwork/aws-bundle
Ruwork AWS Bundle integrates the AWS SDK for PHP with Symfony, offering configuration and service wiring for AWS clients so apps can access S3, SES, and other AWS services through dependency injection. It simplifies client setup, credentials management, and boilerplate in Symfony projects.
Reality check first. With zero stars and zero dependents on GitHub, this is effectively an unpublished internal bundle from the Ruvents/RuWork ecosystem. Before you build anything on it, clone the repo and read src/, config/, and composer.json yourself — there is no community documentation, no StackOverflow answers, and no blog posts to fall back on. Treat the source as the only documentation.
Minimal steps:
Install via Composer. Since there are no packagist stats shown, confirm the package is actually published:
composer require ruwork/aws-bundle
If that fails, add the VCS repository manually:
{
"repositories": [{ "type": "vcs", "url": "https://github.com/ruvents/ruwork-aws-bundle" }]
}
Register the bundle in config/bundles.php:
Ruwork\AwsBundle\RuworkAwsBundle::class => ['all' => true],
Look here first, in this order:
src/DependencyInjection/Configuration.php — this tells you the actual config schema (this is the ground truth for every option you can set).src/DependencyInjection/RuworkAwsBundleExtension.php — shows what services get registered and their IDs.src/DependencyInjection/Compiler/ — any compiler passes, which usually reveal the "magic" behavior.README.md — check last commit date; if it's years stale, assume AWS SDK v2-era code and verify against the SDK version in composer.json.First use case: configure a single AWS client (S3 is the typical entry point) and inject it into a service. The bundle almost certainly exposes clients as container services keyed by name — verify the service ID pattern from the extension class before wiring anything.
Sanity test before writing real code:
// bin/console debug:container --tag=... or
php bin/console debug:container | grep -i aws
Confirm what services actually exist in the container. Don't assume.
Because this is a thin Symfony wrapper around aws/aws-sdk-php, the patterns are about configuration discipline, not novel APIs.
Multi-client, named-client pattern. Most AWS bundles let you define several clients under a config key (e.g. clients: { default: {...}, media: {...} }) and reference them by name. Structure your config so each client maps to a purpose, not a region:
ruwork_aws:
clients:
default:
region: '%env(AWS_REGION)%'
credentials:
key: '%env(AWS_KEY)%'
secret: '%env(AWS_SECRET)%'
media:
region: 'eu-west-1'
# separate credentials / role
Inject the client, not the service locator. Wire the specific client service into the consumer rather than pulling from the container at runtime. This keeps your services testable:
final class Uploader
{
public function __construct(private S3Client $s3) {}
}
Then alias in services.yaml: $s3: '@ruwork_aws.client.media' (check the real service ID).
Wrap raw SDK calls in ports. Never let Aws\Result leak into your domain layer. Define an interface (StoragePort), implement it with the injected client, and let controllers/services depend on the interface. This protects you when/if you migrate off this bundle to async-aws or the official Symfony bundle later — which, given the adoption numbers, you should plan for.
Credential strategy: prefer IAM roles over static keys. In production (EC2/ECS/Lambda), omit credentials entirely from config so the SDK's credential provider chain resolves the instance/task role. Reserve explicit keys for local dev via .env.local. This is the single biggest security win with any AWS bundle.
Testing pattern. Use Aws\MockHandler with the SDK instead of mocking the client. The bundle only hands you a client; the mock belongs below your service boundary:
$mock = new MockHandler([new Result(['ObjectURL' => 'https://...'])]);
$client = new S3Client(['region' => 'us-east-1', 'version' => 'latest', 'handler' => HandlerList::resolve($mock)]);
One client, one region, per concern. Don't try to hit us-east-1 and eu-west-1 through the same client with overrides — define two clients. Endpoint/region overrides on a shared client are a common source of silent misrouting.
Staleness is the top risk. Zero stars means no one is filing issues, so bugs are not being reported or fixed. Pin the exact version in composer.json and vet each upstream commit before bumping. Consider forking into your own VCS and taking ownership — you will almost certainly be the maintainer in practice.
SDK version mismatch. Check composer.json for the aws/aws-sdk-php constraint. If it's ^2.x, it's EOL and you should not adopt it. If ^3.x, verify the bundle isn't using deprecated Aws\Common\* namespaces from v2 — those are gone in v3 and cause confusing "class not found" errors that look like bundle bugs.
Config schema drift. There is no published docs, so the only reliable reference is Configuration.php. If you copy a snippet from the RuWork org's other repos, double-check option names against this bundle's schema — they diverge between bundles.
Service IDs are undocumented. Don't hardcode them from memory. Run php bin/console debug:container --show-private | grep -i aws after installing and alias what you find. Better: aliases in services.yaml (Aws\S3\S3Client: '@ruwork_aws.client.default') so your app code depends on the SDK class, not a bundle-specific ID.
Credential precedence surprises. If you set both static credentials and rely on roles, the static keys win silently — a classic cause of "works locally, forbidden in prod" (or the reverse). Log the resolved region/client at boot in non-prod to confirm what you actually configured.
Debugging HTTP traffic. Enable SDK logging to see what the bundle is actually doing:
default:
debug: true
stats: true
(or pass a handler with a Middleware logger). Without this, AWS errors surface as generic Aws\Exception\AwsException and you'll waste hours guessing.
Extension points are limited and undocumented. If you need to customize client construction, the realistic path is a compiler pass or a service decorator rather than a bundle hook. Look for a client_factory service to decorate; if none exists, define your own S3Client service and skip the bundle for that client — mix-and-match is fine.
Escape hatch: plan your exit. Because this bundle is a thin wrapper, the cost of leaving is low. The moment its SDK constraint blocks a security patch, replace it with the official aws/aws-sdk-php Symfony recipes or async-aws/* and keep your StoragePort implementations untouched. Keep AWS client construction behind one factory/service in your app so the swap is a one-file change.
Don't use it for heavy abstractions. If you find yourself wishing for retry policies, paginators, or SQS pollers, the bundle won't give them to you — the SDK does. Call the SDK's own features (Paginators, Waiter, RetryMiddleware) directly on the injected client rather than expecting bundle-level sugar.
How can I help you explore Laravel packages today?