NixOS LEMP Stack with SSL

Here is an example of getting started with NGINX and PHP. It grabs a wildcard cert for your domain and can be reused. Everything runs as its own user, however installing PHP doesn’t create a user so add that manually. Then NGINX gets added to the extra groups so it can access the PHP socket and SSL certs registered by Acme. I’m using Cloudflare for my DNS but Acme supports many others.

{
  # List packages installed in system profile. To search, run:
  environment.systemPackages = with pkgs; [
    nginx
    php
  ];

  # make php group with no users
  users.groups.php = {};

  users.users = {
    # Define a system user account for PHP and assign primary group
    php = {
      isSystemUser = true;
      group = "php";
    };

    # make sure nginx gets its additional groups
    # need this so the web server can access the php socket and ssl certs
    nginx = {
      isSystemUser = true;
      extraGroups = [ "acme" "php" ];
    };
  };

  security.acme = {
    acceptTerms = true;
    defaults.email = "[email protected]";

    certs."example.com" = {
      domain = "example.com";
      extraDomainNames = [ "*.example.com" ];
      dnsProvider = "cloudflare";
      dnsPropagationCheck = true;
      credentialsFile = /example/pathto/cloudflare;
    };
  };

  services.nginx = {
    enable = true;
    logError = "/var/log/nginx/error.log warn";
    
    clientMaxBodySize = "100M";
    resolver.addresses = [ "1.1.1.1" "8.8.8.8" ];

    # Use recommended settings
    recommendedTlsSettings = true;
    recommendedGzipSettings = true;
    recommendedOptimisation = true;
    recommendedProxySettings = true;

    # virtual host
    virtualHosts."example.com" = {
      default = true;
      forceSSL = true;
      useACMEHost = "example.com"; # use the wildcard cert we got with acme
      root = "/var/www/example.com/html";
      extraConfig = ''
        index index.html index.php;
      '';

      locations."~ ^(.+\\.php)(.*)$".extraConfig = ''
        fastcgi_pass  unix:${config.services.phpfpm.pools.php.socket};
        fastcgi_index index.php;
      '';
    };
  };

  # php-fpm 
  services.phpfpm.pools.php = {
    user = "php";
    group = "php";
    phpPackage = pkgs.php;
    settings = {
      "listen.owner" = "php";
      "listen.group" = "php";
      "listen.mode" = "0660";
      "pm" = "dynamic";
      "pm.max_children" = 75;
      "pm.start_servers" = 10;
      "pm.min_spare_servers" = 5;
      "pm.max_spare_servers" = 20;
      "pm.max_requests" = 500;
    };
  };

  # enable mysql
  services.mysql = {
    enable = true;
    package = pkgs.mariadb;
  };

  # allow nginx to write to its log files
  systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/log/nginx/" ];

  system.stateVersion = "24.05"; # Did you read the comment?
}

References:
https://nixos.wiki/wiki/Nginx
https://nixos.org/manual/nixos/stable/#module-security-acme-nginx
https://discourse.nixos.org/t/unable-to-configure-nginx-with-php-fpm/26298/7

Leave a Reply

Your email address will not be published. Required fields are marked *