Skip to content

Add ePDS-native pdsadmin CLI#5

Merged
daveselfsurf merged 2 commits into
mainfrom
feat/pdsadmin-wrapper-clean
May 29, 2026
Merged

Add ePDS-native pdsadmin CLI#5
daveselfsurf merged 2 commits into
mainfrom
feat/pdsadmin-wrapper-clean

Conversation

@daveselfsurf

Copy link
Copy Markdown
Collaborator

Summary

Adds an ePDS-native pdsadmin CLI under scripts/pdsadmin/, so operators get the familiar Bluesky pdsadmin admin commands against an ePDS deployment. The upstream Bluesky script isn't bundled with ePDS and assumes the /pds docker-compose layout (/pds/pds.env, a pds container, systemd update), so running ./pdsadmin … on an ePDS box fails with command not found.

  • account list [--limit N] — reads the pds-core account DB directly (actor joined with account), read-only and WAL-safe, ordered by actor.createdAt newest-first. This is deliberately not com.atproto.sync.listRepos, which inner-joins repo_root and filters by account status (so it omits repo-less / deactivated accounts) and only exposes a re-index indexedAt rather than creation time. Surfaces a Deactivated column.
  • account create / delete / takedown / untakedown / reset-password, create-invite-code [useCount], request-crawl [relay] — authenticated XRPC calls.
  • Reads PDS_HOSTNAME / PDS_ADMIN_PASSWORD from PDS_ENV_FILE (default /opt/epds/.env; override for local/dev). account list additionally needs Docker access (run with sudo); container/DB path overridable via PDS_CORE_CONTAINER / PDS_ACCOUNT_DB.
  • The upstream update subcommand is intentionally omitted — it pulls Bluesky's image and restarts via systemd, which would break ePDS's docker compose build/up flow.

Because it depends only on stable AT Protocol lexicon endpoints / the account DB schema plus two core env vars (not on package code), it keeps working across future repo changes.

Test plan

  • account list --limit 10 on the self.surf deploy returns the genuine newest accounts (top row matches actor.createdAt from a direct DB query), correctly aligned.
  • Arg validation: bad --limit rejected before any I/O; bad DIDs rejected for delete/takedown/etc.
  • Env guards: missing env file / missing PDS_HOSTNAME/PDS_ADMIN_PASSWORD error clearly.
  • help renders; unknown commands fall back to help.
  • Reviewer: confirm account create mirroring upstream (random password, bypasses ePDS OTP/community-DID provisioning) is acceptable, or should be dropped.

Usage on the server:

sudo /opt/epds/scripts/pdsadmin/pdsadmin.sh account list --limit 10

🤖 Generated with Claude Code

daveselfsurf and others added 2 commits May 29, 2026 11:04
Upstream Bluesky pdsadmin isn't bundled with ePDS and assumes the /pds
docker-compose layout, so it fails on an ePDS box. This adds a wrapper
under scripts/pdsadmin/ reading ePDS's own .env (PDS_ENV_FILE, default
/opt/epds/.env):

- account list — reads the pds-core account DB directly (read-only,
  WAL-safe) ordered by actor.createdAt, so it shows every account
  (including repo-less/deactivated ones that com.atproto.sync.listRepos
  omits) in true creation order, with an optional --limit. Surfaces a
  deactivated column.
- account create/delete/takedown/untakedown/reset-password,
  create-invite-code, request-crawl — authenticated XRPC calls.

The upstream 'update' subcommand is intentionally omitted: it pulls
Bluesky's image and restarts via systemd, which would break ePDS's
docker compose build/up flow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dirname "${BASH_SOURCE[0]}" returns the symlink's directory, so a
symlink (e.g. /usr/local/bin/pdsadmin) made the dispatcher look for its
sibling scripts next to the link instead of in scripts/pdsadmin/, failing
with "/usr/local/bin/account.sh: No such file". Walk the symlink chain to
the real script location before computing SCRIPT_DIR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@daveselfsurf daveselfsurf merged commit 4ff7563 into main May 29, 2026
0 of 5 checks passed
@daveselfsurf daveselfsurf deleted the feat/pdsadmin-wrapper-clean branch May 29, 2026 11:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant