From patchwork Thu Apr 3 06:43:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Cournoyer X-Patchwork-Id: 41209 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id 9F56F27BBEA; Thu, 3 Apr 2025 07:44:27 +0100 (BST) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,DKIM_VALID,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_BLOCKED,RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_CERTIFIED, RCVD_IN_VALIDITY_RPBL,RCVD_IN_VALIDITY_SAFE,SPF_HELO_PASS, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id 1575427BBE2 for ; Thu, 3 Apr 2025 07:44:27 +0100 (BST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u0EJ7-0008D5-RG; Thu, 03 Apr 2025 02:44:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u0EJ6-0008CX-FB for guix-patches@gnu.org; Thu, 03 Apr 2025 02:44:08 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1u0EJ5-0001X0-CY; Thu, 03 Apr 2025 02:44:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:From:To:In-Reply-To:References:Subject; bh=9dx0P1Az3ScDvUq8kR6JJfEWO73dI45oYtmmbmn8ZM8=; b=uJrssEwDblGRBa3jTTDvI44FWBkUCXI/GnQh6OwbesALT19lI/wTmpf1Ws1eqw6+3dEcq9ZJ64HCzWsBvOr9iqM5XeOOgEFgHlkfze/mDkJS36QPHwEoyDTgA0eZpEO//HAKgE2iuM+xje865e4wFjRJgKvM69EIFLNYimvrkC8ocDfgj0AJ+7X3kv7JyV6tS84+BXFNTDKfbmnatyj42UpFKDZDBwA3+sAzDX/bsImovySNdLYC4KplOEvUuSNhSQrMlZK8ImeQsN/WLmLW7CJv5zaGJkEipRwGMHpJiF//5iTweNMwlvaQHBs5x6yq72E+v67+9Ow2e0vZrxsD2A==; Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1u0EJ0-0004eW-F5; Thu, 03 Apr 2025 02:44:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#77396] [PATCH v2 1/2] least-authority: Preserve systemd LISTEN_* environment variables. References: In-Reply-To: Resent-From: Maxim Cournoyer Original-Sender: "Debbugs-submit" Resent-CC: maxim.cournoyer@gmail.com, ludo@gnu.org, guix@cbaines.net, dev@jpoiret.xyz, othacehe@gnu.org, zimon.toutoune@gmail.com, me@tobias.gr, guix-patches@gnu.org Resent-Date: Thu, 03 Apr 2025 06:44:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 77396 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 77396@debbugs.gnu.org Cc: Maxim Cournoyer , Maxim Cournoyer , Ludovic =?utf-8?q?Court=C3=A8s?= , Christopher Baines , Josselin Poiret , Mathieu Othacehe , Simon Tournier , Tobias Geerinckx-Rice X-Debbugs-Original-Xcc: Maxim Cournoyer , Ludovic =?utf-8?q?Court=C3=A8s?= , Christopher Baines , Josselin Poiret , Mathieu Othacehe , Simon Tournier , Tobias Geerinckx-Rice Received: via spool by 77396-submit@debbugs.gnu.org id=B77396.174366264017869 (code B ref 77396); Thu, 03 Apr 2025 06:44:02 +0000 Received: (at 77396) by debbugs.gnu.org; 3 Apr 2025 06:44:00 +0000 Received: from localhost ([127.0.0.1]:60595 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u0EIx-0004e9-O9 for submit@debbugs.gnu.org; Thu, 03 Apr 2025 02:44:00 -0400 Received: from mail-pf1-x42e.google.com ([2607:f8b0:4864:20::42e]:52227) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u0EIu-0004dr-Nf for 77396@debbugs.gnu.org; Thu, 03 Apr 2025 02:43:57 -0400 Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-7340e6f3ce1so423526b3a.0 for <77396@debbugs.gnu.org>; Wed, 02 Apr 2025 23:43:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1743662630; x=1744267430; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=9dx0P1Az3ScDvUq8kR6JJfEWO73dI45oYtmmbmn8ZM8=; b=RtyIsf+/GiER7qmmeLnpTK8DuayKVpJO8LyBID5shtGSJrcFG2m7Q1n8y0Sckl7fmm kzaaNbt9BvAL5BgO1r4LrnroG7Fjp0iwBPQ2qSieBln5ZxUaHCENqiHt+FPD4z5oI6Rh lOvzP25QI4CfC+groQHfI2HdoEi0J0y8HQnW8JYbj5ddQCkvm2evKnFdoPKRh1GfmbdF e8xTeiaPwo+8tqetL7ffXj6DJMVg85DnrykarR7ACCyJgefMbevjdRpDZ9n4fh9K6YKi HYF1ypuQ/sXDTp64cL5xGUD3ifypvCcrPsb4ADJCi9mFcRNSVYMOpvEs7NJM8X4K66Fz nqog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743662630; x=1744267430; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=9dx0P1Az3ScDvUq8kR6JJfEWO73dI45oYtmmbmn8ZM8=; b=PHCBbfElblShkqo+EURMVTNeCa7wBf0f3b5ucJq9uhL86vSvPDgYEW2ILeKUYZYTqQ OdX1tk4gy4V3Q5mQSVHUxzpHiOs4gyFLVbgmTr/wwmCkmXY85TZS25t76lw7XtDb6vHU A4+CvdCiFr8iZwBhhwW0nTADXcCdbpieipaVqWWu8DWVAXVurqkFMVDAJk3bpkpwrQu5 a9NzxUE38frF3t8rMLwPNXzY7skCSkvAU6LK7alW3O2iFPnneFZfZ61R2FCKs5dl0CJA tsGnfM5rzQ8NsG0davIm3rGbXWLQG8tqzd5jbmKyF9PaGOEwht3GbROvBmZQw9cVowcY zKsQ== X-Gm-Message-State: AOJu0YzJFoaC8cSkFvKDlzjYM93pac9QiJdtrHZXFevPqBTX/QLTuLfd 8+KLKcPn/KJoc7e2UcxrzuSbV/SXRc5YA58KVlKAEWJw2sz6Qf8UNp4Z3A== X-Gm-Gg: ASbGnctsTnxaHo7nNZOmlCv2N7nrAefp+cnZyON2M634oFwYZcdeFmMxPiJ7NDwwObx jG4aEvVRcCVMvWs1rvTX76Cs+WYyfNeJ9QTg+hG7scxMsOHOeZYzl4u1/NA/H//jjNJanARxnSi pevmqqud/cukjvGgd/p7UfCwyv4gc4ou+gTjgXrpicZYQPFuqNvSZtV9ktyTDk/FX+kxOY7ncD5 QwGoR+ihIDM9idtK5dzh8/Sw6zvgRA2s+IPxK4oRdqy/CUdeB+ztC2Q9wHqSnvnN6nrf3AxQOWm WUIkx8Q1xqxKiDFzg1M7Zf5X0QJZAF2oIKgMgtxQE/BA5uggWw3AE5oCRLzTERS3 X-Google-Smtp-Source: AGHT+IEscBv7p1DThmgFNQTu/hv+dUJo73dXLBv6jcoprko6wzkejHHlNlrj8/wOwASh2ERmJavKtg== X-Received: by 2002:a05:6a20:c90d:b0:1f5:a3e8:64dd with SMTP id adf61e73a8af0-200f713321cmr2705400637.0.1743662630051; Wed, 02 Apr 2025 23:43:50 -0700 (PDT) Received: from localhost.localdomain ([2405:6586:be0:0:83c8:d31d:2cec:f542]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-af9bc330489sm527711a12.32.2025.04.02.23.43.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Apr 2025 23:43:49 -0700 (PDT) From: Maxim Cournoyer Date: Thu, 3 Apr 2025 15:43:24 +0900 Message-ID: X-Mailer: git-send-email 2.49.0 MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches Otherwise, combining make-systemd-constructor with least-authority-wrapper would not work correctly out of the box. * guix/least-authority.scm (%precious-variables): Rename to... (%default-preserved-environment-variables): ... this, and export it. Add "LISTEN_PID" "LISTEN_FDS" "LISTEN_FDNAMES" environment variables. (least-authority-wrapper): Adjust accordingly. Change-Id: Idd259b15463920965f530e1917d76bf97def3b7b --- guix/least-authority.scm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) base-commit: 8c43056aabc2d22da61dc86049b143f7ae1ef516 diff --git a/guix/least-authority.scm b/guix/least-authority.scm index 3465fe9a48..cd846aaa61 100644 --- a/guix/least-authority.scm +++ b/guix/least-authority.scm @@ -26,7 +26,8 @@ (define-module (guix least-authority) spec->file-system file-system->spec file-system-mapping->bind-mount) - #:export (least-authority-wrapper)) + #:export (least-authority-wrapper + %default-preserved-environment-variables)) ;;; Commentary: ;;; @@ -35,9 +36,10 @@ (define-module (guix least-authority) ;;; ;;; Code: -(define %precious-variables +(define %default-preserved-environment-variables ;; Environment variables preserved by the wrapper by default. - '("HOME" "USER" "LOGNAME" "DISPLAY" "XAUTHORITY" "TERM" "TZ" "PAGER")) + '("HOME" "USER" "LOGNAME" "DISPLAY" "XAUTHORITY" "TERM" "TZ" "PAGER" + "LISTEN_PID" "LISTEN_FDS" "LISTEN_FDNAMES")) ;for make-systemd-constructor (define* (least-authority-wrapper program #:key (name "pola-wrapper") @@ -49,7 +51,7 @@ (define* (least-authority-wrapper program (namespaces %namespaces) (directory "/") (preserved-environment-variables - %precious-variables)) + %default-preserved-environment-variables)) "Return a wrapper of PROGRAM that executes it with the least authority. PROGRAM is executed in separate namespaces according to NAMESPACES, a list of From patchwork Thu Apr 3 06:43:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Maxim Cournoyer X-Patchwork-Id: 41210 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id 8C2BF27BBEA; Thu, 3 Apr 2025 07:45:25 +0100 (BST) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,DKIM_VALID,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_BLOCKED,RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_CERTIFIED, RCVD_IN_VALIDITY_RPBL,RCVD_IN_VALIDITY_SAFE,SPF_HELO_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id 1BE4327BBE2 for ; Thu, 3 Apr 2025 07:45:23 +0100 (BST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u0EKB-0008OJ-VG; Thu, 03 Apr 2025 02:45:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u0EK5-0008N6-0C for guix-patches@gnu.org; Thu, 03 Apr 2025 02:45:10 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1u0EJy-0001nF-6B; Thu, 03 Apr 2025 02:45:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:References:In-Reply-To:Date:From:To:Subject; bh=K14hP8MALA4eahg/H2A+RJMtvuks++Ki0I0witvVbCk=; b=E2nWNS0wz8sbhXHg2TIeogp6bx7ElTWcnA6u2ULgxE88AChTKxxRALkXJdXyfy1V4a3ZKQmhol1LHGr7kzkStqIwTIykYovz20zJENFhYZrvkrLsbR2lWe4efQJBj+vBSCl8q7NKepc7y+jFY+nDz+m2U+a+egEaeXetUDz+HtWH1soT+6UPEAyS/BLVjd+qI6In+AnIPZzUuouA9sMGryc+niJ7eGnZr7oxwJjPP80hpHIy4Gc+G9ex2M/Z1dj+cm1RUxwXOW0g4HkH3jHQYKPm49qRt5kFrnqPD+6eUOfPThJOZwxfcvrDTeELdxLLZzDzVqU7QxVMSCu16KLWTg==; Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1u0EJy-0004gf-0l; Thu, 03 Apr 2025 02:45:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#77396] [PATCH v2 2/2] services: Add ngircd-service-type. Resent-From: Maxim Cournoyer Original-Sender: "Debbugs-submit" Resent-CC: maxim.cournoyer@gmail.com, ludo@gnu.org, guix-patches@gnu.org Resent-Date: Thu, 03 Apr 2025 06:45:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 77396 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 77396@debbugs.gnu.org Cc: Maxim Cournoyer , Maxim Cournoyer , Ludovic =?utf-8?q?Court=C3=A8s?= X-Debbugs-Original-Xcc: Maxim Cournoyer , Ludovic =?utf-8?q?Court=C3=A8s?= Received: via spool by 77396-submit@debbugs.gnu.org id=B77396.174366264717924 (code B ref 77396); Thu, 03 Apr 2025 06:45:01 +0000 Received: (at 77396) by debbugs.gnu.org; 3 Apr 2025 06:44:07 +0000 Received: from localhost ([127.0.0.1]:60601 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u0EJ3-0004ex-Ae for submit@debbugs.gnu.org; Thu, 03 Apr 2025 02:44:07 -0400 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]:59487) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u0EIz-0004dz-F4 for 77396@debbugs.gnu.org; Thu, 03 Apr 2025 02:44:04 -0400 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-7359aca7ef2so654841b3a.2 for <77396@debbugs.gnu.org>; Wed, 02 Apr 2025 23:44:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1743662634; x=1744267434; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=K14hP8MALA4eahg/H2A+RJMtvuks++Ki0I0witvVbCk=; b=T2a5sKkX88KpQeRPZNiQ4EnIlEqcjWgw/NlnYZJ8lsuXfAnnEI9xpY/o9n8puCKFPv 5OE1W1YRCE8Pco4YycICHwMVRrNofNBYS3I/DmNdVSBUmoioQ6Q5JuULDm0mfqiCr4BI FL5yYGLuETX3JERERHATsVjcDHrx7QESO0zWuwU7gP7K3DuUNXF+rUjUpANaziLU5QGD 2QWog3+77HsOvBJcYffGSLrYBrr9SMfYtfx8l71jCVup85JohXYqpNQIXECFbOTHlW91 NML1TGVKo78Gn/hOzYR7fNVhsraxM3d/Am06+MJe39MlORL0mirds6x6wYcpSdaskisy /4QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743662634; x=1744267434; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=K14hP8MALA4eahg/H2A+RJMtvuks++Ki0I0witvVbCk=; b=XDoiqjouRth1XP0PNPAfgwUM+9AzMBAq8oIq2XYd/Zxp7dDjb6Azf9cJsm7zahjy5/ D3GYllP4eOkmiuDIPN9673Z6MPE7otRNZmAmpjf6L/8b1BEUNPbWGtzwY4sX7JSGr+oy M8m0hRVe0+OCOCMXdDf/HlAyUnhB1g3kpcydX3IVCK+1aZ039aI+SW9I1gS1Vxj+KX0E nsxapNAkNxV8zMgJVHw51b/SnFr4ACFTIcqN94xGfgQLse09Y6AZZAMyHbAln2ROYAT2 tHCzBCqveOwO7/MMj56AuloTo9JG0ZglrJKmAXVI+Ay6U40aXFl5s62Qpqn6GnzzJ6M3 QOSQ== X-Gm-Message-State: AOJu0Yzamdom4rQhvzSY/QeDFqYUIgGTiz2rz4yanqvPZBd3Et3s0GWF A5I32TZLqZLMw2+n/RTrvEwAJ5xsiz1SbqJTd7ca5kbOn2DEpO2sMqa77g== X-Gm-Gg: ASbGncvjh4YVVsEq/6vxQk5sOSDZHww6MGD9brW8R7QcwOQkon8fSTm3lg5aX2R3bQN oJu1pVtr6y4IRv1QxPnGQ9SxlbijSasmkaFkBLkgKmxp3L9XI7jOngHzSURPbA7zgSPC1l034Rf uT0Hjf04x0TEuTLkEhoJW8oTZggibjV08ox9Li4v0dv1yU9Ghg4cpf14Fh8/fSaMXdWoRZrmvGz ZddKHGfqF+J6i9Ufsn6M4kD8tm9berV6gkcSV0Rn0MEHA2NcW4I54kpTl+mAZ1RB2qdM2e7w1jk nbM5EOQwDs8HZJLB+hcND8aaibNyOoMqBshdYa2gVMyL8GuItB1s5e1+MHcNDLlD X-Google-Smtp-Source: AGHT+IHM+0O0IoBJH+KzPT5sGt9df/tlnvLcv1kjebNmV8z7LSCMb9L+nqgqbALHdyjb4Ji4AXh20Q== X-Received: by 2002:a05:6a21:920d:b0:1f5:84c8:5d03 with SMTP id adf61e73a8af0-2009f5ba5c5mr33569383637.3.1743662633252; Wed, 02 Apr 2025 23:43:53 -0700 (PDT) Received: from localhost.localdomain ([2405:6586:be0:0:83c8:d31d:2cec:f542]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-af9bc330489sm527711a12.32.2025.04.02.23.43.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Apr 2025 23:43:52 -0700 (PDT) From: Maxim Cournoyer Date: Thu, 3 Apr 2025 15:43:25 +0900 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches * gnu/services/messaging.scm (pascal-case, ngircd-serialize-string) (ngircd-serialize-boolean, ngircd-serialize-file-like) (ngircd-serialize-list-of-strings, ngircd-serialize-list-of-ports) (ngircd-serialize-number, ngircd-serialize-port) (string-or-number?, ngircd-serialize-string-or-number): New procedures. (ngircd-global, ngircd-limits, ngircd-options, ngircd-ssl) (ngircd-operator, ngircd-server, ngircd-channel) (ngircd-configuration): New configurations. (serialize-ngircd-global, serialize-ngircd-limits) (serialize-ngircd-options, serialize-ngircd-operator) (serialize-list-of-ngircd-operators, serialize-ngircd-server) (serialize-ngircd-channel, serialize-list-of-ngircd-channels) (serialize-ngircd-configuration): New procedures. (list-of-ngircd-operators?, list-of-ngircd-servers?) (list-of-ngircd-channels?): New predicates. (ngircd-generate-documentation): New procedure. (ngircd-user+group, ngircd-account, ngircd-wrapper): Likewise. (ngircd-shepherd-service): New shepherd service. (%ngircd-activation): New procedure. (ngircd-service-type): New service type. * gnu/tests/messaging.scm (%ngircd-os): New variable. (run-ngircd-test): New procedure. (%test-ngircd): New test. * doc/guix.texi (Messaging Services): Document it. Change-Id: I3ce9a7fd0b33afab22cf15942a1db0cf5b12bfdb --- doc/guix.texi | 413 +++++++++++++++++++++++ gnu/services/messaging.scm | 653 +++++++++++++++++++++++++++++++++++++ gnu/tests/messaging.scm | 123 +++++++ 3 files changed, 1189 insertions(+) diff --git a/doc/guix.texi b/doc/guix.texi index f6d774fd13..b73f8d7b8a 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -30351,6 +30351,419 @@ Messaging Services @end table @end deftp +@subsubheading ngIRCd service + +@cindex IRCd, Internet Relay Chat daemon +@cindex IRC daemon service +@cindex IRC server service +@cindex IRC (Internet Relay Chat) + +@url{https://ngircd.barton.de/, ngIRCd}, is a lightweight @acronym{IRCd, +Internet Relay Chat daemon}, which can be used to host your own IRC +server. + +@defvar ngircd-service-type +The service type for ngIRCd. Its value is a @code{ngircd-configuration} +object, documented below. + +A simple example configuration could look like: + +@lisp +(service ngircd-service-type + (ngircd-configuration + (channels + (list (ngircd-channel + (name "#fruits") + (topic "All things fruits -- veggies are off-topic")))) + (operators + (list (ngircd-operator + (name "mikan") + (password "tomatoes-are-fruits/carrots-are-not")))))) +@end lisp +@end defvar + +@c To regenerate the rest of this section documentation, use the +@c `ngircd-generate-documentation' procedure in +@c (gnu services messaging). +@c %start of fragment + +@deftp {Data Type} ngircd-configuration +Available @code{ngircd-configuration} fields are: + +@table @asis +@item @code{ngircd} (default: @code{ngircd}) (type: file-like) +The @code{ngircd} package to use. + +@item @code{debug?} (default: @code{#f}) (type: boolean) +Turn on debugging messages. + +@item @code{global} (type: ngircd-global) +A ngircd-global record object used to specify global options. + +@item @code{limits} (type: maybe-ngircd-limits) +The ngircd-limits record object used to specify limits options. + +@item @code{options} (type: maybe-ngircd-options) +The ngircd-options record object used to specify optional features and +configuration options. + +@item @code{ssl} (type: maybe-ngircd-ssl) +The ngircd-ssl record object used to specify the SSL-related options. + +@item @code{operators} (type: maybe-list-of-ngircd-operators) +A list of ngircd-operator record objects used to specify the operators. + +@item @code{servers} (type: maybe-list-of-ngircd-servers) +A list of ngircd-server record objects used to specify other remote +servers to connect to. + +@item @code{channels} (type: maybe-list-of-ngircd-channels) +A list of ngircd-channels record objects specifying pre-defined channels +to be created by the server when starting up. + +@end table + +@end deftp + + +@c %end of fragment + +@c %start of fragment + +@deftp {Data Type} ngircd-global +Available @code{ngircd-global} fields are: + +@table @asis +@item @code{name} (type: maybe-string) +Server name in the IRC network. This is an individual name of the IRC +server, it is not related to the DNS host name. It must be unique in +the IRC network and must contain at least one dot (@samp{.}) character. +When not set, ngIRCd tries to deduce a valid IRC server name from the +local host name. + +@item @code{admin-info-1} (type: maybe-string) +First administrator information. + +@item @code{admin-info-2} (type: maybe-string) +Second administrator information. + +@item @code{admin-email} (type: maybe-string) +Email to reach administrators. + +@item @code{help-file} (type: maybe-file-like) +File-like containing the ngIRCd help text. + +@item @code{info} (type: maybe-string) +Info text of the server. This will be shown by WHOIS and LINKS requests +for example. + +@item @code{listen} (default: @code{("::" "0.0.0.0")}) (type: list-of-strings) +A list of IP address on which the server should listen. By default it +listens on all configured IP addresses and interfaces. + +@item @code{motd-file} (type: file-like) +Text file with the @i{message of the day} (MOTD). This message will be +shown to all users connecting to the server. + +@item @code{motd-phrase} (type: maybe-string) +A simple phrase (<127 chars) to use if you don't want to use a MOTD +file. + +@item @code{network} (type: maybe-string) +The name of the IRC network to which this server belongs. This name is +optional, should only contain ASCII characters, and can't contain +spaces. It is only used to inform clients. + +@item @code{password} (type: maybe-string) +Global password or all users needed to connect to the server. By +default, no password is required. PAM must be disabled for this option +to have an effect. + +@item @code{pid-file} (type: maybe-string) +The file name where the PID of ngIRCd should be written after it starts. +By default, no PID file is created. + +@item @code{ports} (default: @code{(6667)}) (type: list-of-ports) +Port number(s) on which the server should listen for @emph{unencrypted} +connections. + +@item @code{server-uid} (default: @code{"ngircd"}) (type: string-or-number) +The user that the @command{ngircd} command should run as. + +@item @code{server-gid} (default: @code{"ngircd"}) (type: string-or-number) +The group that the @command{ngircd} command should run as. + +@end table + +@end deftp + + +@c %end of fragment + +@c %start of fragment + +@deftp {Data Type} ngircd-limits +Available @code{ngircd-limits} fields are: + +@table @asis +@item @code{connect-retry} (default: @code{60}) (type: maybe-number) +The number of seconds the server should wait before re-attempting to +establish a link to not yet (or no longer) connected servers. + +@item @code{max-connections} (default: @code{0}) (type: maybe-number) +Maximum number of simultaneous in- and outbound connections the server +is allowed to accept. There is no limit by default. + +@item @code{max-connections-ip} (default: @code{5}) (type: maybe-number) +Maximum number of simultaneous connections from a single IP address that +the server will accept. This configuration options lowers the risk of +denial of service attacks (DoS). Set to 0 to remove the limit. + +@item @code{max-joins} (default: @code{10}) (type: maybe-number) +Maximum number of channels a user can be member of. Set to 0 to remove +the limit. + +@item @code{max-list-size} (default: @code{100}) (type: maybe-number) +Maximum number of channels returned in response to a LIST command. + +@item @code{ping-timeout} (default: @code{120}) (type: maybe-number) +Number of seconds of inactivity after which the server will send a PING +to the peer to test whether it is alive or not. + +@item @code{pong-timeout} (default: @code{20}) (type: maybe-number) +If a client fails to answer a PING with a PONG within this amount of +seconds, it will be disconnected by the server. + +@end table + +@end deftp + + +@c %end of fragment + +@c %start of fragment + +@deftp {Data Type} ngircd-options +Available @code{ngircd-options} fields are: + +@table @asis +@item @code{allowed-channel-types} (default: @code{"#&+"}) (type: maybe-string) +List of allowed channel types (channel prefixes) for newly created +channels on the local server. By default, all supported channel types +are allowed. + +@item @code{allow-remote-oper?} (default: @code{#f}) (type: maybe-boolean) +If this option is active, IRC operators connected to remote servers are +allowed to control this local server using administrative commands, for +example like CONNECT, DIE, SQUIT, etc. + +@item @code{connect-ipv4?} (default: @code{#t}) (type: maybe-boolean) +Set to @code{#f} to prevent ngIRCd from connecting to other IRC servers +using the IPv4 protocol, allowed by default. + +@item @code{connect-ipv6?} (default: @code{#t}) (type: maybe-boolean) +Set to @code{#f} to prevent ngIRCd from connecting to other IRC servers +using the IPv6 protocol, allowed by default. + +@item @code{dns?} (default: @code{#t}) (type: maybe-boolean) +Set to @code{#f} to disable DNS lookups when clients connect. If you +configure the daemon to connect to other servers, ngIRCd may still +perform a DNS lookup if required. + +@item @code{more-privacy?} (default: @code{#f}) (type: maybe-boolean) +Set this to @code{#t} to have ngIRCd censor user idle time, logon time +as well as the PART/QUIT messages (that sometimes used to inform +everyone about which client software is being used). WHOWAS requests +are also silently ignored, and NAMES output doesn't list any clients for +non-members. This option is most useful when ngIRCd is being used +together with anonymizing software such as TOR or I2P and one does not +wish to make it too easy to collect statistics on the users. + +@item @code{notice-before-registration?} (default: @code{#f}) (type: maybe-boolean) +Normally ngIRCd doesn't send any messages to a client until it is +registered. Enable this option to let the daemon send @samp{NOTICE *} +messages to clients while connecting. + +@item @code{oper-can-use-mode?} (default: @code{#f}) (type: maybe-boolean) +Should IRC Operators be allowed to use the MODE command even if they are +not(!) channel-operators? + +@item @code{oper-chan-p-auto-op?} (default: @code{#t}) (type: maybe-boolean) +Should IRC Operators get AutoOp (+o) in persistent (+P) channels? + +@item @code{oper-server-mode?} (default: @code{#f}) (type: maybe-boolean) +If @code{open-can-use-mode?} is @code{#t}, this may lead the +compatibility problems with servers that run the ircd-irc2 software. +This option masks mode requests by non-chanops as if they were coming +from the server. Only enable this if you have ircd-irc2 servers in your +IRC network. + +@item @code{pam?} (default: @code{#f}) (type: boolean) +Set to @code{#t} to enable calls to the PAM library at runtime; all +users connecting without password are allowed to connect, all passwords +given will fail. Users identified without PAM are registered with a +tilde (@samp{~}) prepended to their user name. This defaults to +@code{#f} in Guix because the service runs as a unpriveleged user and +thus cannot authenticate other users via the @code{pam_unix} PAM module. + +@item @code{pam-is-optional?} (default: @code{#f}) (type: maybe-boolean) +Set to @code{#t} to make PAM authentication optional, causing clients +not sending a password to still be able to connect, but won't become +identified and keep the tilder (@samp{~}) character prepended to their +supplied user name. + +@item @code{require-auth-ping?} (default: @code{#f}) (type: maybe-boolean) +Set to @code{#t} to have ngIRCd send an authentication PING when a new +client connects, and register this client only after receiving the +corresponding PONG reply. + +@end table + +@end deftp + + +@c %end of fragment + +@c %start of fragment + +@deftp {Data Type} ngircd-ssl +Available @code{ngircd-ssl} fields are: + +@table @asis +@item @code{cert-file} (type: maybe-string) +SSL certificate file of the private server key. + +@item @code{key-file} (type: maybe-string) +File name of the SSL Server Key to be used for SSL connections, which is +required for SSL/TLS support. + +@item @code{ca-file} (default: @code{"/etc/ssl/certs/ca-certificates.crt"}) (type: maybe-string) +A file listing all the certificates of the trusted Certificate +Authorities. + +@item @code{ports} (type: maybe-list-of-ports) +Like the global configuration's @code{port} option, except that ngIRCd +will expect incoming connections to be SSL/TLS encrypted. Common port +numbers for SSL-encrypted IRC are 6669 and 6697. + +@item @code{cipher-list} (type: maybe-string) +The GnuTLS cipher suites allowed for SSL/TLS connections, a value such +as @code{"SECURE128:-VERS-SSL3.0"}. Refer to @samp{man 3 +gnutls_priority_init} for details. + +@item @code{dh-file} (type: maybe-file-like) +A file-like containing the Diffie-Hellman parameters, which can be +created with GnuTLS via @samp{certtool --generate-dh-params}. If this +file is not present, the Diffie-Hellman parameters will be computed on +startup, which may take some time. + +@end table + +@end deftp + + +@c %end of fragment + +@c %start of fragment + +@deftp {Data Type} ngircd-operator +Available @code{ngircd-operator} fields are: + +@table @asis +@item @code{name} (type: string) +ID of the operator (may be different of the nickname). + +@item @code{password} (type: string) +Password of the IRC operator. + +@item @code{mask} (type: maybe-string) +Mask that is to be checked before an /OPER for this account is accepted, +for example: @code{"nick!ident@@*.example.com"}. + +@end table + +@end deftp + + +@c %end of fragment + +@c %start of fragment + +@deftp {Data Type} ngircd-server +Available @code{ngircd-server} fields are: + +@table @asis +@item @code{name} (type: string) +IRC name of the remote server. + +@item @code{host} (type: string) +Internet host name (or IP address) of the peer. + +@item @code{my-password} (type: string) +Own password for this connection. This password has to be configured as +@code{peer-password} on the other server and must not have @samp{:} as +first character. + +@item @code{peer-password} (type: string) +Foreign password for this connection. This password has to be +configured as @code{my-password} on the other server. + +@item @code{bind} (type: maybe-string) +IP address to use as source IP for the outgoing connection. The default +is to let the operating system decide. + +@item @code{port} (type: maybe-port) +Port of the remote server to which ngIRCd should connect (active). If +no port is assigned to a configured server, the daemon only waits for +incoming connections (passive, which is the default). + +@item @code{group} (type: maybe-number) +Group of this server. + +@item @code{passive?} (default: @code{#f}) (type: maybe-boolean) +Set to @code{#t} to disable automatic connection even if the port value +is specified. + +@item @code{ssl-connect?} (default: @code{#f}) (type: maybe-boolean) +Connect to the remote server using TLS/SSL. + +@end table + +@end deftp + + +@c %end of fragment + +@c %start of fragment + +@deftp {Data Type} ngircd-channel +Available @code{ngircd-channel} fields are: + +@table @asis +@item @code{name} (type: string) +Name of the channel, including channel prefix ("#" or "&"). + +@item @code{topic} (type: maybe-string) +Topic for this channel. + +@item @code{modes} (type: maybe-list-of-strings) +Initial channel modes, as used in MODE commands. Modifying lists (ban +list, invite list, exception list) is supported. If multiple MODE +strings are specified, they are evaluated in the order listed (left to +right). + +@item @code{key-file} (type: maybe-file-like) +Path and file name of a ngIRCd key file containing individual channel +keys for different users. Refer to @samp{man 5 ngircd.conf} for more +details. + +@end table + +@end deftp + + +@c %end of fragment + @subsubheading Quassel Service @cindex IRC (Internet Relay Chat) diff --git a/gnu/services/messaging.scm b/gnu/services/messaging.scm index 9bfeabacf4..0072056869 100644 --- a/gnu/services/messaging.scm +++ b/gnu/services/messaging.scm @@ -3,6 +3,7 @@ ;;; Copyright © 2017 Mathieu Othacehe ;;; Copyright © 2015, 2017-2020, 2022-2024 Ludovic Courtès ;;; Copyright © 2018 Pierre-Antoine Rouby +;;; Copyright © 2025 Maxim Cournoyer ;;; ;;; This file is part of GNU Guix. ;;; @@ -20,6 +21,7 @@ ;;; along with GNU Guix. If not, see . (define-module (gnu services messaging) + #:use-module ((gnu home services utils) #:select (object->camel-case-string)) #:use-module (gnu packages admin) #:use-module (gnu packages base) #:use-module (gnu packages irc) @@ -38,7 +40,10 @@ (define-module (gnu services messaging) #:use-module (guix deprecation) #:use-module (guix least-authority) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:use-module (srfi srfi-35) + #:use-module (srfi srfi-71) + #:use-module (ice-9 format) #:use-module (ice-9 match) #:export (prosody-service-type prosody-configuration @@ -58,6 +63,32 @@ (define-module (gnu services messaging) bitlbee-configuration? bitlbee-service-type + + ngircd-configuration + ngircd-configuration? + + ngircd-global + ngircd-global? + + ngircd-limits + ngircd-limits? + + ngircd-options + ngircd-options? + + ngircd-ssl + ngircd-ssl? + + ngircd-operator + ngircd-operator? + + ngircd-server + ngircd-server? + + ngircd-channel + ngircd-channel? + ngircd-service-type + quassel-configuration quassel-service-type @@ -921,6 +952,628 @@ (define bitlbee-service-type "Run @url{http://bitlbee.org,BitlBee}, a daemon that acts as a gateway between IRC and chat networks."))) + +;;; +;;; ngIRCd. +;;; + +(define-maybe string + (prefix ngircd-)) + +(define-maybe file-like + (prefix ngircd-)) + +(define-maybe list-of-strings + (prefix ngircd-)) + +(define (port? x) + (and (number? x) + (and (>= x 0) (<= x 65535)))) + +(define list-of-ports? + (list-of port?)) + +(define-maybe port + (prefix ngircd-)) + +(define-maybe list-of-ports + (prefix ngircd-)) + +(define-maybe number + (prefix ngircd-)) + +(define-maybe boolean + (prefix ngircd-)) + +(define (pascal-case text) + (object->camel-case-string text 'upper)) + +(define (ngircd-serialize-string field value) + (format #f "~a = ~a~%" (pascal-case field) value)) + +(define (ngircd-serialize-boolean field value) + (let* ((field (symbol->string field)) + (name (if (string-suffix? "?" field) + (string-drop-right field 1) + field))) + (format #f "~a = ~:[false~;true~]~%" (pascal-case name) value))) + +(define (ngircd-serialize-file-like field value) + #~(format #f "~a = ~a~%" #$(pascal-case field) #$value)) + +(define (ngircd-serialize-list-of-strings field value) + (format #f "~a = ~{~a~^,~}~%" (pascal-case field) value)) + +(define ngircd-serialize-list-of-ports + ngircd-serialize-list-of-strings) + +(define ngircd-serialize-number ngircd-serialize-string) + +(define ngircd-serialize-port ngircd-serialize-number) + +(define (string-or-number? x) + (or (string? x) (number? x))) + +(define ngircd-serialize-string-or-number ngircd-serialize-string) + +(define-configuration ngircd-global ;[Global] + (name + maybe-string + "Server name in the IRC network. This is an individual name of the IRC +server, it is not related to the DNS host name. It must be unique in the IRC +network and must contain at least one dot (@samp{.}) character. When not set, +ngIRCd tries to deduce a valid IRC server name from the local host name.") + (admin-info-1 + maybe-string + "First administrator information.") + (admin-info-2 + maybe-string + "Second administrator information.") + (admin-email + maybe-string + "Email to reach administrators.") + (help-file + maybe-file-like + "File-like containing the ngIRCd help text.") + (info + maybe-string + "Info text of the server. This will be shown by WHOIS and LINKS requests +for example.") + (listen + (list-of-strings (list "::" "0.0.0.0")) + "A list of IP address on which the server should listen. By default it +listens on all configured IP addresses and interfaces.") + (motd-file + ;; Provide an empty default file to avoid a warning when running --conftest + ;; in the activation script. + (file-like (plain-file "ngircd.motd" "")) + "Text file with the @i{message of the day} (MOTD). This message will be +shown to all users connecting to the server.") + (motd-phrase + maybe-string + "A simple phrase (<127 chars) to use if you don't want to use a MOTD +file.") + (network + maybe-string + "The name of the IRC network to which this server belongs. This name is +optional, should only contain ASCII characters, and can't contain spaces. It +is only used to inform clients.") + (password + maybe-string + "Global password or all users needed to connect to the server. By default, +no password is required. PAM must be disabled for this option to have an +effect.") + (pid-file + maybe-string + "The file name where the PID of ngIRCd should be written after it starts. +By default, no PID file is created.") + (ports + (list-of-ports (list 6667)) + "Port number(s) on which the server should listen for @emph{unencrypted} +connections.") + (server-uid + (string-or-number "ngircd") + "The user that the @command{ngircd} command should run as.") + (server-gid + (string-or-number "ngircd") + "The group that the @command{ngircd} command should run as.") + (prefix ngircd-)) + +(define (serialize-ngircd-global _ config) + #~(string-append + "[Global]\n" + #$(serialize-configuration config ngircd-global-fields))) + +(define-configuration ngircd-limits ;[Limits] + (connect-retry + (maybe-number 60) + "The number of seconds the server should wait before re-attempting to +establish a link to not yet (or no longer) connected servers.") + (max-connections + (maybe-number 0) + "Maximum number of simultaneous in- and outbound connections the server is +allowed to accept. There is no limit by default.") + (max-connections-ip + (maybe-number 5) + "Maximum number of simultaneous connections from a single IP address that +the server will accept. This configuration options lowers the risk of denial +of service attacks (DoS). Set to 0 to remove the limit.") + (max-joins + (maybe-number 10) + "Maximum number of channels a user can be member of. Set to 0 to remove +the limit.") + (max-list-size + (maybe-number 100) + "Maximum number of channels returned in response to a LIST command.") + (ping-timeout + (maybe-number 120) + "Number of seconds of inactivity after which the server will send a PING to +the peer to test whether it is alive or not.") + (pong-timeout + (maybe-number 20) + "If a client fails to answer a PING with a PONG within this amount of +seconds, it will be disconnected by the server.") + (prefix ngircd-)) + +(define (serialize-ngircd-limits _ config) + #~(string-append + "\n[Limits]\n" + #$(serialize-configuration config ngircd-limits-fields))) + +(define-maybe ngircd-limits) + +(define-configuration ngircd-options ;[Options] + (allowed-channel-types + (maybe-string "#&+") + "List of allowed channel types (channel prefixes) for newly created +channels on the local server. By default, all supported channel types are +allowed.") + (allow-remote-oper? + (maybe-boolean #f) + "If this option is active, IRC operators connected to remote servers are +allowed to control this local server using administrative commands, for +example like CONNECT, DIE, SQUIT, etc.") + (connect-ipv4? + (maybe-boolean #t) + "Set to @code{#f} to prevent ngIRCd from connecting to other IRC servers +using the IPv4 protocol, allowed by default.") + (connect-ipv6? + (maybe-boolean #t) + "Set to @code{#f} to prevent ngIRCd from connecting to other IRC servers +using the IPv6 protocol, allowed by default.") + (dns? + (maybe-boolean #t) + "Set to @code{#f} to disable DNS lookups when clients connect. If you +configure the daemon to connect to other servers, ngIRCd may still perform a +DNS lookup if required.") + (more-privacy? + (maybe-boolean #f) + "Set this to @code{#t} to have ngIRCd censor user idle time, logon time as +well as the PART/QUIT messages (that sometimes used to inform everyone about +which client software is being used). WHOWAS requests are also silently +ignored, and NAMES output doesn't list any clients for non-members. This +option is most useful when ngIRCd is being used together with anonymizing +software such as TOR or I2P and one does not wish to make it too easy to +collect statistics on the users.") + (notice-before-registration? + (maybe-boolean #f) + "Normally ngIRCd doesn't send any messages to a client until it is +registered. Enable this option to let the daemon send @samp{NOTICE *} +messages to clients while connecting.") + (oper-can-use-mode? + (maybe-boolean #f) + "Should IRC Operators be allowed to use the MODE command even if they are +not(!) channel-operators?") + (oper-chan-p-auto-op? + (maybe-boolean #t) + "Should IRC Operators get AutoOp (+o) in persistent (+P) channels?") + (oper-server-mode? + (maybe-boolean #f) + "If @code{open-can-use-mode?} is @code{#t}, this may lead the compatibility +problems with servers that run the ircd-irc2 software. This option masks mode +requests by non-chanops as if they were coming from the server. Only enable +this if you have ircd-irc2 servers in your IRC network.") + (pam? + (boolean #f) + "Set to @code{#t} to enable calls to the PAM library at runtime; all users +connecting without password are allowed to connect, all passwords given will +fail. Users identified without PAM are registered with a tilde (@samp{~}) +prepended to their user name. This defaults to @code{#f} in Guix because the +service runs as a unpriveleged user and thus cannot authenticate other users +via the @code{pam_unix} PAM module.") + (pam-is-optional? + (maybe-boolean #f) + "Set to @code{#t} to make PAM authentication optional, causing clients not +sending a password to still be able to connect, but won't become identified +and keep the tilder (@samp{~}) character prepended to their supplied user +name.") + (require-auth-ping? + (maybe-boolean #f) + "Set to @code{#t} to have ngIRCd send an authentication PING when a new +client connects, and register this client only after receiving the +corresponding PONG reply.") + (prefix ngircd-)) + +(define (serialize-ngircd-options _ config) + #~(string-append + "\n[Options]\n" + #$(serialize-configuration config ngircd-options-fields))) + +(define-maybe ngircd-options) + +(define-configuration ngircd-ssl ;[SSL] + (cert-file + maybe-string + "SSL certificate file of the private server key.") + (key-file + maybe-string + "File name of the SSL Server Key to be used for SSL connections, which is +required for SSL/TLS support.") + (ca-file + (maybe-string "/etc/ssl/certs/ca-certificates.crt") + "A file listing all the certificates of the trusted Certificate +Authorities.") + (ports + maybe-list-of-ports + "Like the global configuration's @code{port} option, except that ngIRCd +will expect incoming connections to be SSL/TLS encrypted. Common port numbers +for SSL-encrypted IRC are 6669 and 6697.") + (cipher-list + maybe-string + "The GnuTLS cipher suites allowed for SSL/TLS connections, a value such as +@code{\"SECURE128:-VERS-SSL3.0\"}. Refer to @samp{man 3 gnutls_priority_init} +for details.") + (dh-file + maybe-file-like + "A file-like containing the Diffie-Hellman parameters, which can be created +with GnuTLS via @samp{certtool --generate-dh-params}. If this file is not +present, the Diffie-Hellman parameters will be computed on startup, which may +take some time.") + (prefix ngircd-)) + +(define (serialize-ngircd-ssl _ config) + #~(string-append + "\n[SSL]\n" + #$(serialize-configuration config ngircd-ssl-fields))) + +(define-maybe ngircd-ssl) + +(define-configuration ngircd-operator ;[Operator] + (name + string + "ID of the operator (may be different of the nickname).") + (password + string + "Password of the IRC operator.") + (mask + maybe-string + "Mask that is to be checked before an /OPER for this account is accepted, +for example: @code{\"nick!ident@@*.example.com\"}.") + (prefix ngircd-)) + +(define list-of-ngircd-operators? + (list-of ngircd-operator?)) + +(define (serialize-ngircd-operator _ operator) + #~(string-append + "\n[Operator]\n" + #$(serialize-configuration operator ngircd-operator-fields))) + +(define (serialize-list-of-ngircd-operators _ operators) + #~(string-append #$@(map (cut serialize-ngircd-operator #f <>) operators))) + +(define-maybe list-of-ngircd-operators) + +(define-configuration ngircd-server ;[Server] + (name + string + "IRC name of the remote server.") + (host + string + "Internet host name (or IP address) of the peer.") + (my-password + string + "Own password for this connection. This password has to be configured as +@code{peer-password} on the other server and must not have @samp{:} as first +character.") + (peer-password + string + "Foreign password for this connection. This password has to be configured +as @code{my-password} on the other server.") + (bind + maybe-string + "IP address to use as source IP for the outgoing connection. The default +is to let the operating system decide.") + (port + maybe-port + "Port of the remote server to which ngIRCd should connect (active). If no +port is assigned to a configured server, the daemon only waits for incoming +connections (passive, which is the default).") + (group + maybe-number + "Group of this server.") + (passive? + (maybe-boolean #f) + "Set to @code{#t} to disable automatic connection even if the port value is +specified.") + (ssl-connect? + (maybe-boolean #f) + "Connect to the remote server using TLS/SSL.") + (prefix ngircd-)) + +(define list-of-ngircd-servers? + (list-of ngircd-server?)) + +(define (serialize-ngircd-server _ server) + #~(string-append + "\n[Server]\n" + #$(serialize-configuration server ngircd-server-fields))) + +(define (serialize-list-of-ngircd-servers _ servers) + #~(string-append #$@(map (cut serialize-ngircd-server #f <>) servers))) + +(define-maybe list-of-ngircd-servers) + +(define-configuration ngircd-channel ;[Channel] + (name + string + "Name of the channel, including channel prefix (\"#\" or \"&\").") + (topic + maybe-string + "Topic for this channel.") + (modes + maybe-list-of-strings + "Initial channel modes, as used in MODE commands. Modifying lists (ban +list, invite list, exception list) is supported. If multiple MODE strings are +specified, they are evaluated in the order listed (left to right)." + (serializer (lambda (_ value) + ;; Special case: each mode string gets serialized to a + ;; separate option. + (format #f "~{Modes = ~a~%~}" value)))) + (key-file + maybe-file-like + "Path and file name of a ngIRCd key file containing individual channel keys +for different users. Refer to @samp{man 5 ngircd.conf} for more details.") + (prefix ngircd-)) + +(define list-of-ngircd-channels? + (list-of ngircd-channel?)) + +(define (serialize-ngircd-channel _ channel) + #~(string-append + "\n[Channel]\n" + #$(serialize-configuration channel ngircd-channel-fields))) + +(define (serialize-list-of-ngircd-channels _ channels) + #~(string-append #$@(map (cut serialize-ngircd-channel #f <>) channels))) + +(define-maybe list-of-ngircd-channels) + +(define-configuration ngircd-configuration + (ngircd + (file-like ngircd) + "The @code{ngircd} package to use.") + (debug? + (boolean #f) + "Turn on debugging messages." + (serializer empty-serializer)) + (global + ;; Always use a ngircd-global default to ensure the correct PidFile option + ;; is set, as it is required by the service. + (ngircd-global (ngircd-global)) + "A ngircd-global record object used to specify global options.") + (limits + maybe-ngircd-limits + "The ngircd-limits record object used to specify limits options.") + (options + maybe-ngircd-options + "The ngircd-options record object used to specify optional features and +configuration options.") + (ssl + maybe-ngircd-ssl + "The ngircd-ssl record object used to specify the SSL-related options.") + (operators + maybe-list-of-ngircd-operators + "A list of ngircd-operator record objects used to specify the operators.") + (servers + maybe-list-of-ngircd-servers + "A list of ngircd-server record objects used to specify other remote +servers to connect to.") + (channels + maybe-list-of-ngircd-channels + "A list of ngircd-channels record objects specifying pre-defined channels +to be created by the server when starting up.")) + +(define (ngircd-generate-documentation) + (configuration->documentation 'ngircd-configuration) + (configuration->documentation 'ngircd-global) + (configuration->documentation 'ngircd-limits) + (configuration->documentation 'ngircd-options) + (configuration->documentation 'ngircd-ssl) + (configuration->documentation 'ngircd-operator) + (configuration->documentation 'ngircd-server) + (configuration->documentation 'ngircd-channel)) + +(define (ngircd-user+group config) + "Return the Global->ServerUID and Global->ServerGID configuration options as +values." + (let* ((global (ngircd-configuration-global config)) + (user (ngircd-global-server-uid global)) + (group (ngircd-global-server-gid global))) + (values user group))) + +(define (ngircd-account config) + (let* ((user group (ngircd-user+group config)) + (group-name (if (string? group) + group + "ngircd")) + (user-name (if (string? user) + user + "ngircd")) + (gid (if (number? group) + group + #f)) + (uid (if (number? user) + user + #f))) + (list (user-group + (name group-name) + (id gid) + (system? #t)) + (user-account + (name user-name) + (uid uid) + (group group-name) + (system? #t) + (comment "Ngircd daemon user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin")))))) + +(define (serialize-ngircd-configuration config) + "Return a file-like object corresponding to the serialized + record." + (mixed-text-file "ngircd.conf" + (serialize-configuration + config ngircd-configuration-fields))) + +(define (ngircd-wrapper config) + "Take CONFIG, a object, and provide a least-authority +wrapper for the 'ngircd' command." + (let* ((ngircd.conf (serialize-ngircd-configuration config)) + (user group (ngircd-user+group config)) + (global (ngircd-configuration-global config)) + (help-file (ngircd-global-help-file global)) + (motd-file (ngircd-global-motd-file global)) + (ssl (ngircd-configuration-ssl config)) + (ca-file (ngircd-ssl-ca-file ssl)) + (cert-file (ngircd-ssl-cert-file ssl)) + (key-file (ngircd-ssl-key-file ssl)) + (dh-file (ngircd-ssl-dh-file ssl)) + (channels (ngircd-configuration-channels config))) + (least-authority-wrapper + (file-append (ngircd-configuration-ngircd config) "/sbin/ngircd") + #:name "ngircd-pola-wrapper" + ;; Expose all needed files, such as all options corresponding to + ;; file-like objects and string file names. + #:mappings + (append + (list (file-system-mapping + (source "/dev/log") ;for syslog + (target source)) + (file-system-mapping + (source ngircd.conf) + (target source))) + (if (maybe-value-set? help-file) + (list (file-system-mapping + (source help-file) + (target source))) + '()) + (if (maybe-value-set? motd-file) + (list (file-system-mapping + (source motd-file) + (target source))) + '()) + (if (maybe-value-set? ssl) + ;; When SSL is used, expose the specified keys and certificates. + (append + (if (maybe-value-set? ca-file) + (list (file-system-mapping + (source ca-file) + (target source))) + '()) + (if (maybe-value-set? cert-file) + (list (file-system-mapping + (source cert-file) + (target source))) + '()) + (if (maybe-value-set? key-file) + (list (file-system-mapping + (source key-file) + (target source))) + '()) + (if (maybe-value-set? dh-file) + (list (file-system-mapping + (source dh-file) + (target source))) + '())) + '()) + (if (maybe-value-set? channels) + (filter-map (lambda (channel) + (let ((key-file (ngircd-channel-key-file channel))) + (and (maybe-value-set? key-file) + key-file))) + channels) + '())) + #:user user + #:group group + ;; ngircd wants to look up users in /etc/passwd so run in the global user + ;; namespace. + #:namespaces (fold delq %namespaces '(net user))))) + +(define (ngircd-shepherd-service config) + (match-record config + (ngircd debug? global ssl) + (let* ((ngircd.conf (serialize-ngircd-configuration config)) + (ngircd (file-append ngircd "/sbin/ngircd")) + (addresses (ngircd-global-listen global)) + (ports* (ngircd-global-ports global)) + (ports (if (and (maybe-value-set? ssl) + (maybe-value-set? (ngircd-ssl-ports ssl))) + (append ports* (ngircd-ssl-ports ssl)) + ports*))) + (list (shepherd-service + (provision '(ngircd)) + (requirement '(user-processes networking syslogd)) + (modules (cons '(srfi srfi-1) %default-modules)) + (actions (list (shepherd-configuration-action ngircd.conf))) + (start #~(make-systemd-constructor + (append (list #$(ngircd-wrapper config) + "--nodaemon" "--syslog" + "--config" #$ngircd.conf) + (if #$debug? + '("--debug") + '())) + ;; Compute endpoints for each listen addresses/ports + ;; combinations. + (append-map + (lambda (port) + (map (lambda (addr) + (endpoint + (addrinfo:addr + (car (getaddrinfo + addr + (number->string port) + (logior AI_NUMERICHOST + AI_NUMERICSERV)))))) + (list #$@addresses))) + (list #$@ports)))) + (stop #~(make-systemd-destructor))))))) + +(define (ngircd-activation config) + (let* ((ngircd (file-append (ngircd-configuration-ngircd config))) + (ngircd.conf (serialize-ngircd-configuration config))) + ;; Ensure stdin is not a TTY to avoid pausing for a key during boot + ;; when a problem is detected. + #~(parameterize ((current-input-port (%make-void-port "r"))) + (system* #$(file-append ngircd "/sbin/ngircd") + "--configtest" "--config" #$ngircd.conf)))) + +(define ngircd-service-type + (service-type + (name 'ngircd) + (extensions + (list (service-extension shepherd-root-service-type + ngircd-shepherd-service) + (service-extension profile-service-type + (compose list ngircd-configuration-ngircd)) + (service-extension account-service-type + ngircd-account) + (service-extension activation-service-type + ngircd-activation))) + (description + "Run @url{https://ngircd.barton.de/, ngIRCd}, a lightweight @acronym{IRC, +Internet Relay Chat} daemon."))) + ;;; ;;; Quassel. diff --git a/gnu/tests/messaging.scm b/gnu/tests/messaging.scm index 9eae3f6049..c0c1c4a5d6 100644 --- a/gnu/tests/messaging.scm +++ b/gnu/tests/messaging.scm @@ -2,6 +2,7 @@ ;;; Copyright © 2017, 2018 Clément Lassieur ;;; Copyright © 2017-2018, 2021-2022 Ludovic Courtès ;;; Copyright © 2018 Efraim Flashner +;;; Copyright © 2025 Maxim Cournoyer ;;; ;;; This file is part of GNU Guix. ;;; @@ -23,14 +24,19 @@ (define-module (gnu tests messaging) #:use-module (gnu system) #:use-module (gnu system vm) #:use-module (gnu services) + #:use-module (gnu services base) #:use-module (gnu services messaging) #:use-module (gnu services networking) + #:use-module (gnu services ssh) + #:use-module (gnu packages irc) #:use-module (gnu packages messaging) + #:use-module (gnu packages screen) #:use-module (guix gexp) #:use-module (guix store) #:use-module (guix modules) #:export (%test-prosody %test-bitlbee + %test-ngircd %test-quassel)) (define (run-xmpp-test name xmpp-service pid-file create-account) @@ -217,6 +223,123 @@ (define %test-bitlbee (description "Connect to a BitlBee IRC server.") (value (run-bitlbee-test)))) + +;;; +;;; ngIRCd. +;;; + +(define %ngircd-os + (operating-system + (inherit %simple-os) + (packages (cons* ii screen %base-packages)) + (services + (cons* + (service dhcp-client-service-type) + ;; For ease of debugging. Run the vm with: + ;; '-nic user,model=virtio-net-pci,hostfwd=tcp::10022-:22' + (service openssh-service-type ;for ease of debugging + (openssh-configuration + (permit-root-login #t) + (allow-empty-passwords? #t))) + (service ngircd-service-type + (ngircd-configuration + (debug? #t) + (global + (ngircd-global + (server-uid 990) + (server-gid 990))) + ;; There is no need to serialize the following sections, which + ;; are all optional, but include them anyway to test the + ;; serializers. + (limits (ngircd-limits)) + (options (ngircd-options)) + (ssl (ngircd-ssl)) + (operators (list (ngircd-operator + (name "apteryx") + (password "1234")))) + (channels + (list (ngircd-channel + (name "#guix") + (topic "GNU Guix | https://guix.gnu.org")))))) + %base-services)))) + +(define (run-ngircd-test) + (define vm + (virtual-machine + (operating-system + (marionette-operating-system + %ngircd-os + #:imported-modules (source-module-closure + '((gnu build dbus-service) + (guix build utils) + (gnu services herd))))))) + + (define test + (with-imported-modules '((gnu build marionette)) + #~(begin + (use-modules (srfi srfi-64) + (gnu build marionette)) + + (define marionette + (make-marionette (list #$vm))) + + (test-runner-current (system-test-runner #$output)) + (test-begin "ngircd") + + (test-assert "ngircd service runs" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + (wait-for-service 'ngircd)) + marionette)) + + (test-assert "ngircd listens on TCP port 6667" + (wait-for-tcp-port 6667 marionette)) + + (test-assert "basic irc operations function as expected" + (marionette-eval + '(begin + (use-modules ((gnu build dbus-service) #:select (with-retries)) + (ice-9 textual-ports)) + + (define (write-command command) + (call-with-output-file "in" + (lambda (port) + (display (string-append command "\n") port)))) + + (define (grep-output text) + (with-retries 5 1 ;retry for 5 seconds + (string-contains (call-with-input-file "out" get-string-all) + text))) + + (unless (zero? (system "ii -s localhost -i /tmp &")) + (error "error connecting to irc server")) + + (with-retries 5 1 + (chdir "/tmp/localhost")) ;move to FIFO directory + + (write-command "/join #guix") + (grep-output "GNU Guix | https://guix.gnu.org") + + (write-command "/oper apteryx 1234") + (grep-output "+o")) + marionette)) + + (test-end)))) + + (gexp->derivation "ngircd-test" test)) + +(define %test-ngircd + (system-test + (name "ngircd") + (description "Connect to a ngircd IRC server.") + (value (run-ngircd-test)))) + + +;;; +;;; Quassel. +;;; + (define (run-quassel-test) (define os (marionette-operating-system