{ config, lib, pkgs, ... }: with lib; let cfg = config.services.breve; dataDir = "/var/lib/breve"; configFile = pkgs.writeText "breve.conf" '' hostname = "${cfg.hostname}" port = ${toString cfg.port} baseurl = "${cfg.baseUrl}" urltable = "${dataDir}/urls" tls { cert = "${cfg.certificate}" key = "${cfg.key}" } ''; in { options.services.breve = { enable = mkEnableOption '' Breve: a url shortner service. ''; openPorts = mkOption { type = types.bool; default = false; example = literalExample "true"; description = '' Open the default ports in the firewall: - TCP 443 (or specific port) for HTTPS - TCP 80 (or specific port) for HTTP->HTTPS redirect ''; }; user = mkOption { type = types.str; default = "breve"; description = '' Breve will run under this user (user will be created if it doesn't exist. This can be your user name). ''; }; hostname = mkOption { type = types.str; default = config.networking.hostName; description = '' Breve will bind and generate URLs accorting to this hostname. ''; }; baseUrl = mkOption { type = types.str; default = "https://localhost:3000/"; example = "https://example.com"; description = '' URL to reach the breve index page. Needed in case Breve is served by a reverse proxy on a different url. ''; }; port = mkOption { type = types.int; default = 443; example = 8080; description = '' Breve main interface will be listening on this port. ''; }; certificate = mkOption { type = types.path; default = "${dataDir}/breve.crt"; description = '' The TLS certificate that Breve will be using to encrypt traffic. ''; }; key = mkOption { type = types.path; default = "${dataDir}/breve.key"; description = '' The TLS key that Breve will be using to encrypt traffic. ''; }; certificateChain = mkOption { type = types.listOf types.path; default = []; description = '' List of paths to the TLS certificates chain. ''; }; }; config = mkIf cfg.enable { users.extraUsers."${cfg.user}" = { isSystemUser = true; description = "Breve daemon user"; }; networking.firewall = mkIf cfg.openPorts { allowedTCPPorts = [ cfg.port ] ++ optional (cfg.port == 443) 80; }; systemd.services.breve = { description = "breve: url shortner"; wants = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; environment.XDG_CONFIG_HOME = "${dataDir}/conf"; serviceConfig = { User = cfg.user; ExecStart = "${pkgs.haskellPackages.breve}/bin/breve"; Restart = "on-failure"; StateDirectory = "breve"; }; preStart = '' # link configuration mkdir -p ${dataDir}/conf if [ "$(realpath ${dataDir}/conf/breve)" != "${configFile}" ]; then rm -f ${dataDir}/conf/breve ln -s ${configFile} ${dataDir}/conf/breve fi ''; }; }; }