laravel cloud support#35
Conversation
|
Laravel Cloud is supported and I solved it by running the custom command <?php
declare(strict_types=1);
namespace App\Console\Commands;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
final class SwishDeploy extends Command
{
protected $signature = 'swish:deploy';
protected $description = 'Deploy the Swish certificates from the bucket to the instance disk';
public function handle()
{
$this->info('Starting deployment of Swish certificates...');
try {
// Get all files from the swish directory in the bucket
$files = Storage::allFiles('swish');
if (count($files) === 0) {
$this->info('No files found in the swish directory.');
return 0;
}
$this->info('Found ' . count($files) . ' files to copy.');
// Copy each file from bucket to local storage private directory
foreach ($files as $file) {
$contents = Storage::get($file);
Storage::disk('local')->put($file, $contents);
$this->line("Copied: {$file}");
}
$this->info('Swish certificates deployment completed successfully.');
return 0;
} catch (Exception $exception) {
$this->error('Deployment failed: ' . $exception->getMessage());
return 1;
}
}
} |
|
@vinkla Thanks for your input and info! @tanthammar I think an external copy/deployment is the way to go. Feels odd that this package should handle the file syncing and/or copying of the certificates. While a great and nifty idea that solves a real issue – it's still outside of this package's scope. It would also introduce issues with "cold starts" for the initial copy and such, and any such errors is not something that should be managed or debugged within this package. I would happily take a separate PR that adds info to the readme.md regarding Laravel Cloud-specific deployments and how one would go about and deploy it. I myself have yet to try it, most of my apps that utilize Swish still runs on Forge 😅 And idea for a future version would be to implement |
|
@olssonm — Thank you for the feedback, I agree that the suggested solution to copy certs is awkward. I have an external deploy-command route like you and @vinkla suggested, and it works. One extra wrinkle worth flagging for the docs/blob discussion though. The "missing cert" errors come from the service provider resolving the path via The other gotcha is Laravel Cloud replicas: a deploy command runs once in a single container, but replicas web instances boot from the built Docker image and never run the deploy commands — each has its own ephemeral disk. So the cert has to be copied onto the instance at runtime (a small JIT copy on first use), not just at deploy time.
I tried setting the cert as base64 env var but Laravel Cloud quietly removed it when trying to save env settings. Probably some length issue. I reported it but have yet to get a support answer. For reference, here's what I currently have. Deploy command (copies the cert from the private S3 bucket onto the local disk): <?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
/**
* Laravel cloud is serverless, this is used as deploy command.
*
* Copies the Swish client certificate from the private S3 bucket onto the
* defined local path — cURL needs a real local filesystem path for client mTLS.
*
* Local host must have test cert on path
*/
class InstallSwishCertificate extends Command
{
protected $signature = 'swish:install-certificate';
protected $description = 'Fetch the Swish client certificate from the private S3 bucket onto the local disk';
public function handle(): int
{
/* the package's own config key — keeps command + package in sync */
$path = config('swish.certificates.client');
if (blank($path)) {
$this->warn('SWISH_CLIENT_CERTIFICATE_PATH not set — skipping.');
return self::SUCCESS;
}
/* the real filesystem path cURL will use for mTLS — log it so deploys are verifiable */
$absolutePath = Storage::disk('local')->path($path);
if (Storage::disk('local')->exists($path)) {
$this->info("Swish client certificate already at {$absolutePath}");
return self::SUCCESS;
}
Storage::disk('local')->put($path, Storage::disk('private')->get($path));
if (Storage::disk('local')->exists($path)) {
$this->info("Verified that certificate is at {$absolutePath}");
} else {
$this->error("Failed to write Swish client certificate to {$absolutePath}");
return self::FAILURE;
}
$this->info("Swish client certificate fetched from private bucket → {$absolutePath}");
return self::SUCCESS;
}
}AppServiceProvider — the JIT copy + resolving against the private function registerSwishClient(): void
{
$this->app->singleton('swish', function (): SwishClient {
$key = config('swish.certificates.client');
if (filled($key)
&& ! Storage::disk('local')->exists($key)
&& Storage::disk('private')->exists($key)
) {
Storage::disk('local')->put($key, Storage::disk('private')->get($key));
}
$certificate = new Certificate(
clientPath: filled($key) ? Storage::disk('local')->path($key) : null,
passphrase: config('swish.certificates.password'),
rootPath: config('swish.certificates.root'),
signingPath: config('swish.certificates.signing'),
signingPassphrase: config('swish.certificates.signing_password'),
);
return new SwishClient($certificate, config('swish.endpoint'));
});
} |
|
@tanthammar Of course! Sound like a good idea; just a simple $disk = $config->get('swish.certificates.disk') ?: $config->get('filesystems.default', 'local');Thank you so much for your info regarding Laravel Cloud too, did not know about those caveats 👍 Will definitely need to look into that as more and more people will probably run into the same issue (I do get quite a lot of support mail regarding Swish-certficates and such). |
|
@tanthammar You should be able to run the Swish certification file copying as a build command, which means you won't need to load it at runtime. As you mentioned, it needs to be loaded with an absolute path. To run it as a build command, you need a specific Laravel Cloud environment variable enabled, which you add in front of your build command. Please ask support about this, as I'm not sure if I'm allowed to share it on GitHub. |
|
@vinkla Interesting, will ask support and report back here. Won't submit any PR until then:) |
Suggesting solution to support storing certs on external buckets.
fix #34