Merge branch 'belenios' into 'main'

Draft: Belenios

See merge request nounous/nixos!64
merge-requests/64/merge
Lyes Saadi 2026-04-26 00:00:15 +02:00
commit 8157463076
31 changed files with 2690 additions and 106 deletions

View File

@ -38,13 +38,19 @@
./modules
agenix.nixosModules.default
];
additionalPackages = [ ./pkgs ];
in
{
apprentix = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/apprentix ] ++ baseModules;
};
belenios = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/belenios ] ++ baseModules ++ additionalPackages;
};
collabora = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/collabora ] ++ baseModules;
@ -99,6 +105,7 @@
specialArgs = inputs;
modules = [ ./hosts/vm/vaultwarden ] ++ baseModules;
};
cransIso = nixosSystem {
system = "x86_64-linux";
specialArgs = inputs;
@ -113,6 +120,8 @@
perSystem =
{ config, pkgs, ... }:
{
packages = pkgs.callPackage ./pkgs/packages.nix { inherit pkgs; };
devShells = {
default = pkgs.callPackage ./devshells/default.nix { inherit (inputs) agenix; };
};

View File

@ -1,4 +1,9 @@
{ pkgs, lib, modulesPath, ... }:
{
pkgs,
lib,
modulesPath,
...
}:
{
imports = [
@ -12,14 +17,21 @@
};
nix = {
settings.experimental-features = [ "nix-command" "flakes" ];
settings.experimental-features = [
"nix-command"
"flakes"
];
extraOptions = "experimental-features = nix-command flakes";
};
boot = {
kernelParams = [ "console=ttyS0,115200" ];
kernelPackages = pkgs.linuxPackages_latest;
supportedFilesystems = lib.mkForce [ "btrfs" "vfat" "zfs"];
supportedFilesystems = lib.mkForce [
"btrfs"
"vfat"
"zfs"
];
};
services.openssh = {
@ -37,35 +49,32 @@
programs.vim.enable = true;
environment.systemPackages =
let crans-ip-config =
(
pkgs.writeShellScriptBin "crans-ip-config"
''
#!/usr/bin/env bash
echo -n "ID : "
read ID
ip -c l
echo -n "vlan 10, interface ensXX : "
read INTERFACE10
ip addr add 172.16.10.$ID/24 dev ens$INTERFACE10
let
crans-ip-config = (
pkgs.writeShellScriptBin "crans-ip-config" ''
#!/usr/bin/env bash
echo -n "ID : "
read ID
ip -c l
echo -n "vlan 10, interface ensXX : "
read INTERFACE10
ip addr add 172.16.10.$ID/24 dev ens$INTERFACE10
ip link set ens$INTERFACE10 up
echo -n "souhaitez-vous configurer le vlan 3 ? (o/N)"
read REP
if [[ "$REP" == [oOyY] ]]; then
echo -n "vlan 3, interface ensXX : "
read INTERFACE3
ip addr add 172.16.3.$ID/24 dev ens$INTERFACE3
ip link set ens$INTERFACE10 up
echo -n "souhaitez-vous configurer le vlan 3 ? (o/N)"
read REP
if [[ "$REP" == [oOyY] ]]; then
echo -n "vlan 3, interface ensXX : "
read INTERFACE3
ip addr add 172.16.3.$ID/24 dev ens$INTERFACE3
ip link set ens$INTERFACE10 up
ip route add default via 172.16.3.99
else
ip route add default via 172.16.10.101
fi
''
);
crans-disk-config =
(
pkgs.writeShellScriptBin "crans-disk-config"
ip route add default via 172.16.3.99
else
ip route add default via 172.16.10.101
fi
''
);
crans-disk-config = (
pkgs.writeShellScriptBin "crans-disk-config" ''
#!/usr/bin/env bash
lsblk
echo -n "disque /dev/XXX : "
@ -85,7 +94,9 @@
echo "Pensez également à vous mettre sur la branche appropriée"
''
);
in with pkgs; [
in
with pkgs;
[
bat
fd
helix
@ -94,7 +105,7 @@
shelldap
crans-ip-config
crans-disk-config
];
];
users.users.root = {
password = "crans";

View File

@ -0,0 +1,95 @@
{ ... }:
let
domain = "belenios.crans.org";
email.from = "root@crans.org";
email.contact = "contact@crans.org";
cas.name = "CAS Cr@ns";
cas.server = "https://cas.crans.org/";
in
{
services.belenios = {
enable = true;
config = ''
<!-- -*- Mode: Xml -*- -->
<ocsigen>
<server>
<port>8001</port>
<logdir>/var/log/belenios</logdir>
<datadir>/var/lib/belenios/data</datadir>
<uploaddir>/var/lib/belenios/upload</uploaddir>
<!--
The following limits are there to avoid flooding the server.
<maxuploadfilesize> might need to be increased for handling large
elections.
<maxconnected> is related to the number of simultaneous voters
visiting the server.
-->
<maxuploadfilesize>1024kB</maxuploadfilesize>
<maxconnected>500</maxconnected>
<commandpipe>/var/run/ocsigenserver_command</commandpipe>
<charset>utf-8</charset>
<findlib path="/usr/lib/ocaml"/>
<extension findlib-package="ocsigenserver.ext.staticmod"/>
<extension findlib-package="ocsigenserver.ext.redirectmod"/>
<extension findlib-package="ocsigenserver.ext.ocsipersist-sqlite">
<database file="/var/lib/belenios/data/ocsidb"/>
</extension>
<extension findlib-package="eliom.server"/>
<extension findlib-package="belenios-platform-native"/>
<host charset="utf-8" hostfilter="*" defaulthostname="${domain}">
<!-- <redirect suburl="^$" dest="http://www.example.org"/> -->
<site path="static" charset="utf-8">
<static dir="/usr/share/belenios-server" cache="0"/>
</site>
<site path="monitor">
<eliom findlib-package="eliom.server.monitor.start"/>
</site>
<eliom findlib-package="belenios-server">
<!-- Domain name used in Message-ID -->
<domain name="https://${domain}/"/>
<!--
The following can be adjusted to the capacity of your system.
If <maxrequestbodysizeinmemory> is too small, large elections
might fail, in particular with so-called alternative questions
with many voters.
<maxmailsatonce> depends heavily on how sending emails is
handled by your system.
-->
<maxrequestbodysizeinmemory value="1048576"/>
<maxmailsatonce value="1000"/>
<uuid length="14"/>
<gdpr uri="https://www.belenios.org/rgpd.html"/>
<contact uri="mailto:${email.contact}"/>
<server mail="${email.from}" return-path="${email.contact}"/>
<auth-export name="builtin-cas"/>
<auth-export name="builtin-password"/>
<auth name="${cas.name}"><cas server="${cas.server}"/></auth>
<source file="/usr/share/belenios-server/belenios.tar.gz"/>
<default-group file="/usr/share/belenios-server/groups/default.json"/>
<nh-group file="/usr/share/belenios-server/groups/rfc3526-2048.json"/>
<log file="/var/log/belenios/security.log"/>
<locales dir="/usr/share/belenios-server/locales"/>
<spool dir="/var/lib/belenios/spool"/>
<!-- <warning file="/var/local/belenios/belenios/_run/warning.html"/> -->
</eliom>
</host>
</server>
</ocsigen>
'';
};
}

View File

@ -0,0 +1,24 @@
{ ... }:
{
imports = [
./hardware-configuration.nix
./belenios.nix
];
networking.hostName = "belenios";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 111;
srvNat.enable = true;
};
resticClient.when = "03:27";
};
system.stateVersion = "25.11";
}

View File

@ -0,0 +1,45 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/9fed1492-e7b2-4ec2-a5f4-8825bf8e89a0";
fsType = "ext4";
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.ens18.useDHCP = lib.mkDefault true;
# networking.interfaces.ens19.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View File

@ -8,7 +8,9 @@ let
pam_modules_path = "${pkgs.pam}/lib/security";
# nixos/modules/security/pam.nix
pam_ldap = "${if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap}/lib/security";
pam_ldap = "${
if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap
}/lib/security";
in
{
services.collabora-online = {
@ -22,13 +24,19 @@ in
net = {
listen = "loopback";
post_allow.host = ["::1" "172.0.0.1"];
post_allow.host = [
"::1"
"172.0.0.1"
];
};
# ouvre seulement les fichiers depuis nextcloud
storage.wopi = {
"@allow" = true;
host = ["nextcloud.crans.org" "nextcloud.adm.crans.org"];
host = [
"nextcloud.crans.org"
"nextcloud.adm.crans.org"
];
};
admin_console.enable_pam = true;

View File

@ -1,22 +1,35 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/ef139717-388f-41f3-b707-b0f75af3f546";
fsType = "ext4";
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/ef139717-388f-41f3-b707-b0f75af3f546";
fsType = "ext4";
};
swapDevices = [ ];

View File

@ -44,7 +44,6 @@
];
};
appstoreEnable = true;
extraAppsEnable = true;
};

View File

@ -1,22 +1,35 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/ad1cdd57-44a2-4e1c-83c7-8810a567e0f7";
fsType = "ext4";
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/ad1cdd57-44a2-4e1c-83c7-8810a567e0f7";
fsType = "ext4";
};
swapDevices = [ ];

View File

@ -6,17 +6,21 @@
ens18 = {
ipv4 = {
addresses = [{
address = "172.16.10.118";
prefixLength = 24;
}];
addresses = [
{
address = "172.16.10.118";
prefixLength = 24;
}
];
};
ipv6 = {
addresses = [{
address = "fd00::10:0:ff:fe01:1810";
prefixLength = 64;
}];
addresses = [
{
address = "fd00::10:0:ff:fe01:1810";
prefixLength = 64;
}
];
};
};
@ -24,27 +28,35 @@
ens19 = {
ipv4 = {
addresses = [{
address = "172.16.3.118";
prefixLength = 24;
}];
routes = [{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}];
addresses = [
{
address = "172.16.3.118";
prefixLength = 24;
}
];
routes = [
{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [{
address = "2a0c:700:3::ff:fe01:1803";
prefixLength = 64;
}];
routes = [{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}];
addresses = [
{
address = "2a0c:700:3::ff:fe01:1803";
prefixLength = 64;
}
];
routes = [
{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}
];
};
};

View File

@ -1,22 +1,35 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/c4c2de17-2965-4c0a-b4c5-7d518712c9aa";
fsType = "ext4";
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/c4c2de17-2965-4c0a-b4c5-7d518712c9aa";
fsType = "ext4";
};
swapDevices = [ ];

View File

@ -1,4 +1,4 @@
{...}:
{ ... }:
{
boot.loader.grub = {
splashImage = ../../assets/nix-crans_bootloader.png;

View File

@ -31,7 +31,7 @@ in
home_adh = mkIf cfg.homeAdh.enable {
mountPoint = "/home-adh";
device = "172.16.4.2:/pool/home";
fsType = "nfs";
fsType = "nfs";
};
};
};

View File

@ -52,11 +52,13 @@ in
paths = [
"/etc"
"/var"
] ++ cfg.additionalPaths;
]
++ cfg.additionalPaths;
exclude = [
"/var/cache"
"/var/lib/lxcfs"
] ++ cfg.additionalExcludes;
]
++ cfg.additionalExcludes;
timerConfig = {
OnCalendar = cfg.when;
RandomizedDelaySec = "6h";

View File

@ -202,25 +202,27 @@ in
}) cfg.virtualHosts;
# Génération des alias
getAliases = name: config: lib.foldr (
tld: acc:
acc
++
(lib.foldr (alias: acc: acc ++ ["${alias}.crans.${tld}"]) ["${name}.crans.${tld}"] config.serverAliases)
)
(lib.foldr (alias: acc: acc ++ ["${alias}.crans.${mainTld}"]) [] config.serverAliases)
otherTld;
getAliases =
name: config:
lib.foldr
(
tld: acc:
acc
++ (lib.foldr (alias: acc: acc ++ [ "${alias}.crans.${tld}" ]) [
"${name}.crans.${tld}"
] config.serverAliases)
)
(lib.foldr (alias: acc: acc ++ [ "${alias}.crans.${mainTld}" ]) [ ] config.serverAliases)
otherTld;
# Configuration des alias
aliasConfig = lib.foldr (
vhost: acc:
acc
//
lib.foldr (
// lib.foldr (
alias: acc:
acc
//
{
// {
"${vhost.name}-alias-${alias}" = rec {
rejectSSL = vhost.value.httpOnly;
forceSSL = !rejectSSL;

View File

@ -0,0 +1,52 @@
diff --git a/src/lib/core/dune b/src/lib/core/dune
index b3fa93bc..978bcfd5 100644
--- a/src/lib/core/dune
+++ b/src/lib/core/dune
@@ -1,7 +1,7 @@
(library
(name belenios_core)
(public_name belenios-lib.core)
- (libraries base64 hex yojson atdgen re belenios-platform)
+ (libraries base64 hex yojson atdgen-runtime re belenios-platform)
(modules_without_implementation question_sigs trustees_sig versioned_sig))
(rule
diff --git a/src/lib/question/dune b/src/lib/question/dune
index aecbfad1..f78738ef 100644
--- a/src/lib/question/dune
+++ b/src/lib/question/dune
@@ -2,7 +2,7 @@
(name belenios_question)
(public_name belenios-lib.question)
(modules_without_implementation types)
- (libraries yojson atdgen belenios-platform belenios-lib.core))
+ (libraries yojson atdgen-runtime belenios-platform belenios-lib.core))
(rule
(targets question_h_t.ml question_h_t.mli)
diff --git a/src/lib/shell/dune b/src/lib/shell/dune
index 63828081..de8f3870 100644
--- a/src/lib/shell/dune
+++ b/src/lib/shell/dune
@@ -3,7 +3,7 @@
(public_name belenios-lib)
(libraries
yojson
- atdgen
+ atdgen-runtime
belenios-platform
belenios-lib.core
belenios-lib.v1))
diff --git a/src/lib/v1/dune b/src/lib/v1/dune
index 4c0eb68d..890262c0 100644
--- a/src/lib/v1/dune
+++ b/src/lib/v1/dune
@@ -4,7 +4,7 @@
(modules_without_implementation types)
(libraries
yojson
- atdgen
+ atdgen-runtime
belenios-platform
belenios-lib.core
belenios-lib.question))

View File

@ -0,0 +1,83 @@
{ pkgs }:
let
ocamlPackages = pkgs.ocaml-ng.ocamlPackages_5_3;
version = "3.1";
src = pkgs.fetchFromGitLab {
domain = "gitlab.inria.fr";
owner = "belenios";
repo = "belenios";
rev = version;
hash = "sha256-Mrx6AQakeBg6IeqNyDUZ5j6KaUGOh1AUfrLIxvDI45M=";
};
in
pkgs.stdenvNoCC.mkDerivation rec {
name = "belenios";
inherit version;
belenios = ocamlPackages.buildDunePackage {
pname = "belenios";
inherit version src;
nativeBuildInputs = with ocamlPackages; [
odoc
];
buildInputs = [
belenios-server
belenios-tool
];
};
belenios-lib = pkgs.callPackage ./lib.nix {
inherit
version
src
belenios-platform
ocamlPackages
;
};
belenios-platform = pkgs.callPackage ./platform.nix { inherit version src ocamlPackages; };
belenios-platform-js = pkgs.callPackage ./platform-js.nix {
inherit
version
src
ocamlPackages
belenios-platform
;
};
belenios-platform-native = pkgs.callPackage ./platform-native.nix {
inherit
version
src
ocamlPackages
belenios-platform
;
};
belenios-server = pkgs.callPackage ./server.nix {
inherit
version
src
ocamlPackages
belenios-lib
belenios-platform-native
belenios-platform-js
;
};
belenios-tool = pkgs.callPackage ./tool.nix {
inherit
version
src
ocamlPackages
belenios-lib
belenios-platform-native
;
};
}

View File

@ -0,0 +1,33 @@
{
version,
src,
belenios-platform,
ocamlPackages,
}:
ocamlPackages.buildDunePackage {
pname = "belenios-lib";
inherit version src;
nativeBuildInputs = with ocamlPackages; [
atdgen
];
buildInputs = with ocamlPackages; [
hex
digestif
biniou
];
propagatedBuildInputs = [
belenios-platform
]
++ (with ocamlPackages; [
atdgen-runtime
base64
ocaml_gettext
re
uri
yojson
]);
}

View File

@ -0,0 +1,13 @@
diff --git a/src/web/server/common/dune b/src/web/server/common/dune
index 3324b582..50cf6c46 100644
--- a/src/web/server/common/dune
+++ b/src/web/server/common/dune
@@ -15,7 +15,7 @@
gettext.base
gettext.extension
gettext-camomile
- netstring)
+ sendmail)
(modules_without_implementation
web_i18n_sig
web_services_sig

1715
pkgs/belenios/package-lock.json generated 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
{
version,
src,
belenios-platform,
ocamlPackages,
}:
ocamlPackages.buildDunePackage {
pname = "belenios-platform-js";
inherit version src;
nativeBuildInputs = with ocamlPackages; [
odoc
];
buildInputs = with ocamlPackages; [
belenios-platform
lwt
js_of_ocaml
js_of_ocaml-ppx
digestif
hex
];
}

View File

@ -0,0 +1,27 @@
{
version,
src,
belenios-platform,
ocamlPackages,
libsodium,
}:
ocamlPackages.buildDunePackage {
pname = "belenios-platform-native";
inherit version src;
nativeBuildInputs = with ocamlPackages; [
odoc
];
buildInputs = [
belenios-platform
libsodium
]
++ (with ocamlPackages; [
lwt
cryptokit
digestif
zarith
]);
}

View File

@ -0,0 +1,14 @@
{
version,
src,
ocamlPackages,
}:
ocamlPackages.buildDunePackage {
pname = "belenios-platform";
inherit version src;
propagatedBuildInputs = with ocamlPackages; [
lwt
];
}

View File

@ -0,0 +1,55 @@
{
version,
src,
belenios-lib,
belenios-platform-native,
belenios-platform-js,
ocamlPackages,
}:
ocamlPackages.buildDunePackage {
pname = "belenios-server";
inherit version src;
nativeBuildInputs = with ocamlPackages; [
atdgen
js_of_ocaml-compiler
menhir
ocaml_gettext
];
patches = [ ./netstring.patch ];
buildInputs = [
# belenios-lib
# belenios-platform-native
belenios-platform-js
]
++ (with ocamlPackages; [
# calendar
# csv
eliom
gettext-camomile
# lwt
# ocamlnet
ocsipersist
ocsipersist-lib
ocsipersist-sqlite-config
ocsigen_server
ocaml_gettext
xml-light
tyxml
markup
sendmail
]);
propagatedBuildInputs = [
belenios-lib
belenios-platform-native
]
++ (with ocamlPackages; [
calendar
lwt
xml-light
]);
}

View File

@ -0,0 +1,155 @@
{
lib,
config,
pkgs,
...
}:
let
cfg = config.services.belenios;
configFile = pkgs.writeText "belenios-server.conf" cfg.config;
inherit (lib) mkEnableOption mkOption mkIf;
in
{
options.services.belenios = {
enable = mkEnableOption "Whether to enable the Belenios Web server.";
# package = mkPackageOption pkgs "belenios" {};
config = mkOption {
type = lib.types.str;
description = ''
The Belenios Web server configuration.
See
<https://gitlab.inria.fr/belenios/belenios/-/blob/stable/doc/web.md>
for documentation.
'';
example = ''
<!-- -*- Mode: Xml -*- -->
<ocsigen>
<server>
<port>127.0.0.1:8001</port>
<mimefile>_SHAREDIR_/mime.types</mimefile>
<logdir>_VARDIR_/log</logdir>
<datadir>_VARDIR_/lib</datadir>
<uploaddir>_VARDIR_/upload</uploaddir>
<!--
The following limits are there to avoid flooding the server.
<maxuploadfilesize> might need to be increased for handling large
elections.
<maxconnected> is related to the number of simultaneous voters
visiting the server.
-->
<maxuploadfilesize>5120kB</maxuploadfilesize>
<maxconnected>500</maxconnected>
<commandpipe>_RUNDIR_/ocsigenserver_command</commandpipe>
<charset>utf-8</charset>
<extension name="staticmod"/>
<extension name="redirectmod"/>
<extension name="ocsipersist">
<database file="_VARDIR_/lib/ocsidb"/>
</extension>
<extension name="eliom"/>
<host charset="utf-8" hostfilter="*" defaulthostname="localhost">
<!-- <redirect suburl="^$" dest="http://www.example.org"/> -->
<site path="static" charset="utf-8">
<static dir="_SHAREDIR_/static" cache="0"/>
</site>
<eliom name="belenios">
<public-url prefix="http://127.0.0.1:8001"/>
<!-- Domain name used in Message-ID -->
<domain name="belenios.example.org"/>
<!--
The following can be adjusted to the capacity of your system.
If <maxrequestbodysizeinmemory> is too small, large elections
might fail, in particular with so-called alternative questions
with many voters.
<maxmailsatonce> depends heavily on how sending emails is
handled by your system.
-->
<maxrequestbodysizeinmemory value="1048576"/>
<maxmailsatonce value="1000"/>
<tos uri="http://www.example.org/terms-of-service.html"/>
<!-- <contact uri="mailto:contact@example.org"/> -->
<server mail="noreply@example.org" return-path="bounces@example.org" name="Belenios public server"/>
<auth-export name="builtin-password"/>
<auth-export name="builtin-cas"/>
<auth-export name="demo"><dummy/></auth-export> <!-- DEMO -->
<auth-export name="email"><email/></auth-export> <!-- DEMO -->
<auth name="demo"><dummy allowlist="demo_allowlist"/></auth> <!-- DEMO -->
<auth name="local"><password db="local_passwords"/></auth> <!-- DEMO -->
<auth name="public"><password db="public_passwords" allowsignups="true"/></auth>
<auth name="email"><email/></auth> <!-- DEMO -->
<auth name="captcha"><email use_captcha="true"/></auth> <!-- DEMO -->
<!-- <auth name="google"><oidc server="https://accounts.google.com" client_id="client-id" client_secret="client-secret"/></auth> -->
<source file="_SHAREDIR_/belenios.tar.gz"/>
<logo file="_SHAREDIR_/static/placeholder.png" mime-type="image/png"/>
<favicon file="_VARDIR_/favicon.ico" mime-type="image/png"/>
<sealing file="demo/sealing.txt" mime-type="text/plain"/>
<default-group group="Ed25519"/>
<nh-group group="Ed25519"/>
<share dir="_SHAREDIR_"/>
<storage backend="filesystem">
<uuid length="14"/>
<spool dir="_VARDIR_/spool"/>
<accounts dir="_VARDIR_/accounts"/>
<map from="demo_allowlist" to="demo/dummy_logins.txt"/>
<map from="local_passwords" to="demo/password_db.csv"/>
<map from="public_passwords" to="_VARDIR_/password_db.csv"/>
</storage>
<admin-home file="_VARDIR_/admin-home.html"/>
<success-snippet file="_VARDIR_/success-snippet.html"/>
<warning file="_VARDIR_/warning.html"/>
<footer file="_VARDIR_/footer.html"/>
<!-- <deny-newelection/> -->
<!--
Uncomment the following line to disable revoting. Note that
the ability to revote is important as a (light) measure
against coercion.
-->
<!-- <deny-revote/> -->
</eliom>
</host>
</server>
</ocsigen>
'';
};
};
config = mkIf cfg.enable {
users.users.belenios = {
description = "Belenios Web server service user";
isSystemUser = true;
group = "belenios";
};
users.groups.belenios = { };
systemd.services.belenios = {
description = "Belenios Web server service";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${pkgs.local.belenios-server}/bin/belenios-server -c ${configFile}";
Restart = "always";
User = "belenios";
};
};
};
}

View File

@ -0,0 +1,30 @@
{
version,
src,
belenios-lib,
belenios-platform-native,
libsodium,
ocamlPackages,
}:
ocamlPackages.buildDunePackage {
pname = "belenios-tool";
inherit version src;
buildInputs = [
belenios-lib
# belenios-platform
belenios-platform-native
libsodium
]
++ (with ocamlPackages; [
cmdliner
cryptokit
hex
]);
propagatedBuildInputs = with ocamlPackages; [
lwt
cohttp-lwt-unix
];
}

14
pkgs/default.nix 100644
View File

@ -0,0 +1,14 @@
{ ... }:
{
imports = [
./services.nix
];
# Import local packages
nixpkgs.overlays = [
(final: prev: {
local = import ./packages.nix { pkgs = final; };
})
];
}

59
pkgs/flake.lock 100644
View File

@ -0,0 +1,59 @@
{
"nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1772408722,
"narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
"type": "github"
},
"original": {
"id": "flake-parts",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1774244481,
"narHash": "sha256-4XfMXU0DjN83o6HWZoKG9PegCvKvIhNUnRUI19vzTcQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4590696c8693fea477850fe379a01544293ca4e2",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-25.11",
"type": "indirect"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1772328832,
"narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

52
pkgs/flake.nix 100644
View File

@ -0,0 +1,52 @@
{
inputs = {
nixpkgs.url = "nixpkgs/nixos-25.11";
};
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "x86_64-linux" ];
perSystem =
{ pkgs, ... }:
rec {
devShells.default = pkgs.mkShell {
packages = [ ];
};
packages =
let
ocamlPackages = pkgs.ocaml-ng.ocamlPackages_5_2;
in
rec {
belenios = pkgs.callPackage ./belenios { inherit ocamlPackages belenios-server belenios-tool; };
belenios-lib = pkgs.callPackage ./belenios/lib.nix {
inherit belenios ocamlPackages belenios-platform;
};
belenios-tool = pkgs.callPackage ./belenios/tool.nix {
inherit
belenios
ocamlPackages
belenios-lib
belenios-platform-native
;
};
belenios-server = pkgs.callPackage ./belenios/server.nix {
inherit
belenios
ocamlPackages
belenios-lib
belenios-platform-native
belenios-platform-js
;
};
belenios-platform = pkgs.callPackage ./belenios/platform.nix { inherit belenios ocamlPackages; };
belenios-platform-native = pkgs.callPackage ./belenios/platform-native.nix {
inherit belenios ocamlPackages belenios-platform;
};
belenios-platform-js = pkgs.callPackage ./belenios/platform-js.nix {
inherit belenios ocamlPackages belenios-platform;
};
};
};
};
}

View File

@ -0,0 +1,5 @@
{ pkgs, ... }:
{
belenios = pkgs.callPackage ./belenios { inherit pkgs; };
}

View File

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./belenios/services.nix
];
}