Declaratively serving a PHP package (derivation result) using Nginx

Hello, I’m packaging my Laravel (PHP) project using Flakes.

My flake provides:

  • packages: a derivation that fetches dependencies (composer and npm packages) and builds the project
  • overlays: a overlay for easy adding of my package to nixpkgs instance
  • nixosModules: a NixOS Module that configures a LEMP (Linux, Nginx, MySQL, PHP) stack that serves my package (this part doesn’t work)
  • nixosConfigurations: a configuration for a NixOS Container that I use for testing the above

If you run the test container provided by my flake, you’ll see that the problem is that Nginx doesn’t have necessary permission to show my application (it returns 403 Forbidden).

To recreate the issue you can run:

# Create a container
sudo nixos-container create yotalaravel --flake .#testContainer

# Start a container
sudo nixos-container start yotalaravel

# Show container ip address
sudo nixos-container show-ip yotalaravel

# Show the 403 page served by a container with IP 10.233.1.2
curl http://10.233.1.2 # You can also use firefox to open the page

If I understood correctly, a derivation result (package) is a read-only (immutable) instance in a Nix Store?
That’s surely a problem (or at least a part of it) when serving my Laravel application since it requests storage and bootstrap/cache directories to be writable.
Also, my Laravel app saves uploaded images (to storage directory, if I remember correctly) in it’s work directory, which further doesn’t align with the concept of immutability.

My guess is that I should somehow declaratively copy my derivation result to some directory outside the Nix Store which will then be accessed by Nginx.
And I also have to set the necessary permissions.
How can I do that?

Bonus question would also be how to declaratively manage upgrade, but that’s probably an entirely different problem by itself.

I would say this isn’t only a PHP/Laravel specific issue, so I you have an example in some other language/framework that you can share, please do.
I started using Nix around 6 months ago and I’m learning a lot, especially recently when I stared to write a configuration that I plan to use for my server.
So, I’m very grateful for all answers/explanations. :smiley:

That is possible, though I prefer having the source immutable and patching it to use different directories in standard system locations:

The paths are managed by systemd and passed to the app through environment variables:

2 Likes

i’ll have to dig a bit as i can’t recall at the moment (and don’t currently have the time to check) but we have a few laravel applications in nixpkgs already so you could see what they do

i believe there are environment variables that can change the cache directory, etc… :thinking:

1 Like

here is a nixos module for some software written using laravel: nixpkgs/nixos/modules/services/web-apps/pixelfed.nix at 57443256a0191e0d9f5f6cd130e930096581be48 · NixOS/nixpkgs · GitHub

another option might be to use a different driver for caching, like memcache… but it’s been too long since i worked with laravel to recall if that would work

if you have any trouble with this feel free to keep posting questions

1 Like

@aanderse @jtojnar Thanks a lot guys! :smiley:

if you have any trouble with this feel free to keep posting questions

I’ll definitely need some time to go through all this, so I’ll keep this topic open for now. :sweat_smile:

1 Like

So, I definitely needed some time to figure everything out, but I managed to do everything I wanted. :smiley:
Basically, all path that Laravel expect to be writable are simlinked (in derivation’s postInstall hook) to system paths (for example /var/lib/yota-laravel) that are in turn configured by a systemd service.
Here are the final links to my project if somebody is interested:

I’ll mark @aanderse answer as a solution since I took most of the code from his example.

2 Likes