upgrade
This commit is contained in:
parent
6511ee66dd
commit
8469bcd67a
11 changed files with 16 additions and 1147 deletions
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"url": "https://github.com/NixOS/nixpkgs.git",
|
"url": "https://github.com/NixOS/nixpkgs.git",
|
||||||
"rev": "e4adbfbab8aadf9d80a93d40fb612cb910073af9",
|
"rev": "2394284537b89471c87065b040d3dedd8b5907fe",
|
||||||
"date": "2021-01-25T20:25:09+01:00",
|
"date": "2021-02-10T23:24:22+01:00",
|
||||||
"path": "/nix/store/i43dyq07kr5dy1rbn6vqffg1pwcl9hi9-nixpkgs",
|
"path": "/nix/store/rqgraycidchn5wc5mki5sqj8bl5cpx78-nixpkgs",
|
||||||
"sha256": "0fs32adk4x5xg9m00nykhxhka927wrnwkjx59as673swh46hdvck",
|
"sha256": "1j7vp735is5d32mbrgavpxi3fbnsm6d99a01ap8gn30n5ysd14sl",
|
||||||
"fetchSubmodules": false,
|
"fetchSubmodules": false,
|
||||||
"deepClone": false,
|
"deepClone": false,
|
||||||
"leaveDotGit": false
|
"leaveDotGit": false
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"url": "https://github.com/NixOS/nixpkgs.git",
|
"url": "https://github.com/NixOS/nixpkgs.git",
|
||||||
"rev": "891f607d5301d6730cb1f9dcf3618bcb1ab7f10e",
|
"rev": "758b29b5a28b818e311ad540637a5c1e40867489",
|
||||||
"date": "2021-01-25T12:54:49+01:00",
|
"date": "2021-02-10T23:30:20+01:00",
|
||||||
"path": "/nix/store/0fdmvrw6pcwqf28ymvl8qfbflc9m65jc-nixpkgs",
|
"path": "/nix/store/0d1llmnj9bq8b5wlz2a62ikhy13r9mq9-nixpkgs",
|
||||||
"sha256": "1cr39f0sbr0h5d83dv1q34mcpwnkwwbdk5fqlyqp2mnxghzwssng",
|
"sha256": "00nk1a002zzi0ij4xp2hf7955wj49qdwsm2wy7mzbpjbgick6scp",
|
||||||
"fetchSubmodules": false,
|
"fetchSubmodules": false,
|
||||||
"deepClone": false,
|
"deepClone": false,
|
||||||
"leaveDotGit": false
|
"leaveDotGit": false
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
nixpkgs.config.permittedInsecurePackages = [ "homeassistant-0.114.4" ];
|
||||||
|
|
||||||
networking.hostName = "pepe";
|
networking.hostName = "pepe";
|
||||||
|
|
||||||
# fonts
|
# fonts
|
||||||
|
|
|
@ -28,7 +28,7 @@ in {
|
||||||
homeassistant = false;
|
homeassistant = false;
|
||||||
|
|
||||||
# allow new devices to join
|
# allow new devices to join
|
||||||
permit_join = true;
|
permit_join = false;
|
||||||
|
|
||||||
# MQTT settings
|
# MQTT settings
|
||||||
mqtt = {
|
mqtt = {
|
||||||
|
|
|
@ -10,7 +10,7 @@ in {
|
||||||
#unstable.sonic-visualiser
|
#unstable.sonic-visualiser
|
||||||
sononym-crawler
|
sononym-crawler
|
||||||
darktable
|
darktable
|
||||||
haskellPackages.mahlzeit
|
#haskellPackages.mahlzeit
|
||||||
|
|
||||||
# rust development environment
|
# rust development environment
|
||||||
rustup
|
rustup
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
./property.nix
|
./property.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
nixpkgs.config.permittedInsecurePackages =
|
||||||
|
[ "gogs-0.11.91" "nextcloud-19.0.6" ];
|
||||||
|
|
||||||
# todo: add this to each file instead summing that here
|
# todo: add this to each file instead summing that here
|
||||||
on-failure.plans = {
|
on-failure.plans = {
|
||||||
gogs.name = "gogs";
|
gogs.name = "gogs";
|
||||||
|
|
|
@ -7,9 +7,6 @@ let
|
||||||
|
|
||||||
in {
|
in {
|
||||||
|
|
||||||
# Nextcloud 19 is still supported, but CVE-2020-8259 & CVE-2020-8152 are unfixed!
|
|
||||||
nixpkgs.config.permittedInsecurePackages = [ "nextcloud-19.0.6" ];
|
|
||||||
|
|
||||||
containers.nextcloud = {
|
containers.nextcloud = {
|
||||||
|
|
||||||
# mount host folders
|
# mount host folders
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
|
|
||||||
#./later/syncthing.nix
|
|
||||||
#./later/nextcloud.nix
|
|
||||||
|
|
||||||
./services/light-control.nix
|
./services/light-control.nix
|
||||||
|
|
||||||
./services/castget.nix
|
./services/castget.nix
|
||||||
|
|
|
@ -1,626 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
assert lib.versionOlder lib.version "20.09";
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.later.services.nextcloud;
|
|
||||||
fpm = config.services.phpfpm.pools.nextcloud;
|
|
||||||
|
|
||||||
phpPackage = pkgs.php73;
|
|
||||||
phpPackages = pkgs.php73Packages;
|
|
||||||
|
|
||||||
toKeyValue = generators.toKeyValue {
|
|
||||||
mkKeyValue = generators.mkKeyValueDefault { } " = ";
|
|
||||||
};
|
|
||||||
|
|
||||||
phpOptionsExtensions = ''
|
|
||||||
${optionalString cfg.caching.apcu
|
|
||||||
"extension=${phpPackages.apcu}/lib/php/extensions/apcu.so"}
|
|
||||||
${optionalString cfg.caching.redis
|
|
||||||
"extension=${phpPackages.redis}/lib/php/extensions/redis.so"}
|
|
||||||
${optionalString cfg.caching.memcached
|
|
||||||
"extension=${phpPackages.memcached}/lib/php/extensions/memcached.so"}
|
|
||||||
extension=${phpPackages.imagick}/lib/php/extensions/imagick.so
|
|
||||||
zend_extension = opcache.so
|
|
||||||
opcache.enable = 1
|
|
||||||
'';
|
|
||||||
phpOptions = {
|
|
||||||
upload_max_filesize = cfg.maxUploadSize;
|
|
||||||
post_max_size = cfg.maxUploadSize;
|
|
||||||
memory_limit = cfg.maxUploadSize;
|
|
||||||
} // cfg.phpOptions;
|
|
||||||
phpOptionsStr = phpOptionsExtensions + (toKeyValue phpOptions);
|
|
||||||
|
|
||||||
occ = pkgs.writeScriptBin "nextcloud-occ" ''
|
|
||||||
#! ${pkgs.stdenv.shell}
|
|
||||||
cd ${pkgs.nextcloud}
|
|
||||||
sudo=exec
|
|
||||||
if [[ "$USER" != nextcloud ]]; then
|
|
||||||
sudo='exec /run/wrappers/bin/sudo -u nextcloud --preserve-env=NEXTCLOUD_CONFIG_DIR'
|
|
||||||
fi
|
|
||||||
export NEXTCLOUD_CONFIG_DIR="${cfg.home}/config"
|
|
||||||
$sudo \
|
|
||||||
${phpPackage}/bin/php \
|
|
||||||
-c ${pkgs.writeText "php.ini" phpOptionsStr}\
|
|
||||||
occ $*
|
|
||||||
'';
|
|
||||||
|
|
||||||
in {
|
|
||||||
options.later.services.nextcloud = {
|
|
||||||
enable = mkEnableOption "nextcloud";
|
|
||||||
hostName = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "FQDN for the nextcloud instance.";
|
|
||||||
};
|
|
||||||
home = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "/var/lib/nextcloud";
|
|
||||||
description = "Storage path of nextcloud.";
|
|
||||||
};
|
|
||||||
logLevel = mkOption {
|
|
||||||
type = types.ints.between 0 4;
|
|
||||||
default = 2;
|
|
||||||
description = "Log level value between 0 (DEBUG) and 4 (FATAL).";
|
|
||||||
};
|
|
||||||
https = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = "Use https for generated links.";
|
|
||||||
};
|
|
||||||
|
|
||||||
maxUploadSize = mkOption {
|
|
||||||
default = "512M";
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
Defines the upload limit for files. This changes the relevant options
|
|
||||||
in php.ini and nginx if enabled.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
skeletonDirectory = mkOption {
|
|
||||||
default = "";
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
The directory where the skeleton files are located. These files will be
|
|
||||||
copied to the data directory of new users. Leave empty to not copy any
|
|
||||||
skeleton files.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
nginx.enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Whether to enable nginx virtual host management.
|
|
||||||
Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.<name></literal>.
|
|
||||||
See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
webfinger = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Enable this option if you plan on using the webfinger plugin.
|
|
||||||
The appropriate nginx rewrite rules will be added to your configuration.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
phpOptions = mkOption {
|
|
||||||
type = types.attrsOf types.str;
|
|
||||||
default = {
|
|
||||||
short_open_tag = "Off";
|
|
||||||
expose_php = "Off";
|
|
||||||
error_reporting = "E_ALL & ~E_DEPRECATED & ~E_STRICT";
|
|
||||||
display_errors = "stderr";
|
|
||||||
"opcache.enable_cli" = "1";
|
|
||||||
"opcache.interned_strings_buffer" = "8";
|
|
||||||
"opcache.max_accelerated_files" = "10000";
|
|
||||||
"opcache.memory_consumption" = "128";
|
|
||||||
"opcache.revalidate_freq" = "1";
|
|
||||||
"opcache.fast_shutdown" = "1";
|
|
||||||
"openssl.cafile" = "/etc/ssl/certs/ca-certificates.crt";
|
|
||||||
catch_workers_output = "yes";
|
|
||||||
};
|
|
||||||
description = ''
|
|
||||||
Options for PHP's php.ini file for nextcloud.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
poolSettings = mkOption {
|
|
||||||
type = with types; attrsOf (oneOf [ str int bool ]);
|
|
||||||
default = {
|
|
||||||
"pm" = "dynamic";
|
|
||||||
"pm.max_children" = "32";
|
|
||||||
"pm.start_servers" = "2";
|
|
||||||
"pm.min_spare_servers" = "2";
|
|
||||||
"pm.max_spare_servers" = "4";
|
|
||||||
"pm.max_requests" = "500";
|
|
||||||
};
|
|
||||||
description = ''
|
|
||||||
Options for nextcloud's PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
poolConfig = mkOption {
|
|
||||||
type = types.nullOr types.lines;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Options for nextcloud's PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
config = {
|
|
||||||
dbtype = mkOption {
|
|
||||||
type = types.enum [ "sqlite" "pgsql" "mysql" ];
|
|
||||||
default = "sqlite";
|
|
||||||
description = "Database type.";
|
|
||||||
};
|
|
||||||
dbname = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = "nextcloud";
|
|
||||||
description = "Database name.";
|
|
||||||
};
|
|
||||||
dbuser = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = "nextcloud";
|
|
||||||
description = "Database user.";
|
|
||||||
};
|
|
||||||
dbpass = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Database password. Use <literal>dbpassFile</literal> to avoid this
|
|
||||||
being world-readable in the <literal>/nix/store</literal>.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
dbpassFile = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
The full path to a file that contains the database password.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
dbhost = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = "localhost";
|
|
||||||
description = ''
|
|
||||||
Database host.
|
|
||||||
|
|
||||||
Note: for using Unix authentication with PostgreSQL, this should be
|
|
||||||
set to <literal>/run/postgresql</literal>.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
dbport = mkOption {
|
|
||||||
type = with types; nullOr (either int str);
|
|
||||||
default = null;
|
|
||||||
description = "Database port.";
|
|
||||||
};
|
|
||||||
dbtableprefix = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = "Table prefix in Nextcloud database.";
|
|
||||||
};
|
|
||||||
adminuser = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "root";
|
|
||||||
description = "Admin username.";
|
|
||||||
};
|
|
||||||
adminpass = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Admin password. Use <literal>adminpassFile</literal> to avoid this
|
|
||||||
being world-readable in the <literal>/nix/store</literal>.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
adminpassFile = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
The full path to a file that contains the admin's password.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraTrustedDomains = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
description = ''
|
|
||||||
Trusted domains, from which the nextcloud installation will be
|
|
||||||
acessible. You don't need to add
|
|
||||||
<literal>services.nextcloud.hostname</literal> here.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
trustedProxies = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
description = ''
|
|
||||||
Trusted proxies, to provide if the nextcloud installation is being
|
|
||||||
proxied to secure against e.g. spoofing.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
overwriteProtocol = mkOption {
|
|
||||||
type = types.nullOr (types.enum [ "http" "https" ]);
|
|
||||||
default = null;
|
|
||||||
example = "https";
|
|
||||||
|
|
||||||
description = ''
|
|
||||||
Force Nextcloud to always use HTTPS i.e. for link generation. Nextcloud
|
|
||||||
uses the currently used protocol by default, but when behind a reverse-proxy,
|
|
||||||
it may use <literal>http</literal> for everything although Nextcloud
|
|
||||||
may be served via HTTPS.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
caching = {
|
|
||||||
apcu = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Whether to load the APCu module into PHP.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
redis = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Whether to load the Redis module into PHP.
|
|
||||||
You still need to enable Redis in your config.php.
|
|
||||||
See https://docs.nextcloud.com/server/14/admin_manual/configuration_server/caching_configuration.html
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
memcached = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Whether to load the Memcached module into PHP.
|
|
||||||
You still need to enable Memcached in your config.php.
|
|
||||||
See https://docs.nextcloud.com/server/14/admin_manual/configuration_server/caching_configuration.html
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
autoUpdateApps = {
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Run regular auto update of all apps installed from the nextcloud app store.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
startAt = mkOption {
|
|
||||||
type = with types; either str (listOf str);
|
|
||||||
default = "05:00:00";
|
|
||||||
example = "Sun 14:00:00";
|
|
||||||
description = ''
|
|
||||||
When to run the update. See `systemd.services.<name>.startAt`.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable (mkMerge [
|
|
||||||
{
|
|
||||||
assertions = let acfg = cfg.config;
|
|
||||||
in [
|
|
||||||
{
|
|
||||||
assertion = !(acfg.dbpass != null && acfg.dbpassFile != null);
|
|
||||||
message = "Please specify no more than one of dbpass or dbpassFile";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
assertion = ((acfg.adminpass != null || acfg.adminpassFile != null)
|
|
||||||
&& !(acfg.adminpass != null && acfg.adminpassFile != null));
|
|
||||||
message = "Please specify exactly one of adminpass or adminpassFile";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
warnings = optional (cfg.poolConfig != null) ''
|
|
||||||
Using config.services.nextcloud.poolConfig is deprecated and will become unsupported in a future release.
|
|
||||||
Please migrate your configuration to config.services.nextcloud.poolSettings.
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
systemd.timers.nextcloud-cron = {
|
|
||||||
wantedBy = [ "timers.target" ];
|
|
||||||
timerConfig.OnBootSec = "5m";
|
|
||||||
timerConfig.OnUnitActiveSec = "15m";
|
|
||||||
timerConfig.Unit = "nextcloud-cron.service";
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services = {
|
|
||||||
nextcloud-setup = let
|
|
||||||
c = cfg.config;
|
|
||||||
writePhpArrary = a:
|
|
||||||
"[${concatMapStringsSep "," (val: ''"${toString val}"'') a}]";
|
|
||||||
overrideConfig = pkgs.writeText "nextcloud-config.php" ''
|
|
||||||
<?php
|
|
||||||
${optionalString (c.dbpassFile != null) ''
|
|
||||||
function nix_read_pwd() {
|
|
||||||
$file = "${c.dbpassFile}";
|
|
||||||
if (!file_exists($file)) {
|
|
||||||
throw new \RuntimeException(sprintf(
|
|
||||||
"Cannot start Nextcloud, dbpass file %s set by NixOS doesn't exist!",
|
|
||||||
$file
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return trim(file_get_contents($file));
|
|
||||||
}
|
|
||||||
''}
|
|
||||||
$CONFIG = [
|
|
||||||
'apps_paths' => [
|
|
||||||
[ 'path' => '${cfg.home}/apps', 'url' => '/apps', 'writable' => false ],
|
|
||||||
[ 'path' => '${cfg.home}/store-apps', 'url' => '/store-apps', 'writable' => true ],
|
|
||||||
],
|
|
||||||
'datadirectory' => '${cfg.home}/data',
|
|
||||||
'skeletondirectory' => '${cfg.skeletonDirectory}',
|
|
||||||
${
|
|
||||||
optionalString cfg.caching.apcu
|
|
||||||
"'memcache.local' => '\\OC\\Memcache\\APCu',"
|
|
||||||
}
|
|
||||||
'log_type' => 'syslog',
|
|
||||||
'log_level' => '${builtins.toString cfg.logLevel}',
|
|
||||||
${
|
|
||||||
optionalString (c.overwriteProtocol != null)
|
|
||||||
"'overwriteprotocol' => '${c.overwriteProtocol}',"
|
|
||||||
}
|
|
||||||
${optionalString (c.dbname != null) "'dbname' => '${c.dbname}',"}
|
|
||||||
${optionalString (c.dbhost != null) "'dbhost' => '${c.dbhost}',"}
|
|
||||||
${
|
|
||||||
optionalString (c.dbport != null)
|
|
||||||
"'dbport' => '${toString c.dbport}',"
|
|
||||||
}
|
|
||||||
${optionalString (c.dbuser != null) "'dbuser' => '${c.dbuser}',"}
|
|
||||||
${
|
|
||||||
optionalString (c.dbtableprefix != null)
|
|
||||||
"'dbtableprefix' => '${toString c.dbtableprefix}',"
|
|
||||||
}
|
|
||||||
${
|
|
||||||
optionalString (c.dbpass != null)
|
|
||||||
"'dbpassword' => '${c.dbpass}',"
|
|
||||||
}
|
|
||||||
${
|
|
||||||
optionalString (c.dbpassFile != null)
|
|
||||||
"'dbpassword' => nix_read_pwd(),"
|
|
||||||
}
|
|
||||||
'dbtype' => '${c.dbtype}',
|
|
||||||
'trusted_domains' => ${
|
|
||||||
writePhpArrary ([ cfg.hostName ] ++ c.extraTrustedDomains)
|
|
||||||
},
|
|
||||||
'trusted_proxies' => ${writePhpArrary (c.trustedProxies)},
|
|
||||||
];
|
|
||||||
'';
|
|
||||||
occInstallCmd = let
|
|
||||||
dbpass = if c.dbpassFile != null then
|
|
||||||
''"$(<"${toString c.dbpassFile}")"''
|
|
||||||
else if c.dbpass != null then
|
|
||||||
''"${toString c.dbpass}"''
|
|
||||||
else
|
|
||||||
null;
|
|
||||||
adminpass = if c.adminpassFile != null then
|
|
||||||
''"$(<"${toString c.adminpassFile}")"''
|
|
||||||
else
|
|
||||||
''"${toString c.adminpass}"'';
|
|
||||||
installFlags = concatStringsSep " \\\n "
|
|
||||||
(mapAttrsToList (k: v: "${k} ${toString v}") {
|
|
||||||
"--database" = ''"${c.dbtype}"'';
|
|
||||||
# The following attributes are optional depending on the type of
|
|
||||||
# database. Those that evaluate to null on the left hand side
|
|
||||||
# will be omitted.
|
|
||||||
${if c.dbname != null then "--database-name" else null} =
|
|
||||||
''"${c.dbname}"'';
|
|
||||||
${if c.dbhost != null then "--database-host" else null} =
|
|
||||||
''"${c.dbhost}"'';
|
|
||||||
${if c.dbport != null then "--database-port" else null} =
|
|
||||||
''"${toString c.dbport}"'';
|
|
||||||
${if c.dbuser != null then "--database-user" else null} =
|
|
||||||
''"${c.dbuser}"'';
|
|
||||||
${
|
|
||||||
if (any (x: x != null) [ c.dbpass c.dbpassFile ]) then
|
|
||||||
"--database-pass"
|
|
||||||
else
|
|
||||||
null
|
|
||||||
} = dbpass;
|
|
||||||
${
|
|
||||||
if c.dbtableprefix != null then
|
|
||||||
"--database-table-prefix"
|
|
||||||
else
|
|
||||||
null
|
|
||||||
} = ''"${toString c.dbtableprefix}"'';
|
|
||||||
"--admin-user" = ''"${c.adminuser}"'';
|
|
||||||
"--admin-pass" = adminpass;
|
|
||||||
"--data-dir" = ''"${cfg.home}/data"'';
|
|
||||||
});
|
|
||||||
in ''
|
|
||||||
${occ}/bin/nextcloud-occ maintenance:install \
|
|
||||||
${installFlags}
|
|
||||||
'';
|
|
||||||
occSetTrustedDomainsCmd = concatStringsSep "\n" (imap0 (i: v: ''
|
|
||||||
${occ}/bin/nextcloud-occ config:system:set trusted_domains \
|
|
||||||
${toString i} --value="${toString v}"
|
|
||||||
'') ([ cfg.hostName ] ++ cfg.config.extraTrustedDomains));
|
|
||||||
|
|
||||||
in {
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
before = [ "phpfpm-nextcloud.service" ];
|
|
||||||
path = [ occ ];
|
|
||||||
script = ''
|
|
||||||
chmod og+x ${cfg.home}
|
|
||||||
ln -sf ${pkgs.nextcloud}/apps ${cfg.home}/
|
|
||||||
mkdir -p ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps
|
|
||||||
ln -sf ${overrideConfig} ${cfg.home}/config/override.config.php
|
|
||||||
|
|
||||||
chown -R nextcloud:nginx ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps
|
|
||||||
|
|
||||||
# Do not install if already installed
|
|
||||||
if [[ ! -e ${cfg.home}/config/config.php ]]; then
|
|
||||||
${occInstallCmd}
|
|
||||||
fi
|
|
||||||
|
|
||||||
${occ}/bin/nextcloud-occ upgrade
|
|
||||||
|
|
||||||
${occ}/bin/nextcloud-occ config:system:delete trusted_domains
|
|
||||||
${occSetTrustedDomainsCmd}
|
|
||||||
'';
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
};
|
|
||||||
nextcloud-cron = {
|
|
||||||
environment.NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
serviceConfig.User = "nextcloud";
|
|
||||||
serviceConfig.ExecStart =
|
|
||||||
"${phpPackage}/bin/php -f ${pkgs.nextcloud}/cron.php";
|
|
||||||
};
|
|
||||||
nextcloud-update-plugins = mkIf cfg.autoUpdateApps.enable {
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
serviceConfig.ExecStart = "${occ}/bin/nextcloud-occ app:update --all";
|
|
||||||
serviceConfig.User = "nextcloud";
|
|
||||||
startAt = cfg.autoUpdateApps.startAt;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.phpfpm = {
|
|
||||||
pools.nextcloud = {
|
|
||||||
user = "nextcloud";
|
|
||||||
group = "nginx";
|
|
||||||
phpOptions = phpOptionsStr;
|
|
||||||
phpPackage = phpPackage;
|
|
||||||
phpEnv = {
|
|
||||||
NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
|
|
||||||
PATH =
|
|
||||||
"/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin";
|
|
||||||
};
|
|
||||||
settings = mapAttrs (name: mkDefault) {
|
|
||||||
"listen.owner" = "nginx";
|
|
||||||
"listen.group" = "nginx";
|
|
||||||
} // cfg.poolSettings;
|
|
||||||
extraConfig = cfg.poolConfig;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
users.extraUsers.nextcloud = {
|
|
||||||
home = "${cfg.home}";
|
|
||||||
group = "nginx";
|
|
||||||
createHome = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [ occ ];
|
|
||||||
}
|
|
||||||
|
|
||||||
(mkIf cfg.nginx.enable {
|
|
||||||
services.nginx = {
|
|
||||||
enable = true;
|
|
||||||
virtualHosts = {
|
|
||||||
${cfg.hostName} = {
|
|
||||||
root = pkgs.nextcloud;
|
|
||||||
locations = {
|
|
||||||
"= /robots.txt" = {
|
|
||||||
priority = 100;
|
|
||||||
extraConfig = ''
|
|
||||||
allow all;
|
|
||||||
log_not_found off;
|
|
||||||
access_log off;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
"/" = {
|
|
||||||
priority = 200;
|
|
||||||
extraConfig = "rewrite ^ /index.php;";
|
|
||||||
};
|
|
||||||
"~ ^/store-apps" = {
|
|
||||||
priority = 201;
|
|
||||||
extraConfig = "root ${cfg.home};";
|
|
||||||
};
|
|
||||||
"= /.well-known/carddav" = {
|
|
||||||
priority = 210;
|
|
||||||
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
|
|
||||||
};
|
|
||||||
"= /.well-known/caldav" = {
|
|
||||||
priority = 210;
|
|
||||||
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
|
|
||||||
};
|
|
||||||
"~ ^\\/(?:build|tests|config|lib|3rdparty|templates|data)\\/" = {
|
|
||||||
priority = 300;
|
|
||||||
extraConfig = "deny all;";
|
|
||||||
};
|
|
||||||
"~ ^\\/(?:\\.|autotest|occ|issue|indie|db_|console)" = {
|
|
||||||
priority = 300;
|
|
||||||
extraConfig = "deny all;";
|
|
||||||
};
|
|
||||||
"~ ^\\/(?:index|remote|public|cron|core/ajax\\/update|status|ocs\\/v[12]|updater\\/.+|ocs-provider\\/.+|ocm-provider\\/.+)\\.php(?:$|\\/)" =
|
|
||||||
{
|
|
||||||
priority = 500;
|
|
||||||
extraConfig = ''
|
|
||||||
include ${config.services.nginx.package}/conf/fastcgi.conf;
|
|
||||||
fastcgi_split_path_info ^(.+\.php)(\\/.*)$;
|
|
||||||
try_files $fastcgi_script_name =404;
|
|
||||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|
||||||
fastcgi_param HTTPS ${if cfg.https then "on" else "off"};
|
|
||||||
fastcgi_param modHeadersAvailable true;
|
|
||||||
fastcgi_param front_controller_active true;
|
|
||||||
fastcgi_pass unix:${fpm.socket};
|
|
||||||
fastcgi_intercept_errors on;
|
|
||||||
fastcgi_request_buffering off;
|
|
||||||
fastcgi_read_timeout 120s;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
"~ ^\\/(?:updater|ocs-provider|ocm-provider)(?:$|\\/)".extraConfig =
|
|
||||||
''
|
|
||||||
try_files $uri/ =404;
|
|
||||||
index index.php;
|
|
||||||
'';
|
|
||||||
"~ \\.(?:css|js|woff2?|svg|gif)$".extraConfig = ''
|
|
||||||
try_files $uri /index.php$request_uri;
|
|
||||||
add_header Cache-Control "public, max-age=15778463";
|
|
||||||
add_header X-Content-Type-Options nosniff;
|
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
|
||||||
add_header X-Robots-Tag none;
|
|
||||||
add_header X-Download-Options noopen;
|
|
||||||
add_header X-Permitted-Cross-Domain-Policies none;
|
|
||||||
add_header X-Frame-Options sameorigin;
|
|
||||||
add_header Referrer-Policy no-referrer;
|
|
||||||
access_log off;
|
|
||||||
'';
|
|
||||||
"~ \\.(?:png|html|ttf|ico|jpg|jpeg)$".extraConfig = ''
|
|
||||||
try_files $uri /index.php$request_uri;
|
|
||||||
access_log off;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
extraConfig = ''
|
|
||||||
add_header X-Content-Type-Options nosniff;
|
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
|
||||||
add_header X-Robots-Tag none;
|
|
||||||
add_header X-Download-Options noopen;
|
|
||||||
add_header X-Permitted-Cross-Domain-Policies none;
|
|
||||||
add_header X-Frame-Options sameorigin;
|
|
||||||
add_header Referrer-Policy no-referrer;
|
|
||||||
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
|
||||||
error_page 403 /core/templates/403.php;
|
|
||||||
error_page 404 /core/templates/404.php;
|
|
||||||
client_max_body_size ${cfg.maxUploadSize};
|
|
||||||
fastcgi_buffers 64 4K;
|
|
||||||
fastcgi_hide_header X-Powered-By;
|
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_comp_level 4;
|
|
||||||
gzip_min_length 256;
|
|
||||||
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
|
||||||
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
|
|
||||||
|
|
||||||
${optionalString cfg.webfinger ''
|
|
||||||
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
|
|
||||||
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
|
|
||||||
''}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
|
|
||||||
# meta.doc = ./nextcloud.xml;
|
|
||||||
}
|
|
|
@ -1,505 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
# assert lib.versionOlder lib.version "20.09";
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.services.syncthing;
|
|
||||||
defaultUser = "syncthing";
|
|
||||||
|
|
||||||
devices = mapAttrsToList (name: device: {
|
|
||||||
deviceID = device.id;
|
|
||||||
inherit (device) name addresses introducer;
|
|
||||||
}) cfg.declarative.devices;
|
|
||||||
|
|
||||||
folders = mapAttrsToList (_: folder: {
|
|
||||||
inherit (folder) path id label type;
|
|
||||||
devices = map (device: { deviceId = cfg.declarative.devices.${device}.id; })
|
|
||||||
folder.devices;
|
|
||||||
rescanIntervalS = folder.rescanInterval;
|
|
||||||
fsWatcherEnabled = folder.watch;
|
|
||||||
fsWatcherDelayS = folder.watchDelay;
|
|
||||||
ignorePerms = folder.ignorePerms;
|
|
||||||
versioning = folder.versioning;
|
|
||||||
}) (filterAttrs (_: folder: folder.enable) cfg.declarative.folders);
|
|
||||||
|
|
||||||
# get the api key by parsing the config.xml
|
|
||||||
getApiKey = pkgs.writers.writeDash "getAPIKey" ''
|
|
||||||
${pkgs.libxml2}/bin/xmllint \
|
|
||||||
--xpath 'string(configuration/gui/apikey)'\
|
|
||||||
${cfg.configDir}/config.xml
|
|
||||||
'';
|
|
||||||
|
|
||||||
updateConfig = pkgs.writers.writeDash "merge-syncthing-config" ''
|
|
||||||
set -efu
|
|
||||||
# wait for syncthing port to open
|
|
||||||
until ${pkgs.curl}/bin/curl -Ss ${cfg.guiAddress} -o /dev/null; do
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
API_KEY=$(${getApiKey})
|
|
||||||
OLD_CFG=$(${pkgs.curl}/bin/curl -Ss \
|
|
||||||
-H "X-API-Key: $API_KEY" \
|
|
||||||
${cfg.guiAddress}/rest/system/config)
|
|
||||||
|
|
||||||
# generate the new config by merging with the nixos config options
|
|
||||||
NEW_CFG=$(echo "$OLD_CFG" | ${pkgs.jq}/bin/jq -s '.[] as $in | $in * {
|
|
||||||
"devices": (${builtins.toJSON devices}${
|
|
||||||
optionalString (!cfg.declarative.overrideDevices) " + $in.devices"
|
|
||||||
}),
|
|
||||||
"folders": (${builtins.toJSON folders}${
|
|
||||||
optionalString (!cfg.declarative.overrideFolders) " + $in.folders"
|
|
||||||
})
|
|
||||||
}')
|
|
||||||
|
|
||||||
# POST the new config to syncthing
|
|
||||||
echo "$NEW_CFG" | ${pkgs.curl}/bin/curl -Ss \
|
|
||||||
-H "X-API-Key: $API_KEY" \
|
|
||||||
${cfg.guiAddress}/rest/system/config -d @-
|
|
||||||
|
|
||||||
# restart syncthing after sending the new config
|
|
||||||
${pkgs.curl}/bin/curl -Ss \
|
|
||||||
-H "X-API-Key: $API_KEY" \
|
|
||||||
-X POST \
|
|
||||||
${cfg.guiAddress}/rest/system/restart
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
|
|
||||||
###### interface
|
|
||||||
options = {
|
|
||||||
test.services.syncthing = {
|
|
||||||
|
|
||||||
enable = mkEnableOption ''
|
|
||||||
Syncthing - the self-hosted open-source alternative
|
|
||||||
to Dropbox and Bittorrent Sync. Initial interface will be
|
|
||||||
available on http://127.0.0.1:8384/.
|
|
||||||
'';
|
|
||||||
|
|
||||||
declarative = {
|
|
||||||
cert = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Path to users cert.pem file, will be copied into the syncthing's
|
|
||||||
<literal>configDir</literal>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
key = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Path to users key.pem file, will be copied into the syncthing's
|
|
||||||
<literal>configDir</literal>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
overrideDevices = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Whether to delete the devices which are not configured via the
|
|
||||||
<literal>declarative.devices</literal> option.
|
|
||||||
If set to false, devices added via the webinterface will
|
|
||||||
persist but will have to be deleted manually.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
devices = mkOption {
|
|
||||||
default = { };
|
|
||||||
description = ''
|
|
||||||
Peers/devices which syncthing should communicate with.
|
|
||||||
'';
|
|
||||||
example = {
|
|
||||||
bigbox = {
|
|
||||||
id =
|
|
||||||
"7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU";
|
|
||||||
addresses = [ "tcp://192.168.0.10:51820" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
type = types.attrsOf (types.submodule ({ config, ... }: {
|
|
||||||
options = {
|
|
||||||
|
|
||||||
name = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = config._module.args.name;
|
|
||||||
description = ''
|
|
||||||
Name of the device
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
addresses = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
description = ''
|
|
||||||
The addresses used to connect to the device.
|
|
||||||
If this is let empty, dynamic configuration is attempted
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
id = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
The id of the other peer, this is mandatory. It's documented at
|
|
||||||
https://docs.syncthing.net/dev/device-ids.html
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
introducer = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
If the device should act as an introducer and be allowed
|
|
||||||
to add folders on this computer.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
overrideFolders = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Whether to delete the folders which are not configured via the
|
|
||||||
<literal>declarative.folders</literal> option.
|
|
||||||
If set to false, folders added via the webinterface will persist
|
|
||||||
but will have to be deleted manually.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
folders = mkOption {
|
|
||||||
default = { };
|
|
||||||
description = ''
|
|
||||||
folders which should be shared by syncthing.
|
|
||||||
'';
|
|
||||||
example = {
|
|
||||||
"/home/user/sync" = {
|
|
||||||
id = "syncme";
|
|
||||||
devices = [ "bigbox" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
type = types.attrsOf (types.submodule ({ config, ... }: {
|
|
||||||
options = {
|
|
||||||
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
share this folder.
|
|
||||||
This option is useful when you want to define all folders
|
|
||||||
in one place, but not every machine should share all folders.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
path = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = config._module.args.name;
|
|
||||||
description = ''
|
|
||||||
The path to the folder which should be shared.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
id = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = config._module.args.name;
|
|
||||||
description = ''
|
|
||||||
The id of the folder. Must be the same on all devices.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
label = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = config._module.args.name;
|
|
||||||
description = ''
|
|
||||||
The label of the folder.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
devices = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
description = ''
|
|
||||||
The devices this folder should be shared with. Must be defined
|
|
||||||
in the <literal>declarative.devices</literal> attribute.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
versioning = mkOption {
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
how to keep changed/deleted files with syncthing.
|
|
||||||
there are 4 different types of versioning with different parameters
|
|
||||||
see https://docs.syncthing.net/users/versioning.html#simple-file-versioning
|
|
||||||
'';
|
|
||||||
example = [
|
|
||||||
{
|
|
||||||
versioning = {
|
|
||||||
type = "simple";
|
|
||||||
params.keep = "10";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
versioning = {
|
|
||||||
type = "trashcan";
|
|
||||||
params.cleanoutDays = "1000";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
versioning = {
|
|
||||||
type = "staggered";
|
|
||||||
params = {
|
|
||||||
cleanInterval = "3600";
|
|
||||||
maxAge = "31536000";
|
|
||||||
versionsPath = "/syncthing/backup";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
versioning = {
|
|
||||||
type = "external";
|
|
||||||
params.versionsPath = pkgs.writers.writeBash "backup" ''
|
|
||||||
folderpath="$1"
|
|
||||||
filepath="$2"
|
|
||||||
rm -rf "$folderpath/$filepath"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
type = with types;
|
|
||||||
nullOr (submodule {
|
|
||||||
options = {
|
|
||||||
type = mkOption {
|
|
||||||
type =
|
|
||||||
enum [ "external" "simple" "staggered" "trashcan" ];
|
|
||||||
};
|
|
||||||
params = mkOption { type = attrsOf (either str path); };
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
rescanInterval = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
default = 3600;
|
|
||||||
description = ''
|
|
||||||
How often the folders should be rescaned for changes.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
type = mkOption {
|
|
||||||
type = types.enum [ "sendreceive" "sendonly" "receiveonly" ];
|
|
||||||
default = "sendreceive";
|
|
||||||
description = ''
|
|
||||||
Whether to send only changes from this folder, only receive them
|
|
||||||
or propagate both.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
watch = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Whether the folder should be watched for changes by inotify.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
watchDelay = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
default = 10;
|
|
||||||
description = ''
|
|
||||||
The delay after an inotify event is triggered.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
ignorePerms = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Whether to propagate permission changes.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
guiAddress = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "127.0.0.1:8384";
|
|
||||||
description = ''
|
|
||||||
Address to serve the GUI.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
systemService = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = "Auto launch Syncthing as a system service.";
|
|
||||||
};
|
|
||||||
|
|
||||||
user = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = defaultUser;
|
|
||||||
description = ''
|
|
||||||
Syncthing will be run under this user (user will be created if it doesn't exist.
|
|
||||||
This can be your user name).
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
group = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = defaultUser;
|
|
||||||
description = ''
|
|
||||||
Syncthing will be run under this group (group will not be created if it doesn't exist.
|
|
||||||
This can be your user name).
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
all_proxy = mkOption {
|
|
||||||
type = with types; nullOr str;
|
|
||||||
default = null;
|
|
||||||
example = "socks5://address.com:1234";
|
|
||||||
description = ''
|
|
||||||
Overwrites all_proxy environment variable for the syncthing process to
|
|
||||||
the given value. This is normaly used to let relay client connect
|
|
||||||
through SOCKS5 proxy server.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
dataDir = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = "/var/lib/syncthing";
|
|
||||||
description = ''
|
|
||||||
Path where synced directories will exist.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
configDir = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
description = ''
|
|
||||||
Path where the settings and keys will exist.
|
|
||||||
'';
|
|
||||||
default = let
|
|
||||||
nixos = config.system.stateVersion;
|
|
||||||
cond = versionAtLeast nixos "19.03";
|
|
||||||
in cfg.dataDir + (optionalString cond "/.config/syncthing");
|
|
||||||
};
|
|
||||||
|
|
||||||
openDefaultPorts = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
example = literalExample "true";
|
|
||||||
description = ''
|
|
||||||
Open the default ports in the firewall:
|
|
||||||
- TCP 22000 for transfers
|
|
||||||
- UDP 21027 for discovery
|
|
||||||
If multiple users are running syncthing on this machine, you will need to manually open a set of ports for each instance and leave this disabled.
|
|
||||||
Alternatively, if are running only a single instance on this machine using the default ports, enable this.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
package = mkOption {
|
|
||||||
type = types.package;
|
|
||||||
default = pkgs.syncthing;
|
|
||||||
defaultText = "pkgs.syncthing";
|
|
||||||
example = literalExample "pkgs.syncthing";
|
|
||||||
description = ''
|
|
||||||
Syncthing package to use.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#imports = [
|
|
||||||
# (mkRemovedOptionModule ["services" "syncthing" "useInotify"] ''
|
|
||||||
# This option was removed because syncthing now has the inotify functionality included under the name "fswatcher".
|
|
||||||
# It can be enabled on a per-folder basis through the webinterface.
|
|
||||||
# '')
|
|
||||||
#];
|
|
||||||
|
|
||||||
###### implementation
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
|
|
||||||
networking.firewall = mkIf cfg.openDefaultPorts {
|
|
||||||
allowedTCPPorts = [ 22000 ];
|
|
||||||
allowedUDPPorts = [ 21027 ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.packages = [ pkgs.syncthing ];
|
|
||||||
|
|
||||||
users.users = mkIf (cfg.systemService && cfg.user == defaultUser) {
|
|
||||||
${defaultUser} = {
|
|
||||||
group = cfg.group;
|
|
||||||
home = cfg.dataDir;
|
|
||||||
createHome = true;
|
|
||||||
uid = config.ids.uids.syncthing;
|
|
||||||
description = "Syncthing daemon user";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
users.groups = mkIf (cfg.systemService && cfg.group == defaultUser) {
|
|
||||||
${defaultUser}.gid = config.ids.gids.syncthing;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services = {
|
|
||||||
syncthing = mkIf cfg.systemService {
|
|
||||||
description = "Syncthing service";
|
|
||||||
after = [ "network.target" ];
|
|
||||||
environment = {
|
|
||||||
STNORESTART = "yes";
|
|
||||||
STNOUPGRADE = "yes";
|
|
||||||
inherit (cfg) all_proxy;
|
|
||||||
} // config.networking.proxy.envVars;
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Restart = "on-failure";
|
|
||||||
SuccessExitStatus = "2 3 4";
|
|
||||||
RestartForceExitStatus = "3 4";
|
|
||||||
User = cfg.user;
|
|
||||||
Group = cfg.group;
|
|
||||||
ExecStartPre =
|
|
||||||
mkIf (cfg.declarative.cert != null || cfg.declarative.key != null)
|
|
||||||
"+${
|
|
||||||
pkgs.writers.writeBash "syncthing-copy-keys" ''
|
|
||||||
install -dm700 -o ${cfg.user} -g ${cfg.group} ${cfg.configDir}
|
|
||||||
${optionalString (cfg.declarative.cert != null) ''
|
|
||||||
install -Dm400 -o ${cfg.user} -g ${cfg.group} ${
|
|
||||||
toString cfg.declarative.cert
|
|
||||||
} ${cfg.configDir}/cert.pem
|
|
||||||
''}
|
|
||||||
${optionalString (cfg.declarative.key != null) ''
|
|
||||||
install -Dm400 -o ${cfg.user} -g ${cfg.group} ${
|
|
||||||
toString cfg.declarative.key
|
|
||||||
} ${cfg.configDir}/key.pem
|
|
||||||
''}
|
|
||||||
''
|
|
||||||
}";
|
|
||||||
ExecStart = ''
|
|
||||||
${cfg.package}/bin/syncthing \
|
|
||||||
-no-browser \
|
|
||||||
-gui-address=${cfg.guiAddress} \
|
|
||||||
-home=${cfg.configDir}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
syncthing-init = mkIf
|
|
||||||
(cfg.declarative.devices != { } || cfg.declarative.folders != { }) {
|
|
||||||
after = [ "syncthing.service" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
User = cfg.user;
|
|
||||||
RemainAfterExit = true;
|
|
||||||
Type = "oneshot";
|
|
||||||
ExecStart = updateConfig;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
syncthing-resume = { wantedBy = [ "suspend.target" ]; };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -16,6 +16,7 @@ in {
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
git
|
git
|
||||||
tig
|
tig
|
||||||
|
lazygit
|
||||||
git-crypt
|
git-crypt
|
||||||
gitAndTools.gitflow
|
gitAndTools.gitflow
|
||||||
gitAndTools.gitSVN
|
gitAndTools.gitSVN
|
||||||
|
|
Loading…
Reference in a new issue