mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-13 13:40:28 +03:00
treewide: Fix all Nix ASTs in all markdown files
This allows for correct highlighting and maybe future automatic formatting. The AST was verified to work with nixfmt only.
This commit is contained in:
parent
bc77c7a973
commit
fcc95ff817
150 changed files with 2896 additions and 2087 deletions
|
@ -21,8 +21,10 @@ You can tell NixOS in `configuration.nix` to run this unit automatically
|
|||
at certain points in time, for instance, every night at 03:15:
|
||||
|
||||
```nix
|
||||
nix.gc.automatic = true;
|
||||
nix.gc.dates = "03:15";
|
||||
{
|
||||
nix.gc.automatic = true;
|
||||
nix.gc.dates = "03:15";
|
||||
}
|
||||
```
|
||||
|
||||
The commands above do not remove garbage collector roots, such as old
|
||||
|
|
|
@ -26,9 +26,11 @@ host to rewrite container traffic to use your external IP address. This
|
|||
can be accomplished using the following configuration on the host:
|
||||
|
||||
```nix
|
||||
networking.nat.enable = true;
|
||||
networking.nat.internalInterfaces = ["ve-+"];
|
||||
networking.nat.externalInterface = "eth0";
|
||||
{
|
||||
networking.nat.enable = true;
|
||||
networking.nat.internalInterfaces = ["ve-+"];
|
||||
networking.nat.externalInterface = "eth0";
|
||||
}
|
||||
```
|
||||
|
||||
where `eth0` should be replaced with the desired external interface.
|
||||
|
@ -38,7 +40,9 @@ If you are using Network Manager, you need to explicitly prevent it from
|
|||
managing container interfaces:
|
||||
|
||||
```nix
|
||||
networking.networkmanager.unmanaged = [ "interface-name:ve-*" ];
|
||||
{
|
||||
networking.networkmanager.unmanaged = [ "interface-name:ve-*" ];
|
||||
}
|
||||
```
|
||||
|
||||
You may need to restart your system for the changes to take effect.
|
||||
|
|
|
@ -39,7 +39,9 @@ they were in the same cgroup, then the PostgreSQL process would get
|
|||
`configuration.nix`:
|
||||
|
||||
```nix
|
||||
systemd.services.httpd.serviceConfig.CPUShares = 512;
|
||||
{
|
||||
systemd.services.httpd.serviceConfig.CPUShares = 512;
|
||||
}
|
||||
```
|
||||
|
||||
By default, every cgroup has 1024 CPU shares, so this will halve the CPU
|
||||
|
@ -52,7 +54,9 @@ limits can be specified in `configuration.nix`; for instance, to limit
|
|||
`httpd.service` to 512 MiB of RAM (excluding swap):
|
||||
|
||||
```nix
|
||||
systemd.services.httpd.serviceConfig.MemoryLimit = "512M";
|
||||
{
|
||||
systemd.services.httpd.serviceConfig.MemoryLimit = "512M";
|
||||
}
|
||||
```
|
||||
|
||||
The command `systemd-cgtop` shows a continuously updated list of all
|
||||
|
|
|
@ -5,13 +5,15 @@ You can also specify containers and their configuration in the host's
|
|||
shall be a container named `database` running PostgreSQL:
|
||||
|
||||
```nix
|
||||
containers.database =
|
||||
{ config =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql_14;
|
||||
};
|
||||
};
|
||||
{
|
||||
containers.database =
|
||||
{ config =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql_14;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
If you run `nixos-rebuild switch`, the container will be built. If the
|
||||
|
@ -25,11 +27,13 @@ cannot change the network configuration. You can give a container its
|
|||
own network as follows:
|
||||
|
||||
```nix
|
||||
containers.database = {
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.10";
|
||||
localAddress = "192.168.100.11";
|
||||
};
|
||||
{
|
||||
containers.database = {
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.10";
|
||||
localAddress = "192.168.100.11";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This gives the container a private virtual Ethernet interface with IP
|
||||
|
|
|
@ -82,7 +82,9 @@ In order to enable a systemd *system* service with provided upstream
|
|||
package, use (e.g):
|
||||
|
||||
```nix
|
||||
systemd.packages = [ pkgs.packagekit ];
|
||||
{
|
||||
systemd.packages = [ pkgs.packagekit ];
|
||||
}
|
||||
```
|
||||
|
||||
Usually NixOS modules written by the community do the above, plus take
|
||||
|
|
|
@ -47,9 +47,9 @@ You can write a `let` wherever an expression is allowed. Thus, you also could ha
|
|||
```nix
|
||||
{
|
||||
services.httpd.virtualHosts =
|
||||
let commonConfig = ...; in
|
||||
{ "blog.example.org" = (commonConfig // { ... })
|
||||
"wiki.example.org" = (commonConfig // { ... })
|
||||
let commonConfig = { /* ... */ }; in
|
||||
{ "blog.example.org" = (commonConfig // { /* ... */ });
|
||||
"wiki.example.org" = (commonConfig // { /* ... */ });
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -6,8 +6,10 @@ is useful for doing network configuration not covered by the existing NixOS
|
|||
modules. For instance, to statically configure an IPv6 address:
|
||||
|
||||
```nix
|
||||
networking.localCommands =
|
||||
''
|
||||
ip -6 addr add 2001:610:685:1::1/64 dev eth0
|
||||
'';
|
||||
{
|
||||
networking.localCommands =
|
||||
''
|
||||
ip -6 addr add 2001:610:685:1::1/64 dev eth0
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
|
|
@ -23,7 +23,9 @@ Then you write and test the package as described in the Nixpkgs manual.
|
|||
Finally, you add it to [](#opt-environment.systemPackages), e.g.
|
||||
|
||||
```nix
|
||||
environment.systemPackages = [ pkgs.my-package ];
|
||||
{
|
||||
environment.systemPackages = [ pkgs.my-package ];
|
||||
}
|
||||
```
|
||||
|
||||
and you run `nixos-rebuild`, specifying your own Nixpkgs tree:
|
||||
|
@ -38,24 +40,28 @@ tree. For instance, here is how you specify a build of the
|
|||
`configuration.nix`:
|
||||
|
||||
```nix
|
||||
environment.systemPackages =
|
||||
let
|
||||
my-hello = with pkgs; stdenv.mkDerivation rec {
|
||||
name = "hello-2.8";
|
||||
src = fetchurl {
|
||||
url = "mirror://gnu/hello/${name}.tar.gz";
|
||||
hash = "sha256-5rd/gffPfa761Kn1tl3myunD8TuM+66oy1O7XqVGDXM=";
|
||||
{
|
||||
environment.systemPackages =
|
||||
let
|
||||
my-hello = with pkgs; stdenv.mkDerivation rec {
|
||||
name = "hello-2.8";
|
||||
src = fetchurl {
|
||||
url = "mirror://gnu/hello/${name}.tar.gz";
|
||||
hash = "sha256-5rd/gffPfa761Kn1tl3myunD8TuM+66oy1O7XqVGDXM=";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
[ my-hello ];
|
||||
in
|
||||
[ my-hello ];
|
||||
}
|
||||
```
|
||||
|
||||
Of course, you can also move the definition of `my-hello` into a
|
||||
separate Nix expression, e.g.
|
||||
|
||||
```nix
|
||||
environment.systemPackages = [ (import ./my-hello.nix) ];
|
||||
{
|
||||
environment.systemPackages = [ (import ./my-hello.nix) ];
|
||||
}
|
||||
```
|
||||
|
||||
where `my-hello.nix` contains:
|
||||
|
@ -88,7 +94,9 @@ section](#module-services-flatpak). AppImages will not run "as-is" on NixOS.
|
|||
First you need to install `appimage-run`: add to `/etc/nixos/configuration.nix`
|
||||
|
||||
```nix
|
||||
environment.systemPackages = [ pkgs.appimage-run ];
|
||||
{
|
||||
environment.systemPackages = [ pkgs.appimage-run ];
|
||||
}
|
||||
```
|
||||
|
||||
Then instead of running the AppImage "as-is", run `appimage-run foo.appimage`.
|
||||
|
|
|
@ -5,7 +5,7 @@ The NixOS configuration file generally looks like this:
|
|||
```nix
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{ option definitions
|
||||
{ /* option definitions */
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -80,7 +80,9 @@ Strings
|
|||
: Strings are enclosed in double quotes, e.g.
|
||||
|
||||
```nix
|
||||
networking.hostName = "dexter";
|
||||
{
|
||||
networking.hostName = "dexter";
|
||||
}
|
||||
```
|
||||
|
||||
Special characters can be escaped by prefixing them with a backslash
|
||||
|
@ -89,11 +91,13 @@ Strings
|
|||
Multi-line strings can be enclosed in *double single quotes*, e.g.
|
||||
|
||||
```nix
|
||||
networking.extraHosts =
|
||||
''
|
||||
127.0.0.2 other-localhost
|
||||
10.0.0.1 server
|
||||
'';
|
||||
{
|
||||
networking.extraHosts =
|
||||
''
|
||||
127.0.0.2 other-localhost
|
||||
10.0.0.1 server
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
The main difference is that it strips from each line a number of
|
||||
|
@ -108,8 +112,10 @@ Booleans
|
|||
: These can be `true` or `false`, e.g.
|
||||
|
||||
```nix
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowPing = false;
|
||||
{
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowPing = false;
|
||||
}
|
||||
```
|
||||
|
||||
Integers
|
||||
|
@ -117,7 +123,9 @@ Integers
|
|||
: For example,
|
||||
|
||||
```nix
|
||||
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60;
|
||||
{
|
||||
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60;
|
||||
}
|
||||
```
|
||||
|
||||
(Note that here the attribute name `net.ipv4.tcp_keepalive_time` is
|
||||
|
@ -132,11 +140,13 @@ Sets
|
|||
braces, as in the option definition
|
||||
|
||||
```nix
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/sda1";
|
||||
fsType = "ext4";
|
||||
options = [ "rw" "data=ordered" "relatime" ];
|
||||
};
|
||||
{
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/sda1";
|
||||
fsType = "ext4";
|
||||
options = [ "rw" "data=ordered" "relatime" ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Lists
|
||||
|
@ -145,13 +155,17 @@ Lists
|
|||
separated by whitespace, like this:
|
||||
|
||||
```nix
|
||||
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
|
||||
{
|
||||
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
|
||||
}
|
||||
```
|
||||
|
||||
List elements can be any other type, e.g. sets:
|
||||
|
||||
```nix
|
||||
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
|
||||
{
|
||||
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
|
||||
}
|
||||
```
|
||||
|
||||
Packages
|
||||
|
@ -161,12 +175,14 @@ Packages
|
|||
argument `pkgs`. Typical uses:
|
||||
|
||||
```nix
|
||||
environment.systemPackages =
|
||||
[ pkgs.thunderbird
|
||||
pkgs.emacs
|
||||
];
|
||||
{
|
||||
environment.systemPackages =
|
||||
[ pkgs.thunderbird
|
||||
pkgs.emacs
|
||||
];
|
||||
|
||||
services.postgresql.package = pkgs.postgresql_14;
|
||||
services.postgresql.package = pkgs.postgresql_14;
|
||||
}
|
||||
```
|
||||
|
||||
The latter option definition changes the default PostgreSQL package
|
||||
|
|
|
@ -16,18 +16,20 @@ Examples include:
|
|||
|
||||
You can use them like this:
|
||||
```nix
|
||||
environment.systemPackages = with pkgs; [
|
||||
sl
|
||||
(pass.withExtensions (subpkgs: with subpkgs; [
|
||||
pass-audit
|
||||
pass-otp
|
||||
pass-genphrase
|
||||
]))
|
||||
(python3.withPackages (subpkgs: with subpkgs; [
|
||||
requests
|
||||
]))
|
||||
cowsay
|
||||
];
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
sl
|
||||
(pass.withExtensions (subpkgs: with subpkgs; [
|
||||
pass-audit
|
||||
pass-otp
|
||||
pass-genphrase
|
||||
]))
|
||||
(python3.withPackages (subpkgs: with subpkgs; [
|
||||
requests
|
||||
]))
|
||||
cowsay
|
||||
];
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -38,7 +40,9 @@ dependency on GTK 2. If you want to build it against GTK 3, you can
|
|||
specify that as follows:
|
||||
|
||||
```nix
|
||||
environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ];
|
||||
{
|
||||
environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ];
|
||||
}
|
||||
```
|
||||
|
||||
The function `override` performs the call to the Nix function that
|
||||
|
@ -58,12 +62,14 @@ of the package, such as the source code. For instance, if you want to
|
|||
override the source code of Emacs, you can say:
|
||||
|
||||
```nix
|
||||
environment.systemPackages = [
|
||||
(pkgs.emacs.overrideAttrs (oldAttrs: {
|
||||
name = "emacs-25.0-pre";
|
||||
src = /path/to/my/emacs/tree;
|
||||
}))
|
||||
];
|
||||
{
|
||||
environment.systemPackages = [
|
||||
(pkgs.emacs.overrideAttrs (oldAttrs: {
|
||||
name = "emacs-25.0-pre";
|
||||
src = /path/to/my/emacs/tree;
|
||||
}))
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Here, `overrideAttrs` takes the Nix derivation specified by `pkgs.emacs`
|
||||
|
@ -80,9 +86,11 @@ two instances of the package. If you want to have everything depend on
|
|||
your customised instance, you can apply a *global* override as follows:
|
||||
|
||||
```nix
|
||||
nixpkgs.config.packageOverrides = pkgs:
|
||||
{ emacs = pkgs.emacs.override { gtk = pkgs.gtk3; };
|
||||
};
|
||||
{
|
||||
nixpkgs.config.packageOverrides = pkgs:
|
||||
{ emacs = pkgs.emacs.override { gtk = pkgs.gtk3; };
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The effect of this definition is essentially equivalent to modifying the
|
||||
|
|
|
@ -7,7 +7,9 @@ following line to `configuration.nix` enables the Mozilla Thunderbird
|
|||
email application:
|
||||
|
||||
```nix
|
||||
environment.systemPackages = [ pkgs.thunderbird ];
|
||||
{
|
||||
environment.systemPackages = [ pkgs.thunderbird ];
|
||||
}
|
||||
```
|
||||
|
||||
The effect of this specification is that the Thunderbird package from
|
||||
|
|
|
@ -6,10 +6,12 @@ Ext4 file system on device `/dev/disk/by-label/data` onto the mount
|
|||
point `/data`:
|
||||
|
||||
```nix
|
||||
fileSystems."/data" =
|
||||
{ device = "/dev/disk/by-label/data";
|
||||
fsType = "ext4";
|
||||
};
|
||||
{
|
||||
fileSystems."/data" =
|
||||
{ device = "/dev/disk/by-label/data";
|
||||
fsType = "ext4";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This will create an entry in `/etc/fstab`, which will generate a
|
||||
|
|
|
@ -5,14 +5,18 @@ and other unexpected packets. The firewall applies to both IPv4 and IPv6
|
|||
traffic. It is enabled by default. It can be disabled as follows:
|
||||
|
||||
```nix
|
||||
networking.firewall.enable = false;
|
||||
{
|
||||
networking.firewall.enable = false;
|
||||
}
|
||||
```
|
||||
|
||||
If the firewall is enabled, you can open specific TCP ports to the
|
||||
outside world:
|
||||
|
||||
```nix
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
}
|
||||
```
|
||||
|
||||
Note that TCP port 22 (ssh) is opened automatically if the SSH daemon is
|
||||
|
@ -22,10 +26,12 @@ enabled (`services.openssh.enable = true`). UDP ports can be opened through
|
|||
To open ranges of TCP ports:
|
||||
|
||||
```nix
|
||||
networking.firewall.allowedTCPPortRanges = [
|
||||
{ from = 4000; to = 4007; }
|
||||
{ from = 8000; to = 8010; }
|
||||
];
|
||||
{
|
||||
networking.firewall.allowedTCPPortRanges = [
|
||||
{ from = 4000; to = 4007; }
|
||||
{ from = 8000; to = 8010; }
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, UDP port ranges can be opened through
|
||||
|
|
|
@ -55,9 +55,11 @@ supported through the rocmPackages.clr.icd package. Adding this package to
|
|||
enables OpenCL support:
|
||||
|
||||
```nix
|
||||
hardware.opengl.extraPackages = [
|
||||
rocmPackages.clr.icd
|
||||
];
|
||||
{
|
||||
hardware.opengl.extraPackages = [
|
||||
rocmPackages.clr.icd
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Intel {#sec-gpu-accel-opencl-intel}
|
||||
|
@ -74,9 +76,11 @@ to enable OpenCL support. For example, for Gen8 and later GPUs, the following
|
|||
configuration can be used:
|
||||
|
||||
```nix
|
||||
hardware.opengl.extraPackages = [
|
||||
intel-compute-runtime
|
||||
];
|
||||
{
|
||||
hardware.opengl.extraPackages = [
|
||||
intel-compute-runtime
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Vulkan {#sec-gpu-accel-vulkan}
|
||||
|
@ -141,20 +145,22 @@ makes amdvlk the default driver and hides radv and lavapipe from the device list
|
|||
A specific driver can be forced as follows:
|
||||
|
||||
```nix
|
||||
hardware.opengl.extraPackages = [
|
||||
pkgs.amdvlk
|
||||
];
|
||||
{
|
||||
hardware.opengl.extraPackages = [
|
||||
pkgs.amdvlk
|
||||
];
|
||||
|
||||
# To enable Vulkan support for 32-bit applications, also add:
|
||||
hardware.opengl.extraPackages32 = [
|
||||
pkgs.driversi686Linux.amdvlk
|
||||
];
|
||||
# To enable Vulkan support for 32-bit applications, also add:
|
||||
hardware.opengl.extraPackages32 = [
|
||||
pkgs.driversi686Linux.amdvlk
|
||||
];
|
||||
|
||||
# Force radv
|
||||
environment.variables.AMD_VULKAN_ICD = "RADV";
|
||||
# Or
|
||||
environment.variables.VK_ICD_FILENAMES =
|
||||
"/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json";
|
||||
# Force radv
|
||||
environment.variables.AMD_VULKAN_ICD = "RADV";
|
||||
# Or
|
||||
environment.variables.VK_ICD_FILENAMES =
|
||||
"/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json";
|
||||
}
|
||||
```
|
||||
|
||||
## VA-API {#sec-gpu-accel-va-api}
|
||||
|
@ -178,17 +184,21 @@ $ nix-shell -p libva-utils --run vainfo
|
|||
Modern Intel GPUs use the iHD driver, which can be installed with:
|
||||
|
||||
```nix
|
||||
hardware.opengl.extraPackages = [
|
||||
intel-media-driver
|
||||
];
|
||||
{
|
||||
hardware.opengl.extraPackages = [
|
||||
intel-media-driver
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Older Intel GPUs use the i965 driver, which can be installed with:
|
||||
|
||||
```nix
|
||||
hardware.opengl.extraPackages = [
|
||||
intel-vaapi-driver
|
||||
];
|
||||
{
|
||||
hardware.opengl.extraPackages = [
|
||||
intel-vaapi-driver
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Common issues {#sec-gpu-accel-common-issues}
|
||||
|
|
|
@ -5,18 +5,22 @@ configure network interfaces. However, you can configure an interface
|
|||
manually as follows:
|
||||
|
||||
```nix
|
||||
networking.interfaces.eth0.ipv4.addresses = [ {
|
||||
address = "192.168.1.2";
|
||||
prefixLength = 24;
|
||||
} ];
|
||||
{
|
||||
networking.interfaces.eth0.ipv4.addresses = [ {
|
||||
address = "192.168.1.2";
|
||||
prefixLength = 24;
|
||||
} ];
|
||||
}
|
||||
```
|
||||
|
||||
Typically you'll also want to set a default gateway and set of name
|
||||
servers:
|
||||
|
||||
```nix
|
||||
networking.defaultGateway = "192.168.1.1";
|
||||
networking.nameservers = [ "8.8.8.8" ];
|
||||
{
|
||||
networking.defaultGateway = "192.168.1.1";
|
||||
networking.nameservers = [ "8.8.8.8" ];
|
||||
}
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
|
@ -28,7 +32,9 @@ configuration is performed by `network-setup.service`.
|
|||
The host name is set using [](#opt-networking.hostName):
|
||||
|
||||
```nix
|
||||
networking.hostName = "cartman";
|
||||
{
|
||||
networking.hostName = "cartman";
|
||||
}
|
||||
```
|
||||
|
||||
The default host name is `nixos`. Set it to the empty string (`""`) to
|
||||
|
|
|
@ -9,34 +9,42 @@ may be overridden on a per-interface basis by
|
|||
IPv6 support globally by setting:
|
||||
|
||||
```nix
|
||||
networking.enableIPv6 = false;
|
||||
{
|
||||
networking.enableIPv6 = false;
|
||||
}
|
||||
```
|
||||
|
||||
You can disable IPv6 on a single interface using a normal sysctl (in
|
||||
this example, we use interface `eth0`):
|
||||
|
||||
```nix
|
||||
boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true;
|
||||
{
|
||||
boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true;
|
||||
}
|
||||
```
|
||||
|
||||
As with IPv4 networking interfaces are automatically configured via
|
||||
DHCPv6. You can configure an interface manually:
|
||||
|
||||
```nix
|
||||
networking.interfaces.eth0.ipv6.addresses = [ {
|
||||
address = "fe00:aa:bb:cc::2";
|
||||
prefixLength = 64;
|
||||
} ];
|
||||
{
|
||||
networking.interfaces.eth0.ipv6.addresses = [ {
|
||||
address = "fe00:aa:bb:cc::2";
|
||||
prefixLength = 64;
|
||||
} ];
|
||||
}
|
||||
```
|
||||
|
||||
For configuring a gateway, optionally with explicitly specified
|
||||
interface:
|
||||
|
||||
```nix
|
||||
networking.defaultGateway6 = {
|
||||
address = "fe00::1";
|
||||
interface = "enp0s3";
|
||||
};
|
||||
{
|
||||
networking.defaultGateway6 = {
|
||||
address = "fe00::1";
|
||||
interface = "enp0s3";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
See [](#sec-ipv4) for similar examples and additional information.
|
||||
|
|
|
@ -7,14 +7,16 @@ There are generally two ways of enabling Kubernetes on NixOS. One way is
|
|||
to enable and configure cluster components appropriately by hand:
|
||||
|
||||
```nix
|
||||
services.kubernetes = {
|
||||
apiserver.enable = true;
|
||||
controllerManager.enable = true;
|
||||
scheduler.enable = true;
|
||||
addonManager.enable = true;
|
||||
proxy.enable = true;
|
||||
flannel.enable = true;
|
||||
};
|
||||
{
|
||||
services.kubernetes = {
|
||||
apiserver.enable = true;
|
||||
controllerManager.enable = true;
|
||||
scheduler.enable = true;
|
||||
addonManager.enable = true;
|
||||
proxy.enable = true;
|
||||
flannel.enable = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Another way is to assign cluster roles ("master" and/or "node") to
|
||||
|
@ -22,20 +24,26 @@ the host. This enables apiserver, controllerManager, scheduler,
|
|||
addonManager, kube-proxy and etcd:
|
||||
|
||||
```nix
|
||||
services.kubernetes.roles = [ "master" ];
|
||||
{
|
||||
services.kubernetes.roles = [ "master" ];
|
||||
}
|
||||
```
|
||||
|
||||
While this will enable the kubelet and kube-proxy only:
|
||||
|
||||
```nix
|
||||
services.kubernetes.roles = [ "node" ];
|
||||
{
|
||||
services.kubernetes.roles = [ "node" ];
|
||||
}
|
||||
```
|
||||
|
||||
Assigning both the master and node roles is usable if you want a single
|
||||
node Kubernetes cluster for dev or testing purposes:
|
||||
|
||||
```nix
|
||||
services.kubernetes.roles = [ "master" "node" ];
|
||||
{
|
||||
services.kubernetes.roles = [ "master" "node" ];
|
||||
}
|
||||
```
|
||||
|
||||
Note: Assigning either role will also default both
|
||||
|
|
|
@ -5,7 +5,9 @@ option `boot.kernelPackages`. For instance, this selects the Linux 3.10
|
|||
kernel:
|
||||
|
||||
```nix
|
||||
boot.kernelPackages = pkgs.linuxKernel.packages.linux_3_10;
|
||||
{
|
||||
boot.kernelPackages = pkgs.linuxKernel.packages.linux_3_10;
|
||||
}
|
||||
```
|
||||
|
||||
Note that this not only replaces the kernel, but also packages that are
|
||||
|
@ -40,13 +42,15 @@ If you want to change the kernel configuration, you can use the
|
|||
instance, to enable support for the kernel debugger KGDB:
|
||||
|
||||
```nix
|
||||
nixpkgs.config.packageOverrides = pkgs: pkgs.lib.recursiveUpdate pkgs {
|
||||
linuxKernel.kernels.linux_5_10 = pkgs.linuxKernel.kernels.linux_5_10.override {
|
||||
extraConfig = ''
|
||||
KGDB y
|
||||
'';
|
||||
{
|
||||
nixpkgs.config.packageOverrides = pkgs: pkgs.lib.recursiveUpdate pkgs {
|
||||
linuxKernel.kernels.linux_5_10 = pkgs.linuxKernel.kernels.linux_5_10.override {
|
||||
extraConfig = ''
|
||||
KGDB y
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`extraConfig` takes a list of Linux kernel configuration options, one
|
||||
|
@ -59,14 +63,18 @@ by `udev`. You can force a module to be loaded via
|
|||
[](#opt-boot.kernelModules), e.g.
|
||||
|
||||
```nix
|
||||
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
|
||||
{
|
||||
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
|
||||
}
|
||||
```
|
||||
|
||||
If the module is required early during the boot (e.g. to mount the root
|
||||
file system), you can use [](#opt-boot.initrd.kernelModules):
|
||||
|
||||
```nix
|
||||
boot.initrd.kernelModules = [ "cifs" ];
|
||||
{
|
||||
boot.initrd.kernelModules = [ "cifs" ];
|
||||
}
|
||||
```
|
||||
|
||||
This causes the specified modules and their dependencies to be added to
|
||||
|
@ -76,7 +84,9 @@ Kernel runtime parameters can be set through
|
|||
[](#opt-boot.kernel.sysctl), e.g.
|
||||
|
||||
```nix
|
||||
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120;
|
||||
{
|
||||
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120;
|
||||
}
|
||||
```
|
||||
|
||||
sets the kernel's TCP keepalive time to 120 seconds. To see the
|
||||
|
@ -89,7 +99,9 @@ Please refer to the Nixpkgs manual for the various ways of [building a custom ke
|
|||
To use your custom kernel package in your NixOS configuration, set
|
||||
|
||||
```nix
|
||||
boot.kernelPackages = pkgs.linuxPackagesFor yourCustomKernel;
|
||||
{
|
||||
boot.kernelPackages = pkgs.linuxPackagesFor yourCustomKernel;
|
||||
}
|
||||
```
|
||||
|
||||
## Rust {#sec-linux-rust}
|
||||
|
@ -99,15 +111,17 @@ default. For kernel versions 6.7 or newer, experimental Rust support
|
|||
can be enabled. In a NixOS configuration, set:
|
||||
|
||||
```nix
|
||||
boot.kernelPatches = [
|
||||
{
|
||||
name = "Rust Support";
|
||||
patch = null;
|
||||
features = {
|
||||
rust = true;
|
||||
};
|
||||
}
|
||||
];
|
||||
{
|
||||
boot.kernelPatches = [
|
||||
{
|
||||
name = "Rust Support";
|
||||
patch = null;
|
||||
features = {
|
||||
rust = true;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Developing kernel modules {#sec-linux-config-developing-modules}
|
||||
|
|
|
@ -29,15 +29,19 @@ system is automatically mounted at boot time as `/`, add the following
|
|||
to `configuration.nix`:
|
||||
|
||||
```nix
|
||||
boot.initrd.luks.devices.crypted.device = "/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d";
|
||||
fileSystems."/".device = "/dev/mapper/crypted";
|
||||
{
|
||||
boot.initrd.luks.devices.crypted.device = "/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d";
|
||||
fileSystems."/".device = "/dev/mapper/crypted";
|
||||
}
|
||||
```
|
||||
|
||||
Should grub be used as bootloader, and `/boot` is located on an
|
||||
encrypted partition, it is necessary to add the following grub option:
|
||||
|
||||
```nix
|
||||
boot.loader.grub.enableCryptodisk = true;
|
||||
{
|
||||
boot.loader.grub.enableCryptodisk = true;
|
||||
}
|
||||
```
|
||||
|
||||
## FIDO2 {#sec-luks-file-systems-fido2}
|
||||
|
@ -68,8 +72,10 @@ To ensure that this file system is decrypted using the FIDO2 compatible
|
|||
key, add the following to `configuration.nix`:
|
||||
|
||||
```nix
|
||||
boot.initrd.luks.fido2Support = true;
|
||||
boot.initrd.luks.devices."/dev/sda2".fido2.credential = "f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7";
|
||||
{
|
||||
boot.initrd.luks.fido2Support = true;
|
||||
boot.initrd.luks.devices."/dev/sda2".fido2.credential = "f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7";
|
||||
}
|
||||
```
|
||||
|
||||
You can also use the FIDO2 passwordless setup, but for security reasons,
|
||||
|
@ -77,7 +83,9 @@ you might want to enable it only when your device is PIN protected, such
|
|||
as [Trezor](https://trezor.io/).
|
||||
|
||||
```nix
|
||||
boot.initrd.luks.devices."/dev/sda2".fido2.passwordLess = true;
|
||||
{
|
||||
boot.initrd.luks.devices."/dev/sda2".fido2.passwordLess = true;
|
||||
}
|
||||
```
|
||||
|
||||
### systemd Stage 1 {#sec-luks-file-systems-fido2-systemd}
|
||||
|
@ -88,13 +96,15 @@ unlocking the existing LUKS2 volume `root` using any enrolled FIDO2 compatible
|
|||
tokens.
|
||||
|
||||
```nix
|
||||
boot.initrd = {
|
||||
luks.devices.root = {
|
||||
crypttabExtraOpts = [ "fido2-device=auto" ];
|
||||
device = "/dev/sda2";
|
||||
{
|
||||
boot.initrd = {
|
||||
luks.devices.root = {
|
||||
crypttabExtraOpts = [ "fido2-device=auto" ];
|
||||
device = "/dev/sda2";
|
||||
};
|
||||
systemd.enable = true;
|
||||
};
|
||||
systemd.enable = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
All tokens that should be used for unlocking the LUKS2-encrypted volume must
|
||||
|
|
|
@ -16,7 +16,7 @@ including them from `configuration.nix`, e.g.:
|
|||
{ imports = [ ./vpn.nix ./kde.nix ];
|
||||
services.httpd.enable = true;
|
||||
environment.systemPackages = [ pkgs.emacs ];
|
||||
...
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -42,7 +42,9 @@ merged last, so for list-type options, it will appear at the end of the
|
|||
merged list. If you want it to appear first, you can use `mkBefore`:
|
||||
|
||||
```nix
|
||||
boot.kernelModules = mkBefore [ "kvm-intel" ];
|
||||
{
|
||||
boot.kernelModules = mkBefore [ "kvm-intel" ];
|
||||
}
|
||||
```
|
||||
|
||||
This causes the `kvm-intel` kernel module to be loaded before any other
|
||||
|
@ -60,7 +62,9 @@ When that happens, it's possible to force one definition take precedence
|
|||
over the others:
|
||||
|
||||
```nix
|
||||
services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org";
|
||||
{
|
||||
services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org";
|
||||
}
|
||||
```
|
||||
|
||||
When using multiple modules, you may need to access configuration values
|
||||
|
|
|
@ -4,7 +4,9 @@ To facilitate network configuration, some desktop environments use
|
|||
NetworkManager. You can enable NetworkManager by setting:
|
||||
|
||||
```nix
|
||||
networking.networkmanager.enable = true;
|
||||
{
|
||||
networking.networkmanager.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
some desktop managers (e.g., GNOME) enable NetworkManager automatically
|
||||
|
@ -14,7 +16,9 @@ All users that should have permission to change network settings must
|
|||
belong to the `networkmanager` group:
|
||||
|
||||
```nix
|
||||
users.users.alice.extraGroups = [ "networkmanager" ];
|
||||
{
|
||||
users.users.alice.extraGroups = [ "networkmanager" ];
|
||||
}
|
||||
```
|
||||
|
||||
NetworkManager is controlled using either `nmcli` or `nmtui`
|
||||
|
@ -32,9 +36,11 @@ can be used together if desired. To do this you need to instruct
|
|||
NetworkManager to ignore those interfaces like:
|
||||
|
||||
```nix
|
||||
networking.networkmanager.unmanaged = [
|
||||
"*" "except:type:wwan" "except:type:gsm"
|
||||
];
|
||||
{
|
||||
networking.networkmanager.unmanaged = [
|
||||
"*" "except:type:wwan" "except:type:gsm"
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Refer to the option description for the exact syntax and references to
|
||||
|
|
|
@ -4,21 +4,23 @@ NixOS offers a convenient abstraction to create both read-only as well writable
|
|||
overlays.
|
||||
|
||||
```nix
|
||||
fileSystems = {
|
||||
"/writable-overlay" = {
|
||||
overlay = {
|
||||
lowerdir = [ writableOverlayLowerdir ];
|
||||
upperdir = "/.rw-writable-overlay/upper";
|
||||
workdir = "/.rw-writable-overlay/work";
|
||||
{
|
||||
fileSystems = {
|
||||
"/writable-overlay" = {
|
||||
overlay = {
|
||||
lowerdir = [ writableOverlayLowerdir ];
|
||||
upperdir = "/.rw-writable-overlay/upper";
|
||||
workdir = "/.rw-writable-overlay/work";
|
||||
};
|
||||
# Mount the writable overlay in the initrd.
|
||||
neededForBoot = true;
|
||||
};
|
||||
# Mount the writable overlay in the initrd.
|
||||
neededForBoot = true;
|
||||
"/readonly-overlay".overlay.lowerdir = [
|
||||
writableOverlayLowerdir
|
||||
writableOverlayLowerdir2
|
||||
];
|
||||
};
|
||||
"/readonly-overlay".overlay.lowerdir = [
|
||||
writableOverlayLowerdir
|
||||
writableOverlayLowerdir2
|
||||
];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
If `upperdir` and `workdir` are not null, they will be created before the
|
||||
|
|
|
@ -8,9 +8,11 @@ is to say, expected usage is to add them to the imports list of your
|
|||
`/etc/configuration.nix` as such:
|
||||
|
||||
```nix
|
||||
imports = [
|
||||
<nixpkgs/nixos/modules/profiles/profile-name.nix>
|
||||
];
|
||||
{
|
||||
imports = [
|
||||
<nixpkgs/nixos/modules/profiles/profile-name.nix>
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Even if some of these profiles seem only useful in the context of
|
||||
|
|
|
@ -25,10 +25,12 @@ we assign the name `wan` to the interface with MAC address
|
|||
`52:54:00:12:01:01` using a netword link unit:
|
||||
|
||||
```nix
|
||||
systemd.network.links."10-wan" = {
|
||||
matchConfig.PermanentMACAddress = "52:54:00:12:01:01";
|
||||
linkConfig.Name = "wan";
|
||||
};
|
||||
{
|
||||
systemd.network.links."10-wan" = {
|
||||
matchConfig.PermanentMACAddress = "52:54:00:12:01:01";
|
||||
linkConfig.Name = "wan";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Note that links are directly read by udev, *not networkd*, and will work
|
||||
|
@ -37,10 +39,12 @@ even if networkd is disabled.
|
|||
Alternatively, we can use a plain old udev rule:
|
||||
|
||||
```nix
|
||||
boot.initrd.services.udev.rules = ''
|
||||
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", \
|
||||
ATTR{address}=="52:54:00:12:01:01", KERNEL=="eth*", NAME="wan"
|
||||
'';
|
||||
{
|
||||
boot.initrd.services.udev.rules = ''
|
||||
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", \
|
||||
ATTR{address}=="52:54:00:12:01:01", KERNEL=="eth*", NAME="wan"
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
::: {.warning}
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
Secure shell (SSH) access to your machine can be enabled by setting:
|
||||
|
||||
```nix
|
||||
services.openssh.enable = true;
|
||||
{
|
||||
services.openssh.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
By default, root logins using a password are disallowed. They can be
|
||||
|
@ -14,6 +16,8 @@ You can declaratively specify authorised RSA/DSA public keys for a user
|
|||
as follows:
|
||||
|
||||
```nix
|
||||
users.users.alice.openssh.authorizedKeys.keys =
|
||||
[ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ];
|
||||
{
|
||||
users.users.alice.openssh.authorizedKeys.keys =
|
||||
[ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ];
|
||||
}
|
||||
```
|
||||
|
|
|
@ -21,9 +21,11 @@ Apache HTTP, setting [](#opt-services.httpd.adminAddr)
|
|||
appropriately:
|
||||
|
||||
```nix
|
||||
services.httpd.enable = true;
|
||||
services.httpd.adminAddr = ...;
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
{
|
||||
services.httpd.enable = true;
|
||||
services.httpd.adminAddr = "...";
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
}
|
||||
```
|
||||
|
||||
For a simple Subversion server with basic authentication, configure the
|
||||
|
@ -34,25 +36,28 @@ the `.authz` file describing access permission, and `AuthUserFile` to
|
|||
the password file.
|
||||
|
||||
```nix
|
||||
services.httpd.extraModules = [
|
||||
# note that order is *super* important here
|
||||
{ name = "dav_svn"; path = "${pkgs.apacheHttpdPackages.subversion}/modules/mod_dav_svn.so"; }
|
||||
{ name = "authz_svn"; path = "${pkgs.apacheHttpdPackages.subversion}/modules/mod_authz_svn.so"; }
|
||||
];
|
||||
services.httpd.virtualHosts = {
|
||||
"svn" = {
|
||||
hostName = HOSTNAME;
|
||||
documentRoot = DOCUMENTROOT;
|
||||
locations."/svn".extraConfig = ''
|
||||
DAV svn
|
||||
SVNParentPath REPO_PARENT
|
||||
AuthzSVNAccessFile ACCESS_FILE
|
||||
AuthName "SVN Repositories"
|
||||
AuthType Basic
|
||||
AuthUserFile PASSWORD_FILE
|
||||
Require valid-user
|
||||
'';
|
||||
}
|
||||
{
|
||||
services.httpd.extraModules = [
|
||||
# note that order is *super* important here
|
||||
{ name = "dav_svn"; path = "${pkgs.apacheHttpdPackages.subversion}/modules/mod_dav_svn.so"; }
|
||||
{ name = "authz_svn"; path = "${pkgs.apacheHttpdPackages.subversion}/modules/mod_authz_svn.so"; }
|
||||
];
|
||||
services.httpd.virtualHosts = {
|
||||
"svn" = {
|
||||
hostName = HOSTNAME;
|
||||
documentRoot = DOCUMENTROOT;
|
||||
locations."/svn".extraConfig = ''
|
||||
DAV svn
|
||||
SVNParentPath REPO_PARENT
|
||||
AuthzSVNAccessFile ACCESS_FILE
|
||||
AuthName "SVN Repositories"
|
||||
AuthType Basic
|
||||
AuthUserFile PASSWORD_FILE
|
||||
Require valid-user
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The key `"svn"` is just a symbolic name identifying the virtual host.
|
||||
|
@ -90,7 +95,7 @@ $ htpasswd -s PASSWORD_FILE USER_NAME
|
|||
The file describing access permissions `ACCESS_FILE` will look something
|
||||
like the following:
|
||||
|
||||
```nix
|
||||
```
|
||||
[/]
|
||||
* = r
|
||||
|
||||
|
|
|
@ -6,13 +6,15 @@ management. In the declarative style, users are specified in
|
|||
account named `alice` shall exist:
|
||||
|
||||
```nix
|
||||
users.users.alice = {
|
||||
isNormalUser = true;
|
||||
home = "/home/alice";
|
||||
description = "Alice Foobar";
|
||||
extraGroups = [ "wheel" "networkmanager" ];
|
||||
openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
|
||||
};
|
||||
{
|
||||
users.users.alice = {
|
||||
isNormalUser = true;
|
||||
home = "/home/alice";
|
||||
description = "Alice Foobar";
|
||||
extraGroups = [ "wheel" "networkmanager" ];
|
||||
openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Note that `alice` is a member of the `wheel` and `networkmanager`
|
||||
|
@ -38,7 +40,9 @@ A user ID (uid) is assigned automatically. You can also specify a uid
|
|||
manually by adding
|
||||
|
||||
```nix
|
||||
uid = 1000;
|
||||
{
|
||||
uid = 1000;
|
||||
}
|
||||
```
|
||||
|
||||
to the user specification.
|
||||
|
@ -47,7 +51,9 @@ Groups can be specified similarly. The following states that a group
|
|||
named `students` shall exist:
|
||||
|
||||
```nix
|
||||
users.groups.students.gid = 1000;
|
||||
{
|
||||
users.groups.students.gid = 1000;
|
||||
}
|
||||
```
|
||||
|
||||
As with users, the group ID (gid) is optional and will be assigned
|
||||
|
@ -100,7 +106,9 @@ Instead of using a custom perl script to create users and groups, you can use
|
|||
systemd-sysusers:
|
||||
|
||||
```nix
|
||||
systemd.sysusers.enable = true;
|
||||
{
|
||||
systemd.sysusers.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
The primary benefit of this is to remove a dependency on perl.
|
||||
|
|
|
@ -9,7 +9,9 @@ a Wayland Compositor such as sway without separately enabling a Wayland
|
|||
server:
|
||||
|
||||
```nix
|
||||
{
|
||||
programs.sway.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
This installs the sway compositor along with some essential utilities.
|
||||
|
@ -19,7 +21,9 @@ If you are using a wlroots-based compositor, like sway, and want to be
|
|||
able to share your screen, you might want to activate this option:
|
||||
|
||||
```nix
|
||||
xdg.portal.wlr.enable = true;
|
||||
{
|
||||
xdg.portal.wlr.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
and configure Pipewire using
|
||||
|
|
|
@ -7,25 +7,29 @@ skip the rest of this section on wireless networks.
|
|||
NixOS will start wpa_supplicant for you if you enable this setting:
|
||||
|
||||
```nix
|
||||
networking.wireless.enable = true;
|
||||
{
|
||||
networking.wireless.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
NixOS lets you specify networks for wpa_supplicant declaratively:
|
||||
|
||||
```nix
|
||||
networking.wireless.networks = {
|
||||
echelon = { # SSID with no spaces or special characters
|
||||
psk = "abcdefgh";
|
||||
{
|
||||
networking.wireless.networks = {
|
||||
echelon = { # SSID with no spaces or special characters
|
||||
psk = "abcdefgh";
|
||||
};
|
||||
"echelon's AP" = { # SSID with spaces and/or special characters
|
||||
psk = "ijklmnop";
|
||||
};
|
||||
echelon = { # Hidden SSID
|
||||
hidden = true;
|
||||
psk = "qrstuvwx";
|
||||
};
|
||||
free.wifi = {}; # Public wireless network
|
||||
};
|
||||
"echelon's AP" = { # SSID with spaces and/or special characters
|
||||
psk = "ijklmnop";
|
||||
};
|
||||
echelon = { # Hidden SSID
|
||||
hidden = true;
|
||||
psk = "qrstuvwx";
|
||||
};
|
||||
free.wifi = {}; # Public wireless network
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Be aware that keys will be written to the nix store in plaintext! When
|
||||
|
@ -46,11 +50,13 @@ network={
|
|||
```
|
||||
|
||||
```nix
|
||||
networking.wireless.networks = {
|
||||
echelon = {
|
||||
pskRaw = "dca6d6ed41f4ab5a984c9f55f6f66d4efdc720ebf66959810f4329bb391c5435";
|
||||
{
|
||||
networking.wireless.networks = {
|
||||
echelon = {
|
||||
pskRaw = "dca6d6ed41f4ab5a984c9f55f6f66d4efdc720ebf66959810f4329bb391c5435";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
or you can use it to directly generate the `wpa_supplicant.conf`:
|
||||
|
|
|
@ -4,7 +4,9 @@ The X Window System (X11) provides the basis of NixOS' graphical user
|
|||
interface. It can be enabled as follows:
|
||||
|
||||
```nix
|
||||
services.xserver.enable = true;
|
||||
{
|
||||
services.xserver.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
The X server will automatically detect and use the appropriate video
|
||||
|
@ -12,7 +14,9 @@ driver from a set of X.org drivers (such as `vesa` and `intel`). You can
|
|||
also specify a driver manually, e.g.
|
||||
|
||||
```nix
|
||||
services.xserver.videoDrivers = [ "r128" ];
|
||||
{
|
||||
services.xserver.videoDrivers = [ "r128" ];
|
||||
}
|
||||
```
|
||||
|
||||
to enable X.org's `xf86-video-r128` driver.
|
||||
|
@ -22,15 +26,17 @@ Otherwise, you can only log into a plain undecorated `xterm` window.
|
|||
Thus you should pick one or more of the following lines:
|
||||
|
||||
```nix
|
||||
services.xserver.desktopManager.plasma5.enable = true;
|
||||
services.xserver.desktopManager.xfce.enable = true;
|
||||
services.xserver.desktopManager.gnome.enable = true;
|
||||
services.xserver.desktopManager.mate.enable = true;
|
||||
services.xserver.windowManager.xmonad.enable = true;
|
||||
services.xserver.windowManager.twm.enable = true;
|
||||
services.xserver.windowManager.icewm.enable = true;
|
||||
services.xserver.windowManager.i3.enable = true;
|
||||
services.xserver.windowManager.herbstluftwm.enable = true;
|
||||
{
|
||||
services.xserver.desktopManager.plasma5.enable = true;
|
||||
services.xserver.desktopManager.xfce.enable = true;
|
||||
services.xserver.desktopManager.gnome.enable = true;
|
||||
services.xserver.desktopManager.mate.enable = true;
|
||||
services.xserver.windowManager.xmonad.enable = true;
|
||||
services.xserver.windowManager.twm.enable = true;
|
||||
services.xserver.windowManager.icewm.enable = true;
|
||||
services.xserver.windowManager.i3.enable = true;
|
||||
services.xserver.windowManager.herbstluftwm.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
NixOS's default *display manager* (the program that provides a graphical
|
||||
|
@ -38,22 +44,28 @@ login prompt and manages the X server) is LightDM. You can select an
|
|||
alternative one by picking one of the following lines:
|
||||
|
||||
```nix
|
||||
services.xserver.displayManager.sddm.enable = true;
|
||||
services.xserver.displayManager.gdm.enable = true;
|
||||
{
|
||||
services.xserver.displayManager.sddm.enable = true;
|
||||
services.xserver.displayManager.gdm.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
You can set the keyboard layout (and optionally the layout variant):
|
||||
|
||||
```nix
|
||||
services.xserver.xkb.layout = "de";
|
||||
services.xserver.xkb.variant = "neo";
|
||||
{
|
||||
services.xserver.xkb.layout = "de";
|
||||
services.xserver.xkb.variant = "neo";
|
||||
}
|
||||
```
|
||||
|
||||
The X server is started automatically at boot time. If you don't want
|
||||
this to happen, you can set:
|
||||
|
||||
```nix
|
||||
services.xserver.autorun = false;
|
||||
{
|
||||
services.xserver.autorun = false;
|
||||
}
|
||||
```
|
||||
|
||||
The X server can then be started manually:
|
||||
|
@ -66,7 +78,9 @@ On 64-bit systems, if you want OpenGL for 32-bit programs such as in
|
|||
Wine, you should also set the following:
|
||||
|
||||
```nix
|
||||
hardware.opengl.driSupport32Bit = true;
|
||||
{
|
||||
hardware.opengl.driSupport32Bit = true;
|
||||
}
|
||||
```
|
||||
|
||||
## Auto-login {#sec-x11-auto-login}
|
||||
|
@ -84,16 +98,20 @@ desktop environment. If you wanted no desktop environment and i3 as your
|
|||
your window manager, you'd define:
|
||||
|
||||
```nix
|
||||
services.xserver.displayManager.defaultSession = "none+i3";
|
||||
{
|
||||
services.xserver.displayManager.defaultSession = "none+i3";
|
||||
}
|
||||
```
|
||||
|
||||
Every display manager in NixOS supports auto-login, here is an example
|
||||
using lightdm for a user `alice`:
|
||||
|
||||
```nix
|
||||
services.xserver.displayManager.lightdm.enable = true;
|
||||
services.xserver.displayManager.autoLogin.enable = true;
|
||||
services.xserver.displayManager.autoLogin.user = "alice";
|
||||
{
|
||||
services.xserver.displayManager.lightdm.enable = true;
|
||||
services.xserver.displayManager.autoLogin.enable = true;
|
||||
services.xserver.displayManager.autoLogin.user = "alice";
|
||||
}
|
||||
```
|
||||
|
||||
## Intel Graphics drivers {#sec-x11--graphics-cards-intel}
|
||||
|
@ -119,18 +137,22 @@ drivers. Use the option
|
|||
to set one. The recommended configuration for modern systems is:
|
||||
|
||||
```nix
|
||||
services.xserver.videoDrivers = [ "modesetting" ];
|
||||
{
|
||||
services.xserver.videoDrivers = [ "modesetting" ];
|
||||
}
|
||||
```
|
||||
|
||||
If you experience screen tearing no matter what, this configuration was
|
||||
reported to resolve the issue:
|
||||
|
||||
```nix
|
||||
services.xserver.videoDrivers = [ "intel" ];
|
||||
services.xserver.deviceSection = ''
|
||||
Option "DRI" "2"
|
||||
Option "TearFree" "true"
|
||||
'';
|
||||
{
|
||||
services.xserver.videoDrivers = [ "intel" ];
|
||||
services.xserver.deviceSection = ''
|
||||
Option "DRI" "2"
|
||||
Option "TearFree" "true"
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
Note that this will likely downgrade the performance compared to
|
||||
|
@ -143,15 +165,19 @@ better 3D performance than the X.org drivers. It is not enabled by
|
|||
default because it's not free software. You can enable it as follows:
|
||||
|
||||
```nix
|
||||
services.xserver.videoDrivers = [ "nvidia" ];
|
||||
{
|
||||
services.xserver.videoDrivers = [ "nvidia" ];
|
||||
}
|
||||
```
|
||||
|
||||
If you have an older card, you may have to use one of the legacy drivers:
|
||||
|
||||
```nix
|
||||
hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_470;
|
||||
hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_390;
|
||||
hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_340;
|
||||
{
|
||||
hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_470;
|
||||
hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_390;
|
||||
hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_340;
|
||||
}
|
||||
```
|
||||
|
||||
You may need to reboot after enabling this driver to prevent a clash
|
||||
|
@ -166,7 +192,9 @@ performance. If you still want to use it anyway, you need to explicitly
|
|||
set:
|
||||
|
||||
```nix
|
||||
services.xserver.videoDrivers = [ "amdgpu-pro" ];
|
||||
{
|
||||
services.xserver.videoDrivers = [ "amdgpu-pro" ];
|
||||
}
|
||||
```
|
||||
|
||||
You will need to reboot after enabling this driver to prevent a clash
|
||||
|
@ -178,14 +206,18 @@ Support for Synaptics touchpads (found in many laptops such as the Dell
|
|||
Latitude series) can be enabled as follows:
|
||||
|
||||
```nix
|
||||
services.xserver.libinput.enable = true;
|
||||
{
|
||||
services.xserver.libinput.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
The driver has many options (see [](#ch-options)).
|
||||
For instance, the following disables tap-to-click behavior:
|
||||
|
||||
```nix
|
||||
services.xserver.libinput.touchpad.tapping = false;
|
||||
{
|
||||
services.xserver.libinput.touchpad.tapping = false;
|
||||
}
|
||||
```
|
||||
|
||||
Note: the use of `services.xserver.synaptics` is deprecated since NixOS
|
||||
|
@ -198,9 +230,11 @@ GTK themes can be installed either to user profile or system-wide (via
|
|||
GTK ones, you can use the following configuration:
|
||||
|
||||
```nix
|
||||
qt.enable = true;
|
||||
qt.platformTheme = "gtk2";
|
||||
qt.style = "gtk2";
|
||||
{
|
||||
qt.enable = true;
|
||||
qt.platformTheme = "gtk2";
|
||||
qt.style = "gtk2";
|
||||
}
|
||||
```
|
||||
|
||||
## Custom XKB layouts {#custom-xkb-layouts}
|
||||
|
@ -217,7 +251,7 @@ Create a file called `us-greek` with the following content (under a
|
|||
directory called `symbols`; it's an XKB peculiarity that will help with
|
||||
testing):
|
||||
|
||||
```nix
|
||||
```
|
||||
xkb_symbols "us-greek"
|
||||
{
|
||||
include "us(basic)" // includes the base US keys
|
||||
|
@ -234,11 +268,13 @@ xkb_symbols "us-greek"
|
|||
A minimal layout specification must include the following:
|
||||
|
||||
```nix
|
||||
services.xserver.xkb.extraLayouts.us-greek = {
|
||||
description = "US layout with alt-gr greek";
|
||||
languages = [ "eng" ];
|
||||
symbolsFile = /yourpath/symbols/us-greek;
|
||||
};
|
||||
{
|
||||
services.xserver.xkb.extraLayouts.us-greek = {
|
||||
description = "US layout with alt-gr greek";
|
||||
languages = [ "eng" ];
|
||||
symbolsFile = /yourpath/symbols/us-greek;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
|
@ -275,7 +311,7 @@ Use the *xev* utility from `pkgs.xorg.xev` to find the codes of the keys
|
|||
of interest, then create a `media-key` file to hold the keycodes
|
||||
definitions
|
||||
|
||||
```nix
|
||||
```
|
||||
xkb_keycodes "media"
|
||||
{
|
||||
<volUp> = 123;
|
||||
|
@ -285,7 +321,7 @@ xkb_keycodes "media"
|
|||
|
||||
Now use the newly define keycodes in `media-sym`:
|
||||
|
||||
```nix
|
||||
```
|
||||
xkb_symbols "media"
|
||||
{
|
||||
key.type = "ONE_LEVEL";
|
||||
|
@ -297,12 +333,14 @@ xkb_symbols "media"
|
|||
As before, to install the layout do
|
||||
|
||||
```nix
|
||||
services.xserver.xkb.extraLayouts.media = {
|
||||
description = "Multimedia keys remapping";
|
||||
languages = [ "eng" ];
|
||||
symbolsFile = /path/to/media-key;
|
||||
keycodesFile = /path/to/media-sym;
|
||||
};
|
||||
{
|
||||
services.xserver.xkb.extraLayouts.media = {
|
||||
description = "Multimedia keys remapping";
|
||||
languages = [ "eng" ];
|
||||
symbolsFile = /path/to/media-key;
|
||||
keycodesFile = /path/to/media-sym;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
|
@ -318,7 +356,9 @@ workaround, you can set the keymap using `setxkbmap` at the start of the
|
|||
session with:
|
||||
|
||||
```nix
|
||||
services.xserver.displayManager.sessionCommands = "setxkbmap -keycodes media";
|
||||
{
|
||||
services.xserver.displayManager.sessionCommands = "setxkbmap -keycodes media";
|
||||
}
|
||||
```
|
||||
|
||||
If you are manually starting the X server, you should set the argument
|
||||
|
|
|
@ -3,21 +3,25 @@
|
|||
To enable the Xfce Desktop Environment, set
|
||||
|
||||
```nix
|
||||
services.xserver.desktopManager.xfce.enable = true;
|
||||
services.xserver.displayManager.defaultSession = "xfce";
|
||||
{
|
||||
services.xserver.desktopManager.xfce.enable = true;
|
||||
services.xserver.displayManager.defaultSession = "xfce";
|
||||
}
|
||||
```
|
||||
|
||||
Optionally, *picom* can be enabled for nice graphical effects, some
|
||||
example settings:
|
||||
|
||||
```nix
|
||||
services.picom = {
|
||||
enable = true;
|
||||
fade = true;
|
||||
inactiveOpacity = 0.9;
|
||||
shadow = true;
|
||||
fadeDelta = 4;
|
||||
};
|
||||
{
|
||||
services.picom = {
|
||||
enable = true;
|
||||
fade = true;
|
||||
inactiveOpacity = 0.9;
|
||||
shadow = true;
|
||||
fadeDelta = 4;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Some Xfce programs are not installed automatically. To install them
|
||||
|
|
|
@ -17,13 +17,15 @@ activation script will take these dependencies into account and order the
|
|||
snippets accordingly. As a simple example:
|
||||
|
||||
```nix
|
||||
system.activationScripts.my-activation-script = {
|
||||
deps = [ "etc" ];
|
||||
# supportsDryActivation = true;
|
||||
text = ''
|
||||
echo "Hallo i bims"
|
||||
'';
|
||||
};
|
||||
{
|
||||
system.activationScripts.my-activation-script = {
|
||||
deps = [ "etc" ];
|
||||
# supportsDryActivation = true;
|
||||
text = ''
|
||||
echo "Hallo i bims"
|
||||
'';
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This example creates an activation script snippet that is run after the `etc`
|
||||
|
|
|
@ -18,7 +18,7 @@ This is an example of using `warnings`.
|
|||
This is known to cause some specific problems in certain situations.
|
||||
'' ]
|
||||
else [];
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -35,6 +35,6 @@ This example, extracted from the [`syslogd` module](https://github.com/NixOS/nix
|
|||
message = "rsyslogd conflicts with syslogd";
|
||||
}
|
||||
];
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -9,7 +9,9 @@ Instead of using a custom perl script to activate `/etc`, you activate it via an
|
|||
overlay filesystem:
|
||||
|
||||
```nix
|
||||
system.etc.overlay.enable = true;
|
||||
{
|
||||
system.etc.overlay.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
Using an overlay has two benefits:
|
||||
|
@ -22,7 +24,9 @@ upper layer). However, you can also mount `/etc` immutably (i.e. read-only) by
|
|||
setting:
|
||||
|
||||
```nix
|
||||
system.etc.overlay.mutable = false;
|
||||
{
|
||||
system.etc.overlay.mutable = false;
|
||||
}
|
||||
```
|
||||
|
||||
The overlay is atomically replaced during system switch. However, files that
|
||||
|
|
|
@ -14,11 +14,11 @@ file.
|
|||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
options = {
|
||||
...
|
||||
# ...
|
||||
};
|
||||
|
||||
config = {
|
||||
...
|
||||
# ...
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
|
|
@ -9,7 +9,7 @@ profile:
|
|||
|
||||
```nix
|
||||
{ modulesPath, ... }: {
|
||||
imports = [ "${modulesPath}/profiles/image-based-appliance.nix" ]
|
||||
imports = [ "${modulesPath}/profiles/image-based-appliance.nix" ];
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -6,14 +6,16 @@ hasn't been declared in any module. An option declaration generally
|
|||
looks like this:
|
||||
|
||||
```nix
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = type specification;
|
||||
default = default value;
|
||||
example = example value;
|
||||
description = lib.mdDoc "Description for use in the NixOS manual.";
|
||||
{
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = type specification;
|
||||
default = default value;
|
||||
example = example value;
|
||||
description = lib.mdDoc "Description for use in the NixOS manual.";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The attribute names within the `name` attribute path must be camel
|
||||
|
@ -221,28 +223,34 @@ enforces that there can only be a single display manager enabled.
|
|||
::: {#ex-option-declaration-eot-service .example}
|
||||
### Extensible type placeholder in the service module
|
||||
```nix
|
||||
services.xserver.displayManager.enable = mkOption {
|
||||
description = "Display manager to use";
|
||||
type = with types; nullOr (enum [ ]);
|
||||
};
|
||||
{
|
||||
services.xserver.displayManager.enable = mkOption {
|
||||
description = "Display manager to use";
|
||||
type = with types; nullOr (enum [ ]);
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
::: {#ex-option-declaration-eot-backend-gdm .example}
|
||||
### Extending `services.xserver.displayManager.enable` in the `gdm` module
|
||||
```nix
|
||||
services.xserver.displayManager.enable = mkOption {
|
||||
type = with types; nullOr (enum [ "gdm" ]);
|
||||
};
|
||||
{
|
||||
services.xserver.displayManager.enable = mkOption {
|
||||
type = with types; nullOr (enum [ "gdm" ]);
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
::: {#ex-option-declaration-eot-backend-sddm .example}
|
||||
### Extending `services.xserver.displayManager.enable` in the `sddm` module
|
||||
```nix
|
||||
services.xserver.displayManager.enable = mkOption {
|
||||
type = with types; nullOr (enum [ "sddm" ]);
|
||||
};
|
||||
{
|
||||
services.xserver.displayManager.enable = mkOption {
|
||||
type = with types; nullOr (enum [ "sddm" ]);
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
|
|
@ -4,9 +4,11 @@ Option definitions are generally straight-forward bindings of values to
|
|||
option names, like
|
||||
|
||||
```nix
|
||||
config = {
|
||||
services.httpd.enable = true;
|
||||
};
|
||||
{
|
||||
config = {
|
||||
services.httpd.enable = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
However, sometimes you need to wrap an option definition or set of
|
||||
|
@ -18,10 +20,12 @@ If a set of option definitions is conditional on the value of another
|
|||
option, you may need to use `mkIf`. Consider, for instance:
|
||||
|
||||
```nix
|
||||
config = if config.services.httpd.enable then {
|
||||
environment.systemPackages = [ ... ];
|
||||
...
|
||||
} else {};
|
||||
{
|
||||
config = if config.services.httpd.enable then {
|
||||
environment.systemPackages = [ /* ... */ ];
|
||||
# ...
|
||||
} else {};
|
||||
}
|
||||
```
|
||||
|
||||
This definition will cause Nix to fail with an "infinite recursion"
|
||||
|
@ -30,30 +34,36 @@ on the value being constructed here. After all, you could also write the
|
|||
clearly circular and contradictory:
|
||||
|
||||
```nix
|
||||
config = if config.services.httpd.enable then {
|
||||
services.httpd.enable = false;
|
||||
} else {
|
||||
services.httpd.enable = true;
|
||||
};
|
||||
{
|
||||
config = if config.services.httpd.enable then {
|
||||
services.httpd.enable = false;
|
||||
} else {
|
||||
services.httpd.enable = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The solution is to write:
|
||||
|
||||
```nix
|
||||
config = mkIf config.services.httpd.enable {
|
||||
environment.systemPackages = [ ... ];
|
||||
...
|
||||
};
|
||||
{
|
||||
config = mkIf config.services.httpd.enable {
|
||||
environment.systemPackages = [ /* ... */ ];
|
||||
# ...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The special function `mkIf` causes the evaluation of the conditional to
|
||||
be "pushed down" into the individual definitions, as if you had written:
|
||||
|
||||
```nix
|
||||
config = {
|
||||
environment.systemPackages = if config.services.httpd.enable then [ ... ] else [];
|
||||
...
|
||||
};
|
||||
{
|
||||
config = {
|
||||
environment.systemPackages = if config.services.httpd.enable then [ /* ... */ ] else [];
|
||||
# ...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Setting Priorities {#sec-option-definitions-setting-priorities}
|
||||
|
@ -65,7 +75,9 @@ priority 100 and option defaults have priority 1500.
|
|||
You can specify an explicit priority by using `mkOverride`, e.g.
|
||||
|
||||
```nix
|
||||
services.openssh.enable = mkOverride 10 false;
|
||||
{
|
||||
services.openssh.enable = mkOverride 10 false;
|
||||
}
|
||||
```
|
||||
|
||||
This definition causes all other definitions with priorities above 10 to
|
||||
|
@ -80,7 +92,9 @@ The functions `mkBefore` and `mkAfter` are equal to `mkOrder 500` and `mkOrder 1
|
|||
As an example,
|
||||
|
||||
```nix
|
||||
hardware.firmware = mkBefore [ myFirmware ];
|
||||
{
|
||||
hardware.firmware = mkBefore [ myFirmware ];
|
||||
}
|
||||
```
|
||||
|
||||
This definition ensures that `myFirmware` comes before other unordered
|
||||
|
@ -97,13 +111,15 @@ they were declared in separate modules. This can be done using
|
|||
`mkMerge`:
|
||||
|
||||
```nix
|
||||
config = mkMerge
|
||||
[ # Unconditional stuff.
|
||||
{ environment.systemPackages = [ ... ];
|
||||
}
|
||||
# Conditional stuff.
|
||||
(mkIf config.services.bla.enable {
|
||||
environment.systemPackages = [ ... ];
|
||||
})
|
||||
];
|
||||
{
|
||||
config = mkMerge
|
||||
[ # Unconditional stuff.
|
||||
{ environment.systemPackages = [ /* ... */ ];
|
||||
}
|
||||
# Conditional stuff.
|
||||
(mkIf config.services.bla.enable {
|
||||
environment.systemPackages = [ /* ... */ ];
|
||||
})
|
||||
];
|
||||
}
|
||||
```
|
||||
|
|
|
@ -374,19 +374,21 @@ if you want to allow users to leave it undefined.
|
|||
::: {#ex-submodule-direct .example}
|
||||
### Directly defined submodule
|
||||
```nix
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
type = with types; submodule {
|
||||
options = {
|
||||
foo = mkOption {
|
||||
type = int;
|
||||
};
|
||||
bar = mkOption {
|
||||
type = str;
|
||||
{
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
type = with types; submodule {
|
||||
options = {
|
||||
foo = mkOption {
|
||||
type = int;
|
||||
};
|
||||
bar = mkOption {
|
||||
type = str;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -405,10 +407,12 @@ let
|
|||
};
|
||||
};
|
||||
in
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
type = with types; submodule modOptions;
|
||||
};
|
||||
{
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
type = with types; submodule modOptions;
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -421,29 +425,33 @@ multiple definitions of the submodule option set
|
|||
::: {#ex-submodule-listof-declaration .example}
|
||||
### Declaration of a list of submodules
|
||||
```nix
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
type = with types; listOf (submodule {
|
||||
options = {
|
||||
foo = mkOption {
|
||||
type = int;
|
||||
{
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
type = with types; listOf (submodule {
|
||||
options = {
|
||||
foo = mkOption {
|
||||
type = int;
|
||||
};
|
||||
bar = mkOption {
|
||||
type = str;
|
||||
};
|
||||
};
|
||||
bar = mkOption {
|
||||
type = str;
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
::: {#ex-submodule-listof-definition .example}
|
||||
### Definition of a list of submodules
|
||||
```nix
|
||||
config.mod = [
|
||||
{ foo = 1; bar = "one"; }
|
||||
{ foo = 2; bar = "two"; }
|
||||
];
|
||||
{
|
||||
config.mod = [
|
||||
{ foo = 1; bar = "one"; }
|
||||
{ foo = 2; bar = "two"; }
|
||||
];
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -455,27 +463,31 @@ multiple named definitions of the submodule option set
|
|||
::: {#ex-submodule-attrsof-declaration .example}
|
||||
### Declaration of attribute sets of submodules
|
||||
```nix
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
type = with types; attrsOf (submodule {
|
||||
options = {
|
||||
foo = mkOption {
|
||||
type = int;
|
||||
{
|
||||
options.mod = mkOption {
|
||||
description = "submodule example";
|
||||
type = with types; attrsOf (submodule {
|
||||
options = {
|
||||
foo = mkOption {
|
||||
type = int;
|
||||
};
|
||||
bar = mkOption {
|
||||
type = str;
|
||||
};
|
||||
};
|
||||
bar = mkOption {
|
||||
type = str;
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
::: {#ex-submodule-attrsof-definition .example}
|
||||
### Definition of attribute sets of submodules
|
||||
```nix
|
||||
config.mod.one = { foo = 1; bar = "one"; };
|
||||
config.mod.two = { foo = 2; bar = "two"; };
|
||||
{
|
||||
config.mod.one = { foo = 1; bar = "one"; };
|
||||
config.mod.two = { foo = 2; bar = "two"; };
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -495,10 +507,12 @@ Types are mainly characterized by their `check` and `merge` functions.
|
|||
### Adding a type check
|
||||
|
||||
```nix
|
||||
byte = mkOption {
|
||||
description = "An integer between 0 and 255.";
|
||||
type = types.addCheck types.int (x: x >= 0 && x <= 255);
|
||||
};
|
||||
{
|
||||
byte = mkOption {
|
||||
description = "An integer between 0 and 255.";
|
||||
type = types.addCheck types.int (x: x >= 0 && x <= 255);
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -506,12 +520,14 @@ Types are mainly characterized by their `check` and `merge` functions.
|
|||
### Overriding a type check
|
||||
|
||||
```nix
|
||||
nixThings = mkOption {
|
||||
description = "words that start with 'nix'";
|
||||
type = types.str // {
|
||||
check = (x: lib.hasPrefix "nix" x)
|
||||
{
|
||||
nixThings = mkOption {
|
||||
description = "words that start with 'nix'";
|
||||
type = types.str // {
|
||||
check = (x: lib.hasPrefix "nix" x);
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
|
|
@ -248,28 +248,30 @@ up in the manual.
|
|||
::: {#ex-settings-typed-attrs .example}
|
||||
### Declaring a type-checked `settings` attribute
|
||||
```nix
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
{
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
|
||||
freeformType = settingsFormat.type;
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
# Declare an option for the port such that the type is checked and this option
|
||||
# is shown in the manual.
|
||||
options.port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8080;
|
||||
description = ''
|
||||
Which port this service should listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
# Declare an option for the port such that the type is checked and this option
|
||||
# is shown in the manual.
|
||||
options.port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8080;
|
||||
description = ''
|
||||
Which port this service should listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
default = {};
|
||||
description = ''
|
||||
Configuration for Foo, see
|
||||
<link xlink:href="https://example.com/docs/foo"/>
|
||||
for supported values.
|
||||
'';
|
||||
};
|
||||
default = {};
|
||||
description = ''
|
||||
Configuration for Foo, see
|
||||
<link xlink:href="https://example.com/docs/foo"/>
|
||||
for supported values.
|
||||
'';
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
|
|
@ -94,11 +94,13 @@ To make an existing sysinit service restart correctly during system switch, you
|
|||
have to declare:
|
||||
|
||||
```nix
|
||||
systemd.services.my-sysinit = {
|
||||
requiredBy = [ "sysinit-reactivation.target" ];
|
||||
before = [ "sysinit-reactivation.target" ];
|
||||
restartTriggers = [ config.environment.etc."my-sysinit.d".source ];
|
||||
};
|
||||
{
|
||||
systemd.services.my-sysinit = {
|
||||
requiredBy = [ "sysinit-reactivation.target" ];
|
||||
before = [ "sysinit-reactivation.target" ];
|
||||
restartTriggers = [ config.environment.etc."my-sysinit.d".source ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
You need to configure appropriate `restartTriggers` specific to your service.
|
||||
|
|
|
@ -28,7 +28,7 @@ NixOS modules:
|
|||
```nix
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{ option definitions
|
||||
{ # option definitions
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -43,15 +43,15 @@ is shown in [Example: Structure of NixOS Modules](#ex-module-syntax).
|
|||
|
||||
{
|
||||
imports =
|
||||
[ paths of other modules
|
||||
[ # paths of other modules
|
||||
];
|
||||
|
||||
options = {
|
||||
option declarations
|
||||
# option declarations
|
||||
};
|
||||
|
||||
config = {
|
||||
option definitions
|
||||
# option definitions
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -8,10 +8,10 @@ A NixOS test is a module that has the following structure:
|
|||
# One or more machines:
|
||||
nodes =
|
||||
{ machine =
|
||||
{ config, pkgs, ... }: { … };
|
||||
{ config, pkgs, ... }: { /* ... */ };
|
||||
machine2 =
|
||||
{ config, pkgs, ... }: { … };
|
||||
…
|
||||
{ config, pkgs, ... }: { /* ... */ };
|
||||
# …
|
||||
};
|
||||
|
||||
testScript =
|
||||
|
@ -46,16 +46,20 @@ Tests are invoked differently depending on whether the test is part of NixOS or
|
|||
Tests that are part of NixOS are added to [`nixos/tests/all-tests.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/all-tests.nix).
|
||||
|
||||
```nix
|
||||
{
|
||||
hostname = runTest ./hostname.nix;
|
||||
}
|
||||
```
|
||||
|
||||
Overrides can be added by defining an anonymous module in `all-tests.nix`.
|
||||
|
||||
```nix
|
||||
{
|
||||
hostname = runTest {
|
||||
imports = [ ./hostname.nix ];
|
||||
defaults.networking.firewall.enable = false;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
You can run a test with attribute name `hostname` in `nixos/tests/all-tests.nix` by invoking:
|
||||
|
@ -161,7 +165,7 @@ For faster dev cycles it's also possible to disable the code-linters
|
|||
skipLint = true;
|
||||
nodes.machine =
|
||||
{ config, pkgs, ... }:
|
||||
{ configuration…
|
||||
{ # configuration…
|
||||
};
|
||||
|
||||
testScript =
|
||||
|
@ -177,12 +181,14 @@ linter directly (again, don't commit this within the Nixpkgs
|
|||
repository):
|
||||
|
||||
```nix
|
||||
{
|
||||
testScript =
|
||||
''
|
||||
# fmt: off
|
||||
Python code…
|
||||
# fmt: on
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, the type checking of test scripts can be disabled in the following
|
||||
|
@ -193,7 +199,7 @@ way:
|
|||
skipTypeCheck = true;
|
||||
nodes.machine =
|
||||
{ config, pkgs, ... }:
|
||||
{ configuration…
|
||||
{ # configuration…
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -18,11 +18,11 @@ An example of how to build an image:
|
|||
partitions = {
|
||||
"esp" = {
|
||||
contents = {
|
||||
...
|
||||
# ...
|
||||
};
|
||||
repartConfig = {
|
||||
Type = "esp";
|
||||
...
|
||||
# ...
|
||||
};
|
||||
};
|
||||
"root" = {
|
||||
|
@ -30,7 +30,7 @@ An example of how to build an image:
|
|||
repartConfig = {
|
||||
Type = "root";
|
||||
Label = "nixos";
|
||||
...
|
||||
# ...
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -47,19 +47,21 @@ determined by the mount point, you have to set `stripNixStorePrefix = true;` so
|
|||
that the prefix is stripped from the paths before copying them into the image.
|
||||
|
||||
```nix
|
||||
fileSystems."/nix/store".device = "/dev/disk/by-partlabel/nix-store"
|
||||
{
|
||||
fileSystems."/nix/store".device = "/dev/disk/by-partlabel/nix-store";
|
||||
|
||||
image.repart.partitions = {
|
||||
"store" = {
|
||||
storePaths = [ config.system.build.toplevel ];
|
||||
stripNixStorePrefix = true;
|
||||
repartConfig = {
|
||||
Type = "linux-generic";
|
||||
Label = "nix-store";
|
||||
...
|
||||
image.repart.partitions = {
|
||||
"store" = {
|
||||
storePaths = [ config.system.build.toplevel ];
|
||||
stripNixStorePrefix = true;
|
||||
repartConfig = {
|
||||
Type = "linux-generic";
|
||||
Label = "nix-store";
|
||||
# ...
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Appliance Image {#sec-image-repart-appliance}
|
||||
|
|
|
@ -87,7 +87,9 @@ set `mutableUsers = false`. Another way is to temporarily add the
|
|||
following to your configuration:
|
||||
|
||||
```nix
|
||||
users.users.your-user.initialHashedPassword = "test";
|
||||
{
|
||||
users.users.your-user.initialHashedPassword = "test";
|
||||
}
|
||||
```
|
||||
|
||||
*Important:* delete the \$hostname.qcow2 file if you have started the
|
||||
|
|
|
@ -7,8 +7,10 @@ To install NixOS behind a proxy, do the following before running
|
|||
keep the internet accessible after reboot.
|
||||
|
||||
```nix
|
||||
networking.proxy.default = "http://user:password@proxy:port/";
|
||||
networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
|
||||
{
|
||||
networking.proxy.default = "http://user:password@proxy:port/";
|
||||
networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
|
||||
}
|
||||
```
|
||||
|
||||
1. Setup the proxy environment variables in the shell where you are
|
||||
|
|
|
@ -89,12 +89,14 @@ The first steps to all these are the same:
|
|||
want to add something like this to your `configuration.nix`:
|
||||
|
||||
```nix
|
||||
boot.loader.grub.extraEntries = ''
|
||||
menuentry "Ubuntu" {
|
||||
search --set=ubuntu --fs-uuid 3cc3e652-0c1f-4800-8451-033754f68e6e
|
||||
configfile "($ubuntu)/boot/grub/grub.cfg"
|
||||
}
|
||||
'';
|
||||
{
|
||||
boot.loader.grub.extraEntries = ''
|
||||
menuentry "Ubuntu" {
|
||||
search --set=ubuntu --fs-uuid 3cc3e652-0c1f-4800-8451-033754f68e6e
|
||||
configfile "($ubuntu)/boot/grub/grub.cfg"
|
||||
}
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
(You can find the appropriate UUID for your partition in
|
||||
|
@ -164,7 +166,9 @@ The first steps to all these are the same:
|
|||
`sudo passwd -l root` if you use `sudo`)
|
||||
|
||||
```nix
|
||||
users.users.root.initialHashedPassword = "";
|
||||
{
|
||||
users.users.root.initialHashedPassword = "";
|
||||
}
|
||||
```
|
||||
|
||||
1. Build the NixOS closure and install it in the `system` profile:
|
||||
|
|
|
@ -29,14 +29,18 @@ There are a few modifications you should make in configuration.nix.
|
|||
Enable booting:
|
||||
|
||||
```nix
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
{
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
}
|
||||
```
|
||||
|
||||
Also remove the fsck that runs at startup. It will always fail to run,
|
||||
stopping your boot until you press `*`.
|
||||
|
||||
```nix
|
||||
boot.initrd.checkJournalingFS = false;
|
||||
{
|
||||
boot.initrd.checkJournalingFS = false;
|
||||
}
|
||||
```
|
||||
|
||||
Shared folders can be given a name and a path in the host system in the
|
||||
|
|
|
@ -101,8 +101,10 @@ You can keep a NixOS system up-to-date automatically by adding the
|
|||
following to `configuration.nix`:
|
||||
|
||||
```nix
|
||||
system.autoUpgrade.enable = true;
|
||||
system.autoUpgrade.allowReboot = true;
|
||||
{
|
||||
system.autoUpgrade.enable = true;
|
||||
system.autoUpgrade.allowReboot = true;
|
||||
}
|
||||
```
|
||||
|
||||
This enables a periodically executed systemd service named
|
||||
|
@ -114,5 +116,7 @@ the new generation contains a different kernel, initrd or kernel
|
|||
modules. You can also specify a channel explicitly, e.g.
|
||||
|
||||
```nix
|
||||
system.autoUpgrade.channel = "https://channels.nixos.org/nixos-23.11";
|
||||
{
|
||||
system.autoUpgrade.channel = "https://channels.nixos.org/nixos-23.11";
|
||||
}
|
||||
```
|
||||
|
|
|
@ -253,9 +253,9 @@ Installing Haskell _libraries_ this way, however, is no longer supported. See th
|
|||
|
||||
{
|
||||
options = {
|
||||
foo = mkOption { … };
|
||||
foo = mkOption { /* … */ };
|
||||
};
|
||||
config = mkIf config.foo { … };
|
||||
config = mkIf config.foo { /* … */ };
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -268,9 +268,9 @@ Installing Haskell _libraries_ this way, however, is no longer supported. See th
|
|||
|
||||
{
|
||||
options = {
|
||||
foo = mkOption { option declaration };
|
||||
foo = mkOption { /* option declaration */ };
|
||||
};
|
||||
config = mkIf config.foo { option definition };
|
||||
config = mkIf config.foo { /* option definition */ };
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
let
|
||||
pkgs = import <nixpkgs> {};
|
||||
in
|
||||
pkgs.overridePackages (self: super: ...)
|
||||
pkgs.overridePackages (self: super: { /* ... */ })
|
||||
```
|
||||
|
||||
should be replaced by:
|
||||
|
@ -255,7 +255,7 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
let
|
||||
pkgs = import <nixpkgs> {};
|
||||
in
|
||||
import pkgs.path { overlays = [(self: super: ...)]; }
|
||||
import pkgs.path { overlays = [(self: super: { /* ... */ })]; }
|
||||
```
|
||||
|
||||
- Autoloading connection tracking helpers is now disabled by default. This default was also changed in the Linux kernel and is considered insecure if not configured properly in your firewall. If you need connection tracking helpers (i.e. for active FTP) please enable `networking.firewall.autoLoadConntrackHelpers` and tune `networking.firewall.connectionTrackingModules` to suit your needs.
|
||||
|
|
|
@ -334,22 +334,18 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
- The remaining configuration flags can now be set directly on the `php` attribute. For example, instead of
|
||||
|
||||
```nix
|
||||
{
|
||||
php.override {
|
||||
config.php.embed = true;
|
||||
config.php.apxs2 = false;
|
||||
}
|
||||
php.override {
|
||||
config.php.embed = true;
|
||||
config.php.apxs2 = false;
|
||||
}
|
||||
```
|
||||
|
||||
you should now write
|
||||
|
||||
```nix
|
||||
{
|
||||
php.override {
|
||||
embedSupport = true;
|
||||
apxs2Support = false;
|
||||
}
|
||||
php.override {
|
||||
embedSupport = true;
|
||||
apxs2Support = false;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -383,9 +379,10 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
{
|
||||
specialisation.example-sub-configuration = {
|
||||
configuration = {
|
||||
...
|
||||
# ...
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Replace a `nesting.children` entry with:
|
||||
|
@ -395,9 +392,10 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
specialisation.example-sub-configuration = {
|
||||
inheritParentConfig = false;
|
||||
configuration = {
|
||||
...
|
||||
# ...
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
To switch to a specialised configuration at runtime you need to run:
|
||||
|
@ -469,7 +467,7 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
services.bitcoind = {
|
||||
enable = true;
|
||||
extraConfig = "...";
|
||||
...
|
||||
# ...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
@ -483,7 +481,7 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
dataDir = "/var/lib/bitcoind";
|
||||
user = "bitcoin";
|
||||
extraConfig = "...";
|
||||
...
|
||||
# ...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
@ -502,7 +500,7 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
{
|
||||
services.dokuwiki = {
|
||||
enable = true;
|
||||
...
|
||||
# ...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
@ -517,7 +515,7 @@ When upgrading from a previous release, please be aware of the following incompa
|
|||
forceSSL = true;
|
||||
enableACME = true;
|
||||
};
|
||||
...
|
||||
# ...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -462,6 +462,7 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
Before:
|
||||
```nix
|
||||
{
|
||||
services.keycloak = {
|
||||
enable = true;
|
||||
httpPort = "8080";
|
||||
|
@ -471,10 +472,12 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
"subsystem=undertow"."server=default-server"."http-listener=default".proxy-address-forwarding = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
```nix
|
||||
{
|
||||
services.keycloak = {
|
||||
enable = true;
|
||||
settings = {
|
||||
|
@ -485,6 +488,7 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
};
|
||||
database.passwordFile = "/run/keys/db_password";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- The MoinMoin wiki engine (`services.moinmoin`) has been removed, because Python 2 is being retired from nixpkgs.
|
||||
|
|
|
@ -255,9 +255,11 @@ In addition to numerous new and upgraded packages, this release includes the fol
|
|||
- `services.github-runner` and `services.github-runners.<name>` gained the option `serviceOverrides` which allows overriding the systemd `serviceConfig`. If you have been overriding the systemd service configuration (i.e., by defining `systemd.services.github-runner.serviceConfig`), you have to use the `serviceOverrides` option now. Example:
|
||||
|
||||
```nix
|
||||
services.github-runner.serviceOverrides.SupplementaryGroups = [
|
||||
"docker"
|
||||
];
|
||||
{
|
||||
services.github-runner.serviceOverrides.SupplementaryGroups = [
|
||||
"docker"
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
|
|
@ -25,7 +25,9 @@ In addition to numerous new and updated packages, this release has the following
|
|||
|
||||
- NixOS now defaults to using [nsncd](https://github.com/twosigma/nsncd), a non-caching reimplementation of nscd in Rust, as its NSS lookup dispatcher. This replaces the buggy and deprecated nscd implementation provided through glibc. When you find problems, you can switch back by disabling it:
|
||||
```nix
|
||||
services.nscd.enableNsncd = false;
|
||||
{
|
||||
services.nscd.enableNsncd = false;
|
||||
}
|
||||
```
|
||||
|
||||
- The internal option `boot.bootspec.enable` is now enabled by default because [RFC 0125](https://github.com/NixOS/rfcs/pull/125) was merged. This means you will have a bootspec document called `boot.json` generated for each system and specialisation in the top-level. This is useful to enable advanced boot use cases in NixOS, such as Secure Boot.
|
||||
|
@ -190,11 +192,13 @@ In addition to numerous new and updated packages, this release has the following
|
|||
- MAC-then-encrypt algorithms were removed from the default selection of `services.openssh.settings.Macs`. If you still require these [MACs](https://en.wikipedia.org/wiki/Message_authentication_code), for example when you are relying on libssh2 (e.g. VLC) or the SSH library shipped on the iPhone, you can re-add them like this:
|
||||
|
||||
```nix
|
||||
services.openssh.settings.Macs = [
|
||||
"hmac-sha2-512"
|
||||
"hmac-sha2-256"
|
||||
"umac-128@openssh.com"
|
||||
];
|
||||
{
|
||||
services.openssh.settings.Macs = [
|
||||
"hmac-sha2-512"
|
||||
"hmac-sha2-256"
|
||||
"umac-128@openssh.com"
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
- `podman` now uses the `netavark` network stack. Users will need to delete all of their local containers, images, volumes, etc, by running `podman system reset --force` once before upgrading their systems.
|
||||
|
@ -227,21 +231,25 @@ In addition to numerous new and updated packages, this release has the following
|
|||
- The attributes used by `services.snapper.configs.<name>` have changed. Migrate from this:
|
||||
|
||||
```nix
|
||||
services.snapper.configs.example = {
|
||||
subvolume = "/example";
|
||||
extraConfig = ''
|
||||
ALLOW_USERS="alice"
|
||||
'';
|
||||
};
|
||||
{
|
||||
services.snapper.configs.example = {
|
||||
subvolume = "/example";
|
||||
extraConfig = ''
|
||||
ALLOW_USERS="alice"
|
||||
'';
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
to this:
|
||||
|
||||
```nix
|
||||
services.snapper.configs.example = {
|
||||
SUBVOLUME = "/example";
|
||||
ALLOW_USERS = [ "alice" ];
|
||||
};
|
||||
{
|
||||
services.snapper.configs.example = {
|
||||
SUBVOLUME = "/example";
|
||||
ALLOW_USERS = [ "alice" ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- The default module options for [services.snapserver.openFirewall](#opt-services.snapserver.openFirewall), [services.tmate-ssh-server.openFirewall](#opt-services.tmate-ssh-server.openFirewall) and [services.unifi-video.openFirewall](#opt-services.unifi-video.openFirewall) have been changed from `true` to `false`. You will need to explicitly set this option to `true`, or configure your firewall.
|
||||
|
@ -446,15 +454,17 @@ In addition to numerous new and updated packages, this release has the following
|
|||
- NixOS swap partitions with random encryption can now control the sector size, cipher, and key size used to set up the plain encryption device over the underlying block device rather than allowing them to be determined by `cryptsetup(8)`. One can use these features like so:
|
||||
|
||||
```nix
|
||||
swapDevices = [ {
|
||||
device = "/dev/disk/by-partlabel/swapspace";
|
||||
randomEncryption = {
|
||||
enable = true;
|
||||
cipher = "aes-xts-plain64";
|
||||
keySize = 512;
|
||||
sectorSize = 4096;
|
||||
};
|
||||
} ];
|
||||
{
|
||||
swapDevices = [ {
|
||||
device = "/dev/disk/by-partlabel/swapspace";
|
||||
randomEncryption = {
|
||||
enable = true;
|
||||
cipher = "aes-xts-plain64";
|
||||
keySize = 512;
|
||||
sectorSize = 4096;
|
||||
};
|
||||
} ];
|
||||
}
|
||||
```
|
||||
|
||||
- New option `security.pam.zfs` to enable unlocking and mounting of encrypted ZFS home dataset at login.
|
||||
|
@ -465,7 +475,9 @@ In addition to numerous new and updated packages, this release has the following
|
|||
|
||||
- PostgreSQL has added opt-in support for [JIT compilation](https://www.postgresql.org/docs/current/jit-reason.html). It can be enabled like this:
|
||||
```nix
|
||||
services.postgresql.enableJIT = true;
|
||||
{
|
||||
services.postgresql.enableJIT = true;
|
||||
}
|
||||
```
|
||||
|
||||
- `services.netdata` offers a [`services.netdata.deadlineBeforeStopSec`](#opt-services.netdata.deadlineBeforeStopSec) option which will control the deadline (in seconds) after which systemd will consider your netdata instance as dead if it didn't start in the elapsed time. It is helpful when your netdata instance takes longer to start because of a large amount of state or upgrades.
|
||||
|
|
|
@ -700,11 +700,13 @@ Make sure to also check the many updates in the [Nixpkgs library](#sec-release-2
|
|||
will probably be removed eventually.
|
||||
|
||||
```nix
|
||||
qt = {
|
||||
enable = true;
|
||||
platformTheme = "gnome";
|
||||
style = "adwaita";
|
||||
};
|
||||
{
|
||||
qt = {
|
||||
enable = true;
|
||||
platformTheme = "gnome";
|
||||
style = "adwaita";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- DocBook option documentation is no longer supported, all module documentation
|
||||
|
@ -885,11 +887,13 @@ Make sure to also check the many updates in the [Nixpkgs library](#sec-release-2
|
|||
to a compatible major version, so they can move at their own pace.
|
||||
|
||||
```nix
|
||||
python = python3.override {
|
||||
packageOverrides = self: super: {
|
||||
django = super.django_3;
|
||||
{
|
||||
python = python3.override {
|
||||
packageOverrides = self: super: {
|
||||
django = super.django_3;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- The `qemu-vm.nix` module by default now identifies block devices via
|
||||
|
@ -1229,15 +1233,17 @@ Make sure to also check the many updates in the [Nixpkgs library](#sec-release-2
|
|||
overriding `externalPlugins` and `vendorHash` arguments like this:
|
||||
|
||||
```nix
|
||||
services.coredns = {
|
||||
enable = true;
|
||||
package = pkgs.coredns.override {
|
||||
externalPlugins = [
|
||||
{name = "fanout"; repo = "github.com/networkservicemesh/fanout"; version = "v1.9.1";}
|
||||
];
|
||||
vendorHash = "<SRI hash>";
|
||||
{
|
||||
services.coredns = {
|
||||
enable = true;
|
||||
package = pkgs.coredns.override {
|
||||
externalPlugins = [
|
||||
{name = "fanout"; repo = "github.com/networkservicemesh/fanout"; version = "v1.9.1";}
|
||||
];
|
||||
vendorHash = "<SRI hash>";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
To get the necessary SRI hash, set `vendorHash = "";`. The build will fail
|
||||
|
|
|
@ -223,13 +223,14 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
|||
Example:
|
||||
|
||||
```nix
|
||||
{
|
||||
locations."/".extraConfig = ''
|
||||
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
|
||||
'';
|
||||
locations."^~ /assets/".extraConfig = ''
|
||||
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
|
||||
'';
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
- The package `optparse-bash` is now dropped due to upstream inactivity. Alternatives available in Nixpkgs include [`argc`](https://github.com/sigoden/argc), [`argbash`](https://github.com/matejak/argbash), [`bashly`](https://github.com/DannyBen/bashly) and [`gum`](https://github.com/charmbracelet/gum), to name a few.
|
||||
|
|
|
@ -23,10 +23,12 @@ friendly input method user interface.
|
|||
The following snippet can be used to configure IBus:
|
||||
|
||||
```nix
|
||||
i18n.inputMethod = {
|
||||
enabled = "ibus";
|
||||
ibus.engines = with pkgs.ibus-engines; [ anthy hangul mozc ];
|
||||
};
|
||||
{
|
||||
i18n.inputMethod = {
|
||||
enabled = "ibus";
|
||||
ibus.engines = with pkgs.ibus-engines; [ anthy hangul mozc ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`i18n.inputMethod.ibus.engines` is optional and can be used
|
||||
|
@ -49,7 +51,9 @@ Available extra IBus engines are:
|
|||
`table`. For example:
|
||||
|
||||
```nix
|
||||
ibus.engines = with pkgs.ibus-engines; [ table table-others ];
|
||||
{
|
||||
ibus.engines = with pkgs.ibus-engines; [ table table-others ];
|
||||
}
|
||||
```
|
||||
|
||||
To use any input method, the package must be added in the configuration, as
|
||||
|
@ -75,10 +79,12 @@ built-in Input Method Engine, Pinyin, QuWei and Table-based input methods.
|
|||
The following snippet can be used to configure Fcitx:
|
||||
|
||||
```nix
|
||||
i18n.inputMethod = {
|
||||
enabled = "fcitx5";
|
||||
fcitx5.addons = with pkgs; [ fcitx5-mozc fcitx5-hangul fcitx5-m17n ];
|
||||
};
|
||||
{
|
||||
i18n.inputMethod = {
|
||||
enabled = "fcitx5";
|
||||
fcitx5.addons = with pkgs; [ fcitx5-mozc fcitx5-hangul fcitx5-m17n ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`i18n.inputMethod.fcitx5.addons` is optional and can be
|
||||
|
@ -111,9 +117,11 @@ phonetic Korean characters (hangul) and pictographic Korean characters
|
|||
The following snippet can be used to configure Nabi:
|
||||
|
||||
```nix
|
||||
i18n.inputMethod = {
|
||||
enabled = "nabi";
|
||||
};
|
||||
{
|
||||
i18n.inputMethod = {
|
||||
enabled = "nabi";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Uim {#module-services-input-methods-uim}
|
||||
|
@ -124,9 +132,11 @@ framework. Applications can use it through so-called bridges.
|
|||
The following snippet can be used to configure uim:
|
||||
|
||||
```nix
|
||||
i18n.inputMethod = {
|
||||
enabled = "uim";
|
||||
};
|
||||
{
|
||||
i18n.inputMethod = {
|
||||
enabled = "uim";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Note: The [](#opt-i18n.inputMethod.uim.toolbar) option can be
|
||||
|
@ -142,9 +152,11 @@ etc...
|
|||
The following snippet can be used to configure Hime:
|
||||
|
||||
```nix
|
||||
i18n.inputMethod = {
|
||||
enabled = "hime";
|
||||
};
|
||||
{
|
||||
i18n.inputMethod = {
|
||||
enabled = "hime";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Kime {#module-services-input-methods-kime}
|
||||
|
@ -154,7 +166,9 @@ Kime is Korean IME. it's built with Rust language and let you get simple, safe,
|
|||
The following snippet can be used to configure Kime:
|
||||
|
||||
```nix
|
||||
i18n.inputMethod = {
|
||||
enabled = "kime";
|
||||
};
|
||||
{
|
||||
i18n.inputMethod = {
|
||||
enabled = "kime";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -5,7 +5,9 @@ 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
|
||||
```nix
|
||||
programs.digitalbitbox.enable = true;
|
||||
{
|
||||
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
|
||||
|
@ -22,9 +24,11 @@ For more information, see <https://digitalbitbox.com/start_linux>.
|
|||
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:
|
||||
```nix
|
||||
environment.systemPackages = [
|
||||
pkgs.digitalbitbox
|
||||
];
|
||||
{
|
||||
environment.systemPackages = [
|
||||
pkgs.digitalbitbox
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Hardware {#sec-digitalbitbox-hardware-module}
|
||||
|
@ -32,16 +36,20 @@ environment.systemPackages = [
|
|||
The digitalbitbox hardware package enables the udev rules for Digital Bitbox
|
||||
devices and may be installed as follows:
|
||||
```nix
|
||||
hardware.digitalbitbox.enable = true;
|
||||
{
|
||||
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:
|
||||
```nix
|
||||
programs.digitalbitbox = {
|
||||
enable = true;
|
||||
package = pkgs.digitalbitbox.override {
|
||||
udevRule51 = "something else";
|
||||
{
|
||||
programs.digitalbitbox = {
|
||||
enable = true;
|
||||
package = pkgs.digitalbitbox.override {
|
||||
udevRule51 = "something else";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -13,5 +13,7 @@ palette provides a searchable list of of all menu items in the application.
|
|||
To enable Plotinus, add the following to your
|
||||
{file}`configuration.nix`:
|
||||
```nix
|
||||
programs.plotinus.enable = true;
|
||||
{
|
||||
programs.plotinus.enable = true;
|
||||
}
|
||||
```
|
||||
|
|
|
@ -46,33 +46,35 @@ certs are overwritten when the ACME certs arrive. For
|
|||
`foo.example.com` the config would look like this:
|
||||
|
||||
```nix
|
||||
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";
|
||||
{
|
||||
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";
|
||||
# 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}
|
||||
|
@ -89,65 +91,69 @@ the intent that you will generate certs for all your vhosts and redirect
|
|||
everyone to HTTPS.
|
||||
|
||||
```nix
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.defaults.email = "admin+acme@example.com";
|
||||
{
|
||||
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" ];
|
||||
# /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";
|
||||
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]
|
||||
'';
|
||||
# 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.
|
||||
|
||||
```nix
|
||||
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" ];
|
||||
};
|
||||
{
|
||||
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
|
||||
|
@ -168,31 +174,33 @@ for provider/server specific configuration values. For the sake of these
|
|||
docs, we will provide a fully self-hosted example using bind.
|
||||
|
||||
```nix
|
||||
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.; };";
|
||||
}
|
||||
];
|
||||
};
|
||||
{
|
||||
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";
|
||||
environmentFile = "/var/lib/secrets/certs.secret";
|
||||
# We don't need to wait for propagation since this is a local DNS server
|
||||
dnsPropagationCheck = false;
|
||||
};
|
||||
# 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";
|
||||
environmentFile = "/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`
|
||||
|
@ -200,36 +208,38 @@ 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:
|
||||
|
||||
```nix
|
||||
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
|
||||
{
|
||||
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
|
||||
# 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
|
||||
'';
|
||||
};
|
||||
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
|
||||
|
@ -251,27 +261,29 @@ you will set them as defaults
|
|||
(e.g. [](#opt-security.acme.defaults.dnsProvider)).
|
||||
|
||||
```nix
|
||||
# Configure ACME appropriately
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.defaults.email = "admin+acme@example.com";
|
||||
security.acme.defaults = {
|
||||
dnsProvider = "rfc2136";
|
||||
environmentFile = "/var/lib/secrets/certs.secret";
|
||||
# We don't need to wait for propagation since this is a local DNS server
|
||||
dnsPropagationCheck = false;
|
||||
};
|
||||
{
|
||||
# Configure ACME appropriately
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.defaults.email = "admin+acme@example.com";
|
||||
security.acme.defaults = {
|
||||
dnsProvider = "rfc2136";
|
||||
environmentFile = "/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;
|
||||
# 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
|
||||
|
@ -288,39 +300,41 @@ Below is an example configuration for OpenSMTPD, but this pattern
|
|||
can be applied to any service.
|
||||
|
||||
```nix
|
||||
# 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
|
||||
{
|
||||
# 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}
|
||||
|
|
|
@ -7,16 +7,18 @@ Castopod is an open-source hosting platform made for podcasters who want to enga
|
|||
Use the following configuration to start a public instance of Castopod on `castopod.example.com` domain:
|
||||
|
||||
```nix
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
services.castopod = {
|
||||
enable = true;
|
||||
database.createLocally = true;
|
||||
nginx.virtualHost = {
|
||||
serverName = "castopod.example.com";
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
services.castopod = {
|
||||
enable = true;
|
||||
database.createLocally = true;
|
||||
nginx.virtualHost = {
|
||||
serverName = "castopod.example.com";
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Go to `https://castopod.example.com/cp-install` to create superadmin account after applying the above configuration.
|
||||
|
|
|
@ -24,19 +24,18 @@ A very basic configuration for backing up to a locally accessible directory is:
|
|||
```nix
|
||||
{
|
||||
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";
|
||||
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";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
@ -96,7 +95,7 @@ accessible by root
|
|||
startAt = "hourly";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The following few commands (run as root) let you test your backup.
|
||||
|
|
|
@ -16,8 +16,10 @@ key-value store.
|
|||
To enable FoundationDB, add the following to your
|
||||
{file}`configuration.nix`:
|
||||
```nix
|
||||
services.foundationdb.enable = true;
|
||||
services.foundationdb.package = pkgs.foundationdb71; # FoundationDB 7.1.x
|
||||
{
|
||||
services.foundationdb.enable = true;
|
||||
services.foundationdb.package = pkgs.foundationdb71; # FoundationDB 7.1.x
|
||||
}
|
||||
```
|
||||
|
||||
The {option}`services.foundationdb.package` option is required, and
|
||||
|
@ -110,7 +112,9 @@ FoundationDB stores all data for all server processes under
|
|||
{file}`/var/lib/foundationdb`. You can override this using
|
||||
{option}`services.foundationdb.dataDir`, e.g.
|
||||
```nix
|
||||
services.foundationdb.dataDir = "/data/fdb";
|
||||
{
|
||||
services.foundationdb.dataDir = "/data/fdb";
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, logs are stored under {file}`/var/log/foundationdb`
|
||||
|
@ -266,7 +270,9 @@ For example, to create backups in {command}`/opt/fdb-backups`, first
|
|||
set up the paths in the module options:
|
||||
|
||||
```nix
|
||||
services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ];
|
||||
{
|
||||
services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ];
|
||||
}
|
||||
```
|
||||
|
||||
Restart the FoundationDB service, and it will now be able to write to this
|
||||
|
|
|
@ -16,8 +16,10 @@ PostgreSQL is an advanced, free relational database.
|
|||
|
||||
To enable PostgreSQL, add the following to your {file}`configuration.nix`:
|
||||
```nix
|
||||
services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql_15;
|
||||
{
|
||||
services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql_15;
|
||||
}
|
||||
```
|
||||
Note that you are required to specify the desired version of PostgreSQL (e.g. `pkgs.postgresql_15`). 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.
|
||||
|
||||
|
@ -36,7 +38,9 @@ alice=>
|
|||
|
||||
By default, PostgreSQL stores its databases in {file}`/var/lib/postgresql/$psqlSchema`. You can override this using [](#opt-services.postgresql.dataDir), e.g.
|
||||
```nix
|
||||
services.postgresql.dataDir = "/data/postgresql";
|
||||
{
|
||||
services.postgresql.dataDir = "/data/postgresql";
|
||||
}
|
||||
```
|
||||
|
||||
## Initializing {#module-services-postgres-initializing}
|
||||
|
@ -95,16 +99,19 @@ databases from `ensureDatabases` and `extraUser1` from `ensureUsers`
|
|||
are already created.
|
||||
|
||||
```nix
|
||||
{
|
||||
systemd.services.postgresql.postStart = lib.mkAfter ''
|
||||
$PSQL service1 -c 'GRANT SELECT ON ALL TABLES IN SCHEMA public TO "extraUser1"'
|
||||
$PSQL service1 -c 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO "extraUser1"'
|
||||
# ....
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
##### in intermediate oneshot service {#module-services-postgres-initializing-extra-permissions-superuser-oneshot}
|
||||
|
||||
```nix
|
||||
{
|
||||
systemd.services."migrate-service1-db1" = {
|
||||
serviceConfig.Type = "oneshot";
|
||||
requiredBy = "service1.service";
|
||||
|
@ -119,6 +126,7 @@ are already created.
|
|||
# ....
|
||||
'';
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### as service user {#module-services-postgres-initializing-extra-permissions-service-user}
|
||||
|
@ -130,6 +138,7 @@ are already created.
|
|||
##### in service `preStart` {#module-services-postgres-initializing-extra-permissions-service-user-pre-start}
|
||||
|
||||
```nix
|
||||
{
|
||||
environment.PSQL = "psql --port=${toString services.postgresql.port}";
|
||||
path = [ postgresql ];
|
||||
systemd.services."service1".preStart = ''
|
||||
|
@ -137,11 +146,13 @@ are already created.
|
|||
$PSQL -c 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO "extraUser1"'
|
||||
# ....
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
##### in intermediate oneshot service {#module-services-postgres-initializing-extra-permissions-service-user-oneshot}
|
||||
|
||||
```nix
|
||||
{
|
||||
systemd.services."migrate-service1-db1" = {
|
||||
serviceConfig.Type = "oneshot";
|
||||
requiredBy = "service1.service";
|
||||
|
@ -156,6 +167,7 @@ are already created.
|
|||
# ....
|
||||
'';
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Upgrading {#module-services-postgres-upgrading}
|
||||
|
@ -257,11 +269,13 @@ postgresql_15.pkgs.pg_partman postgresql_15.pkgs.pgroonga
|
|||
|
||||
To add plugins via NixOS configuration, set `services.postgresql.extraPlugins`:
|
||||
```nix
|
||||
services.postgresql.package = pkgs.postgresql_12;
|
||||
services.postgresql.extraPlugins = ps: with ps; [
|
||||
pg_repack
|
||||
postgis
|
||||
];
|
||||
{
|
||||
services.postgresql.package = pkgs.postgresql_12;
|
||||
services.postgresql.extraPlugins = ps: with ps; [
|
||||
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:
|
||||
|
|
|
@ -8,7 +8,9 @@ TigerBeetle is a distributed financial accounting database designed for mission
|
|||
|
||||
To enable TigerBeetle, add the following to your {file}`configuration.nix`:
|
||||
```nix
|
||||
{
|
||||
services.tigerbeetle.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
When first started, the TigerBeetle service will create its data file at {file}`/var/lib/tigerbeetle` unless the file already exists, in which case it will just use the existing file.
|
||||
|
@ -21,12 +23,14 @@ To configure it to listen on a different interface (and to configure it to conne
|
|||
Note that the TigerBeetle module won't open any firewall ports automatically, so if you configure it to listen on an external interface, you'll need to ensure that connections can reach it:
|
||||
|
||||
```nix
|
||||
{
|
||||
services.tigerbeetle = {
|
||||
enable = true;
|
||||
addresses = [ "0.0.0.0:3001" ];
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 3001 ];
|
||||
}
|
||||
```
|
||||
|
||||
A complete list of options for TigerBeetle can be found [here](#opt-services.tigerbeetle.enable).
|
||||
|
|
|
@ -9,7 +9,9 @@ applications on Linux.
|
|||
|
||||
To enable Flatpak, add the following to your {file}`configuration.nix`:
|
||||
```nix
|
||||
{
|
||||
services.flatpak.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
For the sandboxed apps to work correctly, desktop integration portals need to
|
||||
|
@ -17,8 +19,10 @@ 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`:
|
||||
```nix
|
||||
{
|
||||
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
|
||||
xdg.portal.config.common.default = "gtk";
|
||||
}
|
||||
```
|
||||
|
||||
Then, you will need to add a repository, for example,
|
||||
|
|
|
@ -42,7 +42,7 @@ To use the local proxy in Go builds, you can set the proxy as environment variab
|
|||
```nix
|
||||
{
|
||||
environment.variables = {
|
||||
GOPROXY = "http://localhost:3000"
|
||||
GOPROXY = "http://localhost:3000";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -52,5 +52,7 @@ learning Kinos require `gcc` and `gnumake`. To add these, use
|
|||
`extraPackages`:
|
||||
|
||||
```nix
|
||||
services.livebook.extraPackages = with pkgs; [ gcc gnumake ];
|
||||
{
|
||||
services.livebook.extraPackages = with pkgs; [ gcc gnumake ];
|
||||
}
|
||||
```
|
||||
|
|
|
@ -242,7 +242,7 @@ let
|
|||
rm $out/share/applications/emacs.desktop
|
||||
'';
|
||||
});
|
||||
in [...]
|
||||
in [ /* ... */ ]
|
||||
```
|
||||
:::
|
||||
|
||||
|
@ -263,7 +263,9 @@ with the user's login session.
|
|||
To install and enable the {command}`systemd` user service for Emacs
|
||||
daemon, add the following to your {file}`configuration.nix`:
|
||||
```nix
|
||||
services.emacs.enable = true;
|
||||
{
|
||||
services.emacs.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
The {var}`services.emacs.package` option allows a custom
|
||||
|
@ -324,8 +326,10 @@ 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:
|
||||
```nix
|
||||
services.emacs.enable = false;
|
||||
services.emacs.install = true;
|
||||
{
|
||||
services.emacs.enable = false;
|
||||
services.emacs.install = true;
|
||||
}
|
||||
```
|
||||
|
||||
To enable the {command}`systemd` user service for just the
|
||||
|
|
|
@ -10,7 +10,9 @@ framework for Matrix.
|
|||
2. If you want to use PostgreSQL instead of SQLite, do this:
|
||||
|
||||
```nix
|
||||
services.maubot.settings.database = "postgresql://maubot@localhost/maubot";
|
||||
{
|
||||
services.maubot.settings.database = "postgresql://maubot@localhost/maubot";
|
||||
}
|
||||
```
|
||||
|
||||
If the PostgreSQL connection requires a password, you will have to
|
||||
|
@ -18,54 +20,58 @@ framework for Matrix.
|
|||
3. If you plan to expose your Maubot interface to the web, do something
|
||||
like this:
|
||||
```nix
|
||||
services.nginx.virtualHosts."matrix.example.org".locations = {
|
||||
"/_matrix/maubot/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString config.services.maubot.settings.server.port}";
|
||||
proxyWebsockets = true;
|
||||
{
|
||||
services.nginx.virtualHosts."matrix.example.org".locations = {
|
||||
"/_matrix/maubot/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString config.services.maubot.settings.server.port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
services.maubot.settings.server.public_url = "matrix.example.org";
|
||||
# do the following only if you want to use something other than /_matrix/maubot...
|
||||
services.maubot.settings.server.ui_base_path = "/another/base/path";
|
||||
services.maubot.settings.server.public_url = "matrix.example.org";
|
||||
# do the following only if you want to use something other than /_matrix/maubot...
|
||||
services.maubot.settings.server.ui_base_path = "/another/base/path";
|
||||
}
|
||||
```
|
||||
4. Optionally, set `services.maubot.pythonPackages` to a list of python3
|
||||
packages to make available for Maubot plugins.
|
||||
5. Optionally, set `services.maubot.plugins` to a list of Maubot
|
||||
plugins (full list available at https://plugins.maubot.xyz/):
|
||||
```nix
|
||||
services.maubot.plugins = with config.services.maubot.package.plugins; [
|
||||
reactbot
|
||||
# This will only change the default config! After you create a
|
||||
# plugin instance, the default config will be copied into that
|
||||
# instance's config in Maubot's database, and further base config
|
||||
# changes won't affect the running plugin.
|
||||
(rss.override {
|
||||
base_config = {
|
||||
update_interval = 60;
|
||||
max_backoff = 7200;
|
||||
spam_sleep = 2;
|
||||
command_prefix = "rss";
|
||||
admins = [ "@chayleaf:pavluk.org" ];
|
||||
};
|
||||
})
|
||||
];
|
||||
# ...or...
|
||||
services.maubot.plugins = config.services.maubot.package.plugins.allOfficialPlugins;
|
||||
# ...or...
|
||||
services.maubot.plugins = config.services.maubot.package.plugins.allPlugins;
|
||||
# ...or...
|
||||
services.maubot.plugins = with config.services.maubot.package.plugins; [
|
||||
(weather.override {
|
||||
# you can pass base_config as a string
|
||||
base_config = ''
|
||||
default_location: New York
|
||||
default_units: M
|
||||
default_language:
|
||||
show_link: true
|
||||
show_image: false
|
||||
'';
|
||||
})
|
||||
];
|
||||
{
|
||||
services.maubot.plugins = with config.services.maubot.package.plugins; [
|
||||
reactbot
|
||||
# This will only change the default config! After you create a
|
||||
# plugin instance, the default config will be copied into that
|
||||
# instance's config in Maubot's database, and further base config
|
||||
# changes won't affect the running plugin.
|
||||
(rss.override {
|
||||
base_config = {
|
||||
update_interval = 60;
|
||||
max_backoff = 7200;
|
||||
spam_sleep = 2;
|
||||
command_prefix = "rss";
|
||||
admins = [ "@chayleaf:pavluk.org" ];
|
||||
};
|
||||
})
|
||||
];
|
||||
# ...or...
|
||||
services.maubot.plugins = config.services.maubot.package.plugins.allOfficialPlugins;
|
||||
# ...or...
|
||||
services.maubot.plugins = config.services.maubot.package.plugins.allPlugins;
|
||||
# ...or...
|
||||
services.maubot.plugins = with config.services.maubot.package.plugins; [
|
||||
(weather.override {
|
||||
# you can pass base_config as a string
|
||||
base_config = ''
|
||||
default_location: New York
|
||||
default_units: M
|
||||
default_language:
|
||||
show_link: true
|
||||
show_image: false
|
||||
'';
|
||||
})
|
||||
];
|
||||
}
|
||||
```
|
||||
6. Start Maubot at least once before doing the following steps (it's
|
||||
necessary to generate the initial config).
|
||||
|
|
|
@ -57,23 +57,25 @@ locations and database, instead of having to copy or rename them.
|
|||
Make sure to disable `services.gitea`, when doing this.
|
||||
|
||||
```nix
|
||||
services.gitea.enable = false;
|
||||
{
|
||||
services.gitea.enable = false;
|
||||
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
user = "gitea";
|
||||
group = "gitea";
|
||||
stateDir = "/var/lib/gitea";
|
||||
database.name = "gitea";
|
||||
database.user = "gitea";
|
||||
};
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
user = "gitea";
|
||||
group = "gitea";
|
||||
stateDir = "/var/lib/gitea";
|
||||
database.name = "gitea";
|
||||
database.user = "gitea";
|
||||
};
|
||||
|
||||
users.users.gitea = {
|
||||
home = "/var/lib/gitea";
|
||||
useDefaultShell = true;
|
||||
group = "gitea";
|
||||
isSystemUser = true;
|
||||
};
|
||||
users.users.gitea = {
|
||||
home = "/var/lib/gitea";
|
||||
useDefaultShell = true;
|
||||
group = "gitea";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
users.groups.gitea = {};
|
||||
users.groups.gitea = {};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -11,18 +11,20 @@ configure a webserver to proxy HTTP requests to the socket.
|
|||
For instance, the following configuration could be used to use nginx as
|
||||
frontend proxy:
|
||||
```nix
|
||||
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";
|
||||
{
|
||||
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}
|
||||
|
@ -36,35 +38,37 @@ all data like the repositories and uploads will be stored.
|
|||
|
||||
A basic configuration with some custom settings could look like this:
|
||||
```nix
|
||||
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 = {
|
||||
{
|
||||
services.gitlab = {
|
||||
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; };
|
||||
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
|
||||
|
|
|
@ -66,9 +66,9 @@ in {
|
|||
# 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:
|
||||
"meta.${fqdn}".useACMEHost = fqdn;
|
||||
"man.${fqdn}".useACMEHost = fqdn;
|
||||
"git.${fqdn}".useACMEHost = fqdn;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,17 +9,19 @@ A basic config that notifies you of all certificate changes for your
|
|||
domain would look as follows:
|
||||
|
||||
```nix
|
||||
services.certspotter = {
|
||||
enable = true;
|
||||
# replace example.org with your domain name
|
||||
watchlist = [ ".example.org" ];
|
||||
emailRecipients = [ "webmaster@example.org" ];
|
||||
};
|
||||
{
|
||||
services.certspotter = {
|
||||
enable = true;
|
||||
# replace example.org with your domain name
|
||||
watchlist = [ ".example.org" ];
|
||||
emailRecipients = [ "webmaster@example.org" ];
|
||||
};
|
||||
|
||||
# Configure an SMTP client
|
||||
programs.msmtp.enable = true;
|
||||
# Or you can use any other module that provides sendmail, like
|
||||
# services.nullmailer, services.opensmtpd, services.postfix
|
||||
# Configure an SMTP client
|
||||
programs.msmtp.enable = true;
|
||||
# Or you can use any other module that provides sendmail, like
|
||||
# services.nullmailer, services.opensmtpd, services.postfix
|
||||
}
|
||||
```
|
||||
|
||||
In this case, the leading dot in `".example.org"` means that Cert
|
||||
|
@ -59,16 +61,18 @@ For example, you can remove `emailRecipients` and send email
|
|||
notifications manually using the following hook:
|
||||
|
||||
```nix
|
||||
services.certspotter.hooks = [
|
||||
(pkgs.writeShellScript "certspotter-hook" ''
|
||||
function print_email() {
|
||||
echo "Subject: [certspotter] $SUMMARY"
|
||||
echo "Mime-Version: 1.0"
|
||||
echo "Content-Type: text/plain; charset=US-ASCII"
|
||||
echo
|
||||
cat "$TEXT_FILENAME"
|
||||
}
|
||||
print_email | ${config.services.certspotter.sendmailPath} -i webmaster@example.org
|
||||
'')
|
||||
];
|
||||
{
|
||||
services.certspotter.hooks = [
|
||||
(pkgs.writeShellScript "certspotter-hook" ''
|
||||
function print_email() {
|
||||
echo "Subject: [certspotter] $SUMMARY"
|
||||
echo "Mime-Version: 1.0"
|
||||
echo "Content-Type: text/plain; charset=US-ASCII"
|
||||
echo
|
||||
cat "$TEXT_FILENAME"
|
||||
}
|
||||
print_email | ${config.services.certspotter.sendmailPath} -i webmaster@example.org
|
||||
'')
|
||||
];
|
||||
}
|
||||
```
|
||||
|
|
|
@ -11,15 +11,17 @@ email address and saves them to a local Elasticsearch instance looks
|
|||
like this:
|
||||
|
||||
```nix
|
||||
services.parsedmarc = {
|
||||
enable = true;
|
||||
settings.imap = {
|
||||
host = "imap.example.com";
|
||||
user = "alice@example.com";
|
||||
password = "/path/to/imap_password_file";
|
||||
{
|
||||
services.parsedmarc = {
|
||||
enable = true;
|
||||
settings.imap = {
|
||||
host = "imap.example.com";
|
||||
user = "alice@example.com";
|
||||
password = "/path/to/imap_password_file";
|
||||
};
|
||||
provision.geoIp = false; # Not recommended!
|
||||
};
|
||||
provision.geoIp = false; # Not recommended!
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Note that GeoIP provisioning is disabled in the example for
|
||||
|
@ -37,16 +39,18 @@ configured in the domain's dmarc policy is
|
|||
`dmarc@monitoring.example.com`.
|
||||
|
||||
```nix
|
||||
services.parsedmarc = {
|
||||
enable = true;
|
||||
provision = {
|
||||
localMail = {
|
||||
enable = true;
|
||||
hostname = monitoring.example.com;
|
||||
{
|
||||
services.parsedmarc = {
|
||||
enable = true;
|
||||
provision = {
|
||||
localMail = {
|
||||
enable = true;
|
||||
hostname = monitoring.example.com;
|
||||
};
|
||||
geoIp = false; # Not recommended!
|
||||
};
|
||||
geoIp = false; # Not recommended!
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Grafana and GeoIP {#module-services-parsedmarc-grafana-geoip}
|
||||
|
@ -58,55 +62,57 @@ is automatically added as a Grafana datasource, and the dashboard is
|
|||
added to Grafana as well.
|
||||
|
||||
```nix
|
||||
services.parsedmarc = {
|
||||
enable = true;
|
||||
provision = {
|
||||
localMail = {
|
||||
enable = true;
|
||||
hostname = url;
|
||||
};
|
||||
grafana = {
|
||||
datasource = true;
|
||||
dashboard = true;
|
||||
{
|
||||
services.parsedmarc = {
|
||||
enable = true;
|
||||
provision = {
|
||||
localMail = {
|
||||
enable = true;
|
||||
hostname = url;
|
||||
};
|
||||
grafana = {
|
||||
datasource = true;
|
||||
dashboard = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Not required, but recommended for full functionality
|
||||
services.geoipupdate = {
|
||||
settings = {
|
||||
AccountID = 000000;
|
||||
LicenseKey = "/path/to/license_key_file";
|
||||
# Not required, but recommended for full functionality
|
||||
services.geoipupdate = {
|
||||
settings = {
|
||||
AccountID = 000000;
|
||||
LicenseKey = "/path/to/license_key_file";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.grafana = {
|
||||
enable = true;
|
||||
addr = "0.0.0.0";
|
||||
domain = url;
|
||||
rootUrl = "https://" + url;
|
||||
protocol = "socket";
|
||||
security = {
|
||||
adminUser = "admin";
|
||||
adminPasswordFile = "/path/to/admin_password_file";
|
||||
secretKeyFile = "/path/to/secret_key_file";
|
||||
services.grafana = {
|
||||
enable = true;
|
||||
addr = "0.0.0.0";
|
||||
domain = url;
|
||||
rootUrl = "https://" + url;
|
||||
protocol = "socket";
|
||||
security = {
|
||||
adminUser = "admin";
|
||||
adminPasswordFile = "/path/to/admin_password_file";
|
||||
secretKeyFile = "/path/to/secret_key_file";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedTlsSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedProxySettings = true;
|
||||
upstreams.grafana.servers."unix:/${config.services.grafana.socket}" = {};
|
||||
virtualHosts.${url} = {
|
||||
root = config.services.grafana.staticRootPath;
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/".tryFiles = "$uri @grafana";
|
||||
locations."@grafana".proxyPass = "http://grafana";
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedTlsSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedProxySettings = true;
|
||||
upstreams.grafana.servers."unix:/${config.services.grafana.socket}" = {};
|
||||
virtualHosts.${url} = {
|
||||
root = config.services.grafana.staticRootPath;
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/".tryFiles = "$uri @grafana";
|
||||
locations."@grafana".proxyPass = "http://grafana";
|
||||
};
|
||||
};
|
||||
};
|
||||
users.users.nginx.extraGroups = [ "grafana" ];
|
||||
users.users.nginx.extraGroups = [ "grafana" ];
|
||||
}
|
||||
```
|
||||
|
|
|
@ -10,6 +10,7 @@ One of the most common exporters is the
|
|||
it provides hardware and OS metrics from the host it's
|
||||
running on. The exporter could be configured as follows:
|
||||
```nix
|
||||
{
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
port = 9100;
|
||||
|
@ -23,6 +24,7 @@ running on. The exporter could be configured as follows:
|
|||
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
|
||||
|
@ -36,6 +38,7 @@ the [available options](https://nixos.org/nixos/options.html#prometheus.exporter
|
|||
|
||||
Prometheus can now be configured to consume the metrics produced by the exporter:
|
||||
```nix
|
||||
{
|
||||
services.prometheus = {
|
||||
# ...
|
||||
|
||||
|
@ -49,7 +52,8 @@ Prometheus can now be configured to consume the metrics produced by the exporter
|
|||
];
|
||||
|
||||
# ...
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Adding a new exporter {#module-services-prometheus-exporters-new-exporter}
|
||||
|
|
|
@ -7,19 +7,21 @@ A storage server for Firefox Sync that you can easily host yourself.
|
|||
The absolute minimal configuration for the sync server looks like this:
|
||||
|
||||
```nix
|
||||
services.mysql.package = pkgs.mariadb;
|
||||
{
|
||||
services.mysql.package = pkgs.mariadb;
|
||||
|
||||
services.firefox-syncserver = {
|
||||
enable = true;
|
||||
secrets = builtins.toFile "sync-secrets" ''
|
||||
SYNC_MASTER_SECRET=this-secret-is-actually-leaked-to-/nix/store
|
||||
'';
|
||||
singleNode = {
|
||||
services.firefox-syncserver = {
|
||||
enable = true;
|
||||
hostname = "localhost";
|
||||
url = "http://localhost:5000";
|
||||
secrets = builtins.toFile "sync-secrets" ''
|
||||
SYNC_MASTER_SECRET=this-secret-is-actually-leaked-to-/nix/store
|
||||
'';
|
||||
singleNode = {
|
||||
enable = true;
|
||||
hostname = "localhost";
|
||||
url = "http://localhost:5000";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This will start a sync server that is only accessible locally. Once the services is
|
||||
|
|
|
@ -7,14 +7,16 @@ Mosquitto is a MQTT broker often used for IoT or home automation data transport.
|
|||
A minimal configuration for Mosquitto is
|
||||
|
||||
```nix
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
acl = [ "pattern readwrite #" ];
|
||||
omitPasswordAuth = true;
|
||||
settings.allow_anonymous = true;
|
||||
} ];
|
||||
};
|
||||
{
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
acl = [ "pattern readwrite #" ];
|
||||
omitPasswordAuth = true;
|
||||
settings.allow_anonymous = true;
|
||||
} ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This will start a broker on port 1883, listening on all interfaces of the machine, allowing
|
||||
|
@ -25,37 +27,42 @@ full read access to a user `monitor` and restricted write access to a user `serv
|
|||
like
|
||||
|
||||
```nix
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
users = {
|
||||
monitor = {
|
||||
acl = [ "read #" ];
|
||||
password = "monitor";
|
||||
{
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
users = {
|
||||
monitor = {
|
||||
acl = [ "read #" ];
|
||||
password = "monitor";
|
||||
};
|
||||
service = {
|
||||
acl = [ "write service/#" ];
|
||||
password = "service";
|
||||
};
|
||||
};
|
||||
service = {
|
||||
acl = [ "write service/#" ];
|
||||
password = "service";
|
||||
};
|
||||
};
|
||||
} ];
|
||||
};
|
||||
} ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
TLS authentication is configured by setting TLS-related options of the listener:
|
||||
|
||||
```nix
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
port = 8883; # port change is not required, but helpful to avoid mistakes
|
||||
# ...
|
||||
settings = {
|
||||
cafile = "/path/to/mqtt.ca.pem";
|
||||
certfile = "/path/to/mqtt.pem";
|
||||
keyfile = "/path/to/mqtt.key";
|
||||
};
|
||||
} ];
|
||||
{
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
port = 8883; # port change is not required, but helpful to avoid mistakes
|
||||
# ...
|
||||
settings = {
|
||||
cafile = "/path/to/mqtt.ca.pem";
|
||||
certfile = "/path/to/mqtt.pem";
|
||||
keyfile = "/path/to/mqtt.key";
|
||||
};
|
||||
} ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration {#module-services-mosquitto-config}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
The absolute minimal configuration for the netbird daemon looks like this:
|
||||
|
||||
```nix
|
||||
services.netbird.enable = true;
|
||||
{
|
||||
services.netbird.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
This will set up a netbird service listening on the port `51820` associated to the
|
||||
|
@ -14,7 +16,9 @@ This will set up a netbird service listening on the port `51820` associated to t
|
|||
It is strictly equivalent to setting:
|
||||
|
||||
```nix
|
||||
services.netbird.tunnels.wt0.stateDir = "netbird";
|
||||
{
|
||||
services.netbird.tunnels.wt0.stateDir = "netbird";
|
||||
}
|
||||
```
|
||||
|
||||
The `enable` option is mainly kept for backward compatibility, as defining netbird
|
||||
|
@ -29,11 +33,13 @@ The following configuration will start a netbird daemon using the interface `wt1
|
|||
the port 51830. Its configuration file will then be located at `/var/lib/netbird-wt1/config.json`.
|
||||
|
||||
```nix
|
||||
services.netbird.tunnels = {
|
||||
wt1 = {
|
||||
port = 51830;
|
||||
{
|
||||
services.netbird.tunnels = {
|
||||
wt1 = {
|
||||
port = 51830;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
To interact with it, you will need to specify the correct daemon address:
|
||||
|
@ -48,9 +54,11 @@ It is also possible to overwrite default options passed to the service, for
|
|||
example:
|
||||
|
||||
```nix
|
||||
services.netbird.tunnels.wt1.environment = {
|
||||
NB_DAEMON_ADDR = "unix:///var/run/toto.sock"
|
||||
};
|
||||
{
|
||||
services.netbird.tunnels.wt1.environment = {
|
||||
NB_DAEMON_ADDR = "unix:///var/run/toto.sock";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This will set the socket to interact with the netbird service to `/var/run/toto.sock`.
|
||||
|
|
|
@ -18,10 +18,12 @@ The `config.exs` file can be further customized following the instructions on th
|
|||
|
||||
First, the Postgresql service must be enabled in the NixOS configuration
|
||||
```nix
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
package = pkgs.postgresql_13;
|
||||
};
|
||||
{
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
package = pkgs.postgresql_13;
|
||||
};
|
||||
}
|
||||
```
|
||||
and activated with the usual
|
||||
```ShellSession
|
||||
|
@ -39,42 +41,44 @@ In this section we will enable the Pleroma service only locally, so its configur
|
|||
|
||||
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.
|
||||
```nix
|
||||
services.pleroma = {
|
||||
enable = true;
|
||||
secretConfigFile = "/var/lib/pleroma/secrets.exs";
|
||||
configs = [
|
||||
''
|
||||
import Config
|
||||
{
|
||||
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, 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, :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, :media_proxy,
|
||||
enabled: false,
|
||||
redirect_on_failure: true
|
||||
|
||||
config :pleroma, Pleroma.Repo,
|
||||
adapter: Ecto.Adapters.Postgres,
|
||||
username: "pleroma",
|
||||
database: "pleroma",
|
||||
hostname: "localhost"
|
||||
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"
|
||||
# Configure web push notifications
|
||||
config :web_push_encryption, :vapid_details,
|
||||
subject: "mailto:admin@example.net"
|
||||
|
||||
# ... TO CONTINUE ...
|
||||
''
|
||||
];
|
||||
};
|
||||
# ... 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
|
||||
|
@ -122,59 +126,61 @@ $ pleroma_ctl user new <nickname> <email> --admin --moderator --password <passw
|
|||
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
|
||||
```nix
|
||||
security.acme = {
|
||||
email = "root@example.net";
|
||||
acceptTerms = true;
|
||||
};
|
||||
{
|
||||
security.acme = {
|
||||
email = "root@example.net";
|
||||
acceptTerms = true;
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
addSSL = true;
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
addSSL = true;
|
||||
|
||||
recommendedTlsSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = 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.
|
||||
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;
|
||||
virtualHosts = {
|
||||
"pleroma.example.net" = {
|
||||
http2 = true;
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:4000";
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:4000";
|
||||
|
||||
extraConfig = ''
|
||||
etag on;
|
||||
gzip on;
|
||||
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;
|
||||
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
|
||||
'';
|
||||
client_max_body_size 16m;
|
||||
# NOTE: increase if users need to upload very big files
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -26,24 +26,26 @@ A good configuration to start with, including a
|
|||
endpoint as well as a [HTTP File Upload](https://xmpp.org/extensions/xep-0363.html)
|
||||
endpoint will look like this:
|
||||
```nix
|
||||
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";
|
||||
{
|
||||
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";
|
||||
};
|
||||
};
|
||||
muc = [ {
|
||||
domain = "conference.example.org";
|
||||
} ];
|
||||
uploadHttp = {
|
||||
domain = "upload.example.org";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Let's Encrypt Configuration {#module-services-prosody-letsencrypt}
|
||||
|
@ -58,15 +60,17 @@ certificate by leveraging the ACME
|
|||
Provided the setup detailed in the previous section, you'll need the following acme configuration to generate
|
||||
a TLS certificate for the three endponits:
|
||||
```nix
|
||||
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" ];
|
||||
{
|
||||
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" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -7,7 +7,9 @@ Meilisearch is a lightweight, fast and powerful search engine. Think elastic sea
|
|||
the minimum to start meilisearch is
|
||||
|
||||
```nix
|
||||
services.meilisearch.enable = true;
|
||||
{
|
||||
services.meilisearch.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
this will start the http server included with meilisearch on port 7700.
|
||||
|
|
|
@ -19,21 +19,23 @@ be run behind a HTTP proxy on `fediverse.example.com`.
|
|||
|
||||
|
||||
```nix
|
||||
services.akkoma.enable = true;
|
||||
services.akkoma.config = {
|
||||
":pleroma" = {
|
||||
":instance" = {
|
||||
name = "My Akkoma instance";
|
||||
description = "More detailed description";
|
||||
email = "admin@example.com";
|
||||
registration_open = false;
|
||||
};
|
||||
{
|
||||
services.akkoma.enable = true;
|
||||
services.akkoma.config = {
|
||||
":pleroma" = {
|
||||
":instance" = {
|
||||
name = "My Akkoma instance";
|
||||
description = "More detailed description";
|
||||
email = "admin@example.com";
|
||||
registration_open = false;
|
||||
};
|
||||
|
||||
"Pleroma.Web.Endpoint" = {
|
||||
url.host = "fediverse.example.com";
|
||||
"Pleroma.Web.Endpoint" = {
|
||||
url.host = "fediverse.example.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to the [configuration cheat sheet](https://docs.akkoma.dev/stable/configuration/cheatsheet/)
|
||||
|
@ -55,19 +57,21 @@ Although it is possible to expose Akkoma directly, it is common practice to oper
|
|||
HTTP reverse proxy such as nginx.
|
||||
|
||||
```nix
|
||||
services.akkoma.nginx = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
{
|
||||
services.akkoma.nginx = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
clientMaxBodySize = "16m";
|
||||
recommendedTlsSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
};
|
||||
clientMaxBodySize = "16m";
|
||||
recommendedTlsSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to [](#module-security-acme) for details on how to provision an SSL/TLS certificate.
|
||||
|
@ -78,51 +82,53 @@ Without the media proxy function, Akkoma does not store any remote media like pi
|
|||
locally, and clients have to fetch them directly from the source server.
|
||||
|
||||
```nix
|
||||
# Enable nginx slice module distributed with Tengine
|
||||
services.nginx.package = pkgs.tengine;
|
||||
{
|
||||
# Enable nginx slice module distributed with Tengine
|
||||
services.nginx.package = pkgs.tengine;
|
||||
|
||||
# Enable media proxy
|
||||
services.akkoma.config.":pleroma".":media_proxy" = {
|
||||
enabled = true;
|
||||
proxy_opts.redirect_on_failure = true;
|
||||
};
|
||||
|
||||
# Adjust the persistent cache size as needed:
|
||||
# Assuming an average object size of 128 KiB, around 1 MiB
|
||||
# of memory is required for the key zone per GiB of cache.
|
||||
# Ensure that the cache directory exists and is writable by nginx.
|
||||
services.nginx.commonHttpConfig = ''
|
||||
proxy_cache_path /var/cache/nginx/cache/akkoma-media-cache
|
||||
levels= keys_zone=akkoma_media_cache:16m max_size=16g
|
||||
inactive=1y use_temp_path=off;
|
||||
'';
|
||||
|
||||
services.akkoma.nginx = {
|
||||
locations."/proxy" = {
|
||||
proxyPass = "http://unix:/run/akkoma/socket";
|
||||
|
||||
extraConfig = ''
|
||||
proxy_cache akkoma_media_cache;
|
||||
|
||||
# Cache objects in slices of 1 MiB
|
||||
slice 1m;
|
||||
proxy_cache_key $host$uri$is_args$args$slice_range;
|
||||
proxy_set_header Range $slice_range;
|
||||
|
||||
# Decouple proxy and upstream responses
|
||||
proxy_buffering on;
|
||||
proxy_cache_lock on;
|
||||
proxy_ignore_client_abort on;
|
||||
|
||||
# Default cache times for various responses
|
||||
proxy_cache_valid 200 1y;
|
||||
proxy_cache_valid 206 301 304 1h;
|
||||
|
||||
# Allow serving of stale items
|
||||
proxy_cache_use_stale error timeout invalid_header updating;
|
||||
'';
|
||||
# Enable media proxy
|
||||
services.akkoma.config.":pleroma".":media_proxy" = {
|
||||
enabled = true;
|
||||
proxy_opts.redirect_on_failure = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Adjust the persistent cache size as needed:
|
||||
# Assuming an average object size of 128 KiB, around 1 MiB
|
||||
# of memory is required for the key zone per GiB of cache.
|
||||
# Ensure that the cache directory exists and is writable by nginx.
|
||||
services.nginx.commonHttpConfig = ''
|
||||
proxy_cache_path /var/cache/nginx/cache/akkoma-media-cache
|
||||
levels= keys_zone=akkoma_media_cache:16m max_size=16g
|
||||
inactive=1y use_temp_path=off;
|
||||
'';
|
||||
|
||||
services.akkoma.nginx = {
|
||||
locations."/proxy" = {
|
||||
proxyPass = "http://unix:/run/akkoma/socket";
|
||||
|
||||
extraConfig = ''
|
||||
proxy_cache akkoma_media_cache;
|
||||
|
||||
# Cache objects in slices of 1 MiB
|
||||
slice 1m;
|
||||
proxy_cache_key $host$uri$is_args$args$slice_range;
|
||||
proxy_set_header Range $slice_range;
|
||||
|
||||
# Decouple proxy and upstream responses
|
||||
proxy_buffering on;
|
||||
proxy_cache_lock on;
|
||||
proxy_ignore_client_abort on;
|
||||
|
||||
# Default cache times for various responses
|
||||
proxy_cache_valid 200 1y;
|
||||
proxy_cache_valid 206 301 304 1h;
|
||||
|
||||
# Allow serving of stale items
|
||||
proxy_cache_use_stale error timeout invalid_header updating;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### Prefetch remote media {#modules-services-akkoma-prefetch-remote-media}
|
||||
|
@ -132,10 +138,12 @@ fetches all media associated with a post through the media proxy, as soon as the
|
|||
received by the instance.
|
||||
|
||||
```nix
|
||||
services.akkoma.config.":pleroma".":mrf".policies =
|
||||
map (pkgs.formats.elixirConf { }).lib.mkRaw [
|
||||
"Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy"
|
||||
];
|
||||
{
|
||||
services.akkoma.config.":pleroma".":mrf".policies =
|
||||
map (pkgs.formats.elixirConf { }).lib.mkRaw [
|
||||
"Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy"
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
#### Media previews {#modules-services-akkoma-media-previews}
|
||||
|
@ -143,11 +151,13 @@ services.akkoma.config.":pleroma".":mrf".policies =
|
|||
Akkoma can generate previews for media.
|
||||
|
||||
```nix
|
||||
services.akkoma.config.":pleroma".":media_preview_proxy" = {
|
||||
enabled = true;
|
||||
thumbnail_max_width = 1920;
|
||||
thumbnail_max_height = 1080;
|
||||
};
|
||||
{
|
||||
services.akkoma.config.":pleroma".":media_preview_proxy" = {
|
||||
enabled = true;
|
||||
thumbnail_max_width = 1920;
|
||||
thumbnail_max_height = 1080;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Frontend management {#modules-services-akkoma-frontend-management}
|
||||
|
@ -160,29 +170,31 @@ The following example overrides the primary frontend’s default configuration u
|
|||
derivation.
|
||||
|
||||
```nix
|
||||
services.akkoma.frontends.primary.package = pkgs.runCommand "akkoma-fe" {
|
||||
config = builtins.toJSON {
|
||||
expertLevel = 1;
|
||||
collapseMessageWithSubject = false;
|
||||
stopGifs = false;
|
||||
replyVisibility = "following";
|
||||
webPushHideIfCW = true;
|
||||
hideScopeNotice = true;
|
||||
renderMisskeyMarkdown = false;
|
||||
hideSiteFavicon = true;
|
||||
postContentType = "text/markdown";
|
||||
showNavShortcuts = false;
|
||||
};
|
||||
nativeBuildInputs = with pkgs; [ jq xorg.lndir ];
|
||||
passAsFile = [ "config" ];
|
||||
} ''
|
||||
mkdir $out
|
||||
lndir ${pkgs.akkoma-frontends.akkoma-fe} $out
|
||||
{
|
||||
services.akkoma.frontends.primary.package = pkgs.runCommand "akkoma-fe" {
|
||||
config = builtins.toJSON {
|
||||
expertLevel = 1;
|
||||
collapseMessageWithSubject = false;
|
||||
stopGifs = false;
|
||||
replyVisibility = "following";
|
||||
webPushHideIfCW = true;
|
||||
hideScopeNotice = true;
|
||||
renderMisskeyMarkdown = false;
|
||||
hideSiteFavicon = true;
|
||||
postContentType = "text/markdown";
|
||||
showNavShortcuts = false;
|
||||
};
|
||||
nativeBuildInputs = with pkgs; [ jq xorg.lndir ];
|
||||
passAsFile = [ "config" ];
|
||||
} ''
|
||||
mkdir $out
|
||||
lndir ${pkgs.akkoma-frontends.akkoma-fe} $out
|
||||
|
||||
rm $out/static/config.json
|
||||
jq -s add ${pkgs.akkoma-frontends.akkoma-fe}/static/config.json ${config} \
|
||||
>$out/static/config.json
|
||||
'';
|
||||
rm $out/static/config.json
|
||||
jq -s add ${pkgs.akkoma-frontends.akkoma-fe}/static/config.json ${config} \
|
||||
>$out/static/config.json
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
## Federation policies {#modules-services-akkoma-federation-policies}
|
||||
|
@ -198,28 +210,30 @@ of the fediverse and providing a pleasant experience to the users of an instance
|
|||
|
||||
|
||||
```nix
|
||||
services.akkoma.config.":pleroma" = with (pkgs.formats.elixirConf { }).lib; {
|
||||
":mrf".policies = map mkRaw [
|
||||
"Pleroma.Web.ActivityPub.MRF.SimplePolicy"
|
||||
];
|
||||
{
|
||||
services.akkoma.config.":pleroma" = with (pkgs.formats.elixirConf { }).lib; {
|
||||
":mrf".policies = map mkRaw [
|
||||
"Pleroma.Web.ActivityPub.MRF.SimplePolicy"
|
||||
];
|
||||
|
||||
":mrf_simple" = {
|
||||
# Tag all media as sensitive
|
||||
media_nsfw = mkMap {
|
||||
"nsfw.weird.kinky" = "Untagged NSFW content";
|
||||
};
|
||||
":mrf_simple" = {
|
||||
# Tag all media as sensitive
|
||||
media_nsfw = mkMap {
|
||||
"nsfw.weird.kinky" = "Untagged NSFW content";
|
||||
};
|
||||
|
||||
# Reject all activities except deletes
|
||||
reject = mkMap {
|
||||
"kiwifarms.cc" = "Persistent harassment of users, no moderation";
|
||||
};
|
||||
# Reject all activities except deletes
|
||||
reject = mkMap {
|
||||
"kiwifarms.cc" = "Persistent harassment of users, no moderation";
|
||||
};
|
||||
|
||||
# Force posts to be visible by followers only
|
||||
followers_only = mkMap {
|
||||
"beta.birdsite.live" = "Avoid polluting timelines with Twitter posts";
|
||||
# Force posts to be visible by followers only
|
||||
followers_only = mkMap {
|
||||
"beta.birdsite.live" = "Avoid polluting timelines with Twitter posts";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Upload filters {#modules-services-akkoma-upload-filters}
|
||||
|
@ -228,12 +242,14 @@ This example strips GPS and location metadata from uploads, deduplicates them an
|
|||
the file name.
|
||||
|
||||
```nix
|
||||
services.akkoma.config.":pleroma"."Pleroma.Upload".filters =
|
||||
map (pkgs.formats.elixirConf { }).lib.mkRaw [
|
||||
"Pleroma.Upload.Filter.Exiftool"
|
||||
"Pleroma.Upload.Filter.Dedupe"
|
||||
"Pleroma.Upload.Filter.AnonymizeFilename"
|
||||
];
|
||||
{
|
||||
services.akkoma.config.":pleroma"."Pleroma.Upload".filters =
|
||||
map (pkgs.formats.elixirConf { }).lib.mkRaw [
|
||||
"Pleroma.Upload.Filter.Exiftool"
|
||||
"Pleroma.Upload.Filter.Dedupe"
|
||||
"Pleroma.Upload.Filter.AnonymizeFilename"
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Migration from Pleroma {#modules-services-akkoma-migration-pleroma}
|
||||
|
@ -286,9 +302,11 @@ To re‐use the Pleroma data in place, disable Pleroma and enable Akkoma, pointi
|
|||
Pleroma database and upload directory.
|
||||
|
||||
```nix
|
||||
# Adjust these settings according to the database name and upload directory path used by Pleroma
|
||||
services.akkoma.config.":pleroma"."Pleroma.Repo".database = "pleroma";
|
||||
services.akkoma.config.":pleroma".":instance".upload_dir = "/var/lib/pleroma/uploads";
|
||||
{
|
||||
# Adjust these settings according to the database name and upload directory path used by Pleroma
|
||||
services.akkoma.config.":pleroma"."Pleroma.Repo".database = "pleroma";
|
||||
services.akkoma.config.":pleroma".":instance".upload_dir = "/var/lib/pleroma/uploads";
|
||||
}
|
||||
```
|
||||
|
||||
Please keep in mind that after the Akkoma service has been started, any migrations applied by
|
||||
|
@ -304,7 +322,9 @@ details.
|
|||
The Akkoma systemd service may be confined to a chroot with
|
||||
|
||||
```nix
|
||||
services.systemd.akkoma.confinement.enable = true;
|
||||
{
|
||||
services.systemd.akkoma.confinement.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
Confinement of services is not generally supported in NixOS and therefore disabled by default.
|
||||
|
|
|
@ -7,19 +7,21 @@ modern and open source discussion platform.
|
|||
|
||||
A minimal configuration using Let's Encrypt for TLS certificates looks like this:
|
||||
```nix
|
||||
services.discourse = {
|
||||
enable = true;
|
||||
hostname = "discourse.example.com";
|
||||
admin = {
|
||||
email = "admin@example.com";
|
||||
username = "admin";
|
||||
fullName = "Administrator";
|
||||
passwordFile = "/path/to/password_file";
|
||||
{
|
||||
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";
|
||||
};
|
||||
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||
};
|
||||
security.acme.email = "me@example.com";
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.email = "me@example.com";
|
||||
security.acme.acceptTerms = true;
|
||||
}
|
||||
```
|
||||
|
||||
Provided a proper DNS setup, you'll be able to connect to the
|
||||
|
@ -35,19 +37,21 @@ and [](#opt-services.discourse.sslCertificateKey)
|
|||
options:
|
||||
|
||||
```nix
|
||||
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";
|
||||
{
|
||||
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";
|
||||
};
|
||||
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Database access {#module-services-discourse-database}
|
||||
|
@ -81,26 +85,28 @@ A basic setup which assumes you want to use your configured
|
|||
email domain can be done like this:
|
||||
|
||||
```nix
|
||||
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";
|
||||
{
|
||||
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";
|
||||
};
|
||||
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
|
||||
|
@ -163,43 +169,45 @@ Discourse instance and enables
|
|||
GitHub login in the site settings,
|
||||
and changes a few request limits in the backend settings:
|
||||
```nix
|
||||
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)";
|
||||
{
|
||||
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";
|
||||
};
|
||||
login = {
|
||||
enable_github_logins = true;
|
||||
github_client_id = "a2f6dfe838cb3206ce20";
|
||||
github_client_secret._secret = /run/keys/discourse_github_client_secret;
|
||||
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";
|
||||
};
|
||||
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
|
||||
|
@ -254,33 +262,35 @@ plugins, and disable `discourse-spoiler-alert`
|
|||
by default:
|
||||
|
||||
```nix
|
||||
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;
|
||||
{
|
||||
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";
|
||||
};
|
||||
secretKeyBaseFile = "/path/to/secret_key_base_file";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -8,17 +8,19 @@ The following configuration sets up the PostgreSQL as database backend and binds
|
|||
GoToSocial to `127.0.0.1:8080`, expecting to be run behind a HTTP proxy on `gotosocial.example.com`.
|
||||
|
||||
```nix
|
||||
services.gotosocial = {
|
||||
enable = true;
|
||||
setupPostgresqlDB = true;
|
||||
settings = {
|
||||
application-name = "My GoToSocial";
|
||||
host = "gotosocial.example.com";
|
||||
protocol = "https";
|
||||
bind-address = "127.0.0.1";
|
||||
port = 8080;
|
||||
{
|
||||
services.gotosocial = {
|
||||
enable = true;
|
||||
setupPostgresqlDB = true;
|
||||
settings = {
|
||||
application-name = "My GoToSocial";
|
||||
host = "gotosocial.example.com";
|
||||
protocol = "https";
|
||||
bind-address = "127.0.0.1";
|
||||
port = 8080;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to the [GoToSocial Documentation](https://docs.gotosocial.org/en/latest/configuration/general/)
|
||||
|
@ -30,24 +32,26 @@ Although it is possible to expose GoToSocial directly, it is common practice to
|
|||
HTTP reverse proxy such as nginx.
|
||||
|
||||
```nix
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
clientMaxBodySize = "40M";
|
||||
virtualHosts = with config.services.gotosocial.settings; {
|
||||
"${host}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/" = {
|
||||
recommendedProxySettings = true;
|
||||
proxyWebsockets = true;
|
||||
proxyPass = "http://${bind-address}:${toString port}";
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
clientMaxBodySize = "40M";
|
||||
virtualHosts = with config.services.gotosocial.settings; {
|
||||
"${host}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/" = {
|
||||
recommendedProxySettings = true;
|
||||
proxyWebsockets = true;
|
||||
proxyPass = "http://${bind-address}:${toString port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to [](#module-security-acme) for details on how to provision an SSL/TLS certificate.
|
||||
|
|
|
@ -127,15 +127,17 @@ should be set to. See the description of
|
|||
|
||||
A basic configuration with some custom settings could look like this:
|
||||
```nix
|
||||
services.keycloak = {
|
||||
enable = true;
|
||||
settings = {
|
||||
hostname = "keycloak.example.com";
|
||||
hostname-strict-backchannel = true;
|
||||
{
|
||||
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";
|
||||
};
|
||||
initialAdminPassword = "e6Wcm0RrtegMEHl"; # change on first login
|
||||
sslCertificate = "/run/keys/ssl_cert";
|
||||
sslCertificateKey = "/run/keys/ssl_key";
|
||||
database.passwordFile = "/run/keys/db_password";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -7,13 +7,15 @@ Lemmy is a federated alternative to reddit in rust.
|
|||
the minimum to start lemmy is
|
||||
|
||||
```nix
|
||||
services.lemmy = {
|
||||
enable = true;
|
||||
settings = {
|
||||
hostname = "lemmy.union.rocks";
|
||||
database.createLocally = true;
|
||||
{
|
||||
services.lemmy = {
|
||||
enable = true;
|
||||
settings = {
|
||||
hostname = "lemmy.union.rocks";
|
||||
database.createLocally = true;
|
||||
};
|
||||
caddy.enable = true;
|
||||
};
|
||||
caddy.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@ pict-rs is a a simple image hosting service.
|
|||
the minimum to start pict-rs is
|
||||
|
||||
```nix
|
||||
services.pict-rs.enable = true;
|
||||
{
|
||||
services.pict-rs.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
this will start the http server on port 8080 by default.
|
||||
|
|
|
@ -100,7 +100,7 @@ Not all the configuration options are available directly in this module, but you
|
|||
server = {
|
||||
port = 4567;
|
||||
autoDownloadNewChapters = false;
|
||||
maxSourcesInParallel" = 6;
|
||||
maxSourcesInParallel = 6;
|
||||
extensionRepos = [
|
||||
"https://raw.githubusercontent.com/MY_ACCOUNT/MY_REPO/repo/index.min.json"
|
||||
];
|
||||
|
|
|
@ -9,8 +9,10 @@ All of the core apps, optional apps, games, and core developer tools from GNOME
|
|||
To enable the GNOME desktop use:
|
||||
|
||||
```nix
|
||||
services.xserver.desktopManager.gnome.enable = true;
|
||||
services.xserver.displayManager.gdm.enable = true;
|
||||
{
|
||||
services.xserver.desktopManager.gnome.enable = true;
|
||||
services.xserver.displayManager.gdm.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
|
@ -24,7 +26,9 @@ The default applications used in NixOS are very minimal, inspired by the default
|
|||
If you’d like to only use the GNOME desktop and not the apps, you can disable them with:
|
||||
|
||||
```nix
|
||||
services.gnome.core-utilities.enable = false;
|
||||
{
|
||||
services.gnome.core-utilities.enable = false;
|
||||
}
|
||||
```
|
||||
|
||||
and none of them will be installed.
|
||||
|
@ -38,8 +42,10 @@ Note that this mechanism can only exclude core utilities, games and core develop
|
|||
It is also possible to disable many of the [core services](https://github.com/NixOS/nixpkgs/blob/b8ec4fd2a4edc4e30d02ba7b1a2cc1358f3db1d5/nixos/modules/services/x11/desktop-managers/gnome.nix#L329-L348). For example, if you do not need indexing files, you can disable Tracker with:
|
||||
|
||||
```nix
|
||||
services.gnome.tracker-miners.enable = false;
|
||||
services.gnome.tracker.enable = false;
|
||||
{
|
||||
services.gnome.tracker-miners.enable = false;
|
||||
services.gnome.tracker.enable = false;
|
||||
}
|
||||
```
|
||||
|
||||
Note, however, that doing so is not supported and might break some applications. Notably, GNOME Music cannot work without Tracker.
|
||||
|
@ -49,7 +55,9 @@ Note, however, that doing so is not supported and might break some applications.
|
|||
You can install all of the GNOME games with:
|
||||
|
||||
```nix
|
||||
services.gnome.games.enable = true;
|
||||
{
|
||||
services.gnome.games.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
### GNOME core developer tools {#sec-gnome-core-developer-tools}
|
||||
|
@ -57,7 +65,9 @@ services.gnome.games.enable = true;
|
|||
You can install GNOME core developer tools with:
|
||||
|
||||
```nix
|
||||
services.gnome.core-developer-tools.enable = true;
|
||||
{
|
||||
services.gnome.core-developer-tools.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
## Enabling GNOME Flashback {#sec-gnome-enable-flashback}
|
||||
|
@ -65,7 +75,9 @@ services.gnome.core-developer-tools.enable = true;
|
|||
GNOME Flashback provides a desktop environment based on the classic GNOME 2 architecture. You can enable the default GNOME Flashback session, which uses the Metacity window manager, with:
|
||||
|
||||
```nix
|
||||
services.xserver.desktopManager.gnome.flashback.enableMetacity = true;
|
||||
{
|
||||
services.xserver.desktopManager.gnome.flashback.enableMetacity = true;
|
||||
}
|
||||
```
|
||||
|
||||
It is also possible to create custom sessions that replace Metacity with a different window manager using [](#opt-services.xserver.desktopManager.gnome.flashback.customSessions).
|
||||
|
@ -73,14 +85,16 @@ It is also possible to create custom sessions that replace Metacity with a diffe
|
|||
The following example uses `xmonad` window manager:
|
||||
|
||||
```nix
|
||||
services.xserver.desktopManager.gnome.flashback.customSessions = [
|
||||
{
|
||||
wmName = "xmonad";
|
||||
wmLabel = "XMonad";
|
||||
wmCommand = "${pkgs.haskellPackages.xmonad}/bin/xmonad";
|
||||
enableGnomePanel = false;
|
||||
}
|
||||
];
|
||||
{
|
||||
services.xserver.desktopManager.gnome.flashback.customSessions = [
|
||||
{
|
||||
wmName = "xmonad";
|
||||
wmLabel = "XMonad";
|
||||
wmCommand = "${pkgs.haskellPackages.xmonad}/bin/xmonad";
|
||||
enableGnomePanel = false;
|
||||
}
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Icons and GTK Themes {#sec-gnome-icons-and-gtk-themes}
|
||||
|
@ -105,11 +119,13 @@ Some packages that include Shell extensions, like `gnome.gpaste`, don’t have t
|
|||
You can install them like any other package:
|
||||
|
||||
```nix
|
||||
environment.systemPackages = [
|
||||
gnomeExtensions.dash-to-dock
|
||||
gnomeExtensions.gsconnect
|
||||
gnomeExtensions.mpris-indicator-button
|
||||
];
|
||||
{
|
||||
environment.systemPackages = [
|
||||
gnomeExtensions.dash-to-dock
|
||||
gnomeExtensions.gsconnect
|
||||
gnomeExtensions.mpris-indicator-button
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Unfortunately, we lack a way for these to be managed in a completely declarative way.
|
||||
|
@ -137,22 +153,24 @@ You can use `dconf-editor` tool to explore which GSettings you can set.
|
|||
### Example {#sec-gnome-gsettings-overrides-example}
|
||||
|
||||
```nix
|
||||
services.xserver.desktopManager.gnome = {
|
||||
extraGSettingsOverrides = ''
|
||||
# Change default background
|
||||
[org.gnome.desktop.background]
|
||||
picture-uri='file://${pkgs.nixos-artwork.wallpapers.mosaic-blue.gnomeFilePath}'
|
||||
{
|
||||
services.xserver.desktopManager.gnome = {
|
||||
extraGSettingsOverrides = ''
|
||||
# Change default background
|
||||
[org.gnome.desktop.background]
|
||||
picture-uri='file://${pkgs.nixos-artwork.wallpapers.mosaic-blue.gnomeFilePath}'
|
||||
|
||||
# Favorite apps in gnome-shell
|
||||
[org.gnome.shell]
|
||||
favorite-apps=['org.gnome.Console.desktop', 'org.gnome.Nautilus.desktop']
|
||||
'';
|
||||
# Favorite apps in gnome-shell
|
||||
[org.gnome.shell]
|
||||
favorite-apps=['org.gnome.Console.desktop', 'org.gnome.Nautilus.desktop']
|
||||
'';
|
||||
|
||||
extraGSettingsOverridePackages = [
|
||||
pkgs.gsettings-desktop-schemas # for org.gnome.desktop
|
||||
pkgs.gnome.gnome-shell # for org.gnome.shell
|
||||
];
|
||||
};
|
||||
extraGSettingsOverridePackages = [
|
||||
pkgs.gsettings-desktop-schemas # for org.gnome.desktop
|
||||
pkgs.gnome.gnome-shell # for org.gnome.shell
|
||||
];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Frequently Asked Questions {#sec-gnome-faq}
|
||||
|
|
|
@ -6,16 +6,22 @@ Pantheon is the desktop environment created for the elementary OS distribution.
|
|||
|
||||
All of Pantheon is working in NixOS and the applications should be available, aside from a few [exceptions](https://github.com/NixOS/nixpkgs/issues/58161). To enable Pantheon, set
|
||||
```nix
|
||||
services.xserver.desktopManager.pantheon.enable = true;
|
||||
{
|
||||
services.xserver.desktopManager.pantheon.enable = true;
|
||||
}
|
||||
```
|
||||
This automatically enables LightDM and Pantheon's LightDM greeter. If you'd like to disable this, set
|
||||
```nix
|
||||
services.xserver.displayManager.lightdm.greeters.pantheon.enable = false;
|
||||
services.xserver.displayManager.lightdm.enable = false;
|
||||
{
|
||||
services.xserver.displayManager.lightdm.greeters.pantheon.enable = false;
|
||||
services.xserver.displayManager.lightdm.enable = false;
|
||||
}
|
||||
```
|
||||
but please be aware using Pantheon without LightDM as a display manager will break screenlocking from the UI. The NixOS module for Pantheon installs all of Pantheon's default applications. If you'd like to not install Pantheon's apps, set
|
||||
```nix
|
||||
services.pantheon.apps.enable = false;
|
||||
{
|
||||
services.pantheon.apps.enable = false;
|
||||
}
|
||||
```
|
||||
You can also use [](#opt-environment.pantheon.excludePackages) to remove any other app (like `elementary-mail`).
|
||||
|
||||
|
@ -34,25 +40,28 @@ wingpanel-with-indicators.override {
|
|||
indicators = [
|
||||
pkgs.some-special-indicator
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
```
|
||||
```nix
|
||||
switchboard-with-plugs.override {
|
||||
plugs = [
|
||||
pkgs.some-special-plug
|
||||
];
|
||||
};
|
||||
}
|
||||
```
|
||||
please note that, like how the NixOS options describe these as extra plugins, this would only add to the default plugins included with the programs. If for some reason you'd like to configure which plugins to use exactly, both packages have an argument for this:
|
||||
```nix
|
||||
wingpanel-with-indicators.override {
|
||||
useDefaultIndicators = false;
|
||||
indicators = specialListOfIndicators;
|
||||
};
|
||||
|
||||
}
|
||||
```
|
||||
```nix
|
||||
switchboard-with-plugs.override {
|
||||
useDefaultPlugs = false;
|
||||
plugs = specialListOfPlugs;
|
||||
};
|
||||
}
|
||||
```
|
||||
this could be most useful for testing a particular plug-in in isolation.
|
||||
|
||||
|
|
|
@ -40,12 +40,16 @@ For more complete documentation on how to generate a secret with clevis, see the
|
|||
In order to activate unattended decryption of a resource at boot, enable the `clevis` module:
|
||||
|
||||
```nix
|
||||
boot.initrd.clevis.enable = true;
|
||||
{
|
||||
boot.initrd.clevis.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
Then, specify the device you want to decrypt using a given clevis secret. Clevis will automatically try to decrypt the device at boot and will fallback to interactive unlocking if the decryption policy is not fulfilled.
|
||||
```nix
|
||||
boot.initrd.clevis.devices."/dev/nvme0n1p1".secretFile = ./nvme0n1p1.jwe;
|
||||
{
|
||||
boot.initrd.clevis.devices."/dev/nvme0n1p1".secretFile = ./nvme0n1p1.jwe;
|
||||
}
|
||||
```
|
||||
|
||||
Only `bcachefs`, `zfs` and `luks` encrypted devices are supported at this time.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue