Self-Hosted Stoat Tips
This guide is for community admins who are migrating to a Stoat instance they operate themselves. Self-hosting gives you full control over limits and configuration, which makes large migrations significantly easier.
Official hosted service
If you are using api.stoat.chat rather than your own server, skip this guide. The limits and configuration covered here only apply to self-hosted instances.
Configuration Files
Self-hosted Stoat uses two configuration files:
Revolt.toml— the main configuration file. Edit with care; most settings have sensible defaults.Revolt.overrides.toml— place your customizations here. Values in this file take precedence overRevolt.toml. Use this file so your changes survive updates.
Use overrides, not the main config
Always make your changes in Revolt.overrides.toml. If you edit Revolt.toml directly, your changes may be overwritten when you update Stoat.
Raising Limits for Migration
The default limits in Stoat are designed for general community use. When importing a large Discord server, you will likely need to raise several of them.
| Setting | Default | Suggested for large migrations | Description |
|---|---|---|---|
server_channels |
200 | 500 | Maximum channels per server |
server_emoji |
100 | 200 | Maximum custom emoji per server |
message_length |
2000 | 4000 | Maximum characters per message |
attachment_size |
20 MB | 50 MB or higher | Maximum file upload size |
Add these to your Revolt.overrides.toml:
# Revolt.overrides.toml
[limits.global]
server_channels = 500
server_emoji = 200
message_length = 4000
attachment_size = 52428800 # 50 MB in bytes
Restart your Stoat instance after editing the file.
Restart required
Configuration changes do not take effect until you restart the Stoat services. Do this before starting the Ferry migration.
Tell Ferry about raised limits
After raising server limits, also pass --max-channels 500 --max-emoji 200 to ferry migrate so Ferry knows to respect the higher ceiling.
Verify with a dry run
After configuring your self-hosted instance, run ferry migrate with --dry-run to validate structure mapping before committing to a full migration. This exercises all phases without making any API calls.
Autumn File Storage
Autumn is Stoat's file storage service. Uploaded attachments, avatars, and emoji are stored here. Ferry uploads all media to Autumn automatically.
Autumn supports two storage backends:
- Local filesystem — files stored directly on the server. Simple to set up, limited by disk space.
- S3-compatible storage (Minio, AWS S3, Backblaze B2, etc.) — better for large migrations with many GB of media.
For migrations with 10+ GB of media, an S3-compatible backend is recommended. Check the Stoat self-hosting documentation for Autumn configuration details.
Server banners are automatically migrated when a Discord token is provided. The banner is downloaded from Discord's CDN and uploaded to Autumn (6MB limit).
Performance Tuning
For powerful self-hosted instances, you can increase concurrency to speed up migrations. The circuit breaker (5 consecutive failures → 30s pause) provides safety regardless of concurrency level.
| Setting | Default | Description |
|---|---|---|
max_concurrent_channels |
3 | Channels processed in parallel during the message phase |
max_concurrent_requests |
5 | Total concurrent API calls across all channel workers |
These two settings interact: with 3 channels and 5 API slots, each channel averages ~1.7 concurrent calls. Both are adjustable since v2.7.0 — try 6 concurrent channels and 12 concurrent requests on a powerful self-hosted instance:
ferry migrate --export-dir ./export \
--stoat-url https://stoat.example.com --token "$STOAT_TOKEN" \
--max-concurrent-channels 6 --max-concurrent-requests 12
In the GUI, the same settings live under Advanced Options → Speed. Monitor your Stoat server load and reduce the values if you encounter frequent 429 errors. Ferry warns if you raise them while targeting the official api.stoat.chat (where they usually make runs slower, not faster).
Ferry GUI Storage Secret
The Ferry GUI uses a storage secret to persist non-sensitive session settings (such as your Stoat API URL) between page navigations. Tokens are never part of this — they are held in memory only and are never written to disk. By default, a random secret is generated each time Ferry starts.
To persist settings across restarts, set the FERRY_STORAGE_SECRET environment variable:
export FERRY_STORAGE_SECRET="your-random-secret-here"
This is optional. If not set, Ferry will work fine but you will need to re-enter your settings if the GUI process restarts.
Account Age
Stoat may apply stricter rate limits to accounts that were created less than 72 hours ago. Use an established account — your own personal account that you have been using for a while — rather than a brand-new account created just for the migration.
Server owner is best
Running Ferry with the server owner's token avoids nearly all permission-related issues. The owner automatically has all permissions on all channels. Remember: Ferry uses your regular user token, not a bot token.
Permissions
Stoat does not have an "Administrator" permission that grants everything at once. Permissions must be granted individually. There is no shortcut.
If you are running Ferry with an account that is not the server owner, that account's role must have the following permissions on the server and on each channel:
| Permission | Required for |
|---|---|
| ManageChannel | Creating and editing channels |
| ManageServer | Editing server settings and categories |
| ManagePermissions | Setting channel permission overrides |
| ManageRole | Displaying original author names with colours |
| ManageCustomisation | Uploading custom emoji |
| ViewChannel | Reading channels |
| ReadMessageHistory | Reading message history |
| SendMessage | Sending messages |
| ManageMessages | Pinning messages |
| SendEmbeds | Sending embed content |
| UploadFiles | Uploading attachments |
| Masquerade | Showing each message under its original Discord author's name and avatar |
| React | Adding reactions |
The simplest approach is to use the server owner's token and avoid this list entirely.
Voice Channels
Known issue: Bug #194
Voice channel creation may produce text channels instead of voice channels in some Stoat versions. This is a known upstream bug. If voice channel layout matters, check your Stoat version's release notes. You can verify channel types in the Stoat web interface after migration completes.
Voice channels require the Vortex (or LiveKit) service to function. Creating voice channels without this service will create the channel structure but the channels will not be usable for voice.
See Also
- Timestamp Preservation — understanding how message timestamps work after migration, and an advanced workaround for self-hosted instances.