1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.icecast; 7 configFile = pkgs.writeText "icecast.xml" '' 8 <icecast> 9 <hostname>${cfg.hostname}</hostname> 10 11 <authentication> 12 <admin-user>${cfg.admin.user}</admin-user> 13 <admin-password>${cfg.admin.password}</admin-password> 14 </authentication> 15 16 <paths> 17 <logdir>${cfg.logDir}</logdir> 18 <adminroot>${pkgs.icecast}/share/icecast/admin</adminroot> 19 <webroot>${pkgs.icecast}/share/icecast/web</webroot> 20 <alias source="/" dest="/status.xsl"/> 21 </paths> 22 23 <listen-socket> 24 <port>${toString cfg.listen.port}</port> 25 <bind-address>${cfg.listen.address}</bind-address> 26 </listen-socket> 27 28 <security> 29 <chroot>0</chroot> 30 <changeowner> 31 <user>${cfg.user}</user> 32 <group>${cfg.group}</group> 33 </changeowner> 34 </security> 35 36 ${cfg.extraConf} 37 </icecast> 38 ''; 39in { 40 41 ###### interface 42 43 options = { 44 45 services.icecast = { 46 47 enable = mkEnableOption "Icecast server"; 48 49 hostname = mkOption { 50 type = types.str; 51 description = "DNS name or IP address that will be used for the stream directory lookups or possibily the playlist generation if a Host header is not provided."; 52 default = config.networking.domain; 53 }; 54 55 admin = { 56 user = mkOption { 57 type = types.str; 58 description = "Username used for all administration functions."; 59 default = "admin"; 60 }; 61 62 password = mkOption { 63 type = types.str; 64 description = "Password used for all administration functions."; 65 }; 66 }; 67 68 logDir = mkOption { 69 type = types.path; 70 description = "Base directory used for logging."; 71 default = "/var/log/icecast"; 72 }; 73 74 listen = { 75 port = mkOption { 76 type = types.int; 77 description = "TCP port that will be used to accept client connections."; 78 default = 8000; 79 }; 80 81 address = mkOption { 82 type = types.str; 83 description = "Address Icecast will listen on."; 84 default = "::"; 85 }; 86 }; 87 88 user = mkOption { 89 type = types.str; 90 description = "User privileges for the server."; 91 default = "nobody"; 92 }; 93 94 group = mkOption { 95 type = types.str; 96 description = "Group privileges for the server."; 97 default = "nogroup"; 98 }; 99 100 extraConf = mkOption { 101 type = types.lines; 102 description = "icecast.xml content."; 103 default = ""; 104 }; 105 106 }; 107 108 }; 109 110 111 ###### implementation 112 113 config = mkIf cfg.enable { 114 115 systemd.services.icecast = { 116 after = [ "network.target" ]; 117 description = "Icecast Network Audio Streaming Server"; 118 wantedBy = [ "multi-user.target" ]; 119 120 preStart = "mkdir -p ${cfg.logDir} && chown ${cfg.user}:${cfg.group} ${cfg.logDir}"; 121 serviceConfig = { 122 Type = "simple"; 123 ExecStart = "${pkgs.icecast}/bin/icecast -c ${configFile}"; 124 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 125 }; 126 }; 127 128 }; 129 130}