diff --git a/README.md b/README.md index 62bf39f..f4a5c5c 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,8 @@ This distribution includes some examples that can be run out of the box using an ## See also +- [How to run Beekeeper pools as systemd services](./doc/Install.md). + - [Notes about supported MQTT brokers](./doc/Brokers.md) configuration. - [Diagram of message routing](https://raw.githubusercontent.com/jmico/beekeeper/master/doc/images/routing.svg) @@ -241,7 +243,7 @@ This distribution includes some examples that can be run out of the box using an ## Dependencies -This framework requires `Anyevent`, `JSON::XS`, `Term::ReadKey`, `Net::SSLeay` and `ps`. +This framework requires `Anyevent`, `JSON::XS`, `Net::SSLeay`, `Term::ReadKey` and `ps`. To install these dependencies on a Debian system run: ``` diff --git a/doc/Install.md b/doc/Install.md new file mode 100644 index 0000000..930f0c2 --- /dev/null +++ b/doc/Install.md @@ -0,0 +1,59 @@ +## How to run Beekeeper pools as systemd services + +Install Beekeeper dependencies: +``` +# apt install libanyevent-perl libjson-xs-perl libnet-ssleay-perl libterm-readkey-perl procps +``` +Install Beekeeper from CPAN: +``` +# apt install make cpanminus +# cpanm --sudo --notest Beekeeper +``` +Create an user `beekeeper`: +``` +# adduser beekeeper +``` +Copy the provided configuration templates: +``` +# cd /tmp +# git clone https://github.com/jmico/beekeeper.git + +# mkdir /etc/beekeeper +# cp beekeeper/doc/config/beekeeper/*.config.json /etc/beekeeper/ +# cp beekeeper/doc/config/beekeeper/*.environment /etc/beekeeper/ +# chown beekeeper: /etc/beekeeper/* +# chmod 0600 /etc/beekeeper/* + +# cp beekeeper/doc/config/beekeeper/beekeeper.logrotate /etc/logrotate/beekeeper +# cp beekeeper/doc/config/beekeeper/beekeeper@.service /lib/systemd/system/ +# systemctl daemon-reload +``` +Copy the examples to `/home/beekeeper`: +``` +# cp beekeeper/doc/config/beekeeper/myapp /home/beekeeper/ +# cp beekeeper/examples /home/beekeeper/ +# chown -R beekeeper: /home/beekeeper/myapp /home/beekeeper/examples +``` +Edit `pool.config.json` and `bus.config.json` as needed, and ensure that credentials are correct: +``` +# nano /etc/beekeeper/pool.config.json +# nano /etc/beekeeper/bus.config.json +``` +When starting a service `beekeeper@{POOL_ID}` the provided systemd unit template loads `PERL5LIB` +and any other environment variable from `{POOL_ID}.environment`, then starts the pool `{POOL_ID}` +defined in `pool.config.json`. + +Start the test pool `myapp`: +``` +# service beekeeper@myapp start +``` +Check that everything is ok: +``` +# service beekeeper@myapp status +# tail /var/log/beekeeper/myapp.pool.log +# bkpr-top -b +``` +Enable the service to start it at boot: +``` +# systemctl enable beekeeper@myapp +``` diff --git a/doc/config/beekeeper/beekeeper.logrotate b/doc/config/beekeeper/beekeeper.logrotate new file mode 100644 index 0000000..6b7399a --- /dev/null +++ b/doc/config/beekeeper/beekeeper.logrotate @@ -0,0 +1,8 @@ +/var/log/beekeeper/* { + rotate 10 + daily + compress + size 1M + missingok + copytruncate +} diff --git a/doc/config/beekeeper/beekeeper@.service b/doc/config/beekeeper/beekeeper@.service new file mode 100644 index 0000000..c64e02f --- /dev/null +++ b/doc/config/beekeeper/beekeeper@.service @@ -0,0 +1,26 @@ +[Unit] +Description=Beekeeper pool +After=network.target +Wants=network.target + +[Service] +Type=forking +PIDFile=/run/beekeeper/beekeeper-%i.pid + +User=beekeeper +Group=beekeeper + +ExecStartPre=+/bin/mkdir -m 740 -p /run/beekeeper +ExecStartPre=+/bin/chown beekeeper /run/beekeeper +ExecStartPre=+/bin/mkdir -m 740 -p /var/log/beekeeper +ExecStartPre=+/bin/chown beekeeper /var/log/beekeeper + +EnvironmentFile=-/etc/beekeeper/%i.environment + +ExecStart=/bin/sh -c 'bkpr --pool "%i" start' +ExecReload=/bin/sh -c 'bkpr --pool "%i" restart' +ExecStop=/bin/sh -c 'bkpr --pool "%i" stop' + +[Install] +WantedBy=multi-user.target + diff --git a/doc/config/beekeeper/bus.config.json b/doc/config/beekeeper/bus.config.json new file mode 100644 index 0000000..5e5382f --- /dev/null +++ b/doc/config/beekeeper/bus.config.json @@ -0,0 +1,34 @@ +# This file is in relaxed JSON format (it allows comments and trailing commas). +# +# Logical buses used in pool.config.json must be defined here, specifying the +# conection parameters to the MQTT broker that will service them. +# +# Each bus definition accepts the following parameters: +# +# - bus_id : unique identifier of the logical bus (required) +# - bus_role : specifies if the bus is acting as frontend or backend +# - host : hostname or IP address of the broker (default is localhost) +# - port : port of the broker (default is 1883) +# - tls : if set to true enables the use of TLS on broker connection +# - username : username used to connect to the broker +# - password : password used to connect to the broker + +[ + { + "bus_id" : "backend-1", + "bus_role" : "backend", + "host" : "localhost", + "port" : 1883, + "username" : "backend", + "password" : "def456", + "default" : 1, + }, + { + "bus_id" : "frontend-1", + "bus_role" : "frontend", + "host" : "localhost", + "port" : 11883, + "username" : "router", + "password" : "ghi789", + }, +] diff --git a/doc/config/beekeeper/dashboard.config.json b/doc/config/beekeeper/dashboard.config.json new file mode 100644 index 0000000..9a50b53 --- /dev/null +++ b/doc/config/beekeeper/dashboard.config.json @@ -0,0 +1,13 @@ +# This file is in relaxed JSON format (it allows comments and trailing commas). +# +# This is the config file used by Beekeeper::Service::Dashboard::Worker. +# +# Use the following command to hash passwords of dashboard users: +# +# $ echo "Username:" && read U && echo "Password:" && read -s P && echo -n "Dashboard$U$P" | shasum -a 256 && U= P= + +{ + "users": { + "admin": { "password": "fa4b54aab361e08b95965eb34ccb62099b84e1fc57c74ac3e709c2570f782a2c" }, + }, +} diff --git a/doc/config/beekeeper/dashboard.environment b/doc/config/beekeeper/dashboard.environment new file mode 100644 index 0000000..cdbea0b --- /dev/null +++ b/doc/config/beekeeper/dashboard.environment @@ -0,0 +1 @@ +PERL5LIB=/home/beekeeper/examples/dashboard/lib diff --git a/doc/config/beekeeper/examples.environment b/doc/config/beekeeper/examples.environment new file mode 100644 index 0000000..698ab32 --- /dev/null +++ b/doc/config/beekeeper/examples.environment @@ -0,0 +1,5 @@ +PERL5LIB=\ +/home/beekeeper/beekeeper/examples/chat/lib:\ +/home/beekeeper/beekeeper/examples/flood/lib:\ +/home/beekeeper/beekeeper/examples/scraper/lib:\ +/home/beekeeper/beekeeper/examples/websocket/lib diff --git a/doc/config/beekeeper/myapp.environment b/doc/config/beekeeper/myapp.environment new file mode 100644 index 0000000..ab017d4 --- /dev/null +++ b/doc/config/beekeeper/myapp.environment @@ -0,0 +1 @@ +PERL5LIB=/home/beekeeper/myapp/lib diff --git a/doc/config/beekeeper/myapp/lib/MyApp/Test.pm b/doc/config/beekeeper/myapp/lib/MyApp/Test.pm new file mode 100644 index 0000000..c2a2028 --- /dev/null +++ b/doc/config/beekeeper/myapp/lib/MyApp/Test.pm @@ -0,0 +1,48 @@ +package MyApp::Test; + +use strict; +use warnings; + +use Beekeeper::Worker ':log'; +use base 'Beekeeper::Worker'; + + +sub authorize_request { + my ($self, $req) = @_; + + return BKPR_REQUEST_AUTHORIZED; +} + +sub on_startup { + my $self = shift; + + $self->accept_remote_calls( + 'myapp.test.echo' => 'echo', + ); + + $self->accept_notifications( + 'myapp.test.msg' => 'message', + ); + + log_info "Ready"; +} + +sub on_shutdown { + my $self = shift; + + log_info "Stopped"; +} + + +sub echo { + my ($self, $params) = @_; + + return $params; +} + +sub message { + my ($self, $params) = @_; +} + +1; + diff --git a/doc/config/beekeeper/pool.config.json b/doc/config/beekeeper/pool.config.json new file mode 100644 index 0000000..ebf1aeb --- /dev/null +++ b/doc/config/beekeeper/pool.config.json @@ -0,0 +1,51 @@ +# This file is in relaxed JSON format (it allows comments and trailing commas). +# +# All worker pools running on this host must be defined here, specifying +# which logical bus should be used and which services it will run. +# +# Each pool definition must contain the following parameters: +# +# - pool_id : arbitrary identifier of worker pool +# - bus_id : identifier of logical bus used by worker processes +# - workers : a map of worker classes and its config hashes +# +# To start the worker pool use the "bkpr" command: +# +# $ bkpr --pool "myapp" start + +[ + { + "pool_id" : "myapp", + "bus_id" : "backend-1", + "description" : "pool of MyApp workers", + + "workers" : { + "MyApp::Test" : { "worker_count" : 2 }, + }, + }, + { + "pool_id" : "dashboard", + "bus_id" : "backend-1", + "description" : "pool of Dashboard workers", + + "workers" : { + "Beekeeper::Service::Dashboard::Worker" : { "worker_count" : 1 }, + "Beekeeper::Service::LogTail::Worker" : { "worker_count" : 1 }, + "Beekeeper::Service::Router::Worker" : { "worker_count" : 1 }, + }, + }, + { + "pool_id" : "examples", + "bus_id" : "backend-1", + "description" : "pool of Beekeeper examples", + + "workers" : { + "MyApp::Service::Chat::Worker" : { "worker_count" : 2 }, + "MyApp::Service::Auth::Worker" : { "worker_count" : 2 }, + "MyApp::Service::Calculator" : { "worker_count" : 2 }, + "MyApp::Service::Flood::Worker" : { "worker_count" : 2 }, + "MyApp::Service::Scraper::Worker" : { "worker_count" : 2 }, + "Beekeeper::Service::Router::Worker" : { "worker_count" : 2 }, + }, + }, +] diff --git a/lib/Beekeeper.pm b/lib/Beekeeper.pm index 7dd13a6..b9d2f90 100644 --- a/lib/Beekeeper.pm +++ b/lib/Beekeeper.pm @@ -314,6 +314,8 @@ C is an HTML dashboard for Beekeeper projects. =head1 SEE ALSO +L. + L configuration. L between clients, workers and buses.