Guide

Deploy a Discord bot from GitHub

Uploading files by hand works until the day you forget one. Deploying from Git means the server runs exactly what is in your repository, and updating is a push.

6 minute read

Get the repository ready

Before anything is deployed from it, make sure the repository cannot leak your bot.

  • No token in any file, in any commit. Read it from an environment variable (os.environ["BOT_TOKEN"] or process.env.BOT_TOKEN). If a token was ever committed, removing it in a new commit is not enough: it is still in the history. Reset it in the Developer Portal. More on token leaks.
  • A .gitignore with at least .env, node_modules/, venv/, __pycache__/, and any database or data file the bot writes.
  • Dependencies listed: requirements.txt, or package.json with its lock file.
  • Data files out of Git. A data.json that the bot writes and that is also committed will conflict with the next deploy. Commit an example (data.example.json) and ignore the real one.

Public or private?

A public repository needs no credentials to clone, which makes deploying simple. A private one needs a credential, and the safest kind is one that can do as little as possible:

  • GitHub fine-grained token: Settings, Developer settings, Personal access tokens, Fine-grained tokens. Give it access to only that repository and only Contents: Read-only, with an expiry date. If it leaks, someone can read one repository and nothing else.
  • Deploy key: an SSH key added to one repository under its Settings, read-only by default. Good on your own server, where you control the key file.

Avoid classic tokens with the repo scope for this. They can read and write every repository you have.

On your own server

The basic loop is clone once, then pull and restart:

git clone https://github.com/you/your-bot.git /opt/mybot/app
# later, to deploy:
git -C /opt/mybot/app pull --ff-only
sudo systemctl restart mybot

--ff-only refuses to merge if someone edited files on the server, instead of making a mess of them. To deploy on push, a GitHub Actions workflow can SSH in and run those two commands; store the SSH key in the repository's secrets, and give that key a user that can do nothing but this. The systemd guide covers the service itself.

On a bot host

Most hosts that support Git ask for the repository link, a branch, and a token for private repositories, then clone on install or start. Things worth checking before you rely on one:

  • Does it pull on every restart, or only when you reinstall?
  • What happens to files you edited on the server? Some hosts reset them silently.
  • What happens to files your bot created, like a database? They should survive every deploy.
  • Is the token stored somewhere other people with access to the server can see? Then it must be read-only.

On SnowServers

Paste the repository link into Git repository on the Startup tab and restart. The first start clones it; every start after that pulls new commits, and only reinstalls packages if requirements.txt or package.json changed. Files you edited on the server are never overwritten (the update is skipped and the console says which file), and files your bot created are left alone. Private repositories take a read-only token. To restart automatically on push, a short GitHub Actions workflow can call the panel's API. All of it is in the Git deploy docs, and Flurry is $3 a month with a 7-day free trial.