1{ config, pkgs, lib, ... }: 2 3with lib; 4 5let 6 cfg = config.services.rsyncd; 7 settingsFormat = pkgs.formats.ini { }; 8 configFile = settingsFormat.generate "rsyncd.conf" cfg.settings; 9in { 10 options = { 11 services.rsyncd = { 12 13 enable = mkEnableOption (lib.mdDoc "the rsync daemon"); 14 15 port = mkOption { 16 default = 873; 17 type = types.port; 18 description = lib.mdDoc "TCP port the daemon will listen on."; 19 }; 20 21 settings = mkOption { 22 inherit (settingsFormat) type; 23 default = { }; 24 example = { 25 global = { 26 uid = "nobody"; 27 gid = "nobody"; 28 "use chroot" = true; 29 "max connections" = 4; 30 }; 31 ftp = { 32 path = "/var/ftp/./pub"; 33 comment = "whole ftp area"; 34 }; 35 cvs = { 36 path = "/data/cvs"; 37 comment = "CVS repository (requires authentication)"; 38 "auth users" = [ "tridge" "susan" ]; 39 "secrets file" = "/etc/rsyncd.secrets"; 40 }; 41 }; 42 description = lib.mdDoc '' 43 Configuration for rsyncd. See 44 {manpage}`rsyncd.conf(5)`. 45 ''; 46 }; 47 48 socketActivated = mkOption { 49 default = false; 50 type = types.bool; 51 description = 52 lib.mdDoc "If enabled Rsync will be socket-activated rather than run persistently."; 53 }; 54 55 }; 56 }; 57 58 imports = (map (option: 59 mkRemovedOptionModule [ "services" "rsyncd" option ] 60 "This option was removed in favor of `services.rsyncd.settings`.") [ 61 "address" 62 "extraConfig" 63 "motd" 64 "user" 65 "group" 66 ]); 67 68 config = mkIf cfg.enable { 69 70 services.rsyncd.settings.global.port = toString cfg.port; 71 72 systemd = let 73 serviceConfigSecurity = { 74 ProtectSystem = "full"; 75 PrivateDevices = "on"; 76 NoNewPrivileges = "on"; 77 }; 78 in { 79 services.rsync = { 80 enable = !cfg.socketActivated; 81 aliases = [ "rsyncd.service" ]; 82 83 description = "fast remote file copy program daemon"; 84 after = [ "network.target" ]; 85 documentation = [ "man:rsync(1)" "man:rsyncd.conf(5)" ]; 86 87 serviceConfig = serviceConfigSecurity // { 88 ExecStart = 89 "${pkgs.rsync}/bin/rsync --daemon --no-detach --config=${configFile}"; 90 RestartSec = 1; 91 }; 92 93 wantedBy = [ "multi-user.target" ]; 94 }; 95 96 services."rsync@" = { 97 description = "fast remote file copy program daemon"; 98 after = [ "network.target" ]; 99 100 serviceConfig = serviceConfigSecurity // { 101 ExecStart = "${pkgs.rsync}/bin/rsync --daemon --config=${configFile}"; 102 StandardInput = "socket"; 103 StandardOutput = "inherit"; 104 StandardError = "journal"; 105 }; 106 }; 107 108 sockets.rsync = { 109 enable = cfg.socketActivated; 110 111 description = "socket for fast remote file copy program daemon"; 112 conflicts = [ "rsync.service" ]; 113 114 listenStreams = [ (toString cfg.port) ]; 115 socketConfig.Accept = true; 116 117 wantedBy = [ "sockets.target" ]; 118 }; 119 }; 120 121 }; 122 123 meta.maintainers = with lib.maintainers; [ ehmry ]; 124 125 # TODO: socket activated rsyncd 126 127}