diff options
Diffstat (limited to 'nixpkgs/nixos/modules/services/network-filesystems')
3 files changed, 234 insertions, 45 deletions
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix b/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix index 2748571be1f7..57f5f6b006c8 100644 --- a/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix +++ b/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix @@ -5,36 +5,41 @@ let opt = options.services.ipfs; ipfsFlags = toString ([ - (optionalString cfg.autoMount "--mount") - (optionalString cfg.enableGC "--enable-gc") - (optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false") - (optionalString (cfg.defaultMode == "offline") "--offline") + (optionalString cfg.autoMount "--mount") + (optionalString cfg.enableGC "--enable-gc") + (optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false") + (optionalString (cfg.defaultMode == "offline") "--offline") (optionalString (cfg.defaultMode == "norouting") "--routing=none") ] ++ cfg.extraFlags); splitMulitaddr = addrRaw: lib.tail (lib.splitString "/" addrRaw); - multiaddrToListenStream = addrRaw: let + multiaddrToListenStream = addrRaw: + let addr = splitMulitaddr addrRaw; s = builtins.elemAt addr; - in if s 0 == "ip4" && s 2 == "tcp" - then "${s 1}:${s 3}" + in + if s 0 == "ip4" && s 2 == "tcp" + then "${s 1}:${s 3}" else if s 0 == "ip6" && s 2 == "tcp" - then "[${s 1}]:${s 3}" + then "[${s 1}]:${s 3}" else if s 0 == "unix" - then "/${lib.concatStringsSep "/" (lib.tail addr)}" + then "/${lib.concatStringsSep "/" (lib.tail addr)}" else null; # not valid for listen stream, skip - multiaddrToListenDatagram = addrRaw: let + multiaddrToListenDatagram = addrRaw: + let addr = splitMulitaddr addrRaw; s = builtins.elemAt addr; - in if s 0 == "ip4" && s 2 == "udp" - then "${s 1}:${s 3}" + in + if s 0 == "ip4" && s 2 == "udp" + then "${s 1}:${s 3}" else if s 0 == "ip6" && s 2 == "udp" - then "[${s 1}]:${s 3}" + then "[${s 1}]:${s 3}" else null; # not valid for listen datagram, skip -in { +in +{ ###### interface @@ -65,9 +70,10 @@ in { dataDir = mkOption { type = types.str; - default = if versionAtLeast config.system.stateVersion "17.09" - then "/var/lib/ipfs" - else "/var/lib/ipfs/.ipfs"; + default = + if versionAtLeast config.system.stateVersion "17.09" + then "/var/lib/ipfs" + else "/var/lib/ipfs/.ipfs"; description = "The data dir for IPFS"; }; @@ -83,6 +89,12 @@ in { description = "Whether IPFS should try to mount /ipfs and /ipns at startup."; }; + autoMigrate = mkOption { + type = types.bool; + default = true; + description = "Whether IPFS should try to run the fs-repo-migration at startup."; + }; + ipfsMountDir = mkOption { type = types.str; default = "/ipfs"; @@ -137,7 +149,7 @@ in { These are applied last, so may override configuration set by other options in this module. Keep in mind that this configuration is stateful; i.e., unsetting anything in here does not reset the value to the default! ''; - default = {}; + default = { }; example = { Datastore.StorageMax = "100GB"; Discovery.MDNS.Enabled = false; @@ -153,7 +165,7 @@ in { extraFlags = mkOption { type = types.listOf types.str; description = "Extra flags passed to the IPFS daemon"; - default = []; + default = [ ]; }; localDiscovery = mkOption { @@ -168,7 +180,7 @@ in { type = types.nullOr types.int; default = null; description = "The fdlimit for the IPFS systemd unit or <literal>null</literal> to have the daemon attempt to manage it"; - example = 64*1024; + example = 64 * 1024; }; startWhenNeeded = mkOption { @@ -186,6 +198,9 @@ in { environment.systemPackages = [ cfg.package ]; environment.variables.IPFS_PATH = cfg.dataDir; + # https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size + boot.kernel.sysctl."net.core.rmem_max" = mkDefault 2500000; + programs.fuse = mkIf cfg.autoMount { userAllowOther = true; }; @@ -226,33 +241,36 @@ in { ${optionalString (! cfg.localDiscovery) "--profile=server"} else ${if cfg.localDiscovery - then "ipfs config profile apply local-discovery" - else "ipfs config profile apply server" + then "ipfs --offline config profile apply local-discovery" + else "ipfs --offline config profile apply server" } fi '' + optionalString cfg.autoMount '' ipfs --offline config Mounts.FuseAllowOther --json true ipfs --offline config Mounts.IPFS ${cfg.ipfsMountDir} ipfs --offline config Mounts.IPNS ${cfg.ipnsMountDir} + '' + optionalString cfg.autoMigrate '' + ${pkgs.ipfs-migrator}/bin/fs-repo-migrations -y '' + concatStringsSep "\n" (collect - isString - (mapAttrsRecursive - (path: value: - # Using heredoc below so that the value is never improperly quoted - '' - read value <<EOF - ${builtins.toJSON value} - EOF - ipfs --offline config --json "${concatStringsSep "." path}" "$value" - '') - ({ Addresses.API = cfg.apiAddress; - Addresses.Gateway = cfg.gatewayAddress; - Addresses.Swarm = cfg.swarmAddress; - } // - cfg.extraConfig)) - ); + isString + (mapAttrsRecursive + (path: value: + # Using heredoc below so that the value is never improperly quoted + '' + read value <<EOF + ${builtins.toJSON value} + EOF + ipfs --offline config --json "${concatStringsSep "." path}" "$value" + '') + ({ + Addresses.API = cfg.apiAddress; + Addresses.Gateway = cfg.gatewayAddress; + Addresses.Swarm = cfg.swarmAddress; + } // + cfg.extraConfig)) + ); serviceConfig = { - ExecStart = ["" "${cfg.package}/bin/ipfs daemon ${ipfsFlags}"]; + ExecStart = [ "" "${cfg.package}/bin/ipfs daemon ${ipfsFlags}" ]; User = cfg.user; Group = cfg.group; } // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; }; @@ -263,12 +281,16 @@ in { systemd.sockets.ipfs-gateway = { wantedBy = [ "sockets.target" ]; socketConfig = { - ListenStream = let + ListenStream = + let fromCfg = multiaddrToListenStream cfg.gatewayAddress; - in [ "" ] ++ lib.optional (fromCfg != null) fromCfg; - ListenDatagram = let + in + [ "" ] ++ lib.optional (fromCfg != null) fromCfg; + ListenDatagram = + let fromCfg = multiaddrToListenDatagram cfg.gatewayAddress; - in [ "" ] ++ lib.optional (fromCfg != null) fromCfg; + in + [ "" ] ++ lib.optional (fromCfg != null) fromCfg; }; }; @@ -276,9 +298,11 @@ in { wantedBy = [ "sockets.target" ]; # We also include "%t/ipfs.sock" because there is no way to put the "%t" # in the multiaddr. - socketConfig.ListenStream = let + socketConfig.ListenStream = + let fromCfg = multiaddrToListenStream cfg.apiAddress; - in [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg; + in + [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg; }; }; diff --git a/nixpkgs/nixos/modules/services/network-filesystems/litestream/default.nix b/nixpkgs/nixos/modules/services/network-filesystems/litestream/default.nix new file mode 100644 index 000000000000..f1806c5af0a9 --- /dev/null +++ b/nixpkgs/nixos/modules/services/network-filesystems/litestream/default.nix @@ -0,0 +1,100 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.litestream; + settingsFormat = pkgs.formats.yaml {}; +in +{ + options.services.litestream = { + enable = mkEnableOption "litestream"; + + package = mkOption { + description = "Package to use."; + default = pkgs.litestream; + defaultText = "pkgs.litestream"; + type = types.package; + }; + + settings = mkOption { + description = '' + See the <link xlink:href="https://litestream.io/reference/config/">documentation</link>. + ''; + type = settingsFormat.type; + example = { + dbs = [ + { + path = "/var/lib/db1"; + replicas = [ + { + url = "s3://mybkt.litestream.io/db1"; + } + ]; + } + ]; + }; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/secrets/litestream"; + description = '' + Environment file as defined in <citerefentry> + <refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum> + </citerefentry>. + + Secrets may be passed to the service without adding them to the + world-readable Nix store, by specifying placeholder variables as + the option value in Nix and setting these variables accordingly in the + environment file. + + By default, Litestream will perform environment variable expansion + within the config file before reading it. Any references to ''$VAR or + ''${VAR} formatted variables will be replaced with their environment + variable values. If no value is set then it will be replaced with an + empty string. + + <programlisting> + # Content of the environment file + LITESTREAM_ACCESS_KEY_ID=AKIAxxxxxxxxxxxxxxxx + LITESTREAM_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxx + </programlisting> + + Note that this file needs to be available on the host on which + this exporter is running. + ''; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + environment.etc = { + "litestream.yml" = { + source = settingsFormat.generate "litestream-config.yaml" cfg.settings; + }; + }; + + systemd.services.litestream = { + description = "Litestream"; + wantedBy = [ "multi-user.target" ]; + after = [ "networking.target" ]; + serviceConfig = { + EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; + ExecStart = "${cfg.package}/bin/litestream replicate"; + Restart = "always"; + User = "litestream"; + Group = "litestream"; + }; + }; + + users.users.litestream = { + description = "Litestream user"; + group = "litestream"; + isSystemUser = true; + }; + users.groups.litestream = {}; + }; + meta.doc = ./litestream.xml; +} diff --git a/nixpkgs/nixos/modules/services/network-filesystems/litestream/litestream.xml b/nixpkgs/nixos/modules/services/network-filesystems/litestream/litestream.xml new file mode 100644 index 000000000000..598f9be8cf63 --- /dev/null +++ b/nixpkgs/nixos/modules/services/network-filesystems/litestream/litestream.xml @@ -0,0 +1,65 @@ +<chapter xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0" + xml:id="module-services-litestream"> + <title>Litestream</title> + <para> + <link xlink:href="https://litestream.io/">Litestream</link> is a standalone streaming + replication tool for SQLite. + </para> + + <section xml:id="module-services-litestream-configuration"> + <title>Configuration</title> + + <para> + Litestream service is managed by a dedicated user named <literal>litestream</literal> + which needs permission to the database file. Here's an example config which gives + required permissions to access <link linkend="opt-services.grafana.database.path"> + grafana database</link>: +<programlisting> +{ pkgs, ... }: +{ + users.users.litestream.extraGroups = [ "grafana" ]; + + systemd.services.grafana.serviceConfig.ExecStartPost = "+" + pkgs.writeShellScript "grant-grafana-permissions" '' + timeout=10 + + while [ ! -f /var/lib/grafana/data/grafana.db ]; + do + if [ "$timeout" == 0 ]; then + echo "ERROR: Timeout while waiting for /var/lib/grafana/data/grafana.db." + exit 1 + fi + + sleep 1 + + ((timeout--)) + done + + find /var/lib/grafana -type d -exec chmod -v 775 {} \; + find /var/lib/grafana -type f -exec chmod -v 660 {} \; + ''; + + services.litestream = { + enable = true; + + environmentFile = "/run/secrets/litestream"; + + settings = { + dbs = [ + { + path = "/var/lib/grafana/data/grafana.db"; + replicas = [{ + url = "s3://mybkt.litestream.io/grafana"; + }]; + } + ]; + }; + }; +} +</programlisting> + </para> + </section> + +</chapter> |