TTRSS Migration in Practice

This article was last updated on: May 17, 2026 am

Background

A few years ago, I set up a TTRss + RssHub cluster on a cloud server for reading articles.

For details, see this post: Deploying a Full Self-Hosted RSS Solution on K8S - RssHub + Tiny Tiny Rss - East Wind Whisper Tech Blog

Recently, my cloud server subscription was about to expire, so I took the opportunity to migrate everything from the cloud to my Homelab2 cluster at home.

The migration was done on the morning of February 22, 2025, and it went very smoothly. After finishing, my wife hadn’t even woken up yet, so I used the extra time to write up a summary of the migration process.

The content is somewhat of a running log — feel free to reach out if you have questions or suggestions.

Tech Stack

Before Migration

  • K3s v1.23.10+k3s1
  • Ingress: Built-in Traefik
  • Certificates: cert-manager + DNSPod plugin
  • Storage: Built-in local-path
  • Backup: velero (manifests only)
  • Domain: suffix ewhisper.cn

After Migration

  • K3s: v1.31.5+k3s1
  • Ingress: Tailscale Operator
  • Certificates: Tailscale Operator
  • Storage: rook-ceph
  • Backup: volsync
  • Domain: suffix west-beta.ts.net

In summary, this wasn’t just a simple migration — it also required adjustments to storage and networking configurations.

This migration scenario is very specific to my use case, but the planning, steps, and approach should serve as a useful reference for others.

│ 📝Notes:

│ My complete post-migration code is at: homelab2/apps/rsshub at master · east4ming/homelab2

│ For brevity, I won’t paste detailed scripts/YAML here. Check the repo if you’re interested.

Migration in Practice

1. Backup

1.1 K8s Manifests Backup

  • Deploy
  • Service
  • PVC
  • IngressRoute (Traefik)

These were already backed up as JSON files via Velero. Then converted to YAML with unnecessary fields removed using the kubectl-neat.sh script.

│ 📝Notes:

kubectl-neat.sh uses the kubectl krew plugin: neat

PVC Data Backup

  • Redis data: dump.rdb
  • ttrss icons: Empty. No backup needed.
  • ttrss PostgreSQL data: Exec into the container and run pg_dumpall -c -U postgres > export.sql

│ 📚️Reference:
Database Update or Migration | 🐋 Awesome TTRSS

│ Also note: you may want to stop the ttrss Deployment before backing up Postgres data.

2. Downtime

On the original cluster, scale down all Deployments and stop all services.

3. Modify Manifests

Modify manifests to adapt to the new Homelab2 cluster.

  • Add the volsync.backube/privileged-movers annotation to the namespace to enable volsync privileged backup functionality
  • Add an initContainer to the postgres Deployment to delete the lost+found directory in the PostgreSQL data directory, otherwise startup fails (required due to rook-ceph PV behavior)
  • Add an initContainer to the ttrss Deployment using a busybox image to run chmod, setting the /var/www/feed-icons/ directory permissions to 777
  • Update the IngressRoute Host
  • Update SELF_URL_PATH in the ttrss Deployment to the new domain
  • Convert rsshub and ttrss Traefik IngressRoutes to Ingress resources and update the domains
  • Move passwords from environment variables to Secrets (Secrets added to .gitignore) (since my repo is public, passwords must not be exposed)

4. Manual Deployment

1
2
3
cd apps/rsshub
kubectl apply -f ns.yaml
kubectl apply -f deploy/ -f pvc/ -f secret/ -f service/ -f ingress/

5. Restore Data

First, scale down all Deployments except Postgres to prevent dirty data.

5.1. Postgres

Copy export.sql to the Postgres PV first.

Then exec into the Postgres pod and run the following command to restore data:

1
cat export.sql | psql -U postgres

5.2. Redis

Copy dump.rdb to the Redis PV. (Also need to chown)

6. Start Up

Start all Deployments.

7. Update TTRss Feed Settings

Log in to TTRss at: ttrss.west-beta.ts.net, go to: Preferences -> Feeds -> review each one, and change URLs from https://rss.ewhisper.cn… to: https://rss.west-beta.ts.net

8. Verification

  1. Verify RssHub is working properly
  2. Verify TTRss is working properly
    1. Log in to TTRss
    2. Read articles
    3. Verify that subscriptions work correctly

9. Backup

  1. Back up Postgres data

10. Onboard to ArgoCD

Since ArgoCD doesn’t monitor YAML files in subdirectories, all YAML files need to be placed in a single directory.

Use the move_and_rename.sh script to reorganize, then update .gitignore and delete the now-empty directories.

11. Run in Parallel for a While, Then Clean Up the Original Cluster

  1. Reclaim nodes
  2. Clean up DNS records
  3. Clean up domains
  4. Delete original cluster backup S3 bucket
  5. Other miscellaneous cleanup

Conclusion

The above is a summary of this TTRss migration. The detailed steps may not be directly useful to you, but I hope the planning, workflow, and approach can provide some value.