nexcanvas

nexcanvas

Docker app from DerKezorm's Repository

Overview

nexcanvas is a whiteboard for your own server, in the spirit of Apple Freeform: sticky notes, shapes, text, lines, pen and highlighter, photos and PDFs on an endless board, edited by several people at the same time. Everybody sees each change at once, with the pointers and names of the others. Frames and scenes to present from, a shape library with over 350 shapes of its own (flowchart, BPMN, UML, floor plan to scale, network, house and electrics) plus the Lucide icons, over thirty templates and your own, backgrounds like grid, blueprint or chalkboard. Export as PNG and PDF, exchange with nexlore and Obsidian as JSON Canvas. Spaces with read, write and manage rights, accounts by invitation or OpenID Connect (one-button setup for authentik), an optional second factor, public pages, backups and a log. English and German, light and dark, works on the phone.

nexcanvas

Website: www.nexcanvas.de

A whiteboard for your own server, in the spirit of Apple Freeform: sticky notes, shapes, text, lines, pen and highlighter, photos and PDFs on an endless board, edited by several people at the same time. Self-hosted, for yourself, a family or a small team.

nexcanvas is one of the nex apps and looks like them: coral, dark and light. Whoever knows nexlore finds the same frame here, with the same accounts, second factor, sign-in through a provider, log, languages and backups. More on the project site, www.nexcanvas.de.

A network plan with VLANs, the shape library open on the left

A network plan from a template. On the left the shape library: packages as groups, search, favorites and recent shapes; drag a shape onto the board or click it and draw it to size. Lines dock at the edge a shape really has.

Screenshots

A floor plan of a flat with furniture to scale, on a grid

A floor plan to scale, one unit a centimetre: walls, doors, windows and furniture from the floor plan package, a dimension line, the board on a grid that things snap to.

A flowchart with a decision and a loop back

A flowchart. Every shape carries its text; the "+" on a selected shape adds the next one and joins it, Tab adds a child and Shift+Tab a sibling.

The templates, grouped

Over thirty templates in groups (to begin, flow and process, project, rooms, network, thinking, organisation), plus your own: save a board as a template, with its content or only the skeleton.

A home network plan in the light theme A mind map on a phone

Light and dark, and on the phone with every tool at the bottom of the screen.

What it does

  • An endless board. Notes in seven colours, nine shapes with text inside, text in four sizes or handwriting, lines that stick to what they connect (straight or curved, arrows, dashed), pen and highlighter with pressure, an eraser for drawings. Things snap to each other while you drag (Alt does the opposite).
  • Together, live. Everybody sees each change at once, the pointers of the others with their names, and what they have selected. Two people can type in the same note; both their words stay. Undo only ever takes back your own steps, never somebody else's.
  • Photos and files. Drop them on the board, paste them, or take a photo with the phone's camera. Place and device are taken out of photos, large photos get a smaller copy for the board, the same file is stored once. A photo dropped on an empty slot of a mood board fills it. PDFs show page by page; what you draw on a page stays with that page.
  • Frames and scenes. A frame is a named area that takes along what lies in it. The scene list jumps from frame to frame, and presenting shows one frame after the other on the whole screen, also on a public page.
  • A shape library like Visio's. Over 350 shapes of its own in packages: basic shapes, flowchart, BPMN, UML and software, floor plan (to scale), house and electrics, project management, network, signs and arrows, plus the Lucide icons in themed packages. A board carries the drawings of the shapes it uses, so it looks the same on a server without that package. Spaces and the operator install packages as files, add SVGs or save a shape from the board; each account hides the packages it does not need.
  • Templates. Over thirty, from kanban and retro to floor plan, rack layout, Gantt schedule and business model canvas, and your own ones for a space or the whole server.
  • Backgrounds. Plain, dots, squares, lines, millimetre paper or isometric, on paper white, cream, chalkboard, blueprint or a colour of your own, the same for everybody on the board.
  • Turn, group, line up. Turn anything around its middle, group things so they move as one, line several up or spread them evenly.
  • Export. The board, the selection or every frame as a picture (PNG) or a PDF, one page per frame.
  • JSON Canvas. A board saves as a .canvas file the way Obsidian writes it, with its photos and files in a ZIP archive, and a canvas from Obsidian or nexlore comes in, into an open board or as a new one. What only nexcanvas knows (shapes, drawings, turned things, the background) travels along unseen and comes back whole, so a board moves from one nexcanvas to another as a file.
  • Spaces and rights. Boards live in spaces; each member of a space reads, writes or manages there. A space somebody may not read answers like one that does not exist. A board can get a public page, read only, with an end date and a password if you like.
  • Versions and the bin. A state of each board is kept every half hour while people work on it; bring one back with a click. Boards and spaces go to a bin for 30 days.
  • On the phone. All tools with the finger: the tools sit at the bottom, one finger moves the board, two zoom, a long press opens the menu, a double tap starts a text.
  • Around it, as in nexlore. Accounts by invitation, second factor with recovery codes, sign-in through an OIDC provider, a log in four levels, German and English plus languages the operator adds as JSON files, backups of the database together with every photo and file, with a check before going back.

Start

services:
  nexcanvas:
    image: ghcr.io/derkezorm/nexcanvas:latest
    container_name: nexcanvas
    restart: unless-stopped
    ports:
      - "8500:8000"
    volumes:
      - ./data:/data
    environment:
      PUID: 1000
      PGID: 1000
      TZ: Europe/Berlin
docker compose up -d

Built from source instead: clone this repository, put build: . in place of image: and run docker compose up -d --build.

Open http://<your-host>:8500. The first account you create there is the operator. It needs the setup code from the server's log, so that nobody who reaches a fresh instance first can take it:

docker logs nexcanvas

shows the setup code, new at every start until nexcanvas is set up. To choose it yourself, set NEXCANVAS_SETUP_TOKEN. docker-compose.yml in this repository has the same service with every option explained.

Put nexcanvas behind a reverse proxy with TLS before you use it from anywhere but your own desk, and let the proxy pass WebSockets through: boards are edited live over /api/boards/<id>/live.

nexcanvas on the internet

nexcanvas is made to be reachable from outside, for yourself on the road or for a small team. Before you open it:

  1. Set it up first, from your own network, with the setup code from the log. Only then forward a port.
  2. TLS at a reverse proxy, and nexcanvas reachable only through it: publish the port as 127.0.0.1:8500:8000 when the proxy runs on the same host, or keep both on a Docker network without a published port. Pass WebSockets through, and send HSTS from the proxy.
  3. Tell nexcanvas about the proxy: NEXCANVAS_PUBLIC_URL (the address people use), NEXCANVAS_TRUSTED_PROXIES (the proxy's address or network; without it every sign-in seems to come from the proxy and the brake against guessing cannot tell people apart), and NEXCANVAS_COOKIE_SECURE: "on".
  4. A second factor: set up your own under My account, Security. Or sign in through your OpenID Connect provider.
  5. Leave the switches closed you do not need: public pages and API tokens are off until you open them.
  6. Optionally keep the operator's settings at home: NEXCANVAS_OPERATOR_NETWORKS: "192.168.0.0/16" refuses them from anywhere else (behind a proxy only together with NEXCANVAS_TRUSTED_PROXIES).
  7. Backups somewhere else: they hold everything, photos and files included. Copy one off the machine now and then, as carefully as the data directory, and try a restore with "Check".
  8. Pin a version instead of latest, update on purpose, back up before.

Where things are stored

Everything lives in /data: the SQLite database nexcanvas.db (accounts, spaces, boards and their versions), media/ (photos and files, with smaller copies of large photos), secret.key, backups/, logs/, locales/. Mount it from a local disk, never from an SMB or NFS share: SQLite's locking does not work reliably over network filesystems.

Back it up with nexcanvas's own backups (Settings, Server, Backup), which copy the database consistently while it runs and take every photo and file along. A backup is a plain ZIP; whoever has it has everything, so keep downloaded copies as carefully as the data directory itself.

Moving to a new server: download a backup, set up nexcanvas there, upload the backup under Settings, Server, Backup, check it and restore it. Afterwards the new server has the old accounts, spaces, boards, photos and files.

Updating

With an image: docker compose pull && docker compose up -d. Built from source: pull the new code and run docker compose up -d --build. nexcanvas adds what the database lacks at the start; nothing needs doing by hand. Make a backup before a big jump anyway.

Environment

Variable Default Meaning
NEXCANVAS_DATA_DIR /data Database, photos and files, logs, backups, languages
NEXCANVAS_MEDIA_DIR <data>/media Photos and files of the boards
NEXCANVAS_LOCALES_DIR <data>/locales Extra languages, one JSON file each
NEXCANVAS_SECRET_KEY created on first start Protects server-side secrets; when set, it wins over secret.key
NEXCANVAS_PUBLIC_URL from the request The address people use to reach nexcanvas, for invitation links, public pages and the OIDC redirect. The setting in the interface wins when set
NEXCANVAS_TRUSTED_PROXIES none Addresses or networks of reverse proxies whose X-Forwarded-For is believed, comma separated
NEXCANVAS_SETUP_TOKEN made at start The code the first account needs
NEXCANVAS_OPERATOR_NETWORKS none Networks the operator's settings may be changed from, comma separated
NEXCANVAS_UPLOAD_MAX_MB 50 The largest photo or file; the operator can lower it in the settings
NEXCANVAS_SESSION_DAYS 30 A browser session ends after this many days
NEXCANVAS_LOG_LEVEL stored setting quiet, normal, detailed or trace; overrides the setting
NEXCANVAS_COOKIE_SECURE auto on, off or auto (from the request or X-Forwarded-Proto)
NEXCANVAS_API_DOCS false Serves /api/docs and /api/openapi.json
PUID, PGID 1000 Owner of the files in the data directory

Working next to nexlore and Obsidian

nexlore keeps notes, nexcanvas draws. Between them, and with Obsidian, boards travel as JSON Canvas (jsoncanvas.org): notes, texts and shapes become text cards, photos and files file cards, links link cards, frames groups, lines between two things edges. Drawings and lines with a free end are kept in a nexcanvas block the others leave alone. Coming in, a text card becomes a note in the nearest of the seven colours, a group a frame, and a file card the photo or file of that name from the archive.

For programs

n8n and your own scripts can read nexcanvas with an API token: the boards, numbers for a dashboard and a small picture of each board. Off until the operator switches it on; every account then makes its own tokens. Reading only. The routes are in docs/api.md.

Security in short

  • Passwords are hashed with Argon2id; failed sign-ins lock an account for a while, and a brake per sender slows guessing on top. With a second factor, the password alone opens nothing.
  • Every changing request needs the header X-Nexcanvas-Client, which a page on another site cannot send; the live connection checks where it comes from and checks the rights of each connection again every 30 seconds, so a member taken out of a space is out of its boards at once.
  • A space somebody may not read answers exactly like one that does not exist, in every route.
  • Readers get the changes of others but cannot send any; the server keeps every change before it passes it on.
  • Photos and files are served with their own sandboxing policy; whatever a browser would not show by itself is a download. PDFs are drawn by pdf.js without scripts.
  • A canvas archive that comes in is read without ever writing its names to disk; each file is checked like an upload.
  • The log never contains the words on a board, passwords, keys or tokens.

Development

cd backend && python -m venv .venv && .venv/Scripts/python -m pip install -r requirements-dev.txt
.venv/Scripts/python -m uvicorn app.main:app --port 8500
cd frontend && npm ci && npx vite

On Linux the virtual environment's programs are in .venv/bin. The frontend on port 5500 sends /api, the live connection included, to the backend. Tests: python -m pytest -q in backend, npx vitest run in frontend.

License

AGPL-3.0.

The buttons and the icon packages of the shape library use the Lucide icons (ISC, partly MIT from Feather); their notice is in frontend/public/licenses/lucide.txt and ships with the app at /licenses/lucide.txt. Everything else nexcanvas ships or depends on, with its licence, is listed in THIRD-PARTY.md.

Related apps

Details

Repository
ghcr.io/derkezorm/nexcanvas
Last Updated2026-10-05
First Seen2026-10-05

Runtime arguments

Web UI
http://[IP]:[PORT:8000]/
Network
bridge
Shell
sh
Privileged
false

Template configuration

WebUI PortPorttcp

Port you reach nexcanvas at. Container port: 8000

Target
8000
Default
8500
Value
8500
Data (Container Path: /data)Pathrw

Holds the SQLite database with accounts, spaces and boards, the photos and files on the boards, the key secret.key, backups and logs. Keep it on a local disk, not on a network share.

Target
/data
Default
/mnt/user/appdata/nexcanvas
Value
/mnt/user/appdata/nexcanvas
PUIDVariable

User id that should own the files in /data. 99 is the Unraid default.

Default
99
Value
99
PGIDVariable

Group id that should own the files in /data. 100 is the Unraid default.

Default
100
Value
100
Time ZoneVariable

Time zone for timestamps in the log and the versions of a board, for example Europe/Berlin. Leave blank for UTC.

Target
TZ
Setup CodeVariable

The code the first account needs to become the operator. Leave blank: nexcanvas makes a new one at every start until it is set up and writes it to the container log.

Target
NEXCANVAS_SETUP_TOKEN
Public URLVariable

The address people use to reach nexcanvas, for example https://boards.example.com when it sits behind a reverse proxy. Used for invitation links, public pages and the return address of OpenID Connect. Leave blank to take the address of the request; the same can be set later in the settings.

Target
NEXCANVAS_PUBLIC_URL
Trusted ProxiesVariable

Addresses or networks of your reverse proxies, comma separated, for example 172.16.0.0/12. Only their X-Forwarded-For is believed; without it every sign-in seems to come from the proxy and the brake against password guessing cannot tell people apart.

Target
NEXCANVAS_TRUSTED_PROXIES
Container Port (host networking only)Variable

Leave this empty unless you switched Network Type to Host. In bridge mode the WebUI Port above already does the job and setting this will break it, because the mapping still points at 8000. On host networking the port inside the container is the port on your server, so use this to move nexcanvas off 8000 if something else is already there.

Target
NEXCANVAS_PORT
Secret KeyVariable

Protects the server-side secrets (the OpenID Connect client secret, the mail password, second-factor seeds). Leave blank: nexcanvas creates one on first start and keeps it in /data/secret.key.

Target
NEXCANVAS_SECRET_KEY
Secure CookieVariable

auto marks the session cookie Secure when the request arrived over https, also behind a proxy that sends X-Forwarded-Proto. Use on only if a proxy terminates TLS and forwards plain http without that header, and never if nexcanvas should also be reachable over http, or nobody can sign in. off never marks it.

Target
NEXCANVAS_COOKIE_SECURE
Default
auto
Value
auto
Largest Upload (MB)Variable

The largest photo or file in megabytes that can be put on a board. The operator can lower it in the settings.

Target
NEXCANVAS_UPLOAD_MAX_MB
Default
50
Value
50