telephony.scm 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2017 nee <nee-git@hidamari.blue>
  3. ;;; Copyright © 2021, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
  4. ;;;
  5. ;;; This file is part of GNU Guix.
  6. ;;;
  7. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  8. ;;; under the terms of the GNU General Public License as published by
  9. ;;; the Free Software Foundation; either version 3 of the License, or (at
  10. ;;; your option) any later version.
  11. ;;;
  12. ;;; GNU Guix is distributed in the hope that it will be useful, but
  13. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;;; GNU General Public License for more details.
  16. ;;;
  17. ;;; You should have received a copy of the GNU General Public License
  18. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  19. (define-module (gnu services telephony)
  20. #:use-module ((gnu build jami-service) #:select (account-fingerprint?))
  21. #:use-module ((gnu services) #:hide (delete))
  22. #:use-module (gnu services configuration)
  23. #:use-module (gnu services shepherd)
  24. #:use-module (gnu system shadow)
  25. #:use-module (gnu packages admin)
  26. #:use-module (gnu packages certs)
  27. #:use-module (gnu packages glib)
  28. #:use-module (gnu packages guile-xyz)
  29. #:use-module (gnu packages jami)
  30. #:use-module (gnu packages telephony)
  31. #:use-module (guix deprecation)
  32. #:use-module (guix records)
  33. #:use-module (guix modules)
  34. #:use-module (guix packages)
  35. #:use-module (guix gexp)
  36. #:use-module (srfi srfi-1)
  37. #:use-module (srfi srfi-2)
  38. #:use-module (srfi srfi-26)
  39. #:use-module (ice-9 format)
  40. #:use-module (ice-9 match)
  41. #:export (jami-account
  42. jami-account-archive
  43. jami-account-allowed-contacts
  44. jami-account-moderators
  45. jami-account-rendezvous-point?
  46. jami-account-discovery?
  47. jami-account-bootstrap-uri
  48. jami-account-name-server-uri
  49. jami-configuration
  50. jami-configuration-libjami
  51. jami-configuration-dbus
  52. jami-configuration-enable-logging?
  53. jami-configuration-debug?
  54. jami-configuration-auto-answer?
  55. jami-configuration-accounts
  56. jami-service-type
  57. mumble-server-configuration
  58. make-mumble-server-configuration
  59. mumble-server-configuration?
  60. mumble-server-configuration-package
  61. mumble-server-configuration-user
  62. mumble-server-configuration-group
  63. mumble-server-configuration-port
  64. mumble-server-configuration-welcome-text
  65. mumble-server-configuration-server-password
  66. mumble-server-configuration-max-users
  67. mumble-server-configuration-max-user-bandwidth
  68. mumble-server-configuration-database-file
  69. mumble-server-configuration-log-file
  70. mumble-server-configuration-pid-file
  71. mumble-server-configuration-autoban-attempts
  72. mumble-server-configuration-autoban-timeframe
  73. mumble-server-configuration-autoban-time
  74. mumble-server-configuration-opus-threshold
  75. mumble-server-configuration-channel-nesting-limit
  76. mumble-server-configuration-channelname-regex
  77. mumble-server-configuration-username-regex
  78. mumble-server-configuration-text-message-length
  79. mumble-server-configuration-image-message-length
  80. mumble-server-configuration-cert-required?
  81. mumble-server-configuration-remember-channel?
  82. mumble-server-configuration-allow-html?
  83. mumble-server-configuration-allow-ping?
  84. mumble-server-configuration-bonjour?
  85. mumble-server-configuration-send-version?
  86. mumble-server-configuration-log-days
  87. mumble-server-configuration-obfuscate-ips?
  88. mumble-server-configuration-ssl-cert
  89. mumble-server-configuration-ssl-key
  90. mumble-server-configuration-ssl-dh-params
  91. mumble-server-configuration-ssl-ciphers
  92. mumble-server-configuration-public-registration
  93. mumble-server-configuration-file
  94. mumble-server-public-registration-configuration
  95. make-mumble-server-public-registration-configuration
  96. mumble-server-public-registration-configuration?
  97. mumble-server-public-registration-configuration-name
  98. mumble-server-public-registration-configuration-url
  99. mumble-server-public-registration-configuration-password
  100. mumble-server-public-registration-configuration-hostname
  101. mumble-server-service-type))
  102. ;;;
  103. ;;; Jami daemon.
  104. ;;;
  105. ;;; XXX: Passing a computed-file object as the account is used for tests.
  106. (define (string-or-computed-file? val)
  107. (or (string? val)
  108. (computed-file? val)))
  109. (define (string-list? val)
  110. (and (list? val)
  111. (and-map string? val)))
  112. (define (account-fingerprint-list? val)
  113. (and (list? val)
  114. (and-map account-fingerprint? val)))
  115. (define-maybe string-list)
  116. (define-maybe/no-serialization account-fingerprint-list)
  117. (define-maybe boolean)
  118. (define-maybe string)
  119. ;;; The following serializers are used to derive an account details alist from
  120. ;;; a <jami-account> record.
  121. (define (serialize-string-list _ val)
  122. (string-join val ";"))
  123. (define (serialize-boolean _ val)
  124. (format #f "~:[false~;true~]" val))
  125. (define (serialize-string _ val)
  126. val)
  127. ;;; Note: Serialization is used to produce an account details alist that can
  128. ;;; be passed to the SET-ACCOUNT-DETAILS procedure. Fields that do not map to
  129. ;;; a Jami account 'detail' should have their serialization disabled via the
  130. ;;; 'empty-serializer' procedure.
  131. (define-configuration jami-account
  132. (archive
  133. (string-or-computed-file)
  134. "The account archive (backup) file name of the account. This is used to
  135. provision the account when the service starts. The account archive should
  136. @emph{not} be encrypted. It is highly recommended to make it readable only to
  137. the @samp{root} user (i.e., not in the store), to guard against leaking the
  138. secret key material of the Jami account it contains."
  139. empty-serializer)
  140. (allowed-contacts
  141. maybe-account-fingerprint-list
  142. "The list of allowed contacts for the account, entered as their 40
  143. characters long fingerprint. Messages or calls from accounts not in that list
  144. will be rejected. When unspecified, the configuration of the account archive
  145. is used as-is with respect to contacts and public inbound calls/messaging
  146. allowance, which typically defaults to allow any contact to communicate with
  147. the account."
  148. empty-serializer)
  149. (moderators
  150. maybe-account-fingerprint-list
  151. "The list of contacts that should have moderation privileges (to ban, mute,
  152. etc. other users) in rendezvous conferences, entered as their 40 characters
  153. long fingerprint. When unspecified, the configuration of the account archive
  154. is used as-is with respect to moderation, which typically defaults to allow
  155. anyone to moderate."
  156. empty-serializer)
  157. ;; The serializable fields below are to be set with set-account-details.
  158. (rendezvous-point?
  159. maybe-boolean
  160. "Whether the account should operate in the rendezvous mode. In this mode,
  161. all the incoming audio/video calls are mixed into a conference. When left
  162. unspecified, the value from the account archive prevails.")
  163. (peer-discovery?
  164. maybe-boolean
  165. "Whether peer discovery should be enabled. Peer discovery is used to
  166. discover other OpenDHT nodes on the local network, which can be useful to
  167. maintain communication between devices on such network even when the
  168. connection to the the Internet has been lost. When left unspecified, the
  169. value from the account archive prevails.")
  170. (bootstrap-hostnames
  171. maybe-string-list
  172. "A list of hostnames or IPs pointing to OpenDHT nodes, that should be used
  173. to initially join the OpenDHT network. When left unspecified, the value from
  174. the account archive prevails.")
  175. (name-server-uri
  176. maybe-string
  177. "The URI of the name server to use, that can be used to retrieve the
  178. account fingerprint for a registered username."))
  179. (define (jami-account->alist jami-account-object)
  180. "Serialize the JAMI-ACCOUNT object as an alist suitable to be passed to
  181. SET-ACCOUNT-DETAILS."
  182. (define (field-name->account-detail name)
  183. (match name
  184. ('rendezvous-point? "Account.rendezVous")
  185. ('peer-discovery? "Account.peerDiscovery")
  186. ('bootstrap-hostnames "Account.hostname")
  187. ('name-server-uri "RingNS.uri")
  188. (_ #f)))
  189. (filter-map (lambda (field)
  190. (and-let* ((name (field-name->account-detail
  191. (configuration-field-name field)))
  192. (value ((configuration-field-serializer field)
  193. name ((configuration-field-getter field)
  194. jami-account-object)))
  195. ;; The define-maybe default serializer produces an
  196. ;; empty string for unspecified values.
  197. (value* (if (string-null? value)
  198. #f
  199. value)))
  200. (cons name value*)))
  201. jami-account-fields))
  202. (define (jami-account-list? val)
  203. (and (list? val)
  204. (and-map jami-account? val)))
  205. (define-maybe/no-serialization jami-account-list)
  206. (define-configuration/no-serialization jami-configuration
  207. (libjami
  208. (file-like libjami)
  209. "The Jami daemon package to use.")
  210. (dbus
  211. (file-like dbus-for-jami)
  212. "The D-Bus package to use to start the required D-Bus session.")
  213. (nss-certs
  214. (file-like nss-certs)
  215. "The nss-certs package to use to provide TLS certificates.")
  216. (enable-logging?
  217. (boolean #t)
  218. "Whether to enable logging to syslog.")
  219. (debug?
  220. (boolean #f)
  221. "Whether to enable debug level messages.")
  222. (auto-answer?
  223. (boolean #f)
  224. "Whether to force automatic answer to incoming calls.")
  225. (accounts
  226. maybe-jami-account-list
  227. "A list of Jami accounts to be (re-)provisioned every time the Jami daemon
  228. service starts. When providing this field, the account directories under
  229. @file{/var/lib/jami/} are recreated every time the service starts, ensuring a
  230. consistent state."))
  231. (define %jami-accounts
  232. (list (user-group (name "jami") (system? #t))
  233. (user-account
  234. (name "jami")
  235. (group "jami")
  236. (system? #t)
  237. (comment "Jami daemon user")
  238. (home-directory "/var/lib/jami"))))
  239. (define (jami-configuration->command-line-arguments config)
  240. "Derive the command line arguments to used to launch the Jami daemon from
  241. CONFIG, a <jami-configuration> object."
  242. (match-record config <jami-configuration>
  243. (libjami dbus enable-logging? debug? auto-answer?)
  244. `(,#~(string-append #$libjami:bin "/libexec/jamid")
  245. "--persistent" ;stay alive after client quits
  246. ,@(if enable-logging?
  247. '() ;logs go to syslog by default
  248. (list "--console")) ;else stdout/stderr
  249. ,@(if debug?
  250. (list "--debug")
  251. '())
  252. ,@(if auto-answer?
  253. (list "--auto-answer")
  254. '()))))
  255. (define (jami-dbus-session-activation config)
  256. "Create a directory to hold the Jami D-Bus session socket."
  257. (with-imported-modules (source-module-closure '((gnu build activation)))
  258. #~(begin
  259. (use-modules (gnu build activation))
  260. (let ((user (getpwnam "jami")))
  261. (mkdir-p/perms "/var/run/jami" user #o700)
  262. ;; Customize the D-Bus policy to allow 'root' to access other users'
  263. ;; session bus. Also modify the location of the written PID file,
  264. ;; from the default '/var/run/dbus/pid' location. This file is only
  265. ;; honored by the 'dbus-for-jami' package variant.
  266. (call-with-output-file "/var/run/jami/session-local.conf"
  267. (lambda (port)
  268. (format port "\
  269. <busconfig>
  270. <pidfile>/var/run/jami/pid</pidfile>
  271. <policy context=\"mandatory\">
  272. <allow user=\"root\"/>
  273. </policy>
  274. </busconfig>~%")))))))
  275. (define (jami-shepherd-services config)
  276. "Return a <shepherd-service> running the Jami daemon."
  277. (let* ((libjami (jami-configuration-libjami config))
  278. (nss-certs (jami-configuration-nss-certs config))
  279. (dbus (jami-configuration-dbus config))
  280. (dbus-daemon (file-append dbus "/bin/dbus-daemon"))
  281. (accounts (jami-configuration-accounts config))
  282. (declarative-mode? (maybe-value-set? accounts)))
  283. (with-extensions (list guile-packrat ;used by guile-ac-d-bus
  284. guile-ac-d-bus
  285. ;; Fibers is needed to provide the non-blocking
  286. ;; variant of the 'sleep' procedure.
  287. guile-fibers)
  288. (with-imported-modules (source-module-closure
  289. '((gnu build dbus-service)
  290. (gnu build jami-service)
  291. (gnu build shepherd)
  292. (gnu system file-systems)))
  293. (define list-accounts-action
  294. (shepherd-action
  295. (name 'list-accounts)
  296. (documentation "List the available Jami accounts. Return the account
  297. details alists keyed by their account username.")
  298. (procedure
  299. #~(lambda _
  300. ;; Print the accounts summary or long listing, according to
  301. ;; user-provided option.
  302. (let* ((usernames (get-usernames))
  303. (accounts (map-in-order username->account usernames)))
  304. (match accounts
  305. (() ;empty list
  306. (format #t "There is no Jami account available.~%"))
  307. ((one two ...)
  308. (format #t "The following Jami accounts are available:~%")
  309. (for-each
  310. (lambda (account)
  311. (define fingerprint (assoc-ref account
  312. "Account.username"))
  313. (define human-friendly-name
  314. (or (assoc-ref account
  315. "Account.registeredName")
  316. (assoc-ref account
  317. "Account.displayName")
  318. (assoc-ref account
  319. "Account.alias")))
  320. (define disabled?
  321. (and=> (assoc-ref account "Account.enable")
  322. (cut string=? "false" <>)))
  323. (format #t " - ~a~@[ (~a)~] ~:[~;[disabled]~]~%"
  324. fingerprint human-friendly-name disabled?))
  325. accounts)
  326. (display "\n")))
  327. ;; Return the account-details-list alist.
  328. (map cons usernames accounts))))))
  329. (define list-account-details-action
  330. (shepherd-action
  331. (name 'list-account-details)
  332. (documentation "Display the account details of the available Jami
  333. accounts in the @code{recutils} format. Return the account details alists
  334. keyed by their account username.")
  335. (procedure
  336. #~(lambda _
  337. (let* ((usernames (get-usernames))
  338. (accounts (map-in-order username->account usernames)))
  339. (for-each (lambda (account)
  340. (display (account-details->recutil account))
  341. (display "\n\n"))
  342. accounts)
  343. (map cons usernames accounts))))))
  344. (define list-contacts-action
  345. (shepherd-action
  346. (name 'list-contacts)
  347. (documentation "Display the contacts for each Jami account. Return
  348. an alist containing the contacts keyed by the account usernames.")
  349. (procedure
  350. #~(lambda _
  351. (let* ((usernames (get-usernames))
  352. (contacts (map-in-order username->contacts usernames)))
  353. (for-each (lambda (username contacts)
  354. (format #t "Contacts for account ~a:~%"
  355. username)
  356. (format #t "~{ - ~a~%~}~%" contacts))
  357. usernames contacts)
  358. (map cons usernames contacts))))))
  359. (define list-moderators-action
  360. (shepherd-action
  361. (name 'list-moderators)
  362. (documentation "Display the moderators for each Jami account. Return
  363. an alist containing the moderators keyed by the account usernames.")
  364. (procedure
  365. #~(lambda _
  366. (let* ((usernames (get-usernames))
  367. (moderators (map-in-order username->moderators
  368. usernames)))
  369. (for-each
  370. (lambda (username moderators)
  371. (if (username->all-moderators? username)
  372. (format #t "Anyone can moderate for account ~a~%"
  373. username)
  374. (begin
  375. (format #t "Moderators for account ~a:~%" username)
  376. (format #t "~{ - ~a~%~}~%" moderators))))
  377. usernames moderators)
  378. (map cons usernames moderators))))))
  379. (define add-moderator-action
  380. (shepherd-action
  381. (name 'add-moderator)
  382. (documentation "Add a moderator for a given Jami account. The
  383. MODERATOR contact must be given as its 40 characters fingerprint, while the
  384. Jami account can be provided as its registered USERNAME or fingerprint.
  385. @example
  386. herd add-moderator jami 1dbcb0f5f37324228235564b79f2b9737e9a008f username
  387. @end example
  388. Return the moderators for the account known by USERNAME.")
  389. (procedure
  390. #~(lambda (_ moderator username)
  391. (set-all-moderators #f username)
  392. (add-contact moderator username)
  393. (set-moderator moderator #t username)
  394. (username->moderators username)))))
  395. (define ban-contact-action
  396. (shepherd-action
  397. (name 'ban-contact)
  398. (documentation "Ban a contact for a given or all Jami accounts, and
  399. clear their moderator flag. The CONTACT must be given as its 40 characters
  400. fingerprint, while the Jami account can be provided as its registered USERNAME
  401. or fingerprint, or omitted. When the account is omitted, CONTACT is banned
  402. from all accounts.
  403. @example
  404. herd ban-contact jami 1dbcb0f5f37324228235564b79f2b9737e9a008f [username]
  405. @end example")
  406. (procedure
  407. #~(lambda* (_ contact #:optional username)
  408. (let ((usernames (or (and=> username list)
  409. (get-usernames))))
  410. (for-each (lambda (username)
  411. (set-moderator contact #f username)
  412. (remove-contact contact username #:ban? #t))
  413. usernames))))))
  414. (define list-banned-contacts-action
  415. (shepherd-action
  416. (name 'list-banned-contacts)
  417. (documentation "List the banned contacts for each accounts. Return
  418. an alist of the banned contacts, keyed by the account usernames.")
  419. (procedure
  420. #~(lambda _
  421. (define banned-contacts
  422. (let ((usernames (get-usernames)))
  423. (map cons usernames
  424. (map-in-order (lambda (x)
  425. (receive (_ banned)
  426. (username->contacts x)
  427. banned))
  428. usernames))))
  429. (for-each (match-lambda
  430. ((username . banned)
  431. (unless (null? banned)
  432. (format #t "Banned contacts for account ~a:~%"
  433. username)
  434. (format #t "~{ - ~a~%~}~%" banned))))
  435. banned-contacts)
  436. banned-contacts))))
  437. (define enable-account-action
  438. (shepherd-action
  439. (name 'enable-account)
  440. (documentation "Enable an account. It takes USERNAME as an argument,
  441. either a registered username or the fingerprint of the account.")
  442. (procedure
  443. #~(lambda (_ username)
  444. (enable-account username)))))
  445. (define disable-account-action
  446. (shepherd-action
  447. (name 'disable-account)
  448. (documentation "Disable an account. It takes USERNAME as an
  449. argument, either a registered username or the fingerprint of the account.")
  450. (procedure
  451. #~(lambda (_ username)
  452. (disable-account username)))))
  453. (list (shepherd-service
  454. (documentation "Run a D-Bus session for the Jami daemon.")
  455. (provision '(jami-dbus-session))
  456. (modules `((gnu build shepherd)
  457. (gnu build dbus-service)
  458. (gnu build jami-service)
  459. (gnu system file-systems)
  460. ,@%default-modules))
  461. ;; The requirement on dbus-system is to ensure other required
  462. ;; activation for D-Bus, such as a /etc/machine-id file.
  463. (requirement '(dbus-system syslogd))
  464. (start
  465. #~(make-forkexec-constructor/container
  466. (list #$dbus-daemon "--session"
  467. "--address=unix:path=/var/run/jami/bus"
  468. "--syslog-only")
  469. #:pid-file "/var/run/jami/pid"
  470. #:mappings
  471. (list (file-system-mapping
  472. (source "/dev/log") ;for syslog
  473. (target source))
  474. (file-system-mapping
  475. (source "/var/run/jami")
  476. (target source)
  477. (writable? #t)))
  478. #:user "jami"
  479. #:group "jami"
  480. #:environment-variables
  481. ;; This is so that the cx.ring.Ring service D-Bus
  482. ;; definition is found by dbus-daemon.
  483. (list (string-append "XDG_DATA_DIRS="
  484. #$libjami:bin "/share"))))
  485. (stop #~(make-kill-destructor)))
  486. (shepherd-service
  487. (documentation "Run the Jami daemon.")
  488. (provision '(jami))
  489. (actions (list list-accounts-action
  490. list-account-details-action
  491. list-contacts-action
  492. list-moderators-action
  493. add-moderator-action
  494. ban-contact-action
  495. list-banned-contacts-action
  496. enable-account-action
  497. disable-account-action))
  498. (requirement '(jami-dbus-session))
  499. (modules `((ice-9 format)
  500. (ice-9 ftw)
  501. (ice-9 match)
  502. (ice-9 receive)
  503. (srfi srfi-1)
  504. (srfi srfi-26)
  505. (gnu build dbus-service)
  506. (gnu build jami-service)
  507. (gnu build shepherd)
  508. (gnu system file-systems)
  509. ,@%default-modules))
  510. (start
  511. #~(lambda args
  512. (define (delete-file-recursively/safe file)
  513. ;; Ensure we're not deleting things outside of
  514. ;; /var/lib/jami. This prevents a possible attack in case
  515. ;; the daemon is compromised and an attacker gains write
  516. ;; access to /var/lib/jami.
  517. (let ((parent-directory (dirname file)))
  518. (if (eq? 'symlink (stat:type (stat parent-directory)))
  519. (error "abnormality detected; unexpected symlink found at"
  520. parent-directory)
  521. (delete-file-recursively file))))
  522. (when #$declarative-mode?
  523. ;; Clear the Jami configuration and accounts, to enforce the
  524. ;; declared state.
  525. (catch #t
  526. (lambda ()
  527. (for-each (cut delete-file-recursively/safe <>)
  528. '("/var/lib/jami/.cache/jami"
  529. "/var/lib/jami/.config/jami"
  530. "/var/lib/jami/.local/share/jami"
  531. "/var/lib/jami/accounts")))
  532. (lambda args
  533. #t))
  534. ;; Copy the Jami account archives from somewhere readable
  535. ;; by root to a place only the jami user can read.
  536. (let* ((accounts-dir "/var/lib/jami/accounts/")
  537. (pwd (getpwnam "jami"))
  538. (user (passwd:uid pwd))
  539. (group (passwd:gid pwd)))
  540. (mkdir-p accounts-dir)
  541. (chown accounts-dir user group)
  542. (for-each (lambda (f)
  543. (let ((dest (string-append accounts-dir
  544. (basename f))))
  545. (copy-file f dest)
  546. (chown dest user group)))
  547. '#$(and declarative-mode?
  548. (map jami-account-archive accounts)))))
  549. ;; Start the daemon.
  550. (define daemon-pid
  551. ((make-forkexec-constructor/container
  552. (list #$@(jami-configuration->command-line-arguments
  553. config))
  554. #:mappings
  555. (list (file-system-mapping
  556. (source "/dev/log") ;for syslog
  557. (target source))
  558. (file-system-mapping
  559. (source "/var/lib/jami")
  560. (target source)
  561. (writable? #t))
  562. (file-system-mapping
  563. (source "/var/run/jami")
  564. (target source)
  565. (writable? #t))
  566. ;; Expose TLS certificates for GnuTLS.
  567. (file-system-mapping
  568. (source #$(file-append nss-certs "/etc/ssl/certs"))
  569. (target "/etc/ssl/certs")))
  570. #:user "jami"
  571. #:group "jami"
  572. #:environment-variables
  573. (list (string-append "DBUS_SESSION_BUS_ADDRESS="
  574. "unix:path=/var/run/jami/bus")
  575. ;; Expose TLS certificates for OpenSSL.
  576. "SSL_CERT_DIR=/etc/ssl/certs"))))
  577. (setenv "DBUS_SESSION_BUS_ADDRESS"
  578. "unix:path=/var/run/jami/bus")
  579. ;; Wait until the service name has been acquired by D-Bus.
  580. (with-retries 20 1 (jami-service-available?))
  581. (when #$declarative-mode?
  582. ;; Provision the accounts via the D-Bus API of the daemon.
  583. (let* ((jami-account-archives
  584. (map (cut string-append
  585. "/var/lib/jami/accounts/" <>)
  586. (scandir "/var/lib/jami/accounts/"
  587. (lambda (f)
  588. (not (member f '("." "..")))))))
  589. (usernames (map-in-order (cut add-account <>)
  590. jami-account-archives)))
  591. (define (archive-name->username archive)
  592. (list-ref
  593. usernames
  594. (list-index (lambda (f)
  595. (string-suffix? (basename archive) f))
  596. jami-account-archives)))
  597. (for-each
  598. (lambda (archive allowed-contacts moderators
  599. account-details)
  600. (let ((username (archive-name->username
  601. archive)))
  602. (when (not (eq? '#$%unset-value allowed-contacts))
  603. ;; Reject calls from unknown contacts.
  604. (set-account-details
  605. '(("DHT.PublicInCalls" . "false")) username)
  606. ;; Remove all contacts.
  607. (for-each (cut remove-contact <> username)
  608. (username->contacts username))
  609. ;; Add allowed ones.
  610. (for-each (cut add-contact <> username)
  611. allowed-contacts))
  612. (when (not (eq? '#$%unset-value moderators))
  613. ;; Disable the 'AllModerators' property.
  614. (set-all-moderators #f username)
  615. ;; Remove all moderators.
  616. (for-each (cut set-moderator <> #f username)
  617. (username->moderators username))
  618. ;; Add declared moderators.
  619. (for-each (cut set-moderator <> #t username)
  620. moderators))
  621. ;; Set the various account parameters.
  622. (set-account-details account-details username)))
  623. '#$(and declarative-mode?
  624. (map-in-order (cut jami-account-archive <>)
  625. accounts))
  626. '#$(and declarative-mode?
  627. (map-in-order
  628. (cut jami-account-allowed-contacts <>)
  629. accounts))
  630. '#$(and declarative-mode?
  631. (map-in-order (cut jami-account-moderators <>)
  632. accounts))
  633. '#$(and declarative-mode?
  634. (map-in-order jami-account->alist accounts)))))
  635. ;; Finally, return the PID of the daemon process.
  636. daemon-pid))
  637. ;; XXX: jamid takes some time to terminate, and GNU Shepherd
  638. ;; doesn't block when calling waitpid (see:
  639. ;; https://issues.guix.gnu.org/57922). Using SIGKILL instead
  640. ;; of SIGTERM works around that.
  641. (stop #~(make-kill-destructor SIGKILL))))))))
  642. (define jami-service-type
  643. (service-type
  644. (name 'jami)
  645. (default-value (jami-configuration))
  646. (extensions
  647. (list (service-extension shepherd-root-service-type
  648. jami-shepherd-services)
  649. (service-extension account-service-type
  650. (const %jami-accounts))
  651. (service-extension activation-service-type
  652. jami-dbus-session-activation)))
  653. (description "Run the Jami daemon (@command{jamid}). This service is
  654. geared toward the use case of hosting Jami rendezvous points over a headless
  655. server. If you use Jami on your local machine, you may prefer to setup a user
  656. Shepherd service for it instead; this way, the daemon will be shared via your
  657. normal user D-Bus session bus.")))
  658. ;;;
  659. ;;; Mumble server.
  660. ;;;
  661. ;; https://github.com/mumble-voip/mumble/blob/master/scripts/murmur.ini
  662. (define-record-type* <mumble-server-configuration> mumble-server-configuration
  663. make-mumble-server-configuration
  664. mumble-server-configuration?
  665. (package mumble-server-configuration-package ;file-like
  666. (default mumble))
  667. (user mumble-server-configuration-user
  668. (default "mumble-server"))
  669. (group mumble-server-configuration-group
  670. (default "mumble-server"))
  671. (port mumble-server-configuration-port
  672. (default 64738))
  673. (welcome-text mumble-server-configuration-welcome-text
  674. (default ""))
  675. (server-password mumble-server-configuration-server-password
  676. (default ""))
  677. (max-users mumble-server-configuration-max-users
  678. (default 100))
  679. (max-user-bandwidth mumble-server-configuration-max-user-bandwidth
  680. (default #f))
  681. (database-file mumble-server-configuration-database-file
  682. (default "/var/lib/mumble-server/db.sqlite"))
  683. (log-file mumble-server-configuration-log-file
  684. (default "/var/log/mumble-server/mumble-server.log"))
  685. (pid-file mumble-server-configuration-pid-file
  686. (default "/var/run/mumble-server/mumble-server.pid"))
  687. (autoban-attempts mumble-server-configuration-autoban-attempts
  688. (default 10))
  689. (autoban-timeframe mumble-server-configuration-autoban-timeframe
  690. (default 120))
  691. (autoban-time mumble-server-configuration-autoban-time
  692. (default 300))
  693. (opus-threshold mumble-server-configuration-opus-threshold
  694. (default 100)) ; integer percent
  695. (channel-nesting-limit mumble-server-configuration-channel-nesting-limit
  696. (default 10))
  697. (channelname-regex mumble-server-configuration-channelname-regex
  698. (default #f))
  699. (username-regex mumble-server-configuration-username-regex
  700. (default #f))
  701. (text-message-length mumble-server-configuration-text-message-length
  702. (default 5000))
  703. (image-message-length mumble-server-configuration-image-message-length
  704. (default (* 128 1024))) ; 128 Kilobytes
  705. (cert-required? mumble-server-configuration-cert-required?
  706. (default #f))
  707. (remember-channel? mumble-server-configuration-remember-channel?
  708. (default #f))
  709. (allow-html? mumble-server-configuration-allow-html?
  710. (default #f))
  711. (allow-ping? mumble-server-configuration-allow-ping?
  712. (default #f))
  713. (bonjour? mumble-server-configuration-bonjour?
  714. (default #f))
  715. (send-version? mumble-server-configuration-send-version?
  716. (default #f))
  717. (log-days mumble-server-configuration-log-days
  718. (default 31))
  719. (obfuscate-ips? mumble-server-obfuscate-ips?
  720. (default #t))
  721. (ssl-cert mumble-server-configuration-ssl-cert
  722. (default #f))
  723. (ssl-key mumble-server-configuration-ssl-key
  724. (default #f))
  725. (ssl-dh-params mumble-server-configuration-ssl-dh-params
  726. (default #f))
  727. (ssl-ciphers mumble-server-configuration-ssl-ciphers
  728. (default #f))
  729. (public-registration mumble-server-configuration-public-registration
  730. (default #f)) ; <mumble-server-public-registration-configuration>
  731. (file mumble-server-configuration-file
  732. (default #f)))
  733. (define-record-type* <mumble-server-public-registration-configuration>
  734. mumble-server-public-registration-configuration
  735. make-mumble-server-public-registration-configuration
  736. mumble-server-public-registration-configuration?
  737. (name mumble-server-public-registration-configuration-name)
  738. (password mumble-server-public-registration-configuration-password)
  739. (url mumble-server-public-registration-configuration-url)
  740. (hostname mumble-server-public-registration-configuration-hostname
  741. (default #f)))
  742. (define (flatten . lst)
  743. "Return a list that recursively concatenates all sub-lists of LST."
  744. (define (flatten1 head out)
  745. (if (list? head)
  746. (fold-right flatten1 out head)
  747. (cons head out)))
  748. (fold-right flatten1 '() lst))
  749. (define (default-mumble-server-config config)
  750. (match-record
  751. config
  752. <mumble-server-configuration>
  753. (user port welcome-text server-password max-users max-user-bandwidth
  754. database-file log-file pid-file autoban-attempts autoban-timeframe
  755. autoban-time opus-threshold channel-nesting-limit channelname-regex
  756. username-regex text-message-length image-message-length cert-required?
  757. remember-channel? allow-html? allow-ping? bonjour? send-version?
  758. log-days obfuscate-ips? ssl-cert ssl-key ssl-dh-params ssl-ciphers
  759. public-registration)
  760. (apply mixed-text-file "mumble-server.ini"
  761. (flatten
  762. "welcometext=" welcome-text "\n"
  763. "port=" (number->string port) "\n"
  764. (if server-password (list "serverpassword=" server-password "\n") '())
  765. (if max-user-bandwidth (list "bandwidth="
  766. (number->string max-user-bandwidth) "\n")
  767. '())
  768. "users=" (number->string max-users) "\n"
  769. "uname=" user "\n"
  770. "database=" database-file "\n"
  771. "logfile=" log-file "\n"
  772. "pidfile=" pid-file "\n"
  773. (if autoban-attempts (list "autobanAttempts=" (number->string autoban-attempts) "\n") '())
  774. (if autoban-timeframe (list "autobanTimeframe=" (number->string autoban-timeframe) "\n") '())
  775. (if autoban-time (list "autobanTime=" (number->string autoban-time) "\n") '())
  776. (if opus-threshold (list "opusthreshold=" (number->string opus-threshold) "\n") '())
  777. (if channel-nesting-limit (list "channelnestinglimit=" (number->string channel-nesting-limit) "\n") '())
  778. (if channelname-regex (list "channelname=" channelname-regex "\n") '())
  779. (if username-regex (list "username=" username-regex "\n") '())
  780. (if text-message-length (list "textmessagelength=" (number->string text-message-length) "\n") '())
  781. (if image-message-length (list "imagemessagelength=" (number->string image-message-length) "\n") '())
  782. (if log-days (list "logdays=" (number->string log-days) "\n") '())
  783. "obfuscate=" (if obfuscate-ips? "true" "false") "\n"
  784. "certrequired=" (if cert-required? "true" "false") "\n"
  785. "rememberchannel=" (if remember-channel? "true" "false") "\n"
  786. "allowhtml=" (if allow-html? "true" "false") "\n"
  787. "allowping=" (if allow-ping? "true" "false") "\n"
  788. "bonjour=" (if bonjour? "true" "false") "\n"
  789. "sendversion=" (if send-version? "true" "false") "\n"
  790. (cond ((and ssl-cert ssl-key)
  791. (list
  792. "sslCert=" ssl-cert "\n"
  793. "sslKey=" ssl-key "\n"))
  794. ((or ssl-cert ssl-key)
  795. (error "ssl-cert and ssl-key must both be set"
  796. ssl-cert ssl-key))
  797. (else '()))
  798. (if ssl-dh-params (list "sslDHParams=" ssl-dh-params) '())
  799. (if ssl-ciphers (list "sslCiphers=" ssl-ciphers) '())
  800. (match public-registration
  801. (#f '())
  802. (($ <mumble-server-public-registration-configuration>
  803. name password url hostname)
  804. (if (and (or (not server-password) (string-null? server-password))
  805. allow-ping?)
  806. (list
  807. "registerName=" name "\n"
  808. "registerPassword=" password "\n"
  809. "registerUrl=" url "\n"
  810. (if hostname
  811. (string-append "registerHostname=" hostname "\n")
  812. ""))
  813. (error "To publicly register your mumble-server server your server must be publicy visible
  814. and users must be able to join without a password. To fix this set:
  815. (allow-ping? #t)
  816. (server-password \"\")
  817. Or set public-registration to #f"))))))))
  818. (define (mumble-server-activation config)
  819. #~(begin
  820. (use-modules (guix build utils))
  821. (let* ((log-dir (dirname #$(mumble-server-configuration-log-file config)))
  822. (pid-dir (dirname #$(mumble-server-configuration-pid-file config)))
  823. (db-dir (dirname #$(mumble-server-configuration-database-file config)))
  824. (user (getpwnam #$(mumble-server-configuration-user config)))
  825. (init-dir
  826. (lambda (name dir)
  827. (format #t "creating mumble-server ~a directory '~a'\n" name dir)
  828. (mkdir-p dir)
  829. (chown dir (passwd:uid user) (passwd:gid user))
  830. (chmod dir #o700)))
  831. (ini #$(or (mumble-server-configuration-file config)
  832. (default-mumble-server-config config))))
  833. (init-dir "log" log-dir)
  834. (init-dir "pid" pid-dir)
  835. (init-dir "database" db-dir)
  836. (format #t "mumble-server: use config file: ~a~%\n" ini)
  837. (format #t "mumble-server: to set the SuperUser password run:
  838. `~a -ini ~a -readsupw`\n"
  839. #$(file-append (mumble-server-configuration-package config)
  840. "/bin/mumble-server") ini)
  841. #t)))
  842. (define mumble-server-accounts
  843. (match-lambda
  844. (($ <mumble-server-configuration> _ user group)
  845. (list
  846. (user-group
  847. (name group)
  848. (system? #t))
  849. (user-account
  850. (name user)
  851. (group group)
  852. (system? #t)
  853. (comment "Mumble server daemon")
  854. (home-directory "/var/empty")
  855. (shell (file-append shadow "/sbin/nologin")))))))
  856. (define (mumble-server-shepherd-service config)
  857. (list (shepherd-service
  858. (provision '(mumble-server))
  859. (documentation "Run the Mumble server.")
  860. (requirement '(networking))
  861. (start #~(make-forkexec-constructor
  862. '(#$(file-append (mumble-server-configuration-package config)
  863. "/bin/mumble-server")
  864. "-ini"
  865. #$(or (mumble-server-configuration-file config)
  866. (default-mumble-server-config config)))
  867. #:pid-file #$(mumble-server-configuration-pid-file config)))
  868. (stop #~(make-kill-destructor)))))
  869. (define mumble-server-service-type
  870. (service-type (name 'mumble-server)
  871. (description
  872. "Run the Mumble voice-over-IP (VoIP) server.")
  873. (extensions
  874. (list (service-extension shepherd-root-service-type
  875. mumble-server-shepherd-service)
  876. (service-extension activation-service-type
  877. mumble-server-activation)
  878. (service-extension account-service-type
  879. mumble-server-accounts)))
  880. (default-value (mumble-server-configuration))))
  881. (define-deprecated/public-alias
  882. murmur-configuration
  883. mumble-server-configuration)
  884. (define-deprecated/public-alias
  885. make-murmur-configuration
  886. make-mumble-server-configuration)
  887. (define-deprecated/public-alias
  888. murmur-configuration?
  889. mumble-server-configuration?)
  890. (define-deprecated/public-alias
  891. murmur-configuration-package
  892. mumble-server-configuration-package)
  893. (define-deprecated/public-alias
  894. murmur-configuration-user
  895. mumble-server-configuration-user)
  896. (define-deprecated/public-alias
  897. murmur-configuration-group
  898. mumble-server-configuration-group)
  899. (define-deprecated/public-alias
  900. murmur-configuration-port
  901. mumble-server-configuration-port)
  902. (define-deprecated/public-alias
  903. murmur-configuration-welcome-text
  904. mumble-server-configuration-welcome-text)
  905. (define-deprecated/public-alias
  906. murmur-configuration-server-password
  907. mumble-server-configuration-server-password)
  908. (define-deprecated/public-alias
  909. murmur-configuration-max-users
  910. mumble-server-configuration-max-users)
  911. (define-deprecated/public-alias
  912. murmur-configuration-max-user-bandwidth
  913. mumble-server-configuration-max-user-bandwidth)
  914. (define-deprecated/public-alias
  915. murmur-configuration-database-file
  916. mumble-server-configuration-database-file)
  917. (define-deprecated/public-alias
  918. murmur-configuration-log-file
  919. mumble-server-configuration-log-file)
  920. (define-deprecated/public-alias
  921. murmur-configuration-pid-file
  922. mumble-server-configuration-pid-file)
  923. (define-deprecated/public-alias
  924. murmur-configuration-autoban-attempts
  925. mumble-server-configuration-autoban-attempts)
  926. (define-deprecated/public-alias
  927. murmur-configuration-autoban-timeframe
  928. mumble-server-configuration-autoban-timeframe)
  929. (define-deprecated/public-alias
  930. murmur-configuration-autoban-time
  931. mumble-server-configuration-autoban-time)
  932. (define-deprecated/public-alias
  933. murmur-configuration-opus-threshold
  934. mumble-server-configuration-opus-threshold)
  935. (define-deprecated/public-alias
  936. murmur-configuration-channel-nesting-limit
  937. mumble-server-configuration-channel-nesting-limit)
  938. (define-deprecated/public-alias
  939. murmur-configuration-channelname-regex
  940. mumble-server-configuration-channelname-regex)
  941. (define-deprecated/public-alias
  942. murmur-configuration-username-regex
  943. mumble-server-configuration-username-regex)
  944. (define-deprecated/public-alias
  945. murmur-configuration-text-message-length
  946. mumble-server-configuration-text-message-length)
  947. (define-deprecated/public-alias
  948. murmur-configuration-image-message-length
  949. mumble-server-configuration-image-message-length)
  950. (define-deprecated/public-alias
  951. murmur-configuration-cert-required?
  952. mumble-server-configuration-cert-required?)
  953. (define-deprecated/public-alias
  954. murmur-configuration-remember-channel?
  955. mumble-server-configuration-remember-channel?)
  956. (define-deprecated/public-alias
  957. murmur-configuration-allow-html?
  958. mumble-server-configuration-allow-html?)
  959. (define-deprecated/public-alias
  960. murmur-configuration-allow-ping?
  961. mumble-server-configuration-allow-ping?)
  962. (define-deprecated/public-alias
  963. murmur-configuration-bonjour?
  964. mumble-server-configuration-bonjour?)
  965. (define-deprecated/public-alias
  966. murmur-configuration-send-version?
  967. mumble-server-configuration-send-version?)
  968. (define-deprecated/public-alias
  969. murmur-configuration-log-days
  970. mumble-server-configuration-log-days)
  971. (define-deprecated/public-alias
  972. murmur-configuration-obfuscate-ips?
  973. mumble-server-configuration-obfuscate-ips?)
  974. (define-deprecated/public-alias
  975. murmur-configuration-ssl-cert
  976. mumble-server-configuration-ssl-cert)
  977. (define-deprecated/public-alias
  978. murmur-configuration-ssl-key
  979. mumble-server-configuration-ssl-key)
  980. (define-deprecated/public-alias
  981. murmur-configuration-ssl-dh-params
  982. mumble-server-configuration-ssl-dh-params)
  983. (define-deprecated/public-alias
  984. murmur-configuration-ssl-ciphers
  985. mumble-server-configuration-ssl-ciphers)
  986. (define-deprecated/public-alias
  987. murmur-configuration-public-registration
  988. mumble-server-configuration-public-registration)
  989. (define-deprecated/public-alias
  990. murmur-configuration-file
  991. mumble-server-configuration-file)
  992. (define-deprecated/public-alias
  993. murmur-public-registration-configuration
  994. mumble-server-public-registration-configuration)
  995. (define-deprecated/public-alias
  996. make-murmur-public-registration-configuration
  997. make-mumble-server-public-registration-configuration)
  998. (define-deprecated/public-alias
  999. murmur-public-registration-configuration?
  1000. mumble-server-public-registration-configuration?)
  1001. (define-deprecated/public-alias
  1002. murmur-public-registration-configuration-name
  1003. mumble-server-public-registration-configuration-name)
  1004. (define-deprecated/public-alias
  1005. murmur-public-registration-configuration-url
  1006. mumble-server-public-registration-configuration-url)
  1007. (define-deprecated/public-alias
  1008. murmur-public-registration-configuration-password
  1009. mumble-server-public-registration-configuration-password)
  1010. (define-deprecated/public-alias
  1011. murmur-public-registration-configuration-hostname
  1012. mumble-server-public-registration-configuration-hostname)
  1013. (define-deprecated/public-alias
  1014. murmur-service-type
  1015. mumble-server-service-type)
  1016. ;; Local Variables:
  1017. ;; eval: (put 'with-retries 'scheme-indent-function 2)
  1018. ;; End: