commit
163496fb73
@ -0,0 +1,23 @@ |
||||
--[[ |
||||
Converts Code AST nodes produced by pandoc’s DocBook reader |
||||
from citerefentry elements into AST for corresponding role |
||||
for reStructuredText. |
||||
|
||||
We use subset of MyST syntax (CommonMark with features from rST) |
||||
so let’s use the rST AST for rST features. |
||||
|
||||
Reference: https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-manpage |
||||
]] |
||||
|
||||
function Code(elem) |
||||
elem.classes = elem.classes:map(function (x) |
||||
if x == 'citerefentry' then |
||||
elem.attributes['role'] = 'manpage' |
||||
return 'interpreted-text' |
||||
else |
||||
return x |
||||
end |
||||
end) |
||||
|
||||
return elem |
||||
end |
@ -1,3 +1,13 @@ |
||||
--[[ |
||||
Converts Link AST nodes with empty label to DocBook xref elements. |
||||
|
||||
This is a temporary script to be able use cross-references conveniently |
||||
using syntax taken from MyST, while we still use docbook-xsl |
||||
for generating the documentation. |
||||
|
||||
Reference: https://myst-parser.readthedocs.io/en/latest/using/syntax.html#targets-and-cross-referencing |
||||
]] |
||||
|
||||
local function starts_with(start, str) |
||||
return str:sub(1, #start) == start |
||||
end |
@ -0,0 +1,36 @@ |
||||
--[[ |
||||
Converts AST for reStructuredText roles into corresponding |
||||
DocBook elements. |
||||
|
||||
Currently, only a subset of roles is supported. |
||||
|
||||
Reference: |
||||
List of roles: |
||||
https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html |
||||
manpage: |
||||
https://tdg.docbook.org/tdg/5.1/citerefentry.html |
||||
file: |
||||
https://tdg.docbook.org/tdg/5.1/filename.html |
||||
]] |
||||
|
||||
function Code(elem) |
||||
if elem.classes:includes('interpreted-text') then |
||||
local tag = nil |
||||
local content = elem.text |
||||
if elem.attributes['role'] == 'manpage' then |
||||
tag = 'citerefentry' |
||||
local title, volnum = content:match('^(.+)%((%w+)%)$') |
||||
if title == nil then |
||||
-- No volnum in parentheses. |
||||
title = content |
||||
end |
||||
content = '<refentrytitle>' .. title .. '</refentrytitle>' .. (volnum ~= nil and ('<manvolnum>' .. volnum .. '</manvolnum>') or '') |
||||
elseif elem.attributes['role'] == 'file' then |
||||
tag = 'filename' |
||||
end |
||||
|
||||
if tag ~= nil then |
||||
return pandoc.RawInline('docbook', '<' .. tag .. '>' .. content .. '</' .. tag .. '>') |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,18 @@ |
||||
--[[ |
||||
Turns a manpage reference into a link, when a mapping is defined |
||||
in the unix-man-urls.lua file. |
||||
]] |
||||
|
||||
local man_urls = { |
||||
["tmpfiles.d(5)"] = "https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html", |
||||
["nix.conf(5)"] = "https://nixos.org/manual/nix/stable/#sec-conf-file", |
||||
["systemd.time(7)"] = "https://www.freedesktop.org/software/systemd/man/systemd.time.html", |
||||
["systemd.timer(5)"] = "https://www.freedesktop.org/software/systemd/man/systemd.timer.html", |
||||
} |
||||
|
||||
function Code(elem) |
||||
local is_man_role = elem.classes:includes('interpreted-text') and elem.attributes['role'] == 'manpage' |
||||
if is_man_role and man_urls[elem.text] ~= nil then |
||||
return pandoc.Link(elem, man_urls[elem.text]) |
||||
end |
||||
end |
@ -0,0 +1,29 @@ |
||||
--[[ |
||||
Replaces Str AST nodes containing {role}, followed by a Code node |
||||
by a Code node with attrs that would be produced by rST reader |
||||
from the role syntax. |
||||
|
||||
This is to emulate MyST syntax in Pandoc. |
||||
(MyST is a CommonMark flavour with rST features mixed in.) |
||||
|
||||
Reference: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point |
||||
]] |
||||
|
||||
function Inlines(inlines) |
||||
for i = #inlines-1,1,-1 do |
||||
local first = inlines[i] |
||||
local second = inlines[i+1] |
||||
local correct_tags = first.tag == 'Str' and second.tag == 'Code' |
||||
if correct_tags then |
||||
-- docutils supports alphanumeric strings separated by [-._:] |
||||
-- We are slightly more liberal for simplicity. |
||||
local role = first.text:match('^{([-._+:%w]+)}$') |
||||
if role ~= nil then |
||||
inlines:remove(i) |
||||
second.attributes['role'] = role |
||||
second.classes:insert('interpreted-text') |
||||
end |
||||
end |
||||
end |
||||
return inlines |
||||
end |
@ -0,0 +1,25 @@ |
||||
--[[ |
||||
Replaces Code nodes with attrs that would be produced by rST reader |
||||
from the role syntax by a Str AST node containing {role}, followed by a Code node. |
||||
|
||||
This is to emulate MyST syntax in Pandoc. |
||||
(MyST is a CommonMark flavour with rST features mixed in.) |
||||
|
||||
Reference: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point |
||||
]] |
||||
|
||||
function Code(elem) |
||||
local role = elem.attributes['role'] |
||||
|
||||
if elem.classes:includes('interpreted-text') and role ~= nil then |
||||
elem.classes = elem.classes:filter(function (c) |
||||
return c ~= 'interpreted-text' |
||||
end) |
||||
elem.attributes['role'] = nil |
||||
|
||||
return { |
||||
pandoc.Str('{' .. role .. '}'), |
||||
elem, |
||||
} |
||||
end |
||||
end |
@ -0,0 +1,88 @@ |
||||
#! /usr/bin/env nix-shell |
||||
#! nix-shell -I nixpkgs=. -i bash -p pandoc |
||||
|
||||
# This script is temporarily needed while we transition the manual to |
||||
# CommonMark. It converts DocBook files into our CommonMark flavour. |
||||
|
||||
debug= |
||||
files=() |
||||
|
||||
while [ "$#" -gt 0 ]; do |
||||
i="$1"; shift 1 |
||||
case "$i" in |
||||
--debug) |
||||
debug=1 |
||||
;; |
||||
*) |
||||
files+=("$i") |
||||
;; |
||||
esac |
||||
done |
||||
|
||||
echo "WARNING: This is an experimental script and might not preserve all formatting." > /dev/stderr |
||||
echo "Please report any issues you discover." > /dev/stderr |
||||
|
||||
outExtension="md" |
||||
if [[ $debug ]]; then |
||||
outExtension="json" |
||||
fi |
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" |
||||
|
||||
# NOTE: Keep in sync with Nixpkgs manual (/doc/Makefile). |
||||
# TODO: Remove raw-attribute when we can get rid of DocBook altogether. |
||||
pandoc_commonmark_enabled_extensions=+attributes+fenced_divs+footnotes+bracketed_spans+definition_lists+pipe_tables+raw_attribute |
||||
targetLang="commonmark${pandoc_commonmark_enabled_extensions}+smart" |
||||
if [[ $debug ]]; then |
||||
targetLang=json |
||||
fi |
||||
pandoc_flags=( |
||||
# Not needed: |
||||
# - diagram-generator.lua (we do not support that in NixOS manual to limit dependencies) |
||||
# - media extraction (was only required for diagram generator) |
||||
# - myst-reader/roles.lua (only relevant for MyST → DocBook) |
||||
# - link-unix-man-references.lua (links should only be added to display output) |
||||
# - docbook-writer/rst-roles.lua (only relevant for → DocBook) |
||||
# - docbook-writer/labelless-link-is-xref.lua (only relevant for → DocBook) |
||||
"--lua-filter=$DIR/../../doc/build-aux/pandoc-filters/docbook-reader/citerefentry-to-rst-role.lua" |
||||
"--lua-filter=$DIR/../../doc/build-aux/pandoc-filters/myst-writer/roles.lua" |
||||
"--lua-filter=$DIR/doc/unknown-code-language.lua" |
||||
-f docbook |
||||
-t "$targetLang" |
||||
--tab-stop=2 |
||||
--wrap=none |
||||
) |
||||
|
||||
for file in "${files[@]}"; do |
||||
if [[ ! -f "$file" ]]; then |
||||
echo "db-to-md.sh: $file does not exist" > /dev/stderr |
||||
exit 1 |
||||
else |
||||
rootElement=$(xmllint --xpath 'name(//*)' "$file") |
||||
|
||||
if [[ $rootElement = chapter ]]; then |
||||
extension=".chapter.$outExtension" |
||||
elif [[ $rootElement = section ]]; then |
||||
extension=".section.$outExtension" |
||||
else |
||||
echo "db-to-md.sh: $file contains an unsupported root element $rootElement" > /dev/stderr |
||||
exit 1 |
||||
fi |
||||
|
||||
outFile="${file%".section.xml"}" |
||||
outFile="${outFile%".chapter.xml"}" |
||||
outFile="${outFile%".xml"}$extension" |
||||
temp1=$(mktemp) |
||||
$DIR/doc/escape-code-markup.py "$file" "$temp1" |
||||
if [[ $debug ]]; then |
||||
echo "Converted $file to $temp1" > /dev/stderr |
||||
fi |
||||
temp2=$(mktemp) |
||||
$DIR/doc/replace-xrefs-by-empty-links.py "$temp1" "$temp2" |
||||
if [[ $debug ]]; then |
||||
echo "Converted $temp1 to $temp2" > /dev/stderr |
||||
fi |
||||
pandoc "$temp2" -o "$outFile" "${pandoc_flags[@]}" |
||||
echo "Converted $file to $outFile" > /dev/stderr |
||||
fi |
||||
done |
@ -0,0 +1,97 @@ |
||||
#! /usr/bin/env nix-shell |
||||
#! nix-shell -I nixpkgs=channel:nixos-unstable -i python3 -p python3 -p python3.pkgs.lxml |
||||
|
||||
""" |
||||
Pandoc will strip any markup within code elements so |
||||
let’s escape them so that they can be handled manually. |
||||
""" |
||||
|
||||
import lxml.etree as ET |
||||
import re |
||||
import sys |
||||
|
||||
def replace_element_by_text(el: ET.Element, text: str) -> None: |
||||
""" |
||||
Author: bernulf |
||||
Source: https://stackoverflow.com/a/10520552/160386 |
||||
SPDX-License-Identifier: CC-BY-SA-3.0 |
||||
""" |
||||
text = text + (el.tail or "") |
||||
parent = el.getparent() |
||||
if parent is not None: |
||||
previous = el.getprevious() |
||||
if previous is not None: |
||||
previous.tail = (previous.tail or "") + text |
||||
else: |
||||
parent.text = (parent.text or "") + text |
||||
parent.remove(el) |
||||
|
||||
DOCBOOK_NS = "http://docbook.org/ns/docbook" |
||||
|
||||
# List of elements that pandoc’s DocBook reader strips markup from. |
||||
# https://github.com/jgm/pandoc/blob/master/src/Text/Pandoc/Readers/DocBook.hs |
||||
code_elements = [ |
||||
# CodeBlock |
||||
"literallayout", |
||||
"screen", |
||||
"programlisting", |
||||
# Code (inline) |
||||
"classname", |
||||
"code", |
||||
"filename", |
||||
"envar", |
||||
"literal", |
||||
"computeroutput", |
||||
"prompt", |
||||
"parameter", |
||||
"option", |
||||
"markup", |
||||
"wordasword", |
||||
"command", |
||||
"varname", |
||||
"function", |
||||
"type", |
||||
"symbol", |
||||
"constant", |
||||
"userinput", |
||||
"systemitem", |
||||
] |
||||
|
||||
XMLNS_REGEX = re.compile(r'\s+xmlns(?::[^=]+)?="[^"]*"') |
||||
ROOT_ELEMENT_REGEX = re.compile(r'^\s*<[^>]+>') |
||||
|
||||
def remove_xmlns(match: re.Match) -> str: |
||||
""" |
||||
Removes xmlns attributes. |
||||
|
||||
Expects a match containing an opening tag. |
||||
""" |
||||
return XMLNS_REGEX.sub('', match.group(0)) |
||||
|
||||
if __name__ == '__main__': |
||||
assert len(sys.argv) >= 3, "usage: escape-code-markup.py <input> <output>" |
||||
|
||||
tree = ET.parse(sys.argv[1]) |
||||
name_predicate = " or ".join([f"local-name()='{el}'" for el in code_elements]) |
||||
|
||||
for markup in tree.xpath(f"//*[({name_predicate}) and namespace-uri()='{DOCBOOK_NS}']/*"): |
||||
text = ET.tostring(markup, encoding=str) |
||||
|
||||
# tostring adds xmlns attributes to the element we want to stringify |
||||
# as if it was supposed to be usable standalone. |
||||
# We are just converting it to CDATA so we do not care. |
||||
# Let’s strip the namespace declarations to keep the code clean. |
||||
# |
||||
# Note that this removes even namespaces that were potentially |
||||
# in the original file. Though, that should be very rare – |
||||
# most of the time, we will stringify empty DocBook elements |
||||
# like <xref> or <co> or, at worst, <link> with xlink:href attribute. |
||||
# |
||||
# Also note that the regex expects the root element to be first |
||||
# thing in the string. But that should be fine, the tostring method |
||||
# does not produce XML declaration or doctype by default. |
||||
text = ROOT_ELEMENT_REGEX.sub(remove_xmlns, text) |
||||
|
||||
replace_element_by_text(markup, text) |
||||
|
||||
tree.write(sys.argv[2]) |
@ -0,0 +1,32 @@ |
||||
#! /usr/bin/env nix-shell |
||||
#! nix-shell -I nixpkgs=channel:nixos-unstable -i python3 -p python3 -p python3.pkgs.lxml |
||||
|
||||
""" |
||||
Pandoc will try to resolve xrefs and replace them with regular links. |
||||
let’s replace them with links with empty labels which MyST |
||||
and our pandoc filters recognize as cross-references. |
||||
""" |
||||
|
||||
import lxml.etree as ET |
||||
import sys |
||||
|
||||
XLINK_NS = "http://www.w3.org/1999/xlink" |
||||
|
||||
ns = { |
||||
"db": "http://docbook.org/ns/docbook", |
||||
} |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
assert len(sys.argv) >= 3, "usage: replace-xrefs-by-empty-links.py <input> <output>" |
||||
|
||||
tree = ET.parse(sys.argv[1]) |
||||
for xref in tree.findall(".//db:xref", ns): |
||||
text = ET.tostring(xref, encoding=str) |
||||
parent = xref.getparent() |
||||
link = parent.makeelement('link') |
||||
target_name = xref.get("linkend") |
||||
link.set(f"{{{XLINK_NS}}}href", f"#{target_name}") |
||||
parent.replace(xref, link) |
||||
|
||||
tree.write(sys.argv[2]) |
@ -0,0 +1,12 @@ |
||||
--[[ |
||||
Adds “unknown” class to CodeBlock AST nodes without any classes. |
||||
|
||||
This will cause Pandoc to use fenced code block, which we prefer. |
||||
]] |
||||
|
||||
function CodeBlock(elem) |
||||
if #elem.classes == 0 then |
||||
elem.classes:insert('unknown') |
||||
return elem |
||||
end |
||||
end |
|
@ -1,12 +1,13 @@ |
||||
{ nixpkgs ? import ../.. { } |
||||
}: |
||||
with nixpkgs; |
||||
let |
||||
pyEnv = python3.withPackages(ps: [ ps.GitPython ]); |
||||
in |
||||
mkShell { |
||||
packages = [ |
||||
bash |
||||
pyEnv |
||||
luarocks-nix |
||||
nix-prefetch-scripts |
||||
parallel |
||||
]; |
||||
LUAROCKS_NIXPKGS_PATH = toString nixpkgs.path; |
||||
} |
||||
|
@ -0,0 +1,62 @@ |
||||
# Cleaning the Nix Store {#sec-nix-gc} |
||||
|
||||
Nix has a purely functional model, meaning that packages are never |
||||
upgraded in place. Instead new versions of packages end up in a |
||||
different location in the Nix store (`/nix/store`). You should |
||||
periodically run Nix's *garbage collector* to remove old, unreferenced |
||||
packages. This is easy: |
||||
|
||||
```ShellSession |
||||
$ nix-collect-garbage |
||||
``` |
||||
|
||||
Alternatively, you can use a systemd unit that does the same in the |
||||
background: |
||||
|
||||
```ShellSession |
||||
# systemctl start nix-gc.service |
||||
``` |
||||
|
||||
You can tell NixOS in `configuration.nix` to run this unit automatically |
||||
at certain points in time, for instance, every night at 03:15: |
||||
|
||||
```nix |
||||
nix.gc.automatic = true; |
||||
nix.gc.dates = "03:15"; |
||||
``` |
||||
|
||||
The commands above do not remove garbage collector roots, such as old |
||||
system configurations. Thus they do not remove the ability to roll back |
||||
to previous configurations. The following command deletes old roots, |
||||
removing the ability to roll back to them: |
||||
|
||||
```ShellSession |
||||
$ nix-collect-garbage -d |
||||
``` |
||||
|
||||
You can also do this for specific profiles, e.g. |
||||
|
||||
```ShellSession |
||||
$ nix-env -p /nix/var/nix/profiles/per-user/eelco/profile --delete-generations old |
||||
``` |
||||
|
||||
Note that NixOS system configurations are stored in the profile |
||||
`/nix/var/nix/profiles/system`. |
||||
|
||||
Another way to reclaim disk space (often as much as 40% of the size of |
||||
the Nix store) is to run Nix's store optimiser, which seeks out |
||||
identical files in the store and replaces them with hard links to a |
||||
single copy. |
||||
|
||||
```ShellSession |
||||
$ nix-store --optimise |
||||
``` |
||||
|
||||
Since this command needs to read the entire Nix store, it can take quite |
||||
a while to finish. |
||||
|
||||
## NixOS Boot Entries {#sect-nixos-gc-boot-entries} |
||||
|
||||
If your `/boot` partition runs out of space, after clearing old profiles |
||||
you must rebuild your system with `nixos-rebuild` to update the `/boot` |
||||
partition and clear space. |
@ -1,63 +0,0 @@ |
||||
<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="sec-nix-gc"> |
||||
<title>Cleaning the Nix Store</title> |
||||
<para> |
||||
Nix has a purely functional model, meaning that packages are never upgraded |
||||
in place. Instead new versions of packages end up in a different location in |
||||
the Nix store (<filename>/nix/store</filename>). You should periodically run |
||||
Nix’s <emphasis>garbage collector</emphasis> to remove old, unreferenced |
||||
packages. This is easy: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-collect-garbage |
||||
</screen> |
||||
Alternatively, you can use a systemd unit that does the same in the |
||||
background: |
||||
<screen> |
||||
<prompt># </prompt>systemctl start nix-gc.service |
||||
</screen> |
||||
You can tell NixOS in <filename>configuration.nix</filename> to run this unit |
||||
automatically at certain points in time, for instance, every night at 03:15: |
||||
<programlisting> |
||||
<xref linkend="opt-nix.gc.automatic"/> = true; |
||||
<xref linkend="opt-nix.gc.dates"/> = "03:15"; |
||||
</programlisting> |
||||
</para> |
||||
<para> |
||||
The commands above do not remove garbage collector roots, such as old system |
||||
configurations. Thus they do not remove the ability to roll back to previous |
||||
configurations. The following command deletes old roots, removing the ability |
||||
to roll back to them: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-collect-garbage -d |
||||
</screen> |
||||
You can also do this for specific profiles, e.g. |
||||
<screen> |
||||
<prompt>$ </prompt>nix-env -p /nix/var/nix/profiles/per-user/eelco/profile --delete-generations old |
||||
</screen> |
||||
Note that NixOS system configurations are stored in the profile |
||||
<filename>/nix/var/nix/profiles/system</filename>. |
||||
</para> |
||||
<para> |
||||
Another way to reclaim disk space (often as much as 40% of the size of the |
||||
Nix store) is to run Nix’s store optimiser, which seeks out identical files |
||||
in the store and replaces them with hard links to a single copy. |
||||
<screen> |
||||
<prompt>$ </prompt>nix-store --optimise |
||||
</screen> |
||||
Since this command needs to read the entire Nix store, it can take quite a |
||||
while to finish. |
||||
</para> |
||||
<section xml:id="sect-nixos-gc-boot-entries"> |
||||
<title>NixOS Boot Entries</title> |
||||
|
||||
<para> |
||||
If your <filename>/boot</filename> partition runs out of space, after |
||||
clearing old profiles you must rebuild your system with |
||||
<literal>nixos-rebuild</literal> to update the <filename>/boot</filename> |
||||
partition and clear space. |
||||
</para> |
||||
</section> |
||||
</chapter> |
@ -0,0 +1,44 @@ |
||||
# Container Networking {#sec-container-networking} |
||||
|
||||
When you create a container using `nixos-container create`, it gets it |
||||
own private IPv4 address in the range `10.233.0.0/16`. You can get the |
||||
container's IPv4 address as follows: |
||||
|
||||
```ShellSession |
||||
# nixos-container show-ip foo |
||||
10.233.4.2 |
||||
|
||||
$ ping -c1 10.233.4.2 |
||||
64 bytes from 10.233.4.2: icmp_seq=1 ttl=64 time=0.106 ms |
||||
``` |
||||
|
||||
Networking is implemented using a pair of virtual Ethernet devices. The |
||||
network interface in the container is called `eth0`, while the matching |
||||
interface in the host is called `ve-container-name` (e.g., `ve-foo`). |
||||
The container has its own network namespace and the `CAP_NET_ADMIN` |
||||
capability, so it can perform arbitrary network configuration such as |
||||
setting up firewall rules, without affecting or having access to the |
||||
host's network. |
||||
|
||||
By default, containers cannot talk to the outside network. If you want |
||||
that, you should set up Network Address Translation (NAT) rules on the |
||||
host to rewrite container traffic to use your external IP address. This |
||||
can be accomplished using the following configuration on the host: |
||||
|
||||
```nix |
||||
networking.nat.enable = true; |
||||
networking.nat.internalInterfaces = ["ve-+"]; |
||||
networking.nat.externalInterface = "eth0"; |
||||
``` |
||||
|
||||
where `eth0` should be replaced with the desired external interface. |
||||
Note that `ve-+` is a wildcard that matches all container interfaces. |
||||
|
||||
If you are using Network Manager, you need to explicitly prevent it from |
||||
managing container interfaces: |
||||
|
||||
```nix |
||||
networking.networkmanager.unmanaged = [ "interface-name:ve-*" ]; |
||||
``` |
||||
|
||||
You may need to restart your system for the changes to take effect. |
@ -1,59 +0,0 @@ |
||||
<section 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="sec-container-networking"> |
||||
<title>Container Networking</title> |
||||
|
||||
<para> |
||||
When you create a container using <literal>nixos-container create</literal>, |
||||
it gets it own private IPv4 address in the range |
||||
<literal>10.233.0.0/16</literal>. You can get the container’s IPv4 address |
||||
as follows: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container show-ip foo |
||||
10.233.4.2 |
||||
|
||||
<prompt>$ </prompt>ping -c1 10.233.4.2 |
||||
64 bytes from 10.233.4.2: icmp_seq=1 ttl=64 time=0.106 ms |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
Networking is implemented using a pair of virtual Ethernet devices. The |
||||
network interface in the container is called <literal>eth0</literal>, while |
||||
the matching interface in the host is called |
||||
<literal>ve-<replaceable>container-name</replaceable></literal> (e.g., |
||||
<literal>ve-foo</literal>). The container has its own network namespace and |
||||
the <literal>CAP_NET_ADMIN</literal> capability, so it can perform arbitrary |
||||
network configuration such as setting up firewall rules, without affecting or |
||||
having access to the host’s network. |
||||
</para> |
||||
|
||||
<para> |
||||
By default, containers cannot talk to the outside network. If you want that, |
||||
you should set up Network Address Translation (NAT) rules on the host to |
||||
rewrite container traffic to use your external IP address. This can be |
||||
accomplished using the following configuration on the host: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.nat.enable"/> = true; |
||||
<xref linkend="opt-networking.nat.internalInterfaces"/> = ["ve-+"]; |
||||
<xref linkend="opt-networking.nat.externalInterface"/> = "eth0"; |
||||
</programlisting> |
||||
where <literal>eth0</literal> should be replaced with the desired external |
||||
interface. Note that <literal>ve-+</literal> is a wildcard that matches all |
||||
container interfaces. |
||||
</para> |
||||
|
||||
<para> |
||||
If you are using Network Manager, you need to explicitly prevent it from |
||||
managing container interfaces: |
||||
<programlisting> |
||||
networking.networkmanager.unmanaged = [ "interface-name:ve-*" ]; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<para> |
||||
You may need to restart your system for the changes to take effect. |
||||
</para> |
||||
</section> |
@ -0,0 +1,28 @@ |
||||
# Container Management {#ch-containers} |
||||
|
||||
NixOS allows you to easily run other NixOS instances as *containers*. |
||||
Containers are a light-weight approach to virtualisation that runs |
||||
software in the container at the same speed as in the host system. NixOS |
||||
containers share the Nix store of the host, making container creation |
||||
very efficient. |
||||
|
||||
::: {.warning} |
||||
Currently, NixOS containers are not perfectly isolated from the host |
||||
system. This means that a user with root access to the container can do |
||||
things that affect the host. So you should not give container root |
||||
access to untrusted users. |
||||
::: |
||||
|
||||
NixOS containers can be created in two ways: imperatively, using the |
||||
command `nixos-container`, and declaratively, by specifying them in your |
||||
`configuration.nix`. The declarative approach implies that containers |
||||
get upgraded along with your host system when you run `nixos-rebuild`, |
||||
which is often not what you want. By contrast, in the imperative |
||||
approach, containers are configured and updated independently from the |
||||
host system. |
||||
|
||||
```{=docbook} |
||||
<xi:include href="imperative-containers.section.xml" /> |
||||
<xi:include href="declarative-containers.section.xml" /> |
||||
<xi:include href="container-networking.section.xml" /> |
||||
``` |
@ -1,34 +0,0 @@ |
||||
<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="ch-containers"> |
||||
<title>Container Management</title> |
||||
<para> |
||||
NixOS allows you to easily run other NixOS instances as |
||||
<emphasis>containers</emphasis>. Containers are a light-weight approach to |
||||
virtualisation that runs software in the container at the same speed as in |
||||
the host system. NixOS containers share the Nix store of the host, making |
||||
container creation very efficient. |
||||
</para> |
||||
<warning> |
||||
<para> |
||||
Currently, NixOS containers are not perfectly isolated from the host system. |
||||
This means that a user with root access to the container can do things that |
||||
affect the host. So you should not give container root access to untrusted |
||||
users. |
||||
</para> |
||||
</warning> |
||||
<para> |
||||
NixOS containers can be created in two ways: imperatively, using the command |
||||
<command>nixos-container</command>, and declaratively, by specifying them in |
||||
your <filename>configuration.nix</filename>. The declarative approach implies |
||||
that containers get upgraded along with your host system when you run |
||||
<command>nixos-rebuild</command>, which is often not what you want. By |
||||
contrast, in the imperative approach, containers are configured and updated |
||||
independently from the host system. |
||||
</para> |
||||
<xi:include href="imperative-containers.xml" /> |
||||
<xi:include href="declarative-containers.xml" /> |
||||
<xi:include href="container-networking.xml" /> |
||||
</chapter> |
@ -0,0 +1,59 @@ |
||||
# Control Groups {#sec-cgroups} |
||||
|
||||
To keep track of the processes in a running system, systemd uses |
||||
*control groups* (cgroups). A control group is a set of processes used |
||||
to allocate resources such as CPU, memory or I/O bandwidth. There can be |
||||
multiple control group hierarchies, allowing each kind of resource to be |
||||
managed independently. |
||||
|
||||
The command `systemd-cgls` lists all control groups in the `systemd` |
||||
hierarchy, which is what systemd uses to keep track of the processes |
||||
belonging to each service or user session: |
||||
|
||||
```ShellSession |
||||
$ systemd-cgls |
||||
├─user |
||||
│ └─eelco |
||||
│ └─c1 |
||||
│ ├─ 2567 -:0 |
||||
│ ├─ 2682 kdeinit4: kdeinit4 Running... |
||||
│ ├─ ... |
||||
│ └─10851 sh -c less -R |
||||
└─system |
||||
├─httpd.service |
||||
│ ├─2444 httpd -f /nix/store/3pyacby5cpr55a03qwbnndizpciwq161-httpd.conf -DNO_DETACH |
||||
│ └─... |
||||
├─dhcpcd.service |
||||
│ └─2376 dhcpcd --config /nix/store/f8dif8dsi2yaa70n03xir8r653776ka6-dhcpcd.conf |
||||
└─ ... |
||||
``` |
||||
|
||||
Similarly, `systemd-cgls cpu` shows the cgroups in the CPU hierarchy, |
||||
which allows per-cgroup CPU scheduling priorities. By default, every |
||||
systemd service gets its own CPU cgroup, while all user sessions are in |
||||
the top-level CPU cgroup. This ensures, for instance, that a thousand |
||||
run-away processes in the `httpd.service` cgroup cannot starve the CPU |
||||
for one process in the `postgresql.service` cgroup. (By contrast, it |
||||
they were in the same cgroup, then the PostgreSQL process would get |
||||
1/1001 of the cgroup's CPU time.) You can limit a service's CPU share in |
||||
`configuration.nix`: |
||||
|
||||
```nix |
||||
systemd.services.httpd.serviceConfig.CPUShares = 512; |
||||
``` |
||||
|
||||
By default, every cgroup has 1024 CPU shares, so this will halve the CPU |
||||
allocation of the `httpd.service` cgroup. |
||||
|
||||
There also is a `memory` hierarchy that controls memory allocation |
||||
limits; by default, all processes are in the top-level cgroup, so any |
||||
service or session can exhaust all available memory. Per-cgroup memory |
||||
limits can be specified in `configuration.nix`; for instance, to limit |
||||
`httpd.service` to 512 MiB of RAM (excluding swap): |
||||
|
||||
```nix |
||||
systemd.services.httpd.serviceConfig.MemoryLimit = "512M"; |
||||
``` |
||||
|
||||
The command `systemd-cgtop` shows a continuously updated list of all |
||||
cgroups with their CPU and memory usage. |
@ -1,65 +0,0 @@ |
||||
<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="sec-cgroups"> |
||||
<title>Control Groups</title> |
||||
<para> |
||||
To keep track of the processes in a running system, systemd uses |
||||
<emphasis>control groups</emphasis> (cgroups). A control group is a set of |
||||
processes used to allocate resources such as CPU, memory or I/O bandwidth. |
||||
There can be multiple control group hierarchies, allowing each kind of |
||||
resource to be managed independently. |
||||
</para> |
||||
<para> |
||||
The command <command>systemd-cgls</command> lists all control groups in the |
||||
<literal>systemd</literal> hierarchy, which is what systemd uses to keep |
||||
track of the processes belonging to each service or user session: |
||||
<screen> |
||||
<prompt>$ </prompt>systemd-cgls |
||||
├─user |
||||
│ └─eelco |
||||
│ └─c1 |
||||
│ ├─ 2567 -:0 |
||||
│ ├─ 2682 kdeinit4: kdeinit4 Running... |
||||
│ ├─ <replaceable>...</replaceable> |
||||
│ └─10851 sh -c less -R |
||||
└─system |
||||
├─httpd.service |
||||
│ ├─2444 httpd -f /nix/store/3pyacby5cpr55a03qwbnndizpciwq161-httpd.conf -DNO_DETACH |
||||
│ └─<replaceable>...</replaceable> |
||||
├─dhcpcd.service |
||||
│ └─2376 dhcpcd --config /nix/store/f8dif8dsi2yaa70n03xir8r653776ka6-dhcpcd.conf |
||||
└─ <replaceable>...</replaceable> |
||||
</screen> |
||||
Similarly, <command>systemd-cgls cpu</command> shows the cgroups in the CPU |
||||
hierarchy, which allows per-cgroup CPU scheduling priorities. By default, |
||||
every systemd service gets its own CPU cgroup, while all user sessions are in |
||||
the top-level CPU cgroup. This ensures, for instance, that a thousand |
||||
run-away processes in the <literal>httpd.service</literal> cgroup cannot |
||||
starve the CPU for one process in the <literal>postgresql.service</literal> |
||||
cgroup. (By contrast, it they were in the same cgroup, then the PostgreSQL |
||||
process would get 1/1001 of the cgroup’s CPU time.) You can limit a |
||||
service’s CPU share in <filename>configuration.nix</filename>: |
||||
<programlisting> |
||||
<link linkend="opt-systemd.services._name_.serviceConfig">systemd.services.httpd.serviceConfig</link>.CPUShares = 512; |
||||
</programlisting> |
||||
By default, every cgroup has 1024 CPU shares, so this will halve the CPU |
||||
allocation of the <literal>httpd.service</literal> cgroup. |
||||
</para> |
||||
<para> |
||||
There also is a <literal>memory</literal> hierarchy that controls memory |
||||
allocation limits; by default, all processes are in the top-level cgroup, so |
||||
any service or session can exhaust all available memory. Per-cgroup memory |
||||
limits can be specified in <filename>configuration.nix</filename>; for |
||||
instance, to limit <literal>httpd.service</literal> to 512 MiB of RAM |
||||
(excluding swap): |
||||
<programlisting> |
||||
<link linkend="opt-systemd.services._name_.serviceConfig">systemd.services.httpd.serviceConfig</link>.MemoryLimit = "512M"; |
||||
</programlisting> |
||||
</para> |
||||
<para> |
||||
The command <command>systemd-cgtop</command> shows a continuously updated |
||||
list of all cgroups with their CPU and memory usage. |
||||
</para> |
||||
</chapter> |
@ -0,0 +1,48 @@ |
||||
# Declarative Container Specification {#sec-declarative-containers} |
||||
|
||||
You can also specify containers and their configuration in the host's |
||||
`configuration.nix`. For example, the following specifies that there |
||||
shall be a container named `database` running PostgreSQL: |
||||
|
||||
```nix |
||||
containers.database = |
||||
{ config = |
||||
{ config, pkgs, ... }: |
||||
{ services.postgresql.enable = true; |
||||
services.postgresql.package = pkgs.postgresql_9_6; |
||||
}; |
||||
}; |
||||
``` |
||||
|
||||
If you run `nixos-rebuild switch`, the container will be built. If the |
||||
container was already running, it will be updated in place, without |
||||
rebooting. The container can be configured to start automatically by |
||||
setting `containers.database.autoStart = true` in its configuration. |
||||
|
||||
By default, declarative containers share the network namespace of the |
||||
host, meaning that they can listen on (privileged) ports. However, they |
||||
cannot change the network configuration. You can give a container its |
||||
own network as follows: |
||||
|
||||
```nix |
||||
containers.database = { |
||||
privateNetwork = true; |
||||
hostAddress = "192.168.100.10"; |
||||
localAddress = "192.168.100.11"; |
||||
}; |
||||
``` |
||||
|
||||
This gives the container a private virtual Ethernet interface with IP |
||||
address `192.168.100.11`, which is hooked up to a virtual Ethernet |
||||
interface on the host with IP address `192.168.100.10`. (See the next |
||||
section for details on container networking.) |
||||
|
||||
To disable the container, just remove it from `configuration.nix` and |
||||
run `nixos-rebuild |
||||
switch`. Note that this will not delete the root directory of the |
||||
container in `/var/lib/containers`. Containers can be destroyed using |
||||
the imperative method: `nixos-container destroy foo`. |
||||
|
||||
Declarative containers can be started and stopped using the |
||||
corresponding systemd service, e.g. |
||||
`systemctl start container@database`. |
@ -1,60 +0,0 @@ |
||||
<section 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="sec-declarative-containers"> |
||||
<title>Declarative Container Specification</title> |
||||
|
||||
<para> |
||||
You can also specify containers and their configuration in the host’s |
||||
<filename>configuration.nix</filename>. For example, the following specifies |
||||
that there shall be a container named <literal>database</literal> running |
||||
PostgreSQL: |
||||
<programlisting> |
||||
containers.database = |
||||
{ config = |
||||
{ config, pkgs, ... }: |
||||
{ <xref linkend="opt-services.postgresql.enable"/> = true; |
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_9_6; |
||||
}; |
||||
}; |
||||
</programlisting> |
||||
If you run <literal>nixos-rebuild switch</literal>, the container will be |
||||
built. If the container was already running, it will be updated in place, |
||||
without rebooting. The container can be configured to start automatically by |
||||
setting <literal>containers.database.autoStart = true</literal> in its |
||||
configuration. |
||||
</para> |
||||
|
||||
<para> |
||||
By default, declarative containers share the network namespace of the host, |
||||
meaning that they can listen on (privileged) ports. However, they cannot |
||||
change the network configuration. You can give a container its own network as |
||||
follows: |
||||
<programlisting> |
||||
containers.database = { |
||||
<link linkend="opt-containers._name_.privateNetwork">privateNetwork</link> = true; |
||||
<link linkend="opt-containers._name_.hostAddress">hostAddress</link> = "192.168.100.10"; |
||||
<link linkend="opt-containers._name_.localAddress">localAddress</link> = "192.168.100.11"; |
||||
}; |
||||
</programlisting> |
||||
This gives the container a private virtual Ethernet interface with IP address |
||||
<literal>192.168.100.11</literal>, which is hooked up to a virtual Ethernet |
||||
interface on the host with IP address <literal>192.168.100.10</literal>. (See |
||||
the next section for details on container networking.) |
||||
</para> |
||||
|
||||
<para> |
||||
To disable the container, just remove it from |
||||
<filename>configuration.nix</filename> and run <literal>nixos-rebuild |
||||
switch</literal>. Note that this will not delete the root directory of the |
||||
container in <literal>/var/lib/containers</literal>. Containers can be |
||||
destroyed using the imperative method: <literal>nixos-container destroy |
||||
foo</literal>. |
||||
</para> |
||||
|
||||
<para> |
||||
Declarative containers can be started and stopped using the corresponding |
||||
systemd service, e.g. <literal>systemctl start container@database</literal>. |
||||
</para> |
||||
</section> |
@ -0,0 +1,115 @@ |
||||
# Imperative Container Management {#sec-imperative-containers} |
||||
|
||||
We'll cover imperative container management using `nixos-container` |
||||
first. Be aware that container management is currently only possible as |
||||
`root`. |
||||
|
||||
You create a container with identifier `foo` as follows: |
||||
|
||||
```ShellSession |
||||
# nixos-container create foo |
||||
``` |
||||
|
||||
This creates the container's root directory in `/var/lib/containers/foo` |
||||
and a small configuration file in `/etc/containers/foo.conf`. It also |
||||
builds the container's initial system configuration and stores it in |
||||
`/nix/var/nix/profiles/per-container/foo/system`. You can modify the |
||||
initial configuration of the container on the command line. For |
||||
instance, to create a container that has `sshd` running, with the given |
||||
public key for `root`: |
||||
|
||||
```ShellSession |
||||
# nixos-container create foo --config ' |
||||
services.openssh.enable = true; |
||||
users.users.root.openssh.authorizedKeys.keys = ["ssh-dss AAAAB3N…"]; |
||||
' |
||||
``` |
||||
|
||||
By default the next free address in the `10.233.0.0/16` subnet will be |
||||
chosen as container IP. This behavior can be altered by setting |
||||
`--host-address` and `--local-address`: |
||||
|
||||
```ShellSession |
||||
# nixos-container create test --config-file test-container.nix \ |
||||
--local-address 10.235.1.2 --host-address 10.235.1.1 |
||||
``` |
||||
|
||||
Creating a container does not start it. To start the container, run: |
||||
|
||||
```ShellSession |
||||
# nixos-container start foo |
||||
``` |
||||
|
||||
This command will return as soon as the container has booted and has |
||||
reached `multi-user.target`. On the host, the container runs within a |
||||
systemd unit called `container@container-name.service`. Thus, if |
||||
something went wrong, you can get status info using `systemctl`: |
||||
|
||||
```ShellSession |
||||
# systemctl status container@foo |
||||
``` |
||||
|
||||
If the container has started successfully, you can log in as root using |
||||
the `root-login` operation: |
||||
|
||||
```ShellSession |
||||
# nixos-container root-login foo |
||||
[root@foo:~]# |
||||
``` |
||||
|
||||
Note that only root on the host can do this (since there is no |
||||
authentication). You can also get a regular login prompt using the |
||||
`login` operation, which is available to all users on the host: |
||||
|
||||
```ShellSession |
||||
# nixos-container login foo |
||||
foo login: alice |
||||
Password: *** |
||||
``` |
||||
|
||||
With `nixos-container run`, you can execute arbitrary commands in the |
||||
container: |
||||
|
||||
```ShellSession |
||||
# nixos-container run foo -- uname -a |
||||
Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux |
||||
``` |
||||
|
||||
There are several ways to change the configuration of the container. |
||||
First, on the host, you can edit |
||||
`/var/lib/container/name/etc/nixos/configuration.nix`, and run |
||||
|
||||
```ShellSession |
||||
# nixos-container update foo |
||||
``` |
||||
|
||||
This will build and activate the new configuration. You can also specify |
||||
a new configuration on the command line: |
||||
|
||||
```ShellSession |
||||
# nixos-container update foo --config ' |
||||
services.httpd.enable = true; |
||||
services.httpd.adminAddr = "foo@example.org"; |
||||
networking.firewall.allowedTCPPorts = [ 80 ]; |
||||
' |
||||
|
||||
# curl http://$(nixos-container show-ip foo)/ |
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">… |
||||
``` |
||||
|
||||
However, note that this will overwrite the container's |
||||
`/etc/nixos/configuration.nix`. |
||||
|
||||
Alternatively, you can change the configuration from within the |
||||
container itself by running `nixos-rebuild switch` inside the container. |
||||
Note that the container by default does not have a copy of the NixOS |
||||
channel, so you should run `nix-channel --update` first. |
||||
|
||||
Containers can be stopped and started using `nixos-container |
||||
stop` and `nixos-container start`, respectively, or by using |
||||
`systemctl` on the container's service unit. To destroy a container, |
||||
including its file system, do |
||||
|
||||
```ShellSession |
||||
# nixos-container destroy foo |
||||
``` |
@ -1,123 +0,0 @@ |
||||
<section 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="sec-imperative-containers"> |
||||
<title>Imperative Container Management</title> |
||||
|
||||
<para> |
||||
We’ll cover imperative container management using |
||||
<command>nixos-container</command> first. Be aware that container management |
||||
is currently only possible as <literal>root</literal>. |
||||
</para> |
||||
|
||||
<para> |
||||
You create a container with identifier <literal>foo</literal> as follows: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container create <replaceable>foo</replaceable> |
||||
</screen> |
||||
This creates the container’s root directory in |
||||
<filename>/var/lib/containers/<replaceable>foo</replaceable></filename> and a small configuration file |
||||
in <filename>/etc/containers/<replaceable>foo</replaceable>.conf</filename>. It also builds the |
||||
container’s initial system configuration and stores it in |
||||
<filename>/nix/var/nix/profiles/per-container/<replaceable>foo</replaceable>/system</filename>. You can |
||||
modify the initial configuration of the container on the command line. For |
||||
instance, to create a container that has <command>sshd</command> running, |
||||
with the given public key for <literal>root</literal>: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container create <replaceable>foo</replaceable> --config ' |
||||
<xref linkend="opt-services.openssh.enable"/> = true; |
||||
<link linkend="opt-users.users._name_.openssh.authorizedKeys.keys">users.users.root.openssh.authorizedKeys.keys</link> = ["ssh-dss AAAAB3N…"]; |
||||
' |
||||
</screen> |
||||
By default the next free address in the <literal>10.233.0.0/16</literal> subnet will be chosen |
||||
as container IP. This behavior can be altered by setting <literal>--host-address</literal> and |
||||
<literal>--local-address</literal>: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container create test --config-file test-container.nix \ |
||||
--local-address 10.235.1.2 --host-address 10.235.1.1 |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
Creating a container does not start it. To start the container, run: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container start <replaceable>foo</replaceable> |
||||
</screen> |
||||
This command will return as soon as the container has booted and has reached |
||||
<literal>multi-user.target</literal>. On the host, the container runs within |
||||
a systemd unit called |
||||
<literal>container@<replaceable>container-name</replaceable>.service</literal>. |
||||
Thus, if something went wrong, you can get status info using |
||||
<command>systemctl</command>: |
||||
<screen> |
||||
<prompt># </prompt>systemctl status container@<replaceable>foo</replaceable> |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
If the container has started successfully, you can log in as root using the |
||||
<command>root-login</command> operation: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container root-login <replaceable>foo</replaceable> |
||||
<prompt>[root@foo:~]#</prompt> |
||||
</screen> |
||||
Note that only root on the host can do this (since there is no |
||||
authentication). You can also get a regular login prompt using the |
||||
<command>login</command> operation, which is available to all users on the |
||||
host: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container login <replaceable>foo</replaceable> |
||||
foo login: alice |
||||
Password: *** |
||||
</screen> |
||||
With <command>nixos-container run</command>, you can execute arbitrary |
||||
commands in the container: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container run <replaceable>foo</replaceable> -- uname -a |
||||
Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
There are several ways to change the configuration of the container. First, |
||||
on the host, you can edit |
||||
<literal>/var/lib/container/<replaceable>name</replaceable>/etc/nixos/configuration.nix</literal>, |
||||
and run |
||||
<screen> |
||||
<prompt># </prompt>nixos-container update <replaceable>foo</replaceable> |
||||
</screen> |
||||
This will build and activate the new configuration. You can also specify a |
||||
new configuration on the command line: |
||||
<screen> |
||||
<prompt># </prompt>nixos-container update <replaceable>foo</replaceable> --config ' |
||||
<xref linkend="opt-services.httpd.enable"/> = true; |
||||
<xref linkend="opt-services.httpd.adminAddr"/> = "foo@example.org"; |
||||
<xref linkend="opt-networking.firewall.allowedTCPPorts"/> = [ 80 ]; |
||||
' |
||||
|
||||
<prompt># </prompt>curl http://$(nixos-container show-ip <replaceable>foo</replaceable>)/ |
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">… |
||||
</screen> |
||||
However, note that this will overwrite the container’s |
||||
<filename>/etc/nixos/configuration.nix</filename>. |
||||
</para> |
||||
|
||||
<para> |
||||
Alternatively, you can change the configuration from within the container |
||||
itself by running <command>nixos-rebuild switch</command> inside the |
||||
container. Note that the container by default does not have a copy of the |
||||
NixOS channel, so you should run <command>nix-channel --update</command> |
||||
first. |
||||
</para> |
||||
|
||||
<para> |
||||
Containers can be stopped and started using <literal>nixos-container |
||||
stop</literal> and <literal>nixos-container start</literal>, respectively, or |
||||
by using <command>systemctl</command> on the container’s service unit. To |
||||
destroy a container, including its file system, do |
||||
<screen> |
||||
<prompt># </prompt>nixos-container destroy <replaceable>foo</replaceable> |
||||
</screen> |
||||
</para> |
||||
</section> |
@ -0,0 +1,38 @@ |
||||
# Logging {#sec-logging} |
||||
|
||||
System-wide logging is provided by systemd's *journal*, which subsumes |
||||
traditional logging daemons such as syslogd and klogd. Log entries are |
||||
kept in binary files in `/var/log/journal/`. The command `journalctl` |
||||
allows you to see the contents of the journal. For example, |
||||
|
||||
```ShellSession |
||||
$ journalctl -b |
||||
``` |
||||
|
||||
shows all journal entries since the last reboot. (The output of |
||||
`journalctl` is piped into `less` by default.) You can use various |
||||
options and match operators to restrict output to messages of interest. |
||||
For instance, to get all messages from PostgreSQL: |
||||
|
||||
```ShellSession |
||||
$ journalctl -u postgresql.service |
||||
-- Logs begin at Mon, 2013-01-07 13:28:01 CET, end at Tue, 2013-01-08 01:09:57 CET. -- |
||||
... |
||||
Jan 07 15:44:14 hagbard postgres[2681]: [2-1] LOG: database system is shut down |
||||
-- Reboot -- |
||||
Jan 07 15:45:10 hagbard postgres[2532]: [1-1] LOG: database system was shut down at 2013-01-07 15:44:14 CET |
||||
Jan 07 15:45:13 hagbard postgres[2500]: [1-1] LOG: database system is ready to accept connections |
||||
``` |
||||
|
||||
Or to get all messages since the last reboot that have at least a |
||||
"critical" severity level: |
||||
|
||||
```ShellSession |
||||
$ journalctl -b -p crit |
||||
Dec 17 21:08:06 mandark sudo[3673]: pam_unix(sudo:auth): auth could not identify password for [alice] |
||||
Dec 29 01:30:22 mandark kernel[6131]: [1053513.909444] CPU6: Core temperature above threshold, cpu clock throttled (total events = 1) |
||||
``` |
||||
|
||||
The system journal is readable by root and by users in the `wheel` and |
||||
`systemd-journal` groups. All users have a private journal that can be |
||||
read using `journalctl`. |
@ -1,43 +0,0 @@ |
||||
<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="sec-logging"> |
||||
<title>Logging</title> |
||||
<para> |
||||
System-wide logging is provided by systemd’s <emphasis>journal</emphasis>, |
||||
which subsumes traditional logging daemons such as syslogd and klogd. Log |
||||
entries are kept in binary files in <filename>/var/log/journal/</filename>. |
||||
The command <literal>journalctl</literal> allows you to see the contents of |
||||
the journal. For example, |
||||
<screen> |
||||
<prompt>$ </prompt>journalctl -b |
||||
</screen> |
||||
shows all journal entries since the last reboot. (The output of |
||||
<command>journalctl</command> is piped into <command>less</command> by |
||||
default.) You can use various options and match operators to restrict output |
||||
to messages of interest. For instance, to get all messages from PostgreSQL: |
||||
<screen> |
||||
<prompt>$ </prompt>journalctl -u postgresql.service |
||||
-- Logs begin at Mon, 2013-01-07 13:28:01 CET, end at Tue, 2013-01-08 01:09:57 CET. -- |
||||
... |
||||
Jan 07 15:44:14 hagbard postgres[2681]: [2-1] LOG: database system is shut down |
||||
-- Reboot -- |
||||
Jan 07 15:45:10 hagbard postgres[2532]: [1-1] LOG: database system was shut down at 2013-01-07 15:44:14 CET |
||||
Jan 07 15:45:13 hagbard postgres[2500]: [1-1] LOG: database system is ready to accept connections |
||||
</screen> |
||||
Or to get all messages since the last reboot that have at least a |
||||
“critical” severity level: |
||||
<screen> |
||||
<prompt>$ </prompt>journalctl -b -p crit |
||||
Dec 17 21:08:06 mandark sudo[3673]: pam_unix(sudo:auth): auth could not identify password for [alice] |
||||
Dec 29 01:30:22 mandark kernel[6131]: [1053513.909444] CPU6: Core temperature above threshold, cpu clock throttled (total events = 1) |
||||
</screen> |
||||
</para> |
||||
<para> |
||||
The system journal is readable by root and by users in the |
||||
<literal>wheel</literal> and <literal>systemd-journal</literal> groups. All |
||||
users have a private journal that can be read using |
||||
<command>journalctl</command>. |
||||
</para> |
||||
</chapter> |
@ -0,0 +1,11 @@ |
||||
# Maintenance Mode {#sec-maintenance-mode} |
||||
|
||||
You can enter rescue mode by running: |
||||
|
||||
```ShellSession |
||||
# systemctl rescue |
||||
``` |
||||
|
||||
This will eventually give you a single-user root shell. Systemd will |
||||
stop (almost) all system services. To get out of maintenance mode, just |
||||
exit from the rescue shell. |
@ -1,16 +0,0 @@ |
||||
<section 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="sec-maintenance-mode"> |
||||
<title>Maintenance Mode</title> |
||||
|
||||
<para> |
||||
You can enter rescue mode by running: |
||||
<screen> |
||||
<prompt># </prompt>systemctl rescue</screen> |
||||
This will eventually give you a single-user root shell. Systemd will stop |
||||
(almost) all system services. To get out of maintenance mode, just exit from |
||||
the rescue shell. |
||||
</para> |
||||
</section> |
@ -0,0 +1,21 @@ |
||||
# Network Problems {#sec-nix-network-issues} |
||||
|
||||
Nix uses a so-called *binary cache* to optimise building a package from |
||||
source into downloading it as a pre-built binary. That is, whenever a |
||||
command like `nixos-rebuild` needs a path in the Nix store, Nix will try |
||||
to download that path from the Internet rather than build it from |
||||
source. The default binary cache is `https://cache.nixos.org/`. If this |
||||
cache is unreachable, Nix operations may take a long time due to HTTP |
||||
connection timeouts. You can disable the use of the binary cache by |
||||
adding `--option use-binary-caches false`, e.g. |
||||
|
||||
```ShellSession |
||||
# nixos-rebuild switch --option use-binary-caches false |
||||
``` |
||||
|
||||
If you have an alternative binary cache at your disposal, you can use it |
||||
instead: |
||||
|
||||
```ShellSession |
||||
# nixos-rebuild switch --option binary-caches http://my-cache.example.org/ |
||||
``` |
@ -1,27 +0,0 @@ |
||||
<section 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="sec-nix-network-issues"> |
||||
<title>Network Problems</title> |
||||
|
||||
<para> |
||||
Nix uses a so-called <emphasis>binary cache</emphasis> to optimise building a |
||||
package from source into downloading it as a pre-built binary. That is, |
||||
whenever a command like <command>nixos-rebuild</command> needs a path in the |
||||
Nix store, Nix will try to download that path from the Internet rather than |
||||
build it from source. The default binary cache is |
||||
<uri>https://cache.nixos.org/</uri>. If this cache is unreachable, Nix |
||||
operations may take a long time due to HTTP connection timeouts. You can |
||||
disable the use of the binary cache by adding <option>--option |
||||
use-binary-caches false</option>, e.g. |
||||
<screen> |
||||
<prompt># </prompt>nixos-rebuild switch --option use-binary-caches false |
||||
</screen> |
||||
If you have an alternative binary cache at your disposal, you can use it |
||||
instead: |
||||
<screen> |
||||
<prompt># </prompt>nixos-rebuild switch --option binary-caches <replaceable>http://my-cache.example.org/</replaceable> |
||||
</screen> |
||||
</para> |
||||
</section> |
@ -0,0 +1,30 @@ |
||||
# Rebooting and Shutting Down {#sec-rebooting} |
||||
|
||||
The system can be shut down (and automatically powered off) by doing: |
||||
|
||||
```ShellSession |
||||
# shutdown |
||||
``` |
||||
|
||||
This is equivalent to running `systemctl poweroff`. |
||||
|
||||
To reboot the system, run |
||||
|
||||
```ShellSession |
||||
# reboot |
||||
``` |
||||
|
||||
which is equivalent to `systemctl reboot`. Alternatively, you can |
||||
quickly reboot the system using `kexec`, which bypasses the BIOS by |
||||
directly loading the new kernel into memory: |
||||
|
||||
```ShellSession |
||||
# systemctl kexec |
||||
``` |
||||
|
||||
The machine can be suspended to RAM (if supported) using `systemctl suspend`, |
||||
and suspended to disk using `systemctl hibernate`. |
||||
|
||||
These commands can be run by any user who is logged in locally, i.e. on |
||||
a virtual console or in X11; otherwise, the user is asked for |
||||
authentication. |
@ -1,35 +0,0 @@ |
||||
<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="sec-rebooting"> |
||||
<title>Rebooting and Shutting Down</title> |
||||
<para> |
||||
The system can be shut down (and automatically powered off) by doing: |
||||
<screen> |
||||
<prompt># </prompt>shutdown |
||||
</screen> |
||||
This is equivalent to running <command>systemctl poweroff</command>. |
||||
</para> |
||||
<para> |
||||
To reboot the system, run |
||||
<screen> |
||||
<prompt># </prompt>reboot |
||||
</screen> |
||||
which is equivalent to <command>systemctl reboot</command>. Alternatively, |
||||
you can quickly reboot the system using <literal>kexec</literal>, which |
||||
bypasses the BIOS by directly loading the new kernel into memory: |
||||
<screen> |
||||
<prompt># </prompt>systemctl kexec |
||||
</screen> |
||||
</para> |
||||
<para> |
||||
The machine can be suspended to RAM (if supported) using <command>systemctl |
||||
suspend</command>, and suspended to disk using <command>systemctl |
||||
hibernate</command>. |
||||
</para> |
||||
<para> |
||||
These commands can be run by any user who is logged in locally, i.e. on a |
||||
virtual console or in X11; otherwise, the user is asked for authentication. |
||||
</para> |
||||
</chapter> |
@ -0,0 +1,38 @@ |
||||
# Rolling Back Configuration Changes {#sec-rollback} |
||||
|
||||
After running `nixos-rebuild` to switch to a new configuration, you may |
||||
find that the new configuration doesn't work very well. In that case, |
||||
there are several ways to return to a previous configuration. |
||||
|
||||
First, the GRUB boot manager allows you to boot into any previous |
||||
configuration that hasn't been garbage-collected. These configurations |
||||
can be found under the GRUB submenu "NixOS - All configurations". This |
||||
is especially useful if the new configuration fails to boot. After the |
||||
system has booted, you can make the selected configuration the default |
||||
for subsequent boots: |
||||
|
||||
```ShellSession |
||||
# /run/current-system/bin/switch-to-configuration boot |
||||
``` |
||||
|
||||
Second, you can switch to the previous configuration in a running |
||||
system: |
||||
|
||||
```ShellSession |
||||
# nixos-rebuild switch --rollback |
||||
``` |
||||
|
||||
This is equivalent to running: |
||||
|
||||
```ShellSession |
||||
# /nix/var/nix/profiles/system-N-link/bin/switch-to-configuration switch |
||||
``` |
||||
|
||||
where `N` is the number of the NixOS system configuration. To get a |
||||
list of the available configurations, do: |
||||
|
||||
```ShellSession |
||||
$ ls -l /nix/var/nix/profiles/system-*-link |
||||
... |
||||
lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link -> /nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055 |
||||
``` |
@ -1,41 +0,0 @@ |
||||
<section 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="sec-rollback"> |
||||
<title>Rolling Back Configuration Changes</title> |
||||
|
||||
<para> |
||||
After running <command>nixos-rebuild</command> to switch to a new |
||||
configuration, you may find that the new configuration doesn’t work very |
||||
well. In that case, there are several ways to return to a previous |
||||
configuration. |
||||
</para> |
||||
|
||||
<para> |
||||
First, the GRUB boot manager allows you to boot into any previous |
||||
configuration that hasn’t been garbage-collected. These configurations can |
||||
be found under the GRUB submenu “NixOS - All configurations”. This is |
||||
especially useful if the new configuration fails to boot. After the system |
||||
has booted, you can make the selected configuration the default for |
||||
subsequent boots: |
||||
<screen> |
||||
<prompt># </prompt>/run/current-system/bin/switch-to-configuration boot</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
Second, you can switch to the previous configuration in a running system: |
||||
<screen> |
||||
<prompt># </prompt>nixos-rebuild switch --rollback</screen> |
||||
This is equivalent to running: |
||||
<screen> |
||||
<prompt># </prompt>/nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen> |
||||
where <replaceable>N</replaceable> is the number of the NixOS system |
||||
configuration. To get a list of the available configurations, do: |
||||
<screen> |
||||
<prompt>$ </prompt>ls -l /nix/var/nix/profiles/system-*-link |
||||
<replaceable>...</replaceable> |
||||
lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link -> /nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055 |
||||
</screen> |
||||
</para> |
||||
</section> |
@ -0,0 +1,120 @@ |
||||
# Service Management {#sec-systemctl} |
||||
|
||||
In NixOS, all system services are started and monitored using the |
||||
systemd program. systemd is the "init" process of the system (i.e. PID |
||||
1), the parent of all other processes. It manages a set of so-called |
||||
"units", which can be things like system services (programs), but also |
||||
mount points, swap files, devices, targets (groups of units) and more. |
||||
Units can have complex dependencies; for instance, one unit can require |
||||
that another unit must be successfully started before the first unit can |
||||
be started. When the system boots, it starts a unit named |
||||
`default.target`; the dependencies of this unit cause all system |
||||
services to be started, file systems to be mounted, swap files to be |
||||
activated, and so on. |
||||
|
||||
## Interacting with a running systemd {#sect-nixos-systemd-general} |
||||
|
||||
The command `systemctl` is the main way to interact with `systemd`. The |
||||
following paragraphs demonstrate ways to interact with any OS running |
||||
systemd as init system. NixOS is of no exception. The [next section |
||||
](#sect-nixos-systemd-nixos) explains NixOS specific things worth |
||||
knowing. |
||||
|
||||
Without any arguments, `systemctl` the status of active units: |
||||
|
||||
```ShellSession |
||||
$ systemctl |
||||
-.mount loaded active mounted / |
||||
swapfile.swap loaded active active /swapfile |
||||
sshd.service loaded active running SSH Daemon |
||||
graphical.target loaded active active Graphical Interface |
||||
... |
||||
``` |
||||
|
||||
You can ask for detailed status information about a unit, for instance, |
||||
the PostgreSQL database service: |
||||
|
||||
```ShellSession |
||||
$ systemctl status postgresql.service |
||||
postgresql.service - PostgreSQL Server |
||||
Loaded: loaded (/nix/store/pn3q73mvh75gsrl8w7fdlfk3fq5qm5mw-unit/postgresql.service) |
||||
Active: active (running) since Mon, 2013-01-07 15:55:57 CET; 9h ago |
||||
Main PID: 2390 (postgres) |
||||
CGroup: name=systemd:/system/postgresql.service |
||||
├─2390 postgres |
||||
├─2418 postgres: writer process |
||||
├─2419 postgres: wal writer process |
||||
├─2420 postgres: autovacuum launcher process |
||||
├─2421 postgres: stats collector process |
||||
└─2498 postgres: zabbix zabbix [local] idle |
||||
|
||||
Jan 07 15:55:55 hagbard postgres[2394]: [1-1] LOG: database system was shut down at 2013-01-07 15:55:05 CET |
||||
Jan 07 15:55:57 hagbard postgres[2390]: [1-1] LOG: database system is ready to accept connections |
||||
Jan 07 15:55:57 hagbard postgres[2420]: [1-1] LOG: autovacuum launcher started |
||||
Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server. |
||||
``` |
||||
|
||||
Note that this shows the status of the unit (active and running), all |
||||
the processes belonging to the service, as well as the most recent log |
||||
messages from the service. |
||||
|
||||
Units can be stopped, started or restarted: |
||||
|
||||
```ShellSession |
||||
# systemctl stop postgresql.service |
||||
# systemctl start postgresql.service |
||||
# systemctl restart postgresql.service |
||||
``` |
||||
|
||||
These operations are synchronous: they wait until the service has |
||||
finished starting or stopping (or has failed). Starting a unit will |
||||
cause the dependencies of that unit to be started as well (if |
||||
necessary). |
||||
|
||||
## systemd in NixOS {#sect-nixos-systemd-nixos} |
||||
|
||||
Packages in Nixpkgs sometimes provide systemd units with them, usually |
||||
in e.g `#pkg-out#/lib/systemd/`. Putting such a package in |
||||
`environment.systemPackages` doesn\'t make the service available to |
||||
users or the system. |
||||
|
||||
In order to enable a systemd *system* service with provided upstream |
||||
package, use (e.g): |
||||
|
||||
```nix |
||||
systemd.packages = [ pkgs.packagekit ]; |
||||
``` |
||||
|
||||
Usually NixOS modules written by the community do the above, plus take |
||||
care of other details. If a module was written for a service you are |
||||
interested in, you\'d probably need only to use |
||||
`services.#name#.enable = true;`. These services are defined in |
||||
Nixpkgs\' [ `nixos/modules/` directory |
||||
](https://github.com/NixOS/nixpkgs/tree/master/nixos/modules). In case |
||||
the service is simple enough, the above method should work, and start |
||||
the service on boot. |
||||
|
||||
*User* systemd services on the other hand, should be treated |
||||
differently. Given a package that has a systemd unit file at |
||||
`#pkg-out#/lib/systemd/user/`, using [](#opt-systemd.packages) will |
||||
make you able to start the service via `systemctl --user start`, but it |
||||
won\'t start automatically on login. However, You can imperatively |
||||
enable it by adding the package\'s attribute to |
||||
[](#opt-systemd.packages) and then do this (e.g): |
||||
|
||||
```ShellSession |
||||
$ mkdir -p ~/.config/systemd/user/default.target.wants |
||||
$ ln -s /run/current-system/sw/lib/systemd/user/syncthing.service ~/.config/systemd/user/default.target.wants/ |
||||
$ systemctl --user daemon-reload |
||||
$ systemctl --user enable syncthing.service |
||||
``` |
||||
|
||||
If you are interested in a timer file, use `timers.target.wants` instead |
||||
of `default.target.wants` in the 1st and 2nd command. |
||||
|
||||
Using `systemctl --user enable syncthing.service` instead of the above, |
||||
will work, but it\'ll use the absolute path of `syncthing.service` for |
||||
the symlink, and this path is in `/nix/store/.../lib/systemd/user/`. |
||||
Hence [garbage collection](#sec-nix-gc) will remove that file and you |
||||
will wind up with a broken symlink in your systemd configuration, which |
||||
in turn will not make the service / timer start on login. |
@ -1,140 +0,0 @@ |
||||
<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="sec-systemctl"> |
||||
<title>Service Management</title> |
||||
<para> |
||||
In NixOS, all system services are started and monitored using the systemd |
||||
program. systemd is the “init” process of the system (i.e. PID 1), the |
||||
parent of all other processes. It manages a set of so-called “units”, |
||||
which can be things like system services (programs), but also mount points, |
||||
swap files, devices, targets (groups of units) and more. Units can have |
||||
complex dependencies; for instance, one unit can require that another unit |
||||
must be successfully started before the first unit can be started. When the |
||||
system boots, it starts a unit named <literal>default.target</literal>; the |
||||
dependencies of this unit cause all system services to be started, file |
||||
systems to be mounted, swap files to be activated, and so on. |
||||
</para> |
||||
<section xml:id="sect-nixos-systemd-general"> |
||||
<title>Interacting with a running systemd</title> |
||||
<para> |
||||
The command <command>systemctl</command> is the main way to interact with |
||||
<command>systemd</command>. The following paragraphs demonstrate ways to |
||||
interact with any OS running systemd as init system. NixOS is of no |
||||
exception. The <link xlink:href="#sect-nixos-systemd-nixos">next section |
||||
</link> explains NixOS specific things worth knowing. |
||||
</para> |
||||
<para> |
||||
Without any arguments, <literal>systmctl</literal> the status of active units: |
||||
<screen> |
||||
<prompt>$ </prompt>systemctl |
||||
-.mount loaded active mounted / |
||||
swapfile.swap loaded active active /swapfile |
||||
sshd.service loaded active running SSH Daemon |
||||
graphical.target loaded active active Graphical Interface |
||||
<replaceable>...</replaceable> |
||||
</screen> |
||||
</para> |
||||
<para> |
||||
You can ask for detailed status information about a unit, for instance, the |
||||
PostgreSQL database service: |
||||
<screen> |
||||
<prompt>$ </prompt>systemctl status postgresql.service |
||||
postgresql.service - PostgreSQL Server |
||||
Loaded: loaded (/nix/store/pn3q73mvh75gsrl8w7fdlfk3fq5qm5mw-unit/postgresql.service) |
||||
Active: active (running) since Mon, 2013-01-07 15:55:57 CET; 9h ago |
||||
Main PID: 2390 (postgres) |
||||
CGroup: name=systemd:/system/postgresql.service |
||||
├─2390 postgres |
||||
├─2418 postgres: writer process |
||||
├─2419 postgres: wal writer process |
||||
├─2420 postgres: autovacuum launcher process |
||||
├─2421 postgres: stats collector process |
||||
└─2498 postgres: zabbix zabbix [local] idle |
||||
|
||||
Jan 07 15:55:55 hagbard postgres[2394]: [1-1] LOG: database system was shut down at 2013-01-07 15:55:05 CET |
||||
Jan 07 15:55:57 hagbard postgres[2390]: [1-1] LOG: database system is ready to accept connections |
||||
Jan 07 15:55:57 hagbard postgres[2420]: [1-1] LOG: autovacuum launcher started |
||||
Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server. |
||||
</screen> |
||||
Note that this shows the status of the unit (active and running), all the |
||||
processes belonging to the service, as well as the most recent log messages |
||||
from the service. |
||||
</para> |
||||
<para> |
||||
Units can be stopped, started or restarted: |
||||
<screen> |
||||
<prompt># </prompt>systemctl stop postgresql.service |
||||
<prompt># </prompt>systemctl start postgresql.service |
||||
<prompt># </prompt>systemctl restart postgresql.service |
||||
</screen> |
||||
These operations are synchronous: they wait until the service has finished |
||||
starting or stopping (or has failed). Starting a unit will cause the |
||||
dependencies of that unit to be started as well (if necessary). |
||||
</para> |
||||
<!-- TODO: document cgroups, draft: |
||||
each service and user session is a cgroup |
||||
|
||||
- cgroup resource management --> |
||||
</section> |
||||
<section xml:id="sect-nixos-systemd-nixos"> |
||||
<title>systemd in NixOS</title> |
||||
<para> |
||||
Packages in Nixpkgs sometimes provide systemd units with them, usually in |
||||
e.g <literal>#pkg-out#/lib/systemd/</literal>. Putting such a package in |
||||
<literal>environment.systemPackages</literal> doesn't make the service |
||||
available to users or the system. |
||||
</para> |
||||
<para> |
||||
In order to enable a systemd <emphasis>system</emphasis> service with |
||||
provided upstream package, use (e.g): |
||||
<programlisting> |
||||
<xref linkend="opt-systemd.packages"/> = [ pkgs.packagekit ]; |
||||
</programlisting> |
||||
</para> |
||||
<para> |
||||
Usually NixOS modules written by the community do the above, plus take care of |
||||
other details. If a module was written for a service you are interested in, |
||||
you'd probably need only to use |
||||
<literal>services.#name#.enable = true;</literal>. These services are defined |
||||
in Nixpkgs' |
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules"> |
||||
<literal>nixos/modules/</literal> directory </link>. In case the service is |
||||
simple enough, the above method should work, and start the service on boot. |
||||
</para> |
||||
<para> |
||||
<emphasis>User</emphasis> systemd services on the other hand, should be |
||||
treated differently. Given a package that has a systemd unit file at |
||||
<literal>#pkg-out#/lib/systemd/user/</literal>, using |
||||
<xref linkend="opt-systemd.packages"/> will make you able to start the service via |
||||
<literal>systemctl --user start</literal>, but it won't start automatically on login. |
||||
<!-- TODO: Document why systemd.packages doesn't work for user services or fix this. |
||||
https://github.com/NixOS/nixpkgs/blob/2cd6594a8710a801038af2b72348658f732ce84a/nixos/modules/system/boot/systemd-lib.nix#L177-L198 |
||||
|
||||
This has been talked over at https://discourse.nixos.org/t/how-to-enable-upstream-systemd-user-services-declaratively/7649/5 |
||||
--> |
||||
However, You can imperatively enable it by adding the package's attribute to |
||||
<link linkend="opt-environment.systemPackages"> |
||||
<literal>systemd.packages</literal></link> and then do this (e.g): |
||||
<screen> |
||||
<prompt>$ </prompt>mkdir -p ~/.config/systemd/user/default.target.wants |
||||
<prompt>$ </prompt>ln -s /run/current-system/sw/lib/systemd/user/syncthing.service ~/.config/systemd/user/default.target.wants/ |
||||
<prompt>$ </prompt>systemctl --user daemon-reload |
||||
<prompt>$ </prompt>systemctl --user enable syncthing.service |
||||
</screen> |
||||
If you are interested in a timer file, use <literal>timers.target.wants</literal> |
||||
instead of <literal>default.target.wants</literal> in the 1st and 2nd command. |
||||
</para> |
||||
<para> |
||||
Using <literal>systemctl --user enable syncthing.service</literal> instead of |
||||
the above, will work, but it'll use the absolute path of |
||||
<literal>syncthing.service</literal> for the symlink, and this path is in |
||||
<literal>/nix/store/.../lib/systemd/user/</literal>. Hence |
||||
<link xlink:href="#sec-nix-gc">garbage collection</link> will remove that file |
||||
and you will wind up with a broken symlink in your systemd configuration, which |
||||
in turn will not make the service / timer start on login. |
||||
</para> |
||||
</section> |
||||
</chapter> |
||||
|
@ -0,0 +1,28 @@ |
||||
# Nix Store Corruption {#sec-nix-store-corruption} |
||||
|
||||
After a system crash, it's possible for files in the Nix store to become |
||||
corrupted. (For instance, the Ext4 file system has the tendency to |
||||
replace un-synced files with zero bytes.) NixOS tries hard to prevent |
||||
this from happening: it performs a `sync` before switching to a new |
||||
configuration, and Nix's database is fully transactional. If corruption |
||||
still occurs, you may be able to fix it automatically. |
||||
|
||||
If the corruption is in a path in the closure of the NixOS system |
||||
configuration, you can fix it by doing |
||||
|
||||
```ShellSession |
||||
# nixos-rebuild switch --repair |
||||
``` |
||||
|
||||
This will cause Nix to check every path in the closure, and if its |
||||
cryptographic hash differs from the hash recorded in Nix's database, the |
||||
path is rebuilt or redownloaded. |
||||
|
||||
You can also scan the entire Nix store for corrupt paths: |
||||
|
||||
```ShellSession |
||||
# nix-store --verify --check-contents --repair |
||||
``` |
||||
|
||||
Any corrupt paths will be redownloaded if they're available in a binary |
||||
cache; otherwise, they cannot be repaired. |
@ -1,36 +0,0 @@ |
||||
<section 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="sec-nix-store-corruption"> |
||||
<title>Nix Store Corruption</title> |
||||
|
||||
<para> |
||||
After a system crash, it’s possible for files in the Nix store to become |
||||
corrupted. (For instance, the Ext4 file system has the tendency to replace |
||||
un-synced files with zero bytes.) NixOS tries hard to prevent this from |
||||
happening: it performs a <command>sync</command> before switching to a new |
||||
configuration, and Nix’s database is fully transactional. If corruption |
||||
still occurs, you may be able to fix it automatically. |
||||
</para> |
||||
|
||||
<para> |
||||
If the corruption is in a path in the closure of the NixOS system |
||||
configuration, you can fix it by doing |
||||
<screen> |
||||
<prompt># </prompt>nixos-rebuild switch --repair |
||||
</screen> |
||||
This will cause Nix to check every path in the closure, and if its |
||||
cryptographic hash differs from the hash recorded in Nix’s database, the |
||||
path is rebuilt or redownloaded. |
||||
</para> |
||||
|
||||
<para> |
||||
You can also scan the entire Nix store for corrupt paths: |
||||
<screen> |
||||
<prompt># </prompt>nix-store --verify --check-contents --repair |
||||
</screen> |
||||
Any corrupt paths will be redownloaded if they’re available in a binary |
||||
cache; otherwise, they cannot be repaired. |
||||
</para> |
||||
</section> |
@ -0,0 +1,12 @@ |
||||
# Troubleshooting {#ch-troubleshooting} |
||||
|
||||
This chapter describes solutions to common problems you might encounter |
||||
when you manage your NixOS system. |
||||
|
||||
```{=docbook} |
||||
<xi:include href="boot-problems.section.xml" /> |
||||
<xi:include href="maintenance-mode.section.xml" /> |
||||
<xi:include href="rollback.section.xml" /> |
||||
<xi:include href="store-corruption.section.xml" /> |
||||
<xi:include href="network-problems.section.xml" /> |
||||
``` |
@ -1,16 +0,0 @@ |
||||
<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="ch-troubleshooting"> |
||||
<title>Troubleshooting</title> |
||||
<para> |
||||
This chapter describes solutions to common problems you might encounter when |
||||
you manage your NixOS system. |
||||
</para> |
||||
<xi:include href="../from_md/administration/boot-problems.section.xml" /> |
||||
<xi:include href="maintenance-mode.xml" /> |
||||
<xi:include href="rollback.xml" /> |
||||
<xi:include href="store-corruption.xml" /> |
||||
<xi:include href="network-problems.xml" /> |
||||
</chapter> |
@ -0,0 +1,43 @@ |
||||
# User Sessions {#sec-user-sessions} |
||||
|
||||
Systemd keeps track of all users who are logged into the system (e.g. on |
||||
a virtual console or remotely via SSH). The command `loginctl` allows |
||||
querying and manipulating user sessions. For instance, to list all user |
||||
sessions: |
||||
|
||||
```ShellSession |
||||
$ loginctl |
||||
SESSION UID USER SEAT |
||||
c1 500 eelco seat0 |
||||
c3 0 root seat0 |
||||
c4 500 alice |
||||
``` |
||||
|
||||
This shows that two users are logged in locally, while another is logged |
||||
in remotely. ("Seats" are essentially the combinations of displays and |
||||
input devices attached to the system; usually, there is only one seat.) |
||||
To get information about a session: |
||||
|
||||
```ShellSession |
||||
$ loginctl session-status c3 |
||||
c3 - root (0) |
||||
Since: Tue, 2013-01-08 01:17:56 CET; 4min 42s ago |
||||
Leader: 2536 (login) |
||||
Seat: seat0; vc3 |
||||
TTY: /dev/tty3 |
||||
Service: login; type tty; class user |
||||
State: online |
||||
CGroup: name=systemd:/user/root/c3 |
||||
├─ 2536 /nix/store/10mn4xip9n7y9bxqwnsx7xwx2v2g34xn-shadow-4.1.5.1/bin/login -- |
||||
├─10339 -bash |
||||
└─10355 w3m nixos.org |
||||
``` |
||||
|
||||
This shows that the user is logged in on virtual console 3. It also |
||||
lists the processes belonging to this session. Since systemd keeps track |
||||
of this, you can terminate a session in a way that ensures that all the |
||||
session's processes are gone: |
||||
|
||||
```ShellSession |
||||
# loginctl terminate-session c3 |
||||
``` |
@ -1,45 +0,0 @@ |
||||
<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="sec-user-sessions"> |
||||
<title>User Sessions</title> |
||||
<para> |
||||
Systemd keeps track of all users who are logged into the system (e.g. on a |
||||
virtual console or remotely via SSH). The command <command>loginctl</command> |
||||
allows querying and manipulating user sessions. For instance, to list all |
||||
user sessions: |
||||
<screen> |
||||
<prompt>$ </prompt>loginctl |
||||
SESSION UID USER SEAT |
||||
c1 500 eelco seat0 |
||||
c3 0 root seat0 |
||||
c4 500 alice |
||||
</screen> |
||||
This shows that two users are logged in locally, while another is logged in |
||||
remotely. (“Seats” are essentially the combinations of displays and input |
||||
devices attached to the system; usually, there is only one seat.) To get |
||||
information about a session: |
||||
<screen> |
||||
<prompt>$ </prompt>loginctl session-status c3 |
||||
c3 - root (0) |
||||
Since: Tue, 2013-01-08 01:17:56 CET; 4min 42s ago |
||||
Leader: 2536 (login) |
||||
Seat: seat0; vc3 |
||||
TTY: /dev/tty3 |
||||
Service: login; type tty; class user |
||||
State: online |
||||
CGroup: name=systemd:/user/root/c3 |
||||
├─ 2536 /nix/store/10mn4xip9n7y9bxqwnsx7xwx2v2g34xn-shadow-4.1.5.1/bin/login -- |
||||
├─10339 -bash |
||||
└─10355 w3m nixos.org |
||||
</screen> |
||||
This shows that the user is logged in on virtual console 3. It also lists the |
||||
processes belonging to this session. Since systemd keeps track of this, you |
||||
can terminate a session in a way that ensures that all the session’s |
||||
processes are gone: |
||||
<screen> |
||||
<prompt># </prompt>loginctl terminate-session c3 |
||||
</screen> |
||||
</para> |
||||
</chapter> |
@ -0,0 +1,13 @@ |
||||
# Ad-Hoc Configuration {#ad-hoc-network-config} |
||||
|
||||
You can use [](#opt-networking.localCommands) to |
||||
specify shell commands to be run at the end of `network-setup.service`. This |
||||
is useful for doing network configuration not covered by the existing NixOS |
||||
modules. For instance, to statically configure an IPv6 address: |
||||
|
||||
```nix |
||||
networking.localCommands = |
||||
'' |
||||
ip -6 addr add 2001:610:685:1::1/64 dev eth0 |
||||
''; |
||||
``` |
@ -1,20 +0,0 @@ |
||||
<section 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="ad-hoc-network-config"> |
||||
<title>Ad-Hoc Configuration</title> |
||||
|
||||
<para> |
||||
You can use <xref linkend="opt-networking.localCommands"/> to specify shell |
||||
commands to be run at the end of <literal>network-setup.service</literal>. |
||||
This is useful for doing network configuration not covered by the existing |
||||
NixOS modules. For instance, to statically configure an IPv6 address: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.localCommands"/> = |
||||
'' |
||||
ip -6 addr add 2001:610:685:1::1/64 dev eth0 |
||||
''; |
||||
</programlisting> |
||||
</para> |
||||
</section> |
@ -0,0 +1,51 @@ |
||||
# Ad-Hoc Package Management {#sec-ad-hoc-packages} |
||||
|
||||
With the command `nix-env`, you can install and uninstall packages from |
||||
the command line. For instance, to install Mozilla Thunderbird: |
||||
|
||||
```ShellSession |
||||
$ nix-env -iA nixos.thunderbird |
||||
``` |
||||
|
||||
If you invoke this as root, the package is installed in the Nix profile |
||||
`/nix/var/nix/profiles/default` and visible to all users of the system; |
||||
otherwise, the package ends up in |
||||
`/nix/var/nix/profiles/per-user/username/profile` and is not visible to |
||||
other users. The `-A` flag specifies the package by its attribute name; |
||||
without it, the package is installed by matching against its package |
||||
name (e.g. `thunderbird`). The latter is slower because it requires |
||||
matching against all available Nix packages, and is ambiguous if there |
||||
are multiple matching packages. |
||||
|
||||
Packages come from the NixOS channel. You typically upgrade a package by |
||||
updating to the latest version of the NixOS channel: |
||||
|
||||
```ShellSession |
||||
$ nix-channel --update nixos |
||||
``` |
||||
|
||||
and then running `nix-env -i` again. Other packages in the profile are |
||||
*not* affected; this is the crucial difference with the declarative |
||||
style of package management, where running `nixos-rebuild switch` causes |
||||
all packages to be updated to their current versions in the NixOS |
||||
channel. You can however upgrade all packages for which there is a newer |
||||
version by doing: |
||||
|
||||
```ShellSession |
||||
$ nix-env -u '*' |
||||
``` |
||||
|
||||
A package can be uninstalled using the `-e` flag: |
||||
|
||||
```ShellSession |
||||
$ nix-env -e thunderbird |
||||
``` |
||||
|
||||
Finally, you can roll back an undesirable `nix-env` action: |
||||
|
||||
```ShellSession |
||||
$ nix-env --rollback |
||||
``` |
||||
|
||||
`nix-env` has many more flags. For details, see the nix-env(1) manpage or |
||||
the Nix manual. |
@ -1,61 +0,0 @@ |
||||
<section 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="sec-ad-hoc-packages"> |
||||
<title>Ad-Hoc Package Management</title> |
||||
|
||||
<para> |
||||
With the command <command>nix-env</command>, you can install and uninstall |
||||
packages from the command line. For instance, to install Mozilla Thunderbird: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-env -iA nixos.thunderbird</screen> |
||||
If you invoke this as root, the package is installed in the Nix profile |
||||
<filename>/nix/var/nix/profiles/default</filename> and visible to all users |
||||
of the system; otherwise, the package ends up in |
||||
<filename>/nix/var/nix/profiles/per-user/<replaceable>username</replaceable>/profile</filename> |
||||
and is not visible to other users. The <option>-A</option> flag specifies the |
||||
package by its attribute name; without it, the package is installed by |
||||
matching against its package name (e.g. <literal>thunderbird</literal>). The |
||||
latter is slower because it requires matching against all available Nix |
||||
packages, and is ambiguous if there are multiple matching packages. |
||||
</para> |
||||
|
||||
<para> |
||||
Packages come from the NixOS channel. You typically upgrade a package by |
||||
updating to the latest version of the NixOS channel: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-channel --update nixos |
||||
</screen> |
||||
and then running <literal>nix-env -i</literal> again. Other packages in the |
||||
profile are <emphasis>not</emphasis> affected; this is the crucial difference |
||||
with the declarative style of package management, where running |
||||
<command>nixos-rebuild switch</command> causes all packages to be updated to |
||||
their current versions in the NixOS channel. You can however upgrade all |
||||
packages for which there is a newer version by doing: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-env -u '*' |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
A package can be uninstalled using the <option>-e</option> flag: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-env -e thunderbird |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
Finally, you can roll back an undesirable <command>nix-env</command> action: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-env --rollback |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
<command>nix-env</command> has many more flags. For details, see the |
||||
<citerefentry> |
||||
<refentrytitle>nix-env</refentrytitle> |
||||
<manvolnum>1</manvolnum></citerefentry> manpage or the Nix manual. |
||||
</para> |
||||
</section> |
@ -0,0 +1,74 @@ |
||||
# Adding Custom Packages {#sec-custom-packages} |
||||
|
||||
It's possible that a package you need is not available in NixOS. In that |
||||
case, you can do two things. First, you can clone the Nixpkgs |
||||
repository, add the package to your clone, and (optionally) submit a |
||||
patch or pull request to have it accepted into the main Nixpkgs repository. |
||||
This is described in detail in the [Nixpkgs manual](https://nixos.org/nixpkgs/manual). |
||||
In short, you clone Nixpkgs: |
||||
|
||||
```ShellSession |
||||
$ git clone https://github.com/NixOS/nixpkgs |
||||
$ cd nixpkgs |
||||
``` |
||||
|
||||
Then you write and test the package as described in the Nixpkgs manual. |
||||
Finally, you add it to [](#opt-environment.systemPackages), e.g. |
||||
|
||||
```nix |
||||
environment.systemPackages = [ pkgs.my-package ]; |
||||
``` |
||||
|
||||
and you run `nixos-rebuild`, specifying your own Nixpkgs tree: |
||||
|
||||
```ShellSession |
||||
# nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs |
||||
``` |
||||
|
||||
The second possibility is to add the package outside of the Nixpkgs |
||||
tree. For instance, here is how you specify a build of the |
||||
[GNU Hello](https://www.gnu.org/software/hello/) package directly in |
||||
`configuration.nix`: |
||||
|
||||
```nix |
||||
environment.systemPackages = |
||||
let |
||||
my-hello = with pkgs; stdenv.mkDerivation rec { |
||||
name = "hello-2.8"; |
||||
src = fetchurl { |
||||
url = "mirror://gnu/hello/${name}.tar.gz"; |
||||
sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6"; |
||||
}; |
||||
}; |
||||
in |
||||
[ my-hello ]; |
||||
``` |
||||
|
||||
Of course, you can also move the definition of `my-hello` into a |
||||
separate Nix expression, e.g. |
||||
|
||||
```nix |
||||
environment.systemPackages = [ (import ./my-hello.nix) ]; |
||||
``` |
||||
|
||||
where `my-hello.nix` contains: |
||||
|
||||
```nix |
||||
with import <nixpkgs> {}; # bring all of Nixpkgs into scope |
||||
|
||||
stdenv.mkDerivation rec { |
||||
name = "hello-2.8"; |
||||
src = fetchurl { |
||||
url = "mirror://gnu/hello/${name}.tar.gz"; |
||||
sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6"; |
||||
}; |
||||
} |
||||
``` |
||||
|
||||
This allows testing the package easily: |
||||
|
||||
```ShellSession |
||||
$ nix-build my-hello.nix |
||||
$ ./result/bin/hello |
||||
Hello, world! |
||||
``` |
@ -1,73 +0,0 @@ |
||||
<section 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="sec-custom-packages"> |
||||
<title>Adding Custom Packages</title> |
||||
|
||||
<para> |
||||
It’s possible that a package you need is not available in NixOS. In that |
||||
case, you can do two things. First, you can clone the Nixpkgs repository, add |
||||
the package to your clone, and (optionally) submit a patch or pull request to |
||||
have it accepted into the main Nixpkgs repository. This is described in |
||||
detail in the <link |
||||
xlink:href="https://nixos.org/nixpkgs/manual">Nixpkgs |
||||
manual</link>. In short, you clone Nixpkgs: |
||||
<screen> |
||||
<prompt>$ </prompt>git clone https://github.com/NixOS/nixpkgs |
||||
<prompt>$ </prompt>cd nixpkgs |
||||
</screen> |
||||
Then you write and test the package as described in the Nixpkgs manual. |
||||
Finally, you add it to <literal>environment.systemPackages</literal>, e.g. |
||||
<programlisting> |
||||
<xref linkend="opt-environment.systemPackages"/> = [ pkgs.my-package ]; |
||||
</programlisting> |
||||
and you run <command>nixos-rebuild</command>, specifying your own Nixpkgs |
||||
tree: |
||||
<screen> |
||||
<prompt># </prompt>nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
The second possibility is to add the package outside of the Nixpkgs tree. For |
||||
instance, here is how you specify a build of the |
||||
<link xlink:href="https://www.gnu.org/software/hello/">GNU Hello</link> |
||||
package directly in <filename>configuration.nix</filename>: |
||||
<programlisting> |
||||
<xref linkend="opt-environment.systemPackages"/> = |
||||
let |
||||
my-hello = with pkgs; stdenv.mkDerivation rec { |
||||
name = "hello-2.8"; |
||||
src = fetchurl { |
||||
url = "mirror://gnu/hello/${name}.tar.gz"; |
||||
sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6"; |
||||
}; |
||||
}; |
||||
in |
||||
[ my-hello ]; |
||||
</programlisting> |
||||
Of course, you can also move the definition of <literal>my-hello</literal> |
||||
into a separate Nix expression, e.g. |
||||
<programlisting> |
||||
<xref linkend="opt-environment.systemPackages"/> = [ (import ./my-hello.nix) ]; |
||||
</programlisting> |
||||
where <filename>my-hello.nix</filename> contains: |
||||
<programlisting> |
||||
with import <nixpkgs> {}; # bring all of Nixpkgs into scope |
||||
|
||||
stdenv.mkDerivation rec { |
||||
name = "hello-2.8"; |
||||
src = fetchurl { |
||||
url = "mirror://gnu/hello/${name}.tar.gz"; |
||||
sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6"; |
||||
}; |
||||
} |
||||
</programlisting> |
||||
This allows testing the package easily: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-build my-hello.nix |
||||
<prompt>$ </prompt>./result/bin/hello |
||||
Hello, world! |
||||
</screen> |
||||
</para> |
||||
</section> |
@ -0,0 +1,175 @@ |
||||
# NixOS Configuration File {#sec-configuration-file} |
||||
|
||||
The NixOS configuration file generally looks like this: |
||||
|
||||
```nix |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ option definitions |
||||
} |
||||
``` |
||||
|
||||
The first line (`{ config, pkgs, ... }:`) denotes that this is actually |
||||
a function that takes at least the two arguments `config` and `pkgs`. |
||||
(These are explained later, in chapter [](#sec-writing-modules)) The |
||||
function returns a *set* of option definitions (`{ ... }`). |
||||
These definitions have the form `name = value`, where `name` is the |
||||
name of an option and `value` is its value. For example, |
||||
|
||||
```nix |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ services.httpd.enable = true; |
||||
services.httpd.adminAddr = "alice@example.org"; |
||||
services.httpd.virtualHosts.localhost.documentRoot = "/webroot"; |
||||
} |
||||
``` |
||||
|
||||
defines a configuration with three option definitions that together |
||||
enable the Apache HTTP Server with `/webroot` as the document root. |
||||
|
||||
Sets can be nested, and in fact dots in option names are shorthand for |
||||
defining a set containing another set. For instance, |
||||
[](#opt-services.httpd.enable) defines a set named |
||||
`services` that contains a set named `httpd`, which in turn contains an |
||||
option definition named `enable` with value `true`. This means that the |
||||
example above can also be written as: |
||||
|
||||
```nix |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ services = { |
||||
httpd = { |
||||
enable = true; |
||||
adminAddr = "alice@example.org"; |
||||
virtualHosts = { |
||||
localhost = { |
||||
documentRoot = "/webroot"; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
||||
} |
||||
``` |
||||
|
||||
which may be more convenient if you have lots of option definitions that |
||||
share the same prefix (such as `services.httpd`). |
||||
|
||||
NixOS checks your option definitions for correctness. For instance, if |
||||
you try to define an option that doesn't exist (that is, doesn't have a |
||||
corresponding *option declaration*), `nixos-rebuild` will give an error |
||||
like: |
||||
|
||||
```plain |
||||
The option `services.httpd.enable' defined in `/etc/nixos/configuration.nix' does not exist. |
||||
``` |
||||
|
||||
Likewise, values in option definitions must have a correct type. For |
||||
instance, `services.httpd.enable` must be a Boolean (`true` or `false`). |
||||
Trying to give it a value of another type, such as a string, will cause |
||||
an error: |
||||
|
||||
```plain |
||||
The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean. |
||||
``` |
||||
|
||||
Options have various types of values. The most important are: |
||||
|
||||
Strings |
||||
|
||||
: Strings are enclosed in double quotes, e.g. |
||||
|
||||
```nix |
||||
networking.hostName = "dexter"; |
||||
``` |
||||
|
||||
Special characters can be escaped by prefixing them with a backslash |
||||
(e.g. `\"`). |
||||
|
||||
Multi-line strings can be enclosed in *double single quotes*, e.g. |
||||
|
||||
```nix |
||||
networking.extraHosts = |
||||
'' |
||||
127.0.0.2 other-localhost |
||||
10.0.0.1 server |
||||
''; |
||||
``` |
||||
|
||||
The main difference is that it strips from each line a number of |
||||
spaces equal to the minimal indentation of the string as a whole |
||||
(disregarding the indentation of empty lines), and that characters |
||||
like `"` and `\` are not special (making it more convenient for |
||||
including things like shell code). See more info about this in the |
||||
Nix manual [here](https://nixos.org/nix/manual/#ssec-values). |
||||
|
||||
Booleans |
||||
|
||||
: These can be `true` or `false`, e.g. |
||||
|
||||
```nix |
||||
networking.firewall.enable = true; |
||||
networking.firewall.allowPing = false; |
||||
``` |
||||
|
||||
Integers |
||||
|
||||
: For example, |
||||
|
||||
```nix |
||||
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60; |
||||
``` |
||||
|
||||
(Note that here the attribute name `net.ipv4.tcp_keepalive_time` is |
||||
enclosed in quotes to prevent it from being interpreted as a set |
||||
named `net` containing a set named `ipv4`, and so on. This is |
||||
because it's not a NixOS option but the literal name of a Linux |
||||
kernel setting.) |
||||
|
||||
Sets |
||||
|
||||
: Sets were introduced above. They are name/value pairs enclosed in |
||||
braces, as in the option definition |
||||
|
||||
```nix |
||||
fileSystems."/boot" = |
||||
{ device = "/dev/sda1"; |
||||
fsType = "ext4"; |
||||
options = [ "rw" "data=ordered" "relatime" ]; |
||||
}; |
||||
``` |
||||
|
||||
Lists |
||||
|
||||
: The important thing to note about lists is that list elements are |
||||
separated by whitespace, like this: |
||||
|
||||
```nix |
||||
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ]; |
||||
``` |
||||
|
||||
List elements can be any other type, e.g. sets: |
||||
|
||||
```nix |
||||
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; |
||||
``` |
||||
|
||||
Packages |
||||
|
||||
: Usually, the packages you need are already part of the Nix Packages |
||||
collection, which is a set that can be accessed through the function |
||||
argument `pkgs`. Typical uses: |
||||
|
||||
```nix |
||||
environment.systemPackages = |
||||
[ pkgs.thunderbird |
||||
pkgs.emacs |
||||
]; |
||||
|
||||
services.postgresql.package = pkgs.postgresql_10; |
||||
``` |
||||
|
||||
The latter option definition changes the default PostgreSQL package |
||||
used by NixOS's PostgreSQL service to 10.x. For more information on |
||||
packages, including how to add new ones, see |
||||
[](#sec-custom-packages). |
@ -1,216 +0,0 @@ |
||||
<section 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="sec-configuration-file"> |
||||
<title>NixOS Configuration File</title> |
||||
|
||||
<para> |
||||
The NixOS configuration file generally looks like this: |
||||
<programlisting> |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ <replaceable>option definitions</replaceable> |
||||
} |
||||
</programlisting> |
||||
The first line (<literal>{ config, pkgs, ... }:</literal>) denotes that this |
||||
is actually a function that takes at least the two arguments |
||||
<varname>config</varname> and <varname>pkgs</varname>. (These are explained |
||||
later, in chapter <xref linkend="sec-writing-modules" />) The function returns |
||||
a <emphasis>set</emphasis> of option definitions (<literal>{ |
||||
<replaceable>...</replaceable> }</literal>). These definitions have the form |
||||
<literal><replaceable>name</replaceable> = |
||||
<replaceable>value</replaceable></literal>, where |
||||
<replaceable>name</replaceable> is the name of an option and |
||||
<replaceable>value</replaceable> is its value. For example, |
||||
<programlisting> |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ <xref linkend="opt-services.httpd.enable"/> = true; |
||||
<xref linkend="opt-services.httpd.adminAddr"/> = "alice@example.org"; |
||||
<link linkend="opt-services.httpd.virtualHosts">services.httpd.virtualHosts.localhost.documentRoot</link> = "/webroot"; |
||||
} |
||||
</programlisting> |
||||
defines a configuration with three option definitions that together enable |
||||
the Apache HTTP Server with <filename>/webroot</filename> as the document |
||||
root. |
||||
</para> |
||||
|
||||
<para> |
||||
Sets can be nested, and in fact dots in option names are shorthand for |
||||
defining a set containing another set. For instance, |
||||
<xref linkend="opt-services.httpd.enable"/> defines a set named |
||||
<varname>services</varname> that contains a set named |
||||
<varname>httpd</varname>, which in turn contains an option definition named |
||||
<varname>enable</varname> with value <literal>true</literal>. This means that |
||||
the example above can also be written as: |
||||
<programlisting> |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ services = { |
||||
httpd = { |
||||
enable = true; |
||||
adminAddr = "alice@example.org"; |
||||
virtualHosts = { |
||||
localhost = { |
||||
documentRoot = "/webroot"; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
||||
} |
||||
</programlisting> |
||||
which may be more convenient if you have lots of option definitions that |
||||
share the same prefix (such as <literal>services.httpd</literal>). |
||||
</para> |
||||
|
||||
<para> |
||||
NixOS checks your option definitions for correctness. For instance, if you |
||||
try to define an option that doesn’t exist (that is, doesn’t have a |
||||
corresponding <emphasis>option declaration</emphasis>), |
||||
<command>nixos-rebuild</command> will give an error like: |
||||
<screen> |
||||
The option `services.httpd.enable' defined in `/etc/nixos/configuration.nix' does not exist. |
||||
</screen> |
||||
Likewise, values in option definitions must have a correct type. For |
||||
instance, <option>services.httpd.enable</option> must be a Boolean |
||||
(<literal>true</literal> or <literal>false</literal>). Trying to give it a |
||||
value of another type, such as a string, will cause an error: |
||||
<screen> |
||||
The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean. |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
Options have various types of values. The most important are: |
||||
<variablelist> |
||||
<varlistentry> |
||||
<term> |
||||
Strings |
||||
</term> |
||||
<listitem> |
||||
<para> |
||||
Strings are enclosed in double quotes, e.g. |
||||
<programlisting> |
||||
<xref linkend="opt-networking.hostName"/> = "dexter"; |
||||
</programlisting> |
||||
Special characters can be escaped by prefixing them with a backslash |
||||
(e.g. <literal>\"</literal>). |
||||
</para> |
||||
<para> |
||||
Multi-line strings can be enclosed in <emphasis>double single |
||||
quotes</emphasis>, e.g. |
||||
<programlisting> |
||||
<xref linkend="opt-networking.extraHosts"/> = |
||||
'' |
||||
127.0.0.2 other-localhost |
||||
10.0.0.1 server |
||||
''; |
||||
</programlisting> |
||||
The main difference is that it strips from each line a number of spaces |
||||
equal to the minimal indentation of the string as a whole (disregarding |
||||
the indentation of empty lines), and that characters like |
||||
<literal>"</literal> and <literal>\</literal> are not special (making it |
||||
more convenient for including things like shell code). See more info |
||||
about this in the Nix manual |
||||
<link |
||||
xlink:href="https://nixos.org/nix/manual/#ssec-values">here</link>. |
||||
</para> |
||||
</listitem> |
||||
</varlistentry> |
||||
<varlistentry> |
||||
<term> |
||||
Booleans |
||||
</term> |
||||
<listitem> |
||||
<para> |
||||
These can be <literal>true</literal> or <literal>false</literal>, e.g. |
||||
<programlisting> |
||||
<xref linkend="opt-networking.firewall.enable"/> = true; |
||||
<xref linkend="opt-networking.firewall.allowPing"/> = false; |
||||
</programlisting> |
||||
</para> |
||||
</listitem> |
||||
</varlistentry> |
||||
<varlistentry> |
||||
<term> |
||||
Integers |
||||
</term> |
||||
<listitem> |
||||
<para> |
||||
For example, |
||||
<programlisting> |
||||
<xref linkend="opt-boot.kernel.sysctl"/>."net.ipv4.tcp_keepalive_time" = 60; |
||||
</programlisting> |
||||
(Note that here the attribute name |
||||
<literal>net.ipv4.tcp_keepalive_time</literal> is enclosed in quotes to |
||||
prevent it from being interpreted as a set named <literal>net</literal> |
||||
containing a set named <literal>ipv4</literal>, and so on. This is |
||||
because it’s not a NixOS option but the literal name of a Linux kernel |
||||
setting.) |
||||
</para> |
||||
</listitem> |
||||
</varlistentry> |
||||
<varlistentry> |
||||
<term> |
||||
Sets |
||||
</term> |
||||
<listitem> |
||||
<para> |
||||
Sets were introduced above. They are name/value pairs enclosed in braces, |
||||
as in the option definition |
||||
<programlisting> |
||||
<xref linkend="opt-fileSystems"/>."/boot" = |
||||
{ device = "/dev/sda1"; |
||||
fsType = "ext4"; |
||||
options = [ "rw" "data=ordered" "relatime" ]; |
||||
}; |
||||
</programlisting> |
||||
</para> |
||||
</listitem> |
||||
</varlistentry> |
||||
<varlistentry> |
||||
<term> |
||||
Lists |
||||
</term> |
||||
<listitem> |
||||
<para> |
||||
The important thing to note about lists is that list elements are |
||||
separated by whitespace, like this: |
||||
<programlisting> |
||||
<xref linkend="opt-boot.kernelModules"/> = [ "fuse" "kvm-intel" "coretemp" ]; |
||||
</programlisting> |
||||
List elements can be any other type, e.g. sets: |
||||
<programlisting> |
||||
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; |
||||
</programlisting> |
||||
</para> |
||||
</listitem> |
||||
</varlistentry> |
||||
<varlistentry> |
||||
<term> |
||||
Packages |
||||
</term> |
||||
<listitem> |
||||
<para> |
||||
Usually, the packages you need are already part of the Nix Packages |
||||
collection, which is a set that can be accessed through the function |
||||
argument <varname>pkgs</varname>. Typical uses: |
||||
<programlisting> |
||||
<xref linkend="opt-environment.systemPackages"/> = |
||||
[ pkgs.thunderbird |
||||
pkgs.emacs |
||||
]; |
||||
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_10; |
||||
</programlisting> |
||||
The latter option definition changes the default PostgreSQL package used |
||||
by NixOS’s PostgreSQL service to 10.x. For more information on |
||||
packages, including how to add new ones, see |
||||
<xref linkend="sec-custom-packages"/>. |
||||
</para> |
||||
</listitem> |
||||
</varlistentry> |
||||
</variablelist> |
||||
</para> |
||||
</section> |
@ -0,0 +1,19 @@ |
||||
# Configuration Syntax {#sec-configuration-syntax} |
||||
|
||||
The NixOS configuration file `/etc/nixos/configuration.nix` is actually |
||||
a *Nix expression*, which is the Nix package manager's purely functional |
||||
language for describing how to build packages and configurations. This |
||||
means you have all the expressive power of that language at your |
||||
disposal, including the ability to abstract over common patterns, which |
||||
is very useful when managing complex systems. The syntax and semantics |
||||
of the Nix language are fully described in the [Nix |
||||
manual](https://nixos.org/nix/manual/#chap-writing-nix-expressions), but |
||||
here we give a short overview of the most important constructs useful in |
||||
NixOS configuration files. |
||||
|
||||
```{=docbook} |
||||
<xi:include href="config-file.section.xml" /> |
||||
<xi:include href="abstractions.section.xml" /> |
||||
<xi:include href="modularity.section.xml" /> |
||||
<xi:include href="summary.section.xml" /> |
||||
``` |
@ -1,25 +0,0 @@ |
||||
<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="sec-configuration-syntax"> |
||||
<title>Configuration Syntax</title> |
||||
<para> |
||||
The NixOS configuration file |
||||
<filename>/etc/nixos/configuration.nix</filename> is actually a <emphasis>Nix |
||||
expression</emphasis>, which is the Nix package manager’s purely functional |
||||
language for describing how to build packages and configurations. This means |
||||
you have all the expressive power of that language at your disposal, |
||||
including the ability to abstract over common patterns, which is very useful |
||||
when managing complex systems. The syntax and semantics of the Nix language |
||||
are fully described in the |
||||
<link |
||||
xlink:href="https://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix |
||||
manual</link>, but here we give a short overview of the most important |
||||
constructs useful in NixOS configuration files. |
||||
</para> |
||||
<xi:include href="config-file.xml" /> |
||||
<xi:include href="../from_md/configuration/abstractions.section.xml" /> |
||||
<xi:include href="modularity.xml" /> |
||||
<xi:include href="summary.xml" /> |
||||
</chapter> |
@ -0,0 +1,74 @@ |
||||
# Customising Packages {#sec-customising-packages} |
||||
|
||||
Some packages in Nixpkgs have options to enable or disable optional |
||||
functionality or change other aspects of the package. For instance, the |
||||
Firefox wrapper package (which provides Firefox with a set of plugins |
||||
such as the Adobe Flash player) has an option to enable the Google Talk |
||||
plugin. It can be set in `configuration.nix` as follows: |
||||
`nixpkgs.config.firefox.enableGoogleTalkPlugin = true;` |
||||
|
||||
::: {.warning} |
||||
Unfortunately, Nixpkgs currently lacks a way to query available |
||||
configuration options. |
||||
::: |
||||
|
||||
Apart from high-level options, it's possible to tweak a package in |
||||
almost arbitrary ways, such as changing or disabling dependencies of a |
||||
package. For instance, the Emacs package in Nixpkgs by default has a |
||||
dependency on GTK 2. If you want to build it against GTK 3, you can |
||||
specify that as follows: |
||||
|
||||
```nix |
||||
environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ]; |
||||
``` |
||||
|
||||
The function `override` performs the call to the Nix function that |
||||
produces Emacs, with the original arguments amended by the set of |
||||
arguments specified by you. So here the function argument `gtk` gets the |
||||
value `pkgs.gtk3`, causing Emacs to depend on GTK 3. (The parentheses |
||||
are necessary because in Nix, function application binds more weakly |
||||
than list construction, so without them, |
||||
[](#opt-environment.systemPackages) |
||||
would be a list with two elements.) |
||||
|
||||
Even greater customisation is possible using the function |
||||
`overrideAttrs`. While the `override` mechanism above overrides the |
||||
arguments of a package function, `overrideAttrs` allows changing the |
||||
*attributes* passed to `mkDerivation`. This permits changing any aspect |
||||
of the package, such as the source code. For instance, if you want to |
||||
override the source code of Emacs, you can say: |
||||
|
||||
```nix |
||||
environment.systemPackages = [ |
||||
(pkgs.emacs.overrideAttrs (oldAttrs: { |
||||
name = "emacs-25.0-pre"; |
||||
src = /path/to/my/emacs/tree; |
||||
})) |
||||
]; |
||||
``` |
||||
|
||||
Here, `overrideAttrs` takes the Nix derivation specified by `pkgs.emacs` |
||||
and produces a new derivation in which the original's `name` and `src` |
||||
attribute have been replaced by the given values by re-calling |
||||
`stdenv.mkDerivation`. The original attributes are accessible via the |
||||
function argument, which is conventionally named `oldAttrs`. |
||||
|
||||
The overrides shown above are not global. They do not affect the |
||||
original package; other packages in Nixpkgs continue to depend on the |
||||
original rather than the customised package. This means that if another |
||||
package in your system depends on the original package, you end up with |
||||
two instances of the package. If you want to have everything depend on |
||||
your customised instance, you can apply a *global* override as follows: |
||||
|
||||
```nix |
||||
nixpkgs.config.packageOverrides = pkgs: |
||||
{ emacs = pkgs.emacs.override { gtk = pkgs.gtk3; }; |
||||
}; |
||||
``` |
||||
|
||||
The effect of this definition is essentially equivalent to modifying the |
||||
`emacs` attribute in the Nixpkgs source tree. Any package in Nixpkgs |
||||
that depends on `emacs` will be passed your customised instance. |
||||
(However, the value `pkgs.emacs` in `nixpkgs.config.packageOverrides` |
||||
refers to the original rather than overridden instance, to prevent an |
||||
infinite recursion.) |
@ -1,86 +0,0 @@ |
||||
<section 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="sec-customising-packages"> |
||||
<title>Customising Packages</title> |
||||
|
||||
<para> |
||||
Some packages in Nixpkgs have options to enable or disable optional |
||||
functionality or change other aspects of the package. For instance, the |
||||
Firefox wrapper package (which provides Firefox with a set of plugins such as |
||||
the Adobe Flash player) has an option to enable the Google Talk plugin. It |
||||
can be set in <filename>configuration.nix</filename> as follows: <filename> |
||||
nixpkgs.config.firefox.enableGoogleTalkPlugin = true; </filename> |
||||
</para> |
||||
|
||||
<warning> |
||||
<para> |
||||
Unfortunately, Nixpkgs currently lacks a way to query available |
||||
configuration options. |
||||
</para> |
||||
</warning> |
||||
|
||||
<para> |
||||
Apart from high-level options, it’s possible to tweak a package in almost |
||||
arbitrary ways, such as changing or disabling dependencies of a package. For |
||||
instance, the Emacs package in Nixpkgs by default has a dependency on GTK 2. |
||||
If you want to build it against GTK 3, you can specify that as follows: |
||||
<programlisting> |
||||
<xref linkend="opt-environment.systemPackages"/> = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ]; |
||||
</programlisting> |
||||
The function <varname>override</varname> performs the call to the Nix |
||||
function that produces Emacs, with the original arguments amended by the set |
||||
of arguments specified by you. So here the function argument |
||||
<varname>gtk</varname> gets the value <literal>pkgs.gtk3</literal>, causing |
||||
Emacs to depend on GTK 3. (The parentheses are necessary because in Nix, |
||||
function application binds more weakly than list construction, so without |
||||
them, <xref linkend="opt-environment.systemPackages"/> would be a list with |
||||
two elements.) |
||||
</para> |
||||
|
||||
<para> |
||||
Even greater customisation is possible using the function |
||||
<varname>overrideAttrs</varname>. While the <varname>override</varname> |
||||
mechanism above overrides the arguments of a package function, |
||||
<varname>overrideAttrs</varname> allows changing the |
||||
<emphasis>attributes</emphasis> passed to <literal>mkDerivation</literal>. |
||||
This permits changing any aspect of the package, such as the source code. For |
||||
instance, if you want to override the source code of Emacs, you can say: |
||||
<programlisting> |
||||
<xref linkend="opt-environment.systemPackages"/> = [ |
||||
(pkgs.emacs.overrideAttrs (oldAttrs: { |
||||
name = "emacs-25.0-pre"; |
||||
src = /path/to/my/emacs/tree; |
||||
})) |
||||
]; |
||||
</programlisting> |
||||
Here, <varname>overrideAttrs</varname> takes the Nix derivation specified by |
||||
<varname>pkgs.emacs</varname> and produces a new derivation in which the |
||||
original’s <literal>name</literal> and <literal>src</literal> attribute |
||||
have been replaced by the given values by re-calling |
||||
<literal>stdenv.mkDerivation</literal>. The original attributes are |
||||
accessible via the function argument, which is conventionally named |
||||
<varname>oldAttrs</varname>. |
||||
</para> |
||||
|
||||
<para> |
||||
The overrides shown above are not global. They do not affect the original |
||||
package; other packages in Nixpkgs continue to depend on the original rather |
||||
than the customised package. This means that if another package in your |
||||
system depends on the original package, you end up with two instances of the |
||||
package. If you want to have everything depend on your customised instance, |
||||
you can apply a <emphasis>global</emphasis> override as follows: |
||||
<screen> |
||||
nixpkgs.config.packageOverrides = pkgs: |
||||
{ emacs = pkgs.emacs.override { gtk = pkgs.gtk3; }; |
||||
}; |
||||
</screen> |
||||
The effect of this definition is essentially equivalent to modifying the |
||||
<literal>emacs</literal> attribute in the Nixpkgs source tree. Any package in |
||||
Nixpkgs that depends on <literal>emacs</literal> will be passed your |
||||
customised instance. (However, the value <literal>pkgs.emacs</literal> in |
||||
<varname>nixpkgs.config.packageOverrides</varname> refers to the original |
||||
rather than overridden instance, to prevent an infinite recursion.) |
||||
</para> |
||||
</section> |
@ -0,0 +1,46 @@ |
||||
# Declarative Package Management {#sec-declarative-package-mgmt} |
||||
|
||||
With declarative package management, you specify which packages you want |
||||
on your system by setting the option |
||||
[](#opt-environment.systemPackages). For instance, adding the |
||||
following line to `configuration.nix` enables the Mozilla Thunderbird |
||||
email application: |
||||
|
||||
```nix |
||||
environment.systemPackages = [ pkgs.thunderbird ]; |
||||
``` |
||||
|
||||
The effect of this specification is that the Thunderbird package from |
||||
Nixpkgs will be built or downloaded as part of the system when you run |
||||
`nixos-rebuild switch`. |
||||
|
||||
::: {.note} |
||||
Some packages require additional global configuration such as D-Bus or |
||||
systemd service registration so adding them to |
||||
[](#opt-environment.systemPackages) might not be sufficient. You are |
||||
advised to check the [list of options](#ch-options) whether a NixOS |
||||
module for the package does not exist. |
||||
::: |
||||
|
||||
You can get a list of the available packages as follows: |
||||
|
||||
```ShellSession |
||||
$ nix-env -qaP '*' --description |
||||
nixos.firefox firefox-23.0 Mozilla Firefox - the browser, reloaded |
||||
... |
||||
``` |
||||
|
||||
The first column in the output is the *attribute name*, such as |
||||
`nixos.thunderbird`. |
||||
|
||||
Note: the `nixos` prefix tells us that we want to get the package from |
||||
the `nixos` channel and works only in CLI tools. In declarative |
||||
configuration use `pkgs` prefix (variable). |
||||
|
||||
To "uninstall" a package, simply remove it from |
||||
[](#opt-environment.systemPackages) and run `nixos-rebuild switch`. |
||||
|
||||
```{=docbook} |
||||
<xi:include href="customizing-packages.section.xml" /> |
||||
<xi:include href="adding-custom-packages.section.xml" /> |
||||
``` |
@ -1,54 +0,0 @@ |
||||
<section 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="sec-declarative-package-mgmt"> |
||||
<title>Declarative Package Management</title> |
||||
|
||||
<para> |
||||
With declarative package management, you specify which packages you want on |
||||
your system by setting the option |
||||
<xref linkend="opt-environment.systemPackages"/>. For instance, adding the |
||||
following line to <filename>configuration.nix</filename> enables the Mozilla |
||||
Thunderbird email application: |
||||
<programlisting> |
||||
<xref linkend="opt-environment.systemPackages"/> = [ pkgs.thunderbird ]; |
||||
</programlisting> |
||||
The effect of this specification is that the Thunderbird package from Nixpkgs |
||||
will be built or downloaded as part of the system when you run |
||||
<command>nixos-rebuild switch</command>. |
||||
</para> |
||||
|
||||
<note> |
||||
<para> |
||||
Some packages require additional global configuration such as D-Bus or systemd service registration so adding them to <xref linkend="opt-environment.systemPackages"/> might not be sufficient. You are advised to check the <link xlink:href="#ch-options">list of options</link> whether a NixOS module for the package does not exist. |
||||
</para> |
||||
</note> |
||||
|
||||
<para> |
||||
You can get a list of the available packages as follows: |
||||
<screen> |
||||
<prompt>$ </prompt>nix-env -qaP '*' --description |
||||
nixos.firefox firefox-23.0 Mozilla Firefox - the browser, reloaded |
||||
<replaceable>...</replaceable> |
||||
</screen> |
||||
The first column in the output is the <emphasis>attribute name</emphasis>, |
||||
such as <literal>nixos.thunderbird</literal>. |
||||
</para> |
||||
<para> |
||||
Note: the <literal>nixos</literal> prefix tells us that we want to get the |
||||
package from the <literal>nixos</literal> channel and works only in CLI tools. |
||||
|
||||
In declarative configuration use <literal>pkgs</literal> prefix (variable). |
||||
</para> |
||||
|
||||
<para> |
||||
To “uninstall” a package, simply remove it from |
||||
<xref linkend="opt-environment.systemPackages"/> and run |
||||
<command>nixos-rebuild switch</command>. |
||||
</para> |
||||
|
||||
<xi:include href="customizing-packages.xml" /> |
||||
|
||||
<xi:include href="adding-custom-packages.xml" /> |
||||
</section> |
@ -0,0 +1,42 @@ |
||||
# File Systems {#ch-file-systems} |
||||
|
||||
You can define file systems using the `fileSystems` configuration |
||||
option. For instance, the following definition causes NixOS to mount the |
||||
Ext4 file system on device `/dev/disk/by-label/data` onto the mount |
||||
point `/data`: |
||||
|
||||
```nix |
||||
fileSystems."/data" = |
||||
{ device = "/dev/disk/by-label/data"; |
||||
fsType = "ext4"; |
||||
}; |
||||
``` |
||||
|
||||
This will create an entry in `/etc/fstab`, which will generate a |
||||
corresponding [systemd.mount](https://www.freedesktop.org/software/systemd/man/systemd.mount.html) |
||||
unit via [systemd-fstab-generator](https://www.freedesktop.org/software/systemd/man/systemd-fstab-generator.html). |
||||
The filesystem will be mounted automatically unless `"noauto"` is |
||||
present in [options](#opt-fileSystems._name_.options). `"noauto"` |
||||
filesystems can be mounted explicitly using `systemctl` e.g. |
||||
`systemctl start data.mount`. Mount points are created automatically if they don't |
||||
already exist. For `device`, it's best to use the topology-independent |
||||
device aliases in `/dev/disk/by-label` and `/dev/disk/by-uuid`, as these |
||||
don't change if the topology changes (e.g. if a disk is moved to another |
||||
IDE controller). |
||||
|
||||
You can usually omit the file system type (`fsType`), since `mount` can |
||||
usually detect the type and load the necessary kernel module |
||||
automatically. However, if the file system is needed at early boot (in |
||||
the initial ramdisk) and is not `ext2`, `ext3` or `ext4`, then it's best |
||||
to specify `fsType` to ensure that the kernel module is available. |
||||
|
||||
::: {.note} |
||||
System startup will fail if any of the filesystems fails to mount, |
||||
dropping you to the emergency shell. You can make a mount asynchronous |
||||
and non-critical by adding `options = [ "nofail" ];`. |
||||
::: |
||||
|
||||
```{=docbook} |
||||
<xi:include href="luks-file-systems.section.xml" /> |
||||
<xi:include href="sshfs-file-systems.section.xml" /> |
||||
``` |
@ -1,58 +0,0 @@ |
||||
<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="ch-file-systems"> |
||||
<title>File Systems</title> |
||||
<para> |
||||
You can define file systems using the <option>fileSystems</option> |
||||
configuration option. For instance, the following definition causes NixOS to |
||||
mount the Ext4 file system on device |
||||
<filename>/dev/disk/by-label/data</filename> onto the mount point |
||||
<filename>/data</filename>: |
||||
<programlisting> |
||||
<xref linkend="opt-fileSystems"/>."/data" = |
||||
{ device = "/dev/disk/by-label/data"; |
||||
fsType = "ext4"; |
||||
}; |
||||
</programlisting> |
||||
This will create an entry in <filename>/etc/fstab</filename>, which will |
||||
generate a corresponding |
||||
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.mount.html">systemd.mount</link> |
||||
unit via |
||||
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd-fstab-generator.html">systemd-fstab-generator</link>. |
||||
The filesystem will be mounted automatically unless |
||||
<literal>"noauto"</literal> is present in <link |
||||
linkend="opt-fileSystems._name_.options">options</link>. |
||||
<literal>"noauto"</literal> filesystems can be mounted explicitly using |
||||
<command>systemctl</command> e.g. <command>systemctl start |
||||
data.mount</command>. |
||||
Mount points are created automatically if they don’t already exist. For |
||||
<option><link linkend="opt-fileSystems._name_.device">device</link></option>, |
||||
it’s best to use the topology-independent device aliases in |
||||
<filename>/dev/disk/by-label</filename> and |
||||
<filename>/dev/disk/by-uuid</filename>, as these don’t change if the |
||||
topology changes (e.g. if a disk is moved to another IDE controller). |
||||
</para> |
||||
<para> |
||||
You can usually omit the file system type |
||||
(<option><link linkend="opt-fileSystems._name_.fsType">fsType</link></option>), |
||||
since <command>mount</command> can usually detect the type and load the |
||||
necessary kernel module automatically. However, if the file system is needed |
||||
at early boot (in the initial ramdisk) and is not <literal>ext2</literal>, |
||||
<literal>ext3</literal> or <literal>ext4</literal>, then it’s best to |
||||
specify <option>fsType</option> to ensure that the kernel module is |
||||
available. |
||||
</para> |
||||
<note> |
||||
<para> |
||||
System startup will fail if any of the filesystems fails to mount, dropping |
||||
you to the emergency shell. You can make a mount asynchronous and |
||||
non-critical by adding |
||||
<literal><link linkend="opt-fileSystems._name_.options">options</link> = [ |
||||
"nofail" ];</literal>. |
||||
</para> |
||||
</note> |
||||
<xi:include href="luks-file-systems.xml" /> |
||||
<xi:include href="../from_md/configuration/sshfs-file-systems.section.xml" /> |
||||
</chapter> |
@ -0,0 +1,32 @@ |
||||
# Firewall {#sec-firewall} |
||||
|
||||
NixOS has a simple stateful firewall that blocks incoming connections |
||||
and other unexpected packets. The firewall applies to both IPv4 and IPv6 |
||||
traffic. It is enabled by default. It can be disabled as follows: |
||||
|
||||
```nix |
||||
networking.firewall.enable = false; |
||||
``` |
||||
|
||||
If the firewall is enabled, you can open specific TCP ports to the |
||||
outside world: |
||||
|
||||
```nix |
||||
networking.firewall.allowedTCPPorts = [ 80 443 ]; |
||||
``` |
||||
|
||||
Note that TCP port 22 (ssh) is opened automatically if the SSH daemon is |
||||
enabled (`services.openssh.enable = true`). UDP ports can be opened through |
||||
[](#opt-networking.firewall.allowedUDPPorts). |
||||
|
||||
To open ranges of TCP ports: |
||||
|
||||
```nix |
||||
networking.firewall.allowedTCPPortRanges = [ |
||||
{ from = 4000; to = 4007; } |
||||
{ from = 8000; to = 8010; } |
||||
]; |
||||
``` |
||||
|
||||
Similarly, UDP port ranges can be opened through |
||||
[](#opt-networking.firewall.allowedUDPPortRanges). |
@ -1,37 +0,0 @@ |
||||
<section 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="sec-firewall"> |
||||
<title>Firewall</title> |
||||
|
||||
<para> |
||||
NixOS has a simple stateful firewall that blocks incoming connections and |
||||
other unexpected packets. The firewall applies to both IPv4 and IPv6 traffic. |
||||
It is enabled by default. It can be disabled as follows: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.firewall.enable"/> = false; |
||||
</programlisting> |
||||
If the firewall is enabled, you can open specific TCP ports to the outside |
||||
world: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.firewall.allowedTCPPorts"/> = [ 80 443 ]; |
||||
</programlisting> |
||||
Note that TCP port 22 (ssh) is opened automatically if the SSH daemon is |
||||
enabled (<option><xref linkend="opt-services.openssh.enable"/> = |
||||
true</option>). UDP ports can be opened through |
||||
<xref linkend="opt-networking.firewall.allowedUDPPorts"/>. |
||||
</para> |
||||
|
||||
<para> |
||||
To open ranges of TCP ports: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.firewall.allowedTCPPortRanges"/> = [ |
||||
{ from = 4000; to = 4007; } |
||||
{ from = 8000; to = 8010; } |
||||
]; |
||||
</programlisting> |
||||
Similarly, UDP port ranges can be opened through |
||||
<xref linkend="opt-networking.firewall.allowedUDPPortRanges"/>. |
||||
</para> |
||||
</section> |
@ -0,0 +1,204 @@ |
||||
# GPU acceleration {#sec-gpu-accel} |
||||
|
||||
NixOS provides various APIs that benefit from GPU hardware acceleration, |
||||
such as VA-API and VDPAU for video playback; OpenGL and Vulkan for 3D |
||||
graphics; and OpenCL for general-purpose computing. This chapter |
||||
describes how to set up GPU hardware acceleration (as far as this is not |
||||
done automatically) and how to verify that hardware acceleration is |
||||
indeed used. |
||||
|
||||
Most of the aforementioned APIs are agnostic with regards to which |
||||
display server is used. Consequently, these instructions should apply |
||||
both to the X Window System and Wayland compositors. |
||||
|
||||
## OpenCL {#sec-gpu-accel-opencl} |
||||
|
||||
[OpenCL](https://en.wikipedia.org/wiki/OpenCL) is a general compute API. |
||||
It is used by various applications such as Blender and Darktable to |
||||
accelerate certain operations. |
||||
|
||||
OpenCL applications load drivers through the *Installable Client Driver* |
||||
(ICD) mechanism. In this mechanism, an ICD file specifies the path to |
||||
the OpenCL driver for a particular GPU family. In NixOS, there are two |
||||
ways to make ICD files visible to the ICD loader. The first is through |
||||
the `OCL_ICD_VENDORS` environment variable. This variable can contain a |
||||
directory which is scanned by the ICL loader for ICD files. For example: |
||||
|
||||
```ShellSession |
||||
$ export \ |
||||
OCL_ICD_VENDORS=`nix-build '<nixpkgs>' --no-out-link -A rocm-opencl-icd`/etc/OpenCL/vendors/ |
||||
``` |
||||
|
||||
The second mechanism is to add the OpenCL driver package to |
||||
[](#opt-hardware.opengl.extraPackages). |
||||
This links the ICD file under `/run/opengl-driver`, where it will be visible |
||||
to the ICD loader. |
||||
|
||||
The proper installation of OpenCL drivers can be verified through the |
||||
`clinfo` command of the clinfo package. This command will report the |
||||
number of hardware devices that is found and give detailed information |
||||
for each device: |
||||
|
||||
```ShellSession |
||||
$ clinfo | head -n3 |
||||
Number of platforms 1 |
||||
Platform Name AMD Accelerated Parallel Processing |
||||
Platform Vendor Advanced Micro Devices, Inc. |
||||
``` |
||||
|
||||
### AMD {#sec-gpu-accel-opencl-amd} |
||||
|
||||
Modern AMD [Graphics Core |
||||
Next](https://en.wikipedia.org/wiki/Graphics_Core_Next) (GCN) GPUs are |
||||
supported through the rocm-opencl-icd package. Adding this package to |
||||
[](#opt-hardware.opengl.extraPackages) |
||||
enables OpenCL support: |
||||
|
||||
```nix |
||||
hardware.opengl.extraPackages = [ |
||||
rocm-opencl-icd |
||||
]; |
||||
``` |
||||
|
||||
### Intel {#sec-gpu-accel-opencl-intel} |
||||
|
||||
[Intel Gen8 and later |
||||
GPUs](https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units#Gen8) |
||||
are supported by the Intel NEO OpenCL runtime that is provided by the |
||||
intel-compute-runtime package. For Gen7 GPUs, the deprecated Beignet |
||||
runtime can be used, which is provided by the beignet package. The |
||||
proprietary Intel OpenCL runtime, in the intel-ocl package, is an |
||||
alternative for Gen7 GPUs. |
||||
|
||||
The intel-compute-runtime, beignet, or intel-ocl package can be added to |
||||
[](#opt-hardware.opengl.extraPackages) |
||||
to enable OpenCL support. For example, for Gen8 and later GPUs, the following |
||||
configuration can be used: |
||||
|
||||
```nix |
||||
hardware.opengl.extraPackages = [ |
||||
intel-compute-runtime |
||||
]; |
||||
``` |
||||
|
||||
## Vulkan {#sec-gpu-accel-vulkan} |
||||
|
||||
[Vulkan](https://en.wikipedia.org/wiki/Vulkan_(API)) is a graphics and |
||||
compute API for GPUs. It is used directly by games or indirectly though |
||||
compatibility layers like |
||||
[DXVK](https://github.com/doitsujin/dxvk/wiki). |
||||
|
||||
By default, if [](#opt-hardware.opengl.driSupport) |
||||
is enabled, mesa is installed and provides Vulkan for supported hardware. |
||||
|
||||
Similar to OpenCL, Vulkan drivers are loaded through the *Installable |
||||
Client Driver* (ICD) mechanism. ICD files for Vulkan are JSON files that |
||||
specify the path to the driver library and the supported Vulkan version. |
||||
All successfully loaded drivers are exposed to the application as |
||||
different GPUs. In NixOS, there are two ways to make ICD files visible |
||||
to Vulkan applications: an environment variable and a module option. |
||||
|
||||
The first option is through the `VK_ICD_FILENAMES` environment variable. |
||||
This variable can contain multiple JSON files, separated by `:`. For |
||||
example: |
||||
|
||||
```ShellSession |
||||
$ export \ |
||||
VK_ICD_FILENAMES=`nix-build '<nixpkgs>' --no-out-link -A amdvlk`/share/vulkan/icd.d/amd_icd64.json |
||||
``` |
||||
|
||||
The second mechanism is to add the Vulkan driver package to |
||||
[](#opt-hardware.opengl.extraPackages). |
||||
This links the ICD file under `/run/opengl-driver`, where it will be |
||||
visible to the ICD loader. |
||||
|
||||
The proper installation of Vulkan drivers can be verified through the |
||||
`vulkaninfo` command of the vulkan-tools package. This command will |
||||
report the hardware devices and drivers found, in this example output |
||||
amdvlk and radv: |
||||
|
||||
```ShellSession |
||||
$ vulkaninfo | grep GPU |
||||
GPU id : 0 (Unknown AMD GPU) |
||||
GPU id : 1 (AMD RADV NAVI10 (LLVM 9.0.1)) |
||||
... |
||||
GPU0: |
||||
deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU |
||||
deviceName = Unknown AMD GPU |
||||
GPU1: |
||||
deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU |
||||
``` |
||||
|
||||
A simple graphical application that uses Vulkan is `vkcube` from the |
||||
vulkan-tools package. |
||||
|
||||
### AMD {#sec-gpu-accel-vulkan-amd} |
||||
|
||||
Modern AMD [Graphics Core |
||||
Next](https://en.wikipedia.org/wiki/Graphics_Core_Next) (GCN) GPUs are |
||||
supported through either radv, which is part of mesa, or the amdvlk |
||||
package. Adding the amdvlk package to |
||||
[](#opt-hardware.opengl.extraPackages) |
||||
makes amdvlk the default driver and hides radv and lavapipe from the device list. |
||||
A specific driver can be forced as follows: |
||||
|
||||
```nix |
||||
hardware.opengl.extraPackages = [ |
||||
pkgs.amdvlk |
||||
]; |
||||
|
||||
# To enable Vulkan support for 32-bit applications, also add: |
||||
hardware.opengl.extraPackages32 = [ |
||||
pkgs.driversi686Linux.amdvlk |
||||
]; |
||||
|
||||
# Force radv |
||||
environment.variables.AMD_VULKAN_ICD = "RADV"; |
||||
# Or |
||||
environment.variables.VK_ICD_FILENAMES = |
||||
"/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json"; |
||||
``` |
||||
|
||||
## Common issues {#sec-gpu-accel-common-issues} |
||||
|
||||
### User permissions {#sec-gpu-accel-common-issues-permissions} |
||||
|
||||
Except where noted explicitly, it should not be necessary to adjust user |
||||
permissions to use these acceleration APIs. In the default |
||||
configuration, GPU devices have world-read/write permissions |
||||
(`/dev/dri/renderD*`) or are tagged as `uaccess` (`/dev/dri/card*`). The |
||||
access control lists of devices with the `uaccess` tag will be updated |
||||
automatically when a user logs in through `systemd-logind`. For example, |
||||
if the user *jane* is logged in, the access control list should look as |
||||
follows: |
||||
|
||||
```ShellSession |
||||
$ getfacl /dev/dri/card0 |
||||
# file: dev/dri/card0 |
||||
# owner: root |
||||
# group: video |
||||
user::rw- |
||||
user:jane:rw- |
||||
group::rw- |
||||
mask::rw- |
||||
other::--- |
||||
``` |
||||
|
||||
If you disabled (this functionality of) `systemd-logind`, you may need |
||||
to add the user to the `video` group and log in again. |
||||
|
||||
### Mixing different versions of nixpkgs {#sec-gpu-accel-common-issues-mixing-nixpkgs} |
||||
|
||||
The *Installable Client Driver* (ICD) mechanism used by OpenCL and |
||||
Vulkan loads runtimes into its address space using `dlopen`. Mixing an |
||||
ICD loader mechanism and runtimes from different version of nixpkgs may |
||||
not work. For example, if the ICD loader uses an older version of glibc |
||||
than the runtime, the runtime may not be loadable due to missing |
||||
symbols. Unfortunately, the loader will generally be quiet about such |
||||
issues. |
||||
|
||||
If you suspect that you are running into library version mismatches |
||||
between an ICL loader and a runtime, you could run an application with |
||||
the `LD_DEBUG` variable set to get more diagnostic information. For |
||||
example, OpenCL can be tested with `LD_DEBUG=files clinfo`, which should |
||||
report missing symbols. |
@ -1,262 +0,0 @@ |
||||
<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="sec-gpu-accel"> |
||||
<title>GPU acceleration</title> |
||||
|
||||
<para> |
||||
NixOS provides various APIs that benefit from GPU hardware |
||||
acceleration, such as VA-API and VDPAU for video playback; OpenGL and |
||||
Vulkan for 3D graphics; and OpenCL for general-purpose computing. |
||||
This chapter describes how to set up GPU hardware acceleration (as far |
||||
as this is not done automatically) and how to verify that hardware |
||||
acceleration is indeed used. |
||||
</para> |
||||
|
||||
<para> |
||||
Most of the aforementioned APIs are agnostic with regards to which |
||||
display server is used. Consequently, these instructions should apply |
||||
both to the X Window System and Wayland compositors. |
||||
</para> |
||||
|
||||
<section xml:id="sec-gpu-accel-opencl"> |
||||
<title>OpenCL</title> |
||||
|
||||
<para> |
||||
<link xlink:href="https://en.wikipedia.org/wiki/OpenCL">OpenCL</link> is a |
||||
general compute API. It is used by various applications such as |
||||
Blender and Darktable to accelerate certain operations. |
||||
</para> |
||||
|
||||
<para> |
||||
OpenCL applications load drivers through the <emphasis>Installable Client |
||||
Driver</emphasis> (ICD) mechanism. In this mechanism, an ICD file |
||||
specifies the path to the OpenCL driver for a particular GPU family. |
||||
In NixOS, there are two ways to make ICD files visible to the ICD |
||||
loader. The first is through the <varname>OCL_ICD_VENDORS</varname> |
||||
environment variable. This variable can contain a directory which |
||||
is scanned by the ICL loader for ICD files. For example: |
||||
|
||||
<screen><prompt>$</prompt> export \ |
||||
OCL_ICD_VENDORS=`nix-build '<nixpkgs>' --no-out-link -A rocm-opencl-icd`/etc/OpenCL/vendors/</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
The second mechanism is to add the OpenCL driver package to |
||||
<xref linkend="opt-hardware.opengl.extraPackages"/>. This links the |
||||
ICD file under <filename>/run/opengl-driver</filename>, where it will |
||||
be visible to the ICD loader. |
||||
</para> |
||||
|
||||
<para> |
||||
The proper installation of OpenCL drivers can be verified through |
||||
the <command>clinfo</command> command of the <package>clinfo</package> |
||||
package. This command will report the number of hardware devices |
||||
that is found and give detailed information for each device: |
||||
</para> |
||||
|
||||
<screen><prompt>$</prompt> clinfo | head -n3 |
||||
Number of platforms 1 |
||||
Platform Name AMD Accelerated Parallel Processing |
||||
Platform Vendor Advanced Micro Devices, Inc.</screen> |
||||
|
||||
<section xml:id="sec-gpu-accel-opencl-amd"> |
||||
<title>AMD</title> |
||||
|
||||
<para> |
||||
Modern AMD <link |
||||
xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics |
||||
Core Next</link> (GCN) GPUs are supported through the |
||||
<package>rocm-opencl-icd</package> package. Adding this package to |
||||
<xref linkend="opt-hardware.opengl.extraPackages"/> enables OpenCL |
||||
support: |
||||
|
||||
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ |
||||
rocm-opencl-icd |
||||
];</programlisting> |
||||
</para> |
||||
</section> |
||||
|
||||
<section xml:id="sec-gpu-accel-opencl-intel"> |
||||
<title>Intel</title> |
||||
|
||||
<para> |
||||
<link |
||||
xlink:href="https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units#Gen8">Intel |
||||
Gen8 and later GPUs</link> are supported by the Intel NEO OpenCL |
||||
runtime that is provided by the |
||||
<package>intel-compute-runtime</package> package. For Gen7 GPUs, |
||||
the deprecated Beignet runtime can be used, which is provided |
||||
by the <package>beignet</package> package. The proprietary Intel |
||||
OpenCL runtime, in the <package>intel-ocl</package> package, is |
||||
an alternative for Gen7 GPUs. |
||||
</para> |
||||
|
||||
<para> |
||||
The <package>intel-compute-runtime</package>, <package>beignet</package>, |
||||
or <package>intel-ocl</package> package can be added to |
||||
<xref linkend="opt-hardware.opengl.extraPackages"/> to enable OpenCL |
||||
support. For example, for Gen8 and later GPUs, the following |
||||
configuration can be used: |
||||
|
||||
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ |
||||
intel-compute-runtime |
||||
];</programlisting> |
||||
|
||||
</para> |
||||
</section> |
||||
</section> |
||||
|
||||
<section xml:id="sec-gpu-accel-vulkan"> |
||||
<title>Vulkan</title> |
||||
|
||||
<para> |
||||
<link xlink:href="https://en.wikipedia.org/wiki/Vulkan_(API)">Vulkan</link> is a |
||||
graphics and compute API for GPUs. It is used directly by games or indirectly though |
||||
compatibility layers like <link xlink:href="https://github.com/doitsujin/dxvk/wiki">DXVK</link>. |
||||
</para> |
||||
|
||||
<para> |
||||
By default, if <xref linkend="opt-hardware.opengl.driSupport"/> is enabled, |
||||
<package>mesa</package> is installed and provides Vulkan for supported hardware. |
||||
</para> |
||||
|
||||
<para> |
||||
Similar to OpenCL, Vulkan drivers are loaded through the <emphasis>Installable Client |
||||
Driver</emphasis> (ICD) mechanism. ICD files for Vulkan are JSON files that specify |
||||
the path to the driver library and the supported Vulkan version. All successfully |
||||
loaded drivers are exposed to the application as different GPUs. |
||||
In NixOS, there are two ways to make ICD files visible to Vulkan applications: an |
||||
environment variable and a module option. |
||||
</para> |
||||
|
||||
<para> |
||||
The first option is through the <varname>VK_ICD_FILENAMES</varname> |
||||
environment variable. This variable can contain multiple JSON files, separated by |
||||
<literal>:</literal>. For example: |
||||
|
||||
<screen><prompt>$</prompt> export \ |
||||
VK_ICD_FILENAMES=`nix-build '<nixpkgs>' --no-out-link -A amdvlk`/share/vulkan/icd.d/amd_icd64.json</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
The second mechanism is to add the Vulkan driver package to |
||||
<xref linkend="opt-hardware.opengl.extraPackages"/>. This links the |
||||
ICD file under <filename>/run/opengl-driver</filename>, where it will |
||||
be visible to the ICD loader. |
||||
</para> |
||||
|
||||
<para> |
||||
The proper installation of Vulkan drivers can be verified through |
||||
the <command>vulkaninfo</command> command of the <package>vulkan-tools</package> |
||||
package. This command will report the hardware devices and drivers found, |
||||
in this example output amdvlk and radv: |
||||
</para> |
||||
|
||||
<screen><prompt>$</prompt> vulkaninfo | grep GPU |
||||
GPU id : 0 (Unknown AMD GPU) |
||||
GPU id : 1 (AMD RADV NAVI10 (LLVM 9.0.1)) |
||||
... |
||||
GPU0: |
||||
deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU |
||||
deviceName = Unknown AMD GPU |
||||
GPU1: |
||||
deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU</screen> |
||||
|
||||
<para> |
||||
A simple graphical application that uses Vulkan is <command>vkcube</command> |
||||
from the <package>vulkan-tools</package> package. |
||||
</para> |
||||
|
||||
<section xml:id="sec-gpu-accel-vulkan-amd"> |
||||
<title>AMD</title> |
||||
|
||||
<para> |
||||
Modern AMD <link |
||||
xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics |
||||
Core Next</link> (GCN) GPUs are supported through either radv, which is |
||||
part of <package>mesa</package>, or the <package>amdvlk</package> package. |
||||
Adding the <package>amdvlk</package> package to |
||||
<xref linkend="opt-hardware.opengl.extraPackages"/> makes amdvlk the |
||||
default driver and hides radv and lavapipe from the device list. A |
||||
specific driver can be forced as follows: |
||||
|
||||
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ |
||||
pkgs.<package>amdvlk</package> |
||||
]; |
||||
|
||||
# To enable Vulkan support for 32-bit applications, also add: |
||||
<xref linkend="opt-hardware.opengl.extraPackages32"/> = [ |
||||
pkgs.driversi686Linux.<package>amdvlk</package> |
||||
]; |
||||
|
||||
# Force radv |
||||
<xref linkend="opt-environment.variables"/>.AMD_VULKAN_ICD = "RADV"; |
||||
# Or |
||||
<xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES = |
||||
"/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json"; |
||||
</programlisting> |
||||
</para> |
||||
</section> |
||||
</section> |
||||
|
||||
<section xml:id="sec-gpu-accel-common-issues"> |
||||
<title>Common issues</title> |
||||
|
||||
<section xml:id="sec-gpu-accel-common-issues-permissions"> |
||||
<title>User permissions</title> |
||||
|
||||
<para> |
||||
Except where noted explicitly, it should not be necessary to |
||||
adjust user permissions to use these acceleration APIs. In the default |
||||
configuration, GPU devices have world-read/write permissions |
||||
(<filename>/dev/dri/renderD*</filename>) or are tagged as |
||||
<code>uaccess</code> (<filename>/dev/dri/card*</filename>). The |
||||
access control lists of devices with the <varname>uaccess</varname> |
||||
tag will be updated automatically when a user logs in through |
||||
<command>systemd-logind</command>. For example, if the user |
||||
<emphasis>jane</emphasis> is logged in, the access control list |
||||
should look as follows: |
||||
|
||||
<screen><prompt>$</prompt> getfacl /dev/dri/card0 |
||||
# file: dev/dri/card0 |
||||
# owner: root |
||||
# group: video |
||||
user::rw- |
||||
user:jane:rw- |
||||
group::rw- |
||||
mask::rw- |
||||
other::---</screen> |
||||
|
||||
If you disabled (this functionality of) <command>systemd-logind</command>, |
||||
you may need to add the user to the <code>video</code> group and |
||||
log in again. |
||||
</para> |
||||
</section> |
||||
|
||||
<section xml:id="sec-gpu-accel-common-issues-mixing-nixpkgs"> |
||||
<title>Mixing different versions of nixpkgs</title> |
||||
|
||||
<para> |
||||
The <emphasis>Installable Client Driver</emphasis> (ICD) |
||||
mechanism used by OpenCL and Vulkan loads runtimes into its address |
||||
space using <code>dlopen</code>. Mixing an ICD loader mechanism and |
||||
runtimes from different version of nixpkgs may not work. For example, |
||||
if the ICD loader uses an older version of <package>glibc</package> |
||||
than the runtime, the runtime may not be loadable due to |
||||
missing symbols. Unfortunately, the loader will generally be quiet |
||||
about such issues. |
||||
</para> |
||||
|
||||
<para> |
||||
If you suspect that you are running into library version mismatches |
||||
between an ICL loader and a runtime, you could run an application with |
||||
the <code>LD_DEBUG</code> variable set to get more diagnostic |
||||
information. For example, OpenCL can be tested with |
||||
<code>LD_DEBUG=files clinfo</code>, which should report missing |
||||
symbols. |
||||
</para> |
||||
</section> |
||||
</section> |
||||
</chapter> |
@ -0,0 +1,35 @@ |
||||
# IPv4 Configuration {#sec-ipv4} |
||||
|
||||
By default, NixOS uses DHCP (specifically, `dhcpcd`) to automatically |
||||
configure network interfaces. However, you can configure an interface |
||||
manually as follows: |
||||
|
||||
```nix |
||||
networking.interfaces.eth0.ipv4.addresses = [ { |
||||
address = "192.168.1.2"; |
||||
prefixLength = 24; |
||||
} ]; |
||||
``` |
||||
|
||||
Typically you'll also want to set a default gateway and set of name |
||||
servers: |
||||
|
||||
```nix |
||||
networking.defaultGateway = "192.168.1.1"; |
||||
networking.nameservers = [ "8.8.8.8" ]; |
||||
``` |
||||
|
||||
::: {.note} |
||||
Statically configured interfaces are set up by the systemd service |
||||
`interface-name-cfg.service`. The default gateway and name server |
||||
configuration is performed by `network-setup.service`. |
||||
::: |
||||
|
||||
The host name is set using [](#opt-networking.hostName): |
||||
|
||||
```nix |
||||
networking.hostName = "cartman"; |
||||
``` |
||||
|
||||
The default host name is `nixos`. Set it to the empty string (`""`) to |
||||
allow the DHCP server to provide the host name. |
@ -1,43 +0,0 @@ |
||||
<section 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="sec-ipv4"> |
||||
<title>IPv4 Configuration</title> |
||||
|
||||
<para> |
||||
By default, NixOS uses DHCP (specifically, <command>dhcpcd</command>) to |
||||
automatically configure network interfaces. However, you can configure an |
||||
interface manually as follows: |
||||
<programlisting> |
||||
<link linkend="opt-networking.interfaces._name_.ipv4.addresses">networking.interfaces.eth0.ipv4.addresses</link> = [ { |
||||
address = "192.168.1.2"; |
||||
prefixLength = 24; |
||||
} ]; |
||||
</programlisting> |
||||
Typically you’ll also want to set a default gateway and set of name |
||||
servers: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.defaultGateway"/> = "192.168.1.1"; |
||||
<xref linkend="opt-networking.nameservers"/> = [ "8.8.8.8" ]; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<note> |
||||
<para> |
||||
Statically configured interfaces are set up by the systemd service |
||||
<replaceable>interface-name</replaceable><literal>-cfg.service</literal>. |
||||
The default gateway and name server configuration is performed by |
||||
<literal>network-setup.service</literal>. |
||||
</para> |
||||
</note> |
||||
|
||||
<para> |
||||
The host name is set using <xref linkend="opt-networking.hostName"/>: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.hostName"/> = "cartman"; |
||||
</programlisting> |
||||
The default host name is <literal>nixos</literal>. Set it to the empty string |
||||
(<literal>""</literal>) to allow the DHCP server to provide the host name. |
||||
</para> |
||||
</section> |
@ -0,0 +1,42 @@ |
||||
# IPv6 Configuration {#sec-ipv6} |
||||
|
||||
IPv6 is enabled by default. Stateless address autoconfiguration is used |
||||
to automatically assign IPv6 addresses to all interfaces, and Privacy |
||||
Extensions (RFC 4946) are enabled by default. You can adjust the default |
||||
for this by setting [](#opt-networking.tempAddresses). This option |
||||
may be overridden on a per-interface basis by |
||||
[](#opt-networking.interfaces._name_.tempAddress). You can disable |
||||
IPv6 support globally by setting: |
||||
|
||||
```nix |
||||
networking.enableIPv6 = false; |
||||
``` |
||||
|
||||
You can disable IPv6 on a single interface using a normal sysctl (in |
||||
this example, we use interface `eth0`): |
||||
|
||||
```nix |
||||
boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true; |
||||
``` |
||||
|
||||
As with IPv4 networking interfaces are automatically configured via |
||||
DHCPv6. You can configure an interface manually: |
||||
|
||||
```nix |
||||
networking.interfaces.eth0.ipv6.addresses = [ { |
||||
address = "fe00:aa:bb:cc::2"; |
||||
prefixLength = 64; |
||||
} ]; |
||||
``` |
||||
|
||||
For configuring a gateway, optionally with explicitly specified |
||||
interface: |
||||
|
||||
```nix |
||||
networking.defaultGateway6 = { |
||||
address = "fe00::1"; |
||||
interface = "enp0s3"; |
||||
}; |
||||
``` |
||||
|
||||
See [](#sec-ipv4) for similar examples and additional information. |
@ -1,54 +0,0 @@ |
||||
<section 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="sec-ipv6"> |
||||
<title>IPv6 Configuration</title> |
||||
|
||||
<para> |
||||
IPv6 is enabled by default. Stateless address autoconfiguration is used to |
||||
automatically assign IPv6 addresses to all interfaces, and Privacy |
||||
Extensions (RFC 4946) are enabled by default. You can adjust the default |
||||
for this by setting <xref linkend="opt-networking.tempAddresses"/>. |
||||
This option may be overridden on a per-interface basis by |
||||
<xref linkend="opt-networking.interfaces._name_.tempAddress"/>. |
||||
You can disable IPv6 support globally by setting: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.enableIPv6"/> = false; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<para> |
||||
You can disable IPv6 on a single interface using a normal sysctl (in this |
||||
example, we use interface <varname>eth0</varname>): |
||||
<programlisting> |
||||
<xref linkend="opt-boot.kernel.sysctl"/>."net.ipv6.conf.eth0.disable_ipv6" = true; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<para> |
||||
As with IPv4 networking interfaces are automatically configured via DHCPv6. |
||||
You can configure an interface manually: |
||||
<programlisting> |
||||
<link linkend="opt-networking.interfaces._name_.ipv6.addresses">networking.interfaces.eth0.ipv6.addresses</link> = [ { |
||||
address = "fe00:aa:bb:cc::2"; |
||||
prefixLength = 64; |
||||
} ]; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<para> |
||||
For configuring a gateway, optionally with explicitly specified interface: |
||||
<programlisting> |
||||
<xref linkend="opt-networking.defaultGateway6"/> = { |
||||
address = "fe00::1"; |
||||
interface = "enp0s3"; |
||||
}; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<para> |
||||
See <xref linkend='sec-ipv4' /> for similar examples and additional |
||||
information. |
||||
</para> |
||||
</section> |
@ -0,0 +1,104 @@ |
||||
# Kubernetes {#sec-kubernetes} |
||||
|
||||
The NixOS Kubernetes module is a collective term for a handful of |
||||
individual submodules implementing the Kubernetes cluster components. |
||||
|
||||
There are generally two ways of enabling Kubernetes on NixOS. One way is |
||||
to enable and configure cluster components appropriately by hand: |
||||
|
||||
```nix |
||||
services.kubernetes = { |
||||
apiserver.enable = true; |
||||
controllerManager.enable = true; |
||||
scheduler.enable = true; |
||||
addonManager.enable = true; |
||||
proxy.enable = true; |
||||
flannel.enable = true; |
||||
}; |
||||
``` |
||||
|
||||
Another way is to assign cluster roles (\"master\" and/or \"node\") to |
||||
the host. This enables apiserver, controllerManager, scheduler, |
||||
addonManager, kube-proxy and etcd: |
||||
|
||||
```nix |
||||
services.kubernetes.roles = [ "master" ]; |
||||
``` |
||||
|
||||
While this will enable the kubelet and kube-proxy only: |
||||
|
||||
```nix |
||||
services.kubernetes.roles = [ "node" ]; |
||||
``` |
||||
|
||||
Assigning both the master and node roles is usable if you want a single |
||||
node Kubernetes cluster for dev or testing purposes: |
||||
|
||||
```nix |
||||
services.kubernetes.roles = [ "master" "node" ]; |
||||
``` |
||||
|
||||
Note: Assigning either role will also default both |
||||
[](#opt-services.kubernetes.flannel.enable) |
||||
and [](#opt-services.kubernetes.easyCerts) |
||||
to true. This sets up flannel as CNI and activates automatic PKI bootstrapping. |
||||
|
||||
As of kubernetes 1.10.X it has been deprecated to open non-tls-enabled |
||||
ports on kubernetes components. Thus, from NixOS 19.03 all plain HTTP |
||||
ports have been disabled by default. While opening insecure ports is |
||||
still possible, it is recommended not to bind these to other interfaces |
||||
than loopback. To re-enable the insecure port on the apiserver, see options: |
||||
[](#opt-services.kubernetes.apiserver.insecurePort) and |
||||
[](#opt-services.kubernetes.apiserver.insecureBindAddress) |
||||
|
||||
::: {.note} |
||||
As of NixOS 19.03, it is mandatory to configure: |
||||
[](#opt-services.kubernetes.masterAddress). |
||||
The masterAddress must be resolveable and routeable by all cluster nodes. |
||||
In single node clusters, this can be set to `localhost`. |
||||
::: |
||||
|
||||
Role-based access control (RBAC) authorization mode is enabled by |
||||
default. This means that anonymous requests to the apiserver secure port |
||||
will expectedly cause a permission denied error. All cluster components |
||||
must therefore be configured with x509 certificates for two-way tls |
||||
communication. The x509 certificate subject section determines the roles |
||||
and permissions granted by the apiserver to perform clusterwide or |
||||
namespaced operations. See also: [ Using RBAC |
||||
Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/). |
||||
|
||||
The NixOS kubernetes module provides an option for automatic certificate |
||||
bootstrapping and configuration, |
||||
[](#opt-services.kubernetes.easyCerts). |
||||
The PKI bootstrapping process involves setting up a certificate authority (CA) |
||||
daemon (cfssl) on the kubernetes master node. cfssl generates a CA-cert |
||||
for the cluster, and uses the CA-cert for signing subordinate certs issued |
||||
to each of the cluster components. Subsequently, the certmgr daemon monitors |
||||
active certificates and renews them when needed. For single node Kubernetes |
||||
clusters, setting [](#opt-services.kubernetes.easyCerts) |
||||
= true is sufficient and no further action is required. For joining extra node |
||||
machines to an existing cluster on the other hand, establishing initial |
||||
trust is mandatory. |
||||
|
||||
To add new nodes to the cluster: On any (non-master) cluster node where |
||||
[](#opt-services.kubernetes.easyCerts) |
||||
is enabled, the helper script `nixos-kubernetes-node-join` is available on PATH. |
||||
Given a token on stdin, it will copy the token to the kubernetes secrets directory |
||||
and restart the certmgr service. As requested certificates are issued, the |
||||
script will restart kubernetes cluster components as needed for them to |
||||
pick up new keypairs. |
||||
|
||||
::: {.note} |
||||
Multi-master (HA) clusters are not supported by the easyCerts module. |
||||
::: |
||||
|
||||
In order to interact with an RBAC-enabled cluster as an administrator, |
||||
one needs to have cluster-admin privileges. By default, when easyCerts |
||||
is enabled, a cluster-admin kubeconfig file is generated and linked into |
||||
`/etc/kubernetes/cluster-admin.kubeconfig` as determined by |
||||
[](#opt-services.kubernetes.pki.etcClusterAdminKubeconfig). |
||||
`export KUBECONFIG=/etc/kubernetes/cluster-admin.kubeconfig` will make |
||||
kubectl use this kubeconfig to access and authenticate the cluster. The |
||||
cluster-admin kubeconfig references an auto-generated keypair owned by |
||||
root. Thus, only root on the kubernetes master may obtain cluster-admin |
||||
rights by means of this file. |
@ -1,112 +0,0 @@ |
||||
<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="sec-kubernetes"> |
||||
<title>Kubernetes</title> |
||||
<para> |
||||
The NixOS Kubernetes module is a collective term for a handful of individual |
||||
submodules implementing the Kubernetes cluster components. |
||||
</para> |
||||
<para> |
||||
There are generally two ways of enabling Kubernetes on NixOS. One way is to |
||||
enable and configure cluster components appropriately by hand: |
||||
<programlisting> |
||||
services.kubernetes = { |
||||
apiserver.enable = true; |
||||
controllerManager.enable = true; |
||||
scheduler.enable = true; |
||||
addonManager.enable = true; |
||||
proxy.enable = true; |
||||
flannel.enable = true; |
||||
}; |
||||
</programlisting> |
||||
Another way is to assign cluster roles ("master" and/or "node") to the host. |
||||
This enables apiserver, controllerManager, scheduler, addonManager, |
||||
kube-proxy and etcd: |
||||
<programlisting> |
||||
<xref linkend="opt-services.kubernetes.roles"/> = [ "master" ]; |
||||
</programlisting> |
||||
While this will enable the kubelet and kube-proxy only: |
||||
<programlisting> |
||||
<xref linkend="opt-services.kubernetes.roles"/> = [ "node" ]; |
||||
</programlisting> |
||||
Assigning both the master and node roles is usable if you want a single node |
||||
Kubernetes cluster for dev or testing purposes: |
||||
<programlisting> |
||||
<xref linkend="opt-services.kubernetes.roles"/> = [ "master" "node" ]; |
||||
</programlisting> |
||||
Note: Assigning either role will also default both |
||||
<xref linkend="opt-services.kubernetes.flannel.enable"/> and |
||||
<xref linkend="opt-services.kubernetes.easyCerts"/> to true. This sets up |
||||
flannel as CNI and activates automatic PKI bootstrapping. |
||||
</para> |
||||
<para> |
||||
As of kubernetes 1.10.X it has been deprecated to open non-tls-enabled ports |
||||
on kubernetes components. Thus, from NixOS 19.03 all plain HTTP ports have |
||||
been disabled by default. While opening insecure ports is still possible, it |
||||
is recommended not to bind these to other interfaces than loopback. To |
||||
re-enable the insecure port on the apiserver, see options: |
||||
<xref linkend="opt-services.kubernetes.apiserver.insecurePort"/> and |
||||
<xref linkend="opt-services.kubernetes.apiserver.insecureBindAddress"/> |
||||
</para> |
||||
<note> |
||||
<para> |
||||
As of NixOS 19.03, it is mandatory to configure: |
||||
<xref linkend="opt-services.kubernetes.masterAddress"/>. The masterAddress |
||||
must be resolveable and routeable by all cluster nodes. In single node |
||||
clusters, this can be set to <literal>localhost</literal>. |
||||
</para> |
||||
</note> |
||||
<para> |
||||
Role-based access control (RBAC) authorization mode is enabled by default. |
||||
This means that anonymous requests to the apiserver secure port will |
||||
expectedly cause a permission denied error. All cluster components must |
||||
therefore be configured with x509 certificates for two-way tls communication. |
||||
The x509 certificate subject section determines the roles and permissions |
||||
granted by the apiserver to perform clusterwide or namespaced operations. See |
||||
also: |
||||
<link |
||||
xlink:href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/"> |
||||
Using RBAC Authorization</link>. |
||||
</para> |
||||
<para> |
||||
The NixOS kubernetes module provides an option for automatic certificate |
||||
bootstrapping and configuration, |
||||
<xref linkend="opt-services.kubernetes.easyCerts"/>. The PKI bootstrapping |
||||
process involves setting up a certificate authority (CA) daemon (cfssl) on |
||||
the kubernetes master node. cfssl generates a CA-cert for the cluster, and |
||||
uses the CA-cert for signing subordinate certs issued to each of the cluster |
||||
components. Subsequently, the certmgr daemon monitors active certificates and |
||||
renews them when needed. For single node Kubernetes clusters, setting |
||||
<xref linkend="opt-services.kubernetes.easyCerts"/> = true is sufficient and |
||||
no further action is required. For joining extra node machines to an existing |
||||
cluster on the other hand, establishing initial trust is mandatory. |
||||
</para> |
||||
<para> |
||||
To add new nodes to the cluster: On any (non-master) cluster node where |
||||
<xref linkend="opt-services.kubernetes.easyCerts"/> is enabled, the helper |
||||
script <literal>nixos-kubernetes-node-join</literal> is available on PATH. |
||||
Given a token on stdin, it will copy the token to the kubernetes secrets |
||||
directory and restart the certmgr service. As requested certificates are |
||||
issued, the script will restart kubernetes cluster components as needed for |
||||
them to pick up new keypairs. |
||||
</para> |
||||
<note> |
||||
<para> |
||||
Multi-master (HA) clusters are not supported by the easyCerts module. |
||||
</para> |
||||
</note> |
||||
<para> |
||||
In order to interact with an RBAC-enabled cluster as an administrator, one |
||||
needs to have cluster-admin privileges. By default, when easyCerts is |
||||
enabled, a cluster-admin kubeconfig file is generated and linked into |
||||
<literal>/etc/kubernetes/cluster-admin.kubeconfig</literal> as determined by |
||||
<xref linkend="opt-services.kubernetes.pki.etcClusterAdminKubeconfig"/>. |
||||
<literal>export KUBECONFIG=/etc/kubernetes/cluster-admin.kubeconfig</literal> |
||||
will make kubectl use this kubeconfig to access and authenticate the cluster. |
||||
The cluster-admin kubeconfig references an auto-generated keypair owned by |
||||
root. Thus, only root on the kubernetes master may obtain cluster-admin |
||||
rights by means of this file. |
||||
</para> |
||||
</chapter> |
@ -0,0 +1,135 @@ |
||||
# Linux Kernel {#sec-kernel-config} |
||||
|
||||
You can override the Linux kernel and associated packages using the |
||||
option `boot.kernelPackages`. For instance, this selects the Linux 3.10 |
||||
kernel: |
||||
|
||||
```nix |
||||
boot.kernelPackages = pkgs.linuxPackages_3_10; |
||||
``` |
||||
|
||||
Note that this not only replaces the kernel, but also packages that are |
||||
specific to the kernel version, such as the NVIDIA video drivers. This |
||||
ensures that driver packages are consistent with the kernel. |
||||
|
||||
The default Linux kernel configuration should be fine for most users. |
||||
You can see the configuration of your current kernel with the following |
||||
command: |
||||
|
||||
```ShellSession |
||||
zcat /proc/config.gz |
||||
``` |
||||
|
||||
If you want to change the kernel configuration, you can use the |
||||
`packageOverrides` feature (see [](#sec-customising-packages)). For |
||||
instance, to enable support for the kernel debugger KGDB: |
||||
|
||||
```nix |
||||
nixpkgs.config.packageOverrides = pkgs: |
||||
{ linux_3_4 = pkgs.linux_3_4.override { |
||||
extraConfig = |
||||
'' |
||||
KGDB y |
||||
''; |
||||
}; |
||||
}; |
||||
``` |
||||
|
||||
`extraConfig` takes a list of Linux kernel configuration options, one |
||||
per line. The name of the option should not include the prefix |
||||
`CONFIG_`. The option value is typically `y`, `n` or `m` (to build |
||||
something as a kernel module). |
||||
|
||||
Kernel modules for hardware devices are generally loaded automatically |
||||
by `udev`. You can force a module to be loaded via |
||||
[](#opt-boot.kernelModules), e.g. |
||||
|
||||
```nix |
||||
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ]; |
||||
``` |
||||
|
||||
If the module is required early during the boot (e.g. to mount the root |
||||
file system), you can use [](#opt-boot.initrd.kernelModules): |
||||
|
||||
```nix |
||||
boot.initrd.kernelModules = [ "cifs" ]; |
||||
``` |
||||
|
||||
This causes the specified modules and their dependencies to be added to |
||||
the initial ramdisk. |
||||
|
||||
Kernel runtime parameters can be set through |
||||
[](#opt-boot.kernel.sysctl), e.g. |
||||
|
||||
```nix |
||||
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120; |
||||
``` |
||||
|
||||
sets the kernel's TCP keepalive time to 120 seconds. To see the |
||||
available parameters, run `sysctl -a`. |
||||
|
||||
## Customize your kernel {#sec-linux-config-customizing} |
||||
|
||||
The first step before compiling the kernel is to generate an appropriate |
||||
`.config` configuration. Either you pass your own config via the |
||||
`configfile` setting of `linuxManualConfig`: |
||||
|
||||
```nix |
||||
custom-kernel = super.linuxManualConfig { |
||||
inherit (super) stdenv hostPlatform; |
||||
inherit (linux_4_9) src; |
||||
version = "${linux_4_9.version}-custom"; |
||||
|
||||
configfile = /home/me/my_kernel_config; |
||||
allowImportFromDerivation = true; |
||||
}; |
||||
``` |
||||
|
||||
You can edit the config with this snippet (by default `make |
||||
menuconfig` won\'t work out of the box on nixos): |
||||
|
||||
```ShellSession |
||||
nix-shell -E 'with import <nixpkgs> {}; kernelToOverride.overrideAttrs (o: {nativeBuildInputs=o.nativeBuildInputs ++ [ pkg-config ncurses ];})' |
||||
``` |
||||
|
||||
or you can let nixpkgs generate the configuration. Nixpkgs generates it |
||||
via answering the interactive kernel utility `make config`. The answers |
||||
depend on parameters passed to |
||||
`pkgs/os-specific/linux/kernel/generic.nix` (which you can influence by |
||||
overriding `extraConfig, autoModules, |
||||
modDirVersion, preferBuiltin, extraConfig`). |
||||
|
||||
```nix |
||||
mptcp93.override ({ |
||||
name="mptcp-local"; |
||||
|
||||
ignoreConfigErrors = true; |
||||
autoModules = false; |
||||
kernelPreferBuiltin = true; |
||||
|
||||
enableParallelBuilding = true; |
||||
|
||||
extraConfig = '' |
||||
DEBUG_KERNEL y |
||||
FRAME_POINTER y |
||||
KGDB y |
||||
KGDB_SERIAL_CONSOLE y |
||||
DEBUG_INFO y |
||||
''; |
||||
}); |
||||
``` |
||||
|
||||
## Developing kernel modules {#sec-linux-config-developing-modules} |
||||
|
||||
When developing kernel modules it\'s often convenient to run |
||||
edit-compile-run loop as quickly as possible. See below snippet as an |
||||
example of developing `mellanox` drivers. |
||||
|
||||
```ShellSession |
||||
$ nix-build '<nixpkgs>' -A linuxPackages.kernel.dev |
||||
$ nix-shell '<nixpkgs>' -A linuxPackages.kernel |
||||
$ unpackPhase |
||||
$ cd linux-* |
||||
$ make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules |
||||
# insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko |
||||
``` |
@ -1,138 +0,0 @@ |
||||
<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="sec-kernel-config"> |
||||
<title>Linux Kernel</title> |
||||
<para> |
||||
You can override the Linux kernel and associated packages using the option |
||||
<option>boot.kernelPackages</option>. For instance, this selects the Linux |
||||
3.10 kernel: |
||||
<programlisting> |
||||
<xref linkend="opt-boot.kernelPackages"/> = pkgs.linuxPackages_3_10; |
||||
</programlisting> |
||||
Note that this not only replaces the kernel, but also packages that are |
||||
specific to the kernel version, such as the NVIDIA video drivers. This |
||||
ensures that driver packages are consistent with the kernel. |
||||
</para> |
||||
<para> |
||||
The default Linux kernel configuration should be fine for most users. You can |
||||
see the configuration of your current kernel with the following command: |
||||
<programlisting> |
||||
zcat /proc/config.gz |
||||
</programlisting> |
||||
If you want to change the kernel configuration, you can use the |
||||
<option>packageOverrides</option> feature (see |
||||
<xref |
||||
linkend="sec-customising-packages" />). For instance, to enable support |
||||
for the kernel debugger KGDB: |
||||
<programlisting> |
||||
nixpkgs.config.packageOverrides = pkgs: |
||||
{ linux_3_4 = pkgs.linux_3_4.override { |
||||
extraConfig = |
||||
'' |
||||
KGDB y |
||||
''; |
||||
}; |
||||
}; |
||||
</programlisting> |
||||
<varname>extraConfig</varname> takes a list of Linux kernel configuration |
||||
options, one per line. The name of the option should not include the prefix |
||||
<literal>CONFIG_</literal>. The option value is typically |
||||
<literal>y</literal>, <literal>n</literal> or <literal>m</literal> (to build |
||||
something as a kernel module). |
||||
</para> |
||||
<para> |
||||
Kernel modules for hardware devices are generally loaded automatically by |
||||
<command>udev</command>. You can force a module to be loaded via |
||||
<xref linkend="opt-boot.kernelModules"/>, e.g. |
||||
<programlisting> |
||||
<xref linkend="opt-boot.kernelModules"/> = [ "fuse" "kvm-intel" "coretemp" ]; |
||||
</programlisting> |
||||
If the module is required early during the boot (e.g. to mount the root file |
||||
system), you can use <xref linkend="opt-boot.initrd.kernelModules"/>: |
||||
<programlisting> |
||||
<xref linkend="opt-boot.initrd.kernelModules"/> = [ "cifs" ]; |
||||
</programlisting> |
||||
This causes the specified modules and their dependencies to be added to the |
||||
initial ramdisk. |
||||
</para> |
||||
<para> |
||||
Kernel runtime parameters can be set through |
||||
<xref linkend="opt-boot.kernel.sysctl"/>, e.g. |
||||
<programlisting> |
||||
<xref linkend="opt-boot.kernel.sysctl"/>."net.ipv4.tcp_keepalive_time" = 120; |
||||
</programlisting> |
||||
sets the kernel’s TCP keepalive time to 120 seconds. To see the available |
||||
parameters, run <command>sysctl -a</command>. |
||||
</para> |
||||
<section xml:id="sec-linux-config-customizing"> |
||||
<title>Customize your kernel</title> |
||||
|
||||
<para> |
||||
The first step before compiling the kernel is to generate an appropriate |
||||
<literal>.config</literal> configuration. Either you pass your own config |
||||
via the <literal>configfile</literal> setting of |
||||
<literal>linuxManualConfig</literal>: |
||||
<screen><![CDATA[ |
||||
custom-kernel = super.linuxManualConfig { |
||||
inherit (super) stdenv hostPlatform; |
||||
inherit (linux_4_9) src; |
||||
version = "${linux_4_9.version}-custom"; |
||||
|
||||
configfile = /home/me/my_kernel_config; |
||||
allowImportFromDerivation = true; |
||||
}; |
||||
]]></screen> |
||||
You can edit the config with this snippet (by default <command>make |
||||
menuconfig</command> won't work out of the box on nixos): |
||||
<screen><![CDATA[ |
||||
nix-shell -E 'with import <nixpkgs> {}; kernelToOverride.overrideAttrs (o: {nativeBuildInputs=o.nativeBuildInputs ++ [ pkg-config ncurses ];})' |
||||
]]></screen> |
||||
or you can let nixpkgs generate the configuration. Nixpkgs generates it via |
||||
answering the interactive kernel utility <command>make config</command>. The |
||||
answers depend on parameters passed to |
||||
<filename>pkgs/os-specific/linux/kernel/generic.nix</filename> (which you |
||||
can influence by overriding <literal>extraConfig, autoModules, |
||||
modDirVersion, preferBuiltin, extraConfig</literal>). |
||||
<screen><![CDATA[ |
||||
|
||||
mptcp93.override ({ |
||||
name="mptcp-local"; |
||||
|
||||
ignoreConfigErrors = true; |
||||
autoModules = false; |
||||
kernelPreferBuiltin = true; |
||||
|
||||
enableParallelBuilding = true; |
||||
|
||||
extraConfig = '' |
||||
DEBUG_KERNEL y |
||||
FRAME_POINTER y |
||||
KGDB y |
||||
KGDB_SERIAL_CONSOLE y |
||||
DEBUG_INFO y |
||||
''; |
||||
}); |
||||
]]></screen> |
||||
</para> |
||||
</section> |
||||
<section xml:id="sec-linux-config-developing-modules"> |
||||
<title>Developing kernel modules</title> |
||||
|
||||
<para> |
||||
When developing kernel modules it's often convenient to run edit-compile-run |
||||
loop as quickly as possible. See below snippet as an example of developing |
||||
<literal>mellanox</literal> drivers. |
||||
</para> |
||||
|
||||
<screen> |
||||
<prompt>$ </prompt>nix-build '<nixpkgs>' -A linuxPackages.kernel.dev |
||||
<prompt>$ </prompt>nix-shell '<nixpkgs>' -A linuxPackages.kernel |
||||
<prompt>$ </prompt>unpackPhase |
||||
<prompt>$ </prompt>cd linux-* |
||||
<prompt>$ </prompt>make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules |
||||
<prompt># </prompt>insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko |
||||
</screen> |
||||
</section> |
||||
</chapter> |
@ -0,0 +1,77 @@ |
||||
# LUKS-Encrypted File Systems {#sec-luks-file-systems} |
||||
|
||||
NixOS supports file systems that are encrypted using *LUKS* (Linux |
||||
Unified Key Setup). For example, here is how you create an encrypted |
||||
Ext4 file system on the device |
||||
`/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d`: |
||||
|
||||
```ShellSession |
||||
# cryptsetup luksFormat /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d |
||||
|
||||
WARNING! |
||||
======== |
||||
This will overwrite data on /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d irrevocably. |
||||
|
||||
Are you sure? (Type uppercase yes): YES |
||||
Enter LUKS passphrase: *** |
||||
Verify passphrase: *** |
||||
|
||||
# cryptsetup luksOpen /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d crypted |
||||
Enter passphrase for /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d: *** |
||||
|
||||
# mkfs.ext4 /dev/mapper/crypted |
||||
``` |
||||
|
||||
The LUKS volume should be automatically picked up by |
||||
`nixos-generate-config`, but you might want to verify that your |
||||
`hardware-configuration.nix` looks correct. To manually ensure that the |
||||
system is automatically mounted at boot time as `/`, add the following |
||||
to `configuration.nix`: |
||||
|
||||
```nix |
||||
boot.initrd.luks.devices.crypted.device = "/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d"; |
||||
fileSystems."/".device = "/dev/mapper/crypted"; |
||||
``` |
||||
|
||||
Should grub be used as bootloader, and `/boot` is located on an |
||||
encrypted partition, it is necessary to add the following grub option: |
||||
|
||||
```nix |
||||
boot.loader.grub.enableCryptodisk = true; |
||||
``` |
||||
|
||||
## FIDO2 {#sec-luks-file-systems-fido2} |
||||
|
||||
NixOS also supports unlocking your LUKS-Encrypted file system using a |
||||
FIDO2 compatible token. In the following example, we will create a new |
||||
FIDO2 credential and add it as a new key to our existing device |
||||
`/dev/sda2`: |
||||
|
||||
```ShellSession |
||||
# export FIDO2_LABEL="/dev/sda2 @ $HOSTNAME" |
||||
# fido2luks credential "$FIDO2_LABEL" |
||||
f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7 |
||||
|
||||
# fido2luks -i add-key /dev/sda2 f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7 |
||||
Password: |
||||
Password (again): |
||||
Old password: |
||||
Old password (again): |
||||
Added to key to device /dev/sda2, slot: 2 |
||||
``` |
||||
|
||||
To ensure that this file system is decrypted using the FIDO2 compatible |
||||
key, add the following to `configuration.nix`: |
||||
|
||||
```nix |
||||
boot.initrd.luks.fido2Support = true; |
||||
boot.initrd.luks.devices."/dev/sda2".fido2.credential = "f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7"; |
||||
``` |
||||
|
||||
You can also use the FIDO2 passwordless setup, but for security reasons, |
||||
you might want to enable it only when your device is PIN protected, such |
||||
as [Trezor](https://trezor.io/). |
||||
|
||||
```nix |
||||
boot.initrd.luks.devices."/dev/sda2".fido2.passwordLess = true; |
||||
``` |
@ -1,78 +0,0 @@ |
||||
<section 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="sec-luks-file-systems"> |
||||
<title>LUKS-Encrypted File Systems</title> |
||||
|
||||
<para> |
||||
NixOS supports file systems that are encrypted using |
||||
<emphasis>LUKS</emphasis> (Linux Unified Key Setup). For example, here is how |
||||
you create an encrypted Ext4 file system on the device |
||||
<filename>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</filename>: |
||||
<screen> |
||||
<prompt># </prompt>cryptsetup luksFormat <replaceable>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</replaceable> |
||||
|
||||
WARNING! |
||||
======== |
||||
This will overwrite data on /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d irrevocably. |
||||
|
||||
Are you sure? (Type uppercase yes): YES |
||||
Enter LUKS passphrase: *** |
||||
Verify passphrase: *** |
||||
|
||||
<prompt># </prompt>cryptsetup luksOpen <replaceable>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</replaceable> <replaceable>crypted</replaceable> |
||||
Enter passphrase for /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d: *** |
||||
|
||||
<prompt># </prompt>mkfs.ext4 /dev/mapper/<replaceable>crypted</replaceable> |
||||
</screen> |
||||
The LUKS volume should be automatically picked up by |
||||
<command>nixos-generate-config</command>, but you might want to verify that your |
||||
<filename>hardware-configuration.nix</filename> looks correct. |
||||
|
||||
To manually ensure that the system is automatically mounted at boot time as |
||||
<filename>/</filename>, add the following to |
||||
<filename>configuration.nix</filename>: |
||||
<programlisting> |
||||
<link linkend="opt-boot.initrd.luks.devices._name_.device">boot.initrd.luks.devices.crypted.device</link> = "<replaceable>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</replaceable>"; |
||||
<xref linkend="opt-fileSystems"/>."/".device = "/dev/mapper/<replaceable>crypted</replaceable>"; |
||||
</programlisting> |
||||
Should grub be used as bootloader, and <filename>/boot</filename> is located |
||||
on an encrypted partition, it is necessary to add the following grub option: |
||||
<programlisting><xref linkend="opt-boot.loader.grub.enableCryptodisk"/> = true;</programlisting> |
||||
</para> |
||||
<section xml:id="sec-luks-file-systems-fido2"> |
||||
<title>FIDO2</title> |
||||
|
||||
<para> |
||||
NixOS also supports unlocking your LUKS-Encrypted file system using a FIDO2 compatible token. In the following example, we will create a new FIDO2 credential |
||||
and add it as a new key to our existing device <filename>/dev/sda2</filename>: |
||||
|
||||
<screen> |
||||
<prompt># </prompt>export FIDO2_LABEL="<replaceable>/dev/sda2</replaceable> @ $HOSTNAME" |
||||
<prompt># </prompt>fido2luks credential "$FIDO2_LABEL" |
||||
f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7 |
||||
|
||||
<prompt># </prompt>fido2luks -i add-key <replaceable>/dev/sda2</replaceable> <replaceable>f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7</replaceable> |
||||
Password: |
||||
Password (again): |
||||
Old password: |
||||
Old password (again): |
||||
Added to key to device /dev/sda2, slot: 2 |
||||
</screen> |
||||
|
||||
To ensure that this file system is decrypted using the FIDO2 compatible key, add the following to <filename>configuration.nix</filename>: |
||||
<programlisting> |
||||
<link linkend="opt-boot.initrd.luks.fido2Support">boot.initrd.luks.fido2Support</link> = true; |
||||
<link linkend="opt-boot.initrd.luks.devices._name_.fido2.credential">boot.initrd.luks.devices."<replaceable>/dev/sda2</replaceable>".fido2.credential</link> = "<replaceable>f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7</replaceable>"; |
||||
</programlisting> |
||||
|
||||
You can also use the FIDO2 passwordless setup, but for security reasons, you might want to enable it only when your device is PIN protected, such as <link xlink:href="https://trezor.io/">Trezor</link>. |
||||
|
||||
<programlisting> |
||||
<link linkend="opt-boot.initrd.luks.devices._name_.fido2.passwordLess">boot.initrd.luks.devices."<replaceable>/dev/sda2</replaceable>".fido2.passwordLess</link> = true; |
||||
</programlisting> |
||||
</para> |
||||
</section> |
||||
|
||||
</section> |
@ -0,0 +1,133 @@ |
||||
# Modularity {#sec-modularity} |
||||
|
||||
The NixOS configuration mechanism is modular. If your |
||||
`configuration.nix` becomes too big, you can split it into multiple |
||||
files. Likewise, if you have multiple NixOS configurations (e.g. for |
||||
different computers) with some commonality, you can move the common |
||||
configuration into a shared file. |
||||
|
||||
Modules have exactly the same syntax as `configuration.nix`. In fact, |
||||
`configuration.nix` is itself a module. You can use other modules by |
||||
including them from `configuration.nix`, e.g.: |
||||
|
||||
```nix |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ imports = [ ./vpn.nix ./kde.nix ]; |
||||
services.httpd.enable = true; |
||||
environment.systemPackages = [ pkgs.emacs ]; |
||||
... |
||||
} |
||||
``` |
||||
|
||||
Here, we include two modules from the same directory, `vpn.nix` and |
||||
`kde.nix`. The latter might look like this: |
||||
|
||||
```nix |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ services.xserver.enable = true; |
||||
services.xserver.displayManager.sddm.enable = true; |
||||
services.xserver.desktopManager.plasma5.enable = true; |
||||
environment.systemPackages = [ pkgs.vim ]; |
||||
} |
||||
``` |
||||
|
||||
Note that both `configuration.nix` and `kde.nix` define the option |
||||
[](#opt-environment.systemPackages). When multiple modules define an |
||||
option, NixOS will try to *merge* the definitions. In the case of |
||||
[](#opt-environment.systemPackages), that's easy: the lists of |
||||
packages can simply be concatenated. The value in `configuration.nix` is |
||||
merged last, so for list-type options, it will appear at the end of the |
||||
merged list. If you want it to appear first, you can use `mkBefore`: |
||||
|
||||
```nix |
||||
boot.kernelModules = mkBefore [ "kvm-intel" ]; |
||||
``` |
||||
|
||||
This causes the `kvm-intel` kernel module to be loaded before any other |
||||
kernel modules. |
||||
|
||||
For other types of options, a merge may not be possible. For instance, |
||||
if two modules define [](#opt-services.httpd.adminAddr), |
||||
`nixos-rebuild` will give an error: |
||||
|
||||
```plain |
||||
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'. |
||||
``` |
||||
|
||||
When that happens, it's possible to force one definition take precedence |
||||
over the others: |
||||
|
||||
```nix |
||||
services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org"; |
||||
``` |
||||
|
||||
When using multiple modules, you may need to access configuration values |
||||
defined in other modules. This is what the `config` function argument is |
||||
for: it contains the complete, merged system configuration. That is, |
||||
`config` is the result of combining the configurations returned by every |
||||
module [^1] . For example, here is a module that adds some packages to |
||||
[](#opt-environment.systemPackages) only if |
||||
[](#opt-services.xserver.enable) is set to `true` somewhere else: |
||||
|
||||
```nix |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ environment.systemPackages = |
||||
if config.services.xserver.enable then |
||||
[ pkgs.firefox |
||||
pkgs.thunderbird |
||||
] |
||||
else |
||||
[ ]; |
||||
} |
||||
``` |
||||
|
||||
With multiple modules, it may not be obvious what the final value of a |
||||
configuration option is. The command `nixos-option` allows you to find |
||||
out: |
||||
|
||||
```ShellSession |
||||
$ nixos-option services.xserver.enable |
||||
true |
||||
|
||||
$ nixos-option boot.kernelModules |
||||
[ "tun" "ipv6" "loop" ... ] |
||||
``` |
||||
|
||||
Interactive exploration of the configuration is possible using `nix |
||||
repl`, a read-eval-print loop for Nix expressions. A typical use: |
||||
|
||||
```ShellSession |
||||
$ nix repl '<nixpkgs/nixos>' |
||||
|
||||
nix-repl> config.networking.hostName |
||||
"mandark" |
||||
|
||||
nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts |
||||
[ "example.org" "example.gov" ] |
||||
``` |
||||
|
||||
While abstracting your configuration, you may find it useful to generate |
||||
modules using code, instead of writing files. The example below would |
||||
have the same effect as importing a file which sets those options. |
||||
|
||||
```nix |
||||
{ config, pkgs, ... }: |
||||
|
||||
let netConfig = hostName: { |
||||
networking.hostName = hostName; |
||||
networking.useDHCP = false; |
||||
}; |
||||
|
||||
in |
||||
|
||||
{ imports = [ (netConfig "nixos.localdomain") ]; } |
||||
``` |
||||
|
||||
[^1]: If you're wondering how it's possible that the (indirect) *result* |
||||
of a function is passed as an *input* to that same function: that's |
||||
because Nix is a "lazy" language --- it only computes values when |
||||
they are needed. This works as long as no individual configuration |
||||
value depends on itself. |
@ -1,146 +0,0 @@ |
||||
<section 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="sec-modularity"> |
||||
<title>Modularity</title> |
||||
|
||||
<para> |
||||
The NixOS configuration mechanism is modular. If your |
||||
<filename>configuration.nix</filename> becomes too big, you can split it into |
||||
multiple files. Likewise, if you have multiple NixOS configurations (e.g. for |
||||
different computers) with some commonality, you can move the common |
||||
configuration into a shared file. |
||||
</para> |
||||
|
||||
<para> |
||||
Modules have exactly the same syntax as |
||||
<filename>configuration.nix</filename>. In fact, |
||||
<filename>configuration.nix</filename> is itself a module. You can use other |
||||
modules by including them from <filename>configuration.nix</filename>, e.g.: |
||||
<programlisting> |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ imports = [ ./vpn.nix ./kde.nix ]; |
||||
<xref linkend="opt-services.httpd.enable"/> = true; |
||||
<xref linkend="opt-environment.systemPackages"/> = [ pkgs.emacs ]; |
||||
<replaceable>...</replaceable> |
||||
} |
||||
</programlisting> |
||||
Here, we include two modules from the same directory, |
||||
<filename>vpn.nix</filename> and <filename>kde.nix</filename>. The latter |
||||
might look like this: |
||||
<programlisting> |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ <xref linkend="opt-services.xserver.enable"/> = true; |
||||
<xref linkend="opt-services.xserver.displayManager.sddm.enable"/> = true; |
||||
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> = true; |
||||
<xref linkend="opt-environment.systemPackages"/> = [ pkgs.vim ]; |
||||
} |
||||
</programlisting> |
||||
Note that both <filename>configuration.nix</filename> and |
||||
<filename>kde.nix</filename> define the option |
||||
<xref linkend="opt-environment.systemPackages"/>. When multiple modules |
||||
define an option, NixOS will try to <emphasis>merge</emphasis> the |
||||
definitions. In the case of <xref linkend="opt-environment.systemPackages"/>, |
||||
that’s easy: the lists of packages can simply be concatenated. The value in |
||||
<filename>configuration.nix</filename> is merged last, so for list-type |
||||
options, it will appear at the end of the merged list. If you want it to |
||||
appear first, you can use <varname>mkBefore</varname>: |
||||
<programlisting> |
||||
<xref linkend="opt-boot.kernelModules"/> = mkBefore [ "kvm-intel" ]; |
||||
</programlisting> |
||||
This causes the <literal>kvm-intel</literal> kernel module to be loaded |
||||
before any other kernel modules. |
||||
</para> |
||||
|
||||
<para> |
||||
For other types of options, a merge may not be possible. For instance, if two |
||||
modules define <xref linkend="opt-services.httpd.adminAddr"/>, |
||||
<command>nixos-rebuild</command> will give an error: |
||||
<screen> |
||||
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'. |
||||
</screen> |
||||
When that happens, it’s possible to force one definition take precedence |
||||
over the others: |
||||
<programlisting> |
||||
<xref linkend="opt-services.httpd.adminAddr"/> = pkgs.lib.mkForce "bob@example.org"; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<para> |
||||
When using multiple modules, you may need to access configuration values |
||||
defined in other modules. This is what the <varname>config</varname> function |
||||
argument is for: it contains the complete, merged system configuration. That |
||||
is, <varname>config</varname> is the result of combining the configurations |
||||
returned by every module |
||||
<footnote xml:id="footnote-nix-is-lazy"> |
||||
<para> |
||||
If you’re wondering how it’s possible that the (indirect) |
||||
<emphasis>result</emphasis> of a function is passed as an |
||||
<emphasis>input</emphasis> to that same function: that’s because Nix is a |
||||
“lazy” language — it only computes values when they are needed. This |
||||
works as long as no individual configuration value depends on itself. |
||||
</para> |
||||
</footnote> |
||||
. For example, here is a module that adds some packages to |
||||
<xref linkend="opt-environment.systemPackages"/> only if |
||||
<xref linkend="opt-services.xserver.enable"/> is set to |
||||
<literal>true</literal> somewhere else: |
||||
<programlisting> |
||||
{ config, pkgs, ... }: |
||||
|
||||
{ <xref linkend="opt-environment.systemPackages"/> = |
||||
if config.<xref linkend="opt-services.xserver.enable"/> then |
||||
[ pkgs.firefox |
||||
pkgs.thunderbird |
||||
] |
||||
else |
||||
[ ]; |
||||
} |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<para> |
||||
With multiple modules, it may not be obvious what the final value of a |
||||
configuration option is. The command <option>nixos-option</option> allows you |
||||
to find out: |
||||
<screen> |
||||
<prompt>$ </prompt>nixos-option <xref linkend="opt-services.xserver.enable"/> |
||||
true |
||||
|
||||
<prompt>$ </prompt>nixos-option <xref linkend="opt-boot.kernelModules"/> |
||||
[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ] |
||||
</screen> |
||||
Interactive exploration of the configuration is possible using <command>nix |
||||
repl</command>, a read-eval-print loop for Nix expressions. A typical use: |
||||
<screen> |
||||
<prompt>$ </prompt>nix repl '<nixpkgs/nixos>' |
||||
|
||||
<prompt>nix-repl> </prompt>config.<xref linkend="opt-networking.hostName"/> |
||||
"mandark" |
||||
|
||||
<prompt>nix-repl> </prompt>map (x: x.hostName) config.<xref linkend="opt-services.httpd.virtualHosts"/> |
||||
[ "example.org" "example.gov" ] |
||||
</screen> |
||||
</para> |
||||
|
||||
<para> |
||||
While abstracting your configuration, you may find it useful to generate |
||||
modules using code, instead of writing files. The example below would have |
||||
the same effect as importing a file which sets those options. |
||||
<programlisting> |
||||
{ config, pkgs, ... }: |
||||
|
||||
let netConfig = hostName: { |
||||
networking.hostName = hostName; |
||||
networking.useDHCP = false; |
||||
}; |
||||
|
||||
in |
||||
|
||||
{ imports = [ (netConfig "nixos.localdomain") ]; } |
||||
</programlisting> |
||||
</para> |
||||
</section> |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue