1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
|
+++
date = 2022-06-07
title = "Self-Hosting FreshRSS"
description = "A guide to self-hosting the FreshRSS application on your own server."
+++
## Why RSS?
After noticing that I have collected 50+ blogs as bookmarks, I decided
to migrate back to using RSS feeds to stay up-to-date with my favorite
websites. Using RSS allows me to read all of these posts in a single app
(on both mobile & desktop) and allows me to be notified when new posts
are available.
However, I ran into one issue: syncing subscriptions and read/unread
posts across devices. Since I want to be able to easily read on both
mobile and desktop, I decided to look for a self-hosted RSS solution.
Thus, I found [FreshRSS](https://www.freshrss.org/) and was able to
successfully install it on my server in about 30 minutes.
## Documentation
While it's certainly not robust, the [FreshRSS
documentation](https://freshrss.github.io/FreshRSS/) is helpful for
figuring out basic information about the service.
However, I wanted to install this service as a Docker container and
stumbled across the [Docker
README](https://github.com/FreshRSS/FreshRSS/tree/edge/Docker) within
the GitHub repository.
This README was the documentation I actually needed. However, as you'll
see below, I still had to manually edit one file
(`config.php`) to access the API externally via my RSS apps.
## Installation
### DNS
The first step, as required by any external web service, was assigning a
domain name to use. I chose to use a subdomain, like
`rss.example.com`.
To assign this, I created an `A` record in my DNS settings
with the IPv4 address of the server and an `AAAA` record with
the IPv6 address of the server. Note: assigning an IPv6
(`AAAA`) record is optional, but I like to enable IPV6 for my
services.
```config
rss.example.com A xxx.xxx.xxx.xxx
rss.example.com AAAA xxxx:xxxx: ... :xxxx
```
### Docker
I initially tried to set up a `docker-compose.yml` file with
a `.env` file because I prefer to have a file I can look back
at later to see how I initially started the container, but it simply
wouldn't work for me. I'm not sure why, but I assume I wasn't telling
`docker-compose` where the `.env` file was.
Regardless, I chose to simply run the service with
`docker run`. See the following command for my
`docker run` configuration:
```sh
sudo docker run -d --restart unless-stopped --log-opt max-size=10m \
-p 8080:80 \
-e TZ=America/Chicago \
-e 'CRON_MIN=1,31' \
-v freshrss_data:/var/www/FreshRSS/data \
-v freshrss_extensions:/var/www/FreshRSS/extensions \
--name freshrss \
freshrss/freshrss
```
This started the container successfully and allowed me to visit the
FreshRSS instance at `localhost:8080`.
### Fresh RSS Set-Up
I **HIGHLY** suggest that you set up your user account prior to exposing
this service to the public. It's unlikely that someone is trying to
access the exact domain or IP/port you're assigning here, but as soon
as you expose this service, the first person to open the URL will be
able to create the admin user.
In order to set up your FreshRSS service, open the
`localhost:8080` URL in your browser (you may need to use a
local IP instead of `localhost` if you're accessing the page
from a different machine on the network - e.g.,
`192.168.1.20:8080`).
Once the page loads, set up your default user with a strong username and
password. You may also choose to configure other settings prior to
exposing this service.
### Nginx Reverse-Proxy
In order to access this service outside my home, I needed to set up a
reverse-proxy to connect `localhost:8080` to
`rss.example.com`.
First, I created a new Nginx configuration file:
```sh
sudo nano /etc/nginx/sites-available/rss.example.com
```
Within the config file, I pasted the following code:
```config
upstream freshrss {
server 127.0.0.1:8080;
keepalive 64;
}
server {
server_name rss.example.com;
listen 80;
location / {
# The final `/` is important.
proxy_pass http://localhost:8080/;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_read_timeout 90;
# Forward the Authorization header for the Google Reader API.
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
}
}
```
Finally, restart Nginx and you will be able to access your service via
HTTP:
```sh
sudo systemctl restart nginx.service
```
### HTTPS
However, I don't want to access my RSS feeds via HTTP. I want it
available only via HTTPS. In order to do this, I ran the
[certbot](https://certbot.eff.org/) program to generate SSL certificates
for me:
```sh
sudo certbot --nginx
```
This process will automatically generate an SSL certificate for you and
modify the Nginx configuration file to include a redirect from HTTP to
HTTPS.
## Post-Installation Fixes
At this point, we have a functional FreshRSS website, available from
anywhere and secured with HTTPS. However, attempting to connect this
service to an RSS app resulted in many errors regarding unavailable URLs
and incorrect credentials.
### API Set-Up
First, you need to open your user profile in FreshRSS
(`Settings` > `Profile`) and set an API password
in the field at the bottom. This is the password you will need to
provide to your RSS apps.
Once that is set and saved, click the link below the API password field
to open the API check tool. It should look something like
`https://localhost:8080/api/` or
`https://rss.example.com/api/`.
Within this page, you *should* see your correct external URL and
"PASS" at the bottom of each API type. This would mean everything is
set up correctly, and you can now move on and login to any RSS apps that
support self-hosted options.
In my case, the URL showed an internal URL and I had a warning that the
`base_url` variable may be misconfigured. If this is the
case, see the next section for a fix.
### Base URL Fix
In order to fix the `base_url` for the API, I opened up my
docker container with the following command:
```sh
sudo docker exec -it freshrss bash
```
Within this container, update the packages and install an editor:
```sh
apt-get update
apt-get install nano
```
Finally, open up `config.php` in the `data`
directory:
```sh
nano data/config.php
```
Within `config.php`, you will need to update the
`base_url` variable and update it to match your external URL.
In my case, I simply commented-out the incorrect URL with
`//` and added the correct one on a new line:
```php
<?php
return array (
...
// 'base_url' => 'http://localhost:8080',
'base_url' => 'https://rss.example.com',
...
)
>
```
You can now exit the file with `Ctrl + x`, press
`y` to save the file, and then click `Enter` to
keep the same file name.
Finally, just exit out of the docker container:
```sh
exit
```
Next, just restart the container:
```sh
sudo docker restart freshrss
```
Voilà! Your API check should now "PASS" and you should be able to use
one of the API URLs in your RSS apps.
In my case, I use [NetNewsWire](https://netnewswire.com) on my desktop
and phone.
|