Feedly is a nice news aggregator but when you want to profit from all the nice feature you have to purchase pro or pro+. Don’t get me wrong, paying for a nice service is always a good thing, but with all the services one already pays (Spotify, …) it sums up quite nicely, especially if other family members also would like to use the same service ;-) Beside, I am a long time fan of Tiny Tiny RSS (ttrss), one of the best open source news reader out there.
So why not run your own instance of ttrss. I tend to run it on my server or k8s cluster, but as I play around a lot I eventually mess this up, so having a dedicate instance only for ttrss may be a better option. As mentioned in my last blog post, Hetzner has very competitive offers. Choosing an CX11 you get 1 CPU, 2GB of RAM and 20GB of disk space for as low as 2.68€ per month - which is nothing compared to other cloud providers out there. And it’s plenty to host your ttrss.
What’s missing is the setup of the ttrss. As usual I don’t want to do such things manually and if automated others should also be able to profit from my work. So I came up with my new ansible role papanito.ttrss
which automates the whole setup. In combination with the hcloud module I came up with the following playbook, which does
- create a server
- setup ttrss incl. php and postgres
- create a cloudflare tunnel
- hosts: localhost
gather_facts: no
pre_tasks:
- name: Add ssh-keys to hcloud
hcloud_ssh_key:
name: "{{ item.key }}"
public_key: "{{ item.value }}"
state: present
with_dict: "{{ ssh_keys }}"
delegate_to: localhost
tags:
- ansible
- authorised_key
- name: Create a basic server for ttrss
hcloud_server:
name: ttrss
server_type: cx11
image: debian-10
state: present
ssh_keys:
- ansible-user
delegate_to: localhost
register: result
- name: Store ipv4 of host
set_fact:
ttrss_server_ipv4: "{{ result.hcloud_server.ipv4_address }}"
- hosts: ttrss
vars:
ttrss_hostname: "rss.{{ external_domain }}"
ttrss_url: "https://{{ ttrss_hostname }}"
remove_unused_tunnels: true
tunnels:
rss:
hostname: "{{ ttrss_hostname }}"
url: http://localhost
no_logfile: true
ttrss_db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
34396565383164306133656664646136306237386537633162643664376462303363323432376364
3935653031393737303736356330366466613635363634350a376539343765333636623639383861
65313561613337346566346538653432623462366563346434623033626166616664316531623162
3239626430383431360a396135353432616332333931653165653738613133663435623562613936
66303939623539396663326233323738383866653237353561313434656263626361
install_basics: false
roles:
- { role: papanito.ttrss, ttrss_db_password: secret }
- { role: papanito.cloudflared, become: true}
Simply apply and volià you got your own instance of ttrss:

This is a good first start to get your own low-cost ttrss news aggregator which can be used in your browser or as well on mobile. There are still some features missing and if you also have suggestion what can be included in the ansible role, feel free to add an issue.
By the way, I also integrated the feediron which
allows you to replace an article’s contents by the contents of an element on the linked URL’s page i.e. create a “full feed”.
You may have a look at my configuration.