Tutorial for setting up the LAMP stack on a NixOS server?

Thanks @jonringer! :slight_smile: This worked:

  services.httpd.virtualHosts."example.org" = {
    documentRoot = my-source.source-code;
    extraConfig = ''
      <Directory />
        DirectoryIndex index.php
        Require all granted
      </Directory>
      SetEnv MYSQL_HOST localhost
      SetEnv MYSQL_DATABASE ${dbConfig.db}
      SetEnv MYSQL_USER ${dbConfig.user}
      SetEnv MYSQL_PASSWORD ${dbConfig.password}
    '';
  };

Keep in mind this isn’t a good idea, though… as it exposes your password into the nix store which is world readable permission wise.

Given what you have previously posted you don’t actually need a password to authenticate to your database, you can use socket authentication instead.

If you want to have a working session on the LAMP with NixOS. It might be more efficient to handle various questions that could come up.

1 Like

Thanks again @aanderse ! I’ve successfully setup socket authentication. My configuration.nix now looks like this:

{ config, pkgs, ... }:
let
  my-source = import ./source-code-derivation.nix { inherit pkgs; };
  dbConfig = {
    db = "myDb";
    user = "myDbUser";
    socket = "'./run/mysqld/mysqld.sock'";
  };
in
{
  imports = [
    ./hardware-configuration.nix
  ];

  boot.cleanTmpDir = true;
  networking.hostName = "myhostname";
  networking.firewall.allowPing = true;
  services.openssh.enable = true;
  users.users.root.openssh.authorizedKeys.keys = [
    "ssh-ed25519 mykey myemail"
  ];

  environment.systemPackages = with pkgs; [
    neovim
  ];


  networking.firewall.allowedTCPPorts = [ 80 443 ];

  services.httpd.enable = true;
  services.httpd.adminAddr = "myemail";
  services.httpd.enablePHP = true; # oof... not a great idea in my opinion

  services.httpd.virtualHosts."example.org" = {
    documentRoot = my-source.source-code;
    extraConfig = ''
      <Directory />
        DirectoryIndex index.php
        Require all granted
      </Directory>
      SetEnv MYSQL_HOST localhost
      SetEnv MYSQL_DATABASE ${dbConfig.db}
      SetEnv MYSQL_USER ${dbConfig.user}
      SetEnv MYSQL_SOCKET ${dbConfig.socket}
    '';
  };

  services.mysql = {
    enable = true;
    package = pkgs.mariadb;
    bind = "localhost";
    ensureDatabases = [
      dbConfig.db
    ];
    ensureUsers = [
      {
        name = "${dbConfig.user}";
        ensurePermissions = {
          "${dbConfig.db}.*" = "ALL PRIVILEGES";
        };
      }
    ];
  };

}

Do you have any suggestions to decrease space usage in the nix store? I’d like this run this old app on a small VPS, and currently the nix store is taking about 4gb of space.

[root@extravmstianlagstad:/]# du /nix/ -sh
4.1G    /nix/

That’s after running nix-env -p /nix/var/nix/profiles/system --delete-generations +2 and nix-collect-garbage. Is it realistic/practical to decrease that 4gb?

1 Like

I would suggest opening a new topic for your space question. I have never tried to reduce disk space usage with NixOS because I only work on boxes where high disk space usage is expected. Sorry I couldn’t be helpful on this topic.

1 Like

Examine your system’s closure and see what is taking space.
nix path-info -rsSh /run/current-system.

For a NixOS container with your configuration (so without the “my-source” and hardware-configuration) i get a 1.4G closure size.

1 Like

Thanks again for responding, @aanderse !

Thanks @tomberek ! I did nix-build server.nix and then nix path-info -Sh ./result to see that the closure size is 1.6G. Not too bad, I think.

The next step for me is to setup Let’s Encrypt. I see that Nginx - NixOS Wiki has an example of the LEMP stack, so I’ll try using nginx instead of apache.

I think the letsencrypt part works, but I’m not able to load my site. When I go to the root domain, I get an nginx 403 error. When I explicitly go to /index.php, then I get a black page.

  • tail -f /var/log/nginx/access.log reports a 500
  • I don’t see anything in /var/log/nginx/error.log
  • I don’t see anything useful in journalctl -u phpfpm-mypool.service.

Any hints as to where I could look for the error log?

Current configuration.nix:

{ config, pkgs, ... }:
let
  my-source = import ./source-code-derivation.nix { inherit pkgs; };
  dbConfig = {
    db = "myDb";
    user = "myDbUser";
    socket = "'./run/mysqld/mysqld.sock'";
  };
in
{
  imports = [
    ./hardware-configuration.nix
  ];

  boot.cleanTmpDir = true;
  networking.hostName = "extravmexample";
  networking.firewall.allowPing = true;
  services.openssh.enable = true;
  users.users.root.openssh.authorizedKeys.keys = [
    "ssh-ed25519 *** test@example.com"
  ];

  environment.systemPackages = with pkgs; [
    neovim
  ];


  networking.firewall.allowedTCPPorts = [ 80 443 ];

  services.nginx = {
    enable = true;
    virtualHosts."example.com" = {
      enableACME = true;
      forceSSL = true;
      root = my-source.source-code;
      locations."~ \.php$".extraConfig = ''
        fastcgi_pass  unix:${config.services.phpfpm.pools.mypool.socket};
        fastcgi_index index.php;
      '';
    };
  };

  security.acme.certs = {
    "example.com".email = "test@example.com";
  };
  security.acme.acceptTerms = true;

  services.phpfpm.pools.mypool = {
    user = "nobody";
    settings = {
      pm = "dynamic";
      "listen.owner" = config.services.nginx.user;
      "pm.max_children" = 5;
      "pm.start_servers" = 2;
      "pm.min_spare_servers" = 1;
      "pm.max_spare_servers" = 3;
      "pm.max_requests" = 500;
      "catch_workers_output" = 1;
    };
  };

  services.mysql = {
    enable = true;
    package = pkgs.mariadb;
    bind = "localhost";
    ensureDatabases = [
      dbConfig.db
    ];
    ensureUsers = [
      {
        name = "${dbConfig.user}";
        ensurePermissions = {
          "${dbConfig.db}.*" = "ALL PRIVILEGES";
        };
      }
    ];
  };

}

Not sure if it’s worth mentioning, but I’m seeing this in /var/log/nginx/error.log:

2021/08/01 12:25:41 [warn] 38659#38659: could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size

Interesting way of using nix-shelk:

1 Like

It’s a modernized LAMP, but here’s how to setup a PHP project using https://devenv.sh

1 Like

You mean LCMP :face_with_hand_over_mouth:

This is really great @domenkozar :rocket: Having a full stack available for php developers is huge. I hope the devenv team keeps up all the great work!

1 Like

Is there a tutorial somewhere for setting up a PHP app with devenv? I’ve read a bit of devenv’s documentation and the PHP sample above but I’m afraid I need a lot more hand-holding. My main question is: where do I specify the file that is to be used as an entrypoint, e.g., index.php?

This seems like a good example that I assume would point at the base of the repository you included devenv in:

@shyim covered the entire process of php development in a great article as well: