Summary
Pleroma is one of the fediverse implementations for microblogging like Twitter and Mastodon. It uses Elixir which "runs on Erlang VM known for creating low-latency, distributed, and fault-tolerant systems".
Here is the default landing view:
The new major minor version, 2.5.0, was released just last week 🎉🎉🎉
This post shows how to install it on OpenBSD, the solid unix system.
Why was OpenBSD 7.1 used instead of 7.2, the latest ?
I found it was easier to use OpenBSD 7.1 in order to install Pleroma, for Elixir in ports was available.
On 7.2, the mix task below failed with Elixir in Ports:
$ env LC_ALL=en_US.UTF-8 MIX_ENV=prod \
mix phx.server
with the error:
xx:xx:xx.xxx [notice] Application runtime_tools exited: :runtime_tools.start(:normal, []) returned an error: shutdown: failed to start child: :ttb_autostart
** (EXIT) an exception was raised:
** (UndefinedFunctionError) function :observer_backend.ttb_resume_trace/0 is undefined (module :observer_backend is not available)
(runtime_tools 1.19) :observer_backend.ttb_resume_trace()
(runtime_tools 1.19) ttb_autostart.erl:47: :ttb_autostart.init/1
(stdlib 4.0.1) gen_server.erl:848: :gen_server.init_it/2
(stdlib 4.0.1) gen_server.erl:811: :gen_server.init_it/6
(stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
{"Kernel pid terminated",application_controller,"{application_start_failure,runtime_tools,{{shutdown,{failed_to_start_child,ttb_autostart,{undef,[{observer_backend,ttb_resume_trace,[],[]},{ttb_autostart,init,1,[{file,\"ttb_autostart.erl\"},{line,47}]},{gen_server,init_it,2,[{file,\"gen_server.erl\"},{line,848}]},{gen_server,init_it,6,[{file,\"gen_server.erl\"},{line,811}]},{proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,240}]}]}}},{runtime_tools,start,[normal,[]]}}}"}
Kernel pid terminated (application_controller) ({application_start_failure,runtime_tools,{{shutdown,{failed_to_start_child,ttb_autostart,{undef,[{observer_backend,ttb_resume_trace,[],[]},{ttb_autostart,init,1,[{file,"ttb_autostart.erl"},{line,47}]},{gen_server,init_it,2,[{file,"gen_server.erl"},{line,848}]},{gen_server,init_it,6,[{file,"gen_server.erl"},{line,811}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,240}]}]}}},{runtime_tools,start,[normal,[]]}}})
Crash dump is being written to: erl_crash.dump...done
It's possibly because of the version of Elixir offered by 7.2's ports, 1.14.
Environment
- OpenBSD 7.1 (released on Apr 21, 2022)
- PostgreSQL 14.5 (released on Aug 11, 2022)
- Erlang/OTP 21.2.5 (released on Feb 4, 2019)
- Elixir 1.11.4 (released on May 16, 2021)
- Pleroma (released on Dec 23, 2022)
Tutorial
Prepare database / application engine / user
You have to set up the database, the application engine and the service (daemon) user.
Install PostgreSQL server (Optional)
Skip this section, if the database server already runs * with postgresql-contrib, its extensions * in your environment.
Install PostgreSQL and the extensions:
$ doas pkg_add postgresql-server \
postgresql-contrib
The output was:
quirks-5.5 signed on 2022-10-18T12:24:43Z
postgresql-server-14.5:libxml-2.9.13p2: ok
postgresql-server-14.5:postgresql-client-14.5: ok
useradd: Warning: home directory `/var/postgresql' doesn't exist, and -m was not specified
postgresql-server-14.5: ok
postgresql-contrib-14.5: ok
Running tags: ok
The following new rcscripts were installed: /etc/rc.d/postgresql
See rcctl(8) for details.
New and changed readme(s):
/usr/local/share/doc/pkg-readmes/postgresql-server
Then, let's initialize the database system.
Act as _postgresql
:
$ doas su _postgresql -
to run:
$ initdb -D /var/postgresql/data -U postgres
The output was:
The files belonging to this database system will be owned by user "_postgresql".
This user must also own the server process.
The database cluster will be initialized with locale "C".
The default database encoding has accordingly been set to "SQL_ASCII".
The default text search configuration will be set to "english".
Data page checksums are disabled.
creating directory /var/postgresql/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 20
selecting default shared_buffers ... 128MB
selecting default time zone ... Asia/Tokyo
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
initdb: warning: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
Success. You can now start the database server using:
pg_ctl -D /var/postgresql/data -l logfile start
Done.
$ exit
Finally, activate the daemon and start it:
$ doas rcctl enable postgresql
$ doas rcctl start postgresql
Install Elixir
Thankfully, the ports system offers the application environment required:
$ doas pkg_add elixir
The output was:
quirks-5.5 signed on 2022-10-18T12:24:43Z
elixir-1.11.4p0:erlang-21.2p5v0: ok
elixir-1.11.4p0: ok
--- +erlang-21.2p5v0 -------------------
You may wish to add /usr/local/lib/erlang21/man to /etc/man.conf
Install the packages for Pleroma
Also, the ports system helps us.
Install the essential packages:
$ doas pkg_add gmake \
git cmake libmagic
Additionally, there are optional ones:
$ doas pkg_add ImageMagick \
ffmpeg p5-Image-ExifTool
The output of the former was:
quirks-5.5 signed on 2022-10-18T12:24:43Z
gmake-4.3: ok
git-2.35.1p0:cvsps-2.1p2: ok
(...)
git-2.35.1p0: ok
cmake-3.20.3p6v0:libuv-1.44.1: ok
(...)
cmake-3.20.3p6v0: ok
libmagic-5.43: ok
The following new rcscripts were installed: /etc/rc.d/gitdaemon
See rcctl(8) for details.
New and changed readme(s):
/usr/local/share/doc/pkg-readmes/git
That of the latter was:
quirks-5.5 signed on 2022-10-18T12:24:43Z
ImageMagick-6.9.12.38:x265-3.5p0: ok
(...)
ImageMagick-6.9.12.38: ok
ffmpeg-4.4.1p3v1:fribidi-1.0.11: ok
(...)
ffmpeg-4.4.1p3v1: ok
p5-Image-ExifTool-12.40: ok
Running tags: ok
New and changed readme(s):
/usr/local/share/doc/pkg-readmes/ffmpeg
/usr/local/share/doc/pkg-readmes/sdl2
Create user and project directory
Create the app user used in a part of rc.d
, the daemon script:
$ doas useradd \
-d /var/www/_pleroma -m _pleroma
Here, We define /var/www/_pleroma
as the home directory which is automatically created.
Create the project directory next to it and set the permissions:
$ doas mkdir /var/www/pleroma
$ doas chown -R \
_pleroma:_pleroma /var/www/pleroma
Finally, extend the login class of the user, because the default settings may be too small to run Elixir Phoenix apps:
$ doas nvim /etc/login.conf
like below:
+ _pleroma:\
+ :datasize-max=1536M:\
+ :datasize-cur=1536M:\
+ :openfiles-max=4096
Then apply it:
$ doas cap_mkdb /etc/login.conf
As a reference, the results were:
$ ls -l /etc/login*
-rw-r--r-- 1 root wheel 2785 Dec 26 21:02 /etc/login.conf
-rw-r--r-- 1 root wheel 73728 Dec 26 21:02 /etc/login.conf.db
(...)
Install Pleroma
Here is the main part at last.
Assume the current directory and get the source
Act as:
$ doas su _pleroma -
ksh
will be perhaps used as login shell.
Well, go to the project directory:
$ cd /var/www/pleroma
Get the latest stable source in the current directory:
$ git clone -b stable \
https://git.pleroma.social/pleroma/pleroma.git \
.
The output was:
Cloning into '.'...
remote: Enumerating objects: 155563, done.
remote: Counting objects: 100% (1606/1606), done.
remote: Compressing objects: 100% (562/562), done.
remote: Total 155563 (delta 1131), reused 1458 (delta 1040), pack-reused 153957
Receiving objects: 100% (155563/155563), 198.25 MiB | 6.12 MiB/s, done.
Resolving deltas: 100% (118994/118994), done.
Mix task: deps.get
Get the dependencies:
$ mix deps.get
You will be asked to install Hex. Go on with "y" entered:
warning: 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 :phoenix
Shall I install Hex? (if running non-interactively, use "mix local.hex --force") [Yn] y
The output was:
* creating /var/www/_pleroma/.mix/archives/hex-2.0.0
* Getting gettext (https://github.com/tusooa/gettext.git - 72fb2496b6c5280ed911bdc3756890e7f38a4808)
remote: Enumerating objects: 4046, done.
remote: Counting objects: 100% (254/254), done.
remote: Compressing objects: 100% (130/130), done.
remote: Total 4046 (delta 121), reused 213 (delta 100), pack-reused 3792
(...)
Resolving Hex dependencies...
Resolution completed in 1.875s
Unchanged:
accept 0.3.5
(...)
websockex 0.4.3
* Getting phoenix (Hex package)
(...)
* Getting phoenix_pubsub (Hex package)
You have added/upgraded packages you could sponsor, run `mix hex.sponsor` to learn more
Fix elixir-captcha which is incompatible with OpenBSD (Optional)
elixir-captcha
0.1.0 is brought in the previous section, which incompatible with OpenBSD, for it uses make
in any envs. If you want to use the native captcha of Pleroma, you have to tell it to use gmake
instead. Edit:
$ nvim deps/captcha/mix.exs
to:
defmodule Mix.Tasks.Compile.Make do
def run(_) do
- {result, _error_code} = System.cmd("make", [], stderr_to_stdout: true)
+ {result, _error_code} = System.cmd("gmake", [], stderr_to_stdout: true)
Mix.shell().info(result)
(...)
defmodule Mix.Tasks.Clean.Make do
def run(_) do
- {result, _error_code} = System.cmd("make", ['clean'], stderr_to_stdout: true)
+ {result, _error_code} = System.cmd("gmake", ['clean'], stderr_to_stdout: true)
Mix.shell().info(result)
Otherwise, you will get the error below, which is not fatal, in running mix pleroma.instance gen
:
==> captcha
rm -f priv/captcha src/captcha.o
cc -g -c src/captcha.c
mkdir -p priv
cc -I src -o priv/captcha src/captcha.o
cc: error: no such file or directory: 'src/captcha.o'
cc: error: no input files
*** Error 1 in /var/www/pleroma/deps/captcha (Makefile:10 'priv/captcha')
Mix task: pleroma.instance gen
Run to generate Pleroma instance:
$ env MIX_ENV=prod \
mix pleroma.instance gen
You will be asked to install rebar3. Go on with "y" entered as well:
warning: 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)
warning: `config/prod.secret.exs` not found. You may want to create one by running `mix pleroma.instance gen`
Could not find "rebar3", which is needed to build dependency :parse_trans
I can install a local copy which is just used by Mix
Shall I install rebar3? (if running non-interactively, use "mix local.rebar --force") [Yn] y
The output was:
* creating /var/www/_pleroma/.mix/rebar
* creating /var/www/_pleroma/.mix/rebar3
===> Analyzing applications...
===> Compiling parse_trans
(...)
==> pleroma
Compiling 592 files (.ex)
(...)
Generated pleroma app
Configure app
Then you will be asked as below. It's actually up to you.
What domain will your instance use? (e.g pleroma.soykaf.com) [] pleroma-on-openbsd.com
What is the name of your instance? (e.g. The Corndog Emporium) [pleroma-on-openbsd.com]
What is your admin email address? [] ciao@pleroma-on-openbsd.com
What email address do you want to use for sending email notifications? [ciao@pleroma-on-openbsd.com]
Do you want search engines to index your site? (y/n) [n]
Do you want to store the configuration in the database (allows controlling it from admin-fe)? (y/n) [n]
What is the hostname of your database? [localhost] 127.0.0.1
What is the name of your database? [pleroma]
What is the user used to connect to your database? [pleroma]
What is the password used to connect to your database? [autogenerated]
Would you like to use RUM indices? [n]
What port will the app listen to (leave it if you are using the default setup with nginx)? [4000]
What ip will the app listen to (leave it if you are using the default setup with nginx)? [127.0.0.1]
What directory should media uploads go in (when using the local uploader)? [uploads]
What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)? [instance/static/]
Do you want to strip location (GPS) data from uploaded images? This requires exiftool, it was detected as installed. (y/n) [y]
Do you want to read data from uploaded files so clients can use it to prefill fields like image description? This requires exiftool, it was detected as installed. (y/n) [y]
Do you want to anonymize the filenames of uploads? (y/n) [n] y
Do you want to deduplicate uploaded files? (y/n) [n]
Writing config to config/generated_config.exs.
Writing the postgres script to config/setup_db.psql.
Writing /var/www/pleroma/instance/static/robots.txt.
All files successfully written! Refer to the installation instructions for your platform for next steps.
Generating instance is completed !! Prepare your own custom config file:
$ cp config/generated_config.exs \
config/prod.secret.exs
Customize app (Optional)
In case, you might need do edit it:
$ nvim config/prod.secret.exs
For example, when your PostgreSQL server is in an external host and moreover requires TLS/SSL connections:
config :pleroma, Pleroma.Repo,
(...)
- hostname: "(your-hostname)"
+ hostname: "(your-hostname)",
+ port: xxx,
+ ssl: true
(...)
+ config :pleroma, Pleroma.Captcha,
+ enabled: true
Also, when you want use kocaptcha instead of native captcha:
+ config :pleroma, Pleroma.Captcha,
+ enabled: true,
+ method: Pleroma.Captcha.Kocaptcha
Migrate database
Let's set up the database of Pleroma.
Run:
$ psql -U postgres -f config/setup_db.psql
The output was:
CREATE ROLE
CREATE DATABASE
You are now connected to database "pleroma" as user "postgres".
CREATE EXTENSION
CREATE EXTENSION
CREATE EXTENSION
Then run to migrate:
$ env MIX_ENV=prod \
mix ecto.migrate
The output was:
warning: 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)
Compiling 592 files (.ex)
(...)
xx:xx:xx.xxx [info] == Migrated 20221103014728 in 0.0s
xx:xx:xx.xxx [info] == Running 20221111164213 Pleroma.Repo.Migrations.DeprecateQuack.up/0 forward
xx:xx:xx.xxx [info] == Migrated 20221111164213 in 0.0s
Mix task: Start Phoenix server
We are almost ready. Start Phoenix:
$ env LC_ALL=en_US.UTF-8 MIX_ENV=prod \
mix phx.server
The output was:
xx:xx:xx.xxx [warning] Description: 'Authenticity is not established by certificate path validation'
Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'
xx:xx:xx.xxx [info] tzdata release in place is from a file last modified Wed, 21 Oct 2020 18:40:20 GMT. Release file on server was last modified Sat, 29 Oct 2022 01:50:44 GMT.
xx:xx:xx.xxx [warning] The on_load function for module crypt returned:
{:error, {:load, 'Library load-call unsuccessful (1).'}}
xx:xx:xx.xxx [info] Tzdata has updated the release from 2020d to 2022f
xx:xx:xx.xxx [warning] The on_load function for module crypt returned:
{:error, {:load, 'Library load-call unsuccessful (1).'}}
xx:xx:xx.xxx [info] Running Pleroma.Web.Endpoint with cowboy 2.9.0 at 127.0.0.1:4000 (http)
xx:xx:xx.xxx [info] Access Pleroma.Web.Endpoint at https://(your-domain)
xx:xx:xx.xxx [info] Gopher server disabled
xx:xx:xx.xxx [info] Transferring embedded hashtags to `hashtags` (from oid: 0)...
xx:xx:xx.xxx [warn] The on_load function for module crypt returned:
{:error, {:load, 'Library load-call unsuccessful (1).'}}
(...)
xx:xx:xx.xxx [info] Running Pleroma.Web.Endpoint with cowboy 2.9.0 at 127.0.0.1:4000 (http)
xx:xx:xx.xxx [info] Access Pleroma.Web.Endpoint at https://pleroma-on-openbsd.com
xx:xx:xx.xxx [info] Gopher server disabled
xx:xx:xx.xxx [info] Transferring embedded hashtags to `hashtags` (from oid: 0)...
xx:xx:xx.xxx [info] Deleting context objects from `objects` (from oid: 0)...
Testing the server
Keep the Phoenix process above (actually acting as Pleroma) running.
Check if the response returns correctly:
$ curl -I http://127.0.0.1:4000/
In my case, the response header was:
HTTP/1.1 200 OK
access-control-allow-credentials: true
access-control-allow-origin: *
access-control-expose-headers: Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id,Idempotency-Key
cache-control: max-age=0, private, must-revalidate
content-length: 7880
content-security-policy: upgrade-insecure-requests;script-src 'self' 'wasm-unsafe-eval';connect-src 'self' blob: https://pleroma-on-openbsd.com wss://pleroma-on-openbsd.com;media-src 'self' https:;img-src 'self' data: blob: https:;default-src 'none';base-uri 'self';frame-ancestors 'none';style-src 'self' 'unsafe-inline';font-src 'self';manifest-src 'self';
content-type: text/html; charset=utf-8
date: Mon, 26 Dec 2022 12:35:06 GMT
permissions-policy: interest-cohort=()
referrer-policy: same-origin
server: Cowboy
x-content-type-options: nosniff
x-download-options: noopen
x-frame-options: DENY
x-permitted-cross-domain-policies: none
x-request-id: FzRX_VnDh-YizPQAABaR
x-xss-protection: 1; mode=block
Seems sweet :)
When "HTTP/... 200 OK" is printed, the health of your Pleroma is good.
Create a Pleroma admin
Note you are in /var/www/pleroma
as _pleroma.
Run to create a super user:
$ env LC_ALL=en_US.UTF-8 MIX_ENV=prod \
mix pleroma.user new \
(admin-name) (your@e.mail) --admin
You will be asked as below:
A user will be created with the following information:
- nickname: pleroma_admin
- email: pleroma_admin@example.com
- password: [generated; a reset link will be created]
- name: (admin-name)
- bio:
- moderator: false
- admin: true
Continue? [n] y
When I proceeded, the output was:
User (admin-name) created
Admin status of (admin-name): true
Generated password reset token for (admin-name)
URL: https://(your-domain))/api/v1/pleroma/password_reset/xxx...
Start relayd
By default, Pleroma listens to only 127.0.0.1, the localhost.
In order to publish it as service, you have to combine it with some web server. In Pleroma, the cases using nginx seem more than Apache or Caddy.
OpenBSD develops and supports relayd, their native relay daemon which "runs as a load-balancer, application layer gateway, or transparent proxy".
In order for relayd to relay the requests/responses between the outside and Pleroma inside, edit:
$ doas nvim /etc/relayd.conf
The simplest configuration is below:
table <pleroma_server> { 127.0.0.1 }
relay pleroma {
listen on egress port 4000
forward to <pleroma_server> port 4000 check http "/" code 200
}
Activate and start it:
$ doas rcctl enable relayd
$ doas rcctl start relayd
rc.d script
There is another issue left to publish Pleroma as service.
It is not registered as daemon.
To solve it, create the rc.d script:
$ doas nvim /etc/rc.d/pleroma
Write the below in it:
#!/bin/ksh
daemon="cd /var/www/pleroma; env LC_ALL=en_US.UTF-8 MIX_ENV=prod mix"
daemon_user="_pleroma"
daemon_flags="phx.server --no-compile"
. /etc/rc.d/rc.subr
rc_cmd $1
Besides, I tried daemon_execdir="/var/www/pleroma"
instead of cd ...;
but it didn't work.
Set the permissions:
$ doas chmod a+x /etc/rc.d/pleroma
Then activate and run it:
$ doas rcctl enable pleroma
$ doas rcctl start pleroma
Well, there is an alternative way. If you don't want to enable it now, you can start it temporarily with -f
option: The whole command line is doas rcctl -f start pleroma
.
Conclusion
Access with your browser to http://127.0.0.1:4000/
. You will see the front page !!
After signing in, the dashboard must be there 🐡
Enjoy swimming across the fediverse :)