Haven
Private blogging platform for sharing with friends and family
Alternative to: Substack, Tumblr, WordPress.com, CaringBridge
Haven is a private blog application built with Ruby on Rails for sharing what you write with people you choose to share it with, not the public. It has no self-signup, built-in private RSS feeds so friends can follow you, a built-in RSS reader, a markdown editor with live preview, and support for images, video, and audio. Pages load fast with no JavaScript frameworks, ads, or trackers.
Haven Docker Compose example
Self-host Haven on your own server, homelab, or VPS starting from this Docker Compose example.
It runs Haven in Docker containers using the official ghcr.io/havenweb/haven:latest, postgres:16-alpine images, with persistent volumes and automatic restarts preconfigured.
Review the environment variables and adjust them to your setup, save the file as compose.yml (or docker-compose.yml), and start the stack with docker compose up -d.
services:
haven:
image: ghcr.io/havenweb/haven:latest
depends_on:
- postgresql
volumes:
- storage:/app/storage
tmpfs:
- /tmp/pids/
restart: unless-stopped
environment:
# Path to the Rails server PID file. Kept on tmpfs so a restarted container never trips over a stale pid.
PIDFILE: "/tmp/pids/server.pid"
# Rails environment. Keep as production for a real deployment.
RAILS_ENV: "production"
# Hostname of the bundled PostgreSQL service (matches the service name below).
HAVEN_DB_HOST: "postgresql"
# Name of the PostgreSQL database Haven uses.
HAVEN_DB_NAME: "haven"
# PostgreSQL role (user) Haven connects as.
HAVEN_DB_ROLE: "haven"
# Password for the PostgreSQL role. Internal to the compose network only (Postgres runs with trust auth), so it is not security-sensitive.
HAVEN_DB_PASSWORD: "supersecretrandomstring"
# Email of the initial admin account created on first boot. This is your login — change it.
HAVEN_USER_EMAIL: "changeme@example.com"
# Password for the initial admin account created on first boot. Change it.
HAVEN_USER_PASS: "changeme"
postgresql:
image: postgres:16-alpine
restart: unless-stopped
# Non-durability tuning recommended by upstream for Haven's workload.
# https://www.postgresql.org/docs/current/static/non-durability.html
command:
- "postgres"
- "-c"
- "max_connections=1000"
- "-c"
- "synchronous_commit=off"
- "-c"
- "fsync=off"
- "-c"
- "full_page_writes=off"
- "-c"
- "max_wal_size=4GB"
- "-c"
- "checkpoint_timeout=30min"
- "-c"
- "wal_level=logical"
environment:
# Allow connections without a password. Safe here: Postgres is reachable only inside the compose network.
POSTGRES_HOST_AUTH_METHOD: "trust"
# Superuser/role name. With no POSTGRES_DB set, Postgres also creates a database of this name for Haven.
POSTGRES_USER: "haven"
volumes:
- db_data:/var/lib/postgresql/data
volumes:
storage:
db_data:
Values set to changeme are required — replace them with your own
values before starting Haven.
Prefer a managed setup? WinterFlow installs, configures, and updates Haven for you using this same Docker Compose configuration.