nixos-config/lib/fudo/chat.nix

221 lines
6.8 KiB
Nix

{ pkgs, lib, config, ... }:
with lib;
let cfg = config.fudo.chat;
in {
options.fudo.chat = {
enable = mkEnableOption "Enable chat server";
hostname = mkOption {
type = types.str;
description = "Hostname at which this chat server is accessible.";
example = "chat.mydomain.com";
};
site-name = mkOption {
type = types.str;
description = "The name of this chat server.";
example = "My Fancy Chat Site";
};
smtp-server = mkOption {
type = types.str;
description = "SMTP server to use for sending notification emails.";
example = "mail.my-site.com";
};
smtp-user = mkOption {
type = types.str;
description = "Username with which to connect to the SMTP server.";
};
smtp-password-file = mkOption {
type = types.str;
description =
"Path to a file containing the password to use while connecting to the SMTP server.";
};
state-directory = mkOption {
type = types.str;
description = "Path at which to store server state data.";
default = "/var/lib/mattermost";
};
database = mkOption {
type = (types.submodule {
options = {
name = mkOption {
type = types.str;
description = "Database name.";
};
hostname = mkOption {
type = types.str;
description = "Database host.";
};
user = mkOption {
type = types.str;
description = "Database user.";
};
password-file = mkOption {
type = types.str;
description = "Path to file containing database password.";
};
};
});
description = "Database configuration.";
example = {
name = "my_database";
hostname = "my.database.com";
user = "db_user";
password-file = /path/to/some/file.pw;
};
};
};
config = mkIf cfg.enable (let
pkg = pkgs.mattermost;
default-config = builtins.fromJSON (readFile "${pkg}/config/config.json");
modified-config = recursiveUpdate default-config {
ServiceSettings.SiteURL = "https://${cfg.hostname}";
ServiceSettings.ListenAddress = "127.0.0.1:8065";
TeamSettings.SiteName = cfg.site-name;
EmailSettings = {
RequireEmailVerification = true;
SMTPServer = cfg.smtp-server;
SMTPPort = 587;
EnableSMTPAuth = true;
SMTPUsername = cfg.smtp-user;
SMTPPassword = (fileContents cfg.smtp-password-file);
SendEmailNotifications = true;
ConnectionSecurity = "STARTTLS";
FeedbackEmail = "chat@fudo.org";
FeedbackName = "Admin";
};
EnableEmailInvitations = true;
SqlSettings.DriverName = "postgres";
SqlSettings.DataSource = "postgres://${cfg.database.user}:${
fileContents cfg.database.password-file
}@${cfg.database.hostname}:5432/${cfg.database.name}";
};
mattermost-config-file =
pkgs.writeText "mattermost-config.json" (builtins.toJSON modified-config);
mattermost-user = "mattermost";
mattermost-group = "mattermost";
in {
users = {
users = {
${mattermost-user} = {
isSystemUser = true;
group = mattermost-group;
};
};
groups = { ${mattermost-group} = { members = [ mattermost-user ]; }; };
};
system.activationScripts.mattermost = ''
mkdir -p ${cfg.state-directory}
'';
systemd.services.mattermost = {
description = "Mattermost Chat Server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
preStart = ''
mkdir -p ${cfg.state-directory}/config
cp ${mattermost-config-file} ${cfg.state-directory}/config/config.json
ln -sf ${pkg}/bin ${cfg.state-directory}
ln -sf ${pkg}/fonts ${cfg.state-directory}
ln -sf ${pkg}/i18n ${cfg.state-directory}
ln -sf ${pkg}/templates ${cfg.state-directory}
cp -uRL ${pkg}/client ${cfg.state-directory}
chown -R ${mattermost-user}:${mattermost-group} ${cfg.state-directory}
chmod u+w -R ${cfg.state-directory}/client
chmod o-rwx -R ${cfg.state-directory}
'';
serviceConfig = {
PermissionsStartOnly = true;
ExecStart = "${pkg}/bin/mattermost";
WorkingDirectory = cfg.state-directory;
Restart = "always";
RestartSec = "10";
LimitNOFILE = "49152";
User = mattermost-user;
Group = mattermost-group;
};
};
security.acme.certs.${cfg.hostname}.email = config.fudo.common.admin-email;
services.nginx = {
enable = true;
appendHttpConfig = ''
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:10m max_size=3g inactive=120m use_temp_path=off;
'';
virtualHosts = {
"${cfg.hostname}" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8065";
extraConfig = ''
client_max_body_size 50M;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
proxy_read_timeout 600s;
proxy_cache mattermost_cache;
proxy_cache_revalidate on;
proxy_cache_min_uses 2;
proxy_cache_use_stale timeout;
proxy_cache_lock on;
proxy_http_version 1.1;
'';
};
locations."~ /api/v[0-9]+/(users/)?websocket$" = {
proxyPass = "http://127.0.0.1:8065";
extraConfig = ''
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 50M;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
client_body_timeout 60;
send_timeout 300;
lingering_timeout 5;
proxy_connect_timeout 90;
proxy_send_timeout 300;
proxy_read_timeout 90s;
'';
};
};
};
};
});
}