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