The internal/forgejo package landed without its call sites. Restore them:
- main.go: provisionGit() called after both email-verify paths (web link +
interactive code), the forgejo.Config app field, and ConfigFromEnv wiring.
Every verified member (free + paid) gets a git.profullstack.com account;
failures are logged, never block verification; no-op when unconfigured.
- setup.sh §9d: install + run the Forgejo backend on a loopback port fronted
by Caddy at https://git.<root>, members-only, with an admin token minted
into agentbbs.env. Caddy vhost + done-banner + env template entries.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Provision a self-hosted Ergo IRC network (irc.${DOMAIN}) in setup.sh §9b:
single Go binary on its own ports/user, reusing Caddy's Let's Encrypt cert
for 6697 TLS (refreshed by a timer; self-signed fallback on first boot),
loopback 6667 + a loopback WebSocket fronted by Caddy at wss://${DOMAIN}/irc.
Access is MEMBERS-ONLY: every client must authenticate with SASL, self-service
registration is off, and an auth-script (deploy/ergo/auth-script.sh, installed
as /usr/local/bin/ergo-auth-member) approves a login only if the account name
maps to an existing AgentBBS member home dir under <data>/users/. Passphrase is
ignored — membership (the filesystem dir) is the credential. require-sasl has
no IP exemption so WebSocket clients (which reach Ergo via Caddy from 127.0.0.1)
can't bypass the gate; accounts are auto-created on first successful auth.
Public attack surface is TLS-only (ufw opens 6697; 6667 is loopback). Toggle
with IRC=0. See docs/irc.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add three premium-gated SSH routes:
ssh tor-url@host <url> one-shot HTTP(S) GET over Tor (host-side,
curl via SOCKS, 30s/2MB caps, http/https only)
ssh -t tor-irc@host <server> interactive IRC over Tor in the member's pod
ssh -t tor@host <command...> run any command over Tor (torsocks) in the pod
tor-url runs host-side and constrained; tor/tor-irc run inside the member's
isolated pod (new pods.Exec) so arbitrary/interactive commands are sandboxed,
never on the host. internal/tor wraps curl/torsocks/irssi. All gated by
ensurePremium; names reserved. setup.sh installs + enables tor (SOCKS
127.0.0.1:9050) and torsocks.
Note: tor-url is host-side and self-contained. tor/tor-irc still need the pod
image to carry torsocks+irssi and reach the Tor SOCKS — follow-up.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The self-update timer runs setup.sh as a systemd oneshot with no $HOME, so
`go build` aborted with "module cache not found: neither GOMODCACHE nor GOPATH
is set" before compiling — auto-deploys silently pulled new code but never
rebuilt or restarted. On top of that, a cold cache made the 458MB droplet
OOM-kill the compiler.
Set explicit, root-owned, persistent Go caches (/var/cache/agentbbs/{go,go-build})
plus HOME and GOMAXPROCS=1 in setup.sh, and add HOME=/root to the generated
agentbbs-update.service. A warm persistent cache means incremental redeploys
recompile almost nothing, keeping peak memory within RAM+swap; combined with
the existing `go build -p=1` the compiler no longer gets OOM-killed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
enable --now leaves an already-running service untouched, so a redeploy's new
binary never loaded. Use enable + restart.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
caddy validate failed: 'module not registered: http.matchers.host_regexp'.
Drop the regexp; map the subdomain via {http.request.host.labels.N} where N is
the DOMAIN label count. The on-demand ask endpoint still gates cert issuance to
registered members.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- sites.AskHandler now approves <name>.AGENTBBS_HOST on-demand-TLS when <name>
is a registered member (so only real users mint subdomain certs).
- Caddyfile: *.${DOMAIN} block serving users/<name>/public_html with on_demand
TLS; unknown users 404. Needs a wildcard DNS record *.${DOMAIN} -> host.
- Test: TestAskUserSubdomain.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On Ubuntu 22.10+/24.04 sshd is socket-activated via ssh.socket, which owns the
listen port and ignores sshd_config's Port — so the admin-port move silently
failed (safety check aborted before freeing :22). Override ssh.socket's
ListenStream to ADMIN_SSH_PORT when present; fall back to restarting the service
on classic setups.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
512MB droplets OOM-kill the Go build (livekit/redis/modernc deps). Add:
- ensure_swap: adds a 3G swapfile on low-RAM hosts (build + runtime headroom)
- SKIP_BUILD=1: use prebuilt /usr/local/bin/{agentbbs,ascii-live} (copied from
CI or a dev box) instead of compiling on the host
- go build -p=1 to cap peak memory when building on-box
- install unzip (Freedoom fetch needs it)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CreatePremiumCharge/VerifyPremium now POST /payments/create and GET
/payments/:id against the CoinPay API (Bearer COINPAY_API_KEY, business_id =
AGENTBBS_COINPAY_MERCHANT_ID), so the droplet needs no coinpay CLI installed.
The created payment id is stored (store: User.PremiumPayID + premium_pay_id col
+ SetPremiumPayment); ensurePremium verifies that id on a later connect and
grants premium on confirmed/forwarded status. Removed the CLI command-template
env knobs; added AGENTBBS_COINPAY_API_URL. Tests: httptest-backed payments_test
+ store SetPremiumPayment test. Build/vet/gofmt/test green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- payments: AGENTBBS_COINPAY_MERCHANT_ID -> --business-id on the premium
create/pay commands (coinpay CLI reads COINPAY_API_KEY from env for auth).
- deploy.yml: forward COINPAY_API_KEY + COINPAY_MERCHANT_ID (GitHub secrets,
masked in logs) to the remote setup.sh.
- setup.sh: idempotent upsert_env writes those secrets into agentbbs.env
(COINPAY_API_KEY, AGENTBBS_COINPAY_MERCHANT_ID, COINPAY_BUSINESS_ID),
preserving the rest. No secret values are committed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deploy automation (idempotent, runs on every deploy):
- .github/workflows/deploy.yml: push to main/master (or dispatch) SSHes to the
droplet and re-runs setup.sh; deploys the pushed branch; smoke-tests :22.
- scripts/self-update.sh + agentbbs-update.timer: autonomous backstop that
redeploys only when origin advances.
- setup.sh hardened: flock, fetch+reset (survives force-push), fixed the
always-skipped arcade asset fetch path.
Membership model:
- Free, email-verified members get their own Docker pod (pod@ paywall removed)
and a /~name homepage (seeded at join@).
- join@ is now interactive: email -> emailed 6-digit code -> enter code.
- Premium ($10 one-time, lifetime via CoinPay) grants a personal
<name>@host email (new internal/forwardemail; forwardemail.net aliases) and
custom domains (domain@ gated to Premium).
- ensurePremium() silently verifies/grants/provisions on hub login, join@, and
domain@. New-signup details emailed to AGENTBBS_SIGNUP_NOTIFY (subject "bbs").
Store: User.Premium + premium/premium_ref cols, ConfirmEmailCode, GrantPremium.
Tests: store_premium_test.go, forwardemail_test.go. Build/vet/gofmt/test green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Proxy /verify on the main site to the agentbbs loopback endpoint and
surface AGENTBBS_HTTP_ADDR + the SMTP knobs in the generated env file
(links are logged when SMTP is unconfigured; existing env files keep
working via the in-binary 127.0.0.1:8088 default).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- setup.sh: idempotent one-shot droplet provisioner — agentbbs on :22
(admin OpenSSH moved to :2202), rootless podman, Caddy front end for
https://bbs.profullstack.com with tilde-style /~user homepages
- internal/sites + domain@ SSH route: self-service custom domains
(ssh domain@host add example.com) backed by a symlink farm and an
on-demand-TLS ask endpoint so Caddy only issues certs for mapped hosts
- internal/mail + join@ email verification: optional email at signup,
confirmation link served by a loopback /verify endpoint behind Caddy
- internal/source + cmd/ascii-live: live video → terminal ASCII groundwork
(docs/ascii-live.md)
- store: additive sqlite migrations (email/verify columns, domains table)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>