Skip to content

IMPORTANT

Notivae is in early-stage development. No features are fully implemented yet.

Installation

Notivae can run on your own computer or server using Docker, a tool that bundles everything it needs. No need to install each part separately.

We’ll use a tool called docker-compose to launch all components – the app, its backend, and the database – all with one command.

Prerequisites

Make sure these are ready on your system:

Setup Files

To run Notivae, you'll need two files:

  1. docker-compose.yml – defines the services (frontend, backend, database), ports, and volumes.
  2. .env – contains configuration settings like database passwords, ports, and secrets.

Copy the following files to your local machine or server. We recommend placing them under /srv/notivae-stack.

  • The docker-compose.yml file works as-is but can be customized to your environment or use case.
  • The .env file must be reviewed and adjusted. Each variable has a comment or description in the sample. For a deeper explanation, see Configuration.

Your folder structure should look like this:

text
📁 /srv/notivae-stack
 ┣ 📄 docker-compose.yml
 ┗ 📄 .env

WARNING

These configuration files are currently in draft status and are not fully functional. Use them as a reference or base for manual setup until stable versions are released.

yml
services:
  server:
    image: ghcr.io/notivae/server
    restart: unless-stopped
    ports:
      - "127.0.0.1:8765:80"
    env_file: .env
    environment:
      DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://notivae:devpass@postgres/notivae}
      REDIS_URL: redis://redis
    volumes:
      - nvdata:/data
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  web:
    image: ghcr.io/notivae/web
    restart: unless-stopped
    ports:
      - "127.0.0.1:8766:80"

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

  redis:
    image: redis:alpine
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  nvdata:
  pgdata:
dotenv
# ----------------------------------------
# Backend Debugging & Logging
# ----------------------------------------

# Enables debug mode across the app.
# Should be False in production to avoid exposing sensitive details.
#DEBUG=False

# Minimum severity level of log messages to be output.
# Options:
#   DEBUG    - Most verbose, shows everything (useful for local dev).
#   INFO     - General runtime information (default for production).
#   WARNING  - Things that might be problems in the future.
#   ERROR    - Runtime errors that should be investigated.
#   CRITICAL - Application or system-wide failures.
# Use DEBUG for local development, INFO or WARNING for production.
#LOGGING_LEVEL=INFO

# Format used for application logs.
#   console - Human-readable format, ideal for terminal output.
#   json    - Structured logs, preferred for log ingestion (e.g., ELK, Loki).
#LOGGING_FORMAT=console

# If enabled, logs will also be written to the database in addition to stdout.
# Useful for persistent audit logs or advanced querying.
#LOG_TO_DB=True

# ----------------------------------------
# Backend Server Configuration
# ----------------------------------------

# The IP address the backend server will bind to.
# Common values:
#   0.0.0.0 - Bind to all network interfaces (use in Docker or remote envs).
#   127.0.0.1 - Bind to localhost only (useful for local testing).
#SERVER_HOST=0.0.0.0

# The port the backend server will listen on.
# Must be an integer between 1 and 65534.
#SERVER_PORT=8765

# ----------------------------------------
# Database Configuration
# ----------------------------------------

# The full database connection URL used by the backend service to connect
# to PostgreSQL. This should follow the format:
#   dialect+driver://username:password@host:port/database
#   e.g. postgresql+asyncpg://notivae:devpass@postgres/notivae
# If you are using Docker Compose, this should typically point to the
# internal Docker service name (e.g., `postgres`) instead of `localhost`.
DATABASE_URL=postgresql+asyncpg://notivae:devpass@localhost:5432/notivae

# The number of persistent database connections maintained per application worker.
# Increase this value for high-throughput systems with lots of concurrent queries.
#DATABASE_POOL_SIZE=5

# The number of temporary connections that can exceed the pool size during peak usage.
# These "overflow" connections are not persistent and will be discarded after use.
#DATABASE_POOL_MAX_OVERFLOW=10

# Maximum time (in seconds) to wait for a database connection before failing.
# Prevents application hangs under connection saturation or DB outage.
#DATABASE_POOL_TIMEOUT=30

# Time (in seconds) after which idle database connections will be recycled.
# Helps prevent stale or broken connections in long-lived environments.
#DATABASE_POOL_RECYCLE=1800

# ----------------------------------------
# PostgreSQL Container Configuration (Docker Compose)
# ----------------------------------------

# The username that will be created in the Postgres container.
# This must match the user part of DATABASE_URL.
POSTGRES_USER=notivae

# The password assigned to POSTGRES_USER.
# Used for authenticating from the backend or any external tool.
# This must match the password part of DATABASE_URL.
POSTGRES_PASSWORD=devpass

# The name of the default database that will be created in the container.
# This must match the database name in DATABASE_URL.
POSTGRES_DB=notivae

# ----------------------------------------
# OpenID Connect Identity Provider Config
# ----------------------------------------

# The client ID issued by your OpenID Connect provider (e.g. Auth0, Keycloak, etc.).
# This must match the client configured in the identity provider dashboard.
#OIDC_CLIENT_ID=your-client-id

# The client secret corresponding to the OIDC client.
# Keep this value secret and never commit it to version control.
#OIDC_CLIENT_SECRET=your-client-secret

# URI where users are redirected to authorize the application.
#OIDC_AUTH_URI=https://example.com/oauth2/authorize

# URI used to exchange the authorization code for tokens.
#OIDC_TOKEN_URI=https://example.com/oauth2/token

# URI used to fetch authenticated user information.
#OIDC_USERINFO_URI=https://example.com/oauth2/userinfo

# URI to redirect users after logout (optional for some providers).
#OIDC_LOGOUT_URI=https://example.com/oauth2/logout

# Name shown in the UI for this login option (e.g. "Authentik", "My Company SSO").
#OIDC_DISPLAY_NAME=OpenID

# Scopes to request during authentication.
# Adjust depending on the level of access your app needs.
#OIDC_SCOPES="openid profile email"

# ----------------------------------------
# GZip Compression Configuration
# ----------------------------------------

# Minimum size in bytes a response must reach before gzip compression is applied.
# This helps avoid wasting CPU cycles compressing small payloads that won't benefit.
#GZIP_COMPRESSION_MINIMUM_SIZE=1000

# Compression level to use when gzip is enabled.
# 1 = Fastest, lowest compression ratio.
# 9 = Slowest, highest compression ratio.
# 6 is the recommended default for balanced performance.
#GZIP_COMPRESSION_LEVEL=6

Start the Stack

From within the /srv/notivae-stack directory, run:

bash
docker compose up -d

This command will:

  • Start the database and cache (for storage)
  • Start the backend (the engine)
  • Start the frontend (the user interface)

Docker will automatically download any required images on the first run. This may take a while, depending on your internet connection.

Verify

After a few seconds, run this command in your terminal:

bash
curl http://localhost:8765/healtz

You should see a simple response like:

json
{"status":"ok"}

If you see this message, it means the backend is running successfully and responding to requests.

However, you won’t be able to access the web interface yet. The frontend and backend are exposed on different ports and cannot communicate directly in this setup.

INFO

🛠️ To continue, you need to configure a reverse proxy or another solution that connects the frontend to the backend under a unified address.
This is required before opening the web UI in your browser.

Connect Frontend and Backend

Notivae’s frontend expects to reach the backend at /api on the same domain and port — for example:

text
https://notivae.example.com     → frontend
https://notivae.example.com/api → backend

However, in the current setup, the backend and frontend are exposed on different ports:

text
http://localhost:8766 → Frontend
http://localhost:8765 → Backend

This means they can’t communicate properly until you combine them under a unified domain or port.

The solution is a reverse proxy. A reverse proxy acts as a gateway that:

  • Routes browser requests to the correct service (frontend or backend)
  • Handles HTTPS (SSL) if needed
  • Rewrites paths like /api/* to target the backend

This setup is required even if you're running Notivae locally.

Popular reverse proxy options:

  • Caddy — simple, automatic HTTPS
  • Traefik — Docker-native, dynamic
  • Nginx — widely supported, configurable

Need help setting it up?

See the Reverse Proxy Guide for setup examples and config snippets.

TIP

Hosting Notivae behind a home network? You may need a tunnel like Cloudflare Tunnel or Ngrok to make it accessible from the internet.
This is also covered in the Reverse Proxy Guide.

Finalizing your instance

Notivae's web-ui has a built-in wizard to help you configure the final parts or your hosted instance. To start the setup wizard open the following page in your browser.

txt
https://<your-domain-or-ip>/#/init
e.g. https://notivae.example.com/#/init

Updating

To update Notivae to the latest version:

shell
docker-compose pull
docker-compose up -d

This will:

  • Pull the latest image versions
  • Restart the containers using the updated versions

WARNING

This command works only if you are omitting or using floating tags like :latest or :dev in your docker-compose.yml. If you pin versions explicitly in docker-compose.yml, you need to update the tags manually before running pull.

Stopping the Stack

To shut everything down:

shell
docker-compose down

Your data (e.g., database files) will be preserved unless you remove the Docker volumes explicitly.