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.