2020-04-01 11:09:10 +00:00
#!/bin/bash
panic( ) { echo -e " $@ " ; echo "Exiting." ; exit 2; }
spacer( ) { echo -e "\n - - - - - - - - - " ; }
info( ) { echo -e " \e[0;32m $@ \e[0m " ; }
[ [ "root" = = $( whoami) ] ] || panic "Must run as root."
## PACKAGES MANAGEMENT
packageList = ( )
packageList += ( "certbot" )
packageList += ( "nginx" )
packageList += ( "pwgen" )
packageList += ( "python-pip" )
packageList += ( "python3-minimal" )
packageList += ( "python3-distutils" )
packageList += ( "sqlite3" )
packageList += ( "virtualenv" )
info "Updating packages informations"
apt-get update >/dev/null
info " Installing packages ${ packageList [@] } "
apt-get install --no-install-recommends -y ${ packageList [@] } >/dev/null
## CONFIG MANAGEMENT
info "OK, time for some questions."
default_pass = $( pwgen -s 16 1)
[ [ -f ./config ] ] && source ./config
spacer
[ [ -z " $domain " ] ] && read -p "Which domain will be used to connect to your bot (ex: maubot.example.com)? " domain
[ [ -z " $domain " ] ] && panic "You must provide a domain"
spacer
[ [ -z " $home_server " ] ] && read -e -i "matrix.com" -p "Which domain is the matrix 'Home Server' you register your bots on? " home_server
[ [ -z " $home_server " ] ] && panic "You must provide a matrix server"
spacer
[ [ -z " $maubot_user " ] ] && read -e -i "maubot" -p "What will be your user name in the maubot interface? " maubot_user
[ [ -z " $maubot_user " ] ] && panic "You must give a valid username"
spacer
[ [ -z " $maubot_pass " ] ] && read -e -i $default_pass -p " What will be the pass for user ' $maubot_user ' in the maubot interface? " maubot_pass
[ [ -z " $maubot_pass " ] ] && panic "You must give a valid password"
spacer
[ [ -z " $ssl " ] ] && read -e -i "y" -n 1 -p "Do you want to enable SSL via letsencrypt [Y/n]? " ssl
ssl = ${ ssl :- y }
spacer
[ [ -z " $synapse_shared_registration_secret " ] ] && read -p "If the 'Home Server' is yours, what is the registration secret (ignore if you don't know what this is)? " synapse_shared_registration_secret
synapse_shared_registration_secret = ${ synapse_shared_registration_secret :- synapse_shared_registration_secret }
spacer
[ [ -z " $install_dir " ] ] && read -e -i "/opt/maubot" -p "Which install dir to use (Default: /opt/maubot)? " install_dir
install_dir = ${ install_dir :- /opt/maubot }
spacer
[ [ -z " $unix_user " ] ] && read -e -i "www-data" -p "Which unix user will own and execute the maubot code? " unix_user
unix_user = ${ unix_user :- www -data }
spacer
## NGINX DEPLOYEMENT
info "Deploying nginx"
cat << HEREDOC > /etc/nginx/sites-available/maubot.conf
server {
listen 80;
server_name $domain ;
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain" ;
root /var/www/letsencrypt;
}
location /_matrix/maubot/v1/logs {
proxy_pass http://localhost:29316;
proxy_http_version 1.1;
proxy_set_header Upgrade \$ http_upgrade;
proxy_set_header Connection "Upgrade" ;
proxy_set_header X-Forwarded-For \$ remote_addr;
}
location /_matrix/maubot {
proxy_pass http://localhost:29316;
proxy_set_header X-Forwarded-For \$ remote_addr;
}
location / {
rewrite ^( .*) http://\$ server_name/_matrix/maubot/ permanent;
}
}
HEREDOC
ln -s /etc/nginx/sites-available/maubot.conf /etc/nginx/sites-enabled/
service nginx reload
if [ [ "Y" = = ${ ssl ^^ } ] ] ; then
info "Retrieving letsencrypt certificate"
mkdir -p /var/www/letsencrypt/.well-known/acme-challenge/
[ [ -f /etc/letsencrypt/live/$domain /fullchain.pem ] ] || /usr/bin/letsencrypt certonly --webroot --agree-tos -w /var/www/letsencrypt/ --email " domains@ $domain " --expand -d $domain >/dev/null
[ [ -f /etc/letsencrypt/live/$domain /fullchain.pem ] ] || panic " Failed to get a certificate for domain $domain . "
cat << HEREDOC > /etc/nginx/sites-available/maubot.conf
server {
listen 80;
server_name $domain ;
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain" ;
root /var/www/letsencrypt;
}
location / {
rewrite ^( .*) https://\$ server_name\$ 1 permanent;
}
}
server {
listen 443 ssl;
server_name $domain ;
access_log /var/log/nginx/maubot.access.log;
error_log /var/log/nginx/maubot.error.log;
ssl on;
ssl_certificate /etc/letsencrypt/live/$domain /fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$domain /privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
ssl_prefer_server_ciphers on;
location /_matrix/maubot/v1/logs {
proxy_pass http://localhost:29316;
proxy_http_version 1.1;
proxy_set_header Upgrade \$ http_upgrade;
proxy_set_header Connection "Upgrade" ;
proxy_set_header X-Forwarded-For \$ remote_addr;
}
location /_matrix/maubot {
proxy_pass http://localhost:29316;
proxy_set_header X-Forwarded-For \$ remote_addr;
}
location / {
rewrite ^( .*) https://\$ server_name/_matrix/maubot/ permanent;
}
}
HEREDOC
service nginx reload
fi
# MAUBOT DEPLOYMENT
info "Installing maubot"
mkdir -p " $install_dir "
cd " $install_dir "
virtualenv -p /usr/bin/python3 . >/dev/null
source $install_dir /bin/activate
info "Installing maubot dependencies"
pip install --upgrade maubot >/dev/null
mkdir -p $install_dir /{ plugins,trash,logs}
cat << HEREDOC > " $install_dir /config.yaml "
# The full URI to the database. SQLite and Postgres are fully supported.
# Other DBMSes supported by SQLAlchemy may or may not work.
# Format examples:
# SQLite: sqlite:///filename.db
# Postgres: postgres://username:password@hostname/dbname
database: sqlite:///maubot.db
plugin_directories:
# The directory where uploaded new plugins should be stored.
upload: ./plugins
# The directories from which plugins should be loaded.
# Duplicate plugin IDs will be moved to the trash.
load:
- ./plugins
# The directory where old plugin versions and conflicting plugins should be moved.
# Set to "delete" to delete files immediately.
trash: ./trash
# The directory where plugin databases should be stored.
db: ./plugins
server:
# The IP and port to listen to.
hostname: 0.0.0.0
port: 29316
# Public base URL where the server is visible.
public_url: https://$domain
# The base management API path.
base_path: /_matrix/maubot/v1
# The base path for the UI.
ui_base_path: /_matrix/maubot
# The base path for plugin endpoints. The instance ID will be appended directly.
plugin_base_path: /_matrix/maubot/plugin/
# Override path from where to load UI resources.
# Set to false to using pkg_resources to find the path.
override_resource_path: false
# The base appservice API path. Use / for legacy appservice API and /_matrix/app/v1 for v1.
appservice_base_path: /_matrix/app/v1
# The shared secret to sign API access tokens.
# Set to "generate" to generate and save a new token at startup.
unshared_secret: generate
# Shared registration secrets to allow registering new users from the management UI
registration_secrets:
2020-04-01 11:54:49 +00:00
$home_server :
2020-04-01 11:09:10 +00:00
# Client-server API URL
url: https://$home_server
# registration_shared_secret from synapse config
secret: $synapse_shared_registration_secret
# List of administrator users. Plaintext passwords will be bcrypted on startup. Set empty password
# to prevent normal login. Root is a special user that can't have a password and will always exist.
admins:
root: ""
$maubot_user : " $maubot_pass "
# API feature switches.
api_features:
login: true
plugin: true
plugin_upload: true
instance: true
instance_database: true
client: true
client_proxy: true
client_auth: true
dev_open: true
log: true
# Python logging configuration.
#
# See section 16.7.2 of the Python documentation for more info:
# https://docs.python.org/3.6/library/logging.config.html#configuration-dictionary-schema
logging:
version: 1
formatters:
colored:
( ) : maubot.lib.color_log.ColorFormatter
format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s"
normal:
format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s"
handlers:
file:
class: logging.handlers.RotatingFileHandler
formatter: normal
filename: ./maubot.log
maxBytes: 10485760
backupCount: 10
console:
class: logging.StreamHandler
formatter: colored
loggers:
maubot:
level: DEBUG
mautrix:
level: DEBUG
aiohttp:
level: INFO
root:
level: DEBUG
handlers: [ file, console]
HEREDOC
info "Configure database"
alembic -x config = $install_dir /config.yaml upgrade head >/dev/null
# SYSTEMD MANAGEMENT
info "Installing systemd maubot service"
cat << HEREDOC > /etc/systemd/system/maubot.service
[ Unit]
Description = Maubot web interface
Documentation = https://github.com/maubot/maubot
Requires = network.target
After = network.target
[ Service]
WorkingDirectory = $install_dir
Type = simple
User = www-data
ExecStart = $install_dir /bin/python3 -m maubot
[ Install]
WantedBy = multi-user.target
HEREDOC
touch " $install_dir /maubot.log "
chown -R " $unix_user " " $install_dir "
systemctl daemon-reload
systemctl enable maubot
systemctl start maubot
info "Check your service state with 'systemctl status maubot'"
echo -e " \n\nCongratulations, you can now head to http:// $domain and use your $maubot_user : $maubot_pass authentication, which of course you should save for future use ;) \n\n "