2018-05-19 01:12:18 +02:00
|
|
|
# Deploying bots in production
|
|
|
|
|
|
|
|
Usually, work on a bot starts on a laptop. At some point, you'll want
|
|
|
|
to deploy your bot in a production environment, so that it'll stay up
|
|
|
|
regardless of what's happening with your laptop. There are several
|
|
|
|
options for doing so:
|
|
|
|
|
|
|
|
* The simplest is running `zulip-run-bot` inside a `screen` session on
|
|
|
|
a server. This works, but if your server reboots, you'll need to
|
|
|
|
manually restart it, so we don't recommend it.
|
|
|
|
* Using `supervisord` or a similar tool for managing a production
|
|
|
|
process with `zulip-run-bot`. This consumes a bit of resources
|
|
|
|
(since you need a persistent process running), but otherwise works
|
|
|
|
great.
|
|
|
|
* Using the Zulip Botserver, which is a simple Flask server for
|
|
|
|
running a bot in production, and connecting that to Zulip's outgoing
|
|
|
|
webhooks feature. This can be deployed in environments like
|
2019-08-28 02:33:06 +02:00
|
|
|
Heroku's free tier without running a persistent process.
|
2018-05-19 01:12:18 +02:00
|
|
|
|
|
|
|
## Zulip Botserver
|
|
|
|
|
|
|
|
The Zulip Botserver is for people who want to
|
|
|
|
|
|
|
|
* run bots in production.
|
|
|
|
* run multiple bots at once.
|
|
|
|
|
|
|
|
The Zulip Botserver is a Python (Flask) server that implements Zulip's
|
2020-10-23 02:43:28 +02:00
|
|
|
outgoing webhooks API. You can of course write your own servers using
|
|
|
|
the outgoing webhooks API, but the Botserver is designed to make it
|
2018-05-19 01:12:18 +02:00
|
|
|
easy for a novice Python programmer to write a new bot and deploy it
|
|
|
|
in production.
|
|
|
|
|
2019-08-28 02:29:12 +02:00
|
|
|
### How Botserver works
|
|
|
|
|
|
|
|
Zulip Botserver starts a web server that listens to incoming messages
|
|
|
|
from your main Zulip server. The sequence of events in a successful
|
|
|
|
Botserver interaction are:
|
|
|
|
|
|
|
|
1. Your bot user is mentioned or receives a private message:
|
|
|
|
|
|
|
|
```
|
|
|
|
@**My Bot User** hello world
|
|
|
|
```
|
|
|
|
|
|
|
|
1. The Zulip server sends a POST request to the Botserver on `https://bot-server.example.com/`:
|
|
|
|
|
2021-05-26 18:48:00 +02:00
|
|
|
```json
|
2019-08-28 02:29:12 +02:00
|
|
|
{
|
|
|
|
"message":{
|
|
|
|
"content":"@**My Bot User** hello world",
|
|
|
|
},
|
|
|
|
"bot_email":"myuserbot-bot@example.com",
|
|
|
|
"trigger":"mention",
|
|
|
|
"token":"XXXX"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2020-10-23 02:43:28 +02:00
|
|
|
This URL is configured in the Zulip web-app in your Bot User's settings.
|
2019-08-28 02:29:12 +02:00
|
|
|
|
|
|
|
1. The Botserver searches for a bot to handle the message.
|
|
|
|
|
|
|
|
1. The Botserver executes your bot's `handle_message` code.
|
|
|
|
|
|
|
|
Your bot's code should work just like it does with `zulip-run-bot`;
|
|
|
|
for example, you reply using
|
|
|
|
[bot_handler.send_reply](writing-bots#bot_handlersend_reply)).
|
|
|
|
|
2018-05-19 01:12:18 +02:00
|
|
|
### Installing the Zulip Botserver
|
|
|
|
|
2019-08-24 00:50:22 +02:00
|
|
|
Install the `zulip_botserver` package:
|
2018-06-01 02:12:52 +02:00
|
|
|
|
2018-05-19 01:12:18 +02:00
|
|
|
```
|
2019-08-24 00:50:22 +02:00
|
|
|
pip3 install zulip_botserver
|
2018-05-19 01:12:18 +02:00
|
|
|
```
|
|
|
|
|
2018-05-25 19:59:21 +02:00
|
|
|
### Running a bot using the Zulip Botserver
|
2018-05-19 01:12:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
1. Construct the URL for your bot, which will be of the form:
|
|
|
|
|
|
|
|
```
|
2018-05-23 16:20:12 +02:00
|
|
|
http://<hostname>:<port>
|
2018-05-19 01:12:18 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
where the `hostname` is the hostname you'll be running the bot
|
|
|
|
server on, and `port` is the port for it (the recommended default
|
2018-05-23 16:20:12 +02:00
|
|
|
is `5002`).
|
2018-05-19 01:12:18 +02:00
|
|
|
|
|
|
|
1. Register new bot users on the Zulip server's web interface.
|
|
|
|
|
|
|
|
* Log in to the Zulip server.
|
2021-07-01 11:45:22 +02:00
|
|
|
* Navigate to *Personal settings (<i class="fa fa-cog"></i>)* -> *Bots* -> *Add a new bot*.
|
2018-05-19 01:12:18 +02:00
|
|
|
Select *Outgoing webhook* for bot type, fill out the form (using
|
|
|
|
the URL from above) and click on *Create bot*.
|
|
|
|
* A new bot user should appear in the *Active bots* panel.
|
|
|
|
|
2018-05-25 19:59:21 +02:00
|
|
|
1. Download the `zuliprc` file for your bot from the *Active Bots*
|
|
|
|
panel, using the download button.
|
|
|
|
|
2018-05-29 10:53:45 +02:00
|
|
|
1. Run the Botserver, where `helloworld` is the name of the bot you
|
2018-05-25 19:59:21 +02:00
|
|
|
want to run:
|
2018-06-01 02:12:52 +02:00
|
|
|
|
2018-06-01 13:48:56 +02:00
|
|
|
`zulip-botserver --config-file <path_to_zuliprc> --bot-name=helloworld`
|
2018-05-25 19:59:21 +02:00
|
|
|
|
|
|
|
You can specify the port number and various other options; run
|
2018-06-01 13:48:56 +02:00
|
|
|
`zulip-botserver --help` to see how to do this.
|
2018-05-25 19:59:21 +02:00
|
|
|
|
2018-05-29 10:53:45 +02:00
|
|
|
1. Congrats, everything is set up! Test your Botserver like you would
|
2018-05-25 19:59:21 +02:00
|
|
|
test a normal bot.
|
|
|
|
|
2018-05-29 10:53:45 +02:00
|
|
|
### Running multiple bots using the Zulip Botserver
|
2018-05-25 19:59:21 +02:00
|
|
|
|
2018-05-29 10:53:45 +02:00
|
|
|
The Zulip Botserver also supports running multiple bots from a single
|
|
|
|
Botserver process. You can do this with the following procedure.
|
2018-05-25 19:59:21 +02:00
|
|
|
|
2018-05-29 10:18:06 +02:00
|
|
|
1. Download the `botserverrc` from the `your-bots` settings page, using
|
2018-05-25 19:59:21 +02:00
|
|
|
the "Download config of all active outgoing webhook bots in Zulip
|
|
|
|
Botserver format." option at the top.
|
2018-05-23 16:20:12 +02:00
|
|
|
|
2018-05-29 10:18:06 +02:00
|
|
|
1. Open the `botserverrc`. It should contain one or more sections that look like this:
|
2018-07-07 21:23:52 +02:00
|
|
|
|
2018-06-01 02:12:52 +02:00
|
|
|
```
|
|
|
|
[]
|
|
|
|
email=foo-bot@hostname
|
|
|
|
key=dOHHlyqgpt5g0tVuVl6NHxDLlc9eFRX4
|
|
|
|
site=http://hostname
|
2018-06-01 13:36:23 +02:00
|
|
|
token=aQVQmSd6j6IHphJ9m1jhgHdbnhl5ZcsY
|
|
|
|
```
|
2018-07-07 21:23:52 +02:00
|
|
|
|
2018-06-01 13:36:23 +02:00
|
|
|
Each section contains the configuration for an outgoing webhook bot. For each
|
|
|
|
bot, enter the name of the bot you want to run in the square brackets `[]`.
|
|
|
|
For example, if we want `foo-bot@hostname` to run the `helloworld` bot, our
|
|
|
|
new section would look like this:
|
|
|
|
|
|
|
|
```
|
|
|
|
[helloworld]
|
|
|
|
email=foo-bot@hostname
|
|
|
|
key=dOHHlyqgpt5g0tVuVl6NHxDLlc9eFRX4
|
|
|
|
site=http://hostname
|
|
|
|
token=aQVQmSd6j6IHphJ9m1jhgHdbnhl5ZcsY
|
2018-06-01 02:12:52 +02:00
|
|
|
```
|
2018-05-25 19:59:21 +02:00
|
|
|
|
2019-08-28 02:42:49 +02:00
|
|
|
To run an external bot, enter the path to the bot's python file in the square
|
|
|
|
brackets `[]`. For example, if we want to run `~/Documents/my_new_bot.py`, our
|
|
|
|
new section could look like this:
|
|
|
|
|
|
|
|
```
|
|
|
|
[~/Documents/my_new_bot.py]
|
|
|
|
email=foo-bot@hostname
|
|
|
|
key=dOHHlyqgpt5g0tVuVl6NHxDLlc9eFRX4
|
|
|
|
site=http://hostname
|
|
|
|
```
|
|
|
|
|
2018-06-01 02:12:52 +02:00
|
|
|
1. Run the Zulip Botserver by passing the `botserverrc` to it. The
|
|
|
|
command format is:
|
|
|
|
|
|
|
|
```
|
2018-06-01 13:48:56 +02:00
|
|
|
zulip-botserver --config-file <path_to_botserverrc>
|
2018-06-01 02:12:52 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
If omitted, `hostname` defaults to `127.0.0.1` and `port` to `5002`.
|
2018-05-19 01:12:18 +02:00
|
|
|
|
|
|
|
### Running Zulip Botserver with supervisord
|
|
|
|
|
|
|
|
[supervisord](http://supervisord.org/) is a popular tool for running
|
|
|
|
services in production. It helps ensure the service starts on boot,
|
|
|
|
manages log files, restarts the service if it crashes, etc. This
|
|
|
|
section documents how to run the Zulip Botserver using *supervisord*.
|
|
|
|
|
|
|
|
Running the Zulip Botserver with *supervisord* works almost like
|
|
|
|
running it manually.
|
|
|
|
|
|
|
|
1. Install *supervisord* via your package manager; e.g. on Debian/Ubuntu:
|
2018-06-01 02:12:52 +02:00
|
|
|
|
|
|
|
```
|
|
|
|
sudo apt-get install supervisor
|
|
|
|
```
|
2018-05-19 01:12:18 +02:00
|
|
|
|
|
|
|
1. Configure *supervisord*. *supervisord* stores its configuration in
|
|
|
|
`/etc/supervisor/conf.d`.
|
|
|
|
* Do **one** of the following:
|
|
|
|
* Download the [sample config file][supervisord-config-file]
|
|
|
|
and store it in `/etc/supervisor/conf.d/zulip-botserver.conf`.
|
|
|
|
* Copy the following section into your existing supervisord config file.
|
|
|
|
|
2018-06-01 13:48:56 +02:00
|
|
|
[program:zulip-botserver]
|
|
|
|
command=zulip-botserver --config-file=<path/to/your/botserverrc>
|
2018-05-19 01:12:18 +02:00
|
|
|
--hostname <address> --port <port>
|
|
|
|
startsecs=3
|
2018-05-29 10:53:45 +02:00
|
|
|
stdout_logfile=/var/log/zulip-botserver.log ; all output of your Botserver will be logged here
|
2018-05-19 01:12:18 +02:00
|
|
|
redirect_stderr=true
|
|
|
|
|
|
|
|
* Edit the `<>` sections according to your preferences.
|
|
|
|
|
2021-08-31 23:32:37 +02:00
|
|
|
[supervisord-config-file]: https://raw.githubusercontent.com/zulip/python-zulip-api/main/zulip_botserver/zulip-botserver-supervisord.conf
|
2018-05-19 01:12:18 +02:00
|
|
|
|
|
|
|
1. Update *supervisord* to read the configuration file:
|
2018-06-01 02:12:52 +02:00
|
|
|
|
|
|
|
```
|
|
|
|
supervisorctl reread
|
|
|
|
supervisorctl update
|
|
|
|
```
|
|
|
|
|
|
|
|
(or you can use `/etc/init.d/supervisord restart`, but this is less
|
|
|
|
disruptive if you're using *supervisord* for other services as well).
|
2018-05-19 01:12:18 +02:00
|
|
|
|
|
|
|
1. Test if your setup is successful:
|
|
|
|
|
2018-06-01 02:12:52 +02:00
|
|
|
```
|
|
|
|
supervisorctl status
|
|
|
|
```
|
|
|
|
|
|
|
|
The output should include a line similar to this:
|
2018-06-01 13:48:56 +02:00
|
|
|
> zulip-botserver RUNNING pid 28154, uptime 0:00:27
|
2018-05-19 01:12:18 +02:00
|
|
|
|
2018-06-01 02:12:52 +02:00
|
|
|
The standard output of the Botserver will be logged to the path in
|
|
|
|
your *supervisord* configuration.
|
2019-08-28 02:30:57 +02:00
|
|
|
|
|
|
|
If you are hosting the Botserver yourself (as opposed to using a
|
|
|
|
hosting service that provides SSL), we recommend securing your
|
|
|
|
Botserver with SSL using an `nginx` or `Apache` reverse proxy and
|
|
|
|
[Certbot](https://certbot.eff.org/).
|
|
|
|
|
|
|
|
### Troubleshooting
|
|
|
|
|
2020-10-23 02:43:28 +02:00
|
|
|
1. Make sure the API key you're using is for an [outgoing webhook
|
2020-05-20 20:47:44 +02:00
|
|
|
bot](/api/outgoing-webhooks) and you've
|
2019-08-28 02:30:57 +02:00
|
|
|
correctly configured the URL for your Botserver.
|
|
|
|
|
|
|
|
1. Your Botserver needs to be accessible from your Zulip server over
|
|
|
|
HTTP(S). Make sure any firewall allows the connection. We
|
|
|
|
recommend using [zulip-run-bot](running-bots) instead for
|
|
|
|
development/testing on a laptop or other non-server system.
|
|
|
|
|
|
|
|
If your Zulip server is self-hosted, you can test by running `curl
|
|
|
|
http://zulipbotserver.example.com:5002` from your Zulip server;
|
|
|
|
the output should be:
|
|
|
|
|
|
|
|
```
|
|
|
|
$ curl http://zulipbotserver.example.com:5002/
|
|
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
|
|
<title>405 Method Not Allowed</title>
|
|
|
|
<h1>Method Not Allowed</h1>
|
|
|
|
<p>The method is not allowed for the requested URL.</p>
|
|
|
|
```
|