I am subscribed to a lot of blog feeds, but (sadly) I don't have enough time to read all of them. This is especially the case for rather long (but often interesting) posts. Therefore it would be perfect to save these posts and read them in the near future.
There are already existing solutions for this like Mozilla Pocket. But as always I want to host this service on my own server (I have to justify the server somehow). A self-hosted solution is wallabag.
wallabag is a self-hostable PHP application allowing you to not miss any content anymore. Click, save and read it when you can. It extracts content so that you can read it when you have time. -- https://github.com/wallabag/wallabag#what-is-wallabag
Wallabag needs 2 things to work properly:
A wallabag server to actually store the articles.
The wallabag browser plugin Wallabagger to add new articles to your backlog.
Additionally wallabag can be accessed via browser or one of the official apps (Android and iOS).
I am going to run the wallabag server as a container because it is easy to manage the configuration with git and to migrate it to a new host (or share it with you).
Installation with Docker
The following files are stored in this layout:
.
├── data
├── docker
│ ├── Dockerfile
│ └── nginx
│ ├── nginx.conf
│ └── wallabag
├── docker-compose.yml
└── images
The data
and images
directories will be used to store persistent data like images and the scraped articles.
The docker-compose.yml
is based on an example provided by the wallabag project.
As I host the server at home this configuration is not hardened at all! I can't recommend using this configuration to host this service on the public internet!
So let's have a look at the main docker-compose
file. We declare two containers, wallabag
itself and a mariadb
database. There is also a nginx container to handle missing icons, but more about this later.
version: '3'
services:
nginx:
build:
context: ./docker
ports:
- 0.0.0.0:1337:1337
links:
- wallabag
wallabag:
image: wallabag/wallabag:2.4.1
environment:
- MYSQL_ROOT_PASSWORD=wallaroot
- SYMFONY__ENV__DATABASE_DRIVER=pdo_mysql
- SYMFONY__ENV__DATABASE_HOST=db
- SYMFONY__ENV__DATABASE_PORT=3306
- SYMFONY__ENV__DATABASE_NAME=wallabag
- SYMFONY__ENV__DATABASE_USER=wallabag
- SYMFONY__ENV__DATABASE_PASSWORD=wallapass
- SYMFONY__ENV__DATABASE_CHARSET=utf8mb4
- SYMFONY__ENV__MAILER_HOST=127.0.0.1
- SYMFONY__ENV__MAILER_USER=~
- SYMFONY__ENV__MAILER_PASSWORD=~
- SYMFONY__ENV__FROM_EMAIL=wallabag@example.com
- SYMFONY__ENV__DOMAIN_NAME=http://DOMAIN
volumes:
- ./images:/var/www/wallabag/web/assets/images
db:
image: mariadb:10
environment:
- MYSQL_ROOT_PASSWORD=wallaroot
volumes:
- ./data:/var/lib/mysql
redis:
image: redis:alpine
The nginx is needed because of CORS errors. A short look on the GitHub issue tracker showed that this is a known problem. A fix is to use a nginx as reverse proxy and add the following header add_header 'Access-Control-Allow-Origin' 'https://example.com'
. And this is exactly what I did.
The nginx
is based on the upstream image, but we will run a quick apt update && apt upgrade
to ensure we have the latest packages installed. Then we copy the base config nginx.conf
and our site config wallabag
into the container.
FROM nginx:1.19 AS nginx
ENV TZ=Etc/UTC
RUN export DEBIAN_FRONTEND=noninteractive \
&& apt-get update \
&& apt-get dist-upgrade -y --no-install-recommends
COPY nginx/wallabag /etc/nginx/sites-available/wallabag
COPY nginx/nginx.conf /etc/nginx/nginx.conf
RUN mkdir /etc/nginx/sites-enabled/ \
&& ln -s /etc/nginx/sites-available/wallabag /etc/nginx/sites-enabled/wallabag \
&& rm /etc/nginx/conf.d/default.conf
EXPOSE 1337
The main configuration of our nginx is basic, as I do not intent to expose this service to the public internet. I also do not care about error or access logs.
events {}
http {
server_tokens off;
sendfile on;
keepalive_timeout 65;
tcp_nodelay on;
include /etc/nginx/mime.types;
access_log off;
error_log /dev/null;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
The site configuration exposes the server on port 1337
and adds the missing CORS
header described earlier.
server {
listen 1337;
#server_name wallabag.foo.bar;
location / {
proxy_pass http://wallabag;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $remote_addr;
}
add_header 'Access-Control-Allow-Origin' 'http://DOMAIN'
}
Deployment
Now to the easy part. Run docker-compose up
to start the wallabag stack. Wallabag should now be online, and you can pair the browser plugin with the instance.