{ lib, pkgs, config, nixpkgsRaw, etherpad-lite, ... }:
let
env = config.myEnv.tools.etherpad-lite;
cfg = config.myServices.websites.tools.etherpad-lite;
# Make sure we’re not rebuilding whole libreoffice just because of a
# dependency
libreoffice = nixpkgsRaw.libreoffice-fresh;
ecfg = config.services.etherpad-lite;
in {
options.myServices.websites.tools.etherpad-lite = {
enable = lib.mkEnableOption "enable etherpad's website";
};
config = lib.mkIf cfg.enable {
myServices.dns.zones."immae.eu".subdomains.ether =
with config.myServices.dns.helpers; ips servers.eldiron.ips.main;
myServices.chatonsProperties.services.etherpad = {
file.datetime = "2021-01-04T00:01:00";
service = {
name = "Etherpad";
description = "Éditeur de texte collaboratif en temps réel. on peut y écrire simultanément.";
website = "https://ether.immae.eu";
logo = "https://ether.immae.eu/favicon.ico";
status.level = "OK";
status.description = "OK";
registration."" = ["NONE" "MEMBER" "CLIENT"];
registration.load = "OPEN";
install.type = "PACKAGE";
};
software = {
name = "Etherpad";
website = "https://etherpad.org/";
license.url = "https://github.com/ether/etherpad-lite/blob/develop/LICENSE";
license.name = "Apache License Version 2.0";
version = ecfg.package.version;
source.url = "https://github.com/ether/etherpad-lite";
modules = ecfg.package.moduleNames;
};
};
secrets.keys = {
"webapps/tools-etherpad-apikey" = {
permissions = "0400";
text = env.api_key;
};
"webapps/tools-etherpad-sessionkey" = {
permissions = "0400";
text = env.session_key;
};
"webapps/tools-etherpad" = {
permissions = "0400";
keyDependencies = [ libreoffice ];
text = ''
{
"title": "Etherpad",
"favicon": "favicon.ico",
"skinName": "colibris",
"skinVariants": "dark-toolbar light-background super-light-editor full-width-editor",
"ip": "",
"port" : "${ecfg.sockets.node}",
"showSettingsInAdminPage" : false,
"dbType" : "postgres",
"dbSettings" : {
"user" : "${env.postgresql.user}",
"host" : "${env.postgresql.socket}",
"password": "${env.postgresql.password}",
"database": "${env.postgresql.database}",
"charset" : "utf8mb4"
},
"defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n",
"padOptions": {
"noColors": false,
"showControls": true,
"showChat": true,
"showLineNumbers": true,
"useMonospaceFont": false,
"userName": false,
"userColor": false,
"rtl": false,
"alwaysShowChat": false,
"chatAndUsers": false,
"lang": "fr"
},
"suppressErrorsInPadText" : false,
"requireSession" : false,
"editOnly" : false,
"sessionNoPassword" : false,
"minify" : false,
"maxAge" : 21600,
"abiword" : null,
"soffice" : "${libreoffice}/bin/soffice",
"tidyHtml" : "",
"allowUnknownFileEnds" : true,
"requireAuthentication" : false,
"requireAuthorization" : false,
"trustProxy" : true,
"disableIPlogging" : false,
"automaticReconnectionTimeout" : 0,
"scrollWhenFocusLineIsOutOfViewport": {
"percentage": {
"editionAboveViewport": 0,
"editionBelowViewport": 0
},
"duration": 0,
"scrollWhenCaretIsInTheLastLineOfViewport": false,
"percentageToScrollWhenUserPressesArrowUp": 0
},
"users": {
"admin": {
"password": "${env.adminPassword}",
"is_admin": true
},
"ldapauth": {
"hash": "invalid",
"url": "ldaps://${env.ldap.host}",
"accountBase": "${env.ldap.base}",
"accountPattern": "${env.ldap.filter}",
"displayNameAttribute": "cn",
"searchDN": "${env.ldap.dn}",
"searchPWD": "${env.ldap.password}",
"groupSearchBase": "${env.ldap.base}",
"groupAttribute": "member",
"groupAttributeIsDN": true,
"searchScope": "sub",
"groupSearch": "${env.ldap.group_filter}",
"anonymousReadonly": false
}
},
"ep_mypads": {
"warning": "This hash is stored in database, changing anything here will not have any consequence",
"ldap": {
"url": "ldaps://${env.ldap.host}",
"bindDN": "${env.ldap.dn}",
"bindCredentials": "${env.ldap.password}",
"searchBase": "${env.ldap.base}",
"searchFilter": "${env.ldap.filter}",
"properties": {
"login": "uid",
"email": "mail",
"firstname": "givenName",
"lastname": "sn"
},
"defaultLang": "fr"
}
},
"ep_comments_page": {
"displayCommentAsIcon": true,
"highlightSelectedText": true
},
"socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"],
"loadTest": false,
"indentationOnNewLine": false,
"toolbar": {
"left": [
["bold", "italic", "underline", "strikethrough"],
["orderedlist", "unorderedlist", "indent", "outdent"],
["undo", "redo"],
["clearauthorship"]
],
"right": [
["importexport", "timeslider", "savedrevision"],
["settings", "embed"],
["showusers"]
],
"timeslider": [
["timeslider_export", "timeslider_returnToPad"]
]
},
"loglevel": "INFO",
"logconfig" : { "appenders": [ { "type": "console" } ] }
}
'';
};
};
services.etherpad-lite = {
enable = true;
package = etherpad-lite.withModules (p: [
p.ep_align p.ep_bookmark p.ep_colors p.ep_comments_page
p.ep_cursortrace p.ep_delete_empty_pads p.ep_embedmedia
p.ep_font_size p.ep_headings2 p.ep_immae_buttons p.ep_ldapauth
p.ep_line_height p.ep_markdown p.ep_mypads p.ep_page_view
p.ep_previewimages p.ep_ruler p.ep_scrollto
p.ep_set_title_on_pad p.ep_subscript_and_superscript
p.ep_timesliderdiff
]);
modules = [];
sessionKeyFile = config.secrets.fullPaths."webapps/tools-etherpad-sessionkey";
apiKeyFile = config.secrets.fullPaths."webapps/tools-etherpad-apikey";
configFile = config.secrets.fullPaths."webapps/tools-etherpad";
};
systemd.services.etherpad-lite.serviceConfig.SupplementaryGroups = "keys";
systemd.services.etherpad-lite-cleanup.serviceConfig.SupplementaryGroups = "keys";
# Needed so that they get in the closure
systemd.services.etherpad-lite.path = [ libreoffice pkgs.html-tidy ];
services.filesWatcher.etherpad-lite = {
restart = true;
paths = [ ecfg.sessionKeyFile ecfg.apiKeyFile ecfg.configFile ];
};
services.websites.env.tools.modules = [
"headers" "proxy" "proxy_http" "proxy_wstunnel"
];
security.acme.certs.eldiron.extraDomainNames = [ "ether.immae.eu" ];
services.websites.env.tools.vhostConfs.etherpad-lite = {
certName = "eldiron";
hosts = [ "ether.immae.eu" ];
root = null;
extraConfig = [ ''
Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains;"
RequestHeader set X-Forwarded-Proto "https"
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) unix://${ecfg.sockets.node}|ws://ether.immae.eu/$1 [P,NE,QSA,L]
<IfModule mod_proxy.c>
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / unix://${ecfg.sockets.node}|http://ether.immae.eu/
ProxyPassReverse / unix://${ecfg.sockets.node}|http://ether.immae.eu/
<Proxy *>
Options FollowSymLinks MultiViews
AllowOverride None
Require all granted
</Proxy>
</IfModule>
'' ];
};
myServices.monitoring.fromMasterActivatedPlugins = [ "http" ];
myServices.monitoring.fromMasterObjects.service = [
{
service_description = "etherpad website is running on ether.immae.eu";
host_name = config.hostEnv.fqdn;
use = "external-web-service";
check_command = ["check_https" "ether.immae.eu" "/" "<title>Etherpad"];
servicegroups = "webstatus-webapps";
_webstatus_name = "Etherpad";
_webstatus_url = "https://ether.immae.eu/";
}
];
};
}