myservice
i've written a nixos service in myservice.nix and i include it in /etc/nixos/configuration.nix with:
imports [ /path/to/myservice.nix ];
and later i'm using it inside configuration.nix:
services.myservice.enable = true;
question
in one scenario i can't use nixos-rebuild switch but because typing in nix is linked to the options system using foo = mkOption { type = types.int; ...} i'm forced to use the options systems even though i just want to compute a configuration file for nginx using nix.
how to evaluate that nginx.conf only?
#aszlig wrote me this command:
nix-instantiate --eval --strict -E '(import <nixpkgs/nixos> { configuration = { imports = [ nixcloud-reverse-proxy/nixcloud-reverse-proxy.nix ]; services.nixcloud-reverse-proxy.enable = true; }; }).config.system.build.configsFromPath'
execution results in
nix-instantiate --eval --strict -E '(import <nixpkgs/nixos> { configuration = { imports = [ ./nixcloud-reverse-proxy.nix ]; services.nixcloud-reverse-proxy.enable = true; }; }).config.system.build.configsFromPath'
error: attribute ‘configsFromPath’ missing, at (string):1:1
(use ‘--show-trace’ to show detailed location information)
update
nix-build '<nixpkgs/nixos>' -A config.systemd.services.nixcloud-reverse-proxy.runner -I nixos-config=./configuration.nix
...
/nix/store/lp2jbb1wahhlr7qkq81rmfvk84mjk1vk-nixcloud-reverse-proxy-runner
now i can use that to grep the conf file:
cat /nix/store/lp2jbb1wahhlr7qkq81rmfvk84mjk1vk-nixcloud-reverse-proxy-runner | grep -o ' /nix/store/.*nginx-reverse-proxy.conf'
... kind of a workaround but not very precise! i'd rather like a config file in a directory.
I see your file name is nginx-reverse-proxy.conf, so it isn't built with fancy NixOS module system, but with some other ways. In that case (you control how you build your file) you can include it globally:
environment.etc."myconfigs"."nginx-reverse-proxy.conf".text = ...content of that file;
Which your refer then with
$ nix-instantiate --eval -E '
with import <nixpkgs/nixos> {
configuration = { ... };
};
config.environment.etc."myconfigs"."nginx-reverse-proxy.conf".text
'
You probably need to decode that output though using trick described in https://gist.github.com/danbst/a9fc068ff26e31d88de9709965daa2bd
which is itself a convoluted way to do
$ cat $(nix-build -E '
with import <nixpkgs/nixos> {
configuration = { ... };
};
config.environment.etc."myconfigs"."nginx-reverse-proxy.conf".source
')
In case your proxy config is part of general nginx.conf script, then you still can get it using
$ cat $(cat $(nix-build -E '
with import <nixpkgs/nixos> {
configuration = ...;
};
config.system.build.units."nginx.service".unit
')/nginx.service \
| grep nginx.conf \
| sed -r 's/.* (.*nginx.conf).*/\1/g'
)
Because nginx.conf file is private to nginx module, we can't reference it directly, but have to extract it directly from usage site.
Overall, NixOS lacks a good interface to introspect its internals, but it is still possible.
Related
I can start nix-shell with a package from a particular revision, e.g.
nix-shell -p ktlint -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/141439f6f11537ee349a58aaf97a5a5fc072365c.tar.gz
nix-shell -p jq -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/7d7622909a38a46415dd146ec046fdc0f3309f44.tar.gz
Can I start nix-shell with two packages, but from different revisions, in one command? For example, if I wanted both ktlint and jq from the specific revisions above?
Setting NIX_PATH=nixpkgs=... is just syntactic sugar enabling references like <nixpkgs> to work; but one doesn't need to use import <nixpkgs> exclusively -- one can also import directly from an explicit path.
nix-shell -E '
let
pkgsA = (import (builtins.fetchTarball https://github.com/NixOS/nixpkgs/archive/141439f6f11537ee349a58aaf97a5a5fc072365c.tar.gz) {});
pkgsB = (import (builtins.fetchTarball https://github.com/NixOS/nixpkgs/archive/7d7622909a38a46415dd146ec046fdc0f3309f44.tar.gz) {});
in
pkgsA.mkShell {
buildInputs = [
pkgsA.ktlint
pkgsB.jq
];
}'
I followed the steps on http://lethalman.blogspot.com/2014/08/nix-pill-8-generic-builders.html to build GNU Hello, and here is the files I used to build GNU hello 2.9:
$ wget -c http://ftp.gnu.org/gnu/hello/hello-2.9.tar.gz
hello.nix:
$ cat hello.nix
let
pkgs = import <nixpkgs> {};
mkDerivation = import ./autotools.nix pkgs;
in mkDerivation {
name = "hello";
src = ./hello-2.9.tar.gz;
}
autotools.nix:
$ cat autotools.nix
pkgs: attrs:
with pkgs;
let defaultAttrs = {
builder = "${bash}/bin/bash";
args = [ ./builder.sh ];
baseInputs = [ gnutar gzip gnumake gcc binutils coreutils gawk gnused gnugrep ];
buildInputs = [];
system = builtins.currentSystem;
};
in
derivation (defaultAttrs // attrs)
builder.sh:
$ cat builder.sh
set -e
unset PATH
for p in $buildInputs; do
export PATH=$p/bin${PATH:+:}$PATH
done
tar -xf $src
for d in *; do
if [ -d "$d" ]; then
cd "$d"
break
fi
done
./configure --prefix=$out
make
make install
Error messages:
$ nix-build hello.nix
these derivations will be built:
/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv
building '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv'...
/nix/store/vv3xqdggviqqbvym25jf2pwv575y9j1r-builder.sh: line 7: tar: No such file or directory
builder for '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv' failed with exit code 127
error: build of '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv' failed
It seems there is gnutar in the autotools.nix but builder still complains tar: No such file or directory, why is this?
The problem is probably that gnutar is in the baseInputs list, while the buildInputs list you are building your PATH from is totally empty so nothing will be on your PATH. Try changing the for line in your shell script so that it uses the concatentation of both lists to build the path:
for p in $baseInputs $buildInputs; do
You can add echo $PATH to your builder script to debug issues like this.
That is what the blog post author was asking you to do in this sentence from the post:
Complete the new builder.sh by adding $baseInputs in the for loop together with $buildInputs.
I have the following shell.nix (to setup my development environment, no NixOS):
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "my-shiny-project";
buildInputs = [
jq
nodejs-6_x
#postgis {version="2.3.1";}
#postgis ("2.3.1")
#postgis "2.3.1"
postgresql96
zsh
];
shellHook = ''
export SHELL=zsh
export PATH="$PWD/node_modules/.bin/:$PATH"
'';
}
PostGIS expects a version parameter. I'm not sure how to pass that parameter along. Whether I use postgis{version="2.3.1";}, postgis("2.3.1") or postgis "2.3.1", I receive the following error:
error: cannot coerce a set to a string, at /nix/store/0rj9y7gvzzahp93cvdmrwc2v2aznh61p-nixpkgs-18.03pre118061.69607d7662/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:98:11
In the Nameless and single parameter section of functions and imports Nix pill, I see the syntax for calling a function is simply NAME PARAM.
What do I have to add to buildInputs to get PostGIS installed for that specific version of PostgreSQL?
Recently it became possible to use postgresql.withPackages:
with import <nixpkgs> {};
mkShell {
buildInputs = [
jq
nodejs
( postgresql11.withPackages (p: [ p.postgis ]) )
zsh
];
shellHook = ''
export SHELL=${zsh}/bin/zsh
export PATH="${builtins.toPath ./.}/node_modules/.bin/:$PATH"
export PGDATA=${builtins.toPath ./.}/pg
export PGHOST=$PGDATA
pg_ctl initdb
pg_ctl -o "-p 5555 -k $PGDATA" start
psql -p 5555 postgres -c 'create extension postgis' || true
'';
}
This is truly a stab in the dark given that postgresql is designed to be used as a service, but it's only available to you as a package since you're not on NixOS. But try this:
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "my-shiny-project";
buildInputs = [
jq
nodejs-6_x
postgis.v_2_3_1
postgresql96
zsh
];
shellHook = ''
export SHELL=zsh
export PATH="$PWD/node_modules/.bin/:$PATH"
'';
}
Explanation
The postgis package doesn't produce a derivation, so it's output cannot be used directly. Instead it produces a set with attributes for two versions: 2.3.1 and 2.4.0.
Caveat
The above may not work at all. The issue is that postgis is normally provided to postgresql via the extraPlugins attribute like so:
services.postgresql.extraPlugins = [ (pkgs.postgis.override { postgresql = pkgs.postgresql95; }).v_2_3_1 ];
This causes postgresql to be installed in such a way that it can see the postgis library. However, this is done at the service level, not the package leve, and services are only available to NixOS. So if the above doesn't work, try this hunk of code:
with import <nixpkgs> {};
let
pg = postgresql96;
postgresqlWithPlugins =
buildEnv {
name = "postgresql-and-plugins-${(builtins.parseDrvName pg.name).version}";
paths = [ pg pg.lib (postgis.override { postgresql = pg; }).v_2_3_1) ];
buildInputs = [ makeWrapper ];
postBuild =
''
mkdir -p $out/bin
rm $out/bin/{pg_config,postgres,pg_ctl}
cp --target-directory=$out/bin ${pg}/bin/{postgres,pg_config,pg_ctl}
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
'';
};
in
stdenv.mkDerivation {
name = "my-shiny-project";
buildInputs = [
jq
nodejs-6_x
postgresqlWithPlugins
zsh
];
shellHook = ''
export SHELL=zsh
export PATH="$PWD/node_modules/.bin/:$PATH"
'';
}
Basically, this is an untested port of the extraPlugins implementation.
I get the following collision error when attempting to build an environment that, as far as I can see, shouldn't have a collision (in this case, scala-env depends on ideaLocal, so it shouldn't conflict with it):
...
idea-IU-172.4155.36/bin/libyjpagent-linux.so
idea-IU-172.4155.36/bin/libyjpagent-linux64.so
idea-IU-172.4155.36/help/ideahelp.jar
idea-IU-172.4155.36/lib/libpty/linux/x86/libpty.so
idea-IU-172.4155.36/lib/libpty/linux/x86_64/libpty.so
idea-IU-172.4155.36/bin/format.sh
idea-IU-172.4155.36/bin/fsnotifier
idea-IU-172.4155.36/bin/fsnotifier-arm
idea-IU-172.4155.36/bin/fsnotifier64
idea-IU-172.4155.36/bin/idea.sh
idea-IU-172.4155.36/bin/inspect.sh
idea-IU-172.4155.36/bin/printenv.py
idea-IU-172.4155.36/bin/restart.py
building path(s) ‘/nix/store/29g92lnpi0kywy9x7vcgl9yivwa2blm6-scala-env’
created 696 symlinks in user environment
building path(s) ‘/nix/store/qrnbff8nhpmxlzkmv508aymz5razbhgf-user-environment’
Wide character in die at /nix/store/64jc9gd2rkbgdb4yjx3nrgc91bpjj5ky-buildenv.pl line 79.
collision between ‘/nix/store/75sz9nklqmrmzxvf0faxmf6zamgaznfv-idea-local/bin/idea’ and ‘/nix/store/29g92lnpi0kywy9x7vcgl9yivwa2blm6-scala-env/bin/idea’; use ‘nix-env --set-flag priority NUMBER PKGNAME’ to change the priority of one of the conflicting packages
builder for ‘/nix/store/8hp5kdicxy9i02fa07vx85p1gvh4i1bq-user-environment.drv’ failed with exit code 255
error: build of ‘/nix/store/8hp5kdicxy9i02fa07vx85p1gvh4i1bq-user-environment.drv’ failed
Here is the nix expression (most of which can be ignored, but it isn't too long so I'll paste the whole thing):
with import <nixpkgs> { };
let
ideaLocal = stdenv.mkDerivation {
name = "idea-local";
buildInputs = [ ];
builder = builtins.toFile "builder.sh" ''
source $stdenv/setup
mkdir -p $out/bin
tar zxvf $src -C $out/
ln -sf $out/idea-IU* $out/idea
ln -sf $out/idea/bin/idea.sh $out/bin/idea
'';
shellHook = ''
IDEA_JDK=/usr/lib/jvm/zulu-8-amd64
'';
src = fetchurl {
url = https://download.jetbrains.com/idea/ideaIU-2017.2.4-no-jdk.tar.gz;
sha256 = "15a4799ffde294d0f2fce0b735bbfe370e3d0327380a0efc45905241729898e3";
};
priority = 5;
};
in
buildEnv {
name = "scala-env";
paths = [
ammonite
boehmgc
clang
dbus # needed non-explicitly by vscode
emacs
git
# idea.idea-ultimate # disabled temporarily
ideaLocal
less
libunwind
openjdk
openssh
re2
rsync
sbt
stdenv
syncthing # for syncrhonizing data between containers
tmux
unzip
vscode
zlib
];
# builder = builtins.toFile "builder.sh" ''
# source $stdenv/setup
# mkdir -p $out
# echo "" > $out/Done
# echo "Done setting up Scala environment."
# '';
buildInputs = [ makeWrapper ];
# TODO: better filter, use ammonite script?:
postBuild = ''
for f in $(ls -d $out/bin/* | grep "idea"); do
sed -i '/IDEA_JDK/d' $f
wrapProgram $f \
--set IDEA_JDK "/usr/lib/jvm/zulu-8-amd64" \
--set CLANG_PATH "${clang}/bin/clang" \
--set CLANCPP_PATH "${clang}/bin/clang++"
done
'';
}
Edit:
(DevContainer)which idea
/home/brandon/.nix-profile/bin/idea
(DevContainer)ls -last /home/brandon/.nix-profile/bin/idea
4 lrwxrwxrwx 1 brandon brandon 63 Jan 1 1970 /home/brandon/.nix-profile/bin/idea -> /nix/store/75sz9nklqmrmzxvf0faxmf6zamgaznfv-idea-local/bin/idea
So it looks like ideaLocal is being imported as an environment - what's the right way to just have it installed as a package that is a dependency of scalaEnv?
Apparently the solution was to specify the profile, which I think of as the name of the environment, so that both environments aren't installed simultaneously:
nix-env -if scala-default.nix -p scala-env
I'm writing a .nix expression to be used primarily by nix-shell. I'm not sure how to do that. Note this is not on NixOS, but I don't think that is very relevant.
The particular example I'm looking at is that I want to get this version-dependent name that looks like:
idea-ultimate = buildIdea rec {
name = "idea-ultimate-${version}";
version = "2017.2.2"; /* updated by script */
description = "Integrated Development Environment (IDE) by Jetbrains, requires paid license";
license = stdenv.lib.licenses.unfree;
src = fetchurl {
url = "https://download.jetbrains.com/idea/ideaIU-${version}-no-jdk.tar.gz";
sha256 = "b8eb9d612800cc896eb6b6fbefbf9f49d92d2350ae1c3c4598e5e12bf93be401"; /* updated by script */
};
wmClass = "jetbrains-idea";
update-channel = "IDEA_Release";
};
My nix expression is the following:
let
pkgs = import <nixpkgs> {};
stdenv = pkgs.stdenv;
# idea_name = assert pkgs.jetbrains.idea-ultimate.name != ""; pkgs.jetbrains.idea-ultimate.name;
in rec {
scalaEnv = stdenv.mkDerivation rec {
name = "scala-env";
builder = "./scala-build.sh";
shellHook = ''
alias cls=clear
'';
CLANG_PATH = pkgs.clang + "/bin/clang";
CLANGPP_PATH = pkgs.clang + "/bin/clang++";
# A bug in the nixpkgs openjdk (#29151) makes us resort to Zulu OpenJDK for IDEA:
# IDEA_JDK = pkgs.openjdk + "/lib/openjdk";
# PATH = "${pkgs.jetbrains.idea-ultimate}/${idea_name}/bin:$PATH";
IDEA_JDK = /usr/lib/jvm/zulu-8-amd64;
# IDEA_JDK = /opt/zulu8.23.0.3-jdk8.0.144-linux_x64;
# IDEA_JDK = /usr/lib/jvm/java-8-openjdk-amd64;
buildInputs = with pkgs; [
ammonite
boehmgc
clang
emacs
jetbrains.idea-ultimate
less
libunwind
openjdk
re2
sbt
stdenv
unzip
zlib
];
};
}
I have commented out setting PATH as it depends on getting idea_name in the let-clause. As an interesting side note, as is, this does not fail if I leave it uncommented but causes a very bizarre error when executing nix-shell about not being able to execute bash. I've also tried the more simple case of let idea_name = pkgs.jetbrains.idea-ultimate.name; but this fails later on when idea_name is used in setting PATH since idea_name ends up being undefined.
Update:
I began exploring with nix-instantiate, but the derivation of interest seems empty:
[nix-shell:/nix/store]$ nix-instantiate --eval --xml -E "((import <nixpkgs> {}).callPackage ./3hk87pqgl2qdqmskxbhy23cyr24q8g6s-nixpkgs-18.03pre114739.d0d905668c/nixpkgs/pkgs/applications/editors/jetbrains { }).idea-ultimate";
<?xml version='1.0' encoding='utf-8'?>
<expr>
<derivation>
<repeated />
</derivation>
</expr>
If your intent is to get idea-ultimate into nix-shell environment, then just include that package to buildInputs. I see it's already included, so it should already be present in your PATH.
BTW, you can extend your shellHook and export PATH and other variables rather from there, where you have full bash. Why would you do it from bash? Less copying. When you specify
IDEA_JDK = /usr/lib/jvm/zulu-8-amd64;
in Nix, the file /usr/lib/jvm/zulu-8-amd64 get's copied to nix store and IDEA_JDK is set to point to file in /nix/store. Was that your intent?
Regarding nix-instantiate:
$ nix-instantiate --eval -E 'with import <nixpkgs>{}; idea.pycharm-community.outPath'
"/nix/store/71jk0spr30rm4wsihjwbb1hcwwvzqr4k-pycharm-community-2017.1"
but you still have to remove doublequotes (https://gist.github.com/danbst/a9fc068ff26e31d88de9709965daa2bd)
Also, nitpick, assert pkgs.jetbrains.idea-ultimate.name != ""; can be dropped as it's impossible to have empty derivation name in Nix.
And another nitpick. You'll soon find very incovenient to launch IDE from shell every time. It seems a good idea to specify, that some package is used for development, but nix-shell doesn't work well for non-cli applications. Not to mention occasional problems with Nix GC and nix-shell. You'd better install IDE globally or per-user, it is better long-term solution.
[ADDENDUM]
You are looking for this (dev-environment.nix):
with import <nixpkgs> { };
buildEnv {
name = "my-super-dev-env";
paths = [
#emacs
nano
idea.pycharm-community
];
buildInputs = [ makeWrapper ];
postBuild = ''
for f in $(ls -d $out/bin/*); do
wrapProgram $f \
--set IDEA_JDK "/path/to/zulu-jdk" \
--set CLANG_PATH ... \
--set CLANCPP_PATH ...
done
'';
}
which you install using nix-env -if ./dev-environment.nix. It will wrap your programs with those env vars, without polluting your workspace (you can pollute it further using nix-shell with shell hook, if you want).