Skip to content

Instantly share code, notes, and snippets.

@mweinelt
Created May 27, 2025 11:45
Show Gist options
  • Select an option

  • Save mweinelt/b4c6821a9d3a9cfa3edffa13d4c7b559 to your computer and use it in GitHub Desktop.

Select an option

Save mweinelt/b4c6821a9d3a9cfa3edffa13d4c7b559 to your computer and use it in GitHub Desktop.
Dovecot Config Rendering from Nix Attribute
let
pkgs = import <nixpkgs> { };
lib = pkgs.lib;
pr388463 = import (pkgs.fetchFromGitHub {
owner = "jappie3";
repo = "nixpkgs";
rev = "03a9aef5bf5584b96f6e9460861b97da8c546dfd";
hash = "sha256-/2SZpYuRbpNaM84MNstorwSYgrobXp4sGK5O/8TU9As=";
}) { };
package = pr388463.dovecot_2_4;
inherit (lib)
all
concatStringsSep
mapAttrsToList
isAttrs
isList
isBool
;
renderValue =
value:
if isBool value then
if value then "yes" else "no"
else if isList value then
concatStringsSep " " (map toString value)
else
toString value;
renderSection = sectionType: sectionName: attrs:
let
lines = mapAttrsToList renderAttr attrs;
header =
if sectionName != null then
"${sectionType} ${sectionName} {"
else
"${sectionType} {";
in
"${header}\n${concatStringsSep "\n" (map (line: " ${line}") lines)}\n}";
renderAttr = name: value:
if isAttrs value then
let
isNamedBlock = all isAttrs (lib.attrValues value);
in
if isNamedBlock then
concatStringsSep "\n" (
mapAttrsToList (subname: subval: renderSection name subname subval) value
)
else
renderSection name null value
else
"${name} = ${renderValue value}";
renderConfig = cfg:
"dovecot_config_version = ${package.version}\n" + concatStringsSep "\n" (mapAttrsToList renderAttr cfg);
verifyConfig = cfg: pkgs.runCommand "dovecot.conf" {
preferLocalBuild = true;
# TODO: remove || true to break on invalid configurations
} ''
${lib.getExe' package "doveconf"} -c ${pkgs.writeText "dovecot.raw.conf" (renderConfig cfg)} > $out || true
cat $out
'';
settings = {
ssl = false;
protocols = [ "imap" "pop3" ];
auth_policy = {
server_url = "example.com";
auth_policy_server_url = "example.com";
};
service."auth" = {
unix_listener."auth_master" = { };
};
passdb."oauth2" = {
mechanisms_filter = [ "plain" "login" ];
oauth2 = {
# inherit common oauth2 settings from the global scope
grant_url = "http://localhost:8000/token";
fields = {
host = "127.0.0.1";
proxy = true;
proxy_mech = "xoauth2";
pass = "%{passdb:token}";
};
};
};
};
in
verifyConfig settings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment