Aggregator Setup Scripts#
This directory contains scripts to help you set up and register your aggregator with Coves instances.
Overview#
Aggregators are automated services that post content to Coves communities. They are similar to Bluesky's feed generators and labelers. To use aggregators with Coves, you need to:
- Create a PDS account for your aggregator (gets you a DID)
- Prove you own a domain via
.well-known/atproto-did - Register with a Coves instance
- Create a service declaration record
These scripts automate this process for you.
Prerequisites#
- Domain ownership: You must own a domain where you can host the
.well-known/atproto-didfile - Web server: Ability to serve static files over HTTPS
- Tools:
curl,jq(for JSON processing) - Account: Email address for creating the PDS account
Quick Start#
Interactive Setup (Recommended)#
Run the scripts in order:
# Make scripts executable
chmod +x *.sh
# Step 1: Create PDS account
./1-create-pds-account.sh
# Step 2: Generate .well-known file
./2-setup-wellknown.sh
# Step 3: Register with Coves (after uploading .well-known)
./3-register-with-coves.sh
# Step 4: Create service declaration
./4-create-service-declaration.sh
Automated Setup Example#
For a reference implementation of automated setup, see the Kagi News aggregator at aggregators/kagi-news/scripts/setup.sh.
The Kagi script shows how to automate all 4 steps (with the manual .well-known upload step in between).
Script Reference#
1-create-pds-account.sh#
Purpose: Creates a PDS account for your aggregator
Prompts for:
- PDS URL (default: https://bsky.social)
- Handle (e.g., mynewsbot.bsky.social)
- Password
Outputs:
aggregator-config.env- Configuration file with DID and credentials- Prints your DID and access tokens
Notes:
- Keep the config file secure! It contains your credentials
- The PDS automatically generates a DID:PLC for you
- You can use any PDS service, not just bsky.social
2-setup-wellknown.sh#
Purpose: Generates the .well-known/atproto-did file for domain verification
Prompts for:
- Your domain (e.g., rss-bot.example.com)
Outputs:
.well-known/atproto-did- File containing your DIDnginx-example.conf- Example nginx configurationapache-example.conf- Example Apache configuration
Manual step required:
Upload the .well-known directory to your web server. The file must be accessible at:
https://yourdomain.com/.well-known/atproto-did
Verify it works:
curl https://yourdomain.com/.well-known/atproto-did
# Should return your DID (e.g., did:plc:abc123...)
3-register-with-coves.sh#
Purpose: Registers your aggregator with a Coves instance
Prompts for:
- Coves instance URL (default: https://api.coves.social)
Prerequisites:
.well-known/atproto-didmust be accessible from your domain- Scripts 1 and 2 must be completed
What it does:
- Verifies your
.well-known/atproto-didis accessible - Calls
social.coves.aggregator.registerXRPC endpoint - Coves verifies domain ownership
- Inserts your aggregator into the
userstable
Outputs:
- Updates
aggregator-config.envwith Coves instance URL - Prints registration confirmation
4-create-service-declaration.sh#
Purpose: Creates the service declaration record in your repository
Prompts for:
- Display name (e.g., "RSS News Aggregator")
- Description
- Source URL (GitHub repo, etc.)
- Maintainer DID (optional)
What it does:
- Creates a
social.coves.aggregator.servicerecord atat://your-did/social.coves.aggregator.service/self - Jetstream consumer will index this into the
aggregatorstable - Communities can now discover and authorize your aggregator
Outputs:
- Updates
aggregator-config.envwith record URI and CID - Prints record details
Configuration File#
After running the scripts, you'll have an aggregator-config.env file with:
AGGREGATOR_DID="did:plc:..."
AGGREGATOR_HANDLE="mynewsbot.bsky.social"
AGGREGATOR_PDS_URL="https://bsky.social"
AGGREGATOR_EMAIL="bot@example.com"
AGGREGATOR_PASSWORD="..."
AGGREGATOR_ACCESS_JWT="..."
AGGREGATOR_REFRESH_JWT="..."
AGGREGATOR_DOMAIN="rss-bot.example.com"
COVES_INSTANCE_URL="https://api.coves.social"
SERVICE_DECLARATION_URI="at://did:plc:.../social.coves.aggregator.service/self"
SERVICE_DECLARATION_CID="..."
Use this in your aggregator code to authenticate and post.
What Happens Next?#
After completing all 4 steps:
- Your aggregator is registered in the Coves instance's
userstable - Your service declaration is indexed in the
aggregatorstable (takes a few seconds) - Community moderators can now authorize your aggregator for their communities
- Once authorized, your aggregator can post to those communities
Creating an Authorization#
Authorizations are created by community moderators, not by aggregators. The moderator writes a social.coves.aggregator.authorization record to their community's repository.
See docs/aggregators/SETUP_GUIDE.md for more information on the authorization process.
Posting to Communities#
Once authorized, your aggregator can post using:
curl -X POST https://api.coves.social/xrpc/social.coves.community.post.create \
-H "Authorization: Bearer $AGGREGATOR_ACCESS_JWT" \
-H "Content-Type: application/json" \
-d '{
"communityDid": "did:plc:...",
"post": {
"text": "Your post content",
"createdAt": "2024-01-15T12:00:00Z"
}
}'
Troubleshooting#
Error: "DomainVerificationFailed"#
- Verify
.well-known/atproto-didis accessible:curl https://yourdomain.com/.well-known/atproto-did - Check the content matches your DID exactly (no extra whitespace)
- Ensure HTTPS is working (not HTTP)
- Check CORS headers if accessing from browser
Error: "AlreadyRegistered"#
- You've already registered this DID with this Coves instance
- This is safe to ignore if you're re-running the setup
Error: "DIDResolutionFailed"#
- Your DID might be invalid or not found in the PLC directory
- Verify your DID exists:
curl https://plc.directory/<your-did> - Wait a few seconds and try again (PLC directory might be propagating)
Service declaration not appearing#
- Wait 5-10 seconds for Jetstream consumer to index it
- Check the Jetstream logs for errors
- Verify the record was created: Check your PDS at
at://your-did/social.coves.aggregator.service/self
Example: Kagi News Aggregator#
For a complete reference implementation, see the Kagi News aggregator at aggregators/kagi-news/.
The Kagi aggregator includes an automated setup script at aggregators/kagi-news/scripts/setup.sh that demonstrates how to:
- Automate the entire registration process
- Use environment variables for configuration
- Handle errors gracefully
- Integrate the setup into your aggregator project
This shows how you can package scripts 1-4 into a single automated flow for your specific aggregator.
Security Notes#
- Never commit
aggregator-config.envto version control - Store credentials securely (use environment variables or secret management)
- Rotate access tokens regularly
- Use HTTPS for all API calls
- Validate community authorization before posting
More Information#
Support#
If you encounter issues:
- Check the troubleshooting section above
- Review the full documentation in
docs/aggregators/ - Open an issue on GitHub with:
- Which script failed
- Error message
- Your domain (without credentials)