six demon bag
Wind, fire, all that kind of thing!
2020-06-11
Installing Discourse on Devuan
Before deciding on setting up my Q&A site with Question2Answer I evaluated several programs, one of them being Discourse. And even though I ultimately decided against Discourse (because the setup was too complex and it doesn't have all the features I wanted) I don't want my experiences go to waste, so I'll publish them here.
The setup basically consists of 5 parts:
- Ruby
- PostgreSQL (for persistent data)
- Redis (for volatile data, like scheduled jobs, sessions, ...)
- Discourse (duh)
- Nginx (or another web server that can reverse-proxy connections)
I started with this guide, because I think Docker (the official deployment format for Discourse) is a poor choice for any stateful service. However, I had to make several adjustments to make things work.
Ruby
The first thing you need for a successful Discourse setup is a recent enough Ruby interpreter. Since the one shipped with Debian-based systems like Devuan is too old you need to manually install a more recent version. There are several ways to do that, but I chose the rvm
approach for simplicity (even though that's a relative term for anything Ruby).
First download the installer for rvm
:
apt-get install dirmngr
gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io -o rvm-installer
chmod a+x rvm-installer
After you verified that the script rvm-installer
won't do anything nasty on your system (never run curl | bash
, no matter how convenient that may seem) run the following command to install rvm
:
./rvm-installer stable
Then use rvm
to install Ruby:
. /etc/profile.d/rvm.sh
rvm install ruby
rvm --default use ruby
If you want you can also generate the Ruby documentation:
rvm docs generate-ri
PostgreSQL
Install PostgreSQL. The package postgresql-contrib
is required for the hstore
and pg_trgm
extensions. The dev package is needed for the Discourse setup later on. To improve security you should require authentication even for local logins (see line 3).
pg_version='9.6'
apt-get install postgresql postgresql-contrib postgresql-server-dev-${pg_version}
sed -i -e 's/^\(local\s\+all\s\+all\s*\)$/\1 md5/' /etc/postgresql/${pg_version}/main/pg_hba.conf
service postgresql restart
Create a database user and database for Discourse:
su - postgres -c 'createuser --encrypted --pwprompt discourse'
su - postgres -c 'createdb --owner discourse discourse'
su - postgres -c "psql -c 'CREATE EXTENSION hstore; CREATE EXTENSION pg_trgm;' discourse"
Write down the password you specified when creating the database user as you need to put that into the Discourse config later on.
Redis
You need the package redis-server
from backports, because the version that ships with Devuan Ascii is too old for Sidekiq.
cat <<EOF >/etc/apt/preferences.d/redis.pref
Package: redis-*
Pin: release a=stable-backports
Pin-Priority: 1000
EOF
apt-get install redis-server
Discourse
Create a service account so you can run Discourse as a dedicated user:
adduser --system --group --home /srv/discourse --shell /bin/bash --gecos 'Discourse Service User' --disabled-password discourse
You'll need a Git client, and Discourse also requires some helper applications:
apt-get install git brotli imagemagick
Clone the Discourse Git repository and check out the desired version (at the time I evaluated the software the stable version was 2.4.4).
git clone https://github.com/discourse/discourse.git /srv/discourse
git checkout 'v2.4.4'
Create the subdirectories sockets
and pids
in /srv/discourse/tmp
, since they won't be created automatically and their absence would cause some breakage.
mkdir -p /srv/discourse/tmp/sockets
mkdir -p /srv/discourse/tmp/pids
Now you're ready to actually set up Discourse.
cd /srv/discourse
RAILS_ENV=production bundle install
cp config/discourse_defaults.conf config/discourse.conf
chown -R discourse: /srv/discourse
Edit /srv/discourse/config/discourse.conf
. At the very least you need to fill in the following parameters (replace the highlighted values with the appropriate values for your environment; the database password is the one you specified when creating the database user):
db_host = localhost
db_username = discourse
db_password = PASSWORD
hostname = 'dis.example.org'
smtp_address = localhost
smtp_domain = 'example.org'
smtp_enable_start_tls = false
Note: The mail settings assume that you have a local mail server (like Postfix) or a local mail relay (like sSMTP) to accept and forward mail. If your mail setup is different from that you need to adjust the mail parameters accordingly.
Become the user "discourse" (su - discourse
) and run the following command to prime the database, precompile the Discourse assets (you need to fix the brotli
commandline parameters first, though), and create an admin user:
RAILS_ENV=production bundle exec rake db:migrate
sed -i -e '/brotli -f/ s/=/ /g; s/\(quality}\) \(#{path}\)/\1 --input \2/' lib/tasks/assets.rake
RAILS_ENV=production bundle exec rake assets:precompile
RAILS_ENV=production bundle exec rake admin:create
Discourse will be started via Puma, so you need to adjust the application path in the script puma.rb
:
sed -i -e 's|\(APP_ROOT = \).*|\1"/srv/discourse"|' config/puma.rb
Also adjust the Sidekiq configuration:
cat <<EOF > config/sidekiq.yml
---
:verbose: false
:concurrency: 5
:timeout: 25
:optipng: false
:jhead: false
:jpegoptim: false
:gifsicle: false
:svgo: false
development:
:concurrency: 5
:queues:
- [critical, 8]
- [default, 4]
- [low, 2]
- [ultra_low]
production:
:concurrency: 20
:queues:
- [critical, 8]
- [default, 4]
- [low, 2]
- [ultra_low]
EOF
Note: I decided to disable all image optimizations. If you want to use any of them you need to install the respective tool(s) and set their option in sidekiq.yml
to true
.
Lastly, become root again and create init scripts for Discourse and Sidekiq. Remember, this is Devuan; we don't have no stinkin' Systemd here! Now enable and start the services:
curl -sOJ https://www.planetcobalt.net/download/discourse_initscripts.tar.gz
tar xzf discourse_initscripts.tar.gz -C /etc/init.d
cat <<EOF >/etc/default/discourse
APP_ENV='production'
EOF
chmod a+x /etc/init.d/discourse
update-rc.d -f discourse defaults
service discourse start
cat <<EOF >/etc/default/sidekiq-discourse
APP_ENV='production'
EOF
chmod a+x /etc/init.d/sidekiq-discourse
update-rc.d -f sidekiq-discourse defaults
service sidekiq-discourse start
Nginx
At this point Discourse is running and listening on localhost. We'll be using Nginx to reverse-proxy connections to the application service to make it accessible publicly. The Nginx sample config that ships with Discourse is a good starting point, so we'll generate the initial virtual host config from it (replace dis.example.org
with the hostname you specified in discourse.conf
). The brotli
compression option is commented out because Nginx on Devuan doesn't support that algorithm yet.
apt-get install nginx
sed \
-e '/^upstream/,/^}/d' \
-e '/^# upstream/,/^# }/ s/^# //' \
-e 's/\(server_name\) .*/\1 dis.example.org;/' \
-e 's|/var/www/discourse|/srv/discourse|' \
-e 's|/var/nginx/cache|/var/cache/nginx|' \
-e 's/brotli/#&/' \
config/nginx.sample.conf > /etc/nginx/sites-available/discourse.conf
Edit discourse.conf
to make further adjustments as needed. I recommend at least enabling SSL. Once that is done you can enable the virtual host and restart Nginx. I'd suggest to also remove the default config.
ln -s /etc/nginx/sites-available/discourse.conf /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
service nginx restart
Note: Beware that name resolution for the hostname you picked must work at this point, otherwise you'll get a blank page instead of a login dialog when trying to log into your new Discourse.
Navigate to your Discourse site, log in as the admin user, and complete the application configuration.
Posted 19:57 [permalink]