niels / Software / #laravel

Embedding Laravel Passport keys in .env

When deploying a Laravel project to a server, in an ideal scenario, there are two primary steps you should follow:

  • Clone your git repository
  • Configure the .env file

However, the introduction of Laravel Passport seemed to disrupt this streamlined process. Every time I deployed to a new server, I found myself needing to manually copy the oauth-private.key and oauth-public.key files.

In search of a solution to embed these keys within the .env file, I first stumbled upon this method on Laracasts. Although functional, it appeared somewhat untidy due to the double-escaped newline characters.

My pursuit for a cleaner solution led me to another approach on StackOverflow.


To avoid the hassle of manually reformatting these keys, I’ve crafted a convenient convert.php script for the task:

<?php

$privateKeyContent = str_replace(["-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----", "\r", "\n"], ["", "", "", ""], trim(file_get_contents('storage/oauth-private.key')));
$publicKeyContent = str_replace(["-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----", "\r", "\n"], ["", "", "", ""], trim(file_get_contents('storage/oauth-public.key')));

echo "PASSPORT_PRIVATE_KEY=\"-----BEGIN PRIVATE KEY-----\n{$privateKeyContent}\n-----END PRIVATE KEY-----\"\n";
echo "PASSPORT_PUBLIC_KEY=\"-----BEGIN PUBLIC KEY-----\n{$publicKeyContent}\n-----END PUBLIC KEY-----\"";
0 comments

niels / Software / #laravel

Redis Sentinel with Laravel

As the use of Redis Sentinel with Laravel does not appear to be documented at the time of writing, I’m sharing the configuration I’m using.

This is the redis section of my config/database.php:

    'redis' => [

        'client' => env('REDIS_CLIENT', 'predis'),

        'options' => [

            // Don't set 'cluster' option. The only valid values are 'predis' and 'redis',
            // both conflict with sentinel replication.
            // 'cluster' => env('REDIS_CLUSTER', 'predis'),

            'prefix' => Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_',
        ],

        'default' => env('REDIS_SENTINELS', false) ? array_merge(
            array_map(function ($host) {
                return "tcp://{$host}:26379?timeout=0.1";
            }, explode(',', env('REDIS_SENTINELS', ''))),
            [
                'options' => [
                    'replication' => 'sentinel',
                    'service' => 'mymaster',
                    'parameters' => [
                        'database' => 0,
                        'password' => env('REDIS_PASSWORD', null),
                    ],
                ],
            ]
        ) : [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => 0,
        ],

        'cache' => env('REDIS_SENTINELS', false) ? array_merge(
            array_map(function ($host) {
                return "tcp://{$host}:26379?timeout=0.1";
            }, explode(',', env('REDIS_SENTINELS', ''))),
            [
                'options' => [
                    'replication' => 'sentinel',
                    'service' => 'mymaster',
                    'parameters' => [
                        'database' => 1,
                        'password' => env('REDIS_PASSWORD', null),
                    ],
                ],
            ]
        ) : [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => 1,
        ],

    ],

And this is what I have in my .env:

REDIS_SENTINELS=10.62.0.5,10.62.0.9,10.62.0.11,10.62.0.12
REDIS_HOST=10.62.0.5
REDIS_PASSWORD=null
REDIS_PORT=6379

Summary of what it does:

  • Define REDIS_SENTINELS and it will use the Sentinel configuration.
  • Omit or set to false REDIS_SENTINELS and it will use the regular stand-alone Redis.
  • Both Sentinel and non-Sentinel Laravel instances can operate in a mixed environment due to sharing the same prefixes.
0 comments

niels / Software / #filament,#laravel

Auto-reloading Filament (v3) panels using Vite

When integrating a Filament panel into your Laravel project, you might find that Vite’s auto-reloading feature isn’t functioning as expected. This issue arises because the panel isn’t loading Vite-managed resources.

While a long-term solution might involve crafting your own Filament theme that incorporates Vite, there’s a straightforward workaround available. By tweaking the AdminPanelProvider class to inject a Vite resource, you can ensure Vite’s auto-reloading works smoothly:

class AdminPanelProvider extends PanelProvider
{
    public function register(): void
    {
        parent::register();

        FilamentView::registerRenderHook(
            'panels::body.end',
            fn (): string => Blade::render("@vite('resources/js/app.js')"),
        );
    }

    public function panel(Panel $panel): Panel
    {
		  // ... stuff
	}
}

This modification results in the Filament panel loading the standard app.js. Even though it’s not essential within the panel, given that it’s a cached asset, its presence has minimal impact on performance.

0 comments

niels / Software / #linux,#ubuntu

Removing LUKS full-disk encryption

My homelab server is a NUC running Ubuntu that I previously used as a desktop. To ensure it automatically boots up after a power-failure I wanted to disable the LUKS full disk encryption that I use on all my desktops and laptops.

GRUB method

For some reason most how-to’s out there use this method:

  1. Generate a new LUKS key.
  2. Store the new LUKS key on the unencrypted boot partition.
  3. Reconfigure GRUB to use that key and decrypt the root partition automatically.

While that works, I don’t like it. You end up with the overhead of encryption without enjoying the benefits. Not to mention that a small typo in the grub.cfg can prevent GRUB from booting.

Decrypt method

Then I ran into this solution on Ask Ubuntu. It’s simple, it’s beautiful. It’s perfect:

  1. Boot (Ubuntu) from a USB stick.
  2. Decrypt the root partition. In my case: sudo cryptsetup-reencrypt --decrypt /dev/nvme0n1p3.
  3. Remove USB stick and reboot.

The first boot after decryption may show some errors and delays due to cryptsetup now failing. To fix that:

  1. Removed /etc/crypttab.
  2. Run sudo apt remove cryptsetup.
0 comments