<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>gotosocial &amp;mdash; Matthias Klein</title>
    <link>https://blog.klein.ruhr/tag:gotosocial</link>
    <description></description>
    <pubDate>Wed, 20 May 2026 14:41:29 +0200</pubDate>
    <item>
      <title>GoToSocial - ready for Prime Time?</title>
      <link>https://blog.klein.ruhr/gotosocial-ready-for-prime-time</link>
      <description>&lt;![CDATA[img src=&#34;https://data.klein.ruhr/images/gotosocialprimetime.webp&#34; alt=&#34;Beschreibung&#34; style=&#34;border-radius: 12px !important; box-shadow: 0 8px 24px rgba(0,0,0,0.3) !important; margin: 2rem auto !important; display: block !important;&#34;&#xA;Short answer: Hell yes.&#xA;&#xA;After completing the full migration and running in production for weeks, I can confidently say GoToSocial is ready for serious use.&#xA;&#xA;Perfect For: ✅&#xA;&#xA;Self-hosters with limited resources (VPS with 1-2GB RAM? No problem!)&#xA;Single-user or small family instances (works great up to ~50 users based on community reports)&#xA;Homelab enthusiasts who value efficiency and simplicity&#xA;Privacy-conscious users who want full control over their data&#xA;Developers who appreciate clean, well-documented APIs&#xA;&#xA;Think Twice If: ⚠️&#xA;&#xA;Large communities (100+ users - not extensively tested yet)&#xA;Power users who rely heavily on advanced Mastodon features&#xA;Mobile-first users who need perfect app compatibility&#xA;Non-technical admins who prefer GUI-based administration&#xA;!--more--&#xA;Resource Requirements: The Reality Check&#xA;&#xA;Minimum viable setup:&#xA;VPS: 1GB RAM, 1 CPU core, 20GB storage&#xA;Cost: ~$5-10/month&#xA;&#xA;My production setup:&#xA;Server: Proxmox LXC container&#xA;Resources: 2GB RAM, 2 CPU cores, 50GB storage  &#xA;Actual usage: 426MB RAM average, 15% CPU peak&#xA;Cost: $0 (runs on existing homelab hardware)&#xA;&#xA;Scaling considerations:&#xA;Single-user: 512MB RAM sufficient&#xA;5-10 users: 1GB RAM recommended&#xA;10-50 users: 2GB RAM should handle it&#xA;Database grows ~1-2GB per month with active use&#xA;&#xA;Why Even Consider Switching?&#xA;&#xA;After months of running a self-hosted Mastodon instance in my homelab, I was getting increasingly frustrated. Not with the Fediverse concept - that&#39;s brilliant - but with Mastodon&#39;s resource appetite.&#xA;&#xA;The Starting Point:&#xA;&#xA;Mastodon Docker stack: 4-5 GB RAM consumption&#xA;Storage growth: ~100 GB with 7-day media retention&#xA;Performance: Noticeable delays in timeline updates&#xA;Maintenance: Regular cleanup scripts required to keep things manageable&#xA;&#xA;When you&#39;re running 60+ Docker stacks in your homelab like I am, resource efficiency isn&#39;t just nice-to-have - it&#39;s essential. GoToSocial promised the same Fediverse functionality at a fraction of the resource cost.&#xA;&#xA;Technical Stack Context:&#xA;&#xA;My homelab setup&#xA;Proxmox Cluster: 3 nodes&#xA;Total Containers: 60+ Docker stacks&#xA;Mastodon Dependencies:&#xA;  PostgreSQL (shared instance)&#xA;  Redis (shared instance) &#xA;  Elasticsearch (optional, but resource-hungry)&#xA;  Sidekiq workers (multiple processes)&#xA;  Web server + streaming API&#xA;&#xA;The complexity was getting out of hand.&#xA;&#xA;The Migration Process: Technical Deep-Dive&#xA;&#xA;Testing Phase&#xA;&#xA;Before committing fully, I ran GoToSocial parallel to Mastodon for four weeks. This gave me real-world data without burning bridges.&#xA;&#xA;compose.yml - GoToSocial setup&#xA;services:&#xA;  gotosocial:&#xA;    image: superseriousbusiness/gotosocial:latest&#xA;    containername: gotosocial&#xA;    restart: unless-stopped&#xA;    environment:&#xA;      GTSHOST: your-domain.com&#xA;      GTSDBTYPE: postgres&#xA;      GTSDBADDRESS: postgres:5432&#xA;      GTSDBDATABASE: gotosocial&#xA;      GTSDBUSER: gotosocial&#xA;      GTSDBPASSWORD: ${GTSDBPASSWORD}&#xA;      GTSACCOUNTSREGISTRATIONOPEN: false&#xA;      GTSACCOUNTSAPPROVALREQUIRED: true&#xA;      GTSMEDIAREMOTECACHEDAYS: 7&#xA;      GTSSTORAGELOCALBASEPATH: /gotosocial/storage&#xA;    volumes:&#xA;      ./data:/gotosocial/storage&#xA;    networks:&#xA;      traefikdefault&#xA;      gotosocialdb&#xA;    labels:&#xA;      &#34;traefik.enable=true&#34;&#xA;      &#34;traefik.http.routers.gotosocial.rule=Host(\your-domain.com\)&#34;&#xA;      &#34;traefik.http.routers.gotosocial.tls.certresolver=letsencrypt&#34;&#xA;    dependson:&#xA;      postgres&#xA;&#xA;  postgres:&#xA;    image: postgres:15-alpine&#xA;    containername: gotosocialdb&#xA;    restart: unless-stopped&#xA;    environment:&#xA;      POSTGRESDB: gotosocial&#xA;      POSTGRESUSER: gotosocial&#xA;      POSTGRESPASSWORD: ${GTSDBPASSWORD}&#xA;    volumes:&#xA;      ./postgres:/var/lib/postgresql/data&#xA;    networks:&#xA;      gotosocialdb&#xA;&#xA;Key Configuration Decisions:&#xA;&#xA;Separate Database: Not sharing with Mastodon to avoid conflicts&#xA;7-Day Media Retention: Balancing storage vs. content availability&#xA;Traefik Integration: Seamless SSL termination and routing&#xA;Bind Mounts: Easy backup/restore without Docker volume complexity&#xA;&#xA;Account Migration: The Technical Reality&#xA;&#xA;The actual migration process was surprisingly smooth, but had some gotchas:&#xA;&#xA;1\. Mastodon Export&#xA;&#xA;Export process (takes 24-48 hours for large instances)&#xA;Mastodon Admin → Settings → Import/Export → Request Archive&#xA;Results in: archive-[timestamp].tar.gz&#xA;&#xA;2\. Post Import with slurp&#xA;&#xA;Install slurp&#xA;git clone https://github.com/superseriousbusiness/gotosocial-slurp&#xA;cd gotosocial-slurp&#xA;go build .&#xA;&#xA;Import 380 posts from Mastodon archive&#xA;./slurp import \&#xA;  --gts-endpoint https://your-domain.com \&#xA;  --gts-token YOURGTSTOKEN \&#xA;  --mastodon-archive archive-20241215.tar.gz \&#xA;  --dry-run false&#xA;&#xA;Results: Perfect import with media, metadata, and timestamps preserved&#xA;&#xA;3\. Account Redirect Setup&#xA;&#xA;In Mastodon rails console&#xA;rails console&#xA;account = Account.findby(username: &#39;yourusername&#39;)&#xA;account.update(movedtoaccountid: nil) # Clear any previous moves&#xA;Then use Mastodon UI: Settings → Account → Move to different account&#xA;&#xA;Migration Casualties:&#xA;&#xA;Lost ~50 followers (12% dropout rate)&#xA;Likely causes: inactive accounts, app compatibility issues, users who don&#39;t follow redirects&#xA;Lesson: Quality over quantity - the remaining followers are actually engaged&#xA;&#xA;Performance Benchmarks: Numbers Don&#39;t Lie&#xA;&#xA;Memory Usage Deep-Dive&#xA;&#xA;Monitoring setup with docker stats&#xA;docker stats --format &#34;table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}&#34;&#xA;&#xA;Mastodon (before migration):&#xA;CONTAINER       CPU %    MEM USAGE / LIMIT     MEM %&#xA;mastodonweb    45.2%    2.1GiB / 8GiB        26.25%&#xA;mastodonsidekiq 23.1%   1.8GiB / 8GiB        22.50%&#xA;mastodonstreaming 12.4% 512MiB / 8GiB        6.40%&#xA;redis           8.7%     256MiB / 8GiB        3.20%&#xA;postgres        15.3%    800MiB / 8GiB        10.00%&#xA;elasticsearch   35.8%    1.2GiB / 8GiB        15.00%&#xA;Total: ~6.7GB peak usage&#xA;&#xA;GoToSocial (after migration):&#xA;CONTAINER       CPU %    MEM USAGE / LIMIT     MEM %&#xA;gotosocial      12.3%    419MiB / 8GiB        5.24%&#xA;postgres        3.2%     128MiB / 8GiB        1.60%&#xA;fedifetcher     0.8%     3.4MiB / 8GiB        0.04%&#xA;gts-holmirdas   1.1%     3.7MiB / 8GiB        0.05%&#xA;Total: ~555MB peak usage&#xA;&#xA;RAM Efficiency Gain: 92% reduction (6.7GB → 555MB)&#xA;&#xA;Storage Analysis&#xA;&#xA;Mastodon storage breakdown (after 6 months):&#xA;du -sh /opt/mastodon/&#xA;12G     system/  (cache, mediaattachments)&#xA;45G     public/  (user uploads, cached media)&#xA;43G     postgresdata/  (database)&#xA;Total: ~100GB with aggressive 7-day cleanup&#xA;&#xA;GoToSocial storage (extrapolated to same timeframe):&#xA;du -sh /opt/gotosocial/&#xA;8.2G    storage/  (all media, database)&#xA;26G     postgresdata/  (more efficient schema)&#xA;Total: ~35GB with 7-day remote media retention&#xA;&#xA;Storage Efficiency Gain: 65% reduction&#xA;&#xA;Why GoToSocial is so much leaner:&#xA;&#xA;Single binary: No separate web/worker/streaming processes&#xA;Efficient database schema: Less metadata overhead per post&#xA;Smart media handling: Better deduplication and compression&#xA;No Elasticsearch: Full-text search handled by PostgreSQL&#xA;&#xA;Federation Performance: Quality Over Quantity&#xA;&#xA;One of my biggest concerns was federation reach. Would a single-user GoToSocial instance feel isolated?&#xA;&#xA;The Data After 4 Days:&#xA;&#xA;Federation stats from GoToSocial admin API&#xA;curl -H &#34;Authorization: Bearer $ADMINTOKEN&#34; \&#xA;  https://your-domain.com/api/v1/admin/accounts/stats&#xA;&#xA;{&#xA;  &#34;knowninstances&#34;: 2750,&#xA;  &#34;federatedposts&#34;: 12847,&#xA;  &#34;localposts&#34;: 380,&#xA;  &#34;activeusersweek&#34;: 1&#xA;}&#xA;&#xA;Federation happens FAST:&#xA;&#xA;2,750+ instances discovered in 4 days&#xA;No traditional relays needed&#xA;Content discovery through intelligent RSS integration&#xA;Federation quality actually improved (more relevant content, less noise)&#xA;&#xA;Content Discovery: Building GTS-HolMirDas&#xA;&#xA;Here&#39;s where things got interesting. Small Fediverse instances suffer from the &#34;empty timeline problem&#34; - without many local users or relay connections, your federated timeline stays pretty barren.&#xA;&#xA;The Technical Challenge&#xA;&#xA;Traditional approach: Join relays&#xA;Problems:&#xA;- High resource usage&#xA;- Lots of irrelevant content  &#xA;- Reliability issues&#xA;- Limited control over content quality&#xA;&#xA;My Solution: Intelligent RSS-to-Fediverse Bridge&#xA;&#xA;I built GTS-HolMirDas (German pun meaning &#34;fetch this for me&#34;), an open-source tool that:&#xA;&#xA;Core Architecture:&#xA;&#xA;Simplified architecture overview&#xA;class HolMirDas:&#xA;    def init(self):&#xA;        self.rssfeeds = self.loadfeedconfig()  # 102 RSS feeds&#xA;        self.gtsclient = GoToSocialClient()&#xA;        self.duplicatetracker = DuplicateDetector()&#xA;        self.instancetracker = InstanceTracker()&#xA;    &#xA;    def runcycle(self):&#xA;        &#34;&#34;&#34;Main processing loop - runs every hour&#34;&#34;&#34;&#xA;        for feedurl, config in self.rssfeeds.items():&#xA;            self.processfeed(feedurl, config)&#xA;        &#xA;        self.cleanupoldentries()&#xA;        self.updatefederationstats()&#xA;&#xA;Smart Features:&#xA;&#xA;Cross-platform attribution: Properly credits Mastodon, Misskey, Pleroma authors&#xA;Duplicate detection: Prevents the same post from appearing multiple times&#xA;Instance discovery: Automatically tracks new Fediverse instances&#xA;Rate limiting: Respects both RSS and GoToSocial API limits&#xA;&#xA;Performance Metrics&#xA;&#xA;Real-time stats from my instance:&#xA;📊 GTS-HolMirDas Run Statistics:&#xA;   ⏱️  Runtime: 4:39 minutes per cycle&#xA;   📄 Posts processed: 65 per hour  &#xA;   🌐 Current known instances: 2,697&#xA;   ➕ New instances discovered: +22 per run&#xA;   📡 RSS feeds monitored: 102&#xA;   ⚡ Processing rate: 13.9 posts/minute&#xA;   🔄 Runs every 60 minutes automatically&#xA;&#xA;RSS Feed Sources&#xA;&#xA;feedconfig.yml (excerpt)&#xA;feeds:&#xA;  # Major Mastodon instances&#xA;  url: &#34;https://mastodon.social/@Gargron.rss&#34;&#xA;    platform: &#34;mastodon&#34;&#xA;    instance: &#34;mastodon.social&#34;&#xA;  &#xA;  # Specialized instances  &#xA;  url: &#34;https://fosstodon.org/users/exampleuser.rss&#34;&#xA;    platform: &#34;mastodon&#34;&#xA;    instance: &#34;fosstodon.org&#34;&#xA;    &#xA;  # Other Fediverse platforms&#xA;  url: &#34;https://pixelfed.social/users/photographer.atom&#34;&#xA;    platform: &#34;pixelfed&#34;&#xA;    instance: &#34;pixelfed.social&#34;&#xA;&#xA;The Result: A vibrant federated timeline despite being a single-user instance, with content that&#39;s actually relevant to my interests.&#xA;&#xA;Lessons Learned: The Good, The Bad, The Ugly&#xA;&#xA;What Works Brilliantly ✅&#xA;&#xA;Resource Efficiency is Game-Changing&#xA;&#xA;Single binary vs. multiple processes: Much simpler debugging&#xA;Memory usage stays consistently under 500MB even under load&#xA;CPU usage rarely spikes above 15% during federation heavy-lifting&#xA;Storage growth is predictable and manageable&#xA;&#xA;Federation Just Works™&#xA;&#xA;No manual instance discovery needed&#xA;ActivityPub compatibility is excellent&#xA;Cross-platform federation (Mastodon ↔ Misskey ↔ Pleroma) seamless&#xA;Better federation performance than expected&#xA;&#xA;Operational Simplicity&#xA;&#xA;Mastodon maintenance (weekly):&#xA;docker compose exec web bundle exec rake mastodon:media:removeremote&#xA;docker compose exec web bundle exec rake mastodon:previewcards:removeold&#xA;docker compose exec web bundle exec rake mastodon:feeds:build&#xA;+ manual Elasticsearch index management&#xA;+ Sidekiq queue monitoring&#xA;+ Redis memory management&#xA;&#xA;GoToSocial maintenance (monthly):&#xA;That&#39;s it. Seriously.&#xA;&#xA;The Challenges ⚠️&#xA;&#xA;Client Ecosystem&#xA;&#xA;Mobile Apps: Hit-or-miss compatibility&#xA;&#x9;iOS Tusker: Works perfectly, actively maintained&#xA;&#x9;iOS Ice Cubes: Notification issues, otherwise great&#xA;&#x9;Android Tusky: Mostly works, some UI quirks&#xA;&#x9;Android Fedilab: Best overall experience&#xA;Web Clients: Need self-hosting for optimal experience&#xA;&#xA;Missing Mastodon Features (That You Might Miss)&#xA;&#xA;Advanced search capabilities (no Elasticsearch)&#xA;Trending hashtags/posts&#xA;Some admin tools are more basic&#xA;Limited API endpoints compared to Mastodon&#xA;&#xA;Federation Edge Cases&#xA;&#xA;Occasional federation hiccups I encountered:&#xA;Large instances sometimes lag on post delivery (not GTS fault)&#xA;Some Mastodon instances reject GTS posts (rare, usually config issues)&#xA;Media federation can be slow during high-traffic periods&#xA;&#xA;Mobile Apps: Real-World Testing&#xA;&#xA;iOS Testing Results:&#xA;&#xA;Tusker: 9/10&#xA;&#xA;✅ Full feature support&#xA;✅ Reliable notifications&#xA;✅ Good performance&#xA;❌ Paid app ($3.99)&#xA;&#xA;Ice Cubes: 7/10&#xA;&#xA;✅ Beautiful interface&#xA;✅ Active development&#xA;❌ Notification reliability issues&#xA;❌ Some API compatibility gaps&#xA;&#xA;Self-Hosted Web Clients:&#xA;&#xA;My current setup&#xA;services:&#xA;  phanpy:&#xA;    image: cheeaun/phanpy:latest&#xA;    containername: phanpy&#xA;    environment:&#xA;      DEFAULTINSTANCE: your-domain.com&#xA;    labels:&#xA;      &#34;traefik.http.routers.phanpy.rule=Host(\social.your-domain.com\)&#34;&#xA;  &#xA;  elk:&#xA;    image: elkzone/elk:latest&#xA;    containername: elk&#xA;    environment:&#xA;      DEFAULTSERVER: your-domain.com&#xA;    labels:&#xA;      &#34;traefik.http.routers.elk.rule=Host(\elk.your-domain.com\)&#34;&#xA;&#xA;Client Comparison:&#xA;&#xA;Phanpy: Better features, more Mastodon-like, slightly dated UI&#xA;Elk: Gorgeous interface, modern UX, fewer power-user features&#xA;Official GTS Web UI: Basic but functional, good for admin tasks&#xA;&#xA;Cost Analysis&#xA;&#xA;Comparison with Mastodon hosting costs:&#xA;&#xA;Mastodon requirements:&#xA;&#xA;Minimum: 4GB RAM, 2 cores&#xA;Monthly VPS cost: $20-40&#xA;Additional services needed: Redis, Elasticsearch (optional but recommended)&#xA;&#xA;GoToSocial requirements:&#xA;&#xA;Minimum: 1GB RAM, 1 core&#xA;Monthly VPS cost: $5-10&#xA;Additional services: Just PostgreSQL (can use SQLite for single-user)&#xA;&#xA;Annual savings: $180-360 per year&#xA;&#xA;Backup Strategy: Lessons from Migration&#xA;&#xA;!/bin/bash&#xA;My automated backup script&#xA;DATE=$(date +%Y%m%d%H%M%S)&#xA;BACKUPDIR=&#34;/opt/backups/gotosocial&#34;&#xA;&#xA;Database backup&#xA;docker compose exec -T postgres pgdump -U gotosocial gotosocial   \&#xA;  &#34;$BACKUPDIR/dbbackup$DATE.sql&#34;&#xA;&#xA;Media and storage backup&#xA;tar -czf &#34;$BACKUPDIR/storagebackup$DATE.tar.gz&#34; \&#xA;  /opt/gotosocial/data/&#xA;&#xA;Configuration backup  &#xA;cp compose.yml &#34;$BACKUPDIR/composebackup$DATE.yml&#34;&#xA;&#xA;Keep only last 7 days of backups&#xA;find &#34;$BACKUPDIR&#34; -name &#34;.sql&#34; -mtime +7 -delete&#xA;find &#34;$BACKUPDIR&#34; -name &#34;.tar.gz&#34; -mtime +7 -delete&#xA;&#xA;echo &#34;Backup completed: $DATE&#34;&#xA;&#xA;Recovery tested and verified - I&#39;ve successfully restored from backup during my testing phase. The process is straightforward and well-documented.&#xA;&#xA;The Tools That Make It Work&#xA;&#xA;All the supporting tools I built are open source and production-ready:&#xA;&#xA;GTS-HolMirDas&#xA;&#xA;Repository:https://git.klein.ruhr/matthias/gts-holmirdas&#xA;&#xA;Features:&#xA;&#xA;102 RSS feed sources from diverse Fediverse instances&#xA;Cross-platform attribution (Mastodon, Misskey, Pleroma, Pixelfed)&#xA;Intelligent duplicate detection&#xA;Automatic instance discovery&#xA;Rate limiting and error handling&#xA;Docker-ready deployment&#xA;&#xA;Setup in 5 minutes:&#xA;&#xA;git clone https://git.your-domain.com/username/gts-holmirdas.git&#xA;cd gts-holmirdas&#xA;cp config.example.yml config.yml&#xA;Edit config.yml with your GTS instance details&#xA;docker compose up -d&#xA;&#xA;FediFetcher Integration&#xA;&#xA;Repository: blog.thms.uk/fedifetcher&#xA;&#xA;While not my creation, FediFetcher perfectly complements GoToSocial for thread completion:&#xA;&#xA;compose.yml addition&#xA;services:&#xA;  fedifetcher:&#xA;    image: nanos/fedifetcher:latest&#xA;    containername: fedifetcher&#xA;    environment:&#xA;      HOMEINSTANCE=your-domain.com&#xA;      ACCESSTOKEN=${FEDIFETCHERTOKEN}&#xA;      REPLYINTERVALHOURS=1&#xA;      BACKFILLHOURS=24&#xA;    restart: unless-stopped&#xA;&#xA;What it does:&#xA;&#xA;Fetches missing replies to posts in your timeline&#xA;Completes conversation threads automatically&#xA;Backfills content from instances your server hasn&#39;t seen yet&#xA;Minimal resource usage (3-4MB RAM)&#xA;&#xA;Monitoring and Observability&#xA;&#xA;Prometheus metrics (optional but recommended)&#xA;services:&#xA;  prometheus:&#xA;    image: prom/prometheus:latest&#xA;    volumes:&#xA;      ./prometheus.yml:/etc/prometheus/prometheus.yml&#xA;    command:&#xA;      &#39;--config.file=/etc/prometheus/prometheus.yml&#39;&#xA;      &#39;--storage.tsdb.path=/prometheus&#39;&#xA;      &#39;--web.console.libraries=/etc/prometheus/consolelibraries&#39;&#xA;&#xA;prometheus.yml&#xA;scrapeconfigs:&#xA;  jobname: &#39;gotosocial&#39;&#xA;    staticconfigs:&#xA;      targets: [&#39;gotosocial:8080&#39;]&#xA;    metricspath: &#39;/metrics&#39;&#xA;&#xA;Key metrics to monitor:&#xA;&#xA;Memory usage trends&#xA;Database growth rate&#xA;Federation success rates&#xA;API response times&#xA;Storage utilization&#xA;&#xA;Migration Gotchas and Pro Tips&#xA;&#xA;Things I Wish I&#39;d Known Before Starting&#xA;&#xA;1\. Test Federation Early&#xA;&#xA;Verify federation is working before migrating followers&#xA;curl -H &#34;Accept: application/activity+json&#34; \&#xA;  https://your-domain.com/users/yourusername&#xA;&#xA;Should return ActivityPub JSON, not HTML&#xA;&#xA;2\. Mobile App Testing is Critical  &#xA;Don&#39;t assume your favorite Mastodon app will work perfectly. Test extensively with your actual usage patterns before committing.&#xA;&#xA;3\. Content Discovery Takes Time  &#xA;The federated timeline won&#39;t be instantly populated. Plan for a &#34;quiet period&#34; of 1-2 weeks while content discovery tools build up your federation network.&#xA;&#xA;4\. Backup Before Migration&#xA;&#xA;Create a complete Mastodon backup before starting&#xA;docker compose exec web rake mastodon:backup:create&#xA;This creates a full export in /app/backup/&#xA;&#xA;5\. Domain Considerations  &#xA;If you&#39;re changing domains during migration (like I did), be prepared for some federation hiccups. Some instances cache domain information aggressively.&#xA;&#xA;Performance Tuning Tips&#xA;&#xA;PostgreSQL optimization for GoToSocial&#xA;Add to postgres container environment:&#xA;POSTGRESINITDBARGS: &#34;--data-checksums&#34;&#xA;In postgresql.conf:&#xA;sharedbuffers = 128MB          # For 1GB RAM systems&#xA;effectivecachesize = 512MB    # 3/4 of available RAM&#xA;workmem = 4MB                  # Per query operation&#xA;maintenanceworkmem = 64MB     # For maintenance operations&#xA;GoToSocial-specific optimizations:&#xA;In your .env file:&#xA;GTSCACHEMEMORYTARGET=100MB           # Adjust based on available RAM&#xA;GTSMEDIAREMOTECACHEDAYS=7           # Balance storage vs. availability&#xA;GTSACCOUNTSALLOWCUSTOMCSS=false     # Disable if not needed&#xA;GTSWEBASSETBASEDIR=/gotosocial/web  # Serve assets efficiently&#xA;&#xA;Community Impact and Future Plans&#xA;&#xA;What This Migration Means for the Fediverse&#xA;&#xA;Resource Democracy: By proving that high-quality Fediverse instances can run on minimal resources, we&#39;re making decentralization more accessible to everyone.&#xA;&#xA;Tool Ecosystem: The tools developed for this migration (especially GTS-HolMirDas) are helping other small instance operators solve the same content discovery challenges.&#xA;&#xA;Documentation: This migration provides a real-world data point for others considering similar moves.&#xA;&#xA;Future Development Plans&#xA;&#xA;GTS-HolMirDas Roadmap:&#xA;&#xA;Web-based configuration interface&#xA;Better RSS feed quality scoring&#xA;Integration with more Fediverse platforms (PeerTube, Funkwhale)&#xA;Machine learning-based content relevance filtering&#xA;Multi-instance support for hosting providers&#xA;&#xA;Community Feedback Integration: Based on initial user feedback, the most requested features are:&#xA;&#xA;Easier RSS feed discovery and management&#xA;Better content filtering options&#xA;Integration with existing relay networks&#xA;Automated instance health monitoring&#xA;&#xA;Bottom Line: The Numbers Don&#39;t Lie&#xA;&#xA;Migration Summary:&#xA;&#xA;Timeline: 4 weeks of testing, 2 days for full migration&#xA;Resource savings: 92% RAM reduction, 65% storage reduction&#xA;Follower retention: 88% (better than expected)&#xA;Federation growth: 2,750+ instances in first week&#xA;Operational complexity: Significantly reduced&#xA;Cost savings: $180-360 annually in hosting costs&#xA;Satisfaction level: 9.5/10 (would migrate again)&#xA;&#xA;The Real Kicker: GoToSocial doesn&#39;t just match Mastodon&#39;s functionality at lower resource usage - in many ways, it performs better. The federated timeline is more relevant, the interface is faster, and the operational overhead is practically non-existent.&#xA;&#xA;You should definitely consider GoToSocial if:&#xA;&#xA;You&#39;re running a single-user or small instance&#xA;Resource efficiency matters to you&#xA;You value operational simplicity&#xA;You&#39;re comfortable with slightly less mature tooling&#xA;You want to contribute to Fediverse diversity&#xA;&#xA;Stick with Mastodon if:&#xA;&#xA;You&#39;re running a large community (100+ users)&#xA;You need enterprise-grade admin tools&#xA;Your users depend on specific Mastodon features&#xA;You have abundant server resources&#xA;Stability trumps efficiency for your use case&#xA;&#xA;My recommendation: Set up a test GoToSocial instance and run it parallel to your existing setup for a month. The resource cost is minimal, and you&#39;ll get real-world data for your specific use case.&#xA;&#xA;The Fediverse is strongest when it&#39;s diverse - different platforms solving different problems for different communities. GoToSocial has earned its place in that ecosystem.&#xA;&#xA;---&#xA;&#xA;Resources and Links&#xA;&#xA;Essential Tools&#xA;&#xA;GoToSocial:https://gotosocial.org&#xA;GTS-HolMirDas:https://git.klein.ruhr/matthias/gts-holmirdas&#xA;FediFetcher:https://blog.thms.uk/fedifetcher&#xA;Slurp (Post Migration):https://github.com/VyrCossont/slurp&#xA;&#xA;Mobile Apps That Work Well&#xA;&#xA;iOS Tusker: App Store (paid, highly recommended)&#xA;iOS Ice Cubes: App Store (free, some quirks)&#xA;Android Fedilab: F-Droid/Play Store (best Android option)&#xA;Android Tusky: F-Droid/Play Store (decent alternative)&#xA;&#xA;Web Clients (Self-Hosted)&#xA;&#xA;Phanpy:https://github.com/cheeaun/phanpy&#xA;Elk:https://github.com/elk-zone/elk&#xA;&#xA;Community&#xA;&#xA;GoToSocial Documentation:https://docs.gotosocial.org&#xA;Matrix Support: #gotosocial:superseriousbusiness.org&#xA;GitHub Issues:https://github.com/superseriousbusiness/gotosocial&#xA;&#xA;---&#xA;&#xA;Questions? Feedback? Find me on the Fediverse at @matthias@me.klein.ruhr - I&#39;m always happy to discuss self-hosting, the Fediverse, and efficient technology solutions!&#xA;&#xA;If this post helped you with your own migration, consider starring the GTS-HolMirDas repository or contributing to the GoToSocial project. The Fediverse grows stronger with every successful self-hosted instance.]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://data.klein.ruhr/images/gotosocialprimetime.webp" alt="Beschreibung" style="border-radius: 12px !important; box-shadow: 0 8px 24px rgba(0,0,0,0.3) !important; margin: 2rem auto !important; display: block !important;">
Short answer: Hell yes.</p>

<p>After completing the full migration and running in production for weeks, I can confidently say GoToSocial is ready for serious use.</p>

<p><strong>Perfect For:</strong> ✅</p>
<ul><li>Self-hosters with limited resources (VPS with 1-2GB RAM? No problem!)</li>
<li>Single-user or small family instances (works great up to ~50 users based on community reports)</li>
<li>Homelab enthusiasts who value efficiency and simplicity</li>
<li>Privacy-conscious users who want full control over their data</li>
<li>Developers who appreciate clean, well-documented APIs</li></ul>

<p><strong>Think Twice If:</strong> ⚠️</p>
<ul><li>Large communities (100+ users – not extensively tested yet)</li>
<li>Power users who rely heavily on advanced Mastodon features</li>
<li>Mobile-first users who need perfect app compatibility</li>

<li><p>Non-technical admins who prefer GUI-based administration
</p>

<h2 id="resource-requirements-the-reality-check">Resource Requirements: The Reality Check</h2></li></ul>

<pre><code class="language-yaml"># Minimum viable setup:
VPS: 1GB RAM, 1 CPU core, 20GB storage
Cost: ~$5-10/month

# My production setup:
Server: Proxmox LXC container
Resources: 2GB RAM, 2 CPU cores, 50GB storage  
Actual usage: 426MB RAM average, 15% CPU peak
Cost: $0 (runs on existing homelab hardware)

# Scaling considerations:
- Single-user: 512MB RAM sufficient
- 5-10 users: 1GB RAM recommended
- 10-50 users: 2GB RAM should handle it
- Database grows ~1-2GB per month with active use
</code></pre>

<h2 id="why-even-consider-switching">Why Even Consider Switching?</h2>

<p>After months of running a self-hosted Mastodon instance in my homelab, I was getting increasingly frustrated. Not with the Fediverse concept – that&#39;s brilliant – but with Mastodon&#39;s resource appetite.</p>

<p><strong>The Starting Point:</strong></p>
<ul><li>Mastodon Docker stack: 4-5 GB RAM consumption</li>
<li>Storage growth: ~100 GB with 7-day media retention</li>
<li>Performance: Noticeable delays in timeline updates</li>
<li>Maintenance: Regular cleanup scripts required to keep things manageable</li></ul>

<p>When you&#39;re running 60+ Docker stacks in your homelab like I am, resource efficiency isn&#39;t just nice-to-have – it&#39;s essential. GoToSocial promised the same Fediverse functionality at a fraction of the resource cost.</p>

<p><strong>Technical Stack Context:</strong></p>

<pre><code class="language-yaml"># My homelab setup
Proxmox Cluster: 3 nodes
Total Containers: 60+ Docker stacks
Mastodon Dependencies:
  - PostgreSQL (shared instance)
  - Redis (shared instance) 
  - Elasticsearch (optional, but resource-hungry)
  - Sidekiq workers (multiple processes)
  - Web server + streaming API
</code></pre>

<p>The complexity was getting out of hand.</p>

<h2 id="the-migration-process-technical-deep-dive">The Migration Process: Technical Deep-Dive</h2>

<h3 id="testing-phase">Testing Phase</h3>

<p>Before committing fully, I ran GoToSocial parallel to Mastodon for four weeks. This gave me real-world data without burning bridges.</p>

<pre><code class="language-yaml"># compose.yml - GoToSocial setup
services:
  gotosocial:
    image: superseriousbusiness/gotosocial:latest
    container_name: gotosocial
    restart: unless-stopped
    environment:
      GTS_HOST: your-domain.com
      GTS_DB_TYPE: postgres
      GTS_DB_ADDRESS: postgres:5432
      GTS_DB_DATABASE: gotosocial
      GTS_DB_USER: gotosocial
      GTS_DB_PASSWORD: ${GTS_DB_PASSWORD}
      GTS_ACCOUNTS_REGISTRATION_OPEN: false
      GTS_ACCOUNTS_APPROVAL_REQUIRED: true
      GTS_MEDIA_REMOTE_CACHE_DAYS: 7
      GTS_STORAGE_LOCAL_BASE_PATH: /gotosocial/storage
    volumes:
      - ./data:/gotosocial/storage
    networks:
      - traefik_default
      - gotosocial_db
    labels:
      - &#34;traefik.enable=true&#34;
      - &#34;traefik.http.routers.gotosocial.rule=Host(\`your-domain.com\`)&#34;
      - &#34;traefik.http.routers.gotosocial.tls.certresolver=letsencrypt&#34;
    depends_on:
      - postgres

  postgres:
    image: postgres:15-alpine
    container_name: gotosocial_db
    restart: unless-stopped
    environment:
      POSTGRES_DB: gotosocial
      POSTGRES_USER: gotosocial
      POSTGRES_PASSWORD: ${GTS_DB_PASSWORD}
    volumes:
      - ./postgres:/var/lib/postgresql/data
    networks:
      - gotosocial_db
</code></pre>

<p><strong>Key Configuration Decisions:</strong></p>
<ul><li>Separate Database: Not sharing with Mastodon to avoid conflicts</li>
<li>7-Day Media Retention: Balancing storage vs. content availability</li>
<li>Traefik Integration: Seamless SSL termination and routing</li>
<li>Bind Mounts: Easy backup/restore without Docker volume complexity</li></ul>

<h3 id="account-migration-the-technical-reality">Account Migration: The Technical Reality</h3>

<p>The actual migration process was surprisingly smooth, but had some gotchas:</p>

<p><strong>1. Mastodon Export</strong></p>

<pre><code class="language-bash"># Export process (takes 24-48 hours for large instances)
# Mastodon Admin → Settings → Import/Export → Request Archive
# Results in: archive-[timestamp].tar.gz
</code></pre>

<p><strong>2. Post Import with slurp</strong></p>

<pre><code class="language-bash"># Install slurp
git clone https://github.com/superseriousbusiness/gotosocial-slurp
cd gotosocial-slurp
go build .

# Import 380 posts from Mastodon archive
./slurp import \
  --gts-endpoint https://your-domain.com \
  --gts-token YOUR_GTS_TOKEN \
  --mastodon-archive archive-20241215.tar.gz \
  --dry-run false

# Results: Perfect import with media, metadata, and timestamps preserved
</code></pre>

<p><strong>3. Account Redirect Setup</strong></p>

<pre><code class="language-bash"># In Mastodon rails console
rails console
account = Account.find_by(username: &#39;your_username&#39;)
account.update(moved_to_account_id: nil) # Clear any previous moves
# Then use Mastodon UI: Settings → Account → Move to different account
</code></pre>

<p><strong>Migration Casualties:</strong></p>
<ul><li>Lost ~50 followers (12% dropout rate)</li>
<li>Likely causes: inactive accounts, app compatibility issues, users who don&#39;t follow redirects</li>
<li>Lesson: Quality over quantity – the remaining followers are actually engaged</li></ul>

<h2 id="performance-benchmarks-numbers-don-t-lie">Performance Benchmarks: Numbers Don&#39;t Lie</h2>

<h3 id="memory-usage-deep-dive">Memory Usage Deep-Dive</h3>

<pre><code class="language-bash"># Monitoring setup with docker stats
docker stats --format &#34;table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}&#34;

# Mastodon (before migration):
CONTAINER       CPU %    MEM USAGE / LIMIT     MEM %
mastodon_web    45.2%    2.1GiB / 8GiB        26.25%
mastodon_sidekiq 23.1%   1.8GiB / 8GiB        22.50%
mastodon_streaming 12.4% 512MiB / 8GiB        6.40%
redis           8.7%     256MiB / 8GiB        3.20%
postgres        15.3%    800MiB / 8GiB        10.00%
elasticsearch   35.8%    1.2GiB / 8GiB        15.00%
Total: ~6.7GB peak usage

# GoToSocial (after migration):
CONTAINER       CPU %    MEM USAGE / LIMIT     MEM %
gotosocial      12.3%    419MiB / 8GiB        5.24%
postgres        3.2%     128MiB / 8GiB        1.60%
fedifetcher     0.8%     3.4MiB / 8GiB        0.04%
gts-holmirdas   1.1%     3.7MiB / 8GiB        0.05%
Total: ~555MB peak usage

RAM Efficiency Gain: 92% reduction (6.7GB → 555MB)
</code></pre>

<p><img src="https://data.klein.ruhr/images/ram-usage-comparison.webp" alt=""></p>

<h3 id="storage-analysis">Storage Analysis</h3>

<pre><code class="language-bash"># Mastodon storage breakdown (after 6 months):
du -sh /opt/mastodon/*
12G     system/  (cache, media_attachments)
45G     public/  (user uploads, cached media)
43G     postgres_data/  (database)
Total: ~100GB with aggressive 7-day cleanup

# GoToSocial storage (extrapolated to same timeframe):
du -sh /opt/gotosocial/*
8.2G    storage/  (all media, database)
26G     postgres_data/  (more efficient schema)
Total: ~35GB with 7-day remote media retention

Storage Efficiency Gain: 65% reduction
</code></pre>

<p><img src="https://data.klein.ruhr/images/storage-comparison.webp" alt=""></p>

<p><strong>Why GoToSocial is so much leaner:</strong></p>
<ul><li>Single binary: No separate web/worker/streaming processes</li>
<li>Efficient database schema: Less metadata overhead per post</li>
<li>Smart media handling: Better deduplication and compression</li>
<li>No Elasticsearch: Full-text search handled by PostgreSQL</li></ul>

<h2 id="federation-performance-quality-over-quantity">Federation Performance: Quality Over Quantity</h2>

<p>One of my biggest concerns was federation reach. Would a single-user GoToSocial instance feel isolated?</p>

<p><strong>The Data After 4 Days:</strong></p>

<pre><code class="language-bash"># Federation stats from GoToSocial admin API
curl -H &#34;Authorization: Bearer $ADMIN_TOKEN&#34; \
  https://your-domain.com/api/v1/admin/accounts/stats

{
  &#34;known_instances&#34;: 2750,
  &#34;federated_posts&#34;: 12847,
  &#34;local_posts&#34;: 380,
  &#34;active_users_week&#34;: 1
}
</code></pre>

<p><strong>Federation happens FAST:</strong></p>
<ul><li>2,750+ instances discovered in 4 days</li>
<li>No traditional relays needed</li>
<li>Content discovery through intelligent RSS integration</li>
<li>Federation quality actually improved (more relevant content, less noise)
<img src="https://data.klein.ruhr/images/federation-growth.webp" alt=""></li></ul>

<h2 id="content-discovery-building-gts-holmirdas">Content Discovery: Building GTS-HolMirDas</h2>

<p>Here&#39;s where things got interesting. Small Fediverse instances suffer from the “empty timeline problem” – without many local users or relay connections, your federated timeline stays pretty barren.</p>

<p><strong>The Technical Challenge</strong></p>

<pre><code class="language-bash"># Traditional approach: Join relays
# Problems:
# - High resource usage
# - Lots of irrelevant content  
# - Reliability issues
# - Limited control over content quality
</code></pre>

<p><strong>My Solution: Intelligent RSS-to-Fediverse Bridge</strong></p>

<p>I built GTS-HolMirDas (German pun meaning “fetch this for me”), an open-source tool that:</p>

<p><strong>Core Architecture:</strong></p>

<pre><code class="language-python"># Simplified architecture overview
class HolMirDas:
    def __init__(self):
        self.rss_feeds = self.load_feed_config()  # 102 RSS feeds
        self.gts_client = GoToSocialClient()
        self.duplicate_tracker = DuplicateDetector()
        self.instance_tracker = InstanceTracker()
    
    def run_cycle(self):
        &#34;&#34;&#34;Main processing loop - runs every hour&#34;&#34;&#34;
        for feed_url, config in self.rss_feeds.items():
            self.process_feed(feed_url, config)
        
        self.cleanup_old_entries()
        self.update_federation_stats()
</code></pre>

<p><strong>Smart Features:</strong></p>
<ul><li>Cross-platform attribution: Properly credits Mastodon, Misskey, Pleroma authors</li>
<li>Duplicate detection: Prevents the same post from appearing multiple times</li>
<li>Instance discovery: Automatically tracks new Fediverse instances</li>
<li>Rate limiting: Respects both RSS and GoToSocial API limits</li></ul>

<p><strong>Performance Metrics</strong></p>

<pre><code class="language-bash"># Real-time stats from my instance:
📊 GTS-HolMirDas Run Statistics:
   ⏱️  Runtime: 4:39 minutes per cycle
   📄 Posts processed: 65 per hour  
   🌐 Current known instances: 2,697
   ➕ New instances discovered: +22 per run
   📡 RSS feeds monitored: 102
   ⚡ Processing rate: 13.9 posts/minute
   🔄 Runs every 60 minutes automatically
</code></pre>

<p><strong>RSS Feed Sources</strong></p>

<pre><code class="language-yaml"># feed_config.yml (excerpt)
feeds:
  # Major Mastodon instances
  - url: &#34;https://mastodon.social/@Gargron.rss&#34;
    platform: &#34;mastodon&#34;
    instance: &#34;mastodon.social&#34;
  
  # Specialized instances  
  - url: &#34;https://fosstodon.org/users/example_user.rss&#34;
    platform: &#34;mastodon&#34;
    instance: &#34;fosstodon.org&#34;
    
  # Other Fediverse platforms
  - url: &#34;https://pixelfed.social/users/photographer.atom&#34;
    platform: &#34;pixelfed&#34;
    instance: &#34;pixelfed.social&#34;
</code></pre>

<p><strong>The Result:</strong> A vibrant federated timeline despite being a single-user instance, with content that&#39;s actually relevant to my interests.</p>

<h2 id="lessons-learned-the-good-the-bad-the-ugly">Lessons Learned: The Good, The Bad, The Ugly</h2>

<h3 id="what-works-brilliantly">What Works Brilliantly ✅</h3>

<p><strong>Resource Efficiency is Game-Changing</strong></p>
<ul><li>Single binary vs. multiple processes: Much simpler debugging</li>
<li>Memory usage stays consistently under 500MB even under load</li>
<li>CPU usage rarely spikes above 15% during federation heavy-lifting</li>
<li>Storage growth is predictable and manageable</li></ul>

<p><strong>Federation Just Works™</strong></p>
<ul><li>No manual instance discovery needed</li>
<li>ActivityPub compatibility is excellent</li>
<li>Cross-platform federation (Mastodon ↔ Misskey ↔ Pleroma) seamless</li>
<li>Better federation performance than expected</li></ul>

<p><strong>Operational Simplicity</strong></p>

<pre><code class="language-bash"># Mastodon maintenance (weekly):
docker compose exec web bundle exec rake mastodon:media:remove_remote
docker compose exec web bundle exec rake mastodon:preview_cards:remove_old
docker compose exec web bundle exec rake mastodon:feeds:build
# + manual Elasticsearch index management
# + Sidekiq queue monitoring
# + Redis memory management

# GoToSocial maintenance (monthly):
# That&#39;s it. Seriously.
</code></pre>

<h3 id="the-challenges">The Challenges ⚠️</h3>

<p><strong>Client Ecosystem</strong></p>
<ul><li>Mobile Apps: Hit-or-miss compatibility
<ul><li>iOS Tusker: Works perfectly, actively maintained</li>
<li>iOS Ice Cubes: Notification issues, otherwise great</li>
<li>Android Tusky: Mostly works, some UI quirks</li>
<li>Android Fedilab: Best overall experience</li></ul></li>
<li>Web Clients: Need self-hosting for optimal experience</li></ul>

<p><strong>Missing Mastodon Features (That You Might Miss)</strong></p>
<ul><li>Advanced search capabilities (no Elasticsearch)</li>
<li>Trending hashtags/posts</li>
<li>Some admin tools are more basic</li>
<li>Limited API endpoints compared to Mastodon</li></ul>

<p><strong>Federation Edge Cases</strong></p>

<pre><code class="language-bash"># Occasional federation hiccups I encountered:
- Large instances sometimes lag on post delivery (not GTS fault)
- Some Mastodon instances reject GTS posts (rare, usually config issues)
- Media federation can be slow during high-traffic periods
</code></pre>

<h2 id="mobile-apps-real-world-testing">Mobile Apps: Real-World Testing</h2>

<p><strong>iOS Testing Results:</strong></p>

<p><strong>Tusker: 9/10</strong></p>
<ul><li>✅ Full feature support</li>
<li>✅ Reliable notifications</li>
<li>✅ Good performance</li>
<li>❌ Paid app ($3.99)</li></ul>

<p><strong>Ice Cubes: 7/10</strong></p>
<ul><li>✅ Beautiful interface</li>
<li>✅ Active development</li>
<li>❌ Notification reliability issues</li>
<li>❌ Some API compatibility gaps</li></ul>

<p><strong>Self-Hosted Web Clients:</strong></p>

<pre><code class="language-yaml"># My current setup
services:
  phanpy:
    image: cheeaun/phanpy:latest
    container_name: phanpy
    environment:
      DEFAULT_INSTANCE: your-domain.com
    labels:
      - &#34;traefik.http.routers.phanpy.rule=Host(\`social.your-domain.com\`)&#34;
  
  elk:
    image: elkzone/elk:latest
    container_name: elk
    environment:
      DEFAULT_SERVER: your-domain.com
    labels:
      - &#34;traefik.http.routers.elk.rule=Host(\`elk.your-domain.com\`)&#34;
</code></pre>

<p><strong>Client Comparison:</strong></p>
<ul><li>Phanpy: Better features, more Mastodon-like, slightly dated UI</li>
<li>Elk: Gorgeous interface, modern UX, fewer power-user features</li>
<li>Official GTS Web UI: Basic but functional, good for admin tasks</li></ul>

<h2 id="cost-analysis">Cost Analysis</h2>

<p><strong>Comparison with Mastodon hosting costs:</strong></p>

<p><strong>Mastodon requirements:</strong></p>
<ul><li>Minimum: 4GB RAM, 2 cores</li>
<li>Monthly VPS cost: $20-40</li>
<li>Additional services needed: Redis, Elasticsearch (optional but recommended)</li></ul>

<p><strong>GoToSocial requirements:</strong></p>
<ul><li>Minimum: 1GB RAM, 1 core</li>
<li>Monthly VPS cost: $5-10</li>
<li>Additional services: Just PostgreSQL (can use SQLite for single-user)</li></ul>

<p><strong>Annual savings: $180-360 per year</strong></p>

<p><img src="https://data.klein.ruhr/images/cost-comparison.webp" alt=""></p>

<h2 id="backup-strategy-lessons-from-migration">Backup Strategy: Lessons from Migration</h2>

<pre><code class="language-bash">#!/bin/bash
# My automated backup script
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=&#34;/opt/backups/gotosocial&#34;

# Database backup
docker compose exec -T postgres pg_dump -U gotosocial gotosocial &gt; \
  &#34;$BACKUP_DIR/db_backup_$DATE.sql&#34;

# Media and storage backup
tar -czf &#34;$BACKUP_DIR/storage_backup_$DATE.tar.gz&#34; \
  /opt/gotosocial/data/

# Configuration backup  
cp compose.yml &#34;$BACKUP_DIR/compose_backup_$DATE.yml&#34;

# Keep only last 7 days of backups
find &#34;$BACKUP_DIR&#34; -name &#34;*.sql&#34; -mtime +7 -delete
find &#34;$BACKUP_DIR&#34; -name &#34;*.tar.gz&#34; -mtime +7 -delete

echo &#34;Backup completed: $DATE&#34;
</code></pre>

<p>Recovery tested and verified – I&#39;ve successfully restored from backup during my testing phase. The process is straightforward and well-documented.</p>

<h2 id="the-tools-that-make-it-work">The Tools That Make It Work</h2>

<p>All the supporting tools I built are open source and production-ready:</p>

<h3 id="gts-holmirdas">GTS-HolMirDas</h3>

<p><strong>Repository:</strong><a href="https://git.klein.ruhr/matthias/gts-holmirdas?ref=blog.klein.ruhr">https://git.klein.ruhr/matthias/gts-holmirdas</a></p>

<p><strong>Features:</strong></p>
<ul><li>102 RSS feed sources from diverse Fediverse instances</li>
<li>Cross-platform attribution (Mastodon, Misskey, Pleroma, Pixelfed)</li>
<li>Intelligent duplicate detection</li>
<li>Automatic instance discovery</li>
<li>Rate limiting and error handling</li>
<li>Docker-ready deployment</li></ul>

<p><strong>Setup in 5 minutes:</strong></p>

<pre><code class="language-bash">git clone https://git.your-domain.com/username/gts-holmirdas.git
cd gts-holmirdas
cp config.example.yml config.yml
# Edit config.yml with your GTS instance details
docker compose up -d
</code></pre>

<h3 id="fedifetcher-integration">FediFetcher Integration</h3>

<p><strong>Repository:</strong> blog.thms.uk/fedifetcher</p>

<p>While not my creation, FediFetcher perfectly complements GoToSocial for thread completion:</p>

<pre><code class="language-yaml"># compose.yml addition
services:
  fedifetcher:
    image: nanos/fedifetcher:latest
    container_name: fedifetcher
    environment:
      - HOME_INSTANCE=your-domain.com
      - ACCESS_TOKEN=${FEDIFETCHER_TOKEN}
      - REPLY_INTERVAL_HOURS=1
      - BACKFILL_HOURS=24
    restart: unless-stopped
</code></pre>

<p><strong>What it does:</strong></p>
<ul><li>Fetches missing replies to posts in your timeline</li>
<li>Completes conversation threads automatically</li>
<li>Backfills content from instances your server hasn&#39;t seen yet</li>
<li>Minimal resource usage (3-4MB RAM)</li></ul>

<h2 id="monitoring-and-observability">Monitoring and Observability</h2>

<pre><code class="language-yaml"># Prometheus metrics (optional but recommended)
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - &#39;--config.file=/etc/prometheus/prometheus.yml&#39;
      - &#39;--storage.tsdb.path=/prometheus&#39;
      - &#39;--web.console.libraries=/etc/prometheus/console_libraries&#39;

# prometheus.yml
scrape_configs:
  - job_name: &#39;gotosocial&#39;
    static_configs:
      - targets: [&#39;gotosocial:8080&#39;]
    metrics_path: &#39;/metrics&#39;
</code></pre>

<p><strong>Key metrics to monitor:</strong></p>
<ul><li>Memory usage trends</li>
<li>Database growth rate</li>
<li>Federation success rates</li>
<li>API response times</li>
<li>Storage utilization</li></ul>

<h2 id="migration-gotchas-and-pro-tips">Migration Gotchas and Pro Tips</h2>

<h3 id="things-i-wish-i-d-known-before-starting">Things I Wish I&#39;d Known Before Starting</h3>

<p><strong>1. Test Federation Early</strong></p>

<pre><code class="language-bash"># Verify federation is working before migrating followers
curl -H &#34;Accept: application/activity+json&#34; \
  https://your-domain.com/users/your_username

# Should return ActivityPub JSON, not HTML
</code></pre>

<p><strong>2. Mobile App Testing is Critical</strong><br>
Don&#39;t assume your favorite Mastodon app will work perfectly. Test extensively with your actual usage patterns before committing.</p>

<p><strong>3. Content Discovery Takes Time</strong><br>
The federated timeline won&#39;t be instantly populated. Plan for a “quiet period” of 1-2 weeks while content discovery tools build up your federation network.</p>

<p><strong>4. Backup Before Migration</strong></p>

<pre><code class="language-bash"># Create a complete Mastodon backup before starting
docker compose exec web rake mastodon:backup:create
# This creates a full export in /app/backup/
</code></pre>

<p><strong>5. Domain Considerations</strong><br>
If you&#39;re changing domains during migration (like I did), be prepared for some federation hiccups. Some instances cache domain information aggressively.</p>

<h2 id="performance-tuning-tips">Performance Tuning Tips</h2>

<pre><code class="language-bash"># PostgreSQL optimization for GoToSocial
# Add to postgres container environment:
POSTGRES_INITDB_ARGS: &#34;--data-checksums&#34;
# In postgresql.conf:
shared_buffers = 128MB          # For 1GB RAM systems
effective_cache_size = 512MB    # 3/4 of available RAM
work_mem = 4MB                  # Per query operation
maintenance_work_mem = 64MB     # For maintenance operations
</code></pre>

<pre><code class="language-bash"># GoToSocial-specific optimizations:
# In your .env file:
GTS_CACHE_MEMORY_TARGET=100MB           # Adjust based on available RAM
GTS_MEDIA_REMOTE_CACHE_DAYS=7           # Balance storage vs. availability
GTS_ACCOUNTS_ALLOW_CUSTOM_CSS=false     # Disable if not needed
GTS_WEB_ASSET_BASE_DIR=/gotosocial/web  # Serve assets efficiently
</code></pre>

<h2 id="community-impact-and-future-plans">Community Impact and Future Plans</h2>

<h3 id="what-this-migration-means-for-the-fediverse">What This Migration Means for the Fediverse</h3>

<p><strong>Resource Democracy:</strong> By proving that high-quality Fediverse instances can run on minimal resources, we&#39;re making decentralization more accessible to everyone.</p>

<p><strong>Tool Ecosystem:</strong> The tools developed for this migration (especially GTS-HolMirDas) are helping other small instance operators solve the same content discovery challenges.</p>

<p><strong>Documentation:</strong> This migration provides a real-world data point for others considering similar moves.</p>

<h3 id="future-development-plans">Future Development Plans</h3>

<p><strong>GTS-HolMirDas Roadmap:</strong></p>
<ul><li>Web-based configuration interface</li>
<li>Better RSS feed quality scoring</li>
<li>Integration with more Fediverse platforms (PeerTube, Funkwhale)</li>
<li>Machine learning-based content relevance filtering</li>
<li>Multi-instance support for hosting providers</li></ul>

<p><strong>Community Feedback Integration:</strong> Based on initial user feedback, the most requested features are:</p>
<ul><li>Easier RSS feed discovery and management</li>
<li>Better content filtering options</li>
<li>Integration with existing relay networks</li>
<li>Automated instance health monitoring</li></ul>

<h2 id="bottom-line-the-numbers-don-t-lie">Bottom Line: The Numbers Don&#39;t Lie</h2>

<p><strong>Migration Summary:</strong></p>
<ul><li>Timeline: 4 weeks of testing, 2 days for full migration</li>
<li>Resource savings: 92% RAM reduction, 65% storage reduction</li>
<li>Follower retention: 88% (better than expected)</li>
<li>Federation growth: 2,750+ instances in first week</li>
<li>Operational complexity: Significantly reduced</li>
<li>Cost savings: $180-360 annually in hosting costs</li>
<li>Satisfaction level: 9.5/10 (would migrate again)</li></ul>

<p><strong>The Real Kicker:</strong> GoToSocial doesn&#39;t just match Mastodon&#39;s functionality at lower resource usage – in many ways, it performs better. The federated timeline is more relevant, the interface is faster, and the operational overhead is practically non-existent.</p>

<p><strong>You should definitely consider GoToSocial if:</strong></p>
<ul><li>You&#39;re running a single-user or small instance</li>
<li>Resource efficiency matters to you</li>
<li>You value operational simplicity</li>
<li>You&#39;re comfortable with slightly less mature tooling</li>
<li>You want to contribute to Fediverse diversity</li></ul>

<p><strong>Stick with Mastodon if:</strong></p>
<ul><li>You&#39;re running a large community (100+ users)</li>
<li>You need enterprise-grade admin tools</li>
<li>Your users depend on specific Mastodon features</li>
<li>You have abundant server resources</li>
<li>Stability trumps efficiency for your use case</li></ul>

<p><strong>My recommendation:</strong> Set up a test GoToSocial instance and run it parallel to your existing setup for a month. The resource cost is minimal, and you&#39;ll get real-world data for your specific use case.</p>

<p>The Fediverse is strongest when it&#39;s diverse – different platforms solving different problems for different communities. GoToSocial has earned its place in that ecosystem.</p>

<hr>

<h2 id="resources-and-links">Resources and Links</h2>

<h3 id="essential-tools">Essential Tools</h3>
<ul><li><strong>GoToSocial:</strong><a href="https://gotosocial.org/?ref=blog.klein.ruhr">https://gotosocial.org</a></li>
<li><strong>GTS-HolMirDas:</strong><a href="https://git.klein.ruhr/matthias/gts-holmirdas?ref=blog.klein.ruhr">https://git.klein.ruhr/matthias/gts-holmirdas</a></li>
<li><strong>FediFetcher:</strong><a href="https://blog.thms.uk/fedifetcher?ref=blog.klein.ruhr">https://blog.thms.uk/fedifetcher</a></li>
<li><strong>Slurp (Post Migration):</strong><a href="https://github.com/VyrCossont/slurp?ref=blog.klein.ruhr">https://github.com/VyrCossont/slurp</a></li></ul>

<h3 id="mobile-apps-that-work-well">Mobile Apps That Work Well</h3>
<ul><li><strong>iOS Tusker:</strong> App Store (paid, highly recommended)</li>
<li><strong>iOS Ice Cubes:</strong> App Store (free, some quirks)</li>
<li><strong>Android Fedilab:</strong> F-Droid/Play Store (best Android option)</li>
<li><strong>Android Tusky:</strong> F-Droid/Play Store (decent alternative)</li></ul>

<h3 id="web-clients-self-hosted">Web Clients (Self-Hosted)</h3>
<ul><li><strong>Phanpy:</strong><a href="https://github.com/cheeaun/phanpy?ref=blog.klein.ruhr">https://github.com/cheeaun/phanpy</a></li>
<li><strong>Elk:</strong><a href="https://github.com/elk-zone/elk?ref=blog.klein.ruhr">https://github.com/elk-zone/elk</a></li></ul>

<h3 id="community">Community</h3>
<ul><li><strong>GoToSocial Documentation:</strong><a href="https://docs.gotosocial.org/?ref=blog.klein.ruhr">https://docs.gotosocial.org</a></li>
<li><strong>Matrix Support:</strong> <a href="https://blog.klein.ruhr/tag:gotosocial" class="hashtag"><span>#</span><span class="p-category">gotosocial</span></a>:superseriousbusiness.org</li>
<li><strong>GitHub Issues:</strong><a href="https://github.com/superseriousbusiness/gotosocial?ref=blog.klein.ruhr">https://github.com/superseriousbusiness/gotosocial</a></li></ul>

<hr>

<p><strong>Questions? Feedback?</strong> Find me on the Fediverse at <a href="https://me.klein.ruhr/@matthias?ref=blog.klein.ruhr"><a href="https://blog.klein.ruhr/@/matthias@me.klein.ruhr" class="u-url mention">@<span>matthias@me.klein.ruhr</span></a></a> – I&#39;m always happy to discuss self-hosting, the Fediverse, and efficient technology solutions!</p>

<p>If this post helped you with your own migration, consider starring the GTS-HolMirDas repository or contributing to the GoToSocial project. The Fediverse grows stronger with every successful self-hosted instance.</p>
]]></content:encoded>
      <guid>https://blog.klein.ruhr/gotosocial-ready-for-prime-time</guid>
      <pubDate>Mon, 04 Aug 2025 02:17:17 +0000</pubDate>
    </item>
  </channel>
</rss>