Self-hosting a read-it-later inbox: Wallabag on a $5 VPS, with the iOS share-sheet integration that actually works

Pocket announced its shutdown in 2025. Instapaper still exists but is third-handed and feels frozen. Reader-by-Readwise is good but it’s a $10/month subscription. The self-hosted answer is Wallabag — PHP+MySQL, runs on a $5 VPS, has clean iOS / Android apps, exports OPML and JSON. Once it’s set up, you don’t think about it again for years.

This is the install I run, the iOS share-sheet flow that actually works (the official app’s is mediocre), and the catches that will trip you up.

Why Wallabag and not the others

  • Wallabag: PHP. MariaDB / Postgres / SQLite for the database. Web UI is functional, mobile apps exist for iOS and Android. The article-extraction quality (using Readability + a curated rule set per domain) is genuinely close to Pocket’s. Default install ~250 MB RAM.
  • Shiori: Go binary, lighter. Bookmark-focused rather than read-later-focused; saves articles but the reading view is less polished. Good if you mostly want a bookmark archive.
  • Omnivore: shut down in 2024.
  • Karakeep / Hoarder: newer, slick, but younger codebase — I’d pick this if I were starting today and willing to bet on it. For “stable for years,” Wallabag still wins.

Install on a $5 VPS

Hetzner CX11 / DO basic / Vultr cheap-tier all work. Docker is the path of least resistance.

# /opt/wallabag/docker-compose.yml
services:
  wallabag:
    image: wallabag/wallabag:latest
    environment:
      - SYMFONY__ENV__DATABASE_DRIVER=pdo_mysql
      - SYMFONY__ENV__DATABASE_HOST=db
      - SYMFONY__ENV__DATABASE_NAME=wallabag
      - SYMFONY__ENV__DATABASE_USER=wallabag
      - SYMFONY__ENV__DATABASE_PASSWORD=change-me-strong
      - SYMFONY__ENV__DOMAIN_NAME=https://wallabag.example.com
      - SYMFONY__ENV__MAILER_DSN=null://null
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./images:/var/www/wallabag/web/assets/images
    depends_on:
      - db

  db:
    image: mariadb:10
    environment:
      - MYSQL_ROOT_PASSWORD=also-change-me
      - MYSQL_DATABASE=wallabag
      - MYSQL_USER=wallabag
      - MYSQL_PASSWORD=change-me-strong
    volumes:
      - ./mariadb:/var/lib/mysql

Bring it up, then put a real reverse proxy with TLS in front. Caddy does both halves in one config:

# /etc/caddy/Caddyfile
wallabag.example.com {
    reverse_proxy 127.0.0.1:8080
}

Visit https://wallabag.example.com. Default login: wallabag / wallabag. Change this immediately from Settings → Users → Edit. Then create a real account, log in as that, and disable the default wallabag user.

The iOS share-sheet flow that works

Wallabag’s official iOS app exists and you can install it. But the share-sheet save in the official app has been quirky for years — it sometimes hangs, sometimes silently fails, sometimes saves but doesn’t appear until you force-pull-to-refresh. Don’t use it for the save flow. The setup that’s reliable:

  1. Get an API client_id and client_secret from Wallabag. Settings → API clients management → Create a new client. Note the values.
  2. Build a one-action iOS Shortcut that POSTs the URL to /api/entries.json with bearer-token auth. The whole shortcut is six actions:
1. Receive URLs from Share Sheet
2. Get Contents of URL  → POST to https://wallabag.example.com/oauth/v2/token
       Body (Form):
         grant_type:  password
         client_id:   <your client_id>
         client_secret: <your client_secret>
         username:    you
         password:    your password
3. Get Dictionary Value "access_token" from response
4. Get Contents of URL  → POST to https://wallabag.example.com/api/entries.json
       Headers:
         Authorization: Bearer <access_token from step 3>
       Body (Form):
         url: <the URL from step 1>
5. Show Notification "Saved to Wallabag"

Now from any iOS app: share button → Save to Wallabag (your custom shortcut). It runs in <2 seconds, shows a notification, and you go back to whatever you were doing. The Wallabag app on iOS becomes pure-reading; saving is via the Shortcut.

The two reading apps worth using

  • Reader (the iOS official Wallabag app). Free. Functional. Use it just for reading; saves are unreliable as noted.
  • FrenchPress (third-party). $5 one-time. Better typography, swipe-actions, dark theme that doesn’t break on weird article CSS. The reading experience is markedly nicer than the official app.

The catches I learned the hard way

  • Disable the default wallabag user immediately. Default-credential scanners hit Wallabag instances within hours of going live. Don’t get popped on day one.
  • Set MAILER_DSN=null://null as above unless you actually want password-reset emails. Otherwise Wallabag will try to talk to a SMTP server that doesn’t exist and timeouts will slow down account flows.
  • Article extraction fails on a small handful of sites with paywalls or aggressive JS rendering — NYTimes, Bloomberg, FT, Substack-with-paywall. Wallabag falls back to a partial save (URL + page title only). The fix per-site is in Settings → Internal settings → Site config; for paywall sites you can paste a YAML-style extraction rule. Or just skip those.
  • Backups: dump the MariaDB nightly with docker exec wallabag-db mysqldump -u root -p$PASS wallabag > backup.sql, plus rsync the images/ directory to your NAS. Restoring from these is well-documented and works.
  • Don’t expose the API key in the Shortcut if you ever AirDrop the Shortcut to someone else — the iCloud-synced Shortcut will include your password. Use a long random string for the password and don’t share the Shortcut.

The end-state

A small VPS that quietly receives URLs from your iPhone, fetches the article, strips the ads, stores the cleaned text. A reading app that pulls from it for offline-friendly long-form reading on the train or a plane. JSON export at /api/export if you ever want to leave. And no monthly bill arriving for the privilege of saving an article you wanted to read later.

Photo: Coffee mug and smartphone in hand by Mart Production on Pexels.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.