Takovej selfhosting Notionu bez fancy tabulek.
Outline je open-source nástroj pro tvorbu a správu interní dokumentace a znalostních bází.
Použité technologie
Nginx
Nginx je výkonný webový server a reverzní proxy, který se používá pro obsluhu statického obsahu, směrování požadavků na backend služby a vyvažování zátěže. Je známý svou rychlostí, nízkou spotřebou paměti a spolehlivostí při vysoké zátěži.
Outline
Outline je open-source nástroj pro tvorbu a správu interní dokumentace a znalostních bází. Poskytuje jednoduché a přehledné uživatelské rozhraní pro týmovou spolupráci, verzování a rychlé vyhledávání obsahu.
Dex
Dex je open-source identitní služba, která funguje jako „OpenID Connect“ provider. Slouží k centralizovanému ověřování uživatelů a umožňuje propojit různé aplikace s externími identity providery (např. Google, GitHub nebo LDAP).
Postgres
PostgreSQL (Postgres) je pokročilý open-source relační databázový systém. Nabízí podporu pro komplexní dotazy, transakce, indexy, JSON data a rozšiřitelnost pomocí vlastních funkcí, čímž se hodí pro širokou škálu aplikací od menších po enterprise řešení.
Redis
Redis je in-memory databáze a cache systém, který umožňuje velmi rychlý přístup k datům. Často se používá pro ukládání relací, front, výsledků výpočtů nebo jako prostředník pro komunikaci mezi službami díky podpoře publikace a odběru zpráv (pub/sub).
Docker / Docker Compose
Docker je platforma pro kontejnerizaci aplikací, která umožňuje spouštět software izolovaně s veškerými závislostmi. Docker Compose pak usnadňuje definování a správu vícekontejnerových aplikací pomocí jednoduchého konfiguračního souboru.
Diagram

Postřehy
Outline
Outline neumožňuje přihlašování pomocí uživatelského jména a hesla, což je poněkud nepříjemné. Musí se nakonfigurovat jedna z podporovaných služeb. Aplikace umí pracovat se Slack identitami, Google identitami a dalšími poskytovateli. Pokud nemůžete použít žádnou z těchto služeb, je tam naštěstí možnost Magic Link via Email. Je to sice nepříjemné, ale funkční řešení. Pokaždé, když se chcete přihlásit, pošle vám aplikace email s přihlašovacím odkazem. V mém setupu jsem se rozhodl použít Dex jako OIDC službu, přes kterou se mohu přihlašovat pomocí emailu a hesla.
Dex
Dex je velmi minimalistický, takže nemá webové rozhraní. Navíc jeho dokumentace je hodně nekvalitní. Nejjednodušším způsobem, jak vše rozchodit, je přidat statického klienta a uživatele přímo do konfiguračního souboru. Musíte si ale vytvořit bcrypt hashovaná hesla. Vycházel jsem z tohoto návodu.
SMTP
Aby fungovalo odesílání emailů, je potřeba nakonfigurovat SMTP server. Pokud žádný po ruce nemáte, můžete použít váš Gmail účet. V nastavení Gmailu se musí vytvořit aplikační klíč, který se pak vloží do .env souboru do SMTP sekce.
Setup
.env
URL=https://outline.<domain.com>
PORT=3050
WEB_CONCURRENCY=1
SECRET_KEY=<secret key>
UTILS_SECRET=<utils secret>
DATABASE_URL=postgres://outline:<db password>@outline-postgres:5432/outline
PGSSLMODE=disable
POSTGRES_USER=outline
POSTGRES_PASSWORD=<db password>
POSTGRES_DB=outline
REDIS_URL=redis://outline-redis:6379
FILE_STORAGE=local
FORCE_HTTPS=true
OIDC_CLIENT_ID=outline
OIDC_CLIENT_SECRET=<oidc client secret>
OIDC_AUTH_URI=https://auth.<domain.com>/dex/auth
OIDC_TOKEN_URI=http://dex:5556/dex/token
OIDC_USERINFO_URI=http://dex:5556/dex/userinfo
OIDC_USERNAME_CLAIM=email
OIDC_DISPLAY_NAME=OIDC Provider
OIDC_SCOPES=openid profile email
SMTP_SERVICE=gmail
SMTP_USERNAME=<you>@gmail.com
SMTP_PASSWORD="<app code>"
SMTP_FROM_EMAIL=<you>@gmail.com
RATE_LIMITER_ENABLED=true
RATE_LIMITER_REQUESTS=1000
RATE_LIMITER_DURATION_WINDOW=60
ENABLE_UPDATES=true
DEBUG=http
LOG_LEVEL=info
DEX Config (config.yaml)
issuer: https://auth.<domain.com>/dex
storage:
type: sqlite3
config:
file: /var/dex/dex.db
web:
http: 0.0.0.0:5556
staticClients:
- id: outline
redirectURIs:
- "https://outline.<domain.com>/auth/oidc.callback"
name: "Knowledge Base"
secret: <oidc client secret>
oauth2:
skipApprovalScreen: true
enablePasswordDB: true
staticPasswords:
# Admin
- email: "<admin>@gmail.com"
hash: "<bcrypt password hash>"
username: "admin"
userID: "admin-001"
- email: "<user>@gmail.com"
hash: "<bcript password hash>"
username: "user"
userID: "user-001"
# Pro debug
logger:
level: "info"
format: "text"
Docker Compose
services:
outline:
image: docker.getoutline.com/outlinewiki/outline:latest
env_file: ./.env
ports:
- "3050:3050"
expose:
- "3050"
volumes:
- storage-data:/var/lib/outline/data
depends_on:
- outline-postgres
- outline-redis
outline-redis:
image: redis
env_file: ./.env
expose:
- "6379"
volumes:
- ./redis.conf:/redis.conf
command: ["redis-server", "/redis.conf"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 30s
retries: 3
outline-postgres:
image: postgres
env_file: ./.env
expose:
- "5432"
volumes:
- database-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-d", "outline", "-U", "user"]
interval: 30s
timeout: 20s
retries: 3
dex:
image: dexidp/dex:v2.37.0
ports:
- "5556:5556" # Vystaveno pro nginx proxy
expose:
- "5556"
volumes:
- ./dex-config:/etc/dex:ro # Read-only mount konfigurace
- dex-data:/var/dex # Persistentni SQLite databáze
command: ["dex", "serve", "/etc/dex/config.yaml"]
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5556/dex/healthz"]
interval: 30s
timeout: 10s
retries: 3
restart: unless-stopped
volumes:
storage-data:
database-data:
dex-data:
Nginx
auth.
server {
listen 80;
server_name auth.<domain.com>;
# P┼Öesm─Ťrov├ín├ş HTTP na HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name auth.<domain.com>;
# SSL certifik├íty (upravte cestu podle va┼í├ş konfigurace)
ssl_certificate /etc/nginx/ssl/<domain.com>/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/<domain.com>/privkey.pem;
# SSL konfigurace
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# Proxy nastaven├ş pro Home Assistant
location / {
proxy_pass http://<service ip>:5556;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeout nastaven├ş
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering nastaven├ş
proxy_buffering off;
proxy_request_buffering off;
}
# Logov├ín├ş
access_log /var/log/nginx/auth.<domain.com>.access.log;
error_log /var/log/nginx/auth.<domain.com>.error.log;
}
outline.
server {
listen 80;
server_name outline.<domain.com>;
# P┼Öesm─Ťrov├ín├ş HTTP na HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name outline.<domain.com>;
# SSL certifik├íty (upravte cestu podle va┼í├ş konfigurace)
ssl_certificate /etc/nginx/ssl/<domain.com>/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/<domain.com>/privkey.pem;
# SSL konfigurace
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# Proxy nastaven├ş pro Home Assistant
location / {
proxy_pass http://<service ip>:3050;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeout nastaven├ş
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering nastaven├ş
proxy_buffering off;
proxy_request_buffering off;
}
# Logov├ín├ş
access_log /var/log/nginx/outline.<domain.com>.access.log;
error_log /var/log/nginx/outline.<domain.com>.error.log;
}
![]()






