Hosting a Python Discord Bot for Free with Fly.io

Jonah LawrenceJonah Lawrence
4 min read

Intro

As Heroku is no longer going to be free after November 28, 2022, I am sharing another way to host a Discord bot 24/7 for free.

You will be able to host any kind of bot on Fly.io with few limitations by following the steps below. You can also optionally attach a PostgreSQL database for storing data.

Deploying a Python Discord Bot to Fly.io

This article was originally a video tutorial, which you can check out here:

1. Install the flyctl command line tool

If you have the Homebrew package manager installed, flyctl can be installed by running:

brew install flyctl

If not, you can run the install script:

curl -L https://fly.io/install.sh | sh

Windows

Run the Powershell install script:

iwr https://fly.io/install.ps1 -useb | iex

Arch Linux

Run the package installer:

yay -S flyctl-bin

Linux

Run the install script:

curl -L https://fly.io/install.sh | sh

More info: https://fly.io/docs/getting-started/installing-flyctl/

2. Create an account by running flyctl auth signup and finishing through the browser

After installing flyctl, you should now be able to use it in the command line. Use flyctl auth signup to launch your browser and complete the account creation steps. If you already have an account, you can use flyctl auth login.

3. Add a Dockerfile with the Python version and dependency install method

Method 1: requirements.txt

Create a list of your dependencies in a requirements.txt. You can find out what you have installed using pip freeze.

Discord.py example:

discord.py>=2.0.0,<3
python-dotenv==0.20.0

Nextcord example:

nextcord>=2.5.0,<3
python-dotenv==0.20.0

To tell Fly.io to install these dependencies, create a file called Dockerfile (no file extension) with the following contents:

FROM python:3.10
WORKDIR /bot
COPY requirements.txt /bot/
RUN pip install -r requirements.txt
COPY . /bot
CMD python bot.py

In this case python bot.py is the command used to run the bot. If your bot starts in a different file, you should change that here.

Method 2: Using Poetry

If you are using Poetry for dependencies, your Dockerfile will look more like this:

FROM python:3.10
RUN pip install poetry
WORKDIR /bot
COPY poetry.lock pyproject.toml /bot/
RUN poetry config virtualenvs.create false && poetry install --no-interaction --no-ansi
COPY . /bot
CMD python bot.py

(Poetry Dockerfile is based on this tutorial by Replicate.com)

4. flyctl launch

In the project folder, run flyctl launch

Give your project a name, type Y or N depending on if you want a Postgresql database or not, type N to not have it deploy.

This will create a fly.toml, but you can delete most of it so that it looks similar to this:

app = "my-bot-name"  # your bot's app name
primary_region = "den"  # a region of your choice

[[services]]
  internal_port = 8080
  protocol = "tcp"
  auto_start_machines = true
  auto_stop_machines = false  # prevent automatic suspension
  min_machines_running = 1  # keep a machine running at all times

5. flyctl deploy

Type flyctl deploy to deploy the first version!

Once it is completed, your bot will be running on Fly.io!

6. Set the environment vars

If you will be deploying your bot without your .env or configuration files, you will need to set secrets for fly.io to know about.

This will include all environment variables, for example:

flyctl secrets set 'DISCORD_TOKEN=My.TOken.3213.example' 'LOG_CHANNEL_ID=1234567890'

See https://fly.io/docs/reference/secrets/#setting-secrets

You're done!

To deploy further versions, you can run flyctl deploy or see below for automatic deploys from GitHub.

Note: If your bot is responding to commands twice, this may mean your bot is running on multiple machines. To fix this, try running the command fly scale count 1 to remove the extra machine(s). Also, you should ensure your bot is only running in one location; you should not run the bot on fly.io and locally or on another host at the same time.

Keep in mind that only shared-cpu-1x 256mb VMs are included for free. Run fly scale show to identify the VM resources you are using and update a group by name to be free using fly scale vm shared-cpu-1x --group app.


Continuous deployment from GitHub

You can find the video for this part here:

  1. Run flyctl auth token to get a Fly API token

  2. Go to your repo's Settings > Secrets > Actions and click New repository secret

  3. Enter FLY_API_TOKEN as the name and your token from step 1 as the value

  4. Create a folder, .github/workflows/ and inside create a file that uses the flyctl action on push. You may name it what you like, for example, fly.yml.

Example fly.yml:

name: Fly Deploy
on:
  push:
    branches:
      - main

env:
  FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

jobs:
  deploy:
    name: Deploy app
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: flyctl deploy --remote-only

Make sure the branch name is correct for your default branch.

More info: https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/


Conclusion

Thanks for reading!

I hope you found this tutorial useful.

Check out the full videos for further explanations and be sure to like and subscribe!

Part 1 (Setup and Hosting) - https://youtu.be/J7Fm7MdZn_E

Part 2 (Continuous Deployment) - https://youtu.be/6u9BrDaSHJc

- Jonah Lawrence

GitHub: DenverCoder1

YouTube: Jonah Lawrence - Dev Pro Tips

Discord server: https://discord.gg/fPrdqh3Zfu

5
Subscribe to my newsletter

Read articles from Jonah Lawrence directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jonah Lawrence
Jonah Lawrence

๐Ÿ’ป Full Stack Dev ๐ŸŽจ UI designer ๐ŸŽ“ Student ๐Ÿ“บ Youtuber @ youtube.com/DevProTips ๐Ÿ™ git.io/DenverCoder1