Readeck

Deploy Readeck for production

This document will show how to deploy Readeck on a Linux server with systemd and an HTTP reverse proxy. You'll need root access to create a user and install the service.

Create a user

It's strongly recommended to not run Readeck as the root user so the first thing we'll do is to create a group and a user for the service.

groupadd --system readeck
useradd --system --home-dir /var/lib/readeck --no-create-home --shell /bin/false --gid readeck readeck
mkdir /var/lib/readeck
chown readeck:readeck /var/lib/readeck

This creates a readeck user belonging to the group readeck, as well as a directory /var/lib/readeck.

Install the Readeck binary

This downloads the last Readeck release and makes it executable by any user on the system.

wget -O /usr/local/bin/readeck https://codeberg.org/readeck/readeck/releases/download/0.22.1/readeck-0.22.1-linux-amd64
chmod a+x /usr/local/bin/readeck

Create a configuration folder

You don't need a configuration file at first but you'll need a configuration folder:

mkdir /etc/readeck
chown readeck:root /etc/readeck
chmod 0750 /etc/readeck

Note

Should you need to create your own configuration file first, create /etc/readeck/config.toml using the provided example and replace the values that need replacing.

Tip

In case of a fully automated deployment, you can create one or several users with the command readeck user.

Create a Systemd service

Create a file /etc/systemd/system/readeck.service with the following content:

[Unit]
Description=Readeck - Open Source bookmark manager
After=network.target

[Service]
User=readeck
Group=readeck
WorkingDirectory=/var/lib/readeck
ExecStart=/usr/local/bin/readeck serve -config /etc/readeck/config.toml
Restart=on-failure
RestartSec=5

# Optional sandboxing options
ProtectSystem=full
ReadWritePaths=/etc/readeck /var/lib/readeck
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=yes
RestrictRealtime=yes
DevicePolicy=closed
ProtectClock=yes
ProtectHostname=yes
ProtectProc=invisible
ProtectSystem=full
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
LockPersonality=yes
SystemCallArchitectures=native
SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap @cpu-emulation @privileged

CapabilityBoundingSet=~CAP_RAWIO CAP_MKNOD
CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT
CapabilityBoundingSet=~CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK
CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_WAKE_ALARM
CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG
CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE
CapabilityBoundingSet=~CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW
CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG

[Install]
WantedBy=multi-user.target

Now, you can reload systemd and start readeck:

systemctl daemon-reload
systemctl start readeck

You can check that Readeck is running:

systemctl status readeck

Setup a reverse proxy

Important

When setting up a reverse proxy, don't add your own Content-Security-Policy headers. Readeck already has a very restrictive policy and you'll end up breaking your installation or having a less safe policy.

Now, Readeck is running but is listening publicly on the port 8000 for anyone who wants to connect. You might not want that and put it behind a reverse proxy such as Nginx or Caddy.

Let's first edit the configuration to listen only on localhost. In /etc/readeck/config.toml, edit the following lines:

[server]
host = "127.0.0.1"
port = 8000
allowed_hosts = ["read.example.net"]
trusted_proxies = ["127.0.0.1"]

Change the value of allowed_hosts, and port if you'd like to use something else.

Tip

Setting a value for allowed_hosts is not mandatory but a good security measure.

Nginx

We'll assume Nginx is installed and that you followed any necessary step to have a TLS certificate. Here's a fragment of a virtual host than can serve Readeck:

server {
    server_name readeck.example.net;

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

    # ... certificate configuration

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header  X-Real-IP         $remote_addr;
        proxy_set_header  Host              $host;
        proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto $scheme;
        proxy_redirect off;
        proxy_buffering off;
        client_max_body_size 50M;
    }
}

Warning

Make sure there is no trailing slash in the proxy_pass value, as Nginx behaves differently in that case.

Caddy

Here's a configuration fragment for a Caddyfile serving Readeck:

readeck.example.net {
    reverse_proxy localhost:8000
}

Apache 2

Here's a configuration fragment for an Apache 2 virtual host serving Readeck:

<VirtualHost *:80>
    ServerName readeck.example.net
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =readeck.example.net
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
    ServerName readeck.example.net

    # ... certificate configuration

    RewriteEngine on
    RewriteCond %{SERVER_NAME} !=readeck.example.net
    RewriteRule ^ - [F]

    RequestHeader set X-Forwarded-Proto https

    ErrorLog ${APACHE_LOG_DIR}/readeck.error.log
    CustomLog ${APACHE_LOG_DIR}/readeck.access.log combined

    ProxyRequests off
    ProxyPass / http://127.0.0.1:8000/
    ProxyPassReverse / http://127.0.0.1:8000/
    ProxyPreserveHost On
</VirtualHost>

Using CDNs and tunnels

Readeck has not been tested behind CDNs and tunnels and it doesn't provide any guaranty it will work in such setups.

If you're using Cloudflare, you must disable Rocket Loader, otherwise, no JavaScript features will work.

  • Commands
  • Compose Files
  • © 2024-2026 Readeck