aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2024 Fabio Natali <me@fabionatali.com>
;;;
;;; 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 <http://www.gnu.org/licenses/>.

(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 modules)
  #:use-module (guix records)
  #:use-module (ice-9 match)
  #:export (%readymedia-default-cache-directory
            %readymedia-default-log-directory
            %readymedia-default-port
            %readymedia-log-file
            %readymedia-user-account
            %readymedia-user-group
            readymedia-configuration
            readymedia-configuration?
            readymedia-configuration-readymedia
            readymedia-configuration-port
            readymedia-configuration-cache-directory
            readymedia-configuration-extra-config
            readymedia-configuration-friendly-name
            readymedia-configuration-log-directory
            readymedia-configuration-media-directories
            readymedia-media-directory
            readymedia-media-directory-path
            readymedia-media-directory-types
            readymedia-media-directory?
            readymedia-service-type))

;;; Commentary:
;;;
;;; UPnP services.
;;;
;;; Code:

(define %readymedia-default-cache-directory "/var/cache/readymedia")
(define %readymedia-default-log-directory "/var/log/readymedia")
(define %readymedia-log-file "minidlna.log")
(define %readymedia-user-group "readymedia")
(define %readymedia-user-account "readymedia")

(define-record-type* <readymedia-configuration>
  readymedia-configuration make-readymedia-configuration
  readymedia-configuration?
  (readymedia readymedia-configuration-readymedia
              (default readymedia))
  (port readymedia-configuration-port
        (default #f))
  (cache-directory readymedia-configuration-cache-directory
                   (default %readymedia-default-cache-directory))
  (log-directory readymedia-configuration-log-directory
                 (default %readymedia-default-log-directory))
  (friendly-name readymedia-configuration-friendly-name
                 (default #f))
  (media-directories readymedia-configuration-media-directories)
  (extra-config readymedia-configuration-extra-config
                (default '())))

;; READYMEDIA-MEDIA-DIR is a record that indicates the path of a media folder
;; and the types of media included within it. Allowed individual types are the
;; symbols 'A' for audio, 'V' for video, and 'P' for pictures. The types field
;; can contain any combination of individual types; an empty list means that
;; no type is specified.
(define-record-type* <readymedia-media-directory>
  readymedia-media-directory make-readymedia-media-directory
  readymedia-media-directory?
  (path readymedia-media-directory-path)
  (types readymedia-media-directory-types
         (default '())))

(define (readymedia-configuration->config-file config)
  "Return the ReadyMedia/MiniDLNA configuration file corresponding to CONFIG."
  (match-record config <readymedia-configuration>
    (port friendly-name cache-directory log-directory media-directories extra-config)
    (apply mixed-text-file
           "minidlna.conf"
           "db_dir=" cache-directory "\n"
           "log_dir=" log-directory "\n"
           (if friendly-name
               (string-append "friendly_name=" friendly-name "\n")
               "")
           (if port
               (string-append "port=" (number->string port) "\n")
               "")
           (append (map (match-record-lambda <readymedia-media-directory>
                            (path types)
                          (apply string-append
                                 "media_dir="
                                 (append (map symbol->string types)
                                         (match types
                                           (() (list))
                                           (_ (list ",")))
                                         (list path "\n"))))
                        media-directories)
                   (map (match-lambda
                          ((key . value)
                           (string-append key "=" value "\n")))
                        extra-config)))))

(define (readymedia-shepherd-service config)
  "Return a least-authority ReadyMedia/MiniDLNA Shepherd service."
  (match-record config <readymedia-configuration>
    (cache-directory log-directory media-directories)
    (let ((minidlna-conf (readymedia-configuration->config-file config)))
      (shepherd-service
       (documentation "Run the ReadyMedia/MiniDLNA daemon.")
       (provision '(readymedia))
       (requirement '(networking user-processes))
       (start
        #~(make-forkexec-constructor
           (list #$(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 (directory)
                                  (file-system-mapping
                                   (source (readymedia-media-directory-path directory))
                                   (target source)))
                                media-directories))
                    #:namespaces (delq 'net %namespaces))
                 "-f"
                 #$minidlna-conf
                 "-S")
           #:log-file #$(string-append log-directory "/" %readymedia-log-file)
           #:user #$%readymedia-user-account
           #:group #$%readymedia-user-group))
       (stop #~(make-kill-destructor))))))

(define readymedia-accounts
  (list (user-account
         (name "readymedia")
         (group "readymedia")
         (system? #t)
         (comment "ReadyMedia/MiniDLNA daemon user")
         (home-directory "/var/empty")
         (shell (file-append shadow "/sbin/nologin")))
        (user-group
         (name "readymedia")
         (system? #t))))

(define (readymedia-activation config)
  "Set up directories for ReadyMedia/MiniDLNA."
  (match-record config <readymedia-configuration>
    (cache-directory log-directory media-directories)
    (with-imported-modules (source-module-closure '((gnu build activation)))
      #~(begin
          (use-modules (gnu build activation))

          (for-each (lambda (directory)
                      (unless (file-exists? directory)
                        (mkdir-p/perms directory
                                       (getpw #$%readymedia-user-account)
                                       #o755)))
                    (list #$cache-directory
                          #$log-directory
                          #$@(map readymedia-media-directory-path
                                  media-directories)))))))

(define readymedia-service-type
  (service-type
   (name 'readymedia)
   (extensions
    (list (service-extension shepherd-root-service-type
                             (compose list readymedia-shepherd-service))
          (service-extension account-service-type
                             (const readymedia-accounts))
          (service-extension activation-service-type
                             readymedia-activation)))
   (description
    "Run @command{minidlnad}, the ReadyMedia/MiniDLNA media server.")))
2022-01-03 23:23:07 -0500'>2022-01-03.guix-authorizations: Remove Alex Sassmannshausen due to inactivity....* .guix-authorizations: Remove atheia. Leo Famulari 2022-01-03.guix-authorizations: Remove Alex Griffin due to inactivity....* .guix-authorizations: Remove ajgrf. Leo Famulari 2022-01-03.guix-authorizations: Remove Gábor Boskovits due to inactivity....* .guix-authorizations: Remove boskovits. Leo Famulari 2021-09-06.guix-authorizations: Rename leoprikler to lilyp....* .guix-authorizations: Rename leoprikler to lilyp. Liliana Marie Prikler 2021-06-30.guix-authorizations: Remove kkebreau....* .guix-authorizations: Remove kkebreau from the committers. Kei Kebreau 2021-06-23.guix-authorizations: Update bavier's key....As requested at <https://lists.gnu.org/archive/html/guix-devel/2021-06/msg00123.html>. * .guix-authorizations: Update bavier's signing key fingerprint. Ludovic Courtès 2021-04-28.guix-authorizations: Remove lle_bout....* .guix-authorizations: Remove lle_bout from the committers. Marius Bakke 2021-04-11.guix-authorizations: Add raghavgururajan....* .guix-authorizations: Add raghavgururajan to the committers. Tobias Geerinckx-Rice 2021-04-09Revert ".guix-authorizations: Remove biscuolo due to inactivity."...The original commit was made mistakenly; I forgot to look at all of our Git repos, including maintenance.git, when checking for recent activity. This reverts commit 94521669ed23096f930be68efc691ccb793cc76f. Leo Famulari 2021-04-07.guix-authorizations: Remove biscuolo due to inactivity....* .guix-authorizations: Remove biscuolo. Leo Famulari 2021-04-07.guix-authorizations: Remove wingo due to inactivity....* .guix-authorizations: Remove wingo. Leo Famulari 2021-04-07.guix-authorizations: Remove sleep_walker due to inactivity....* .guix-authorizations: Remove sleep_walker. Leo Famulari 2021-04-07.guix-authorizations: Remove rhelling due to inactivity....* .guix-authorizations: Remove rhelling. Leo Famulari 2021-04-07.guix-authorizations: Remove lsl88 due to inactivity....* .guix-authorizations: Remove lsl88. Leo Famulari 2021-04-07.guix-authorizations: Remove benwoodcroft due to inactivity....* .guix-authorizations: Remove benwoodcroft. Leo Famulari 2021-04-07.guix-authorizations: Remove alexvong1995 due to inactivity....* .guix-authorizations: Remove alexvong1995. Leo Famulari 2021-04-06.guix-authorizations: Remove taylanub....This is a followup to the events discussed here: https://lists.gnu.org/archive/html/guix-devel/2021-03/msg00195.html Taylan was already removed from the Guix project on Savannah on March 10, 2021. * .guix-authorizations: Remove taylanub from the committers. Leo Famulari 2021-04-06.guix-authorizations: Remove thomasd....* .guix-authorizations: Remove thomasd from the committers. Leo Famulari 2021-03-08.guix-authorizations: Add lbraun....* .guix-authorizations: Add lbraun and "lbraun (professional)" to the committers. Leo Famulari 2021-02-18.guix-authorizations: Add lle_bout....* .guix-authorizations: Add lle_bout to the committers. Tobias Geerinckx-Rice