How to Self-Host AFFiNE with Docker Compose

What Is AFFiNE?

AFFiNE is an open-source knowledge management platform that combines documents, whiteboards, and databases in a single workspace. Think of it as Notion + Miro — you get rich text documents with block editing, infinite canvas whiteboards for visual thinking, and database views (table, kanban) for structured data. Pages can switch between document and whiteboard modes seamlessly.

Updated March 2026: Verified with AFFiNE v0.26+ Docker images and configurations.

AFFiNE is still pre-1.0 (currently v0.26.3) but is one of the most ambitious self-hosted Notion alternatives in active development, with 45,000+ GitHub stars.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 4 GB of RAM minimum (8 GB recommended)
  • 20 GB of free disk space
  • A domain name (required for remote access)

Docker Compose Configuration

Create a docker-compose.yml file:

services:
  affine:
    image: ghcr.io/toeverything/affine-graphql:stable
    ports:
      - "3010:3010"
      - "5555:5555"
    environment:
      NODE_ENV: production
      AFFINE_CONFIG_PATH: /root/.affine/config
      REDIS_SERVER_HOST: redis
      DATABASE_URL: postgresql://affine:${POSTGRES_PASSWORD}@postgres:5432/affine
      AFFINE_SERVER_HOST: "0.0.0.0"
      AFFINE_SERVER_PORT: "3010"
      AFFINE_SERVER_HTTPS: "false"
      AFFINE_SERVER_EXTERNAL_URL: ${AFFINE_URL}
    volumes:
      - affine-config:/root/.affine/config
      - affine-storage:/root/.affine/storage
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    command: ['sh', '-c', 'node ./scripts/self-host-predeploy && node ./dist/index.js']
    restart: unless-stopped

  redis:
    image: redis:7.4-alpine
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3
    restart: unless-stopped

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: affine
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: affine
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U affine -d affine"]
      interval: 10s
      timeout: 3s
      retries: 3
    restart: unless-stopped

volumes:
  affine-config:
  affine-storage:
  redis-data:
  postgres-data:

Create a .env file:

# PostgreSQL password — use a strong random password
POSTGRES_PASSWORD=change_me_strong_password

# The full external URL where AFFiNE is accessible (no trailing slash)
AFFINE_URL=https://affine.yourdomain.com

Start the stack:

docker compose up -d

Initial Setup

  1. Wait 1-2 minutes for database migrations to complete
  2. Navigate to your AFFiNE URL (e.g., https://affine.yourdomain.com)
  3. Create an account with email and password
  4. The first user can access admin features
  5. Create your first workspace and start editing — toggle between document and whiteboard modes with a click

Configuration

Workspace Structure

AFFiNE organizes content as:

  • Workspaces — isolated spaces for different projects or teams
  • Pages — individual documents that can be docs or whiteboards
  • Sub-pages — nested pages for hierarchical organization
  • Databases — structured data views within pages

Document Features

  • Block-based editing with slash commands
  • Markdown shortcuts (type # for headings, - for lists)
  • Code blocks with syntax highlighting
  • Tables, callouts, dividers, images
  • Inline databases (table, kanban views)
  • Page links and backlinks

Whiteboard Features

  • Infinite canvas with free-form drawing
  • Shapes, connectors, text blocks
  • Embed documents within whiteboards
  • Real-time collaboration on the canvas
  • Hand-drawn style option (Excalidraw-inspired)

Advanced Configuration (Optional)

Email Configuration

For password reset and email verification:

environment:
  MAILER_HOST: smtp.example.com
  MAILER_PORT: 587
  MAILER_USER: your_smtp_user
  MAILER_PASSWORD: your_smtp_password
  MAILER_SENDER: [email protected]

OAuth Authentication

AFFiNE supports Google OAuth for login:

environment:
  OAUTH_GOOGLE_CLIENT_ID: your_google_client_id
  OAUTH_GOOGLE_CLIENT_SECRET: your_google_client_secret

Reverse Proxy

Set up a reverse proxy pointing to port 3010. AFFiNE uses WebSocket connections for real-time collaboration, so ensure WebSocket passthrough is enabled.

For detailed setup: Reverse Proxy Setup

Backup

Critical data to back up:

  • PostgreSQL database: docker compose exec postgres pg_dump -U affine affine > affine_backup.sql
  • Storage volume: affine-storage contains uploaded files and assets
  • Config volume: affine-config contains server configuration
  • Environment file: Your .env with credentials

For a complete backup strategy: Backup Strategy

Troubleshooting

”Migration failed” on startup

Symptom: AFFiNE container exits with migration errors. Fix: This usually means PostgreSQL wasn’t ready when AFFiNE tried to connect. Ensure the health check is working: docker compose ps. Restart AFFiNE after PostgreSQL is healthy: docker compose restart affine.

Whiteboard performance is slow

Symptom: The whiteboard canvas lags or stutters. Fix: Whiteboards are rendered client-side using WebGL. This is a client browser performance issue, not a server issue. Use a modern browser (Chrome/Edge recommended). Reduce the number of elements on a single whiteboard.

WebSocket errors in browser console

Symptom: Real-time collaboration doesn’t work, browser console shows WebSocket errors. Fix: Ensure your reverse proxy forwards WebSocket connections. For Nginx, add Upgrade and Connection headers. Verify AFFINE_SERVER_EXTERNAL_URL matches your actual URL.

Account creation fails

Symptom: Can’t create a new account. Fix: Check AFFiNE logs: docker compose logs affine. If SMTP is not configured, some auth flows may fail. Check that PostgreSQL has space and the connection is healthy.

Frequently Asked Questions

Is AFFiNE stable enough for production use?

AFFiNE is pre-1.0 software (currently v0.26.3). It works well for personal use and small team experimentation, but expect occasional bugs and breaking changes between releases. For mission-critical team documentation, Outline or BookStack are more battle-tested. AFFiNE improves with every release and the team ships updates frequently.

How does AFFiNE compare to Notion?

AFFiNE covers the core Notion features — block-based documents, databases (table/kanban views), and workspace organization. Its unique advantage is the integrated whiteboard canvas (edgeless mode), which Notion doesn’t have. AFFiNE lacks some Notion features like formulas, rollups, and the breadth of integrations. The main trade-off is maturity: Notion is polished; AFFiNE is ambitious but rougher around the edges.

Does AFFiNE support real-time collaboration?

Yes. When self-hosted with the Docker Compose setup above, multiple users can edit the same page simultaneously with real-time sync via WebSocket connections. Ensure your reverse proxy forwards WebSocket traffic correctly. Each user creates their own account and gets invited to shared workspaces.

Can I import data from Notion?

AFFiNE supports importing Markdown files. For Notion exports, use Notion’s “Export all workspace content” as Markdown, then import the files into AFFiNE. Some formatting (databases, advanced blocks) may not transfer perfectly and needs manual adjustment.

Why does AFFiNE use the :stable Docker tag instead of a version number?

AFFiNE’s official self-hosted Docker image (ghcr.io/toeverything/affine-graphql:stable) tracks the latest stable release. They don’t publish individual version tags for the self-hosted image. The :stable tag is the recommended approach from the AFFiNE team. Pin your deployment by noting the digest (docker images --digests) if you need reproducibility.

How much storage does AFFiNE need?

The application itself uses about 500 MB. Storage grows with your content — primarily uploaded images, files, and database records stored in PostgreSQL. For a small team (5-10 users), plan for 5-10 GB. The affine-storage volume holds uploaded files and the postgres-data volume holds the database.

Can I use AFFiNE offline?

The desktop app supports offline editing with local-first architecture — changes sync when you reconnect. The self-hosted server acts as the sync hub. Web browser access requires an active connection to your server.

Resource Requirements

  • RAM: 1-2 GB for AFFiNE + 500 MB for PostgreSQL + 100 MB for Redis = 2-3 GB total
  • CPU: Moderate — Node.js server with database operations
  • Disk: ~500 MB for the application, plus user data

Verdict

AFFiNE is the most visually ambitious self-hosted Notion alternative. The combination of documents and whiteboards in one app is unique — no other self-hosted tool does this. If you use Notion and Miro together, AFFiNE aims to replace both.

The caveat: AFFiNE is still pre-1.0 (v0.26.3 as of March 2026). Expect occasional bugs and breaking changes between versions. For production team documentation, Outline or BookStack are more stable. For personal use or teams comfortable with rapidly evolving software, AFFiNE is exciting and improving fast.

Choose AFFiNE if whiteboards are essential to your workflow. Choose AppFlowy for a more mature Notion clone. Choose Outline for stable team documentation.

Comments