FreshRSS RSS-Bridge
Overview
This image is a paired feed appliance. FreshRSS is the fast, self-hosted RSS and Atom reader. RSS-Bridge is its companion, which creates feeds for sites that do not publish their own. FreshRSS gives you a single clean reading interface that you own and control, with no tracking and no third-party cloud. When a site, video channel or social account has no RSS feed, RSS-Bridge builds one from the page so that FreshRSS can subscribe to it.
The two are wired together with security in mind. FreshRSS is the authenticated, internet-facing half, served by nginx and PHP 8.3 FPM on port 80. RSS-Bridge is the private half. It fetches upstream URLs on the requester's behalf, so an internet-exposed instance could be abused by anyone as an open feed proxy. RSS-Bridge is therefore bound to loopback only, on 127.0.0.1:8080, and is never reachable from the network. FreshRSS reaches RSS-Bridge over that loopback address and subscribes to the feed URLs it produces.
The whole stack runs on a hardened Ubuntu 24.04 LTS base that is patched at build time. It stores everything in a self-contained SQLite database on a dedicated Azure data disk, and it generates a unique administrator password on the first boot of every VM. Backed by 24/7 SecureAnyCloud support.
What you get:
- FreshRSS 1.29.1 served by nginx and PHP 8.3 FPM on
:80, with a per-VMadminaccount - RSS-Bridge (release 2025-08-05) as the private feed generator, bound to
127.0.0.1:8080only - Open proxy protection by design: RSS-Bridge is never exposed to the network, only FreshRSS is
- An example RSS-Bridge feed already subscribed for
admin, so the integration works out of the box - A self-contained SQLite database, with no separate database server to run or tune
- A per-VM admin password generated on first boot and recorded in a root-only file
- The Google Reader and Fever compatible APIs, enabled for mobile and desktop reader apps
- A dedicated Azure data disk at
/var/lib/freshrssfor the database, cache, favicons and feeds nginx.serviceandphp8.3-fpm.serviceas enabled and active systemd units- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes - 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.
Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point. Size up for large feed collections or many users.
In the network security group (NSG), allow inbound 22/tcp from your management network and 80/tcp for the FreshRSS web interface. Do not open port 8080 to the network. You do not need to, because RSS-Bridge is bound to loopback and FreshRSS reaches it over that address.
FreshRSS serves plain HTTP on port 80. For production, terminate TLS in front of it with your own domain (see Step 11).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for FreshRSS by SecureAnyCloud, and select Create.
On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).
Review the dedicated data disk on the Disks tab. Then select Review + create, then Create.
Step 2 - Deploy from the Azure CLI
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:freshrss-rss-bridge:default:latest
az vm create \
--resource-group <your-rg> \
--name freshrss-rss-bridge \
--image sac1647283583153:freshrss-rss-bridge:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name freshrss-rss-bridge --port 80 --priority 1010Step 3 - Connect to your VM
ssh azureuser@<public-ip>Step 4 - Confirm the services are running
nginx serves FreshRSS on port 80 and forwards PHP requests to PHP 8.3 FPM over a local socket. RSS-Bridge runs behind the same PHP-FPM. Confirm that the services are active and that nginx is listening on port 80:
systemctl is-active nginx php8.3-fpm freshrss-firstboot ss -tlnp | grep ':80 'Step 5 - Retrieve your admin password
On the first boot of every VM, freshrss-firstboot.service generates a unique password for the admin administrator account. It seeds the FreshRSS admin account with that password and sets the same password as the Google Reader and Fever API password. It writes the details to a root-only file. Read it with:
sudo cat /root/freshrss-credentials.txtThe file records the FreshRSS URL, the admin username and its password, the Google Reader and Fever API endpoints, and a note that RSS-Bridge runs on loopback only. Store the password in a safe place.
Step 6 - Confirm the FreshRSS stack and health endpoint
nginx serves an unauthenticated /healthz endpoint for load balancer probes. Confirm the FreshRSS release and the PHP version, check that the web interface responds, and check that the Fever API is enabled:
grep -oP "FRESHRSS_VERSION = '\K[^']+" /var/www/freshrss/constants.php php -v | head -1 curl -sI http://127.0.0.1/healthz | head -1 curl -s "http://127.0.0.1/api/fever.php?api"You should see the FreshRSS release 1.29.1, PHP 8.3, HTTP/1.1 200 OK from /healthz. The Fever API returns {"api_version":4,"auth":0}, which confirms that it is enabled.
Step 7 - Confirm RSS-Bridge is loopback only and generates feeds
RSS-Bridge is the companion that turns sites without feeds into feeds. It fetches upstream URLs on your behalf, so it is deliberately bound to 127.0.0.1:8080 and is never exposed to the network. This keeps it from being abused as an open proxy. Confirm that it listens on loopback only and responds:
ss -tln | grep ':8080 ' curl -sI http://127.0.0.1:8080/ | head -1The listen address is 127.0.0.1:8080 (and the IPv6 loopback [::1]:8080), never 0.0.0.0, and the interface returns HTTP/1.1 200 OK over loopback. From outside the VM, the same port is closed:
curl --max-time 5 http://<public-ip>:8080/
# curl: (28) Connection timed out — port 8080 is not open to the internet by design.
# RSS-Bridge is only reachable from the VM itself, over 127.0.0.1.Now test the feed pipeline end to end. The image ships a small built-in self-test source, reachable only on loopback, so you can confirm feed generation without depending on an external site. The following command asks the CSS Selector Bridge to turn that page into an Atom feed, exactly as FreshRSS does on the VM:
curl -s -G http://127.0.0.1:8080/ \
--data-urlencode action=display \
--data-urlencode bridge=CssSelectorBridge \
--data-urlencode home_page=http://127.0.0.1:8080/selftest/feed-source.html \
--data-urlencode 'url_selector=article h2 a' \
--data-urlencode format=Atom | head -12It prints a valid Atom document, an <feed> element with <entry> items. This shows that RSS-Bridge can fetch a page, extract items and emit a feed for FreshRSS to consume.
Step 8 - Open FreshRSS in your browser
Browse to http://<public-ip>/. FreshRSS redirects anonymous visitors to the sign-in page.
Step 9 - Sign in and read your feeds
Enter admin and the password from Step 5, then select Sign in. FreshRSS opens the reader. Your subscriptions are listed in the left-hand sidebar, and articles appear in the main pane.
The image ships with two subscriptions so that you have content straight away: a FreshRSS releases feed and a SecureAnyCloud RSS-Bridge example source feed. RSS-Bridge serves the second feed over loopback, so you can see the FreshRSS to RSS-Bridge integration working out of the box.
Step 10 - Subscribe FreshRSS to an RSS-Bridge feed
This is the core of the paired appliance. When you find a site with no RSS feed, you build one with RSS-Bridge and subscribe FreshRSS to it. RSS-Bridge runs on the same VM on loopback, so the feed URL that FreshRSS uses points at 127.0.0.1:8080, in the form:
http://127.0.0.1:8080/?action=display&bridge=<Bridge>&...&format=AtomTo add a feed, select the + (subscribe) control at the top of the FreshRSS sidebar and paste an RSS-Bridge feed URL of that shape, for example a CssSelectorBridge, YoutubeBridge or RedditBridge URL. FreshRSS fetches it over loopback and adds it like any other feed. The example feed that ships with the image was created this way.
Open Manage subscriptions (Subscription management) to see each feed and its underlying URL, including the loopback RSS-Bridge address.
To discover the exact bridge and parameters for a site, open RSS-Bridge's own UI from the VM. It is loopback only, so use an SSH local port forward from your workstation, which needs no NSG change:
ssh -L 8080:127.0.0.1:8080 azureuser@<public-ip>
# then browse to http://localhost:8080/ on your workstationRSS-Bridge shows a searchable list of bridges. Fill in a bridge form, select Generate feed, then copy the resulting http://127.0.0.1:8080/...&format=Atom URL into FreshRSS.
The enabled bridges include the generic CSS Selector, XPath, Feed Merge, Feed Reducer and Filter bridges plus popular site bridges such as YouTube, Reddit, Mastodon, Telegram and Twitch.
Step 11 - Connect mobile and desktop reader apps
To read on the go, point a compatible mobile or desktop app, such as Reeder, Fluent Reader, FeedMe or NetNewsWire, at this instance. In your app, choose the Google Reader API or Fever API. Use these endpoints with the admin username and the API password from Step 5:
Google Reader API: http://<public-ip>/api/greader.php Fever API: http://<public-ip>/api/fever.phpStep 12 - Production hardening: add a domain and TLS
The image ships FreshRSS on plain HTTP on port 80. TLS is a production step that this guide documents but the image does not bake in, so you can bring your own domain and certificate. For production:
- Put your own domain in front of the VM and terminate TLS. Use a reverse proxy such as Azure Application Gateway, or run certbot on the VM to issue a Let's Encrypt certificate for your domain. Forward traffic to nginx on
:80. - Once HTTPS is in place, restrict the NSG so that only
443/tcp(and22/tcpfrom your management network) is open to the internet. - Leave RSS-Bridge exactly as shipped, on loopback only. It never needs a public port, because FreshRSS reaches it over loopback. Never add an NSG rule for
8080.
Step 13 - Confirm your data lives on the dedicated disk
All FreshRSS data lives under /var/lib/freshrss, which is a dedicated Azure data disk captured into the image and re-provisioned on every VM. It holds the SQLite database, the per-user configuration, the feed cache and favicons:
df -h /var/lib/freshrss | tail -1 ls /var/lib/freshrss findmnt -no SOURCE,TARGET,FSTYPE /var/lib/freshrssServer Components
Component Version Role
FreshRSS 1.29.1 Self hosted RSS and Atom reader, internet facing on :80
RSS-Bridge 2025-08-05 Feed generator for sites without feeds, loopback only on 127.0.0.1:8080
nginx 1.24.0 Reverse proxy fronting FreshRSS on :80
PHP FPM 8.3 Runs FreshRSS and RSS-Bridge
SQLite bundled FreshRSS database on the dedicated data disk
Maintenance
- Back up your data: a backup is a copy of
/var/lib/freshrss(the SQLite database, per-user config, cache and favicons). Snapshot the data disk ortarthe directory. FreshRSS also ships./cli/db-backup.phpfor database-only exports. - Add users: sign in as admin and use the user management screen under Settings, or run
sudo -u www-data php /var/www/freshrss/cli/create-user.php --user <name> --password <pw>on the VM. - Refresh feeds: FreshRSS refreshes feeds on a schedule. Force a refresh for a user with
sudo -u www-data php /var/www/freshrss/cli/actualize-user.php --user admin. - Enable more bridges: the RSS-Bridge configuration at
/var/www/rss-bridge/config.ini.phpenables a curated set under[system]. Add anenabled_bridges[] = <BridgeName>line and refresh. Keep the set curated rather than enabling all bridges. The available bridge names are in/var/www/rss-bridge/bridges/. - Keep RSS-Bridge private: never open port 8080 in your NSG, and never rebind RSS-Bridge off loopback. Its loopback binding is the open-proxy protection for the whole appliance.
- Mobile and desktop apps: connect over the Google Reader or Fever API endpoints shown in Step 11, with the
adminuser and the API password. - Security updates: unattended security upgrades are enabled, so the OS keeps itself patched. Reboot when a new kernel is installed.
- TLS: for production, front FreshRSS with your own domain and a TLS-terminating reverse proxy or Azure Application Gateway (see Step 12).
Support
SecureAnyCloud provides 24/7/365 expert technical support for this image. Contact sales@secureanycloud.com. FreshRSS is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). RSS-Bridge is released into the public domain under the Unlicense. SecureAnyCloud provides this image, and additional charges apply for build, maintenance and 24/7 support.
Deploy on Azure
Launch FreshRSS + RSS-Bridge on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com