Merge remote-tracking branch 'upstream/release-18.03' into meta-check-18.03
commit
ac3d9c3d13
|
@ -0,0 +1,6 @@
|
|||
*.chapter.xml
|
||||
*.section.xml
|
||||
.version
|
||||
out
|
||||
manual-full.xml
|
||||
highlightjs
|
|
@ -0,0 +1,96 @@
|
|||
MD_TARGETS=$(addsuffix .xml, $(basename $(wildcard ./*.md ./**/*.md)))
|
||||
|
||||
.PHONY: all
|
||||
all: validate out/html/index.html out/epub/manual.epub
|
||||
|
||||
.PHONY: debug
|
||||
debug:
|
||||
nix-shell --run "xmloscopy --docbook5 ./manual.xml ./manual-full.xml"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f ${MD_TARGETS} .version manual-full.xml
|
||||
rm -rf ./out/ ./highlightjs
|
||||
|
||||
.PHONY: validate
|
||||
validate: manual-full.xml
|
||||
jing "$$RNG" manual-full.xml
|
||||
|
||||
out/html/index.html: manual-full.xml style.css highlightjs
|
||||
mkdir -p out/html
|
||||
xsltproc ${xsltFlags} \
|
||||
--nonet --xinclude \
|
||||
--output $@ \
|
||||
"$$XSL/docbook/xhtml/docbook.xsl" \
|
||||
./manual-full.xml
|
||||
|
||||
mkdir -p out/html/highlightjs/
|
||||
echo "document.onreadystatechange = function () { \
|
||||
var listings = document.querySelectorAll('.programlisting, .screen'); \
|
||||
for (i = 0; i < listings.length; ++i) { \
|
||||
hljs.highlightBlock(listings[i]); \
|
||||
} \
|
||||
} " > out/html/highlightjs/loader.js
|
||||
|
||||
cp -r highlightjs out/html/
|
||||
|
||||
cp ./overrides.css out/html/
|
||||
cp ./style.css out/html/style.css
|
||||
|
||||
mkdir -p out/html/images/callouts
|
||||
cp "$$XSL/docbook/images/callouts/"*.svg out/html/images/callouts/
|
||||
chmod u+w -R out/html/
|
||||
|
||||
out/epub/manual.epub: manual-full.xml
|
||||
mkdir -p out/epub/scratch
|
||||
xsltproc ${xsltFlags} --nonet \
|
||||
--output out/epub/scratch/ \
|
||||
"$$XSL/docbook/epub/docbook.xsl" \
|
||||
./manual-full.xml
|
||||
|
||||
cp ./overrides.css out/epub/scratch/OEBPS
|
||||
cp ./style.css out/epub/scratch/OEBPS
|
||||
mkdir -p out/epub/scratch/OEBPS/images/callouts/
|
||||
cp "$$XSL/docbook/images/callouts/"*.svg out/epub/scratch/OEBPS/images/callouts/
|
||||
echo "application/epub+zip" > mimetype
|
||||
zip -0Xq "out/epub/manual.epub" mimetype
|
||||
rm mimetype
|
||||
cd "out/epub/scratch/" && zip -Xr9D "../manual.epub" *
|
||||
rm -rf "out/epub/scratch/"
|
||||
|
||||
highlightjs:
|
||||
mkdir -p highlightjs
|
||||
cp -r "$$HIGHLIGHTJS/highlight.pack.js" highlightjs/
|
||||
cp -r "$$HIGHLIGHTJS/LICENSE" highlightjs/
|
||||
cp -r "$$HIGHLIGHTJS/mono-blue.css" highlightjs/
|
||||
|
||||
|
||||
manual-full.xml: ${MD_TARGETS} .version *.xml
|
||||
xmllint --nonet --xinclude --noxincludenode manual.xml --output manual-full.xml
|
||||
|
||||
.version:
|
||||
nix-instantiate --eval \
|
||||
-E '(import ../lib).nixpkgsVersion' > .version
|
||||
|
||||
%.section.xml: %.section.md
|
||||
pandoc $^ -w docbook+smart \
|
||||
-f markdown+smart \
|
||||
| sed -e 's|<ulink url=|<link xlink:href=|' \
|
||||
-e 's|</ulink>|</link>|' \
|
||||
-e 's|<sect. id=|<section xml:id=|' \
|
||||
-e 's|</sect[0-9]>|</section>|' \
|
||||
-e '1s| id=| xml:id=|' \
|
||||
-e '1s|\(<[^ ]* \)|\1xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" |' \
|
||||
| cat > $@
|
||||
|
||||
%.chapter.xml: %.chapter.md
|
||||
pandoc $^ -w docbook+smart \
|
||||
--top-level-division=chapter \
|
||||
-f markdown+smart \
|
||||
| sed -e 's|<ulink url=|<link xlink:href=|' \
|
||||
-e 's|</ulink>|</link>|' \
|
||||
-e 's|<sect. id=|<section xml:id=|' \
|
||||
-e 's|</sect[0-9]>|</section>|' \
|
||||
-e '1s| id=| xml:id=|' \
|
||||
-e '1s|\(<[^ ]* \)|\1|' \
|
||||
| cat > $@
|
|
@ -6,12 +6,27 @@
|
|||
|
||||
<para>The DocBook sources of the Nixpkgs manual are in the <filename
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/tree/master/doc">doc</filename>
|
||||
subdirectory of the Nixpkgs repository. If you make modifications to
|
||||
the manual, it's important to build it before committing. You can do that as follows:
|
||||
subdirectory of the Nixpkgs repository.</para>
|
||||
|
||||
<para>You can quickly check your edits with <command>make</command>:</para>
|
||||
|
||||
<screen>
|
||||
$ cd /path/to/nixpkgs
|
||||
$ nix-build doc
|
||||
$ cd /path/to/nixpkgs/doc
|
||||
$ nix-shell
|
||||
[nix-shell]$ make
|
||||
</screen>
|
||||
|
||||
<para>If you experience problems, run <command>make debug</command>
|
||||
to help understand the docbook errors.</para>
|
||||
|
||||
<para>After making modifications to the manual, it's important to
|
||||
build it before committing. You can do that as follows:
|
||||
|
||||
<screen>
|
||||
$ cd /path/to/nixpkgs/doc
|
||||
$ nix-shell
|
||||
[nix-shell]$ make clean
|
||||
[nix-shell]$ nix-build .
|
||||
</screen>
|
||||
|
||||
If the build succeeds, the manual will be in
|
||||
|
|
131
doc/default.nix
131
doc/default.nix
|
@ -7,112 +7,41 @@ in
|
|||
pkgs.stdenv.mkDerivation {
|
||||
name = "nixpkgs-manual";
|
||||
|
||||
buildInputs = with pkgs; [ pandoc libxml2 libxslt zip jing ];
|
||||
|
||||
buildInputs = with pkgs; [ pandoc libxml2 libxslt zip ];
|
||||
src = ./.;
|
||||
|
||||
xsltFlags = ''
|
||||
--param section.autolabel 1
|
||||
--param section.label.includes.component.label 1
|
||||
--param html.stylesheet 'style.css'
|
||||
--param xref.with.number.and.title 1
|
||||
--param toc.section.depth 3
|
||||
--param admon.style '''
|
||||
--param callout.graphics.extension '.gif'
|
||||
# Hacking on these variables? Make sure to close and open
|
||||
# nix-shell between each test, maybe even:
|
||||
# $ nix-shell --run "make clean all"
|
||||
# otherwise they won't reapply :)
|
||||
HIGHLIGHTJS = pkgs.documentation-highlighter;
|
||||
XSL = "${pkgs.docbook5_xsl}/xml/xsl";
|
||||
RNG = "${pkgs.docbook5}/xml/rng/docbook/docbook.rng";
|
||||
xsltFlags = lib.concatStringsSep " " [
|
||||
"--param section.autolabel 1"
|
||||
"--param section.label.includes.component.label 1"
|
||||
"--stringparam html.stylesheet 'style.css overrides.css highlightjs/mono-blue.css'"
|
||||
"--stringparam html.script './highlightjs/highlight.pack.js ./highlightjs/loader.js'"
|
||||
"--param xref.with.number.and.title 1"
|
||||
"--param toc.section.depth 3"
|
||||
"--stringparam admon.style ''"
|
||||
"--stringparam callout.graphics.extension .svg"
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
echo ${lib.nixpkgsVersion} > .version
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
dest="$out/share/doc/nixpkgs"
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
mv out/html "$dest"
|
||||
mv "$dest/index.html" "$dest/manual.html"
|
||||
|
||||
buildCommand = let toDocbook = { useChapters ? false, inputFile, outputFile }:
|
||||
let
|
||||
extraHeader = lib.optionalString (!useChapters)
|
||||
''xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" '';
|
||||
in ''
|
||||
{
|
||||
pandoc '${inputFile}' -w docbook+smart ${lib.optionalString useChapters "--top-level-division=chapter"} \
|
||||
-f markdown+smart \
|
||||
| sed -e 's|<ulink url=|<link xlink:href=|' \
|
||||
-e 's|</ulink>|</link>|' \
|
||||
-e 's|<sect. id=|<section xml:id=|' \
|
||||
-e 's|</sect[0-9]>|</section>|' \
|
||||
-e '1s| id=| xml:id=|' \
|
||||
-e '1s|\(<[^ ]* \)|\1${extraHeader}|'
|
||||
} > '${outputFile}'
|
||||
'';
|
||||
in
|
||||
mv out/epub/manual.epub "$dest/nixpkgs-manual.epub"
|
||||
|
||||
''
|
||||
ln -s '${sources}/'*.xml .
|
||||
mkdir ./languages-frameworks
|
||||
cp -s '${sources-langs}'/* ./languages-frameworks
|
||||
''
|
||||
+ toDocbook {
|
||||
inputFile = ./introduction.md;
|
||||
outputFile = "introduction.xml";
|
||||
useChapters = true;
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ./shell.md;
|
||||
outputFile = "shell.xml";
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ./languages-frameworks/python.md;
|
||||
outputFile = "./languages-frameworks/python.xml";
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ./languages-frameworks/haskell.md;
|
||||
outputFile = "./languages-frameworks/haskell.xml";
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ../pkgs/development/idris-modules/README.md;
|
||||
outputFile = "languages-frameworks/idris.xml";
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ../pkgs/development/node-packages/README.md;
|
||||
outputFile = "languages-frameworks/node.xml";
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ../pkgs/development/r-modules/README.md;
|
||||
outputFile = "languages-frameworks/r.xml";
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ./languages-frameworks/rust.md;
|
||||
outputFile = "./languages-frameworks/rust.xml";
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ./languages-frameworks/vim.md;
|
||||
outputFile = "./languages-frameworks/vim.xml";
|
||||
}
|
||||
+ ''
|
||||
echo ${lib.nixpkgsVersion} > .version
|
||||
|
||||
# validate against relaxng schema
|
||||
xmllint --nonet --xinclude --noxincludenode manual.xml --output manual-full.xml
|
||||
${pkgs.jing}/bin/jing ${pkgs.docbook5}/xml/rng/docbook/docbook.rng manual-full.xml
|
||||
|
||||
dst=$out/share/doc/nixpkgs
|
||||
mkdir -p $dst
|
||||
xsltproc $xsltFlags --nonet --xinclude \
|
||||
--output $dst/manual.html \
|
||||
${pkgs.docbook5_xsl}/xml/xsl/docbook/xhtml/docbook.xsl \
|
||||
./manual.xml
|
||||
|
||||
cp ${./style.css} $dst/style.css
|
||||
|
||||
mkdir -p $dst/images/callouts
|
||||
cp "${pkgs.docbook5_xsl}/xml/xsl/docbook/images/callouts/"*.gif $dst/images/callouts/
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
echo "doc manual $dst manual.html" >> $out/nix-support/hydra-build-products
|
||||
|
||||
xsltproc $xsltFlags --nonet --xinclude \
|
||||
--output $dst/epub/ \
|
||||
${pkgs.docbook5_xsl}/xml/xsl/docbook/epub/docbook.xsl \
|
||||
./manual.xml
|
||||
|
||||
cp -r $dst/images $dst/epub/OEBPS
|
||||
echo "application/epub+zip" > mimetype
|
||||
manual="$dst/nixpkgs-manual.epub"
|
||||
zip -0Xq "$manual" mimetype
|
||||
cd $dst/epub && zip -Xr9D "$manual" *
|
||||
rm -rf $dst/epub
|
||||
mkdir -p $out/nix-support/
|
||||
echo "doc manual $dest manual.html" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
Idris packages
|
||||
==============
|
||||
|
||||
This directory contains build rules for idris packages. In addition,
|
||||
it contains several functions to build and compose those packages.
|
||||
Everything is exposed to the user via the `idrisPackages` attribute.
|
||||
|
||||
callPackage
|
||||
------------
|
||||
|
||||
This is like the normal nixpkgs callPackage function, specialized to
|
||||
idris packages.
|
||||
|
||||
builtins
|
||||
---------
|
||||
|
||||
This is a list of all of the libraries that come packaged with Idris
|
||||
itself.
|
||||
|
||||
build-idris-package
|
||||
--------------------
|
||||
|
||||
A function to build an idris package. Its sole argument is a set like
|
||||
you might pass to `stdenv.mkDerivation`, except `build-idris-package`
|
||||
sets several attributes for you. See `build-idris-package.nix` for
|
||||
details.
|
||||
|
||||
build-builtin-package
|
||||
----------------------
|
||||
|
||||
A version of `build-idris-package` specialized to builtin libraries.
|
||||
Mostly for internal use.
|
||||
|
||||
with-packages
|
||||
-------------
|
||||
|
||||
Bundle idris together with a list of packages. Because idris currently
|
||||
only supports a single directory in its library path, you must include
|
||||
all desired libraries here, including `prelude` and `base`.
|
|
@ -17,19 +17,18 @@ such as Perl or Haskell. These are described in this chapter.</para>
|
|||
<xi:include href="bower.xml" />
|
||||
<xi:include href="coq.xml" />
|
||||
<xi:include href="go.xml" />
|
||||
<xi:include href="haskell.xml" />
|
||||
<xi:include href="idris.xml" /> <!-- generated from ../../pkgs/development/idris-modules/README.md -->
|
||||
<xi:include href="haskell.section.xml" />
|
||||
<xi:include href="idris.section.xml" />
|
||||
<xi:include href="java.xml" />
|
||||
<xi:include href="lua.xml" />
|
||||
<xi:include href="node.xml" /> <!-- generated from ../../pkgs/development/node-packages/README.md -->
|
||||
<xi:include href="node.section.xml" />
|
||||
<xi:include href="perl.xml" />
|
||||
<xi:include href="python.xml" />
|
||||
<xi:include href="python.section.xml" />
|
||||
<xi:include href="qt.xml" />
|
||||
<xi:include href="r.xml" /> <!-- generated from ../../pkgs/development/r-modules/README.md -->
|
||||
<xi:include href="r.section.xml" />
|
||||
<xi:include href="ruby.xml" />
|
||||
<xi:include href="rust.xml" />
|
||||
<xi:include href="rust.section.xml" />
|
||||
<xi:include href="texlive.xml" />
|
||||
<xi:include href="vim.xml" />
|
||||
|
||||
<xi:include href="vim.section.xml" />
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
Node.js packages
|
||||
================
|
||||
The `pkgs/development/node-packages` folder contains a generated collection of
|
||||
[NPM packages](https://npmjs.com/) that can be installed with the Nix package
|
||||
manager.
|
||||
|
||||
As a rule of thumb, the package set should only provide *end user* software
|
||||
packages, such as command-line utilities. Libraries should only be added to the
|
||||
package set if there is a non-NPM package that requires it.
|
||||
|
||||
When it is desired to use NPM libraries in a development project, use the
|
||||
`node2nix` generator directly on the `package.json` configuration file of the
|
||||
project.
|
||||
|
||||
The package set also provides support for multiple Node.js versions. The policy
|
||||
is that a new package should be added to the collection for the latest stable LTS
|
||||
release (which is currently 6.x), unless there is an explicit reason to support
|
||||
a different release.
|
||||
|
||||
If your package uses native addons, you need to examine what kind of native
|
||||
build system it uses. Here are some examples:
|
||||
|
||||
* `node-gyp`
|
||||
* `node-gyp-builder`
|
||||
* `node-pre-gyp`
|
||||
|
||||
After you have identified the correct system, you need to override your package
|
||||
expression while adding in build system as a build input. For example, `dat`
|
||||
requires `node-gyp-build`, so we override its expression in `default-v6.nix`:
|
||||
|
||||
```nix
|
||||
dat = nodePackages.dat.override (oldAttrs: {
|
||||
buildInputs = oldAttrs.buildInputs ++ [ nodePackages.node-gyp-build ];
|
||||
});
|
||||
```
|
||||
|
||||
To add a package from NPM to nixpkgs:
|
||||
|
||||
1. Modify `pkgs/development/node-packages/node-packages-v6.json` to add, update
|
||||
or remove package entries. (Or `pkgs/development/node-packages/node-packages-v4.json`
|
||||
for packages depending on Node.js 4.x)
|
||||
2. Run the script: `(cd pkgs/development/node-packages && ./generate.sh)`.
|
||||
3. Build your new package to test your changes:
|
||||
`cd /path/to/nixpkgs && nix-build -A nodePackages.<new-or-updated-package>`.
|
||||
To build against a specific Node.js version (e.g. 4.x):
|
||||
`nix-build -A nodePackages_4_x.<new-or-updated-package>`
|
||||
4. Add and commit all modified and generated files.
|
||||
|
||||
For more information about the generation process, consult the
|
||||
[README.md](https://github.com/svanderburg/node2nix) file of the `node2nix`
|
||||
tool.
|
|
@ -871,8 +871,10 @@ Executing `python setup.py bdist_wheel` in a `nix-shell `fails with
|
|||
```
|
||||
ValueError: ZIP does not support timestamps before 1980
|
||||
```
|
||||
This is because files are included that depend on items in the Nix store which have a timestamp of, that is, it corresponds to January the 1st, 1970 at 00:00:00. And as the error informs you, ZIP does not support that.
|
||||
The command `bdist_wheel` takes into account `SOURCE_DATE_EPOCH`, and `nix-shell` sets this to 1. By setting it to a value corresponding to 1980 or later, or by unsetting it, it is possible to build wheels.
|
||||
|
||||
This is because files from the Nix store (which have a timestamp of the UNIX epoch of January 1, 1970) are included in the .ZIP, but .ZIP archives follow the DOS convention of counting timestamps from 1980.
|
||||
|
||||
The command `bdist_wheel` reads the `SOURCE_DATE_EPOCH` environment variable, which `nix-shell` sets to 1. Unsetting this variable or giving it a value corresponding to 1980 or later enables building wheels.
|
||||
|
||||
Use 1980 as timestamp:
|
||||
```shell
|
||||
|
@ -882,7 +884,7 @@ or the current time:
|
|||
```shell
|
||||
nix-shell --run "SOURCE_DATE_EPOCH=$(date +%s) python3 setup.py bdist_wheel"
|
||||
```
|
||||
or unset:
|
||||
or unset `SOURCE_DATE_EPOCH`:
|
||||
```shell
|
||||
nix-shell --run "unset SOURCE_DATE_EPOCH; python3 setup.py bdist_wheel"
|
||||
```
|
|
@ -0,0 +1,120 @@
|
|||
R packages
|
||||
==========
|
||||
|
||||
## Installation
|
||||
|
||||
Define an environment for R that contains all the libraries that you'd like to
|
||||
use by adding the following snippet to your $HOME/.config/nixpkgs/config.nix file:
|
||||
|
||||
```nix
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
|
||||
rEnv = super.rWrapper.override {
|
||||
packages = with self.rPackages; [
|
||||
devtools
|
||||
ggplot2
|
||||
reshape2
|
||||
yaml
|
||||
optparse
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Then you can use `nix-env -f "<nixpkgs>" -iA rEnv` to install it into your user
|
||||
profile. The set of available libraries can be discovered by running the
|
||||
command `nix-env -f "<nixpkgs>" -qaP -A rPackages`. The first column from that
|
||||
output is the name that has to be passed to rWrapper in the code snipped above.
|
||||
|
||||
However, if you'd like to add a file to your project source to make the
|
||||
environment available for other contributors, you can create a `default.nix`
|
||||
file like so:
|
||||
```nix
|
||||
let
|
||||
pkgs = import <nixpkgs> {};
|
||||
stdenv = pkgs.stdenv;
|
||||
in with pkgs; {
|
||||
myProject = stdenv.mkDerivation {
|
||||
name = "myProject";
|
||||
version = "1";
|
||||
src = if pkgs.lib.inNixShell then null else nix;
|
||||
|
||||
buildInputs = with rPackages; [
|
||||
R
|
||||
ggplot2
|
||||
knitr
|
||||
];
|
||||
};
|
||||
}
|
||||
```
|
||||
and then run `nix-shell .` to be dropped into a shell with those packages
|
||||
available.
|
||||
|
||||
## RStudio
|
||||
|
||||
RStudio uses a standard set of packages and ignores any custom R
|
||||
environments or installed packages you may have. To create a custom
|
||||
environment, see `rstudioWrapper`, which functions similarly to
|
||||
`rWrapper`:
|
||||
|
||||
```nix
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
|
||||
rstudioEnv = super.rstudioWrapper.override {
|
||||
packages = with self.rPackages; [
|
||||
dplyr
|
||||
ggplot2
|
||||
reshape2
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Then like above, `nix-env -f "<nixpkgs>" -iA rstudioEnv` will install
|
||||
this into your user profile.
|
||||
|
||||
Alternatively, you can create a self-contained `shell.nix` without the need to
|
||||
modify any configuration files:
|
||||
|
||||
```nix
|
||||
{ pkgs ? import <nixpkgs> {}
|
||||
}:
|
||||
|
||||
pkgs.rstudioWrapper.override {
|
||||
packages = with pkgs.rPackages; [ dplyr ggplot2 reshape2 ];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Executing `nix-shell` will then drop you into an environment equivalent to the
|
||||
one above. If you need additional packages just add them to the list and
|
||||
re-enter the shell.
|
||||
|
||||
## Updating the package set
|
||||
|
||||
```bash
|
||||
nix-shell generate-shell.nix
|
||||
|
||||
Rscript generate-r-packages.R cran > cran-packages.nix.new
|
||||
mv cran-packages.nix.new cran-packages.nix
|
||||
|
||||
Rscript generate-r-packages.R bioc > bioc-packages.nix.new
|
||||
mv bioc-packages.nix.new bioc-packages.nix
|
||||
```
|
||||
|
||||
`generate-r-packages.R <repo>` reads `<repo>-packages.nix`, therefor the renaming.
|
||||
|
||||
|
||||
## Testing if the Nix-expression could be evaluated
|
||||
|
||||
```bash
|
||||
nix-build test-evaluation.nix --dry-run
|
||||
```
|
||||
|
||||
If this exits fine, the expression is ok. If not, you have to edit `default.nix`
|
|
@ -16,6 +16,12 @@ cargo
|
|||
into the `environment.systemPackages` or bring them into
|
||||
scope with `nix-shell -p rustc cargo`.
|
||||
|
||||
> If you are using NixOS and you want to use rust without a nix expression you
|
||||
> probably want to add the following in your `configuration.nix` to build
|
||||
> crates with C dependencies.
|
||||
>
|
||||
> environment.systemPackages = [binutils gcc gnumake openssl pkgconfig]
|
||||
|
||||
For daily builds (beta and nightly) use either rustup from
|
||||
nixpkgs or use the [Rust nightlies
|
||||
overlay](#using-the-rust-nightlies-overlay).
|
||||
|
@ -76,7 +82,7 @@ an example for a minimal `hello` crate:
|
|||
Compiling hello v0.1.0 (file:///tmp/hello)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.20 secs
|
||||
$ carnix -o hello.nix --src ./. Cargo.lock --standalone
|
||||
$ nix-build hello.nix
|
||||
$ nix-build hello.nix -A hello_0_1_0
|
||||
|
||||
Now, the file produced by the call to `carnix`, called `hello.nix`, looks like:
|
||||
|
||||
|
@ -276,6 +282,84 @@ features, we would write:
|
|||
|
||||
Where `diesel.nix` is the file generated by Carnix, as explained above.
|
||||
|
||||
|
||||
## Setting Up `nix-shell`
|
||||
Oftentimes you want to develop code from within `nix-shell`. Unfortunately
|
||||
`buildRustCrate` does not support common `nix-shell` operations directly
|
||||
(see [this issue](https://github.com/NixOS/nixpkgs/issues/37945))
|
||||
so we will use `stdenv.mkDerivation` instead.
|
||||
|
||||
Using the example `hello` project above, we want to do the following:
|
||||
- Have access to `cargo` and `rustc`
|
||||
- Have the `openssl` library available to a crate through it's _normal_
|
||||
compilation mechanism (`pkg-config`).
|
||||
|
||||
A typical `shell.nix` might look like:
|
||||
|
||||
```
|
||||
with import <nixpkgs> {};
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "rust-env";
|
||||
buildInputs = [
|
||||
rustc cargo
|
||||
|
||||
# Example Additional Dependencies
|
||||
pkgconfig openssl
|
||||
];
|
||||
|
||||
# Set Environment Variables
|
||||
RUST_BACKTRACE = 1;
|
||||
}
|
||||
```
|
||||
|
||||
You should now be able to run the following:
|
||||
```
|
||||
$ nix-shell --pure
|
||||
$ cargo build
|
||||
$ cargo test
|
||||
```
|
||||
|
||||
### Controlling Rust Version Inside `nix-shell`
|
||||
To control your rust version (i.e. use nightly) from within `shell.nix` (or
|
||||
other nix expressions) you can use the following `shell.nix`
|
||||
|
||||
```
|
||||
# Latest Nightly
|
||||
with import <nixpkgs> {};
|
||||
let src = fetchFromGitHub {
|
||||
owner = "mozilla";
|
||||
repo = "nixpkgs-mozilla";
|
||||
# commit from: 2018-03-27
|
||||
rev = "2945b0b6b2fd19e7d23bac695afd65e320efcebe";
|
||||
sha256 = "034m1dryrzh2lmjvk3c0krgip652dql46w5yfwpvh7gavd3iypyw";
|
||||
};
|
||||
in
|
||||
with import "${src.out}/rust-overlay.nix" pkgs pkgs;
|
||||
stdenv.mkDerivation {
|
||||
name = "rust-env";
|
||||
buildInputs = [
|
||||
# Note: to use use stable, just replace `nightly` with `stable`
|
||||
latest.rustChannels.nightly.rust
|
||||
|
||||
# Add some extra dependencies from `pkgs`
|
||||
pkgconfig openssl
|
||||
];
|
||||
|
||||
# Set Environment Variables
|
||||
RUST_BACKTRACE = 1;
|
||||
}
|
||||
```
|
||||
|
||||
Now run:
|
||||
```
|
||||
$ rustc --version
|
||||
rustc 1.26.0-nightly (188e693b3 2018-03-26)
|
||||
```
|
||||
|
||||
To see that you are using nightly.
|
||||
|
||||
|
||||
## Using the Rust nightlies overlay
|
||||
|
||||
Mozilla provides an overlay for nixpkgs to bring a nightly version of Rust into scope.
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
</info>
|
||||
|
||||
<xi:include href="introduction.xml" />
|
||||
<xi:include href="introduction.chapter.xml" />
|
||||
<xi:include href="quick-start.xml" />
|
||||
<xi:include href="stdenv.xml" />
|
||||
<xi:include href="multiple-output.xml" />
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
.programlisting img {
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
.calloutlist img {
|
||||
width: 1.5em;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{ pkgs ? import ../. {} }:
|
||||
(import ./default.nix).overrideAttrs (x: {
|
||||
buildInputs = x.buildInputs ++ [ pkgs.xmloscopy ];
|
||||
})
|
|
@ -4,6 +4,8 @@ author: zimbatm
|
|||
date: 2017-10-30
|
||||
---
|
||||
|
||||
# mkShell
|
||||
|
||||
pkgs.mkShell is a special kind of derivation that is only useful when using
|
||||
it combined with nix-shell. It will in fact fail to instantiate when invoked
|
||||
with nix-build.
|
|
@ -29,8 +29,8 @@ h2 /* chapters, appendices, subtitle */
|
|||
}
|
||||
|
||||
/* Extra space between chapters, appendices. */
|
||||
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
|
||||
{
|
||||
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
|
||||
{
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ pre.screen, pre.programlisting
|
|||
padding: 3px 3px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
color: #600000;
|
||||
|
||||
background: #f4f4f8;
|
||||
font-family: monospace;
|
||||
border-radius: 0.4em;
|
||||
|
@ -118,7 +118,6 @@ div.example pre.programlisting
|
|||
margin: 0 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Notes, warnings etc:
|
||||
***************************************************************************/
|
||||
|
@ -172,7 +171,7 @@ div.navfooter *
|
|||
|
||||
|
||||
/***************************************************************************
|
||||
Links colors and highlighting:
|
||||
Links colors and highlighting:
|
||||
***************************************************************************/
|
||||
|
||||
a { text-decoration: none; }
|
||||
|
@ -209,7 +208,7 @@ tt, code
|
|||
.term
|
||||
{
|
||||
font-weight: bold;
|
||||
|
||||
|
||||
}
|
||||
|
||||
div.variablelist dd p, div.glosslist dd p
|
||||
|
@ -252,4 +251,4 @@ table
|
|||
div.affiliation
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ let
|
|||
|
||||
# packaging
|
||||
customisation = callLibs ./customisation.nix;
|
||||
maintainers = import ./maintainers-list.nix;
|
||||
maintainers = import ../maintainers/maintainer-list.nix;
|
||||
meta = callLibs ./meta.nix;
|
||||
sources = callLibs ./sources.nix;
|
||||
versions = callLibs ./versions.nix;
|
||||
|
|
|
@ -660,7 +660,7 @@ rec {
|
|||
doRename = { from, to, visible, warn, use }:
|
||||
let
|
||||
toOf = attrByPath to
|
||||
(abort "Renaming error: option `${showOption to}' does not exists.");
|
||||
(abort "Renaming error: option `${showOption to}' does not exist.");
|
||||
in
|
||||
{ config, options, ... }:
|
||||
{ options = setAttrByPath from (mkOption {
|
||||
|
|
|
@ -176,6 +176,11 @@
|
|||
github = "abigailbuccaneer";
|
||||
name = "Abigail Bunyan";
|
||||
};
|
||||
aborsu = {
|
||||
email = "a.borsu@gmail.com";
|
||||
github = "aborsu";
|
||||
name = "Augustin Borsu";
|
||||
};
|
||||
aboseley = {
|
||||
email = "adam.boseley@gmail.com";
|
||||
github = "aboseley";
|
||||
|
@ -314,6 +319,11 @@
|
|||
github = "amiloradovsky";
|
||||
name = "Andrew Miloradovsky";
|
||||
};
|
||||
aminechikhaoui = {
|
||||
email = "amine.chikhaoui91@gmail.com";
|
||||
github = "AmineChikhaoui";
|
||||
name = "Amine Chikhaoui";
|
||||
};
|
||||
amorsillo = {
|
||||
email = "andrew.morsillo@gmail.com";
|
||||
github = "AndrewMorsillo";
|
||||
|
@ -555,7 +565,6 @@
|
|||
};
|
||||
bjg = {
|
||||
email = "bjg@gnu.org";
|
||||
github = "civodul";
|
||||
name = "Brian Gough";
|
||||
};
|
||||
bjornfor = {
|
||||
|
@ -632,11 +641,6 @@
|
|||
github = "calbrecht";
|
||||
name = "Christian Albrecht";
|
||||
};
|
||||
calrama = {
|
||||
email = "moritz@ucworks.org";
|
||||
github = "MoritzMaxeiner";
|
||||
name = "Moritz Maxeiner";
|
||||
};
|
||||
calvertvl = {
|
||||
email = "calvertvl@gmail.com";
|
||||
github = "calvertvl";
|
||||
|
@ -1524,6 +1528,11 @@
|
|||
github = "hrdinka";
|
||||
name = "Christoph Hrdinka";
|
||||
};
|
||||
hschaeidt = {
|
||||
email = "he.schaeidt@gmail.com";
|
||||
github = "hschaeidt";
|
||||
name = "Hendrik Schaeidt";
|
||||
};
|
||||
htr = {
|
||||
email = "hugo@linux.com";
|
||||
github = "htr";
|
||||
|
@ -1663,7 +1672,7 @@
|
|||
name = "Johannes Frankenau";
|
||||
};
|
||||
jgeerds = {
|
||||
email = "jascha@jgeerds.name";
|
||||
email = "jascha@geerds.org";
|
||||
github = "jgeerds";
|
||||
name = "Jascha Geerds";
|
||||
};
|
||||
|
@ -2013,6 +2022,11 @@
|
|||
github = "lo1tuma";
|
||||
name = "Mathias Schreck";
|
||||
};
|
||||
lopsided98 = {
|
||||
email = "benwolsieffer@gmail.com";
|
||||
github = "lopsided98";
|
||||
name = "Ben Wolsieffer";
|
||||
};
|
||||
loskutov = {
|
||||
email = "ignat.loskutov@gmail.com";
|
||||
github = "loskutov";
|
||||
|
@ -3155,6 +3169,11 @@
|
|||
github = "sellout";
|
||||
name = "Greg Pfeil";
|
||||
};
|
||||
sengaya = {
|
||||
email = "tlo@sengaya.de";
|
||||
github = "sengaya";
|
||||
name = "Thilo Uttendorfer";
|
||||
};
|
||||
sepi = {
|
||||
email = "raffael@mancini.lu";
|
||||
github = "sepi";
|
|
@ -1,5 +1,5 @@
|
|||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i python3 -p 'python3.withPackages(ps: with ps; [ packaging requests toolz ])' -p git
|
||||
#! nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ packaging requests toolz ])" -p git
|
||||
|
||||
"""
|
||||
Update a Python package expression by passing in the `.nix` file, or the directory containing it.
|
||||
|
@ -358,4 +358,4 @@ def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
main()
|
||||
|
|
|
@ -282,8 +282,8 @@ options.mod = mkOption {
|
|||
option set (<xref linkend='ex-submodule-listof-definition' />).</para>
|
||||
|
||||
|
||||
<example xml:id='ex-submodule-listof-declaration'><title>Declaration of a list
|
||||
nof submodules</title>
|
||||
<example xml:id='ex-submodule-listof-declaration'><title>Declaration of a list
|
||||
of submodules</title>
|
||||
<screen>
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
|
|
|
@ -227,6 +227,18 @@ $ sudo groupdel nixbld</screen>
|
|||
line)</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<note><para>Support for <literal>NIXOS_LUSTRATE</literal> was added
|
||||
in NixOS 16.09. The act of "lustrating" refers to the
|
||||
wiping of the existing distribution. Creating
|
||||
<literal>/etc/NIXOS_LUSTRATE</literal> can also be used on
|
||||
NixOS to remove all mutable files from your root partition
|
||||
(anything that's not in <literal>/nix</literal> or
|
||||
<literal>/boot</literal> gets "lustrated" on the next
|
||||
boot.</para>
|
||||
<para>lustrate /ˈlʌstreɪt/ verb.</para>
|
||||
<para>purify by expiatory sacrifice, ceremonial washing, or
|
||||
some other ritual action.</para></note>
|
||||
|
||||
<para>Let's create the files:</para>
|
||||
|
||||
<screen>
|
||||
|
|
|
@ -322,6 +322,43 @@ following incompatible changes:</para>
|
|||
<link xlink:href="https://github.com/rvl/pump.io-nixos">external module</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The Prosody XMPP server has received a major update. The following modules were renamed:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>services.prosody.modules.httpserver</option> is now <option>services.prosody.modules.http_files</option>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>services.prosody.modules.console</option> is now <option>services.prosody.modules.admin_telnet</option>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Many new modules are now core modules, most notably <option>services.prosody.modules.carbons</option>
|
||||
and <option>services.prosody.modules.mam</option>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The better-performing <literal>libevent</literal> backend is now enabled by default.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literal>withCommunityModules</literal> now passes through the modules to <option>services.prosody.extraModules</option>.
|
||||
Use <literal>withOnlyInstalledCommunityModules</literal> for modules that should not be enabled directly, e.g <literal>lib_ldap</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
All prometheus exporter modules are now defined as submodules.
|
||||
The exporters are configured using <literal>services.prometheus.exporters</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
@ -381,15 +418,6 @@ following incompatible changes:</para>
|
|||
have been added to set up static routing.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The option <option>services.xserver.desktopManager.default</option> is now
|
||||
<literal>none</literal> by default. An assertion failure is thrown if WM's
|
||||
and DM's default are <literal>none</literal>.
|
||||
To explicitly run a plain X session without and DM or WM, the newly
|
||||
introduced option <option>services.xserver.plainX</option> must be set to true.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The option <option>services.logstash.listenAddress</option> is now <literal>127.0.0.1</literal> by default.
|
||||
|
|
|
@ -32,7 +32,6 @@ with lib;
|
|||
networkmanager-l2tp = pkgs.networkmanager-l2tp.override { withGnome = false; };
|
||||
networkmanager-openconnect = pkgs.networkmanager-openconnect.override { withGnome = false; };
|
||||
networkmanager-openvpn = pkgs.networkmanager-openvpn.override { withGnome = false; };
|
||||
networkmanager-pptp = pkgs.networkmanager-pptp.override { withGnome = false; };
|
||||
networkmanager-vpnc = pkgs.networkmanager-vpnc.override { withGnome = false; };
|
||||
networkmanager-iodine = pkgs.networkmanager-iodine.override { withGnome = false; };
|
||||
pinentry = pkgs.pinentry_ncurses;
|
||||
|
|
|
@ -35,6 +35,7 @@ let
|
|||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
apply = x: assert (builtins.stringLength x < 32 || abort "Username '${x}' is longer than 31 characters which is not allowed!"); x;
|
||||
description = ''
|
||||
The name of the user account. If undefined, the name of the
|
||||
attribute set will be used.
|
||||
|
@ -91,6 +92,7 @@ let
|
|||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
apply = x: assert (builtins.stringLength x < 17 || abort "Group name '${x}' is longer than 16 characters which is not allowed!"); x;
|
||||
default = "nogroup";
|
||||
description = "The user's primary group.";
|
||||
};
|
||||
|
|
|
@ -15,13 +15,19 @@ let
|
|||
|
||||
opengl = config.hardware.opengl;
|
||||
|
||||
kernel = pkgs.linux_4_9.override {
|
||||
extraConfig = ''
|
||||
KALLSYMS_ALL y
|
||||
'';
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
config = mkIf enabled {
|
||||
|
||||
nixpkgs.config.xorg.abiCompat = "1.18";
|
||||
nixpkgs.config.xorg.abiCompat = "1.19";
|
||||
|
||||
services.xserver.drivers = singleton
|
||||
{ name = "amdgpu"; modules = [ package ]; libPath = [ package ]; };
|
||||
|
@ -31,6 +37,9 @@ in
|
|||
|
||||
boot.extraModulePackages = [ package ];
|
||||
|
||||
boot.kernelPackages =
|
||||
pkgs.recurseIntoAttrs (pkgs.linuxPackagesFor kernel);
|
||||
|
||||
boot.blacklistedKernelModules = [ "radeon" ];
|
||||
|
||||
hardware.firmware = [ package ];
|
||||
|
@ -38,10 +47,15 @@ in
|
|||
system.activationScripts.setup-amdgpu-pro = ''
|
||||
mkdir -p /run/lib
|
||||
ln -sfn ${package}/lib ${package.libCompatDir}
|
||||
ln -sfn ${package} /run/amdgpu-pro
|
||||
'' + optionalString opengl.driSupport32Bit ''
|
||||
ln -sfn ${package32}/lib ${package32.libCompatDir}
|
||||
'';
|
||||
|
||||
system.requiredKernelConfig = with config.lib.kernelConfig; [
|
||||
(isYes "KALLSYMS_ALL")
|
||||
];
|
||||
|
||||
environment.etc = {
|
||||
"amd/amdrc".source = package + "/etc/amd/amdrc";
|
||||
"amd/amdapfxx.blb".source = package + "/etc/amd/amdapfxx.blb";
|
||||
|
|
|
@ -16,8 +16,6 @@ let
|
|||
kernelPackages.nvidia_x11
|
||||
else if elem "nvidiaBeta" drivers then
|
||||
kernelPackages.nvidia_x11_beta
|
||||
else if elem "nvidiaLegacy173" drivers then
|
||||
kernelPackages.nvidia_x11_legacy173
|
||||
else if elem "nvidiaLegacy304" drivers then
|
||||
kernelPackages.nvidia_x11_legacy304
|
||||
else if elem "nvidiaLegacy340" drivers then
|
||||
|
|
|
@ -21,9 +21,6 @@ in
|
|||
"it cannot be cross compiled";
|
||||
};
|
||||
|
||||
# Needed by RPi firmware
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
|
||||
|
|
|
@ -21,9 +21,6 @@ in
|
|||
"it cannot be cross compiled";
|
||||
};
|
||||
|
||||
# Needed by RPi firmware
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
|
||||
|
|
|
@ -21,9 +21,6 @@ in
|
|||
"it cannot be cross compiled";
|
||||
};
|
||||
|
||||
# Needed by RPi firmware
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
|
||||
|
|
|
@ -20,6 +20,20 @@ let
|
|||
in
|
||||
{
|
||||
options.sdImage = {
|
||||
imageName = mkOption {
|
||||
default = "${config.sdImage.imageBaseName}-${config.system.nixos.label}-${pkgs.stdenv.system}.img";
|
||||
description = ''
|
||||
Name of the generated image file.
|
||||
'';
|
||||
};
|
||||
|
||||
imageBaseName = mkOption {
|
||||
default = "nixos-sd-image";
|
||||
description = ''
|
||||
Prefix of the name of the generated image file.
|
||||
'';
|
||||
};
|
||||
|
||||
storePaths = mkOption {
|
||||
type = with types; listOf package;
|
||||
example = literalExample "[ pkgs.stdenv ]";
|
||||
|
@ -61,19 +75,25 @@ in
|
|||
sdImage.storePaths = [ config.system.build.toplevel ];
|
||||
|
||||
system.build.sdImage = pkgs.stdenv.mkDerivation {
|
||||
name = "sd-image-${pkgs.stdenv.system}.img";
|
||||
name = config.sdImage.imageName;
|
||||
|
||||
buildInputs = with pkgs; [ dosfstools e2fsprogs mtools libfaketime utillinux ];
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out/nix-support $out/sd-image
|
||||
export img=$out/sd-image/${config.sdImage.imageName}
|
||||
|
||||
echo "${pkgs.stdenv.system}" > $out/nix-support/system
|
||||
echo "file sd-image $img" >> $out/nix-support/hydra-build-products
|
||||
|
||||
# Create the image file sized to fit /boot and /, plus 20M of slack
|
||||
rootSizeBlocks=$(du -B 512 --apparent-size ${rootfsImage} | awk '{ print $1 }')
|
||||
bootSizeBlocks=$((${toString config.sdImage.bootSize} * 1024 * 1024 / 512))
|
||||
imageSize=$((rootSizeBlocks * 512 + bootSizeBlocks * 512 + 20 * 1024 * 1024))
|
||||
truncate -s $imageSize $out
|
||||
truncate -s $imageSize $img
|
||||
|
||||
# type=b is 'W95 FAT32', type=83 is 'Linux'.
|
||||
sfdisk $out <<EOF
|
||||
sfdisk $img <<EOF
|
||||
label: dos
|
||||
label-id: 0x2178694e
|
||||
|
||||
|
@ -82,11 +102,11 @@ in
|
|||
EOF
|
||||
|
||||
# Copy the rootfs into the SD image
|
||||
eval $(partx $out -o START,SECTORS --nr 2 --pairs)
|
||||
dd conv=notrunc if=${rootfsImage} of=$out seek=$START count=$SECTORS
|
||||
eval $(partx $img -o START,SECTORS --nr 2 --pairs)
|
||||
dd conv=notrunc if=${rootfsImage} of=$img seek=$START count=$SECTORS
|
||||
|
||||
# Create a FAT32 /boot partition of suitable size into bootpart.img
|
||||
eval $(partx $out -o START,SECTORS --nr 1 --pairs)
|
||||
eval $(partx $img -o START,SECTORS --nr 1 --pairs)
|
||||
truncate -s $((SECTORS * 512)) bootpart.img
|
||||
faketime "1970-01-01 00:00:00" mkfs.vfat -i 0x2178694e -n NIXOS_BOOT bootpart.img
|
||||
|
||||
|
@ -96,7 +116,7 @@ in
|
|||
|
||||
# Copy the populated /boot into the SD image
|
||||
(cd boot; mcopy -bpsvm -i ../bootpart.img ./* ::)
|
||||
dd conv=notrunc if=bootpart.img of=$out seek=$START count=$SECTORS
|
||||
dd conv=notrunc if=bootpart.img of=$img seek=$START count=$SECTORS
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -382,6 +382,6 @@ fi
|
|||
if [ "$action" = build-vm ]; then
|
||||
cat >&2 <<EOF
|
||||
|
||||
Done. The virtual machine can be started by running $(echo $pathToConfig/bin/run-*-vm).
|
||||
Done. The virtual machine can be started by running $(echo $pathToConfig/bin/run-*-vm)
|
||||
EOF
|
||||
fi
|
||||
|
|
|
@ -19,4 +19,6 @@ with lib;
|
|||
# Add some more video drivers to give X11 a shot at working in
|
||||
# VMware and QEMU.
|
||||
services.xserver.videoDrivers = mkOverride 40 [ "virtualbox" "vmware" "cirrus" "vesa" "modesetting" ];
|
||||
|
||||
powerManagement.enable = false;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,21 @@ in
|
|||
|
||||
options.system = {
|
||||
|
||||
# XXX: Reintroduce old options to make nixops before 1.6 able to evaluate configurations
|
||||
# XXX: Remove after nixops has been bumped to a compatible version
|
||||
nixosVersion = mkOption {
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
type = types.str;
|
||||
default = config.system.nixos.version;
|
||||
};
|
||||
nixosVersionSuffix = mkOption {
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
type = types.str;
|
||||
default = config.system.nixos.versionSuffix;
|
||||
};
|
||||
|
||||
nixos.version = mkOption {
|
||||
internal = true;
|
||||
type = types.str;
|
||||
|
@ -70,7 +85,7 @@ in
|
|||
defaultChannel = mkOption {
|
||||
internal = true;
|
||||
type = types.str;
|
||||
default = https://nixos.org/channels/nixos-unstable;
|
||||
default = https://nixos.org/channels/nixos-18.03;
|
||||
description = "Default NixOS channel to which the root user is subscribed.";
|
||||
};
|
||||
|
||||
|
|
|
@ -159,6 +159,7 @@
|
|||
./services/audio/ympd.nix
|
||||
./services/backup/almir.nix
|
||||
./services/backup/bacula.nix
|
||||
./services/backup/borgbackup.nix
|
||||
./services/backup/crashplan.nix
|
||||
./services/backup/crashplan-small-business.nix
|
||||
./services/backup/mysql-backup.nix
|
||||
|
@ -322,7 +323,7 @@
|
|||
./services/misc/geoip-updater.nix
|
||||
./services/misc/gitea.nix
|
||||
#./services/misc/gitit.nix
|
||||
./services/misc/gitlab.nix
|
||||
#./services/misc/gitlab.nix
|
||||
./services/misc/gitolite.nix
|
||||
./services/misc/gogs.nix
|
||||
./services/misc/gollum.nix
|
||||
|
@ -396,16 +397,7 @@
|
|||
./services/monitoring/osquery.nix
|
||||
./services/monitoring/prometheus/default.nix
|
||||
./services/monitoring/prometheus/alertmanager.nix
|
||||
./services/monitoring/prometheus/blackbox-exporter.nix
|
||||
./services/monitoring/prometheus/collectd-exporter.nix
|
||||
./services/monitoring/prometheus/fritzbox-exporter.nix
|
||||
./services/monitoring/prometheus/json-exporter.nix
|
||||
./services/monitoring/prometheus/minio-exporter.nix
|
||||
./services/monitoring/prometheus/nginx-exporter.nix
|
||||
./services/monitoring/prometheus/node-exporter.nix
|
||||
./services/monitoring/prometheus/snmp-exporter.nix
|
||||
./services/monitoring/prometheus/unifi-exporter.nix
|
||||
./services/monitoring/prometheus/varnish-exporter.nix
|
||||
./services/monitoring/prometheus/exporters.nix
|
||||
./services/monitoring/riemann.nix
|
||||
./services/monitoring/riemann-dash.nix
|
||||
./services/monitoring/riemann-tools.nix
|
||||
|
|
|
@ -10,4 +10,10 @@
|
|||
password = "demo";
|
||||
uid = 1000;
|
||||
};
|
||||
|
||||
services.xserver.displayManager.sddm.autoLogin = {
|
||||
enable = true;
|
||||
relogin = true;
|
||||
user = "demo";
|
||||
};
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ in
|
|||
programs.bash = {
|
||||
|
||||
shellInit = ''
|
||||
. ${config.system.build.setEnvironment}
|
||||
${config.system.build.setEnvironment.text}
|
||||
|
||||
${cfge.shellInit}
|
||||
'';
|
||||
|
|
|
@ -108,7 +108,7 @@ in
|
|||
if [ -n "$__ETC_ZSHENV_SOURCED" ]; then return; fi
|
||||
export __ETC_ZSHENV_SOURCED=1
|
||||
|
||||
. ${config.system.build.setEnvironment}
|
||||
${config.system.build.setEnvironment.text}
|
||||
|
||||
${cfge.shellInit}
|
||||
|
||||
|
|
|
@ -196,9 +196,9 @@ with lib;
|
|||
(mkRenamedOptionModule [ "virtualization" "growPartition" ] [ "boot" "growPartition" ])
|
||||
|
||||
# misc/version.nix
|
||||
(mkRenamedOptionModule [ "config" "system" "nixosVersion" ] [ "config" "system" "nixos" "version" ])
|
||||
#(mkRenamedOptionModule [ "config" "system" "nixosVersion" ] [ "config" "system" "nixos" "version" ])
|
||||
(mkRenamedOptionModule [ "config" "system" "nixosRelease" ] [ "config" "system" "nixos" "release" ])
|
||||
(mkRenamedOptionModule [ "config" "system" "nixosVersionSuffix" ] [ "config" "system" "nixos" "versionSuffix" ])
|
||||
#(mkRenamedOptionModule [ "config" "system" "nixosVersionSuffix" ] [ "config" "system" "nixos" "versionSuffix" ])
|
||||
(mkRenamedOptionModule [ "config" "system" "nixosRevision" ] [ "config" "system" "nixos" "revision" ])
|
||||
(mkRenamedOptionModule [ "config" "system" "nixosCodeName" ] [ "config" "system" "nixos" "codeName" ])
|
||||
(mkRenamedOptionModule [ "config" "system" "nixosLabel" ] [ "config" "system" "nixos" "label" ])
|
||||
|
@ -240,5 +240,11 @@ with lib;
|
|||
|
||||
# Xen
|
||||
(mkRenamedOptionModule [ "virtualisation" "xen" "qemu-package" ] [ "virtualisation" "xen" "package-qemu" ])
|
||||
];
|
||||
] ++ (flip map [ "blackboxExporter" "collectdExporter" "fritzboxExporter"
|
||||
"jsonExporter" "minioExporter" "nginxExporter" "nodeExporter"
|
||||
"snmpExporter" "unifiExporter" "varnishExporter" ]
|
||||
(opt: mkRemovedOptionModule [ "services" "prometheus" "${opt}" ] ''
|
||||
The prometheus exporters are now configured using `services.prometheus.exporters'.
|
||||
See the 18.03 release notes for more information.
|
||||
'' ));
|
||||
}
|
||||
|
|
|
@ -47,8 +47,8 @@ in
|
|||
default = true;
|
||||
description =
|
||||
''
|
||||
Whether users of the <code>wheel</code> group can execute
|
||||
commands as super user without entering a password.
|
||||
Whether users of the <code>wheel</code> group must
|
||||
provide a password to run commands as super user via <command>sudo</command>.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,580 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
isLocalPath = x:
|
||||
builtins.substring 0 1 x == "/" # absolute path
|
||||
|| builtins.substring 0 1 x == "." # relative path
|
||||
|| builtins.match "[.*:.*]" == null; # not machine:path
|
||||
|
||||
mkExcludeFile = cfg:
|
||||
# Write each exclude pattern to a new line
|
||||
pkgs.writeText "excludefile" (concatStringsSep "\n" cfg.exclude);
|
||||
|
||||
mkKeepArgs = cfg:
|
||||
# If cfg.prune.keep e.g. has a yearly attribute,
|
||||
# its content is passed on as --keep-yearly
|
||||
concatStringsSep " "
|
||||
(mapAttrsToList (x: y: "--keep-${x}=${toString y}") cfg.prune.keep);
|
||||
|
||||
mkBackupScript = cfg: ''
|
||||
on_exit()
|
||||
{
|
||||
exitStatus=$?
|
||||
# Reset the EXIT handler, or else we're called again on 'exit' below
|
||||
trap - EXIT
|
||||
${cfg.postHook}
|
||||
exit $exitStatus
|
||||
}
|
||||
trap 'on_exit' INT TERM QUIT EXIT
|
||||
|
||||
archiveName="${cfg.archiveBaseName}-$(date ${cfg.dateFormat})"
|
||||
archiveSuffix="${optionalString cfg.appendFailedSuffix ".failed"}"
|
||||
${cfg.preHook}
|
||||
'' + optionalString cfg.doInit ''
|
||||
# Run borg init if the repo doesn't exist yet
|
||||
if ! borg list > /dev/null; then
|
||||
borg init \
|
||||
--encryption ${cfg.encryption.mode} \
|
||||
$extraInitArgs
|
||||
${cfg.postInit}
|
||||
fi
|
||||
'' + ''
|
||||
borg create \
|
||||
--compression ${cfg.compression} \
|
||||
--exclude-from ${mkExcludeFile cfg} \
|
||||
$extraCreateArgs \
|
||||
"::$archiveName$archiveSuffix" \
|
||||
${escapeShellArgs cfg.paths}
|
||||
'' + optionalString cfg.appendFailedSuffix ''
|
||||
borg rename "::$archiveName$archiveSuffix" "$archiveName"
|
||||
'' + ''
|
||||
${cfg.postCreate}
|
||||
'' + optionalString (cfg.prune.keep != { }) ''
|
||||
borg prune \
|
||||
${mkKeepArgs cfg} \
|
||||
--prefix ${escapeShellArg cfg.prune.prefix} \
|
||||
$extraPruneArgs
|
||||
${cfg.postPrune}
|
||||
'';
|
||||
|
||||
mkPassEnv = cfg: with cfg.encryption;
|
||||
if passCommand != null then
|
||||
{ BORG_PASSCOMMAND = passCommand; }
|
||||
else if passphrase != null then
|
||||
{ BORG_PASSPHRASE = passphrase; }
|
||||
else { };
|
||||
|
||||
mkBackupService = name: cfg:
|
||||
let
|
||||
userHome = config.users.users.${cfg.user}.home;
|
||||
in nameValuePair "borgbackup-job-${name}" {
|
||||
description = "BorgBackup job ${name}";
|
||||
path = with pkgs; [
|
||||
borgbackup openssh
|
||||
];
|
||||
script = mkBackupScript cfg;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
# Only run when no other process is using CPU or disk
|
||||
CPUSchedulingPolicy = "idle";
|
||||
IOSchedulingClass = "idle";
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths =
|
||||
[ "${userHome}/.config/borg" "${userHome}/.cache/borg" ]
|
||||
# Borg needs write access to repo if it is not remote
|
||||
++ optional (isLocalPath cfg.repo) cfg.repo;
|
||||
PrivateTmp = true;
|
||||
};
|
||||
environment = {
|
||||
BORG_REPO = cfg.repo;
|
||||
inherit (cfg) extraInitArgs extraCreateArgs extraPruneArgs;
|
||||
} // (mkPassEnv cfg) // cfg.environment;
|
||||
inherit (cfg) startAt;
|
||||
};
|
||||
|
||||
# Paths listed in ReadWritePaths must exist before service is started
|
||||
mkActivationScript = name: cfg:
|
||||
let
|
||||
install = "install -o ${cfg.user} -g ${cfg.group}";
|
||||
in
|
||||
nameValuePair "borgbackup-job-${name}" (stringAfter [ "users" ] (''
|
||||
# Eensure that the home directory already exists
|
||||
# We can't assert createHome == true because that's not the case for root
|
||||
cd "${config.users.users.${cfg.user}.home}"
|
||||
${install} -d .config/borg
|
||||
${install} -d .cache/borg
|
||||
'' + optionalString (isLocalPath cfg.repo) ''
|
||||
${install} -d ${escapeShellArg cfg.repo}
|
||||
''));
|
||||
|
||||
mkPassAssertion = name: cfg: {
|
||||
assertion = with cfg.encryption;
|
||||
mode != "none" -> passCommand != null || passphrase != null;
|
||||
message =
|
||||
"passCommand or passphrase has to be specified because"
|
||||
+ '' borgbackup.jobs.${name}.encryption != "none"'';
|
||||
};
|
||||
|
||||
mkRepoService = name: cfg:
|
||||
nameValuePair "borgbackup-repo-${name}" {
|
||||
description = "Create BorgBackup repository ${name} directory";
|
||||
script = ''
|
||||
mkdir -p ${escapeShellArg cfg.path}
|
||||
chown ${cfg.user}:${cfg.group} ${escapeShellArg cfg.path}
|
||||
'';
|
||||
serviceConfig = {
|
||||
# The service's only task is to ensure that the specified path exists
|
||||
Type = "oneshot";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
mkAuthorizedKey = cfg: appendOnly: key:
|
||||
let
|
||||
# Because of the following line, clients do not need to specify an absolute repo path
|
||||
cdCommand = "cd ${escapeShellArg cfg.path}";
|
||||
restrictedArg = "--restrict-to-${if cfg.allowSubRepos then "path" else "repository"} .";
|
||||
appendOnlyArg = optionalString appendOnly "--append-only";
|
||||
quotaArg = optionalString (cfg.quota != null) "--storage-quota ${cfg.quota}";
|
||||
serveCommand = "borg serve ${restrictedArg} ${appendOnlyArg} ${quotaArg}";
|
||||
in
|
||||
''command="${cdCommand} && ${serveCommand}",restrict ${key}'';
|
||||
|
||||
mkUsersConfig = name: cfg: {
|
||||
users.${cfg.user} = {
|
||||
openssh.authorizedKeys.keys =
|
||||
(map (mkAuthorizedKey cfg false) cfg.authorizedKeys
|
||||
++ map (mkAuthorizedKey cfg true) cfg.authorizedKeysAppendOnly);
|
||||
useDefaultShell = true;
|
||||
};
|
||||
groups.${cfg.group} = { };
|
||||
};
|
||||
|
||||
mkKeysAssertion = name: cfg: {
|
||||
assertion = cfg.authorizedKeys != [ ] || cfg.authorizedKeysAppendOnly != [ ];
|
||||
message =
|
||||
"borgbackup.repos.${name} does not make sense"
|
||||
+ " without at least one public key";
|
||||
};
|
||||
|
||||
in {
|
||||
meta.maintainers = with maintainers; [ dotlambda ];
|
||||
|
||||
###### interface
|
||||
|
||||
options.services.borgbackup.jobs = mkOption {
|
||||
description = "Deduplicating backups using BorgBackup.";
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
rootBackup = {
|
||||
paths = "/";
|
||||
exclude = [ "/nix" ];
|
||||
repo = "/path/to/local/repo";
|
||||
encryption = {
|
||||
mode = "repokey";
|
||||
passphrase = "secret";
|
||||
};
|
||||
compression = "auto,lzma";
|
||||
startAt = "weekly";
|
||||
};
|
||||
}
|
||||
'';
|
||||
type = types.attrsOf (types.submodule (let globalConfig = config; in
|
||||
{ name, config, ... }: {
|
||||
options = {
|
||||
|
||||
paths = mkOption {
|
||||
type = with types; either path (nonEmptyListOf path);
|
||||
description = "Path(s) to back up.";
|
||||
example = "/home/user";
|
||||
apply = x: if isList x then x else [ x ];
|
||||
};
|
||||
|
||||
repo = mkOption {
|
||||
type = types.str;
|
||||
description = "Remote or local repository to back up to.";
|
||||
example = "user@machine:/path/to/repo";
|
||||
};
|
||||
|
||||
archiveBaseName = mkOption {
|
||||
type = types.strMatching "[^/{}]+";
|
||||
default = "${globalConfig.networking.hostName}-${name}";
|
||||
defaultText = "\${config.networking.hostName}-<name>";
|
||||
description = ''
|
||||
How to name the created archives. A timestamp, whose format is
|
||||
determined by <option>dateFormat</option>, will be appended. The full
|
||||
name can be modified at runtime (<literal>$archiveName</literal>).
|
||||
Placeholders like <literal>{hostname}</literal> must not be used.
|
||||
'';
|
||||
};
|
||||
|
||||
dateFormat = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Arguments passed to <command>date</command>
|
||||
to create a timestamp suffix for the archive name.
|
||||
'';
|
||||
default = "+%Y-%m-%dT%H:%M:%S";
|
||||
example = "-u +%s";
|
||||
};
|
||||
|
||||
startAt = mkOption {
|
||||
type = with types; either str (listOf str);
|
||||
default = "daily";
|
||||
description = ''
|
||||
When or how often the backup should run.
|
||||
Must be in the format described in
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle>
|
||||
<manvolnum>7</manvolnum></citerefentry>.
|
||||
If you do not want the backup to start
|
||||
automatically, use <literal>[ ]</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The user <command>borg</command> is run as.
|
||||
User or group need read permission
|
||||
for the specified <option>paths</option>.
|
||||
'';
|
||||
default = "root";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The group borg is run as. User or group needs read permission
|
||||
for the specified <option>paths</option>.
|
||||
'';
|
||||
default = "root";
|
||||
};
|
||||
|
||||
encryption.mode = mkOption {
|
||||
type = types.enum [
|
||||
"repokey" "keyfile"
|
||||
"repokey-blake2" "keyfile-blake2"
|
||||
"authenticated" "authenticated-blake2"
|
||||
"none"
|
||||
];
|
||||
description = ''
|
||||
Encryption mode to use. Setting a mode
|
||||
other than <literal>"none"</literal> requires
|
||||
you to specify a <option>passCommand</option>
|
||||
or a <option>passphrase</option>.
|
||||
'';
|
||||
};
|
||||
|
||||
encryption.passCommand = mkOption {
|
||||
type = with types; nullOr str;
|
||||
description = ''
|
||||
A command which prints the passphrase to stdout.
|
||||
Mutually exclusive with <option>passphrase</option>.
|
||||
'';
|
||||
default = null;
|
||||
example = "cat /path/to/passphrase_file";
|
||||
};
|
||||
|
||||
encryption.passphrase = mkOption {
|
||||
type = with types; nullOr str;
|
||||
description = ''
|
||||
The passphrase the backups are encrypted with.
|
||||
Mutually exclusive with <option>passCommand</option>.
|
||||
If you do not want the passphrase to be stored in the
|
||||
world-readable Nix store, use <option>passCommand</option>.
|
||||
'';
|
||||
default = null;
|
||||
};
|
||||
|
||||
compression = mkOption {
|
||||
# "auto" is optional,
|
||||
# compression mode must be given,
|
||||
# compression level is optional
|
||||
type = types.strMatching "none|(auto,)?(lz4|zstd|zlib|lzma)(,[[:digit:]]{1,2})?";
|
||||
description = ''
|
||||
Compression method to use. Refer to
|
||||
<command>borg help compression</command>
|
||||
for all available options.
|
||||
'';
|
||||
default = "lz4";
|
||||
example = "auto,lzma";
|
||||
};
|
||||
|
||||
exclude = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = ''
|
||||
Exclude paths matching any of the given patterns. See
|
||||
<command>borg help patterns</command> for pattern syntax.
|
||||
'';
|
||||
default = [ ];
|
||||
example = [
|
||||
"/home/*/.cache"
|
||||
"/nix"
|
||||
];
|
||||
};
|
||||
|
||||
doInit = mkOption {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Run <command>borg init</command> if the
|
||||
specified <option>repo</option> does not exist.
|
||||
You should set this to <literal>false</literal>
|
||||
if the repository is located on an external drive
|
||||
that might not always be mounted.
|
||||
'';
|
||||
default = true;
|
||||
};
|
||||
|
||||
appendFailedSuffix = mkOption {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Append a <literal>.failed</literal> suffix
|
||||
to the archive name, which is only removed if
|
||||
<command>borg create</command> has a zero exit status.
|
||||
'';
|
||||
default = true;
|
||||
};
|
||||
|
||||
prune.keep = mkOption {
|
||||
# Specifying e.g. `prune.keep.yearly = -1`
|
||||
# means there is no limit of yearly archives to keep
|
||||
# The regex is for use with e.g. --keep-within 1y
|
||||
type = with types; attrsOf (either int (strMatching "[[:digit:]]+[Hdwmy]"));
|
||||
description = ''
|
||||
Prune a repository by deleting all archives not matching any of the
|
||||
specified retention options. See <command>borg help prune</command>
|
||||
for the available options.
|
||||
'';
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
within = "1d"; # Keep all archives from the last day
|
||||
daily = 7;
|
||||
weekly = 4;
|
||||
monthly = -1; # Keep at least one archive for each month
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
prune.prefix = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Only consider archive names starting with this prefix for pruning.
|
||||
By default, only archives created by this job are considered.
|
||||
Use <literal>""</literal> to consider all archives.
|
||||
'';
|
||||
default = config.archiveBaseName;
|
||||
defaultText = "\${archiveBaseName}";
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
description = ''
|
||||
Environment variables passed to the backup script.
|
||||
You can for example specify which SSH key to use.
|
||||
'';
|
||||
default = { };
|
||||
example = { BORG_RSH = "ssh -i /path/to/key"; };
|
||||
};
|
||||
|
||||
preHook = mkOption {
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Shell commands to run before the backup.
|
||||
This can for example be used to mount file systems.
|
||||
'';
|
||||
default = "";
|
||||
example = ''
|
||||
# To add excluded paths at runtime
|
||||
extraCreateArgs="$extraCreateArgs --exclude /some/path"
|
||||
'';
|
||||
};
|
||||
|
||||
postInit = mkOption {
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Shell commands to run after <command>borg init</command>.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
postCreate = mkOption {
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Shell commands to run after <command>borg create</command>. The name
|
||||
of the created archive is stored in <literal>$archiveName</literal>.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
postPrune = mkOption {
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Shell commands to run after <command>borg prune</command>.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
postHook = mkOption {
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Shell commands to run just before exit. They are executed
|
||||
even if a previous command exits with a non-zero exit code.
|
||||
The latter is available as <literal>$exitStatus</literal>.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
extraInitArgs = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Additional arguments for <command>borg init</command>.
|
||||
Can also be set at runtime using <literal>$extraInitArgs</literal>.
|
||||
'';
|
||||
default = "";
|
||||
example = "--append-only";
|
||||
};
|
||||
|
||||
extraCreateArgs = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Additional arguments for <command>borg create</command>.
|
||||
Can also be set at runtime using <literal>$extraCreateArgs</literal>.
|
||||
'';
|
||||
default = "";
|
||||
example = "--stats --checkpoint-interval 600";
|
||||
};
|
||||
|
||||
extraPruneArgs = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Additional arguments for <command>borg prune</command>.
|
||||
Can also be set at runtime using <literal>$extraPruneArgs</literal>.
|
||||
'';
|
||||
default = "";
|
||||
example = "--save-space";
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
));
|
||||
};
|
||||
|
||||
options.services.borgbackup.repos = mkOption {
|
||||
description = ''
|
||||
Serve BorgBackup repositories to given public SSH keys,
|
||||
restricting their access to the repository only.
|
||||
Also, clients do not need to specify the absolute path when accessing the repository,
|
||||
i.e. <literal>user@machine:.</literal> is enough. (Note colon and dot.)
|
||||
'';
|
||||
default = { };
|
||||
type = types.attrsOf (types.submodule (
|
||||
{ name, config, ... }: {
|
||||
options = {
|
||||
|
||||
path = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Where to store the backups. Note that the directory
|
||||
is created automatically, with correct permissions.
|
||||
'';
|
||||
default = "/var/lib/borgbackup";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The user <command>borg serve</command> is run as.
|
||||
User or group needs write permission
|
||||
for the specified <option>path</option>.
|
||||
'';
|
||||
default = "borg";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The group <command>borg serve</command> is run as.
|
||||
User or group needs write permission
|
||||
for the specified <option>path</option>.
|
||||
'';
|
||||
default = "borg";
|
||||
};
|
||||
|
||||
authorizedKeys = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = ''
|
||||
Public SSH keys that are given full write access to this repository.
|
||||
You should use a different SSH key for each repository you write to, because
|
||||
the specified keys are restricted to running <command>borg serve</command>
|
||||
and can only access this single repository.
|
||||
'';
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
authorizedKeysAppendOnly = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = ''
|
||||
Public SSH keys that can only be used to append new data (archives) to the repository.
|
||||
Note that archives can still be marked as deleted and are subsequently removed from disk
|
||||
upon accessing the repo with full write access, e.g. when pruning.
|
||||
'';
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
allowSubRepos = mkOption {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Allow clients to create repositories in subdirectories of the
|
||||
specified <option>path</option>. These can be accessed using
|
||||
<literal>user@machine:path/to/subrepo</literal>. Note that a
|
||||
<option>quota</option> applies to repositories independently.
|
||||
Therefore, if this is enabled, clients can create multiple
|
||||
repositories and upload an arbitrary amount of data.
|
||||
'';
|
||||
default = false;
|
||||
};
|
||||
|
||||
quota = mkOption {
|
||||
# See the definition of parse_file_size() in src/borg/helpers/parseformat.py
|
||||
type = with types; nullOr (strMatching "[[:digit:].]+[KMGTP]?");
|
||||
description = ''
|
||||
Storage quota for the repository. This quota is ensured for all
|
||||
sub-repositories if <option>allowSubRepos</option> is enabled
|
||||
but not for the overall storage space used.
|
||||
'';
|
||||
default = null;
|
||||
example = "100G";
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
));
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf (with config.services.borgbackup; jobs != { } || repos != { })
|
||||
(with config.services.borgbackup; {
|
||||
assertions =
|
||||
mapAttrsToList mkPassAssertion jobs
|
||||
++ mapAttrsToList mkKeysAssertion repos;
|
||||
|
||||
system.activationScripts = mapAttrs' mkActivationScript jobs;
|
||||
|
||||
systemd.services =
|
||||
# A job named "foo" is mapped to systemd.services.borgbackup-job-foo
|
||||
mapAttrs' mkBackupService jobs
|
||||
# A repo named "foo" is mapped to systemd.services.borgbackup-repo-foo
|
||||
// mapAttrs' mkRepoService repos;
|
||||
|
||||
users = mkMerge (mapAttrsToList mkUsersConfig repos);
|
||||
|
||||
environment.systemPackages = with pkgs; [ borgbackup ];
|
||||
});
|
||||
}
|
|
@ -386,7 +386,7 @@ in
|
|||
echo Resetting znapzend zetups
|
||||
${pkgs.znapzend}/bin/znapzendzetup list \
|
||||
| grep -oP '(?<=\*\*\* backup plan: ).*(?= \*\*\*)' \
|
||||
| xargs ${pkgs.znapzend}/bin/znapzendzetup delete
|
||||
| xargs -I{} ${pkgs.znapzend}/bin/znapzendzetup delete "{}"
|
||||
'' + concatStringsSep "\n" (mapAttrsToList (dataset: config: ''
|
||||
echo Importing znapzend zetup ${config} for dataset ${dataset}
|
||||
${pkgs.znapzend}/bin/znapzendzetup import --write ${dataset} ${config}
|
||||
|
|
|
@ -145,6 +145,11 @@ in {
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# server references the dejavu fonts
|
||||
environment.systemPackages = [
|
||||
pkgs.dejavu_fonts
|
||||
];
|
||||
|
||||
users.extraGroups = optional (cfg.group == "jenkins") {
|
||||
name = "jenkins";
|
||||
gid = config.ids.gids.jenkins;
|
||||
|
@ -200,10 +205,12 @@ in {
|
|||
${replacePlugins}
|
||||
'';
|
||||
|
||||
# For reference: https://wiki.jenkins.io/display/JENKINS/JenkinsLinuxStartupScript
|
||||
script = ''
|
||||
${pkgs.jdk}/bin/java ${concatStringsSep " " cfg.extraJavaOptions} -jar ${cfg.package}/webapps/jenkins.war --httpListenAddress=${cfg.listenAddress} \
|
||||
--httpPort=${toString cfg.port} \
|
||||
--prefix=${cfg.prefix} \
|
||||
-Djava.awt.headless=true \
|
||||
${concatStringsSep " " cfg.extraOptions}
|
||||
'';
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ in
|
|||
JAVA_HOME = jre;
|
||||
GRAYLOG_CONF = "${confFile}";
|
||||
};
|
||||
path = [ pkgs.openjdk8 pkgs.which pkgs.procps ];
|
||||
path = [ pkgs.jre_headless pkgs.which pkgs.procps ];
|
||||
preStart = ''
|
||||
mkdir -p /var/lib/graylog -m 755
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ let
|
|||
|
||||
''
|
||||
default_internal_user = ${cfg.user}
|
||||
default_internal_group = ${cfg.group}
|
||||
${optionalString (cfg.mailUser != null) "mail_uid = ${cfg.mailUser}"}
|
||||
${optionalString (cfg.mailGroup != null) "mail_gid = ${cfg.mailGroup}"}
|
||||
|
||||
|
|
|
@ -1,205 +1,69 @@
|
|||
# The following was taken from github.com/crohr/syslogger and is BSD
|
||||
# licensed.
|
||||
require 'syslog'
|
||||
require 'logger'
|
||||
require 'thread'
|
||||
|
||||
class Syslogger
|
||||
|
||||
VERSION = "1.6.0"
|
||||
|
||||
attr_reader :level, :ident, :options, :facility, :max_octets
|
||||
attr_accessor :formatter
|
||||
|
||||
MAPPING = {
|
||||
Logger::DEBUG => Syslog::LOG_DEBUG,
|
||||
Logger::INFO => Syslog::LOG_INFO,
|
||||
Logger::WARN => Syslog::LOG_WARNING,
|
||||
Logger::ERROR => Syslog::LOG_ERR,
|
||||
Logger::FATAL => Syslog::LOG_CRIT,
|
||||
Logger::UNKNOWN => Syslog::LOG_ALERT
|
||||
}
|
||||
|
||||
#
|
||||
# Initializes default options for the logger
|
||||
# <tt>ident</tt>:: the name of your program [default=$0].
|
||||
# <tt>options</tt>:: syslog options [default=<tt>Syslog::LOG_PID | Syslog::LOG_CONS</tt>].
|
||||
# Correct values are:
|
||||
# LOG_CONS : writes the message on the console if an error occurs when sending the message;
|
||||
# LOG_NDELAY : no delay before sending the message;
|
||||
# LOG_PERROR : messages will also be written on STDERR;
|
||||
# LOG_PID : adds the process number to the message (just after the program name)
|
||||
# <tt>facility</tt>:: the syslog facility [default=nil] Correct values include:
|
||||
# Syslog::LOG_DAEMON
|
||||
# Syslog::LOG_USER
|
||||
# Syslog::LOG_SYSLOG
|
||||
# Syslog::LOG_LOCAL2
|
||||
# Syslog::LOG_NEWS
|
||||
# etc.
|
||||
#
|
||||
# Usage:
|
||||
# logger = Syslogger.new("my_app", Syslog::LOG_PID | Syslog::LOG_CONS, Syslog::LOG_LOCAL0)
|
||||
# logger.level = Logger::INFO # use Logger levels
|
||||
# logger.warn "warning message"
|
||||
# logger.debug "debug message"
|
||||
#
|
||||
def initialize(ident = $0, options = Syslog::LOG_PID | Syslog::LOG_CONS, facility = nil)
|
||||
@ident = ident
|
||||
@options = options || (Syslog::LOG_PID | Syslog::LOG_CONS)
|
||||
@facility = facility
|
||||
@level = Logger::INFO
|
||||
@mutex = Mutex.new
|
||||
@formatter = Logger::Formatter.new
|
||||
end
|
||||
|
||||
%w{debug info warn error fatal unknown}.each do |logger_method|
|
||||
# Accepting *args as message could be nil.
|
||||
# Default params not supported in ruby 1.8.7
|
||||
define_method logger_method.to_sym do |*args, &block|
|
||||
return true if @level > Logger.const_get(logger_method.upcase)
|
||||
message = args.first || block && block.call
|
||||
add(Logger.const_get(logger_method.upcase), message)
|
||||
end
|
||||
|
||||
unless logger_method == 'unknown'
|
||||
define_method "#{logger_method}?".to_sym do
|
||||
@level <= Logger.const_get(logger_method.upcase)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Log a message at the Logger::INFO level. Useful for use with Rack::CommonLogger
|
||||
def write(msg)
|
||||
add(Logger::INFO, msg)
|
||||
end
|
||||
|
||||
# Logs a message at the Logger::INFO level.
|
||||
def <<(msg)
|
||||
add(Logger::INFO, msg)
|
||||
end
|
||||
|
||||
# Low level method to add a message.
|
||||
# +severity+:: the level of the message. One of Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN
|
||||
# +message+:: the message string.
|
||||
# If nil, the method will call the block and use the result as the message string.
|
||||
# If both are nil or no block is given, it will use the progname as per the behaviour of both the standard Ruby logger, and the Rails BufferedLogger.
|
||||
# +progname+:: optionally, overwrite the program name that appears in the log message.
|
||||
def add(severity, message = nil, progname = nil, &block)
|
||||
if message.nil? && block.nil? && !progname.nil?
|
||||
message, progname = progname, nil
|
||||
end
|
||||
progname ||= @ident
|
||||
|
||||
@mutex.synchronize do
|
||||
Syslog.open(progname, @options, @facility) do |s|
|
||||
s.mask = Syslog::LOG_UPTO(MAPPING[@level])
|
||||
communication = clean(message || block && block.call)
|
||||
if self.max_octets
|
||||
buffer = "#{tags_text}"
|
||||
communication.bytes do |byte|
|
||||
buffer.concat(byte)
|
||||
# if the last byte we added is potentially part of an escape, we'll go ahead and add another byte
|
||||
if buffer.bytesize >= self.max_octets && !['%'.ord,'\\'.ord].include?(byte)
|
||||
s.log(MAPPING[severity],buffer)
|
||||
buffer = ""
|
||||
end
|
||||
end
|
||||
s.log(MAPPING[severity],buffer) unless buffer.empty?
|
||||
else
|
||||
s.log(MAPPING[severity],"#{tags_text}#{communication}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Set the max octets of the messages written to the log
|
||||
def max_octets=(max_octets)
|
||||
@max_octets = max_octets
|
||||
end
|
||||
|
||||
# Sets the minimum level for messages to be written in the log.
|
||||
# +level+:: one of <tt>Logger::DEBUG</tt>, <tt>Logger::INFO</tt>, <tt>Logger::WARN</tt>, <tt>Logger::ERROR</tt>, <tt>Logger::FATAL</tt>, <tt>Logger::UNKNOWN</tt>
|
||||
def level=(level)
|
||||
level = Logger.const_get(level.to_s.upcase) if level.is_a?(Symbol)
|
||||
|
||||
unless level.is_a?(Fixnum)
|
||||
raise ArgumentError.new("Invalid logger level `#{level.inspect}`")
|
||||
end
|
||||
|
||||
@level = level
|
||||
end
|
||||
|
||||
# Sets the ident string passed along to Syslog
|
||||
def ident=(ident)
|
||||
@ident = ident
|
||||
end
|
||||
|
||||
# Tagging code borrowed from ActiveSupport gem
|
||||
def tagged(*tags)
|
||||
new_tags = push_tags(*tags)
|
||||
yield self
|
||||
ensure
|
||||
pop_tags(new_tags.size)
|
||||
end
|
||||
|
||||
def push_tags(*tags)
|
||||
tags.flatten.reject{ |i| i.respond_to?(:empty?) ? i.empty? : !i }.tap do |new_tags|
|
||||
current_tags.concat new_tags
|
||||
end
|
||||
end
|
||||
|
||||
def pop_tags(size = 1)
|
||||
current_tags.pop size
|
||||
end
|
||||
|
||||
def clear_tags!
|
||||
current_tags.clear
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Borrowed from SyslogLogger.
|
||||
def clean(message)
|
||||
message = message.to_s.dup
|
||||
message.strip! # remove whitespace
|
||||
message.gsub!(/\n/, '\\n') # escape newlines
|
||||
message.gsub!(/%/, '%%') # syslog(3) freaks on % (printf)
|
||||
message.gsub!(/\e\[[^m]*m/, '') # remove useless ansi color codes
|
||||
message
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tags_text
|
||||
tags = current_tags
|
||||
if tags.any?
|
||||
tags.collect { |tag| "[#{tag}] " }.join
|
||||
end
|
||||
end
|
||||
|
||||
def current_tags
|
||||
Thread.current[:syslogger_tagged_logging_tags] ||= []
|
||||
end
|
||||
end
|
||||
|
||||
worker_processes 2
|
||||
working_directory ENV["GITLAB_PATH"]
|
||||
pid ENV["UNICORN_PATH"] + "/tmp/pids/unicorn.pid"
|
||||
worker_processes 3
|
||||
|
||||
listen ENV["UNICORN_PATH"] + "/tmp/sockets/gitlab.socket", :backlog => 1024
|
||||
listen "/run/gitlab/gitlab.socket", :backlog => 1024
|
||||
|
||||
working_directory ENV["GITLAB_PATH"]
|
||||
|
||||
pid ENV["UNICORN_PATH"] + "/tmp/pids/unicorn.pid"
|
||||
|
||||
timeout 60
|
||||
|
||||
logger Syslogger.new
|
||||
|
||||
# combine Ruby 2.0.0dev or REE with "preload_app true" for memory savings
|
||||
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
||||
preload_app true
|
||||
|
||||
GC.respond_to?(:copy_on_write_friendly=) and
|
||||
GC.copy_on_write_friendly = true
|
||||
|
||||
check_client_connection false
|
||||
|
||||
before_fork do |server, worker|
|
||||
# the following is highly recommended for Rails + "preload_app true"
|
||||
# as there's no need for the master process to hold a connection
|
||||
defined?(ActiveRecord::Base) and
|
||||
ActiveRecord::Base.connection.disconnect!
|
||||
|
||||
# The following is only recommended for memory/DB-constrained
|
||||
# installations. It is not needed if your system can house
|
||||
# twice as many worker_processes as you have configured.
|
||||
#
|
||||
# This allows a new master process to incrementally
|
||||
# phase out the old master process with SIGTTOU to avoid a
|
||||
# thundering herd (especially in the "preload_app false" case)
|
||||
# when doing a transparent upgrade. The last worker spawned
|
||||
# will then kill off the old master process with a SIGQUIT.
|
||||
old_pid = "#{server.config[:pid]}.oldbin"
|
||||
if old_pid != server.pid
|
||||
begin
|
||||
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
|
||||
Process.kill(sig, File.read(old_pid).to_i)
|
||||
rescue Errno::ENOENT, Errno::ESRCH
|
||||
end
|
||||
end
|
||||
|
||||
# Throttle the master from forking too quickly by sleeping. Due
|
||||
# to the implementation of standard Unix signal handlers, this
|
||||
# helps (but does not completely) prevent identical, repeated signals
|
||||
# from being lost when the receiving process is busy.
|
||||
# sleep 1
|
||||
end
|
||||
|
||||
after_fork do |server, worker|
|
||||
# per-process listener ports for debugging/admin/migrations
|
||||
# addr = "127.0.0.1:#{9293 + worker.nr}"
|
||||
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
|
||||
|
||||
# the following is *required* for Rails + "preload_app true",
|
||||
defined?(ActiveRecord::Base) and
|
||||
ActiveRecord::Base.establish_connection
|
||||
|
||||
# reset prometheus client, this will cause any opened metrics files to be closed
|
||||
defined?(::Prometheus::Client.reinitialize_on_pid_change) &&
|
||||
Prometheus::Client.reinitialize_on_pid_change
|
||||
|
||||
# if preload_app is true, then you may also want to check and
|
||||
# restart any other shared sockets/descriptors such as Memcached,
|
||||
# and Redis. TokyoCabinet file handles are safe to reuse
|
||||
# between any number of forked children (assuming your kernel
|
||||
# correctly implements pread()/pwrite() system calls)
|
||||
end
|
||||
|
|
|
@ -4,6 +4,8 @@ with lib;
|
|||
|
||||
let
|
||||
cfg = config.services.gitea;
|
||||
pg = config.services.postgresql;
|
||||
usePostgresql = cfg.database.type == "postgres";
|
||||
configFile = pkgs.writeText "app.ini" ''
|
||||
APP_NAME = ${cfg.appName}
|
||||
RUN_USER = ${cfg.user}
|
||||
|
@ -16,6 +18,9 @@ let
|
|||
USER = ${cfg.database.user}
|
||||
PASSWD = #dbpass#
|
||||
PATH = ${cfg.database.path}
|
||||
${optionalString usePostgresql ''
|
||||
SSL_MODE = disable
|
||||
''}
|
||||
|
||||
[repository]
|
||||
ROOT = ${cfg.repositoryRoot}
|
||||
|
@ -35,6 +40,10 @@ let
|
|||
SECRET_KEY = #secretkey#
|
||||
INSTALL_LOCK = true
|
||||
|
||||
[log]
|
||||
ROOT_PATH = ${cfg.log.rootPath}
|
||||
LEVEL = ${cfg.log.level}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
in
|
||||
|
@ -60,6 +69,19 @@ in
|
|||
description = "gitea data directory.";
|
||||
};
|
||||
|
||||
log = {
|
||||
rootPath = mkOption {
|
||||
default = "${cfg.stateDir}/log";
|
||||
type = types.str;
|
||||
description = "Root path for log files.";
|
||||
};
|
||||
level = mkOption {
|
||||
default = "Trace";
|
||||
type = types.enum [ "Trace" "Debug" "Info" "Warn" "Error" "Critical" ];
|
||||
description = "General log level.";
|
||||
};
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "gitea";
|
||||
|
@ -82,7 +104,7 @@ in
|
|||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 3306;
|
||||
default = (if !usePostgresql then 3306 else pg.port);
|
||||
description = "Database host port.";
|
||||
};
|
||||
|
||||
|
@ -123,6 +145,15 @@ in
|
|||
default = "${cfg.stateDir}/data/gitea.db";
|
||||
description = "Path to the sqlite3 database file.";
|
||||
};
|
||||
|
||||
createDatabase = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to create a local postgresql database automatically.
|
||||
This only applies if database type "postgres" is selected.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
appName = mkOption {
|
||||
|
@ -186,10 +217,11 @@ in
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.postgresql.enable = mkIf usePostgresql (mkDefault true);
|
||||
|
||||
systemd.services.gitea = {
|
||||
description = "gitea";
|
||||
after = [ "network.target" ];
|
||||
after = [ "network.target" "postgresql.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.gitea.bin ];
|
||||
|
||||
|
@ -231,12 +263,31 @@ in
|
|||
mkdir -p ${cfg.stateDir}/conf
|
||||
cp -r ${pkgs.gitea.out}/locale ${cfg.stateDir}/conf/locale
|
||||
fi
|
||||
'' + optionalString (usePostgresql && cfg.database.createDatabase) ''
|
||||
if ! test -e "${cfg.stateDir}/db-created"; then
|
||||
echo "CREATE ROLE ${cfg.database.user}
|
||||
WITH ENCRYPTED PASSWORD '$(head -n1 ${cfg.database.passwordFile})'
|
||||
NOCREATEDB NOCREATEROLE LOGIN" |
|
||||
${pkgs.sudo}/bin/sudo -u ${pg.superUser} ${pg.package}/bin/psql
|
||||
${pkgs.sudo}/bin/sudo -u ${pg.superUser} \
|
||||
${pg.package}/bin/createdb \
|
||||
--owner=${cfg.database.user} \
|
||||
--encoding=UTF8 \
|
||||
--lc-collate=C \
|
||||
--lc-ctype=C \
|
||||
--template=template0 \
|
||||
${cfg.database.name}
|
||||
touch "${cfg.stateDir}/db-created"
|
||||
fi
|
||||
'' + ''
|
||||
chown ${cfg.user} -R ${cfg.stateDir}
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = cfg.user;
|
||||
WorkingDirectory = cfg.stateDir;
|
||||
PermissionsStartOnly = true;
|
||||
ExecStart = "${pkgs.gitea.bin}/bin/gitea web";
|
||||
Restart = "always";
|
||||
};
|
||||
|
@ -253,6 +304,7 @@ in
|
|||
description = "Gitea Service";
|
||||
home = cfg.stateDir;
|
||||
createHome = true;
|
||||
useDefaultShell = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -143,6 +143,7 @@ let
|
|||
GITLAB_PATH = "${cfg.packages.gitlab}/share/gitlab/";
|
||||
GITLAB_STATE_PATH = "${cfg.statePath}";
|
||||
GITLAB_UPLOADS_PATH = "${cfg.statePath}/uploads";
|
||||
SCHEMA = "${cfg.statePath}/db/schema.rb";
|
||||
GITLAB_LOG_PATH = "${cfg.statePath}/log";
|
||||
GITLAB_SHELL_PATH = "${cfg.packages.gitlab-shell}";
|
||||
GITLAB_SHELL_CONFIG_PATH = "${cfg.statePath}/shell/config.yml";
|
||||
|
@ -500,7 +501,7 @@ in {
|
|||
Type = "simple";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
TimeoutSec = "300";
|
||||
TimeoutSec = "infinity";
|
||||
Restart = "on-failure";
|
||||
WorkingDirectory = gitlabEnv.HOME;
|
||||
ExecStart = "${cfg.packages.gitaly}/bin/gitaly ${gitalyToml}";
|
||||
|
@ -566,6 +567,7 @@ in {
|
|||
mkdir -p ${cfg.statePath}/tmp/pids
|
||||
mkdir -p ${cfg.statePath}/tmp/sockets
|
||||
mkdir -p ${cfg.statePath}/shell
|
||||
mkdir -p ${cfg.statePath}/db
|
||||
|
||||
rm -rf ${cfg.statePath}/config ${cfg.statePath}/shell/hooks
|
||||
mkdir -p ${cfg.statePath}/config
|
||||
|
@ -580,6 +582,7 @@ in {
|
|||
ln -sf ${cfg.statePath}/log /run/gitlab/log
|
||||
ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads
|
||||
ln -sf ${cfg.statePath}/tmp /run/gitlab/tmp
|
||||
ln -sf $GITLAB_SHELL_CONFIG_PATH /run/gitlab/shell-config.yml
|
||||
chown -R ${cfg.user}:${cfg.group} /run/gitlab
|
||||
|
||||
# Prepare home directory
|
||||
|
@ -587,6 +590,7 @@ in {
|
|||
touch ${gitlabEnv.HOME}/.ssh/authorized_keys
|
||||
chown -R ${cfg.user}:${cfg.group} ${gitlabEnv.HOME}/
|
||||
|
||||
cp -rf ${cfg.packages.gitlab}/share/gitlab/db/* ${cfg.statePath}/db
|
||||
cp -rf ${cfg.packages.gitlab}/share/gitlab/config.dist/* ${cfg.statePath}/config
|
||||
${optionalString cfg.smtp.enable ''
|
||||
ln -sf ${smtpSettings} ${cfg.statePath}/config/initializers/smtp_settings.rb
|
||||
|
|
|
@ -104,7 +104,6 @@ in {
|
|||
config = mkIf cfg.enable {
|
||||
systemd.services.home-assistant = {
|
||||
description = "Home Assistant";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
preStart = lib.optionalString (cfg.config != null) ''
|
||||
rm -f ${cfg.configDir}/configuration.yaml
|
||||
|
@ -121,6 +120,16 @@ in {
|
|||
ReadWritePaths = "${cfg.configDir}";
|
||||
PrivateTmp = true;
|
||||
};
|
||||
path = [
|
||||
"/run/wrappers" # needed for ping
|
||||
];
|
||||
};
|
||||
|
||||
systemd.targets.home-assistant = rec {
|
||||
description = "Home Assistant";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "home-assistant.service" ];
|
||||
after = wants;
|
||||
};
|
||||
|
||||
users.extraUsers.hass = {
|
||||
|
|
|
@ -6,6 +6,8 @@ let
|
|||
|
||||
cfg = config.services.parsoid;
|
||||
|
||||
parsoid = pkgs.nodePackages."parsoid-git://github.com/abbradar/parsoid#stable";
|
||||
|
||||
confTree = {
|
||||
worker_heartbeat_timeout = 300000;
|
||||
logging = { level = "info"; };
|
||||
|
@ -93,7 +95,7 @@ in
|
|||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
ExecStart = "${pkgs.nodePackages.parsoid}/lib/node_modules/parsoid/bin/server.js -c ${confFile} -n ${toString cfg.workers}";
|
||||
ExecStart = "${parsoid}/lib/node_modules/parsoid/bin/server.js -c ${confFile} -n ${toString cfg.workers}";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ let
|
|||
DATABASE_USER = cfg.database.user;
|
||||
DATABASE_PASSWORD = cfg.database.password;
|
||||
DATABASE_PATH = cfg.database.path;
|
||||
DATABASE_CONN_MAX_LIFETIME = cfg.database.connMaxLifetime;
|
||||
|
||||
SECURITY_ADMIN_USER = cfg.security.adminUser;
|
||||
SECURITY_ADMIN_PASSWORD = cfg.security.adminPassword;
|
||||
|
@ -143,6 +144,15 @@ in {
|
|||
default = "${cfg.dataDir}/data/grafana.db";
|
||||
type = types.path;
|
||||
};
|
||||
|
||||
connMaxLifetime = mkOption {
|
||||
description = ''
|
||||
Sets the maximum amount of time (in seconds) a connection may be reused.
|
||||
For MySQL this setting should be shorter than the `wait_timeout' variable.
|
||||
'';
|
||||
default = 14400;
|
||||
type = types.int;
|
||||
};
|
||||
};
|
||||
|
||||
security = {
|
||||
|
@ -241,7 +251,9 @@ in {
|
|||
description = "Grafana Service Daemon";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["networking.target"];
|
||||
environment = mapAttrs' (n: v: nameValuePair "GF_${n}" (toString v)) envOptions;
|
||||
environment = {
|
||||
QT_QPA_PLATFORM = "offscreen";
|
||||
} // mapAttrs' (n: v: nameValuePair "GF_${n}" (toString v)) envOptions;
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package.bin}/bin/grafana-server -homepath ${cfg.dataDir}";
|
||||
WorkingDirectory = cfg.dataDir;
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.blackboxExporter;
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.blackboxExporter = {
|
||||
enable = mkEnableOption "prometheus blackbox exporter";
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path to configuration file.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9115;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the blackbox exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
systemd.services.prometheus-blackbox-exporter = {
|
||||
description = "Prometheus exporter for blackbox probes";
|
||||
unitConfig.Documentation = "https://github.com/prometheus/blackbox_exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
AmbientCapabilities = [ "CAP_NET_RAW" ]; # for ping probes
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
|
||||
--web.listen-address :${toString cfg.port} \
|
||||
--config.file ${cfg.configFile} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.collectdExporter;
|
||||
|
||||
collectSettingsArgs = if (cfg.collectdBinary.enable) then ''
|
||||
-collectd.listen-address ${optionalString (cfg.collectdBinary.listenAddress != null) cfg.collectdBinary.listenAddress}:${toString cfg.collectdBinary.port} \
|
||||
-collectd.security-level ${cfg.collectdBinary.securityLevel} \
|
||||
'' else "";
|
||||
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.collectdExporter = {
|
||||
enable = mkEnableOption "prometheus collectd exporter";
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9103;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
This is used for scraping as well as the to receive collectd data via the write_http plugin.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "0.0.0.0";
|
||||
description = ''
|
||||
Address to listen on for web interface, telemetry and collectd JSON data.
|
||||
'';
|
||||
};
|
||||
|
||||
collectdBinary = {
|
||||
enable = mkEnableOption "collectd binary protocol receiver";
|
||||
|
||||
authFile = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
description = "File mapping user names to pre-shared keys (passwords).";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 25826;
|
||||
description = ''Network address on which to accept collectd binary network packets.'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "0.0.0.0";
|
||||
description = ''
|
||||
Address to listen on for binary network packets.
|
||||
'';
|
||||
};
|
||||
|
||||
securityLevel = mkOption {
|
||||
type = types.enum ["None" "Sign" "Encrypt"];
|
||||
default = "None";
|
||||
description = ''
|
||||
Minimum required security level for accepted packets.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the collectd exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
logFormat = mkOption {
|
||||
type = types.str;
|
||||
default = "logger:stderr";
|
||||
example = "logger:syslog?appname=bob&local=7 or logger:stdout?json=true";
|
||||
description = ''
|
||||
Set the log target and format.
|
||||
'';
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.enum ["debug" "info" "warn" "error" "fatal"];
|
||||
default = "info";
|
||||
description = ''
|
||||
Only log messages with the given severity or above.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = (optional cfg.openFirewall cfg.port) ++
|
||||
(optional (cfg.openFirewall && cfg.collectdBinary.enable) cfg.collectdBinary.port);
|
||||
|
||||
systemd.services.prometheus-collectd-exporter = {
|
||||
description = "Prometheus exporter for Collectd metrics";
|
||||
unitConfig.Documentation = "https://github.com/prometheus/collectd_exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
|
||||
-log.format ${cfg.logFormat} \
|
||||
-log.level ${cfg.logLevel} \
|
||||
-web.listen-address ${optionalString (cfg.listenAddress != null) cfg.listenAddress}:${toString cfg.port} \
|
||||
${collectSettingsArgs} \
|
||||
${concatStringsSep " " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters;
|
||||
|
||||
# each attribute in `exporterOpts` is expected to have specified:
|
||||
# - port (types.int): port on which the exporter listens
|
||||
# - serviceOpts (types.attrs): config that is merged with the
|
||||
# default definition of the exporter's
|
||||
# systemd service
|
||||
# - extraOpts (types.attrs): extra configuration options to
|
||||
# configure the exporter with, which
|
||||
# are appended to the default options
|
||||
#
|
||||
# Note that `extraOpts` is optional, but a script for the exporter's
|
||||
# systemd service must be provided by specifying either
|
||||
# `serviceOpts.script` or `serviceOpts.serviceConfig.ExecStart`
|
||||
exporterOpts = {
|
||||
blackbox = import ./exporters/blackbox.nix { inherit config lib pkgs; };
|
||||
collectd = import ./exporters/collectd.nix { inherit config lib pkgs; };
|
||||
fritzbox = import ./exporters/fritzbox.nix { inherit config lib pkgs; };
|
||||
json = import ./exporters/json.nix { inherit config lib pkgs; };
|
||||
minio = import ./exporters/minio.nix { inherit config lib pkgs; };
|
||||
nginx = import ./exporters/nginx.nix { inherit config lib pkgs; };
|
||||
node = import ./exporters/node.nix { inherit config lib pkgs; };
|
||||
postfix = import ./exporters/postfix.nix { inherit config lib pkgs; };
|
||||
snmp = import ./exporters/snmp.nix { inherit config lib pkgs; };
|
||||
unifi = import ./exporters/unifi.nix { inherit config lib pkgs; };
|
||||
varnish = import ./exporters/varnish.nix { inherit config lib pkgs; };
|
||||
};
|
||||
|
||||
mkExporterOpts = ({ name, port }: {
|
||||
enable = mkEnableOption "the prometheus ${name} exporter";
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = port;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
description = ''
|
||||
Address to listen on.
|
||||
'';
|
||||
};
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options to pass to the ${name} exporter.
|
||||
'';
|
||||
};
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
firewallFilter = mkOption {
|
||||
type = types.str;
|
||||
default = "-p tcp -m tcp --dport ${toString port}";
|
||||
example = literalExample ''
|
||||
"-i eth0 -p tcp -m tcp --dport ${toString port}"
|
||||
'';
|
||||
description = ''
|
||||
Specify a filter for iptables to use when
|
||||
<option>services.prometheus.exporters.${name}.openFirewall</option>
|
||||
is true. It is used as `ip46tables -I INPUT <option>firewallFilter</option> -j ACCEPT`.
|
||||
'';
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "nobody";
|
||||
description = ''
|
||||
User name under which the ${name} exporter shall be run.
|
||||
Has no effect when <option>systemd.services.prometheus-${name}-exporter.serviceConfig.DynamicUser</option> is true.
|
||||
'';
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "nobody";
|
||||
description = ''
|
||||
Group under which the ${name} exporter shall be run.
|
||||
Has no effect when <option>systemd.services.prometheus-${name}-exporter.serviceConfig.DynamicUser</option> is true.
|
||||
'';
|
||||
};
|
||||
});
|
||||
|
||||
mkSubModule = { name, port, extraOpts, serviceOpts }: {
|
||||
${name} = mkOption {
|
||||
type = types.submodule {
|
||||
options = (mkExporterOpts {
|
||||
inherit name port;
|
||||
} // extraOpts);
|
||||
};
|
||||
internal = true;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
mkSubModules = (foldl' (a: b: a//b) {}
|
||||
(mapAttrsToList (name: opts: mkSubModule {
|
||||
inherit name;
|
||||
inherit (opts) port serviceOpts;
|
||||
extraOpts = opts.extraOpts or {};
|
||||
}) exporterOpts)
|
||||
);
|
||||
|
||||
mkExporterConf = { name, conf, serviceOpts }:
|
||||
mkIf conf.enable {
|
||||
networking.firewall.extraCommands = mkIf conf.openFirewall ''
|
||||
ip46tables -I INPUT ${conf.firewallFilter} -j ACCEPT
|
||||
'';
|
||||
systemd.services."prometheus-${name}-exporter" = mkMerge ([{
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
Restart = mkDefault "always";
|
||||
PrivateTmp = mkDefault true;
|
||||
WorkingDirectory = mkDefault /tmp;
|
||||
} // mkIf (!(serviceOpts.serviceConfig.DynamicUser or false)) {
|
||||
User = conf.user;
|
||||
Group = conf.group;
|
||||
};
|
||||
} serviceOpts ]);
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.prometheus.exporters = mkOption {
|
||||
type = types.submodule {
|
||||
options = (mkSubModules);
|
||||
};
|
||||
description = "Prometheus exporter configuration";
|
||||
default = {};
|
||||
example = literalExample ''
|
||||
{
|
||||
node = {
|
||||
enable = true;
|
||||
enabledCollectors = [ "systemd" ];
|
||||
};
|
||||
varnish.enable = true;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkMerge ([{
|
||||
assertions = [{
|
||||
assertion = (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null);
|
||||
message = ''
|
||||
Please ensure you have either `services.prometheus.exporters.snmp.configuration'
|
||||
or `services.prometheus.exporters.snmp.configurationPath' set!
|
||||
'';
|
||||
}];
|
||||
}] ++ [(mkIf config.services.minio.enable {
|
||||
services.prometheus.exporters.minio.minioAddress = mkDefault "http://localhost:9000";
|
||||
services.prometheus.exporters.minio.minioAccessKey = mkDefault config.services.minio.accessKey;
|
||||
services.prometheus.exporters.minio.minioAccessSecret = mkDefault config.services.minio.secretKey;
|
||||
})] ++ (mapAttrsToList (name: conf:
|
||||
mkExporterConf {
|
||||
inherit name;
|
||||
inherit (conf) serviceOpts;
|
||||
conf = cfg.${name};
|
||||
}) exporterOpts)
|
||||
);
|
||||
|
||||
meta.doc = ./exporters.xml;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="module-services-prometheus-exporters">
|
||||
|
||||
<title>Prometheus exporters</title>
|
||||
|
||||
<para>Prometheus exporters provide metrics for the <link xlink:href="https://prometheus.io">prometheus monitoring system</link>.</para>
|
||||
|
||||
<section><title>Configuration</title>
|
||||
<para>One of the most common exporters is the <link xlink:href="https://github.com/prometheus/node_exporter">node exporter</link>, it provides hardware and OS metrics from the host it's running on. The exporter could be configured as follows:
|
||||
<programlisting>
|
||||
services.promtheus.exporters.node = {
|
||||
enable = true;
|
||||
enabledCollectors = [
|
||||
"logind"
|
||||
"systemd"
|
||||
];
|
||||
disabledCollectors = [
|
||||
"textfile"
|
||||
];
|
||||
openFirewall = true;
|
||||
firewallFilter = "-i br0 -p tcp -m tcp --dport 9100";
|
||||
};
|
||||
</programlisting>
|
||||
It should now serve all metrics from the collectors
|
||||
that are explicitly enabled and the ones that are
|
||||
<link xlink:href="https://github.com/prometheus/node_exporter#enabled-by-default">enabled by default</link>, via http under <literal>/metrics</literal>. In this example the firewall should just
|
||||
allow incoming connections to the exporter's port on the bridge interface <literal>br0</literal>
|
||||
(this would have to be configured seperately of course).
|
||||
For more information about configuration see <literal>man configuration.nix</literal> or
|
||||
search through the <link xlink:href="https://nixos.org/nixos/options.html#prometheus.exporters">available options</link>.
|
||||
</para>
|
||||
</section>
|
||||
<section><title>Adding a new exporter</title>
|
||||
<para>To add a new exporter, it has to be packaged first (see <literal>nixpkgs/pkgs/servers/monitoring/prometheus/</literal> for examples), then a module can be added. The postfix exporter is used in this example:</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Some default options for all exporters are provided by
|
||||
<literal>nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix</literal>:
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem override='none'>
|
||||
<itemizedlist>
|
||||
<listitem><para><literal>enable</literal></para></listitem>
|
||||
<listitem><para><literal>port</literal></para></listitem>
|
||||
<listitem><para><literal>listenAddress</literal></para></listitem>
|
||||
<listitem><para><literal>extraFlags</literal></para></listitem>
|
||||
<listitem><para><literal>openFirewall</literal></para></listitem>
|
||||
<listitem><para><literal>firewallFilter</literal></para></listitem>
|
||||
<listitem><para><literal>user</literal></para></listitem>
|
||||
<listitem><para><literal>group</literal></para></listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>As there is already a package available, the module can now be added.
|
||||
This is accomplished by adding a new file to the
|
||||
<literal>nixos/modules/services/monitoring/prometheus/exporters/</literal> directory,
|
||||
which will be called postfix.nix and contains all exporter specific options
|
||||
and configuration:
|
||||
<programlisting>
|
||||
# nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
|
||||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
# for convenience we define cfg here
|
||||
cfg = config.services.prometheus.exporters.postfix;
|
||||
in
|
||||
{
|
||||
port = 9154; # The postfix exporter listens on this port by default
|
||||
|
||||
# `extraOpts` is an attribute set which contains additional options
|
||||
# (and optional overrides for default options).
|
||||
# Note that this attribute is optional.
|
||||
extraOpts = {
|
||||
telemetryPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/metrics";
|
||||
description = ''
|
||||
Path under which to expose metrics.
|
||||
'';
|
||||
};
|
||||
logfilePath = mkOption {
|
||||
type = types.path;
|
||||
default = /var/log/postfix_exporter_input.log;
|
||||
example = /var/log/mail.log;
|
||||
description = ''
|
||||
Path where Postfix writes log entries.
|
||||
This file will be truncated by this exporter!
|
||||
'';
|
||||
};
|
||||
showqPath = mkOption {
|
||||
type = types.path;
|
||||
default = /var/spool/postfix/public/showq;
|
||||
example = /var/lib/postfix/queue/public/showq;
|
||||
description = ''
|
||||
Path at which Postfix places its showq socket.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# `serviceOpts` is an attribute set which contains configuration
|
||||
# for the exporter's systemd service. One of
|
||||
# `serviceOpts.script` and `serviceOpts.serviceConfig.ExecStart`
|
||||
# has to be specified here. This will be merged with the default
|
||||
# service confiuration.
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--web.telemetry-path ${cfg.telemetryPath} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
This should already be enough for the postfix exporter. Additionally one could
|
||||
now add assertions and conditional default values. This can be done in the
|
||||
'meta-module' that combines all exporter definitions and generates the submodules:
|
||||
<literal>nixpkgs/nixos/modules/services/prometheus/exporters.nix</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</chapter>
|
|
@ -0,0 +1,31 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.blackbox;
|
||||
in
|
||||
{
|
||||
port = 9115;
|
||||
extraOpts = {
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path to configuration file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
AmbientCapabilities = [ "CAP_NET_RAW" ]; # for ping probes
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--config.file ${cfg.configFile} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.collectd;
|
||||
in
|
||||
{
|
||||
port = 9103;
|
||||
extraOpts = {
|
||||
collectdBinary = {
|
||||
enable = mkEnableOption "collectd binary protocol receiver";
|
||||
|
||||
authFile = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
description = "File mapping user names to pre-shared keys (passwords).";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 25826;
|
||||
description = ''Network address on which to accept collectd binary network packets.'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
description = ''
|
||||
Address to listen on for binary network packets.
|
||||
'';
|
||||
};
|
||||
|
||||
securityLevel = mkOption {
|
||||
type = types.enum ["None" "Sign" "Encrypt"];
|
||||
default = "None";
|
||||
description = ''
|
||||
Minimum required security level for accepted packets.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
logFormat = mkOption {
|
||||
type = types.str;
|
||||
default = "logger:stderr";
|
||||
example = "logger:syslog?appname=bob&local=7 or logger:stdout?json=true";
|
||||
description = ''
|
||||
Set the log target and format.
|
||||
'';
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.enum ["debug" "info" "warn" "error" "fatal"];
|
||||
default = "info";
|
||||
description = ''
|
||||
Only log messages with the given severity or above.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = let
|
||||
collectSettingsArgs = if (cfg.collectdBinary.enable) then ''
|
||||
-collectd.listen-address ${cfg.collectdBinary.listenAddress}:${toString cfg.collectdBinary.port} \
|
||||
-collectd.security-level ${cfg.collectdBinary.securityLevel} \
|
||||
'' else "";
|
||||
in {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
|
||||
-log.format ${cfg.logFormat} \
|
||||
-log.level ${cfg.logLevel} \
|
||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
${collectSettingsArgs} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.fritzbox;
|
||||
in
|
||||
{
|
||||
port = 9133;
|
||||
extraOpts = {
|
||||
gatewayAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "fritz.box";
|
||||
description = ''
|
||||
The hostname or IP of the FRITZ!Box.
|
||||
'';
|
||||
};
|
||||
|
||||
gatewayPort = mkOption {
|
||||
type = types.int;
|
||||
default = 49000;
|
||||
description = ''
|
||||
The port of the FRITZ!Box UPnP service.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-fritzbox-exporter}/bin/fritzbox_exporter \
|
||||
-listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
-gateway-address ${cfg.gatewayAddress} \
|
||||
-gateway-port ${toString cfg.gatewayPort} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.json;
|
||||
in
|
||||
{
|
||||
port = 7979;
|
||||
extraOpts = {
|
||||
url = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
URL to scrape JSON from.
|
||||
'';
|
||||
};
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path to configuration file.
|
||||
'';
|
||||
};
|
||||
listenAddress = {}; # not used
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
|
||||
--port ${toString cfg.port} \
|
||||
${cfg.url} ${cfg.configFile} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.minio;
|
||||
in
|
||||
{
|
||||
port = 9290;
|
||||
extraOpts = {
|
||||
minioAddress = mkOption {
|
||||
type = types.str;
|
||||
example = "https://10.0.0.1:9000";
|
||||
description = ''
|
||||
The URL of the minio server.
|
||||
Use HTTPS if Minio accepts secure connections only.
|
||||
By default this connects to the local minio server if enabled.
|
||||
'';
|
||||
};
|
||||
|
||||
minioAccessKey = mkOption {
|
||||
type = types.str;
|
||||
example = "yourMinioAccessKey";
|
||||
description = ''
|
||||
The value of the Minio access key.
|
||||
It is required in order to connect to the server.
|
||||
By default this uses the one from the local minio server if enabled
|
||||
and <literal>config.services.minio.accessKey</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
minioAccessSecret = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The value of the Minio access secret.
|
||||
It is required in order to connect to the server.
|
||||
By default this uses the one from the local minio server if enabled
|
||||
and <literal>config.services.minio.secretKey</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
minioBucketStats = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Collect statistics about the buckets and files in buckets.
|
||||
It requires more computation, use it carefully in case of large buckets..
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
|
||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
-minio.server ${cfg.minioAddress} \
|
||||
-minio.access-key ${cfg.minioAccessKey} \
|
||||
-minio.access-secret ${cfg.minioAccessSecret} \
|
||||
${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.nginx;
|
||||
in
|
||||
{
|
||||
port = 9113;
|
||||
extraOpts = {
|
||||
scrapeUri = mkOption {
|
||||
type = types.string;
|
||||
default = "http://localhost/nginx_status";
|
||||
description = ''
|
||||
Address to access the nginx status page.
|
||||
Can be enabled with services.nginx.statusPage = true.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-nginx-exporter}/bin/nginx_exporter \
|
||||
-nginx.scrape_uri '${cfg.scrapeUri}' \
|
||||
-telemetry.address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.node;
|
||||
in
|
||||
{
|
||||
port = 9100;
|
||||
extraOpts = {
|
||||
enabledCollectors = mkOption {
|
||||
type = types.listOf types.string;
|
||||
default = [];
|
||||
example = ''[ "systemd" ]'';
|
||||
description = ''
|
||||
Collectors to enable. The collectors listed here are enabled in addition to the default ones.
|
||||
'';
|
||||
};
|
||||
disabledCollectors = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = ''[ "timex" ]'';
|
||||
description = ''
|
||||
Collectors to disable which are enabled by default.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-node-exporter}/bin/node_exporter \
|
||||
${concatMapStringsSep " " (x: "--collector." + x) cfg.enabledCollectors} \
|
||||
${concatMapStringsSep " " (x: "--no-collector." + x) cfg.disabledCollectors} \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.postfix;
|
||||
in
|
||||
{
|
||||
port = 9154;
|
||||
extraOpts = {
|
||||
telemetryPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/metrics";
|
||||
description = ''
|
||||
Path under which to expose metrics.
|
||||
'';
|
||||
};
|
||||
logfilePath = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/log/postfix_exporter_input.log";
|
||||
example = "/var/log/mail.log";
|
||||
description = ''
|
||||
Path where Postfix writes log entries.
|
||||
This file will be truncated by this exporter!
|
||||
'';
|
||||
};
|
||||
showqPath = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/spool/postfix/public/showq";
|
||||
example = "/var/lib/postfix/queue/public/showq";
|
||||
description = ''
|
||||
Path where Postfix places it's showq socket.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--web.telemetry-path ${cfg.telemetryPath} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.snmp;
|
||||
in
|
||||
{
|
||||
port = 9116;
|
||||
extraOpts = {
|
||||
configurationPath = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
Path to a snmp exporter configuration file. Mutually exclusive with 'configuration' option.
|
||||
'';
|
||||
example = "./snmp.yml";
|
||||
};
|
||||
|
||||
configuration = mkOption {
|
||||
type = types.nullOr types.attrs;
|
||||
default = {};
|
||||
description = ''
|
||||
Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option.
|
||||
'';
|
||||
example = ''
|
||||
{
|
||||
"default" = {
|
||||
"version" = 2;
|
||||
"auth" = {
|
||||
"community" = "public";
|
||||
};
|
||||
};
|
||||
};
|
||||
'';
|
||||
};
|
||||
|
||||
logFormat = mkOption {
|
||||
type = types.str;
|
||||
default = "logger:stderr";
|
||||
description = ''
|
||||
Set the log target and format.
|
||||
'';
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.enum ["debug" "info" "warn" "error" "fatal"];
|
||||
default = "info";
|
||||
description = ''
|
||||
Only log messages with the given severity or above.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = let
|
||||
configFile = if cfg.configurationPath != null
|
||||
then cfg.configurationPath
|
||||
else "${pkgs.writeText "snmp-eporter-conf.yml" (builtins.toJSON cfg.configuration)}";
|
||||
in {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
|
||||
-config.file ${configFile} \
|
||||
-log.format ${cfg.logFormat} \
|
||||
-log.level ${cfg.logLevel} \
|
||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.unifi;
|
||||
in
|
||||
{
|
||||
port = 9130;
|
||||
extraOpts = {
|
||||
unifiAddress = mkOption {
|
||||
type = types.str;
|
||||
example = "https://10.0.0.1:8443";
|
||||
description = ''
|
||||
URL of the UniFi Controller API.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiInsecure = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If enabled skip the verification of the TLS certificate of the UniFi Controller API.
|
||||
Use with caution.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiUsername = mkOption {
|
||||
type = types.str;
|
||||
example = "ReadOnlyUser";
|
||||
description = ''
|
||||
username for authentication against UniFi Controller API.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiPassword = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Password for authentication against UniFi Controller API.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiTimeout = mkOption {
|
||||
type = types.str;
|
||||
default = "5s";
|
||||
example = "2m";
|
||||
description = ''
|
||||
Timeout including unit for UniFi Controller API requests.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
|
||||
-telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
|
||||
-unifi.addr ${cfg.unifiAddress} \
|
||||
-unifi.username ${cfg.unifiUsername} \
|
||||
-unifi.password ${cfg.unifiPassword} \
|
||||
-unifi.timeout ${cfg.unifiTimeout} \
|
||||
${optionalString cfg.unifiInsecure "-unifi.insecure" } \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{ config, lib, pkgs }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.varnish;
|
||||
in
|
||||
{
|
||||
port = 9131;
|
||||
serviceOpts = {
|
||||
path = [ pkgs.varnish ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
|
||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.fritzboxExporter;
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.fritzboxExporter = {
|
||||
enable = mkEnableOption "prometheus fritzbox exporter";
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9133;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
gatewayAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "fritz.box";
|
||||
description = ''
|
||||
The hostname or IP of the FRITZ!Box.
|
||||
'';
|
||||
};
|
||||
|
||||
gatewayPort = mkOption {
|
||||
type = types.int;
|
||||
default = 49000;
|
||||
description = ''
|
||||
The port of the FRITZ!Box UPnP service.
|
||||
'';
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the fritzbox exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
systemd.services.prometheus-fritzbox-exporter = {
|
||||
description = "Prometheus exporter for FRITZ!Box via UPnP";
|
||||
unitConfig.Documentation = "https://github.com/ndecker/fritzbox_exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-fritzbox-exporter}/bin/fritzbox_exporter \
|
||||
-listen-address :${toString cfg.port} \
|
||||
-gateway-address ${cfg.gatewayAddress} \
|
||||
-gateway-port ${toString cfg.gatewayPort} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.jsonExporter;
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.jsonExporter = {
|
||||
enable = mkEnableOption "prometheus JSON exporter";
|
||||
|
||||
url = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
URL to scrape JSON from.
|
||||
'';
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path to configuration file.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 7979;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the JSON exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
systemd.services.prometheus-json-exporter = {
|
||||
description = "Prometheus exporter for JSON over HTTP";
|
||||
unitConfig.Documentation = "https://github.com/kawamuray/prometheus-json-exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
|
||||
--port ${toString cfg.port} \
|
||||
${cfg.url} ${cfg.configFile} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.minioExporter;
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.minioExporter = {
|
||||
enable = mkEnableOption "prometheus minio exporter";
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9290;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "0.0.0.0";
|
||||
description = ''
|
||||
Address to listen on for web interface and telemetry.
|
||||
'';
|
||||
};
|
||||
|
||||
minioAddress = mkOption {
|
||||
type = types.str;
|
||||
example = "https://10.0.0.1:9000";
|
||||
default = if config.services.minio.enable then "http://localhost:9000" else null;
|
||||
description = ''
|
||||
The URL of the minio server.
|
||||
Use HTTPS if Minio accepts secure connections only.
|
||||
By default this connects to the local minio server if enabled.
|
||||
'';
|
||||
};
|
||||
|
||||
minioAccessKey = mkOption ({
|
||||
type = types.str;
|
||||
example = "BKIKJAA5BMMU2RHO6IBB";
|
||||
description = ''
|
||||
The value of the Minio access key.
|
||||
It is required in order to connect to the server.
|
||||
By default this uses the one from the local minio server if enabled
|
||||
and <literal>config.services.minio.accessKey</literal>.
|
||||
'';
|
||||
} // optionalAttrs (config.services.minio.enable && config.services.minio.accessKey != "") {
|
||||
default = config.services.minio.accessKey;
|
||||
});
|
||||
|
||||
minioAccessSecret = mkOption ({
|
||||
type = types.str;
|
||||
description = ''
|
||||
The calue of the Minio access secret.
|
||||
It is required in order to connect to the server.
|
||||
By default this uses the one from the local minio server if enabled
|
||||
and <literal>config.services.minio.secretKey</literal>.
|
||||
'';
|
||||
} // optionalAttrs (config.services.minio.enable && config.services.minio.secretKey != "") {
|
||||
default = config.services.minio.secretKey;
|
||||
});
|
||||
|
||||
minioBucketStats = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Collect statistics about the buckets and files in buckets.
|
||||
It requires more computation, use it carefully in case of large buckets..
|
||||
'';
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the minio exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
systemd.services.prometheus-minio-exporter = {
|
||||
description = "Prometheus exporter for Minio server metrics";
|
||||
unitConfig.Documentation = "https://github.com/joe-pll/minio-exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = optional config.services.minio.enable "minio.service";
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
|
||||
-web.listen-address ${optionalString (cfg.listenAddress != null) cfg.listenAddress}:${toString cfg.port} \
|
||||
-minio.server ${cfg.minioAddress} \
|
||||
-minio.access-key ${cfg.minioAccessKey} \
|
||||
-minio.access-secret ${cfg.minioAccessSecret} \
|
||||
${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.nginxExporter;
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.nginxExporter = {
|
||||
enable = mkEnableOption "prometheus nginx exporter";
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9113;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.string;
|
||||
default = "0.0.0.0";
|
||||
description = ''
|
||||
Address to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
scrapeUri = mkOption {
|
||||
type = types.string;
|
||||
default = "http://localhost/nginx_status";
|
||||
description = ''
|
||||
Address to access the nginx status page.
|
||||
Can be enabled with services.nginx.statusPage = true.
|
||||
'';
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the nginx exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
systemd.services.prometheus-nginx-exporter = {
|
||||
after = [ "network.target" "nginx.service" ];
|
||||
description = "Prometheus exporter for nginx metrics";
|
||||
unitConfig.Documentation = "https://github.com/discordianfish/nginx_exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-nginx-exporter}/bin/nginx_exporter \
|
||||
-nginx.scrape_uri '${cfg.scrapeUri}' \
|
||||
-telemetry.address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.nodeExporter;
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.nodeExporter = {
|
||||
enable = mkEnableOption "prometheus node exporter";
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9100;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.string;
|
||||
default = "0.0.0.0";
|
||||
description = ''
|
||||
Address to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
enabledCollectors = mkOption {
|
||||
type = types.listOf types.string;
|
||||
default = [];
|
||||
example = ''[ "systemd" ]'';
|
||||
description = ''
|
||||
Collectors to enable. The collectors listed here are enabled in addition to the default ones.
|
||||
'';
|
||||
};
|
||||
|
||||
disabledCollectors = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = ''[ "timex" ]'';
|
||||
description = ''
|
||||
Collectors to disable which are enabled by default.
|
||||
'';
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the node exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
systemd.services.prometheus-node-exporter = {
|
||||
description = "Prometheus exporter for machine metrics";
|
||||
unitConfig.Documentation = "https://github.com/prometheus/node_exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
script = ''
|
||||
exec ${pkgs.prometheus-node-exporter}/bin/node_exporter \
|
||||
${concatMapStringsSep " " (x: "--collector." + x) cfg.enabledCollectors} \
|
||||
${concatMapStringsSep " " (x: "--no-collector." + x) cfg.disabledCollectors} \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.snmpExporter;
|
||||
mkConfigFile = pkgs.writeText "snmp.yml" (if cfg.configurationPath == null then builtins.toJSON cfg.configuration else builtins.readFile cfg.configurationPath);
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.snmpExporter = {
|
||||
enable = mkEnableOption "Prometheus snmp exporter";
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "nobody";
|
||||
description = ''
|
||||
User name under which snmp exporter shall be run.
|
||||
'';
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "nogroup";
|
||||
description = ''
|
||||
Group under which snmp exporter shall be run.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9116;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Address to listen on for web interface and telemetry.
|
||||
'';
|
||||
};
|
||||
|
||||
configurationPath = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
Path to a snmp exporter configuration file. Mutually exclusive with 'configuration' option.
|
||||
'';
|
||||
example = "./snmp.yml";
|
||||
};
|
||||
|
||||
configuration = mkOption {
|
||||
type = types.nullOr types.attrs;
|
||||
default = {};
|
||||
description = ''
|
||||
Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option.
|
||||
'';
|
||||
example = ''
|
||||
{
|
||||
"default" = {
|
||||
"version" = 2;
|
||||
"auth" = {
|
||||
"community" = "public";
|
||||
};
|
||||
};
|
||||
};
|
||||
'';
|
||||
};
|
||||
|
||||
logFormat = mkOption {
|
||||
type = types.str;
|
||||
default = "logger:stderr";
|
||||
description = ''
|
||||
Set the log target and format.
|
||||
'';
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.enum ["debug" "info" "warn" "error" "fatal"];
|
||||
default = "info";
|
||||
description = ''
|
||||
Only log messages with the given severity or above.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
assertions = singleton
|
||||
{
|
||||
assertion = (cfg.configurationPath == null) != (cfg.configuration == null);
|
||||
message = "Please ensure you have either 'configuration' or 'configurationPath' set!";
|
||||
};
|
||||
|
||||
systemd.services.prometheus-snmp-exporter = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
script = ''
|
||||
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
|
||||
-config.file ${mkConfigFile} \
|
||||
-log.format ${cfg.logFormat} \
|
||||
-log.level ${cfg.logLevel} \
|
||||
-web.listen-address ${optionalString (cfg.listenAddress != null) cfg.listenAddress}:${toString cfg.port}
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = "/tmp";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.unifiExporter;
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.unifiExporter = {
|
||||
enable = mkEnableOption "prometheus unifi exporter";
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9130;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiAddress = mkOption {
|
||||
type = types.str;
|
||||
example = "https://10.0.0.1:8443";
|
||||
description = ''
|
||||
URL of the UniFi Controller API.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiInsecure = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If enabled skip the verification of the TLS certificate of the UniFi Controller API.
|
||||
Use with caution.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiUsername = mkOption {
|
||||
type = types.str;
|
||||
example = "ReadOnlyUser";
|
||||
description = ''
|
||||
username for authentication against UniFi Controller API.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiPassword = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Password for authentication against UniFi Controller API.
|
||||
'';
|
||||
};
|
||||
|
||||
unifiTimeout = mkOption {
|
||||
type = types.str;
|
||||
default = "5s";
|
||||
example = "2m";
|
||||
description = ''
|
||||
Timeout including unit for UniFi Controller API requests.
|
||||
'';
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the unifi exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
systemd.services.prometheus-unifi-exporter = {
|
||||
description = "Prometheus exporter for UniFi Controller metrics";
|
||||
unitConfig.Documentation = "https://github.com/mdlayher/unifi_exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = optional config.services.unifi.enable "unifi.service";
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
|
||||
-telemetry.addr :${toString cfg.port} \
|
||||
-unifi.addr ${cfg.unifiAddress} \
|
||||
-unifi.username ${cfg.unifiUsername} \
|
||||
-unifi.password ${cfg.unifiPassword} \
|
||||
-unifi.timeout ${cfg.unifiTimeout} \
|
||||
${optionalString cfg.unifiInsecure "-unifi.insecure" } \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
# Shamelessly cribbed from nginx-exporter.nix. ~ C.
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.varnishExporter;
|
||||
in {
|
||||
options = {
|
||||
services.prometheus.varnishExporter = {
|
||||
enable = mkEnableOption "prometheus Varnish exporter";
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9131;
|
||||
description = ''
|
||||
Port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra commandline options when launching the Varnish exporter.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open port in firewall for incoming connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
|
||||
|
||||
systemd.services.prometheus-varnish-exporter = {
|
||||
description = "Prometheus exporter for Varnish metrics";
|
||||
unitConfig.Documentation = "https://github.com/jonnenauha/prometheus_varnish_exporter";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.varnish ];
|
||||
script = ''
|
||||
exec ${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
|
||||
-web.listen-address :${toString cfg.port} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = /tmp;
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -135,8 +135,7 @@ in {
|
|||
default = { inherit networkmanager modemmanager wpa_supplicant
|
||||
networkmanager-openvpn networkmanager-vpnc
|
||||
networkmanager-openconnect networkmanager-fortisslvpn
|
||||
networkmanager-pptp networkmanager-l2tp
|
||||
networkmanager-iodine; };
|
||||
networkmanager-l2tp networkmanager-iodine; };
|
||||
internal = true;
|
||||
};
|
||||
|
||||
|
@ -267,8 +266,6 @@ in {
|
|||
message = "You can not use networking.networkmanager with networking.wireless";
|
||||
}];
|
||||
|
||||
boot.kernelModules = [ "ppp_mppe" ]; # Needed for most (all?) PPTP VPN connections.
|
||||
|
||||
environment.etc = with cfg.basePackages; [
|
||||
{ source = configFile;
|
||||
target = "NetworkManager/NetworkManager.conf";
|
||||
|
@ -285,9 +282,6 @@ in {
|
|||
{ source = "${networkmanager-fortisslvpn}/etc/NetworkManager/VPN/nm-fortisslvpn-service.name";
|
||||
target = "NetworkManager/VPN/nm-fortisslvpn-service.name";
|
||||
}
|
||||
{ source = "${networkmanager-pptp}/etc/NetworkManager/VPN/nm-pptp-service.name";
|
||||
target = "NetworkManager/VPN/nm-pptp-service.name";
|
||||
}
|
||||
{ source = "${networkmanager-l2tp}/etc/NetworkManager/VPN/nm-l2tp-service.name";
|
||||
target = "NetworkManager/VPN/nm-l2tp-service.name";
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ in
|
|||
environment.NIX_SECRET_KEY_FILE = cfg.secretKeyFile;
|
||||
|
||||
serviceConfig = {
|
||||
Restart = "always";
|
||||
RestartSec = "5s";
|
||||
ExecStart = "${pkgs.nix-serve}/bin/nix-serve " +
|
||||
"--listen ${cfg.bindAddress}:${toString cfg.port} ${cfg.extraParams}";
|
||||
User = "nix-serve";
|
||||
|
|
|
@ -15,6 +15,7 @@ let
|
|||
description = "Path to the key file.";
|
||||
};
|
||||
|
||||
# TODO: rename to certificate to match the prosody config
|
||||
cert = mkOption {
|
||||
type = types.path;
|
||||
description = "Path to the certificate file.";
|
||||
|
@ -30,7 +31,7 @@ let
|
|||
};
|
||||
|
||||
moduleOpts = {
|
||||
|
||||
# Generally required
|
||||
roster = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
|
@ -61,12 +62,38 @@ let
|
|||
description = "Service discovery";
|
||||
};
|
||||
|
||||
legacyauth = mkOption {
|
||||
# Not essential, but recommended
|
||||
carbons = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Legacy authentication. Only used by some old clients and bots";
|
||||
description = "Keep multiple clients in sync";
|
||||
};
|
||||
|
||||
pep = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enables users to publish their mood, activity, playing music and more";
|
||||
};
|
||||
|
||||
private = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Private XML storage (for room bookmarks, etc.)";
|
||||
};
|
||||
|
||||
blocklist = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Allow users to block communications with other users";
|
||||
};
|
||||
|
||||
vcard = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Allow users to set vCards";
|
||||
};
|
||||
|
||||
# Nice to have
|
||||
version = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
|
@ -91,36 +118,112 @@ let
|
|||
description = "Replies to XMPP pings with pongs";
|
||||
};
|
||||
|
||||
console = mkOption {
|
||||
register = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "telnet to port 5582";
|
||||
default = true;
|
||||
description = "Allow users to register on this server using a client and change passwords";
|
||||
};
|
||||
|
||||
mam = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Store messages in an archive and allow users to access it";
|
||||
};
|
||||
|
||||
# Admin interfaces
|
||||
admin_adhoc = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Allows administration via an XMPP client that supports ad-hoc commands";
|
||||
};
|
||||
|
||||
admin_telnet = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Opens telnet console interface on localhost port 5582";
|
||||
};
|
||||
|
||||
# HTTP modules
|
||||
bosh = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable BOSH clients, aka 'Jabber over HTTP'";
|
||||
};
|
||||
|
||||
httpserver = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Serve static files from a directory over HTTP";
|
||||
};
|
||||
|
||||
websocket = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable WebSocket support";
|
||||
};
|
||||
|
||||
http_files = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Serve static files from a directory over HTTP";
|
||||
};
|
||||
|
||||
# Other specific functionality
|
||||
limits = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable bandwidth limiting for XMPP connections";
|
||||
};
|
||||
|
||||
groups = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Shared roster support";
|
||||
};
|
||||
|
||||
server_contact_info = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Publish contact information for this service";
|
||||
};
|
||||
|
||||
announce = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Send announcement to all online users";
|
||||
};
|
||||
|
||||
welcome = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Welcome users who register accounts";
|
||||
};
|
||||
|
||||
watchregistrations = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Alert admins of registrations";
|
||||
};
|
||||
|
||||
motd = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Send a message to users when they log in";
|
||||
};
|
||||
|
||||
legacyauth = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Legacy authentication. Only used by some old clients and bots";
|
||||
};
|
||||
|
||||
proxy65 = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enables a file transfer proxy service which clients behind NAT can use";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
toLua = x:
|
||||
if builtins.isString x then ''"${x}"''
|
||||
else if builtins.isBool x then toString x
|
||||
else if builtins.isBool x then (if x == true then "true" else "false")
|
||||
else if builtins.isInt x then toString x
|
||||
else if builtins.isList x then ''{ ${lib.concatStringsSep ", " (map (n: toLua n) x) } }''
|
||||
else throw "Invalid Lua value";
|
||||
|
||||
createSSLOptsStr = o: ''
|
||||
|
@ -198,6 +301,59 @@ in
|
|||
description = "Allow account creation";
|
||||
};
|
||||
|
||||
c2sRequireEncryption = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Force clients to use encrypted connections? This option will
|
||||
prevent clients from authenticating unless they are using encryption.
|
||||
'';
|
||||
};
|
||||
|
||||
s2sRequireEncryption = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Force servers to use encrypted connections? This option will
|
||||
prevent servers from authenticating unless they are using encryption.
|
||||
Note that this is different from authentication.
|
||||
'';
|
||||
};
|
||||
|
||||
s2sSecureAuth = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Force certificate authentication for server-to-server connections?
|
||||
This provides ideal security, but requires servers you communicate
|
||||
with to support encryption AND present valid, trusted certificates.
|
||||
For more information see https://prosody.im/doc/s2s#security
|
||||
'';
|
||||
};
|
||||
|
||||
s2sInsecureDomains = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "insecure.example.com" ];
|
||||
description = ''
|
||||
Some servers have invalid or self-signed certificates. You can list
|
||||
remote domains here that will not be required to authenticate using
|
||||
certificates. They will be authenticated using DNS instead, even
|
||||
when s2s_secure_auth is enabled.
|
||||
'';
|
||||
};
|
||||
|
||||
s2sSecureDomains = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "jabber.org" ];
|
||||
description = ''
|
||||
Even if you leave s2s_secure_auth disabled, you can still require valid
|
||||
certificates for some domains by specifying a list here.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
modules = moduleOpts;
|
||||
|
||||
extraModules = mkOption {
|
||||
|
@ -206,6 +362,12 @@ in
|
|||
description = "Enable custom modules";
|
||||
};
|
||||
|
||||
extraPluginPaths = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [];
|
||||
description = "Addtional path in which to look find plugins/modules";
|
||||
};
|
||||
|
||||
virtualHosts = mkOption {
|
||||
|
||||
description = "Define the virtual hosts";
|
||||
|
@ -255,38 +417,48 @@ in
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.prosody ];
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
environment.etc."prosody/prosody.cfg.lua".text = ''
|
||||
|
||||
pidfile = "/var/lib/prosody/prosody.pid"
|
||||
|
||||
|
||||
log = "*syslog"
|
||||
|
||||
data_path = "/var/lib/prosody"
|
||||
|
||||
allow_registration = ${boolToString cfg.allowRegistration};
|
||||
|
||||
${ optionalString cfg.modules.console "console_enabled = true;" }
|
||||
plugin_paths = {
|
||||
${lib.concatStringsSep ", " (map (n: "\"${n}\"") cfg.extraPluginPaths) }
|
||||
}
|
||||
|
||||
${ optionalString (cfg.ssl != null) (createSSLOptsStr cfg.ssl) }
|
||||
|
||||
admins = { ${lib.concatStringsSep ", " (map (n: "\"${n}\"") cfg.admins) } };
|
||||
admins = ${toLua cfg.admins}
|
||||
|
||||
-- we already build with libevent, so we can just enable it for a more performant server
|
||||
use_libevent = true
|
||||
|
||||
modules_enabled = {
|
||||
|
||||
${ lib.concatStringsSep "\n\ \ " (lib.mapAttrsToList
|
||||
(name: val: optionalString val ''"${name}";'')
|
||||
(name: val: optionalString val "${toLua name};")
|
||||
cfg.modules) }
|
||||
|
||||
${ optionalString cfg.allowRegistration "\"register\"\;" }
|
||||
|
||||
${ lib.concatStringsSep "\n" (map (x: "\"${x}\";") cfg.extraModules)}
|
||||
|
||||
"posix";
|
||||
${ lib.concatStringsSep "\n" (map (x: "${toLua x};") cfg.package.communityModules)}
|
||||
${ lib.concatStringsSep "\n" (map (x: "${toLua x};") cfg.extraModules)}
|
||||
};
|
||||
|
||||
allow_registration = ${toLua cfg.allowRegistration}
|
||||
|
||||
c2s_require_encryption = ${toLua cfg.c2sRequireEncryption}
|
||||
|
||||
s2s_require_encryption = ${toLua cfg.s2sRequireEncryption}
|
||||
|
||||
s2s_secure_auth = ${toLua cfg.s2sSecureAuth}
|
||||
|
||||
s2s_insecure_domains = ${toLua cfg.s2sInsecureDomains}
|
||||
|
||||
s2s_secure_domains = ${toLua cfg.s2sSecureDomains}
|
||||
|
||||
|
||||
${ cfg.extraConfig }
|
||||
|
||||
${ lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: ''
|
||||
|
|
|
@ -50,12 +50,7 @@ in
|
|||
description = ''
|
||||
If enabled, start the Resilio Sync daemon. Once enabled, you can
|
||||
interact with the service through the Web UI, or configure it in your
|
||||
NixOS configuration. Enabling the <literal>resilio</literal> service
|
||||
also installs a systemd user unit which can be used to start
|
||||
user-specific copies of the daemon. Once installed, you can use
|
||||
<literal>systemctl --user start resilio</literal> as your user to start
|
||||
the daemon using the configuration file located at
|
||||
<literal>$HOME/.config/resilio-sync/config.json</literal>.
|
||||
NixOS configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ in
|
|||
mkdir -m 0755 -p ${stateDir}/dev/
|
||||
cp ${confFile} ${stateDir}/unbound.conf
|
||||
${optionalString cfg.enableRootTrustAnchor ''
|
||||
${pkgs.unbound}/bin/unbound-anchor -a ${rootTrustAnchorFile}
|
||||
${pkgs.unbound}/bin/unbound-anchor -a ${rootTrustAnchorFile} || echo "Root anchor updated!"
|
||||
chown unbound ${stateDir} ${rootTrustAnchorFile}
|
||||
''}
|
||||
touch ${stateDir}/dev/random
|
||||
|
|
|
@ -124,7 +124,7 @@ in
|
|||
|
||||
listenAddresses = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "127.0.0.1:631" ];
|
||||
default = [ "localhost:631" ];
|
||||
example = [ "*:631" ];
|
||||
description = ''
|
||||
A list of addresses and ports on which to listen.
|
||||
|
@ -321,7 +321,10 @@ in
|
|||
''}
|
||||
'';
|
||||
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig = {
|
||||
PrivateTmp = true;
|
||||
RuntimeDirectory = [ "cups" ];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.cups-browsed = mkIf avahiEnabled
|
||||
|
|
|
@ -118,7 +118,7 @@ with lib;
|
|||
default = [];
|
||||
example = [
|
||||
{ urlPath = "/foo/bar.png";
|
||||
files = "/home/eelco/some-file.png";
|
||||
file = "/home/eelco/some-file.png";
|
||||
}
|
||||
];
|
||||
description = ''
|
||||
|
|
|
@ -87,11 +87,11 @@ in
|
|||
|
||||
default = mkOption {
|
||||
type = types.str;
|
||||
default = "none";
|
||||
example = "plasma5";
|
||||
default = "";
|
||||
example = "none";
|
||||
description = "Default desktop manager loaded if none have been chosen.";
|
||||
apply = defaultDM:
|
||||
if defaultDM == "none" && cfg.session.list != [] then
|
||||
if defaultDM == "" && cfg.session.list != [] then
|
||||
(head cfg.session.list).name
|
||||
else if any (w: w.name == defaultDM) cfg.session.list then
|
||||
defaultDM
|
||||
|
|
|
@ -182,8 +182,7 @@ in {
|
|||
{ inherit (pkgs) networkmanager modemmanager wpa_supplicant;
|
||||
inherit (pkgs.gnome3) networkmanager-openvpn networkmanager-vpnc
|
||||
networkmanager-openconnect networkmanager-fortisslvpn
|
||||
networkmanager-pptp networkmanager-iodine
|
||||
networkmanager-l2tp; };
|
||||
networkmanager-iodine networkmanager-l2tp; };
|
||||
|
||||
# Needed for themes and backgrounds
|
||||
environment.pathsToLink = [ "/share" ];
|
||||
|
|
|
@ -12,6 +12,7 @@ in
|
|||
./afterstep.nix
|
||||
./bspwm.nix
|
||||
./dwm.nix
|
||||
./evilwm.nix
|
||||
./exwm.nix
|
||||
./fluxbox.nix
|
||||
./fvwm.nix
|
||||
|
@ -61,9 +62,7 @@ in
|
|||
example = "wmii";
|
||||
description = "Default window manager loaded if none have been chosen.";
|
||||
apply = defaultWM:
|
||||
if defaultWM == "none" && cfg.session != [] then
|
||||
(head cfg.session).name
|
||||
else if any (w: w.name == defaultWM) cfg.session then
|
||||
if any (w: w.name == defaultWM) cfg.session then
|
||||
defaultWM
|
||||
else
|
||||
throw "Default window manager (${defaultWM}) not found.";
|
||||
|
|
|
@ -161,15 +161,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
plainX = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether the X11 session can be plain (without DM/WM) and
|
||||
the Xsession script will be used as fallback or not.
|
||||
'';
|
||||
};
|
||||
|
||||
autorun = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
|
@ -561,11 +552,6 @@ in
|
|||
+ "${toString (length primaryHeads)} heads set to primary: "
|
||||
+ concatMapStringsSep ", " (x: x.output) primaryHeads;
|
||||
})
|
||||
{ assertion = cfg.desktopManager.default == "none" && cfg.windowManager.default == "none" -> cfg.plainX;
|
||||
message = "Either the desktop manager or the window manager shouldn't be `none`! "
|
||||
+ "To explicitly allow this, you can also set `services.xserver.plainX` to `true`. "
|
||||
+ "The `default` value looks for enabled WMs/DMs and select the first one.";
|
||||
}
|
||||
];
|
||||
|
||||
environment.etc =
|
||||
|
|
|
@ -182,7 +182,7 @@ sub GrubFs {
|
|||
# Based on the type pull in the identifier from the system
|
||||
my ($status, @devInfo) = runCommand("@utillinux@/bin/blkid -o export @{[$fs->device]}");
|
||||
if ($status != 0) {
|
||||
die "Failed to get blkid info for @{[$fs->mount]} on @{[$fs->device]}";
|
||||
die "Failed to get blkid info (returned $status) for @{[$fs->mount]} on @{[$fs->device]}";
|
||||
}
|
||||
my @matches = join("", @devInfo) =~ m/@{[uc $fsIdentifier]}=([^\n]*)/;
|
||||
if ($#matches != 0) {
|
||||
|
|
|
@ -142,7 +142,7 @@ let
|
|||
default = { };
|
||||
example = { mtu = "1492"; window = "524288"; };
|
||||
description = ''
|
||||
Other route options. See the symbol <literal>OPTION</literal>
|
||||
Other route options. See the symbol <literal>OPTIONS</literal>
|
||||
in the <literal>ip-route(8)</literal> manual page for the details.
|
||||
'';
|
||||
};
|
||||
|
@ -191,7 +191,7 @@ let
|
|||
preferTempAddress = mkOption {
|
||||
type = types.bool;
|
||||
default = cfg.enableIPv6;
|
||||
defaultText = literalExample "config.networking.enableIpv6";
|
||||
defaultText = literalExample "config.networking.enableIPv6";
|
||||
description = ''
|
||||
When using SLAAC prefer a temporary (IPv6) address over the EUI-64
|
||||
address for originating connections. This is used to reduce tracking.
|
||||
|
|
|
@ -319,8 +319,8 @@ in
|
|||
networkingOptions =
|
||||
mkOption {
|
||||
default = [
|
||||
"-net nic,vlan=0,model=virtio"
|
||||
"-net user,vlan=0\${QEMU_NET_OPTS:+,$QEMU_NET_OPTS}"
|
||||
"-net nic,netdev=user.0,model=virtio"
|
||||
"-netdev user,id=user.0\${QEMU_NET_OPTS:+,$QEMU_NET_OPTS}"
|
||||
];
|
||||
type = types.listOf types.str;
|
||||
description = ''
|
||||
|
@ -434,9 +434,11 @@ in
|
|||
|
||||
virtualisation.pathsInNixDB = [ config.system.build.toplevel ];
|
||||
|
||||
# FIXME: Figure out how to make this work on non-x86
|
||||
virtualisation.qemu.options =
|
||||
mkIf (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [ "-vga std" "-usbdevice tablet" ];
|
||||
# FIXME: Consolidate this one day.
|
||||
virtualisation.qemu.options = mkMerge [
|
||||
(mkIf (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [ "-vga std" "-usb" "-device usb-tablet,bus=usb-bus.0" ])
|
||||
(mkIf (pkgs.stdenv.isArm || pkgs.stdenv.isAarch64) [ "-device virtio-gpu-pci" "-device usb-ehci,id=usb0" "-device usb-kbd" "-device usb-tablet" ])
|
||||
];
|
||||
|
||||
# Mount the host filesystem via 9P, and bind-mount the Nix store
|
||||
# of the host into our own filesystem. We use mkVMOverride to
|
||||
|
|
|
@ -52,17 +52,17 @@ in rec {
|
|||
(all nixos.dummy)
|
||||
(all nixos.manual)
|
||||
|
||||
nixos.iso_minimal.x86_64-linux
|
||||
nixos.iso_minimal.i686-linux
|
||||
nixos.iso_graphical.x86_64-linux
|
||||
nixos.ova.x86_64-linux
|
||||
nixos.iso_minimal.x86_64-linux or []
|
||||
nixos.iso_minimal.i686-linux or []
|
||||
nixos.iso_graphical.x86_64-linux or []
|
||||
nixos.ova.x86_64-linux or []
|
||||
|
||||
#(all nixos.tests.containers)
|
||||
nixos.tests.chromium.x86_64-linux
|
||||
nixos.tests.chromium.x86_64-linux or []
|
||||
(all nixos.tests.firefox)
|
||||
(all nixos.tests.firewall)
|
||||
(all nixos.tests.gnome3)
|
||||
nixos.tests.installer.zfsroot.x86_64-linux # ZFS is 64bit only
|
||||
nixos.tests.installer.zfsroot.x86_64-linux or [] # ZFS is 64bit only
|
||||
(all nixos.tests.installer.lvm)
|
||||
(all nixos.tests.installer.luksroot)
|
||||
(all nixos.tests.installer.separateBoot)
|
||||
|
@ -81,7 +81,7 @@ in rec {
|
|||
(all nixos.tests.boot.uefiUsb)
|
||||
(all nixos.tests.boot-stage1)
|
||||
(all nixos.tests.hibernate)
|
||||
nixos.tests.docker.x86_64-linux
|
||||
nixos.tests.docker.x86_64-linux or []
|
||||
(all nixos.tests.ecryptfs)
|
||||
(all nixos.tests.env)
|
||||
(all nixos.tests.ipv6)
|
||||
|
|
|
@ -16,11 +16,14 @@ let
|
|||
inherit system;
|
||||
} // args);
|
||||
|
||||
callTestOnTheseSystems = systems: fn: args: forMatchingSystems systems (system: hydraJob (importTest fn args system));
|
||||
callTest = callTestOnTheseSystems supportedSystems;
|
||||
callTestOnMatchingSystems = systems: fn: args:
|
||||
forMatchingSystems
|
||||
systems
|
||||
(system: hydraJob (importTest fn args system));
|
||||
callTest = callTestOnMatchingSystems supportedSystems;
|
||||
|
||||
callSubTests = callSubTestsOnTheseSystems supportedSystems;
|
||||
callSubTestsOnTheseSystems = systems: fn: args: let
|
||||
callSubTests = callSubTestsOnMatchingSystems supportedSystems;
|
||||
callSubTestsOnMatchingSystems = systems: fn: args: let
|
||||
discover = attrs: let
|
||||
subTests = filterAttrs (const (hasAttr "test")) attrs;
|
||||
in mapAttrs (const (t: hydraJob t.test)) subTests;
|
||||
|
@ -51,6 +54,17 @@ let
|
|||
}).config.system.build.isoImage);
|
||||
|
||||
|
||||
makeSdImage =
|
||||
{ module, maintainers ? ["dezgeg"], system }:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
|
||||
hydraJob ((import lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules = [ module versionModule ];
|
||||
}).config.system.build.sdImage);
|
||||
|
||||
|
||||
makeSystemTarball =
|
||||
{ module, maintainers ? ["viric"], system }:
|
||||
|
||||
|
@ -151,6 +165,10 @@ in rec {
|
|||
inherit system;
|
||||
});
|
||||
|
||||
sd_image = forTheseSystems [ "aarch64-linux" ] (system: makeSdImage {
|
||||
module = ./modules/installer/cd-dvd/sd-image-aarch64.nix;
|
||||
inherit system;
|
||||
});
|
||||
|
||||
# A bootable VirtualBox virtual appliance as an OVA file (i.e. packaged OVF).
|
||||
ova = forMatchingSystems [ "x86_64-linux" ] (system:
|
||||
|
@ -229,9 +247,9 @@ in rec {
|
|||
tests.boot-stage1 = callTest tests/boot-stage1.nix {};
|
||||
tests.borgbackup = callTest tests/borgbackup.nix {};
|
||||
tests.buildbot = callTest tests/buildbot.nix {};
|
||||
tests.cadvisor = callTestOnTheseSystems ["x86_64-linux"] tests/cadvisor.nix {};
|
||||
tests.ceph = callTestOnTheseSystems ["x86_64-linux"] tests/ceph.nix {};
|
||||
tests.chromium = (callSubTestsOnTheseSystems ["x86_64-linux"] tests/chromium.nix {}).stable;
|
||||
tests.cadvisor = callTestOnMatchingSystems ["x86_64-linux"] tests/cadvisor.nix {};
|
||||
tests.ceph = callTestOnMatchingSystems ["x86_64-linux"] tests/ceph.nix {};
|
||||
tests.chromium = (callSubTestsOnMatchingSystems ["x86_64-linux"] tests/chromium.nix {}).stable or {};
|
||||
tests.cjdns = callTest tests/cjdns.nix {};
|
||||
tests.cloud-init = callTest tests/cloud-init.nix {};
|
||||
tests.containers-ipv4 = callTest tests/containers-ipv4.nix {};
|
||||
|
@ -245,21 +263,21 @@ in rec {
|
|||
tests.containers-hosts = callTest tests/containers-hosts.nix {};
|
||||
tests.containers-macvlans = callTest tests/containers-macvlans.nix {};
|
||||
tests.couchdb = callTest tests/couchdb.nix {};
|
||||
tests.docker = callTestOnTheseSystems ["x86_64-linux"] tests/docker.nix {};
|
||||
tests.docker-tools = callTestOnTheseSystems ["x86_64-linux"] tests/docker-tools.nix {};
|
||||
tests.docker-edge = callTestOnTheseSystems ["x86_64-linux"] tests/docker-edge.nix {};
|
||||
tests.docker = callTestOnMatchingSystems ["x86_64-linux"] tests/docker.nix {};
|
||||
tests.docker-tools = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-tools.nix {};
|
||||
tests.docker-edge = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-edge.nix {};
|
||||
tests.dovecot = callTest tests/dovecot.nix {};
|
||||
tests.dnscrypt-proxy = callTestOnTheseSystems ["x86_64-linux"] tests/dnscrypt-proxy.nix {};
|
||||
tests.dnscrypt-proxy = callTestOnMatchingSystems ["x86_64-linux"] tests/dnscrypt-proxy.nix {};
|
||||
tests.ecryptfs = callTest tests/ecryptfs.nix {};
|
||||
tests.etcd = callTestOnTheseSystems ["x86_64-linux"] tests/etcd.nix {};
|
||||
tests.ec2-nixops = (callSubTestsOnTheseSystems ["x86_64-linux"] tests/ec2.nix {}).boot-ec2-nixops;
|
||||
tests.ec2-config = (callSubTestsOnTheseSystems ["x86_64-linux"] tests/ec2.nix {}).boot-ec2-config;
|
||||
tests.elk = callSubTestsOnTheseSystems ["x86_64-linux"] tests/elk.nix {};
|
||||
tests.etcd = callTestOnMatchingSystems ["x86_64-linux"] tests/etcd.nix {};
|
||||
tests.ec2-nixops = (callSubTestsOnMatchingSystems ["x86_64-linux"] tests/ec2.nix {}).boot-ec2-nixops or {};
|
||||
tests.ec2-config = (callSubTestsOnMatchingSystems ["x86_64-linux"] tests/ec2.nix {}).boot-ec2-config or {};
|
||||
tests.elk = callSubTestsOnMatchingSystems ["x86_64-linux"] tests/elk.nix {};
|
||||
tests.env = callTest tests/env.nix {};
|
||||
tests.ferm = callTest tests/ferm.nix {};
|
||||
tests.firefox = callTest tests/firefox.nix {};
|
||||
tests.firewall = callTest tests/firewall.nix {};
|
||||
tests.fleet = callTestOnTheseSystems ["x86_64-linux"] tests/fleet.nix {};
|
||||
tests.fleet = callTestOnMatchingSystems ["x86_64-linux"] tests/fleet.nix {};
|
||||
tests.fwupd = callTest tests/fwupd.nix {};
|
||||
#tests.gitlab = callTest tests/gitlab.nix {};
|
||||
tests.gitolite = callTest tests/gitolite.nix {};
|
||||
|
@ -292,7 +310,7 @@ in rec {
|
|||
tests.kernel-copperhead = callTest tests/kernel-copperhead.nix {};
|
||||
tests.kernel-latest = callTest tests/kernel-latest.nix {};
|
||||
tests.kernel-lts = callTest tests/kernel-lts.nix {};
|
||||
tests.kubernetes = hydraJob (import tests/kubernetes/default.nix { system = "x86_64-linux"; });
|
||||
tests.kubernetes = callSubTestsOnMatchingSystems ["x86_64-linux"] tests/kubernetes/default.nix {};
|
||||
tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; };
|
||||
tests.ldap = callTest tests/ldap.nix {};
|
||||
#tests.lightdm = callTest tests/lightdm.nix {};
|
||||
|
@ -322,14 +340,14 @@ in rec {
|
|||
tests.nginx = callTest tests/nginx.nix { };
|
||||
tests.nghttpx = callTest tests/nghttpx.nix { };
|
||||
tests.nix-ssh-serve = callTest tests/nix-ssh-serve.nix { };
|
||||
tests.novacomd = callTestOnTheseSystems ["x86_64-linux"] tests/novacomd.nix { };
|
||||
tests.novacomd = callTestOnMatchingSystems ["x86_64-linux"] tests/novacomd.nix { };
|
||||
tests.leaps = callTest tests/leaps.nix { };
|
||||
tests.nsd = callTest tests/nsd.nix {};
|
||||
tests.openssh = callTest tests/openssh.nix {};
|
||||
tests.openldap = callTest tests/openldap.nix {};
|
||||
tests.owncloud = callTest tests/owncloud.nix {};
|
||||
tests.pam-oath-login = callTest tests/pam-oath-login.nix {};
|
||||
#tests.panamax = callTestOnTheseSystems ["x86_64-linux"] tests/panamax.nix {};
|
||||
#tests.panamax = callTestOnMatchingSystems ["x86_64-linux"] tests/panamax.nix {};
|
||||
tests.peerflix = callTest tests/peerflix.nix {};
|
||||
tests.php-pcre = callTest tests/php-pcre.nix {};
|
||||
tests.postgresql = callSubTests tests/postgresql.nix {};
|
||||
|
@ -340,6 +358,7 @@ in rec {
|
|||
tests.predictable-interface-names = callSubTests tests/predictable-interface-names.nix {};
|
||||
tests.printing = callTest tests/printing.nix {};
|
||||
tests.prometheus = callTest tests/prometheus.nix {};
|
||||
tests.prosody = callTest tests/prosody.nix {};
|
||||
tests.proxy = callTest tests/proxy.nix {};
|
||||
# tests.quagga = callTest tests/quagga.nix {};
|
||||
tests.quake3 = callTest tests/quake3.nix {};
|
||||
|
@ -362,7 +381,7 @@ in rec {
|
|||
tests.tomcat = callTest tests/tomcat.nix {};
|
||||
tests.udisks2 = callTest tests/udisks2.nix {};
|
||||
tests.vault = callTest tests/vault.nix {};
|
||||
tests.virtualbox = callSubTestsOnTheseSystems ["x86_64-linux"] tests/virtualbox.nix {};
|
||||
tests.virtualbox = callSubTestsOnMatchingSystems ["x86_64-linux"] tests/virtualbox.nix {};
|
||||
tests.wordpress = callTest tests/wordpress.nix {};
|
||||
tests.xfce = callTest tests/xfce.nix {};
|
||||
tests.xmonad = callTest tests/xmonad.nix {};
|
||||
|
|
|
@ -17,20 +17,14 @@ import ./make-test.nix ({ pkgs, lib, ... }:
|
|||
startAll;
|
||||
|
||||
$machine->fail("test -f ~root/at-1");
|
||||
$machine->fail("test -f ~root/batch-1");
|
||||
$machine->fail("test -f ~alice/at-1");
|
||||
$machine->fail("test -f ~alice/batch-1");
|
||||
|
||||
$machine->succeed("echo 'touch ~root/at-1' | at now+1min");
|
||||
$machine->succeed("echo 'touch ~root/batch-1' | batch");
|
||||
$machine->succeed("su - alice -c \"echo 'touch at-1' | at now+1min\"");
|
||||
$machine->succeed("su - alice -c \"echo 'touch batch-1' | batch\"");
|
||||
|
||||
$machine->succeed("sleep 1.5m");
|
||||
|
||||
$machine->succeed("test -f ~root/at-1");
|
||||
$machine->succeed("test -f ~root/batch-1");
|
||||
$machine->succeed("test -f ~alice/at-1");
|
||||
$machine->succeed("test -f ~alice/batch-1");
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,21 +1,162 @@
|
|||
import ./make-test.nix ({ pkgs, ...}: {
|
||||
import ./make-test.nix ({ pkgs, ... }:
|
||||
|
||||
let
|
||||
passphrase = "supersecret";
|
||||
dataDir = "/ran:dom/data";
|
||||
excludeFile = "not_this_file";
|
||||
keepFile = "important_file";
|
||||
keepFileData = "important_data";
|
||||
localRepo = "/root/back:up";
|
||||
archiveName = "my_archive";
|
||||
remoteRepo = "borg@server:."; # No need to specify path
|
||||
privateKey = pkgs.writeText "id_ed25519" ''
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBx8UB04Q6Q/fwDFjakHq904PYFzG9pU2TJ9KXpaPMcrwAAAJB+cF5HfnBe
|
||||
RwAAAAtzc2gtZWQyNTUxOQAAACBx8UB04Q6Q/fwDFjakHq904PYFzG9pU2TJ9KXpaPMcrw
|
||||
AAAEBN75NsJZSpt63faCuaD75Unko0JjlSDxMhYHAPJk2/xXHxQHThDpD9/AMWNqQer3Tg
|
||||
9gXMb2lTZMn0pelo8xyvAAAADXJzY2h1ZXR6QGt1cnQ=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
'';
|
||||
publicKey = ''
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHHxQHThDpD9/AMWNqQer3Tg9gXMb2lTZMn0pelo8xyv root@client
|
||||
'';
|
||||
privateKeyAppendOnly = pkgs.writeText "id_ed25519" ''
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBacZuz1ELGQdhI7PF6dGFafCDlvh8pSEc4cHjkW0QjLwAAAJC9YTxxvWE8
|
||||
cQAAAAtzc2gtZWQyNTUxOQAAACBacZuz1ELGQdhI7PF6dGFafCDlvh8pSEc4cHjkW0QjLw
|
||||
AAAEAAhV7wTl5dL/lz+PF/d4PnZXuG1Id6L/mFEiGT1tZsuFpxm7PUQsZB2Ejs8Xp0YVp8
|
||||
IOW+HylIRzhweORbRCMvAAAADXJzY2h1ZXR6QGt1cnQ=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
'';
|
||||
publicKeyAppendOnly = ''
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpxm7PUQsZB2Ejs8Xp0YVp8IOW+HylIRzhweORbRCMv root@client
|
||||
'';
|
||||
|
||||
in {
|
||||
name = "borgbackup";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ mic92 ];
|
||||
meta = with pkgs.stdenv.lib; {
|
||||
maintainers = with maintainers; [ dotlambda ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
machine = { config, pkgs, ... }: {
|
||||
environment.systemPackages = [ pkgs.borgbackup ];
|
||||
client = { config, pkgs, ... }: {
|
||||
services.borgbackup.jobs = {
|
||||
|
||||
local = rec {
|
||||
paths = dataDir;
|
||||
repo = localRepo;
|
||||
preHook = ''
|
||||
# Don't append a timestamp
|
||||
archiveName="${archiveName}"
|
||||
'';
|
||||
encryption = {
|
||||
mode = "repokey";
|
||||
inherit passphrase;
|
||||
};
|
||||
compression = "auto,zlib,9";
|
||||
prune.keep = {
|
||||
within = "1y";
|
||||
yearly = 5;
|
||||
};
|
||||
exclude = [ "*/${excludeFile}" ];
|
||||
postHook = "echo post";
|
||||
startAt = [ ]; # Do not run automatically
|
||||
};
|
||||
|
||||
remote = {
|
||||
paths = dataDir;
|
||||
repo = remoteRepo;
|
||||
encryption.mode = "none";
|
||||
startAt = [ ];
|
||||
environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519";
|
||||
};
|
||||
|
||||
remoteAppendOnly = {
|
||||
paths = dataDir;
|
||||
repo = remoteRepo;
|
||||
encryption.mode = "none";
|
||||
startAt = [ ];
|
||||
environment.BORG_RSH = "ssh -oStrictHostKeyChecking=no -i /root/id_ed25519.appendOnly";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
server = { config, pkgs, ... }: {
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
passwordAuthentication = false;
|
||||
challengeResponseAuthentication = false;
|
||||
};
|
||||
|
||||
services.borgbackup.repos.repo1 = {
|
||||
authorizedKeys = [ publicKey ];
|
||||
path = "/data/borgbackup";
|
||||
};
|
||||
|
||||
# Second repo to make sure the authorizedKeys options are merged correctly
|
||||
services.borgbackup.repos.repo2 = {
|
||||
authorizedKeysAppendOnly = [ publicKeyAppendOnly ];
|
||||
path = "/data/borgbackup";
|
||||
quota = ".5G";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
my $borg = "BORG_PASSPHRASE=supersecret borg";
|
||||
$machine->succeed("$borg init --encryption=repokey /tmp/backup");
|
||||
$machine->succeed("mkdir /tmp/data/ && echo 'data' >/tmp/data/file");
|
||||
$machine->succeed("$borg create --stats /tmp/backup::test /tmp/data");
|
||||
$machine->succeed("$borg extract /tmp/backup::test");
|
||||
$machine->succeed('c=$(cat data/file) && echo "c = $c" >&2 && [[ "$c" == "data" ]]');
|
||||
startAll;
|
||||
|
||||
$client->fail('test -d "${remoteRepo}"');
|
||||
|
||||
$client->succeed("cp ${privateKey} /root/id_ed25519");
|
||||
$client->succeed("chmod 0600 /root/id_ed25519");
|
||||
$client->succeed("cp ${privateKeyAppendOnly} /root/id_ed25519.appendOnly");
|
||||
$client->succeed("chmod 0600 /root/id_ed25519.appendOnly");
|
||||
|
||||
$client->succeed("mkdir -p ${dataDir}");
|
||||
$client->succeed("touch ${dataDir}/${excludeFile}");
|
||||
$client->succeed("echo '${keepFileData}' > ${dataDir}/${keepFile}");
|
||||
|
||||
subtest "local", sub {
|
||||
my $borg = "BORG_PASSPHRASE='${passphrase}' borg";
|
||||
$client->systemctl("start --wait borgbackup-job-local");
|
||||
$client->fail("systemctl is-failed borgbackup-job-local");
|
||||
# Make sure exactly one archive has been created
|
||||
$client->succeed("c=\$($borg list '${localRepo}' | wc -l) && [[ \$c == '1' ]]");
|
||||
# Make sure excludeFile has been excluded
|
||||
$client->fail("$borg list '${localRepo}::${archiveName}' | grep -qF '${excludeFile}'");
|
||||
# Make sure keepFile has the correct content
|
||||
$client->succeed("$borg extract '${localRepo}::${archiveName}'");
|
||||
$client->succeed('c=$(cat ${dataDir}/${keepFile}) && [[ "$c" == "${keepFileData}" ]]');
|
||||
};
|
||||
|
||||
subtest "remote", sub {
|
||||
my $borg = "BORG_RSH='ssh -oStrictHostKeyChecking=no -i /root/id_ed25519' borg";
|
||||
$server->waitForUnit("sshd.service");
|
||||
$client->waitForUnit("network.target");
|
||||
$client->systemctl("start --wait borgbackup-job-remote");
|
||||
$client->fail("systemctl is-failed borgbackup-job-remote");
|
||||
|
||||
# Make sure we can't access repos other than the specified one
|
||||
$client->fail("$borg list borg\@server:wrong");
|
||||
|
||||
#TODO: Make sure that data is actually deleted
|
||||
};
|
||||
|
||||
subtest "remoteAppendOnly", sub {
|
||||
my $borg = "BORG_RSH='ssh -oStrictHostKeyChecking=no -i /root/id_ed25519.appendOnly' borg";
|
||||
$server->waitForUnit("sshd.service");
|
||||
$client->waitForUnit("network.target");
|
||||
$client->systemctl("start --wait borgbackup-job-remoteAppendOnly");
|
||||
$client->fail("systemctl is-failed borgbackup-job-remoteAppendOnly");
|
||||
|
||||
# Make sure we can't access repos other than the specified one
|
||||
$client->fail("$borg list borg\@server:wrong");
|
||||
|
||||
#TODO: Make sure that data is not actually deleted
|
||||
};
|
||||
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -138,8 +138,8 @@ let
|
|||
boulder = let
|
||||
owner = "letsencrypt";
|
||||
repo = "boulder";
|
||||
rev = "9866abab8962a591f06db457a4b84c518cc88243";
|
||||
version = "20170510";
|
||||
rev = "9c6a1f2adc4c26d925588f5ae366cfd4efb7813a";
|
||||
version = "20180129";
|
||||
|
||||
in pkgs.buildGoPackage rec {
|
||||
name = "${repo}-${version}";
|
||||
|
@ -147,7 +147,7 @@ let
|
|||
src = pkgs.fetchFromGitHub {
|
||||
name = "${name}-src";
|
||||
inherit rev owner repo;
|
||||
sha256 = "170m5cjngbrm36wi7wschqw8jzs7kxpcyzmshq3pcrmcpigrhna1";
|
||||
sha256 = "09kszswrifm9rc6idfaq0p1mz5w21as2qbc8gd5pphrq9cf9pn55";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
|
@ -168,6 +168,18 @@ let
|
|||
cat "${snakeOilCa}/ca.pem" > test/test-ca.pem
|
||||
'';
|
||||
|
||||
# Until vendored pkcs11 is go 1.9 compatible
|
||||
preBuild = ''
|
||||
rm -r go/src/github.com/letsencrypt/boulder/vendor/github.com/miekg/pkcs11
|
||||
'';
|
||||
|
||||
extraSrcs = map mkGoDep [
|
||||
{ goPackagePath = "github.com/miekg/pkcs11";
|
||||
rev = "6dbd569b952ec150d1425722dbbe80f2c6193f83";
|
||||
sha256 = "1m8g6fx7df6hf6q6zsbyw1icjmm52dmsx28rgb0h930wagvngfwb";
|
||||
}
|
||||
];
|
||||
|
||||
goPackagePath = "github.com/${owner}/${repo}";
|
||||
buildInputs = [ pkgs.libtool ];
|
||||
};
|
||||
|
@ -284,7 +296,11 @@ let
|
|||
ocsp-updater.after = [ "boulder-publisher" ];
|
||||
ocsp-responder.args = "--config ${cfgDir}/ocsp-responder.json";
|
||||
ct-test-srv = {};
|
||||
mail-test-srv.args = "--closeFirst 5";
|
||||
mail-test-srv.args = let
|
||||
key = "${boulderSource}/test/mail-test-srv/minica-key.pem";
|
||||
crt = "${boulderSource}/test/mail-test-srv/minica.pem";
|
||||
in
|
||||
"--closeFirst 5 --cert ${crt} --key ${key}";
|
||||
};
|
||||
|
||||
commonPath = [ softhsm pkgs.mariadb goose boulder ];
|
||||
|
|
|
@ -20,7 +20,7 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||
containers.foo.config = {};
|
||||
};
|
||||
};
|
||||
in [ pkgs.stdenv emptyContainer.config.containers.foo.path ];
|
||||
in [ pkgs.stdenv emptyContainer.config.containers.foo.path pkgs.libxslt ];
|
||||
};
|
||||
|
||||
testScript =
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Test for NixOS' container support.
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
name = "containers-bridge";
|
||||
name = "containers-tmpfs";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ ckampka ];
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ import ./make-test.nix ({ pkgs, ... }: {
|
|||
docker =
|
||||
{ config, pkgs, ... }: {
|
||||
virtualisation = {
|
||||
diskSize = 1024;
|
||||
diskSize = 2048;
|
||||
docker.enable = true;
|
||||
};
|
||||
};
|
||||
|
@ -21,19 +21,29 @@ import ./make-test.nix ({ pkgs, ... }: {
|
|||
$docker->waitForUnit("sockets.target");
|
||||
|
||||
$docker->succeed("docker load --input='${pkgs.dockerTools.examples.bash}'");
|
||||
$docker->succeed("docker run ${pkgs.dockerTools.examples.bash.imageName} /bin/bash --version");
|
||||
$docker->succeed("docker run --rm ${pkgs.dockerTools.examples.bash.imageName} /bin/bash --version");
|
||||
$docker->succeed("docker rmi ${pkgs.dockerTools.examples.bash.imageName}");
|
||||
|
||||
# Check if the nix store is correctly initialized by listing dependencies of the installed Nix binary
|
||||
$docker->succeed("docker load --input='${pkgs.dockerTools.examples.nix}'");
|
||||
$docker->succeed("docker run ${pkgs.dockerTools.examples.nix.imageName} /bin/nix-store -qR ${pkgs.nix}");
|
||||
$docker->succeed("docker run --rm ${pkgs.dockerTools.examples.nix.imageName} /bin/nix-store -qR ${pkgs.nix}");
|
||||
$docker->succeed("docker rmi ${pkgs.dockerTools.examples.nix.imageName}");
|
||||
|
||||
# To test the pullImage tool
|
||||
$docker->succeed("docker load --input='${pkgs.dockerTools.examples.nixFromDockerHub}'");
|
||||
$docker->succeed("docker run nixos/nix:1.11 nix-store --version");
|
||||
$docker->succeed("docker run --rm nixos/nix:1.11 nix-store --version");
|
||||
$docker->succeed("docker rmi nixos/nix:1.11");
|
||||
|
||||
# To test runAsRoot and entry point
|
||||
$docker->succeed("docker load --input='${pkgs.dockerTools.examples.nginx}'");
|
||||
$docker->succeed("docker run --name nginx -d -p 8000:80 ${pkgs.dockerTools.examples.nginx.imageName}");
|
||||
$docker->waitUntilSucceeds('curl http://localhost:8000/');
|
||||
$docker->succeed("docker rm --force nginx");
|
||||
$docker->succeed("docker rmi '${pkgs.dockerTools.examples.nginx.imageName}'");
|
||||
|
||||
# An pulled image can be used as base image
|
||||
$docker->succeed("docker load --input='${pkgs.dockerTools.examples.onTopOfPulledImage}'");
|
||||
$docker->succeed("docker run --rm ontopofpulledimage hello");
|
||||
$docker->succeed("docker rmi ontopofpulledimage");
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -20,6 +20,6 @@ import ./make-test.nix ({ lib, ... }:
|
|||
$machine->start;
|
||||
$machine->waitForUnit("grafana.service");
|
||||
$machine->waitForOpenPort(3000);
|
||||
$machine->succeed("curl -sS http://127.0.0.1:3000/");
|
||||
$machine->succeed("curl -sSfL http://127.0.0.1:3000/");
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -69,13 +69,20 @@ let
|
|||
let
|
||||
iface = if grubVersion == 1 then "ide" else "virtio";
|
||||
isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi);
|
||||
|
||||
# FIXME don't duplicate the -enable-kvm etc. flags here yet again!
|
||||
qemuFlags =
|
||||
(if system == "x86_64-linux" then "-m 768 " else "-m 512 ") +
|
||||
(optionalString (system == "x86_64-linux") "-cpu kvm64 ");
|
||||
(optionalString (system == "x86_64-linux") "-cpu kvm64 ") +
|
||||
(optionalString (system == "aarch64-linux") "-enable-kvm -machine virt,gic-version=host -cpu host ");
|
||||
|
||||
hdFlags = ''hda => "vm-state-machine/machine.qcow2", hdaInterface => "${iface}", ''
|
||||
+ optionalString isEfi ''bios => "${pkgs.OVMF.fd}/FV/OVMF.fd", '';
|
||||
in
|
||||
''
|
||||
+ optionalString isEfi (if pkgs.stdenv.isAarch64
|
||||
then ''bios => "${pkgs.OVMF.fd}/FV/QEMU_EFI.fd", ''
|
||||
else ''bios => "${pkgs.OVMF.fd}/FV/OVMF.fd", '');
|
||||
in if !isEfi && !(pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) then
|
||||
throw "Non-EFI boot methods are only supported on i686 / x86_64"
|
||||
else ''
|
||||
$machine->start;
|
||||
|
||||
# Make sure that we get a login prompt etc.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue