How to Install BookWyrm on a Debian 12 server

bookwyrm setup screen

How to Install BookWyrm on a Debian 12 server

BookWyrm is an open-source federated social network for book readers. It acts as an ad-free Goodreads alternative. It uses the ActivityPub protocol to send and receive user activity between other BookWyrm instances and other services that use the protocol like Mastodon. It offers a lot of features like book reviews, ratings, reading activity, book shelves such as “to-read”, “currently-reading” and “read”, book lists, and following other users and their reading progress. It also offers user moderation features like blocking or manually approving followers and multiple privacy levels for statuses, shelves, and lists.

In this tutorial, you will learn how to install BookWyrm federated social network for book readers on a Debian 12 server.


  • A server running Debian 12.

  • A non-root user with sudo privileges.

  • A Fully Qualified Domain Name (FQDN) like bookwyrm.example.com pointing to your server.

  • An SMTP account with an email service like Amazon SES or Mailgun.

  • Make sure everything is updated.
    $ sudo apt update
    $ sudo apt upgrade

  • Few packages that your system needs.
    $ sudo apt install wget curl nano ufw software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release debian-archive-keyring unzip -y

    Some of these packages may already be installed on your system.

Step 1 – Configure Firewall

The first step is to configure the firewall. Debian comes with ufw (Uncomplicated Firewall) by default.

Check if the firewall is running.
$ sudo ufw status

You will get the following output.
Status: inactive

Allow SSH port so that the firewall doesn’t break the current connection upon enabling it.
$ sudo ufw allow OpenSSH

Allow HTTP and HTTPS ports as well.
$ sudo ufw allow http
$ sudo ufw allow https

Enable the Firewall

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Check the status of the firewall again.
$ sudo ufw status

You should see a similar output.
Status: active

To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
443 ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)

Step 2 – Install and Configure PostgreSQL

Ubuntu 22.04 ships with PostgreSQL 14 by default. We will be using PostgreSQL 15 instead.

Run the following command to add the PostgreSQL GPG key.
$ curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | sudo tee /usr/share/keyrings/postgresql-key.gpg >/dev/null

Add the APT repository to your sources list.
$ sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/postgresql-key.gpg arch=amd64] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

Update the system repository.
$ sudo apt update

Now, you can install PostgreSQL using the command below.
$ sudo apt install postgresql postgresql-contrib

The postgresql-contrib package contains some extra utilities.

Check the status of the PostgreSQL service.
$ sudo systemctl status postgresql
? postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; preset: enabled)
Active: active (exited) since Sat 2023-09-09 07:39:21 UTC; 16s ago
Main PID: 3653 (code=exited, status=0/SUCCESS)
CPU: 1ms

Sep 09 07:39:21 bookwyrm systemd[1]: Starting postgresql.service - PostgreSQL RDBMS...
Sep 09 07:39:21 bookwyrm systemd[1]: Finished postgresql.service - PostgreSQL RDBMS.

You can see that the service is enabled and running by default.

Launch the PostgreSQL shell.
$ sudo -i -u postgres psql

Create the BookWyrm database.
postgres=# CREATE DATABASE bookwyrm TEMPLATE template0 ENCODING 'UNICODE';

Create the BookWyrm user and choose a strong password.
postgres-# CREATE USER bookwyrmuser WITH PASSWORD 'Your_Password';

Change the database owner to the BookWyrm user.
postgres-# ALTER DATABASE bookwyrm OWNER TO bookwyrmuser;

Grant all privileges on the database to the BookWyrm user.
postgres-# GRANT ALL PRIVILEGES ON DATABASE bookwyrm TO bookwyrmuser;

Exit the shell.
postgres-# q

Verify that your credentials work.
$ psql --username bookwyrmuser --password --host localhost bookwyrm
psql (15.4 (Debian 15.4-1.pgdg120+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.


Exit the shell by typing q.

Step 3 – Install Redis

Magento uses Redis for session and cache storage. It is entirely optional and you can use the database for session storage. But Redis does a better job. The latest version of Magento works with Redis 7.0. Ubuntu ships with Redis 6.0 so we will use the Redis repository for installation.

Import the official Redis GPG key.
$ curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg

Add the APT repository to your sources list.
$ echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list

Update the system repository list.
$ sudo apt update

Issue the following command to install the Redis server.
$ sudo apt install redis

Confirm the Redis version.
$ redis-server -v
Redis server v=7.2.1 sha=00000000:0 malloc=jemalloc-5.3.0 bits=64 build=95712a67f5005c28

Let us verify the service connection by using the following command.
$ redis-cli

You will be switched to the Redis shell.

The first step is to set the password for the Redis default user. Replace Your_Redis_Password with a strong password of your choice. Make sure you prefix the password with the > character.> acl setuser default >Your_Redis_Password

Test the Redis Authentication.> AUTH Your_Redis_Password

Ping the service.> ping

Exit the service by typing exit.

If you want, you can use the following command to generate the Redis password.
$ openssl rand 60 | openssl base64 -A

Step 4 – Install Nginx

Debian 12 ships with an older version of Nginx. To install the latest version, you need to download the official Nginx repository.

Import Nginx’s signing key.
$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

Add the repository for Nginx’s stable version.
$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/debian `lsb_release -cs` nginx"
| sudo tee /etc/apt/sources.list.d/nginx.list

Update the system repositories.
$ sudo apt update

Install Nginx.
$ sudo apt install nginx

Verify the installation. On Debian systems, the following command will only work with sudo.
$ sudo nginx -v
nginx version: nginx/1.24.0

Start the Nginx server.
$ sudo systemctl start nginx

Check the service status.
$ sudo systemctl status nginx
? nginx.service - nginx - high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Sat 2023-09-09 08:40:27 UTC; 1s ago
Docs: https://nginx.org/en/docs/
Process: 6946 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
Main PID: 6947 (nginx)
Tasks: 2 (limit: 1107)
Memory: 1.7M
CPU: 8ms
CGroup: /system.slice/nginx.service
??6947 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
??6948 "nginx: worker process"

Step 5 – Install SSL

We need to install Certbot to generate the SSL certificate. You can either install Certbot using Debian’s repository or grab the latest version using the Snapd tool. We will be using the Snapd version.

Debian 12 comes doesn’t come with Snapd installed. Install Snapd package.
$ sudo apt install snapd

Run the following commands to ensure that your version of Snapd is up to date.
$ sudo snap install core && sudo snap refresh core

Install Certbot.
$ sudo snap install --classic certbot

Use the following command to ensure that the Certbot command can be run by creating a symbolic link to the /usr/bin directory.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Verify if Certbot is functioning correctly.
$ certbot --version
certbot 2.6.0

Generate the SSL certificate.
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d bookwyrm.example.com

The above command will download a certificate to the /etc/letsencrypt/live/bookwyrm.example.com directory on your server.

Generate a Diffie-Hellman group certificate.
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

Check the Certbot renewal scheduler service.
$ sudo systemctl list-timers

You will find snap.certbot.renew.service as one of the services scheduled to run.
NEXT LEFT LAST PASSED UNIT ACTIVATES ----------------------------------------------------------------------------------------------------------------
Sat 2023-09-09 23:49:00 UTC 15h left - - snap.certbot.renew.timer snap.certbot.renew.service
Sun 2023-09-10 00:00:00 UTC 15h left - - dpkg-db-backup.timer dpkg-db-backup.service
Sun 2023-09-10 00:00:00 UTC 15h left Sat 2023-09-09 06:42:47 UTC 2h 1min ago exim4-base.timer exim4-base.service

Do a dry run of the process to check whether the SSL renewal is working fine.
$ sudo certbot renew --dry-run

If you see no errors, you are all set. Your certificate will renew automatically.

Step 6 – Download BookWyrm

Create a directory for BookWyrm.
$ sudo mkdir /opt/bookwyrm

Switch to the directory.
$ cd /opt/bookwyrm

Clone the BookWyrm application’s production branch from GitHub.
$ sudo git clone https://github.com/bookwyrm-social/bookwyrm.git --branch production --single-branch ./

Create the environment file by copying the example file.
$ sudo cp .env.example .env

Step 7 – Configure BookWyrm

Generate a secret key for BookWyrm.
$ openssl rand 60 | openssl base64 -A

Open the environment file for editing.
$ sudo nano .env

Configure the following variables.
[email protected]





## only enable it if you have a fairly powered server with a minimum of 2 CPU Cores and 2GB of RAM

Let us go through all the variables in the environment file.

  • SECRET_KEY – the key which you generated above
  • DOMAIN – the fully qualified domain name (FQDN) for your BookWyrn instance. In our case, it would be bookwyrm.example.com.
  • POSTGRES_PASSWORD – PostgreSQL password configured in step 2.
  • POSTGRES_HOST – set to localhost if you are hosting it on the same machine.
  • POSTGRES_USER – set to bookwyrmuser which you chose in step 2.
  • POSTGRES_DB – set to bookwyrm as chosen in step 2.
  • REDIS_ACTIVITY_HOST and REDIS_BROKER_HOST – set them to localhost if you are hosting the Redis server on the same machine.
  • REDIS_ACTIVITY_PORT and REDIS_BROKER_PORT – set them to the default Redis port 6379.
  • REDIS_ACTIVITY_DB and REDIS_BROKER_DB – set them to 0 and 1 respectively. We will use different databases for both.
  • REDIS_ACTIVITY_PASSWORD and REDIS_BROKER_PASSWORD – set them to the Redis password as chosen in step 3.
  • FLOWER_USER – choose a username for the Flower service which is needed by BookWyrm.
  • FLOWER_PASSWORD – choose a password for the Flower service.
  • EMAIL_HOST – set to the SMTP host of the email service you are using.
  • EMAIL_PORT – set to the SMTP port of the email service.
  • EMAIL_HOST_USER – set to the SMTP username.
  • EMAIL_HOST_PASSWORD – set to the SMTP password.
  • EMAIL_USE_TLS – set it to true if your email service uses TLS.
  • EMAIL_USE_SSL – set it to true if your email service uses SSL.
  • EMAIL_SENDER_NAME – choose the name of the sender for the emails sent by your instance.
  • EMAIL_SENDER_DOMAIN – set it to the domain name used by the email service.
  • ENABLE_PREVIEW_IMAGES – set it to true if you want your instance to generate preview images automatically. However, make sure your server has ample CPU and RAM for this since this is an intensive process.

Once you are finished, save the file by pressing Ctrl + X and entering Y when prompted.

Step 8 – Configure Nginx

Copy the file /opt/bookwyrm/nginx/server_config to the Nginx configuration directory.
$ sudo cp /opt/bookwyrm/nginx/server_config /etc/nginx/conf.d/server_config

Create and open the file /etc/nginx/conf.d/bookwyrm.conf for editing.
$ sudo nano /etc/nginx/conf.d/bookwyrm.conf

Paste the following code in it.
include /etc/nginx/conf.d/server_config;

upstream web {
server localhost:8000;

server {
listen [::]:80;
listen 80;

server_name bookwyrm.example.com;

# redirect http to https
return 301 https://bookwyrm.example.com$request_uri;

server {
access_log /var/log/nginx/bookwyrm.access.log cache_log;
error_log /var/log/nginx/bookwyrm.error.log;

listen [::]:443 ssl http2;
listen 443 ssl http2;

server_name bookwyrm.example.com;

client_max_body_size 3M;

if ($host != "bookwyrm.example.com") {
return 301 $scheme://bookwyrm.example.com$request_uri;

# SSL code
ssl_certificate /etc/letsencrypt/live/bookwyrm.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bookwyrm.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/bookwyrm.example.com/chain.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_prefer_server_ciphers off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
resolver [2606:4700:4700::1111] [2606:4700:4700::1001] [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s;
resolver_timeout 2s;

ssl_protocols TLSv1.2 TLSv1.3;

tcp_nopush on;
types_hash_max_size 2048;

gzip on;

proxy_read_timeout 1800s;

# store responses to anonymous users for up to 1 minute
proxy_cache bookwyrm_cache;
proxy_cache_valid any 1m;
add_header X-Cache-Status $upstream_cache_status;

# ignore the set cookie header when deciding to
# store a response in the cache
proxy_ignore_headers Cache-Control Set-Cookie Expires;

# PUT requests always bypass the cache
# logged in sessions also do not populate the cache
# to avoid serving personal data to anonymous users
proxy_cache_methods GET HEAD;
proxy_no_cache $cookie_sessionid;
proxy_cache_bypass $cookie_sessionid;

# tell the web container the address of the outside client
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;

location ~ ^/(login[^-/]|password-reset|resend-link|2fa-check) {
limit_req zone=loginlimit;
proxy_pass http://web;

# do not log periodic polling requests from logged in users
location /api/updates/ {
access_log off;
proxy_pass http://web;

location / {
proxy_pass http://web;

# directly serve images and static files from the
# bookwyrm filesystem using sendfile.
# make the logs quieter by not reporting these requests
location ~ ^/(images|static)/ {
root /opt/bookwyrm;
try_files $uri =404;
add_header X-Cache-Status STATIC;
access_log off;

# monitor the celery queues with flower, no caching enabled
location /flower/ {
proxy_pass http://localhost:8888;
proxy_cache_bypass 1;

Once finished, save the file by pressing Ctrl + X and entering Y when prompted.

Open the file /etc/nginx/nginx.conf for editing.
$ sudo nano /etc/nginx/nginx.conf

Add the following line before the line include /etc/nginx/conf.d/*.conf;.
server_names_hash_bucket_size 64;

Save the file by pressing Ctrl + X and entering Y when prompted.

Verify the Nginx configuration file syntax.
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart the Nginx service to enable the new configuration.
$ sudo systemctl restart nginx

Step 9 – Install BookWyrm

Before Installing BookWyrm, we need to install some Python packages.
$ sudo apt install python3-venv python3-pip python3-dev libpq-dev

Switch to the Bookwyrm directory.
$ cd /opt/bookwyrm

Change the ownership of the folder to the currently logged-in user.
$ sudo chown -R $USER:$USER .

Make the Python venv directory.
$ python3 -m venv ./venv

Install BookWyrm Python dependencies using the pip package manager.
$ ./venv/bin/pip3 install -r requirements.txt

Migrate the database schema.
$ venv/bin/python3 manage.py migrate

Initialize the database.
$ venv/bin/python3 manage.py initdb

Compile the themes.
$ venv/bin/python3 manage.py compile_themes

Create the static files.
$ venv/bin/python3 manage.py collectstatic --no-input

Create and set up the BookWyrm system user.
$ sudo useradd bookwyrm -r

Change the owner of the installation directory to the BookWyrm user.
$ sudo chown -R bookwyrm:bookwyrm /opt/bookwyrm

From now on, to run any BookWyrm related command, run it as the BookWyrm user.
$ sudo -u bookwyrm echo I am the ${whoami} user
I am the bookwyrm user

Create BookWyrm service unit file

BookWyrm ships with the service unit files for the service, worker, and scheduler. Copy them to the /etc/systemd/system directory.
$ sudo cp /opt/bookwyrm/contrib/systemd/*.service /etc/systemd/system/

Enable and start the services using the following command.
$ sudo systemctl enable bookwyrm bookwyrm-worker bookwyrm-scheduler --now

Check the status of the BookWyrm service.
$ sudo systemctl status bookwyrm
? bookwyrm.service - BookWyrm
Loaded: loaded (/etc/systemd/system/bookwyrm.service; enabled; preset: enabled)
Active: active (running) since Mon 2023-09-11 00:05:54 UTC; 7s ago
Main PID: 28583 (gunicorn)
Tasks: 2 (limit: 1107)
Memory: 99.2M
CPU: 1.254s
CGroup: /system.slice/bookwyrm.service
??28583 /opt/bookwyrm/venv/bin/python3 /opt/bookwyrm/venv/bin/gunicorn bookwyrm.wsgi:application --bind
??28603 /opt/bookwyrm/venv/bin/python3 /opt/bookwyrm/venv/bin/gunicorn bookwyrm.wsgi:application --bind

Similarly, you can check the status of the remaining two services.

The final step in the installation process involves generating the admin code which is needed to create the administrator account.
$ sudo -u bookwyrm /opt/bookwyrm/venv/bin/python3 /opt/bookwyrm/manage.py admin_code

You can get the code at any time by re-running the same command.

You should get a similar output.
Use this code to create your admin account:

The next step is to access BookWyrm and set up your instance.

Step 10 – Access BookWyrm

Open the URL https://bookwyrm.example.com in your browser and you will get the following page.

BookWyrm Setup Screen

If everything seems okay, click the Continue button to proceed to the next page.

Create BookWyrm Administrator Account

Fill in the admin key you got in the previous step along with the administrator account credentials. Click the Sign up button when finished to proceed to the next page.

BookWyrm Site Settings

Here you will be asked to configure your site and add information and site policies.

Next, check your email settings by clicking the System >> Email Configuration from the left sidebar. Confirm your email settings listed on the page and click the Send test email button to send yourself a test email.

BookWyrm Email Configuration Page

If the mail was sent successfully, you should receive the following mail.

BookWyrm Test Email

You can also configure the remaining settings by accessing them from the left sidebar. Once you have done all that, your BookWyrm instance is ready for use.

Step 11 – Backup BookWyrm

BookWyrm ships with a Backup utility but it is customised for the Docker installation. It also ships with an automatic backup pruning utility which cleans the backup folder automatically. We will change the backup utility to suit our installation method and use the provided backup pruning utility along with it.

Create the ~/bookwyrm-backup.sh file and open it for editing.
$ nano ~/bookwyrm-backup.sh

Paste the following code in it.

if [ -z "$POSTGRES_DB" ]; then
echo "Database not specified, defaulting to bookwyrm"
if [ -z "$POSTGRES_USER" ]; then
echo "Database user not specified, defaulting to bookwyrm"

filename=backup_${BACKUP_DB}_$(date +%F)_$(date +%T)
PGPASSWORD="Your_Password" pg_dump -h localhost -U $BACKUP_USER $BACKUP_DB > ~/backups/$filename.sql

Save the file by pressing Ctrl + X and entering Y when prompted. Change the values of the POSTGRES_DB, POSTGRES_USER, and the PGPASSWORD variables according to the values you configured in step 2.

Copy the file to the /usr/local/bin directory.
$ sudo cp ~/bookwyrm-backup.sh /usr/local/bin/bookwyrm-backup.sh

Make the backup file executable.
$ sudo chmod +x /usr/local/bin/bookwyrm-backup.sh

Create the backup directory.
$ mkdir ~/backups

Copy the /opt/bookwyrm/postgres-docker/weed.sh file to the /usr/local/bin directory.
$ sudo cp /opt/bookwyrm/postgres-docker/weed.sh /usr/local/bin/bookwyrm-weed.sh

Create and open the cronfile for editing.
$ nano cronfile

Paste the following code in it.
0 0 * * * /usr/local/bin/bookwyrm-backup.sh
# This script will weed the backups directory. It will keep the 14
# most-recent backups, then one backup/week for the next four backups, then one
# backup/month after that.
0 5 * * * /usr/local/bin/bookwyrm-weed.sh -d 14 -w 4 -m -1 ~/backups

Save the file by pressing Ctrl + X and entering Y when prompted.

Copy the cronfile to the /etc/cron.d directory.
$ sudo cp ~/cronfile /etc/cron.d/cronfile

Set the correct permissions for the cronfile.
$ sudo chmod 0644 /etc/cron.d/cronfile

Submit the file to the crontab.
$ sudo crontab /etc/cron.d/cronfile

Create the cron.log file.
$ sudo touch /var/log/cron.log

Test the backup creation.
$ bookwyrm-backup.sh

Check the backups directory.
$ ls ~/backups -al
total 764
drwxr-xr-x 2 navjot navjot 4096 Sep 11 01:31 .
drwx------ 7 navjot navjot 4096 Sep 11 01:31 ..
-rw-r--r-- 1 navjot navjot 257577 Sep 11 01:21 backup_bookwyrm_2023-09-11.sql
-rw-r--r-- 1 navjot navjot 257577 Sep 11 01:27 backup_bookwyrm_2023-09-11_01:27:35.sql
-rw-r--r-- 1 navjot navjot 257577 Sep 11 01:31 backup_bookwyrm_2023-09-11_01:31:45.sql

Step 12 – Update BookWyrm

Updating your BookWyrm instance involves quite a few steps. First, pull the latest changes from the BookWyrm GitHub repository.
$ cd /opt/bookwyrm
$ sudo -u bookwyrm git pull

Install new Python dependencies.
$ sudo -u bookwyrm venv/bin/pip install -r requirements.txt

Compile the themes.
$ sudo -u bookwyrm venv/bin/python3 manage.py compile_themes

Collect all the static files.
$ sudo -u bookwyrm venv/bin/python3 manage.py collectstatic --no-input

Migrate the database. Create a backup first using the previous step.
$ sudo -u bookwyrm venv/bin/python3 manage.py migrate

Restart the BookWyrm services.
$ sudo systemctl restart bookwyrm bookwyrm-worker bookwyrm-scheduler


This concludes our tutorial on installing the BookWyrm social network on a Debian 12 server. If you have any questions, post them in the comments below.

Đăng ký liền tay Nhận Ngay Bài Mới

Subscribe ngay

Cám ơn bạn đã đăng ký !

Lỗi đăng ký !

Add Comment

Click here to post a comment

Đăng ký liền tay
Nhận Ngay Bài Mới

Subscribe ngay

Cám ơn bạn đã đăng ký !

Lỗi đăng ký !