Commit graph

3 commits

Author SHA1 Message Date
807ecf2530
chore: keep all agentbbs services on latest software (#69)
Some checks are pending
CI / build (push) Waiting to run
deploy / deploy (push) Waiting to run
test / test (push) Waiting to run
* ci: add mailu-update workflow to keep the mail stack current

The deploy/mailu compose stack pins the floating series tags
(ghcr.io/mailu/*:2024.06); patch releases within the series only land when
someone runs `docker compose pull`, so the box drifts behind on security fixes.

Add a scheduled (weekly) + on-demand workflow that SSHes to the droplet
(reusing deploy.yml's DEPLOY_* secrets), backs up DKIM keys + the admin DB,
pulls the latest images for the pinned series, recreates the containers, and
health-checks the Mailu front on 127.0.0.1:8080. Shares deploy.yml's
concurrency group so it never races a code deploy. Stays within the pinned
series on purpose — crossing to a future series stays a deliberate PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: bump Forgejo to 11.0.15 + add Dependabot to keep deps current

Audit of every version pin in the repo: Ergo (2.18.0), Go (1.26 → latest
patch via setup-go), the Ubuntu pod base (24.04 LTS), and the GitHub Action
majors are all already current. Only Forgejo was stale — bump 11.0.1 →
11.0.15 (latest patch of the 11.x LTS line; a 15.x major stays a deliberate,
tested upgrade because of DB migrations).

Add .github/dependabot.yml so github-actions, Go modules, and the Docker
image tags (Mailu compose + pod Containerfile) get review-gated update PRs
weekly. Shell-string pins (FORGEJO_VERSION/ERGO_VERSION in setup.sh) can't be
watched by Dependabot; noted inline. Mailu runtime patch level is handled by
the mailu-update workflow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* mailu: document RECIPIENT_DELIMITER=+ in mailu.env.example

Plus-addressing (chovy+tag@ -> chovy@) is a hard prerequisite for qaaas.dev's
packages/mail but was missing from the example, so tagged mail bounces as an
unknown recipient until an operator sets it by hand. Add it with a note that it
governs DELIVERY only, not login (Mailu auths the exact address; base <name>@
is the single login and already receives all +tagged mail).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 20:06:06 -07:00
006235ce92
Feat/mail all members (#55)
* feat(mail): give every verified member a free @bbs.profullstack.com mailbox

Email was built but paid-only (Founding Lifetime gate) and never wired to a
running backend. Make it a free benefit of membership and split the address
domain from the mail-server host.

- internal/mailu: Mailu admin-API client; EnsureUser idempotently provisions a
  mailbox via the loopback admin REST API (token = mailu.env API_TOKEN).
- main.go: auto-provision <name>@<mailDomain> at join@ verification and on first
  Mail open; un-gate the Mail hub entry + mail@ (membership/email-verified, not
  Premium); address domain (AGENTBBS_MAIL_ADDR_DOMAIN, default the BBS host) is
  now distinct from the mail server host (AGENTBBS_MAIL_DOMAIN) and the webmail
  URL. Drop the forwardemail alias path (Mailu now owns delivery for everyone).
- mailbox: gate on membership (a registered handle) instead of Paid;
  ErrNotPaid -> ErrNotMember.
- join@ copy: list email under free membership; premium now pitches custom
  domains + Tor only.
- setup.sh / docs/mail.md / deploy/mailu: address-domain vs server-host split,
  Mailu API token, MX for the address domain, local-relay SMTP for verify codes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(mailu): pin Docker network subnet to match SUBNET; ignore runtime state

The base compose declares no network, so Docker assigns the default bridge an
arbitrary subnet that won't match mailu.env SUBNET — breaking Mailu's internal
service auth/relay. Add a docker-compose.override.yml.example that pins the
default network to 192.168.203.0/24, and gitignore the live override + Mailu
runtime state (mailu.env, certs/, data/).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(mail): plaintext loopback IMAP so the gateway bypasses Mailu's front

Mailu's front (nginx mail proxy) pre-authenticates against Mailu's user DB before
proxying to Dovecot, which rejects the Dovecot master-user login <addr>*gateway.
The gateway must reach Dovecot directly. The imap container has no TLS cert (only
the front does), so the bypass is plaintext over loopback — the master password
never leaves the host.

- mailbox: IMAPConfig.Plaintext dials with DialInsecure (loopback only).
- main.go: mailClientFor sets Plaintext from AGENTBBS_MAIL_IMAP_PLAINTEXT.
- override.example: add the unbound resolver (admin needs DNSSEC), webmail image
  fix (2024.06 uses mailu/webmail), and publish Dovecot 143 on 127.0.0.1:14143.
- docs/mail.md: document the front-bypass, the dovecot.conf master passdb (Mailu
  includes that exact filename), and the 644 master-users perms (640 = temp_fail).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* deploy(mailu): wire gateway IMAP to the loopback Dovecot path in setup.sh

setup.sh §9e set AGENTBBS_MAIL_IMAP_ADDR to the front's :993, which the front's
auth proxy rejects for the master-user login (and would clobber the working
loopback wiring on every self-update). Point it at 127.0.0.1:14143 +
AGENTBBS_MAIL_IMAP_PLAINTEXT=1 instead, matching the override + docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(mail): give free members a webmail password at join@

The gateway opens mailboxes via the Dovecot master user (no member password),
but webmail (Roundcube) needs the member to have a password. join@ now sets a
fresh, readable webmail password via the Mailu API and shows it with the webmail
URL + login, so free members can use webmail at mail.profullstack.com.

- mailu: SetPassword (PATCH /user/<email> raw_password) + test.
- main.go: setWebmailPassword + readablePassword; join@ displays url/login/password.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 03:38:31 -07:00
cb09300357 Self-host Mailu mail stack at mail.profullstack.com
Members get a real <name>@mail.profullstack.com mailbox, served by a
co-located Mailu (Postfix+Dovecot+Roundcube+rspamd) Docker stack. Coexists
with the host Caddy: Mailu owns the mail ports; Caddy fronts the loopback
webmail and supplies the TLS cert (TLS_FLAVOR=mail), the same cert-copy
pattern as the Ergo/IRC and NNTP services.

- deploy/mailu/: docker-compose.yml, mailu.env.example, refresh-certs.sh
  (copy Caddy's mail cert into Mailu on renewal), provision-mailbox.sh
  (member mailbox + Dovecot gateway master user), README.
- setup.sh: MAIL flag + mail.${DOMAIN#*.} Caddy site + §9e (cert timer,
  mail-port firewall, conditional compose bring-up, AGENTBBS_MAIL_* env).
- docs/mail.md: architecture, DNS (MX/SPF/DKIM/DMARC/PTR), gateway
  master-user setup, env, provisioning, webmail-only policy.

Apex profullstack.com stays corporate; member mail is only on mail.*.
Infra is inspection-verified (bash -n, YAML lint); deploy pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 16:33:25 +00:00