Skip to content

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 over Revolt.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.