···11+<chapter xmlns="http://docbook.org/ns/docbook"
22+ xmlns:xlink="http://www.w3.org/1999/xlink"
33+ xmlns:xi="http://www.w3.org/2001/XInclude"
44+ version="5.0"
55+ xml:id="module-services-sourcehut">
66+ <title>Sourcehut</title>
77+ <para>
88+ <link xlink:href="https://sr.ht.com/">Sourcehut</link> is an open-source,
99+ self-hostable software development platform. The server setup can be automated using
1010+ <link linkend="opt-services.sourcehut.enable">services.sourcehut</link>.
1111+ </para>
1212+1313+ <section xml:id="module-services-sourcehut-basic-usage">
1414+ <title>Basic usage</title>
1515+ <para>
1616+ Sourcehut is a Python and Go based set of applications.
1717+ <literal><link linkend="opt-services.sourcehut.enable">services.sourcehut</link></literal>
1818+ by default will use
1919+ <literal><link linkend="opt-services.nginx.enable">services.nginx</link></literal>,
2020+ <literal><link linkend="opt-services.nginx.enable">services.redis</link></literal>,
2121+ <literal><link linkend="opt-services.nginx.enable">services.cron</link></literal>,
2222+ and
2323+ <literal><link linkend="opt-services.postgresql.enable">services.postgresql</link></literal>.
2424+ </para>
2525+2626+ <para>
2727+ A very basic configuration may look like this:
2828+<programlisting>
2929+{ pkgs, ... }:
3030+let
3131+ fqdn =
3232+ let
3333+ join = hostName: domain: hostName + optionalString (domain != null) ".${domain}";
3434+ in join config.networking.hostName config.networking.domain;
3535+in {
3636+3737+ networking = {
3838+ <link linkend="opt-networking.hostName">hostName</link> = "srht";
3939+ <link linkend="opt-networking.domain">domain</link> = "tld";
4040+ <link linkend="opt-networking.firewall.allowedTCPPorts">firewall.allowedTCPPorts</link> = [ 22 80 443 ];
4141+ };
4242+4343+ services.sourcehut = {
4444+ <link linkend="opt-services.sourcehut.enable">enable</link> = true;
4545+ <link linkend="opt-services.sourcehut.originBase">originBase</link> = fqdn;
4646+ <link linkend="opt-services.sourcehut.services">services</link> = [ "meta" "man" "git" ];
4747+ <link linkend="opt-services.sourcehut.settings">settings</link> = {
4848+ "sr.ht" = {
4949+ environment = "production";
5050+ global-domain = fqdn;
5151+ origin = "https://${fqdn}";
5252+ # Produce keys with srht-keygen from <package>sourcehut.coresrht</package>.
5353+ network-key = "SECRET";
5454+ service-key = "SECRET";
5555+ };
5656+ webhooks.private-key= "SECRET";
5757+ };
5858+ };
5959+6060+ <link linkend="opt-security.acme.certs._name_.extraDomainNames">security.acme.certs."${fqdn}".extraDomainNames</link> = [
6161+ "meta.${fqdn}"
6262+ "man.${fqdn}"
6363+ "git.${fqdn}"
6464+ ];
6565+6666+ services.nginx = {
6767+ <link linkend="opt-services.nginx.enable">enable</link> = true;
6868+ # only recommendedProxySettings are strictly required, but the rest make sense as well.
6969+ <link linkend="opt-services.nginx.recommendedTlsSettings">recommendedTlsSettings</link> = true;
7070+ <link linkend="opt-services.nginx.recommendedOptimisation">recommendedOptimisation</link> = true;
7171+ <link linkend="opt-services.nginx.recommendedGzipSettings">recommendedGzipSettings</link> = true;
7272+ <link linkend="opt-services.nginx.recommendedProxySettings">recommendedProxySettings</link> = true;
7373+7474+ # Settings to setup what certificates are used for which endpoint.
7575+ <link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
7676+ <link linkend="opt-services.nginx.virtualHosts._name_.enableACME">"${fqdn}".enableACME</link> = true;
7777+ <link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">"meta.${fqdn}".useACMEHost</link> = fqdn:
7878+ <link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">"man.${fqdn}".useACMEHost</link> = fqdn:
7979+ <link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">"git.${fqdn}".useACMEHost</link> = fqdn:
8080+ };
8181+ };
8282+}
8383+</programlisting>
8484+ </para>
8585+8686+ <para>
8787+ The <literal>hostName</literal> option is used internally to configure the nginx
8888+ reverse-proxy. The <literal>settings</literal> attribute set is
8989+ used by the configuration generator and the result is placed in <literal>/etc/sr.ht/config.ini</literal>.
9090+ </para>
9191+ </section>
9292+9393+ <section xml:id="module-services-sourcehut-configuration">
9494+ <title>Configuration</title>
9595+9696+ <para>
9797+ All configuration parameters are also stored in
9898+ <literal>/etc/sr.ht/config.ini</literal> which is generated by
9999+ the module and linked from the store to ensure that all values from <literal>config.ini</literal>
100100+ can be modified by the module.
101101+ </para>
102102+103103+ </section>
104104+105105+ <section xml:id="module-services-sourcehut-httpd">
106106+ <title>Using an alternative webserver as reverse-proxy (e.g. <literal>httpd</literal>)</title>
107107+ <para>
108108+ By default, <package>nginx</package> is used as reverse-proxy for <package>sourcehut</package>.
109109+ However, it's possible to use e.g. <package>httpd</package> by explicitly disabling
110110+ <package>nginx</package> using <xref linkend="opt-services.nginx.enable" /> and fixing the
111111+ <literal>settings</literal>.
112112+ </para>
113113+</section>
114114+115115+</chapter>
+161
nixos/modules/services/misc/sourcehut/todo.nix
···11+{ config, lib, pkgs, ... }:
22+33+with lib;
44+let
55+ cfg = config.services.sourcehut;
66+ cfgIni = cfg.settings;
77+ scfg = cfg.todo;
88+ iniKey = "todo.sr.ht";
99+1010+ rcfg = config.services.redis;
1111+ drv = pkgs.sourcehut.todosrht;
1212+in
1313+{
1414+ options.services.sourcehut.todo = {
1515+ user = mkOption {
1616+ type = types.str;
1717+ default = "todosrht";
1818+ description = ''
1919+ User for todo.sr.ht.
2020+ '';
2121+ };
2222+2323+ port = mkOption {
2424+ type = types.port;
2525+ default = 5003;
2626+ description = ''
2727+ Port on which the "todo" module should listen.
2828+ '';
2929+ };
3030+3131+ database = mkOption {
3232+ type = types.str;
3333+ default = "todo.sr.ht";
3434+ description = ''
3535+ PostgreSQL database name for todo.sr.ht.
3636+ '';
3737+ };
3838+3939+ statePath = mkOption {
4040+ type = types.path;
4141+ default = "${cfg.statePath}/todosrht";
4242+ description = ''
4343+ State path for todo.sr.ht.
4444+ '';
4545+ };
4646+ };
4747+4848+ config = with scfg; lib.mkIf (cfg.enable && elem "todo" cfg.services) {
4949+ users = {
5050+ users = {
5151+ "${user}" = {
5252+ isSystemUser = true;
5353+ group = user;
5454+ extraGroups = [ "postfix" ];
5555+ description = "todo.sr.ht user";
5656+ };
5757+ };
5858+ groups = {
5959+ "${user}" = { };
6060+ };
6161+ };
6262+6363+ services.postgresql = {
6464+ authentication = ''
6565+ local ${database} ${user} trust
6666+ '';
6767+ ensureDatabases = [ database ];
6868+ ensureUsers = [
6969+ {
7070+ name = user;
7171+ ensurePermissions = { "DATABASE \"${database}\"" = "ALL PRIVILEGES"; };
7272+ }
7373+ ];
7474+ };
7575+7676+ systemd = {
7777+ tmpfiles.rules = [
7878+ "d ${statePath} 0750 ${user} ${user} -"
7979+ ];
8080+8181+ services = {
8282+ todosrht = import ./service.nix { inherit config pkgs lib; } scfg drv iniKey {
8383+ after = [ "postgresql.service" "network.target" ];
8484+ requires = [ "postgresql.service" ];
8585+ wantedBy = [ "multi-user.target" ];
8686+8787+ description = "todo.sr.ht website service";
8888+8989+ serviceConfig.ExecStart = "${cfg.python}/bin/gunicorn ${drv.pname}.app:app -b ${cfg.address}:${toString port}";
9090+ };
9191+9292+ todosrht-lmtp = {
9393+ after = [ "postgresql.service" "network.target" ];
9494+ bindsTo = [ "postgresql.service" ];
9595+ wantedBy = [ "multi-user.target" ];
9696+9797+ description = "todo.sr.ht process service";
9898+ serviceConfig = {
9999+ Type = "simple";
100100+ User = user;
101101+ Restart = "always";
102102+ ExecStart = "${cfg.python}/bin/todosrht-lmtp";
103103+ };
104104+ };
105105+106106+ todosrht-webhooks = {
107107+ after = [ "postgresql.service" "network.target" ];
108108+ requires = [ "postgresql.service" ];
109109+ wantedBy = [ "multi-user.target" ];
110110+111111+ description = "todo.sr.ht webhooks service";
112112+ serviceConfig = {
113113+ Type = "simple";
114114+ User = user;
115115+ Restart = "always";
116116+ ExecStart = "${cfg.python}/bin/celery -A ${drv.pname}.webhooks worker --loglevel=info";
117117+ };
118118+119119+ };
120120+ };
121121+ };
122122+123123+ services.sourcehut.settings = {
124124+ # URL todo.sr.ht is being served at (protocol://domain)
125125+ "todo.sr.ht".origin = mkDefault "http://todo.${cfg.originBase}";
126126+ # Address and port to bind the debug server to
127127+ "todo.sr.ht".debug-host = mkDefault "0.0.0.0";
128128+ "todo.sr.ht".debug-port = mkDefault port;
129129+ # Configures the SQLAlchemy connection string for the database.
130130+ "todo.sr.ht".connection-string = mkDefault "postgresql:///${database}?user=${user}&host=/var/run/postgresql";
131131+ # Set to "yes" to automatically run migrations on package upgrade.
132132+ "todo.sr.ht".migrate-on-upgrade = mkDefault "yes";
133133+ # todo.sr.ht's OAuth client ID and secret for meta.sr.ht
134134+ # Register your client at meta.example.org/oauth
135135+ "todo.sr.ht".oauth-client-id = mkDefault null;
136136+ "todo.sr.ht".oauth-client-secret = mkDefault null;
137137+ # Outgoing email for notifications generated by users
138138+ "todo.sr.ht".notify-from = mkDefault "CHANGEME@example.org";
139139+ # The redis connection used for the webhooks worker
140140+ "todo.sr.ht".webhooks = mkDefault "redis://${rcfg.bind}:${toString rcfg.port}/1";
141141+ # Network-key
142142+ "todo.sr.ht".network-key = mkDefault null;
143143+144144+ # Path for the lmtp daemon's unix socket. Direct incoming mail to this socket.
145145+ # Alternatively, specify IP:PORT and an SMTP server will be run instead.
146146+ "todo.sr.ht::mail".sock = mkDefault "/tmp/todo.sr.ht-lmtp.sock";
147147+ # The lmtp daemon will make the unix socket group-read/write for users in this
148148+ # group.
149149+ "todo.sr.ht::mail".sock-group = mkDefault "postfix";
150150+151151+ "todo.sr.ht::mail".posting-domain = mkDefault "todo.${cfg.originBase}";
152152+ };
153153+154154+ services.nginx.virtualHosts."todo.${cfg.originBase}" = {
155155+ forceSSL = true;
156156+ locations."/".proxyPass = "http://${cfg.address}:${toString port}";
157157+ locations."/query".proxyPass = "http://${cfg.address}:${toString (port + 100)}";
158158+ locations."/static".root = "${pkgs.sourcehut.todosrht}/${pkgs.sourcehut.python.sitePackages}/todosrht";
159159+ };
160160+ };
161161+}
···2525 # Using local file instead of content of commit #33e3d896a47 because
2626 # sourceRoot make it unappliable
2727 ./qt515.patch
2828+2929+ # Change from upstream master that removes extern-C scopes which
3030+ # cause failures with modern glib. This can likely be removed if
3131+ # there is an upstream release >1.12
3232+ (fetchpatch {
3333+ name = "fix-extern-c.patch";
3434+ url = "https://github.com/DreamSourceLab/DSView/commit/33cc733abe19872bf5ed08540a94b798d0d4ecf4.patch";
3535+ sha256 = "sha256-TLfLQa3sdyNHTpMMvId/V6uUuOFihOZMFJOj9frnDoY=";
3636+ stripLen = 2;
3737+ extraPrefix = "";
3838+ })
2839 ];
29403041 nativeBuildInputs = [ cmake pkg-config ];
···1818 # The websites youtube-dl deals with are a very moving target. That means that
1919 # downloads break constantly. Because of that, updates should always be backported
2020 # to the latest stable release.
2121- version = "2021.05.16";
2121+ version = "2021.06.06";
22222323 src = fetchurl {
2424 url = "https://yt-dl.org/downloads/${version}/${pname}-${version}.tar.gz";
2525- sha256 = "1z8sdzvkxhscnzy7cnjag308glif0k8jylr11biqwzypm1f2l0fl";
2525+ sha256 = "1hqan9h55x9gfdakw554vic68w9gpvhblchwxlw265zxp56hxjrw";
2626 };
27272828 nativeBuildInputs = [ installShellFiles makeWrapper ];
···654654 rdiff_backup = rdiff-backup; # added 2014-11-23
655655 rdmd = dtools; # added 2017-08-19
656656 readline80 = throw "readline-8.0 is no longer supported in nixpkgs, please use 'readline' for main supported version or 'readline81' for most recent version"; # added 2021-04-22
657657- retroshare = throw "retroshare was removed because it was broken"; # added 2021-05-17
658657 rhc = throw "rhc was deprecated on 2019-04-09: abandoned by upstream.";
659658 rng_tools = rng-tools; # added 2018-10-24
660659 robomongo = robo3t; #added 2017-09-28