Pleroma in Jail

I used to have a mastodon jail. With the 2.5.0 version it become very hard to maintain and I decided to shut it down and open an account on another instance. But I wasn’t very satisfied by the fail.

So, I decided to try Pleroma which use ActivityPub as mastdon to federated instances. It make Pleroma instances visible by mastodon instances and vice versa.

We start with a functional jail (see my articles in french on this website), with ssh access and use of my poudriere as package repository.

Pre-requisite

Some software are required in order to install pleroma. You must install them on your jail.

Install gmake

# pkg install gmake

Install bash

# pkg install bash

install Elixir

# pkg install elixir

Install postgresql96-server and postgresql96-client

# pkg install postgresql96-server postgresql96-client

add user pleroma

# pw useradd -n pleroma -c "Pleroma user" -s /usr/local/bin/bash -m -w random
<Password for 'pleroma' is: RANDOMGENERATED>

  On the PosgreSQL jail execute as root Be sure to keep the generated password safe

Download pleroma sources

It time to start pleroma installation.

Being pleroma

# su - pleroma
% cd ~

Clonning source

% git clone https://git.pleroma.social/pleroma/pleroma.git

Install dependencies

% cd pleroma
% mix deps.get
<i clas="fa fa-2x fa-times-circle" style="vertical-align:middle;"></i>the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell)
!!! RUNNING IN LOCALHOST DEV MODE! !!!
FEDERATION WON'T WORK UNTIL YOU CONFIGURE A dev.secret.exs
Could not find Hex, which is needed to build dependency :plug_cowboy
Shall I install Hex? (if running non-interactively, use "mix local.hex --force") [Yn] y
* creating /home/pleroma/.mix/archives/hex-0.18.2
* Getting phoenix (https://github.com/phoenixframework/phoenix.git)
remote: Enumerating objects: 82, done.
remote: Counting objects: 100% (82/82), done.
remote: Compressing objects: 100% (82/82), done.
remote: Total 39579 (delta 2), reused 68 (delta 0), pack-reused 39497
Receiving objects: 100% (39579/39579), 10.19 MiB | 10.88 MiB/s, done.
Resolving deltas: 100% (25684/25684), done.
* Getting crypt (https://github.com/msantos/crypt)
remote: Enumerating objects: 245, done.
remote: Total 245 (delta 0), reused 0 (delta 0), pack-reused 245
Receiving objects: 100% (245/245), 150.83 KiB | 780.00 KiB/s, done.
Resolving deltas: 100% (104/104), done.
* Getting websocket_client (https://github.com/jeremyong/websocket_client.git)
remote: Enumerating objects: 2, done.
remote: Counting objects: 100% (2/2), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 375 (delta 0), reused 2 (delta 0), pack-reused 373
Receiving objects: 100% (375/375), 81.11 KiB | 839.00 KiB/s, done.
Resolving deltas: 100% (219/219), done.
Resolving Hex dependencies...
Dependency resolution completed:
Unchanged:
  base64url 0.0.1
  bunt 0.2.0
  cachex 3.0.2
  calendar 0.17.4
  certifi 2.3.1
  comeonin 4.1.1
  connection 1.0.4
  cors_plug 1.5.2
  cowboy 1.1.2
  cowlib 1.0.2
  credo 0.9.3
  db_connection 1.1.3
  decimal 1.5.0
  earmark 1.3.0
  ecto 2.2.10
  eternal 1.2.0
  ex_aws 2.1.0
  ex_aws_s3 2.0.1
  ex_doc 0.19.1
  ex_machina 2.2.0
  gen_smtp 0.13.0
  gettext 0.15.0
  hackney 1.13.0
  html_sanitize_ex 1.3.0
  httpoison 1.2.0
  idna 5.1.2
  jason 1.0.0
  jose 1.8.4
  makeup 0.5.5
  makeup_elixir 0.10.0
  meck 0.8.9
  metrics 1.0.1
  mime 1.3.1
  mimerl 1.0.2
  mochiweb 2.15.0
  mock 0.3.1
  mogrify 0.6.1
  nimble_parsec 0.4.0
  parse_trans 3.2.0
  pbkdf2_elixir 0.12.3
  phoenix_ecto 3.3.0
  phoenix_html 2.11.2
  phoenix_pubsub 1.1.1
  plug 1.7.1
  plug_cowboy 1.0.0
  plug_crypto 1.0.0
  poison 3.1.0
  poolboy 1.5.1
  postgrex 0.13.5
  ranch 1.3.2
  ssl_verify_fun 1.1.1
  swoosh 0.20.0
  tesla 1.2.1
  trailing_format_plug 0.0.7
  tzdata 0.5.17
  unicode_util_compat 0.3.1
  unsafe 1.0.0
  web_push_encryption 0.2.1
* Getting plug_cowboy (Hex package)
* Getting phoenix_pubsub (Hex package)
* Getting phoenix_ecto (Hex package)
* Getting postgrex (Hex package)
* Getting gettext (Hex package)
* Getting comeonin (Hex package)
* Getting pbkdf2_elixir (Hex package)
* Getting trailing_format_plug (Hex package)
* Getting html_sanitize_ex (Hex package)
* Getting phoenix_html (Hex package)
* Getting calendar (Hex package)
* Getting cachex (Hex package)
* Getting httpoison (Hex package)
* Getting tesla (Hex package)
* Getting jason (Hex package)
* Getting mogrify (Hex package)
* Getting ex_aws (Hex package)
* Getting ex_aws_s3 (Hex package)
* Getting earmark (Hex package)
* Getting ex_machina (Hex package)
* Getting credo (Hex package)
* Getting mock (Hex package)
* Getting cors_plug (Hex package)
* Getting ex_doc (Hex package)
* Getting web_push_encryption (Hex package)
* Getting swoosh (Hex package)
* Getting gen_smtp (Hex package)
* Getting hackney (Hex package)
* Getting mime (Hex package)
* Getting certifi (Hex package)
* Getting idna (Hex package)
* Getting metrics (Hex package)
* Getting mimerl (Hex package)
* Getting ssl_verify_fun (Hex package)
* Getting unicode_util_compat (Hex package)
* Getting parse_trans (Hex package)
* Getting jose (Hex package)
* Getting poison (Hex package)
* Getting base64url (Hex package)
* Getting makeup_elixir (Hex package)
* Getting makeup (Hex package)
* Getting nimble_parsec (Hex package)
* Getting plug (Hex package)
* Getting plug_crypto (Hex package)
* Getting meck (Hex package)
* Getting bunt (Hex package)
* Getting eternal (Hex package)
* Getting unsafe (Hex package)
* Getting tzdata (Hex package)
* Getting mochiweb (Hex package)
* Getting connection (Hex package)
* Getting db_connection (Hex package)
* Getting decimal (Hex package)
* Getting ecto (Hex package)
* Getting poolboy (Hex package)
* Getting cowboy (Hex package)
* Getting cowlib (Hex package)
* Getting ranch (Hex package)
- Generate configuration

Generate pleroma instance

% mix pleroma.instance gen
…
To get started:
1. Verify the contents of the generated files.
2. Run `sudo -u postgres psql -f 'config/setup_db.psql'`.
3. Run `mv 'config/generated_config.exs' 'config/prod.secret.exs'`.

Copy config/setup_db.psql on PostgreSQL jail

I use an another jail for my PosgreSQL databases (once again look at my article - in french - on this blog). If you have PostgreSQL installed on the Pleroma jail, skip this step.

% scp config/setup_db.psql root@192.168.12.3:/tmp/.

The root password on PostgreSQL jail will be ask

  On the PosgreSQL jail execute as root

Create the role and the database

# sudo -u postgres psql -f '/tmp/setup_db.psql'
CREATE ROLE
CREATE DATABASE
You are now connected to database "pleroma_dev" as user "postgres".
CREATE EXTENSION
CREATE EXTENSION
CREATE EXTENSION

Allow remote connection to the database

Edit the /var/db/pgsql/data96/pg_hba.conf to allow local (or remote depending of you configuration) connexions.

 Back on pleroma jail, as pleroma user

Move generated configuration as production configuration

% mv config/{generated_config.exs,prod.secret.exs}

Run the database migration

% MIX_ENV=prod mix ecto.migrate

Verify the migration on the PosgreSQL jail, login as root

# sudo -u postgres psql -d pleroma_dev
psql (9.6.10)
Type "help" for help.

pleroma_dev=# \dt
                   List of relations
 Schema |            Name             | Type  |  Owner
--------+-----------------------------+-------+---------
 public | activities                  | table | pleroma
 public | apps                        | table | pleroma
 public | filters                     | table | pleroma
 public | lists                       | table | pleroma
 public | notifications               | table | pleroma
 public | oauth_authorizations        | table | pleroma
 public | oauth_tokens                | table | pleroma
 public | objects                     | table | pleroma
 public | password_reset_tokens       | table | pleroma
 public | push_subscriptions          | table | pleroma
 public | schema_migrations           | table | pleroma
 public | user_invite_tokens          | table | pleroma
 public | users                       | table | pleroma
 public | websub_client_subscriptions | table | pleroma
 public | websub_server_subscriptions | table | pleroma
(15 rows)

pleroma_dev=# \q

Back on the pleroma jail as pleroma user

nginx configuration on the host

This is the first part of the configuration, in order to obtain a valid certificate for our host pleroma.example.com.

Let's Encrypt certificate

We use let’s encrypt certificates.

Be sure the host name resolvable

# dig pleroma.example.com

; <<>> DiG 9.12.3-P1 <<>> pleroma.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15552
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;pleroma.example.com.	IN	A

;; ANSWER SECTION:
pleroma.example.com. 86400 IN	A	203.0.113.96

;; Query time: 63 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: lun. déc. 24 13:12:01 CET 2018
;; MSG SIZE  rcvd: 72

nginx basic configuration

server {
    listen 80;
    server_name pleroma.example.com;
        access_log /var/log/nginx/foobar-access.log main;
        error_log /var/log/nginx/foobar-error.log;

     location /.well-known/acme-challenge {
        root /usr/local/www/foobar;
    }

}

Obtain a certificate with certbot

# certbot certonly -d pleroma.exemple.com
…

Complete nginx configuration

First the SSL part

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
server {
    listen 443 ssl http2;
    # listen [::]:443 ssl http2;
    server_name pleroma.example.com;

    access_log /var/log/nginx/pleroma-access.log main;
    error_log /var/log/nginx/pleroma-error.log;

    ssl_protocols TLSv1.2;
    ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_certificate /usr/local/etc/letsencrypt/live/pleroma.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/etc/letsencrypt/live/pleroma.example.com/privkey.pem;er 
    ssl_dhparam /usr/local/etc/ssl/dhparam.pem;

    location /.well-known/acme-challenge {
        root /usr/local/www/foorbar;
    }
}

Then the proxy_pass part

Must be put before the last }

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml;

    # the nginx default is 1m, not enough for large media uploads
    client_max_body_size 16m;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;

        proxy_pass http://192.168.12.4:4000;

        client_max_body_size 16m;
    }

    location ~ ^/(media|proxy) {
        proxy_cache pleroma_media_cache;
        slice              1m;
        proxy_cache_key    $host$uri$is_args$args$slice_range;
        proxy_set_header   Range $slice_range;
        proxy_http_version 1.1;
        proxy_cache_valid  200 206 301 304 1h;
        proxy_cache_lock on;
        proxy_ignore_client_abort on;
        proxy_buffering off;
        chunked_transfer_encoding on;
        proxy_pass http://192.168.12.4:4000;
    }

Enable and test the configuration

# ln -s /usr/local/etc/nginx/sites-available/pleroma_jail.conf /usr/local/etc/nginx/sites-enabled/.
# nginx -t

Launch Pleroma on the jail

The next step is to launch and test your pleroma instance:

# su - pleroma
% cd pleroma
% MIX_ENV=prod /usr/local/bin/mix phx.server
…

You should be able to connect to your pleroma instance with the hostname you’ve defined in DNS.

Launch automatically

By default pleroma sources come with startup for OpenBSD and NetNSD, but nothing for FreeBSD. We gonna transform the NetBSD one into a FreeBSD startup script.

Copy the original file

# cp /usr/home/pleroma/pleroma/installation/netbsd/rc.d/pleroma /usr/local/etc/rc.d/pleroma

Edit the new file

  • We need, to reorder the mandatory keyword PROVIDE and REQUIRE1
1
2
# REQUIRE: DAEMON pgsql
# PROVIDE: pleroma
  • Change pkg in paths into bin
  • Add some variables:
1
2
pleroma_user="pleroma"
pleroma_home="/usr/home/pleroma"
  • Then change the check_pidfile function to be conform to our installation and OS.
check_pidfile()
{
        #pid=$(pgrep -U "${pleroma_user}" /bin/beam.smp$)
        pid=$(pgrep beam.smp$)
        echo -n "${pid}"
}

The complete script

Here is the complete script:2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/bin/sh
# REQUIRE: DAEMON pgsql
# PROVIDE: pleroma

if [ -f /etc/rc.subr ]; then
        . /etc/rc.subr
fi

name="pleroma"
rcvar=${name}_enable
command="/usr/local/bin/elixir"
command_args="--detached -S /usr/local/bin/mix phx.server"
start_precmd="ulimit -n unlimited"
pidfile="/dev/null"
pleroma_user="pleroma"
pleroma_home="/usr/home/pleroma"

pleroma_chdir="${pleroma_home}/pleroma"
pleroma_env="HOME=${pleroma_home} MIX_ENV=prod"

check_pidfile()
{
        #pid=$(pgrep -U "${pleroma_user}" /bin/beam.smp$)
        pid=$(pgrep beam.smp$)
        echo -n "${pid}"
}

if [ -f /etc/rc.subr -a -d /etc/rc.d -a -f /etc/rc.d/DAEMON ]; then
        # newer NetBSD
        load_rc_config ${name}
        run_rc_command "$1"
else
        # ancient NetBSD, Solaris and illumos, Linux, etc...
        cmd=${1:-start}

        case ${cmd} in
            start)
                echo "Starting ${name}."
                 ${start_cmd}
                 ;;

            stop)
                 echo "Stopping ${name}."
                 check_pidfile
                 ! [ -n ${pid} ] && kill ${pid}
                 ;;

            restart)
                 ( $0 stop )
                 sleep 5
                 $0 start
                 ;;

            *)
                echo 1>&2 "Usage: $0 [start|stop|restart]"
                exit 1
                ;;
     esac
    exit 0
fi

Put in /etc/rc.conf

The last step is to put it on the /etc/rc.conf file, by editing it or use the sysrc command:

# sysrc pleroma_enable="YES"

Let’s start

# service pleroma start

And it should work.

To conclude

With a small amount of effort we can make pleroma working in a FreeBSD jail.


  1. Have a look to rcorder(8) to understand rc files [return]
  2. I will propose a PR for this script [return]