Skip to main content

How to Self-Host Wallabag: Read-Later App (Pocket Alternative) 2026

·OSSAlt Team
wallabagread-laterpocketinstapaperself-hostingdocker2026

TL;DR

Wallabag (MIT, ~10K GitHub stars, PHP/Symfony) is the open source Pocket replacement. Save articles from the web for offline reading — browser extensions, mobile apps (iOS/Android), and Kindle delivery. It fetches full article text, stores it on your server, lets you highlight and annotate, and syncs read state across all devices. Pocket Premium costs $44.99/year. Wallabag is free to self-host. Unlike Shiori (bookmark manager), Wallabag is focused purely on read-later with highlights, annotations, and reading progress.

Key Takeaways

  • Wallabag: MIT, ~10K stars, PHP — read-later tool, offline article storage with full text
  • Highlights and annotations: Select text to highlight in yellow, add personal notes
  • Kindle delivery: Send saved articles to your Kindle e-reader
  • Mobile apps: Official iOS and Android apps with offline sync
  • Browser extensions: Chrome, Firefox, Edge, Opera — save with one click
  • Pocket/Instapaper import: Import your reading list from Pocket, Instapaper, or Pinboard

Wallabag vs Pocket vs Shiori

FeatureWallabagPocketShiori
LicenseMITProprietaryMIT
CostFree (hosting)Free / $44.99/yrFree
Full-text fetchYesYesYes
HighlightsYesNo (free), Yes (Premium)No
AnnotationsYesNoNo
Kindle deliveryYesYes (Premium)No
TagsYesYesYes
Archive / ScreenshotNoNoNo
Reading time estimateYesYesNo
iOS appYes (official)YesVia browser
Android appYes (official)YesVia browser
RSS outputYesYesNo

Part 1: Docker Setup

# docker-compose.yml
services:
  wallabag:
    image: wallabag/wallabag:latest
    container_name: wallabag
    restart: unless-stopped
    ports:
      - "8080:80"
    depends_on:
      - wallabag_db
      - wallabag_redis
    volumes:
      - wallabag_data:/var/www/wallabag/data
      - wallabag_images:/var/www/wallabag/web/assets/images
    environment:
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
      SYMFONY__ENV__DATABASE_DRIVER: pdo_mysql
      SYMFONY__ENV__DATABASE_HOST: wallabag_db
      SYMFONY__ENV__DATABASE_PORT: 3306
      SYMFONY__ENV__DATABASE_NAME: wallabag
      SYMFONY__ENV__DATABASE_USER: wallabag
      SYMFONY__ENV__DATABASE_PASSWORD: "${MYSQL_PASSWORD}"
      SYMFONY__ENV__MAILER_DSN: "smtp://smtp.yourdomain.com:587?username=noreply@yourdomain.com&password=${SMTP_PASSWORD}"
      SYMFONY__ENV__FROM_EMAIL: "noreply@yourdomain.com"
      SYMFONY__ENV__DOMAIN_NAME: "https://read.yourdomain.com"
      SYMFONY__ENV__SERVER_NAME: "Wallabag"
      SYMFONY__ENV__REDIS_HOST: wallabag_redis
      SYMFONY__ENV__TWOFACTOR_AUTH: "false"
      POPULATE_DATABASE: "true"          # Set to false after first run

  wallabag_db:
    image: mariadb:11
    restart: unless-stopped
    volumes:
      - wallabag_db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
      MYSQL_DATABASE: wallabag
      MYSQL_USER: wallabag
      MYSQL_PASSWORD: "${MYSQL_PASSWORD}"

  wallabag_redis:
    image: redis:7-alpine
    restart: unless-stopped

volumes:
  wallabag_data:
  wallabag_images:
  wallabag_db_data:
# .env
MYSQL_ROOT_PASSWORD=your-root-password
MYSQL_PASSWORD=your-db-password
SMTP_PASSWORD=your-smtp-password

docker compose up -d

Visit http://your-server:8080 — default credentials: wallabag / wallabag. Change immediately.


Part 2: HTTPS with Caddy

read.yourdomain.com {
    reverse_proxy localhost:8080
}

Part 3: Initial Setup

  1. Log in with wallabag / wallabag
  2. Top-right menu → Config → Settings
  3. Change your password
  4. Set your language and timezone
  5. After first run, set POPULATE_DATABASE: "false" in docker-compose.yml to prevent re-seeding

Create Additional Users

  1. Admin panel → Users → Create a user
  2. Set username, email, password

Or via CLI:

docker exec wallabag php bin/console wallabag:user:create \
  --username bob --password secret --email bob@yourdomain.com

Part 4: Browser Extensions

Chrome/Chromium: Install from Chrome Web Store

Firefox: Install from Firefox Add-ons

Configure the extension:

  • Wallabag URL: https://read.yourdomain.com
  • Username + password
  • Click the extension icon on any article page → saves immediately

Part 5: Mobile Apps

iOS App

  1. Install Wallabag 2 iOS from App Store
  2. Server: https://read.yourdomain.com
  3. Username + password
  4. App downloads all articles for offline reading

Android App

  1. Install Wallabag 2 from Play Store (or F-Droid)
  2. Same server URL and credentials
  3. Articles sync for offline reading

iOS/Android Share Sheet

Once the app is installed:

  1. In Safari/Chrome → Share → Wallabag
  2. Article is saved instantly

Part 6: Kindle Delivery

Send your reading list to Kindle for reading on e-ink:

  1. Config → Kindle → enter your @kindle.com email address
  2. Add noreply@yourdomain.com to your approved Kindle senders (in Amazon settings)
  3. On any article: Actions → Send to Kindle

Wallabag converts the article to a clean Kindle-friendly format and emails it.


Part 7: Highlights and Annotations

Select any text in an article → Highlight or Annotate:

  • Highlights: Mark important text in yellow
  • Annotations: Add your own notes attached to a text selection

View all your annotations: Annotations in the sidebar.

Export annotations:

# Via API:
curl "https://read.yourdomain.com/api/annotations.json?page=1" \
  -H "Authorization: Bearer YOUR_TOKEN"

Part 8: Import from Pocket / Instapaper

From Pocket

  1. Pocket: Settings → Export → Request export → download pocket.html
  2. Wallabag: Import → Pocket → upload the HTML file

From Instapaper

  1. Instapaper: Settings → Export CSV → download CSV
  2. Wallabag: Import → Instapaper → upload CSV

From Pinboard

  1. Pinboard: Settings → Backup → JSON
  2. Wallabag: Import → Pinboard → upload JSON

Part 9: REST API

# Get OAuth token:
TOKEN=$(curl -s -X POST https://read.yourdomain.com/oauth/v2/token \
  -d 'grant_type=password&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&username=wallabag&password=wallabag' \
  | jq -r .access_token)

# Create OAuth client first:
docker exec wallabag php bin/console wallabag:client:create --name "myapp"

# Save an article:
curl -X POST https://read.yourdomain.com/api/entries.json \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/article","tags":"tech,readlater"}'

# List unread articles:
curl "https://read.yourdomain.com/api/entries.json?archive=0&page=1&perPage=10" \
  -H "Authorization: Bearer $TOKEN" | jq '._embedded.items[].title'

# Mark as read:
curl -X PATCH "https://read.yourdomain.com/api/entries/42.json" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"archive":1}'

Part 10: RSS Feeds

Every tag and category in Wallabag has an RSS feed — subscribe in FreshRSS or any reader:

# All unread articles as RSS:
https://read.yourdomain.com/feed/alice/TOKEN/unread

# Tagged "tech":
https://read.yourdomain.com/feed/alice/TOKEN/tags/tech

# Get your RSS token:
Config → RSS → Generate token

Maintenance

# Update Wallabag:
docker compose pull
docker compose up -d

# Run migrations after update:
docker exec wallabag php bin/console doctrine:migrations:migrate --no-interaction

# Backup database:
docker exec wallabag_db mysqldump -u wallabag -p"${MYSQL_PASSWORD}" wallabag \
  | gzip > wallabag-db-$(date +%Y%m%d).sql.gz

# Backup images:
tar -czf wallabag-images-$(date +%Y%m%d).tar.gz \
  $(docker volume inspect wallabag_wallabag_images --format '{{.Mountpoint}}')

# Logs:
docker compose logs -f wallabag

See all open source read-later and bookmark tools at OSSAlt.com/categories/productivity.

Comments