- Python 100%
| app | Add TOOTCTL_PATH to .env variables. Add daily_stats table accumulative stats. Add ALT text description. Fix purge error. | |
| graphs | first commit | |
| logs | first commit | |
| LICENSE | Add AGPL-3.0 license | |
| README.md | Add save historic stats | |
| requirements.txt | first commit | |
Cleaner
Tool to automatically remove dead or inactive federated servers from a Mastodon server.
Description
This script analyzes all servers federated with your Mastodon server, checks their availability (DNS and HTTP), and automatically purges those that have been consecutively failing for 14 days. All verification data is stored in an independent PostgreSQL database to reliably track each server's status.
Features
- Asynchronous and concurrent DNS and HTTP checking
- Dedicated database to store verification history
- Quarantine system with automatic purging after N days of failures
- Detailed logs with automatic rotation
- Dry-run mode to test without making actual changes
- Interactive configuration on first run
- Support for Unbound as local DNS resolver
Project Structure
cleaner
├── .env # Configuration (auto-generated)
├── logs # Execution logs
│ ├── cleanup.log # Full logs
│ ├── errors.log # Only errors
│ └── purge.log # Purge records
└── app
├── cleaner.py # Main script
├── publish.py # publish to Mastodon
├── publica.py # publish to Mastodon (catalan language)
├── db
│ ├── schema.py # Database schema creation
│ └── stats.py # save historic stats
│
└── services
└── postgres.py # PostgreSQL connection management
Prerequisites
- Python 3.10+
- PostgreSQL (installed and running)
- Mastodon (with access to
/api/v1/instance/peersAPI) - Unbound (recommended for fast DNS resolution)
Python Dependencies
pip install asyncpg aiohttp loguru python-dotenv
Installation
- Clone the repository
git clone https://codeberg.org/spla/cleaner.git
cd cleaner
- Create virtual environment
python3 -m venv .
source bin/activate
- Install dependencies
pip install -r requirements.txt
Usage
First run (interactive configuration)
python app/cleaner.py
The script will ask for:
Your Mastodon server URL PostgreSQL credentials Advanced parameters (concurrency, timeouts, etc.) Responses are saved to the .env file.
Normal execution (dry-run by default)
python app/cleaner.py
Checks all federated servers Updates the database DOES NOT purge anything (analysis mode) Execute with real purge
python app/cleaner.py --execute
Checks all servers Updates the database PURGES servers that have been failing for 14 consecutive days Run with DEBUG log level
python app/cleaner.py --log-level DEBUG
Configuration
The auto-generated .env file contains:
MASTODON_URL=https://your-mastodon-server.org
DB_DSN=postgresql://user:password@localhost:5432/your_database
CONCURRENCY=20
TIMEOUT_DNS=5
TIMEOUT_HTTP=10
MAX_FAILURE_DAYS=14
BATCH_SIZE=50
Recommended settings
| Parameter | Default | Description |
|---|---|---|
| CONCURRENCY | 20-50 | Concurrent checks (higher = faster but more resource intensive |
| TIMEOUT_DNS | 3-5 | Maximum seconds for DNS resolution |
| TIMEOUT_HTTP | 5-10 | Maximum seconds for HTTP request |
| MAX_FAILURE_DAYS | 14 | Consecutive failure days before purging |
| BATCH_SIZE | 50 | How many domains to purge per batch |
Database
The script automatically creates a new database (default fedcleaner) with the server_health table:
| Field | Description |
|---|---|
| domain | Federated server domain name |
| first_seen | First time the server was checked |
| last_checked | Last verification time |
| check_count | Total number of verifications |
| consecutive_failures | Current consecutive failures |
| last_success | Last time it responded successfully |
| status | alive, quarantine or dead |
| should_purge | Flagged for purging |
Useful queries
-- Connect to the database
psql-Umastodon-dfedcleaner-- View server status distribution
SELECTstatus,COUNT(*)FROMserver_healthGROUPBYstatus;-- View domains flagged for purging
SELECTdomain,consecutive_failures,last_checkedFROMserver_healthWHEREshould_purge=trueLIMIT10;Automation with cron
To run the script daily in dry-run mode:
Edit crontab
crontab -e
Add (runs every day at 3:00 AM)
0 3 * * * cd /home/mastodon/bots/cleaner && source bin/activate && python app/cleaner.py > /dev/null
After several days (when MAX_FAILURE_DAYS has accumulated), you can manually run the real purge:
python app/cleaner.py --execute
Troubleshooting
"Too many open files"
Reduce CONCURRENCY in .env:
CONCURRENCY=10
PostgreSQL connection error
Verify credentials in .env and ensure PostgreSQL is running:
sudo systemctl status postgresql
Issues with Unbound
Make sure Unbound is configured as local resolver:
cat /etc/resolv.conf
Should show: nameserver 127.0.0.1
Logs
Logs are stored in logs/ with automatic rotation:
cleanup_YYYY-MM-DD.log: Full logs
errors_YYYY-MM-DD.log: Only errors
purge_YYYY-MM-DD.log: Purge records
Dry-run mode
By default, the script runs in dry-run mode (analysis without purging). This mode:
Checks all servers
Updates the database
Does NOT execute tootctl domains purge
To perform a real purge, use --execute.
Security
Passwords are stored in the .env file with 600 permissions
The database is independent from Mastodon's database
Purges are done in batches to avoid system overload
License
Contributing
Contributions are welcome. Open an issue or pull request.