[Solved] How do I add packages to path environment of container?

I have an apache + php-cgi container set up and serving an index.php script. Now I’d like to run an external command from the PHP script, for this example, let’s try to run git --version.

Here’s the /etc/nixos/containers/web-test-1.nix I’m using…

{ config, pkgs, ... }:

{
  containers."web-test-1" = {
    autoStart = true;

    bindMounts = {
      "/var/www" = {
        hostPath = "/srv/web-test-1/www";
        isReadOnly = true;
      };
    };

    config = { config, pkgs, ... }: {
      networking.firewall = {
        enable = true;
        allowedTCPPorts = [ 80 ];
      };

      environment.systemPackages = with pkgs; [
        git
      ];

      services.httpd = {
        enable = true;

        adminAddr = "admin@example.com";
        documentRoot = "/var/www";
        hostName = "web-test-1";

        logFormat = "combined";

        extraConfig = ''
          <Directory /var/www>
            Options -Indexes +FollowSymLinks
            AddLanguage en en
            LanguagePriority en

            AllowOverride None

            Require all granted
          </Directory>

          <IfModule dir_module>
            DirectoryIndex index.php
          </IfModule>

          <Files ".ht*">
            Require all denied
          </Files>

          <IfModule mime_module>
            TypesConfig conf/mime.types

            AddType application/x-compress .Z
            AddType application/x-gzip .gz .tgz
          </IfModule>

          <IfModule deflate_module>
            AddOutputFilterByType DEFLATE text/html
            AddOutputFilterByType DEFLATE text/plain
            AddOutputFilterByType DEFLATE text/xml
            AddOutputFilterByType DEFLATE text/css
            AddOutputFilterByType DEFLATE text/javascript
            AddOutputFilterByType DEFLATE application/javascript
            AddOutputFilterByType DEFLATE application/json
          </IfModule>

          # Security
          ServerSignature Off
          ServerTokens Prod

          Timeout 4800
        '';

        enablePHP = true;
        phpPackage = pkgs.php56;
        phpOptions = ''
        '';

        robotsEntries = ''
          User-agent: *
          Disallow: /
        '';
      };
    };
  };
}

Which is imported into my /etc/nixos/configuration.nix

{ config, pkgs, ... }:A simple import

{
  imports =
    [ ./containers/web-test-1.nix
    ];

  networking.firewall.allowedTCPPorts = [ 80 ];  # Allow access to Apache's port.

  # ... other configuration settings
}

sudo nixos-rebuild switch spins up the server on port 80, and I can add an index.php to /srv/web-test-1/www/

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">

    <title>Test</title>

  </head>
  <body>
    <pre>
<?= shell_exec("env") ?>
    </pre>
  </body>
</html>

And I see the environment variables available to my PHP shell commands…

LANG=en_US.UTF-8
INVOCATION_ID=8d952cc30d5f4fd9bf7c58e4c279a6fb
PHPRC=/nix/store/fj6vb8ixb2mzvzasidisr6g0mihwjva5-php.ini
TZDIR=/nix/store/brib029xs79az5vhjd5nhixp1l39ni31-tzdata-2017c/share/zoneinfo
PWD=/var/www
JOURNAL_STREAM=9:344676
SHLVL=1
LOCALE_ARCHIVE=/nix/store/vg0s4sl74f5ik64wrrx0q9n6m48vvmgs-glibc-locales-2.26-131/lib/locale/locale-archive
PATH=/nix/store/sg6fxslp4mygfb9vvxxmvpmskslf5b7q-apache-httpd-2.4.33/bin:/nix/store/cb3slv3szhp46xkrczqw7mscy5mnk64l-coreutils-8.29/bin:/nix/store/s63b2myh6rxfl4aqwi9yxd6rq66djk33-gnugrep-3.1/bin:/nix/store/cb3slv3szhp46xkrczqw7mscy5mnk64l-coreutils-8.29/bin:/nix/store/364b5gkvgrm87bh1scxm5h8shp975n0r-findutils-4.6.0/bin:/nix/store/s63b2myh6rxfl4aqwi9yxd6rq66djk33-gnugrep-3.1/bin:/nix/store/navldm477k3ar6cy0zlw9rk43i459g69-gnused-4.4/bin:/nix/store/fl3mcaqqk2vg0dmk01dfbs6nbm5skpzc-systemd-237/bin:/nix/store/sg6fxslp4mygfb9vvxxmvpmskslf5b7q-apache-httpd-2.4.33/sbin:/nix/store/cb3slv3szhp46xkrczqw7mscy5mnk64l-coreutils-8.29/sbin:/nix/store/s63b2myh6rxfl4aqwi9yxd6rq66djk33-gnugrep-3.1/sbin:/nix/store/cb3slv3szhp46xkrczqw7mscy5mnk64l-coreutils-8.29/sbin:/nix/store/364b5gkvgrm87bh1scxm5h8shp975n0r-findutils-4.6.0/sbin:/nix/store/s63b2myh6rxfl4aqwi9yxd6rq66djk33-gnugrep-3.1/sbin:/nix/store/navldm477k3ar6cy0zlw9rk43i459g69-gnused-4.4/sbin:/nix/store/fl3mcaqqk2vg0dmk01dfbs6nbm5skpzc-systemd-237/sbin
OLDPWD=/
_=/nix/store/cb3slv3szhp46xkrczqw7mscy5mnk64l-coreutils-8.29/bin/env

Looking at the PATH var, I’ve very few commands available. To “install” git in the container, I updated /etc/nixos/containers/web-test-1.nix with:

{ config, pkgs, ... }:

{
  containers."web-test-1" = {
    config = { config, pkgs, ... }: {
      environment.systemPackages = with pkgs; [
        git
      ];
    };
  };
}

And while I can use sudo machinectl shell root@web-test-1 to run git inside the container, I cannot run git in a PHP shell command; for example…

<?php echo shell_exec("git --version"); ?>

will complain that the git command cannot be found. I checked the PATH var after “installing” git, and git's path doesn’t appear in the list.

Since I can run env, I tried using that to find the git executable with <?php echo shell_exec("env git --version"); ?>, but the git command still isn’t found.

So how does one add a package’s bin/ folder to a container’s PATH environment?

This is likely not the correct question to ask. Maybe there’s some configuration in Apache’s conf or PHP’s ini where I should be setting the PATH, but I’m at a loss what that configuration may be or how to make that happen in my nix configuration.

The issue is that PHP is run by apache httpd, and apache httpd is in turn executed in a systemd unit that has only access to pre-defined paths.

By default lists are merged by the nixos module system so you could try and add something like this to your container config:

systemd.services.httpd.path = with pkgs; [ git ];
2 Likes

Outstanding! That worked.

I had concerns that change might replace the existing values, but they appear to have merged just fine.

Thanks @zimbatm :slight_smile: