How to Self-Host FreshRSS in 2026: Feed Refresh, Mobile API and Backups
A practical FreshRSS self-hosting guide covering Docker, ports, persistent data, TLS, security, backups and the failures that block production use. With checks.
A failed FreshRSS deployment does not always crash. It may serve a login page while feeds never refresh because cron is disabled or outbound DNS fails. Start with an end-to-end check instead: add feeds, run a scheduled refresh, mark an item read and synchronize that state through the mobile API.
That check matches the cataloged purpose of FreshRSS: self-hosted RSS reader with a compatible mobile API. It also exposes missing dependencies, wrong proxy assumptions and ephemeral data earlier than an uptime probe can.
Map FreshRSS before touching Docker
Separate four concerns for FreshRSS: ingress, the listener on 80, durable state and supporting services or local capacity. The external requirement for FreshRSS is scheduled feed refresh and outbound access to feed hosts. Test outbound DNS, TLS and provider behavior without publishing another inbound service.
Run the known-good transaction — add feeds, run a scheduled refresh, mark an item read and synchronize that state through the mobile API — before calling that separation complete. Measure feed count, refresh interval, slow publishers, database writes and concurrent API clients and keep the result with the deployment record. It provides both an acceptance criterion and the first capacity baseline.
Back up the state FreshRSS cannot recreate
Make a recovery manifest for FreshRSS: data, extensions and the selected database. Mount /var/www/FreshRSS/data before bootstrap, write harmless sample data and replace the container to prove that path is actually persistent. Check ownership and free space now, because a mounted but unwritable path behaves like no persistence at all.
Back up to a failure domain separate from the running server. Recreate FreshRSS from its pinned image and verify that subscriptions, categories, read state, filters and extensions return and scheduled refresh retrieves a new item. The persistent-volume guide helps translate that exercise into snapshot and retention policy.
Choose the FreshRSS trust boundary
Threat-model the action FreshRSS performs, not just its login form. Here the high-risk mistake is leaving the initial setup or default user accessible on a public host. Implement this boundary: finish setup privately, protect API passwords and configure trusted proxies before enabling mobile synchronization.
CRON_MIN controls behavior rather than confidentiality; validate its type and value, and store genuine FreshRSS credentials separately. Do not solve a permission error by running the container as root or mounting the host broadly. Resource limits also belong to the security design when feed count, refresh interval, slow publishers, database writes and concurrent API clients can be triggered by users.
What must pass before real FreshRSS data arrives
Convert the FreshRSS smoke test into a repeatable release command or short runbook. Its output must demonstrate this outcome: add feeds, run a scheduled refresh, mark an item read and synchronize that state through the mobile API. Record the application version, container digest, route hostname and test-data identifier with the result.
Run the same check after a routine container swap and after restoring data, extensions and the selected database elsewhere. The restore has succeeded when subscriptions, categories, read state, filters and extensions return and scheduled refresh retrieves a new item. Compare timing and consumption related to feed count, refresh interval, slow publishers, database writes and concurrent API clients; a large change is worth investigation even when the final action still passes.
Then exercise a safe failure: temporarily deny the test path used by scheduled feed refresh and outbound access to feed hosts. Confirm that FreshRSS surfaces the fault and returns to normal without destructive manual edits. Preserve only the necessary, redacted log excerpt. This four-part gate covers startup, persistence, recovery and failure handling.
A Docker baseline for FreshRSS
A production-shaped launch is intentionally boring: named state, explicit port and no secret inside the image.
docker run -d \
--name freshrss \
--restart unless-stopped \
-p 127.0.0.1:80:80 \
-v freshrss-data:/var/www/FreshRSS/data \
-e CRON_MIN=15 \
freshrss/freshrss:latest
The example is a baseline rather than a complete supporting stack. Allow and verify the outbound or client-side path required for scheduled feed refresh and outbound access to feed hosts. Check the effective mounts and listener, then try to add feeds, run a scheduled refresh, mark an item read and synchronize that state through the mobile API. Pin the working image before the next restart.
Prevent proxy success from masking application failure
The browser, API client and FreshRSS must agree on one origin. To make that true, declare trusted proxies and the canonical HTTPS base. Preserve the original host and protocol while keeping port 80 unavailable as a competing public address.
The site-down troubleshooting guide helps distinguish an unreachable route from a responding application. That distinction matters here: feeds never refresh because cron is disabled or outbound DNS fails. Only the former is fixed by ingress changes; the latter needs FreshRSS logs, state or workload inspection.
Watch the workload, not only the container
Observe the work FreshRSS performs: feed count, refresh interval, slow publishers, database writes and concurrent API clients. Set limits with headroom for that work and avoid a liveness probe that competes with it. The operator check should still attempt to add feeds, run a scheduled refresh, mark an item read and synchronize that state through the mobile API on a schedule.
For updates, remember that extensions, database migrations and feed-parser changes can affect refreshes even when login still works. Deploy the candidate against a recovered copy and repeat the known test. If feeds never refresh because cron is disabled or outbound DNS fails, use runtime logs and the actual network request to find which assumption changed.
Move the repeatable infrastructure work to Dockup
Dockup's one-click FreshRSS deployment should make replacement safe: the route continues to target 80, secrets are not baked into the image and persistent paths return on the new container. The same deployment can run on Dockup compute or an attached machine.
Complete the app-specific work by allowing and verifying scheduled feed refresh and outbound access to feed hosts, applying the canonical public address and running this acceptance check: add feeds, run a scheduled refresh, mark an item read and synchronize that state through the mobile API. Add the restore result to the runbook before real users arrive.
Frequently asked questions
What does FreshRSS need for a production deployment?
Route the FreshRSS container on port 80 through one HTTPS origin. The external delivery requirement is scheduled feed refresh and outbound access to feed hosts. Do not call FreshRSS ready until you can add feeds, run a scheduled refresh, mark an item read and synchronize that state through the mobile API.
Which FreshRSS data belongs in a backup?
Persist /var/www/FreshRSS/data and include data, extensions and the selected database in the same recovery manifest. A clean FreshRSS restore passes only when subscriptions, categories, read state, filters and extensions return and scheduled refresh retrieves a new item.
Does FreshRSS require HTTPS behind a reverse proxy?
Use HTTPS for the public FreshRSS origin and keep port 80 on the internal route. Apply the FreshRSS setting correctly: declare trusted proxies and the canonical HTTPS base. For FreshRSS, HTTPS protects credentials or user content in transit and keeps origin-sensitive client behavior consistent.
How should a FreshRSS upgrade be tested?
Restore current FreshRSS state into an isolated deployment, apply the candidate version and repeat its acceptance transaction. Pay particular attention because extensions, database migrations and feed-parser changes can affect refreshes even when login still works. Keep the previous FreshRSS image until its data-migration and rollback boundary are understood.
