# Outline Not Starting

## The Problem

Outline fails to start in Docker, entering a restart loop or crashing immediately. The logs show one of these errors:

> **Updated March 2026:** Verified with latest Docker images and configurations.

```
Error: connect ECONNREFUSED 127.0.0.1:5432
```

```
FATAL: password authentication failed for user "outline"
```

```
NOAUTH Authentication required
```

```
Error: [MISSING_ENV_FILE] missing .env file
```

Or Outline starts but crashes on the first login attempt with `Invalid key length`.

## The Cause

Outline has several strict requirements that differ from most self-hosted apps:

1. **DATABASE_URL uses `localhost`** — doesn't work inside Docker's network
2. **Redis URL format changed** in v0.67.0+ — usernames in the URL are rejected
3. **SECRET_KEY must be exactly 64 hex characters** — other formats crash at runtime
4. **PostgreSQL credentials mismatch** — the Compose service and DATABASE_URL disagree
5. **Missing required environment variables** — Outline doesn't start without a complete config

## The Fix

### Method 1: Fix DATABASE_URL (Most Common)

Inside Docker, services reach each other by service name — not `localhost`. Change:

```env
# WRONG — localhost refers to the Outline container itself
DATABASE_URL=postgres://outline:password@localhost:5432/outline

# CORRECT — use the Compose service name
DATABASE_URL=postgres://outline:password@postgres:5432/outline
```

The hostname in DATABASE_URL must match the service name in your `docker-compose.yml`:

```yaml
services:
  outline:
    image: outlinewiki/outline:1.5.0
    # ...
  postgres:  # ← This name must match the DATABASE_URL hostname
    image: postgres:16-alpine
    # ...
```

### Method 2: Fix Redis URL Format (v0.67.0+)

Starting with Outline v0.67.0, the Redis URL parser rejects usernames. Change:

```env
# WRONG — has a username before the colon
REDIS_URL=redis://user:password@redis:6379

# CORRECT — colon only, no username
REDIS_URL=redis://:password@redis:6379

# CORRECT — no auth (if Redis has no password)
REDIS_URL=redis://redis:6379
```

Like DATABASE_URL, the hostname must match the Redis service name in your Compose file.

### Method 3: Fix SECRET_KEY Format

Outline's SECRET_KEY must be exactly 64 hexadecimal characters (representing 32 bytes). Generate it correctly:

```bash
openssl rand -hex 32
```

This outputs a 64-character hex string like `a1b2c3d4e5f6...`.

**Common mistakes:**

| Value | Problem |
|-------|---------|
| `my-super-secret-key` | Not hexadecimal |
| `aaaaaaaaaaaaaaaa` | Only 16 chars (needs 64) |
| `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` | 32 chars — looks right but is only 16 bytes when hex-decoded |

Also generate `UTILS_SECRET` the same way:

```bash
openssl rand -hex 32
```

### Method 4: Fix PostgreSQL Credential Mismatch

Ensure the credentials in your Compose file match DATABASE_URL exactly:

```yaml
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: outline         # Must match DATABASE_URL user
      POSTGRES_PASSWORD: strongpass   # Must match DATABASE_URL password
      POSTGRES_DB: outline           # Must match DATABASE_URL database
    volumes:
      - postgres-data:/var/lib/postgresql/data
    restart: unless-stopped
```

```env
# Must match the values above exactly
DATABASE_URL=postgres://outline:strongpass@postgres:5432/outline
```

**If credentials worked before but now fail:** PostgreSQL stores credentials in the data volume. If you change `POSTGRES_PASSWORD` in the Compose file but the volume already exists, the old password persists. Either:

```bash
# Option A: Update the password inside PostgreSQL
docker exec -it postgres psql -U outline -c "ALTER USER outline PASSWORD 'newpassword';"

# Option B: Delete the volume and recreate (DESTROYS ALL DATA)
docker compose down -v
docker compose up -d
```

### Method 5: Fix Missing Environment Variables

Outline requires these variables at minimum:

```env
# Authentication
SECRET_KEY=<64 hex chars from openssl rand -hex 32>
UTILS_SECRET=<64 hex chars from openssl rand -hex 32>

# Database
DATABASE_URL=postgres://outline:password@postgres:5432/outline

# Redis
REDIS_URL=redis://redis:6379

# Application
URL=https://wiki.example.com
PORT=3000

# File storage
FILE_STORAGE=local
FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data
```

You also need at least one authentication provider configured (Slack, Google, OIDC, SAML, or email). Without one, Outline starts but you can't log in.

**For email-based login:**
```env
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=outline@example.com
SMTP_PASSWORD=smtp-password
SMTP_FROM_EMAIL=outline@example.com
SMTP_SECURE=true
```

### Method 6: Fix Database Migration Errors

If you see migration-related errors on first start:

```
SequelizeDatabaseError: column "sourceMetadata" does not exist
```

This is a known bug in v0.73.0 with fresh databases. Upgrade to v0.74.0+ or run migrations manually:

```bash
docker exec outline yarn db:migrate
docker compose restart outline
```

For general migration issues after upgrading:

```bash
# Check current migration status
docker exec outline yarn db:migrate:status

# Run pending migrations
docker exec outline yarn db:migrate
```

## Complete Working Docker Compose

```yaml
services:
  outline:
    image: outlinewiki/outline:1.5.0
    container_name: outline
    env_file: .env
    ports:
      - "3000:3000"
    volumes:
      - outline-data:/var/lib/outline/data
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped

  postgres:
    image: postgres:16-alpine
    container_name: outline-postgres
    environment:
      POSTGRES_USER: outline
      POSTGRES_PASSWORD: strongpass
      POSTGRES_DB: outline
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U outline"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  redis:
    image: redis:7.4-alpine
    container_name: outline-redis
    restart: unless-stopped

volumes:
  outline-data:
  postgres-data:
```

## Prevention

- Generate SECRET_KEY and UTILS_SECRET with `openssl rand -hex 32` — never use arbitrary strings
- Always use Docker service names (not `localhost`) in DATABASE_URL and REDIS_URL
- Test the database connection before starting Outline: `docker exec postgres pg_isready -U outline`
- Pin the Outline image version — don't use `:latest` to avoid surprise breaking changes
- Add a healthcheck on PostgreSQL so Outline waits for the database to be ready

## Related

- [How to Self-Host Outline](/apps/outline)
- [Best Self-Hosted Note-Taking Apps](/best/note-taking)
- [BookStack vs Outline](/compare/bookstack-vs-outline)
- [Docker Compose Basics](/foundations/docker-compose-basics)
