From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms13.migadu.com with LMTPS id YK1gCn5tyGbMyAAAe85BDQ:P1 (envelope-from ) for ; Fri, 23 Aug 2024 11:07:42 +0000 Received: from aspmx1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2.migadu.com with LMTPS id YK1gCn5tyGbMyAAAe85BDQ (envelope-from ) for ; Fri, 23 Aug 2024 13:07:42 +0200 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=debbugs.gnu.org header.s=debbugs-gnu-org header.b=ec7EeOf0; dkim=fail ("headers rsa verify failed") header.d=fabionatali.com header.s=gm1 header.b=CDvri3Cj; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=gnu.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1724411262; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=Moxaj0gowUdUsr05GFT/JalCHHneQl1jbRZJwphVwXU=; b=biWkc5s+rl8MOB5KTiwnEm0o0hgNTiRUOzlRcmtoNFHD1u2QaqLKuaTePCCrxsLUGWcGce X/zW3y2qKlJpMj7wiBM4Aj9+CdN8eKcMwyY3CQiwB4SwJoiarQpz6EKKipayErj/66nyR7 8eKVpxlw5jVxPhDpO86ZwLe85qz21uvScHvlovxb0oEz9BLESYK+MXVr8ILy7ZQfWe3KLp LnKd10wKRs9728gsg7zGNYdshiNDdNFJ21wR0imnqwk5TgWJboFkvqlLrK/kJirnUJ6B0F MdREZ4XdWuDPMX77VRxhwf4ioMvdP9N/4LXVfQFaZFDlq90SskMZR06K4yHLdQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=debbugs.gnu.org header.s=debbugs-gnu-org header.b=ec7EeOf0; dkim=fail ("headers rsa verify failed") header.d=fabionatali.com header.s=gm1 header.b=CDvri3Cj; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=gnu.org ARC-Seal: i=1; s=key1; d=yhetil.org; t=1724411262; a=rsa-sha256; cv=none; b=VZyy2JlXTTfbxIRadEOsyIi8UZqlIjDVK0Kf+FFDeMNAI+Ob+nKSRX+VNrw4uaI/I1Iwbn 9UYR/mBB3uqWLRbGWo3C1INVr5r1EjCg5B77ufQ6rqHGXhCFkb9+auskf2gRuekW1NcSBX PlFpBTGbuuzdHlV49Od6eD5ly/krFsq0m3jAiTc+gjg6zFLn+QjvkdAba/gDdtiFoU7u2H b/JA6soZnoM0Q8gBPvFGd9/9XHI1KqgWAXUqNbyPtEjH7HKT/AbB8qxgyt2t8EF3mmw9Pp KshkQ3kuE2RvHFEFmUuDTQUt+r/aQBxj6S+47kGmiTV236ZQNQUGIxr0B+erFQ== Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id CA1AA758C7 for ; Fri, 23 Aug 2024 13:07:39 +0200 (CEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1shS8X-0004lN-B9; Fri, 23 Aug 2024 07:07:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1shS8T-0004WG-JT for guix-patches@gnu.org; Fri, 23 Aug 2024 07:07:18 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1shS8S-00041Y-JX; Fri, 23 Aug 2024 07:07:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:References:In-Reply-To:Date:From:To:Subject; bh=Moxaj0gowUdUsr05GFT/JalCHHneQl1jbRZJwphVwXU=; b=ec7EeOf0Z6Uq78C2bPPQxWxrdFyWWvhutA+lRFzbrWBMoBAYXMhakqas3VkvfbrGW+VElNBPg9dyQkb/Srikt7/TtNGt+7gMj5i8UYjvdKp2MwH7lg1VjmYrpPyjllURXDRoylXHp9oVJM6NXZGeQMFGuMIzgGmtKPfkve7WPoVX3RPCFC08WGlTmWusWmvd5lADwD94YwU6fd1U1NT/49porMuzP7+9kFxaVYdNzRPuqiE7Y+7qAclMgrPh4D7RFIfoXoLVG71xFtgp7fReOOkywW0btV0oEruVu//Fv1xw4WoOr7yZHxm1Slu8iyON16RFxZJwtlw50zQshcQDyw==; Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1shS9C-0004Mw-47; Fri, 23 Aug 2024 07:08:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#72398] [PATCH v4] services: Add readymedia-service-type. Resent-From: Fabio Natali Original-Sender: "Debbugs-submit" Resent-CC: pelzflorian@pelzflorian.de, ludo@gnu.org, matt@excalamus.com, maxim.cournoyer@gmail.com, guix-patches@gnu.org Resent-Date: Fri, 23 Aug 2024 11:08:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 72398 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 72398@debbugs.gnu.org Cc: arunisaac@systemreboot.net, mirai@makinata.eu, Fabio Natali , Florian Pelz , Ludovic =?UTF-8?Q?Court=C3=A8s?= , Matthew Trzcinski , Maxim Cournoyer X-Debbugs-Original-Xcc: Florian Pelz , Ludovic =?UTF-8?Q?Court=C3=A8s?= , Matthew Trzcinski , Maxim Cournoyer Received: via spool by 72398-submit@debbugs.gnu.org id=B72398.172441125316750 (code B ref 72398); Fri, 23 Aug 2024 11:08:02 +0000 Received: (at 72398) by debbugs.gnu.org; 23 Aug 2024 11:07:33 +0000 Received: from localhost ([127.0.0.1]:39066 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1shS8i-0004M5-2p for submit@debbugs.gnu.org; Fri, 23 Aug 2024 07:07:33 -0400 Received: from relay9-d.mail.gandi.net ([217.70.183.199]:34313) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1shS8e-0004Ll-9x for 72398@debbugs.gnu.org; Fri, 23 Aug 2024 07:07:30 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id EBD12FF805; Fri, 23 Aug 2024 11:06:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fabionatali.com; s=gm1; t=1724411174; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Moxaj0gowUdUsr05GFT/JalCHHneQl1jbRZJwphVwXU=; b=CDvri3CjM/cLaQFGAIUX1A9tmOoRHdyOJ5/v6m1rE9fNHyrsKnPyob5vlGeoV2L02GFd4K c74jTLRrHhiMKD5kkh8ngYZhrQ/2OHGI7KuJTJA45un2hqNRBLVpJHfJ8XA9rymBQf+Ohx ja88QMFrdBcrE17zf2SjJOZBA9bI7Uz94CvmBJ/lA+mAEIQL/QP97rBrR9iIiCU+LrFN56 7o/9uNVLYGEy023TX6axR0395lcuEMovtML8bzQkBzAwQnRLXYiWpchvqYg5NTOZYBrjDz fYjDUN+F4NvGXTQ0wGepqQHrfJYrJptpEHASHni7fCdqW4sWzPMKlNc8otPgVQ== Date: Fri, 23 Aug 2024 12:04:42 +0100 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: <87r0agp27q.fsf@systemreboot.net> References: <87r0agp27q.fsf@systemreboot.net> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-GND-Sasl: me@fabionatali.com X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Fabio Natali X-ACL-Warn: , Fabio Natali via Guix-patches From: Fabio Natali via Guix-patches via Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN X-Spam-Score: -5.58 X-Migadu-Queue-Id: CA1AA758C7 X-Migadu-Scanner: mx10.migadu.com X-Migadu-Spam-Score: -5.58 X-TUID: oabXErTQZZSj * gnu/services/upnp.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: I80b02235ec36b7a1ea85fea98bdc9e08126b09a3 --- Ok, brilliant, thanks Arun. I'm sending a v4 then where I switch back to non-configurable ReadyMedia user and group. The patch also fixes the logging mechanism - in the previous versions the logging file was configurable but the service didn't make use of it. If you want to give this a last check in a VM, as per my previous messages in this thread, here's the relevant instructions. Create a folder, e.g. '/tmp/foo', and populate it with at least one music file, e.g. '/tmp/foo/foo.mp3'. Create a system definition that includes the ReadyMedia service: --8<---------------cut here---------------start------------->8--- (services (cons* (service gnome-desktop-service-type) (service readymedia-service-type (readymedia-configuration (media-directories (list (readymedia-media-directory (path "/music") (type 'A)))))) %desktop-services))) --8<---------------cut here---------------end--------------->8--- >From within the Guix repository checkout, once the ReadyMedia service patch has been applied, build and launch a VM with: --8<---------------cut here---------------start------------->8--- $(./pre-inst-env guix system vm --share=/tmp/foo=/music CONFIG) -m 2048 -smp 2 --8<---------------cut here---------------end--------------->8--- >From the VM, you should be able to verify that the ReadyMedia service is running with 'sudo herd status'. If available as a package in the VM, you should be able to use VLC to connect to the ReadyMedia service and play music from the '/tmp/foo' folder. You may want to follow these instructions https://www.vlchelp.com/access-media-upnp-dlna/. Let me know if you spot anything. If either of you are happy with it and want to gently push it upstream... that'd be fab. Thanks for all the help. Best, F. doc/guix.texi | 107 ++++++++++++++++++++++ gnu/local.mk | 1 + gnu/services/upnp.scm | 205 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 gnu/services/upnp.scm diff --git a/doc/guix.texi b/doc/guix.texi index fcaf6b3fbb..ddc997b6bf 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -129,6 +129,7 @@ Copyright @copyright{} 2024 Richard Sent@* Copyright @copyright{} 2024 Dariqq@* Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@* +Copyright @copyright{} 2024 Fabio Natali@* Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -41605,6 +41606,112 @@ Miscellaneous Services @end deftp +@c %end of fragment + +@cindex DLNA/UPnP +@subsubheading DLNA/UPnP Services + +The @code{(gnu services upnp)} module offers services related to the +DLNA and UPnP-VA networking protocols. For now, it provides the +@code{readymedia-service-type}. + +@uref{https://sourceforge.net/projects/minidlna/, ReadyMedia} +(formerly known as MiniDLNA) is a DLNA/UPnP-AV media server. The +project's daemon, @code{minidlnad}, can serve media files (audio, +pictures, and video) to DLNA/UPnP-AV clients available in the network. + +@code{readymedia-service-type} is a Guix service that wraps around +ReadyMedia's @code{minidlnad}. For increased security, the service +makes use of @code{least-authority-wrapper} which limits the resources +that the daemon has access to. The daemon runs as the +@code{readymedia} unprivileged user, which is a member of the +@code{readymedia} group. + +Consider the following configuration: + +@lisp +(use-service-modules upnp @dots{}) + +(operating-system + ;; @dots{} + (services + (list + (service readymedia-service-type + (readymedia-configuration + (media-directoriess + (list + (readymedia-media-directory (path "/media/audio") + (type 'A)) + (readymedia-media-directory (path "/media/video") + (type 'V)) + (readymedia-media-directory (path "/media/misc")))) + (extra-config '(("notify_interval" . 60))))) + ;; @dots{} + ))) +@end lisp + +This sets up the ReadyMedia daemon to serve files from the media +folders specified in @code{media-directories}. The +@code{media-directories} field is mandatory. All other fields (such +as network ports and the server name) come with a predefined default +and can be omitted. + +@c %start of fragment + +@deftp {Data Type} readymedia-configuration +Available @code{readymedia-configuration} fields are: + +@table @asis +@item @code{readymedia} (default: @code{readymedia}) (type: package) +The ReadyMedia package to be used for the service. + +@item @code{friendly-name} (default: @code{#f}) (type: maybe-string) +A custom name that will be displayed on connected clients. + +@item @code{media-directories} (type: list) +The list of media folders to serve content from. Each item is a +@code{readymedia-media-directory}. + +@item @code{cache-directory} (default: @code{"/var/cache/readymedia"}) (type: string) +A folder for ReadyMedia's cache files. If not existing already, the +folder will be created as part of the service activation and the +ReadyMedia user will be assigned ownership. + +@item @code{log-directory} (default: @code{"/var/log/readymedia"}) (type: string) +A folder for ReadyMedia's log files. If not existing already, the +folder will be created as part of the service activation and the +ReadyMedia user will be assigned ownership. + +@item @code{port} (default: @code{#f}) (type: maybe-integer) +A custom port that the service will be listening on. + +@item @code{extra-config} (default: @code{'()}) (type: alist) +An association list of further options, as accepted by ReadyMedia. + +@end table + +@end deftp + +@c %end of fragment + +@c %start of fragment + +@deftp {Data Type} readymedia-media-directory +A @code{media-directories} entry includes a @code{path} and, +optionally, a media type string. + +@table @asis +@item @code{path} (type: string) +The media folder location. + +@item @code{type} (default: @code{#f}) (type: maybe-symbol) +Valid media types are @code{'A} for audio, @code{'P} for pictures, +@code{'V} for video, and a combination of those individual symbols for +mixed types. False means no type specified. + +@end table + +@end deftp @c %end of fragment diff --git a/gnu/local.mk b/gnu/local.mk index ad5494fe95..ef4e6d006f 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -752,6 +752,7 @@ GNU_SYSTEM_MODULES = \ %D%/services/syncthing.scm \ %D%/services/sysctl.scm \ %D%/services/telephony.scm \ + %D%/services/upnp.scm \ %D%/services/version-control.scm \ %D%/services/vnc.scm \ %D%/services/vpn.scm \ diff --git a/gnu/services/upnp.scm b/gnu/services/upnp.scm new file mode 100644 index 0000000000..779da27837 --- /dev/null +++ b/gnu/services/upnp.scm @@ -0,0 +1,205 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2024 Fabio Natali +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu services upnp) + #:use-module (gnu build linux-container) + #:use-module (gnu packages admin) + #:use-module (gnu packages upnp) + #:use-module (gnu services admin) + #:use-module (gnu services base) + #:use-module (gnu services shepherd) + #:use-module (gnu services) + #:use-module (gnu system file-systems) + #:use-module (gnu system shadow) + #:use-module (guix gexp) + #:use-module (guix least-authority) + #:use-module (guix records) + #:use-module (ice-9 match) + #:export (%readymedia-log-file + %readymedia-user-account + %readymedia-user-group + readymedia-configuration + readymedia-configuration-cache-directory + readymedia-configuration-extra-config + readymedia-configuration-friendly-name + readymedia-configuration-log-directory + readymedia-configuration-media-directories + readymedia-configuration-port + readymedia-configuration-readymedia + readymedia-configuration? + readymedia-media-directory + readymedia-media-directory-path + readymedia-media-directory-type + readymedia-media-directory? + readymedia-service-type)) + +;;; Commentary: +;;; +;;; UPnP services. +;;; +;;; Code: + +(define %readymedia-user-group "readymedia") +(define %readymedia-user-account "readymedia") +(define %readymedia-log-file "minidlna.log") + +(define-record-type* + readymedia-configuration make-readymedia-configuration + readymedia-configuration? + (readymedia readymedia-configuration-readymedia + (default readymedia)) + (cache-directory readymedia-configuration-cache-directory + (default "/var/cache/readymedia")) + (log-directory readymedia-configuration-log-directory + (default "/var/log/readymedia")) + (friendly-name readymedia-configuration-friendly-name + (default #f)) + (media-directories readymedia-configuration-media-directories) + (port readymedia-configuration-port + (default #f)) + (extra-config readymedia-configuration-extra-config + (default '()))) + +;; READYMEDIA-MEDIA-DIR is a record that indicates path and media type of a +;; media folder. Type can be false (no media type specified) or a symbol +;; (e.g. 'A' for audio, 'V' for video, 'AV' for audio and video). The allowed +;; individual types are 'A' for audio, 'P' for pictures, 'V' for video. +(define-record-type* + readymedia-media-directory make-readymedia-media-directory + readymedia-media-directory? + (path readymedia-media-directory-path) + (type readymedia-media-directory-type (default #f))) + +(define (readymedia-media-directory-type->string type) + "Convert a media-directory TYPE to a string." + (match type + (#f "") + (symbol (symbol->string type)))) + +(define (readymedia-media-directory->string entry) + "Convert a media-directory ENTRY to a ReadyMedia/MiniDLNA media dir string." + (let ((type (readymedia-media-directory-type entry))) + (format #f + "media_dir=~a,~a" + (readymedia-media-directory-type->string type) + (readymedia-media-directory-path entry)))) + +(define (readymedia-extra-config-entry->string entry) + "Convert a extra-config ENTRY to a ReadyMedia/MiniDLNA configuration string." + (let ((key (car entry)) + (value (cdr entry))) + (format #f "~a=~a" key value))) + +(define (readymedia-configuration->config-file config) + "Return the ReadyMedia/MiniDLNA configuration file corresponding to CONFIG." + (let ((friendly-name (readymedia-configuration-friendly-name config)) + (media-directories (readymedia-configuration-media-directories config)) + (cache-directory (readymedia-configuration-cache-directory config)) + (log-directory (readymedia-configuration-log-directory config)) + (port (readymedia-configuration-port config)) + (extra-config (readymedia-configuration-extra-config config))) + (mixed-text-file + "minidlna.conf" + "db_dir=" cache-directory "\n" + "log_dir=" log-directory "\n" + (if friendly-name (format #f "friendly_name=~a\n" friendly-name) "") + (if port (format #f "port=~a\n" port) "") + (string-join + (map readymedia-media-directory->string media-directories) "\n" 'suffix) + (string-join + (map readymedia-extra-config-entry->string extra-config) "\n" 'suffix)))) + +(define (readymedia-shepherd-service config) + "Return a least-authority ReadyMedia/MiniDLNA Shepherd service." + (let* ((minidlna-conf (readymedia-configuration->config-file config)) + (media-directories (readymedia-configuration-media-directories config)) + (cache-directory (readymedia-configuration-cache-directory config)) + (log-directory (readymedia-configuration-log-directory config)) + (log-file (string-append log-directory "/" %readymedia-log-file)) + (readymedia (least-authority-wrapper + (file-append + (readymedia-configuration-readymedia config) + "/sbin/minidlnad") + #:name "minidlna" + #:mappings + (cons* (file-system-mapping + (source cache-directory) + (target source) + (writable? #t)) + (file-system-mapping + (source log-directory) + (target source) + (writable? #t)) + (file-system-mapping + (source minidlna-conf) + (target source)) + (map + (lambda (e) + (file-system-mapping + (source (readymedia-media-directory-path e)) + (target source) + (writable? #f))) + media-directories)) + #:namespaces (delq 'net %namespaces)))) + (list (shepherd-service + (documentation "Run the ReadyMedia/MiniDLNA daemon.") + (provision '(readymedia)) + (requirement '(networking user-processes)) + (start + #~(begin + (use-modules (gnu build activation)) + (let* ((user (getpw #$%readymedia-user-account)) + (dirs (list + #$cache-directory + #$log-directory + #$@(map (lambda (e) + (readymedia-media-directory-path e)) + media-directories))) + (init-directory (lambda (d) + (unless (file-exists? d) + (mkdir-p/perms d user #o755))))) + (for-each init-directory dirs)) + (make-forkexec-constructor + ;; "-S" is to daemonise minidlnad. + (list #$readymedia "-f" #$minidlna-conf "-S") + #:log-file #$log-file + #:user #$%readymedia-user-account + #:group #$%readymedia-user-group))) + (stop #~(make-kill-destructor)))))) + +(define readymedia-accounts + (list (user-group + (name "readymedia") + (system? #t)) + (user-account + (name "readymedia") + (group "readymedia") + (system? #t) + (comment "ReadyMedia/MiniDLNA daemon user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin"))))) + +(define readymedia-service-type + (service-type + (name 'readymedia) + (extensions + (list + (service-extension shepherd-root-service-type readymedia-shepherd-service) + (service-extension account-service-type (const readymedia-accounts)))) + (description + "Run @command{minidlnad}, the ReadyMedia/MiniDLNA media server."))) base-commit: ed4e0b48f16530def08862657301178b5cf00a9a -- 2.45.2