Merge remote-tracking branch 'origin/staging-next' into staging
Conflicts: pkgs/development/libraries/audio/roc-toolkit/default.nix
This commit is contained in:
commit
ca4da963f8
|
@ -17,9 +17,16 @@ function Inlines(inlines)
|
||||||
if correct_tags then
|
if correct_tags then
|
||||||
-- docutils supports alphanumeric strings separated by [-._:]
|
-- docutils supports alphanumeric strings separated by [-._:]
|
||||||
-- We are slightly more liberal for simplicity.
|
-- We are slightly more liberal for simplicity.
|
||||||
local role = first.text:match('^{([-._+:%w]+)}$')
|
-- Allow preceding punctuation (eg '('), otherwise '({file}`...`)'
|
||||||
if role ~= nil then
|
-- does not match. Also allow anything followed by a non-breaking space
|
||||||
|
-- since pandoc emits those after certain abbreviations (e.g. e.g.).
|
||||||
|
local prefix, role = first.text:match('^(.*){([-._+:%w]+)}$')
|
||||||
|
if role ~= nil and (prefix == '' or prefix:match("^.*[%p ]$") ~= nil) then
|
||||||
|
if prefix == '' then
|
||||||
inlines:remove(i)
|
inlines:remove(i)
|
||||||
|
else
|
||||||
|
first.text = prefix
|
||||||
|
end
|
||||||
second.attributes['role'] = role
|
second.attributes['role'] = role
|
||||||
second.classes:insert('interpreted-text')
|
second.classes:insert('interpreted-text')
|
||||||
end
|
end
|
||||||
|
|
|
@ -9831,6 +9831,16 @@
|
||||||
githubId = 5047140;
|
githubId = 5047140;
|
||||||
name = "Victor Collod";
|
name = "Victor Collod";
|
||||||
};
|
};
|
||||||
|
munksgaard = {
|
||||||
|
name = "Philip Munksgaard";
|
||||||
|
email = "philip@munksgaard.me";
|
||||||
|
github = "munksgaard";
|
||||||
|
githubId = 230613;
|
||||||
|
matrix = "@philip:matrix.munksgaard.me";
|
||||||
|
keys = [{
|
||||||
|
fingerprint = "5658 4D09 71AF E45F CC29 6BD7 4CE6 2A90 EFC0 B9B2";
|
||||||
|
}];
|
||||||
|
};
|
||||||
muscaln = {
|
muscaln = {
|
||||||
email = "muscaln@protonmail.com";
|
email = "muscaln@protonmail.com";
|
||||||
github = "muscaln";
|
github = "muscaln";
|
||||||
|
@ -16283,4 +16293,10 @@
|
||||||
github = "Detegr";
|
github = "Detegr";
|
||||||
githubId = 724433;
|
githubId = 724433;
|
||||||
};
|
};
|
||||||
|
RossComputerGuy = {
|
||||||
|
name = "Tristan Ross";
|
||||||
|
email = "tristan.ross@midstall.com";
|
||||||
|
github = "RossComputerGuy";
|
||||||
|
githubId = 19699320;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,7 @@ with lib.maintainers; {
|
||||||
kalbasit
|
kalbasit
|
||||||
mic92
|
mic92
|
||||||
zowoq
|
zowoq
|
||||||
|
qbit
|
||||||
];
|
];
|
||||||
scope = "Maintain Golang compilers.";
|
scope = "Maintain Golang compilers.";
|
||||||
shortName = "Go";
|
shortName = "Go";
|
||||||
|
|
|
@ -40,6 +40,26 @@ file.
|
||||||
$ nix-build nixos/release.nix -A manual.x86_64-linux
|
$ nix-build nixos/release.nix -A manual.x86_64-linux
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This file should *not* usually be written by hand. Instead it is preferred
|
||||||
|
to write documentation using CommonMark and converting it to CommonMark
|
||||||
|
using pandoc. The simplest documentation can be converted using just
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
$ pandoc doc.md -t docbook --top-level-division=chapter -f markdown+smart > doc.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
More elaborate documentation may wish to add one or more of the pandoc
|
||||||
|
filters used to build the remainder of the manual, for example the GNOME
|
||||||
|
desktop uses
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
$ pandoc gnome.md -t docbook --top-level-division=chapter \
|
||||||
|
--extract-media=media -f markdown+smart \
|
||||||
|
--lua-filter ../../../../../doc/build-aux/pandoc-filters/myst-reader/roles.lua \
|
||||||
|
--lua-filter ../../../../../doc/build-aux/pandoc-filters/docbook-writer/rst-roles.lua \
|
||||||
|
> gnome.xml
|
||||||
|
```
|
||||||
|
|
||||||
- `buildDocsInSandbox` indicates whether the option documentation for the
|
- `buildDocsInSandbox` indicates whether the option documentation for the
|
||||||
module can be built in a derivation sandbox. This option is currently only
|
module can be built in a derivation sandbox. This option is currently only
|
||||||
honored for modules shipped by nixpkgs. User modules and modules taken from
|
honored for modules shipped by nixpkgs. User modules and modules taken from
|
||||||
|
|
|
@ -50,6 +50,27 @@
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
$ nix-build nixos/release.nix -A manual.x86_64-linux
|
$ nix-build nixos/release.nix -A manual.x86_64-linux
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
This file should <emphasis>not</emphasis> usually be written by
|
||||||
|
hand. Instead it is preferred to write documentation using
|
||||||
|
CommonMark and converting it to CommonMark using pandoc. The
|
||||||
|
simplest documentation can be converted using just
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ pandoc doc.md -t docbook --top-level-division=chapter -f markdown+smart > doc.xml
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
More elaborate documentation may wish to add one or more of the
|
||||||
|
pandoc filters used to build the remainder of the manual, for
|
||||||
|
example the GNOME desktop uses
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ pandoc gnome.md -t docbook --top-level-division=chapter \
|
||||||
|
--extract-media=media -f markdown+smart \
|
||||||
|
--lua-filter ../../../../../doc/build-aux/pandoc-filters/myst-reader/roles.lua \
|
||||||
|
--lua-filter ../../../../../doc/build-aux/pandoc-filters/docbook-writer/rst-roles.lua \
|
||||||
|
> gnome.xml
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -50,3 +50,21 @@ for mf in ${MD_FILES[*]}; do
|
||||||
done
|
done
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
# now handle module chapters. we'll need extra checks to ensure that we don't process
|
||||||
|
# markdown files we're not interested in, so we'll require an x.nix file for ever x.md
|
||||||
|
# that we'll convert to xml.
|
||||||
|
pushd "$DIR/../../modules"
|
||||||
|
|
||||||
|
mapfile -t MD_FILES < <(find . -type f -regex '.*\.md$')
|
||||||
|
|
||||||
|
for mf in ${MD_FILES[*]}; do
|
||||||
|
[ -f "${mf%.md}.nix" ] || continue
|
||||||
|
|
||||||
|
pandoc --top-level-division=chapter "$mf" "${pandoc_flags[@]}" -o "${mf%.md}.xml"
|
||||||
|
sed -i -e '1 i <!-- Do not edit this file directly, edit its companion .md instead\
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->' \
|
||||||
|
"${mf%.md}.xml"
|
||||||
|
done
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
158
nixos/modules/i18n/input-method/default.md
Normal file
158
nixos/modules/i18n/input-method/default.md
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
# Input Methods {#module-services-input-methods}
|
||||||
|
|
||||||
|
Input methods are an operating system component that allows any data, such as
|
||||||
|
keyboard strokes or mouse movements, to be received as input. In this way
|
||||||
|
users can enter characters and symbols not found on their input devices.
|
||||||
|
Using an input method is obligatory for any language that has more graphemes
|
||||||
|
than there are keys on the keyboard.
|
||||||
|
|
||||||
|
The following input methods are available in NixOS:
|
||||||
|
|
||||||
|
- IBus: The intelligent input bus.
|
||||||
|
- Fcitx: A customizable lightweight input method.
|
||||||
|
- Nabi: A Korean input method based on XIM.
|
||||||
|
- Uim: The universal input method, is a library with a XIM bridge.
|
||||||
|
- Hime: An extremely easy-to-use input method framework.
|
||||||
|
- Kime: Korean IME
|
||||||
|
|
||||||
|
## IBus {#module-services-input-methods-ibus}
|
||||||
|
|
||||||
|
IBus is an Intelligent Input Bus. It provides full featured and user
|
||||||
|
friendly input method user interface.
|
||||||
|
|
||||||
|
The following snippet can be used to configure IBus:
|
||||||
|
|
||||||
|
```
|
||||||
|
i18n.inputMethod = {
|
||||||
|
enabled = "ibus";
|
||||||
|
ibus.engines = with pkgs.ibus-engines; [ anthy hangul mozc ];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
`i18n.inputMethod.ibus.engines` is optional and can be used
|
||||||
|
to add extra IBus engines.
|
||||||
|
|
||||||
|
Available extra IBus engines are:
|
||||||
|
|
||||||
|
- Anthy (`ibus-engines.anthy`): Anthy is a system for
|
||||||
|
Japanese input method. It converts Hiragana text to Kana Kanji mixed text.
|
||||||
|
- Hangul (`ibus-engines.hangul`): Korean input method.
|
||||||
|
- m17n (`ibus-engines.m17n`): m17n is an input method that
|
||||||
|
uses input methods and corresponding icons in the m17n database.
|
||||||
|
- mozc (`ibus-engines.mozc`): A Japanese input method from
|
||||||
|
Google.
|
||||||
|
- Table (`ibus-engines.table`): An input method that load
|
||||||
|
tables of input methods.
|
||||||
|
- table-others (`ibus-engines.table-others`): Various
|
||||||
|
table-based input methods. To use this, and any other table-based input
|
||||||
|
methods, it must appear in the list of engines along with
|
||||||
|
`table`. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
ibus.engines = with pkgs.ibus-engines; [ table table-others ];
|
||||||
|
```
|
||||||
|
|
||||||
|
To use any input method, the package must be added in the configuration, as
|
||||||
|
shown above, and also (after running `nixos-rebuild`) the
|
||||||
|
input method must be added from IBus' preference dialog.
|
||||||
|
|
||||||
|
### Troubleshooting {#module-services-input-methods-troubleshooting}
|
||||||
|
|
||||||
|
If IBus works in some applications but not others, a likely cause of this
|
||||||
|
is that IBus is depending on a different version of `glib`
|
||||||
|
to what the applications are depending on. This can be checked by running
|
||||||
|
`nix-store -q --requisites <path> | grep glib`,
|
||||||
|
where `<path>` is the path of either IBus or an
|
||||||
|
application in the Nix store. The `glib` packages must
|
||||||
|
match exactly. If they do not, uninstalling and reinstalling the
|
||||||
|
application is a likely fix.
|
||||||
|
|
||||||
|
## Fcitx {#module-services-input-methods-fcitx}
|
||||||
|
|
||||||
|
Fcitx is an input method framework with extension support. It has three
|
||||||
|
built-in Input Method Engine, Pinyin, QuWei and Table-based input methods.
|
||||||
|
|
||||||
|
The following snippet can be used to configure Fcitx:
|
||||||
|
|
||||||
|
```
|
||||||
|
i18n.inputMethod = {
|
||||||
|
enabled = "fcitx";
|
||||||
|
fcitx.engines = with pkgs.fcitx-engines; [ mozc hangul m17n ];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
`i18n.inputMethod.fcitx.engines` is optional and can be
|
||||||
|
used to add extra Fcitx engines.
|
||||||
|
|
||||||
|
Available extra Fcitx engines are:
|
||||||
|
|
||||||
|
- Anthy (`fcitx-engines.anthy`): Anthy is a system for
|
||||||
|
Japanese input method. It converts Hiragana text to Kana Kanji mixed text.
|
||||||
|
- Chewing (`fcitx-engines.chewing`): Chewing is an
|
||||||
|
intelligent Zhuyin input method. It is one of the most popular input
|
||||||
|
methods among Traditional Chinese Unix users.
|
||||||
|
- Hangul (`fcitx-engines.hangul`): Korean input method.
|
||||||
|
- Unikey (`fcitx-engines.unikey`): Vietnamese input method.
|
||||||
|
- m17n (`fcitx-engines.m17n`): m17n is an input method that
|
||||||
|
uses input methods and corresponding icons in the m17n database.
|
||||||
|
- mozc (`fcitx-engines.mozc`): A Japanese input method from
|
||||||
|
Google.
|
||||||
|
- table-others (`fcitx-engines.table-others`): Various
|
||||||
|
table-based input methods.
|
||||||
|
|
||||||
|
## Nabi {#module-services-input-methods-nabi}
|
||||||
|
|
||||||
|
Nabi is an easy to use Korean X input method. It allows you to enter
|
||||||
|
phonetic Korean characters (hangul) and pictographic Korean characters
|
||||||
|
(hanja).
|
||||||
|
|
||||||
|
The following snippet can be used to configure Nabi:
|
||||||
|
|
||||||
|
```
|
||||||
|
i18n.inputMethod = {
|
||||||
|
enabled = "nabi";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uim {#module-services-input-methods-uim}
|
||||||
|
|
||||||
|
Uim (short for "universal input method") is a multilingual input method
|
||||||
|
framework. Applications can use it through so-called bridges.
|
||||||
|
|
||||||
|
The following snippet can be used to configure uim:
|
||||||
|
|
||||||
|
```
|
||||||
|
i18n.inputMethod = {
|
||||||
|
enabled = "uim";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: The [](#opt-i18n.inputMethod.uim.toolbar) option can be
|
||||||
|
used to choose uim toolbar.
|
||||||
|
|
||||||
|
## Hime {#module-services-input-methods-hime}
|
||||||
|
|
||||||
|
Hime is an extremely easy-to-use input method framework. It is lightweight,
|
||||||
|
stable, powerful and supports many commonly used input methods, including
|
||||||
|
Cangjie, Zhuyin, Dayi, Rank, Shrimp, Greek, Korean Pinyin, Latin Alphabet,
|
||||||
|
etc...
|
||||||
|
|
||||||
|
The following snippet can be used to configure Hime:
|
||||||
|
|
||||||
|
```
|
||||||
|
i18n.inputMethod = {
|
||||||
|
enabled = "hime";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Kime {#module-services-input-methods-kime}
|
||||||
|
|
||||||
|
Kime is Korean IME. it's built with Rust language and let you get simple, safe, fast Korean typing
|
||||||
|
|
||||||
|
The following snippet can be used to configure Kime:
|
||||||
|
|
||||||
|
```
|
||||||
|
i18n.inputMethod = {
|
||||||
|
enabled = "kime";
|
||||||
|
};
|
||||||
|
```
|
|
@ -1,20 +1,19 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-input-methods">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-input-methods">
|
|
||||||
<title>Input Methods</title>
|
<title>Input Methods</title>
|
||||||
<para>
|
<para>
|
||||||
Input methods are an operating system component that allows any data, such as
|
Input methods are an operating system component that allows any
|
||||||
keyboard strokes or mouse movements, to be received as input. In this way
|
data, such as keyboard strokes or mouse movements, to be received as
|
||||||
users can enter characters and symbols not found on their input devices.
|
input. In this way users can enter characters and symbols not found
|
||||||
Using an input method is obligatory for any language that has more graphemes
|
on their input devices. Using an input method is obligatory for any
|
||||||
than there are keys on the keyboard.
|
language that has more graphemes than there are keys on the
|
||||||
|
keyboard.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The following input methods are available in NixOS:
|
The following input methods are available in NixOS:
|
||||||
</para>
|
</para>
|
||||||
<itemizedlist>
|
<itemizedlist spacing="compact">
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
IBus: The intelligent input bus.
|
IBus: The intelligent input bus.
|
||||||
|
@ -48,243 +47,228 @@
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
<section xml:id="module-services-input-methods-ibus">
|
<section xml:id="module-services-input-methods-ibus">
|
||||||
<title>IBus</title>
|
<title>IBus</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
IBus is an Intelligent Input Bus. It provides full featured and user
|
IBus is an Intelligent Input Bus. It provides full featured and
|
||||||
friendly input method user interface.
|
user friendly input method user interface.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following snippet can be used to configure IBus:
|
The following snippet can be used to configure IBus:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
i18n.inputMethod = {
|
i18n.inputMethod = {
|
||||||
<link linkend="opt-i18n.inputMethod.enabled">enabled</link> = "ibus";
|
enabled = "ibus";
|
||||||
<link linkend="opt-i18n.inputMethod.ibus.engines">ibus.engines</link> = with pkgs.ibus-engines; [ anthy hangul mozc ];
|
ibus.engines = with pkgs.ibus-engines; [ anthy hangul mozc ];
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<literal>i18n.inputMethod.ibus.engines</literal> is optional and can be used
|
<literal>i18n.inputMethod.ibus.engines</literal> is optional and
|
||||||
to add extra IBus engines.
|
can be used to add extra IBus engines.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Available extra IBus engines are:
|
Available extra IBus engines are:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Anthy (<literal>ibus-engines.anthy</literal>): Anthy is a system for
|
Anthy (<literal>ibus-engines.anthy</literal>): Anthy is a
|
||||||
Japanese input method. It converts Hiragana text to Kana Kanji mixed text.
|
system for Japanese input method. It converts Hiragana text to
|
||||||
|
Kana Kanji mixed text.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Hangul (<literal>ibus-engines.hangul</literal>): Korean input method.
|
Hangul (<literal>ibus-engines.hangul</literal>): Korean input
|
||||||
|
method.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
m17n (<literal>ibus-engines.m17n</literal>): m17n is an input method that
|
m17n (<literal>ibus-engines.m17n</literal>): m17n is an input
|
||||||
uses input methods and corresponding icons in the m17n database.
|
method that uses input methods and corresponding icons in the
|
||||||
|
m17n database.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
mozc (<literal>ibus-engines.mozc</literal>): A Japanese input method from
|
mozc (<literal>ibus-engines.mozc</literal>): A Japanese input
|
||||||
Google.
|
method from Google.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Table (<literal>ibus-engines.table</literal>): An input method that load
|
Table (<literal>ibus-engines.table</literal>): An input method
|
||||||
tables of input methods.
|
that load tables of input methods.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
table-others (<literal>ibus-engines.table-others</literal>): Various
|
table-others (<literal>ibus-engines.table-others</literal>):
|
||||||
table-based input methods. To use this, and any other table-based input
|
Various table-based input methods. To use this, and any other
|
||||||
methods, it must appear in the list of engines along with
|
table-based input methods, it must appear in the list of
|
||||||
<literal>table</literal>. For example:
|
engines along with <literal>table</literal>. For example:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
ibus.engines = with pkgs.ibus-engines; [ table table-others ];
|
ibus.engines = with pkgs.ibus-engines; [ table table-others ];
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To use any input method, the package must be added in the configuration, as
|
To use any input method, the package must be added in the
|
||||||
shown above, and also (after running <literal>nixos-rebuild</literal>) the
|
configuration, as shown above, and also (after running
|
||||||
input method must be added from IBus' preference dialog.
|
<literal>nixos-rebuild</literal>) the input method must be added
|
||||||
|
from IBus’ preference dialog.
|
||||||
</para>
|
</para>
|
||||||
|
<section xml:id="module-services-input-methods-troubleshooting">
|
||||||
<simplesect xml:id="module-services-input-methods-troubleshooting">
|
|
||||||
<title>Troubleshooting</title>
|
<title>Troubleshooting</title>
|
||||||
<para>
|
<para>
|
||||||
If IBus works in some applications but not others, a likely cause of this
|
If IBus works in some applications but not others, a likely
|
||||||
is that IBus is depending on a different version of <literal>glib</literal>
|
cause of this is that IBus is depending on a different version
|
||||||
to what the applications are depending on. This can be checked by running
|
of <literal>glib</literal> to what the applications are
|
||||||
|
depending on. This can be checked by running
|
||||||
<literal>nix-store -q --requisites <path> | grep glib</literal>,
|
<literal>nix-store -q --requisites <path> | grep glib</literal>,
|
||||||
where <literal><path></literal> is the path of either IBus or an
|
where <literal><path></literal> is the path of either IBus
|
||||||
application in the Nix store. The <literal>glib</literal> packages must
|
or an application in the Nix store. The <literal>glib</literal>
|
||||||
match exactly. If they do not, uninstalling and reinstalling the
|
packages must match exactly. If they do not, uninstalling and
|
||||||
application is a likely fix.
|
reinstalling the application is a likely fix.
|
||||||
</para>
|
</para>
|
||||||
</simplesect>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-input-methods-fcitx">
|
<section xml:id="module-services-input-methods-fcitx">
|
||||||
<title>Fcitx</title>
|
<title>Fcitx</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Fcitx is an input method framework with extension support. It has three
|
Fcitx is an input method framework with extension support. It has
|
||||||
built-in Input Method Engine, Pinyin, QuWei and Table-based input methods.
|
three built-in Input Method Engine, Pinyin, QuWei and Table-based
|
||||||
|
input methods.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following snippet can be used to configure Fcitx:
|
The following snippet can be used to configure Fcitx:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
i18n.inputMethod = {
|
i18n.inputMethod = {
|
||||||
<link linkend="opt-i18n.inputMethod.enabled">enabled</link> = "fcitx";
|
enabled = "fcitx";
|
||||||
<link linkend="opt-i18n.inputMethod.fcitx.engines">fcitx.engines</link> = with pkgs.fcitx-engines; [ mozc hangul m17n ];
|
fcitx.engines = with pkgs.fcitx-engines; [ mozc hangul m17n ];
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<literal>i18n.inputMethod.fcitx.engines</literal> is optional and can be
|
<literal>i18n.inputMethod.fcitx.engines</literal> is optional and
|
||||||
used to add extra Fcitx engines.
|
can be used to add extra Fcitx engines.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Available extra Fcitx engines are:
|
Available extra Fcitx engines are:
|
||||||
</para>
|
</para>
|
||||||
|
<itemizedlist spacing="compact">
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Anthy (<literal>fcitx-engines.anthy</literal>): Anthy is a system for
|
Anthy (<literal>fcitx-engines.anthy</literal>): Anthy is a
|
||||||
Japanese input method. It converts Hiragana text to Kana Kanji mixed text.
|
system for Japanese input method. It converts Hiragana text to
|
||||||
|
Kana Kanji mixed text.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Chewing (<literal>fcitx-engines.chewing</literal>): Chewing is an
|
Chewing (<literal>fcitx-engines.chewing</literal>): Chewing is
|
||||||
intelligent Zhuyin input method. It is one of the most popular input
|
an intelligent Zhuyin input method. It is one of the most
|
||||||
methods among Traditional Chinese Unix users.
|
popular input methods among Traditional Chinese Unix users.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Hangul (<literal>fcitx-engines.hangul</literal>): Korean input method.
|
Hangul (<literal>fcitx-engines.hangul</literal>): Korean input
|
||||||
|
method.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Unikey (<literal>fcitx-engines.unikey</literal>): Vietnamese input method.
|
Unikey (<literal>fcitx-engines.unikey</literal>): Vietnamese
|
||||||
|
input method.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
m17n (<literal>fcitx-engines.m17n</literal>): m17n is an input method that
|
m17n (<literal>fcitx-engines.m17n</literal>): m17n is an input
|
||||||
uses input methods and corresponding icons in the m17n database.
|
method that uses input methods and corresponding icons in the
|
||||||
|
m17n database.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
mozc (<literal>fcitx-engines.mozc</literal>): A Japanese input method from
|
mozc (<literal>fcitx-engines.mozc</literal>): A Japanese input
|
||||||
Google.
|
method from Google.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
table-others (<literal>fcitx-engines.table-others</literal>): Various
|
table-others (<literal>fcitx-engines.table-others</literal>):
|
||||||
table-based input methods.
|
Various table-based input methods.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-input-methods-nabi">
|
<section xml:id="module-services-input-methods-nabi">
|
||||||
<title>Nabi</title>
|
<title>Nabi</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Nabi is an easy to use Korean X input method. It allows you to enter
|
Nabi is an easy to use Korean X input method. It allows you to
|
||||||
phonetic Korean characters (hangul) and pictographic Korean characters
|
enter phonetic Korean characters (hangul) and pictographic Korean
|
||||||
(hanja).
|
characters (hanja).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following snippet can be used to configure Nabi:
|
The following snippet can be used to configure Nabi:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
i18n.inputMethod = {
|
i18n.inputMethod = {
|
||||||
<link linkend="opt-i18n.inputMethod.enabled">enabled</link> = "nabi";
|
enabled = "nabi";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-input-methods-uim">
|
<section xml:id="module-services-input-methods-uim">
|
||||||
<title>Uim</title>
|
<title>Uim</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Uim (short for "universal input method") is a multilingual input method
|
Uim (short for <quote>universal input method</quote>) is a
|
||||||
framework. Applications can use it through so-called bridges.
|
multilingual input method framework. Applications can use it
|
||||||
|
through so-called bridges.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following snippet can be used to configure uim:
|
The following snippet can be used to configure uim:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
i18n.inputMethod = {
|
i18n.inputMethod = {
|
||||||
<link linkend="opt-i18n.inputMethod.enabled">enabled</link> = "uim";
|
enabled = "uim";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Note: The <xref linkend="opt-i18n.inputMethod.uim.toolbar"/> option can be
|
Note: The <xref linkend="opt-i18n.inputMethod.uim.toolbar" />
|
||||||
used to choose uim toolbar.
|
option can be used to choose uim toolbar.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-input-methods-hime">
|
<section xml:id="module-services-input-methods-hime">
|
||||||
<title>Hime</title>
|
<title>Hime</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Hime is an extremely easy-to-use input method framework. It is lightweight,
|
Hime is an extremely easy-to-use input method framework. It is
|
||||||
stable, powerful and supports many commonly used input methods, including
|
lightweight, stable, powerful and supports many commonly used
|
||||||
Cangjie, Zhuyin, Dayi, Rank, Shrimp, Greek, Korean Pinyin, Latin Alphabet,
|
input methods, including Cangjie, Zhuyin, Dayi, Rank, Shrimp,
|
||||||
etc...
|
Greek, Korean Pinyin, Latin Alphabet, etc…
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following snippet can be used to configure Hime:
|
The following snippet can be used to configure Hime:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
i18n.inputMethod = {
|
i18n.inputMethod = {
|
||||||
<link linkend="opt-i18n.inputMethod.enabled">enabled</link> = "hime";
|
enabled = "hime";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-input-methods-kime">
|
<section xml:id="module-services-input-methods-kime">
|
||||||
<title>Kime</title>
|
<title>Kime</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Kime is Korean IME. it's built with Rust language and let you get simple, safe, fast Korean typing
|
Kime is Korean IME. it’s built with Rust language and let you get
|
||||||
|
simple, safe, fast Korean typing
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following snippet can be used to configure Kime:
|
The following snippet can be used to configure Kime:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
i18n.inputMethod = {
|
i18n.inputMethod = {
|
||||||
<link linkend="opt-i18n.inputMethod.enabled">enabled</link> = "kime";
|
enabled = "kime";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
47
nixos/modules/programs/digitalbitbox/default.md
Normal file
47
nixos/modules/programs/digitalbitbox/default.md
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# Digital Bitbox {#module-programs-digitalbitbox}
|
||||||
|
|
||||||
|
Digital Bitbox is a hardware wallet and second-factor authenticator.
|
||||||
|
|
||||||
|
The `digitalbitbox` programs module may be installed by setting
|
||||||
|
`programs.digitalbitbox` to `true` in a manner similar to
|
||||||
|
```
|
||||||
|
programs.digitalbitbox.enable = true;
|
||||||
|
```
|
||||||
|
and bundles the `digitalbitbox` package (see [](#sec-digitalbitbox-package)),
|
||||||
|
which contains the `dbb-app` and `dbb-cli` binaries, along with the hardware
|
||||||
|
module (see [](#sec-digitalbitbox-hardware-module)) which sets up the necessary
|
||||||
|
udev rules to access the device.
|
||||||
|
|
||||||
|
Enabling the digitalbitbox module is pretty much the easiest way to get a
|
||||||
|
Digital Bitbox device working on your system.
|
||||||
|
|
||||||
|
For more information, see <https://digitalbitbox.com/start_linux>.
|
||||||
|
|
||||||
|
## Package {#sec-digitalbitbox-package}
|
||||||
|
|
||||||
|
The binaries, `dbb-app` (a GUI tool) and `dbb-cli` (a CLI tool), are available
|
||||||
|
through the `digitalbitbox` package which could be installed as follows:
|
||||||
|
```
|
||||||
|
environment.systemPackages = [
|
||||||
|
pkgs.digitalbitbox
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hardware {#sec-digitalbitbox-hardware-module}
|
||||||
|
|
||||||
|
The digitalbitbox hardware package enables the udev rules for Digital Bitbox
|
||||||
|
devices and may be installed as follows:
|
||||||
|
```
|
||||||
|
hardware.digitalbitbox.enable = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to alter the udev rules, one may provide different values for the
|
||||||
|
`udevRule51` and `udevRule52` attributes by means of overriding as follows:
|
||||||
|
```
|
||||||
|
programs.digitalbitbox = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.digitalbitbox.override {
|
||||||
|
udevRule51 = "something else";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
|
@ -33,7 +33,7 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
doc = ./doc.xml;
|
doc = ./default.xml;
|
||||||
maintainers = with lib.maintainers; [ vidbina ];
|
maintainers = with lib.maintainers; [ vidbina ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
70
nixos/modules/programs/digitalbitbox/default.xml
Normal file
70
nixos/modules/programs/digitalbitbox/default.xml
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-programs-digitalbitbox">
|
||||||
|
<title>Digital Bitbox</title>
|
||||||
|
<para>
|
||||||
|
Digital Bitbox is a hardware wallet and second-factor authenticator.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>digitalbitbox</literal> programs module may be
|
||||||
|
installed by setting <literal>programs.digitalbitbox</literal> to
|
||||||
|
<literal>true</literal> in a manner similar to
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
programs.digitalbitbox.enable = true;
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
and bundles the <literal>digitalbitbox</literal> package (see
|
||||||
|
<xref linkend="sec-digitalbitbox-package" />), which contains the
|
||||||
|
<literal>dbb-app</literal> and <literal>dbb-cli</literal> binaries,
|
||||||
|
along with the hardware module (see
|
||||||
|
<xref linkend="sec-digitalbitbox-hardware-module" />) which sets up
|
||||||
|
the necessary udev rules to access the device.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Enabling the digitalbitbox module is pretty much the easiest way to
|
||||||
|
get a Digital Bitbox device working on your system.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more information, see
|
||||||
|
<link xlink:href="https://digitalbitbox.com/start_linux">https://digitalbitbox.com/start_linux</link>.
|
||||||
|
</para>
|
||||||
|
<section xml:id="sec-digitalbitbox-package">
|
||||||
|
<title>Package</title>
|
||||||
|
<para>
|
||||||
|
The binaries, <literal>dbb-app</literal> (a GUI tool) and
|
||||||
|
<literal>dbb-cli</literal> (a CLI tool), are available through the
|
||||||
|
<literal>digitalbitbox</literal> package which could be installed
|
||||||
|
as follows:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
environment.systemPackages = [
|
||||||
|
pkgs.digitalbitbox
|
||||||
|
];
|
||||||
|
</programlisting>
|
||||||
|
</section>
|
||||||
|
<section xml:id="sec-digitalbitbox-hardware-module">
|
||||||
|
<title>Hardware</title>
|
||||||
|
<para>
|
||||||
|
The digitalbitbox hardware package enables the udev rules for
|
||||||
|
Digital Bitbox devices and may be installed as follows:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
hardware.digitalbitbox.enable = true;
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
In order to alter the udev rules, one may provide different values
|
||||||
|
for the <literal>udevRule51</literal> and
|
||||||
|
<literal>udevRule52</literal> attributes by means of overriding as
|
||||||
|
follows:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
programs.digitalbitbox = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.digitalbitbox.override {
|
||||||
|
udevRule51 = "something else";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
|
@ -1,74 +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="module-programs-digitalbitbox">
|
|
||||||
<title>Digital Bitbox</title>
|
|
||||||
<para>
|
|
||||||
Digital Bitbox is a hardware wallet and second-factor authenticator.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>digitalbitbox</literal> programs module may be installed by
|
|
||||||
setting <literal>programs.digitalbitbox</literal> to <literal>true</literal>
|
|
||||||
in a manner similar to
|
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-programs.digitalbitbox.enable"/> = true;
|
|
||||||
</programlisting>
|
|
||||||
and bundles the <literal>digitalbitbox</literal> package (see
|
|
||||||
<xref
|
|
||||||
linkend="sec-digitalbitbox-package" />), which contains the
|
|
||||||
<literal>dbb-app</literal> and <literal>dbb-cli</literal> binaries, along
|
|
||||||
with the hardware module (see
|
|
||||||
<xref
|
|
||||||
linkend="sec-digitalbitbox-hardware-module" />) which sets up the
|
|
||||||
necessary udev rules to access the device.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Enabling the digitalbitbox module is pretty much the easiest way to get a
|
|
||||||
Digital Bitbox device working on your system.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For more information, see
|
|
||||||
<link xlink:href="https://digitalbitbox.com/start_linux" />.
|
|
||||||
</para>
|
|
||||||
<section xml:id="sec-digitalbitbox-package">
|
|
||||||
<title>Package</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The binaries, <literal>dbb-app</literal> (a GUI tool) and
|
|
||||||
<literal>dbb-cli</literal> (a CLI tool), are available through the
|
|
||||||
<literal>digitalbitbox</literal> package which could be installed as
|
|
||||||
follows:
|
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-environment.systemPackages"/> = [
|
|
||||||
pkgs.digitalbitbox
|
|
||||||
];
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="sec-digitalbitbox-hardware-module">
|
|
||||||
<title>Hardware</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The digitalbitbox hardware package enables the udev rules for Digital Bitbox
|
|
||||||
devices and may be installed as follows:
|
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-hardware.digitalbitbox.enable"/> = true;
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
In order to alter the udev rules, one may provide different values for the
|
|
||||||
<literal>udevRule51</literal> and <literal>udevRule52</literal> attributes
|
|
||||||
by means of overriding as follows:
|
|
||||||
<programlisting>
|
|
||||||
programs.digitalbitbox = {
|
|
||||||
<link linkend="opt-programs.digitalbitbox.enable">enable</link> = true;
|
|
||||||
<link linkend="opt-programs.digitalbitbox.package">package</link> = pkgs.digitalbitbox.override {
|
|
||||||
udevRule51 = "something else";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
17
nixos/modules/programs/plotinus.md
Normal file
17
nixos/modules/programs/plotinus.md
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Plotinus {#module-program-plotinus}
|
||||||
|
|
||||||
|
*Source:* {file}`modules/programs/plotinus.nix`
|
||||||
|
|
||||||
|
*Upstream documentation:* <https://github.com/p-e-w/plotinus>
|
||||||
|
|
||||||
|
Plotinus is a searchable command palette in every modern GTK application.
|
||||||
|
|
||||||
|
When in a GTK 3 application and Plotinus is enabled, you can press
|
||||||
|
`Ctrl+Shift+P` to open the command palette. The command
|
||||||
|
palette provides a searchable list of of all menu items in the application.
|
||||||
|
|
||||||
|
To enable Plotinus, add the following to your
|
||||||
|
{file}`configuration.nix`:
|
||||||
|
```
|
||||||
|
programs.plotinus.enable = true;
|
||||||
|
```
|
|
@ -1,8 +1,6 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-program-plotinus">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-program-plotinus">
|
|
||||||
<title>Plotinus</title>
|
<title>Plotinus</title>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Source:</emphasis>
|
<emphasis>Source:</emphasis>
|
||||||
|
@ -10,21 +8,23 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Upstream documentation:</emphasis>
|
<emphasis>Upstream documentation:</emphasis>
|
||||||
<link xlink:href="https://github.com/p-e-w/plotinus"/>
|
<link xlink:href="https://github.com/p-e-w/plotinus">https://github.com/p-e-w/plotinus</link>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Plotinus is a searchable command palette in every modern GTK application.
|
Plotinus is a searchable command palette in every modern GTK
|
||||||
|
application.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
When in a GTK 3 application and Plotinus is enabled, you can press
|
When in a GTK 3 application and Plotinus is enabled, you can press
|
||||||
<literal>Ctrl+Shift+P</literal> to open the command palette. The command
|
<literal>Ctrl+Shift+P</literal> to open the command palette. The
|
||||||
palette provides a searchable list of of all menu items in the application.
|
command palette provides a searchable list of of all menu items in
|
||||||
|
the application.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To enable Plotinus, add the following to your
|
To enable Plotinus, add the following to your
|
||||||
<filename>configuration.nix</filename>:
|
<filename>configuration.nix</filename>:
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-programs.plotinus.enable"/> = true;
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
programs.plotinus.enable = true;
|
||||||
|
</programlisting>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
109
nixos/modules/programs/zsh/oh-my-zsh.md
Normal file
109
nixos/modules/programs/zsh/oh-my-zsh.md
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
# Oh my ZSH {#module-programs-zsh-ohmyzsh}
|
||||||
|
|
||||||
|
[`oh-my-zsh`](https://ohmyz.sh/) is a framework to manage your [ZSH](https://www.zsh.org/)
|
||||||
|
configuration including completion scripts for several CLI tools or custom
|
||||||
|
prompt themes.
|
||||||
|
|
||||||
|
## Basic usage {#module-programs-oh-my-zsh-usage}
|
||||||
|
|
||||||
|
The module uses the `oh-my-zsh` package with all available
|
||||||
|
features. The initial setup using Nix expressions is fairly similar to the
|
||||||
|
configuration format of `oh-my-zsh`.
|
||||||
|
```
|
||||||
|
{
|
||||||
|
programs.zsh.ohMyZsh = {
|
||||||
|
enable = true;
|
||||||
|
plugins = [ "git" "python" "man" ];
|
||||||
|
theme = "agnoster";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
For a detailed explanation of these arguments please refer to the
|
||||||
|
[`oh-my-zsh` docs](https://github.com/robbyrussell/oh-my-zsh/wiki).
|
||||||
|
|
||||||
|
The expression generates the needed configuration and writes it into your
|
||||||
|
`/etc/zshrc`.
|
||||||
|
|
||||||
|
## Custom additions {#module-programs-oh-my-zsh-additions}
|
||||||
|
|
||||||
|
Sometimes third-party or custom scripts such as a modified theme may be
|
||||||
|
needed. `oh-my-zsh` provides the
|
||||||
|
[`ZSH_CUSTOM`](https://github.com/robbyrussell/oh-my-zsh/wiki/Customization#overriding-internals)
|
||||||
|
environment variable for this which points to a directory with additional
|
||||||
|
scripts.
|
||||||
|
|
||||||
|
The module can do this as well:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
programs.zsh.ohMyZsh.custom = "~/path/to/custom/scripts";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom environments {#module-programs-oh-my-zsh-environments}
|
||||||
|
|
||||||
|
There are several extensions for `oh-my-zsh` packaged in
|
||||||
|
`nixpkgs`. One of them is
|
||||||
|
[nix-zsh-completions](https://github.com/spwhitt/nix-zsh-completions)
|
||||||
|
which bundles completion scripts and a plugin for `oh-my-zsh`.
|
||||||
|
|
||||||
|
Rather than using a single mutable path for `ZSH_CUSTOM`,
|
||||||
|
it's also possible to generate this path from a list of Nix packages:
|
||||||
|
```
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
programs.zsh.ohMyZsh.customPkgs = [
|
||||||
|
pkgs.nix-zsh-completions
|
||||||
|
# and even more...
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Internally a single store path will be created using
|
||||||
|
`buildEnv`. Please refer to the docs of
|
||||||
|
[`buildEnv`](https://nixos.org/nixpkgs/manual/#sec-building-environment)
|
||||||
|
for further reference.
|
||||||
|
|
||||||
|
*Please keep in mind that this is not compatible with
|
||||||
|
`programs.zsh.ohMyZsh.custom` as it requires an immutable
|
||||||
|
store path while `custom` shall remain mutable! An
|
||||||
|
evaluation failure will be thrown if both `custom` and
|
||||||
|
`customPkgs` are set.*
|
||||||
|
|
||||||
|
## Package your own customizations {#module-programs-oh-my-zsh-packaging-customizations}
|
||||||
|
|
||||||
|
If third-party customizations (e.g. new themes) are supposed to be added to
|
||||||
|
`oh-my-zsh` there are several pitfalls to keep in mind:
|
||||||
|
|
||||||
|
- To comply with the default structure of `ZSH` the entire
|
||||||
|
output needs to be written to `$out/share/zsh.`
|
||||||
|
|
||||||
|
- Completion scripts are supposed to be stored at
|
||||||
|
`$out/share/zsh/site-functions`. This directory is part of the
|
||||||
|
[`fpath`](http://zsh.sourceforge.net/Doc/Release/Functions.html)
|
||||||
|
and the package should be compatible with pure `ZSH`
|
||||||
|
setups. The module will automatically link the contents of
|
||||||
|
`site-functions` to completions directory in the proper
|
||||||
|
store path.
|
||||||
|
|
||||||
|
- The `plugins` directory needs the structure
|
||||||
|
`pluginname/pluginname.plugin.zsh` as structured in the
|
||||||
|
[upstream repo.](https://github.com/robbyrussell/oh-my-zsh/tree/91b771914bc7c43dd7c7a43b586c5de2c225ceb7/plugins)
|
||||||
|
|
||||||
|
A derivation for `oh-my-zsh` may look like this:
|
||||||
|
```
|
||||||
|
{ stdenv, fetchFromGitHub }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
name = "exemplary-zsh-customization-${version}";
|
||||||
|
version = "1.0.0";
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
# path to the upstream repository
|
||||||
|
};
|
||||||
|
|
||||||
|
dontBuild = true;
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/share/zsh/site-functions
|
||||||
|
cp {themes,plugins} $out/share/zsh
|
||||||
|
cp completions $out/share/zsh/site-functions
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
```
|
|
@ -1,75 +1,73 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-programs-zsh-ohmyzsh">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-programs-zsh-ohmyzsh">
|
|
||||||
<title>Oh my ZSH</title>
|
<title>Oh my ZSH</title>
|
||||||
<para>
|
<para>
|
||||||
<literal><link xlink:href="https://ohmyz.sh/">oh-my-zsh</link></literal> is a
|
<link xlink:href="https://ohmyz.sh/"><literal>oh-my-zsh</literal></link>
|
||||||
framework to manage your <link xlink:href="https://www.zsh.org/">ZSH</link>
|
is a framework to manage your
|
||||||
configuration including completion scripts for several CLI tools or custom
|
<link xlink:href="https://www.zsh.org/">ZSH</link> configuration
|
||||||
prompt themes.
|
including completion scripts for several CLI tools or custom prompt
|
||||||
|
themes.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-programs-oh-my-zsh-usage">
|
<section xml:id="module-programs-oh-my-zsh-usage">
|
||||||
<title>Basic usage</title>
|
<title>Basic usage</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The module uses the <literal>oh-my-zsh</literal> package with all available
|
The module uses the <literal>oh-my-zsh</literal> package with all
|
||||||
features. The initial setup using Nix expressions is fairly similar to the
|
available features. The initial setup using Nix expressions is
|
||||||
configuration format of <literal>oh-my-zsh</literal>.
|
fairly similar to the configuration format of
|
||||||
|
<literal>oh-my-zsh</literal>.
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
programs.zsh.ohMyZsh = {
|
programs.zsh.ohMyZsh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
plugins = [ "git" "python" "man" ];
|
plugins = [ "git" "python" "man" ];
|
||||||
theme = "agnoster";
|
theme = "agnoster";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
<para>
|
||||||
For a detailed explanation of these arguments please refer to the
|
For a detailed explanation of these arguments please refer to the
|
||||||
<link xlink:href="https://github.com/robbyrussell/oh-my-zsh/wiki"><literal>oh-my-zsh</literal>
|
<link xlink:href="https://github.com/robbyrussell/oh-my-zsh/wiki"><literal>oh-my-zsh</literal>
|
||||||
docs</link>.
|
docs</link>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The expression generates the needed configuration and writes it into your
|
The expression generates the needed configuration and writes it
|
||||||
<literal>/etc/zshrc</literal>.
|
into your <literal>/etc/zshrc</literal>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-programs-oh-my-zsh-additions">
|
<section xml:id="module-programs-oh-my-zsh-additions">
|
||||||
<title>Custom additions</title>
|
<title>Custom additions</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Sometimes third-party or custom scripts such as a modified theme may be
|
Sometimes third-party or custom scripts such as a modified theme
|
||||||
needed. <literal>oh-my-zsh</literal> provides the
|
may be needed. <literal>oh-my-zsh</literal> provides the
|
||||||
<link xlink:href="https://github.com/robbyrussell/oh-my-zsh/wiki/Customization#overriding-internals"><literal>ZSH_CUSTOM</literal></link>
|
<link xlink:href="https://github.com/robbyrussell/oh-my-zsh/wiki/Customization#overriding-internals"><literal>ZSH_CUSTOM</literal></link>
|
||||||
environment variable for this which points to a directory with additional
|
environment variable for this which points to a directory with
|
||||||
scripts.
|
additional scripts.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The module can do this as well:
|
The module can do this as well:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
programs.zsh.ohMyZsh.custom = "~/path/to/custom/scripts";
|
programs.zsh.ohMyZsh.custom = "~/path/to/custom/scripts";
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-programs-oh-my-zsh-environments">
|
<section xml:id="module-programs-oh-my-zsh-environments">
|
||||||
<title>Custom environments</title>
|
<title>Custom environments</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
There are several extensions for <literal>oh-my-zsh</literal> packaged in
|
There are several extensions for <literal>oh-my-zsh</literal>
|
||||||
<literal>nixpkgs</literal>. One of them is
|
packaged in <literal>nixpkgs</literal>. One of them is
|
||||||
<link xlink:href="https://github.com/spwhitt/nix-zsh-completions">nix-zsh-completions</link>
|
<link xlink:href="https://github.com/spwhitt/nix-zsh-completions">nix-zsh-completions</link>
|
||||||
which bundles completion scripts and a plugin for
|
which bundles completion scripts and a plugin for
|
||||||
<literal>oh-my-zsh</literal>.
|
<literal>oh-my-zsh</literal>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Rather than using a single mutable path for <literal>ZSH_CUSTOM</literal>,
|
Rather than using a single mutable path for
|
||||||
it's also possible to generate this path from a list of Nix packages:
|
<literal>ZSH_CUSTOM</literal>, it’s also possible to generate this
|
||||||
|
path from a list of Nix packages:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
|
@ -79,65 +77,67 @@
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
<para>
|
||||||
Internally a single store path will be created using
|
Internally a single store path will be created using
|
||||||
<literal>buildEnv</literal>. Please refer to the docs of
|
<literal>buildEnv</literal>. Please refer to the docs of
|
||||||
<link xlink:href="https://nixos.org/nixpkgs/manual/#sec-building-environment"><literal>buildEnv</literal></link>
|
<link xlink:href="https://nixos.org/nixpkgs/manual/#sec-building-environment"><literal>buildEnv</literal></link>
|
||||||
for further reference.
|
for further reference.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Please keep in mind that this is not compatible with
|
<emphasis>Please keep in mind that this is not compatible with
|
||||||
<literal>programs.zsh.ohMyZsh.custom</literal> as it requires an immutable
|
<literal>programs.zsh.ohMyZsh.custom</literal> as it requires an
|
||||||
store path while <literal>custom</literal> shall remain mutable! An
|
immutable store path while <literal>custom</literal> shall remain
|
||||||
evaluation failure will be thrown if both <literal>custom</literal> and
|
mutable! An evaluation failure will be thrown if both
|
||||||
<literal>customPkgs</literal> are set.</emphasis>
|
<literal>custom</literal> and <literal>customPkgs</literal> are
|
||||||
|
set.</emphasis>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-programs-oh-my-zsh-packaging-customizations">
|
<section xml:id="module-programs-oh-my-zsh-packaging-customizations">
|
||||||
<title>Package your own customizations</title>
|
<title>Package your own customizations</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If third-party customizations (e.g. new themes) are supposed to be added to
|
If third-party customizations (e.g. new themes) are supposed to be
|
||||||
<literal>oh-my-zsh</literal> there are several pitfalls to keep in mind:
|
added to <literal>oh-my-zsh</literal> there are several pitfalls
|
||||||
|
to keep in mind:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
To comply with the default structure of <literal>ZSH</literal> the entire
|
To comply with the default structure of <literal>ZSH</literal>
|
||||||
output needs to be written to <literal>$out/share/zsh.</literal>
|
the entire output needs to be written to
|
||||||
|
<literal>$out/share/zsh.</literal>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Completion scripts are supposed to be stored at
|
Completion scripts are supposed to be stored at
|
||||||
<literal>$out/share/zsh/site-functions</literal>. This directory is part
|
<literal>$out/share/zsh/site-functions</literal>. This
|
||||||
of the
|
directory is part of the
|
||||||
<literal><link xlink:href="http://zsh.sourceforge.net/Doc/Release/Functions.html">fpath</link></literal>
|
<link xlink:href="http://zsh.sourceforge.net/Doc/Release/Functions.html"><literal>fpath</literal></link>
|
||||||
and the package should be compatible with pure <literal>ZSH</literal>
|
and the package should be compatible with pure
|
||||||
setups. The module will automatically link the contents of
|
<literal>ZSH</literal> setups. The module will automatically
|
||||||
<literal>site-functions</literal> to completions directory in the proper
|
link the contents of <literal>site-functions</literal> to
|
||||||
store path.
|
completions directory in the proper store path.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The <literal>plugins</literal> directory needs the structure
|
The <literal>plugins</literal> directory needs the structure
|
||||||
<literal>pluginname/pluginname.plugin.zsh</literal> as structured in the
|
<literal>pluginname/pluginname.plugin.zsh</literal> as
|
||||||
|
structured in the
|
||||||
<link xlink:href="https://github.com/robbyrussell/oh-my-zsh/tree/91b771914bc7c43dd7c7a43b586c5de2c225ceb7/plugins">upstream
|
<link xlink:href="https://github.com/robbyrussell/oh-my-zsh/tree/91b771914bc7c43dd7c7a43b586c5de2c225ceb7/plugins">upstream
|
||||||
repo.</link>
|
repo.</link>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A derivation for <literal>oh-my-zsh</literal> may look like this:
|
A derivation for <literal>oh-my-zsh</literal> may look like this:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{ stdenv, fetchFromGitHub }:
|
{ stdenv, fetchFromGitHub }:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
name = "exemplary-zsh-customization-${version}";
|
name = "exemplary-zsh-customization-${version}";
|
||||||
version = "1.0.0";
|
version = "1.0.0";
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
# path to the upstream repository
|
# path to the upstream repository
|
||||||
};
|
};
|
||||||
|
@ -150,6 +150,5 @@ stdenv.mkDerivation rec {
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
354
nixos/modules/security/acme/default.md
Normal file
354
nixos/modules/security/acme/default.md
Normal file
|
@ -0,0 +1,354 @@
|
||||||
|
# SSL/TLS Certificates with ACME {#module-security-acme}
|
||||||
|
|
||||||
|
NixOS supports automatic domain validation & certificate retrieval and
|
||||||
|
renewal using the ACME protocol. Any provider can be used, but by default
|
||||||
|
NixOS uses Let's Encrypt. The alternative ACME client
|
||||||
|
[lego](https://go-acme.github.io/lego/) is used under
|
||||||
|
the hood.
|
||||||
|
|
||||||
|
Automatic cert validation and configuration for Apache and Nginx virtual
|
||||||
|
hosts is included in NixOS, however if you would like to generate a wildcard
|
||||||
|
cert or you are not using a web server you will have to configure DNS
|
||||||
|
based validation.
|
||||||
|
|
||||||
|
## Prerequisites {#module-security-acme-prerequisites}
|
||||||
|
|
||||||
|
To use the ACME module, you must accept the provider's terms of service
|
||||||
|
by setting [](#opt-security.acme.acceptTerms)
|
||||||
|
to `true`. The Let's Encrypt ToS can be found
|
||||||
|
[here](https://letsencrypt.org/repository/).
|
||||||
|
|
||||||
|
You must also set an email address to be used when creating accounts with
|
||||||
|
Let's Encrypt. You can set this for all certs with
|
||||||
|
[](#opt-security.acme.defaults.email)
|
||||||
|
and/or on a per-cert basis with
|
||||||
|
[](#opt-security.acme.certs._name_.email).
|
||||||
|
This address is only used for registration and renewal reminders,
|
||||||
|
and cannot be used to administer the certificates in any way.
|
||||||
|
|
||||||
|
Alternatively, you can use a different ACME server by changing the
|
||||||
|
[](#opt-security.acme.defaults.server) option
|
||||||
|
to a provider of your choosing, or just change the server for one cert with
|
||||||
|
[](#opt-security.acme.certs._name_.server).
|
||||||
|
|
||||||
|
You will need an HTTP server or DNS server for verification. For HTTP,
|
||||||
|
the server must have a webroot defined that can serve
|
||||||
|
{file}`.well-known/acme-challenge`. This directory must be
|
||||||
|
writeable by the user that will run the ACME client. For DNS, you must
|
||||||
|
set up credentials with your provider/server for use with lego.
|
||||||
|
|
||||||
|
## Using ACME certificates in Nginx {#module-security-acme-nginx}
|
||||||
|
|
||||||
|
NixOS supports fetching ACME certificates for you by setting
|
||||||
|
`enableACME = true;` in a virtualHost config. We first create self-signed
|
||||||
|
placeholder certificates in place of the real ACME certs. The placeholder
|
||||||
|
certs are overwritten when the ACME certs arrive. For
|
||||||
|
`foo.example.com` the config would look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@example.com";
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"foo.example.com" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
# All serverAliases will be added as extra domain names on the certificate.
|
||||||
|
serverAliases = [ "bar.example.com" ];
|
||||||
|
locations."/" = {
|
||||||
|
root = "/var/www";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# We can also add a different vhost and reuse the same certificate
|
||||||
|
# but we have to append extraDomainNames manually beforehand:
|
||||||
|
# security.acme.certs."foo.example.com".extraDomainNames = [ "baz.example.com" ];
|
||||||
|
"baz.example.com" = {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = "foo.example.com";
|
||||||
|
locations."/" = {
|
||||||
|
root = "/var/www";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using ACME certificates in Apache/httpd {#module-security-acme-httpd}
|
||||||
|
|
||||||
|
Using ACME certificates with Apache virtual hosts is identical
|
||||||
|
to using them with Nginx. The attribute names are all the same, just replace
|
||||||
|
"nginx" with "httpd" where appropriate.
|
||||||
|
|
||||||
|
## Manual configuration of HTTP-01 validation {#module-security-acme-configuring}
|
||||||
|
|
||||||
|
First off you will need to set up a virtual host to serve the challenges.
|
||||||
|
This example uses a vhost called `certs.example.com`, with
|
||||||
|
the intent that you will generate certs for all your vhosts and redirect
|
||||||
|
everyone to HTTPS.
|
||||||
|
|
||||||
|
```
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@example.com";
|
||||||
|
|
||||||
|
# /var/lib/acme/.challenges must be writable by the ACME user
|
||||||
|
# and readable by the Nginx user. The easiest way to achieve
|
||||||
|
# this is to add the Nginx user to the ACME group.
|
||||||
|
users.users.nginx.extraGroups = [ "acme" ];
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"acmechallenge.example.com" = {
|
||||||
|
# Catchall vhost, will redirect users to HTTPS for all vhosts
|
||||||
|
serverAliases = [ "*.example.com" ];
|
||||||
|
locations."/.well-known/acme-challenge" = {
|
||||||
|
root = "/var/lib/acme/.challenges";
|
||||||
|
};
|
||||||
|
locations."/" = {
|
||||||
|
return = "301 https://$host$request_uri";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
# Alternative config for Apache
|
||||||
|
users.users.wwwrun.extraGroups = [ "acme" ];
|
||||||
|
services.httpd = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"acmechallenge.example.com" = {
|
||||||
|
# Catchall vhost, will redirect users to HTTPS for all vhosts
|
||||||
|
serverAliases = [ "*.example.com" ];
|
||||||
|
# /var/lib/acme/.challenges must be writable by the ACME user and readable by the Apache user.
|
||||||
|
# By default, this is the case.
|
||||||
|
documentRoot = "/var/lib/acme/.challenges";
|
||||||
|
extraConfig = ''
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{HTTPS} off
|
||||||
|
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge [NC]
|
||||||
|
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you need to configure ACME to generate a certificate.
|
||||||
|
|
||||||
|
```
|
||||||
|
security.acme.certs."foo.example.com" = {
|
||||||
|
webroot = "/var/lib/acme/.challenges";
|
||||||
|
email = "foo@example.com";
|
||||||
|
# Ensure that the web server you use can read the generated certs
|
||||||
|
# Take a look at the group option for the web server you choose.
|
||||||
|
group = "nginx";
|
||||||
|
# Since we have a wildcard vhost to handle port 80,
|
||||||
|
# we can generate certs for anything!
|
||||||
|
# Just make sure your DNS resolves them.
|
||||||
|
extraDomainNames = [ "mail.example.com" ];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The private key {file}`key.pem` and certificate
|
||||||
|
{file}`fullchain.pem` will be put into
|
||||||
|
{file}`/var/lib/acme/foo.example.com`.
|
||||||
|
|
||||||
|
Refer to [](#ch-options) for all available configuration
|
||||||
|
options for the [security.acme](#opt-security.acme.certs)
|
||||||
|
module.
|
||||||
|
|
||||||
|
## Configuring ACME for DNS validation {#module-security-acme-config-dns}
|
||||||
|
|
||||||
|
This is useful if you want to generate a wildcard certificate, since
|
||||||
|
ACME servers will only hand out wildcard certs over DNS validation.
|
||||||
|
There are a number of supported DNS providers and servers you can utilise,
|
||||||
|
see the [lego docs](https://go-acme.github.io/lego/dns/)
|
||||||
|
for provider/server specific configuration values. For the sake of these
|
||||||
|
docs, we will provide a fully self-hosted example using bind.
|
||||||
|
|
||||||
|
```
|
||||||
|
services.bind = {
|
||||||
|
enable = true;
|
||||||
|
extraConfig = ''
|
||||||
|
include "/var/lib/secrets/dnskeys.conf";
|
||||||
|
'';
|
||||||
|
zones = [
|
||||||
|
rec {
|
||||||
|
name = "example.com";
|
||||||
|
file = "/var/db/bind/${name}";
|
||||||
|
master = true;
|
||||||
|
extraConfig = "allow-update { key rfc2136key.example.com.; };";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
# Now we can configure ACME
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@example.com";
|
||||||
|
security.acme.certs."example.com" = {
|
||||||
|
domain = "*.example.com";
|
||||||
|
dnsProvider = "rfc2136";
|
||||||
|
credentialsFile = "/var/lib/secrets/certs.secret";
|
||||||
|
# We don't need to wait for propagation since this is a local DNS server
|
||||||
|
dnsPropagationCheck = false;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The {file}`dnskeys.conf` and {file}`certs.secret`
|
||||||
|
must be kept secure and thus you should not keep their contents in your
|
||||||
|
Nix config. Instead, generate them one time with a systemd service:
|
||||||
|
|
||||||
|
```
|
||||||
|
systemd.services.dns-rfc2136-conf = {
|
||||||
|
requiredBy = ["acme-example.com.service" "bind.service"];
|
||||||
|
before = ["acme-example.com.service" "bind.service"];
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!/var/lib/secrets/dnskeys.conf";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
UMask = 0077;
|
||||||
|
};
|
||||||
|
path = [ pkgs.bind ];
|
||||||
|
script = ''
|
||||||
|
mkdir -p /var/lib/secrets
|
||||||
|
chmod 755 /var/lib/secrets
|
||||||
|
tsig-keygen rfc2136key.example.com > /var/lib/secrets/dnskeys.conf
|
||||||
|
chown named:root /var/lib/secrets/dnskeys.conf
|
||||||
|
chmod 400 /var/lib/secrets/dnskeys.conf
|
||||||
|
|
||||||
|
# extract secret value from the dnskeys.conf
|
||||||
|
while read x y; do if [ "$x" = "secret" ]; then secret="''${y:1:''${#y}-3}"; fi; done < /var/lib/secrets/dnskeys.conf
|
||||||
|
|
||||||
|
cat > /var/lib/secrets/certs.secret << EOF
|
||||||
|
RFC2136_NAMESERVER='127.0.0.1:53'
|
||||||
|
RFC2136_TSIG_ALGORITHM='hmac-sha256.'
|
||||||
|
RFC2136_TSIG_KEY='rfc2136key.example.com'
|
||||||
|
RFC2136_TSIG_SECRET='$secret'
|
||||||
|
EOF
|
||||||
|
chmod 400 /var/lib/secrets/certs.secret
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you're all set to generate certs! You should monitor the first invocation
|
||||||
|
by running `systemctl start acme-example.com.service &
|
||||||
|
journalctl -fu acme-example.com.service` and watching its log output.
|
||||||
|
|
||||||
|
## Using DNS validation with web server virtual hosts {#module-security-acme-config-dns-with-vhosts}
|
||||||
|
|
||||||
|
It is possible to use DNS-01 validation with all certificates,
|
||||||
|
including those automatically configured via the Nginx/Apache
|
||||||
|
[`enableACME`](#opt-services.nginx.virtualHosts._name_.enableACME)
|
||||||
|
option. This configuration pattern is fully
|
||||||
|
supported and part of the module's test suite for Nginx + Apache.
|
||||||
|
|
||||||
|
You must follow the guide above on configuring DNS-01 validation
|
||||||
|
first, however instead of setting the options for one certificate
|
||||||
|
(e.g. [](#opt-security.acme.certs._name_.dnsProvider))
|
||||||
|
you will set them as defaults
|
||||||
|
(e.g. [](#opt-security.acme.defaults.dnsProvider)).
|
||||||
|
|
||||||
|
```
|
||||||
|
# Configure ACME appropriately
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@example.com";
|
||||||
|
security.acme.defaults = {
|
||||||
|
dnsProvider = "rfc2136";
|
||||||
|
credentialsFile = "/var/lib/secrets/certs.secret";
|
||||||
|
# We don't need to wait for propagation since this is a local DNS server
|
||||||
|
dnsPropagationCheck = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# For each virtual host you would like to use DNS-01 validation with,
|
||||||
|
# set acmeRoot = null
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"foo.example.com" = {
|
||||||
|
enableACME = true;
|
||||||
|
acmeRoot = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And that's it! Next time your configuration is rebuilt, or when
|
||||||
|
you add a new virtualHost, it will be DNS-01 validated.
|
||||||
|
|
||||||
|
## Using ACME with services demanding root owned certificates {#module-security-acme-root-owned}
|
||||||
|
|
||||||
|
Some services refuse to start if the configured certificate files
|
||||||
|
are not owned by root. PostgreSQL and OpenSMTPD are examples of these.
|
||||||
|
There is no way to change the user the ACME module uses (it will always be
|
||||||
|
`acme`), however you can use systemd's
|
||||||
|
`LoadCredential` feature to resolve this elegantly.
|
||||||
|
Below is an example configuration for OpenSMTPD, but this pattern
|
||||||
|
can be applied to any service.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Configure ACME however you like (DNS or HTTP validation), adding
|
||||||
|
# the following configuration for the relevant certificate.
|
||||||
|
# Note: You cannot use `systemctl reload` here as that would mean
|
||||||
|
# the LoadCredential configuration below would be skipped and
|
||||||
|
# the service would continue to use old certificates.
|
||||||
|
security.acme.certs."mail.example.com".postRun = ''
|
||||||
|
systemctl restart opensmtpd
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Now you must augment OpenSMTPD's systemd service to load
|
||||||
|
# the certificate files.
|
||||||
|
systemd.services.opensmtpd.requires = ["acme-finished-mail.example.com.target"];
|
||||||
|
systemd.services.opensmtpd.serviceConfig.LoadCredential = let
|
||||||
|
certDir = config.security.acme.certs."mail.example.com".directory;
|
||||||
|
in [
|
||||||
|
"cert.pem:${certDir}/cert.pem"
|
||||||
|
"key.pem:${certDir}/key.pem"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Finally, configure OpenSMTPD to use these certs.
|
||||||
|
services.opensmtpd = let
|
||||||
|
credsDir = "/run/credentials/opensmtpd.service";
|
||||||
|
in {
|
||||||
|
enable = true;
|
||||||
|
setSendmail = false;
|
||||||
|
serverConfiguration = ''
|
||||||
|
pki mail.example.com cert "${credsDir}/cert.pem"
|
||||||
|
pki mail.example.com key "${credsDir}/key.pem"
|
||||||
|
listen on localhost tls pki mail.example.com
|
||||||
|
action act1 relay host smtp://127.0.0.1:10027
|
||||||
|
match for local action act1
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Regenerating certificates {#module-security-acme-regenerate}
|
||||||
|
|
||||||
|
Should you need to regenerate a particular certificate in a hurry, such
|
||||||
|
as when a vulnerability is found in Let's Encrypt, there is now a convenient
|
||||||
|
mechanism for doing so. Running
|
||||||
|
`systemctl clean --what=state acme-example.com.service`
|
||||||
|
will remove all certificate files and the account data for the given domain,
|
||||||
|
allowing you to then `systemctl start acme-example.com.service`
|
||||||
|
to generate fresh ones.
|
||||||
|
|
||||||
|
## Fixing JWS Verification error {#module-security-acme-fix-jws}
|
||||||
|
|
||||||
|
It is possible that your account credentials file may become corrupt and need
|
||||||
|
to be regenerated. In this scenario lego will produce the error `JWS verification error`.
|
||||||
|
The solution is to simply delete the associated accounts file and
|
||||||
|
re-run the affected service(s).
|
||||||
|
|
||||||
|
```
|
||||||
|
# Find the accounts folder for the certificate
|
||||||
|
systemctl cat acme-example.com.service | grep -Po 'accounts/[^:]*'
|
||||||
|
export accountdir="$(!!)"
|
||||||
|
# Move this folder to some place else
|
||||||
|
mv /var/lib/acme/.lego/$accountdir{,.bak}
|
||||||
|
# Recreate the folder using systemd-tmpfiles
|
||||||
|
systemd-tmpfiles --create
|
||||||
|
# Get a new account and reissue certificates
|
||||||
|
# Note: Do this for all certs that share the same account email address
|
||||||
|
systemctl start acme-example.com.service
|
||||||
|
```
|
|
@ -916,6 +916,6 @@ in {
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
maintainers = lib.teams.acme.members;
|
maintainers = lib.teams.acme.members;
|
||||||
doc = ./doc.xml;
|
doc = ./default.xml;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
395
nixos/modules/security/acme/default.xml
Normal file
395
nixos/modules/security/acme/default.xml
Normal file
|
@ -0,0 +1,395 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-security-acme">
|
||||||
|
<title>SSL/TLS Certificates with ACME</title>
|
||||||
|
<para>
|
||||||
|
NixOS supports automatic domain validation & certificate
|
||||||
|
retrieval and renewal using the ACME protocol. Any provider can be
|
||||||
|
used, but by default NixOS uses Let’s Encrypt. The alternative ACME
|
||||||
|
client
|
||||||
|
<link xlink:href="https://go-acme.github.io/lego/">lego</link> is
|
||||||
|
used under the hood.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Automatic cert validation and configuration for Apache and Nginx
|
||||||
|
virtual hosts is included in NixOS, however if you would like to
|
||||||
|
generate a wildcard cert or you are not using a web server you will
|
||||||
|
have to configure DNS based validation.
|
||||||
|
</para>
|
||||||
|
<section xml:id="module-security-acme-prerequisites">
|
||||||
|
<title>Prerequisites</title>
|
||||||
|
<para>
|
||||||
|
To use the ACME module, you must accept the provider’s terms of
|
||||||
|
service by setting
|
||||||
|
<xref linkend="opt-security.acme.acceptTerms" /> to
|
||||||
|
<literal>true</literal>. The Let’s Encrypt ToS can be found
|
||||||
|
<link xlink:href="https://letsencrypt.org/repository/">here</link>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
You must also set an email address to be used when creating
|
||||||
|
accounts with Let’s Encrypt. You can set this for all certs with
|
||||||
|
<xref linkend="opt-security.acme.defaults.email" /> and/or on a
|
||||||
|
per-cert basis with
|
||||||
|
<xref linkend="opt-security.acme.certs._name_.email" />. This
|
||||||
|
address is only used for registration and renewal reminders, and
|
||||||
|
cannot be used to administer the certificates in any way.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Alternatively, you can use a different ACME server by changing the
|
||||||
|
<xref linkend="opt-security.acme.defaults.server" /> option to a
|
||||||
|
provider of your choosing, or just change the server for one cert
|
||||||
|
with <xref linkend="opt-security.acme.certs._name_.server" />.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
You will need an HTTP server or DNS server for verification. For
|
||||||
|
HTTP, the server must have a webroot defined that can serve
|
||||||
|
<filename>.well-known/acme-challenge</filename>. This directory
|
||||||
|
must be writeable by the user that will run the ACME client. For
|
||||||
|
DNS, you must set up credentials with your provider/server for use
|
||||||
|
with lego.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-security-acme-nginx">
|
||||||
|
<title>Using ACME certificates in Nginx</title>
|
||||||
|
<para>
|
||||||
|
NixOS supports fetching ACME certificates for you by setting
|
||||||
|
<literal>enableACME = true;</literal> in a virtualHost config. We
|
||||||
|
first create self-signed placeholder certificates in place of the
|
||||||
|
real ACME certs. The placeholder certs are overwritten when the
|
||||||
|
ACME certs arrive. For <literal>foo.example.com</literal> the
|
||||||
|
config would look like this:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@example.com";
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"foo.example.com" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
# All serverAliases will be added as extra domain names on the certificate.
|
||||||
|
serverAliases = [ "bar.example.com" ];
|
||||||
|
locations."/" = {
|
||||||
|
root = "/var/www";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# We can also add a different vhost and reuse the same certificate
|
||||||
|
# but we have to append extraDomainNames manually beforehand:
|
||||||
|
# security.acme.certs."foo.example.com".extraDomainNames = [ "baz.example.com" ];
|
||||||
|
"baz.example.com" = {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = "foo.example.com";
|
||||||
|
locations."/" = {
|
||||||
|
root = "/var/www";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-security-acme-httpd">
|
||||||
|
<title>Using ACME certificates in Apache/httpd</title>
|
||||||
|
<para>
|
||||||
|
Using ACME certificates with Apache virtual hosts is identical to
|
||||||
|
using them with Nginx. The attribute names are all the same, just
|
||||||
|
replace <quote>nginx</quote> with <quote>httpd</quote> where
|
||||||
|
appropriate.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-security-acme-configuring">
|
||||||
|
<title>Manual configuration of HTTP-01 validation</title>
|
||||||
|
<para>
|
||||||
|
First off you will need to set up a virtual host to serve the
|
||||||
|
challenges. This example uses a vhost called
|
||||||
|
<literal>certs.example.com</literal>, with the intent that you
|
||||||
|
will generate certs for all your vhosts and redirect everyone to
|
||||||
|
HTTPS.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@example.com";
|
||||||
|
|
||||||
|
# /var/lib/acme/.challenges must be writable by the ACME user
|
||||||
|
# and readable by the Nginx user. The easiest way to achieve
|
||||||
|
# this is to add the Nginx user to the ACME group.
|
||||||
|
users.users.nginx.extraGroups = [ "acme" ];
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"acmechallenge.example.com" = {
|
||||||
|
# Catchall vhost, will redirect users to HTTPS for all vhosts
|
||||||
|
serverAliases = [ "*.example.com" ];
|
||||||
|
locations."/.well-known/acme-challenge" = {
|
||||||
|
root = "/var/lib/acme/.challenges";
|
||||||
|
};
|
||||||
|
locations."/" = {
|
||||||
|
return = "301 https://$host$request_uri";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
# Alternative config for Apache
|
||||||
|
users.users.wwwrun.extraGroups = [ "acme" ];
|
||||||
|
services.httpd = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"acmechallenge.example.com" = {
|
||||||
|
# Catchall vhost, will redirect users to HTTPS for all vhosts
|
||||||
|
serverAliases = [ "*.example.com" ];
|
||||||
|
# /var/lib/acme/.challenges must be writable by the ACME user and readable by the Apache user.
|
||||||
|
# By default, this is the case.
|
||||||
|
documentRoot = "/var/lib/acme/.challenges";
|
||||||
|
extraConfig = ''
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{HTTPS} off
|
||||||
|
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge [NC]
|
||||||
|
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Now you need to configure ACME to generate a certificate.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
security.acme.certs."foo.example.com" = {
|
||||||
|
webroot = "/var/lib/acme/.challenges";
|
||||||
|
email = "foo@example.com";
|
||||||
|
# Ensure that the web server you use can read the generated certs
|
||||||
|
# Take a look at the group option for the web server you choose.
|
||||||
|
group = "nginx";
|
||||||
|
# Since we have a wildcard vhost to handle port 80,
|
||||||
|
# we can generate certs for anything!
|
||||||
|
# Just make sure your DNS resolves them.
|
||||||
|
extraDomainNames = [ "mail.example.com" ];
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
The private key <filename>key.pem</filename> and certificate
|
||||||
|
<filename>fullchain.pem</filename> will be put into
|
||||||
|
<filename>/var/lib/acme/foo.example.com</filename>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Refer to <xref linkend="ch-options" /> for all available
|
||||||
|
configuration options for the
|
||||||
|
<link linkend="opt-security.acme.certs">security.acme</link>
|
||||||
|
module.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-security-acme-config-dns">
|
||||||
|
<title>Configuring ACME for DNS validation</title>
|
||||||
|
<para>
|
||||||
|
This is useful if you want to generate a wildcard certificate,
|
||||||
|
since ACME servers will only hand out wildcard certs over DNS
|
||||||
|
validation. There are a number of supported DNS providers and
|
||||||
|
servers you can utilise, see the
|
||||||
|
<link xlink:href="https://go-acme.github.io/lego/dns/">lego
|
||||||
|
docs</link> for provider/server specific configuration values. For
|
||||||
|
the sake of these docs, we will provide a fully self-hosted
|
||||||
|
example using bind.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
services.bind = {
|
||||||
|
enable = true;
|
||||||
|
extraConfig = ''
|
||||||
|
include "/var/lib/secrets/dnskeys.conf";
|
||||||
|
'';
|
||||||
|
zones = [
|
||||||
|
rec {
|
||||||
|
name = "example.com";
|
||||||
|
file = "/var/db/bind/${name}";
|
||||||
|
master = true;
|
||||||
|
extraConfig = "allow-update { key rfc2136key.example.com.; };";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
# Now we can configure ACME
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@example.com";
|
||||||
|
security.acme.certs."example.com" = {
|
||||||
|
domain = "*.example.com";
|
||||||
|
dnsProvider = "rfc2136";
|
||||||
|
credentialsFile = "/var/lib/secrets/certs.secret";
|
||||||
|
# We don't need to wait for propagation since this is a local DNS server
|
||||||
|
dnsPropagationCheck = false;
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
The <filename>dnskeys.conf</filename> and
|
||||||
|
<filename>certs.secret</filename> must be kept secure and thus you
|
||||||
|
should not keep their contents in your Nix config. Instead,
|
||||||
|
generate them one time with a systemd service:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
systemd.services.dns-rfc2136-conf = {
|
||||||
|
requiredBy = ["acme-example.com.service" "bind.service"];
|
||||||
|
before = ["acme-example.com.service" "bind.service"];
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!/var/lib/secrets/dnskeys.conf";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
UMask = 0077;
|
||||||
|
};
|
||||||
|
path = [ pkgs.bind ];
|
||||||
|
script = ''
|
||||||
|
mkdir -p /var/lib/secrets
|
||||||
|
chmod 755 /var/lib/secrets
|
||||||
|
tsig-keygen rfc2136key.example.com > /var/lib/secrets/dnskeys.conf
|
||||||
|
chown named:root /var/lib/secrets/dnskeys.conf
|
||||||
|
chmod 400 /var/lib/secrets/dnskeys.conf
|
||||||
|
|
||||||
|
# extract secret value from the dnskeys.conf
|
||||||
|
while read x y; do if [ "$x" = "secret" ]; then secret="''${y:1:''${#y}-3}"; fi; done < /var/lib/secrets/dnskeys.conf
|
||||||
|
|
||||||
|
cat > /var/lib/secrets/certs.secret << EOF
|
||||||
|
RFC2136_NAMESERVER='127.0.0.1:53'
|
||||||
|
RFC2136_TSIG_ALGORITHM='hmac-sha256.'
|
||||||
|
RFC2136_TSIG_KEY='rfc2136key.example.com'
|
||||||
|
RFC2136_TSIG_SECRET='$secret'
|
||||||
|
EOF
|
||||||
|
chmod 400 /var/lib/secrets/certs.secret
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Now you’re all set to generate certs! You should monitor the first
|
||||||
|
invocation by running
|
||||||
|
<literal>systemctl start acme-example.com.service & journalctl -fu acme-example.com.service</literal>
|
||||||
|
and watching its log output.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-security-acme-config-dns-with-vhosts">
|
||||||
|
<title>Using DNS validation with web server virtual hosts</title>
|
||||||
|
<para>
|
||||||
|
It is possible to use DNS-01 validation with all certificates,
|
||||||
|
including those automatically configured via the Nginx/Apache
|
||||||
|
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME"><literal>enableACME</literal></link>
|
||||||
|
option. This configuration pattern is fully supported and part of
|
||||||
|
the module’s test suite for Nginx + Apache.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
You must follow the guide above on configuring DNS-01 validation
|
||||||
|
first, however instead of setting the options for one certificate
|
||||||
|
(e.g.
|
||||||
|
<xref linkend="opt-security.acme.certs._name_.dnsProvider" />) you
|
||||||
|
will set them as defaults (e.g.
|
||||||
|
<xref linkend="opt-security.acme.defaults.dnsProvider" />).
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
# Configure ACME appropriately
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@example.com";
|
||||||
|
security.acme.defaults = {
|
||||||
|
dnsProvider = "rfc2136";
|
||||||
|
credentialsFile = "/var/lib/secrets/certs.secret";
|
||||||
|
# We don't need to wait for propagation since this is a local DNS server
|
||||||
|
dnsPropagationCheck = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# For each virtual host you would like to use DNS-01 validation with,
|
||||||
|
# set acmeRoot = null
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"foo.example.com" = {
|
||||||
|
enableACME = true;
|
||||||
|
acmeRoot = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
And that’s it! Next time your configuration is rebuilt, or when
|
||||||
|
you add a new virtualHost, it will be DNS-01 validated.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-security-acme-root-owned">
|
||||||
|
<title>Using ACME with services demanding root owned
|
||||||
|
certificates</title>
|
||||||
|
<para>
|
||||||
|
Some services refuse to start if the configured certificate files
|
||||||
|
are not owned by root. PostgreSQL and OpenSMTPD are examples of
|
||||||
|
these. There is no way to change the user the ACME module uses (it
|
||||||
|
will always be <literal>acme</literal>), however you can use
|
||||||
|
systemd’s <literal>LoadCredential</literal> feature to resolve
|
||||||
|
this elegantly. Below is an example configuration for OpenSMTPD,
|
||||||
|
but this pattern can be applied to any service.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
# Configure ACME however you like (DNS or HTTP validation), adding
|
||||||
|
# the following configuration for the relevant certificate.
|
||||||
|
# Note: You cannot use `systemctl reload` here as that would mean
|
||||||
|
# the LoadCredential configuration below would be skipped and
|
||||||
|
# the service would continue to use old certificates.
|
||||||
|
security.acme.certs."mail.example.com".postRun = ''
|
||||||
|
systemctl restart opensmtpd
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Now you must augment OpenSMTPD's systemd service to load
|
||||||
|
# the certificate files.
|
||||||
|
systemd.services.opensmtpd.requires = ["acme-finished-mail.example.com.target"];
|
||||||
|
systemd.services.opensmtpd.serviceConfig.LoadCredential = let
|
||||||
|
certDir = config.security.acme.certs."mail.example.com".directory;
|
||||||
|
in [
|
||||||
|
"cert.pem:${certDir}/cert.pem"
|
||||||
|
"key.pem:${certDir}/key.pem"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Finally, configure OpenSMTPD to use these certs.
|
||||||
|
services.opensmtpd = let
|
||||||
|
credsDir = "/run/credentials/opensmtpd.service";
|
||||||
|
in {
|
||||||
|
enable = true;
|
||||||
|
setSendmail = false;
|
||||||
|
serverConfiguration = ''
|
||||||
|
pki mail.example.com cert "${credsDir}/cert.pem"
|
||||||
|
pki mail.example.com key "${credsDir}/key.pem"
|
||||||
|
listen on localhost tls pki mail.example.com
|
||||||
|
action act1 relay host smtp://127.0.0.1:10027
|
||||||
|
match for local action act1
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-security-acme-regenerate">
|
||||||
|
<title>Regenerating certificates</title>
|
||||||
|
<para>
|
||||||
|
Should you need to regenerate a particular certificate in a hurry,
|
||||||
|
such as when a vulnerability is found in Let’s Encrypt, there is
|
||||||
|
now a convenient mechanism for doing so. Running
|
||||||
|
<literal>systemctl clean --what=state acme-example.com.service</literal>
|
||||||
|
will remove all certificate files and the account data for the
|
||||||
|
given domain, allowing you to then
|
||||||
|
<literal>systemctl start acme-example.com.service</literal> to
|
||||||
|
generate fresh ones.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-security-acme-fix-jws">
|
||||||
|
<title>Fixing JWS Verification error</title>
|
||||||
|
<para>
|
||||||
|
It is possible that your account credentials file may become
|
||||||
|
corrupt and need to be regenerated. In this scenario lego will
|
||||||
|
produce the error <literal>JWS verification error</literal>. The
|
||||||
|
solution is to simply delete the associated accounts file and
|
||||||
|
re-run the affected service(s).
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
# Find the accounts folder for the certificate
|
||||||
|
systemctl cat acme-example.com.service | grep -Po 'accounts/[^:]*'
|
||||||
|
export accountdir="$(!!)"
|
||||||
|
# Move this folder to some place else
|
||||||
|
mv /var/lib/acme/.lego/$accountdir{,.bak}
|
||||||
|
# Recreate the folder using systemd-tmpfiles
|
||||||
|
systemd-tmpfiles --create
|
||||||
|
# Get a new account and reissue certificates
|
||||||
|
# Note: Do this for all certs that share the same account email address
|
||||||
|
systemctl start acme-example.com.service
|
||||||
|
</programlisting>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
|
@ -1,414 +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="module-security-acme">
|
|
||||||
<title>SSL/TLS Certificates with ACME</title>
|
|
||||||
<para>
|
|
||||||
NixOS supports automatic domain validation & certificate retrieval and
|
|
||||||
renewal using the ACME protocol. Any provider can be used, but by default
|
|
||||||
NixOS uses Let's Encrypt. The alternative ACME client
|
|
||||||
<link xlink:href="https://go-acme.github.io/lego/">lego</link> is used under
|
|
||||||
the hood.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Automatic cert validation and configuration for Apache and Nginx virtual
|
|
||||||
hosts is included in NixOS, however if you would like to generate a wildcard
|
|
||||||
cert or you are not using a web server you will have to configure DNS
|
|
||||||
based validation.
|
|
||||||
</para>
|
|
||||||
<section xml:id="module-security-acme-prerequisites">
|
|
||||||
<title>Prerequisites</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To use the ACME module, you must accept the provider's terms of service
|
|
||||||
by setting <literal><xref linkend="opt-security.acme.acceptTerms" /></literal>
|
|
||||||
to <literal>true</literal>. The Let's Encrypt ToS can be found
|
|
||||||
<link xlink:href="https://letsencrypt.org/repository/">here</link>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You must also set an email address to be used when creating accounts with
|
|
||||||
Let's Encrypt. You can set this for all certs with
|
|
||||||
<literal><xref linkend="opt-security.acme.defaults.email" /></literal>
|
|
||||||
and/or on a per-cert basis with
|
|
||||||
<literal><xref linkend="opt-security.acme.certs._name_.email" /></literal>.
|
|
||||||
This address is only used for registration and renewal reminders,
|
|
||||||
and cannot be used to administer the certificates in any way.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Alternatively, you can use a different ACME server by changing the
|
|
||||||
<literal><xref linkend="opt-security.acme.defaults.server" /></literal> option
|
|
||||||
to a provider of your choosing, or just change the server for one cert with
|
|
||||||
<literal><xref linkend="opt-security.acme.certs._name_.server" /></literal>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You will need an HTTP server or DNS server for verification. For HTTP,
|
|
||||||
the server must have a webroot defined that can serve
|
|
||||||
<filename>.well-known/acme-challenge</filename>. This directory must be
|
|
||||||
writeable by the user that will run the ACME client. For DNS, you must
|
|
||||||
set up credentials with your provider/server for use with lego.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-security-acme-nginx">
|
|
||||||
<title>Using ACME certificates in Nginx</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
NixOS supports fetching ACME certificates for you by setting
|
|
||||||
<literal><link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link>
|
|
||||||
= true;</literal> in a virtualHost config. We first create self-signed
|
|
||||||
placeholder certificates in place of the real ACME certs. The placeholder
|
|
||||||
certs are overwritten when the ACME certs arrive. For
|
|
||||||
<literal>foo.example.com</literal> the config would look like this:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-security.acme.acceptTerms" /> = true;
|
|
||||||
<xref linkend="opt-security.acme.defaults.email" /> = "admin+acme@example.com";
|
|
||||||
services.nginx = {
|
|
||||||
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
|
|
||||||
"foo.example.com" = {
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
|
||||||
# All serverAliases will be added as <link linkend="opt-security.acme.certs._name_.extraDomainNames">extra domain names</link> on the certificate.
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.serverAliases">serverAliases</link> = [ "bar.example.com" ];
|
|
||||||
locations."/" = {
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.root">root</link> = "/var/www";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# We can also add a different vhost and reuse the same certificate
|
|
||||||
# but we have to append extraDomainNames manually beforehand:
|
|
||||||
# <link linkend="opt-security.acme.certs._name_.extraDomainNames">security.acme.certs."foo.example.com".extraDomainNames</link> = [ "baz.example.com" ];
|
|
||||||
"baz.example.com" = {
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">useACMEHost</link> = "foo.example.com";
|
|
||||||
locations."/" = {
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.root">root</link> = "/var/www";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-security-acme-httpd">
|
|
||||||
<title>Using ACME certificates in Apache/httpd</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Using ACME certificates with Apache virtual hosts is identical
|
|
||||||
to using them with Nginx. The attribute names are all the same, just replace
|
|
||||||
"nginx" with "httpd" where appropriate.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-security-acme-configuring">
|
|
||||||
<title>Manual configuration of HTTP-01 validation</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
First off you will need to set up a virtual host to serve the challenges.
|
|
||||||
This example uses a vhost called <literal>certs.example.com</literal>, with
|
|
||||||
the intent that you will generate certs for all your vhosts and redirect
|
|
||||||
everyone to HTTPS.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-security.acme.acceptTerms" /> = true;
|
|
||||||
<xref linkend="opt-security.acme.defaults.email" /> = "admin+acme@example.com";
|
|
||||||
|
|
||||||
# /var/lib/acme/.challenges must be writable by the ACME user
|
|
||||||
# and readable by the Nginx user. The easiest way to achieve
|
|
||||||
# this is to add the Nginx user to the ACME group.
|
|
||||||
<link linkend="opt-users.users._name_.extraGroups">users.users.nginx.extraGroups</link> = [ "acme" ];
|
|
||||||
|
|
||||||
services.nginx = {
|
|
||||||
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
|
|
||||||
"acmechallenge.example.com" = {
|
|
||||||
# Catchall vhost, will redirect users to HTTPS for all vhosts
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.serverAliases">serverAliases</link> = [ "*.example.com" ];
|
|
||||||
locations."/.well-known/acme-challenge" = {
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.root">root</link> = "/var/lib/acme/.challenges";
|
|
||||||
};
|
|
||||||
locations."/" = {
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.return">return</link> = "301 https://$host$request_uri";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# Alternative config for Apache
|
|
||||||
<link linkend="opt-users.users._name_.extraGroups">users.users.wwwrun.extraGroups</link> = [ "acme" ];
|
|
||||||
services.httpd = {
|
|
||||||
<link linkend="opt-services.httpd.enable">enable = true;</link>
|
|
||||||
<link linkend="opt-services.httpd.virtualHosts">virtualHosts</link> = {
|
|
||||||
"acmechallenge.example.com" = {
|
|
||||||
# Catchall vhost, will redirect users to HTTPS for all vhosts
|
|
||||||
<link linkend="opt-services.httpd.virtualHosts._name_.serverAliases">serverAliases</link> = [ "*.example.com" ];
|
|
||||||
# /var/lib/acme/.challenges must be writable by the ACME user and readable by the Apache user.
|
|
||||||
# By default, this is the case.
|
|
||||||
<link linkend="opt-services.httpd.virtualHosts._name_.documentRoot">documentRoot</link> = "/var/lib/acme/.challenges";
|
|
||||||
<link linkend="opt-services.httpd.virtualHosts._name_.extraConfig">extraConfig</link> = ''
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteCond %{HTTPS} off
|
|
||||||
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge [NC]
|
|
||||||
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Now you need to configure ACME to generate a certificate.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-security.acme.certs"/>."foo.example.com" = {
|
|
||||||
<link linkend="opt-security.acme.certs._name_.webroot">webroot</link> = "/var/lib/acme/.challenges";
|
|
||||||
<link linkend="opt-security.acme.certs._name_.email">email</link> = "foo@example.com";
|
|
||||||
# Ensure that the web server you use can read the generated certs
|
|
||||||
# Take a look at the <link linkend="opt-services.nginx.group">group</link> option for the web server you choose.
|
|
||||||
<link linkend="opt-security.acme.certs._name_.group">group</link> = "nginx";
|
|
||||||
# Since we have a wildcard vhost to handle port 80,
|
|
||||||
# we can generate certs for anything!
|
|
||||||
# Just make sure your DNS resolves them.
|
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomainNames">extraDomainNames</link> = [ "mail.example.com" ];
|
|
||||||
};
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The private key <filename>key.pem</filename> and certificate
|
|
||||||
<filename>fullchain.pem</filename> will be put into
|
|
||||||
<filename>/var/lib/acme/foo.example.com</filename>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Refer to <xref linkend="ch-options" /> for all available configuration
|
|
||||||
options for the <link linkend="opt-security.acme.certs">security.acme</link>
|
|
||||||
module.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-security-acme-config-dns">
|
|
||||||
<title>Configuring ACME for DNS validation</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This is useful if you want to generate a wildcard certificate, since
|
|
||||||
ACME servers will only hand out wildcard certs over DNS validation.
|
|
||||||
There are a number of supported DNS providers and servers you can utilise,
|
|
||||||
see the <link xlink:href="https://go-acme.github.io/lego/dns/">lego docs</link>
|
|
||||||
for provider/server specific configuration values. For the sake of these
|
|
||||||
docs, we will provide a fully self-hosted example using bind.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
services.bind = {
|
|
||||||
<link linkend="opt-services.bind.enable">enable</link> = true;
|
|
||||||
<link linkend="opt-services.bind.extraConfig">extraConfig</link> = ''
|
|
||||||
include "/var/lib/secrets/dnskeys.conf";
|
|
||||||
'';
|
|
||||||
<link linkend="opt-services.bind.zones">zones</link> = [
|
|
||||||
rec {
|
|
||||||
name = "example.com";
|
|
||||||
file = "/var/db/bind/${name}";
|
|
||||||
master = true;
|
|
||||||
extraConfig = "allow-update { key rfc2136key.example.com.; };";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
# Now we can configure ACME
|
|
||||||
<xref linkend="opt-security.acme.acceptTerms" /> = true;
|
|
||||||
<xref linkend="opt-security.acme.defaults.email" /> = "admin+acme@example.com";
|
|
||||||
<xref linkend="opt-security.acme.certs" />."example.com" = {
|
|
||||||
<link linkend="opt-security.acme.certs._name_.domain">domain</link> = "*.example.com";
|
|
||||||
<link linkend="opt-security.acme.certs._name_.dnsProvider">dnsProvider</link> = "rfc2136";
|
|
||||||
<link linkend="opt-security.acme.certs._name_.credentialsFile">credentialsFile</link> = "/var/lib/secrets/certs.secret";
|
|
||||||
# We don't need to wait for propagation since this is a local DNS server
|
|
||||||
<link linkend="opt-security.acme.certs._name_.dnsPropagationCheck">dnsPropagationCheck</link> = false;
|
|
||||||
};
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The <filename>dnskeys.conf</filename> and <filename>certs.secret</filename>
|
|
||||||
must be kept secure and thus you should not keep their contents in your
|
|
||||||
Nix config. Instead, generate them one time with a systemd service:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
systemd.services.dns-rfc2136-conf = {
|
|
||||||
requiredBy = ["acme-example.com.service" "bind.service"];
|
|
||||||
before = ["acme-example.com.service" "bind.service"];
|
|
||||||
unitConfig = {
|
|
||||||
ConditionPathExists = "!/var/lib/secrets/dnskeys.conf";
|
|
||||||
};
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
UMask = 0077;
|
|
||||||
};
|
|
||||||
path = [ pkgs.bind ];
|
|
||||||
script = ''
|
|
||||||
mkdir -p /var/lib/secrets
|
|
||||||
chmod 755 /var/lib/secrets
|
|
||||||
tsig-keygen rfc2136key.example.com > /var/lib/secrets/dnskeys.conf
|
|
||||||
chown named:root /var/lib/secrets/dnskeys.conf
|
|
||||||
chmod 400 /var/lib/secrets/dnskeys.conf
|
|
||||||
|
|
||||||
# extract secret value from the dnskeys.conf
|
|
||||||
while read x y; do if [ "$x" = "secret" ]; then secret="''${y:1:''${#y}-3}"; fi; done < /var/lib/secrets/dnskeys.conf
|
|
||||||
|
|
||||||
cat > /var/lib/secrets/certs.secret << EOF
|
|
||||||
RFC2136_NAMESERVER='127.0.0.1:53'
|
|
||||||
RFC2136_TSIG_ALGORITHM='hmac-sha256.'
|
|
||||||
RFC2136_TSIG_KEY='rfc2136key.example.com'
|
|
||||||
RFC2136_TSIG_SECRET='$secret'
|
|
||||||
EOF
|
|
||||||
chmod 400 /var/lib/secrets/certs.secret
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Now you're all set to generate certs! You should monitor the first invocation
|
|
||||||
by running <literal>systemctl start acme-example.com.service &
|
|
||||||
journalctl -fu acme-example.com.service</literal> and watching its log output.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section xml:id="module-security-acme-config-dns-with-vhosts">
|
|
||||||
<title>Using DNS validation with web server virtual hosts</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
It is possible to use DNS-01 validation with all certificates,
|
|
||||||
including those automatically configured via the Nginx/Apache
|
|
||||||
<literal><link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link></literal>
|
|
||||||
option. This configuration pattern is fully
|
|
||||||
supported and part of the module's test suite for Nginx + Apache.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You must follow the guide above on configuring DNS-01 validation
|
|
||||||
first, however instead of setting the options for one certificate
|
|
||||||
(e.g. <xref linkend="opt-security.acme.certs._name_.dnsProvider" />)
|
|
||||||
you will set them as defaults
|
|
||||||
(e.g. <xref linkend="opt-security.acme.defaults.dnsProvider" />).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
# Configure ACME appropriately
|
|
||||||
<xref linkend="opt-security.acme.acceptTerms" /> = true;
|
|
||||||
<xref linkend="opt-security.acme.defaults.email" /> = "admin+acme@example.com";
|
|
||||||
<xref linkend="opt-security.acme.defaults" /> = {
|
|
||||||
<link linkend="opt-security.acme.defaults.dnsProvider">dnsProvider</link> = "rfc2136";
|
|
||||||
<link linkend="opt-security.acme.defaults.credentialsFile">credentialsFile</link> = "/var/lib/secrets/certs.secret";
|
|
||||||
# We don't need to wait for propagation since this is a local DNS server
|
|
||||||
<link linkend="opt-security.acme.defaults.dnsPropagationCheck">dnsPropagationCheck</link> = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
# For each virtual host you would like to use DNS-01 validation with,
|
|
||||||
# set acmeRoot = null
|
|
||||||
services.nginx = {
|
|
||||||
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
|
|
||||||
"foo.example.com" = {
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.acmeRoot">acmeRoot</link> = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
And that's it! Next time your configuration is rebuilt, or when
|
|
||||||
you add a new virtualHost, it will be DNS-01 validated.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section xml:id="module-security-acme-root-owned">
|
|
||||||
<title>Using ACME with services demanding root owned certificates</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Some services refuse to start if the configured certificate files
|
|
||||||
are not owned by root. PostgreSQL and OpenSMTPD are examples of these.
|
|
||||||
There is no way to change the user the ACME module uses (it will always be
|
|
||||||
<literal>acme</literal>), however you can use systemd's
|
|
||||||
<literal>LoadCredential</literal> feature to resolve this elegantly.
|
|
||||||
Below is an example configuration for OpenSMTPD, but this pattern
|
|
||||||
can be applied to any service.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
# Configure ACME however you like (DNS or HTTP validation), adding
|
|
||||||
# the following configuration for the relevant certificate.
|
|
||||||
# Note: You cannot use `systemctl reload` here as that would mean
|
|
||||||
# the LoadCredential configuration below would be skipped and
|
|
||||||
# the service would continue to use old certificates.
|
|
||||||
security.acme.certs."mail.example.com".postRun = ''
|
|
||||||
systemctl restart opensmtpd
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Now you must augment OpenSMTPD's systemd service to load
|
|
||||||
# the certificate files.
|
|
||||||
<link linkend="opt-systemd.services._name_.requires">systemd.services.opensmtpd.requires</link> = ["acme-finished-mail.example.com.target"];
|
|
||||||
<link linkend="opt-systemd.services._name_.serviceConfig">systemd.services.opensmtpd.serviceConfig.LoadCredential</link> = let
|
|
||||||
certDir = config.security.acme.certs."mail.example.com".directory;
|
|
||||||
in [
|
|
||||||
"cert.pem:${certDir}/cert.pem"
|
|
||||||
"key.pem:${certDir}/key.pem"
|
|
||||||
];
|
|
||||||
|
|
||||||
# Finally, configure OpenSMTPD to use these certs.
|
|
||||||
services.opensmtpd = let
|
|
||||||
credsDir = "/run/credentials/opensmtpd.service";
|
|
||||||
in {
|
|
||||||
enable = true;
|
|
||||||
setSendmail = false;
|
|
||||||
serverConfiguration = ''
|
|
||||||
pki mail.example.com cert "${credsDir}/cert.pem"
|
|
||||||
pki mail.example.com key "${credsDir}/key.pem"
|
|
||||||
listen on localhost tls pki mail.example.com
|
|
||||||
action act1 relay host smtp://127.0.0.1:10027
|
|
||||||
match for local action act1
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
</programlisting>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section xml:id="module-security-acme-regenerate">
|
|
||||||
<title>Regenerating certificates</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Should you need to regenerate a particular certificate in a hurry, such
|
|
||||||
as when a vulnerability is found in Let's Encrypt, there is now a convenient
|
|
||||||
mechanism for doing so. Running
|
|
||||||
<literal>systemctl clean --what=state acme-example.com.service</literal>
|
|
||||||
will remove all certificate files and the account data for the given domain,
|
|
||||||
allowing you to then <literal>systemctl start acme-example.com.service</literal>
|
|
||||||
to generate fresh ones.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-security-acme-fix-jws">
|
|
||||||
<title>Fixing JWS Verification error</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
It is possible that your account credentials file may become corrupt and need
|
|
||||||
to be regenerated. In this scenario lego will produce the error <literal>JWS verification error</literal>.
|
|
||||||
The solution is to simply delete the associated accounts file and
|
|
||||||
re-run the affected service(s).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
# Find the accounts folder for the certificate
|
|
||||||
systemctl cat acme-example.com.service | grep -Po 'accounts/[^:]*'
|
|
||||||
export accountdir="$(!!)"
|
|
||||||
# Move this folder to some place else
|
|
||||||
mv /var/lib/acme/.lego/$accountdir{,.bak}
|
|
||||||
# Recreate the folder using systemd-tmpfiles
|
|
||||||
systemd-tmpfiles --create
|
|
||||||
# Get a new account and reissue certificates
|
|
||||||
# Note: Do this for all certs that share the same account email address
|
|
||||||
systemctl start acme-example.com.service
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
163
nixos/modules/services/backup/borgbackup.md
Normal file
163
nixos/modules/services/backup/borgbackup.md
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
# BorgBackup {#module-borgbase}
|
||||||
|
|
||||||
|
*Source:* {file}`modules/services/backup/borgbackup.nix`
|
||||||
|
|
||||||
|
*Upstream documentation:* <https://borgbackup.readthedocs.io/>
|
||||||
|
|
||||||
|
[BorgBackup](https://www.borgbackup.org/) (short: Borg)
|
||||||
|
is a deduplicating backup program. Optionally, it supports compression and
|
||||||
|
authenticated encryption.
|
||||||
|
|
||||||
|
The main goal of Borg is to provide an efficient and secure way to backup
|
||||||
|
data. The data deduplication technique used makes Borg suitable for daily
|
||||||
|
backups since only changes are stored. The authenticated encryption technique
|
||||||
|
makes it suitable for backups to not fully trusted targets.
|
||||||
|
|
||||||
|
## Configuring {#module-services-backup-borgbackup-configuring}
|
||||||
|
|
||||||
|
A complete list of options for the Borgbase module may be found
|
||||||
|
[here](#opt-services.borgbackup.jobs).
|
||||||
|
|
||||||
|
## Basic usage for a local backup {#opt-services-backup-borgbackup-local-directory}
|
||||||
|
|
||||||
|
A very basic configuration for backing up to a locally accessible directory is:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
opt.services.borgbackup.jobs = {
|
||||||
|
{ rootBackup = {
|
||||||
|
paths = "/";
|
||||||
|
exclude = [ "/nix" "/path/to/local/repo" ];
|
||||||
|
repo = "/path/to/local/repo";
|
||||||
|
doInit = true;
|
||||||
|
encryption = {
|
||||||
|
mode = "repokey";
|
||||||
|
passphrase = "secret";
|
||||||
|
};
|
||||||
|
compression = "auto,lzma";
|
||||||
|
startAt = "weekly";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
If you do not want the passphrase to be stored in the world-readable
|
||||||
|
Nix store, use passCommand. You find an example below.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Create a borg backup server {#opt-services-backup-create-server}
|
||||||
|
|
||||||
|
You should use a different SSH key for each repository you write to,
|
||||||
|
because the specified keys are restricted to running borg serve and can only
|
||||||
|
access this single repository. You need the output of the generate pub file.
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
# sudo ssh-keygen -N '' -t ed25519 -f /run/keys/id_ed25519_my_borg_repo
|
||||||
|
# cat /run/keys/id_ed25519_my_borg_repo
|
||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID78zmOyA+5uPG4Ot0hfAy+sLDPU1L4AiIoRYEIVbbQ/ root@nixos
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the following snippet to your NixOS configuration:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.borgbackup.repos = {
|
||||||
|
my_borg_repo = {
|
||||||
|
authorizedKeys = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID78zmOyA+5uPG4Ot0hfAy+sLDPU1L4AiIoRYEIVbbQ/ root@nixos"
|
||||||
|
] ;
|
||||||
|
path = "/var/lib/my_borg_repo" ;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backup to the borg repository server {#opt-services-backup-borgbackup-remote-server}
|
||||||
|
|
||||||
|
The following NixOS snippet creates an hourly backup to the service
|
||||||
|
(on the host nixos) as created in the section above. We assume
|
||||||
|
that you have stored a secret passphrasse in the file
|
||||||
|
{file}`/run/keys/borgbackup_passphrase`, which should be only
|
||||||
|
accessible by root
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.borgbackup.jobs = {
|
||||||
|
backupToLocalServer = {
|
||||||
|
paths = [ "/etc/nixos" ];
|
||||||
|
doInit = true;
|
||||||
|
repo = "borg@nixos:." ;
|
||||||
|
encryption = {
|
||||||
|
mode = "repokey-blake2";
|
||||||
|
passCommand = "cat /run/keys/borgbackup_passphrase";
|
||||||
|
};
|
||||||
|
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_my_borg_repo"; };
|
||||||
|
compression = "auto,lzma";
|
||||||
|
startAt = "hourly";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The following few commands (run as root) let you test your backup.
|
||||||
|
```
|
||||||
|
> nixos-rebuild switch
|
||||||
|
...restarting the following units: polkit.service
|
||||||
|
> systemctl restart borgbackup-job-backupToLocalServer
|
||||||
|
> sleep 10
|
||||||
|
> systemctl restart borgbackup-job-backupToLocalServer
|
||||||
|
> export BORG_PASSPHRASE=topSecrect
|
||||||
|
> borg list --rsh='ssh -i /run/keys/id_ed25519_my_borg_repo' borg@nixos:.
|
||||||
|
nixos-backupToLocalServer-2020-03-30T21:46:17 Mon, 2020-03-30 21:46:19 [84feb97710954931ca384182f5f3cb90665f35cef214760abd7350fb064786ac]
|
||||||
|
nixos-backupToLocalServer-2020-03-30T21:46:30 Mon, 2020-03-30 21:46:32 [e77321694ecd160ca2228611747c6ad1be177d6e0d894538898de7a2621b6e68]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backup to a hosting service {#opt-services-backup-borgbackup-borgbase}
|
||||||
|
|
||||||
|
Several companies offer [(paid) hosting services](https://www.borgbackup.org/support/commercial.html)
|
||||||
|
for Borg repositories.
|
||||||
|
|
||||||
|
To backup your home directory to borgbase you have to:
|
||||||
|
|
||||||
|
- Generate a SSH key without a password, to access the remote server. E.g.
|
||||||
|
|
||||||
|
sudo ssh-keygen -N '' -t ed25519 -f /run/keys/id_ed25519_borgbase
|
||||||
|
|
||||||
|
- Create the repository on the server by following the instructions for your
|
||||||
|
hosting server.
|
||||||
|
- Initialize the repository on the server. Eg.
|
||||||
|
|
||||||
|
sudo borg init --encryption=repokey-blake2 \
|
||||||
|
-rsh "ssh -i /run/keys/id_ed25519_borgbase" \
|
||||||
|
zzz2aaaaa@zzz2aaaaa.repo.borgbase.com:repo
|
||||||
|
|
||||||
|
- Add it to your NixOS configuration, e.g.
|
||||||
|
|
||||||
|
{
|
||||||
|
services.borgbackup.jobs = {
|
||||||
|
my_Remote_Backup = {
|
||||||
|
paths = [ "/" ];
|
||||||
|
exclude = [ "/nix" "'**/.cache'" ];
|
||||||
|
repo = "zzz2aaaaa@zzz2aaaaa.repo.borgbase.com:repo";
|
||||||
|
encryption = {
|
||||||
|
mode = "repokey-blake2";
|
||||||
|
passCommand = "cat /run/keys/borgbackup_passphrase";
|
||||||
|
};
|
||||||
|
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase"; };
|
||||||
|
compression = "auto,lzma";
|
||||||
|
startAt = "daily";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
|
||||||
|
## Vorta backup client for the desktop {#opt-services-backup-borgbackup-vorta}
|
||||||
|
|
||||||
|
Vorta is a backup client for macOS and Linux desktops. It integrates the
|
||||||
|
mighty BorgBackup with your desktop environment to protect your data from
|
||||||
|
disk failure, ransomware and theft.
|
||||||
|
|
||||||
|
It can be installed in NixOS e.g. by adding `pkgs.vorta`
|
||||||
|
to [](#opt-environment.systemPackages).
|
||||||
|
|
||||||
|
Details about using Vorta can be found under
|
||||||
|
[https://vorta.borgbase.com](https://vorta.borgbase.com/usage) .
|
|
@ -1,8 +1,6 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-borgbase">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-borgbase">
|
|
||||||
<title>BorgBackup</title>
|
<title>BorgBackup</title>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Source:</emphasis>
|
<emphasis>Source:</emphasis>
|
||||||
|
@ -10,18 +8,19 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Upstream documentation:</emphasis>
|
<emphasis>Upstream documentation:</emphasis>
|
||||||
<link xlink:href="https://borgbackup.readthedocs.io/"/>
|
<link xlink:href="https://borgbackup.readthedocs.io/">https://borgbackup.readthedocs.io/</link>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://www.borgbackup.org/">BorgBackup</link> (short: Borg)
|
<link xlink:href="https://www.borgbackup.org/">BorgBackup</link>
|
||||||
is a deduplicating backup program. Optionally, it supports compression and
|
(short: Borg) is a deduplicating backup program. Optionally, it
|
||||||
authenticated encryption.
|
supports compression and authenticated encryption.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The main goal of Borg is to provide an efficient and secure way to backup
|
The main goal of Borg is to provide an efficient and secure way to
|
||||||
data. The data deduplication technique used makes Borg suitable for daily
|
backup data. The data deduplication technique used makes Borg
|
||||||
backups since only changes are stored. The authenticated encryption technique
|
suitable for daily backups since only changes are stored. The
|
||||||
makes it suitable for backups to not fully trusted targets.
|
authenticated encryption technique makes it suitable for backups to
|
||||||
|
not fully trusted targets.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-backup-borgbackup-configuring">
|
<section xml:id="module-services-backup-borgbackup-configuring">
|
||||||
<title>Configuring</title>
|
<title>Configuring</title>
|
||||||
|
@ -32,111 +31,113 @@
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="opt-services-backup-borgbackup-local-directory">
|
<section xml:id="opt-services-backup-borgbackup-local-directory">
|
||||||
<title>Basic usage for a local backup</title>
|
<title>Basic usage for a local backup</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A very basic configuration for backing up to a locally accessible directory
|
A very basic configuration for backing up to a locally accessible
|
||||||
is:
|
directory is:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
opt.services.borgbackup.jobs = {
|
opt.services.borgbackup.jobs = {
|
||||||
{ rootBackup = {
|
{ rootBackup = {
|
||||||
paths = "/";
|
paths = "/";
|
||||||
exclude = [ "/nix" "/path/to/local/repo" ];
|
exclude = [ "/nix" "/path/to/local/repo" ];
|
||||||
repo = "/path/to/local/repo";
|
repo = "/path/to/local/repo";
|
||||||
doInit = true;
|
doInit = true;
|
||||||
encryption = {
|
encryption = {
|
||||||
mode = "repokey";
|
mode = "repokey";
|
||||||
passphrase = "secret";
|
passphrase = "secret";
|
||||||
};
|
};
|
||||||
compression = "auto,lzma";
|
compression = "auto,lzma";
|
||||||
startAt = "weekly";
|
startAt = "weekly";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
<warning>
|
<warning>
|
||||||
<para>
|
<para>
|
||||||
If you do not want the passphrase to be stored in the world-readable
|
If you do not want the passphrase to be stored in the
|
||||||
Nix store, use passCommand. You find an example below.
|
world-readable Nix store, use passCommand. You find an example
|
||||||
|
below.
|
||||||
</para>
|
</para>
|
||||||
</warning>
|
</warning>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="opt-services-backup-create-server">
|
<section xml:id="opt-services-backup-create-server">
|
||||||
<title>Create a borg backup server</title>
|
<title>Create a borg backup server</title>
|
||||||
<para>You should use a different SSH key for each repository you write to,
|
|
||||||
because the specified keys are restricted to running borg serve and can only
|
|
||||||
access this single repository. You need the output of the generate pub file.
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
<screen>
|
You should use a different SSH key for each repository you write
|
||||||
<prompt># </prompt>sudo ssh-keygen -N '' -t ed25519 -f /run/keys/id_ed25519_my_borg_repo
|
to, because the specified keys are restricted to running borg
|
||||||
<prompt># </prompt>cat /run/keys/id_ed25519_my_borg_repo
|
serve and can only access this single repository. You need the
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID78zmOyA+5uPG4Ot0hfAy+sLDPU1L4AiIoRYEIVbbQ/ root@nixos</screen>
|
output of the generate pub file.
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
# sudo ssh-keygen -N '' -t ed25519 -f /run/keys/id_ed25519_my_borg_repo
|
||||||
|
# cat /run/keys/id_ed25519_my_borg_repo
|
||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID78zmOyA+5uPG4Ot0hfAy+sLDPU1L4AiIoRYEIVbbQ/ root@nixos
|
||||||
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Add the following snippet to your NixOS configuration:
|
Add the following snippet to your NixOS configuration:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
services.borgbackup.repos = {
|
services.borgbackup.repos = {
|
||||||
my_borg_repo = {
|
my_borg_repo = {
|
||||||
authorizedKeys = [
|
authorizedKeys = [
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID78zmOyA+5uPG4Ot0hfAy+sLDPU1L4AiIoRYEIVbbQ/ root@nixos"
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID78zmOyA+5uPG4Ot0hfAy+sLDPU1L4AiIoRYEIVbbQ/ root@nixos"
|
||||||
] ;
|
] ;
|
||||||
path = "/var/lib/my_borg_repo" ;
|
path = "/var/lib/my_borg_repo" ;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="opt-services-backup-borgbackup-remote-server">
|
<section xml:id="opt-services-backup-borgbackup-remote-server">
|
||||||
<title>Backup to the borg repository server</title>
|
<title>Backup to the borg repository server</title>
|
||||||
<para>The following NixOS snippet creates an hourly backup to the service
|
|
||||||
(on the host nixos) as created in the section above. We assume
|
|
||||||
that you have stored a secret passphrasse in the file
|
|
||||||
<code>/run/keys/borgbackup_passphrase</code>, which should be only
|
|
||||||
accessible by root
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
|
The following NixOS snippet creates an hourly backup to the
|
||||||
|
service (on the host nixos) as created in the section above. We
|
||||||
|
assume that you have stored a secret passphrasse in the file
|
||||||
|
<filename>/run/keys/borgbackup_passphrase</filename>, which should
|
||||||
|
be only accessible by root
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
services.borgbackup.jobs = {
|
services.borgbackup.jobs = {
|
||||||
backupToLocalServer = {
|
backupToLocalServer = {
|
||||||
paths = [ "/etc/nixos" ];
|
paths = [ "/etc/nixos" ];
|
||||||
doInit = true;
|
doInit = true;
|
||||||
repo = "borg@nixos:." ;
|
repo = "borg@nixos:." ;
|
||||||
encryption = {
|
encryption = {
|
||||||
mode = "repokey-blake2";
|
mode = "repokey-blake2";
|
||||||
passCommand = "cat /run/keys/borgbackup_passphrase";
|
passCommand = "cat /run/keys/borgbackup_passphrase";
|
||||||
};
|
};
|
||||||
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_my_borg_repo"; };
|
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_my_borg_repo"; };
|
||||||
compression = "auto,lzma";
|
compression = "auto,lzma";
|
||||||
startAt = "hourly";
|
startAt = "hourly";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};</programlisting>
|
};
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
The following few commands (run as root) let you test your backup.
|
||||||
</para>
|
</para>
|
||||||
<para>The following few commands (run as root) let you test your backup.
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
> nixos-rebuild switch
|
> nixos-rebuild switch
|
||||||
...restarting the following units: polkit.service
|
...restarting the following units: polkit.service
|
||||||
> systemctl restart borgbackup-job-backupToLocalServer
|
> systemctl restart borgbackup-job-backupToLocalServer
|
||||||
> sleep 10
|
> sleep 10
|
||||||
> systemctl restart borgbackup-job-backupToLocalServer
|
> systemctl restart borgbackup-job-backupToLocalServer
|
||||||
> export BORG_PASSPHRASE=topSecrect
|
> export BORG_PASSPHRASE=topSecrect
|
||||||
> borg list --rsh='ssh -i /run/keys/id_ed25519_my_borg_repo' borg@nixos:.
|
> borg list --rsh='ssh -i /run/keys/id_ed25519_my_borg_repo' borg@nixos:.
|
||||||
nixos-backupToLocalServer-2020-03-30T21:46:17 Mon, 2020-03-30 21:46:19 [84feb97710954931ca384182f5f3cb90665f35cef214760abd7350fb064786ac]
|
nixos-backupToLocalServer-2020-03-30T21:46:17 Mon, 2020-03-30 21:46:19 [84feb97710954931ca384182f5f3cb90665f35cef214760abd7350fb064786ac]
|
||||||
nixos-backupToLocalServer-2020-03-30T21:46:30 Mon, 2020-03-30 21:46:32 [e77321694ecd160ca2228611747c6ad1be177d6e0d894538898de7a2621b6e68]</programlisting>
|
nixos-backupToLocalServer-2020-03-30T21:46:30 Mon, 2020-03-30 21:46:32 [e77321694ecd160ca2228611747c6ad1be177d6e0d894538898de7a2621b6e68]
|
||||||
</para>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="opt-services-backup-borgbackup-borgbase">
|
<section xml:id="opt-services-backup-borgbackup-borgbase">
|
||||||
<title>Backup to a hosting service</title>
|
<title>Backup to a hosting service</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Several companies offer <link
|
Several companies offer
|
||||||
xlink:href="https://www.borgbackup.org/support/commercial.html">(paid)
|
<link xlink:href="https://www.borgbackup.org/support/commercial.html">(paid)
|
||||||
hosting services</link> for Borg repositories.
|
hosting services</link> for Borg repositories.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
|
@ -145,65 +146,70 @@ nixos-backupToLocalServer-2020-03-30T21:46:30 Mon, 2020-03-30 21:46:32 [e7732169
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Generate a SSH key without a password, to access the remote server. E.g.
|
Generate a SSH key without a password, to access the remote
|
||||||
</para>
|
server. E.g.
|
||||||
<para>
|
|
||||||
<programlisting>sudo ssh-keygen -N '' -t ed25519 -f /run/keys/id_ed25519_borgbase</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
sudo ssh-keygen -N '' -t ed25519 -f /run/keys/id_ed25519_borgbase
|
||||||
|
</programlisting>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Create the repository on the server by following the instructions for your
|
Create the repository on the server by following the
|
||||||
hosting server.
|
instructions for your hosting server.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Initialize the repository on the server. Eg.
|
Initialize the repository on the server. Eg.
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
sudo borg init --encryption=repokey-blake2 \
|
sudo borg init --encryption=repokey-blake2 \
|
||||||
-rsh "ssh -i /run/keys/id_ed25519_borgbase" \
|
-rsh "ssh -i /run/keys/id_ed25519_borgbase" \
|
||||||
zzz2aaaaa@zzz2aaaaa.repo.borgbase.com:repo</programlisting>
|
zzz2aaaaa@zzz2aaaaa.repo.borgbase.com:repo
|
||||||
</para>
|
</programlisting>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Add it to your NixOS configuration, e.g.
|
<para>
|
||||||
|
Add it to your NixOS configuration, e.g.
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
services.borgbackup.jobs = {
|
services.borgbackup.jobs = {
|
||||||
my_Remote_Backup = {
|
my_Remote_Backup = {
|
||||||
paths = [ "/" ];
|
paths = [ "/" ];
|
||||||
exclude = [ "/nix" "'**/.cache'" ];
|
exclude = [ "/nix" "'**/.cache'" ];
|
||||||
repo = "zzz2aaaaa@zzz2aaaaa.repo.borgbase.com:repo";
|
repo = "zzz2aaaaa@zzz2aaaaa.repo.borgbase.com:repo";
|
||||||
encryption = {
|
encryption = {
|
||||||
mode = "repokey-blake2";
|
mode = "repokey-blake2";
|
||||||
passCommand = "cat /run/keys/borgbackup_passphrase";
|
passCommand = "cat /run/keys/borgbackup_passphrase";
|
||||||
};
|
};
|
||||||
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase"; };
|
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase"; };
|
||||||
compression = "auto,lzma";
|
compression = "auto,lzma";
|
||||||
startAt = "daily";
|
startAt = "daily";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}}</programlisting>
|
}}
|
||||||
</para>
|
</programlisting>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="opt-services-backup-borgbackup-vorta">
|
<section xml:id="opt-services-backup-borgbackup-vorta">
|
||||||
<title>Vorta backup client for the desktop</title>
|
<title>Vorta backup client for the desktop</title>
|
||||||
<para>
|
<para>
|
||||||
Vorta is a backup client for macOS and Linux desktops. It integrates the
|
Vorta is a backup client for macOS and Linux desktops. It
|
||||||
mighty BorgBackup with your desktop environment to protect your data from
|
integrates the mighty BorgBackup with your desktop environment to
|
||||||
disk failure, ransomware and theft.
|
protect your data from disk failure, ransomware and theft.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
It can be installed in NixOS e.g. by adding <package>pkgs.vorta</package>
|
It can be installed in NixOS e.g. by adding
|
||||||
to <xref linkend="opt-environment.systemPackages" />.
|
<literal>pkgs.vorta</literal> to
|
||||||
|
<xref linkend="opt-environment.systemPackages" />.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Details about using Vorta can be found under <link
|
Details about using Vorta can be found under
|
||||||
xlink:href="https://vorta.borgbase.com/usage">https://vorta.borgbase.com
|
<link xlink:href="https://vorta.borgbase.com/usage">https://vorta.borgbase.com</link>
|
||||||
</link>.
|
.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
309
nixos/modules/services/databases/foundationdb.md
Normal file
309
nixos/modules/services/databases/foundationdb.md
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
# FoundationDB {#module-services-foundationdb}
|
||||||
|
|
||||||
|
*Source:* {file}`modules/services/databases/foundationdb.nix`
|
||||||
|
|
||||||
|
*Upstream documentation:* <https://apple.github.io/foundationdb/>
|
||||||
|
|
||||||
|
*Maintainer:* Austin Seipp
|
||||||
|
|
||||||
|
*Available version(s):* 5.1.x, 5.2.x, 6.0.x
|
||||||
|
|
||||||
|
FoundationDB (or "FDB") is an open source, distributed, transactional
|
||||||
|
key-value store.
|
||||||
|
|
||||||
|
## Configuring and basic setup {#module-services-foundationdb-configuring}
|
||||||
|
|
||||||
|
To enable FoundationDB, add the following to your
|
||||||
|
{file}`configuration.nix`:
|
||||||
|
```
|
||||||
|
services.foundationdb.enable = true;
|
||||||
|
services.foundationdb.package = pkgs.foundationdb52; # FoundationDB 5.2.x
|
||||||
|
```
|
||||||
|
|
||||||
|
The {option}`services.foundationdb.package` option is required, and
|
||||||
|
must always be specified. Due to the fact FoundationDB network protocols and
|
||||||
|
on-disk storage formats may change between (major) versions, and upgrades
|
||||||
|
must be explicitly handled by the user, you must always manually specify
|
||||||
|
this yourself so that the NixOS module will use the proper version. Note
|
||||||
|
that minor, bugfix releases are always compatible.
|
||||||
|
|
||||||
|
After running {command}`nixos-rebuild`, you can verify whether
|
||||||
|
FoundationDB is running by executing {command}`fdbcli` (which is
|
||||||
|
added to {option}`environment.systemPackages`):
|
||||||
|
```ShellSession
|
||||||
|
$ sudo -u foundationdb fdbcli
|
||||||
|
Using cluster file `/etc/foundationdb/fdb.cluster'.
|
||||||
|
|
||||||
|
The database is available.
|
||||||
|
|
||||||
|
Welcome to the fdbcli. For help, type `help'.
|
||||||
|
fdb> status
|
||||||
|
|
||||||
|
Using cluster file `/etc/foundationdb/fdb.cluster'.
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
Redundancy mode - single
|
||||||
|
Storage engine - memory
|
||||||
|
Coordinators - 1
|
||||||
|
|
||||||
|
Cluster:
|
||||||
|
FoundationDB processes - 1
|
||||||
|
Machines - 1
|
||||||
|
Memory availability - 5.4 GB per process on machine with least available
|
||||||
|
Fault Tolerance - 0 machines
|
||||||
|
Server time - 04/20/18 15:21:14
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
fdb>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also write programs using the available client libraries. For
|
||||||
|
example, the following Python program can be run in order to grab the
|
||||||
|
cluster status, as a quick example. (This example uses
|
||||||
|
{command}`nix-shell` shebang support to automatically supply the
|
||||||
|
necessary Python modules).
|
||||||
|
```ShellSession
|
||||||
|
a@link> cat fdb-status.py
|
||||||
|
#! /usr/bin/env nix-shell
|
||||||
|
#! nix-shell -i python -p python pythonPackages.foundationdb52
|
||||||
|
|
||||||
|
import fdb
|
||||||
|
import json
|
||||||
|
|
||||||
|
def main():
|
||||||
|
fdb.api_version(520)
|
||||||
|
db = fdb.open()
|
||||||
|
|
||||||
|
@fdb.transactional
|
||||||
|
def get_status(tr):
|
||||||
|
return str(tr['\xff\xff/status/json'])
|
||||||
|
|
||||||
|
obj = json.loads(get_status(db))
|
||||||
|
print('FoundationDB available: %s' % obj['client']['database_status']['available'])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
a@link> chmod +x fdb-status.py
|
||||||
|
a@link> ./fdb-status.py
|
||||||
|
FoundationDB available: True
|
||||||
|
a@link>
|
||||||
|
```
|
||||||
|
|
||||||
|
FoundationDB is run under the {command}`foundationdb` user and group
|
||||||
|
by default, but this may be changed in the NixOS configuration. The systemd
|
||||||
|
unit {command}`foundationdb.service` controls the
|
||||||
|
{command}`fdbmonitor` process.
|
||||||
|
|
||||||
|
By default, the NixOS module for FoundationDB creates a single SSD-storage
|
||||||
|
based database for development and basic usage. This storage engine is
|
||||||
|
designed for SSDs and will perform poorly on HDDs; however it can handle far
|
||||||
|
more data than the alternative "memory" engine and is a better default
|
||||||
|
choice for most deployments. (Note that you can change the storage backend
|
||||||
|
on-the-fly for a given FoundationDB cluster using
|
||||||
|
{command}`fdbcli`.)
|
||||||
|
|
||||||
|
Furthermore, only 1 server process and 1 backup agent are started in the
|
||||||
|
default configuration. See below for more on scaling to increase this.
|
||||||
|
|
||||||
|
FoundationDB stores all data for all server processes under
|
||||||
|
{file}`/var/lib/foundationdb`. You can override this using
|
||||||
|
{option}`services.foundationdb.dataDir`, e.g.
|
||||||
|
```
|
||||||
|
services.foundationdb.dataDir = "/data/fdb";
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly, logs are stored under {file}`/var/log/foundationdb`
|
||||||
|
by default, and there is a corresponding
|
||||||
|
{option}`services.foundationdb.logDir` as well.
|
||||||
|
|
||||||
|
## Scaling processes and backup agents {#module-services-foundationdb-scaling}
|
||||||
|
|
||||||
|
Scaling the number of server processes is quite easy; simply specify
|
||||||
|
{option}`services.foundationdb.serverProcesses` to be the number of
|
||||||
|
FoundationDB worker processes that should be started on the machine.
|
||||||
|
|
||||||
|
FoundationDB worker processes typically require 4GB of RAM per-process at
|
||||||
|
minimum for good performance, so this option is set to 1 by default since
|
||||||
|
the maximum amount of RAM is unknown. You're advised to abide by this
|
||||||
|
restriction, so pick a number of processes so that each has 4GB or more.
|
||||||
|
|
||||||
|
A similar option exists in order to scale backup agent processes,
|
||||||
|
{option}`services.foundationdb.backupProcesses`. Backup agents are
|
||||||
|
not as performance/RAM sensitive, so feel free to experiment with the number
|
||||||
|
of available backup processes.
|
||||||
|
|
||||||
|
## Clustering {#module-services-foundationdb-clustering}
|
||||||
|
|
||||||
|
FoundationDB on NixOS works similarly to other Linux systems, so this
|
||||||
|
section will be brief. Please refer to the full FoundationDB documentation
|
||||||
|
for more on clustering.
|
||||||
|
|
||||||
|
FoundationDB organizes clusters using a set of
|
||||||
|
*coordinators*, which are just specially-designated
|
||||||
|
worker processes. By default, every installation of FoundationDB on NixOS
|
||||||
|
will start as its own individual cluster, with a single coordinator: the
|
||||||
|
first worker process on {command}`localhost`.
|
||||||
|
|
||||||
|
Coordinators are specified globally using the
|
||||||
|
{command}`/etc/foundationdb/fdb.cluster` file, which all servers and
|
||||||
|
client applications will use to find and join coordinators. Note that this
|
||||||
|
file *can not* be managed by NixOS so easily:
|
||||||
|
FoundationDB is designed so that it will rewrite the file at runtime for all
|
||||||
|
clients and nodes when cluster coordinators change, with clients
|
||||||
|
transparently handling this without intervention. It is fundamentally a
|
||||||
|
mutable file, and you should not try to manage it in any way in NixOS.
|
||||||
|
|
||||||
|
When dealing with a cluster, there are two main things you want to do:
|
||||||
|
|
||||||
|
- Add a node to the cluster for storage/compute.
|
||||||
|
- Promote an ordinary worker to a coordinator.
|
||||||
|
|
||||||
|
A node must already be a member of the cluster in order to properly be
|
||||||
|
promoted to a coordinator, so you must always add it first if you wish to
|
||||||
|
promote it.
|
||||||
|
|
||||||
|
To add a machine to a FoundationDB cluster:
|
||||||
|
|
||||||
|
- Choose one of the servers to start as the initial coordinator.
|
||||||
|
- Copy the {command}`/etc/foundationdb/fdb.cluster` file from this
|
||||||
|
server to all the other servers. Restart FoundationDB on all of these
|
||||||
|
other servers, so they join the cluster.
|
||||||
|
- All of these servers are now connected and working together in the
|
||||||
|
cluster, under the chosen coordinator.
|
||||||
|
|
||||||
|
At this point, you can add as many nodes as you want by just repeating the
|
||||||
|
above steps. By default there will still be a single coordinator: you can
|
||||||
|
use {command}`fdbcli` to change this and add new coordinators.
|
||||||
|
|
||||||
|
As a convenience, FoundationDB can automatically assign coordinators based
|
||||||
|
on the redundancy mode you wish to achieve for the cluster. Once all the
|
||||||
|
nodes have been joined, simply set the replication policy, and then issue
|
||||||
|
the {command}`coordinators auto` command
|
||||||
|
|
||||||
|
For example, assuming we have 3 nodes available, we can enable double
|
||||||
|
redundancy mode, then auto-select coordinators. For double redundancy, 3
|
||||||
|
coordinators is ideal: therefore FoundationDB will make
|
||||||
|
*every* node a coordinator automatically:
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
fdbcli> configure double ssd
|
||||||
|
fdbcli> coordinators auto
|
||||||
|
```
|
||||||
|
|
||||||
|
This will transparently update all the servers within seconds, and
|
||||||
|
appropriately rewrite the {command}`fdb.cluster` file, as well as
|
||||||
|
informing all client processes to do the same.
|
||||||
|
|
||||||
|
## Client connectivity {#module-services-foundationdb-connectivity}
|
||||||
|
|
||||||
|
By default, all clients must use the current {command}`fdb.cluster`
|
||||||
|
file to access a given FoundationDB cluster. This file is located by default
|
||||||
|
in {command}`/etc/foundationdb/fdb.cluster` on all machines with the
|
||||||
|
FoundationDB service enabled, so you may copy the active one from your
|
||||||
|
cluster to a new node in order to connect, if it is not part of the cluster.
|
||||||
|
|
||||||
|
## Client authorization and TLS {#module-services-foundationdb-authorization}
|
||||||
|
|
||||||
|
By default, any user who can connect to a FoundationDB process with the
|
||||||
|
correct cluster configuration can access anything. FoundationDB uses a
|
||||||
|
pluggable design to transport security, and out of the box it supports a
|
||||||
|
LibreSSL-based plugin for TLS support. This plugin not only does in-flight
|
||||||
|
encryption, but also performs client authorization based on the given
|
||||||
|
endpoint's certificate chain. For example, a FoundationDB server may be
|
||||||
|
configured to only accept client connections over TLS, where the client TLS
|
||||||
|
certificate is from organization *Acme Co* in the
|
||||||
|
*Research and Development* unit.
|
||||||
|
|
||||||
|
Configuring TLS with FoundationDB is done using the
|
||||||
|
{option}`services.foundationdb.tls` options in order to control the
|
||||||
|
peer verification string, as well as the certificate and its private key.
|
||||||
|
|
||||||
|
Note that the certificate and its private key must be accessible to the
|
||||||
|
FoundationDB user account that the server runs under. These files are also
|
||||||
|
NOT managed by NixOS, as putting them into the store may reveal private
|
||||||
|
information.
|
||||||
|
|
||||||
|
After you have a key and certificate file in place, it is not enough to
|
||||||
|
simply set the NixOS module options -- you must also configure the
|
||||||
|
{command}`fdb.cluster` file to specify that a given set of
|
||||||
|
coordinators use TLS. This is as simple as adding the suffix
|
||||||
|
{command}`:tls` to your cluster coordinator configuration, after the
|
||||||
|
port number. For example, assuming you have a coordinator on localhost with
|
||||||
|
the default configuration, simply specifying:
|
||||||
|
|
||||||
|
```
|
||||||
|
XXXXXX:XXXXXX@127.0.0.1:4500:tls
|
||||||
|
```
|
||||||
|
|
||||||
|
will configure all clients and server processes to use TLS from now on.
|
||||||
|
|
||||||
|
## Backups and Disaster Recovery {#module-services-foundationdb-disaster-recovery}
|
||||||
|
|
||||||
|
The usual rules for doing FoundationDB backups apply on NixOS as written in
|
||||||
|
the FoundationDB manual. However, one important difference is the security
|
||||||
|
profile for NixOS: by default, the {command}`foundationdb` systemd
|
||||||
|
unit uses *Linux namespaces* to restrict write access to
|
||||||
|
the system, except for the log directory, data directory, and the
|
||||||
|
{command}`/etc/foundationdb/` directory. This is enforced by default
|
||||||
|
and cannot be disabled.
|
||||||
|
|
||||||
|
However, a side effect of this is that the {command}`fdbbackup`
|
||||||
|
command doesn't work properly for local filesystem backups: FoundationDB
|
||||||
|
uses a server process alongside the database processes to perform backups
|
||||||
|
and copy the backups to the filesystem. As a result, this process is put
|
||||||
|
under the restricted namespaces above: the backup process can only write to
|
||||||
|
a limited number of paths.
|
||||||
|
|
||||||
|
In order to allow flexible backup locations on local disks, the FoundationDB
|
||||||
|
NixOS module supports a
|
||||||
|
{option}`services.foundationdb.extraReadWritePaths` option. This
|
||||||
|
option takes a list of paths, and adds them to the systemd unit, allowing
|
||||||
|
the processes inside the service to write (and read) the specified
|
||||||
|
directories.
|
||||||
|
|
||||||
|
For example, to create backups in {command}`/opt/fdb-backups`, first
|
||||||
|
set up the paths in the module options:
|
||||||
|
|
||||||
|
```
|
||||||
|
services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ];
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart the FoundationDB service, and it will now be able to write to this
|
||||||
|
directory (even if it does not yet exist.) Note: this path
|
||||||
|
*must* exist before restarting the unit. Otherwise,
|
||||||
|
systemd will not include it in the private FoundationDB namespace (and it
|
||||||
|
will not add it dynamically at runtime).
|
||||||
|
|
||||||
|
You can now perform a backup:
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
$ sudo -u foundationdb fdbbackup start -t default -d file:///opt/fdb-backups
|
||||||
|
$ sudo -u foundationdb fdbbackup status -t default
|
||||||
|
```
|
||||||
|
|
||||||
|
## Known limitations {#module-services-foundationdb-limitations}
|
||||||
|
|
||||||
|
The FoundationDB setup for NixOS should currently be considered beta.
|
||||||
|
FoundationDB is not new software, but the NixOS compilation and integration
|
||||||
|
has only undergone fairly basic testing of all the available functionality.
|
||||||
|
|
||||||
|
- There is no way to specify individual parameters for individual
|
||||||
|
{command}`fdbserver` processes. Currently, all server processes
|
||||||
|
inherit all the global {command}`fdbmonitor` settings.
|
||||||
|
- Ruby bindings are not currently installed.
|
||||||
|
- Go bindings are not currently installed.
|
||||||
|
|
||||||
|
## Options {#module-services-foundationdb-options}
|
||||||
|
|
||||||
|
NixOS's FoundationDB module allows you to configure all of the most relevant
|
||||||
|
configuration options for {command}`fdbmonitor`, matching it quite
|
||||||
|
closely. A complete list of options for the FoundationDB module may be found
|
||||||
|
[here](#opt-services.foundationdb.enable). You should
|
||||||
|
also read the FoundationDB documentation as well.
|
||||||
|
|
||||||
|
## Full documentation {#module-services-foundationdb-full-docs}
|
||||||
|
|
||||||
|
FoundationDB is a complex piece of software, and requires careful
|
||||||
|
administration to properly use. Full documentation for administration can be
|
||||||
|
found here: <https://apple.github.io/foundationdb/>.
|
|
@ -1,8 +1,6 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-foundationdb">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-foundationdb">
|
|
||||||
<title>FoundationDB</title>
|
<title>FoundationDB</title>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Source:</emphasis>
|
<emphasis>Source:</emphasis>
|
||||||
|
@ -10,7 +8,7 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Upstream documentation:</emphasis>
|
<emphasis>Upstream documentation:</emphasis>
|
||||||
<link xlink:href="https://apple.github.io/foundationdb/"/>
|
<link xlink:href="https://apple.github.io/foundationdb/">https://apple.github.io/foundationdb/</link>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Maintainer:</emphasis> Austin Seipp
|
<emphasis>Maintainer:</emphasis> Austin Seipp
|
||||||
|
@ -19,42 +17,42 @@
|
||||||
<emphasis>Available version(s):</emphasis> 5.1.x, 5.2.x, 6.0.x
|
<emphasis>Available version(s):</emphasis> 5.1.x, 5.2.x, 6.0.x
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
FoundationDB (or "FDB") is an open source, distributed, transactional
|
FoundationDB (or <quote>FDB</quote>) is an open source, distributed,
|
||||||
key-value store.
|
transactional key-value store.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-foundationdb-configuring">
|
<section xml:id="module-services-foundationdb-configuring">
|
||||||
<title>Configuring and basic setup</title>
|
<title>Configuring and basic setup</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To enable FoundationDB, add the following to your
|
To enable FoundationDB, add the following to your
|
||||||
<filename>configuration.nix</filename>:
|
<filename>configuration.nix</filename>:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.foundationdb.enable = true;
|
services.foundationdb.enable = true;
|
||||||
services.foundationdb.package = pkgs.foundationdb52; # FoundationDB 5.2.x
|
services.foundationdb.package = pkgs.foundationdb52; # FoundationDB 5.2.x
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <option>services.foundationdb.package</option> option is required, and
|
The <option>services.foundationdb.package</option> option is
|
||||||
must always be specified. Due to the fact FoundationDB network protocols and
|
required, and must always be specified. Due to the fact
|
||||||
on-disk storage formats may change between (major) versions, and upgrades
|
FoundationDB network protocols and on-disk storage formats may
|
||||||
must be explicitly handled by the user, you must always manually specify
|
change between (major) versions, and upgrades must be explicitly
|
||||||
this yourself so that the NixOS module will use the proper version. Note
|
handled by the user, you must always manually specify this
|
||||||
that minor, bugfix releases are always compatible.
|
yourself so that the NixOS module will use the proper version.
|
||||||
|
Note that minor, bugfix releases are always compatible.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
After running <command>nixos-rebuild</command>, you can verify whether
|
After running <command>nixos-rebuild</command>, you can verify
|
||||||
FoundationDB is running by executing <command>fdbcli</command> (which is
|
whether FoundationDB is running by executing
|
||||||
added to <option>environment.systemPackages</option>):
|
<command>fdbcli</command> (which is added to
|
||||||
<screen>
|
<option>environment.systemPackages</option>):
|
||||||
<prompt>$ </prompt>sudo -u foundationdb fdbcli
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ sudo -u foundationdb fdbcli
|
||||||
Using cluster file `/etc/foundationdb/fdb.cluster'.
|
Using cluster file `/etc/foundationdb/fdb.cluster'.
|
||||||
|
|
||||||
The database is available.
|
The database is available.
|
||||||
|
|
||||||
Welcome to the fdbcli. For help, type `help'.
|
Welcome to the fdbcli. For help, type `help'.
|
||||||
<prompt>fdb> </prompt>status
|
fdb> status
|
||||||
|
|
||||||
Using cluster file `/etc/foundationdb/fdb.cluster'.
|
Using cluster file `/etc/foundationdb/fdb.cluster'.
|
||||||
|
|
||||||
|
@ -72,18 +70,17 @@ Cluster:
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
<prompt>fdb></prompt>
|
fdb>
|
||||||
</screen>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
You can also write programs using the available client libraries. For
|
You can also write programs using the available client libraries.
|
||||||
example, the following Python program can be run in order to grab the
|
For example, the following Python program can be run in order to
|
||||||
cluster status, as a quick example. (This example uses
|
grab the cluster status, as a quick example. (This example uses
|
||||||
<command>nix-shell</command> shebang support to automatically supply the
|
<command>nix-shell</command> shebang support to automatically
|
||||||
necessary Python modules).
|
supply the necessary Python modules).
|
||||||
<screen>
|
</para>
|
||||||
<prompt>a@link> </prompt>cat fdb-status.py
|
<programlisting>
|
||||||
|
a@link> cat fdb-status.py
|
||||||
#! /usr/bin/env nix-shell
|
#! /usr/bin/env nix-shell
|
||||||
#! nix-shell -i python -p python pythonPackages.foundationdb52
|
#! nix-shell -i python -p python pythonPackages.foundationdb52
|
||||||
|
|
||||||
|
@ -101,108 +98,103 @@ def main():
|
||||||
obj = json.loads(get_status(db))
|
obj = json.loads(get_status(db))
|
||||||
print('FoundationDB available: %s' % obj['client']['database_status']['available'])
|
print('FoundationDB available: %s' % obj['client']['database_status']['available'])
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
<prompt>a@link> </prompt>chmod +x fdb-status.py
|
a@link> chmod +x fdb-status.py
|
||||||
<prompt>a@link> </prompt>./fdb-status.py
|
a@link> ./fdb-status.py
|
||||||
FoundationDB available: True
|
FoundationDB available: True
|
||||||
<prompt>a@link></prompt>
|
a@link>
|
||||||
</screen>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
FoundationDB is run under the <command>foundationdb</command> user and group
|
FoundationDB is run under the <command>foundationdb</command> user
|
||||||
by default, but this may be changed in the NixOS configuration. The systemd
|
and group by default, but this may be changed in the NixOS
|
||||||
unit <command>foundationdb.service</command> controls the
|
configuration. The systemd unit
|
||||||
|
<command>foundationdb.service</command> controls the
|
||||||
<command>fdbmonitor</command> process.
|
<command>fdbmonitor</command> process.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
By default, the NixOS module for FoundationDB creates a single SSD-storage
|
By default, the NixOS module for FoundationDB creates a single
|
||||||
based database for development and basic usage. This storage engine is
|
SSD-storage based database for development and basic usage. This
|
||||||
designed for SSDs and will perform poorly on HDDs; however it can handle far
|
storage engine is designed for SSDs and will perform poorly on
|
||||||
more data than the alternative "memory" engine and is a better default
|
HDDs; however it can handle far more data than the alternative
|
||||||
choice for most deployments. (Note that you can change the storage backend
|
<quote>memory</quote> engine and is a better default choice for
|
||||||
|
most deployments. (Note that you can change the storage backend
|
||||||
on-the-fly for a given FoundationDB cluster using
|
on-the-fly for a given FoundationDB cluster using
|
||||||
<command>fdbcli</command>.)
|
<command>fdbcli</command>.)
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Furthermore, only 1 server process and 1 backup agent are started in the
|
Furthermore, only 1 server process and 1 backup agent are started
|
||||||
default configuration. See below for more on scaling to increase this.
|
in the default configuration. See below for more on scaling to
|
||||||
|
increase this.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
FoundationDB stores all data for all server processes under
|
FoundationDB stores all data for all server processes under
|
||||||
<filename>/var/lib/foundationdb</filename>. You can override this using
|
<filename>/var/lib/foundationdb</filename>. You can override this
|
||||||
<option>services.foundationdb.dataDir</option>, e.g.
|
using <option>services.foundationdb.dataDir</option>, e.g.
|
||||||
<programlisting>
|
|
||||||
services.foundationdb.dataDir = "/data/fdb";
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
services.foundationdb.dataDir = "/data/fdb";
|
||||||
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Similarly, logs are stored under <filename>/var/log/foundationdb</filename>
|
Similarly, logs are stored under
|
||||||
by default, and there is a corresponding
|
<filename>/var/log/foundationdb</filename> by default, and there
|
||||||
<option>services.foundationdb.logDir</option> as well.
|
is a corresponding <option>services.foundationdb.logDir</option>
|
||||||
|
as well.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-foundationdb-scaling">
|
<section xml:id="module-services-foundationdb-scaling">
|
||||||
<title>Scaling processes and backup agents</title>
|
<title>Scaling processes and backup agents</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Scaling the number of server processes is quite easy; simply specify
|
Scaling the number of server processes is quite easy; simply
|
||||||
<option>services.foundationdb.serverProcesses</option> to be the number of
|
specify <option>services.foundationdb.serverProcesses</option> to
|
||||||
FoundationDB worker processes that should be started on the machine.
|
be the number of FoundationDB worker processes that should be
|
||||||
|
started on the machine.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
FoundationDB worker processes typically require 4GB of RAM per-process at
|
FoundationDB worker processes typically require 4GB of RAM
|
||||||
minimum for good performance, so this option is set to 1 by default since
|
per-process at minimum for good performance, so this option is set
|
||||||
the maximum amount of RAM is unknown. You're advised to abide by this
|
to 1 by default since the maximum amount of RAM is unknown. You’re
|
||||||
restriction, so pick a number of processes so that each has 4GB or more.
|
advised to abide by this restriction, so pick a number of
|
||||||
|
processes so that each has 4GB or more.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A similar option exists in order to scale backup agent processes,
|
A similar option exists in order to scale backup agent processes,
|
||||||
<option>services.foundationdb.backupProcesses</option>. Backup agents are
|
<option>services.foundationdb.backupProcesses</option>. Backup
|
||||||
not as performance/RAM sensitive, so feel free to experiment with the number
|
agents are not as performance/RAM sensitive, so feel free to
|
||||||
of available backup processes.
|
experiment with the number of available backup processes.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-foundationdb-clustering">
|
<section xml:id="module-services-foundationdb-clustering">
|
||||||
<title>Clustering</title>
|
<title>Clustering</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
FoundationDB on NixOS works similarly to other Linux systems, so this
|
FoundationDB on NixOS works similarly to other Linux systems, so
|
||||||
section will be brief. Please refer to the full FoundationDB documentation
|
this section will be brief. Please refer to the full FoundationDB
|
||||||
for more on clustering.
|
documentation for more on clustering.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
FoundationDB organizes clusters using a set of
|
FoundationDB organizes clusters using a set of
|
||||||
<emphasis>coordinators</emphasis>, which are just specially-designated
|
<emphasis>coordinators</emphasis>, which are just
|
||||||
worker processes. By default, every installation of FoundationDB on NixOS
|
specially-designated worker processes. By default, every
|
||||||
will start as its own individual cluster, with a single coordinator: the
|
installation of FoundationDB on NixOS will start as its own
|
||||||
first worker process on <command>localhost</command>.
|
individual cluster, with a single coordinator: the first worker
|
||||||
|
process on <command>localhost</command>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Coordinators are specified globally using the
|
Coordinators are specified globally using the
|
||||||
<command>/etc/foundationdb/fdb.cluster</command> file, which all servers and
|
<command>/etc/foundationdb/fdb.cluster</command> file, which all
|
||||||
client applications will use to find and join coordinators. Note that this
|
servers and client applications will use to find and join
|
||||||
file <emphasis>can not</emphasis> be managed by NixOS so easily:
|
coordinators. Note that this file <emphasis>can not</emphasis> be
|
||||||
FoundationDB is designed so that it will rewrite the file at runtime for all
|
managed by NixOS so easily: FoundationDB is designed so that it
|
||||||
clients and nodes when cluster coordinators change, with clients
|
will rewrite the file at runtime for all clients and nodes when
|
||||||
transparently handling this without intervention. It is fundamentally a
|
cluster coordinators change, with clients transparently handling
|
||||||
mutable file, and you should not try to manage it in any way in NixOS.
|
this without intervention. It is fundamentally a mutable file, and
|
||||||
|
you should not try to manage it in any way in NixOS.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When dealing with a cluster, there are two main things you want to do:
|
When dealing with a cluster, there are two main things you want to
|
||||||
|
do:
|
||||||
</para>
|
</para>
|
||||||
|
<itemizedlist spacing="compact">
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Add a node to the cluster for storage/compute.
|
Add a node to the cluster for storage/compute.
|
||||||
|
@ -214,18 +206,15 @@ services.foundationdb.dataDir = "/data/fdb";
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A node must already be a member of the cluster in order to properly be
|
A node must already be a member of the cluster in order to
|
||||||
promoted to a coordinator, so you must always add it first if you wish to
|
properly be promoted to a coordinator, so you must always add it
|
||||||
promote it.
|
first if you wish to promote it.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To add a machine to a FoundationDB cluster:
|
To add a machine to a FoundationDB cluster:
|
||||||
</para>
|
</para>
|
||||||
|
<itemizedlist spacing="compact">
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Choose one of the servers to start as the initial coordinator.
|
Choose one of the servers to start as the initial coordinator.
|
||||||
|
@ -233,179 +222,172 @@ services.foundationdb.dataDir = "/data/fdb";
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Copy the <command>/etc/foundationdb/fdb.cluster</command> file from this
|
Copy the <command>/etc/foundationdb/fdb.cluster</command> file
|
||||||
server to all the other servers. Restart FoundationDB on all of these
|
from this server to all the other servers. Restart
|
||||||
other servers, so they join the cluster.
|
FoundationDB on all of these other servers, so they join the
|
||||||
|
cluster.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
All of these servers are now connected and working together in the
|
All of these servers are now connected and working together in
|
||||||
cluster, under the chosen coordinator.
|
the cluster, under the chosen coordinator.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
At this point, you can add as many nodes as you want by just repeating the
|
At this point, you can add as many nodes as you want by just
|
||||||
above steps. By default there will still be a single coordinator: you can
|
repeating the above steps. By default there will still be a single
|
||||||
use <command>fdbcli</command> to change this and add new coordinators.
|
coordinator: you can use <command>fdbcli</command> to change this
|
||||||
|
and add new coordinators.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
As a convenience, FoundationDB can automatically assign coordinators based
|
As a convenience, FoundationDB can automatically assign
|
||||||
on the redundancy mode you wish to achieve for the cluster. Once all the
|
coordinators based on the redundancy mode you wish to achieve for
|
||||||
nodes have been joined, simply set the replication policy, and then issue
|
the cluster. Once all the nodes have been joined, simply set the
|
||||||
the <command>coordinators auto</command> command
|
replication policy, and then issue the
|
||||||
|
<command>coordinators auto</command> command
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For example, assuming we have 3 nodes available, we can enable double
|
For example, assuming we have 3 nodes available, we can enable
|
||||||
redundancy mode, then auto-select coordinators. For double redundancy, 3
|
double redundancy mode, then auto-select coordinators. For double
|
||||||
coordinators is ideal: therefore FoundationDB will make
|
redundancy, 3 coordinators is ideal: therefore FoundationDB will
|
||||||
<emphasis>every</emphasis> node a coordinator automatically:
|
make <emphasis>every</emphasis> node a coordinator automatically:
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
<screen>
|
fdbcli> configure double ssd
|
||||||
<prompt>fdbcli> </prompt>configure double ssd
|
fdbcli> coordinators auto
|
||||||
<prompt>fdbcli> </prompt>coordinators auto
|
</programlisting>
|
||||||
</screen>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This will transparently update all the servers within seconds, and
|
This will transparently update all the servers within seconds, and
|
||||||
appropriately rewrite the <command>fdb.cluster</command> file, as well as
|
appropriately rewrite the <command>fdb.cluster</command> file, as
|
||||||
informing all client processes to do the same.
|
well as informing all client processes to do the same.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-foundationdb-connectivity">
|
<section xml:id="module-services-foundationdb-connectivity">
|
||||||
<title>Client connectivity</title>
|
<title>Client connectivity</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
By default, all clients must use the current <command>fdb.cluster</command>
|
By default, all clients must use the current
|
||||||
file to access a given FoundationDB cluster. This file is located by default
|
<command>fdb.cluster</command> file to access a given FoundationDB
|
||||||
in <command>/etc/foundationdb/fdb.cluster</command> on all machines with the
|
cluster. This file is located by default in
|
||||||
FoundationDB service enabled, so you may copy the active one from your
|
<command>/etc/foundationdb/fdb.cluster</command> on all machines
|
||||||
cluster to a new node in order to connect, if it is not part of the cluster.
|
with the FoundationDB service enabled, so you may copy the active
|
||||||
|
one from your cluster to a new node in order to connect, if it is
|
||||||
|
not part of the cluster.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-foundationdb-authorization">
|
<section xml:id="module-services-foundationdb-authorization">
|
||||||
<title>Client authorization and TLS</title>
|
<title>Client authorization and TLS</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
By default, any user who can connect to a FoundationDB process with the
|
By default, any user who can connect to a FoundationDB process
|
||||||
correct cluster configuration can access anything. FoundationDB uses a
|
with the correct cluster configuration can access anything.
|
||||||
pluggable design to transport security, and out of the box it supports a
|
FoundationDB uses a pluggable design to transport security, and
|
||||||
LibreSSL-based plugin for TLS support. This plugin not only does in-flight
|
out of the box it supports a LibreSSL-based plugin for TLS
|
||||||
encryption, but also performs client authorization based on the given
|
support. This plugin not only does in-flight encryption, but also
|
||||||
endpoint's certificate chain. For example, a FoundationDB server may be
|
performs client authorization based on the given endpoint’s
|
||||||
configured to only accept client connections over TLS, where the client TLS
|
certificate chain. For example, a FoundationDB server may be
|
||||||
certificate is from organization <emphasis>Acme Co</emphasis> in the
|
configured to only accept client connections over TLS, where the
|
||||||
<emphasis>Research and Development</emphasis> unit.
|
client TLS certificate is from organization <emphasis>Acme
|
||||||
|
Co</emphasis> in the <emphasis>Research and Development</emphasis>
|
||||||
|
unit.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Configuring TLS with FoundationDB is done using the
|
Configuring TLS with FoundationDB is done using the
|
||||||
<option>services.foundationdb.tls</option> options in order to control the
|
<option>services.foundationdb.tls</option> options in order to
|
||||||
peer verification string, as well as the certificate and its private key.
|
control the peer verification string, as well as the certificate
|
||||||
|
and its private key.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Note that the certificate and its private key must be accessible to the
|
Note that the certificate and its private key must be accessible
|
||||||
FoundationDB user account that the server runs under. These files are also
|
to the FoundationDB user account that the server runs under. These
|
||||||
NOT managed by NixOS, as putting them into the store may reveal private
|
files are also NOT managed by NixOS, as putting them into the
|
||||||
information.
|
store may reveal private information.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
After you have a key and certificate file in place, it is not enough to
|
After you have a key and certificate file in place, it is not
|
||||||
simply set the NixOS module options -- you must also configure the
|
enough to simply set the NixOS module options – you must also
|
||||||
<command>fdb.cluster</command> file to specify that a given set of
|
configure the <command>fdb.cluster</command> file to specify that
|
||||||
coordinators use TLS. This is as simple as adding the suffix
|
a given set of coordinators use TLS. This is as simple as adding
|
||||||
<command>:tls</command> to your cluster coordinator configuration, after the
|
the suffix <command>:tls</command> to your cluster coordinator
|
||||||
port number. For example, assuming you have a coordinator on localhost with
|
configuration, after the port number. For example, assuming you
|
||||||
the default configuration, simply specifying:
|
have a coordinator on localhost with the default configuration,
|
||||||
|
simply specifying:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
XXXXXX:XXXXXX@127.0.0.1:4500:tls
|
XXXXXX:XXXXXX@127.0.0.1:4500:tls
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
will configure all clients and server processes to use TLS from now on.
|
will configure all clients and server processes to use TLS from
|
||||||
|
now on.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-foundationdb-disaster-recovery">
|
<section xml:id="module-services-foundationdb-disaster-recovery">
|
||||||
<title>Backups and Disaster Recovery</title>
|
<title>Backups and Disaster Recovery</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The usual rules for doing FoundationDB backups apply on NixOS as written in
|
The usual rules for doing FoundationDB backups apply on NixOS as
|
||||||
the FoundationDB manual. However, one important difference is the security
|
written in the FoundationDB manual. However, one important
|
||||||
profile for NixOS: by default, the <command>foundationdb</command> systemd
|
difference is the security profile for NixOS: by default, the
|
||||||
unit uses <emphasis>Linux namespaces</emphasis> to restrict write access to
|
<command>foundationdb</command> systemd unit uses <emphasis>Linux
|
||||||
the system, except for the log directory, data directory, and the
|
namespaces</emphasis> to restrict write access to the system,
|
||||||
<command>/etc/foundationdb/</command> directory. This is enforced by default
|
except for the log directory, data directory, and the
|
||||||
and cannot be disabled.
|
<command>/etc/foundationdb/</command> directory. This is enforced
|
||||||
|
by default and cannot be disabled.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
However, a side effect of this is that the <command>fdbbackup</command>
|
However, a side effect of this is that the
|
||||||
command doesn't work properly for local filesystem backups: FoundationDB
|
<command>fdbbackup</command> command doesn’t work properly for
|
||||||
uses a server process alongside the database processes to perform backups
|
local filesystem backups: FoundationDB uses a server process
|
||||||
and copy the backups to the filesystem. As a result, this process is put
|
alongside the database processes to perform backups and copy the
|
||||||
under the restricted namespaces above: the backup process can only write to
|
backups to the filesystem. As a result, this process is put under
|
||||||
a limited number of paths.
|
the restricted namespaces above: the backup process can only write
|
||||||
|
to a limited number of paths.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
In order to allow flexible backup locations on local disks, the FoundationDB
|
In order to allow flexible backup locations on local disks, the
|
||||||
NixOS module supports a
|
FoundationDB NixOS module supports a
|
||||||
<option>services.foundationdb.extraReadWritePaths</option> option. This
|
<option>services.foundationdb.extraReadWritePaths</option> option.
|
||||||
option takes a list of paths, and adds them to the systemd unit, allowing
|
This option takes a list of paths, and adds them to the systemd
|
||||||
the processes inside the service to write (and read) the specified
|
unit, allowing the processes inside the service to write (and
|
||||||
directories.
|
read) the specified directories.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For example, to create backups in <command>/opt/fdb-backups</command>, first
|
For example, to create backups in
|
||||||
set up the paths in the module options:
|
<command>/opt/fdb-backups</command>, first set up the paths in the
|
||||||
|
module options:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ];
|
services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ];
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Restart the FoundationDB service, and it will now be able to write to this
|
Restart the FoundationDB service, and it will now be able to write
|
||||||
directory (even if it does not yet exist.) Note: this path
|
to this directory (even if it does not yet exist.) Note: this path
|
||||||
<emphasis>must</emphasis> exist before restarting the unit. Otherwise,
|
<emphasis>must</emphasis> exist before restarting the unit.
|
||||||
systemd will not include it in the private FoundationDB namespace (and it
|
Otherwise, systemd will not include it in the private FoundationDB
|
||||||
will not add it dynamically at runtime).
|
namespace (and it will not add it dynamically at runtime).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
You can now perform a backup:
|
You can now perform a backup:
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
<screen>
|
$ sudo -u foundationdb fdbbackup start -t default -d file:///opt/fdb-backups
|
||||||
<prompt>$ </prompt>sudo -u foundationdb fdbbackup start -t default -d file:///opt/fdb-backups
|
$ sudo -u foundationdb fdbbackup status -t default
|
||||||
<prompt>$ </prompt>sudo -u foundationdb fdbbackup status -t default
|
</programlisting>
|
||||||
</screen>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-foundationdb-limitations">
|
<section xml:id="module-services-foundationdb-limitations">
|
||||||
<title>Known limitations</title>
|
<title>Known limitations</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The FoundationDB setup for NixOS should currently be considered beta.
|
The FoundationDB setup for NixOS should currently be considered
|
||||||
FoundationDB is not new software, but the NixOS compilation and integration
|
beta. FoundationDB is not new software, but the NixOS compilation
|
||||||
has only undergone fairly basic testing of all the available functionality.
|
and integration has only undergone fairly basic testing of all the
|
||||||
|
available functionality.
|
||||||
</para>
|
</para>
|
||||||
|
<itemizedlist spacing="compact">
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
There is no way to specify individual parameters for individual
|
There is no way to specify individual parameters for
|
||||||
<command>fdbserver</command> processes. Currently, all server processes
|
individual <command>fdbserver</command> processes. Currently,
|
||||||
inherit all the global <command>fdbmonitor</command> settings.
|
all server processes inherit all the global
|
||||||
|
<command>fdbmonitor</command> settings.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -422,22 +404,22 @@ services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ];
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-foundationdb-options">
|
<section xml:id="module-services-foundationdb-options">
|
||||||
<title>Options</title>
|
<title>Options</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
NixOS's FoundationDB module allows you to configure all of the most relevant
|
NixOS’s FoundationDB module allows you to configure all of the
|
||||||
configuration options for <command>fdbmonitor</command>, matching it quite
|
most relevant configuration options for
|
||||||
closely. A complete list of options for the FoundationDB module may be found
|
<command>fdbmonitor</command>, matching it quite closely. A
|
||||||
<link linkend="opt-services.foundationdb.enable">here</link>. You should
|
complete list of options for the FoundationDB module may be found
|
||||||
also read the FoundationDB documentation as well.
|
<link linkend="opt-services.foundationdb.enable">here</link>. You
|
||||||
|
should also read the FoundationDB documentation as well.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-foundationdb-full-docs">
|
<section xml:id="module-services-foundationdb-full-docs">
|
||||||
<title>Full documentation</title>
|
<title>Full documentation</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
FoundationDB is a complex piece of software, and requires careful
|
FoundationDB is a complex piece of software, and requires careful
|
||||||
administration to properly use. Full documentation for administration can be
|
administration to properly use. Full documentation for
|
||||||
found here: <link xlink:href="https://apple.github.io/foundationdb/"/>.
|
administration can be found here:
|
||||||
|
<link xlink:href="https://apple.github.io/foundationdb/">https://apple.github.io/foundationdb/</link>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
173
nixos/modules/services/databases/postgresql.md
Normal file
173
nixos/modules/services/databases/postgresql.md
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# PostgreSQL {#module-postgresql}
|
||||||
|
|
||||||
|
<!-- FIXME: render nicely -->
|
||||||
|
<!-- FIXME: source can be added automatically -->
|
||||||
|
|
||||||
|
*Source:* {file}`modules/services/databases/postgresql.nix`
|
||||||
|
|
||||||
|
*Upstream documentation:* <http://www.postgresql.org/docs/>
|
||||||
|
|
||||||
|
<!-- FIXME: more stuff, like maintainer? -->
|
||||||
|
|
||||||
|
PostgreSQL is an advanced, free relational database.
|
||||||
|
<!-- MORE -->
|
||||||
|
|
||||||
|
## Configuring {#module-services-postgres-configuring}
|
||||||
|
|
||||||
|
To enable PostgreSQL, add the following to your {file}`configuration.nix`:
|
||||||
|
```
|
||||||
|
services.postgresql.enable = true;
|
||||||
|
services.postgresql.package = pkgs.postgresql_11;
|
||||||
|
```
|
||||||
|
Note that you are required to specify the desired version of PostgreSQL (e.g. `pkgs.postgresql_11`). Since upgrading your PostgreSQL version requires a database dump and reload (see below), NixOS cannot provide a default value for [](#opt-services.postgresql.package) such as the most recent release of PostgreSQL.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
After running {command}`nixos-rebuild`, you can verify
|
||||||
|
whether PostgreSQL works by running {command}`psql`:
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
$ psql
|
||||||
|
psql (9.2.9)
|
||||||
|
Type "help" for help.
|
||||||
|
|
||||||
|
alice=>
|
||||||
|
```
|
||||||
|
-->
|
||||||
|
|
||||||
|
By default, PostgreSQL stores its databases in {file}`/var/lib/postgresql/$psqlSchema`. You can override this using [](#opt-services.postgresql.dataDir), e.g.
|
||||||
|
```
|
||||||
|
services.postgresql.dataDir = "/data/postgresql";
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrading {#module-services-postgres-upgrading}
|
||||||
|
|
||||||
|
::: {.note}
|
||||||
|
The steps below demonstrate how to upgrade from an older version to `pkgs.postgresql_13`.
|
||||||
|
These instructions are also applicable to other versions.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Major PostgreSQL upgrades require a downtime and a few imperative steps to be called. This is the case because
|
||||||
|
each major version has some internal changes in the databases' state during major releases. Because of that,
|
||||||
|
NixOS places the state into {file}`/var/lib/postgresql/<version>` where each `version`
|
||||||
|
can be obtained like this:
|
||||||
|
```
|
||||||
|
$ nix-instantiate --eval -A postgresql_13.psqlSchema
|
||||||
|
"13"
|
||||||
|
```
|
||||||
|
For an upgrade, a script like this can be used to simplify the process:
|
||||||
|
```
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
{
|
||||||
|
environment.systemPackages = [
|
||||||
|
(let
|
||||||
|
# XXX specify the postgresql package you'd like to upgrade to.
|
||||||
|
# Do not forget to list the extensions you need.
|
||||||
|
newPostgres = pkgs.postgresql_13.withPackages (pp: [
|
||||||
|
# pp.plv8
|
||||||
|
]);
|
||||||
|
in pkgs.writeScriptBin "upgrade-pg-cluster" ''
|
||||||
|
set -eux
|
||||||
|
# XXX it's perhaps advisable to stop all services that depend on postgresql
|
||||||
|
systemctl stop postgresql
|
||||||
|
|
||||||
|
export NEWDATA="/var/lib/postgresql/${newPostgres.psqlSchema}"
|
||||||
|
|
||||||
|
export NEWBIN="${newPostgres}/bin"
|
||||||
|
|
||||||
|
export OLDDATA="${config.services.postgresql.dataDir}"
|
||||||
|
export OLDBIN="${config.services.postgresql.package}/bin"
|
||||||
|
|
||||||
|
install -d -m 0700 -o postgres -g postgres "$NEWDATA"
|
||||||
|
cd "$NEWDATA"
|
||||||
|
sudo -u postgres $NEWBIN/initdb -D "$NEWDATA"
|
||||||
|
|
||||||
|
sudo -u postgres $NEWBIN/pg_upgrade \
|
||||||
|
--old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \
|
||||||
|
--old-bindir $OLDBIN --new-bindir $NEWBIN \
|
||||||
|
"$@"
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The upgrade process is:
|
||||||
|
|
||||||
|
1. Rebuild nixos configuration with the configuration above added to your {file}`configuration.nix`. Alternatively, add that into separate file and reference it in `imports` list.
|
||||||
|
2. Login as root (`sudo su -`)
|
||||||
|
3. Run `upgrade-pg-cluster`. It will stop old postgresql, initialize a new one and migrate the old one to the new one. You may supply arguments like `--jobs 4` and `--link` to speedup migration process. See <https://www.postgresql.org/docs/current/pgupgrade.html> for details.
|
||||||
|
4. Change postgresql package in NixOS configuration to the one you were upgrading to via [](#opt-services.postgresql.package). Rebuild NixOS. This should start new postgres using upgraded data directory and all services you stopped during the upgrade.
|
||||||
|
5. After the upgrade it's advisable to analyze the new cluster.
|
||||||
|
|
||||||
|
- For PostgreSQL ≥ 14, use the `vacuumdb` command printed by the upgrades script.
|
||||||
|
- For PostgreSQL < 14, run (as `su -l postgres` in the [](#opt-services.postgresql.dataDir), in this example {file}`/var/lib/postgresql/13`):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./analyze_new_cluster.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
The next step removes the old state-directory!
|
||||||
|
:::
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./delete_old_cluster.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options {#module-services-postgres-options}
|
||||||
|
|
||||||
|
A complete list of options for the PostgreSQL module may be found [here](#opt-services.postgresql.enable).
|
||||||
|
|
||||||
|
## Plugins {#module-services-postgres-plugins}
|
||||||
|
|
||||||
|
Plugins collection for each PostgreSQL version can be accessed with `.pkgs`. For example, for `pkgs.postgresql_11` package, its plugin collection is accessed by `pkgs.postgresql_11.pkgs`:
|
||||||
|
```ShellSession
|
||||||
|
$ nix repl '<nixpkgs>'
|
||||||
|
|
||||||
|
Loading '<nixpkgs>'...
|
||||||
|
Added 10574 variables.
|
||||||
|
|
||||||
|
nix-repl> postgresql_11.pkgs.<TAB><TAB>
|
||||||
|
postgresql_11.pkgs.cstore_fdw postgresql_11.pkgs.pg_repack
|
||||||
|
postgresql_11.pkgs.pg_auto_failover postgresql_11.pkgs.pg_safeupdate
|
||||||
|
postgresql_11.pkgs.pg_bigm postgresql_11.pkgs.pg_similarity
|
||||||
|
postgresql_11.pkgs.pg_cron postgresql_11.pkgs.pg_topn
|
||||||
|
postgresql_11.pkgs.pg_hll postgresql_11.pkgs.pgjwt
|
||||||
|
postgresql_11.pkgs.pg_partman postgresql_11.pkgs.pgroonga
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
To add plugins via NixOS configuration, set `services.postgresql.extraPlugins`:
|
||||||
|
```
|
||||||
|
services.postgresql.package = pkgs.postgresql_11;
|
||||||
|
services.postgresql.extraPlugins = with pkgs.postgresql_11.pkgs; [
|
||||||
|
pg_repack
|
||||||
|
postgis
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
You can build custom PostgreSQL-with-plugins (to be used outside of NixOS) using function `.withPackages`. For example, creating a custom PostgreSQL package in an overlay can look like:
|
||||||
|
```
|
||||||
|
self: super: {
|
||||||
|
postgresql_custom = self.postgresql_11.withPackages (ps: [
|
||||||
|
ps.pg_repack
|
||||||
|
ps.postgis
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's a recipe on how to override a particular plugin through an overlay:
|
||||||
|
```
|
||||||
|
self: super: {
|
||||||
|
postgresql_11 = super.postgresql_11.override { this = self.postgresql_11; } // {
|
||||||
|
pkgs = super.postgresql_11.pkgs // {
|
||||||
|
pg_repack = super.postgresql_11.pkgs.pg_repack.overrideAttrs (_: {
|
||||||
|
name = "pg_repack-v20181024";
|
||||||
|
src = self.fetchzip {
|
||||||
|
url = "https://github.com/reorg/pg_repack/archive/923fa2f3c709a506e111cc963034bf2fd127aa00.tar.gz";
|
||||||
|
sha256 = "17k6hq9xaax87yz79j773qyigm4fwk8z4zh5cyp6z0sxnwfqxxw5";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
|
@ -1,117 +1,115 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-postgresql">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-postgresql">
|
|
||||||
<title>PostgreSQL</title>
|
<title>PostgreSQL</title>
|
||||||
<!-- FIXME: render nicely -->
|
|
||||||
<!-- FIXME: source can be added automatically -->
|
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Source:</emphasis> <filename>modules/services/databases/postgresql.nix</filename>
|
<emphasis>Source:</emphasis>
|
||||||
|
<filename>modules/services/databases/postgresql.nix</filename>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Upstream documentation:</emphasis> <link xlink:href="http://www.postgresql.org/docs/"/>
|
<emphasis>Upstream documentation:</emphasis>
|
||||||
|
<link xlink:href="http://www.postgresql.org/docs/">http://www.postgresql.org/docs/</link>
|
||||||
</para>
|
</para>
|
||||||
<!-- FIXME: more stuff, like maintainer? -->
|
|
||||||
<para>
|
<para>
|
||||||
PostgreSQL is an advanced, free relational database.
|
PostgreSQL is an advanced, free relational database.
|
||||||
<!-- MORE -->
|
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-postgres-configuring">
|
<section xml:id="module-services-postgres-configuring">
|
||||||
<title>Configuring</title>
|
<title>Configuring</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To enable PostgreSQL, add the following to your <filename>configuration.nix</filename>:
|
To enable PostgreSQL, add the following to your
|
||||||
<programlisting>
|
<filename>configuration.nix</filename>:
|
||||||
<xref linkend="opt-services.postgresql.enable"/> = true;
|
|
||||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_11;
|
|
||||||
</programlisting>
|
|
||||||
Note that you are required to specify the desired version of PostgreSQL (e.g. <literal>pkgs.postgresql_11</literal>). Since upgrading your PostgreSQL version requires a database dump and reload (see below), NixOS cannot provide a default value for <xref linkend="opt-services.postgresql.package"/> such as the most recent release of PostgreSQL.
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
<!--
|
services.postgresql.enable = true;
|
||||||
<para>After running <command>nixos-rebuild</command>, you can verify
|
services.postgresql.package = pkgs.postgresql_11;
|
||||||
whether PostgreSQL works by running <command>psql</command>:
|
</programlisting>
|
||||||
|
|
||||||
<screen>
|
|
||||||
<prompt>$ </prompt>psql
|
|
||||||
psql (9.2.9)
|
|
||||||
Type "help" for help.
|
|
||||||
|
|
||||||
<prompt>alice=></prompt>
|
|
||||||
</screen>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
By default, PostgreSQL stores its databases in <filename>/var/lib/postgresql/$psqlSchema</filename>. You can override this using <xref linkend="opt-services.postgresql.dataDir"/>, e.g.
|
Note that you are required to specify the desired version of
|
||||||
<programlisting>
|
PostgreSQL (e.g. <literal>pkgs.postgresql_11</literal>). Since
|
||||||
<xref linkend="opt-services.postgresql.dataDir"/> = "/data/postgresql";
|
upgrading your PostgreSQL version requires a database dump and
|
||||||
</programlisting>
|
reload (see below), NixOS cannot provide a default value for
|
||||||
|
<xref linkend="opt-services.postgresql.package" /> such as the
|
||||||
|
most recent release of PostgreSQL.
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
By default, PostgreSQL stores its databases in
|
||||||
|
<filename>/var/lib/postgresql/$psqlSchema</filename>. You can
|
||||||
|
override this using
|
||||||
|
<xref linkend="opt-services.postgresql.dataDir" />, e.g.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
services.postgresql.dataDir = "/data/postgresql";
|
||||||
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-postgres-upgrading">
|
<section xml:id="module-services-postgres-upgrading">
|
||||||
<title>Upgrading</title>
|
<title>Upgrading</title>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
The steps below demonstrate how to upgrade from an older version to <package>pkgs.postgresql_13</package>.
|
The steps below demonstrate how to upgrade from an older version
|
||||||
These instructions are also applicable to other versions.
|
to <literal>pkgs.postgresql_13</literal>. These instructions are
|
||||||
|
also applicable to other versions.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
<para>
|
<para>
|
||||||
Major PostgreSQL upgrades require a downtime and a few imperative steps to be called. This is the case because
|
Major PostgreSQL upgrades require a downtime and a few imperative
|
||||||
each major version has some internal changes in the databases' state during major releases. Because of that,
|
steps to be called. This is the case because each major version
|
||||||
NixOS places the state into <filename>/var/lib/postgresql/<version></filename> where each <literal>version</literal>
|
has some internal changes in the databases’ state during major
|
||||||
can be obtained like this:
|
releases. Because of that, NixOS places the state into
|
||||||
|
<filename>/var/lib/postgresql/<version></filename> where
|
||||||
|
each <literal>version</literal> can be obtained like this:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<prompt>$ </prompt>nix-instantiate --eval -A postgresql_13.psqlSchema
|
$ nix-instantiate --eval -A postgresql_13.psqlSchema
|
||||||
"13"
|
"13"
|
||||||
</programlisting>
|
</programlisting>
|
||||||
For an upgrade, a script like this can be used to simplify the process:
|
<para>
|
||||||
|
For an upgrade, a script like this can be used to simplify the
|
||||||
|
process:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
{
|
{
|
||||||
<xref linkend="opt-environment.systemPackages" /> = [
|
environment.systemPackages = [
|
||||||
(let
|
(let
|
||||||
# XXX specify the postgresql package you'd like to upgrade to.
|
# XXX specify the postgresql package you'd like to upgrade to.
|
||||||
# Do not forget to list the extensions you need.
|
# Do not forget to list the extensions you need.
|
||||||
newPostgres = pkgs.postgresql_13.withPackages (pp: [
|
newPostgres = pkgs.postgresql_13.withPackages (pp: [
|
||||||
# pp.plv8
|
# pp.plv8
|
||||||
]);
|
]);
|
||||||
in pkgs.writeScriptBin "upgrade-pg-cluster" ''
|
in pkgs.writeScriptBin "upgrade-pg-cluster" ''
|
||||||
set -eux
|
set -eux
|
||||||
# XXX it's perhaps advisable to stop all services that depend on postgresql
|
# XXX it's perhaps advisable to stop all services that depend on postgresql
|
||||||
systemctl stop postgresql
|
systemctl stop postgresql
|
||||||
|
|
||||||
export NEWDATA="/var/lib/postgresql/${newPostgres.psqlSchema}"
|
export NEWDATA="/var/lib/postgresql/${newPostgres.psqlSchema}"
|
||||||
|
|
||||||
export NEWBIN="${newPostgres}/bin"
|
export NEWBIN="${newPostgres}/bin"
|
||||||
|
|
||||||
export OLDDATA="${config.<xref linkend="opt-services.postgresql.dataDir"/>}"
|
export OLDDATA="${config.services.postgresql.dataDir}"
|
||||||
export OLDBIN="${config.<xref linkend="opt-services.postgresql.package"/>}/bin"
|
export OLDBIN="${config.services.postgresql.package}/bin"
|
||||||
|
|
||||||
install -d -m 0700 -o postgres -g postgres "$NEWDATA"
|
install -d -m 0700 -o postgres -g postgres "$NEWDATA"
|
||||||
cd "$NEWDATA"
|
cd "$NEWDATA"
|
||||||
sudo -u postgres $NEWBIN/initdb -D "$NEWDATA"
|
sudo -u postgres $NEWBIN/initdb -D "$NEWDATA"
|
||||||
|
|
||||||
sudo -u postgres $NEWBIN/pg_upgrade \
|
sudo -u postgres $NEWBIN/pg_upgrade \
|
||||||
--old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \
|
--old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \
|
||||||
--old-bindir $OLDBIN --new-bindir $NEWBIN \
|
--old-bindir $OLDBIN --new-bindir $NEWBIN \
|
||||||
"$@"
|
"$@"
|
||||||
'')
|
'')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The upgrade process is:
|
The upgrade process is:
|
||||||
</para>
|
</para>
|
||||||
|
<orderedlist numeration="arabic">
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Rebuild nixos configuration with the configuration above added to your <filename>configuration.nix</filename>. Alternatively, add that into separate file and reference it in <literal>imports</literal> list.
|
Rebuild nixos configuration with the configuration above added
|
||||||
|
to your <filename>configuration.nix</filename>. Alternatively,
|
||||||
|
add that into separate file and reference it in
|
||||||
|
<literal>imports</literal> list.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -121,61 +119,81 @@ Type "help" for help.
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Run <literal>upgrade-pg-cluster</literal>. It will stop old postgresql, initialize a new one and migrate the old one to the new one. You may supply arguments like <literal>--jobs 4</literal> and <literal>--link</literal> to speedup migration process. See <link xlink:href="https://www.postgresql.org/docs/current/pgupgrade.html" /> for details.
|
Run <literal>upgrade-pg-cluster</literal>. It will stop old
|
||||||
|
postgresql, initialize a new one and migrate the old one to
|
||||||
|
the new one. You may supply arguments like
|
||||||
|
<literal>--jobs 4</literal> and <literal>--link</literal> to
|
||||||
|
speedup migration process. See
|
||||||
|
<link xlink:href="https://www.postgresql.org/docs/current/pgupgrade.html">https://www.postgresql.org/docs/current/pgupgrade.html</link>
|
||||||
|
for details.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Change postgresql package in NixOS configuration to the one you were upgrading to via <xref linkend="opt-services.postgresql.package" />. Rebuild NixOS. This should start new postgres using upgraded data directory and all services you stopped during the upgrade.
|
Change postgresql package in NixOS configuration to the one
|
||||||
|
you were upgrading to via
|
||||||
|
<xref linkend="opt-services.postgresql.package" />. Rebuild
|
||||||
|
NixOS. This should start new postgres using upgraded data
|
||||||
|
directory and all services you stopped during the upgrade.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
After the upgrade it's advisable to analyze the new cluster.
|
After the upgrade it’s advisable to analyze the new cluster.
|
||||||
</para>
|
</para>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
For PostgreSQL ≥ 14, use the <literal>vacuumdb</literal> command printed by the upgrades script.
|
For PostgreSQL ≥ 14, use the <literal>vacuumdb</literal>
|
||||||
|
command printed by the upgrades script.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
For PostgreSQL < 14, run (as <literal>su -l postgres</literal> in the <xref linkend="opt-services.postgresql.dataDir" />, in this example <filename>/var/lib/postgresql/13</filename>):
|
For PostgreSQL < 14, run (as
|
||||||
<programlisting>
|
<literal>su -l postgres</literal> in the
|
||||||
<prompt>$ </prompt>./analyze_new_cluster.sh
|
<xref linkend="opt-services.postgresql.dataDir" />, in
|
||||||
</programlisting>
|
this example <filename>/var/lib/postgresql/13</filename>):
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ ./analyze_new_cluster.sh
|
||||||
|
</programlisting>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
<warning>
|
||||||
<para>
|
<para>
|
||||||
<warning><para>The next step removes the old state-directory!</para></warning>
|
The next step removes the old state-directory!
|
||||||
<programlisting>
|
|
||||||
<prompt>$ </prompt>./delete_old_cluster.sh
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
</warning>
|
||||||
|
<programlisting>
|
||||||
|
$ ./delete_old_cluster.sh
|
||||||
|
</programlisting>
|
||||||
</listitem>
|
</listitem>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-postgres-options">
|
<section xml:id="module-services-postgres-options">
|
||||||
<title>Options</title>
|
<title>Options</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A complete list of options for the PostgreSQL module may be found <link linkend="opt-services.postgresql.enable">here</link>.
|
A complete list of options for the PostgreSQL module may be found
|
||||||
|
<link linkend="opt-services.postgresql.enable">here</link>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-postgres-plugins">
|
<section xml:id="module-services-postgres-plugins">
|
||||||
<title>Plugins</title>
|
<title>Plugins</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Plugins collection for each PostgreSQL version can be accessed with <literal>.pkgs</literal>. For example, for <literal>pkgs.postgresql_11</literal> package, its plugin collection is accessed by <literal>pkgs.postgresql_11.pkgs</literal>:
|
Plugins collection for each PostgreSQL version can be accessed
|
||||||
<screen>
|
with <literal>.pkgs</literal>. For example, for
|
||||||
<prompt>$ </prompt>nix repl '<nixpkgs>'
|
<literal>pkgs.postgresql_11</literal> package, its plugin
|
||||||
|
collection is accessed by
|
||||||
|
<literal>pkgs.postgresql_11.pkgs</literal>:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ nix repl '<nixpkgs>'
|
||||||
|
|
||||||
Loading '<nixpkgs>'...
|
Loading '<nixpkgs>'...
|
||||||
Added 10574 variables.
|
Added 10574 variables.
|
||||||
|
|
||||||
<prompt>nix-repl> </prompt>postgresql_11.pkgs.<TAB><TAB>
|
nix-repl> postgresql_11.pkgs.<TAB><TAB>
|
||||||
postgresql_11.pkgs.cstore_fdw postgresql_11.pkgs.pg_repack
|
postgresql_11.pkgs.cstore_fdw postgresql_11.pkgs.pg_repack
|
||||||
postgresql_11.pkgs.pg_auto_failover postgresql_11.pkgs.pg_safeupdate
|
postgresql_11.pkgs.pg_auto_failover postgresql_11.pkgs.pg_safeupdate
|
||||||
postgresql_11.pkgs.pg_bigm postgresql_11.pkgs.pg_similarity
|
postgresql_11.pkgs.pg_bigm postgresql_11.pkgs.pg_similarity
|
||||||
|
@ -183,22 +201,24 @@ postgresql_11.pkgs.pg_cron postgresql_11.pkgs.pg_topn
|
||||||
postgresql_11.pkgs.pg_hll postgresql_11.pkgs.pgjwt
|
postgresql_11.pkgs.pg_hll postgresql_11.pkgs.pgjwt
|
||||||
postgresql_11.pkgs.pg_partman postgresql_11.pkgs.pgroonga
|
postgresql_11.pkgs.pg_partman postgresql_11.pkgs.pgroonga
|
||||||
...
|
...
|
||||||
</screen>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To add plugins via NixOS configuration, set <literal>services.postgresql.extraPlugins</literal>:
|
To add plugins via NixOS configuration, set
|
||||||
|
<literal>services.postgresql.extraPlugins</literal>:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_11;
|
services.postgresql.package = pkgs.postgresql_11;
|
||||||
<xref linkend="opt-services.postgresql.extraPlugins"/> = with pkgs.postgresql_11.pkgs; [
|
services.postgresql.extraPlugins = with pkgs.postgresql_11.pkgs; [
|
||||||
pg_repack
|
pg_repack
|
||||||
postgis
|
postgis
|
||||||
];
|
];
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
You can build custom PostgreSQL-with-plugins (to be used outside of NixOS) using function <literal>.withPackages</literal>. For example, creating a custom PostgreSQL package in an overlay can look like:
|
You can build custom PostgreSQL-with-plugins (to be used outside
|
||||||
|
of NixOS) using function <literal>.withPackages</literal>. For
|
||||||
|
example, creating a custom PostgreSQL package in an overlay can
|
||||||
|
look like:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
self: super: {
|
self: super: {
|
||||||
postgresql_custom = self.postgresql_11.withPackages (ps: [
|
postgresql_custom = self.postgresql_11.withPackages (ps: [
|
||||||
|
@ -207,25 +227,24 @@ self: super: {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Here's a recipe on how to override a particular plugin through an overlay:
|
Here’s a recipe on how to override a particular plugin through an
|
||||||
|
overlay:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
self: super: {
|
self: super: {
|
||||||
postgresql_11 = super.postgresql_11.override { this = self.postgresql_11; } // {
|
postgresql_11 = super.postgresql_11.override { this = self.postgresql_11; } // {
|
||||||
pkgs = super.postgresql_11.pkgs // {
|
pkgs = super.postgresql_11.pkgs // {
|
||||||
pg_repack = super.postgresql_11.pkgs.pg_repack.overrideAttrs (_: {
|
pg_repack = super.postgresql_11.pkgs.pg_repack.overrideAttrs (_: {
|
||||||
name = "pg_repack-v20181024";
|
name = "pg_repack-v20181024";
|
||||||
src = self.fetchzip {
|
src = self.fetchzip {
|
||||||
url = "https://github.com/reorg/pg_repack/archive/923fa2f3c709a506e111cc963034bf2fd127aa00.tar.gz";
|
url = "https://github.com/reorg/pg_repack/archive/923fa2f3c709a506e111cc963034bf2fd127aa00.tar.gz";
|
||||||
sha256 = "17k6hq9xaax87yz79j773qyigm4fwk8z4zh5cyp6z0sxnwfqxxw5";
|
sha256 = "17k6hq9xaax87yz79j773qyigm4fwk8z4zh5cyp6z0sxnwfqxxw5";
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
39
nixos/modules/services/desktops/flatpak.md
Normal file
39
nixos/modules/services/desktops/flatpak.md
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# Flatpak {#module-services-flatpak}
|
||||||
|
|
||||||
|
*Source:* {file}`modules/services/desktop/flatpak.nix`
|
||||||
|
|
||||||
|
*Upstream documentation:* <https://github.com/flatpak/flatpak/wiki>
|
||||||
|
|
||||||
|
Flatpak is a system for building, distributing, and running sandboxed desktop
|
||||||
|
applications on Linux.
|
||||||
|
|
||||||
|
To enable Flatpak, add the following to your {file}`configuration.nix`:
|
||||||
|
```
|
||||||
|
services.flatpak.enable = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
For the sandboxed apps to work correctly, desktop integration portals need to
|
||||||
|
be installed. If you run GNOME, this will be handled automatically for you;
|
||||||
|
in other cases, you will need to add something like the following to your
|
||||||
|
{file}`configuration.nix`:
|
||||||
|
```
|
||||||
|
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, you will need to add a repository, for example,
|
||||||
|
[Flathub](https://github.com/flatpak/flatpak/wiki),
|
||||||
|
either using the following commands:
|
||||||
|
```ShellSession
|
||||||
|
$ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||||
|
$ flatpak update
|
||||||
|
```
|
||||||
|
or by opening the
|
||||||
|
[repository file](https://flathub.org/repo/flathub.flatpakrepo) in GNOME Software.
|
||||||
|
|
||||||
|
Finally, you can search and install programs:
|
||||||
|
```ShellSession
|
||||||
|
$ flatpak search bustle
|
||||||
|
$ flatpak install flathub org.freedesktop.Bustle
|
||||||
|
$ flatpak run org.freedesktop.Bustle
|
||||||
|
```
|
||||||
|
Again, GNOME Software offers graphical interface for these tasks.
|
|
@ -1,8 +1,6 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-flatpak">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-flatpak">
|
|
||||||
<title>Flatpak</title>
|
<title>Flatpak</title>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Source:</emphasis>
|
<emphasis>Source:</emphasis>
|
||||||
|
@ -10,47 +8,52 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Upstream documentation:</emphasis>
|
<emphasis>Upstream documentation:</emphasis>
|
||||||
<link xlink:href="https://github.com/flatpak/flatpak/wiki"/>
|
<link xlink:href="https://github.com/flatpak/flatpak/wiki">https://github.com/flatpak/flatpak/wiki</link>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Flatpak is a system for building, distributing, and running sandboxed desktop
|
Flatpak is a system for building, distributing, and running
|
||||||
applications on Linux.
|
sandboxed desktop applications on Linux.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To enable Flatpak, add the following to your
|
To enable Flatpak, add the following to your
|
||||||
<filename>configuration.nix</filename>:
|
<filename>configuration.nix</filename>:
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-services.flatpak.enable"/> = true;
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
services.flatpak.enable = true;
|
||||||
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
For the sandboxed apps to work correctly, desktop integration portals need to
|
For the sandboxed apps to work correctly, desktop integration
|
||||||
be installed. If you run GNOME, this will be handled automatically for you;
|
portals need to be installed. If you run GNOME, this will be handled
|
||||||
in other cases, you will need to add something like the following to your
|
automatically for you; in other cases, you will need to add
|
||||||
|
something like the following to your
|
||||||
<filename>configuration.nix</filename>:
|
<filename>configuration.nix</filename>:
|
||||||
<programlisting>
|
|
||||||
<xref linkend="opt-xdg.portal.extraPortals"/> = [ pkgs.xdg-desktop-portal-gtk ];
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
|
||||||
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Then, you will need to add a repository, for example,
|
Then, you will need to add a repository, for example,
|
||||||
<link xlink:href="https://github.com/flatpak/flatpak/wiki">Flathub</link>,
|
<link xlink:href="https://github.com/flatpak/flatpak/wiki">Flathub</link>,
|
||||||
either using the following commands:
|
either using the following commands:
|
||||||
<screen>
|
</para>
|
||||||
<prompt>$ </prompt>flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
<programlisting>
|
||||||
<prompt>$ </prompt>flatpak update
|
$ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||||
</screen>
|
$ flatpak update
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
or by opening the
|
or by opening the
|
||||||
<link xlink:href="https://flathub.org/repo/flathub.flatpakrepo">repository
|
<link xlink:href="https://flathub.org/repo/flathub.flatpakrepo">repository
|
||||||
file</link> in GNOME Software.
|
file</link> in GNOME Software.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Finally, you can search and install programs:
|
Finally, you can search and install programs:
|
||||||
<screen>
|
</para>
|
||||||
<prompt>$ </prompt>flatpak search bustle
|
<programlisting>
|
||||||
<prompt>$ </prompt>flatpak install flathub org.freedesktop.Bustle
|
$ flatpak search bustle
|
||||||
<prompt>$ </prompt>flatpak run org.freedesktop.Bustle
|
$ flatpak install flathub org.freedesktop.Bustle
|
||||||
</screen>
|
$ flatpak run org.freedesktop.Bustle
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
Again, GNOME Software offers graphical interface for these tasks.
|
Again, GNOME Software offers graphical interface for these tasks.
|
||||||
</para>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
39
nixos/modules/services/development/blackfire.md
Normal file
39
nixos/modules/services/development/blackfire.md
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# Blackfire profiler {#module-services-blackfire}
|
||||||
|
|
||||||
|
*Source:* {file}`modules/services/development/blackfire.nix`
|
||||||
|
|
||||||
|
*Upstream documentation:* <https://blackfire.io/docs/introduction>
|
||||||
|
|
||||||
|
[Blackfire](https://blackfire.io) is a proprietary tool for profiling applications. There are several languages supported by the product but currently only PHP support is packaged in Nixpkgs. The back-end consists of a module that is loaded into the language runtime (called *probe*) and a service (*agent*) that the probe connects to and that sends the profiles to the server.
|
||||||
|
|
||||||
|
To use it, you will need to enable the agent and the probe on your server. The exact method will depend on the way you use PHP but here is an example of NixOS configuration for PHP-FPM:
|
||||||
|
```
|
||||||
|
let
|
||||||
|
php = pkgs.php.withExtensions ({ enabled, all }: enabled ++ (with all; [
|
||||||
|
blackfire
|
||||||
|
]));
|
||||||
|
in {
|
||||||
|
# Enable the probe extension for PHP-FPM.
|
||||||
|
services.phpfpm = {
|
||||||
|
phpPackage = php;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable and configure the agent.
|
||||||
|
services.blackfire-agent = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
# You will need to get credentials at https://blackfire.io/my/settings/credentials
|
||||||
|
# You can also use other options described in https://blackfire.io/docs/up-and-running/configuration/agent
|
||||||
|
server-id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
|
||||||
|
server-token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Make the agent run on start-up.
|
||||||
|
# (WantedBy= from the upstream unit not respected: https://github.com/NixOS/nixpkgs/issues/81138)
|
||||||
|
# Alternately, you can start it manually with `systemctl start blackfire-agent`.
|
||||||
|
systemd.services.blackfire-agent.wantedBy = [ "phpfpm-foo.service" ];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
On your developer machine, you will also want to install [the client](https://blackfire.io/docs/up-and-running/installation#install-a-profiling-client) (see `blackfire` package) or the browser extension to actually trigger the profiling.
|
|
@ -1,4 +1,6 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="module-services-blackfire">
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-blackfire">
|
||||||
<title>Blackfire profiler</title>
|
<title>Blackfire profiler</title>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Source:</emphasis>
|
<emphasis>Source:</emphasis>
|
||||||
|
@ -6,14 +8,24 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Upstream documentation:</emphasis>
|
<emphasis>Upstream documentation:</emphasis>
|
||||||
<link xlink:href="https://blackfire.io/docs/introduction"/>
|
<link xlink:href="https://blackfire.io/docs/introduction">https://blackfire.io/docs/introduction</link>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://blackfire.io">Blackfire</link> is a proprietary tool for profiling applications. There are several languages supported by the product but currently only PHP support is packaged in Nixpkgs. The back-end consists of a module that is loaded into the language runtime (called <firstterm>probe</firstterm>) and a service (<firstterm>agent</firstterm>) that the probe connects to and that sends the profiles to the server.
|
<link xlink:href="https://blackfire.io">Blackfire</link> is a
|
||||||
|
proprietary tool for profiling applications. There are several
|
||||||
|
languages supported by the product but currently only PHP support is
|
||||||
|
packaged in Nixpkgs. The back-end consists of a module that is
|
||||||
|
loaded into the language runtime (called <emphasis>probe</emphasis>)
|
||||||
|
and a service (<emphasis>agent</emphasis>) that the probe connects
|
||||||
|
to and that sends the profiles to the server.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To use it, you will need to enable the agent and the probe on your server. The exact method will depend on the way you use PHP but here is an example of NixOS configuration for PHP-FPM:
|
To use it, you will need to enable the agent and the probe on your
|
||||||
<programlisting>let
|
server. The exact method will depend on the way you use PHP but here
|
||||||
|
is an example of NixOS configuration for PHP-FPM:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
let
|
||||||
php = pkgs.php.withExtensions ({ enabled, all }: enabled ++ (with all; [
|
php = pkgs.php.withExtensions ({ enabled, all }: enabled ++ (with all; [
|
||||||
blackfire
|
blackfire
|
||||||
]));
|
]));
|
||||||
|
@ -29,18 +41,21 @@ in {
|
||||||
settings = {
|
settings = {
|
||||||
# You will need to get credentials at https://blackfire.io/my/settings/credentials
|
# You will need to get credentials at https://blackfire.io/my/settings/credentials
|
||||||
# You can also use other options described in https://blackfire.io/docs/up-and-running/configuration/agent
|
# You can also use other options described in https://blackfire.io/docs/up-and-running/configuration/agent
|
||||||
server-id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
|
server-id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
|
||||||
server-token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
server-token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Make the agent run on start-up.
|
# Make the agent run on start-up.
|
||||||
# (WantedBy= from the upstream unit not respected: https://github.com/NixOS/nixpkgs/issues/81138)
|
# (WantedBy= from the upstream unit not respected: https://github.com/NixOS/nixpkgs/issues/81138)
|
||||||
# Alternately, you can start it manually with `systemctl start blackfire-agent`.
|
# Alternately, you can start it manually with `systemctl start blackfire-agent`.
|
||||||
systemd.services.blackfire-agent.wantedBy = [ "phpfpm-foo.service" ];
|
systemd.services.blackfire-agent.wantedBy = [ "phpfpm-foo.service" ];
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
On your developer machine, you will also want to install <link xlink:href="https://blackfire.io/docs/up-and-running/installation#install-a-profiling-client">the client</link> (see <package>blackfire</package> package) or the browser extension to actually trigger the profiling.
|
On your developer machine, you will also want to install
|
||||||
|
<link xlink:href="https://blackfire.io/docs/up-and-running/installation#install-a-profiling-client">the
|
||||||
|
client</link> (see <literal>blackfire</literal> package) or the
|
||||||
|
browser extension to actually trigger the profiling.
|
||||||
</para>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
399
nixos/modules/services/editors/emacs.md
Normal file
399
nixos/modules/services/editors/emacs.md
Normal file
|
@ -0,0 +1,399 @@
|
||||||
|
# Emacs {#module-services-emacs}
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Documentation contributors:
|
||||||
|
Damien Cassou @DamienCassou
|
||||||
|
Thomas Tuegel @ttuegel
|
||||||
|
Rodney Lorrimar @rvl
|
||||||
|
Adam Hoese @adisbladis
|
||||||
|
-->
|
||||||
|
|
||||||
|
[Emacs](https://www.gnu.org/software/emacs/) is an
|
||||||
|
extensible, customizable, self-documenting real-time display editor — and
|
||||||
|
more. At its core is an interpreter for Emacs Lisp, a dialect of the Lisp
|
||||||
|
programming language with extensions to support text editing.
|
||||||
|
|
||||||
|
Emacs runs within a graphical desktop environment using the X Window System,
|
||||||
|
but works equally well on a text terminal. Under
|
||||||
|
macOS, a "Mac port" edition is available, which
|
||||||
|
uses Apple's native GUI frameworks.
|
||||||
|
|
||||||
|
Nixpkgs provides a superior environment for
|
||||||
|
running Emacs. It's simple to create custom builds
|
||||||
|
by overriding the default packages. Chaotic collections of Emacs Lisp code
|
||||||
|
and extensions can be brought under control using declarative package
|
||||||
|
management. NixOS even provides a
|
||||||
|
{command}`systemd` user service for automatically starting the Emacs
|
||||||
|
daemon.
|
||||||
|
|
||||||
|
## Installing Emacs {#module-services-emacs-installing}
|
||||||
|
|
||||||
|
Emacs can be installed in the normal way for Nix (see
|
||||||
|
[](#sec-package-management)). In addition, a NixOS
|
||||||
|
*service* can be enabled.
|
||||||
|
|
||||||
|
### The Different Releases of Emacs {#module-services-emacs-releases}
|
||||||
|
|
||||||
|
Nixpkgs defines several basic Emacs packages.
|
||||||
|
The following are attributes belonging to the {var}`pkgs` set:
|
||||||
|
|
||||||
|
{var}`emacs`
|
||||||
|
: The latest stable version of Emacs using the [GTK 2](http://www.gtk.org)
|
||||||
|
widget toolkit.
|
||||||
|
|
||||||
|
{var}`emacs-nox`
|
||||||
|
: Emacs built without any dependency on X11 libraries.
|
||||||
|
|
||||||
|
{var}`emacsMacport`
|
||||||
|
: Emacs with the "Mac port" patches, providing a more native look and
|
||||||
|
feel under macOS.
|
||||||
|
|
||||||
|
If those aren't suitable, then the following imitation Emacs editors are
|
||||||
|
also available in Nixpkgs:
|
||||||
|
[Zile](https://www.gnu.org/software/zile/),
|
||||||
|
[mg](http://homepage.boetes.org/software/mg/),
|
||||||
|
[Yi](http://yi-editor.github.io/),
|
||||||
|
[jmacs](https://joe-editor.sourceforge.io/).
|
||||||
|
|
||||||
|
### Adding Packages to Emacs {#module-services-emacs-adding-packages}
|
||||||
|
|
||||||
|
Emacs includes an entire ecosystem of functionality beyond text editing,
|
||||||
|
including a project planner, mail and news reader, debugger interface,
|
||||||
|
calendar, and more.
|
||||||
|
|
||||||
|
Most extensions are gotten with the Emacs packaging system
|
||||||
|
({file}`package.el`) from
|
||||||
|
[Emacs Lisp Package Archive (ELPA)](https://elpa.gnu.org/),
|
||||||
|
[MELPA](https://melpa.org/),
|
||||||
|
[MELPA Stable](https://stable.melpa.org/), and
|
||||||
|
[Org ELPA](http://orgmode.org/elpa.html). Nixpkgs is
|
||||||
|
regularly updated to mirror all these archives.
|
||||||
|
|
||||||
|
Under NixOS, you can continue to use
|
||||||
|
`package-list-packages` and
|
||||||
|
`package-install` to install packages. You can also
|
||||||
|
declare the set of Emacs packages you need using the derivations from
|
||||||
|
Nixpkgs. The rest of this section discusses declarative installation of
|
||||||
|
Emacs packages through nixpkgs.
|
||||||
|
|
||||||
|
The first step to declare the list of packages you want in your Emacs
|
||||||
|
installation is to create a dedicated derivation. This can be done in a
|
||||||
|
dedicated {file}`emacs.nix` file such as:
|
||||||
|
|
||||||
|
[]{#ex-emacsNix}
|
||||||
|
|
||||||
|
```nix
|
||||||
|
/*
|
||||||
|
This is a nix expression to build Emacs and some Emacs packages I like
|
||||||
|
from source on any distribution where Nix is installed. This will install
|
||||||
|
all the dependencies from the nixpkgs repository and build the binary files
|
||||||
|
without interfering with the host distribution.
|
||||||
|
|
||||||
|
To build the project, type the following from the current directory:
|
||||||
|
|
||||||
|
$ nix-build emacs.nix
|
||||||
|
|
||||||
|
To run the newly compiled executable:
|
||||||
|
|
||||||
|
$ ./result/bin/emacs
|
||||||
|
*/
|
||||||
|
|
||||||
|
# The first non-comment line in this file indicates that
|
||||||
|
# the whole file represents a function.
|
||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
|
||||||
|
let
|
||||||
|
# The let expression below defines a myEmacs binding pointing to the
|
||||||
|
# current stable version of Emacs. This binding is here to separate
|
||||||
|
# the choice of the Emacs binary from the specification of the
|
||||||
|
# required packages.
|
||||||
|
myEmacs = pkgs.emacs;
|
||||||
|
# This generates an emacsWithPackages function. It takes a single
|
||||||
|
# argument: a function from a package set to a list of packages
|
||||||
|
# (the packages that will be available in Emacs).
|
||||||
|
emacsWithPackages = (pkgs.emacsPackagesFor myEmacs).emacsWithPackages;
|
||||||
|
in
|
||||||
|
# The rest of the file specifies the list of packages to install. In the
|
||||||
|
# example, two packages (magit and zerodark-theme) are taken from
|
||||||
|
# MELPA stable.
|
||||||
|
emacsWithPackages (epkgs: (with epkgs.melpaStablePackages; [
|
||||||
|
magit # ; Integrate git <C-x g>
|
||||||
|
zerodark-theme # ; Nicolas' theme
|
||||||
|
])
|
||||||
|
# Two packages (undo-tree and zoom-frm) are taken from MELPA.
|
||||||
|
++ (with epkgs.melpaPackages; [
|
||||||
|
undo-tree # ; <C-x u> to show the undo tree
|
||||||
|
zoom-frm # ; increase/decrease font size for all buffers %lt;C-x C-+>
|
||||||
|
])
|
||||||
|
# Three packages are taken from GNU ELPA.
|
||||||
|
++ (with epkgs.elpaPackages; [
|
||||||
|
auctex # ; LaTeX mode
|
||||||
|
beacon # ; highlight my cursor when scrolling
|
||||||
|
nameless # ; hide current package name everywhere in elisp code
|
||||||
|
])
|
||||||
|
# notmuch is taken from a nixpkgs derivation which contains an Emacs mode.
|
||||||
|
++ [
|
||||||
|
pkgs.notmuch # From main packages set
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
The result of this configuration will be an {command}`emacs`
|
||||||
|
command which launches Emacs with all of your chosen packages in the
|
||||||
|
{var}`load-path`.
|
||||||
|
|
||||||
|
You can check that it works by executing this in a terminal:
|
||||||
|
```ShellSession
|
||||||
|
$ nix-build emacs.nix
|
||||||
|
$ ./result/bin/emacs -q
|
||||||
|
```
|
||||||
|
and then typing `M-x package-initialize`. Check that you
|
||||||
|
can use all the packages you want in this Emacs instance. For example, try
|
||||||
|
switching to the zerodark theme through `M-x load-theme <RET> zerodark <RET> y`.
|
||||||
|
|
||||||
|
::: {.tip}
|
||||||
|
A few popular extensions worth checking out are: auctex, company,
|
||||||
|
edit-server, flycheck, helm, iedit, magit, multiple-cursors, projectile,
|
||||||
|
and yasnippet.
|
||||||
|
:::
|
||||||
|
|
||||||
|
The list of available packages in the various ELPA repositories can be seen
|
||||||
|
with the following commands:
|
||||||
|
[]{#module-services-emacs-querying-packages}
|
||||||
|
```
|
||||||
|
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.elpaPackages
|
||||||
|
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.melpaPackages
|
||||||
|
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.melpaStablePackages
|
||||||
|
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.orgPackages
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are on NixOS, you can install this particular Emacs for all users by
|
||||||
|
adding it to the list of system packages (see
|
||||||
|
[](#sec-declarative-package-mgmt)). Simply modify your file
|
||||||
|
{file}`configuration.nix` to make it contain:
|
||||||
|
[]{#module-services-emacs-configuration-nix}
|
||||||
|
```
|
||||||
|
{
|
||||||
|
environment.systemPackages = [
|
||||||
|
# [...]
|
||||||
|
(import /path/to/emacs.nix { inherit pkgs; })
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, the next {command}`nixos-rebuild switch` will take
|
||||||
|
care of adding your {command}`emacs` to the {var}`PATH`
|
||||||
|
environment variable (see [](#sec-changing-config)).
|
||||||
|
|
||||||
|
<!-- fixme: i think the following is better done with config.nix
|
||||||
|
https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides
|
||||||
|
-->
|
||||||
|
|
||||||
|
If you are not on NixOS or want to install this particular Emacs only for
|
||||||
|
yourself, you can do so by adding it to your
|
||||||
|
{file}`~/.config/nixpkgs/config.nix` (see
|
||||||
|
[Nixpkgs manual](https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides)):
|
||||||
|
[]{#module-services-emacs-config-nix}
|
||||||
|
```
|
||||||
|
{
|
||||||
|
packageOverrides = super: let self = super.pkgs; in {
|
||||||
|
myemacs = import /path/to/emacs.nix { pkgs = self; };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, the next `nix-env -f '<nixpkgs>' -iA
|
||||||
|
myemacs` will take care of adding your emacs to the
|
||||||
|
{var}`PATH` environment variable.
|
||||||
|
|
||||||
|
### Advanced Emacs Configuration {#module-services-emacs-advanced}
|
||||||
|
|
||||||
|
If you want, you can tweak the Emacs package itself from your
|
||||||
|
{file}`emacs.nix`. For example, if you want to have a
|
||||||
|
GTK 3-based Emacs instead of the default GTK 2-based binary and remove the
|
||||||
|
automatically generated {file}`emacs.desktop` (useful if you
|
||||||
|
only use {command}`emacsclient`), you can change your file
|
||||||
|
{file}`emacs.nix` in this way:
|
||||||
|
|
||||||
|
[]{#ex-emacsGtk3Nix}
|
||||||
|
```
|
||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
let
|
||||||
|
myEmacs = (pkgs.emacs.override {
|
||||||
|
# Use gtk3 instead of the default gtk2
|
||||||
|
withGTK3 = true;
|
||||||
|
withGTK2 = false;
|
||||||
|
}).overrideAttrs (attrs: {
|
||||||
|
# I don't want emacs.desktop file because I only use
|
||||||
|
# emacsclient.
|
||||||
|
postInstall = (attrs.postInstall or "") + ''
|
||||||
|
rm $out/share/applications/emacs.desktop
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
in [...]
|
||||||
|
```
|
||||||
|
|
||||||
|
After building this file as shown in [the example above](#ex-emacsNix), you
|
||||||
|
will get an GTK 3-based Emacs binary pre-loaded with your favorite packages.
|
||||||
|
|
||||||
|
## Running Emacs as a Service {#module-services-emacs-running}
|
||||||
|
|
||||||
|
NixOS provides an optional
|
||||||
|
{command}`systemd` service which launches
|
||||||
|
[Emacs daemon](https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html)
|
||||||
|
with the user's login session.
|
||||||
|
|
||||||
|
*Source:* {file}`modules/services/editors/emacs.nix`
|
||||||
|
|
||||||
|
### Enabling the Service {#module-services-emacs-enabling}
|
||||||
|
|
||||||
|
To install and enable the {command}`systemd` user service for Emacs
|
||||||
|
daemon, add the following to your {file}`configuration.nix`:
|
||||||
|
```
|
||||||
|
services.emacs.enable = true;
|
||||||
|
services.emacs.package = import /home/cassou/.emacs.d { pkgs = pkgs; };
|
||||||
|
```
|
||||||
|
|
||||||
|
The {var}`services.emacs.package` option allows a custom
|
||||||
|
derivation to be used, for example, one created by
|
||||||
|
`emacsWithPackages`.
|
||||||
|
|
||||||
|
Ensure that the Emacs server is enabled for your user's Emacs
|
||||||
|
configuration, either by customizing the {var}`server-mode`
|
||||||
|
variable, or by adding `(server-start)` to
|
||||||
|
{file}`~/.emacs.d/init.el`.
|
||||||
|
|
||||||
|
To start the daemon, execute the following:
|
||||||
|
```ShellSession
|
||||||
|
$ nixos-rebuild switch # to activate the new configuration.nix
|
||||||
|
$ systemctl --user daemon-reload # to force systemd reload
|
||||||
|
$ systemctl --user start emacs.service # to start the Emacs daemon
|
||||||
|
```
|
||||||
|
The server should now be ready to serve Emacs clients.
|
||||||
|
|
||||||
|
### Starting the client {#module-services-emacs-starting-client}
|
||||||
|
|
||||||
|
Ensure that the emacs server is enabled, either by customizing the
|
||||||
|
{var}`server-mode` variable, or by adding
|
||||||
|
`(server-start)` to {file}`~/.emacs`.
|
||||||
|
|
||||||
|
To connect to the emacs daemon, run one of the following:
|
||||||
|
```
|
||||||
|
emacsclient FILENAME
|
||||||
|
emacsclient --create-frame # opens a new frame (window)
|
||||||
|
emacsclient --create-frame --tty # opens a new frame on the current terminal
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring the {var}`EDITOR` variable {#module-services-emacs-editor-variable}
|
||||||
|
|
||||||
|
<!--<title>{command}`emacsclient` as the Default Editor</title>-->
|
||||||
|
|
||||||
|
If [](#opt-services.emacs.defaultEditor) is
|
||||||
|
`true`, the {var}`EDITOR` variable will be set
|
||||||
|
to a wrapper script which launches {command}`emacsclient`.
|
||||||
|
|
||||||
|
Any setting of {var}`EDITOR` in the shell config files will
|
||||||
|
override {var}`services.emacs.defaultEditor`. To make sure
|
||||||
|
{var}`EDITOR` refers to the Emacs wrapper script, remove any
|
||||||
|
existing {var}`EDITOR` assignment from
|
||||||
|
{file}`.profile`, {file}`.bashrc`,
|
||||||
|
{file}`.zshenv` or any other shell config file.
|
||||||
|
|
||||||
|
If you have formed certain bad habits when editing files, these can be
|
||||||
|
corrected with a shell alias to the wrapper script:
|
||||||
|
```
|
||||||
|
alias vi=$EDITOR
|
||||||
|
```
|
||||||
|
|
||||||
|
### Per-User Enabling of the Service {#module-services-emacs-per-user}
|
||||||
|
|
||||||
|
In general, {command}`systemd` user services are globally enabled
|
||||||
|
by symlinks in {file}`/etc/systemd/user`. In the case where
|
||||||
|
Emacs daemon is not wanted for all users, it is possible to install the
|
||||||
|
service but not globally enable it:
|
||||||
|
```
|
||||||
|
services.emacs.enable = false;
|
||||||
|
services.emacs.install = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
To enable the {command}`systemd` user service for just the
|
||||||
|
currently logged in user, run:
|
||||||
|
```
|
||||||
|
systemctl --user enable emacs
|
||||||
|
```
|
||||||
|
This will add the symlink
|
||||||
|
{file}`~/.config/systemd/user/emacs.service`.
|
||||||
|
|
||||||
|
## Configuring Emacs {#module-services-emacs-configuring}
|
||||||
|
|
||||||
|
The Emacs init file should be changed to load the extension packages at
|
||||||
|
startup:
|
||||||
|
[]{#module-services-emacs-package-initialisation}
|
||||||
|
```
|
||||||
|
(require 'package)
|
||||||
|
|
||||||
|
;; optional. makes unpure packages archives unavailable
|
||||||
|
(setq package-archives nil)
|
||||||
|
|
||||||
|
(setq package-enable-at-startup nil)
|
||||||
|
(package-initialize)
|
||||||
|
```
|
||||||
|
|
||||||
|
After the declarative emacs package configuration has been tested,
|
||||||
|
previously downloaded packages can be cleaned up by removing
|
||||||
|
{file}`~/.emacs.d/elpa` (do make a backup first, in case you
|
||||||
|
forgot a package).
|
||||||
|
|
||||||
|
<!--
|
||||||
|
todo: is it worth documenting customizations for
|
||||||
|
server-switch-hook, server-done-hook?
|
||||||
|
-->
|
||||||
|
|
||||||
|
### A Major Mode for Nix Expressions {#module-services-emacs-major-mode}
|
||||||
|
|
||||||
|
Of interest may be {var}`melpaPackages.nix-mode`, which
|
||||||
|
provides syntax highlighting for the Nix language. This is particularly
|
||||||
|
convenient if you regularly edit Nix files.
|
||||||
|
|
||||||
|
### Accessing man pages {#module-services-emacs-man-pages}
|
||||||
|
|
||||||
|
You can use `woman` to get completion of all available
|
||||||
|
man pages. For example, type `M-x woman <RET> nixos-rebuild <RET>.`
|
||||||
|
|
||||||
|
### Editing DocBook 5 XML Documents {#sec-emacs-docbook-xml}
|
||||||
|
|
||||||
|
Emacs includes
|
||||||
|
[nXML](https://www.gnu.org/software/emacs/manual/html_node/nxml-mode/Introduction.html),
|
||||||
|
a major-mode for validating and editing XML documents. When editing DocBook
|
||||||
|
5.0 documents, such as [this one](#book-nixos-manual),
|
||||||
|
nXML needs to be configured with the relevant schema, which is not
|
||||||
|
included.
|
||||||
|
|
||||||
|
To install the DocBook 5.0 schemas, either add
|
||||||
|
{var}`pkgs.docbook5` to [](#opt-environment.systemPackages)
|
||||||
|
([NixOS](#sec-declarative-package-mgmt)), or run
|
||||||
|
`nix-env -f '<nixpkgs>' -iA docbook5`
|
||||||
|
([Nix](#sec-ad-hoc-packages)).
|
||||||
|
|
||||||
|
Then customize the variable {var}`rng-schema-locating-files` to
|
||||||
|
include {file}`~/.emacs.d/schemas.xml` and put the following
|
||||||
|
text into that file:
|
||||||
|
[]{#ex-emacs-docbook-xml}
|
||||||
|
```xml
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
To let emacs find this file, evaluate:
|
||||||
|
(add-to-list 'rng-schema-locating-files "~/.emacs.d/schemas.xml")
|
||||||
|
-->
|
||||||
|
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||||
|
<!--
|
||||||
|
Use this variation if pkgs.docbook5 is added to environment.systemPackages
|
||||||
|
-->
|
||||||
|
<namespace ns="http://docbook.org/ns/docbook"
|
||||||
|
uri="/run/current-system/sw/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
|
||||||
|
<!--
|
||||||
|
Use this variation if installing schema with "nix-env -iA pkgs.docbook5".
|
||||||
|
<namespace ns="http://docbook.org/ns/docbook"
|
||||||
|
uri="../.nix-profile/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
|
||||||
|
-->
|
||||||
|
</locatingRules>
|
||||||
|
```
|
|
@ -1,66 +1,51 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-emacs">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-emacs">
|
|
||||||
<title>Emacs</title>
|
<title>Emacs</title>
|
||||||
<!--
|
|
||||||
Documentation contributors:
|
|
||||||
Damien Cassou @DamienCassou
|
|
||||||
Thomas Tuegel @ttuegel
|
|
||||||
Rodney Lorrimar @rvl
|
|
||||||
Adam Hoese @adisbladis
|
|
||||||
-->
|
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://www.gnu.org/software/emacs/">Emacs</link> is an
|
<link xlink:href="https://www.gnu.org/software/emacs/">Emacs</link>
|
||||||
extensible, customizable, self-documenting real-time display editor — and
|
is an extensible, customizable, self-documenting real-time display
|
||||||
more. At its core is an interpreter for Emacs Lisp, a dialect of the Lisp
|
editor — and more. At its core is an interpreter for Emacs Lisp, a
|
||||||
programming language with extensions to support text editing.
|
dialect of the Lisp programming language with extensions to support
|
||||||
|
text editing.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Emacs runs within a graphical desktop environment using the X Window System,
|
Emacs runs within a graphical desktop environment using the X Window
|
||||||
but works equally well on a text terminal. Under
|
System, but works equally well on a text terminal. Under macOS, a
|
||||||
<productname>macOS</productname>, a "Mac port" edition is available, which
|
<quote>Mac port</quote> edition is available, which uses Apple’s
|
||||||
uses Apple's native GUI frameworks.
|
native GUI frameworks.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<productname>Nixpkgs</productname> provides a superior environment for
|
Nixpkgs provides a superior environment for running Emacs. It’s
|
||||||
running <application>Emacs</application>. It's simple to create custom builds
|
simple to create custom builds by overriding the default packages.
|
||||||
by overriding the default packages. Chaotic collections of Emacs Lisp code
|
Chaotic collections of Emacs Lisp code and extensions can be brought
|
||||||
and extensions can be brought under control using declarative package
|
under control using declarative package management. NixOS even
|
||||||
management. <productname>NixOS</productname> even provides a
|
provides a <command>systemd</command> user service for automatically
|
||||||
<command>systemd</command> user service for automatically starting the Emacs
|
starting the Emacs daemon.
|
||||||
daemon.
|
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-emacs-installing">
|
<section xml:id="module-services-emacs-installing">
|
||||||
<title>Installing <application>Emacs</application></title>
|
<title>Installing Emacs</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Emacs can be installed in the normal way for Nix (see
|
Emacs can be installed in the normal way for Nix (see
|
||||||
<xref linkend="sec-package-management" />). In addition, a NixOS
|
<xref linkend="sec-package-management" />). In addition, a NixOS
|
||||||
<emphasis>service</emphasis> can be enabled.
|
<emphasis>service</emphasis> can be enabled.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-releases">
|
<section xml:id="module-services-emacs-releases">
|
||||||
<title>The Different Releases of Emacs</title>
|
<title>The Different Releases of Emacs</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<productname>Nixpkgs</productname> defines several basic Emacs packages.
|
Nixpkgs defines several basic Emacs packages. The following are
|
||||||
The following are attributes belonging to the <varname>pkgs</varname> set:
|
attributes belonging to the <varname>pkgs</varname> set:
|
||||||
<variablelist>
|
</para>
|
||||||
|
<variablelist spacing="compact">
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
|
||||||
<varname>emacs</varname>
|
|
||||||
</term>
|
|
||||||
<term>
|
<term>
|
||||||
<varname>emacs</varname>
|
<varname>emacs</varname>
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The latest stable version of Emacs using the
|
The latest stable version of Emacs using the
|
||||||
<link
|
<link xlink:href="http://www.gtk.org">GTK 2</link> widget
|
||||||
xlink:href="http://www.gtk.org">GTK 2</link>
|
toolkit.
|
||||||
widget toolkit.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -75,68 +60,61 @@
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
|
||||||
<varname>emacsMacport</varname>
|
|
||||||
</term>
|
|
||||||
<term>
|
<term>
|
||||||
<varname>emacsMacport</varname>
|
<varname>emacsMacport</varname>
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Emacs with the "Mac port" patches, providing a more native look and
|
Emacs with the <quote>Mac port</quote> patches, providing
|
||||||
feel under macOS.
|
a more native look and feel under macOS.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If those aren't suitable, then the following imitation Emacs editors are
|
If those aren’t suitable, then the following imitation Emacs
|
||||||
also available in Nixpkgs:
|
editors are also available in Nixpkgs:
|
||||||
<link xlink:href="https://www.gnu.org/software/zile/">Zile</link>,
|
<link xlink:href="https://www.gnu.org/software/zile/">Zile</link>,
|
||||||
<link xlink:href="http://homepage.boetes.org/software/mg/">mg</link>,
|
<link xlink:href="http://homepage.boetes.org/software/mg/">mg</link>,
|
||||||
<link xlink:href="http://yi-editor.github.io/">Yi</link>,
|
<link xlink:href="http://yi-editor.github.io/">Yi</link>,
|
||||||
<link xlink:href="https://joe-editor.sourceforge.io/">jmacs</link>.
|
<link xlink:href="https://joe-editor.sourceforge.io/">jmacs</link>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-adding-packages">
|
<section xml:id="module-services-emacs-adding-packages">
|
||||||
<title>Adding Packages to Emacs</title>
|
<title>Adding Packages to Emacs</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Emacs includes an entire ecosystem of functionality beyond text editing,
|
Emacs includes an entire ecosystem of functionality beyond text
|
||||||
including a project planner, mail and news reader, debugger interface,
|
editing, including a project planner, mail and news reader,
|
||||||
calendar, and more.
|
debugger interface, calendar, and more.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Most extensions are gotten with the Emacs packaging system
|
Most extensions are gotten with the Emacs packaging system
|
||||||
(<filename>package.el</filename>) from
|
(<filename>package.el</filename>) from
|
||||||
<link
|
<link xlink:href="https://elpa.gnu.org/">Emacs Lisp Package
|
||||||
xlink:href="https://elpa.gnu.org/">Emacs Lisp Package Archive
|
Archive (ELPA)</link>,
|
||||||
(<acronym>ELPA</acronym>)</link>,
|
<link xlink:href="https://melpa.org/">MELPA</link>,
|
||||||
<link xlink:href="https://melpa.org/"><acronym>MELPA</acronym></link>,
|
<link xlink:href="https://stable.melpa.org/">MELPA
|
||||||
<link xlink:href="https://stable.melpa.org/">MELPA Stable</link>, and
|
Stable</link>, and
|
||||||
<link xlink:href="http://orgmode.org/elpa.html">Org ELPA</link>. Nixpkgs is
|
<link xlink:href="http://orgmode.org/elpa.html">Org ELPA</link>.
|
||||||
regularly updated to mirror all these archives.
|
Nixpkgs is regularly updated to mirror all these archives.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Under NixOS, you can continue to use
|
Under NixOS, you can continue to use
|
||||||
<function>package-list-packages</function> and
|
<literal>package-list-packages</literal> and
|
||||||
<function>package-install</function> to install packages. You can also
|
<literal>package-install</literal> to install packages. You can
|
||||||
declare the set of Emacs packages you need using the derivations from
|
also declare the set of Emacs packages you need using the
|
||||||
Nixpkgs. The rest of this section discusses declarative installation of
|
derivations from Nixpkgs. The rest of this section discusses
|
||||||
Emacs packages through nixpkgs.
|
declarative installation of Emacs packages through nixpkgs.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The first step to declare the list of packages you want in your Emacs
|
The first step to declare the list of packages you want in your
|
||||||
installation is to create a dedicated derivation. This can be done in a
|
Emacs installation is to create a dedicated derivation. This can
|
||||||
dedicated <filename>emacs.nix</filename> file such as:
|
be done in a dedicated <filename>emacs.nix</filename> file such
|
||||||
<example xml:id="ex-emacsNix">
|
as:
|
||||||
<title>Nix expression to build Emacs with packages (<filename>emacs.nix</filename>)</title>
|
</para>
|
||||||
|
<para>
|
||||||
|
<anchor xml:id="ex-emacsNix" />
|
||||||
|
</para>
|
||||||
<programlisting language="nix">
|
<programlisting language="nix">
|
||||||
/*
|
/*
|
||||||
This is a nix expression to build Emacs and some Emacs packages I like
|
This is a nix expression to build Emacs and some Emacs packages I like
|
||||||
|
@ -152,185 +130,142 @@ To run the newly compiled executable:
|
||||||
|
|
||||||
$ ./result/bin/emacs
|
$ ./result/bin/emacs
|
||||||
*/
|
*/
|
||||||
{ pkgs ? import <nixpkgs> {} }: <co xml:id="ex-emacsNix-1" />
|
|
||||||
|
# The first non-comment line in this file indicates that
|
||||||
|
# the whole file represents a function.
|
||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
|
||||||
let
|
let
|
||||||
myEmacs = pkgs.emacs; <co xml:id="ex-emacsNix-2" />
|
# The let expression below defines a myEmacs binding pointing to the
|
||||||
emacsWithPackages = (pkgs.emacsPackagesFor myEmacs).emacsWithPackages; <co xml:id="ex-emacsNix-3" />
|
# current stable version of Emacs. This binding is here to separate
|
||||||
|
# the choice of the Emacs binary from the specification of the
|
||||||
|
# required packages.
|
||||||
|
myEmacs = pkgs.emacs;
|
||||||
|
# This generates an emacsWithPackages function. It takes a single
|
||||||
|
# argument: a function from a package set to a list of packages
|
||||||
|
# (the packages that will be available in Emacs).
|
||||||
|
emacsWithPackages = (pkgs.emacsPackagesFor myEmacs).emacsWithPackages;
|
||||||
in
|
in
|
||||||
emacsWithPackages (epkgs: (with epkgs.melpaStablePackages; [ <co xml:id="ex-emacsNix-4" />
|
# The rest of the file specifies the list of packages to install. In the
|
||||||
|
# example, two packages (magit and zerodark-theme) are taken from
|
||||||
|
# MELPA stable.
|
||||||
|
emacsWithPackages (epkgs: (with epkgs.melpaStablePackages; [
|
||||||
magit # ; Integrate git <C-x g>
|
magit # ; Integrate git <C-x g>
|
||||||
zerodark-theme # ; Nicolas' theme
|
zerodark-theme # ; Nicolas' theme
|
||||||
]) ++ (with epkgs.melpaPackages; [ <co xml:id="ex-emacsNix-5" />
|
])
|
||||||
|
# Two packages (undo-tree and zoom-frm) are taken from MELPA.
|
||||||
|
++ (with epkgs.melpaPackages; [
|
||||||
undo-tree # ; <C-x u> to show the undo tree
|
undo-tree # ; <C-x u> to show the undo tree
|
||||||
zoom-frm # ; increase/decrease font size for all buffers %lt;C-x C-+>
|
zoom-frm # ; increase/decrease font size for all buffers %lt;C-x C-+>
|
||||||
]) ++ (with epkgs.elpaPackages; [ <co xml:id="ex-emacsNix-6" />
|
])
|
||||||
|
# Three packages are taken from GNU ELPA.
|
||||||
|
++ (with epkgs.elpaPackages; [
|
||||||
auctex # ; LaTeX mode
|
auctex # ; LaTeX mode
|
||||||
beacon # ; highlight my cursor when scrolling
|
beacon # ; highlight my cursor when scrolling
|
||||||
nameless # ; hide current package name everywhere in elisp code
|
nameless # ; hide current package name everywhere in elisp code
|
||||||
]) ++ [
|
])
|
||||||
pkgs.notmuch # From main packages set <co xml:id="ex-emacsNix-7" />
|
# notmuch is taken from a nixpkgs derivation which contains an Emacs mode.
|
||||||
|
++ [
|
||||||
|
pkgs.notmuch # From main packages set
|
||||||
])
|
])
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</example>
|
|
||||||
<calloutlist>
|
|
||||||
<callout arearefs="ex-emacsNix-1">
|
|
||||||
<para>
|
<para>
|
||||||
The first non-comment line in this file (<literal>{ pkgs ? ...
|
The result of this configuration will be an
|
||||||
}</literal>) indicates that the whole file represents a function.
|
<command>emacs</command> command which launches Emacs with all
|
||||||
|
of your chosen packages in the <varname>load-path</varname>.
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
|
||||||
<callout arearefs="ex-emacsNix-2">
|
|
||||||
<para>
|
|
||||||
The <varname>let</varname> expression below defines a
|
|
||||||
<varname>myEmacs</varname> binding pointing to the current stable
|
|
||||||
version of Emacs. This binding is here to separate the choice of the
|
|
||||||
Emacs binary from the specification of the required packages.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="ex-emacsNix-3">
|
|
||||||
<para>
|
|
||||||
This generates an <varname>emacsWithPackages</varname> function. It
|
|
||||||
takes a single argument: a function from a package set to a list of
|
|
||||||
packages (the packages that will be available in Emacs).
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="ex-emacsNix-4">
|
|
||||||
<para>
|
|
||||||
The rest of the file specifies the list of packages to install. In the
|
|
||||||
example, two packages (<varname>magit</varname> and
|
|
||||||
<varname>zerodark-theme</varname>) are taken from MELPA stable.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="ex-emacsNix-5">
|
|
||||||
<para>
|
|
||||||
Two packages (<varname>undo-tree</varname> and
|
|
||||||
<varname>zoom-frm</varname>) are taken from MELPA.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="ex-emacsNix-6">
|
|
||||||
<para>
|
|
||||||
Three packages are taken from GNU ELPA.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="ex-emacsNix-7">
|
|
||||||
<para>
|
|
||||||
<varname>notmuch</varname> is taken from a nixpkgs derivation which
|
|
||||||
contains an Emacs mode.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
</calloutlist>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The result of this configuration will be an <command>emacs</command>
|
|
||||||
command which launches Emacs with all of your chosen packages in the
|
|
||||||
<varname>load-path</varname>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
You can check that it works by executing this in a terminal:
|
You can check that it works by executing this in a terminal:
|
||||||
<screen>
|
|
||||||
<prompt>$ </prompt>nix-build emacs.nix
|
|
||||||
<prompt>$ </prompt>./result/bin/emacs -q
|
|
||||||
</screen>
|
|
||||||
and then typing <literal>M-x package-initialize</literal>. Check that you
|
|
||||||
can use all the packages you want in this Emacs instance. For example, try
|
|
||||||
switching to the zerodark theme through <literal>M-x load-theme <RET>
|
|
||||||
zerodark <RET> y</literal>.
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ nix-build emacs.nix
|
||||||
|
$ ./result/bin/emacs -q
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
and then typing <literal>M-x package-initialize</literal>. Check
|
||||||
|
that you can use all the packages you want in this Emacs
|
||||||
|
instance. For example, try switching to the zerodark theme
|
||||||
|
through
|
||||||
|
<literal>M-x load-theme <RET> zerodark <RET> y</literal>.
|
||||||
|
</para>
|
||||||
<tip>
|
<tip>
|
||||||
<para>
|
<para>
|
||||||
A few popular extensions worth checking out are: auctex, company,
|
A few popular extensions worth checking out are: auctex,
|
||||||
edit-server, flycheck, helm, iedit, magit, multiple-cursors, projectile,
|
company, edit-server, flycheck, helm, iedit, magit,
|
||||||
and yasnippet.
|
multiple-cursors, projectile, and yasnippet.
|
||||||
</para>
|
</para>
|
||||||
</tip>
|
</tip>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The list of available packages in the various ELPA repositories can be seen
|
The list of available packages in the various ELPA repositories
|
||||||
with the following commands:
|
can be seen with the following commands:
|
||||||
<example xml:id="module-services-emacs-querying-packages">
|
<anchor xml:id="module-services-emacs-querying-packages" />
|
||||||
<title>Querying Emacs packages</title>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.elpaPackages
|
|
||||||
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.melpaPackages
|
|
||||||
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.melpaStablePackages
|
|
||||||
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.orgPackages
|
|
||||||
]]></programlisting>
|
|
||||||
</example>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.elpaPackages
|
||||||
|
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.melpaPackages
|
||||||
|
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.melpaStablePackages
|
||||||
|
nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.orgPackages
|
||||||
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
If you are on NixOS, you can install this particular Emacs for all users by
|
If you are on NixOS, you can install this particular Emacs for
|
||||||
adding it to the list of system packages (see
|
all users by adding it to the list of system packages (see
|
||||||
<xref linkend="sec-declarative-package-mgmt" />). Simply modify your file
|
<xref linkend="sec-declarative-package-mgmt" />). Simply modify
|
||||||
<filename>configuration.nix</filename> to make it contain:
|
your file <filename>configuration.nix</filename> to make it
|
||||||
<example xml:id="module-services-emacs-configuration-nix">
|
contain:
|
||||||
<title>Custom Emacs in <filename>configuration.nix</filename></title>
|
<anchor xml:id="module-services-emacs-configuration-nix" />
|
||||||
<programlisting><![CDATA[
|
</para>
|
||||||
|
<programlisting>
|
||||||
{
|
{
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
# [...]
|
# [...]
|
||||||
(import /path/to/emacs.nix { inherit pkgs; })
|
(import /path/to/emacs.nix { inherit pkgs; })
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
]]></programlisting>
|
</programlisting>
|
||||||
</example>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
In this case, the next <command>nixos-rebuild switch</command> will take
|
In this case, the next <command>nixos-rebuild switch</command>
|
||||||
care of adding your <command>emacs</command> to the <varname>PATH</varname>
|
will take care of adding your <command>emacs</command> to the
|
||||||
environment variable (see <xref linkend="sec-changing-config" />).
|
<varname>PATH</varname> environment variable (see
|
||||||
|
<xref linkend="sec-changing-config" />).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<!-- fixme: i think the following is better done with config.nix
|
|
||||||
https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides
|
|
||||||
-->
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you are not on NixOS or want to install this particular Emacs only for
|
If you are not on NixOS or want to install this particular Emacs
|
||||||
yourself, you can do so by adding it to your
|
only for yourself, you can do so by adding it to your
|
||||||
<filename>~/.config/nixpkgs/config.nix</filename> (see
|
<filename>~/.config/nixpkgs/config.nix</filename> (see
|
||||||
<link xlink:href="https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides">Nixpkgs
|
<link xlink:href="https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides">Nixpkgs
|
||||||
manual</link>):
|
manual</link>):
|
||||||
<example xml:id="module-services-emacs-config-nix">
|
<anchor xml:id="module-services-emacs-config-nix" />
|
||||||
<title>Custom Emacs in <filename>~/.config/nixpkgs/config.nix</filename></title>
|
</para>
|
||||||
<programlisting><![CDATA[
|
<programlisting>
|
||||||
{
|
{
|
||||||
packageOverrides = super: let self = super.pkgs; in {
|
packageOverrides = super: let self = super.pkgs; in {
|
||||||
myemacs = import /path/to/emacs.nix { pkgs = self; };
|
myemacs = import /path/to/emacs.nix { pkgs = self; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
]]></programlisting>
|
</programlisting>
|
||||||
</example>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
In this case, the next <literal>nix-env -f '<nixpkgs>' -iA
|
In this case, the next
|
||||||
myemacs</literal> will take care of adding your emacs to the
|
<literal>nix-env -f '<nixpkgs>' -iA myemacs</literal> will
|
||||||
<varname>PATH</varname> environment variable.
|
take care of adding your emacs to the <varname>PATH</varname>
|
||||||
|
environment variable.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-advanced">
|
<section xml:id="module-services-emacs-advanced">
|
||||||
<title>Advanced Emacs Configuration</title>
|
<title>Advanced Emacs Configuration</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you want, you can tweak the Emacs package itself from your
|
If you want, you can tweak the Emacs package itself from your
|
||||||
<filename>emacs.nix</filename>. For example, if you want to have a
|
<filename>emacs.nix</filename>. For example, if you want to have
|
||||||
GTK 3-based Emacs instead of the default GTK 2-based binary and remove the
|
a GTK 3-based Emacs instead of the default GTK 2-based binary
|
||||||
automatically generated <filename>emacs.desktop</filename> (useful if you
|
and remove the automatically generated
|
||||||
only use <command>emacsclient</command>), you can change your file
|
<filename>emacs.desktop</filename> (useful if you only use
|
||||||
|
<command>emacsclient</command>), you can change your file
|
||||||
<filename>emacs.nix</filename> in this way:
|
<filename>emacs.nix</filename> in this way:
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
<example xml:id="ex-emacsGtk3Nix">
|
<anchor xml:id="ex-emacsGtk3Nix" />
|
||||||
<title>Custom Emacs build</title>
|
</para>
|
||||||
<programlisting><![CDATA[
|
<programlisting>
|
||||||
{ pkgs ? import <nixpkgs> {} }:
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
let
|
let
|
||||||
myEmacs = (pkgs.emacs.override {
|
myEmacs = (pkgs.emacs.override {
|
||||||
# Use gtk3 instead of the default gtk2
|
# Use gtk3 instead of the default gtk2
|
||||||
|
@ -339,135 +274,130 @@ let
|
||||||
}).overrideAttrs (attrs: {
|
}).overrideAttrs (attrs: {
|
||||||
# I don't want emacs.desktop file because I only use
|
# I don't want emacs.desktop file because I only use
|
||||||
# emacsclient.
|
# emacsclient.
|
||||||
postInstall = (attrs.postInstall or "") + ''
|
postInstall = (attrs.postInstall or "") + ''
|
||||||
rm $out/share/applications/emacs.desktop
|
rm $out/share/applications/emacs.desktop
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
in [...]
|
in [...]
|
||||||
]]></programlisting>
|
</programlisting>
|
||||||
</example>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
After building this file as shown in <xref linkend="ex-emacsNix" />, you
|
After building this file as shown in
|
||||||
will get an GTK 3-based Emacs binary pre-loaded with your favorite packages.
|
<link linkend="ex-emacsNix">the example above</link>, you will
|
||||||
|
get an GTK 3-based Emacs binary pre-loaded with your favorite
|
||||||
|
packages.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-emacs-running">
|
<section xml:id="module-services-emacs-running">
|
||||||
<title>Running Emacs as a Service</title>
|
<title>Running Emacs as a Service</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<productname>NixOS</productname> provides an optional
|
NixOS provides an optional <command>systemd</command> service
|
||||||
<command>systemd</command> service which launches
|
which launches
|
||||||
<link xlink:href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html">
|
<link xlink:href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html">Emacs
|
||||||
Emacs daemon </link> with the user's login session.
|
daemon</link> with the user’s login session.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Source:</emphasis>
|
<emphasis>Source:</emphasis>
|
||||||
<filename>modules/services/editors/emacs.nix</filename>
|
<filename>modules/services/editors/emacs.nix</filename>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-enabling">
|
<section xml:id="module-services-emacs-enabling">
|
||||||
<title>Enabling the Service</title>
|
<title>Enabling the Service</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To install and enable the <command>systemd</command> user service for Emacs
|
To install and enable the <command>systemd</command> user
|
||||||
daemon, add the following to your <filename>configuration.nix</filename>:
|
service for Emacs daemon, add the following to your
|
||||||
|
<filename>configuration.nix</filename>:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<xref linkend="opt-services.emacs.enable"/> = true;
|
services.emacs.enable = true;
|
||||||
<xref linkend="opt-services.emacs.package"/> = import /home/cassou/.emacs.d { pkgs = pkgs; };
|
services.emacs.package = import /home/cassou/.emacs.d { pkgs = pkgs; };
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <varname>services.emacs.package</varname> option allows a custom
|
The <varname>services.emacs.package</varname> option allows a
|
||||||
derivation to be used, for example, one created by
|
custom derivation to be used, for example, one created by
|
||||||
<function>emacsWithPackages</function>.
|
<literal>emacsWithPackages</literal>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Ensure that the Emacs server is enabled for your user's Emacs
|
Ensure that the Emacs server is enabled for your user’s Emacs
|
||||||
configuration, either by customizing the <varname>server-mode</varname>
|
configuration, either by customizing the
|
||||||
variable, or by adding <literal>(server-start)</literal> to
|
<varname>server-mode</varname> variable, or by adding
|
||||||
|
<literal>(server-start)</literal> to
|
||||||
<filename>~/.emacs.d/init.el</filename>.
|
<filename>~/.emacs.d/init.el</filename>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To start the daemon, execute the following:
|
To start the daemon, execute the following:
|
||||||
<screen>
|
</para>
|
||||||
<prompt>$ </prompt>nixos-rebuild switch # to activate the new configuration.nix
|
<programlisting>
|
||||||
<prompt>$ </prompt>systemctl --user daemon-reload # to force systemd reload
|
$ nixos-rebuild switch # to activate the new configuration.nix
|
||||||
<prompt>$ </prompt>systemctl --user start emacs.service # to start the Emacs daemon
|
$ systemctl --user daemon-reload # to force systemd reload
|
||||||
</screen>
|
$ systemctl --user start emacs.service # to start the Emacs daemon
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
The server should now be ready to serve Emacs clients.
|
The server should now be ready to serve Emacs clients.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-starting-client">
|
<section xml:id="module-services-emacs-starting-client">
|
||||||
<title>Starting the client</title>
|
<title>Starting the client</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Ensure that the emacs server is enabled, either by customizing the
|
Ensure that the emacs server is enabled, either by customizing
|
||||||
<varname>server-mode</varname> variable, or by adding
|
the <varname>server-mode</varname> variable, or by adding
|
||||||
<literal>(server-start)</literal> to <filename>~/.emacs</filename>.
|
<literal>(server-start)</literal> to
|
||||||
|
<filename>~/.emacs</filename>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To connect to the emacs daemon, run one of the following:
|
To connect to the emacs daemon, run one of the following:
|
||||||
<programlisting><![CDATA[
|
</para>
|
||||||
|
<programlisting>
|
||||||
emacsclient FILENAME
|
emacsclient FILENAME
|
||||||
emacsclient --create-frame # opens a new frame (window)
|
emacsclient --create-frame # opens a new frame (window)
|
||||||
emacsclient --create-frame --tty # opens a new frame on the current terminal
|
emacsclient --create-frame --tty # opens a new frame on the current terminal
|
||||||
]]></programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-editor-variable">
|
<section xml:id="module-services-emacs-editor-variable">
|
||||||
<title>Configuring the <varname>EDITOR</varname> variable</title>
|
<title>Configuring the <varname>EDITOR</varname> variable</title>
|
||||||
|
|
||||||
<!--<title><command>emacsclient</command> as the Default Editor</title>-->
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If <xref linkend="opt-services.emacs.defaultEditor" /> is
|
If <xref linkend="opt-services.emacs.defaultEditor" /> is
|
||||||
<literal>true</literal>, the <varname>EDITOR</varname> variable will be set
|
<literal>true</literal>, the <varname>EDITOR</varname> variable
|
||||||
to a wrapper script which launches <command>emacsclient</command>.
|
will be set to a wrapper script which launches
|
||||||
|
<command>emacsclient</command>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Any setting of <varname>EDITOR</varname> in the shell config files will
|
Any setting of <varname>EDITOR</varname> in the shell config
|
||||||
override <varname>services.emacs.defaultEditor</varname>. To make sure
|
files will override
|
||||||
<varname>EDITOR</varname> refers to the Emacs wrapper script, remove any
|
<varname>services.emacs.defaultEditor</varname>. To make sure
|
||||||
existing <varname>EDITOR</varname> assignment from
|
<varname>EDITOR</varname> refers to the Emacs wrapper script,
|
||||||
|
remove any existing <varname>EDITOR</varname> assignment from
|
||||||
<filename>.profile</filename>, <filename>.bashrc</filename>,
|
<filename>.profile</filename>, <filename>.bashrc</filename>,
|
||||||
<filename>.zshenv</filename> or any other shell config file.
|
<filename>.zshenv</filename> or any other shell config file.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you have formed certain bad habits when editing files, these can be
|
If you have formed certain bad habits when editing files, these
|
||||||
corrected with a shell alias to the wrapper script:
|
can be corrected with a shell alias to the wrapper script:
|
||||||
<programlisting>alias vi=$EDITOR</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
alias vi=$EDITOR
|
||||||
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-per-user">
|
<section xml:id="module-services-emacs-per-user">
|
||||||
<title>Per-User Enabling of the Service</title>
|
<title>Per-User Enabling of the Service</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
In general, <command>systemd</command> user services are globally enabled
|
In general, <command>systemd</command> user services are
|
||||||
by symlinks in <filename>/etc/systemd/user</filename>. In the case where
|
globally enabled by symlinks in
|
||||||
Emacs daemon is not wanted for all users, it is possible to install the
|
<filename>/etc/systemd/user</filename>. In the case where Emacs
|
||||||
service but not globally enable it:
|
daemon is not wanted for all users, it is possible to install
|
||||||
<programlisting>
|
the service but not globally enable it:
|
||||||
<xref linkend="opt-services.emacs.enable"/> = false;
|
|
||||||
<xref linkend="opt-services.emacs.install"/> = true;
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
services.emacs.enable = false;
|
||||||
|
services.emacs.install = true;
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
To enable the <command>systemd</command> user service for just
|
||||||
|
the currently logged in user, run:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
systemctl --user enable emacs
|
||||||
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
To enable the <command>systemd</command> user service for just the
|
|
||||||
currently logged in user, run:
|
|
||||||
<programlisting>systemctl --user enable emacs</programlisting>
|
|
||||||
This will add the symlink
|
This will add the symlink
|
||||||
<filename>~/.config/systemd/user/emacs.service</filename>.
|
<filename>~/.config/systemd/user/emacs.service</filename>.
|
||||||
</para>
|
</para>
|
||||||
|
@ -475,13 +405,12 @@ emacsclient --create-frame --tty # opens a new frame on the current terminal
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-emacs-configuring">
|
<section xml:id="module-services-emacs-configuring">
|
||||||
<title>Configuring Emacs</title>
|
<title>Configuring Emacs</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The Emacs init file should be changed to load the extension packages at
|
The Emacs init file should be changed to load the extension
|
||||||
startup:
|
packages at startup:
|
||||||
<example xml:id="module-services-emacs-package-initialisation">
|
<anchor xml:id="module-services-emacs-package-initialisation" />
|
||||||
<title>Package initialization in <filename>.emacs</filename></title>
|
</para>
|
||||||
<programlisting><![CDATA[
|
<programlisting>
|
||||||
(require 'package)
|
(require 'package)
|
||||||
|
|
||||||
;; optional. makes unpure packages archives unavailable
|
;; optional. makes unpure packages archives unavailable
|
||||||
|
@ -489,92 +418,73 @@ emacsclient --create-frame --tty # opens a new frame on the current terminal
|
||||||
|
|
||||||
(setq package-enable-at-startup nil)
|
(setq package-enable-at-startup nil)
|
||||||
(package-initialize)
|
(package-initialize)
|
||||||
]]></programlisting>
|
</programlisting>
|
||||||
</example>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
After the declarative emacs package configuration has been tested,
|
After the declarative emacs package configuration has been tested,
|
||||||
previously downloaded packages can be cleaned up by removing
|
previously downloaded packages can be cleaned up by removing
|
||||||
<filename>~/.emacs.d/elpa</filename> (do make a backup first, in case you
|
<filename>~/.emacs.d/elpa</filename> (do make a backup first, in
|
||||||
forgot a package).
|
case you forgot a package).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<!--
|
|
||||||
todo: is it worth documenting customizations for
|
|
||||||
server-switch-hook, server-done-hook?
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-major-mode">
|
<section xml:id="module-services-emacs-major-mode">
|
||||||
<title>A Major Mode for Nix Expressions</title>
|
<title>A Major Mode for Nix Expressions</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Of interest may be <varname>melpaPackages.nix-mode</varname>, which
|
Of interest may be <varname>melpaPackages.nix-mode</varname>,
|
||||||
provides syntax highlighting for the Nix language. This is particularly
|
which provides syntax highlighting for the Nix language. This is
|
||||||
convenient if you regularly edit Nix files.
|
particularly convenient if you regularly edit Nix files.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-emacs-man-pages">
|
<section xml:id="module-services-emacs-man-pages">
|
||||||
<title>Accessing man pages</title>
|
<title>Accessing man pages</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
You can use <function>woman</function> to get completion of all available
|
You can use <literal>woman</literal> to get completion of all
|
||||||
man pages. For example, type <literal>M-x woman <RET> nixos-rebuild
|
available man pages. For example, type
|
||||||
<RET>.</literal>
|
<literal>M-x woman <RET> nixos-rebuild <RET>.</literal>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="sec-emacs-docbook-xml">
|
<section xml:id="sec-emacs-docbook-xml">
|
||||||
<title>Editing DocBook 5 XML Documents</title>
|
<title>Editing DocBook 5 XML Documents</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Emacs includes
|
Emacs includes
|
||||||
<link
|
<link xlink:href="https://www.gnu.org/software/emacs/manual/html_node/nxml-mode/Introduction.html">nXML</link>,
|
||||||
xlink:href="https://www.gnu.org/software/emacs/manual/html_node/nxml-mode/Introduction.html">nXML</link>,
|
a major-mode for validating and editing XML documents. When
|
||||||
a major-mode for validating and editing XML documents. When editing DocBook
|
editing DocBook 5.0 documents, such as
|
||||||
5.0 documents, such as <link linkend="book-nixos-manual">this one</link>,
|
<link linkend="book-nixos-manual">this one</link>, nXML needs to
|
||||||
nXML needs to be configured with the relevant schema, which is not
|
be configured with the relevant schema, which is not included.
|
||||||
included.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To install the DocBook 5.0 schemas, either add
|
To install the DocBook 5.0 schemas, either add
|
||||||
<varname>pkgs.docbook5</varname> to
|
<varname>pkgs.docbook5</varname> to
|
||||||
<xref linkend="opt-environment.systemPackages" />
|
<xref linkend="opt-environment.systemPackages" />
|
||||||
(<link
|
(<link linkend="sec-declarative-package-mgmt">NixOS</link>), or
|
||||||
linkend="sec-declarative-package-mgmt">NixOS</link>), or run
|
run <literal>nix-env -f '<nixpkgs>' -iA docbook5</literal>
|
||||||
<literal>nix-env -f '<nixpkgs>' -iA docbook5</literal>
|
|
||||||
(<link linkend="sec-ad-hoc-packages">Nix</link>).
|
(<link linkend="sec-ad-hoc-packages">Nix</link>).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Then customize the variable <varname>rng-schema-locating-files</varname> to
|
Then customize the variable
|
||||||
include <filename>~/.emacs.d/schemas.xml</filename> and put the following
|
<varname>rng-schema-locating-files</varname> to include
|
||||||
text into that file:
|
<filename>~/.emacs.d/schemas.xml</filename> and put the
|
||||||
<example xml:id="ex-emacs-docbook-xml">
|
following text into that file:
|
||||||
<title>nXML Schema Configuration (<filename>~/.emacs.d/schemas.xml</filename>)</title>
|
<anchor xml:id="ex-emacs-docbook-xml" />
|
||||||
<programlisting language="xml"><![CDATA[
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
To let emacs find this file, evaluate:
|
|
||||||
(add-to-list 'rng-schema-locating-files "~/.emacs.d/schemas.xml")
|
|
||||||
-->
|
|
||||||
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
|
||||||
<!--
|
|
||||||
Use this variation if pkgs.docbook5 is added to environment.systemPackages
|
|
||||||
-->
|
|
||||||
<namespace ns="http://docbook.org/ns/docbook"
|
|
||||||
uri="/run/current-system/sw/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
|
|
||||||
<!--
|
|
||||||
Use this variation if installing schema with "nix-env -iA pkgs.docbook5".
|
|
||||||
<namespace ns="http://docbook.org/ns/docbook"
|
|
||||||
uri="../.nix-profile/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
|
|
||||||
-->
|
|
||||||
</locatingRules>
|
|
||||||
]]></programlisting>
|
|
||||||
</example>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting language="xml">
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
To let emacs find this file, evaluate:
|
||||||
|
(add-to-list 'rng-schema-locating-files "~/.emacs.d/schemas.xml")
|
||||||
|
-->
|
||||||
|
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||||
|
<!--
|
||||||
|
Use this variation if pkgs.docbook5 is added to environment.systemPackages
|
||||||
|
-->
|
||||||
|
<namespace ns="http://docbook.org/ns/docbook"
|
||||||
|
uri="/run/current-system/sw/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
|
||||||
|
<!--
|
||||||
|
Use this variation if installing schema with "nix-env -iA pkgs.docbook5".
|
||||||
|
<namespace ns="http://docbook.org/ns/docbook"
|
||||||
|
uri="../.nix-profile/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
|
||||||
|
-->
|
||||||
|
</locatingRules>
|
||||||
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
17
nixos/modules/services/hardware/trezord.md
Normal file
17
nixos/modules/services/hardware/trezord.md
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Trezor {#trezor}
|
||||||
|
|
||||||
|
Trezor is an open-source cryptocurrency hardware wallet and security token
|
||||||
|
allowing secure storage of private keys.
|
||||||
|
|
||||||
|
It offers advanced features such U2F two-factor authorization, SSH login
|
||||||
|
through
|
||||||
|
[Trezor SSH agent](https://wiki.trezor.io/Apps:SSH_agent),
|
||||||
|
[GPG](https://wiki.trezor.io/GPG) and a
|
||||||
|
[password manager](https://wiki.trezor.io/Trezor_Password_Manager).
|
||||||
|
For more information, guides and documentation, see <https://wiki.trezor.io>.
|
||||||
|
|
||||||
|
To enable Trezor support, add the following to your {file}`configuration.nix`:
|
||||||
|
|
||||||
|
services.trezord.enable = true;
|
||||||
|
|
||||||
|
This will add all necessary udev rules and start Trezor Bridge.
|
|
@ -1,26 +1,29 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="trezor">
|
||||||
version="5.0"
|
|
||||||
xml:id="trezor">
|
|
||||||
<title>Trezor</title>
|
<title>Trezor</title>
|
||||||
<para>
|
<para>
|
||||||
Trezor is an open-source cryptocurrency hardware wallet and security token
|
Trezor is an open-source cryptocurrency hardware wallet and security
|
||||||
allowing secure storage of private keys.
|
token allowing secure storage of private keys.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
It offers advanced features such U2F two-factor authorization, SSH login
|
It offers advanced features such U2F two-factor authorization, SSH
|
||||||
through
|
login through
|
||||||
<link xlink:href="https://wiki.trezor.io/Apps:SSH_agent">Trezor SSH agent</link>,
|
<link xlink:href="https://wiki.trezor.io/Apps:SSH_agent">Trezor SSH
|
||||||
|
agent</link>,
|
||||||
<link xlink:href="https://wiki.trezor.io/GPG">GPG</link> and a
|
<link xlink:href="https://wiki.trezor.io/GPG">GPG</link> and a
|
||||||
<link xlink:href="https://wiki.trezor.io/Trezor_Password_Manager">password manager</link>.
|
<link xlink:href="https://wiki.trezor.io/Trezor_Password_Manager">password
|
||||||
For more information, guides and documentation, see <link xlink:href="https://wiki.trezor.io"/>.
|
manager</link>. For more information, guides and documentation, see
|
||||||
|
<link xlink:href="https://wiki.trezor.io">https://wiki.trezor.io</link>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To enable Trezor support, add the following to your <filename>configuration.nix</filename>:
|
To enable Trezor support, add the following to your
|
||||||
|
<filename>configuration.nix</filename>:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<xref linkend="opt-services.trezord.enable"/> = true;
|
services.trezord.enable = true;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
<para>
|
||||||
This will add all necessary udev rules and start Trezor Bridge.
|
This will add all necessary udev rules and start Trezor Bridge.
|
||||||
</para>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
82
nixos/modules/services/mail/mailman.md
Normal file
82
nixos/modules/services/mail/mailman.md
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
# Mailman {#module-services-mailman}
|
||||||
|
|
||||||
|
[Mailman](https://www.list.org) is free
|
||||||
|
software for managing electronic mail discussion and e-newsletter
|
||||||
|
lists. Mailman and its web interface can be configured using the
|
||||||
|
corresponding NixOS module. Note that this service is best used with
|
||||||
|
an existing, securely configured Postfix setup, as it does not automatically configure this.
|
||||||
|
|
||||||
|
## Basic usage with Postfix {#module-services-mailman-basic-usage}
|
||||||
|
|
||||||
|
For a basic configuration with Postfix as the MTA, the following settings are suggested:
|
||||||
|
```
|
||||||
|
{ config, ... }: {
|
||||||
|
services.postfix = {
|
||||||
|
enable = true;
|
||||||
|
relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"];
|
||||||
|
sslCert = config.security.acme.certs."lists.example.org".directory + "/full.pem";
|
||||||
|
sslKey = config.security.acme.certs."lists.example.org".directory + "/key.pem";
|
||||||
|
config = {
|
||||||
|
transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
|
||||||
|
local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.mailman = {
|
||||||
|
enable = true;
|
||||||
|
serve.enable = true;
|
||||||
|
hyperkitty.enable = true;
|
||||||
|
webHosts = ["lists.example.org"];
|
||||||
|
siteOwner = "mailman@example.org";
|
||||||
|
};
|
||||||
|
services.nginx.virtualHosts."lists.example.org".enableACME = true;
|
||||||
|
networking.firewall.allowedTCPPorts = [ 25 80 443 ];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
DNS records will also be required:
|
||||||
|
|
||||||
|
- `AAAA` and `A` records pointing to the host in question, in order for browsers to be able to discover the address of the web server;
|
||||||
|
- An `MX` record pointing to a domain name at which the host is reachable, in order for other mail servers to be able to deliver emails to the mailing lists it hosts.
|
||||||
|
|
||||||
|
After this has been done and appropriate DNS records have been
|
||||||
|
set up, the Postorius mailing list manager and the Hyperkitty
|
||||||
|
archive browser will be available at
|
||||||
|
https://lists.example.org/. Note that this setup is not
|
||||||
|
sufficient to deliver emails to most email providers nor to
|
||||||
|
avoid spam -- a number of additional measures for authenticating
|
||||||
|
incoming and outgoing mails, such as SPF, DMARC and DKIM are
|
||||||
|
necessary, but outside the scope of the Mailman module.
|
||||||
|
|
||||||
|
## Using with other MTAs {#module-services-mailman-other-mtas}
|
||||||
|
|
||||||
|
Mailman also supports other MTA, though with a little bit more configuration. For example, to use Mailman with Exim, you can use the following settings:
|
||||||
|
```
|
||||||
|
{ config, ... }: {
|
||||||
|
services = {
|
||||||
|
mailman = {
|
||||||
|
enable = true;
|
||||||
|
siteOwner = "mailman@example.org";
|
||||||
|
enablePostfix = false;
|
||||||
|
settings.mta = {
|
||||||
|
incoming = "mailman.mta.exim4.LMTP";
|
||||||
|
outgoing = "mailman.mta.deliver.deliver";
|
||||||
|
lmtp_host = "localhost";
|
||||||
|
lmtp_port = "8024";
|
||||||
|
smtp_host = "localhost";
|
||||||
|
smtp_port = "25";
|
||||||
|
configuration = "python:mailman.config.exim4";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
exim = {
|
||||||
|
enable = true;
|
||||||
|
# You can configure Exim in a separate file to reduce configuration.nix clutter
|
||||||
|
config = builtins.readFile ./exim.conf;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The exim config needs some special additions to work with Mailman. Currently
|
||||||
|
NixOS can't manage Exim config with such granularity. Please refer to
|
||||||
|
[Mailman documentation](https://mailman.readthedocs.io/en/latest/src/mailman/docs/mta.html)
|
||||||
|
for more info on configuring Mailman for working with Exim.
|
|
@ -1,79 +1,95 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-mailman">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-mailman">
|
|
||||||
<title>Mailman</title>
|
<title>Mailman</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://www.list.org">Mailman</link> is free
|
<link xlink:href="https://www.list.org">Mailman</link> is free
|
||||||
software for managing electronic mail discussion and e-newsletter
|
software for managing electronic mail discussion and e-newsletter
|
||||||
lists. Mailman and its web interface can be configured using the
|
lists. Mailman and its web interface can be configured using the
|
||||||
corresponding NixOS module. Note that this service is best used with
|
corresponding NixOS module. Note that this service is best used with
|
||||||
an existing, securely configured Postfix setup, as it does not automatically configure this.
|
an existing, securely configured Postfix setup, as it does not
|
||||||
|
automatically configure this.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<section xml:id="module-services-mailman-basic-usage">
|
<section xml:id="module-services-mailman-basic-usage">
|
||||||
<title>Basic usage with Postfix</title>
|
<title>Basic usage with Postfix</title>
|
||||||
<para>
|
<para>
|
||||||
For a basic configuration with Postfix as the MTA, the following settings are suggested:
|
For a basic configuration with Postfix as the MTA, the following
|
||||||
<programlisting>{ config, ... }: {
|
settings are suggested:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{ config, ... }: {
|
||||||
services.postfix = {
|
services.postfix = {
|
||||||
enable = true;
|
enable = true;
|
||||||
relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"];
|
relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"];
|
||||||
sslCert = config.security.acme.certs."lists.example.org".directory + "/full.pem";
|
sslCert = config.security.acme.certs."lists.example.org".directory + "/full.pem";
|
||||||
sslKey = config.security.acme.certs."lists.example.org".directory + "/key.pem";
|
sslKey = config.security.acme.certs."lists.example.org".directory + "/key.pem";
|
||||||
config = {
|
config = {
|
||||||
transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
|
transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
|
||||||
local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
|
local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
services.mailman = {
|
services.mailman = {
|
||||||
<link linkend="opt-services.mailman.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.mailman.serve.enable">serve.enable</link> = true;
|
serve.enable = true;
|
||||||
<link linkend="opt-services.mailman.hyperkitty.enable">hyperkitty.enable</link> = true;
|
hyperkitty.enable = true;
|
||||||
<link linkend="opt-services.mailman.webHosts">webHosts</link> = ["lists.example.org"];
|
webHosts = ["lists.example.org"];
|
||||||
<link linkend="opt-services.mailman.siteOwner">siteOwner</link> = "mailman@example.org";
|
siteOwner = "mailman@example.org";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">services.nginx.virtualHosts."lists.example.org".enableACME</link> = true;
|
services.nginx.virtualHosts."lists.example.org".enableACME = true;
|
||||||
<link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 25 80 443 ];
|
networking.firewall.allowedTCPPorts = [ 25 80 443 ];
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
DNS records will also be required:
|
DNS records will also be required:
|
||||||
<itemizedlist>
|
|
||||||
<listitem><para><literal>AAAA</literal> and <literal>A</literal> records pointing to the host in question, in order for browsers to be able to discover the address of the web server;</para></listitem>
|
|
||||||
<listitem><para>An <literal>MX</literal> record pointing to a domain name at which the host is reachable, in order for other mail servers to be able to deliver emails to the mailing lists it hosts.</para></listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
</para>
|
||||||
|
<itemizedlist spacing="compact">
|
||||||
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
After this has been done and appropriate DNS records have been
|
<literal>AAAA</literal> and <literal>A</literal> records
|
||||||
set up, the Postorius mailing list manager and the Hyperkitty
|
pointing to the host in question, in order for browsers to be
|
||||||
archive browser will be available at
|
able to discover the address of the web server;
|
||||||
https://lists.example.org/. Note that this setup is not
|
</para>
|
||||||
sufficient to deliver emails to most email providers nor to
|
</listitem>
|
||||||
avoid spam -- a number of additional measures for authenticating
|
<listitem>
|
||||||
incoming and outgoing mails, such as SPF, DMARC and DKIM are
|
<para>
|
||||||
necessary, but outside the scope of the Mailman module.
|
An <literal>MX</literal> record pointing to a domain name at
|
||||||
|
which the host is reachable, in order for other mail servers
|
||||||
|
to be able to deliver emails to the mailing lists it hosts.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
After this has been done and appropriate DNS records have been set
|
||||||
|
up, the Postorius mailing list manager and the Hyperkitty archive
|
||||||
|
browser will be available at https://lists.example.org/. Note that
|
||||||
|
this setup is not sufficient to deliver emails to most email
|
||||||
|
providers nor to avoid spam – a number of additional measures for
|
||||||
|
authenticating incoming and outgoing mails, such as SPF, DMARC and
|
||||||
|
DKIM are necessary, but outside the scope of the Mailman module.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-mailman-other-mtas">
|
<section xml:id="module-services-mailman-other-mtas">
|
||||||
<title>Using with other MTAs</title>
|
<title>Using with other MTAs</title>
|
||||||
<para>
|
<para>
|
||||||
Mailman also supports other MTA, though with a little bit more configuration. For example, to use Mailman with Exim, you can use the following settings:
|
Mailman also supports other MTA, though with a little bit more
|
||||||
<programlisting>{ config, ... }: {
|
configuration. For example, to use Mailman with Exim, you can use
|
||||||
|
the following settings:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{ config, ... }: {
|
||||||
services = {
|
services = {
|
||||||
mailman = {
|
mailman = {
|
||||||
enable = true;
|
enable = true;
|
||||||
siteOwner = "mailman@example.org";
|
siteOwner = "mailman@example.org";
|
||||||
<link linkend="opt-services.mailman.enablePostfix">enablePostfix</link> = false;
|
enablePostfix = false;
|
||||||
settings.mta = {
|
settings.mta = {
|
||||||
incoming = "mailman.mta.exim4.LMTP";
|
incoming = "mailman.mta.exim4.LMTP";
|
||||||
outgoing = "mailman.mta.deliver.deliver";
|
outgoing = "mailman.mta.deliver.deliver";
|
||||||
lmtp_host = "localhost";
|
lmtp_host = "localhost";
|
||||||
lmtp_port = "8024";
|
lmtp_port = "8024";
|
||||||
smtp_host = "localhost";
|
smtp_host = "localhost";
|
||||||
smtp_port = "25";
|
smtp_port = "25";
|
||||||
configuration = "python:mailman.config.exim4";
|
configuration = "python:mailman.config.exim4";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
exim = {
|
exim = {
|
||||||
|
@ -82,13 +98,15 @@
|
||||||
config = builtins.readFile ./exim.conf;
|
config = builtins.readFile ./exim.conf;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
The exim config needs some special additions to work with Mailman. Currently
|
The exim config needs some special additions to work with Mailman.
|
||||||
NixOS can't manage Exim config with such granularity. Please refer to
|
Currently NixOS can’t manage Exim config with such granularity.
|
||||||
<link xlink:href="https://mailman.readthedocs.io/en/latest/src/mailman/docs/mta.html">Mailman documentation</link>
|
Please refer to
|
||||||
for more info on configuring Mailman for working with Exim.
|
<link xlink:href="https://mailman.readthedocs.io/en/latest/src/mailman/docs/mta.html">Mailman
|
||||||
|
documentation</link> for more info on configuring Mailman for
|
||||||
|
working with Exim.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
110
nixos/modules/services/matrix/mjolnir.md
Normal file
110
nixos/modules/services/matrix/mjolnir.md
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
# Mjolnir (Matrix Moderation Tool) {#module-services-mjolnir}
|
||||||
|
|
||||||
|
This chapter will show you how to set up your own, self-hosted
|
||||||
|
[Mjolnir](https://github.com/matrix-org/mjolnir) instance.
|
||||||
|
|
||||||
|
As an all-in-one moderation tool, it can protect your server from
|
||||||
|
malicious invites, spam messages, and whatever else you don't want.
|
||||||
|
In addition to server-level protection, Mjolnir is great for communities
|
||||||
|
wanting to protect their rooms without having to use their personal
|
||||||
|
accounts for moderation.
|
||||||
|
|
||||||
|
The bot by default includes support for bans, redactions, anti-spam,
|
||||||
|
server ACLs, room directory changes, room alias transfers, account
|
||||||
|
deactivation, room shutdown, and more.
|
||||||
|
|
||||||
|
See the [README](https://github.com/matrix-org/mjolnir#readme)
|
||||||
|
page and the [Moderator's guide](https://github.com/matrix-org/mjolnir/blob/main/docs/moderators.md)
|
||||||
|
for additional instructions on how to setup and use Mjolnir.
|
||||||
|
|
||||||
|
For [additional settings](#opt-services.mjolnir.settings)
|
||||||
|
see [the default configuration](https://github.com/matrix-org/mjolnir/blob/main/config/default.yaml).
|
||||||
|
|
||||||
|
## Mjolnir Setup {#module-services-mjolnir-setup}
|
||||||
|
|
||||||
|
First create a new Room which will be used as a management room for Mjolnir. In
|
||||||
|
this room, Mjolnir will log possible errors and debugging information. You'll
|
||||||
|
need to set this Room-ID in [services.mjolnir.managementRoom](#opt-services.mjolnir.managementRoom).
|
||||||
|
|
||||||
|
Next, create a new user for Mjolnir on your homeserver, if not present already.
|
||||||
|
|
||||||
|
The Mjolnir Matrix user expects to be free of any rate limiting.
|
||||||
|
See [Synapse #6286](https://github.com/matrix-org/synapse/issues/6286)
|
||||||
|
for an example on how to achieve this.
|
||||||
|
|
||||||
|
If you want Mjolnir to be able to deactivate users, move room aliases, shutdown rooms, etc.
|
||||||
|
you'll need to make the Mjolnir user a Matrix server admin.
|
||||||
|
|
||||||
|
Now invite the Mjolnir user to the management room.
|
||||||
|
|
||||||
|
It is recommended to use [Pantalaimon](https://github.com/matrix-org/pantalaimon),
|
||||||
|
so your management room can be encrypted. This also applies if you are looking to moderate an encrypted room.
|
||||||
|
|
||||||
|
To enable the Pantalaimon E2E Proxy for mjolnir, enable
|
||||||
|
[services.mjolnir.pantalaimon](#opt-services.mjolnir.pantalaimon.enable). This will
|
||||||
|
autoconfigure a new Pantalaimon instance, which will connect to the homeserver
|
||||||
|
set in [services.mjolnir.homeserverUrl](#opt-services.mjolnir.homeserverUrl) and Mjolnir itself
|
||||||
|
will be configured to connect to the new Pantalaimon instance.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.mjolnir = {
|
||||||
|
enable = true;
|
||||||
|
homeserverUrl = "https://matrix.domain.tld";
|
||||||
|
pantalaimon = {
|
||||||
|
enable = true;
|
||||||
|
username = "mjolnir";
|
||||||
|
passwordFile = "/run/secrets/mjolnir-password";
|
||||||
|
};
|
||||||
|
protectedRooms = [
|
||||||
|
"https://matrix.to/#/!xxx:domain.tld"
|
||||||
|
];
|
||||||
|
managementRoom = "!yyy:domain.tld";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Element Matrix Services (EMS) {#module-services-mjolnir-setup-ems}
|
||||||
|
|
||||||
|
If you are using a managed ["Element Matrix Services (EMS)"](https://ems.element.io/)
|
||||||
|
server, you will need to consent to the terms and conditions. Upon startup, an error
|
||||||
|
log entry with a URL to the consent page will be generated.
|
||||||
|
|
||||||
|
## Synapse Antispam Module {#module-services-mjolnir-matrix-synapse-antispam}
|
||||||
|
|
||||||
|
A Synapse module is also available to apply the same rulesets the bot
|
||||||
|
uses across an entire homeserver.
|
||||||
|
|
||||||
|
To use the Antispam Module, add `matrix-synapse-plugins.matrix-synapse-mjolnir-antispam`
|
||||||
|
to the Synapse plugin list and enable the `mjolnir.Module` module.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.matrix-synapse = {
|
||||||
|
plugins = with pkgs; [
|
||||||
|
matrix-synapse-plugins.matrix-synapse-mjolnir-antispam
|
||||||
|
];
|
||||||
|
extraConfig = ''
|
||||||
|
modules:
|
||||||
|
- module: mjolnir.Module
|
||||||
|
config:
|
||||||
|
# Prevent servers/users in the ban lists from inviting users on this
|
||||||
|
# server to rooms. Default true.
|
||||||
|
block_invites: true
|
||||||
|
# Flag messages sent by servers/users in the ban lists as spam. Currently
|
||||||
|
# this means that spammy messages will appear as empty to users. Default
|
||||||
|
# false.
|
||||||
|
block_messages: false
|
||||||
|
# Remove users from the user directory search by filtering matrix IDs and
|
||||||
|
# display names by the entries in the user ban list. Default false.
|
||||||
|
block_usernames: false
|
||||||
|
# The room IDs of the ban lists to honour. Unlike other parts of Mjolnir,
|
||||||
|
# this list cannot be room aliases or permalinks. This server is expected
|
||||||
|
# to already be joined to the room - Mjolnir will not automatically join
|
||||||
|
# these rooms.
|
||||||
|
ban_lists:
|
||||||
|
- "!roomid:example.org"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
|
@ -1,8 +1,6 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-mjolnir">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-mjolnir">
|
|
||||||
<title>Mjolnir (Matrix Moderation Tool)</title>
|
<title>Mjolnir (Matrix Moderation Tool)</title>
|
||||||
<para>
|
<para>
|
||||||
This chapter will show you how to set up your own, self-hosted
|
This chapter will show you how to set up your own, self-hosted
|
||||||
|
@ -11,10 +9,10 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
As an all-in-one moderation tool, it can protect your server from
|
As an all-in-one moderation tool, it can protect your server from
|
||||||
malicious invites, spam messages, and whatever else you don't want.
|
malicious invites, spam messages, and whatever else you don’t want.
|
||||||
In addition to server-level protection, Mjolnir is great for communities
|
In addition to server-level protection, Mjolnir is great for
|
||||||
wanting to protect their rooms without having to use their personal
|
communities wanting to protect their rooms without having to use
|
||||||
accounts for moderation.
|
their personal accounts for moderation.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The bot by default includes support for bans, redactions, anti-spam,
|
The bot by default includes support for bans, redactions, anti-spam,
|
||||||
|
@ -22,83 +20,99 @@
|
||||||
deactivation, room shutdown, and more.
|
deactivation, room shutdown, and more.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
See the <link xlink:href="https://github.com/matrix-org/mjolnir#readme">README</link>
|
See the
|
||||||
page and the <link xlink:href="https://github.com/matrix-org/mjolnir/blob/main/docs/moderators.md">Moderator's guide</link>
|
<link xlink:href="https://github.com/matrix-org/mjolnir#readme">README</link>
|
||||||
for additional instructions on how to setup and use Mjolnir.
|
page and the
|
||||||
|
<link xlink:href="https://github.com/matrix-org/mjolnir/blob/main/docs/moderators.md">Moderator’s
|
||||||
|
guide</link> for additional instructions on how to setup and use
|
||||||
|
Mjolnir.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
For <link linkend="opt-services.mjolnir.settings">additional settings</link>
|
For <link linkend="opt-services.mjolnir.settings">additional
|
||||||
see <link xlink:href="https://github.com/matrix-org/mjolnir/blob/main/config/default.yaml">the default configuration</link>.
|
settings</link> see
|
||||||
|
<link xlink:href="https://github.com/matrix-org/mjolnir/blob/main/config/default.yaml">the
|
||||||
|
default configuration</link>.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-mjolnir-setup">
|
<section xml:id="module-services-mjolnir-setup">
|
||||||
<title>Mjolnir Setup</title>
|
<title>Mjolnir Setup</title>
|
||||||
<para>
|
<para>
|
||||||
First create a new Room which will be used as a management room for Mjolnir. In
|
First create a new Room which will be used as a management room
|
||||||
this room, Mjolnir will log possible errors and debugging information. You'll
|
for Mjolnir. In this room, Mjolnir will log possible errors and
|
||||||
need to set this Room-ID in <link linkend="opt-services.mjolnir.managementRoom">services.mjolnir.managementRoom</link>.
|
debugging information. You’ll need to set this Room-ID in
|
||||||
|
<link linkend="opt-services.mjolnir.managementRoom">services.mjolnir.managementRoom</link>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Next, create a new user for Mjolnir on your homeserver, if not present already.
|
Next, create a new user for Mjolnir on your homeserver, if not
|
||||||
|
present already.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The Mjolnir Matrix user expects to be free of any rate limiting.
|
The Mjolnir Matrix user expects to be free of any rate limiting.
|
||||||
See <link xlink:href="https://github.com/matrix-org/synapse/issues/6286">Synapse #6286</link>
|
See
|
||||||
for an example on how to achieve this.
|
<link xlink:href="https://github.com/matrix-org/synapse/issues/6286">Synapse
|
||||||
|
#6286</link> for an example on how to achieve this.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If you want Mjolnir to be able to deactivate users, move room aliases, shutdown rooms, etc.
|
If you want Mjolnir to be able to deactivate users, move room
|
||||||
you'll need to make the Mjolnir user a Matrix server admin.
|
aliases, shutdown rooms, etc. you’ll need to make the Mjolnir user
|
||||||
|
a Matrix server admin.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Now invite the Mjolnir user to the management room.
|
Now invite the Mjolnir user to the management room.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
It is recommended to use <link xlink:href="https://github.com/matrix-org/pantalaimon">Pantalaimon</link>,
|
It is recommended to use
|
||||||
so your management room can be encrypted. This also applies if you are looking to moderate an encrypted room.
|
<link xlink:href="https://github.com/matrix-org/pantalaimon">Pantalaimon</link>,
|
||||||
|
so your management room can be encrypted. This also applies if you
|
||||||
|
are looking to moderate an encrypted room.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To enable the Pantalaimon E2E Proxy for mjolnir, enable
|
To enable the Pantalaimon E2E Proxy for mjolnir, enable
|
||||||
<link linkend="opt-services.mjolnir.pantalaimon.enable">services.mjolnir.pantalaimon</link>. This will
|
<link linkend="opt-services.mjolnir.pantalaimon.enable">services.mjolnir.pantalaimon</link>.
|
||||||
autoconfigure a new Pantalaimon instance, which will connect to the homeserver
|
This will autoconfigure a new Pantalaimon instance, which will
|
||||||
set in <link linkend="opt-services.mjolnir.homeserverUrl">services.mjolnir.homeserverUrl</link> and Mjolnir itself
|
connect to the homeserver set in
|
||||||
will be configured to connect to the new Pantalaimon instance.
|
<link linkend="opt-services.mjolnir.homeserverUrl">services.mjolnir.homeserverUrl</link>
|
||||||
|
and Mjolnir itself will be configured to connect to the new
|
||||||
|
Pantalaimon instance.
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
services.mjolnir = {
|
services.mjolnir = {
|
||||||
enable = true;
|
enable = true;
|
||||||
<link linkend="opt-services.mjolnir.homeserverUrl">homeserverUrl</link> = "https://matrix.domain.tld";
|
homeserverUrl = "https://matrix.domain.tld";
|
||||||
<link linkend="opt-services.mjolnir.pantalaimon">pantalaimon</link> = {
|
pantalaimon = {
|
||||||
<link linkend="opt-services.mjolnir.pantalaimon.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.mjolnir.pantalaimon.username">username</link> = "mjolnir";
|
username = "mjolnir";
|
||||||
<link linkend="opt-services.mjolnir.pantalaimon.passwordFile">passwordFile</link> = "/run/secrets/mjolnir-password";
|
passwordFile = "/run/secrets/mjolnir-password";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.mjolnir.protectedRooms">protectedRooms</link> = [
|
protectedRooms = [
|
||||||
"https://matrix.to/#/!xxx:domain.tld"
|
"https://matrix.to/#/!xxx:domain.tld"
|
||||||
];
|
];
|
||||||
<link linkend="opt-services.mjolnir.managementRoom">managementRoom</link> = "!yyy:domain.tld";
|
managementRoom = "!yyy:domain.tld";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<section xml:id="module-services-mjolnir-setup-ems">
|
<section xml:id="module-services-mjolnir-setup-ems">
|
||||||
<title>Element Matrix Services (EMS)</title>
|
<title>Element Matrix Services (EMS)</title>
|
||||||
<para>
|
<para>
|
||||||
If you are using a managed <link xlink:href="https://ems.element.io/">"Element Matrix Services (EMS)"</link>
|
If you are using a managed
|
||||||
server, you will need to consent to the terms and conditions. Upon startup, an error
|
<link xlink:href="https://ems.element.io/"><quote>Element Matrix
|
||||||
log entry with a URL to the consent page will be generated.
|
Services (EMS)</quote></link> server, you will need to consent
|
||||||
|
to the terms and conditions. Upon startup, an error log entry
|
||||||
|
with a URL to the consent page will be generated.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-mjolnir-matrix-synapse-antispam">
|
<section xml:id="module-services-mjolnir-matrix-synapse-antispam">
|
||||||
<title>Synapse Antispam Module</title>
|
<title>Synapse Antispam Module</title>
|
||||||
<para>
|
<para>
|
||||||
A Synapse module is also available to apply the same rulesets the bot
|
A Synapse module is also available to apply the same rulesets the
|
||||||
uses across an entire homeserver.
|
bot uses across an entire homeserver.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To use the Antispam Module, add <package>matrix-synapse-plugins.matrix-synapse-mjolnir-antispam</package>
|
To use the Antispam Module, add
|
||||||
to the Synapse plugin list and enable the <literal>mjolnir.Module</literal> module.
|
<literal>matrix-synapse-plugins.matrix-synapse-mjolnir-antispam</literal>
|
||||||
|
to the Synapse plugin list and enable the
|
||||||
|
<literal>mjolnir.Module</literal> module.
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
|
@ -125,7 +139,7 @@
|
||||||
# to already be joined to the room - Mjolnir will not automatically join
|
# to already be joined to the room - Mjolnir will not automatically join
|
||||||
# these rooms.
|
# these rooms.
|
||||||
ban_lists:
|
ban_lists:
|
||||||
- "!roomid:example.org"
|
- "!roomid:example.org"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
216
nixos/modules/services/matrix/synapse.md
Normal file
216
nixos/modules/services/matrix/synapse.md
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
# Matrix {#module-services-matrix}
|
||||||
|
|
||||||
|
[Matrix](https://matrix.org/) is an open standard for
|
||||||
|
interoperable, decentralised, real-time communication over IP. It can be used
|
||||||
|
to power Instant Messaging, VoIP/WebRTC signalling, Internet of Things
|
||||||
|
communication - or anywhere you need a standard HTTP API for publishing and
|
||||||
|
subscribing to data whilst tracking the conversation history.
|
||||||
|
|
||||||
|
This chapter will show you how to set up your own, self-hosted Matrix
|
||||||
|
homeserver using the Synapse reference homeserver, and how to serve your own
|
||||||
|
copy of the Element web client. See the
|
||||||
|
[Try Matrix Now!](https://matrix.org/docs/projects/try-matrix-now.html)
|
||||||
|
overview page for links to Element Apps for Android and iOS,
|
||||||
|
desktop clients, as well as bridges to other networks and other projects
|
||||||
|
around Matrix.
|
||||||
|
|
||||||
|
## Synapse Homeserver {#module-services-matrix-synapse}
|
||||||
|
|
||||||
|
[Synapse](https://github.com/matrix-org/synapse) is
|
||||||
|
the reference homeserver implementation of Matrix from the core development
|
||||||
|
team at matrix.org. The following configuration example will set up a
|
||||||
|
synapse server for the `example.org` domain, served from
|
||||||
|
the host `myhostname.example.org`. For more information,
|
||||||
|
please refer to the
|
||||||
|
[installation instructions of Synapse](https://matrix-org.github.io/synapse/latest/setup/installation.html) .
|
||||||
|
```
|
||||||
|
{ pkgs, lib, config, ... }:
|
||||||
|
let
|
||||||
|
fqdn = "${config.networking.hostName}.${config.networking.domain}";
|
||||||
|
clientConfig = {
|
||||||
|
"m.homeserver".base_url = "https://${fqdn}";
|
||||||
|
"m.identity_server" = {};
|
||||||
|
};
|
||||||
|
serverConfig."m.server" = "${config.services.matrix-synapse.settings.server_name}:443";
|
||||||
|
mkWellKnown = data: ''
|
||||||
|
add_header Content-Type application/json;
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
return 200 '${builtins.toJSON data}';
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
networking.hostName = "myhostname";
|
||||||
|
networking.domain = "example.org";
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
|
||||||
|
services.postgresql.enable = true;
|
||||||
|
services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||||
|
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||||
|
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||||
|
TEMPLATE template0
|
||||||
|
LC_COLLATE = "C"
|
||||||
|
LC_CTYPE = "C";
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
recommendedTlsSettings = true;
|
||||||
|
recommendedOptimisation = true;
|
||||||
|
recommendedGzipSettings = true;
|
||||||
|
recommendedProxySettings = true;
|
||||||
|
virtualHosts = {
|
||||||
|
# If the A and AAAA DNS records on example.org do not point on the same host as the
|
||||||
|
# records for myhostname.example.org, you can easily move the /.well-known
|
||||||
|
# virtualHost section of the code to the host that is serving example.org, while
|
||||||
|
# the rest stays on myhostname.example.org with no other changes required.
|
||||||
|
# This pattern also allows to seamlessly move the homeserver from
|
||||||
|
# myhostname.example.org to myotherhost.example.org by only changing the
|
||||||
|
# /.well-known redirection target.
|
||||||
|
"${config.networking.domain}" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
# This section is not needed if the server_name of matrix-synapse is equal to
|
||||||
|
# the domain (i.e. example.org from @foo:example.org) and the federation port
|
||||||
|
# is 8448.
|
||||||
|
# Further reference can be found in the docs about delegation under
|
||||||
|
# https://matrix-org.github.io/synapse/latest/delegate.html
|
||||||
|
locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
|
||||||
|
# This is usually needed for homeserver discovery (from e.g. other Matrix clients).
|
||||||
|
# Further reference can be found in the upstream docs at
|
||||||
|
# https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient
|
||||||
|
locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
|
||||||
|
};
|
||||||
|
"${fqdn}" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
# It's also possible to do a redirect here or something else, this vhost is not
|
||||||
|
# needed for Matrix. It's recommended though to *not put* element
|
||||||
|
# here, see also the section about Element.
|
||||||
|
locations."/".extraConfig = ''
|
||||||
|
return 404;
|
||||||
|
'';
|
||||||
|
# Forward all Matrix API calls to the synapse Matrix homeserver. A trailing slash
|
||||||
|
# *must not* be used here.
|
||||||
|
locations."/_matrix".proxyPass = "http://[::1]:8008";
|
||||||
|
# Forward requests for e.g. SSO and password-resets.
|
||||||
|
locations."/_synapse/client".proxyPass = "http://[::1]:8008";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.matrix-synapse = {
|
||||||
|
enable = true;
|
||||||
|
settings.server_name = config.networking.domain;
|
||||||
|
settings.listeners = [
|
||||||
|
{ port = 8008;
|
||||||
|
bind_addresses = [ "::1" ];
|
||||||
|
type = "http";
|
||||||
|
tls = false;
|
||||||
|
x_forwarded = true;
|
||||||
|
resources = [ {
|
||||||
|
names = [ "client" "federation" ];
|
||||||
|
compress = true;
|
||||||
|
} ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Registering Matrix users {#module-services-matrix-register-users}
|
||||||
|
|
||||||
|
If you want to run a server with public registration by anybody, you can
|
||||||
|
then enable `services.matrix-synapse.settings.enable_registration = true;`.
|
||||||
|
Otherwise, or you can generate a registration secret with
|
||||||
|
{command}`pwgen -s 64 1` and set it with
|
||||||
|
[](#opt-services.matrix-synapse.settings.registration_shared_secret).
|
||||||
|
To create a new user or admin, run the following after you have set the secret
|
||||||
|
and have rebuilt NixOS:
|
||||||
|
```ShellSession
|
||||||
|
$ nix-shell -p matrix-synapse
|
||||||
|
$ register_new_matrix_user -k your-registration-shared-secret http://localhost:8008
|
||||||
|
New user localpart: your-username
|
||||||
|
Password:
|
||||||
|
Confirm password:
|
||||||
|
Make admin [no]:
|
||||||
|
Success!
|
||||||
|
```
|
||||||
|
In the example, this would create a user with the Matrix Identifier
|
||||||
|
`@your-username:example.org`.
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
When using [](#opt-services.matrix-synapse.settings.registration_shared_secret), the secret
|
||||||
|
will end up in the world-readable store. Instead it's recommended to deploy the secret
|
||||||
|
in an additional file like this:
|
||||||
|
|
||||||
|
- Create a file with the following contents:
|
||||||
|
|
||||||
|
```
|
||||||
|
registration_shared_secret: your-very-secret-secret
|
||||||
|
```
|
||||||
|
- Deploy the file with a secret-manager such as
|
||||||
|
[{option}`deployment.keys`](https://nixops.readthedocs.io/en/latest/overview.html#managing-keys)
|
||||||
|
from {manpage}`nixops(1)` or [sops-nix](https://github.com/Mic92/sops-nix/) to
|
||||||
|
e.g. {file}`/run/secrets/matrix-shared-secret` and ensure that it's readable
|
||||||
|
by `matrix-synapse`.
|
||||||
|
- Include the file like this in your configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.matrix-synapse.extraConfigFiles = [
|
||||||
|
"/run/secrets/matrix-shared-secret"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: {.note}
|
||||||
|
It's also possible to user alternative authentication mechanism such as
|
||||||
|
[LDAP (via `matrix-synapse-ldap3`)](https://github.com/matrix-org/matrix-synapse-ldap3)
|
||||||
|
or [OpenID](https://matrix-org.github.io/synapse/latest/openid.html).
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Element (formerly known as Riot) Web Client {#module-services-matrix-element-web}
|
||||||
|
|
||||||
|
[Element Web](https://github.com/vector-im/riot-web/) is
|
||||||
|
the reference web client for Matrix and developed by the core team at
|
||||||
|
matrix.org. Element was formerly known as Riot.im, see the
|
||||||
|
[Element introductory blog post](https://element.io/blog/welcome-to-element/)
|
||||||
|
for more information. The following snippet can be optionally added to the code before
|
||||||
|
to complete the synapse installation with a web client served at
|
||||||
|
`https://element.myhostname.example.org` and
|
||||||
|
`https://element.example.org`. Alternatively, you can use the hosted
|
||||||
|
copy at <https://app.element.io/>,
|
||||||
|
or use other web clients or native client applications. Due to the
|
||||||
|
`/.well-known` urls set up done above, many clients should
|
||||||
|
fill in the required connection details automatically when you enter your
|
||||||
|
Matrix Identifier. See
|
||||||
|
[Try Matrix Now!](https://matrix.org/docs/projects/try-matrix-now.html)
|
||||||
|
for a list of existing clients and their supported featureset.
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.nginx.virtualHosts."element.${fqdn}" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
serverAliases = [
|
||||||
|
"element.${config.networking.domain}"
|
||||||
|
];
|
||||||
|
|
||||||
|
root = pkgs.element-web.override {
|
||||||
|
conf = {
|
||||||
|
default_server_config = clientConfig; # see `clientConfig` from the snippet above.
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
::: {.note}
|
||||||
|
The Element developers do not recommend running Element and your Matrix
|
||||||
|
homeserver on the same fully-qualified domain name for security reasons. In
|
||||||
|
the example, this means that you should not reuse the
|
||||||
|
`myhostname.example.org` virtualHost to also serve Element,
|
||||||
|
but instead serve it on a different subdomain, like
|
||||||
|
`element.example.org` in the example. See the
|
||||||
|
[Element Important Security Notes](https://github.com/vector-im/element-web/tree/v1.10.0#important-security-notes)
|
||||||
|
for more information on this subject.
|
||||||
|
:::
|
|
@ -1,256 +1,243 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-matrix">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-matrix">
|
|
||||||
<title>Matrix</title>
|
<title>Matrix</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://matrix.org/">Matrix</link> is an open standard for
|
<link xlink:href="https://matrix.org/">Matrix</link> is an open
|
||||||
interoperable, decentralised, real-time communication over IP. It can be used
|
standard for interoperable, decentralised, real-time communication
|
||||||
to power Instant Messaging, VoIP/WebRTC signalling, Internet of Things
|
over IP. It can be used to power Instant Messaging, VoIP/WebRTC
|
||||||
communication - or anywhere you need a standard HTTP API for publishing and
|
signalling, Internet of Things communication - or anywhere you need
|
||||||
subscribing to data whilst tracking the conversation history.
|
a standard HTTP API for publishing and subscribing to data whilst
|
||||||
|
tracking the conversation history.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
This chapter will show you how to set up your own, self-hosted Matrix
|
This chapter will show you how to set up your own, self-hosted
|
||||||
homeserver using the Synapse reference homeserver, and how to serve your own
|
Matrix homeserver using the Synapse reference homeserver, and how to
|
||||||
copy of the Element web client. See the
|
serve your own copy of the Element web client. See the
|
||||||
<link xlink:href="https://matrix.org/docs/projects/try-matrix-now.html">Try
|
<link xlink:href="https://matrix.org/docs/projects/try-matrix-now.html">Try
|
||||||
Matrix Now!</link> overview page for links to Element Apps for Android and iOS,
|
Matrix Now!</link> overview page for links to Element Apps for
|
||||||
desktop clients, as well as bridges to other networks and other projects
|
Android and iOS, desktop clients, as well as bridges to other
|
||||||
around Matrix.
|
networks and other projects around Matrix.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-matrix-synapse">
|
<section xml:id="module-services-matrix-synapse">
|
||||||
<title>Synapse Homeserver</title>
|
<title>Synapse Homeserver</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://github.com/matrix-org/synapse">Synapse</link> is
|
<link xlink:href="https://github.com/matrix-org/synapse">Synapse</link>
|
||||||
the reference homeserver implementation of Matrix from the core development
|
is the reference homeserver implementation of Matrix from the core
|
||||||
team at matrix.org. The following configuration example will set up a
|
development team at matrix.org. The following configuration
|
||||||
synapse server for the <literal>example.org</literal> domain, served from
|
example will set up a synapse server for the
|
||||||
the host <literal>myhostname.example.org</literal>. For more information,
|
<literal>example.org</literal> domain, served from the host
|
||||||
|
<literal>myhostname.example.org</literal>. For more information,
|
||||||
please refer to the
|
please refer to the
|
||||||
<link xlink:href="https://matrix-org.github.io/synapse/latest/setup/installation.html">
|
<link xlink:href="https://matrix-org.github.io/synapse/latest/setup/installation.html">installation
|
||||||
installation instructions of Synapse </link>.
|
instructions of Synapse</link> .
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{ pkgs, lib, config, ... }:
|
{ pkgs, lib, config, ... }:
|
||||||
let
|
let
|
||||||
fqdn = "${config.networking.hostName}.${config.networking.domain}";
|
fqdn = "${config.networking.hostName}.${config.networking.domain}";
|
||||||
clientConfig = {
|
clientConfig = {
|
||||||
"m.homeserver".base_url = "https://${fqdn}";
|
"m.homeserver".base_url = "https://${fqdn}";
|
||||||
"m.identity_server" = {};
|
"m.identity_server" = {};
|
||||||
};
|
};
|
||||||
serverConfig."m.server" = "${config.services.matrix-synapse.settings.server_name}:443";
|
serverConfig."m.server" = "${config.services.matrix-synapse.settings.server_name}:443";
|
||||||
mkWellKnown = data: ''
|
mkWellKnown = data: ''
|
||||||
add_header Content-Type application/json;
|
add_header Content-Type application/json;
|
||||||
add_header Access-Control-Allow-Origin *;
|
add_header Access-Control-Allow-Origin *;
|
||||||
return 200 '${builtins.toJSON data}';
|
return 200 '${builtins.toJSON data}';
|
||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
<xref linkend="opt-networking.hostName" /> = "myhostname";
|
networking.hostName = "myhostname";
|
||||||
<xref linkend="opt-networking.domain" /> = "example.org";
|
networking.domain = "example.org";
|
||||||
<xref linkend="opt-networking.firewall.allowedTCPPorts" /> = [ 80 443 ];
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
|
||||||
<xref linkend="opt-services.postgresql.enable" /> = true;
|
services.postgresql.enable = true;
|
||||||
<xref linkend="opt-services.postgresql.initialScript" /> = pkgs.writeText "synapse-init.sql" ''
|
services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||||
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||||
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||||
TEMPLATE template0
|
TEMPLATE template0
|
||||||
LC_COLLATE = "C"
|
LC_COLLATE = "C"
|
||||||
LC_CTYPE = "C";
|
LC_CTYPE = "C";
|
||||||
'';
|
'';
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.nginx.recommendedTlsSettings">recommendedTlsSettings</link> = true;
|
recommendedTlsSettings = true;
|
||||||
<link linkend="opt-services.nginx.recommendedOptimisation">recommendedOptimisation</link> = true;
|
recommendedOptimisation = true;
|
||||||
<link linkend="opt-services.nginx.recommendedGzipSettings">recommendedGzipSettings</link> = true;
|
recommendedGzipSettings = true;
|
||||||
<link linkend="opt-services.nginx.recommendedProxySettings">recommendedProxySettings</link> = true;
|
recommendedProxySettings = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
|
virtualHosts = {
|
||||||
"${config.networking.domain}" = { <co xml:id='ex-matrix-synapse-dns' />
|
# If the A and AAAA DNS records on example.org do not point on the same host as the
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
# records for myhostname.example.org, you can easily move the /.well-known
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
# virtualHost section of the code to the host that is serving example.org, while
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/server".extraConfig</link> = mkWellKnown serverConfig; <co xml:id='ex-matrix-synapse-well-known-server' />
|
# the rest stays on myhostname.example.org with no other changes required.
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/client".extraConfig</link> = mkWellKnown clientConfig; <co xml:id='ex-matrix-synapse-well-known-client' />
|
# This pattern also allows to seamlessly move the homeserver from
|
||||||
|
# myhostname.example.org to myotherhost.example.org by only changing the
|
||||||
|
# /.well-known redirection target.
|
||||||
|
"${config.networking.domain}" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
# This section is not needed if the server_name of matrix-synapse is equal to
|
||||||
|
# the domain (i.e. example.org from @foo:example.org) and the federation port
|
||||||
|
# is 8448.
|
||||||
|
# Further reference can be found in the docs about delegation under
|
||||||
|
# https://matrix-org.github.io/synapse/latest/delegate.html
|
||||||
|
locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
|
||||||
|
# This is usually needed for homeserver discovery (from e.g. other Matrix clients).
|
||||||
|
# Further reference can be found in the upstream docs at
|
||||||
|
# https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient
|
||||||
|
locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
|
||||||
};
|
};
|
||||||
"${fqdn}" = {
|
"${fqdn}" = {
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
enableACME = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
forceSSL = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."/".extraConfig</link> = '' <co xml:id='ex-matrix-synapse-rev-default' />
|
# It's also possible to do a redirect here or something else, this vhost is not
|
||||||
|
# needed for Matrix. It's recommended though to *not put* element
|
||||||
|
# here, see also the section about Element.
|
||||||
|
locations."/".extraConfig = ''
|
||||||
return 404;
|
return 404;
|
||||||
'';
|
'';
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.proxyPass">locations."/_matrix".proxyPass</link> = "http://[::1]:8008"; <co xml:id='ex-matrix-synapse-rev-proxy-pass' />
|
# Forward all Matrix API calls to the synapse Matrix homeserver. A trailing slash
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.proxyPass">locations."/_synapse/client".proxyPass</link> = "http://[::1]:8008"; <co xml:id='ex-matrix-synapse-rev-client' />
|
# *must not* be used here.
|
||||||
|
locations."/_matrix".proxyPass = "http://[::1]:8008";
|
||||||
|
# Forward requests for e.g. SSO and password-resets.
|
||||||
|
locations."/_synapse/client".proxyPass = "http://[::1]:8008";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.matrix-synapse = {
|
services.matrix-synapse = {
|
||||||
<link linkend="opt-services.matrix-synapse.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.matrix-synapse.settings.server_name">settings.server_name</link> = config.networking.domain;
|
settings.server_name = config.networking.domain;
|
||||||
<link linkend="opt-services.matrix-synapse.settings.listeners">settings.listeners</link> = [
|
settings.listeners = [
|
||||||
{ <link linkend="opt-services.matrix-synapse.settings.listeners._.port">port</link> = 8008;
|
{ port = 8008;
|
||||||
<link linkend="opt-services.matrix-synapse.settings.listeners._.bind_addresses">bind_addresses</link> = [ "::1" ];
|
bind_addresses = [ "::1" ];
|
||||||
<link linkend="opt-services.matrix-synapse.settings.listeners._.type">type</link> = "http";
|
type = "http";
|
||||||
<link linkend="opt-services.matrix-synapse.settings.listeners._.tls">tls</link> = false;
|
tls = false;
|
||||||
<link linkend="opt-services.matrix-synapse.settings.listeners._.x_forwarded">x_forwarded</link> = true;
|
x_forwarded = true;
|
||||||
<link linkend="opt-services.matrix-synapse.settings.listeners._.resources">resources</link> = [ {
|
resources = [ {
|
||||||
<link linkend="opt-services.matrix-synapse.settings.listeners._.resources._.names">names</link> = [ "client" "federation" ];
|
names = [ "client" "federation" ];
|
||||||
<link linkend="opt-services.matrix-synapse.settings.listeners._.resources._.compress">compress</link> = true;
|
compress = true;
|
||||||
} ];
|
} ];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
<calloutlist>
|
|
||||||
<callout arearefs='ex-matrix-synapse-dns'>
|
|
||||||
<para>
|
|
||||||
If the <code>A</code> and <code>AAAA</code> DNS records on
|
|
||||||
<literal>example.org</literal> do not point on the same host as the records
|
|
||||||
for <code>myhostname.example.org</code>, you can easily move the
|
|
||||||
<code>/.well-known</code> virtualHost section of the code to the host that
|
|
||||||
is serving <literal>example.org</literal>, while the rest stays on
|
|
||||||
<literal>myhostname.example.org</literal> with no other changes required.
|
|
||||||
This pattern also allows to seamlessly move the homeserver from
|
|
||||||
<literal>myhostname.example.org</literal> to
|
|
||||||
<literal>myotherhost.example.org</literal> by only changing the
|
|
||||||
<code>/.well-known</code> redirection target.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs='ex-matrix-synapse-well-known-server'>
|
|
||||||
<para>
|
|
||||||
This section is not needed if the <link linkend="opt-services.matrix-synapse.settings.server_name">server_name</link>
|
|
||||||
of <package>matrix-synapse</package> is equal to the domain (i.e.
|
|
||||||
<literal>example.org</literal> from <literal>@foo:example.org</literal>)
|
|
||||||
and the federation port is 8448.
|
|
||||||
Further reference can be found in the <link xlink:href="https://matrix-org.github.io/synapse/latest/delegate.html">docs
|
|
||||||
about delegation</link>.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs='ex-matrix-synapse-well-known-client'>
|
|
||||||
<para>
|
|
||||||
This is usually needed for homeserver discovery (from e.g. other Matrix clients).
|
|
||||||
Further reference can be found in the <link xlink:href="https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient">upstream docs</link>
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs='ex-matrix-synapse-rev-default'>
|
|
||||||
<para>
|
|
||||||
It's also possible to do a redirect here or something else, this vhost is not
|
|
||||||
needed for Matrix. It's recommended though to <emphasis>not put</emphasis> element
|
|
||||||
here, see also the <link linkend='ex-matrix-synapse-rev-default'>section about Element</link>.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs='ex-matrix-synapse-rev-proxy-pass'>
|
|
||||||
<para>
|
|
||||||
Forward all Matrix API calls to the synapse Matrix homeserver. A trailing slash
|
|
||||||
<emphasis>must not</emphasis> be used here.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs='ex-matrix-synapse-rev-client'>
|
|
||||||
<para>
|
|
||||||
Forward requests for e.g. SSO and password-resets.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
</calloutlist>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-matrix-register-users">
|
<section xml:id="module-services-matrix-register-users">
|
||||||
<title>Registering Matrix users</title>
|
<title>Registering Matrix users</title>
|
||||||
<para>
|
<para>
|
||||||
If you want to run a server with public registration by anybody, you can
|
If you want to run a server with public registration by anybody,
|
||||||
then enable <literal><link linkend="opt-services.matrix-synapse.settings.enable_registration">services.matrix-synapse.settings.enable_registration</link> =
|
you can then enable
|
||||||
true;</literal>. Otherwise, or you can generate a registration secret with
|
<literal>services.matrix-synapse.settings.enable_registration = true;</literal>.
|
||||||
|
Otherwise, or you can generate a registration secret with
|
||||||
<command>pwgen -s 64 1</command> and set it with
|
<command>pwgen -s 64 1</command> and set it with
|
||||||
<option><link linkend="opt-services.matrix-synapse.settings.registration_shared_secret">services.matrix-synapse.settings.registration_shared_secret</link></option>.
|
<xref linkend="opt-services.matrix-synapse.settings.registration_shared_secret" />.
|
||||||
To create a new user or admin, run the following after you have set the secret
|
To create a new user or admin, run the following after you have
|
||||||
and have rebuilt NixOS:
|
set the secret and have rebuilt NixOS:
|
||||||
<screen>
|
</para>
|
||||||
<prompt>$ </prompt>nix-shell -p matrix-synapse
|
<programlisting>
|
||||||
<prompt>$ </prompt>register_new_matrix_user -k <replaceable>your-registration-shared-secret</replaceable> http://localhost:8008
|
$ nix-shell -p matrix-synapse
|
||||||
<prompt>New user localpart: </prompt><replaceable>your-username</replaceable>
|
$ register_new_matrix_user -k your-registration-shared-secret http://localhost:8008
|
||||||
<prompt>Password:</prompt>
|
New user localpart: your-username
|
||||||
<prompt>Confirm password:</prompt>
|
Password:
|
||||||
<prompt>Make admin [no]:</prompt>
|
Confirm password:
|
||||||
|
Make admin [no]:
|
||||||
Success!
|
Success!
|
||||||
</screen>
|
</programlisting>
|
||||||
In the example, this would create a user with the Matrix Identifier
|
<para>
|
||||||
<literal>@your-username:example.org</literal>.
|
In the example, this would create a user with the Matrix
|
||||||
|
Identifier <literal>@your-username:example.org</literal>.
|
||||||
|
</para>
|
||||||
<warning>
|
<warning>
|
||||||
<para>
|
<para>
|
||||||
When using <xref linkend="opt-services.matrix-synapse.settings.registration_shared_secret" />, the secret
|
When using
|
||||||
will end up in the world-readable store. Instead it's recommended to deploy the secret
|
<xref linkend="opt-services.matrix-synapse.settings.registration_shared_secret" />,
|
||||||
in an additional file like this:
|
the secret will end up in the world-readable store. Instead it’s
|
||||||
|
recommended to deploy the secret in an additional file like
|
||||||
|
this:
|
||||||
|
</para>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Create a file with the following contents:
|
Create a file with the following contents:
|
||||||
<programlisting>registration_shared_secret: your-very-secret-secret</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
registration_shared_secret: your-very-secret-secret
|
||||||
|
</programlisting>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Deploy the file with a secret-manager such as <link xlink:href="https://nixops.readthedocs.io/en/latest/overview.html#managing-keys"><option>deployment.keys</option></link>
|
Deploy the file with a secret-manager such as
|
||||||
from <citerefentry><refentrytitle>nixops</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
<link xlink:href="https://nixops.readthedocs.io/en/latest/overview.html#managing-keys"><option>deployment.keys</option></link>
|
||||||
or <link xlink:href="https://github.com/Mic92/sops-nix/">sops-nix</link> to
|
from
|
||||||
e.g. <filename>/run/secrets/matrix-shared-secret</filename> and ensure that it's readable
|
<citerefentry><refentrytitle>nixops</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||||
by <package>matrix-synapse</package>.
|
or
|
||||||
|
<link xlink:href="https://github.com/Mic92/sops-nix/">sops-nix</link>
|
||||||
|
to e.g.
|
||||||
|
<filename>/run/secrets/matrix-shared-secret</filename> and
|
||||||
|
ensure that it’s readable by
|
||||||
|
<literal>matrix-synapse</literal>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Include the file like this in your configuration:
|
Include the file like this in your configuration:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
<xref linkend="opt-services.matrix-synapse.extraConfigFiles" /> = [
|
services.matrix-synapse.extraConfigFiles = [
|
||||||
"/run/secrets/matrix-shared-secret"
|
"/run/secrets/matrix-shared-secret"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
|
||||||
</warning>
|
</warning>
|
||||||
</para>
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
It's also possible to user alternative authentication mechanism such as
|
It’s also possible to user alternative authentication mechanism
|
||||||
<link xlink:href="https://github.com/matrix-org/matrix-synapse-ldap3">LDAP (via <literal>matrix-synapse-ldap3</literal>)</link>
|
such as
|
||||||
or <link xlink:href="https://matrix-org.github.io/synapse/latest/openid.html">OpenID</link>.
|
<link xlink:href="https://github.com/matrix-org/matrix-synapse-ldap3">LDAP
|
||||||
|
(via <literal>matrix-synapse-ldap3</literal>)</link> or
|
||||||
|
<link xlink:href="https://matrix-org.github.io/synapse/latest/openid.html">OpenID</link>.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-matrix-element-web">
|
<section xml:id="module-services-matrix-element-web">
|
||||||
<title>Element (formerly known as Riot) Web Client</title>
|
<title>Element (formerly known as Riot) Web Client</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://github.com/vector-im/riot-web/">Element Web</link> is
|
<link xlink:href="https://github.com/vector-im/riot-web/">Element
|
||||||
the reference web client for Matrix and developed by the core team at
|
Web</link> is the reference web client for Matrix and developed by
|
||||||
matrix.org. Element was formerly known as Riot.im, see the
|
the core team at matrix.org. Element was formerly known as
|
||||||
<link xlink:href="https://element.io/blog/welcome-to-element/">Element introductory blog post</link>
|
Riot.im, see the
|
||||||
for more information. The following snippet can be optionally added to the code before
|
<link xlink:href="https://element.io/blog/welcome-to-element/">Element
|
||||||
to complete the synapse installation with a web client served at
|
introductory blog post</link> for more information. The following
|
||||||
<code>https://element.myhostname.example.org</code> and
|
snippet can be optionally added to the code before to complete the
|
||||||
<code>https://element.example.org</code>. Alternatively, you can use the hosted
|
synapse installation with a web client served at
|
||||||
copy at <link xlink:href="https://app.element.io/">https://app.element.io/</link>,
|
<literal>https://element.myhostname.example.org</literal> and
|
||||||
|
<literal>https://element.example.org</literal>. Alternatively, you
|
||||||
|
can use the hosted copy at
|
||||||
|
<link xlink:href="https://app.element.io/">https://app.element.io/</link>,
|
||||||
or use other web clients or native client applications. Due to the
|
or use other web clients or native client applications. Due to the
|
||||||
<literal>/.well-known</literal> urls set up done above, many clients should
|
<literal>/.well-known</literal> urls set up done above, many
|
||||||
fill in the required connection details automatically when you enter your
|
clients should fill in the required connection details
|
||||||
Matrix Identifier. See
|
automatically when you enter your Matrix Identifier. See
|
||||||
<link xlink:href="https://matrix.org/docs/projects/try-matrix-now.html">Try
|
<link xlink:href="https://matrix.org/docs/projects/try-matrix-now.html">Try
|
||||||
Matrix Now!</link> for a list of existing clients and their supported
|
Matrix Now!</link> for a list of existing clients and their
|
||||||
featureset.
|
supported featureset.
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
services.nginx.virtualHosts."element.${fqdn}" = {
|
services.nginx.virtualHosts."element.${fqdn}" = {
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
enableACME = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
forceSSL = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.serverAliases">serverAliases</link> = [
|
serverAliases = [
|
||||||
"element.${config.networking.domain}"
|
"element.${config.networking.domain}"
|
||||||
];
|
];
|
||||||
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.root">root</link> = pkgs.element-web.override {
|
root = pkgs.element-web.override {
|
||||||
conf = {
|
conf = {
|
||||||
default_server_config = clientConfig; # see `clientConfig` from the snippet above.
|
default_server_config = clientConfig; # see `clientConfig` from the snippet above.
|
||||||
};
|
};
|
||||||
|
@ -258,18 +245,18 @@ Success!
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
The Element developers do not recommend running Element and your Matrix
|
The Element developers do not recommend running Element and your
|
||||||
homeserver on the same fully-qualified domain name for security reasons. In
|
Matrix homeserver on the same fully-qualified domain name for
|
||||||
the example, this means that you should not reuse the
|
security reasons. In the example, this means that you should not
|
||||||
<literal>myhostname.example.org</literal> virtualHost to also serve Element,
|
reuse the <literal>myhostname.example.org</literal> virtualHost
|
||||||
but instead serve it on a different subdomain, like
|
to also serve Element, but instead serve it on a different
|
||||||
<literal>element.example.org</literal> in the example. See the
|
subdomain, like <literal>element.example.org</literal> in the
|
||||||
|
example. See the
|
||||||
<link xlink:href="https://github.com/vector-im/element-web/tree/v1.10.0#important-security-notes">Element
|
<link xlink:href="https://github.com/vector-im/element-web/tree/v1.10.0#important-security-notes">Element
|
||||||
Important Security Notes</link> for more information on this subject.
|
Important Security Notes</link> for more information on this
|
||||||
|
subject.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
</section>
|
</section>
|
||||||
|
|
112
nixos/modules/services/misc/gitlab.md
Normal file
112
nixos/modules/services/misc/gitlab.md
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
# GitLab {#module-services-gitlab}
|
||||||
|
|
||||||
|
GitLab is a feature-rich git hosting service.
|
||||||
|
|
||||||
|
## Prerequisites {#module-services-gitlab-prerequisites}
|
||||||
|
|
||||||
|
The `gitlab` service exposes only an Unix socket at
|
||||||
|
`/run/gitlab/gitlab-workhorse.socket`. You need to
|
||||||
|
configure a webserver to proxy HTTP requests to the socket.
|
||||||
|
|
||||||
|
For instance, the following configuration could be used to use nginx as
|
||||||
|
frontend proxy:
|
||||||
|
```
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
recommendedGzipSettings = true;
|
||||||
|
recommendedOptimisation = true;
|
||||||
|
recommendedProxySettings = true;
|
||||||
|
recommendedTlsSettings = true;
|
||||||
|
virtualHosts."git.example.com" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/".proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuring {#module-services-gitlab-configuring}
|
||||||
|
|
||||||
|
GitLab depends on both PostgreSQL and Redis and will automatically enable
|
||||||
|
both services. In the case of PostgreSQL, a database and a role will be
|
||||||
|
created.
|
||||||
|
|
||||||
|
The default state dir is `/var/gitlab/state`. This is where
|
||||||
|
all data like the repositories and uploads will be stored.
|
||||||
|
|
||||||
|
A basic configuration with some custom settings could look like this:
|
||||||
|
```
|
||||||
|
services.gitlab = {
|
||||||
|
enable = true;
|
||||||
|
databasePasswordFile = "/var/keys/gitlab/db_password";
|
||||||
|
initialRootPasswordFile = "/var/keys/gitlab/root_password";
|
||||||
|
https = true;
|
||||||
|
host = "git.example.com";
|
||||||
|
port = 443;
|
||||||
|
user = "git";
|
||||||
|
group = "git";
|
||||||
|
smtp = {
|
||||||
|
enable = true;
|
||||||
|
address = "localhost";
|
||||||
|
port = 25;
|
||||||
|
};
|
||||||
|
secrets = {
|
||||||
|
dbFile = "/var/keys/gitlab/db";
|
||||||
|
secretFile = "/var/keys/gitlab/secret";
|
||||||
|
otpFile = "/var/keys/gitlab/otp";
|
||||||
|
jwsFile = "/var/keys/gitlab/jws";
|
||||||
|
};
|
||||||
|
extraConfig = {
|
||||||
|
gitlab = {
|
||||||
|
email_from = "gitlab-no-reply@example.com";
|
||||||
|
email_display_name = "Example GitLab";
|
||||||
|
email_reply_to = "gitlab-no-reply@example.com";
|
||||||
|
default_projects_features = { builds = false; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're setting up a new GitLab instance, generate new
|
||||||
|
secrets. You for instance use
|
||||||
|
`tr -dc A-Za-z0-9 < /dev/urandom | head -c 128 > /var/keys/gitlab/db` to
|
||||||
|
generate a new db secret. Make sure the files can be read by, and
|
||||||
|
only by, the user specified by
|
||||||
|
[services.gitlab.user](#opt-services.gitlab.user). GitLab
|
||||||
|
encrypts sensitive data stored in the database. If you're restoring
|
||||||
|
an existing GitLab instance, you must specify the secrets secret
|
||||||
|
from `config/secrets.yml` located in your GitLab
|
||||||
|
state folder.
|
||||||
|
|
||||||
|
When `incoming_mail.enabled` is set to `true`
|
||||||
|
in [extraConfig](#opt-services.gitlab.extraConfig) an additional
|
||||||
|
service called `gitlab-mailroom` is enabled for fetching incoming mail.
|
||||||
|
|
||||||
|
Refer to [](#ch-options) for all available configuration
|
||||||
|
options for the [services.gitlab](#opt-services.gitlab.enable) module.
|
||||||
|
|
||||||
|
## Maintenance {#module-services-gitlab-maintenance}
|
||||||
|
|
||||||
|
### Backups {#module-services-gitlab-maintenance-backups}
|
||||||
|
|
||||||
|
Backups can be configured with the options in
|
||||||
|
[services.gitlab.backup](#opt-services.gitlab.backup.keepTime). Use
|
||||||
|
the [services.gitlab.backup.startAt](#opt-services.gitlab.backup.startAt)
|
||||||
|
option to configure regular backups.
|
||||||
|
|
||||||
|
To run a manual backup, start the `gitlab-backup` service:
|
||||||
|
```ShellSession
|
||||||
|
$ systemctl start gitlab-backup.service
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rake tasks {#module-services-gitlab-maintenance-rake}
|
||||||
|
|
||||||
|
You can run GitLab's rake tasks with `gitlab-rake`
|
||||||
|
which will be available on the system when GitLab is enabled. You
|
||||||
|
will have to run the command as the user that you configured to run
|
||||||
|
GitLab with.
|
||||||
|
|
||||||
|
A list of all available rake tasks can be obtained by running:
|
||||||
|
```ShellSession
|
||||||
|
$ sudo -u git -H gitlab-rake -T
|
||||||
|
```
|
|
@ -1,151 +1,143 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-gitlab">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-gitlab">
|
|
||||||
<title>GitLab</title>
|
<title>GitLab</title>
|
||||||
<para>
|
<para>
|
||||||
GitLab is a feature-rich git hosting service.
|
GitLab is a feature-rich git hosting service.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-gitlab-prerequisites">
|
<section xml:id="module-services-gitlab-prerequisites">
|
||||||
<title>Prerequisites</title>
|
<title>Prerequisites</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <literal>gitlab</literal> service exposes only an Unix socket at
|
The <literal>gitlab</literal> service exposes only an Unix socket
|
||||||
<literal>/run/gitlab/gitlab-workhorse.socket</literal>. You need to
|
at <literal>/run/gitlab/gitlab-workhorse.socket</literal>. You
|
||||||
configure a webserver to proxy HTTP requests to the socket.
|
need to configure a webserver to proxy HTTP requests to the
|
||||||
|
socket.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For instance, the following configuration could be used to use nginx as
|
For instance, the following configuration could be used to use
|
||||||
frontend proxy:
|
nginx as frontend proxy:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<link linkend="opt-services.nginx.enable">services.nginx</link> = {
|
services.nginx = {
|
||||||
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.nginx.recommendedGzipSettings">recommendedGzipSettings</link> = true;
|
recommendedGzipSettings = true;
|
||||||
<link linkend="opt-services.nginx.recommendedOptimisation">recommendedOptimisation</link> = true;
|
recommendedOptimisation = true;
|
||||||
<link linkend="opt-services.nginx.recommendedProxySettings">recommendedProxySettings</link> = true;
|
recommendedProxySettings = true;
|
||||||
<link linkend="opt-services.nginx.recommendedTlsSettings">recommendedTlsSettings</link> = true;
|
recommendedTlsSettings = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link>."git.example.com" = {
|
virtualHosts."git.example.com" = {
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
enableACME = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
forceSSL = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.proxyPass">locations."/".proxyPass</link> = "http://unix:/run/gitlab/gitlab-workhorse.socket";
|
locations."/".proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-gitlab-configuring">
|
<section xml:id="module-services-gitlab-configuring">
|
||||||
<title>Configuring</title>
|
<title>Configuring</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
GitLab depends on both PostgreSQL and Redis and will automatically enable
|
GitLab depends on both PostgreSQL and Redis and will automatically
|
||||||
both services. In the case of PostgreSQL, a database and a role will be
|
enable both services. In the case of PostgreSQL, a database and a
|
||||||
created.
|
role will be created.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The default state dir is <literal>/var/gitlab/state</literal>. This is where
|
The default state dir is <literal>/var/gitlab/state</literal>.
|
||||||
all data like the repositories and uploads will be stored.
|
This is where all data like the repositories and uploads will be
|
||||||
|
stored.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A basic configuration with some custom settings could look like this:
|
A basic configuration with some custom settings could look like
|
||||||
|
this:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.gitlab = {
|
services.gitlab = {
|
||||||
<link linkend="opt-services.gitlab.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.gitlab.databasePasswordFile">databasePasswordFile</link> = "/var/keys/gitlab/db_password";
|
databasePasswordFile = "/var/keys/gitlab/db_password";
|
||||||
<link linkend="opt-services.gitlab.initialRootPasswordFile">initialRootPasswordFile</link> = "/var/keys/gitlab/root_password";
|
initialRootPasswordFile = "/var/keys/gitlab/root_password";
|
||||||
<link linkend="opt-services.gitlab.https">https</link> = true;
|
https = true;
|
||||||
<link linkend="opt-services.gitlab.host">host</link> = "git.example.com";
|
host = "git.example.com";
|
||||||
<link linkend="opt-services.gitlab.port">port</link> = 443;
|
port = 443;
|
||||||
<link linkend="opt-services.gitlab.user">user</link> = "git";
|
user = "git";
|
||||||
<link linkend="opt-services.gitlab.group">group</link> = "git";
|
group = "git";
|
||||||
smtp = {
|
smtp = {
|
||||||
<link linkend="opt-services.gitlab.smtp.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.gitlab.smtp.address">address</link> = "localhost";
|
address = "localhost";
|
||||||
<link linkend="opt-services.gitlab.smtp.port">port</link> = 25;
|
port = 25;
|
||||||
};
|
};
|
||||||
secrets = {
|
secrets = {
|
||||||
<link linkend="opt-services.gitlab.secrets.dbFile">dbFile</link> = "/var/keys/gitlab/db";
|
dbFile = "/var/keys/gitlab/db";
|
||||||
<link linkend="opt-services.gitlab.secrets.secretFile">secretFile</link> = "/var/keys/gitlab/secret";
|
secretFile = "/var/keys/gitlab/secret";
|
||||||
<link linkend="opt-services.gitlab.secrets.otpFile">otpFile</link> = "/var/keys/gitlab/otp";
|
otpFile = "/var/keys/gitlab/otp";
|
||||||
<link linkend="opt-services.gitlab.secrets.jwsFile">jwsFile</link> = "/var/keys/gitlab/jws";
|
jwsFile = "/var/keys/gitlab/jws";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.gitlab.extraConfig">extraConfig</link> = {
|
extraConfig = {
|
||||||
gitlab = {
|
gitlab = {
|
||||||
email_from = "gitlab-no-reply@example.com";
|
email_from = "gitlab-no-reply@example.com";
|
||||||
email_display_name = "Example GitLab";
|
email_display_name = "Example GitLab";
|
||||||
email_reply_to = "gitlab-no-reply@example.com";
|
email_reply_to = "gitlab-no-reply@example.com";
|
||||||
default_projects_features = { builds = false; };
|
default_projects_features = { builds = false; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you're setting up a new GitLab instance, generate new
|
If you’re setting up a new GitLab instance, generate new secrets.
|
||||||
secrets. You for instance use <literal>tr -dc A-Za-z0-9 <
|
You for instance use
|
||||||
/dev/urandom | head -c 128 > /var/keys/gitlab/db</literal> to
|
<literal>tr -dc A-Za-z0-9 < /dev/urandom | head -c 128 > /var/keys/gitlab/db</literal>
|
||||||
generate a new db secret. Make sure the files can be read by, and
|
to generate a new db secret. Make sure the files can be read by,
|
||||||
only by, the user specified by <link
|
and only by, the user specified by
|
||||||
linkend="opt-services.gitlab.user">services.gitlab.user</link>. GitLab
|
<link linkend="opt-services.gitlab.user">services.gitlab.user</link>.
|
||||||
encrypts sensitive data stored in the database. If you're restoring
|
GitLab encrypts sensitive data stored in the database. If you’re
|
||||||
an existing GitLab instance, you must specify the secrets secret
|
restoring an existing GitLab instance, you must specify the
|
||||||
from <literal>config/secrets.yml</literal> located in your GitLab
|
secrets secret from <literal>config/secrets.yml</literal> located
|
||||||
state folder.
|
in your GitLab state folder.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When <literal>incoming_mail.enabled</literal> is set to <literal>true</literal>
|
When <literal>incoming_mail.enabled</literal> is set to
|
||||||
in <link linkend="opt-services.gitlab.extraConfig">extraConfig</link> an additional
|
<literal>true</literal> in
|
||||||
service called <literal>gitlab-mailroom</literal> is enabled for fetching incoming mail.
|
<link linkend="opt-services.gitlab.extraConfig">extraConfig</link>
|
||||||
|
an additional service called <literal>gitlab-mailroom</literal> is
|
||||||
|
enabled for fetching incoming mail.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Refer to <xref linkend="ch-options" /> for all available configuration
|
Refer to <xref linkend="ch-options" /> for all available
|
||||||
options for the
|
configuration options for the
|
||||||
<link linkend="opt-services.gitlab.enable">services.gitlab</link> module.
|
<link linkend="opt-services.gitlab.enable">services.gitlab</link>
|
||||||
|
module.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-gitlab-maintenance">
|
<section xml:id="module-services-gitlab-maintenance">
|
||||||
<title>Maintenance</title>
|
<title>Maintenance</title>
|
||||||
|
|
||||||
<section xml:id="module-services-gitlab-maintenance-backups">
|
<section xml:id="module-services-gitlab-maintenance-backups">
|
||||||
<title>Backups</title>
|
<title>Backups</title>
|
||||||
<para>
|
<para>
|
||||||
Backups can be configured with the options in <link
|
Backups can be configured with the options in
|
||||||
linkend="opt-services.gitlab.backup.keepTime">services.gitlab.backup</link>. Use
|
<link linkend="opt-services.gitlab.backup.keepTime">services.gitlab.backup</link>.
|
||||||
the <link
|
Use the
|
||||||
linkend="opt-services.gitlab.backup.startAt">services.gitlab.backup.startAt</link>
|
<link linkend="opt-services.gitlab.backup.startAt">services.gitlab.backup.startAt</link>
|
||||||
option to configure regular backups.
|
option to configure regular backups.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To run a manual backup, start the <literal>gitlab-backup</literal> service:
|
To run a manual backup, start the
|
||||||
<screen>
|
<literal>gitlab-backup</literal> service:
|
||||||
<prompt>$ </prompt>systemctl start gitlab-backup.service
|
|
||||||
</screen>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ systemctl start gitlab-backup.service
|
||||||
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-gitlab-maintenance-rake">
|
<section xml:id="module-services-gitlab-maintenance-rake">
|
||||||
<title>Rake tasks</title>
|
<title>Rake tasks</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
You can run GitLab's rake tasks with <literal>gitlab-rake</literal>
|
You can run GitLab’s rake tasks with
|
||||||
which will be available on the system when GitLab is enabled. You
|
<literal>gitlab-rake</literal> which will be available on the
|
||||||
will have to run the command as the user that you configured to run
|
system when GitLab is enabled. You will have to run the command
|
||||||
GitLab with.
|
as the user that you configured to run GitLab with.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A list of all available rake tasks can be obtained by running:
|
A list of all available rake tasks can be obtained by running:
|
||||||
<screen>
|
|
||||||
<prompt>$ </prompt>sudo -u git -H gitlab-rake -T
|
|
||||||
</screen>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ sudo -u git -H gitlab-rake -T
|
||||||
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
93
nixos/modules/services/misc/sourcehut/default.md
Normal file
93
nixos/modules/services/misc/sourcehut/default.md
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
# Sourcehut {#module-services-sourcehut}
|
||||||
|
|
||||||
|
[Sourcehut](https://sr.ht.com/) is an open-source,
|
||||||
|
self-hostable software development platform. The server setup can be automated using
|
||||||
|
[services.sourcehut](#opt-services.sourcehut.enable).
|
||||||
|
|
||||||
|
## Basic usage {#module-services-sourcehut-basic-usage}
|
||||||
|
|
||||||
|
Sourcehut is a Python and Go based set of applications.
|
||||||
|
This NixOS module also provides basic configuration integrating Sourcehut into locally running
|
||||||
|
`services.nginx`, `services.redis.servers.sourcehut`, `services.postfix`
|
||||||
|
and `services.postgresql` services.
|
||||||
|
|
||||||
|
A very basic configuration may look like this:
|
||||||
|
```
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
fqdn =
|
||||||
|
let
|
||||||
|
join = hostName: domain: hostName + optionalString (domain != null) ".${domain}";
|
||||||
|
in join config.networking.hostName config.networking.domain;
|
||||||
|
in {
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
hostName = "srht";
|
||||||
|
domain = "tld";
|
||||||
|
firewall.allowedTCPPorts = [ 22 80 443 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.sourcehut = {
|
||||||
|
enable = true;
|
||||||
|
git.enable = true;
|
||||||
|
man.enable = true;
|
||||||
|
meta.enable = true;
|
||||||
|
nginx.enable = true;
|
||||||
|
postfix.enable = true;
|
||||||
|
postgresql.enable = true;
|
||||||
|
redis.enable = true;
|
||||||
|
settings = {
|
||||||
|
"sr.ht" = {
|
||||||
|
environment = "production";
|
||||||
|
global-domain = fqdn;
|
||||||
|
origin = "https://${fqdn}";
|
||||||
|
# Produce keys with srht-keygen from sourcehut.coresrht.
|
||||||
|
network-key = "/run/keys/path/to/network-key";
|
||||||
|
service-key = "/run/keys/path/to/service-key";
|
||||||
|
};
|
||||||
|
webhooks.private-key= "/run/keys/path/to/webhook-key";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
security.acme.certs."${fqdn}".extraDomainNames = [
|
||||||
|
"meta.${fqdn}"
|
||||||
|
"man.${fqdn}"
|
||||||
|
"git.${fqdn}"
|
||||||
|
];
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
# only recommendedProxySettings are strictly required, but the rest make sense as well.
|
||||||
|
recommendedTlsSettings = true;
|
||||||
|
recommendedOptimisation = true;
|
||||||
|
recommendedGzipSettings = true;
|
||||||
|
recommendedProxySettings = true;
|
||||||
|
|
||||||
|
# Settings to setup what certificates are used for which endpoint.
|
||||||
|
virtualHosts = {
|
||||||
|
"${fqdn}".enableACME = true;
|
||||||
|
"meta.${fqdn}".useACMEHost = fqdn:
|
||||||
|
"man.${fqdn}".useACMEHost = fqdn:
|
||||||
|
"git.${fqdn}".useACMEHost = fqdn:
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `hostName` option is used internally to configure the nginx
|
||||||
|
reverse-proxy. The `settings` attribute set is
|
||||||
|
used by the configuration generator and the result is placed in `/etc/sr.ht/config.ini`.
|
||||||
|
|
||||||
|
## Configuration {#module-services-sourcehut-configuration}
|
||||||
|
|
||||||
|
All configuration parameters are also stored in
|
||||||
|
`/etc/sr.ht/config.ini` which is generated by
|
||||||
|
the module and linked from the store to ensure that all values from `config.ini`
|
||||||
|
can be modified by the module.
|
||||||
|
|
||||||
|
## Using an alternative webserver as reverse-proxy (e.g. `httpd`) {#module-services-sourcehut-httpd}
|
||||||
|
|
||||||
|
By default, `nginx` is used as reverse-proxy for `sourcehut`.
|
||||||
|
However, it's possible to use e.g. `httpd` by explicitly disabling
|
||||||
|
`nginx` using [](#opt-services.nginx.enable) and fixing the
|
||||||
|
`settings`.
|
|
@ -1390,6 +1390,6 @@ in
|
||||||
'')
|
'')
|
||||||
];
|
];
|
||||||
|
|
||||||
meta.doc = ./sourcehut.xml;
|
meta.doc = ./default.xml;
|
||||||
meta.maintainers = with maintainers; [ tomberek ];
|
meta.maintainers = with maintainers; [ tomberek ];
|
||||||
}
|
}
|
||||||
|
|
113
nixos/modules/services/misc/sourcehut/default.xml
Normal file
113
nixos/modules/services/misc/sourcehut/default.xml
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-sourcehut">
|
||||||
|
<title>Sourcehut</title>
|
||||||
|
<para>
|
||||||
|
<link xlink:href="https://sr.ht.com/">Sourcehut</link> is an
|
||||||
|
open-source, self-hostable software development platform. The server
|
||||||
|
setup can be automated using
|
||||||
|
<link linkend="opt-services.sourcehut.enable">services.sourcehut</link>.
|
||||||
|
</para>
|
||||||
|
<section xml:id="module-services-sourcehut-basic-usage">
|
||||||
|
<title>Basic usage</title>
|
||||||
|
<para>
|
||||||
|
Sourcehut is a Python and Go based set of applications. This NixOS
|
||||||
|
module also provides basic configuration integrating Sourcehut
|
||||||
|
into locally running <literal>services.nginx</literal>,
|
||||||
|
<literal>services.redis.servers.sourcehut</literal>,
|
||||||
|
<literal>services.postfix</literal> and
|
||||||
|
<literal>services.postgresql</literal> services.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A very basic configuration may look like this:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
fqdn =
|
||||||
|
let
|
||||||
|
join = hostName: domain: hostName + optionalString (domain != null) ".${domain}";
|
||||||
|
in join config.networking.hostName config.networking.domain;
|
||||||
|
in {
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
hostName = "srht";
|
||||||
|
domain = "tld";
|
||||||
|
firewall.allowedTCPPorts = [ 22 80 443 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.sourcehut = {
|
||||||
|
enable = true;
|
||||||
|
git.enable = true;
|
||||||
|
man.enable = true;
|
||||||
|
meta.enable = true;
|
||||||
|
nginx.enable = true;
|
||||||
|
postfix.enable = true;
|
||||||
|
postgresql.enable = true;
|
||||||
|
redis.enable = true;
|
||||||
|
settings = {
|
||||||
|
"sr.ht" = {
|
||||||
|
environment = "production";
|
||||||
|
global-domain = fqdn;
|
||||||
|
origin = "https://${fqdn}";
|
||||||
|
# Produce keys with srht-keygen from sourcehut.coresrht.
|
||||||
|
network-key = "/run/keys/path/to/network-key";
|
||||||
|
service-key = "/run/keys/path/to/service-key";
|
||||||
|
};
|
||||||
|
webhooks.private-key= "/run/keys/path/to/webhook-key";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
security.acme.certs."${fqdn}".extraDomainNames = [
|
||||||
|
"meta.${fqdn}"
|
||||||
|
"man.${fqdn}"
|
||||||
|
"git.${fqdn}"
|
||||||
|
];
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
# only recommendedProxySettings are strictly required, but the rest make sense as well.
|
||||||
|
recommendedTlsSettings = true;
|
||||||
|
recommendedOptimisation = true;
|
||||||
|
recommendedGzipSettings = true;
|
||||||
|
recommendedProxySettings = true;
|
||||||
|
|
||||||
|
# Settings to setup what certificates are used for which endpoint.
|
||||||
|
virtualHosts = {
|
||||||
|
"${fqdn}".enableACME = true;
|
||||||
|
"meta.${fqdn}".useACMEHost = fqdn:
|
||||||
|
"man.${fqdn}".useACMEHost = fqdn:
|
||||||
|
"git.${fqdn}".useACMEHost = fqdn:
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
The <literal>hostName</literal> option is used internally to
|
||||||
|
configure the nginx reverse-proxy. The <literal>settings</literal>
|
||||||
|
attribute set is used by the configuration generator and the
|
||||||
|
result is placed in <literal>/etc/sr.ht/config.ini</literal>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-sourcehut-configuration">
|
||||||
|
<title>Configuration</title>
|
||||||
|
<para>
|
||||||
|
All configuration parameters are also stored in
|
||||||
|
<literal>/etc/sr.ht/config.ini</literal> which is generated by the
|
||||||
|
module and linked from the store to ensure that all values from
|
||||||
|
<literal>config.ini</literal> can be modified by the module.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-sourcehut-httpd">
|
||||||
|
<title>Using an alternative webserver as reverse-proxy (e.g.
|
||||||
|
<literal>httpd</literal>)</title>
|
||||||
|
<para>
|
||||||
|
By default, <literal>nginx</literal> is used as reverse-proxy for
|
||||||
|
<literal>sourcehut</literal>. However, it’s possible to use e.g.
|
||||||
|
<literal>httpd</literal> by explicitly disabling
|
||||||
|
<literal>nginx</literal> using
|
||||||
|
<xref linkend="opt-services.nginx.enable" /> and fixing the
|
||||||
|
<literal>settings</literal>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
|
@ -1,119 +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="module-services-sourcehut">
|
|
||||||
<title>Sourcehut</title>
|
|
||||||
<para>
|
|
||||||
<link xlink:href="https://sr.ht.com/">Sourcehut</link> is an open-source,
|
|
||||||
self-hostable software development platform. The server setup can be automated using
|
|
||||||
<link linkend="opt-services.sourcehut.enable">services.sourcehut</link>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section xml:id="module-services-sourcehut-basic-usage">
|
|
||||||
<title>Basic usage</title>
|
|
||||||
<para>
|
|
||||||
Sourcehut is a Python and Go based set of applications.
|
|
||||||
This NixOS module also provides basic configuration integrating Sourcehut into locally running
|
|
||||||
<literal><link linkend="opt-services.nginx.enable">services.nginx</link></literal>,
|
|
||||||
<literal><link linkend="opt-services.redis.servers">services.redis.servers.sourcehut</link></literal>,
|
|
||||||
<literal><link linkend="opt-services.postfix.enable">services.postfix</link></literal>
|
|
||||||
and
|
|
||||||
<literal><link linkend="opt-services.postgresql.enable">services.postgresql</link></literal> services.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
A very basic configuration may look like this:
|
|
||||||
<programlisting>
|
|
||||||
{ pkgs, ... }:
|
|
||||||
let
|
|
||||||
fqdn =
|
|
||||||
let
|
|
||||||
join = hostName: domain: hostName + optionalString (domain != null) ".${domain}";
|
|
||||||
in join config.networking.hostName config.networking.domain;
|
|
||||||
in {
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
<link linkend="opt-networking.hostName">hostName</link> = "srht";
|
|
||||||
<link linkend="opt-networking.domain">domain</link> = "tld";
|
|
||||||
<link linkend="opt-networking.firewall.allowedTCPPorts">firewall.allowedTCPPorts</link> = [ 22 80 443 ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.sourcehut = {
|
|
||||||
<link linkend="opt-services.sourcehut.enable">enable</link> = true;
|
|
||||||
<link linkend="opt-services.sourcehut.git.enable">git.enable</link> = true;
|
|
||||||
<link linkend="opt-services.sourcehut.man.enable">man.enable</link> = true;
|
|
||||||
<link linkend="opt-services.sourcehut.meta.enable">meta.enable</link> = true;
|
|
||||||
<link linkend="opt-services.sourcehut.nginx.enable">nginx.enable</link> = true;
|
|
||||||
<link linkend="opt-services.sourcehut.postfix.enable">postfix.enable</link> = true;
|
|
||||||
<link linkend="opt-services.sourcehut.postgresql.enable">postgresql.enable</link> = true;
|
|
||||||
<link linkend="opt-services.sourcehut.redis.enable">redis.enable</link> = true;
|
|
||||||
<link linkend="opt-services.sourcehut.settings">settings</link> = {
|
|
||||||
"sr.ht" = {
|
|
||||||
environment = "production";
|
|
||||||
global-domain = fqdn;
|
|
||||||
origin = "https://${fqdn}";
|
|
||||||
# Produce keys with srht-keygen from <package>sourcehut.coresrht</package>.
|
|
||||||
network-key = "/run/keys/path/to/network-key";
|
|
||||||
service-key = "/run/keys/path/to/service-key";
|
|
||||||
};
|
|
||||||
webhooks.private-key= "/run/keys/path/to/webhook-key";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomainNames">security.acme.certs."${fqdn}".extraDomainNames</link> = [
|
|
||||||
"meta.${fqdn}"
|
|
||||||
"man.${fqdn}"
|
|
||||||
"git.${fqdn}"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.nginx = {
|
|
||||||
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
|
||||||
# only recommendedProxySettings are strictly required, but the rest make sense as well.
|
|
||||||
<link linkend="opt-services.nginx.recommendedTlsSettings">recommendedTlsSettings</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.recommendedOptimisation">recommendedOptimisation</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.recommendedGzipSettings">recommendedGzipSettings</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.recommendedProxySettings">recommendedProxySettings</link> = true;
|
|
||||||
|
|
||||||
# Settings to setup what certificates are used for which endpoint.
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">"${fqdn}".enableACME</link> = true;
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">"meta.${fqdn}".useACMEHost</link> = fqdn:
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">"man.${fqdn}".useACMEHost</link> = fqdn:
|
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">"git.${fqdn}".useACMEHost</link> = fqdn:
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The <literal>hostName</literal> option is used internally to configure the nginx
|
|
||||||
reverse-proxy. The <literal>settings</literal> attribute set is
|
|
||||||
used by the configuration generator and the result is placed in <literal>/etc/sr.ht/config.ini</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section xml:id="module-services-sourcehut-configuration">
|
|
||||||
<title>Configuration</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
All configuration parameters are also stored in
|
|
||||||
<literal>/etc/sr.ht/config.ini</literal> which is generated by
|
|
||||||
the module and linked from the store to ensure that all values from <literal>config.ini</literal>
|
|
||||||
can be modified by the module.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section xml:id="module-services-sourcehut-httpd">
|
|
||||||
<title>Using an alternative webserver as reverse-proxy (e.g. <literal>httpd</literal>)</title>
|
|
||||||
<para>
|
|
||||||
By default, <package>nginx</package> is used as reverse-proxy for <package>sourcehut</package>.
|
|
||||||
However, it's possible to use e.g. <package>httpd</package> by explicitly disabling
|
|
||||||
<package>nginx</package> using <xref linkend="opt-services.nginx.enable" /> and fixing the
|
|
||||||
<literal>settings</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</chapter>
|
|
93
nixos/modules/services/misc/taskserver/default.md
Normal file
93
nixos/modules/services/misc/taskserver/default.md
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
# Taskserver {#module-services-taskserver}
|
||||||
|
|
||||||
|
Taskserver is the server component of
|
||||||
|
[Taskwarrior](https://taskwarrior.org/), a free and
|
||||||
|
open source todo list application.
|
||||||
|
|
||||||
|
*Upstream documentation:* <https://taskwarrior.org/docs/#taskd>
|
||||||
|
|
||||||
|
## Configuration {#module-services-taskserver-configuration}
|
||||||
|
|
||||||
|
Taskserver does all of its authentication via TLS using client certificates,
|
||||||
|
so you either need to roll your own CA or purchase a certificate from a
|
||||||
|
known CA, which allows creation of client certificates. These certificates
|
||||||
|
are usually advertised as "server certificates".
|
||||||
|
|
||||||
|
So in order to make it easier to handle your own CA, there is a helper tool
|
||||||
|
called {command}`nixos-taskserver` which manages the custom CA along
|
||||||
|
with Taskserver organisations, users and groups.
|
||||||
|
|
||||||
|
While the client certificates in Taskserver only authenticate whether a user
|
||||||
|
is allowed to connect, every user has its own UUID which identifies it as an
|
||||||
|
entity.
|
||||||
|
|
||||||
|
With {command}`nixos-taskserver` the client certificate is created
|
||||||
|
along with the UUID of the user, so it handles all of the credentials needed
|
||||||
|
in order to setup the Taskwarrior client to work with a Taskserver.
|
||||||
|
|
||||||
|
## The nixos-taskserver tool {#module-services-taskserver-nixos-taskserver-tool}
|
||||||
|
|
||||||
|
Because Taskserver by default only provides scripts to setup users
|
||||||
|
imperatively, the {command}`nixos-taskserver` tool is used for
|
||||||
|
addition and deletion of organisations along with users and groups defined
|
||||||
|
by [](#opt-services.taskserver.organisations) and as well for
|
||||||
|
imperative set up.
|
||||||
|
|
||||||
|
The tool is designed to not interfere if the command is used to manually set
|
||||||
|
up some organisations, users or groups.
|
||||||
|
|
||||||
|
For example if you add a new organisation using {command}`nixos-taskserver
|
||||||
|
org add foo`, the organisation is not modified and deleted no
|
||||||
|
matter what you define in
|
||||||
|
{option}`services.taskserver.organisations`, even if you're adding
|
||||||
|
the same organisation in that option.
|
||||||
|
|
||||||
|
The tool is modelled to imitate the official {command}`taskd`
|
||||||
|
command, documentation for each subcommand can be shown by using the
|
||||||
|
{option}`--help` switch.
|
||||||
|
|
||||||
|
## Declarative/automatic CA management {#module-services-taskserver-declarative-ca-management}
|
||||||
|
|
||||||
|
Everything is done according to what you specify in the module options,
|
||||||
|
however in order to set up a Taskwarrior client for synchronisation with a
|
||||||
|
Taskserver instance, you have to transfer the keys and certificates to the
|
||||||
|
client machine.
|
||||||
|
|
||||||
|
This is done using {command}`nixos-taskserver user export $orgname
|
||||||
|
$username` which is printing a shell script fragment to stdout
|
||||||
|
which can either be used verbatim or adjusted to import the user on the
|
||||||
|
client machine.
|
||||||
|
|
||||||
|
For example, let's say you have the following configuration:
|
||||||
|
```ShellSession
|
||||||
|
{
|
||||||
|
services.taskserver.enable = true;
|
||||||
|
services.taskserver.fqdn = "server";
|
||||||
|
services.taskserver.listenHost = "::";
|
||||||
|
services.taskserver.organisations.my-company.users = [ "alice" ];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This creates an organisation called `my-company` with the
|
||||||
|
user `alice`.
|
||||||
|
|
||||||
|
Now in order to import the `alice` user to another machine
|
||||||
|
`alicebox`, all we need to do is something like this:
|
||||||
|
```ShellSession
|
||||||
|
$ ssh server nixos-taskserver user export my-company alice | sh
|
||||||
|
```
|
||||||
|
Of course, if no SSH daemon is available on the server you can also copy
|
||||||
|
& paste it directly into a shell.
|
||||||
|
|
||||||
|
After this step the user should be set up and you can start synchronising
|
||||||
|
your tasks for the first time with {command}`task sync init` on
|
||||||
|
`alicebox`.
|
||||||
|
|
||||||
|
Subsequent synchronisation requests merely require the command {command}`task
|
||||||
|
sync` after that stage.
|
||||||
|
|
||||||
|
## Manual CA management {#module-services-taskserver-manual-ca-management}
|
||||||
|
|
||||||
|
If you set any options within
|
||||||
|
[service.taskserver.pki.manual](#opt-services.taskserver.pki.manual.ca.cert).*,
|
||||||
|
{command}`nixos-taskserver` won't issue certificates, but you can
|
||||||
|
still use it for adding or removing user accounts.
|
|
@ -566,5 +566,5 @@ in {
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
meta.doc = ./doc.xml;
|
meta.doc = ./default.xml;
|
||||||
}
|
}
|
||||||
|
|
130
nixos/modules/services/misc/taskserver/default.xml
Normal file
130
nixos/modules/services/misc/taskserver/default.xml
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-taskserver">
|
||||||
|
<title>Taskserver</title>
|
||||||
|
<para>
|
||||||
|
Taskserver is the server component of
|
||||||
|
<link xlink:href="https://taskwarrior.org/">Taskwarrior</link>, a
|
||||||
|
free and open source todo list application.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<emphasis>Upstream documentation:</emphasis>
|
||||||
|
<link xlink:href="https://taskwarrior.org/docs/#taskd">https://taskwarrior.org/docs/#taskd</link>
|
||||||
|
</para>
|
||||||
|
<section xml:id="module-services-taskserver-configuration">
|
||||||
|
<title>Configuration</title>
|
||||||
|
<para>
|
||||||
|
Taskserver does all of its authentication via TLS using client
|
||||||
|
certificates, so you either need to roll your own CA or purchase a
|
||||||
|
certificate from a known CA, which allows creation of client
|
||||||
|
certificates. These certificates are usually advertised as
|
||||||
|
<quote>server certificates</quote>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
So in order to make it easier to handle your own CA, there is a
|
||||||
|
helper tool called <command>nixos-taskserver</command> which
|
||||||
|
manages the custom CA along with Taskserver organisations, users
|
||||||
|
and groups.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
While the client certificates in Taskserver only authenticate
|
||||||
|
whether a user is allowed to connect, every user has its own UUID
|
||||||
|
which identifies it as an entity.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
With <command>nixos-taskserver</command> the client certificate is
|
||||||
|
created along with the UUID of the user, so it handles all of the
|
||||||
|
credentials needed in order to setup the Taskwarrior client to
|
||||||
|
work with a Taskserver.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-taskserver-nixos-taskserver-tool">
|
||||||
|
<title>The nixos-taskserver tool</title>
|
||||||
|
<para>
|
||||||
|
Because Taskserver by default only provides scripts to setup users
|
||||||
|
imperatively, the <command>nixos-taskserver</command> tool is used
|
||||||
|
for addition and deletion of organisations along with users and
|
||||||
|
groups defined by
|
||||||
|
<xref linkend="opt-services.taskserver.organisations" /> and as
|
||||||
|
well for imperative set up.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The tool is designed to not interfere if the command is used to
|
||||||
|
manually set up some organisations, users or groups.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example if you add a new organisation using
|
||||||
|
<command>nixos-taskserver org add foo</command>, the organisation
|
||||||
|
is not modified and deleted no matter what you define in
|
||||||
|
<option>services.taskserver.organisations</option>, even if you’re
|
||||||
|
adding the same organisation in that option.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The tool is modelled to imitate the official
|
||||||
|
<command>taskd</command> command, documentation for each
|
||||||
|
subcommand can be shown by using the <option>--help</option>
|
||||||
|
switch.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-taskserver-declarative-ca-management">
|
||||||
|
<title>Declarative/automatic CA management</title>
|
||||||
|
<para>
|
||||||
|
Everything is done according to what you specify in the module
|
||||||
|
options, however in order to set up a Taskwarrior client for
|
||||||
|
synchronisation with a Taskserver instance, you have to transfer
|
||||||
|
the keys and certificates to the client machine.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is done using
|
||||||
|
<command>nixos-taskserver user export $orgname $username</command>
|
||||||
|
which is printing a shell script fragment to stdout which can
|
||||||
|
either be used verbatim or adjusted to import the user on the
|
||||||
|
client machine.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example, let’s say you have the following configuration:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{
|
||||||
|
services.taskserver.enable = true;
|
||||||
|
services.taskserver.fqdn = "server";
|
||||||
|
services.taskserver.listenHost = "::";
|
||||||
|
services.taskserver.organisations.my-company.users = [ "alice" ];
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
This creates an organisation called <literal>my-company</literal>
|
||||||
|
with the user <literal>alice</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Now in order to import the <literal>alice</literal> user to
|
||||||
|
another machine <literal>alicebox</literal>, all we need to do is
|
||||||
|
something like this:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ ssh server nixos-taskserver user export my-company alice | sh
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Of course, if no SSH daemon is available on the server you can
|
||||||
|
also copy & paste it directly into a shell.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
After this step the user should be set up and you can start
|
||||||
|
synchronising your tasks for the first time with
|
||||||
|
<command>task sync init</command> on <literal>alicebox</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Subsequent synchronisation requests merely require the command
|
||||||
|
<command>task sync</command> after that stage.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-taskserver-manual-ca-management">
|
||||||
|
<title>Manual CA management</title>
|
||||||
|
<para>
|
||||||
|
If you set any options within
|
||||||
|
<link linkend="opt-services.taskserver.pki.manual.ca.cert">service.taskserver.pki.manual</link>.*,
|
||||||
|
<command>nixos-taskserver</command> won’t issue certificates, but
|
||||||
|
you can still use it for adding or removing user accounts.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
|
@ -1,135 +0,0 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-taskserver">
|
|
||||||
<title>Taskserver</title>
|
|
||||||
<para>
|
|
||||||
Taskserver is the server component of
|
|
||||||
<link xlink:href="https://taskwarrior.org/">Taskwarrior</link>, a free and
|
|
||||||
open source todo list application.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<emphasis>Upstream documentation:</emphasis>
|
|
||||||
<link xlink:href="https://taskwarrior.org/docs/#taskd"/>
|
|
||||||
</para>
|
|
||||||
<section xml:id="module-services-taskserver-configuration">
|
|
||||||
<title>Configuration</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Taskserver does all of its authentication via TLS using client certificates,
|
|
||||||
so you either need to roll your own CA or purchase a certificate from a
|
|
||||||
known CA, which allows creation of client certificates. These certificates
|
|
||||||
are usually advertised as <quote>server certificates</quote>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
So in order to make it easier to handle your own CA, there is a helper tool
|
|
||||||
called <command>nixos-taskserver</command> which manages the custom CA along
|
|
||||||
with Taskserver organisations, users and groups.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
While the client certificates in Taskserver only authenticate whether a user
|
|
||||||
is allowed to connect, every user has its own UUID which identifies it as an
|
|
||||||
entity.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
With <command>nixos-taskserver</command> the client certificate is created
|
|
||||||
along with the UUID of the user, so it handles all of the credentials needed
|
|
||||||
in order to setup the Taskwarrior client to work with a Taskserver.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-services-taskserver-nixos-taskserver-tool">
|
|
||||||
<title>The nixos-taskserver tool</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Because Taskserver by default only provides scripts to setup users
|
|
||||||
imperatively, the <command>nixos-taskserver</command> tool is used for
|
|
||||||
addition and deletion of organisations along with users and groups defined
|
|
||||||
by <xref linkend="opt-services.taskserver.organisations"/> and as well for
|
|
||||||
imperative set up.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The tool is designed to not interfere if the command is used to manually set
|
|
||||||
up some organisations, users or groups.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
For example if you add a new organisation using <command>nixos-taskserver
|
|
||||||
org add foo</command>, the organisation is not modified and deleted no
|
|
||||||
matter what you define in
|
|
||||||
<option>services.taskserver.organisations</option>, even if you're adding
|
|
||||||
the same organisation in that option.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The tool is modelled to imitate the official <command>taskd</command>
|
|
||||||
command, documentation for each subcommand can be shown by using the
|
|
||||||
<option>--help</option> switch.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-services-taskserver-declarative-ca-management">
|
|
||||||
<title>Declarative/automatic CA management</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Everything is done according to what you specify in the module options,
|
|
||||||
however in order to set up a Taskwarrior client for synchronisation with a
|
|
||||||
Taskserver instance, you have to transfer the keys and certificates to the
|
|
||||||
client machine.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This is done using <command>nixos-taskserver user export $orgname
|
|
||||||
$username</command> which is printing a shell script fragment to stdout
|
|
||||||
which can either be used verbatim or adjusted to import the user on the
|
|
||||||
client machine.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
For example, let's say you have the following configuration:
|
|
||||||
<screen>
|
|
||||||
{
|
|
||||||
<xref linkend="opt-services.taskserver.enable"/> = true;
|
|
||||||
<xref linkend="opt-services.taskserver.fqdn"/> = "server";
|
|
||||||
<xref linkend="opt-services.taskserver.listenHost"/> = "::";
|
|
||||||
<link linkend="opt-services.taskserver.organisations._name_.users">services.taskserver.organisations.my-company.users</link> = [ "alice" ];
|
|
||||||
}
|
|
||||||
</screen>
|
|
||||||
This creates an organisation called <literal>my-company</literal> with the
|
|
||||||
user <literal>alice</literal>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Now in order to import the <literal>alice</literal> user to another machine
|
|
||||||
<literal>alicebox</literal>, all we need to do is something like this:
|
|
||||||
<screen>
|
|
||||||
<prompt>$ </prompt>ssh server nixos-taskserver user export my-company alice | sh
|
|
||||||
</screen>
|
|
||||||
Of course, if no SSH daemon is available on the server you can also copy
|
|
||||||
& paste it directly into a shell.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
After this step the user should be set up and you can start synchronising
|
|
||||||
your tasks for the first time with <command>task sync init</command> on
|
|
||||||
<literal>alicebox</literal>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Subsequent synchronisation requests merely require the command <command>task
|
|
||||||
sync</command> after that stage.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-services-taskserver-manual-ca-management">
|
|
||||||
<title>Manual CA management</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If you set any options within
|
|
||||||
<link linkend="opt-services.taskserver.pki.manual.ca.cert">service.taskserver.pki.manual</link>.*,
|
|
||||||
<command>nixos-taskserver</command> won't issue certificates, but you can
|
|
||||||
still use it for adding or removing user accounts.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
46
nixos/modules/services/misc/weechat.md
Normal file
46
nixos/modules/services/misc/weechat.md
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
# WeeChat {#module-services-weechat}
|
||||||
|
|
||||||
|
[WeeChat](https://weechat.org/) is a fast and
|
||||||
|
extensible IRC client.
|
||||||
|
|
||||||
|
## Basic Usage {#module-services-weechat-basic-usage}
|
||||||
|
|
||||||
|
By default, the module creates a
|
||||||
|
[`systemd`](https://www.freedesktop.org/wiki/Software/systemd/)
|
||||||
|
unit which runs the chat client in a detached
|
||||||
|
[`screen`](https://www.gnu.org/software/screen/)
|
||||||
|
session.
|
||||||
|
|
||||||
|
This can be done by enabling the `weechat` service:
|
||||||
|
```
|
||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.weechat.enable = true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The service is managed by a dedicated user named `weechat`
|
||||||
|
in the state directory `/var/lib/weechat`.
|
||||||
|
|
||||||
|
## Re-attaching to WeeChat {#module-services-weechat-reattach}
|
||||||
|
|
||||||
|
WeeChat runs in a screen session owned by a dedicated user. To explicitly
|
||||||
|
allow your another user to attach to this session, the
|
||||||
|
`screenrc` needs to be tweaked by adding
|
||||||
|
[multiuser](https://www.gnu.org/software/screen/manual/html_node/Multiuser.html#Multiuser)
|
||||||
|
support:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
programs.screen.screenrc = ''
|
||||||
|
multiuser on
|
||||||
|
acladd normal_user
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Now, the session can be re-attached like this:
|
||||||
|
```
|
||||||
|
screen -x weechat/weechat-screen
|
||||||
|
```
|
||||||
|
|
||||||
|
*The session name can be changed using [services.weechat.sessionName.](options.html#opt-services.weechat.sessionName)*
|
|
@ -1,8 +1,6 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-weechat">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-weechat">
|
|
||||||
<title>WeeChat</title>
|
<title>WeeChat</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://weechat.org/">WeeChat</link> is a fast and
|
<link xlink:href="https://weechat.org/">WeeChat</link> is a fast and
|
||||||
|
@ -10,57 +8,56 @@
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-weechat-basic-usage">
|
<section xml:id="module-services-weechat-basic-usage">
|
||||||
<title>Basic Usage</title>
|
<title>Basic Usage</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
By default, the module creates a
|
By default, the module creates a
|
||||||
<literal><link xlink:href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</link></literal>
|
<link xlink:href="https://www.freedesktop.org/wiki/Software/systemd/"><literal>systemd</literal></link>
|
||||||
unit which runs the chat client in a detached
|
unit which runs the chat client in a detached
|
||||||
<literal><link xlink:href="https://www.gnu.org/software/screen/">screen</link></literal>
|
<link xlink:href="https://www.gnu.org/software/screen/"><literal>screen</literal></link>
|
||||||
session.
|
session.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This can be done by enabling the <literal>weechat</literal> service:
|
This can be done by enabling the <literal>weechat</literal>
|
||||||
|
service:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
<link linkend="opt-services.weechat.enable">services.weechat.enable</link> = true;
|
services.weechat.enable = true;
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The service is managed by a dedicated user named <literal>weechat</literal>
|
The service is managed by a dedicated user named
|
||||||
in the state directory <literal>/var/lib/weechat</literal>.
|
<literal>weechat</literal> in the state directory
|
||||||
|
<literal>/var/lib/weechat</literal>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-weechat-reattach">
|
<section xml:id="module-services-weechat-reattach">
|
||||||
<title>Re-attaching to WeeChat</title>
|
<title>Re-attaching to WeeChat</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
WeeChat runs in a screen session owned by a dedicated user. To explicitly
|
WeeChat runs in a screen session owned by a dedicated user. To
|
||||||
allow your another user to attach to this session, the
|
explicitly allow your another user to attach to this session, the
|
||||||
<literal>screenrc</literal> needs to be tweaked by adding
|
<literal>screenrc</literal> needs to be tweaked by adding
|
||||||
<link xlink:href="https://www.gnu.org/software/screen/manual/html_node/Multiuser.html#Multiuser">multiuser</link>
|
<link xlink:href="https://www.gnu.org/software/screen/manual/html_node/Multiuser.html#Multiuser">multiuser</link>
|
||||||
support:
|
support:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
<link linkend="opt-programs.screen.screenrc">programs.screen.screenrc</link> = ''
|
programs.screen.screenrc = ''
|
||||||
multiuser on
|
multiuser on
|
||||||
acladd normal_user
|
acladd normal_user
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
<para>
|
||||||
Now, the session can be re-attached like this:
|
Now, the session can be re-attached like this:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
screen -x weechat/weechat-screen
|
screen -x weechat/weechat-screen
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<emphasis>The session name can be changed using
|
<emphasis>The session name can be changed using
|
||||||
<link linkend="opt-services.weechat.sessionName">services.weechat.sessionName.</link></emphasis>
|
<link xlink:href="options.html#opt-services.weechat.sessionName">services.weechat.sessionName.</link></emphasis>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -25,7 +25,7 @@ services.parsedmarc = {
|
||||||
Note that GeoIP provisioning is disabled in the example for
|
Note that GeoIP provisioning is disabled in the example for
|
||||||
simplicity, but should be turned on for fully functional reports.
|
simplicity, but should be turned on for fully functional reports.
|
||||||
|
|
||||||
## Local mail
|
## Local mail {#module-services-parsedmarc-local-mail}
|
||||||
Instead of watching an external inbox, a local inbox can be
|
Instead of watching an external inbox, a local inbox can be
|
||||||
automatically provisioned. The recipient's name is by default set to
|
automatically provisioned. The recipient's name is by default set to
|
||||||
`dmarc`, but can be configured in
|
`dmarc`, but can be configured in
|
||||||
|
@ -49,7 +49,7 @@ services.parsedmarc = {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## Grafana and GeoIP
|
## Grafana and GeoIP {#module-services-parsedmarc-grafana-geoip}
|
||||||
The reports can be visualized and summarized with parsedmarc's
|
The reports can be visualized and summarized with parsedmarc's
|
||||||
official Grafana dashboard. For all views to work, and for the data to
|
official Grafana dashboard. For all views to work, and for the data to
|
||||||
be complete, GeoIP databases are also required. The following example
|
be complete, GeoIP databases are also required. The following example
|
||||||
|
|
|
@ -539,8 +539,6 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Don't edit the docbook xml directly, edit the md and generate it:
|
|
||||||
# `pandoc parsedmarc.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > parsedmarc.xml`
|
|
||||||
meta.doc = ./parsedmarc.xml;
|
meta.doc = ./parsedmarc.xml;
|
||||||
meta.maintainers = [ lib.maintainers.talyz ];
|
meta.maintainers = [ lib.maintainers.talyz ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-parsedmarc">
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-parsedmarc">
|
||||||
<title>parsedmarc</title>
|
<title>parsedmarc</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -15,7 +17,7 @@
|
||||||
email address and saves them to a local Elasticsearch instance
|
email address and saves them to a local Elasticsearch instance
|
||||||
looks like this:
|
looks like this:
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting language="nix">
|
||||||
services.parsedmarc = {
|
services.parsedmarc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings.imap = {
|
settings.imap = {
|
||||||
|
@ -31,7 +33,7 @@ services.parsedmarc = {
|
||||||
simplicity, but should be turned on for fully functional reports.
|
simplicity, but should be turned on for fully functional reports.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="local-mail">
|
<section xml:id="module-services-parsedmarc-local-mail">
|
||||||
<title>Local mail</title>
|
<title>Local mail</title>
|
||||||
<para>
|
<para>
|
||||||
Instead of watching an external inbox, a local inbox can be
|
Instead of watching an external inbox, a local inbox can be
|
||||||
|
@ -44,7 +46,7 @@ services.parsedmarc = {
|
||||||
email address that should be configured in the domain’s dmarc
|
email address that should be configured in the domain’s dmarc
|
||||||
policy is <literal>dmarc@monitoring.example.com</literal>.
|
policy is <literal>dmarc@monitoring.example.com</literal>.
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting language="nix">
|
||||||
services.parsedmarc = {
|
services.parsedmarc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
provision = {
|
provision = {
|
||||||
|
@ -57,7 +59,7 @@ services.parsedmarc = {
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="grafana-and-geoip">
|
<section xml:id="module-services-parsedmarc-grafana-geoip">
|
||||||
<title>Grafana and GeoIP</title>
|
<title>Grafana and GeoIP</title>
|
||||||
<para>
|
<para>
|
||||||
The reports can be visualized and summarized with parsedmarc’s
|
The reports can be visualized and summarized with parsedmarc’s
|
||||||
|
@ -67,7 +69,7 @@ services.parsedmarc = {
|
||||||
Elasticsearch instance is automatically added as a Grafana
|
Elasticsearch instance is automatically added as a Grafana
|
||||||
datasource, and the dashboard is added to Grafana as well.
|
datasource, and the dashboard is added to Grafana as well.
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting language="nix">
|
||||||
services.parsedmarc = {
|
services.parsedmarc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
provision = {
|
provision = {
|
||||||
|
|
180
nixos/modules/services/monitoring/prometheus/exporters.md
Normal file
180
nixos/modules/services/monitoring/prometheus/exporters.md
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
# Prometheus exporters {#module-services-prometheus-exporters}
|
||||||
|
|
||||||
|
Prometheus exporters provide metrics for the
|
||||||
|
[prometheus monitoring system](https://prometheus.io).
|
||||||
|
|
||||||
|
## Configuration {#module-services-prometheus-exporters-configuration}
|
||||||
|
|
||||||
|
One of the most common exporters is the
|
||||||
|
[node exporter](https://github.com/prometheus/node_exporter),
|
||||||
|
it provides hardware and OS metrics from the host it's
|
||||||
|
running on. The exporter could be configured as follows:
|
||||||
|
```
|
||||||
|
services.prometheus.exporters.node = {
|
||||||
|
enable = true;
|
||||||
|
port = 9100;
|
||||||
|
enabledCollectors = [
|
||||||
|
"logind"
|
||||||
|
"systemd"
|
||||||
|
];
|
||||||
|
disabledCollectors = [
|
||||||
|
"textfile"
|
||||||
|
];
|
||||||
|
openFirewall = true;
|
||||||
|
firewallFilter = "-i br0 -p tcp -m tcp --dport 9100";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
It should now serve all metrics from the collectors that are explicitly
|
||||||
|
enabled and the ones that are
|
||||||
|
[enabled by default](https://github.com/prometheus/node_exporter#enabled-by-default),
|
||||||
|
via http under `/metrics`. In this
|
||||||
|
example the firewall should just allow incoming connections to the
|
||||||
|
exporter's port on the bridge interface `br0` (this would
|
||||||
|
have to be configured separately of course). For more information about
|
||||||
|
configuration see `man configuration.nix` or search through
|
||||||
|
the [available options](https://nixos.org/nixos/options.html#prometheus.exporters).
|
||||||
|
|
||||||
|
Prometheus can now be configured to consume the metrics produced by the exporter:
|
||||||
|
```
|
||||||
|
services.prometheus = {
|
||||||
|
# ...
|
||||||
|
|
||||||
|
scrapeConfigs = [
|
||||||
|
{
|
||||||
|
job_name = "node";
|
||||||
|
static_configs = [{
|
||||||
|
targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding a new exporter {#module-services-prometheus-exporters-new-exporter}
|
||||||
|
|
||||||
|
To add a new exporter, it has to be packaged first (see
|
||||||
|
`nixpkgs/pkgs/servers/monitoring/prometheus/` for
|
||||||
|
examples), then a module can be added. The postfix exporter is used in this
|
||||||
|
example:
|
||||||
|
|
||||||
|
- Some default options for all exporters are provided by
|
||||||
|
`nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix`:
|
||||||
|
|
||||||
|
- `enable`
|
||||||
|
- `port`
|
||||||
|
- `listenAddress`
|
||||||
|
- `extraFlags`
|
||||||
|
- `openFirewall`
|
||||||
|
- `firewallFilter`
|
||||||
|
- `user`
|
||||||
|
- `group`
|
||||||
|
- As there is already a package available, the module can now be added. This
|
||||||
|
is accomplished by adding a new file to the
|
||||||
|
`nixos/modules/services/monitoring/prometheus/exporters/`
|
||||||
|
directory, which will be called postfix.nix and contains all exporter
|
||||||
|
specific options and configuration:
|
||||||
|
```
|
||||||
|
# nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
|
||||||
|
{ config, lib, pkgs, options }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
# for convenience we define cfg here
|
||||||
|
cfg = config.services.prometheus.exporters.postfix;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
port = 9154; # The postfix exporter listens on this port by default
|
||||||
|
|
||||||
|
# `extraOpts` is an attribute set which contains additional options
|
||||||
|
# (and optional overrides for default options).
|
||||||
|
# Note that this attribute is optional.
|
||||||
|
extraOpts = {
|
||||||
|
telemetryPath = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "/metrics";
|
||||||
|
description = ''
|
||||||
|
Path under which to expose metrics.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
logfilePath = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = /var/log/postfix_exporter_input.log;
|
||||||
|
example = /var/log/mail.log;
|
||||||
|
description = ''
|
||||||
|
Path where Postfix writes log entries.
|
||||||
|
This file will be truncated by this exporter!
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
showqPath = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = /var/spool/postfix/public/showq;
|
||||||
|
example = /var/lib/postfix/queue/public/showq;
|
||||||
|
description = ''
|
||||||
|
Path at which Postfix places its showq socket.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# `serviceOpts` is an attribute set which contains configuration
|
||||||
|
# for the exporter's systemd service. One of
|
||||||
|
# `serviceOpts.script` and `serviceOpts.serviceConfig.ExecStart`
|
||||||
|
# has to be specified here. This will be merged with the default
|
||||||
|
# service configuration.
|
||||||
|
# Note that by default 'DynamicUser' is 'true'.
|
||||||
|
serviceOpts = {
|
||||||
|
serviceConfig = {
|
||||||
|
DynamicUser = false;
|
||||||
|
ExecStart = ''
|
||||||
|
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
||||||
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
|
--web.telemetry-path ${cfg.telemetryPath} \
|
||||||
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- This should already be enough for the postfix exporter. Additionally one
|
||||||
|
could now add assertions and conditional default values. This can be done
|
||||||
|
in the 'meta-module' that combines all exporter definitions and generates
|
||||||
|
the submodules:
|
||||||
|
`nixpkgs/nixos/modules/services/prometheus/exporters.nix`
|
||||||
|
|
||||||
|
## Updating an exporter module {#module-services-prometheus-exporters-update-exporter-module}
|
||||||
|
|
||||||
|
Should an exporter option change at some point, it is possible to add
|
||||||
|
information about the change to the exporter definition similar to
|
||||||
|
`nixpkgs/nixos/modules/rename.nix`:
|
||||||
|
```
|
||||||
|
{ config, lib, pkgs, options }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.prometheus.exporters.nginx;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
port = 9113;
|
||||||
|
extraOpts = {
|
||||||
|
# additional module options
|
||||||
|
# ...
|
||||||
|
};
|
||||||
|
serviceOpts = {
|
||||||
|
# service configuration
|
||||||
|
# ...
|
||||||
|
};
|
||||||
|
imports = [
|
||||||
|
# 'services.prometheus.exporters.nginx.telemetryEndpoint' -> 'services.prometheus.exporters.nginx.telemetryPath'
|
||||||
|
(mkRenamedOptionModule [ "telemetryEndpoint" ] [ "telemetryPath" ])
|
||||||
|
|
||||||
|
# removed option 'services.prometheus.exporters.nginx.insecure'
|
||||||
|
(mkRemovedOptionModule [ "insecure" ] ''
|
||||||
|
This option was replaced by 'prometheus.exporters.nginx.sslVerify' which defaults to true.
|
||||||
|
'')
|
||||||
|
({ options.warnings = options.warnings; })
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
|
@ -1,60 +1,61 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-prometheus-exporters">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-prometheus-exporters">
|
|
||||||
<title>Prometheus exporters</title>
|
<title>Prometheus exporters</title>
|
||||||
<para>
|
<para>
|
||||||
Prometheus exporters provide metrics for the
|
Prometheus exporters provide metrics for the
|
||||||
<link xlink:href="https://prometheus.io">prometheus monitoring system</link>.
|
<link xlink:href="https://prometheus.io">prometheus monitoring
|
||||||
|
system</link>.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-prometheus-exporters-configuration">
|
<section xml:id="module-services-prometheus-exporters-configuration">
|
||||||
<title>Configuration</title>
|
<title>Configuration</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
One of the most common exporters is the
|
One of the most common exporters is the
|
||||||
<link xlink:href="https://github.com/prometheus/node_exporter">node
|
<link xlink:href="https://github.com/prometheus/node_exporter">node
|
||||||
exporter</link>, it provides hardware and OS metrics from the host it's
|
exporter</link>, it provides hardware and OS metrics from the host
|
||||||
running on. The exporter could be configured as follows:
|
it’s running on. The exporter could be configured as follows:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.prometheus.exporters.node = {
|
services.prometheus.exporters.node = {
|
||||||
enable = true;
|
enable = true;
|
||||||
port = 9100;
|
port = 9100;
|
||||||
enabledCollectors = [
|
enabledCollectors = [
|
||||||
"logind"
|
"logind"
|
||||||
"systemd"
|
"systemd"
|
||||||
];
|
];
|
||||||
disabledCollectors = [
|
disabledCollectors = [
|
||||||
"textfile"
|
"textfile"
|
||||||
];
|
];
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
firewallFilter = "-i br0 -p tcp -m tcp --dport 9100";
|
firewallFilter = "-i br0 -p tcp -m tcp --dport 9100";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
It should now serve all metrics from the collectors that are explicitly
|
<para>
|
||||||
enabled and the ones that are
|
It should now serve all metrics from the collectors that are
|
||||||
|
explicitly enabled and the ones that are
|
||||||
<link xlink:href="https://github.com/prometheus/node_exporter#enabled-by-default">enabled
|
<link xlink:href="https://github.com/prometheus/node_exporter#enabled-by-default">enabled
|
||||||
by default</link>, via http under <literal>/metrics</literal>. In this
|
by default</link>, via http under <literal>/metrics</literal>. In
|
||||||
example the firewall should just allow incoming connections to the
|
this example the firewall should just allow incoming connections
|
||||||
exporter's port on the bridge interface <literal>br0</literal> (this would
|
to the exporter’s port on the bridge interface
|
||||||
have to be configured separately of course). For more information about
|
<literal>br0</literal> (this would have to be configured
|
||||||
configuration see <literal>man configuration.nix</literal> or search through
|
separately of course). For more information about configuration
|
||||||
the
|
see <literal>man configuration.nix</literal> or search through the
|
||||||
<link xlink:href="https://nixos.org/nixos/options.html#prometheus.exporters">available
|
<link xlink:href="https://nixos.org/nixos/options.html#prometheus.exporters">available
|
||||||
options</link>.
|
options</link>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Prometheus can now be configured to consume the metrics produced by the exporter:
|
Prometheus can now be configured to consume the metrics produced
|
||||||
|
by the exporter:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.prometheus = {
|
services.prometheus = {
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
scrapeConfigs = [
|
scrapeConfigs = [
|
||||||
{
|
{
|
||||||
job_name = "node";
|
job_name = "node";
|
||||||
static_configs = [{
|
static_configs = [{
|
||||||
targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ];
|
targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -62,27 +63,22 @@
|
||||||
# ...
|
# ...
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-prometheus-exporters-new-exporter">
|
<section xml:id="module-services-prometheus-exporters-new-exporter">
|
||||||
<title>Adding a new exporter</title>
|
<title>Adding a new exporter</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To add a new exporter, it has to be packaged first (see
|
To add a new exporter, it has to be packaged first (see
|
||||||
<literal>nixpkgs/pkgs/servers/monitoring/prometheus/</literal> for
|
<literal>nixpkgs/pkgs/servers/monitoring/prometheus/</literal> for
|
||||||
examples), then a module can be added. The postfix exporter is used in this
|
examples), then a module can be added. The postfix exporter is
|
||||||
example:
|
used in this example:
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Some default options for all exporters are provided by
|
Some default options for all exporters are provided by
|
||||||
<literal>nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix</literal>:
|
<literal>nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix</literal>:
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
<itemizedlist spacing="compact">
|
||||||
<listitem override='none'>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<literal>enable</literal>
|
<literal>enable</literal>
|
||||||
|
@ -127,11 +123,12 @@
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
As there is already a package available, the module can now be added. This
|
As there is already a package available, the module can now be
|
||||||
is accomplished by adding a new file to the
|
added. This is accomplished by adding a new file to the
|
||||||
<literal>nixos/modules/services/monitoring/prometheus/exporters/</literal>
|
<literal>nixos/modules/services/monitoring/prometheus/exporters/</literal>
|
||||||
directory, which will be called postfix.nix and contains all exporter
|
directory, which will be called postfix.nix and contains all
|
||||||
specific options and configuration:
|
exporter specific options and configuration:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
# nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
|
# nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
|
||||||
{ config, lib, pkgs, options }:
|
{ config, lib, pkgs, options }:
|
||||||
|
@ -151,7 +148,7 @@ in
|
||||||
extraOpts = {
|
extraOpts = {
|
||||||
telemetryPath = mkOption {
|
telemetryPath = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "/metrics";
|
default = "/metrics";
|
||||||
description = ''
|
description = ''
|
||||||
Path under which to expose metrics.
|
Path under which to expose metrics.
|
||||||
'';
|
'';
|
||||||
|
@ -188,20 +185,20 @@ in
|
||||||
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
||||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
--web.telemetry-path ${cfg.telemetryPath} \
|
--web.telemetry-path ${cfg.telemetryPath} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This should already be enough for the postfix exporter. Additionally one
|
This should already be enough for the postfix exporter.
|
||||||
could now add assertions and conditional default values. This can be done
|
Additionally one could now add assertions and conditional
|
||||||
in the 'meta-module' that combines all exporter definitions and generates
|
default values. This can be done in the
|
||||||
the submodules:
|
<quote>meta-module</quote> that combines all exporter
|
||||||
|
definitions and generates the submodules:
|
||||||
<literal>nixpkgs/nixos/modules/services/prometheus/exporters.nix</literal>
|
<literal>nixpkgs/nixos/modules/services/prometheus/exporters.nix</literal>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
@ -210,9 +207,10 @@ in
|
||||||
<section xml:id="module-services-prometheus-exporters-update-exporter-module">
|
<section xml:id="module-services-prometheus-exporters-update-exporter-module">
|
||||||
<title>Updating an exporter module</title>
|
<title>Updating an exporter module</title>
|
||||||
<para>
|
<para>
|
||||||
Should an exporter option change at some point, it is possible to add
|
Should an exporter option change at some point, it is possible to
|
||||||
information about the change to the exporter definition similar to
|
add information about the change to the exporter definition
|
||||||
<literal>nixpkgs/nixos/modules/rename.nix</literal>:
|
similar to <literal>nixpkgs/nixos/modules/rename.nix</literal>:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{ config, lib, pkgs, options }:
|
{ config, lib, pkgs, options }:
|
||||||
|
|
||||||
|
@ -232,17 +230,16 @@ in
|
||||||
# ...
|
# ...
|
||||||
};
|
};
|
||||||
imports = [
|
imports = [
|
||||||
# 'services.prometheus.exporters.nginx.telemetryEndpoint' -> 'services.prometheus.exporters.nginx.telemetryPath'
|
# 'services.prometheus.exporters.nginx.telemetryEndpoint' -> 'services.prometheus.exporters.nginx.telemetryPath'
|
||||||
(mkRenamedOptionModule [ "telemetryEndpoint" ] [ "telemetryPath" ])
|
(mkRenamedOptionModule [ "telemetryEndpoint" ] [ "telemetryPath" ])
|
||||||
|
|
||||||
# removed option 'services.prometheus.exporters.nginx.insecure'
|
# removed option 'services.prometheus.exporters.nginx.insecure'
|
||||||
(mkRemovedOptionModule [ "insecure" ] ''
|
(mkRemovedOptionModule [ "insecure" ] ''
|
||||||
This option was replaced by 'prometheus.exporters.nginx.sslVerify' which defaults to true.
|
This option was replaced by 'prometheus.exporters.nginx.sslVerify' which defaults to true.
|
||||||
'')
|
'')
|
||||||
({ options.warnings = options.warnings; })
|
({ options.warnings = options.warnings; })
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -1,23 +1,14 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
# Litestream {#module-services-litestream}
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
[Litestream](https://litestream.io/) is a standalone streaming
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-litestream">
|
|
||||||
<title>Litestream</title>
|
|
||||||
<para>
|
|
||||||
<link xlink:href="https://litestream.io/">Litestream</link> is a standalone streaming
|
|
||||||
replication tool for SQLite.
|
replication tool for SQLite.
|
||||||
</para>
|
|
||||||
|
|
||||||
<section xml:id="module-services-litestream-configuration">
|
## Configuration {#module-services-litestream-configuration}
|
||||||
<title>Configuration</title>
|
|
||||||
|
|
||||||
<para>
|
Litestream service is managed by a dedicated user named `litestream`
|
||||||
Litestream service is managed by a dedicated user named <literal>litestream</literal>
|
|
||||||
which needs permission to the database file. Here's an example config which gives
|
which needs permission to the database file. Here's an example config which gives
|
||||||
required permissions to access <link linkend="opt-services.grafana.settings.database.path">
|
required permissions to access [grafana database](#opt-services.grafana.settings.database.path):
|
||||||
grafana database</link>:
|
```
|
||||||
<programlisting>
|
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
users.users.litestream.extraGroups = [ "grafana" ];
|
users.users.litestream.extraGroups = [ "grafana" ];
|
||||||
|
@ -58,8 +49,4 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
```
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</chapter>
|
|
|
@ -94,5 +94,6 @@ in
|
||||||
};
|
};
|
||||||
users.groups.litestream = {};
|
users.groups.litestream = {};
|
||||||
};
|
};
|
||||||
meta.doc = ./litestream.xml;
|
|
||||||
|
meta.doc = ./default.xml;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-litestream">
|
||||||
|
<title>Litestream</title>
|
||||||
|
<para>
|
||||||
|
<link xlink:href="https://litestream.io/">Litestream</link> is a
|
||||||
|
standalone streaming replication tool for SQLite.
|
||||||
|
</para>
|
||||||
|
<section xml:id="module-services-litestream-configuration">
|
||||||
|
<title>Configuration</title>
|
||||||
|
<para>
|
||||||
|
Litestream service is managed by a dedicated user named
|
||||||
|
<literal>litestream</literal> which needs permission to the
|
||||||
|
database file. Here’s an example config which gives required
|
||||||
|
permissions to access
|
||||||
|
<link linkend="opt-services.grafana.settings.database.path">grafana
|
||||||
|
database</link>:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
users.users.litestream.extraGroups = [ "grafana" ];
|
||||||
|
|
||||||
|
systemd.services.grafana.serviceConfig.ExecStartPost = "+" + pkgs.writeShellScript "grant-grafana-permissions" ''
|
||||||
|
timeout=10
|
||||||
|
|
||||||
|
while [ ! -f /var/lib/grafana/data/grafana.db ];
|
||||||
|
do
|
||||||
|
if [ "$timeout" == 0 ]; then
|
||||||
|
echo "ERROR: Timeout while waiting for /var/lib/grafana/data/grafana.db."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
((timeout--))
|
||||||
|
done
|
||||||
|
|
||||||
|
find /var/lib/grafana -type d -exec chmod -v 775 {} \;
|
||||||
|
find /var/lib/grafana -type f -exec chmod -v 660 {} \;
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.litestream = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
environmentFile = "/run/secrets/litestream";
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
dbs = [
|
||||||
|
{
|
||||||
|
path = "/var/lib/grafana/data/grafana.db";
|
||||||
|
replicas = [{
|
||||||
|
url = "s3://mybkt.litestream.io/grafana";
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
|
@ -311,8 +311,6 @@ in
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
maintainers = with lib.maintainers; [ pennae ];
|
maintainers = with lib.maintainers; [ pennae ];
|
||||||
# Don't edit the docbook xml directly, edit the md and generate it:
|
|
||||||
# `pandoc firefox-syncserver.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > firefox-syncserver.xml`
|
|
||||||
doc = ./firefox-syncserver.xml;
|
doc = ./firefox-syncserver.xml;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-firefox-syncserver">
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-firefox-syncserver">
|
||||||
<title>Firefox Sync server</title>
|
<title>Firefox Sync server</title>
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -671,8 +671,6 @@ in
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
maintainers = with lib.maintainers; [ pennae ];
|
maintainers = with lib.maintainers; [ pennae ];
|
||||||
# Don't edit the docbook xml directly, edit the md and generate it:
|
|
||||||
# `pandoc mosquitto.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > mosquitto.xml`
|
|
||||||
doc = ./mosquitto.xml;
|
doc = ./mosquitto.xml;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-mosquitto">
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-mosquitto">
|
||||||
<title>Mosquitto</title>
|
<title>Mosquitto</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -9,7 +11,7 @@
|
||||||
<para>
|
<para>
|
||||||
A minimal configuration for Mosquitto is
|
A minimal configuration for Mosquitto is
|
||||||
</para>
|
</para>
|
||||||
<programlisting language="bash">
|
<programlisting language="nix">
|
||||||
services.mosquitto = {
|
services.mosquitto = {
|
||||||
enable = true;
|
enable = true;
|
||||||
listeners = [ {
|
listeners = [ {
|
||||||
|
@ -31,7 +33,7 @@ services.mosquitto = {
|
||||||
restricted write access to a user <literal>service</literal> could
|
restricted write access to a user <literal>service</literal> could
|
||||||
look like
|
look like
|
||||||
</para>
|
</para>
|
||||||
<programlisting language="bash">
|
<programlisting language="nix">
|
||||||
services.mosquitto = {
|
services.mosquitto = {
|
||||||
enable = true;
|
enable = true;
|
||||||
listeners = [ {
|
listeners = [ {
|
||||||
|
@ -52,7 +54,7 @@ services.mosquitto = {
|
||||||
TLS authentication is configured by setting TLS-related options of
|
TLS authentication is configured by setting TLS-related options of
|
||||||
the listener:
|
the listener:
|
||||||
</para>
|
</para>
|
||||||
<programlisting language="bash">
|
<programlisting language="nix">
|
||||||
services.mosquitto = {
|
services.mosquitto = {
|
||||||
enable = true;
|
enable = true;
|
||||||
listeners = [ {
|
listeners = [ {
|
||||||
|
|
180
nixos/modules/services/networking/pleroma.md
Normal file
180
nixos/modules/services/networking/pleroma.md
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
# Pleroma {#module-services-pleroma}
|
||||||
|
|
||||||
|
[Pleroma](https://pleroma.social/) is a lightweight activity pub server.
|
||||||
|
|
||||||
|
## Generating the Pleroma config {#module-services-pleroma-generate-config}
|
||||||
|
|
||||||
|
The `pleroma_ctl` CLI utility will prompt you some questions and it will generate an initial config file. This is an example of usage
|
||||||
|
```ShellSession
|
||||||
|
$ mkdir tmp-pleroma
|
||||||
|
$ cd tmp-pleroma
|
||||||
|
$ nix-shell -p pleroma-otp
|
||||||
|
$ pleroma_ctl instance gen --output config.exs --output-psql setup.psql
|
||||||
|
```
|
||||||
|
|
||||||
|
The `config.exs` file can be further customized following the instructions on the [upstream documentation](https://docs-develop.pleroma.social/backend/configuration/cheatsheet/). Many refinements can be applied also after the service is running.
|
||||||
|
|
||||||
|
## Initializing the database {#module-services-pleroma-initialize-db}
|
||||||
|
|
||||||
|
First, the Postgresql service must be enabled in the NixOS configuration
|
||||||
|
```
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.postgresql_13;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
and activated with the usual
|
||||||
|
```ShellSession
|
||||||
|
$ nixos-rebuild switch
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can create and seed the database, using the `setup.psql` file that you generated in the previous section, by running
|
||||||
|
```ShellSession
|
||||||
|
$ sudo -u postgres psql -f setup.psql
|
||||||
|
```
|
||||||
|
|
||||||
|
## Enabling the Pleroma service locally {#module-services-pleroma-enable}
|
||||||
|
|
||||||
|
In this section we will enable the Pleroma service only locally, so its configurations can be improved incrementally.
|
||||||
|
|
||||||
|
This is an example of configuration, where [](#opt-services.pleroma.configs) option contains the content of the file `config.exs`, generated [in the first section](#module-services-pleroma-generate-config), but with the secrets (database password, endpoint secret key, salts, etc.) removed. Removing secrets is important, because otherwise they will be stored publicly in the Nix store.
|
||||||
|
```
|
||||||
|
services.pleroma = {
|
||||||
|
enable = true;
|
||||||
|
secretConfigFile = "/var/lib/pleroma/secrets.exs";
|
||||||
|
configs = [
|
||||||
|
''
|
||||||
|
import Config
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
|
url: [host: "pleroma.example.net", scheme: "https", port: 443],
|
||||||
|
http: [ip: {127, 0, 0, 1}, port: 4000]
|
||||||
|
|
||||||
|
config :pleroma, :instance,
|
||||||
|
name: "Test",
|
||||||
|
email: "admin@example.net",
|
||||||
|
notify_email: "admin@example.net",
|
||||||
|
limit: 5000,
|
||||||
|
registrations_open: true
|
||||||
|
|
||||||
|
config :pleroma, :media_proxy,
|
||||||
|
enabled: false,
|
||||||
|
redirect_on_failure: true
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Repo,
|
||||||
|
adapter: Ecto.Adapters.Postgres,
|
||||||
|
username: "pleroma",
|
||||||
|
database: "pleroma",
|
||||||
|
hostname: "localhost"
|
||||||
|
|
||||||
|
# Configure web push notifications
|
||||||
|
config :web_push_encryption, :vapid_details,
|
||||||
|
subject: "mailto:admin@example.net"
|
||||||
|
|
||||||
|
# ... TO CONTINUE ...
|
||||||
|
''
|
||||||
|
];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Secrets must be moved into a file pointed by [](#opt-services.pleroma.secretConfigFile), in our case `/var/lib/pleroma/secrets.exs`. This file can be created copying the previously generated `config.exs` file and then removing all the settings, except the secrets. This is an example
|
||||||
|
```
|
||||||
|
# Pleroma instance passwords
|
||||||
|
|
||||||
|
import Config
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
|
secret_key_base: "<the secret generated by pleroma_ctl>",
|
||||||
|
signing_salt: "<the secret generated by pleroma_ctl>"
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Repo,
|
||||||
|
password: "<the secret generated by pleroma_ctl>"
|
||||||
|
|
||||||
|
# Configure web push notifications
|
||||||
|
config :web_push_encryption, :vapid_details,
|
||||||
|
public_key: "<the secret generated by pleroma_ctl>",
|
||||||
|
private_key: "<the secret generated by pleroma_ctl>"
|
||||||
|
|
||||||
|
# ... TO CONTINUE ...
|
||||||
|
```
|
||||||
|
Note that the lines of the same configuration group are comma separated (i.e. all the lines end with a comma, except the last one), so when the lines with passwords are added or removed, commas must be adjusted accordingly.
|
||||||
|
|
||||||
|
The service can be enabled with the usual
|
||||||
|
```ShellSession
|
||||||
|
$ nixos-rebuild switch
|
||||||
|
```
|
||||||
|
|
||||||
|
The service is accessible only from the local `127.0.0.1:4000` port. It can be tested using a port forwarding like this
|
||||||
|
```ShellSession
|
||||||
|
$ ssh -L 4000:localhost:4000 myuser@example.net
|
||||||
|
```
|
||||||
|
and then accessing <http://localhost:4000> from a web browser.
|
||||||
|
|
||||||
|
## Creating the admin user {#module-services-pleroma-admin-user}
|
||||||
|
|
||||||
|
After Pleroma service is running, all [Pleroma administration utilities](https://docs-develop.pleroma.social/) can be used. In particular an admin user can be created with
|
||||||
|
```ShellSession
|
||||||
|
$ pleroma_ctl user new <nickname> <email> --admin --moderator --password <password>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuring Nginx {#module-services-pleroma-nginx}
|
||||||
|
|
||||||
|
In this configuration, Pleroma is listening only on the local port 4000. Nginx can be configured as a Reverse Proxy, for forwarding requests from public ports to the Pleroma service. This is an example of configuration, using
|
||||||
|
[Let's Encrypt](https://letsencrypt.org/) for the TLS certificates
|
||||||
|
```
|
||||||
|
security.acme = {
|
||||||
|
email = "root@example.net";
|
||||||
|
acceptTerms = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
addSSL = true;
|
||||||
|
|
||||||
|
recommendedTlsSettings = true;
|
||||||
|
recommendedOptimisation = true;
|
||||||
|
recommendedGzipSettings = true;
|
||||||
|
|
||||||
|
recommendedProxySettings = false;
|
||||||
|
# NOTE: if enabled, the NixOS proxy optimizations will override the Pleroma
|
||||||
|
# specific settings, and they will enter in conflict.
|
||||||
|
|
||||||
|
virtualHosts = {
|
||||||
|
"pleroma.example.net" = {
|
||||||
|
http2 = true;
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://127.0.0.1:4000";
|
||||||
|
|
||||||
|
extraConfig = ''
|
||||||
|
etag on;
|
||||||
|
gzip on;
|
||||||
|
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always;
|
||||||
|
add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always;
|
||||||
|
if ($request_method = OPTIONS) {
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header X-Permitted-Cross-Domain-Policies none;
|
||||||
|
add_header X-Frame-Options DENY;
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header Referrer-Policy same-origin;
|
||||||
|
add_header X-Download-Options noopen;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
|
||||||
|
client_max_body_size 16m;
|
||||||
|
# NOTE: increase if users need to upload very big files
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
|
@ -1,63 +1,91 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-pleroma">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-pleroma">
|
|
||||||
<title>Pleroma</title>
|
<title>Pleroma</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://pleroma.social/">Pleroma</link> is a lightweight activity pub server.</para>
|
<link xlink:href="https://pleroma.social/">Pleroma</link> is a
|
||||||
|
lightweight activity pub server.
|
||||||
|
</para>
|
||||||
<section xml:id="module-services-pleroma-generate-config">
|
<section xml:id="module-services-pleroma-generate-config">
|
||||||
<title>Generating the Pleroma config</title>
|
<title>Generating the Pleroma config</title>
|
||||||
<para>The <literal>pleroma_ctl</literal> CLI utility will prompt you some questions and it will generate an initial config file. This is an example of usage
|
<para>
|
||||||
<programlisting>
|
The <literal>pleroma_ctl</literal> CLI utility will prompt you
|
||||||
<prompt>$ </prompt>mkdir tmp-pleroma
|
some questions and it will generate an initial config file. This
|
||||||
<prompt>$ </prompt>cd tmp-pleroma
|
is an example of usage
|
||||||
<prompt>$ </prompt>nix-shell -p pleroma-otp
|
</para>
|
||||||
<prompt>$ </prompt>pleroma_ctl instance gen --output config.exs --output-psql setup.psql
|
<programlisting>
|
||||||
</programlisting>
|
$ mkdir tmp-pleroma
|
||||||
|
$ cd tmp-pleroma
|
||||||
|
$ nix-shell -p pleroma-otp
|
||||||
|
$ pleroma_ctl instance gen --output config.exs --output-psql setup.psql
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
The <literal>config.exs</literal> file can be further customized
|
||||||
|
following the instructions on the
|
||||||
|
<link xlink:href="https://docs-develop.pleroma.social/backend/configuration/cheatsheet/">upstream
|
||||||
|
documentation</link>. Many refinements can be applied also after
|
||||||
|
the service is running.
|
||||||
</para>
|
</para>
|
||||||
<para>The <literal>config.exs</literal> file can be further customized following the instructions on the <link xlink:href="https://docs-develop.pleroma.social/backend/configuration/cheatsheet/">upstream documentation</link>. Many refinements can be applied also after the service is running.</para>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-pleroma-initialize-db">
|
<section xml:id="module-services-pleroma-initialize-db">
|
||||||
<title>Initializing the database</title>
|
<title>Initializing the database</title>
|
||||||
<para>First, the Postgresql service must be enabled in the NixOS configuration
|
<para>
|
||||||
|
First, the Postgresql service must be enabled in the NixOS
|
||||||
|
configuration
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.postgresql = {
|
services.postgresql = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.postgresql_13;
|
package = pkgs.postgresql_13;
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
<para>
|
||||||
and activated with the usual
|
and activated with the usual
|
||||||
<programlisting>
|
|
||||||
<prompt>$ </prompt>nixos-rebuild switch
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
<para>Then you can create and seed the database, using the <literal>setup.psql</literal> file that you generated in the previous section, by running
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<prompt>$ </prompt>sudo -u postgres psql -f setup.psql
|
$ nixos-rebuild switch
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Then you can create and seed the database, using the
|
||||||
|
<literal>setup.psql</literal> file that you generated in the
|
||||||
|
previous section, by running
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ sudo -u postgres psql -f setup.psql
|
||||||
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-pleroma-enable">
|
<section xml:id="module-services-pleroma-enable">
|
||||||
<title>Enabling the Pleroma service locally</title>
|
<title>Enabling the Pleroma service locally</title>
|
||||||
<para>In this section we will enable the Pleroma service only locally, so its configurations can be improved incrementally.</para>
|
<para>
|
||||||
<para>This is an example of configuration, where <link linkend="opt-services.pleroma.configs">services.pleroma.configs</link> option contains the content of the file <literal>config.exs</literal>, generated <link linkend="module-services-pleroma-generate-config">in the first section</link>, but with the secrets (database password, endpoint secret key, salts, etc.) removed. Removing secrets is important, because otherwise they will be stored publicly in the Nix store.
|
In this section we will enable the Pleroma service only locally,
|
||||||
|
so its configurations can be improved incrementally.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is an example of configuration, where
|
||||||
|
<xref linkend="opt-services.pleroma.configs" /> option contains
|
||||||
|
the content of the file <literal>config.exs</literal>, generated
|
||||||
|
<link linkend="module-services-pleroma-generate-config">in the
|
||||||
|
first section</link>, but with the secrets (database password,
|
||||||
|
endpoint secret key, salts, etc.) removed. Removing secrets is
|
||||||
|
important, because otherwise they will be stored publicly in the
|
||||||
|
Nix store.
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.pleroma = {
|
services.pleroma = {
|
||||||
enable = true;
|
enable = true;
|
||||||
secretConfigFile = "/var/lib/pleroma/secrets.exs";
|
secretConfigFile = "/var/lib/pleroma/secrets.exs";
|
||||||
configs = [
|
configs = [
|
||||||
''
|
''
|
||||||
import Config
|
import Config
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
url: [host: "pleroma.example.net", scheme: "https", port: 443],
|
url: [host: "pleroma.example.net", scheme: "https", port: 443],
|
||||||
http: [ip: {127, 0, 0, 1}, port: 4000]
|
http: [ip: {127, 0, 0, 1}, port: 4000]
|
||||||
|
|
||||||
config :pleroma, :instance,
|
config :pleroma, :instance,
|
||||||
name: "Test",
|
name: "Test",
|
||||||
email: "admin@example.net",
|
email: "admin@example.net",
|
||||||
notify_email: "admin@example.net",
|
notify_email: "admin@example.net",
|
||||||
limit: 5000,
|
limit: 5000,
|
||||||
registrations_open: true
|
registrations_open: true
|
||||||
|
|
||||||
|
@ -67,68 +95,97 @@ services.pleroma = {
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
adapter: Ecto.Adapters.Postgres,
|
adapter: Ecto.Adapters.Postgres,
|
||||||
username: "pleroma",
|
username: "pleroma",
|
||||||
database: "pleroma",
|
database: "pleroma",
|
||||||
hostname: "localhost"
|
hostname: "localhost"
|
||||||
|
|
||||||
# Configure web push notifications
|
# Configure web push notifications
|
||||||
config :web_push_encryption, :vapid_details,
|
config :web_push_encryption, :vapid_details,
|
||||||
subject: "mailto:admin@example.net"
|
subject: "mailto:admin@example.net"
|
||||||
|
|
||||||
# ... TO CONTINUE ...
|
# ... TO CONTINUE ...
|
||||||
''
|
''
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Secrets must be moved into a file pointed by
|
||||||
|
<xref linkend="opt-services.pleroma.secretConfigFile" />, in our
|
||||||
|
case <literal>/var/lib/pleroma/secrets.exs</literal>. This file
|
||||||
|
can be created copying the previously generated
|
||||||
|
<literal>config.exs</literal> file and then removing all the
|
||||||
|
settings, except the secrets. This is an example
|
||||||
</para>
|
</para>
|
||||||
<para>Secrets must be moved into a file pointed by <link linkend="opt-services.pleroma.secretConfigFile">services.pleroma.secretConfigFile</link>, in our case <literal>/var/lib/pleroma/secrets.exs</literal>. This file can be created copying the previously generated <literal>config.exs</literal> file and then removing all the settings, except the secrets. This is an example
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
# Pleroma instance passwords
|
# Pleroma instance passwords
|
||||||
|
|
||||||
import Config
|
import Config
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
secret_key_base: "<the secret generated by pleroma_ctl>",
|
secret_key_base: "<the secret generated by pleroma_ctl>",
|
||||||
signing_salt: "<the secret generated by pleroma_ctl>"
|
signing_salt: "<the secret generated by pleroma_ctl>"
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
password: "<the secret generated by pleroma_ctl>"
|
password: "<the secret generated by pleroma_ctl>"
|
||||||
|
|
||||||
# Configure web push notifications
|
# Configure web push notifications
|
||||||
config :web_push_encryption, :vapid_details,
|
config :web_push_encryption, :vapid_details,
|
||||||
public_key: "<the secret generated by pleroma_ctl>",
|
public_key: "<the secret generated by pleroma_ctl>",
|
||||||
private_key: "<the secret generated by pleroma_ctl>"
|
private_key: "<the secret generated by pleroma_ctl>"
|
||||||
|
|
||||||
# ... TO CONTINUE ...
|
# ... TO CONTINUE ...
|
||||||
</programlisting>
|
</programlisting>
|
||||||
Note that the lines of the same configuration group are comma separated (i.e. all the lines end with a comma, except the last one), so when the lines with passwords are added or removed, commas must be adjusted accordingly.</para>
|
<para>
|
||||||
|
Note that the lines of the same configuration group are comma
|
||||||
<para>The service can be enabled with the usual
|
separated (i.e. all the lines end with a comma, except the last
|
||||||
<programlisting>
|
one), so when the lines with passwords are added or removed,
|
||||||
<prompt>$ </prompt>nixos-rebuild switch
|
commas must be adjusted accordingly.
|
||||||
</programlisting>
|
</para>
|
||||||
|
<para>
|
||||||
|
The service can be enabled with the usual
|
||||||
</para>
|
</para>
|
||||||
<para>The service is accessible only from the local <literal>127.0.0.1:4000</literal> port. It can be tested using a port forwarding like this
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<prompt>$ </prompt>ssh -L 4000:localhost:4000 myuser@example.net
|
$ nixos-rebuild switch
|
||||||
</programlisting>
|
</programlisting>
|
||||||
and then accessing <link xlink:href="http://localhost:4000">http://localhost:4000</link> from a web browser.</para>
|
<para>
|
||||||
|
The service is accessible only from the local
|
||||||
|
<literal>127.0.0.1:4000</literal> port. It can be tested using a
|
||||||
|
port forwarding like this
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ ssh -L 4000:localhost:4000 myuser@example.net
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
and then accessing
|
||||||
|
<link xlink:href="http://localhost:4000">http://localhost:4000</link>
|
||||||
|
from a web browser.
|
||||||
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-pleroma-admin-user">
|
<section xml:id="module-services-pleroma-admin-user">
|
||||||
<title>Creating the admin user</title>
|
<title>Creating the admin user</title>
|
||||||
<para>After Pleroma service is running, all <link xlink:href="https://docs-develop.pleroma.social/">Pleroma administration utilities</link> can be used. In particular an admin user can be created with
|
<para>
|
||||||
<programlisting>
|
After Pleroma service is running, all
|
||||||
<prompt>$ </prompt>pleroma_ctl user new <nickname> <email> --admin --moderator --password <password>
|
<link xlink:href="https://docs-develop.pleroma.social/">Pleroma
|
||||||
</programlisting>
|
administration utilities</link> can be used. In particular an
|
||||||
|
admin user can be created with
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ pleroma_ctl user new <nickname> <email> --admin --moderator --password <password>
|
||||||
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-pleroma-nginx">
|
<section xml:id="module-services-pleroma-nginx">
|
||||||
<title>Configuring Nginx</title>
|
<title>Configuring Nginx</title>
|
||||||
<para>In this configuration, Pleroma is listening only on the local port 4000. Nginx can be configured as a Reverse Proxy, for forwarding requests from public ports to the Pleroma service. This is an example of configuration, using
|
<para>
|
||||||
<link xlink:href="https://letsencrypt.org/">Let's Encrypt</link> for the TLS certificates
|
In this configuration, Pleroma is listening only on the local port
|
||||||
|
4000. Nginx can be configured as a Reverse Proxy, for forwarding
|
||||||
|
requests from public ports to the Pleroma service. This is an
|
||||||
|
example of configuration, using
|
||||||
|
<link xlink:href="https://letsencrypt.org/">Let’s Encrypt</link>
|
||||||
|
for the TLS certificates
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
security.acme = {
|
security.acme = {
|
||||||
email = "root@example.net";
|
email = "root@example.net";
|
||||||
acceptTerms = true;
|
acceptTerms = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -145,13 +202,13 @@ services.nginx = {
|
||||||
# specific settings, and they will enter in conflict.
|
# specific settings, and they will enter in conflict.
|
||||||
|
|
||||||
virtualHosts = {
|
virtualHosts = {
|
||||||
"pleroma.example.net" = {
|
"pleroma.example.net" = {
|
||||||
http2 = true;
|
http2 = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
|
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://127.0.0.1:4000";
|
proxyPass = "http://127.0.0.1:4000";
|
||||||
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
etag on;
|
etag on;
|
||||||
|
@ -164,7 +221,7 @@ services.nginx = {
|
||||||
if ($request_method = OPTIONS) {
|
if ($request_method = OPTIONS) {
|
||||||
return 204;
|
return 204;
|
||||||
}
|
}
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
add_header X-Permitted-Cross-Domain-Policies none;
|
add_header X-Permitted-Cross-Domain-Policies none;
|
||||||
add_header X-Frame-Options DENY;
|
add_header X-Frame-Options DENY;
|
||||||
add_header X-Content-Type-Options nosniff;
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
@ -172,7 +229,7 @@ services.nginx = {
|
||||||
add_header X-Download-Options noopen;
|
add_header X-Download-Options noopen;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection "upgrade";
|
proxy_set_header Connection "upgrade";
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
|
|
||||||
client_max_body_size 16m;
|
client_max_body_size 16m;
|
||||||
|
@ -183,6 +240,5 @@ services.nginx = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
72
nixos/modules/services/networking/prosody.md
Normal file
72
nixos/modules/services/networking/prosody.md
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
# Prosody {#module-services-prosody}
|
||||||
|
|
||||||
|
[Prosody](https://prosody.im/) is an open-source, modern XMPP server.
|
||||||
|
|
||||||
|
## Basic usage {#module-services-prosody-basic-usage}
|
||||||
|
|
||||||
|
A common struggle for most XMPP newcomers is to find the right set
|
||||||
|
of XMPP Extensions (XEPs) to setup. Forget to activate a few of
|
||||||
|
those and your XMPP experience might turn into a nightmare!
|
||||||
|
|
||||||
|
The XMPP community tackles this problem by creating a meta-XEP
|
||||||
|
listing a decent set of XEPs you should implement. This meta-XEP
|
||||||
|
is issued every year, the 2020 edition being
|
||||||
|
[XEP-0423](https://xmpp.org/extensions/xep-0423.html).
|
||||||
|
|
||||||
|
The NixOS Prosody module will implement most of these recommendend XEPs out of
|
||||||
|
the box. That being said, two components still require some
|
||||||
|
manual configuration: the
|
||||||
|
[Multi User Chat (MUC)](https://xmpp.org/extensions/xep-0045.html)
|
||||||
|
and the [HTTP File Upload](https://xmpp.org/extensions/xep-0363.html) ones.
|
||||||
|
You'll need to create a DNS subdomain for each of those. The current convention is to name your
|
||||||
|
MUC endpoint `conference.example.org` and your HTTP upload domain `upload.example.org`.
|
||||||
|
|
||||||
|
A good configuration to start with, including a
|
||||||
|
[Multi User Chat (MUC)](https://xmpp.org/extensions/xep-0045.html)
|
||||||
|
endpoint as well as a [HTTP File Upload](https://xmpp.org/extensions/xep-0363.html)
|
||||||
|
endpoint will look like this:
|
||||||
|
```
|
||||||
|
services.prosody = {
|
||||||
|
enable = true;
|
||||||
|
admins = [ "root@example.org" ];
|
||||||
|
ssl.cert = "/var/lib/acme/example.org/fullchain.pem";
|
||||||
|
ssl.key = "/var/lib/acme/example.org/key.pem";
|
||||||
|
virtualHosts."example.org" = {
|
||||||
|
enabled = true;
|
||||||
|
domain = "example.org";
|
||||||
|
ssl.cert = "/var/lib/acme/example.org/fullchain.pem";
|
||||||
|
ssl.key = "/var/lib/acme/example.org/key.pem";
|
||||||
|
};
|
||||||
|
muc = [ {
|
||||||
|
domain = "conference.example.org";
|
||||||
|
} ];
|
||||||
|
uploadHttp = {
|
||||||
|
domain = "upload.example.org";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Let's Encrypt Configuration {#module-services-prosody-letsencrypt}
|
||||||
|
|
||||||
|
As you can see in the code snippet from the
|
||||||
|
[previous section](#module-services-prosody-basic-usage),
|
||||||
|
you'll need a single TLS certificate covering your main endpoint,
|
||||||
|
the MUC one as well as the HTTP Upload one. We can generate such a
|
||||||
|
certificate by leveraging the ACME
|
||||||
|
[extraDomainNames](#opt-security.acme.certs._name_.extraDomainNames) module option.
|
||||||
|
|
||||||
|
Provided the setup detailed in the previous section, you'll need the following acme configuration to generate
|
||||||
|
a TLS certificate for the three endponits:
|
||||||
|
```
|
||||||
|
security.acme = {
|
||||||
|
email = "root@example.org";
|
||||||
|
acceptTerms = true;
|
||||||
|
certs = {
|
||||||
|
"example.org" = {
|
||||||
|
webroot = "/var/www/example.org";
|
||||||
|
email = "root@example.org";
|
||||||
|
extraDomainNames = [ "conference.example.org" "upload.example.org" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
|
@ -904,5 +904,6 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.doc = ./prosody.xml;
|
meta.doc = ./prosody.xml;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-prosody">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-prosody">
|
|
||||||
<title>Prosody</title>
|
<title>Prosody</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://prosody.im/">Prosody</link> is an open-source, modern XMPP server.
|
<link xlink:href="https://prosody.im/">Prosody</link> is an
|
||||||
|
open-source, modern XMPP server.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-prosody-basic-usage">
|
<section xml:id="module-services-prosody-basic-usage">
|
||||||
<title>Basic usage</title>
|
<title>Basic usage</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A common struggle for most XMPP newcomers is to find the right set
|
A common struggle for most XMPP newcomers is to find the right set
|
||||||
of XMPP Extensions (XEPs) to setup. Forget to activate a few of
|
of XMPP Extensions (XEPs) to setup. Forget to activate a few of
|
||||||
those and your XMPP experience might turn into a nightmare!
|
those and your XMPP experience might turn into a nightmare!
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The XMPP community tackles this problem by creating a meta-XEP
|
The XMPP community tackles this problem by creating a meta-XEP
|
||||||
listing a decent set of XEPs you should implement. This meta-XEP
|
listing a decent set of XEPs you should implement. This meta-XEP
|
||||||
|
@ -23,65 +20,73 @@
|
||||||
<link xlink:href="https://xmpp.org/extensions/xep-0423.html">XEP-0423</link>.
|
<link xlink:href="https://xmpp.org/extensions/xep-0423.html">XEP-0423</link>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The NixOS Prosody module will implement most of these recommendend XEPs out of
|
The NixOS Prosody module will implement most of these recommendend
|
||||||
the box. That being said, two components still require some
|
XEPs out of the box. That being said, two components still require
|
||||||
manual configuration: the
|
some manual configuration: the
|
||||||
<link xlink:href="https://xmpp.org/extensions/xep-0045.html">Multi User Chat (MUC)</link>
|
<link xlink:href="https://xmpp.org/extensions/xep-0045.html">Multi
|
||||||
and the <link xlink:href="https://xmpp.org/extensions/xep-0363.html">HTTP File Upload</link> ones.
|
User Chat (MUC)</link> and the
|
||||||
You'll need to create a DNS subdomain for each of those. The current convention is to name your
|
<link xlink:href="https://xmpp.org/extensions/xep-0363.html">HTTP
|
||||||
MUC endpoint <literal>conference.example.org</literal> and your HTTP upload domain <literal>upload.example.org</literal>.
|
File Upload</link> ones. You’ll need to create a DNS subdomain for
|
||||||
|
each of those. The current convention is to name your MUC endpoint
|
||||||
|
<literal>conference.example.org</literal> and your HTTP upload
|
||||||
|
domain <literal>upload.example.org</literal>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
A good configuration to start with, including a
|
A good configuration to start with, including a
|
||||||
<link xlink:href="https://xmpp.org/extensions/xep-0045.html">Multi User Chat (MUC)</link>
|
<link xlink:href="https://xmpp.org/extensions/xep-0045.html">Multi
|
||||||
endpoint as well as a <link xlink:href="https://xmpp.org/extensions/xep-0363.html">HTTP File Upload</link>
|
User Chat (MUC)</link> endpoint as well as a
|
||||||
endpoint will look like this:
|
<link xlink:href="https://xmpp.org/extensions/xep-0363.html">HTTP
|
||||||
|
File Upload</link> endpoint will look like this:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.prosody = {
|
services.prosody = {
|
||||||
<link linkend="opt-services.prosody.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.prosody.admins">admins</link> = [ "root@example.org" ];
|
admins = [ "root@example.org" ];
|
||||||
<link linkend="opt-services.prosody.ssl.cert">ssl.cert</link> = "/var/lib/acme/example.org/fullchain.pem";
|
ssl.cert = "/var/lib/acme/example.org/fullchain.pem";
|
||||||
<link linkend="opt-services.prosody.ssl.key">ssl.key</link> = "/var/lib/acme/example.org/key.pem";
|
ssl.key = "/var/lib/acme/example.org/key.pem";
|
||||||
<link linkend="opt-services.prosody.virtualHosts">virtualHosts</link>."example.org" = {
|
virtualHosts."example.org" = {
|
||||||
<link linkend="opt-services.prosody.virtualHosts._name_.enabled">enabled</link> = true;
|
enabled = true;
|
||||||
<link linkend="opt-services.prosody.virtualHosts._name_.domain">domain</link> = "example.org";
|
domain = "example.org";
|
||||||
<link linkend="opt-services.prosody.virtualHosts._name_.ssl.cert">ssl.cert</link> = "/var/lib/acme/example.org/fullchain.pem";
|
ssl.cert = "/var/lib/acme/example.org/fullchain.pem";
|
||||||
<link linkend="opt-services.prosody.virtualHosts._name_.ssl.key">ssl.key</link> = "/var/lib/acme/example.org/key.pem";
|
ssl.key = "/var/lib/acme/example.org/key.pem";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.prosody.muc">muc</link> = [ {
|
muc = [ {
|
||||||
<link linkend="opt-services.prosody.muc">domain</link> = "conference.example.org";
|
domain = "conference.example.org";
|
||||||
} ];
|
} ];
|
||||||
<link linkend="opt-services.prosody.uploadHttp">uploadHttp</link> = {
|
uploadHttp = {
|
||||||
<link linkend="opt-services.prosody.uploadHttp.domain">domain</link> = "upload.example.org";
|
domain = "upload.example.org";
|
||||||
};
|
};
|
||||||
};</programlisting>
|
};
|
||||||
</para>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-prosody-letsencrypt">
|
<section xml:id="module-services-prosody-letsencrypt">
|
||||||
<title>Let's Encrypt Configuration</title>
|
<title>Let’s Encrypt Configuration</title>
|
||||||
<para>
|
<para>
|
||||||
As you can see in the code snippet from the
|
As you can see in the code snippet from the
|
||||||
<link linkend="module-services-prosody-basic-usage">previous section</link>,
|
<link linkend="module-services-prosody-basic-usage">previous
|
||||||
you'll need a single TLS certificate covering your main endpoint,
|
section</link>, you’ll need a single TLS certificate covering your
|
||||||
the MUC one as well as the HTTP Upload one. We can generate such a
|
main endpoint, the MUC one as well as the HTTP Upload one. We can
|
||||||
certificate by leveraging the ACME
|
generate such a certificate by leveraging the ACME
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomainNames">extraDomainNames</link> module option.
|
<link linkend="opt-security.acme.certs._name_.extraDomainNames">extraDomainNames</link>
|
||||||
|
module option.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Provided the setup detailed in the previous section, you'll need the following acme configuration to generate
|
Provided the setup detailed in the previous section, you’ll need
|
||||||
a TLS certificate for the three endponits:
|
the following acme configuration to generate a TLS certificate for
|
||||||
|
the three endponits:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
security.acme = {
|
security.acme = {
|
||||||
<link linkend="opt-security.acme.defaults.email">email</link> = "root@example.org";
|
email = "root@example.org";
|
||||||
<link linkend="opt-security.acme.acceptTerms">acceptTerms</link> = true;
|
acceptTerms = true;
|
||||||
<link linkend="opt-security.acme.certs">certs</link> = {
|
certs = {
|
||||||
"example.org" = {
|
"example.org" = {
|
||||||
<link linkend="opt-security.acme.certs._name_.webroot">webroot</link> = "/var/www/example.org";
|
webroot = "/var/www/example.org";
|
||||||
<link linkend="opt-security.acme.certs._name_.email">email</link> = "root@example.org";
|
email = "root@example.org";
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomainNames">extraDomainNames</link> = [ "conference.example.org" "upload.example.org" ];
|
extraDomainNames = [ "conference.example.org" "upload.example.org" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};</programlisting>
|
};
|
||||||
</para>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
141
nixos/modules/services/networking/yggdrasil.md
Normal file
141
nixos/modules/services/networking/yggdrasil.md
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
# Yggdrasil {#module-services-networking-yggdrasil}
|
||||||
|
|
||||||
|
*Source:* {file}`modules/services/networking/yggdrasil/default.nix`
|
||||||
|
|
||||||
|
*Upstream documentation:* <https://yggdrasil-network.github.io/>
|
||||||
|
|
||||||
|
Yggdrasil is an early-stage implementation of a fully end-to-end encrypted,
|
||||||
|
self-arranging IPv6 network.
|
||||||
|
|
||||||
|
## Configuration {#module-services-networking-yggdrasil-configuration}
|
||||||
|
|
||||||
|
### Simple ephemeral node {#module-services-networking-yggdrasil-configuration-simple}
|
||||||
|
|
||||||
|
An annotated example of a simple configuration:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.yggdrasil = {
|
||||||
|
enable = true;
|
||||||
|
persistentKeys = false;
|
||||||
|
# The NixOS module will generate new keys and a new IPv6 address each time
|
||||||
|
# it is started if persistentKeys is not enabled.
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
Peers = [
|
||||||
|
# Yggdrasil will automatically connect and "peer" with other nodes it
|
||||||
|
# discovers via link-local multicast announcements. Unless this is the
|
||||||
|
# case (it probably isn't) a node needs peers within the existing
|
||||||
|
# network that it can tunnel to.
|
||||||
|
"tcp://1.2.3.4:1024"
|
||||||
|
"tcp://1.2.3.5:1024"
|
||||||
|
# Public peers can be found at
|
||||||
|
# https://github.com/yggdrasil-network/public-peers
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Persistent node with prefix {#module-services-networking-yggdrasil-configuration-prefix}
|
||||||
|
|
||||||
|
A node with a fixed address that announces a prefix:
|
||||||
|
```
|
||||||
|
let
|
||||||
|
address = "210:5217:69c0:9afc:1b95:b9f:8718:c3d2";
|
||||||
|
prefix = "310:5217:69c0:9afc";
|
||||||
|
# taken from the output of "yggdrasilctl getself".
|
||||||
|
in {
|
||||||
|
|
||||||
|
services.yggdrasil = {
|
||||||
|
enable = true;
|
||||||
|
persistentKeys = true; # Maintain a fixed public key and IPv6 address.
|
||||||
|
settings = {
|
||||||
|
Peers = [ "tcp://1.2.3.4:1024" "tcp://1.2.3.5:1024" ];
|
||||||
|
NodeInfo = {
|
||||||
|
# This information is visible to the network.
|
||||||
|
name = config.networking.hostName;
|
||||||
|
location = "The North Pole";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
|
||||||
|
# Forward traffic under the prefix.
|
||||||
|
|
||||||
|
networking.interfaces.${eth0}.ipv6.addresses = [{
|
||||||
|
# Set a 300::/8 address on the local physical device.
|
||||||
|
address = prefix + "::1";
|
||||||
|
prefixLength = 64;
|
||||||
|
}];
|
||||||
|
|
||||||
|
services.radvd = {
|
||||||
|
# Announce the 300::/8 prefix to eth0.
|
||||||
|
enable = true;
|
||||||
|
config = ''
|
||||||
|
interface eth0
|
||||||
|
{
|
||||||
|
AdvSendAdvert on;
|
||||||
|
prefix ${prefix}::/64 {
|
||||||
|
AdvOnLink on;
|
||||||
|
AdvAutonomous on;
|
||||||
|
};
|
||||||
|
route 200::/8 {};
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Yggdrasil attached Container {#module-services-networking-yggdrasil-configuration-container}
|
||||||
|
|
||||||
|
A NixOS container attached to the Yggdrasil network via a node running on the
|
||||||
|
host:
|
||||||
|
```
|
||||||
|
let
|
||||||
|
yggPrefix64 = "310:5217:69c0:9afc";
|
||||||
|
# Again, taken from the output of "yggdrasilctl getself".
|
||||||
|
in
|
||||||
|
{
|
||||||
|
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
|
||||||
|
# Enable IPv6 forwarding.
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
bridges.br0.interfaces = [ ];
|
||||||
|
# A bridge only to containers…
|
||||||
|
|
||||||
|
interfaces.br0 = {
|
||||||
|
# … configured with a prefix address.
|
||||||
|
ipv6.addresses = [{
|
||||||
|
address = "${yggPrefix64}::1";
|
||||||
|
prefixLength = 64;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
containers.foo = {
|
||||||
|
autoStart = true;
|
||||||
|
privateNetwork = true;
|
||||||
|
hostBridge = "br0";
|
||||||
|
# Attach the container to the bridge only.
|
||||||
|
config = { config, pkgs, ... }: {
|
||||||
|
networking.interfaces.eth0.ipv6 = {
|
||||||
|
addresses = [{
|
||||||
|
# Configure a prefix address.
|
||||||
|
address = "${yggPrefix64}::2";
|
||||||
|
prefixLength = 64;
|
||||||
|
}];
|
||||||
|
routes = [{
|
||||||
|
# Configure the prefix route.
|
||||||
|
address = "200::";
|
||||||
|
prefixLength = 7;
|
||||||
|
via = "${yggPrefix64}::1";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.httpd.enable = true;
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0"?>
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0" xml:id="module-services-networking-yggdrasil">
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-networking-yggdrasil">
|
||||||
<title>Yggdrasil</title>
|
<title>Yggdrasil</title>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Source:</emphasis>
|
<emphasis>Source:</emphasis>
|
||||||
|
@ -7,11 +8,11 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Upstream documentation:</emphasis>
|
<emphasis>Upstream documentation:</emphasis>
|
||||||
<link xlink:href="https://yggdrasil-network.github.io/"/>
|
<link xlink:href="https://yggdrasil-network.github.io/">https://yggdrasil-network.github.io/</link>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Yggdrasil is an early-stage implementation of a fully end-to-end encrypted,
|
Yggdrasil is an early-stage implementation of a fully end-to-end
|
||||||
self-arranging IPv6 network.
|
encrypted, self-arranging IPv6 network.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-networking-yggdrasil-configuration">
|
<section xml:id="module-services-networking-yggdrasil-configuration">
|
||||||
<title>Configuration</title>
|
<title>Configuration</title>
|
||||||
|
@ -19,6 +20,7 @@ self-arranging IPv6 network.
|
||||||
<title>Simple ephemeral node</title>
|
<title>Simple ephemeral node</title>
|
||||||
<para>
|
<para>
|
||||||
An annotated example of a simple configuration:
|
An annotated example of a simple configuration:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
{
|
{
|
||||||
services.yggdrasil = {
|
services.yggdrasil = {
|
||||||
|
@ -29,12 +31,12 @@ An annotated example of a simple configuration:
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
Peers = [
|
Peers = [
|
||||||
# Yggdrasil will automatically connect and "peer" with other nodes it
|
# Yggdrasil will automatically connect and "peer" with other nodes it
|
||||||
# discovers via link-local multicast announcements. Unless this is the
|
# discovers via link-local multicast announcements. Unless this is the
|
||||||
# case (it probably isn't) a node needs peers within the existing
|
# case (it probably isn't) a node needs peers within the existing
|
||||||
# network that it can tunnel to.
|
# network that it can tunnel to.
|
||||||
"tcp://1.2.3.4:1024"
|
"tcp://1.2.3.4:1024"
|
||||||
"tcp://1.2.3.5:1024"
|
"tcp://1.2.3.5:1024"
|
||||||
# Public peers can be found at
|
# Public peers can be found at
|
||||||
# https://github.com/yggdrasil-network/public-peers
|
# https://github.com/yggdrasil-network/public-peers
|
||||||
];
|
];
|
||||||
|
@ -42,38 +44,38 @@ An annotated example of a simple configuration:
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-networking-yggdrasil-configuration-prefix">
|
<section xml:id="module-services-networking-yggdrasil-configuration-prefix">
|
||||||
<title>Persistent node with prefix</title>
|
<title>Persistent node with prefix</title>
|
||||||
<para>
|
<para>
|
||||||
A node with a fixed address that announces a prefix:
|
A node with a fixed address that announces a prefix:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
let
|
let
|
||||||
address = "210:5217:69c0:9afc:1b95:b9f:8718:c3d2";
|
address = "210:5217:69c0:9afc:1b95:b9f:8718:c3d2";
|
||||||
prefix = "310:5217:69c0:9afc";
|
prefix = "310:5217:69c0:9afc";
|
||||||
# taken from the output of "yggdrasilctl getself".
|
# taken from the output of "yggdrasilctl getself".
|
||||||
in {
|
in {
|
||||||
|
|
||||||
services.yggdrasil = {
|
services.yggdrasil = {
|
||||||
enable = true;
|
enable = true;
|
||||||
persistentKeys = true; # Maintain a fixed public key and IPv6 address.
|
persistentKeys = true; # Maintain a fixed public key and IPv6 address.
|
||||||
settings = {
|
settings = {
|
||||||
Peers = [ "tcp://1.2.3.4:1024" "tcp://1.2.3.5:1024" ];
|
Peers = [ "tcp://1.2.3.4:1024" "tcp://1.2.3.5:1024" ];
|
||||||
NodeInfo = {
|
NodeInfo = {
|
||||||
# This information is visible to the network.
|
# This information is visible to the network.
|
||||||
name = config.networking.hostName;
|
name = config.networking.hostName;
|
||||||
location = "The North Pole";
|
location = "The North Pole";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
|
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
|
||||||
# Forward traffic under the prefix.
|
# Forward traffic under the prefix.
|
||||||
|
|
||||||
networking.interfaces.${eth0}.ipv6.addresses = [{
|
networking.interfaces.${eth0}.ipv6.addresses = [{
|
||||||
# Set a 300::/8 address on the local physical device.
|
# Set a 300::/8 address on the local physical device.
|
||||||
address = prefix + "::1";
|
address = prefix + "::1";
|
||||||
prefixLength = 64;
|
prefixLength = 64;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
@ -94,30 +96,30 @@ in {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-networking-yggdrasil-configuration-container">
|
<section xml:id="module-services-networking-yggdrasil-configuration-container">
|
||||||
<title>Yggdrasil attached Container</title>
|
<title>Yggdrasil attached Container</title>
|
||||||
<para>
|
<para>
|
||||||
A NixOS container attached to the Yggdrasil network via a node running on the
|
A NixOS container attached to the Yggdrasil network via a node
|
||||||
host:
|
running on the host:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
let
|
let
|
||||||
yggPrefix64 = "310:5217:69c0:9afc";
|
yggPrefix64 = "310:5217:69c0:9afc";
|
||||||
# Again, taken from the output of "yggdrasilctl getself".
|
# Again, taken from the output of "yggdrasilctl getself".
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
|
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
|
||||||
# Enable IPv6 forwarding.
|
# Enable IPv6 forwarding.
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
bridges.br0.interfaces = [ ];
|
bridges.br0.interfaces = [ ];
|
||||||
# A bridge only to containers…
|
# A bridge only to containers…
|
||||||
|
|
||||||
interfaces.br0 = {
|
interfaces.br0 = {
|
||||||
# … configured with a prefix address.
|
# … configured with a prefix address.
|
||||||
ipv6.addresses = [{
|
ipv6.addresses = [{
|
||||||
address = "${yggPrefix64}::1";
|
address = "${yggPrefix64}::1";
|
||||||
prefixLength = 64;
|
prefixLength = 64;
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
@ -126,20 +128,20 @@ in
|
||||||
containers.foo = {
|
containers.foo = {
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
privateNetwork = true;
|
privateNetwork = true;
|
||||||
hostBridge = "br0";
|
hostBridge = "br0";
|
||||||
# Attach the container to the bridge only.
|
# Attach the container to the bridge only.
|
||||||
config = { config, pkgs, ... }: {
|
config = { config, pkgs, ... }: {
|
||||||
networking.interfaces.eth0.ipv6 = {
|
networking.interfaces.eth0.ipv6 = {
|
||||||
addresses = [{
|
addresses = [{
|
||||||
# Configure a prefix address.
|
# Configure a prefix address.
|
||||||
address = "${yggPrefix64}::2";
|
address = "${yggPrefix64}::2";
|
||||||
prefixLength = 64;
|
prefixLength = 64;
|
||||||
}];
|
}];
|
||||||
routes = [{
|
routes = [{
|
||||||
# Configure the prefix route.
|
# Configure the prefix route.
|
||||||
address = "200::";
|
address = "200::";
|
||||||
prefixLength = 7;
|
prefixLength = 7;
|
||||||
via = "${yggPrefix64}::1";
|
via = "${yggPrefix64}::1";
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -150,7 +152,6 @@ in
|
||||||
|
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Meilisearch is a lightweight, fast and powerful search engine. Think elastic search with a much smaller footprint.
|
Meilisearch is a lightweight, fast and powerful search engine. Think elastic search with a much smaller footprint.
|
||||||
|
|
||||||
## Quickstart
|
## Quickstart {#module-services-meilisearch-quickstart}
|
||||||
|
|
||||||
the minimum to start meilisearch is
|
the minimum to start meilisearch is
|
||||||
|
|
||||||
|
@ -14,19 +14,19 @@ this will start the http server included with meilisearch on port 7700.
|
||||||
|
|
||||||
test with `curl -X GET 'http://localhost:7700/health'`
|
test with `curl -X GET 'http://localhost:7700/health'`
|
||||||
|
|
||||||
## Usage
|
## Usage {#module-services-meilisearch-usage}
|
||||||
|
|
||||||
you first need to add documents to an index before you can search for documents.
|
you first need to add documents to an index before you can search for documents.
|
||||||
|
|
||||||
### Add a documents to the `movies` index
|
### Add a documents to the `movies` index {#module-services-meilisearch-quickstart-add}
|
||||||
|
|
||||||
`curl -X POST 'http://127.0.0.1:7700/indexes/movies/documents' --data '[{"id": "123", "title": "Superman"}, {"id": 234, "title": "Batman"}]'`
|
`curl -X POST 'http://127.0.0.1:7700/indexes/movies/documents' --data '[{"id": "123", "title": "Superman"}, {"id": 234, "title": "Batman"}]'`
|
||||||
|
|
||||||
### Search documents in the `movies` index
|
### Search documents in the `movies` index {#module-services-meilisearch-quickstart-search}
|
||||||
|
|
||||||
`curl 'http://127.0.0.1:7700/indexes/movies/search' --data '{ "q": "botman" }'` (note the typo is intentional and there to demonstrate the typo tolerant capabilities)
|
`curl 'http://127.0.0.1:7700/indexes/movies/search' --data '{ "q": "botman" }'` (note the typo is intentional and there to demonstrate the typo tolerant capabilities)
|
||||||
|
|
||||||
## Defaults
|
## Defaults {#module-services-meilisearch-defaults}
|
||||||
|
|
||||||
- The default nixos package doesn't come with the [dashboard](https://docs.meilisearch.com/learn/getting_started/quick_start.html#search), since the dashboard features makes some assets downloads at compile time.
|
- The default nixos package doesn't come with the [dashboard](https://docs.meilisearch.com/learn/getting_started/quick_start.html#search), since the dashboard features makes some assets downloads at compile time.
|
||||||
|
|
||||||
|
@ -34,6 +34,6 @@ you first need to add documents to an index before you can search for documents.
|
||||||
|
|
||||||
- Default deployment is development mode. It doesn't require a secret master key. All routes are not protected and accessible.
|
- Default deployment is development mode. It doesn't require a secret master key. All routes are not protected and accessible.
|
||||||
|
|
||||||
## Missing
|
## Missing {#module-services-meilisearch-missing}
|
||||||
|
|
||||||
- the snapshot feature is not yet configurable from the module, it's just a matter of adding the relevant environment variables.
|
- the snapshot feature is not yet configurable from the module, it's just a matter of adding the relevant environment variables.
|
||||||
|
|
|
@ -9,8 +9,6 @@ in
|
||||||
{
|
{
|
||||||
|
|
||||||
meta.maintainers = with maintainers; [ Br1ght0ne happysalada ];
|
meta.maintainers = with maintainers; [ Br1ght0ne happysalada ];
|
||||||
# Don't edit the docbook xml directly, edit the md and generate it:
|
|
||||||
# `pandoc meilisearch.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > meilisearch.xml`
|
|
||||||
meta.doc = ./meilisearch.xml;
|
meta.doc = ./meilisearch.xml;
|
||||||
|
|
||||||
###### interface
|
###### interface
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-meilisearch">
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-meilisearch">
|
||||||
<title>Meilisearch</title>
|
<title>Meilisearch</title>
|
||||||
<para>
|
<para>
|
||||||
Meilisearch is a lightweight, fast and powerful search engine. Think
|
Meilisearch is a lightweight, fast and powerful search engine. Think
|
||||||
elastic search with a much smaller footprint.
|
elastic search with a much smaller footprint.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="quickstart">
|
<section xml:id="module-services-meilisearch-quickstart">
|
||||||
<title>Quickstart</title>
|
<title>Quickstart</title>
|
||||||
<para>
|
<para>
|
||||||
the minimum to start meilisearch is
|
the minimum to start meilisearch is
|
||||||
</para>
|
</para>
|
||||||
<programlisting language="bash">
|
<programlisting language="nix">
|
||||||
services.meilisearch.enable = true;
|
services.meilisearch.enable = true;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
|
@ -21,20 +23,20 @@ services.meilisearch.enable = true;
|
||||||
<literal>curl -X GET 'http://localhost:7700/health'</literal>
|
<literal>curl -X GET 'http://localhost:7700/health'</literal>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="usage">
|
<section xml:id="module-services-meilisearch-usage">
|
||||||
<title>Usage</title>
|
<title>Usage</title>
|
||||||
<para>
|
<para>
|
||||||
you first need to add documents to an index before you can search
|
you first need to add documents to an index before you can search
|
||||||
for documents.
|
for documents.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="add-a-documents-to-the-movies-index">
|
<section xml:id="module-services-meilisearch-quickstart-add">
|
||||||
<title>Add a documents to the <literal>movies</literal>
|
<title>Add a documents to the <literal>movies</literal>
|
||||||
index</title>
|
index</title>
|
||||||
<para>
|
<para>
|
||||||
<literal>curl -X POST 'http://127.0.0.1:7700/indexes/movies/documents' --data '[{"id": "123", "title": "Superman"}, {"id": 234, "title": "Batman"}]'</literal>
|
<literal>curl -X POST 'http://127.0.0.1:7700/indexes/movies/documents' --data '[{"id": "123", "title": "Superman"}, {"id": 234, "title": "Batman"}]'</literal>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="search-documents-in-the-movies-index">
|
<section xml:id="module-services-meilisearch-quickstart-search">
|
||||||
<title>Search documents in the <literal>movies</literal>
|
<title>Search documents in the <literal>movies</literal>
|
||||||
index</title>
|
index</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -44,7 +46,7 @@ services.meilisearch.enable = true;
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="defaults">
|
<section xml:id="module-services-meilisearch-defaults">
|
||||||
<title>Defaults</title>
|
<title>Defaults</title>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -70,7 +72,7 @@ services.meilisearch.enable = true;
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="missing">
|
<section xml:id="module-services-meilisearch-missing">
|
||||||
<title>Missing</title>
|
<title>Missing</title>
|
||||||
<itemizedlist spacing="compact">
|
<itemizedlist spacing="compact">
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -4,7 +4,7 @@ with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.flexget;
|
cfg = config.services.flexget;
|
||||||
pkg = pkgs.flexget;
|
pkg = cfg.package;
|
||||||
ymlFile = pkgs.writeText "flexget.yml" ''
|
ymlFile = pkgs.writeText "flexget.yml" ''
|
||||||
${cfg.config}
|
${cfg.config}
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ in {
|
||||||
services.flexget = {
|
services.flexget = {
|
||||||
enable = mkEnableOption (lib.mdDoc "Run FlexGet Daemon");
|
enable = mkEnableOption (lib.mdDoc "Run FlexGet Daemon");
|
||||||
|
|
||||||
|
package = mkPackageOptionMD pkgs "flexget" {};
|
||||||
|
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
default = "deluge";
|
default = "deluge";
|
||||||
example = "some_user";
|
example = "some_user";
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-akkoma">
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-akkoma">
|
||||||
<title>Akkoma</title>
|
<title>Akkoma</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -371,7 +373,7 @@ services.systemd.akkoma.confinement.enable = true;
|
||||||
and
|
and
|
||||||
<option>services.systemd.akkoma.serviceConfig.BindReadOnlyPaths</option>
|
<option>services.systemd.akkoma.serviceConfig.BindReadOnlyPaths</option>
|
||||||
permit access to outside paths through bind mounts. Refer to
|
permit access to outside paths through bind mounts. Refer to
|
||||||
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#BindPaths="><link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html"><citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry></link></link>
|
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#BindPaths="><citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry></link>
|
||||||
for details.
|
for details.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
286
nixos/modules/services/web-apps/discourse.md
Normal file
286
nixos/modules/services/web-apps/discourse.md
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
# Discourse {#module-services-discourse}
|
||||||
|
|
||||||
|
[Discourse](https://www.discourse.org/) is a
|
||||||
|
modern and open source discussion platform.
|
||||||
|
|
||||||
|
## Basic usage {#module-services-discourse-basic-usage}
|
||||||
|
|
||||||
|
A minimal configuration using Let's Encrypt for TLS certificates looks like this:
|
||||||
|
```
|
||||||
|
services.discourse = {
|
||||||
|
enable = true;
|
||||||
|
hostname = "discourse.example.com";
|
||||||
|
admin = {
|
||||||
|
email = "admin@example.com";
|
||||||
|
username = "admin";
|
||||||
|
fullName = "Administrator";
|
||||||
|
passwordFile = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
security.acme.email = "me@example.com";
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
Provided a proper DNS setup, you'll be able to connect to the
|
||||||
|
instance at `discourse.example.com` and log in
|
||||||
|
using the credentials provided in
|
||||||
|
`services.discourse.admin`.
|
||||||
|
|
||||||
|
## Using a regular TLS certificate {#module-services-discourse-tls}
|
||||||
|
|
||||||
|
To set up TLS using a regular certificate and key on file, use
|
||||||
|
the [](#opt-services.discourse.sslCertificate)
|
||||||
|
and [](#opt-services.discourse.sslCertificateKey)
|
||||||
|
options:
|
||||||
|
|
||||||
|
```
|
||||||
|
services.discourse = {
|
||||||
|
enable = true;
|
||||||
|
hostname = "discourse.example.com";
|
||||||
|
sslCertificate = "/path/to/ssl_certificate";
|
||||||
|
sslCertificateKey = "/path/to/ssl_certificate_key";
|
||||||
|
admin = {
|
||||||
|
email = "admin@example.com";
|
||||||
|
username = "admin";
|
||||||
|
fullName = "Administrator";
|
||||||
|
passwordFile = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database access {#module-services-discourse-database}
|
||||||
|
|
||||||
|
Discourse uses PostgreSQL to store most of its
|
||||||
|
data. A database will automatically be enabled and a database
|
||||||
|
and role created unless [](#opt-services.discourse.database.host) is changed from
|
||||||
|
its default of `null` or [](#opt-services.discourse.database.createLocally) is set
|
||||||
|
to `false`.
|
||||||
|
|
||||||
|
External database access can also be configured by setting
|
||||||
|
[](#opt-services.discourse.database.host),
|
||||||
|
[](#opt-services.discourse.database.username) and
|
||||||
|
[](#opt-services.discourse.database.passwordFile) as
|
||||||
|
appropriate. Note that you need to manually create a database
|
||||||
|
called `discourse` (or the name you chose in
|
||||||
|
[](#opt-services.discourse.database.name)) and
|
||||||
|
allow the configured database user full access to it.
|
||||||
|
|
||||||
|
## Email {#module-services-discourse-mail}
|
||||||
|
|
||||||
|
In addition to the basic setup, you'll want to configure an SMTP
|
||||||
|
server Discourse can use to send user
|
||||||
|
registration and password reset emails, among others. You can
|
||||||
|
also optionally let Discourse receive
|
||||||
|
email, which enables people to reply to threads and conversations
|
||||||
|
via email.
|
||||||
|
|
||||||
|
A basic setup which assumes you want to use your configured
|
||||||
|
[hostname](#opt-services.discourse.hostname) as
|
||||||
|
email domain can be done like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
services.discourse = {
|
||||||
|
enable = true;
|
||||||
|
hostname = "discourse.example.com";
|
||||||
|
sslCertificate = "/path/to/ssl_certificate";
|
||||||
|
sslCertificateKey = "/path/to/ssl_certificate_key";
|
||||||
|
admin = {
|
||||||
|
email = "admin@example.com";
|
||||||
|
username = "admin";
|
||||||
|
fullName = "Administrator";
|
||||||
|
passwordFile = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
mail.outgoing = {
|
||||||
|
serverAddress = "smtp.emailprovider.com";
|
||||||
|
port = 587;
|
||||||
|
username = "user@emailprovider.com";
|
||||||
|
passwordFile = "/path/to/smtp_password_file";
|
||||||
|
};
|
||||||
|
mail.incoming.enable = true;
|
||||||
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
This assumes you have set up an MX record for the address you've
|
||||||
|
set in [hostname](#opt-services.discourse.hostname) and
|
||||||
|
requires proper SPF, DKIM and DMARC configuration to be done for
|
||||||
|
the domain you're sending from, in order for email to be reliably delivered.
|
||||||
|
|
||||||
|
If you want to use a different domain for your outgoing email
|
||||||
|
(for example `example.com` instead of
|
||||||
|
`discourse.example.com`) you should set
|
||||||
|
[](#opt-services.discourse.mail.notificationEmailAddress) and
|
||||||
|
[](#opt-services.discourse.mail.contactEmailAddress) manually.
|
||||||
|
|
||||||
|
::: {.note}
|
||||||
|
Setup of TLS for incoming email is currently only configured
|
||||||
|
automatically when a regular TLS certificate is used, i.e. when
|
||||||
|
[](#opt-services.discourse.sslCertificate) and
|
||||||
|
[](#opt-services.discourse.sslCertificateKey) are
|
||||||
|
set.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Additional settings {#module-services-discourse-settings}
|
||||||
|
|
||||||
|
Additional site settings and backend settings, for which no
|
||||||
|
explicit NixOS options are provided,
|
||||||
|
can be set in [](#opt-services.discourse.siteSettings) and
|
||||||
|
[](#opt-services.discourse.backendSettings) respectively.
|
||||||
|
|
||||||
|
### Site settings {#module-services-discourse-site-settings}
|
||||||
|
|
||||||
|
"Site settings" are the settings that can be
|
||||||
|
changed through the Discourse
|
||||||
|
UI. Their *default* values can be set using
|
||||||
|
[](#opt-services.discourse.siteSettings).
|
||||||
|
|
||||||
|
Settings are expressed as a Nix attribute set which matches the
|
||||||
|
structure of the configuration in
|
||||||
|
[config/site_settings.yml](https://github.com/discourse/discourse/blob/master/config/site_settings.yml).
|
||||||
|
To find a setting's path, you only need to care about the first
|
||||||
|
two levels; i.e. its category (e.g. `login`)
|
||||||
|
and name (e.g. `invite_only`).
|
||||||
|
|
||||||
|
Settings containing secret data should be set to an attribute
|
||||||
|
set containing the attribute `_secret` - a
|
||||||
|
string pointing to a file containing the value the option
|
||||||
|
should be set to. See the example.
|
||||||
|
|
||||||
|
### Backend settings {#module-services-discourse-backend-settings}
|
||||||
|
|
||||||
|
Settings are expressed as a Nix attribute set which matches the
|
||||||
|
structure of the configuration in
|
||||||
|
[config/discourse.conf](https://github.com/discourse/discourse/blob/stable/config/discourse_defaults.conf).
|
||||||
|
Empty parameters can be defined by setting them to
|
||||||
|
`null`.
|
||||||
|
|
||||||
|
### Example {#module-services-discourse-settings-example}
|
||||||
|
|
||||||
|
The following example sets the title and description of the
|
||||||
|
Discourse instance and enables
|
||||||
|
GitHub login in the site settings,
|
||||||
|
and changes a few request limits in the backend settings:
|
||||||
|
```
|
||||||
|
services.discourse = {
|
||||||
|
enable = true;
|
||||||
|
hostname = "discourse.example.com";
|
||||||
|
sslCertificate = "/path/to/ssl_certificate";
|
||||||
|
sslCertificateKey = "/path/to/ssl_certificate_key";
|
||||||
|
admin = {
|
||||||
|
email = "admin@example.com";
|
||||||
|
username = "admin";
|
||||||
|
fullName = "Administrator";
|
||||||
|
passwordFile = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
mail.outgoing = {
|
||||||
|
serverAddress = "smtp.emailprovider.com";
|
||||||
|
port = 587;
|
||||||
|
username = "user@emailprovider.com";
|
||||||
|
passwordFile = "/path/to/smtp_password_file";
|
||||||
|
};
|
||||||
|
mail.incoming.enable = true;
|
||||||
|
siteSettings = {
|
||||||
|
required = {
|
||||||
|
title = "My Cats";
|
||||||
|
site_description = "Discuss My Cats (and be nice plz)";
|
||||||
|
};
|
||||||
|
login = {
|
||||||
|
enable_github_logins = true;
|
||||||
|
github_client_id = "a2f6dfe838cb3206ce20";
|
||||||
|
github_client_secret._secret = /run/keys/discourse_github_client_secret;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
backendSettings = {
|
||||||
|
max_reqs_per_ip_per_minute = 300;
|
||||||
|
max_reqs_per_ip_per_10_seconds = 60;
|
||||||
|
max_asset_reqs_per_ip_per_10_seconds = 250;
|
||||||
|
max_reqs_per_ip_mode = "warn+block";
|
||||||
|
};
|
||||||
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
In the resulting site settings file, the
|
||||||
|
`login.github_client_secret` key will be set
|
||||||
|
to the contents of the
|
||||||
|
{file}`/run/keys/discourse_github_client_secret`
|
||||||
|
file.
|
||||||
|
|
||||||
|
## Plugins {#module-services-discourse-plugins}
|
||||||
|
|
||||||
|
You can install Discourse plugins
|
||||||
|
using the [](#opt-services.discourse.plugins)
|
||||||
|
option. Pre-packaged plugins are provided in
|
||||||
|
`<your_discourse_package_here>.plugins`. If
|
||||||
|
you want the full suite of plugins provided through
|
||||||
|
`nixpkgs`, you can also set the [](#opt-services.discourse.package) option to
|
||||||
|
`pkgs.discourseAllPlugins`.
|
||||||
|
|
||||||
|
Plugins can be built with the
|
||||||
|
`<your_discourse_package_here>.mkDiscoursePlugin`
|
||||||
|
function. Normally, it should suffice to provide a
|
||||||
|
`name` and `src` attribute. If
|
||||||
|
the plugin has Ruby dependencies, however, they need to be
|
||||||
|
packaged in accordance with the [Developing with Ruby](https://nixos.org/manual/nixpkgs/stable/#developing-with-ruby)
|
||||||
|
section of the Nixpkgs manual and the
|
||||||
|
appropriate gem options set in `bundlerEnvArgs`
|
||||||
|
(normally `gemdir` is sufficient). A plugin's
|
||||||
|
Ruby dependencies are listed in its
|
||||||
|
{file}`plugin.rb` file as function calls to
|
||||||
|
`gem`. To construct the corresponding
|
||||||
|
{file}`Gemfile` manually, run {command}`bundle init`, then add the `gem` lines to it
|
||||||
|
verbatim.
|
||||||
|
|
||||||
|
Much of the packaging can be done automatically by the
|
||||||
|
{file}`nixpkgs/pkgs/servers/web-apps/discourse/update.py`
|
||||||
|
script - just add the plugin to the `plugins`
|
||||||
|
list in the `update_plugins` function and run
|
||||||
|
the script:
|
||||||
|
```bash
|
||||||
|
./update.py update-plugins
|
||||||
|
```
|
||||||
|
|
||||||
|
Some plugins provide [site settings](#module-services-discourse-site-settings).
|
||||||
|
Their defaults can be configured using [](#opt-services.discourse.siteSettings), just like
|
||||||
|
regular site settings. To find the names of these settings, look
|
||||||
|
in the `config/settings.yml` file of the plugin
|
||||||
|
repo.
|
||||||
|
|
||||||
|
For example, to add the [discourse-spoiler-alert](https://github.com/discourse/discourse-spoiler-alert)
|
||||||
|
and [discourse-solved](https://github.com/discourse/discourse-solved)
|
||||||
|
plugins, and disable `discourse-spoiler-alert`
|
||||||
|
by default:
|
||||||
|
|
||||||
|
```
|
||||||
|
services.discourse = {
|
||||||
|
enable = true;
|
||||||
|
hostname = "discourse.example.com";
|
||||||
|
sslCertificate = "/path/to/ssl_certificate";
|
||||||
|
sslCertificateKey = "/path/to/ssl_certificate_key";
|
||||||
|
admin = {
|
||||||
|
email = "admin@example.com";
|
||||||
|
username = "admin";
|
||||||
|
fullName = "Administrator";
|
||||||
|
passwordFile = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
mail.outgoing = {
|
||||||
|
serverAddress = "smtp.emailprovider.com";
|
||||||
|
port = 587;
|
||||||
|
username = "user@emailprovider.com";
|
||||||
|
passwordFile = "/path/to/smtp_password_file";
|
||||||
|
};
|
||||||
|
mail.incoming.enable = true;
|
||||||
|
plugins = with config.services.discourse.package.plugins; [
|
||||||
|
discourse-spoiler-alert
|
||||||
|
discourse-solved
|
||||||
|
];
|
||||||
|
siteSettings = {
|
||||||
|
plugins = {
|
||||||
|
spoiler_enabled = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
```
|
|
@ -1,148 +1,137 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-discourse">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-discourse">
|
|
||||||
<title>Discourse</title>
|
<title>Discourse</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://www.discourse.org/">Discourse</link> is a
|
<link xlink:href="https://www.discourse.org/">Discourse</link> is a
|
||||||
modern and open source discussion platform.
|
modern and open source discussion platform.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<section xml:id="module-services-discourse-basic-usage">
|
<section xml:id="module-services-discourse-basic-usage">
|
||||||
<title>Basic usage</title>
|
<title>Basic usage</title>
|
||||||
<para>
|
<para>
|
||||||
A minimal configuration using Let's Encrypt for TLS certificates looks like this:
|
A minimal configuration using Let’s Encrypt for TLS certificates
|
||||||
|
looks like this:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.discourse = {
|
services.discourse = {
|
||||||
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
hostname = "discourse.example.com";
|
||||||
admin = {
|
admin = {
|
||||||
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
email = "admin@example.com";
|
||||||
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
username = "admin";
|
||||||
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
fullName = "Administrator";
|
||||||
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
passwordFile = "/path/to/password_file";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
};
|
};
|
||||||
<link linkend="opt-security.acme.defaults.email">security.acme.email</link> = "me@example.com";
|
security.acme.email = "me@example.com";
|
||||||
<link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link> = true;
|
security.acme.acceptTerms = true;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Provided a proper DNS setup, you'll be able to connect to the
|
Provided a proper DNS setup, you’ll be able to connect to the
|
||||||
instance at <literal>discourse.example.com</literal> and log in
|
instance at <literal>discourse.example.com</literal> and log in
|
||||||
using the credentials provided in
|
using the credentials provided in
|
||||||
<literal>services.discourse.admin</literal>.
|
<literal>services.discourse.admin</literal>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-discourse-tls">
|
<section xml:id="module-services-discourse-tls">
|
||||||
<title>Using a regular TLS certificate</title>
|
<title>Using a regular TLS certificate</title>
|
||||||
<para>
|
<para>
|
||||||
To set up TLS using a regular certificate and key on file, use
|
To set up TLS using a regular certificate and key on file, use the
|
||||||
the <xref linkend="opt-services.discourse.sslCertificate" />
|
<xref linkend="opt-services.discourse.sslCertificate" /> and
|
||||||
and <xref linkend="opt-services.discourse.sslCertificateKey" />
|
<xref linkend="opt-services.discourse.sslCertificateKey" />
|
||||||
options:
|
options:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.discourse = {
|
services.discourse = {
|
||||||
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
hostname = "discourse.example.com";
|
||||||
<link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate";
|
sslCertificate = "/path/to/ssl_certificate";
|
||||||
<link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key";
|
sslCertificateKey = "/path/to/ssl_certificate_key";
|
||||||
admin = {
|
admin = {
|
||||||
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
email = "admin@example.com";
|
||||||
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
username = "admin";
|
||||||
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
fullName = "Administrator";
|
||||||
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
passwordFile = "/path/to/password_file";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-discourse-database">
|
<section xml:id="module-services-discourse-database">
|
||||||
<title>Database access</title>
|
<title>Database access</title>
|
||||||
<para>
|
<para>
|
||||||
<productname>Discourse</productname> uses
|
Discourse uses PostgreSQL to store most of its data. A database
|
||||||
<productname>PostgreSQL</productname> to store most of its
|
will automatically be enabled and a database and role created
|
||||||
data. A database will automatically be enabled and a database
|
unless <xref linkend="opt-services.discourse.database.host" /> is
|
||||||
and role created unless <xref
|
changed from its default of <literal>null</literal> or
|
||||||
linkend="opt-services.discourse.database.host" /> is changed from
|
<xref linkend="opt-services.discourse.database.createLocally" />
|
||||||
its default of <literal>null</literal> or <xref
|
is set to <literal>false</literal>.
|
||||||
linkend="opt-services.discourse.database.createLocally" /> is set
|
|
||||||
to <literal>false</literal>.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
External database access can also be configured by setting
|
External database access can also be configured by setting
|
||||||
<xref linkend="opt-services.discourse.database.host" />, <xref
|
<xref linkend="opt-services.discourse.database.host" />,
|
||||||
linkend="opt-services.discourse.database.username" /> and <xref
|
<xref linkend="opt-services.discourse.database.username" /> and
|
||||||
linkend="opt-services.discourse.database.passwordFile" /> as
|
<xref linkend="opt-services.discourse.database.passwordFile" /> as
|
||||||
appropriate. Note that you need to manually create a database
|
appropriate. Note that you need to manually create a database
|
||||||
called <literal>discourse</literal> (or the name you chose in
|
called <literal>discourse</literal> (or the name you chose in
|
||||||
<xref linkend="opt-services.discourse.database.name" />) and
|
<xref linkend="opt-services.discourse.database.name" />) and allow
|
||||||
allow the configured database user full access to it.
|
the configured database user full access to it.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-discourse-mail">
|
<section xml:id="module-services-discourse-mail">
|
||||||
<title>Email</title>
|
<title>Email</title>
|
||||||
<para>
|
<para>
|
||||||
In addition to the basic setup, you'll want to configure an SMTP
|
In addition to the basic setup, you’ll want to configure an SMTP
|
||||||
server <productname>Discourse</productname> can use to send user
|
server Discourse can use to send user registration and password
|
||||||
registration and password reset emails, among others. You can
|
reset emails, among others. You can also optionally let Discourse
|
||||||
also optionally let <productname>Discourse</productname> receive
|
receive email, which enables people to reply to threads and
|
||||||
email, which enables people to reply to threads and conversations
|
conversations via email.
|
||||||
via email.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A basic setup which assumes you want to use your configured <link
|
A basic setup which assumes you want to use your configured
|
||||||
linkend="opt-services.discourse.hostname">hostname</link> as
|
<link linkend="opt-services.discourse.hostname">hostname</link> as
|
||||||
email domain can be done like this:
|
email domain can be done like this:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.discourse = {
|
services.discourse = {
|
||||||
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
hostname = "discourse.example.com";
|
||||||
<link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate";
|
sslCertificate = "/path/to/ssl_certificate";
|
||||||
<link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key";
|
sslCertificateKey = "/path/to/ssl_certificate_key";
|
||||||
admin = {
|
admin = {
|
||||||
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
email = "admin@example.com";
|
||||||
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
username = "admin";
|
||||||
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
fullName = "Administrator";
|
||||||
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
passwordFile = "/path/to/password_file";
|
||||||
};
|
};
|
||||||
mail.outgoing = {
|
mail.outgoing = {
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com";
|
serverAddress = "smtp.emailprovider.com";
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587;
|
port = 587;
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com";
|
username = "user@emailprovider.com";
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file";
|
passwordFile = "/path/to/smtp_password_file";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true;
|
mail.incoming.enable = true;
|
||||||
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
This assumes you have set up an MX record for the address you've
|
|
||||||
set in <link linkend="opt-services.discourse.hostname">hostname</link> and
|
|
||||||
requires proper SPF, DKIM and DMARC configuration to be done for
|
|
||||||
the domain you're sending from, in order for email to be reliably delivered.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you want to use a different domain for your outgoing email
|
This assumes you have set up an MX record for the address you’ve
|
||||||
(for example <literal>example.com</literal> instead of
|
set in
|
||||||
<literal>discourse.example.com</literal>) you should set
|
<link linkend="opt-services.discourse.hostname">hostname</link>
|
||||||
<xref linkend="opt-services.discourse.mail.notificationEmailAddress" /> and
|
and requires proper SPF, DKIM and DMARC configuration to be done
|
||||||
<xref linkend="opt-services.discourse.mail.contactEmailAddress" /> manually.
|
for the domain you’re sending from, in order for email to be
|
||||||
|
reliably delivered.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you want to use a different domain for your outgoing email (for
|
||||||
|
example <literal>example.com</literal> instead of
|
||||||
|
<literal>discourse.example.com</literal>) you should set
|
||||||
|
<xref linkend="opt-services.discourse.mail.notificationEmailAddress" />
|
||||||
|
and
|
||||||
|
<xref linkend="opt-services.discourse.mail.contactEmailAddress" />
|
||||||
|
manually.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
Setup of TLS for incoming email is currently only configured
|
Setup of TLS for incoming email is currently only configured
|
||||||
|
@ -152,44 +141,39 @@ services.discourse = {
|
||||||
set.
|
set.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-discourse-settings">
|
<section xml:id="module-services-discourse-settings">
|
||||||
<title>Additional settings</title>
|
<title>Additional settings</title>
|
||||||
<para>
|
<para>
|
||||||
Additional site settings and backend settings, for which no
|
Additional site settings and backend settings, for which no
|
||||||
explicit <productname>NixOS</productname> options are provided,
|
explicit NixOS options are provided, can be set in
|
||||||
can be set in <xref linkend="opt-services.discourse.siteSettings" /> and
|
<xref linkend="opt-services.discourse.siteSettings" /> and
|
||||||
<xref linkend="opt-services.discourse.backendSettings" /> respectively.
|
<xref linkend="opt-services.discourse.backendSettings" />
|
||||||
|
respectively.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<section xml:id="module-services-discourse-site-settings">
|
<section xml:id="module-services-discourse-site-settings">
|
||||||
<title>Site settings</title>
|
<title>Site settings</title>
|
||||||
<para>
|
<para>
|
||||||
<quote>Site settings</quote> are the settings that can be
|
<quote>Site settings</quote> are the settings that can be
|
||||||
changed through the <productname>Discourse</productname>
|
changed through the Discourse UI. Their
|
||||||
UI. Their <emphasis>default</emphasis> values can be set using
|
<emphasis>default</emphasis> values can be set using
|
||||||
<xref linkend="opt-services.discourse.siteSettings" />.
|
<xref linkend="opt-services.discourse.siteSettings" />.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Settings are expressed as a Nix attribute set which matches the
|
Settings are expressed as a Nix attribute set which matches the
|
||||||
structure of the configuration in
|
structure of the configuration in
|
||||||
<link xlink:href="https://github.com/discourse/discourse/blob/master/config/site_settings.yml">config/site_settings.yml</link>.
|
<link xlink:href="https://github.com/discourse/discourse/blob/master/config/site_settings.yml">config/site_settings.yml</link>.
|
||||||
To find a setting's path, you only need to care about the first
|
To find a setting’s path, you only need to care about the first
|
||||||
two levels; i.e. its category (e.g. <literal>login</literal>)
|
two levels; i.e. its category (e.g. <literal>login</literal>)
|
||||||
and name (e.g. <literal>invite_only</literal>).
|
and name (e.g. <literal>invite_only</literal>).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Settings containing secret data should be set to an attribute
|
Settings containing secret data should be set to an attribute
|
||||||
set containing the attribute <literal>_secret</literal> - a
|
set containing the attribute <literal>_secret</literal> - a
|
||||||
string pointing to a file containing the value the option
|
string pointing to a file containing the value the option should
|
||||||
should be set to. See the example.
|
be set to. See the example.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-discourse-backend-settings">
|
<section xml:id="module-services-discourse-backend-settings">
|
||||||
<title>Backend settings</title>
|
<title>Backend settings</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -200,58 +184,57 @@ services.discourse = {
|
||||||
<literal>null</literal>.
|
<literal>null</literal>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-discourse-settings-example">
|
<section xml:id="module-services-discourse-settings-example">
|
||||||
<title>Example</title>
|
<title>Example</title>
|
||||||
<para>
|
<para>
|
||||||
The following example sets the title and description of the
|
The following example sets the title and description of the
|
||||||
<productname>Discourse</productname> instance and enables
|
Discourse instance and enables GitHub login in the site
|
||||||
<productname>GitHub</productname> login in the site settings,
|
settings, and changes a few request limits in the backend
|
||||||
and changes a few request limits in the backend settings:
|
settings:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.discourse = {
|
services.discourse = {
|
||||||
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
hostname = "discourse.example.com";
|
||||||
<link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate";
|
sslCertificate = "/path/to/ssl_certificate";
|
||||||
<link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key";
|
sslCertificateKey = "/path/to/ssl_certificate_key";
|
||||||
admin = {
|
admin = {
|
||||||
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
email = "admin@example.com";
|
||||||
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
username = "admin";
|
||||||
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
fullName = "Administrator";
|
||||||
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
passwordFile = "/path/to/password_file";
|
||||||
};
|
};
|
||||||
mail.outgoing = {
|
mail.outgoing = {
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com";
|
serverAddress = "smtp.emailprovider.com";
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587;
|
port = 587;
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com";
|
username = "user@emailprovider.com";
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file";
|
passwordFile = "/path/to/smtp_password_file";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true;
|
mail.incoming.enable = true;
|
||||||
<link linkend="opt-services.discourse.siteSettings">siteSettings</link> = {
|
siteSettings = {
|
||||||
required = {
|
required = {
|
||||||
title = "My Cats";
|
title = "My Cats";
|
||||||
site_description = "Discuss My Cats (and be nice plz)";
|
site_description = "Discuss My Cats (and be nice plz)";
|
||||||
};
|
};
|
||||||
login = {
|
login = {
|
||||||
enable_github_logins = true;
|
enable_github_logins = true;
|
||||||
github_client_id = "a2f6dfe838cb3206ce20";
|
github_client_id = "a2f6dfe838cb3206ce20";
|
||||||
github_client_secret._secret = /run/keys/discourse_github_client_secret;
|
github_client_secret._secret = /run/keys/discourse_github_client_secret;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.discourse.backendSettings">backendSettings</link> = {
|
backendSettings = {
|
||||||
max_reqs_per_ip_per_minute = 300;
|
max_reqs_per_ip_per_minute = 300;
|
||||||
max_reqs_per_ip_per_10_seconds = 60;
|
max_reqs_per_ip_per_10_seconds = 60;
|
||||||
max_asset_reqs_per_ip_per_10_seconds = 250;
|
max_asset_reqs_per_ip_per_10_seconds = 250;
|
||||||
max_reqs_per_ip_mode = "warn+block";
|
max_reqs_per_ip_mode = "warn+block";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
In the resulting site settings file, the
|
In the resulting site settings file, the
|
||||||
<literal>login.github_client_secret</literal> key will be set
|
<literal>login.github_client_secret</literal> key will be set to
|
||||||
to the contents of the
|
the contents of the
|
||||||
<filename>/run/keys/discourse_github_client_secret</filename>
|
<filename>/run/keys/discourse_github_client_secret</filename>
|
||||||
file.
|
file.
|
||||||
</para>
|
</para>
|
||||||
|
@ -260,96 +243,89 @@ services.discourse = {
|
||||||
<section xml:id="module-services-discourse-plugins">
|
<section xml:id="module-services-discourse-plugins">
|
||||||
<title>Plugins</title>
|
<title>Plugins</title>
|
||||||
<para>
|
<para>
|
||||||
You can install <productname>Discourse</productname> plugins
|
You can install Discourse plugins using the
|
||||||
using the <xref linkend="opt-services.discourse.plugins" />
|
<xref linkend="opt-services.discourse.plugins" /> option.
|
||||||
option. Pre-packaged plugins are provided in
|
Pre-packaged plugins are provided in
|
||||||
<literal><your_discourse_package_here>.plugins</literal>. If
|
<literal><your_discourse_package_here>.plugins</literal>. If
|
||||||
you want the full suite of plugins provided through
|
you want the full suite of plugins provided through
|
||||||
<literal>nixpkgs</literal>, you can also set the <xref
|
<literal>nixpkgs</literal>, you can also set the
|
||||||
linkend="opt-services.discourse.package" /> option to
|
<xref linkend="opt-services.discourse.package" /> option to
|
||||||
<literal>pkgs.discourseAllPlugins</literal>.
|
<literal>pkgs.discourseAllPlugins</literal>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Plugins can be built with the
|
Plugins can be built with the
|
||||||
<literal><your_discourse_package_here>.mkDiscoursePlugin</literal>
|
<literal><your_discourse_package_here>.mkDiscoursePlugin</literal>
|
||||||
function. Normally, it should suffice to provide a
|
function. Normally, it should suffice to provide a
|
||||||
<literal>name</literal> and <literal>src</literal> attribute. If
|
<literal>name</literal> and <literal>src</literal> attribute. If
|
||||||
the plugin has Ruby dependencies, however, they need to be
|
the plugin has Ruby dependencies, however, they need to be
|
||||||
packaged in accordance with the <link
|
packaged in accordance with the
|
||||||
xlink:href="https://nixos.org/manual/nixpkgs/stable/#developing-with-ruby">Developing
|
<link xlink:href="https://nixos.org/manual/nixpkgs/stable/#developing-with-ruby">Developing
|
||||||
with Ruby</link> section of the Nixpkgs manual and the
|
with Ruby</link> section of the Nixpkgs manual and the appropriate
|
||||||
appropriate gem options set in <literal>bundlerEnvArgs</literal>
|
gem options set in <literal>bundlerEnvArgs</literal> (normally
|
||||||
(normally <literal>gemdir</literal> is sufficient). A plugin's
|
<literal>gemdir</literal> is sufficient). A plugin’s Ruby
|
||||||
Ruby dependencies are listed in its
|
dependencies are listed in its <filename>plugin.rb</filename> file
|
||||||
<filename>plugin.rb</filename> file as function calls to
|
as function calls to <literal>gem</literal>. To construct the
|
||||||
<literal>gem</literal>. To construct the corresponding
|
corresponding <filename>Gemfile</filename> manually, run
|
||||||
<filename>Gemfile</filename> manually, run <command>bundle
|
<command>bundle init</command>, then add the
|
||||||
init</command>, then add the <literal>gem</literal> lines to it
|
<literal>gem</literal> lines to it verbatim.
|
||||||
verbatim.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Much of the packaging can be done automatically by the
|
Much of the packaging can be done automatically by the
|
||||||
<filename>nixpkgs/pkgs/servers/web-apps/discourse/update.py</filename>
|
<filename>nixpkgs/pkgs/servers/web-apps/discourse/update.py</filename>
|
||||||
script - just add the plugin to the <literal>plugins</literal>
|
script - just add the plugin to the <literal>plugins</literal>
|
||||||
list in the <function>update_plugins</function> function and run
|
list in the <literal>update_plugins</literal> function and run the
|
||||||
the script:
|
script:
|
||||||
|
</para>
|
||||||
<programlisting language="bash">
|
<programlisting language="bash">
|
||||||
./update.py update-plugins
|
./update.py update-plugins
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Some plugins provide <link
|
Some plugins provide
|
||||||
linkend="module-services-discourse-site-settings">site
|
<link linkend="module-services-discourse-site-settings">site
|
||||||
settings</link>. Their defaults can be configured using <xref
|
settings</link>. Their defaults can be configured using
|
||||||
linkend="opt-services.discourse.siteSettings" />, just like
|
<xref linkend="opt-services.discourse.siteSettings" />, just like
|
||||||
regular site settings. To find the names of these settings, look
|
regular site settings. To find the names of these settings, look
|
||||||
in the <literal>config/settings.yml</literal> file of the plugin
|
in the <literal>config/settings.yml</literal> file of the plugin
|
||||||
repo.
|
repo.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For example, to add the <link
|
For example, to add the
|
||||||
xlink:href="https://github.com/discourse/discourse-spoiler-alert">discourse-spoiler-alert</link>
|
<link xlink:href="https://github.com/discourse/discourse-spoiler-alert">discourse-spoiler-alert</link>
|
||||||
and <link
|
and
|
||||||
xlink:href="https://github.com/discourse/discourse-solved">discourse-solved</link>
|
<link xlink:href="https://github.com/discourse/discourse-solved">discourse-solved</link>
|
||||||
plugins, and disable <literal>discourse-spoiler-alert</literal>
|
plugins, and disable <literal>discourse-spoiler-alert</literal> by
|
||||||
by default:
|
default:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.discourse = {
|
services.discourse = {
|
||||||
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
hostname = "discourse.example.com";
|
||||||
<link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate";
|
sslCertificate = "/path/to/ssl_certificate";
|
||||||
<link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key";
|
sslCertificateKey = "/path/to/ssl_certificate_key";
|
||||||
admin = {
|
admin = {
|
||||||
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
email = "admin@example.com";
|
||||||
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
username = "admin";
|
||||||
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
fullName = "Administrator";
|
||||||
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
passwordFile = "/path/to/password_file";
|
||||||
};
|
};
|
||||||
mail.outgoing = {
|
mail.outgoing = {
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com";
|
serverAddress = "smtp.emailprovider.com";
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587;
|
port = 587;
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com";
|
username = "user@emailprovider.com";
|
||||||
<link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file";
|
passwordFile = "/path/to/smtp_password_file";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true;
|
mail.incoming.enable = true;
|
||||||
<link linkend="opt-services.discourse.mail.incoming.enable">plugins</link> = with config.services.discourse.package.plugins; [
|
plugins = with config.services.discourse.package.plugins; [
|
||||||
discourse-spoiler-alert
|
discourse-spoiler-alert
|
||||||
discourse-solved
|
discourse-solved
|
||||||
];
|
];
|
||||||
<link linkend="opt-services.discourse.siteSettings">siteSettings</link> = {
|
siteSettings = {
|
||||||
plugins = {
|
plugins = {
|
||||||
spoiler_enabled = false;
|
spoiler_enabled = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
66
nixos/modules/services/web-apps/grocy.md
Normal file
66
nixos/modules/services/web-apps/grocy.md
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# Grocy {#module-services-grocy}
|
||||||
|
|
||||||
|
[Grocy](https://grocy.info/) is a web-based self-hosted groceries
|
||||||
|
& household management solution for your home.
|
||||||
|
|
||||||
|
## Basic usage {#module-services-grocy-basic-usage}
|
||||||
|
|
||||||
|
A very basic configuration may look like this:
|
||||||
|
```
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
services.grocy = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "grocy.tld";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This configures a simple vhost using [nginx](#opt-services.nginx.enable)
|
||||||
|
which listens to `grocy.tld` with fully configured ACME/LE (this can be
|
||||||
|
disabled by setting [services.grocy.nginx.enableSSL](#opt-services.grocy.nginx.enableSSL)
|
||||||
|
to `false`). After the initial setup the credentials `admin:admin`
|
||||||
|
can be used to login.
|
||||||
|
|
||||||
|
The application's state is persisted at `/var/lib/grocy/grocy.db` in a
|
||||||
|
`sqlite3` database. The migration is applied when requesting the `/`-route
|
||||||
|
of the application.
|
||||||
|
|
||||||
|
## Settings {#module-services-grocy-settings}
|
||||||
|
|
||||||
|
The configuration for `grocy` is located at `/etc/grocy/config.php`.
|
||||||
|
By default, the following settings can be defined in the NixOS-configuration:
|
||||||
|
```
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
services.grocy.settings = {
|
||||||
|
# The default currency in the system for invoices etc.
|
||||||
|
# Please note that exchange rates aren't taken into account, this
|
||||||
|
# is just the setting for what's shown in the frontend.
|
||||||
|
currency = "EUR";
|
||||||
|
|
||||||
|
# The display language (and locale configuration) for grocy.
|
||||||
|
culture = "de";
|
||||||
|
|
||||||
|
calendar = {
|
||||||
|
# Whether or not to show the week-numbers
|
||||||
|
# in the calendar.
|
||||||
|
showWeekNumber = true;
|
||||||
|
|
||||||
|
# Index of the first day to be shown in the calendar (0=Sunday, 1=Monday,
|
||||||
|
# 2=Tuesday and so on).
|
||||||
|
firstDayOfWeek = 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to alter the configuration file on your own, you can do this manually with
|
||||||
|
an expression like this:
|
||||||
|
```
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
environment.etc."grocy/config.php".text = lib.mkAfter ''
|
||||||
|
// Arbitrary PHP code in grocy's configuration file
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
```
|
|
@ -1,77 +1,84 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-grocy">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-grocy">
|
|
||||||
|
|
||||||
<title>Grocy</title>
|
<title>Grocy</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://grocy.info/">Grocy</link> is a web-based self-hosted groceries
|
<link xlink:href="https://grocy.info/">Grocy</link> is a web-based
|
||||||
& household management solution for your home.
|
self-hosted groceries & household management solution for your
|
||||||
|
home.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<section xml:id="module-services-grocy-basic-usage">
|
<section xml:id="module-services-grocy-basic-usage">
|
||||||
<title>Basic usage</title>
|
<title>Basic usage</title>
|
||||||
<para>
|
<para>
|
||||||
A very basic configuration may look like this:
|
A very basic configuration may look like this:
|
||||||
<programlisting>{ pkgs, ... }:
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
services.grocy = {
|
services.grocy = {
|
||||||
<link linkend="opt-services.grocy.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.grocy.hostName">hostName</link> = "grocy.tld";
|
hostName = "grocy.tld";
|
||||||
};
|
};
|
||||||
}</programlisting>
|
}
|
||||||
This configures a simple vhost using <link linkend="opt-services.nginx.enable">nginx</link>
|
</programlisting>
|
||||||
which listens to <literal>grocy.tld</literal> with fully configured ACME/LE (this can be
|
<para>
|
||||||
disabled by setting <link linkend="opt-services.grocy.nginx.enableSSL">services.grocy.nginx.enableSSL</link>
|
This configures a simple vhost using
|
||||||
to <literal>false</literal>). After the initial setup the credentials <literal>admin:admin</literal>
|
<link linkend="opt-services.nginx.enable">nginx</link> which
|
||||||
can be used to login.
|
listens to <literal>grocy.tld</literal> with fully configured
|
||||||
|
ACME/LE (this can be disabled by setting
|
||||||
|
<link linkend="opt-services.grocy.nginx.enableSSL">services.grocy.nginx.enableSSL</link>
|
||||||
|
to <literal>false</literal>). After the initial setup the
|
||||||
|
credentials <literal>admin:admin</literal> can be used to login.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The application's state is persisted at <literal>/var/lib/grocy/grocy.db</literal> in a
|
The application’s state is persisted at
|
||||||
<package>sqlite3</package> database. The migration is applied when requesting the <literal>/</literal>-route
|
<literal>/var/lib/grocy/grocy.db</literal> in a
|
||||||
of the application.
|
<literal>sqlite3</literal> database. The migration is applied when
|
||||||
|
requesting the <literal>/</literal>-route of the application.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-grocy-settings">
|
<section xml:id="module-services-grocy-settings">
|
||||||
<title>Settings</title>
|
<title>Settings</title>
|
||||||
<para>
|
<para>
|
||||||
The configuration for <literal>grocy</literal> is located at <literal>/etc/grocy/config.php</literal>.
|
The configuration for <literal>grocy</literal> is located at
|
||||||
By default, the following settings can be defined in the NixOS-configuration:
|
<literal>/etc/grocy/config.php</literal>. By default, the
|
||||||
<programlisting>{ pkgs, ... }:
|
following settings can be defined in the NixOS-configuration:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
services.grocy.settings = {
|
services.grocy.settings = {
|
||||||
# The default currency in the system for invoices etc.
|
# The default currency in the system for invoices etc.
|
||||||
# Please note that exchange rates aren't taken into account, this
|
# Please note that exchange rates aren't taken into account, this
|
||||||
# is just the setting for what's shown in the frontend.
|
# is just the setting for what's shown in the frontend.
|
||||||
<link linkend="opt-services.grocy.settings.currency">currency</link> = "EUR";
|
currency = "EUR";
|
||||||
|
|
||||||
# The display language (and locale configuration) for grocy.
|
# The display language (and locale configuration) for grocy.
|
||||||
<link linkend="opt-services.grocy.settings.currency">culture</link> = "de";
|
culture = "de";
|
||||||
|
|
||||||
calendar = {
|
calendar = {
|
||||||
# Whether or not to show the week-numbers
|
# Whether or not to show the week-numbers
|
||||||
# in the calendar.
|
# in the calendar.
|
||||||
<link linkend="opt-services.grocy.settings.calendar.showWeekNumber">showWeekNumber</link> = true;
|
showWeekNumber = true;
|
||||||
|
|
||||||
# Index of the first day to be shown in the calendar (0=Sunday, 1=Monday,
|
# Index of the first day to be shown in the calendar (0=Sunday, 1=Monday,
|
||||||
# 2=Tuesday and so on).
|
# 2=Tuesday and so on).
|
||||||
<link linkend="opt-services.grocy.settings.calendar.firstDayOfWeek">firstDayOfWeek</link> = 2;
|
firstDayOfWeek = 2;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
If you want to alter the configuration file on your own, you can do this manually with
|
If you want to alter the configuration file on your own, you can
|
||||||
an expression like this:
|
do this manually with an expression like this:
|
||||||
<programlisting>{ lib, ... }:
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{ lib, ... }:
|
||||||
{
|
{
|
||||||
environment.etc."grocy/config.php".text = lib.mkAfter ''
|
environment.etc."grocy/config.php".text = lib.mkAfter ''
|
||||||
// Arbitrary PHP code in grocy's configuration file
|
// Arbitrary PHP code in grocy's configuration file
|
||||||
'';
|
'';
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
45
nixos/modules/services/web-apps/jitsi-meet.md
Normal file
45
nixos/modules/services/web-apps/jitsi-meet.md
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Jitsi Meet {#module-services-jitsi-meet}
|
||||||
|
|
||||||
|
With Jitsi Meet on NixOS you can quickly configure a complete,
|
||||||
|
private, self-hosted video conferencing solution.
|
||||||
|
|
||||||
|
## Basic usage {#module-services-jitsi-basic-usage}
|
||||||
|
|
||||||
|
A minimal configuration using Let's Encrypt for TLS certificates looks like this:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.jitsi-meet = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "jitsi.example.com";
|
||||||
|
};
|
||||||
|
services.jitsi-videobridge.openFirewall = true;
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
security.acme.email = "me@example.com";
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration {#module-services-jitsi-configuration}
|
||||||
|
|
||||||
|
Here is the minimal configuration with additional configurations:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.jitsi-meet = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "jitsi.example.com";
|
||||||
|
config = {
|
||||||
|
enableWelcomePage = false;
|
||||||
|
prejoinPageEnabled = true;
|
||||||
|
defaultLang = "fi";
|
||||||
|
};
|
||||||
|
interfaceConfig = {
|
||||||
|
SHOW_JITSI_WATERMARK = false;
|
||||||
|
SHOW_WATERMARK_FOR_GUESTS = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.jitsi-videobridge.openFirewall = true;
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
security.acme.email = "me@example.com";
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
}
|
||||||
|
```
|
|
@ -1,55 +1,55 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-jitsi-meet">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-jitsi-meet">
|
|
||||||
<title>Jitsi Meet</title>
|
<title>Jitsi Meet</title>
|
||||||
<para>
|
<para>
|
||||||
With Jitsi Meet on NixOS you can quickly configure a complete,
|
With Jitsi Meet on NixOS you can quickly configure a complete,
|
||||||
private, self-hosted video conferencing solution.
|
private, self-hosted video conferencing solution.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<section xml:id="module-services-jitsi-basic-usage">
|
<section xml:id="module-services-jitsi-basic-usage">
|
||||||
<title>Basic usage</title>
|
<title>Basic usage</title>
|
||||||
<para>
|
<para>
|
||||||
A minimal configuration using Let's Encrypt for TLS certificates looks like this:
|
A minimal configuration using Let’s Encrypt for TLS certificates
|
||||||
<programlisting>{
|
looks like this:
|
||||||
services.jitsi-meet = {
|
|
||||||
<link linkend="opt-services.jitsi-meet.enable">enable</link> = true;
|
|
||||||
<link linkend="opt-services.jitsi-meet.enable">hostName</link> = "jitsi.example.com";
|
|
||||||
};
|
|
||||||
<link linkend="opt-services.jitsi-videobridge.openFirewall">services.jitsi-videobridge.openFirewall</link> = true;
|
|
||||||
<link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
|
|
||||||
<link linkend="opt-security.acme.defaults.email">security.acme.email</link> = "me@example.com";
|
|
||||||
<link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link> = true;
|
|
||||||
}</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{
|
||||||
|
services.jitsi-meet = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "jitsi.example.com";
|
||||||
|
};
|
||||||
|
services.jitsi-videobridge.openFirewall = true;
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
security.acme.email = "me@example.com";
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-jitsi-configuration">
|
<section xml:id="module-services-jitsi-configuration">
|
||||||
<title>Configuration</title>
|
<title>Configuration</title>
|
||||||
<para>
|
<para>
|
||||||
Here is the minimal configuration with additional configurations:
|
Here is the minimal configuration with additional configurations:
|
||||||
<programlisting>{
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{
|
||||||
services.jitsi-meet = {
|
services.jitsi-meet = {
|
||||||
<link linkend="opt-services.jitsi-meet.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.jitsi-meet.enable">hostName</link> = "jitsi.example.com";
|
hostName = "jitsi.example.com";
|
||||||
<link linkend="opt-services.jitsi-meet.config">config</link> = {
|
config = {
|
||||||
enableWelcomePage = false;
|
enableWelcomePage = false;
|
||||||
prejoinPageEnabled = true;
|
prejoinPageEnabled = true;
|
||||||
defaultLang = "fi";
|
defaultLang = "fi";
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.jitsi-meet.interfaceConfig">interfaceConfig</link> = {
|
interfaceConfig = {
|
||||||
SHOW_JITSI_WATERMARK = false;
|
SHOW_JITSI_WATERMARK = false;
|
||||||
SHOW_WATERMARK_FOR_GUESTS = false;
|
SHOW_WATERMARK_FOR_GUESTS = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.jitsi-videobridge.openFirewall">services.jitsi-videobridge.openFirewall</link> = true;
|
services.jitsi-videobridge.openFirewall = true;
|
||||||
<link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
<link linkend="opt-security.acme.defaults.email">security.acme.email</link> = "me@example.com";
|
security.acme.email = "me@example.com";
|
||||||
<link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link> = true;
|
security.acme.acceptTerms = true;
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
141
nixos/modules/services/web-apps/keycloak.md
Normal file
141
nixos/modules/services/web-apps/keycloak.md
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
# Keycloak {#module-services-keycloak}
|
||||||
|
|
||||||
|
[Keycloak](https://www.keycloak.org/) is an
|
||||||
|
open source identity and access management server with support for
|
||||||
|
[OpenID Connect](https://openid.net/connect/),
|
||||||
|
[OAUTH 2.0](https://oauth.net/2/) and
|
||||||
|
[SAML 2.0](https://en.wikipedia.org/wiki/SAML_2.0).
|
||||||
|
|
||||||
|
## Administration {#module-services-keycloak-admin}
|
||||||
|
|
||||||
|
An administrative user with the username
|
||||||
|
`admin` is automatically created in the
|
||||||
|
`master` realm. Its initial password can be
|
||||||
|
configured by setting [](#opt-services.keycloak.initialAdminPassword)
|
||||||
|
and defaults to `changeme`. The password is
|
||||||
|
not stored safely and should be changed immediately in the
|
||||||
|
admin panel.
|
||||||
|
|
||||||
|
Refer to the [Keycloak Server Administration Guide](
|
||||||
|
https://www.keycloak.org/docs/latest/server_admin/index.html
|
||||||
|
) for information on
|
||||||
|
how to administer your Keycloak
|
||||||
|
instance.
|
||||||
|
|
||||||
|
## Database access {#module-services-keycloak-database}
|
||||||
|
|
||||||
|
Keycloak can be used with either PostgreSQL, MariaDB or
|
||||||
|
MySQL. Which one is used can be
|
||||||
|
configured in [](#opt-services.keycloak.database.type). The selected
|
||||||
|
database will automatically be enabled and a database and role
|
||||||
|
created unless [](#opt-services.keycloak.database.host) is changed
|
||||||
|
from its default of `localhost` or
|
||||||
|
[](#opt-services.keycloak.database.createLocally) is set to `false`.
|
||||||
|
|
||||||
|
External database access can also be configured by setting
|
||||||
|
[](#opt-services.keycloak.database.host),
|
||||||
|
[](#opt-services.keycloak.database.name),
|
||||||
|
[](#opt-services.keycloak.database.username),
|
||||||
|
[](#opt-services.keycloak.database.useSSL) and
|
||||||
|
[](#opt-services.keycloak.database.caCert) as
|
||||||
|
appropriate. Note that you need to manually create the database
|
||||||
|
and allow the configured database user full access to it.
|
||||||
|
|
||||||
|
[](#opt-services.keycloak.database.passwordFile)
|
||||||
|
must be set to the path to a file containing the password used
|
||||||
|
to log in to the database. If [](#opt-services.keycloak.database.host)
|
||||||
|
and [](#opt-services.keycloak.database.createLocally)
|
||||||
|
are kept at their defaults, the database role
|
||||||
|
`keycloak` with that password is provisioned
|
||||||
|
on the local database instance.
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
The path should be provided as a string, not a Nix path, since Nix
|
||||||
|
paths are copied into the world readable Nix store.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Hostname {#module-services-keycloak-hostname}
|
||||||
|
|
||||||
|
The hostname is used to build the public URL used as base for
|
||||||
|
all frontend requests and must be configured through
|
||||||
|
[](#opt-services.keycloak.settings.hostname).
|
||||||
|
|
||||||
|
::: {.note}
|
||||||
|
If you're migrating an old Wildfly based Keycloak instance
|
||||||
|
and want to keep compatibility with your current clients,
|
||||||
|
you'll likely want to set [](#opt-services.keycloak.settings.http-relative-path)
|
||||||
|
to `/auth`. See the option description
|
||||||
|
for more details.
|
||||||
|
:::
|
||||||
|
|
||||||
|
[](#opt-services.keycloak.settings.hostname-strict-backchannel)
|
||||||
|
determines whether Keycloak should force all requests to go
|
||||||
|
through the frontend URL. By default,
|
||||||
|
Keycloak allows backend requests to
|
||||||
|
instead use its local hostname or IP address and may also
|
||||||
|
advertise it to clients through its OpenID Connect Discovery
|
||||||
|
endpoint.
|
||||||
|
|
||||||
|
For more information on hostname configuration, see the [Hostname
|
||||||
|
section of the Keycloak Server Installation and Configuration
|
||||||
|
Guide](https://www.keycloak.org/server/hostname).
|
||||||
|
|
||||||
|
## Setting up TLS/SSL {#module-services-keycloak-tls}
|
||||||
|
|
||||||
|
By default, Keycloak won't accept
|
||||||
|
unsecured HTTP connections originating from outside its local
|
||||||
|
network.
|
||||||
|
|
||||||
|
HTTPS support requires a TLS/SSL certificate and a private key,
|
||||||
|
both [PEM formatted](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail).
|
||||||
|
Their paths should be set through
|
||||||
|
[](#opt-services.keycloak.sslCertificate) and
|
||||||
|
[](#opt-services.keycloak.sslCertificateKey).
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
The paths should be provided as a strings, not a Nix paths,
|
||||||
|
since Nix paths are copied into the world readable Nix store.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Themes {#module-services-keycloak-themes}
|
||||||
|
|
||||||
|
You can package custom themes and make them visible to
|
||||||
|
Keycloak through [](#opt-services.keycloak.themes). See the
|
||||||
|
[Themes section of the Keycloak Server Development Guide](
|
||||||
|
https://www.keycloak.org/docs/latest/server_development/#_themes
|
||||||
|
) and the description of the aforementioned NixOS option for
|
||||||
|
more information.
|
||||||
|
|
||||||
|
## Configuration file settings {#module-services-keycloak-settings}
|
||||||
|
|
||||||
|
Keycloak server configuration parameters can be set in
|
||||||
|
[](#opt-services.keycloak.settings). These correspond
|
||||||
|
directly to options in
|
||||||
|
{file}`conf/keycloak.conf`. Some of the most
|
||||||
|
important parameters are documented as suboptions, the rest can
|
||||||
|
be found in the [All
|
||||||
|
configuration section of the Keycloak Server Installation and
|
||||||
|
Configuration Guide](https://www.keycloak.org/server/all-config).
|
||||||
|
|
||||||
|
Options containing secret data should be set to an attribute
|
||||||
|
set containing the attribute `_secret` - a
|
||||||
|
string pointing to a file containing the value the option
|
||||||
|
should be set to. See the description of
|
||||||
|
[](#opt-services.keycloak.settings) for an example.
|
||||||
|
|
||||||
|
## Example configuration {#module-services-keycloak-example-config}
|
||||||
|
|
||||||
|
A basic configuration with some custom settings could look like this:
|
||||||
|
```
|
||||||
|
services.keycloak = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
hostname = "keycloak.example.com";
|
||||||
|
hostname-strict-backchannel = true;
|
||||||
|
};
|
||||||
|
initialAdminPassword = "e6Wcm0RrtegMEHl"; # change on first login
|
||||||
|
sslCertificate = "/run/keys/ssl_cert";
|
||||||
|
sslCertificateKey = "/run/keys/ssl_key";
|
||||||
|
database.passwordFile = "/run/keys/db_password";
|
||||||
|
};
|
||||||
|
```
|
|
@ -1,139 +1,120 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-keycloak">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-keycloak">
|
|
||||||
<title>Keycloak</title>
|
<title>Keycloak</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://www.keycloak.org/">Keycloak</link> is an
|
<link xlink:href="https://www.keycloak.org/">Keycloak</link> is an
|
||||||
open source identity and access management server with support for
|
open source identity and access management server with support for
|
||||||
<link xlink:href="https://openid.net/connect/">OpenID
|
<link xlink:href="https://openid.net/connect/">OpenID
|
||||||
Connect</link>, <link xlink:href="https://oauth.net/2/">OAUTH
|
Connect</link>, <link xlink:href="https://oauth.net/2/">OAUTH
|
||||||
2.0</link> and <link
|
2.0</link> and
|
||||||
xlink:href="https://en.wikipedia.org/wiki/SAML_2.0">SAML
|
<link xlink:href="https://en.wikipedia.org/wiki/SAML_2.0">SAML
|
||||||
2.0</link>.
|
2.0</link>.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-keycloak-admin">
|
<section xml:id="module-services-keycloak-admin">
|
||||||
<title>Administration</title>
|
<title>Administration</title>
|
||||||
<para>
|
<para>
|
||||||
An administrative user with the username
|
An administrative user with the username <literal>admin</literal>
|
||||||
<literal>admin</literal> is automatically created in the
|
is automatically created in the <literal>master</literal> realm.
|
||||||
<literal>master</literal> realm. Its initial password can be
|
Its initial password can be configured by setting
|
||||||
configured by setting <xref linkend="opt-services.keycloak.initialAdminPassword" />
|
<xref linkend="opt-services.keycloak.initialAdminPassword" /> and
|
||||||
and defaults to <literal>changeme</literal>. The password is
|
defaults to <literal>changeme</literal>. The password is not
|
||||||
not stored safely and should be changed immediately in the
|
stored safely and should be changed immediately in the admin
|
||||||
admin panel.
|
panel.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Refer to the <link
|
Refer to the
|
||||||
xlink:href="https://www.keycloak.org/docs/latest/server_admin/index.html">
|
<link xlink:href="https://www.keycloak.org/docs/latest/server_admin/index.html">Keycloak
|
||||||
Keycloak Server Administration Guide</link> for information on
|
Server Administration Guide</link> for information on how to
|
||||||
how to administer your <productname>Keycloak</productname>
|
administer your Keycloak instance.
|
||||||
instance.
|
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-keycloak-database">
|
<section xml:id="module-services-keycloak-database">
|
||||||
<title>Database access</title>
|
<title>Database access</title>
|
||||||
<para>
|
<para>
|
||||||
<productname>Keycloak</productname> can be used with either
|
Keycloak can be used with either PostgreSQL, MariaDB or MySQL.
|
||||||
<productname>PostgreSQL</productname>,
|
Which one is used can be configured in
|
||||||
<productname>MariaDB</productname> or
|
<xref linkend="opt-services.keycloak.database.type" />. The
|
||||||
<productname>MySQL</productname>. Which one is used can be
|
selected database will automatically be enabled and a database and
|
||||||
configured in <xref
|
role created unless
|
||||||
linkend="opt-services.keycloak.database.type" />. The selected
|
<xref linkend="opt-services.keycloak.database.host" /> is changed
|
||||||
database will automatically be enabled and a database and role
|
from its default of <literal>localhost</literal> or
|
||||||
created unless <xref
|
<xref linkend="opt-services.keycloak.database.createLocally" /> is
|
||||||
linkend="opt-services.keycloak.database.host" /> is changed
|
|
||||||
from its default of <literal>localhost</literal> or <xref
|
|
||||||
linkend="opt-services.keycloak.database.createLocally" /> is
|
|
||||||
set to <literal>false</literal>.
|
set to <literal>false</literal>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
External database access can also be configured by setting
|
External database access can also be configured by setting
|
||||||
<xref linkend="opt-services.keycloak.database.host" />, <xref
|
<xref linkend="opt-services.keycloak.database.host" />,
|
||||||
linkend="opt-services.keycloak.database.name" />, <xref
|
<xref linkend="opt-services.keycloak.database.name" />,
|
||||||
linkend="opt-services.keycloak.database.username" />, <xref
|
<xref linkend="opt-services.keycloak.database.username" />,
|
||||||
linkend="opt-services.keycloak.database.useSSL" /> and <xref
|
<xref linkend="opt-services.keycloak.database.useSSL" /> and
|
||||||
linkend="opt-services.keycloak.database.caCert" /> as
|
<xref linkend="opt-services.keycloak.database.caCert" /> as
|
||||||
appropriate. Note that you need to manually create the database
|
appropriate. Note that you need to manually create the database
|
||||||
and allow the configured database user full access to it.
|
and allow the configured database user full access to it.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<xref linkend="opt-services.keycloak.database.passwordFile" />
|
<xref linkend="opt-services.keycloak.database.passwordFile" />
|
||||||
must be set to the path to a file containing the password used
|
must be set to the path to a file containing the password used to
|
||||||
to log in to the database. If <xref linkend="opt-services.keycloak.database.host" />
|
log in to the database. If
|
||||||
and <xref linkend="opt-services.keycloak.database.createLocally" />
|
<xref linkend="opt-services.keycloak.database.host" /> and
|
||||||
|
<xref linkend="opt-services.keycloak.database.createLocally" />
|
||||||
are kept at their defaults, the database role
|
are kept at their defaults, the database role
|
||||||
<literal>keycloak</literal> with that password is provisioned
|
<literal>keycloak</literal> with that password is provisioned on
|
||||||
on the local database instance.
|
the local database instance.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<warning>
|
<warning>
|
||||||
<para>
|
<para>
|
||||||
The path should be provided as a string, not a Nix path, since Nix
|
The path should be provided as a string, not a Nix path, since
|
||||||
paths are copied into the world readable Nix store.
|
Nix paths are copied into the world readable Nix store.
|
||||||
</para>
|
</para>
|
||||||
</warning>
|
</warning>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-keycloak-hostname">
|
<section xml:id="module-services-keycloak-hostname">
|
||||||
<title>Hostname</title>
|
<title>Hostname</title>
|
||||||
<para>
|
<para>
|
||||||
The hostname is used to build the public URL used as base for
|
The hostname is used to build the public URL used as base for all
|
||||||
all frontend requests and must be configured through <xref
|
frontend requests and must be configured through
|
||||||
linkend="opt-services.keycloak.settings.hostname" />.
|
<xref linkend="opt-services.keycloak.settings.hostname" />.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
If you're migrating an old Wildfly based Keycloak instance
|
If you’re migrating an old Wildfly based Keycloak instance and
|
||||||
and want to keep compatibility with your current clients,
|
want to keep compatibility with your current clients, you’ll
|
||||||
you'll likely want to set <xref
|
likely want to set
|
||||||
linkend="opt-services.keycloak.settings.http-relative-path"
|
<xref linkend="opt-services.keycloak.settings.http-relative-path" />
|
||||||
/> to <literal>/auth</literal>. See the option description
|
to <literal>/auth</literal>. See the option description for more
|
||||||
for more details.
|
details.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<xref linkend="opt-services.keycloak.settings.hostname-strict-backchannel" />
|
<xref linkend="opt-services.keycloak.settings.hostname-strict-backchannel" />
|
||||||
determines whether Keycloak should force all requests to go
|
determines whether Keycloak should force all requests to go
|
||||||
through the frontend URL. By default,
|
through the frontend URL. By default, Keycloak allows backend
|
||||||
<productname>Keycloak</productname> allows backend requests to
|
requests to instead use its local hostname or IP address and may
|
||||||
instead use its local hostname or IP address and may also
|
also advertise it to clients through its OpenID Connect Discovery
|
||||||
advertise it to clients through its OpenID Connect Discovery
|
|
||||||
endpoint.
|
endpoint.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For more information on hostname configuration, see the <link
|
For more information on hostname configuration, see the
|
||||||
xlink:href="https://www.keycloak.org/server/hostname">Hostname
|
<link xlink:href="https://www.keycloak.org/server/hostname">Hostname
|
||||||
section of the Keycloak Server Installation and Configuration
|
section of the Keycloak Server Installation and Configuration
|
||||||
Guide</link>.
|
Guide</link>.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-keycloak-tls">
|
<section xml:id="module-services-keycloak-tls">
|
||||||
<title>Setting up TLS/SSL</title>
|
<title>Setting up TLS/SSL</title>
|
||||||
<para>
|
<para>
|
||||||
By default, <productname>Keycloak</productname> won't accept
|
By default, Keycloak won’t accept unsecured HTTP connections
|
||||||
unsecured HTTP connections originating from outside its local
|
originating from outside its local network.
|
||||||
network.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
HTTPS support requires a TLS/SSL certificate and a private key,
|
HTTPS support requires a TLS/SSL certificate and a private key,
|
||||||
both <link
|
both
|
||||||
xlink:href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail">PEM
|
<link xlink:href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail">PEM
|
||||||
formatted</link>. Their paths should be set through <xref
|
formatted</link>. Their paths should be set through
|
||||||
linkend="opt-services.keycloak.sslCertificate" /> and <xref
|
<xref linkend="opt-services.keycloak.sslCertificate" /> and
|
||||||
linkend="opt-services.keycloak.sslCertificateKey" />.
|
<xref linkend="opt-services.keycloak.sslCertificateKey" />.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<warning>
|
<warning>
|
||||||
<para>
|
<para>
|
||||||
The paths should be provided as a strings, not a Nix paths,
|
The paths should be provided as a strings, not a Nix paths,
|
||||||
|
@ -141,62 +122,56 @@
|
||||||
</para>
|
</para>
|
||||||
</warning>
|
</warning>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-keycloak-themes">
|
<section xml:id="module-services-keycloak-themes">
|
||||||
<title>Themes</title>
|
<title>Themes</title>
|
||||||
<para>
|
<para>
|
||||||
You can package custom themes and make them visible to
|
You can package custom themes and make them visible to Keycloak
|
||||||
Keycloak through <xref linkend="opt-services.keycloak.themes"
|
through <xref linkend="opt-services.keycloak.themes" />. See the
|
||||||
/>. See the <link
|
<link xlink:href="https://www.keycloak.org/docs/latest/server_development/#_themes">Themes
|
||||||
xlink:href="https://www.keycloak.org/docs/latest/server_development/#_themes">
|
section of the Keycloak Server Development Guide</link> and the
|
||||||
Themes section of the Keycloak Server Development Guide</link>
|
description of the aforementioned NixOS option for more
|
||||||
and the description of the aforementioned NixOS option for
|
information.
|
||||||
more information.
|
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-keycloak-settings">
|
<section xml:id="module-services-keycloak-settings">
|
||||||
<title>Configuration file settings</title>
|
<title>Configuration file settings</title>
|
||||||
<para>
|
<para>
|
||||||
Keycloak server configuration parameters can be set in <xref
|
Keycloak server configuration parameters can be set in
|
||||||
linkend="opt-services.keycloak.settings" />. These correspond
|
<xref linkend="opt-services.keycloak.settings" />. These
|
||||||
directly to options in
|
correspond directly to options in
|
||||||
<filename>conf/keycloak.conf</filename>. Some of the most
|
<filename>conf/keycloak.conf</filename>. Some of the most
|
||||||
important parameters are documented as suboptions, the rest can
|
important parameters are documented as suboptions, the rest can be
|
||||||
be found in the <link
|
found in the
|
||||||
xlink:href="https://www.keycloak.org/server/all-config">All
|
<link xlink:href="https://www.keycloak.org/server/all-config">All
|
||||||
configuration section of the Keycloak Server Installation and
|
configuration section of the Keycloak Server Installation and
|
||||||
Configuration Guide</link>.
|
Configuration Guide</link>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Options containing secret data should be set to an attribute
|
Options containing secret data should be set to an attribute set
|
||||||
set containing the attribute <literal>_secret</literal> - a
|
containing the attribute <literal>_secret</literal> - a string
|
||||||
string pointing to a file containing the value the option
|
pointing to a file containing the value the option should be set
|
||||||
should be set to. See the description of <xref
|
to. See the description of
|
||||||
linkend="opt-services.keycloak.settings" /> for an example.
|
<xref linkend="opt-services.keycloak.settings" /> for an example.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<section xml:id="module-services-keycloak-example-config">
|
<section xml:id="module-services-keycloak-example-config">
|
||||||
<title>Example configuration</title>
|
<title>Example configuration</title>
|
||||||
<para>
|
<para>
|
||||||
A basic configuration with some custom settings could look like this:
|
A basic configuration with some custom settings could look like
|
||||||
|
this:
|
||||||
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.keycloak = {
|
services.keycloak = {
|
||||||
<link linkend="opt-services.keycloak.enable">enable</link> = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
<link linkend="opt-services.keycloak.settings.hostname">hostname</link> = "keycloak.example.com";
|
hostname = "keycloak.example.com";
|
||||||
<link linkend="opt-services.keycloak.settings.hostname-strict-backchannel">hostname-strict-backchannel</link> = true;
|
hostname-strict-backchannel = true;
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.keycloak.initialAdminPassword">initialAdminPassword</link> = "e6Wcm0RrtegMEHl"; # change on first login
|
initialAdminPassword = "e6Wcm0RrtegMEHl"; # change on first login
|
||||||
<link linkend="opt-services.keycloak.sslCertificate">sslCertificate</link> = "/run/keys/ssl_cert";
|
sslCertificate = "/run/keys/ssl_cert";
|
||||||
<link linkend="opt-services.keycloak.sslCertificateKey">sslCertificateKey</link> = "/run/keys/ssl_key";
|
sslCertificateKey = "/run/keys/ssl_key";
|
||||||
<link linkend="opt-services.keycloak.database.passwordFile">database.passwordFile</link> = "/run/keys/db_password";
|
database.passwordFile = "/run/keys/db_password";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -6,8 +6,6 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
meta.maintainers = with maintainers; [ happysalada ];
|
meta.maintainers = with maintainers; [ happysalada ];
|
||||||
# Don't edit the docbook xml directly, edit the md and generate it:
|
|
||||||
# `pandoc lemmy.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > lemmy.xml`
|
|
||||||
meta.doc = ./lemmy.xml;
|
meta.doc = ./lemmy.xml;
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-lemmy">
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-lemmy">
|
||||||
<title>Lemmy</title>
|
<title>Lemmy</title>
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -1,107 +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="module-services-matomo">
|
|
||||||
<title>Matomo</title>
|
|
||||||
<para>
|
|
||||||
Matomo is a real-time web analytics application. This module configures
|
|
||||||
php-fpm as backend for Matomo, optionally configuring an nginx vhost as well.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
An automatic setup is not suported by Matomo, so you need to configure Matomo
|
|
||||||
itself in the browser-based Matomo setup.
|
|
||||||
</para>
|
|
||||||
<section xml:id="module-services-matomo-database-setup">
|
|
||||||
<title>Database Setup</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You also need to configure a MariaDB or MySQL database and -user for Matomo
|
|
||||||
yourself, and enter those credentials in your browser. You can use
|
|
||||||
passwordless database authentication via the UNIX_SOCKET authentication
|
|
||||||
plugin with the following SQL commands:
|
|
||||||
<programlisting>
|
|
||||||
# For MariaDB
|
|
||||||
INSTALL PLUGIN unix_socket SONAME 'auth_socket';
|
|
||||||
CREATE DATABASE matomo;
|
|
||||||
CREATE USER 'matomo'@'localhost' IDENTIFIED WITH unix_socket;
|
|
||||||
GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
|
||||||
|
|
||||||
# For MySQL
|
|
||||||
INSTALL PLUGIN auth_socket SONAME 'auth_socket.so';
|
|
||||||
CREATE DATABASE matomo;
|
|
||||||
CREATE USER 'matomo'@'localhost' IDENTIFIED WITH auth_socket;
|
|
||||||
GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
|
||||||
</programlisting>
|
|
||||||
Then fill in <literal>matomo</literal> as database user and database name,
|
|
||||||
and leave the password field blank. This authentication works by allowing
|
|
||||||
only the <literal>matomo</literal> unix user to authenticate as the
|
|
||||||
<literal>matomo</literal> database user (without needing a password), but no
|
|
||||||
other users. For more information on passwordless login, see
|
|
||||||
<link xlink:href="https://mariadb.com/kb/en/mariadb/unix_socket-authentication-plugin/" />.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Of course, you can use password based authentication as well, e.g. when the
|
|
||||||
database is not on the same host.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-services-matomo-archive-processing">
|
|
||||||
<title>Archive Processing</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This module comes with the systemd service
|
|
||||||
<literal>matomo-archive-processing.service</literal> and a timer that
|
|
||||||
automatically triggers archive processing every hour. This means that you
|
|
||||||
can safely
|
|
||||||
<link xlink:href="https://matomo.org/docs/setup-auto-archiving/#disable-browser-triggers-for-matomo-archiving-and-limit-matomo-reports-to-updating-every-hour">
|
|
||||||
disable browser triggers for Matomo archiving </link> at
|
|
||||||
<literal>Administration > System > General Settings</literal>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
With automatic archive processing, you can now also enable to
|
|
||||||
<link xlink:href="https://matomo.org/docs/privacy/#step-2-delete-old-visitors-logs">
|
|
||||||
delete old visitor logs </link> at <literal>Administration > System >
|
|
||||||
Privacy</literal>, but make sure that you run <literal>systemctl start
|
|
||||||
matomo-archive-processing.service</literal> at least once without errors if
|
|
||||||
you have already collected data before, so that the reports get archived
|
|
||||||
before the source data gets deleted.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-services-matomo-backups">
|
|
||||||
<title>Backup</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You only need to take backups of your MySQL database and the
|
|
||||||
<filename>/var/lib/matomo/config/config.ini.php</filename> file. Use a user
|
|
||||||
in the <literal>matomo</literal> group or root to access the file. For more
|
|
||||||
information, see
|
|
||||||
<link xlink:href="https://matomo.org/faq/how-to-install/faq_138/" />.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-services-matomo-issues">
|
|
||||||
<title>Issues</title>
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Matomo will warn you that the JavaScript tracker is not writable. This is
|
|
||||||
because it's located in the read-only nix store. You can safely ignore
|
|
||||||
this, unless you need a plugin that needs JavaScript tracker access.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section xml:id="module-services-matomo-other-web-servers">
|
|
||||||
<title>Using other Web Servers than nginx</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You can use other web servers by forwarding calls for
|
|
||||||
<filename>index.php</filename> and <filename>piwik.php</filename> to the
|
|
||||||
<literal><link linkend="opt-services.phpfpm.pools._name_.socket">services.phpfpm.pools.<name>.socket</link></literal> fastcgi unix socket. You can use
|
|
||||||
the nginx configuration in the module code as a reference to what else
|
|
||||||
should be configured.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
77
nixos/modules/services/web-apps/matomo.md
Normal file
77
nixos/modules/services/web-apps/matomo.md
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# Matomo {#module-services-matomo}
|
||||||
|
|
||||||
|
Matomo is a real-time web analytics application. This module configures
|
||||||
|
php-fpm as backend for Matomo, optionally configuring an nginx vhost as well.
|
||||||
|
|
||||||
|
An automatic setup is not suported by Matomo, so you need to configure Matomo
|
||||||
|
itself in the browser-based Matomo setup.
|
||||||
|
|
||||||
|
## Database Setup {#module-services-matomo-database-setup}
|
||||||
|
|
||||||
|
You also need to configure a MariaDB or MySQL database and -user for Matomo
|
||||||
|
yourself, and enter those credentials in your browser. You can use
|
||||||
|
passwordless database authentication via the UNIX_SOCKET authentication
|
||||||
|
plugin with the following SQL commands:
|
||||||
|
```
|
||||||
|
# For MariaDB
|
||||||
|
INSTALL PLUGIN unix_socket SONAME 'auth_socket';
|
||||||
|
CREATE DATABASE matomo;
|
||||||
|
CREATE USER 'matomo'@'localhost' IDENTIFIED WITH unix_socket;
|
||||||
|
GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
||||||
|
|
||||||
|
# For MySQL
|
||||||
|
INSTALL PLUGIN auth_socket SONAME 'auth_socket.so';
|
||||||
|
CREATE DATABASE matomo;
|
||||||
|
CREATE USER 'matomo'@'localhost' IDENTIFIED WITH auth_socket;
|
||||||
|
GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
||||||
|
```
|
||||||
|
Then fill in `matomo` as database user and database name,
|
||||||
|
and leave the password field blank. This authentication works by allowing
|
||||||
|
only the `matomo` unix user to authenticate as the
|
||||||
|
`matomo` database user (without needing a password), but no
|
||||||
|
other users. For more information on passwordless login, see
|
||||||
|
<https://mariadb.com/kb/en/mariadb/unix_socket-authentication-plugin/>.
|
||||||
|
|
||||||
|
Of course, you can use password based authentication as well, e.g. when the
|
||||||
|
database is not on the same host.
|
||||||
|
|
||||||
|
## Archive Processing {#module-services-matomo-archive-processing}
|
||||||
|
|
||||||
|
This module comes with the systemd service
|
||||||
|
`matomo-archive-processing.service` and a timer that
|
||||||
|
automatically triggers archive processing every hour. This means that you
|
||||||
|
can safely
|
||||||
|
[disable browser triggers for Matomo archiving](
|
||||||
|
https://matomo.org/docs/setup-auto-archiving/#disable-browser-triggers-for-matomo-archiving-and-limit-matomo-reports-to-updating-every-hour
|
||||||
|
) at
|
||||||
|
`Administration > System > General Settings`.
|
||||||
|
|
||||||
|
With automatic archive processing, you can now also enable to
|
||||||
|
[delete old visitor logs](https://matomo.org/docs/privacy/#step-2-delete-old-visitors-logs)
|
||||||
|
at `Administration > System > Privacy`, but make sure that you run `systemctl start
|
||||||
|
matomo-archive-processing.service` at least once without errors if
|
||||||
|
you have already collected data before, so that the reports get archived
|
||||||
|
before the source data gets deleted.
|
||||||
|
|
||||||
|
## Backup {#module-services-matomo-backups}
|
||||||
|
|
||||||
|
You only need to take backups of your MySQL database and the
|
||||||
|
{file}`/var/lib/matomo/config/config.ini.php` file. Use a user
|
||||||
|
in the `matomo` group or root to access the file. For more
|
||||||
|
information, see
|
||||||
|
<https://matomo.org/faq/how-to-install/faq_138/>.
|
||||||
|
|
||||||
|
## Issues {#module-services-matomo-issues}
|
||||||
|
|
||||||
|
- Matomo will warn you that the JavaScript tracker is not writable. This is
|
||||||
|
because it's located in the read-only nix store. You can safely ignore
|
||||||
|
this, unless you need a plugin that needs JavaScript tracker access.
|
||||||
|
|
||||||
|
## Using other Web Servers than nginx {#module-services-matomo-other-web-servers}
|
||||||
|
|
||||||
|
You can use other web servers by forwarding calls for
|
||||||
|
{file}`index.php` and {file}`piwik.php` to the
|
||||||
|
[`services.phpfpm.pools.<name>.socket`](#opt-services.phpfpm.pools._name_.socket)
|
||||||
|
fastcgi unix socket. You can use
|
||||||
|
the nginx configuration in the module code as a reference to what else
|
||||||
|
should be configured.
|
|
@ -325,7 +325,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
doc = ./matomo-doc.xml;
|
doc = ./matomo.xml;
|
||||||
maintainers = with lib.maintainers; [ florianjacob ];
|
maintainers = with lib.maintainers; [ florianjacob ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
107
nixos/modules/services/web-apps/matomo.xml
Normal file
107
nixos/modules/services/web-apps/matomo.xml
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-matomo">
|
||||||
|
<title>Matomo</title>
|
||||||
|
<para>
|
||||||
|
Matomo is a real-time web analytics application. This module
|
||||||
|
configures php-fpm as backend for Matomo, optionally configuring an
|
||||||
|
nginx vhost as well.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
An automatic setup is not suported by Matomo, so you need to
|
||||||
|
configure Matomo itself in the browser-based Matomo setup.
|
||||||
|
</para>
|
||||||
|
<section xml:id="module-services-matomo-database-setup">
|
||||||
|
<title>Database Setup</title>
|
||||||
|
<para>
|
||||||
|
You also need to configure a MariaDB or MySQL database and -user
|
||||||
|
for Matomo yourself, and enter those credentials in your browser.
|
||||||
|
You can use passwordless database authentication via the
|
||||||
|
UNIX_SOCKET authentication plugin with the following SQL commands:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
# For MariaDB
|
||||||
|
INSTALL PLUGIN unix_socket SONAME 'auth_socket';
|
||||||
|
CREATE DATABASE matomo;
|
||||||
|
CREATE USER 'matomo'@'localhost' IDENTIFIED WITH unix_socket;
|
||||||
|
GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
||||||
|
|
||||||
|
# For MySQL
|
||||||
|
INSTALL PLUGIN auth_socket SONAME 'auth_socket.so';
|
||||||
|
CREATE DATABASE matomo;
|
||||||
|
CREATE USER 'matomo'@'localhost' IDENTIFIED WITH auth_socket;
|
||||||
|
GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Then fill in <literal>matomo</literal> as database user and
|
||||||
|
database name, and leave the password field blank. This
|
||||||
|
authentication works by allowing only the
|
||||||
|
<literal>matomo</literal> unix user to authenticate as the
|
||||||
|
<literal>matomo</literal> database user (without needing a
|
||||||
|
password), but no other users. For more information on
|
||||||
|
passwordless login, see
|
||||||
|
<link xlink:href="https://mariadb.com/kb/en/mariadb/unix_socket-authentication-plugin/">https://mariadb.com/kb/en/mariadb/unix_socket-authentication-plugin/</link>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Of course, you can use password based authentication as well, e.g.
|
||||||
|
when the database is not on the same host.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-matomo-archive-processing">
|
||||||
|
<title>Archive Processing</title>
|
||||||
|
<para>
|
||||||
|
This module comes with the systemd service
|
||||||
|
<literal>matomo-archive-processing.service</literal> and a timer
|
||||||
|
that automatically triggers archive processing every hour. This
|
||||||
|
means that you can safely
|
||||||
|
<link xlink:href="https://matomo.org/docs/setup-auto-archiving/#disable-browser-triggers-for-matomo-archiving-and-limit-matomo-reports-to-updating-every-hour">disable
|
||||||
|
browser triggers for Matomo archiving</link> at
|
||||||
|
<literal>Administration > System > General Settings</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
With automatic archive processing, you can now also enable to
|
||||||
|
<link xlink:href="https://matomo.org/docs/privacy/#step-2-delete-old-visitors-logs">delete
|
||||||
|
old visitor logs</link> at
|
||||||
|
<literal>Administration > System > Privacy</literal>, but
|
||||||
|
make sure that you run
|
||||||
|
<literal>systemctl start matomo-archive-processing.service</literal>
|
||||||
|
at least once without errors if you have already collected data
|
||||||
|
before, so that the reports get archived before the source data
|
||||||
|
gets deleted.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-matomo-backups">
|
||||||
|
<title>Backup</title>
|
||||||
|
<para>
|
||||||
|
You only need to take backups of your MySQL database and the
|
||||||
|
<filename>/var/lib/matomo/config/config.ini.php</filename> file.
|
||||||
|
Use a user in the <literal>matomo</literal> group or root to
|
||||||
|
access the file. For more information, see
|
||||||
|
<link xlink:href="https://matomo.org/faq/how-to-install/faq_138/">https://matomo.org/faq/how-to-install/faq_138/</link>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-matomo-issues">
|
||||||
|
<title>Issues</title>
|
||||||
|
<itemizedlist spacing="compact">
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Matomo will warn you that the JavaScript tracker is not
|
||||||
|
writable. This is because it’s located in the read-only nix
|
||||||
|
store. You can safely ignore this, unless you need a plugin
|
||||||
|
that needs JavaScript tracker access.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-matomo-other-web-servers">
|
||||||
|
<title>Using other Web Servers than nginx</title>
|
||||||
|
<para>
|
||||||
|
You can use other web servers by forwarding calls for
|
||||||
|
<filename>index.php</filename> and <filename>piwik.php</filename>
|
||||||
|
to the
|
||||||
|
<link linkend="opt-services.phpfpm.pools._name_.socket"><literal>services.phpfpm.pools.<name>.socket</literal></link>
|
||||||
|
fastcgi unix socket. You can use the nginx configuration in the
|
||||||
|
module code as a reference to what else should be configured.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
237
nixos/modules/services/web-apps/nextcloud.md
Normal file
237
nixos/modules/services/web-apps/nextcloud.md
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
# Nextcloud {#module-services-nextcloud}
|
||||||
|
|
||||||
|
[Nextcloud](https://nextcloud.com/) is an open-source,
|
||||||
|
self-hostable cloud platform. The server setup can be automated using
|
||||||
|
[services.nextcloud](#opt-services.nextcloud.enable). A
|
||||||
|
desktop client is packaged at `pkgs.nextcloud-client`.
|
||||||
|
|
||||||
|
The current default by NixOS is `nextcloud25` which is also the latest
|
||||||
|
major version available.
|
||||||
|
|
||||||
|
## Basic usage {#module-services-nextcloud-basic-usage}
|
||||||
|
|
||||||
|
Nextcloud is a PHP-based application which requires an HTTP server
|
||||||
|
([`services.nextcloud`](#opt-services.nextcloud.enable)
|
||||||
|
optionally supports
|
||||||
|
[`services.nginx`](#opt-services.nginx.enable))
|
||||||
|
and a database (it's recommended to use
|
||||||
|
[`services.postgresql`](#opt-services.postgresql.enable)).
|
||||||
|
|
||||||
|
A very basic configuration may look like this:
|
||||||
|
```
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
services.nextcloud = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "nextcloud.tld";
|
||||||
|
config = {
|
||||||
|
dbtype = "pgsql";
|
||||||
|
dbuser = "nextcloud";
|
||||||
|
dbhost = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself
|
||||||
|
dbname = "nextcloud";
|
||||||
|
adminpassFile = "/path/to/admin-pass-file";
|
||||||
|
adminuser = "root";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = [ "nextcloud" ];
|
||||||
|
ensureUsers = [
|
||||||
|
{ name = "nextcloud";
|
||||||
|
ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# ensure that postgres is running *before* running the setup
|
||||||
|
systemd.services."nextcloud-setup" = {
|
||||||
|
requires = ["postgresql.service"];
|
||||||
|
after = ["postgresql.service"];
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `hostName` option is used internally to configure an HTTP
|
||||||
|
server using [`PHP-FPM`](https://php-fpm.org/)
|
||||||
|
and `nginx`. The `config` attribute set is
|
||||||
|
used by the imperative installer and all values are written to an additional file
|
||||||
|
to ensure that changes can be applied by changing the module's options.
|
||||||
|
|
||||||
|
In case the application serves multiple domains (those are checked with
|
||||||
|
[`$_SERVER['HTTP_HOST']`](http://php.net/manual/en/reserved.variables.server.php))
|
||||||
|
it's needed to add them to
|
||||||
|
[`services.nextcloud.config.extraTrustedDomains`](#opt-services.nextcloud.config.extraTrustedDomains).
|
||||||
|
|
||||||
|
Auto updates for Nextcloud apps can be enabled using
|
||||||
|
[`services.nextcloud.autoUpdateApps`](#opt-services.nextcloud.autoUpdateApps.enable).
|
||||||
|
|
||||||
|
## Common problems {#module-services-nextcloud-pitfalls-during-upgrade}
|
||||||
|
|
||||||
|
- **General notes.**
|
||||||
|
Unfortunately Nextcloud appears to be very stateful when it comes to
|
||||||
|
managing its own configuration. The config file lives in the home directory
|
||||||
|
of the `nextcloud` user (by default
|
||||||
|
`/var/lib/nextcloud/config/config.php`) and is also used to
|
||||||
|
track several states of the application (e.g., whether installed or not).
|
||||||
|
|
||||||
|
All configuration parameters are also stored in
|
||||||
|
{file}`/var/lib/nextcloud/config/override.config.php` which is generated by
|
||||||
|
the module and linked from the store to ensure that all values from
|
||||||
|
{file}`config.php` can be modified by the module.
|
||||||
|
However {file}`config.php` manages the application's state and shouldn't be
|
||||||
|
touched manually because of that.
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
Don't delete {file}`config.php`! This file
|
||||||
|
tracks the application's state and a deletion can cause unwanted
|
||||||
|
side-effects!
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
Don't rerun `nextcloud-occ maintenance:install`!
|
||||||
|
This command tries to install the application
|
||||||
|
and can cause unwanted side-effects!
|
||||||
|
:::
|
||||||
|
- **Multiple version upgrades.**
|
||||||
|
Nextcloud doesn't allow to move more than one major-version forward. E.g., if you're on
|
||||||
|
`v16`, you cannot upgrade to `v18`, you need to upgrade to
|
||||||
|
`v17` first. This is ensured automatically as long as the
|
||||||
|
[stateVersion](#opt-system.stateVersion) is declared properly. In that case
|
||||||
|
the oldest version available (one major behind the one from the previous NixOS
|
||||||
|
release) will be selected by default and the module will generate a warning that reminds
|
||||||
|
the user to upgrade to latest Nextcloud *after* that deploy.
|
||||||
|
- **`Error: Command "upgrade" is not defined.`**
|
||||||
|
This error usually occurs if the initial installation
|
||||||
|
({command}`nextcloud-occ maintenance:install`) has failed. After that, the application
|
||||||
|
is not installed, but the upgrade is attempted to be executed. Further context can
|
||||||
|
be found in [NixOS/nixpkgs#111175](https://github.com/NixOS/nixpkgs/issues/111175).
|
||||||
|
|
||||||
|
First of all, it makes sense to find out what went wrong by looking at the logs
|
||||||
|
of the installation via {command}`journalctl -u nextcloud-setup` and try to fix
|
||||||
|
the underlying issue.
|
||||||
|
|
||||||
|
- If this occurs on an *existing* setup, this is most likely because
|
||||||
|
the maintenance mode is active. It can be deactivated by running
|
||||||
|
{command}`nextcloud-occ maintenance:mode --off`. It's advisable though to
|
||||||
|
check the logs first on why the maintenance mode was activated.
|
||||||
|
- ::: {.warning}
|
||||||
|
Only perform the following measures on
|
||||||
|
*freshly installed instances!*
|
||||||
|
:::
|
||||||
|
|
||||||
|
A re-run of the installer can be forced by *deleting*
|
||||||
|
{file}`/var/lib/nextcloud/config/config.php`. This is the only time
|
||||||
|
advisable because the fresh install doesn't have any state that can be lost.
|
||||||
|
In case that doesn't help, an entire re-creation can be forced via
|
||||||
|
{command}`rm -rf ~nextcloud/`.
|
||||||
|
|
||||||
|
- **Server-side encryption.**
|
||||||
|
Nextcloud supports [server-side encryption (SSE)](https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html).
|
||||||
|
This is not an end-to-end encryption, but can be used to encrypt files that will be persisted
|
||||||
|
to external storage such as S3. Please note that this won't work anymore when using OpenSSL 3
|
||||||
|
for PHP's openssl extension because this is implemented using the legacy cipher RC4.
|
||||||
|
If [](#opt-system.stateVersion) is *above* `22.05`,
|
||||||
|
this is disabled by default. To turn it on again and for further information please refer to
|
||||||
|
[](#opt-services.nextcloud.enableBrokenCiphersForSSE).
|
||||||
|
|
||||||
|
## Using an alternative webserver as reverse-proxy (e.g. `httpd`) {#module-services-nextcloud-httpd}
|
||||||
|
|
||||||
|
By default, `nginx` is used as reverse-proxy for `nextcloud`.
|
||||||
|
However, it's possible to use e.g. `httpd` by explicitly disabling
|
||||||
|
`nginx` using [](#opt-services.nginx.enable) and fixing the
|
||||||
|
settings `listen.owner` & `listen.group` in the
|
||||||
|
[corresponding `phpfpm` pool](#opt-services.phpfpm.pools).
|
||||||
|
|
||||||
|
An exemplary configuration may look like this:
|
||||||
|
```
|
||||||
|
{ config, lib, pkgs, ... }: {
|
||||||
|
services.nginx.enable = false;
|
||||||
|
services.nextcloud = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "localhost";
|
||||||
|
|
||||||
|
/* further, required options */
|
||||||
|
};
|
||||||
|
services.phpfpm.pools.nextcloud.settings = {
|
||||||
|
"listen.owner" = config.services.httpd.user;
|
||||||
|
"listen.group" = config.services.httpd.group;
|
||||||
|
};
|
||||||
|
services.httpd = {
|
||||||
|
enable = true;
|
||||||
|
adminAddr = "webmaster@localhost";
|
||||||
|
extraModules = [ "proxy_fcgi" ];
|
||||||
|
virtualHosts."localhost" = {
|
||||||
|
documentRoot = config.services.nextcloud.package;
|
||||||
|
extraConfig = ''
|
||||||
|
<Directory "${config.services.nextcloud.package}">
|
||||||
|
<FilesMatch "\.php$">
|
||||||
|
<If "-f %{REQUEST_FILENAME}">
|
||||||
|
SetHandler "proxy:unix:${config.services.phpfpm.pools.nextcloud.socket}|fcgi://localhost/"
|
||||||
|
</If>
|
||||||
|
</FilesMatch>
|
||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteBase /
|
||||||
|
RewriteRule ^index\.php$ - [L]
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteRule . /index.php [L]
|
||||||
|
</IfModule>
|
||||||
|
DirectoryIndex index.php
|
||||||
|
Require all granted
|
||||||
|
Options +FollowSymLinks
|
||||||
|
</Directory>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installing Apps and PHP extensions {#installing-apps-php-extensions-nextcloud}
|
||||||
|
|
||||||
|
Nextcloud apps are installed statefully through the web interface.
|
||||||
|
Some apps may require extra PHP extensions to be installed.
|
||||||
|
This can be configured with the [](#opt-services.nextcloud.phpExtraExtensions) setting.
|
||||||
|
|
||||||
|
Alternatively, extra apps can also be declared with the [](#opt-services.nextcloud.extraApps) setting.
|
||||||
|
When using this setting, apps can no longer be managed statefully because this can lead to Nextcloud updating apps
|
||||||
|
that are managed by Nix. If you want automatic updates it is recommended that you use web interface to install apps.
|
||||||
|
|
||||||
|
## Maintainer information {#module-services-nextcloud-maintainer-info}
|
||||||
|
|
||||||
|
As stated in the previous paragraph, we must provide a clean upgrade-path for Nextcloud
|
||||||
|
since it cannot move more than one major version forward on a single upgrade. This chapter
|
||||||
|
adds some notes how Nextcloud updates should be rolled out in the future.
|
||||||
|
|
||||||
|
While minor and patch-level updates are no problem and can be done directly in the
|
||||||
|
package-expression (and should be backported to supported stable branches after that),
|
||||||
|
major-releases should be added in a new attribute (e.g. Nextcloud `v19.0.0`
|
||||||
|
should be available in `nixpkgs` as `pkgs.nextcloud19`).
|
||||||
|
To provide simple upgrade paths it's generally useful to backport those as well to stable
|
||||||
|
branches. As long as the package-default isn't altered, this won't break existing setups.
|
||||||
|
After that, the versioning-warning in the `nextcloud`-module should be
|
||||||
|
updated to make sure that the
|
||||||
|
[package](#opt-services.nextcloud.package)-option selects the latest version
|
||||||
|
on fresh setups.
|
||||||
|
|
||||||
|
If major-releases will be abandoned by upstream, we should check first if those are needed
|
||||||
|
in NixOS for a safe upgrade-path before removing those. In that case we should keep those
|
||||||
|
packages, but mark them as insecure in an expression like this (in
|
||||||
|
`<nixpkgs/pkgs/servers/nextcloud/default.nix>`):
|
||||||
|
```
|
||||||
|
/* ... */
|
||||||
|
{
|
||||||
|
nextcloud17 = generic {
|
||||||
|
version = "17.0.x";
|
||||||
|
sha256 = "0000000000000000000000000000000000000000000000000000";
|
||||||
|
eol = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ideally we should make sure that it's possible to jump two NixOS versions forward:
|
||||||
|
i.e. the warnings and the logic in the module should guard a user to upgrade from a
|
||||||
|
Nextcloud on e.g. 19.09 to a Nextcloud on 20.09.
|
|
@ -1,226 +1,249 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-nextcloud">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-nextcloud">
|
|
||||||
<title>Nextcloud</title>
|
<title>Nextcloud</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://nextcloud.com/">Nextcloud</link> is an open-source,
|
<link xlink:href="https://nextcloud.com/">Nextcloud</link> is an
|
||||||
self-hostable cloud platform. The server setup can be automated using
|
open-source, self-hostable cloud platform. The server setup can be
|
||||||
<link linkend="opt-services.nextcloud.enable">services.nextcloud</link>. A
|
automated using
|
||||||
desktop client is packaged at <literal>pkgs.nextcloud-client</literal>.
|
<link linkend="opt-services.nextcloud.enable">services.nextcloud</link>.
|
||||||
|
A desktop client is packaged at
|
||||||
|
<literal>pkgs.nextcloud-client</literal>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The current default by NixOS is <package>nextcloud25</package> which is also the latest
|
The current default by NixOS is <literal>nextcloud25</literal> which
|
||||||
major version available.
|
is also the latest major version available.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-nextcloud-basic-usage">
|
<section xml:id="module-services-nextcloud-basic-usage">
|
||||||
<title>Basic usage</title>
|
<title>Basic usage</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Nextcloud is a PHP-based application which requires an HTTP server
|
Nextcloud is a PHP-based application which requires an HTTP server
|
||||||
(<literal><link linkend="opt-services.nextcloud.enable">services.nextcloud</link></literal>
|
(<link linkend="opt-services.nextcloud.enable"><literal>services.nextcloud</literal></link>
|
||||||
optionally supports
|
optionally supports
|
||||||
<literal><link linkend="opt-services.nginx.enable">services.nginx</link></literal>)
|
<link linkend="opt-services.nginx.enable"><literal>services.nginx</literal></link>)
|
||||||
and a database (it's recommended to use
|
and a database (it’s recommended to use
|
||||||
<literal><link linkend="opt-services.postgresql.enable">services.postgresql</link></literal>).
|
<link linkend="opt-services.postgresql.enable"><literal>services.postgresql</literal></link>).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A very basic configuration may look like this:
|
A very basic configuration may look like this:
|
||||||
<programlisting>{ pkgs, ... }:
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
<link linkend="opt-services.nextcloud.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.nextcloud.hostName">hostName</link> = "nextcloud.tld";
|
hostName = "nextcloud.tld";
|
||||||
config = {
|
config = {
|
||||||
<link linkend="opt-services.nextcloud.config.dbtype">dbtype</link> = "pgsql";
|
dbtype = "pgsql";
|
||||||
<link linkend="opt-services.nextcloud.config.dbuser">dbuser</link> = "nextcloud";
|
dbuser = "nextcloud";
|
||||||
<link linkend="opt-services.nextcloud.config.dbhost">dbhost</link> = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself
|
dbhost = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself
|
||||||
<link linkend="opt-services.nextcloud.config.dbname">dbname</link> = "nextcloud";
|
dbname = "nextcloud";
|
||||||
<link linkend="opt-services.nextcloud.config.adminpassFile">adminpassFile</link> = "/path/to/admin-pass-file";
|
adminpassFile = "/path/to/admin-pass-file";
|
||||||
<link linkend="opt-services.nextcloud.config.adminuser">adminuser</link> = "root";
|
adminuser = "root";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.postgresql = {
|
services.postgresql = {
|
||||||
<link linkend="opt-services.postgresql.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.postgresql.ensureDatabases">ensureDatabases</link> = [ "nextcloud" ];
|
ensureDatabases = [ "nextcloud" ];
|
||||||
<link linkend="opt-services.postgresql.ensureUsers">ensureUsers</link> = [
|
ensureUsers = [
|
||||||
{ name = "nextcloud";
|
{ name = "nextcloud";
|
||||||
ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES";
|
ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# ensure that postgres is running *before* running the setup
|
# ensure that postgres is running *before* running the setup
|
||||||
systemd.services."nextcloud-setup" = {
|
systemd.services."nextcloud-setup" = {
|
||||||
requires = ["postgresql.service"];
|
requires = ["postgresql.service"];
|
||||||
after = ["postgresql.service"];
|
after = ["postgresql.service"];
|
||||||
};
|
};
|
||||||
|
|
||||||
<link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <literal>hostName</literal> option is used internally to configure an HTTP
|
The <literal>hostName</literal> option is used internally to
|
||||||
server using <literal><link xlink:href="https://php-fpm.org/">PHP-FPM</link></literal>
|
configure an HTTP server using
|
||||||
and <literal>nginx</literal>. The <literal>config</literal> attribute set is
|
<link xlink:href="https://php-fpm.org/"><literal>PHP-FPM</literal></link>
|
||||||
used by the imperative installer and all values are written to an additional file
|
and <literal>nginx</literal>. The <literal>config</literal>
|
||||||
to ensure that changes can be applied by changing the module's options.
|
attribute set is used by the imperative installer and all values
|
||||||
|
are written to an additional file to ensure that changes can be
|
||||||
|
applied by changing the module’s options.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
In case the application serves multiple domains (those are checked with
|
In case the application serves multiple domains (those are checked
|
||||||
<literal><link xlink:href="http://php.net/manual/en/reserved.variables.server.php">$_SERVER['HTTP_HOST']</link></literal>)
|
with
|
||||||
it's needed to add them to
|
<link xlink:href="http://php.net/manual/en/reserved.variables.server.php"><literal>$_SERVER['HTTP_HOST']</literal></link>)
|
||||||
<literal><link linkend="opt-services.nextcloud.config.extraTrustedDomains">services.nextcloud.config.extraTrustedDomains</link></literal>.
|
it’s needed to add them to
|
||||||
|
<link linkend="opt-services.nextcloud.config.extraTrustedDomains"><literal>services.nextcloud.config.extraTrustedDomains</literal></link>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Auto updates for Nextcloud apps can be enabled using
|
Auto updates for Nextcloud apps can be enabled using
|
||||||
<literal><link linkend="opt-services.nextcloud.autoUpdateApps.enable">services.nextcloud.autoUpdateApps</link></literal>.
|
<link linkend="opt-services.nextcloud.autoUpdateApps.enable"><literal>services.nextcloud.autoUpdateApps</literal></link>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-nextcloud-pitfalls-during-upgrade">
|
<section xml:id="module-services-nextcloud-pitfalls-during-upgrade">
|
||||||
<title>Common problems</title>
|
<title>Common problems</title>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<formalpara>
|
|
||||||
<title>General notes</title>
|
|
||||||
<para>
|
<para>
|
||||||
Unfortunately Nextcloud appears to be very stateful when it comes to
|
<emphasis role="strong">General notes.</emphasis>
|
||||||
managing its own configuration. The config file lives in the home directory
|
Unfortunately Nextcloud appears to be very stateful when it
|
||||||
of the <literal>nextcloud</literal> user (by default
|
comes to managing its own configuration. The config file lives
|
||||||
<literal>/var/lib/nextcloud/config/config.php</literal>) and is also used to
|
in the home directory of the <literal>nextcloud</literal> user
|
||||||
track several states of the application (e.g., whether installed or not).
|
(by default
|
||||||
|
<literal>/var/lib/nextcloud/config/config.php</literal>) and
|
||||||
|
is also used to track several states of the application (e.g.,
|
||||||
|
whether installed or not).
|
||||||
</para>
|
</para>
|
||||||
</formalpara>
|
|
||||||
<para>
|
<para>
|
||||||
All configuration parameters are also stored in
|
All configuration parameters are also stored in
|
||||||
<filename>/var/lib/nextcloud/config/override.config.php</filename> which is generated by
|
<filename>/var/lib/nextcloud/config/override.config.php</filename>
|
||||||
the module and linked from the store to ensure that all values from
|
which is generated by the module and linked from the store to
|
||||||
<filename>config.php</filename> can be modified by the module.
|
ensure that all values from <filename>config.php</filename>
|
||||||
However <filename>config.php</filename> manages the application's state and shouldn't be
|
can be modified by the module. However
|
||||||
touched manually because of that.
|
<filename>config.php</filename> manages the application’s
|
||||||
|
state and shouldn’t be touched manually because of that.
|
||||||
</para>
|
</para>
|
||||||
<warning>
|
<warning>
|
||||||
<para>Don't delete <filename>config.php</filename>! This file
|
<para>
|
||||||
tracks the application's state and a deletion can cause unwanted
|
Don’t delete <filename>config.php</filename>! This file
|
||||||
side-effects!</para>
|
tracks the application’s state and a deletion can cause
|
||||||
|
unwanted side-effects!
|
||||||
|
</para>
|
||||||
</warning>
|
</warning>
|
||||||
|
|
||||||
<warning>
|
<warning>
|
||||||
<para>Don't rerun <literal>nextcloud-occ
|
<para>
|
||||||
maintenance:install</literal>! This command tries to install the application
|
Don’t rerun
|
||||||
and can cause unwanted side-effects!</para>
|
<literal>nextcloud-occ maintenance:install</literal>! This
|
||||||
|
command tries to install the application and can cause
|
||||||
|
unwanted side-effects!
|
||||||
|
</para>
|
||||||
</warning>
|
</warning>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<formalpara>
|
|
||||||
<title>Multiple version upgrades</title>
|
|
||||||
<para>
|
<para>
|
||||||
Nextcloud doesn't allow to move more than one major-version forward. E.g., if you're on
|
<emphasis role="strong">Multiple version upgrades.</emphasis>
|
||||||
<literal>v16</literal>, you cannot upgrade to <literal>v18</literal>, you need to upgrade to
|
Nextcloud doesn’t allow to move more than one major-version
|
||||||
<literal>v17</literal> first. This is ensured automatically as long as the
|
forward. E.g., if you’re on <literal>v16</literal>, you cannot
|
||||||
<link linkend="opt-system.stateVersion">stateVersion</link> is declared properly. In that case
|
upgrade to <literal>v18</literal>, you need to upgrade to
|
||||||
the oldest version available (one major behind the one from the previous NixOS
|
<literal>v17</literal> first. This is ensured automatically as
|
||||||
release) will be selected by default and the module will generate a warning that reminds
|
long as the
|
||||||
the user to upgrade to latest Nextcloud <emphasis>after</emphasis> that deploy.
|
<link linkend="opt-system.stateVersion">stateVersion</link> is
|
||||||
|
declared properly. In that case the oldest version available
|
||||||
|
(one major behind the one from the previous NixOS release)
|
||||||
|
will be selected by default and the module will generate a
|
||||||
|
warning that reminds the user to upgrade to latest Nextcloud
|
||||||
|
<emphasis>after</emphasis> that deploy.
|
||||||
</para>
|
</para>
|
||||||
</formalpara>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<formalpara>
|
|
||||||
<title><literal>Error: Command "upgrade" is not defined.</literal></title>
|
|
||||||
<para>
|
<para>
|
||||||
|
<emphasis role="strong"><literal>Error: Command "upgrade" is not defined.</literal></emphasis>
|
||||||
This error usually occurs if the initial installation
|
This error usually occurs if the initial installation
|
||||||
(<command>nextcloud-occ maintenance:install</command>) has failed. After that, the application
|
(<command>nextcloud-occ maintenance:install</command>) has
|
||||||
is not installed, but the upgrade is attempted to be executed. Further context can
|
failed. After that, the application is not installed, but the
|
||||||
be found in <link xlink:href="https://github.com/NixOS/nixpkgs/issues/111175">NixOS/nixpkgs#111175</link>.
|
upgrade is attempted to be executed. Further context can be
|
||||||
|
found in
|
||||||
|
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/111175">NixOS/nixpkgs#111175</link>.
|
||||||
</para>
|
</para>
|
||||||
</formalpara>
|
|
||||||
<para>
|
<para>
|
||||||
First of all, it makes sense to find out what went wrong by looking at the logs
|
First of all, it makes sense to find out what went wrong by
|
||||||
of the installation via <command>journalctl -u nextcloud-setup</command> and try to fix
|
looking at the logs of the installation via
|
||||||
the underlying issue.
|
<command>journalctl -u nextcloud-setup</command> and try to
|
||||||
|
fix the underlying issue.
|
||||||
</para>
|
</para>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
If this occurs on an <emphasis>existing</emphasis> setup, this is most likely because
|
If this occurs on an <emphasis>existing</emphasis> setup,
|
||||||
the maintenance mode is active. It can be deactivated by running
|
this is most likely because the maintenance mode is
|
||||||
<command>nextcloud-occ maintenance:mode --off</command>. It's advisable though to
|
active. It can be deactivated by running
|
||||||
check the logs first on why the maintenance mode was activated.
|
<command>nextcloud-occ maintenance:mode --off</command>.
|
||||||
|
It’s advisable though to check the logs first on why the
|
||||||
|
maintenance mode was activated.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<warning><para>Only perform the following measures on
|
<warning>
|
||||||
<emphasis>freshly installed instances!</emphasis></para></warning>
|
|
||||||
<para>
|
<para>
|
||||||
A re-run of the installer can be forced by <emphasis>deleting</emphasis>
|
Only perform the following measures on <emphasis>freshly
|
||||||
<filename>/var/lib/nextcloud/config/config.php</filename>. This is the only time
|
installed instances!</emphasis>
|
||||||
advisable because the fresh install doesn't have any state that can be lost.
|
</para>
|
||||||
In case that doesn't help, an entire re-creation can be forced via
|
</warning>
|
||||||
|
<para>
|
||||||
|
A re-run of the installer can be forced by
|
||||||
|
<emphasis>deleting</emphasis>
|
||||||
|
<filename>/var/lib/nextcloud/config/config.php</filename>.
|
||||||
|
This is the only time advisable because the fresh install
|
||||||
|
doesn’t have any state that can be lost. In case that
|
||||||
|
doesn’t help, an entire re-creation can be forced via
|
||||||
<command>rm -rf ~nextcloud/</command>.
|
<command>rm -rf ~nextcloud/</command>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<formalpara>
|
|
||||||
<title>Server-side encryption</title>
|
|
||||||
<para>
|
<para>
|
||||||
Nextcloud supports <link xlink:href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html">server-side encryption (SSE)</link>.
|
<emphasis role="strong">Server-side encryption.</emphasis>
|
||||||
This is not an end-to-end encryption, but can be used to encrypt files that will be persisted
|
Nextcloud supports
|
||||||
to external storage such as S3. Please note that this won't work anymore when using OpenSSL 3
|
<link xlink:href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html">server-side
|
||||||
for PHP's openssl extension because this is implemented using the legacy cipher RC4.
|
encryption (SSE)</link>. This is not an end-to-end encryption,
|
||||||
If <xref linkend="opt-system.stateVersion" /> is <emphasis>above</emphasis> <literal>22.05</literal>,
|
but can be used to encrypt files that will be persisted to
|
||||||
this is disabled by default. To turn it on again and for further information please refer to
|
external storage such as S3. Please note that this won’t work
|
||||||
|
anymore when using OpenSSL 3 for PHP’s openssl extension
|
||||||
|
because this is implemented using the legacy cipher RC4. If
|
||||||
|
<xref linkend="opt-system.stateVersion" /> is
|
||||||
|
<emphasis>above</emphasis> <literal>22.05</literal>, this is
|
||||||
|
disabled by default. To turn it on again and for further
|
||||||
|
information please refer to
|
||||||
<xref linkend="opt-services.nextcloud.enableBrokenCiphersForSSE" />.
|
<xref linkend="opt-services.nextcloud.enableBrokenCiphersForSSE" />.
|
||||||
</para>
|
</para>
|
||||||
</formalpara>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-nextcloud-httpd">
|
<section xml:id="module-services-nextcloud-httpd">
|
||||||
<title>Using an alternative webserver as reverse-proxy (e.g. <literal>httpd</literal>)</title>
|
<title>Using an alternative webserver as reverse-proxy (e.g.
|
||||||
|
<literal>httpd</literal>)</title>
|
||||||
<para>
|
<para>
|
||||||
By default, <package>nginx</package> is used as reverse-proxy for <package>nextcloud</package>.
|
By default, <literal>nginx</literal> is used as reverse-proxy for
|
||||||
However, it's possible to use e.g. <package>httpd</package> by explicitly disabling
|
<literal>nextcloud</literal>. However, it’s possible to use e.g.
|
||||||
<package>nginx</package> using <xref linkend="opt-services.nginx.enable" /> and fixing the
|
<literal>httpd</literal> by explicitly disabling
|
||||||
settings <literal>listen.owner</literal> & <literal>listen.group</literal> in the
|
<literal>nginx</literal> using
|
||||||
<link linkend="opt-services.phpfpm.pools">corresponding <literal>phpfpm</literal> pool</link>.
|
<xref linkend="opt-services.nginx.enable" /> and fixing the
|
||||||
|
settings <literal>listen.owner</literal> &
|
||||||
|
<literal>listen.group</literal> in the
|
||||||
|
<link linkend="opt-services.phpfpm.pools">corresponding
|
||||||
|
<literal>phpfpm</literal> pool</link>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
An exemplary configuration may look like this:
|
An exemplary configuration may look like this:
|
||||||
<programlisting>{ config, lib, pkgs, ... }: {
|
</para>
|
||||||
<link linkend="opt-services.nginx.enable">services.nginx.enable</link> = false;
|
<programlisting>
|
||||||
|
{ config, lib, pkgs, ... }: {
|
||||||
|
services.nginx.enable = false;
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
<link linkend="opt-services.nextcloud.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.nextcloud.hostName">hostName</link> = "localhost";
|
hostName = "localhost";
|
||||||
|
|
||||||
/* further, required options */
|
/* further, required options */
|
||||||
};
|
};
|
||||||
<link linkend="opt-services.phpfpm.pools._name_.settings">services.phpfpm.pools.nextcloud.settings</link> = {
|
services.phpfpm.pools.nextcloud.settings = {
|
||||||
"listen.owner" = config.services.httpd.user;
|
"listen.owner" = config.services.httpd.user;
|
||||||
"listen.group" = config.services.httpd.group;
|
"listen.group" = config.services.httpd.group;
|
||||||
};
|
};
|
||||||
services.httpd = {
|
services.httpd = {
|
||||||
<link linkend="opt-services.httpd.enable">enable</link> = true;
|
enable = true;
|
||||||
<link linkend="opt-services.httpd.adminAddr">adminAddr</link> = "webmaster@localhost";
|
adminAddr = "webmaster@localhost";
|
||||||
<link linkend="opt-services.httpd.extraModules">extraModules</link> = [ "proxy_fcgi" ];
|
extraModules = [ "proxy_fcgi" ];
|
||||||
virtualHosts."localhost" = {
|
virtualHosts."localhost" = {
|
||||||
<link linkend="opt-services.httpd.virtualHosts._name_.documentRoot">documentRoot</link> = config.services.nextcloud.package;
|
documentRoot = config.services.nextcloud.package;
|
||||||
<link linkend="opt-services.httpd.virtualHosts._name_.extraConfig">extraConfig</link> = ''
|
extraConfig = ''
|
||||||
<Directory "${config.services.nextcloud.package}">
|
<Directory "${config.services.nextcloud.package}">
|
||||||
<FilesMatch "\.php$">
|
<FilesMatch "\.php$">
|
||||||
<If "-f %{REQUEST_FILENAME}">
|
<If "-f %{REQUEST_FILENAME}">
|
||||||
SetHandler "proxy:unix:${config.services.phpfpm.pools.nextcloud.socket}|fcgi://localhost/"
|
SetHandler "proxy:unix:${config.services.phpfpm.pools.nextcloud.socket}|fcgi://localhost/"
|
||||||
</If>
|
</If>
|
||||||
</FilesMatch>
|
</FilesMatch>
|
||||||
<IfModule mod_rewrite.c>
|
<IfModule mod_rewrite.c>
|
||||||
|
@ -238,68 +261,73 @@
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="installing-apps-php-extensions-nextcloud">
|
<section xml:id="installing-apps-php-extensions-nextcloud">
|
||||||
<title>Installing Apps and PHP extensions</title>
|
<title>Installing Apps and PHP extensions</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Nextcloud apps are installed statefully through the web interface.
|
Nextcloud apps are installed statefully through the web interface.
|
||||||
|
Some apps may require extra PHP extensions to be installed. This
|
||||||
Some apps may require extra PHP extensions to be installed.
|
can be configured with the
|
||||||
This can be configured with the <xref linkend="opt-services.nextcloud.phpExtraExtensions" /> setting.
|
<xref linkend="opt-services.nextcloud.phpExtraExtensions" />
|
||||||
|
setting.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Alternatively, extra apps can also be declared with the <xref linkend="opt-services.nextcloud.extraApps" /> setting.
|
Alternatively, extra apps can also be declared with the
|
||||||
When using this setting, apps can no longer be managed statefully because this can lead to Nextcloud updating apps
|
<xref linkend="opt-services.nextcloud.extraApps" /> setting. When
|
||||||
that are managed by Nix. If you want automatic updates it is recommended that you use web interface to install apps.
|
using this setting, apps can no longer be managed statefully
|
||||||
|
because this can lead to Nextcloud updating apps that are managed
|
||||||
|
by Nix. If you want automatic updates it is recommended that you
|
||||||
|
use web interface to install apps.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="module-services-nextcloud-maintainer-info">
|
<section xml:id="module-services-nextcloud-maintainer-info">
|
||||||
<title>Maintainer information</title>
|
<title>Maintainer information</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
As stated in the previous paragraph, we must provide a clean upgrade-path for Nextcloud
|
As stated in the previous paragraph, we must provide a clean
|
||||||
since it cannot move more than one major version forward on a single upgrade. This chapter
|
upgrade-path for Nextcloud since it cannot move more than one
|
||||||
adds some notes how Nextcloud updates should be rolled out in the future.
|
major version forward on a single upgrade. This chapter adds some
|
||||||
|
notes how Nextcloud updates should be rolled out in the future.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
While minor and patch-level updates are no problem and can be done directly in the
|
While minor and patch-level updates are no problem and can be done
|
||||||
package-expression (and should be backported to supported stable branches after that),
|
directly in the package-expression (and should be backported to
|
||||||
major-releases should be added in a new attribute (e.g. Nextcloud <literal>v19.0.0</literal>
|
supported stable branches after that), major-releases should be
|
||||||
should be available in <literal>nixpkgs</literal> as <literal>pkgs.nextcloud19</literal>).
|
added in a new attribute (e.g. Nextcloud
|
||||||
To provide simple upgrade paths it's generally useful to backport those as well to stable
|
<literal>v19.0.0</literal> should be available in
|
||||||
branches. As long as the package-default isn't altered, this won't break existing setups.
|
<literal>nixpkgs</literal> as
|
||||||
After that, the versioning-warning in the <literal>nextcloud</literal>-module should be
|
<literal>pkgs.nextcloud19</literal>). To provide simple upgrade
|
||||||
updated to make sure that the
|
paths it’s generally useful to backport those as well to stable
|
||||||
<link linkend="opt-services.nextcloud.package">package</link>-option selects the latest version
|
branches. As long as the package-default isn’t altered, this won’t
|
||||||
on fresh setups.
|
break existing setups. After that, the versioning-warning in the
|
||||||
|
<literal>nextcloud</literal>-module should be updated to make sure
|
||||||
|
that the
|
||||||
|
<link linkend="opt-services.nextcloud.package">package</link>-option
|
||||||
|
selects the latest version on fresh setups.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If major-releases will be abandoned by upstream, we should check first if those are needed
|
If major-releases will be abandoned by upstream, we should check
|
||||||
in NixOS for a safe upgrade-path before removing those. In that case we should keep those
|
first if those are needed in NixOS for a safe upgrade-path before
|
||||||
packages, but mark them as insecure in an expression like this (in
|
removing those. In that case we should keep those packages, but
|
||||||
|
mark them as insecure in an expression like this (in
|
||||||
<literal><nixpkgs/pkgs/servers/nextcloud/default.nix></literal>):
|
<literal><nixpkgs/pkgs/servers/nextcloud/default.nix></literal>):
|
||||||
<programlisting>/* ... */
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
/* ... */
|
||||||
{
|
{
|
||||||
nextcloud17 = generic {
|
nextcloud17 = generic {
|
||||||
version = "17.0.x";
|
version = "17.0.x";
|
||||||
sha256 = "0000000000000000000000000000000000000000000000000000";
|
sha256 = "0000000000000000000000000000000000000000000000000000";
|
||||||
eol = true;
|
eol = true;
|
||||||
};
|
};
|
||||||
}</programlisting>
|
}
|
||||||
</para>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Ideally we should make sure that it's possible to jump two NixOS versions forward:
|
Ideally we should make sure that it’s possible to jump two NixOS
|
||||||
i.e. the warnings and the logic in the module should guard a user to upgrade from a
|
versions forward: i.e. the warnings and the logic in the module
|
||||||
Nextcloud on e.g. 19.09 to a Nextcloud on 20.09.
|
should guard a user to upgrade from a Nextcloud on e.g. 19.09 to a
|
||||||
|
Nextcloud on 20.09.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -15,6 +15,7 @@ this will start the http server on port 8080 by default.
|
||||||
## Usage {#module-services-pict-rs-usage}
|
## Usage {#module-services-pict-rs-usage}
|
||||||
|
|
||||||
pict-rs offers the following endpoints:
|
pict-rs offers the following endpoints:
|
||||||
|
|
||||||
- `POST /image` for uploading an image. Uploaded content must be valid multipart/form-data with an
|
- `POST /image` for uploading an image. Uploaded content must be valid multipart/form-data with an
|
||||||
image array located within the `images[]` key
|
image array located within the `images[]` key
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
meta.maintainers = with maintainers; [ happysalada ];
|
meta.maintainers = with maintainers; [ happysalada ];
|
||||||
# Don't edit the docbook xml directly, edit the md and generate it:
|
|
||||||
# `pandoc pict-rs.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > pict-rs.xml`
|
|
||||||
meta.doc = ./pict-rs.xml;
|
meta.doc = ./pict-rs.xml;
|
||||||
|
|
||||||
options.services.pict-rs = {
|
options.services.pict-rs = {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-pict-rs">
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-pict-rs">
|
||||||
<title>Pict-rs</title>
|
<title>Pict-rs</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -8,7 +10,7 @@
|
||||||
<para>
|
<para>
|
||||||
the minimum to start pict-rs is
|
the minimum to start pict-rs is
|
||||||
</para>
|
</para>
|
||||||
<programlisting language="bash">
|
<programlisting language="nix">
|
||||||
services.pict-rs.enable = true;
|
services.pict-rs.enable = true;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
|
@ -18,14 +20,20 @@ services.pict-rs.enable = true;
|
||||||
<section xml:id="module-services-pict-rs-usage">
|
<section xml:id="module-services-pict-rs-usage">
|
||||||
<title>Usage</title>
|
<title>Usage</title>
|
||||||
<para>
|
<para>
|
||||||
pict-rs offers the following endpoints: -
|
pict-rs offers the following endpoints:
|
||||||
<literal>POST /image</literal> for uploading an image. Uploaded
|
|
||||||
content must be valid multipart/form-data with an image array
|
|
||||||
located within the <literal>images[]</literal> key
|
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<itemizedlist>
|
||||||
This endpoint returns the following JSON structure on success with a 201 Created status
|
<listitem>
|
||||||
```json
|
<para>
|
||||||
|
<literal>POST /image</literal> for uploading an image.
|
||||||
|
Uploaded content must be valid multipart/form-data with an
|
||||||
|
image array located within the <literal>images[]</literal> key
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This endpoint returns the following JSON structure on success
|
||||||
|
with a 201 Created status
|
||||||
|
</para>
|
||||||
|
<programlisting language="json">
|
||||||
{
|
{
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
|
@ -43,9 +51,8 @@ This endpoint returns the following JSON structure on success with a 201 Created
|
||||||
],
|
],
|
||||||
"msg": "ok"
|
"msg": "ok"
|
||||||
}
|
}
|
||||||
```
|
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<itemizedlist>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<literal>GET /image/download?url=...</literal> Download an
|
<literal>GET /image/download?url=...</literal> Download an
|
||||||
|
@ -66,8 +73,20 @@ This endpoint returns the following JSON structure on success with a 201 Created
|
||||||
<literal>GET /image/details/original/{file}</literal> for
|
<literal>GET /image/details/original/{file}</literal> for
|
||||||
getting the details of a full-resolution image. The returned
|
getting the details of a full-resolution image. The returned
|
||||||
JSON is structured like so:
|
JSON is structured like so:
|
||||||
<literal>json { "width": 800, "height": 537, "content_type": "image/webp", "created_at": [ 2020, 345, 67376, 394363487 ] }</literal>
|
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting language="json">
|
||||||
|
{
|
||||||
|
"width": 800,
|
||||||
|
"height": 537,
|
||||||
|
"content_type": "image/webp",
|
||||||
|
"created_at": [
|
||||||
|
2020,
|
||||||
|
345,
|
||||||
|
67376,
|
||||||
|
394363487
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
|
@ -124,7 +143,11 @@ This endpoint returns the following JSON structure on success with a 201 Created
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
An example of usage could be
|
An example of usage could be
|
||||||
<literal>GET /image/process.jpg?src=asdf.png&thumbnail=256&blur=3.0</literal>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
GET /image/process.jpg?src=asdf.png&thumbnail=256&blur=3.0
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
which would create a 256x256px JPEG thumbnail and blur it
|
which would create a 256x256px JPEG thumbnail and blur it
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
35
nixos/modules/services/web-apps/plausible.md
Normal file
35
nixos/modules/services/web-apps/plausible.md
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# Plausible {#module-services-plausible}
|
||||||
|
|
||||||
|
[Plausible](https://plausible.io/) is a privacy-friendly alternative to
|
||||||
|
Google analytics.
|
||||||
|
|
||||||
|
## Basic Usage {#module-services-plausible-basic-usage}
|
||||||
|
|
||||||
|
At first, a secret key is needed to be generated. This can be done with e.g.
|
||||||
|
```ShellSession
|
||||||
|
$ openssl rand -base64 64
|
||||||
|
```
|
||||||
|
|
||||||
|
After that, `plausible` can be deployed like this:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
services.plausible = {
|
||||||
|
enable = true;
|
||||||
|
adminUser = {
|
||||||
|
# activate is used to skip the email verification of the admin-user that's
|
||||||
|
# automatically created by plausible. This is only supported if
|
||||||
|
# postgresql is configured by the module. This is done by default, but
|
||||||
|
# can be turned off with services.plausible.database.postgres.setup.
|
||||||
|
activate = true;
|
||||||
|
email = "admin@localhost";
|
||||||
|
passwordFile = "/run/secrets/plausible-admin-pwd";
|
||||||
|
};
|
||||||
|
server = {
|
||||||
|
baseUrl = "http://analytics.example.org";
|
||||||
|
# secretKeybaseFile is a path to the file which contains the secret generated
|
||||||
|
# with openssl as described above.
|
||||||
|
secretKeybaseFile = "/run/secrets/plausible-secret-key-base";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
|
@ -1,51 +1,45 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
<!-- Do not edit this file directly, edit its companion .md instead
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
and regenerate this file using nixos/doc/manual/md-to-db.sh -->
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-plausible">
|
||||||
version="5.0"
|
|
||||||
xml:id="module-services-plausible">
|
|
||||||
<title>Plausible</title>
|
<title>Plausible</title>
|
||||||
<para>
|
<para>
|
||||||
<link xlink:href="https://plausible.io/">Plausible</link> is a privacy-friendly alternative to
|
<link xlink:href="https://plausible.io/">Plausible</link> is a
|
||||||
Google analytics.
|
privacy-friendly alternative to Google analytics.
|
||||||
</para>
|
</para>
|
||||||
<section xml:id="module-services-plausible-basic-usage">
|
<section xml:id="module-services-plausible-basic-usage">
|
||||||
<title>Basic Usage</title>
|
<title>Basic Usage</title>
|
||||||
<para>
|
<para>
|
||||||
At first, a secret key is needed to be generated. This can be done with e.g.
|
At first, a secret key is needed to be generated. This can be done
|
||||||
<screen><prompt>$ </prompt>openssl rand -base64 64</screen>
|
with e.g.
|
||||||
</para>
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ openssl rand -base64 64
|
||||||
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
After that, <package>plausible</package> can be deployed like this:
|
After that, <literal>plausible</literal> can be deployed like
|
||||||
<programlisting>{
|
this:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
{
|
||||||
services.plausible = {
|
services.plausible = {
|
||||||
<link linkend="opt-services.plausible.enable">enable</link> = true;
|
enable = true;
|
||||||
adminUser = {
|
adminUser = {
|
||||||
<link linkend="opt-services.plausible.adminUser.activate">activate</link> = true; <co xml:id='ex-plausible-cfg-activate' />
|
# activate is used to skip the email verification of the admin-user that's
|
||||||
<link linkend="opt-services.plausible.adminUser.email">email</link> = "admin@localhost";
|
# automatically created by plausible. This is only supported if
|
||||||
<link linkend="opt-services.plausible.adminUser.passwordFile">passwordFile</link> = "/run/secrets/plausible-admin-pwd";
|
# postgresql is configured by the module. This is done by default, but
|
||||||
|
# can be turned off with services.plausible.database.postgres.setup.
|
||||||
|
activate = true;
|
||||||
|
email = "admin@localhost";
|
||||||
|
passwordFile = "/run/secrets/plausible-admin-pwd";
|
||||||
};
|
};
|
||||||
server = {
|
server = {
|
||||||
<link linkend="opt-services.plausible.server.baseUrl">baseUrl</link> = "http://analytics.example.org";
|
baseUrl = "http://analytics.example.org";
|
||||||
<link linkend="opt-services.plausible.server.secretKeybaseFile">secretKeybaseFile</link> = "/run/secrets/plausible-secret-key-base"; <co xml:id='ex-plausible-cfg-secretbase' />
|
# secretKeybaseFile is a path to the file which contains the secret generated
|
||||||
|
# with openssl as described above.
|
||||||
|
secretKeybaseFile = "/run/secrets/plausible-secret-key-base";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}</programlisting>
|
}
|
||||||
<calloutlist>
|
</programlisting>
|
||||||
<callout arearefs='ex-plausible-cfg-activate'>
|
|
||||||
<para>
|
|
||||||
<varname>activate</varname> is used to skip the email verification of the admin-user that's
|
|
||||||
automatically created by <package>plausible</package>. This is only supported if
|
|
||||||
<package>postgresql</package> is configured by the module. This is done by default, but
|
|
||||||
can be turned off with <xref linkend="opt-services.plausible.database.postgres.setup" />.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs='ex-plausible-cfg-secretbase'>
|
|
||||||
<para>
|
|
||||||
<varname>secretKeybaseFile</varname> is a path to the file which contains the secret generated
|
|
||||||
with <package>openssl</package> as described above.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
</calloutlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -1,139 +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="module-services-garage">
|
|
||||||
<title>Garage</title>
|
|
||||||
<para>
|
|
||||||
<link xlink:href="https://garagehq.deuxfleurs.fr/">Garage</link>
|
|
||||||
is an open-source, self-hostable S3 store, simpler than MinIO, for geodistributed stores.
|
|
||||||
The server setup can be automated using
|
|
||||||
<link linkend="opt-services.garage.enable">services.garage</link>. A
|
|
||||||
client configured to your local Garage instance is available in
|
|
||||||
the global environment as <literal>garage-manage</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The current default by NixOS is <package>garage_0_8</package> which is also the latest
|
|
||||||
major version available.
|
|
||||||
</para>
|
|
||||||
<section xml:id="module-services-garage-upgrade-scenarios">
|
|
||||||
<title>General considerations on upgrades</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Garage provides a cookbook documentation on how to upgrade:
|
|
||||||
<link xlink:href="https://garagehq.deuxfleurs.fr/documentation/cookbook/upgrading/">https://garagehq.deuxfleurs.fr/documentation/cookbook/upgrading/</link>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<warning>
|
|
||||||
<para>Garage has two types of upgrades: patch-level upgrades and minor/major version upgrades.</para>
|
|
||||||
|
|
||||||
<para>In all cases, you should read the changelog and ideally test the upgrade on a staging cluster.</para>
|
|
||||||
|
|
||||||
<para>Checking the health of your cluster can be achieved using <literal>garage-manage repair</literal>.</para>
|
|
||||||
</warning>
|
|
||||||
|
|
||||||
|
|
||||||
<warning>
|
|
||||||
<para>Until 1.0 is released, patch-level upgrades are considered as minor version upgrades.
|
|
||||||
Minor version upgrades are considered as major version upgrades.
|
|
||||||
i.e. 0.6 to 0.7 is a major version upgrade.</para>
|
|
||||||
</warning>
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<formalpara>
|
|
||||||
<title>Straightforward upgrades (patch-level upgrades)</title>
|
|
||||||
<para>
|
|
||||||
Upgrades must be performed one by one, i.e. for each node, stop it, upgrade it : change <link linkend="opt-system.stateVersion">stateVersion</link> or <link linkend="opt-services.garage.package">services.garage.package</link>, restart it if it was not already by switching.
|
|
||||||
</para>
|
|
||||||
</formalpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<formalpara>
|
|
||||||
<title>Multiple version upgrades</title>
|
|
||||||
<para>
|
|
||||||
Garage do not provide any guarantee on moving more than one major-version forward.
|
|
||||||
E.g., if you're on <literal>0.7</literal>, you cannot upgrade to <literal>0.9</literal>.
|
|
||||||
You need to upgrade to <literal>0.8</literal> first.
|
|
||||||
|
|
||||||
As long as <link linkend="opt-system.stateVersion">stateVersion</link> is declared properly,
|
|
||||||
this is enforced automatically. The module will issue a warning to remind the user to upgrade to latest
|
|
||||||
Garage <emphasis>after</emphasis> that deploy.
|
|
||||||
</para>
|
|
||||||
</formalpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section xml:id="module-services-garage-advanced-upgrades">
|
|
||||||
<title>Advanced upgrades (minor/major version upgrades)</title>
|
|
||||||
<para>Here are some baseline instructions to handle advanced upgrades in Garage, when in doubt, please refer to upstream instructions.</para>
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem><para>Disable API and web access to Garage.</para></listitem>
|
|
||||||
<listitem><para>Perform <literal>garage-manage repair --all-nodes --yes tables</literal> and <literal>garage-manage repair --all-nodes --yes blocks</literal>.</para></listitem>
|
|
||||||
<listitem><para>Verify the resulting logs and check that data is synced properly between all nodes.
|
|
||||||
If you have time, do additional checks (<literal>scrub</literal>, <literal>block_refs</literal>, etc.).</para></listitem>
|
|
||||||
<listitem><para>Check if queues are empty by <literal>garage-manage stats</literal> or through monitoring tools.</para></listitem>
|
|
||||||
<listitem><para>Run <literal>systemctl stop garage</literal> to stop the actual Garage version.</para></listitem>
|
|
||||||
<listitem><para>Backup the metadata folder of ALL your nodes, e.g. for a metadata directory (the default one) in <literal>/var/lib/garage/meta</literal>,
|
|
||||||
you can run <literal>pushd /var/lib/garage; tar -acf meta-v0.7.tar.zst meta/; popd</literal>.</para></listitem>
|
|
||||||
<listitem><para>Run the offline migration: <literal>nix-shell -p garage_0_8 --run "garage offline-repair --yes"</literal>, this can take some time depending on how many objects are stored in your cluster.</para></listitem>
|
|
||||||
<listitem><para>Bump Garage version in your NixOS configuration, either by changing <link linkend="opt-system.stateVersion">stateVersion</link> or bumping <link linkend="opt-services.garage.package">services.garage.package</link>, this should restart Garage automatically.</para></listitem>
|
|
||||||
<listitem><para>Perform <literal>garage-manage repair --all-nodes --yes tables</literal> and <literal>garage-manage repair --all-nodes --yes blocks</literal>.</para></listitem>
|
|
||||||
<listitem><para>Wait for a full table sync to run.</para></listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Your upgraded cluster should be in a working state, re-enable API and web access.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section xml:id="module-services-garage-maintainer-info">
|
|
||||||
<title>Maintainer information</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
As stated in the previous paragraph, we must provide a clean upgrade-path for Garage
|
|
||||||
since it cannot move more than one major version forward on a single upgrade. This chapter
|
|
||||||
adds some notes how Garage updates should be rolled out in the future.
|
|
||||||
|
|
||||||
This is inspired from how Nextcloud does it.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
While patch-level updates are no problem and can be done directly in the
|
|
||||||
package-expression (and should be backported to supported stable branches after that),
|
|
||||||
major-releases should be added in a new attribute (e.g. Garage <literal>v0.8.0</literal>
|
|
||||||
should be available in <literal>nixpkgs</literal> as <literal>pkgs.garage_0_8_0</literal>).
|
|
||||||
To provide simple upgrade paths it's generally useful to backport those as well to stable
|
|
||||||
branches. As long as the package-default isn't altered, this won't break existing setups.
|
|
||||||
After that, the versioning-warning in the <literal>garage</literal>-module should be
|
|
||||||
updated to make sure that the
|
|
||||||
<link linkend="opt-services.garage.package">package</link>-option selects the latest version
|
|
||||||
on fresh setups.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If major-releases will be abandoned by upstream, we should check first if those are needed
|
|
||||||
in NixOS for a safe upgrade-path before removing those. In that case we shold keep those
|
|
||||||
packages, but mark them as insecure in an expression like this (in
|
|
||||||
<literal><nixpkgs/pkgs/tools/filesystem/garage/default.nix></literal>):
|
|
||||||
<programlisting>/* ... */
|
|
||||||
{
|
|
||||||
garage_0_7_3 = generic {
|
|
||||||
version = "0.7.3";
|
|
||||||
sha256 = "0000000000000000000000000000000000000000000000000000";
|
|
||||||
eol = true;
|
|
||||||
};
|
|
||||||
}</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Ideally we should make sure that it's possible to jump two NixOS versions forward:
|
|
||||||
i.e. the warnings and the logic in the module should guard a user to upgrade from a
|
|
||||||
Garage on e.g. 22.11 to a Garage on 23.11.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</chapter>
|
|
96
nixos/modules/services/web-servers/garage.md
Normal file
96
nixos/modules/services/web-servers/garage.md
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# Garage {#module-services-garage}
|
||||||
|
|
||||||
|
[Garage](https://garagehq.deuxfleurs.fr/)
|
||||||
|
is an open-source, self-hostable S3 store, simpler than MinIO, for geodistributed stores.
|
||||||
|
The server setup can be automated using
|
||||||
|
[services.garage](#opt-services.garage.enable). A
|
||||||
|
client configured to your local Garage instance is available in
|
||||||
|
the global environment as `garage-manage`.
|
||||||
|
|
||||||
|
The current default by NixOS is `garage_0_8` which is also the latest
|
||||||
|
major version available.
|
||||||
|
|
||||||
|
## General considerations on upgrades {#module-services-garage-upgrade-scenarios}
|
||||||
|
|
||||||
|
Garage provides a cookbook documentation on how to upgrade:
|
||||||
|
<https://garagehq.deuxfleurs.fr/documentation/cookbook/upgrading/>
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
Garage has two types of upgrades: patch-level upgrades and minor/major version upgrades.
|
||||||
|
|
||||||
|
In all cases, you should read the changelog and ideally test the upgrade on a staging cluster.
|
||||||
|
|
||||||
|
Checking the health of your cluster can be achieved using `garage-manage repair`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: {.warning}
|
||||||
|
Until 1.0 is released, patch-level upgrades are considered as minor version upgrades.
|
||||||
|
Minor version upgrades are considered as major version upgrades.
|
||||||
|
i.e. 0.6 to 0.7 is a major version upgrade.
|
||||||
|
:::
|
||||||
|
|
||||||
|
- **Straightforward upgrades (patch-level upgrades).**
|
||||||
|
Upgrades must be performed one by one, i.e. for each node, stop it, upgrade it : change [stateVersion](#opt-system.stateVersion) or [services.garage.package](#opt-services.garage.package), restart it if it was not already by switching.
|
||||||
|
- **Multiple version upgrades.**
|
||||||
|
Garage do not provide any guarantee on moving more than one major-version forward.
|
||||||
|
E.g., if you're on `0.7`, you cannot upgrade to `0.9`.
|
||||||
|
You need to upgrade to `0.8` first.
|
||||||
|
As long as [stateVersion](#opt-system.stateVersion) is declared properly,
|
||||||
|
this is enforced automatically. The module will issue a warning to remind the user to upgrade to latest
|
||||||
|
Garage *after* that deploy.
|
||||||
|
|
||||||
|
## Advanced upgrades (minor/major version upgrades) {#module-services-garage-advanced-upgrades}
|
||||||
|
|
||||||
|
Here are some baseline instructions to handle advanced upgrades in Garage, when in doubt, please refer to upstream instructions.
|
||||||
|
|
||||||
|
- Disable API and web access to Garage.
|
||||||
|
- Perform `garage-manage repair --all-nodes --yes tables` and `garage-manage repair --all-nodes --yes blocks`.
|
||||||
|
- Verify the resulting logs and check that data is synced properly between all nodes.
|
||||||
|
If you have time, do additional checks (`scrub`, `block_refs`, etc.).
|
||||||
|
- Check if queues are empty by `garage-manage stats` or through monitoring tools.
|
||||||
|
- Run `systemctl stop garage` to stop the actual Garage version.
|
||||||
|
- Backup the metadata folder of ALL your nodes, e.g. for a metadata directory (the default one) in `/var/lib/garage/meta`,
|
||||||
|
you can run `pushd /var/lib/garage; tar -acf meta-v0.7.tar.zst meta/; popd`.
|
||||||
|
- Run the offline migration: `nix-shell -p garage_0_8 --run "garage offline-repair --yes"`, this can take some time depending on how many objects are stored in your cluster.
|
||||||
|
- Bump Garage version in your NixOS configuration, either by changing [stateVersion](#opt-system.stateVersion) or bumping [services.garage.package](#opt-services.garage.package), this should restart Garage automatically.
|
||||||
|
- Perform `garage-manage repair --all-nodes --yes tables` and `garage-manage repair --all-nodes --yes blocks`.
|
||||||
|
- Wait for a full table sync to run.
|
||||||
|
|
||||||
|
Your upgraded cluster should be in a working state, re-enable API and web access.
|
||||||
|
|
||||||
|
## Maintainer information {#module-services-garage-maintainer-info}
|
||||||
|
|
||||||
|
As stated in the previous paragraph, we must provide a clean upgrade-path for Garage
|
||||||
|
since it cannot move more than one major version forward on a single upgrade. This chapter
|
||||||
|
adds some notes how Garage updates should be rolled out in the future.
|
||||||
|
This is inspired from how Nextcloud does it.
|
||||||
|
|
||||||
|
While patch-level updates are no problem and can be done directly in the
|
||||||
|
package-expression (and should be backported to supported stable branches after that),
|
||||||
|
major-releases should be added in a new attribute (e.g. Garage `v0.8.0`
|
||||||
|
should be available in `nixpkgs` as `pkgs.garage_0_8_0`).
|
||||||
|
To provide simple upgrade paths it's generally useful to backport those as well to stable
|
||||||
|
branches. As long as the package-default isn't altered, this won't break existing setups.
|
||||||
|
After that, the versioning-warning in the `garage`-module should be
|
||||||
|
updated to make sure that the
|
||||||
|
[package](#opt-services.garage.package)-option selects the latest version
|
||||||
|
on fresh setups.
|
||||||
|
|
||||||
|
If major-releases will be abandoned by upstream, we should check first if those are needed
|
||||||
|
in NixOS for a safe upgrade-path before removing those. In that case we shold keep those
|
||||||
|
packages, but mark them as insecure in an expression like this (in
|
||||||
|
`<nixpkgs/pkgs/tools/filesystem/garage/default.nix>`):
|
||||||
|
```
|
||||||
|
/* ... */
|
||||||
|
{
|
||||||
|
garage_0_7_3 = generic {
|
||||||
|
version = "0.7.3";
|
||||||
|
sha256 = "0000000000000000000000000000000000000000000000000000";
|
||||||
|
eol = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ideally we should make sure that it's possible to jump two NixOS versions forward:
|
||||||
|
i.e. the warnings and the logic in the module should guard a user to upgrade from a
|
||||||
|
Garage on e.g. 22.11 to a Garage on 23.11.
|
|
@ -9,7 +9,7 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
meta = {
|
meta = {
|
||||||
doc = ./garage-doc.xml;
|
doc = ./garage.xml;
|
||||||
maintainers = with pkgs.lib.maintainers; [ raitobezarius ];
|
maintainers = with pkgs.lib.maintainers; [ raitobezarius ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue