forked from M-Labs/it-infra
nixbld: RT working, no mail
This commit is contained in:
parent
ef3544f8f3
commit
a97302a80a
|
@ -17,6 +17,7 @@ in
|
|||
./hardware-configuration.nix
|
||||
./backup-module.nix
|
||||
./github-backup-module.nix
|
||||
./rt.nix
|
||||
];
|
||||
|
||||
boot.loader.grub.enable = true;
|
||||
|
@ -685,6 +686,14 @@ in
|
|||
useACMEHost = "nixbld.m-labs.hk";
|
||||
root = "/var/www/perso";
|
||||
};
|
||||
"rt.m-labs.hk" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "nixbld.m-labs.hk";
|
||||
locations."/".proxyPass = "http://127.0.0.1:4201";
|
||||
extraConfig = ''
|
||||
client_max_body_size 100M;
|
||||
'';
|
||||
};
|
||||
"nmigen.org" = {
|
||||
addSSL = true;
|
||||
useACMEHost = "nixbld.m-labs.hk";
|
||||
|
@ -737,5 +746,15 @@ in
|
|||
};
|
||||
services.jitsi-videobridge.openFirewall = true;
|
||||
|
||||
services.rt = {
|
||||
enable = true;
|
||||
organization = "M-Labs";
|
||||
domain = "rt.m-labs.hk";
|
||||
rtName = "Helpdesk";
|
||||
ownerEmail = "sb" + "@m-labs.hk";
|
||||
commentAddress = "helpdesk" + "@m-labs.hk";
|
||||
correspondAddress = "helpdesk" + "@m-labs.hk";
|
||||
};
|
||||
|
||||
system.stateVersion = "21.05";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,311 @@
|
|||
# based on https://gist.github.com/ajs124/ff04ab14435908d914cf5cedbc56a52e
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.rt;
|
||||
|
||||
configFile = pkgs.writeTextFile {
|
||||
name = "RT_SiteConfig.pm";
|
||||
text = ''
|
||||
use utf8;
|
||||
|
||||
# System (Base configuration)
|
||||
Set($rtname, '${cfg.rtName}'); # Changing this will break responses to existing tickets
|
||||
Set($Organization, '${cfg.organization}'); # Changing this will break all existing tickets
|
||||
Set($CorrespondAddress, '${cfg.correspondAddress}');
|
||||
Set($CommentAddress, '${cfg.commentAddress}');
|
||||
Set($WebDomain, '${cfg.domain}');
|
||||
Set($Timezone, '${cfg.timeZone}');
|
||||
|
||||
Set($DatabaseType, 'Pg');
|
||||
Set($DatabaseHost, 'localhost');
|
||||
Set($DatabaseUser, 'rt_user');
|
||||
Set($DatabaseName, 'rt5');
|
||||
# Read database password from file
|
||||
open my $fh, '<', '${cfg.dbPasswordFile}' or die 'Can\'t open file $!';
|
||||
my $dbpw = do { local $/; <$fh> };
|
||||
$dbpw =~ s/^\s+|\s+$//g;
|
||||
Set($DatabasePassword, $dbpw);
|
||||
|
||||
# System (Logging)
|
||||
Set($LogToSTDERR, undef); # Don't log twice
|
||||
|
||||
# System (Incoming mail gateway)
|
||||
Set($OwnerEmail, '${cfg.ownerEmail}');
|
||||
Set($MaxAttachmentSize, 15360000);
|
||||
Set($CheckMoreMSMailHeaders, 1);
|
||||
Set($LoopsToRTOwner, 0);
|
||||
|
||||
# System (Outgoing mail)
|
||||
Set($SetOutgoingMailFrom, '${cfg.ownerEmail}');
|
||||
|
||||
# System (Sendmail configuration)
|
||||
Set($SendmailPath, '${cfg.sendmailPath}');
|
||||
Set($SendmailArguments, '${concatStringsSep " " cfg.sendmailArguments}');
|
||||
|
||||
# System (Application logic)
|
||||
Set($ParseNewMessageForTicketCcs, 1);
|
||||
|
||||
# System (Extra Security)
|
||||
Set($RestrictLoginReferrer, 1);
|
||||
|
||||
# System (Date and time handling)
|
||||
Set($DefaultTimeUnitsToHours, 1);
|
||||
Set($TimeInICal, 1);
|
||||
Set($DateTimeFormat, 'RFC2822');
|
||||
|
||||
# System (Authorization and user configuration)
|
||||
Set($AutoLogoff, 262800); # 6 months
|
||||
Set($WebSecureCookies, 1);
|
||||
|
||||
# Web Interface (Base configuration)
|
||||
Set($DefaultQueue, 'General'); # Defaults to the first from the alphabet
|
||||
Set($RememberDefaultQueue, 1);
|
||||
Set($CanonicalizeRedirectURLs, 1);
|
||||
Set($CanonicalizeURLsInFeeds, 1);
|
||||
Set($WebBaseURL, '${cfg.baseUrl}');
|
||||
Set($LogoLinkURL, '${cfg.baseUrl}');
|
||||
|
||||
# Web Interface (Home page)
|
||||
Set($DefaultSummaryRows, 50);
|
||||
|
||||
# Web Interface (Ticket search)
|
||||
Set($DefaultSearchResultOrder, 'DESC'); # Display newer tickets first
|
||||
Set($SearchResultsAutoRedirect, 1); # Don't show result list when there is only one match
|
||||
Set(%FullTextSearch,
|
||||
Enable => 1,
|
||||
Indexed => 1,
|
||||
Column => 'ContentIndex',
|
||||
Table => 'AttachmentsIndex',
|
||||
);
|
||||
|
||||
# Web Interface (Ticket options)
|
||||
Set($ShowMoreAboutPrivilegedUsers, 1);
|
||||
Set($MoreAboutRequestorGroupsLimit, undef);
|
||||
Set($HideUnsetFieldsOnDisplay, 1);
|
||||
|
||||
# Web Interface (Articles)
|
||||
Set($ArticleOnTicketCreate, 0);
|
||||
|
||||
# Web Interface (Message box properties)
|
||||
Set($MessageBoxRichText, 0);
|
||||
Set($MessageBoxIncludeSignatureOnComment, 0);
|
||||
|
||||
# Web Interface (Transaction display)
|
||||
Set($MaxInlineBody, 0);
|
||||
|
||||
# Web Interface (Administrative interface)
|
||||
Set($ShowRTPortal, 0);
|
||||
Set($ShowEditSsytemConfig, 0);
|
||||
|
||||
# Features (External storage)
|
||||
Set(%ExternalStorage,
|
||||
Type => 'Disk',
|
||||
Path => '/var/lib/rt/attachments',
|
||||
);
|
||||
Set($ExternalStorageCutoffSize, 0);
|
||||
|
||||
# Features (Cryptography)
|
||||
Set(%Crypt, RejectOnMissingPrivateKey => 0, RejectOnBadData => 0, AllowEncryptDataInDB => 0);
|
||||
Set(%SMIME, Enable => 1, Keyring => '${pkgs.cacert}/etc/ssl/certs/');
|
||||
Set(%GnuPG, Enable => 1);
|
||||
Set(%GnuPGOptions,
|
||||
'keyserver' => 'hkp://keys.openpgp.org',
|
||||
'always-trust' => undef,
|
||||
'auto-key-locate' => 'keyserver',
|
||||
'keyserver-options' => 'auto-key-retrieve'
|
||||
);
|
||||
|
||||
${cfg.extraConfig}
|
||||
|
||||
1;
|
||||
'';
|
||||
checkPhase = ''
|
||||
${pkgs.perl}/bin/perl -c $out
|
||||
'';
|
||||
};
|
||||
in {
|
||||
options.services.rt = with types; {
|
||||
|
||||
enable = mkEnableOption "rt system";
|
||||
|
||||
package = mkOption {
|
||||
description = "Package to use";
|
||||
default = pkgs.rt;
|
||||
defaultText = "pkgs.rt";
|
||||
type = package;
|
||||
};
|
||||
|
||||
baseUrl = mkOption {
|
||||
description = "Base URL for web interface";
|
||||
default = "https://${cfg.domain}";
|
||||
defaultText = "https://\${cfg.domain}";
|
||||
type = str;
|
||||
};
|
||||
|
||||
commentAddress = mkOption {
|
||||
description = "Default address from/to which comments are sent";
|
||||
type = str;
|
||||
};
|
||||
|
||||
correspondAddress = mkOption {
|
||||
description = "Default address from/to which correspondences are sent";
|
||||
type = str;
|
||||
};
|
||||
|
||||
dbPasswordFile = mkOption {
|
||||
description = "File containing the database password";
|
||||
type = str;
|
||||
default = "/etc/nixos/secret/rtpasswd";
|
||||
internal = true;
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
description = "Which domain RT is running on";
|
||||
type = str;
|
||||
};
|
||||
|
||||
ownerEmail = mkOption {
|
||||
description = "Address of a human who manages RT. RT will send errors generated by the mail gateway to this address; it will also be displayed as the contact person on the RT's login page.";
|
||||
type = str;
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
description = "Which port rt-server should listen on";
|
||||
type = port;
|
||||
default = 4201;
|
||||
};
|
||||
|
||||
sendmailPath = mkOption {
|
||||
description = "Sendmail binary used to send... mail";
|
||||
default = "${pkgs.msmtp}/bin/sendmail";
|
||||
defaultText = "\${pkgs.msmtp}/bin/sendmail";
|
||||
type = str;
|
||||
};
|
||||
|
||||
sendmailArguments = mkOption {
|
||||
description = "Arguments to call sendmailPath with";
|
||||
default = [ ];
|
||||
type = listOf (oneOf [ str path ]);
|
||||
};
|
||||
|
||||
timeZone = mkOption {
|
||||
description = "Used to convert times entered by users into GMT, as they are stored in the database, and back again; users can override this";
|
||||
type = str;
|
||||
default = config.time.timeZone;
|
||||
defaultText = "[time.timeZone]";
|
||||
};
|
||||
|
||||
rtName = mkOption {
|
||||
description = "Name of this RT instance";
|
||||
type = str;
|
||||
};
|
||||
|
||||
organization = mkOption {
|
||||
description = "Name of the organization of this instance";
|
||||
type = str;
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
description = "Verbatim config to append to generated on";
|
||||
type = lines;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
config = let
|
||||
components = [
|
||||
"rt-clean-sessions"
|
||||
"rt-email-dashboards"
|
||||
"rt-email-digest-daily"
|
||||
"rt-email-digest-weekly"
|
||||
"rt-externalize-attachments"
|
||||
"rt-fulltext-indexer"
|
||||
"rt-validator"
|
||||
];
|
||||
|
||||
mkTimer = name: {
|
||||
"${name}" = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.Unit = [ "${name}.service" ];
|
||||
};
|
||||
};
|
||||
|
||||
mkService = name: extraArgs: {
|
||||
"${name}" = {
|
||||
stopIfChanged = false;
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = if extraArgs == ""
|
||||
then "${cfg.package}/bin/${name}"
|
||||
else mkForce "${cfg.package}/bin/${name} ${extraArgs}";
|
||||
User = "rt";
|
||||
Group = "rt";
|
||||
|
||||
PrivateNetwork = false;
|
||||
MemoryDenyWriteExecute = false;
|
||||
|
||||
ReadOnlyPaths = [ cfg.dbPasswordFile ];
|
||||
};
|
||||
|
||||
environment = {
|
||||
RT_SITE_CONFIG = configFile;
|
||||
};
|
||||
|
||||
path = with pkgs; [
|
||||
w3m
|
||||
];
|
||||
};
|
||||
};
|
||||
in (mkIf cfg.enable {
|
||||
systemd.services = mkMerge ((map (c: mkService c "") components) ++ [
|
||||
(mkService "rt-server" "--port ${toString cfg.port} --server Starman")
|
||||
(mkService "rt-clean-sessions" "--skip-user")
|
||||
(mkService "rt-fulltext-indexer" "--limit 500000")
|
||||
(mkService "rt-validator" "--check")
|
||||
{
|
||||
rt-server = {
|
||||
serviceConfig = {
|
||||
StateDirectory = [ "rt/" "rt/attachments/" "rt/shredder/" "rt/smime/" ];
|
||||
RuntimeDirectory = [ "rt/" "rt/mason_data/" ];
|
||||
LogsDirectory = "rt/";
|
||||
};
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
}
|
||||
{
|
||||
rt-externalize-attachments = {
|
||||
serviceConfig.StateDirectory = "rt/attachments/";
|
||||
};
|
||||
}
|
||||
|
||||
{ rt-email-digest-daily.serviceConfig.ExecStart = mkForce "${cfg.package}/bin/rt-email-digest -m daily"; }
|
||||
{ rt-email-digest-weekly.serviceConfig.ExecStart = mkForce "${cfg.package}/bin/rt-email-digest -m weekly"; }
|
||||
]);
|
||||
|
||||
systemd.timers = mkMerge ((map mkTimer components) ++ [
|
||||
{
|
||||
rt-clean-sessions.timerConfig.OnCalendar = "daily";
|
||||
rt-email-dashboards.timerConfig.OnCalendar = "hourly";
|
||||
rt-email-digest-daily.timerConfig.OnCalendar = "daily";
|
||||
rt-email-digest-weekly.timerConfig.OnCalendar = "weekly";
|
||||
rt-externalize-attachments.timerConfig.OnCalendar = "01:00";
|
||||
rt-fulltext-indexer.timerConfig.OnCalendar = "02:00";
|
||||
rt-validator.timerConfig.OnCalendar = "*-*-01 03:00:00";
|
||||
}
|
||||
]);
|
||||
|
||||
users.users.rt = {
|
||||
isSystemUser = true;
|
||||
};
|
||||
users.groups.rt = {};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/secrets/rt 0500 rt rt -"
|
||||
"d /var/lib/rt/gpg 0700 rt rt -"
|
||||
"z ${cfg.dbPasswordFile} 0400 rt rt -"
|
||||
];
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue