I’ll try to keep this simple, descriptive-but-assuming-you-know-some-basics, and clear.
{ config, pkgs, lib, ... }:
let
# declare a custom php package with any php extensions and tweaks we need, like memcached for example
php' = pkgs.php.buildEnv {
extensions = { enabled, all }: with all; enabled ++ [ memcached ];
extraConfig = ''
memory_limit = 256M
'';
};
in
{
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.httpd.enable = true;
services.httpd.adminAddr = "webmaster@example.org";
services.httpd.extraModules = [ "proxy_fcgi" ];
services.httpd.virtualHosts."example.org" = {
documentRoot = "/var/www/example.org/public";
# want ssl + a let's encrypt certificate? add `forceSSL = true;` right here
extraConfig = ''
# https://laravel.com/docs/8.x/deployment#nginx
Header always append X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
<Directory /var/www/example.org/public>
AllowOverride all
DirectoryIndex index.php
<FilesMatch "\.php$">
<If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:unix:${config.services.phpfpm.pools.example.socket}|fcgi://localhost/"
</If>
</FilesMatch>
</Directory>
'';
};
services.mysql.enable = true;
services.mysql.package = pkgs.mariadb;
# configure a php-fpm pool to run our web application
services.phpfpm.pools.example = {
user = "example";
group = "example";
phpPackage = php';
settings = {
"listen.owner" = config.services.httpd.user;
"listen.group" = config.services.httpd.group;
# you should probably take some time to understand these values, see https://www.php.net/manual/en/install.fpm.configuration.php
"pm" = "dynamic";
"pm.max_children" = 8;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 4;
"pm.max_requests" = 500;
"request_terminate_timeout" = 300;
};
};
# you might need a laravel scheduler service to run
systemd.services.example-laravel-scheduler = {
description = "example laravel scheduler";
startAt = "minutely";
# ensure this service doesn't run unless the app is properly installed
unitConfig = {
ConditionPathExists = "/var/www/example.org/.env";
ConditionDirectoryNotEmpty = "/var/www/example.org/vendor";
};
serviceConfig = {
Type = "oneshot";
User = "example";
Group = "example";
SyslogIdentifier = "example-laravel-scheduler";
WorkingDirectory = "/var/www/example.org";
ExecStart = "${php'}/bin/php artisan schedule:run -v";
};
};
# create the basic directory structure we need
systemd.tmpfiles.rules = [
"d /var/www"
"d /var/www/example.org 0750 example example"
];
# because we probably want free ssl certificates
security.acme.acceptTerms = true;
security.acme.email = "webmaster@example.org";
# create a separate user to run php as for security, isolation, better reproducibility, etc...
users.users.example = {
description = "php-fpm user for our example laravel web application";
isNormalUser = true;
shell = pkgs.bash;
# packages needed to install your laravel application, etc...
packages = [
php'
php'.packages.composer
pkgs.git
pkgs.nodejs
];
openssh.authorizedKeys.keys = [
# maybe a deploy key goes here and hooks into your CI/CD pipeline?
];
};
users.groups.example = {};
users.users.wwwrun.extraGroups = [
"acme"
"example"
];
}
From here you rebuild, hop on your server, and become the “example” user via sudo -iu example
(or whatever):
[example@lamp:~]$ cd /var/www/example.org/
[example@lamp:~]$ git clone git@github.com:adamzivcak/example.git .
[example@lamp:~]$ # hack up your .env file with the details of your install
[example@lamp:~]$ nano .env
[example@lamp:~]$ # prepare your web app for production, see https://laravel.com/docs/8.x/deployment for details
[example@lamp:~]$ composer install --optimize-autoloader --no-dev
[example@lamp:~]$ php artisan config:cache
[example@lamp:~]$ php artisan route:cache
[example@lamp:~]$ php artisan view:cache
I haven’t got into anything more detailed like laravel
queues via redis
or beanstalkd
, but if you want me to feel free to ask about it. A small part of my job involves deploying a large number of web applications written in php
, a non trivial amount of which are laravel
. Almost all of these web apps are deployed on NixOS.
I hope this helps.
ping @stianlagstad because of Tutorial for setting up the LAMP stack on a NixOS server?