Skip to content

Instantly share code, notes, and snippets.

@waveletlet
Last active October 21, 2022 16:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save waveletlet/6a38e30f14e28fa0edecd5ff733771e0 to your computer and use it in GitHub Desktop.
Save waveletlet/6a38e30f14e28fa0edecd5ff733771e0 to your computer and use it in GitHub Desktop.

Jackal Setup on Debian 9 Stretch with PostgreSQL

These are my notes for installing jackal on a server where I already have PostgreSQL and Caddy set up to host a Mattermost instance. Some of the roadblocks I hit are most likely due to the idiosyncracies of however I set up postgres for mattermost, which is my only experience with postgres.

Tested with go 1.11.5 (current version available in Debian testing/buster repo)

First, get the code and build:

go get -d github.com/ortuman/jackal
cd $GOPATH/src/github.com/ortuman/jackal
make install

Make a user to run jackal (all commands from here on are run as root):

adduser jackal

Setup PostgreSQL

As db admin user, make jackal database and user. On my system, the db admin is 'postgres'.

sudo --login --user postgres
psql

# in the postgres console:
CREATE ROLE jackal WITH LOGIN PASSWORD 'passwordstring';
CREATE DATABASE jackal;
GRANT ALL PRIVILEGES ON DATABASE jackal TO jackal;

Next, import the database schema:

psql --user jackal --password -f sql/postgres.up.psql

But on my system, that returned the error psql: FATAL: no pg_hba.conf entry for host "[local]", user "jackal", database "jackal", SSL off.

This suggests you should add a line like hostnossl jackal jackal 127.0.0.1/32 md5 to pg_hba.conf.

But on my system, that didn't work, while the following line to set up connection through a unix socket did.

local    jackal   jackal    peer

Then importing the schema as the jackal user worked fine:

su jackal
psql --user jackal --password -f sql/postgres.up.psql

However, currently jackal is set up to connect to postgres through ipv4, and that line will need to be switched to the following before running jackal.

hostnossl    jackal    jackal    127.0.0.1/32    md5

A more permissive pg_hba.conf (for example, with host all all 127.0.0.1/32 md5) would have probably avoided having to jump through all those hoops.

Remember to reload postgres after editing the config file.

vi /etc/postgresql/9.6/main/pg_hba.conf
systemctl reload postgresql

Set up TLS

To set jackal up on anything but localhost, it seems to expect the path to a TLS certificate and key file. Which is great! Since Let's Encrypt there's no reason to not encrypt your chat server connections. My system already has a website for which Caddy is managing a Let's Encrypt certificate. I don't have another domain name to use, and I don't feel like using a subdomain for jackal, so I'm going to share the cert between caddy and jackal. (Can you even get two Let's Encrypt certs for the same domain? Something I just assumed "no" to but didn't do any research.) It would have been less convoluted if I wasn't sharing the cert and could point the jackal config at it's own personal certificate files.

First, find the files! Who are they owned by? Let's put the jackal user in that group.

ls -l /etc/ssl/caddy/acme/acme-v01.api.letsencrypt.org/sites/mydomain.com/
usermod -a -G www-data jackal

Next, I make a directory to point jackal to, and hardlink the files into it. Hardlinking lets the jackal user see the cert/key without loosening restrictions on the original path, and in theory means jackal will see the new certs whenever caddy automatically bugs Let's Encrypt for them. This avoids the issue of certificate expiration I would have if I simply copied the certs to a new directory and changed the ownership of the copies to the jackal user. (Although I'm not sure whether or not the renewed certs will still be group readable, I'll find out in three months!)

mkdir /etc/ssl/jackal
cp -l /etc/ssl/caddy/acme/acme-v01.api.letsencrypt.org/sites/mydomain.com/* /etc/ssl/jackal/
chmod 700 /etc/ssl/jackal
chown jackal:jackal /etc/ssl/jackal
cd /etc/ssl/caddy/acme/acme-v01.api.letsencrypt.org/sites/mydomain.com/
chmod g+r /etc/ssl/jackal/*

Configure jackal

mkdir /etc/jackal
cd /etc/jackal
wget https://raw.githubusercontent.com/ortuman/jackal/master/example.jackal.yml
cp /etc/jackal/example.jackal.yml /etc/jackal/jackal.yml
# putting the db password in here, so restricting the permissions
chown -R root:jackal /etc/jackal
chmod -R 750 /etc/jackal

Include the following in 'jackal.yml' for the hostname set up above, and to use postgres.

router:
  hosts:
    - name: mydomain.com
      tls:
        privkey_path: "/etc/ssl/jackal/mydomain.com.key"
        cert_path: "/etc/ssl/jackal/mydomain.com.crt"

storage:
  type: pgsql
  pgsql:
    host: 127.0.0.1:5432
    user: jackal
    password: passwordstring
    database: jackal
    ssl_mode: disable

For using ssl to connect to postgres, the 'ssl_mode' line above can be changed. The options accepted by postgres are require, verify-full, verify-ca, and disable.

Note that the jackal line of the postgres 'pg_hba.conf' file will need to be changed to reflect whatever setting is chosen. For example, host jackal jackal 127.0.0.1/32 md5 will allow SSL connections from localhost, and passwords will be hashed with md5.

Make a systemd service

I keep manually built applications in their own path:

mkdir /opt/jackal
mv /home/user/go/bin/jackal /opt/jackal/
chown -R jackal:jackal /opt/jackal/
chmod 500 /opt/jackal/jackal
chmod 700 /opt/jackal

Systemd service file: '/etc/systemd/system/jackal.service'

[Unit]
Description=jackal
After=network.target
After=postgresql.service
Requires=postgresql.service

[Service]
Type=simple
PIDFile=/opt/jackal/jackal.pid
ExecStart=/opt/jackal/jackal
Restart=always
RestartSec=10
WorkingDirectory=/opt/jackal
User=jackal
Group=jackal

[Install]
WantedBy=multi-user.target

Start the service, make sure it's running well, and enable it so it starts automatically on boot.

systemctl start jackal.service
systemctl status jackal
systemctl enable jackal.service

Misc

Disable jackal user log in: vipw, change the jackal line to jackal:x:1001:1001::/home/jackal:/usr/sbin/nologin Disable jackal user password: vipw -s, change jackal line to jackal:!:17965:::::: (note: 3rd value is unimportant, it's a timestamp for when password was last changed. The important part is '!' in the second slot.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment