From dce39b836a0fd6e37ab2499c2e0e232572c17ad6 Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Fri, 6 Aug 2021 20:34:18 -0600 Subject: [PATCH] add redis process, put circus in charge of process management --- .gitignore | 2 +- config.nix.tpl => config.nix | 5 +-- default.nix | 65 ++++++++++++++++++++++++++++------- srv/cmd/mediocre-blog/main.go | 42 ++++++++++++---------- srv/mailinglist/mailer.go | 9 +++++ 5 files changed, 90 insertions(+), 33 deletions(-) rename config.nix.tpl => config.nix (54%) diff --git a/.gitignore b/.gitignore index 79ffe03..2d3cf65 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ result -config.nix +prod.config.nix diff --git a/config.nix.tpl b/config.nix similarity index 54% rename from config.nix.tpl rename to config.nix index 5539376..b0396a8 100644 --- a/config.nix.tpl +++ b/config.nix @@ -1,9 +1,10 @@ { - powSecret = ""; + powSecret = "ssshhh"; mlSMTPAddr = ""; mlSMTPAuth = ""; - dataDir = "."; + dataDir = "/tmp/mediocre-blog-data"; publicURL = "http://localhost:4000"; listenProto = "tcp"; listenAddr = ":4000"; + redisListenPath = "/tmp/mediocre-blog-redis"; } diff --git a/default.nix b/default.nix index 8e634bf..a713f8a 100644 --- a/default.nix +++ b/default.nix @@ -3,11 +3,60 @@ let pkgs = utils.pkgs; system = utils.system; in - rec { - srv = (import ./srv).build; - static = (import ./static).build; + {config ? ./config.nix}: rec { config = (import ./config.nix); + static = (import ./static).build; + + srv = (import ./srv).build; + srvBin = pkgs.writeScript "mediocregopher-mediocre-blog-srvBin" '' + #!/bin/sh + exec ${srv}/bin/mediocre-blog \ + -pow-secret "${config.powSecret}" \ + -ml-smtp-addr "${config.mlSMTPAddr}" \ + -ml-smtp-auth "${config.mlSMTPAuth}" \ + -data-dir "${config.dataDir}" \ + -public-url "${config.publicURL}" \ + -static-dir "${static}" \ + -listen-proto "${config.listenProto}" \ + -listen-addr "${config.listenAddr}" + ''; + + redisCfg = pkgs.writeText "mediocregopher-mediocre-blog-redisCfg" '' + port 0 + unixsocket ${config.redisListenPath} + daemonize no + loglevel notice + logfile "" + appendonly yes + appendfilename "appendonly.aof" + dir ${config.dataDir}/redis + ''; + + redisBin = pkgs.writeScript "mediocregopher-mediocre-blog-redisBin" '' + #!/bin/sh + mkdir -p ${config.dataDir}/redis + exec ${pkgs.redis}/bin/redis-server ${redisCfg} + ''; + + circusCfg = pkgs.writeText "mediocregopher-mediocre-blog-circusCfg" '' + [circus] + endpoint = tcp://127.0.0.1:0 + pubsub_endpoint = tcp://127.0.0.1:0 + + [watcher:srv] + cmd = ${srvBin} + numprocesses = 1 + + [watcher:redis] + cmd = ${redisBin} + numprocesses = 1 + ''; + + circusBin = pkgs.writeScript "mediocregopher-mediocre-blog-circusBin" '' + exec ${pkgs.circus}/bin/circusd ${circusCfg} + ''; + service = pkgs.writeText "mediocregopher-mediocre-blog" '' [Unit] Description=mediocregopher mediocre blog @@ -18,15 +67,7 @@ in Restart=always RestartSec=1s User=mediocregopher - ExecStart=${srv}/bin/mediocre-blog \ - -pow-secret "${config.powSecret}" \ - -ml-smtp-addr "${config.mlSMTPAddr}" \ - -ml-smtp-auth "${config.mlSMTPAuth}" \ - -data-dir "${config.dataDir}" \ - -public-url "${config.publicURL}" \ - -static-dir "${static}" \ - -listen-proto "${config.listenProto}" \ - -listen-addr "${config.listenAddr}" + ExecStart=${circusBin} [Install] WantedBy=multi-user.target diff --git a/srv/cmd/mediocre-blog/main.go b/srv/cmd/mediocre-blog/main.go index 66c17ee..0a5f8b7 100644 --- a/srv/cmd/mediocre-blog/main.go +++ b/srv/cmd/mediocre-blog/main.go @@ -62,10 +62,6 @@ func main() { logger.Fatal(ctx, "-static-dir or -static-proxy-url is required") case *powSecret == "": logger.Fatal(ctx, "-pow-secret is required") - case *smtpAddr == "": - logger.Fatal(ctx, "-ml-smtp-addr is required") - case *smtpAuthStr == "": - logger.Fatal(ctx, "-ml-smtp-auth is required") } publicURL, err := url.Parse(*publicURLStr) @@ -87,14 +83,22 @@ func main() { } powTarget := uint32(powTargetUint) - smtpAuthParts := strings.SplitN(*smtpAuthStr, ":", 2) - if len(smtpAuthParts) < 2 { - logger.Fatal(ctx, "invalid -ml-smtp-auth") - } - smtpAuth := sasl.NewPlainClient("", smtpAuthParts[0], smtpAuthParts[1]) - smtpSendAs := smtpAuthParts[0] + var mailerCfg mailinglist.MailerParams - // initialization + if *smtpAddr != "" { + mailerCfg.SMTPAddr = *smtpAddr + smtpAuthParts := strings.SplitN(*smtpAuthStr, ":", 2) + if len(smtpAuthParts) < 2 { + logger.Fatal(ctx, "invalid -ml-smtp-auth") + } + mailerCfg.SMTPAuth = sasl.NewPlainClient("", smtpAuthParts[0], smtpAuthParts[1]) + mailerCfg.SendAs = smtpAuthParts[0] + + ctx = mctx.Annotate(ctx, + "smtpAddr", mailerCfg.SMTPAddr, + "smtpSendAs", mailerCfg.SendAs, + ) + } ctx = mctx.Annotate(ctx, "publicURL", publicURL.String(), @@ -102,10 +106,10 @@ func main() { "listenAddr", *listenAddr, "dataDir", *dataDir, "powTarget", fmt.Sprintf("%x", powTarget), - "smtpAddr", *smtpAddr, - "smtpSendAs", smtpSendAs, ) + // initialization + if *staticDir != "" { ctx = mctx.Annotate(ctx, "staticDir", *staticDir) } else { @@ -127,11 +131,13 @@ func main() { // sugar requirePow := func(h http.Handler) http.Handler { return requirePowMiddleware(powMgr, h) } - mailer := mailinglist.NewMailer(mailinglist.MailerParams{ - SMTPAddr: *smtpAddr, - SMTPAuth: smtpAuth, - SendAs: smtpSendAs, - }) + var mailer mailinglist.Mailer + if *smtpAddr == "" { + logger.Info(ctx, "-smtp-addr not given, using NullMailer") + mailer = mailinglist.NullMailer + } else { + mailer = mailinglist.NewMailer(mailerCfg) + } mlStore, err := mailinglist.NewStore(path.Join(*dataDir, "mailinglist.sqlite3")) if err != nil { diff --git a/srv/mailinglist/mailer.go b/srv/mailinglist/mailer.go index 81d0b91..12fc398 100644 --- a/srv/mailinglist/mailer.go +++ b/srv/mailinglist/mailer.go @@ -10,6 +10,15 @@ type Mailer interface { Send(to, subject, body string) error } +// NullMailer acts as a Mailer but actually just does nothing. +var NullMailer = nullMailer{} + +type nullMailer struct{} + +func (nullMailer) Send(to, subject, body string) error { + return nil +} + // MailerParams are used to initialize a new Mailer instance type MailerParams struct { SMTPAddr string