telephony.scm 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  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. `(,(file-append libjami "/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=" #$libjami "/share"))))
  484. (stop #~(make-kill-destructor)))
  485. (shepherd-service
  486. (documentation "Run the Jami daemon.")
  487. (provision '(jami))
  488. (actions (list list-accounts-action
  489. list-account-details-action
  490. list-contacts-action
  491. list-moderators-action
  492. add-moderator-action
  493. ban-contact-action
  494. list-banned-contacts-action
  495. enable-account-action
  496. disable-account-action))
  497. (requirement '(jami-dbus-session))
  498. (modules `((ice-9 format)
  499. (ice-9 ftw)
  500. (ice-9 match)
  501. (ice-9 receive)
  502. (srfi srfi-1)
  503. (srfi srfi-26)
  504. (gnu build dbus-service)
  505. (gnu build jami-service)
  506. (gnu build shepherd)
  507. (gnu system file-systems)
  508. ,@%default-modules))
  509. (start
  510. #~(lambda args
  511. (define (delete-file-recursively/safe file)
  512. ;; Ensure we're not deleting things outside of
  513. ;; /var/lib/jami. This prevents a possible attack in case
  514. ;; the daemon is compromised and an attacker gains write
  515. ;; access to /var/lib/jami.
  516. (let ((parent-directory (dirname file)))
  517. (if (eq? 'symlink (stat:type (stat parent-directory)))
  518. (error "abnormality detected; unexpected symlink found at"
  519. parent-directory)
  520. (delete-file-recursively file))))
  521. (when #$declarative-mode?
  522. ;; Clear the Jami configuration and accounts, to enforce the
  523. ;; declared state.
  524. (catch #t
  525. (lambda ()
  526. (for-each (cut delete-file-recursively/safe <>)
  527. '("/var/lib/jami/.cache/jami"
  528. "/var/lib/jami/.config/jami"
  529. "/var/lib/jami/.local/share/jami"
  530. "/var/lib/jami/accounts")))
  531. (lambda args
  532. #t))
  533. ;; Copy the Jami account archives from somewhere readable
  534. ;; by root to a place only the jami user can read.
  535. (let* ((accounts-dir "/var/lib/jami/accounts/")
  536. (pwd (getpwnam "jami"))
  537. (user (passwd:uid pwd))
  538. (group (passwd:gid pwd)))
  539. (mkdir-p accounts-dir)
  540. (chown accounts-dir user group)
  541. (for-each (lambda (f)
  542. (let ((dest (string-append accounts-dir
  543. (basename f))))
  544. (copy-file f dest)
  545. (chown dest user group)))
  546. '#$(and declarative-mode?
  547. (map jami-account-archive accounts)))))
  548. ;; Start the daemon.
  549. (define daemon-pid
  550. ((make-forkexec-constructor/container
  551. '#$(jami-configuration->command-line-arguments config)
  552. #:mappings
  553. (list (file-system-mapping
  554. (source "/dev/log") ;for syslog
  555. (target source))
  556. (file-system-mapping
  557. (source "/var/lib/jami")
  558. (target source)
  559. (writable? #t))
  560. (file-system-mapping
  561. (source "/var/run/jami")
  562. (target source)
  563. (writable? #t))
  564. ;; Expose TLS certificates for GnuTLS.
  565. (file-system-mapping
  566. (source #$(file-append nss-certs "/etc/ssl/certs"))
  567. (target "/etc/ssl/certs")))
  568. #:user "jami"
  569. #:group "jami"
  570. #:environment-variables
  571. (list (string-append "DBUS_SESSION_BUS_ADDRESS="
  572. "unix:path=/var/run/jami/bus")
  573. ;; Expose TLS certificates for OpenSSL.
  574. "SSL_CERT_DIR=/etc/ssl/certs"))))
  575. (setenv "DBUS_SESSION_BUS_ADDRESS"
  576. "unix:path=/var/run/jami/bus")
  577. ;; Wait until the service name has been acquired by D-Bus.
  578. (with-retries 20 1 (jami-service-available?))
  579. (when #$declarative-mode?
  580. ;; Provision the accounts via the D-Bus API of the daemon.
  581. (let* ((jami-account-archives
  582. (map (cut string-append
  583. "/var/lib/jami/accounts/" <>)
  584. (scandir "/var/lib/jami/accounts/"
  585. (lambda (f)
  586. (not (member f '("." "..")))))))
  587. (usernames (map-in-order (cut add-account <>)
  588. jami-account-archives)))
  589. (define (archive-name->username archive)
  590. (list-ref
  591. usernames
  592. (list-index (lambda (f)
  593. (string-suffix? (basename archive) f))
  594. jami-account-archives)))
  595. (for-each
  596. (lambda (archive allowed-contacts moderators
  597. account-details)
  598. (let ((username (archive-name->username
  599. archive)))
  600. (when (not (eq? '#$%unset-value allowed-contacts))
  601. ;; Reject calls from unknown contacts.
  602. (set-account-details
  603. '(("DHT.PublicInCalls" . "false")) username)
  604. ;; Remove all contacts.
  605. (for-each (cut remove-contact <> username)
  606. (username->contacts username))
  607. ;; Add allowed ones.
  608. (for-each (cut add-contact <> username)
  609. allowed-contacts))
  610. (when (not (eq? '#$%unset-value moderators))
  611. ;; Disable the 'AllModerators' property.
  612. (set-all-moderators #f username)
  613. ;; Remove all moderators.
  614. (for-each (cut set-moderator <> #f username)
  615. (username->moderators username))
  616. ;; Add declared moderators.
  617. (for-each (cut set-moderator <> #t username)
  618. moderators))
  619. ;; Set the various account parameters.
  620. (set-account-details account-details username)))
  621. '#$(and declarative-mode?
  622. (map-in-order (cut jami-account-archive <>)
  623. accounts))
  624. '#$(and declarative-mode?
  625. (map-in-order
  626. (cut jami-account-allowed-contacts <>)
  627. accounts))
  628. '#$(and declarative-mode?
  629. (map-in-order (cut jami-account-moderators <>)
  630. accounts))
  631. '#$(and declarative-mode?
  632. (map-in-order jami-account->alist accounts)))))
  633. ;; Finally, return the PID of the daemon process.
  634. daemon-pid))
  635. ;; XXX: jamid takes some time to terminate, and GNU Shepherd
  636. ;; doesn't block when calling waitpid (see:
  637. ;; https://issues.guix.gnu.org/57922). Using SIGKILL instead
  638. ;; of SIGTERM works around that.
  639. (stop #~(make-kill-destructor SIGKILL))))))))
  640. (define jami-service-type
  641. (service-type
  642. (name 'jami)
  643. (default-value (jami-configuration))
  644. (extensions
  645. (list (service-extension shepherd-root-service-type
  646. jami-shepherd-services)
  647. (service-extension account-service-type
  648. (const %jami-accounts))
  649. (service-extension activation-service-type
  650. jami-dbus-session-activation)))
  651. (description "Run the Jami daemon (@command{jamid}). This service is
  652. geared toward the use case of hosting Jami rendezvous points over a headless
  653. server. If you use Jami on your local machine, you may prefer to setup a user
  654. Shepherd service for it instead; this way, the daemon will be shared via your
  655. normal user D-Bus session bus.")))
  656. ;;;
  657. ;;; Mumble server.
  658. ;;;
  659. ;; https://github.com/mumble-voip/mumble/blob/master/scripts/murmur.ini
  660. (define-record-type* <mumble-server-configuration> mumble-server-configuration
  661. make-mumble-server-configuration
  662. mumble-server-configuration?
  663. (package mumble-server-configuration-package ;file-like
  664. (default mumble))
  665. (user mumble-server-configuration-user
  666. (default "mumble-server"))
  667. (group mumble-server-configuration-group
  668. (default "mumble-server"))
  669. (port mumble-server-configuration-port
  670. (default 64738))
  671. (welcome-text mumble-server-configuration-welcome-text
  672. (default ""))
  673. (server-password mumble-server-configuration-server-password
  674. (default ""))
  675. (max-users mumble-server-configuration-max-users
  676. (default 100))
  677. (max-user-bandwidth mumble-server-configuration-max-user-bandwidth
  678. (default #f))
  679. (database-file mumble-server-configuration-database-file
  680. (default "/var/lib/mumble-server/db.sqlite"))
  681. (log-file mumble-server-configuration-log-file
  682. (default "/var/log/mumble-server/mumble-server.log"))
  683. (pid-file mumble-server-configuration-pid-file
  684. (default "/var/run/mumble-server/mumble-server.pid"))
  685. (autoban-attempts mumble-server-configuration-autoban-attempts
  686. (default 10))
  687. (autoban-timeframe mumble-server-configuration-autoban-timeframe
  688. (default 120))
  689. (autoban-time mumble-server-configuration-autoban-time
  690. (default 300))
  691. (opus-threshold mumble-server-configuration-opus-threshold
  692. (default 100)) ; integer percent
  693. (channel-nesting-limit mumble-server-configuration-channel-nesting-limit
  694. (default 10))
  695. (channelname-regex mumble-server-configuration-channelname-regex
  696. (default #f))
  697. (username-regex mumble-server-configuration-username-regex
  698. (default #f))
  699. (text-message-length mumble-server-configuration-text-message-length
  700. (default 5000))
  701. (image-message-length mumble-server-configuration-image-message-length
  702. (default (* 128 1024))) ; 128 Kilobytes
  703. (cert-required? mumble-server-configuration-cert-required?
  704. (default #f))
  705. (remember-channel? mumble-server-configuration-remember-channel?
  706. (default #f))
  707. (allow-html? mumble-server-configuration-allow-html?
  708. (default #f))
  709. (allow-ping? mumble-server-configuration-allow-ping?
  710. (default #f))
  711. (bonjour? mumble-server-configuration-bonjour?
  712. (default #f))
  713. (send-version? mumble-server-configuration-send-version?
  714. (default #f))
  715. (log-days mumble-server-configuration-log-days
  716. (default 31))
  717. (obfuscate-ips? mumble-server-obfuscate-ips?
  718. (default #t))
  719. (ssl-cert mumble-server-configuration-ssl-cert
  720. (default #f))
  721. (ssl-key mumble-server-configuration-ssl-key
  722. (default #f))
  723. (ssl-dh-params mumble-server-configuration-ssl-dh-params
  724. (default #f))
  725. (ssl-ciphers mumble-server-configuration-ssl-ciphers
  726. (default #f))
  727. (public-registration mumble-server-configuration-public-registration
  728. (default #f)) ; <mumble-server-public-registration-configuration>
  729. (file mumble-server-configuration-file
  730. (default #f)))
  731. (define-record-type* <mumble-server-public-registration-configuration>
  732. mumble-server-public-registration-configuration
  733. make-mumble-server-public-registration-configuration
  734. mumble-server-public-registration-configuration?
  735. (name mumble-server-public-registration-configuration-name)
  736. (password mumble-server-public-registration-configuration-password)
  737. (url mumble-server-public-registration-configuration-url)
  738. (hostname mumble-server-public-registration-configuration-hostname
  739. (default #f)))
  740. (define (flatten . lst)
  741. "Return a list that recursively concatenates all sub-lists of LST."
  742. (define (flatten1 head out)
  743. (if (list? head)
  744. (fold-right flatten1 out head)
  745. (cons head out)))
  746. (fold-right flatten1 '() lst))
  747. (define (default-mumble-server-config config)
  748. (match-record
  749. config
  750. <mumble-server-configuration>
  751. (user port welcome-text server-password max-users max-user-bandwidth
  752. database-file log-file pid-file autoban-attempts autoban-timeframe
  753. autoban-time opus-threshold channel-nesting-limit channelname-regex
  754. username-regex text-message-length image-message-length cert-required?
  755. remember-channel? allow-html? allow-ping? bonjour? send-version?
  756. log-days obfuscate-ips? ssl-cert ssl-key ssl-dh-params ssl-ciphers
  757. public-registration)
  758. (apply mixed-text-file "mumble-server.ini"
  759. (flatten
  760. "welcometext=" welcome-text "\n"
  761. "port=" (number->string port) "\n"
  762. (if server-password (list "serverpassword=" server-password "\n") '())
  763. (if max-user-bandwidth (list "bandwidth="
  764. (number->string max-user-bandwidth) "\n")
  765. '())
  766. "users=" (number->string max-users) "\n"
  767. "uname=" user "\n"
  768. "database=" database-file "\n"
  769. "logfile=" log-file "\n"
  770. "pidfile=" pid-file "\n"
  771. (if autoban-attempts (list "autobanAttempts=" (number->string autoban-attempts) "\n") '())
  772. (if autoban-timeframe (list "autobanTimeframe=" (number->string autoban-timeframe) "\n") '())
  773. (if autoban-time (list "autobanTime=" (number->string autoban-time) "\n") '())
  774. (if opus-threshold (list "opusthreshold=" (number->string opus-threshold) "\n") '())
  775. (if channel-nesting-limit (list "channelnestinglimit=" (number->string channel-nesting-limit) "\n") '())
  776. (if channelname-regex (list "channelname=" channelname-regex "\n") '())
  777. (if username-regex (list "username=" username-regex "\n") '())
  778. (if text-message-length (list "textmessagelength=" (number->string text-message-length) "\n") '())
  779. (if image-message-length (list "imagemessagelength=" (number->string image-message-length) "\n") '())
  780. (if log-days (list "logdays=" (number->string log-days) "\n") '())
  781. "obfuscate=" (if obfuscate-ips? "true" "false") "\n"
  782. "certrequired=" (if cert-required? "true" "false") "\n"
  783. "rememberchannel=" (if remember-channel? "true" "false") "\n"
  784. "allowhtml=" (if allow-html? "true" "false") "\n"
  785. "allowping=" (if allow-ping? "true" "false") "\n"
  786. "bonjour=" (if bonjour? "true" "false") "\n"
  787. "sendversion=" (if send-version? "true" "false") "\n"
  788. (cond ((and ssl-cert ssl-key)
  789. (list
  790. "sslCert=" ssl-cert "\n"
  791. "sslKey=" ssl-key "\n"))
  792. ((or ssl-cert ssl-key)
  793. (error "ssl-cert and ssl-key must both be set"
  794. ssl-cert ssl-key))
  795. (else '()))
  796. (if ssl-dh-params (list "sslDHParams=" ssl-dh-params) '())
  797. (if ssl-ciphers (list "sslCiphers=" ssl-ciphers) '())
  798. (match public-registration
  799. (#f '())
  800. (($ <mumble-server-public-registration-configuration>
  801. name password url hostname)
  802. (if (and (or (not server-password) (string-null? server-password))
  803. allow-ping?)
  804. (list
  805. "registerName=" name "\n"
  806. "registerPassword=" password "\n"
  807. "registerUrl=" url "\n"
  808. (if hostname
  809. (string-append "registerHostname=" hostname "\n")
  810. ""))
  811. (error "To publicly register your mumble-server server your server must be publicy visible
  812. and users must be able to join without a password. To fix this set:
  813. (allow-ping? #t)
  814. (server-password \"\")
  815. Or set public-registration to #f"))))))))
  816. (define (mumble-server-activation config)
  817. #~(begin
  818. (use-modules (guix build utils))
  819. (let* ((log-dir (dirname #$(mumble-server-configuration-log-file config)))
  820. (pid-dir (dirname #$(mumble-server-configuration-pid-file config)))
  821. (db-dir (dirname #$(mumble-server-configuration-database-file config)))
  822. (user (getpwnam #$(mumble-server-configuration-user config)))
  823. (init-dir
  824. (lambda (name dir)
  825. (format #t "creating mumble-server ~a directory '~a'\n" name dir)
  826. (mkdir-p dir)
  827. (chown dir (passwd:uid user) (passwd:gid user))
  828. (chmod dir #o700)))
  829. (ini #$(or (mumble-server-configuration-file config)
  830. (default-mumble-server-config config))))
  831. (init-dir "log" log-dir)
  832. (init-dir "pid" pid-dir)
  833. (init-dir "database" db-dir)
  834. (format #t "mumble-server: use config file: ~a~%\n" ini)
  835. (format #t "mumble-server: to set the SuperUser password run:
  836. `~a -ini ~a -readsupw`\n"
  837. #$(file-append (mumble-server-configuration-package config)
  838. "/bin/mumble-server") ini)
  839. #t)))
  840. (define mumble-server-accounts
  841. (match-lambda
  842. (($ <mumble-server-configuration> _ user group)
  843. (list
  844. (user-group
  845. (name group)
  846. (system? #t))
  847. (user-account
  848. (name user)
  849. (group group)
  850. (system? #t)
  851. (comment "Mumble server daemon")
  852. (home-directory "/var/empty")
  853. (shell (file-append shadow "/sbin/nologin")))))))
  854. (define (mumble-server-shepherd-service config)
  855. (list (shepherd-service
  856. (provision '(mumble-server))
  857. (documentation "Run the Mumble server.")
  858. (requirement '(networking))
  859. (start #~(make-forkexec-constructor
  860. '(#$(file-append (mumble-server-configuration-package config)
  861. "/bin/mumble-server")
  862. "-ini"
  863. #$(or (mumble-server-configuration-file config)
  864. (default-mumble-server-config config)))
  865. #:pid-file #$(mumble-server-configuration-pid-file config)))
  866. (stop #~(make-kill-destructor)))))
  867. (define mumble-server-service-type
  868. (service-type (name 'mumble-server)
  869. (description
  870. "Run the Mumble voice-over-IP (VoIP) server.")
  871. (extensions
  872. (list (service-extension shepherd-root-service-type
  873. mumble-server-shepherd-service)
  874. (service-extension activation-service-type
  875. mumble-server-activation)
  876. (service-extension account-service-type
  877. mumble-server-accounts)))
  878. (default-value (mumble-server-configuration))))
  879. (define-deprecated/public-alias
  880. murmur-configuration
  881. mumble-server-configuration)
  882. (define-deprecated/public-alias
  883. make-murmur-configuration
  884. make-mumble-server-configuration)
  885. (define-deprecated/public-alias
  886. murmur-configuration?
  887. mumble-server-configuration?)
  888. (define-deprecated/public-alias
  889. murmur-configuration-package
  890. mumble-server-configuration-package)
  891. (define-deprecated/public-alias
  892. murmur-configuration-user
  893. mumble-server-configuration-user)
  894. (define-deprecated/public-alias
  895. murmur-configuration-group
  896. mumble-server-configuration-group)
  897. (define-deprecated/public-alias
  898. murmur-configuration-port
  899. mumble-server-configuration-port)
  900. (define-deprecated/public-alias
  901. murmur-configuration-welcome-text
  902. mumble-server-configuration-welcome-text)
  903. (define-deprecated/public-alias
  904. murmur-configuration-server-password
  905. mumble-server-configuration-server-password)
  906. (define-deprecated/public-alias
  907. murmur-configuration-max-users
  908. mumble-server-configuration-max-users)
  909. (define-deprecated/public-alias
  910. murmur-configuration-max-user-bandwidth
  911. mumble-server-configuration-max-user-bandwidth)
  912. (define-deprecated/public-alias
  913. murmur-configuration-database-file
  914. mumble-server-configuration-database-file)
  915. (define-deprecated/public-alias
  916. murmur-configuration-log-file
  917. mumble-server-configuration-log-file)
  918. (define-deprecated/public-alias
  919. murmur-configuration-pid-file
  920. mumble-server-configuration-pid-file)
  921. (define-deprecated/public-alias
  922. murmur-configuration-autoban-attempts
  923. mumble-server-configuration-autoban-attempts)
  924. (define-deprecated/public-alias
  925. murmur-configuration-autoban-timeframe
  926. mumble-server-configuration-autoban-timeframe)
  927. (define-deprecated/public-alias
  928. murmur-configuration-autoban-time
  929. mumble-server-configuration-autoban-time)
  930. (define-deprecated/public-alias
  931. murmur-configuration-opus-threshold
  932. mumble-server-configuration-opus-threshold)
  933. (define-deprecated/public-alias
  934. murmur-configuration-channel-nesting-limit
  935. mumble-server-configuration-channel-nesting-limit)
  936. (define-deprecated/public-alias
  937. murmur-configuration-channelname-regex
  938. mumble-server-configuration-channelname-regex)
  939. (define-deprecated/public-alias
  940. murmur-configuration-username-regex
  941. mumble-server-configuration-username-regex)
  942. (define-deprecated/public-alias
  943. murmur-configuration-text-message-length
  944. mumble-server-configuration-text-message-length)
  945. (define-deprecated/public-alias
  946. murmur-configuration-image-message-length
  947. mumble-server-configuration-image-message-length)
  948. (define-deprecated/public-alias
  949. murmur-configuration-cert-required?
  950. mumble-server-configuration-cert-required?)
  951. (define-deprecated/public-alias
  952. murmur-configuration-remember-channel?
  953. mumble-server-configuration-remember-channel?)
  954. (define-deprecated/public-alias
  955. murmur-configuration-allow-html?
  956. mumble-server-configuration-allow-html?)
  957. (define-deprecated/public-alias
  958. murmur-configuration-allow-ping?
  959. mumble-server-configuration-allow-ping?)
  960. (define-deprecated/public-alias
  961. murmur-configuration-bonjour?
  962. mumble-server-configuration-bonjour?)
  963. (define-deprecated/public-alias
  964. murmur-configuration-send-version?
  965. mumble-server-configuration-send-version?)
  966. (define-deprecated/public-alias
  967. murmur-configuration-log-days
  968. mumble-server-configuration-log-days)
  969. (define-deprecated/public-alias
  970. murmur-configuration-obfuscate-ips?
  971. mumble-server-configuration-obfuscate-ips?)
  972. (define-deprecated/public-alias
  973. murmur-configuration-ssl-cert
  974. mumble-server-configuration-ssl-cert)
  975. (define-deprecated/public-alias
  976. murmur-configuration-ssl-key
  977. mumble-server-configuration-ssl-key)
  978. (define-deprecated/public-alias
  979. murmur-configuration-ssl-dh-params
  980. mumble-server-configuration-ssl-dh-params)
  981. (define-deprecated/public-alias
  982. murmur-configuration-ssl-ciphers
  983. mumble-server-configuration-ssl-ciphers)
  984. (define-deprecated/public-alias
  985. murmur-configuration-public-registration
  986. mumble-server-configuration-public-registration)
  987. (define-deprecated/public-alias
  988. murmur-configuration-file
  989. mumble-server-configuration-file)
  990. (define-deprecated/public-alias
  991. murmur-public-registration-configuration
  992. mumble-server-public-registration-configuration)
  993. (define-deprecated/public-alias
  994. make-murmur-public-registration-configuration
  995. make-mumble-server-public-registration-configuration)
  996. (define-deprecated/public-alias
  997. murmur-public-registration-configuration?
  998. mumble-server-public-registration-configuration?)
  999. (define-deprecated/public-alias
  1000. murmur-public-registration-configuration-name
  1001. mumble-server-public-registration-configuration-name)
  1002. (define-deprecated/public-alias
  1003. murmur-public-registration-configuration-url
  1004. mumble-server-public-registration-configuration-url)
  1005. (define-deprecated/public-alias
  1006. murmur-public-registration-configuration-password
  1007. mumble-server-public-registration-configuration-password)
  1008. (define-deprecated/public-alias
  1009. murmur-public-registration-configuration-hostname
  1010. mumble-server-public-registration-configuration-hostname)
  1011. (define-deprecated/public-alias
  1012. murmur-service-type
  1013. mumble-server-service-type)
  1014. ;; Local Variables:
  1015. ;; eval: (put 'with-retries 'scheme-indent-function 2)
  1016. ;; End: