Excalidraw

Excalidraw

Docker app from junkerderprovinz's Repository

Overview

Excalidraw is a virtual whiteboard for sketches that look hand-drawn. This is a self-hosted build of it that keeps to itself: shared links, live collaboration, the session scene, the fonts and the icons all come from your own server, and the browser never contacts anyone else. What that means in practice: • Shared links are stored in this container, not on json.excalidraw.com • A live session keeps its scene here, not in Google Firestore • Pasted images stay here, not in Firebase Storage • The collaboration socket is this container, not oss-collab.excalidraw.com • Fonts are served from the image, and the analytics script is gone • Everything is encrypted in your browser before it is stored. The key sits in the part of the link after the #, which browsers never send to a server, so the container holds bytes it cannot read Two features would still talk to Excalidraw's servers, so they are switches rather than a decision made for you, and both are off by default: the shape library and the text-to-diagram feature. Off means the request never leaves your server. Notes: • Use the HTTPS port. Live collaboration needs crypto.subtle, which browsers only provide over HTTPS, so on the plain HTTP port the "start session" button fails with a cryptography error. The container generates a self-signed certificate on first start and keeps it in /config, so your browser only has to be told once. • The HTTP port is there for a reverse proxy that terminates TLS, and for the single-user case where no session is ever started. • Behind a reverse proxy: allow WebSocket upgrades on /socket.io/ and a body size of 64 MB, otherwise collaboration cannot connect and drawings with images are refused. • /config holds the drawings database and the certificate. Back it up and you have backed up everything.

excalidraw

Build  Lint  Docker Pulls  Image Size  Arch  Go  nginx  Unraid  License: AGPL-3.0


Excalidraw is a virtual whiteboard for sketches that look hand-drawn. This is a self-hosted build of it that keeps to itself: shared links, live collaboration, the session scene, the fonts and the icons all come from your own server, and the browser never contacts anyone else. One container, one port, nothing to configure.

Install from Unraid's Community Applications   Install from the MOS Hub   Install from the ZimaOS and CasaOS store   Install from the umbrelOS community app store

Download the docker-compose file   Download the source archive


A one-knight job: I build it, keep it running, work through the issues and add what people ask for, until nothing is missing. It is free, with no accounts, no telemetry, no ads and no paid tier. No asterisk anywhere. Nothing readable ever leaves your own walls. Forged on evenings and weekends, with heart and stubbornness.

If it has earned a place on your server or computer, toss a coin to your knight: it helps cover the costs and keeps the project alive. It also makes this knight's heart beat a little faster. Three ways below, whichever suits you.

Buy me a coffee   PayPal   Donate with crypto


Table of Contents

  1. What it looks like
  2. What it does
  3. How it compares
  4. Getting started
  5. How AI is used here
  6. Support this project

1. What it looks like

The drawing and the names in these pictures are made up.

Two people drawing on the same Excalidraw board in dark mode, the second one's cursor labelled Jonas
A live session, relayed and stored by the container on your server

The live collaboration dialog with the session link and its QR code
The session link points at your server, and the key in it never reaches any server


2. What it does

  • The same Excalidraw. Built from a pinned upstream commit, with one file replaced: the one that talks to Firestore. The encryption and the merge logic for two people drawing at once are unchanged.
  • Shared links and live sessions stay home. A small Go store over SQLite keeps scenes, rooms and pasted images, and Excalidraw's own room server relays between browsers.
  • Nothing calls out. The fonts come from the image and the analytics script is gone. A gate at the end of the build fails if any outside address is left in the app.
  • Two features are switches. The shape library (ENABLE_LIBRARY) and text to diagram (ENABLE_AI) would contact Excalidraw's servers, so they are off until you turn them on.
  • HTTPS from the first start. Live collaboration needs a secure context, so the container makes a self-signed certificate and keeps it in /config.
  • Nothing to configure. The app only uses relative paths, so the same image works on a LAN address, behind a reverse proxy and under a subdomain.

3. How it compares

The published Excalidraw image runs the app unchanged, and the app still talks to Excalidraw's own infrastructure. That is how a free hosted service pays for itself, and it is all decided when the app is built, which is why the published image cannot offer it as a setting.

What Upstream Here
Shared links json.excalidraw.com this container, in SQLite
Live session scene Google Firestore this container, in SQLite
Pasted images Firebase Storage this container, in SQLite
Collaboration socket oss-collab.excalidraw.com this container
Fonts a CDN this container
Analytics simpleanalyticscdn.com removed
Shape library libraries.excalidraw.com off by default, ENABLE_LIBRARY
Text to diagram oss-ai.excalidraw.com off by default, ENABLE_AI

Everything a drawing contains is encrypted in your browser before it is stored. The key sits in the part of the link after the #, which browsers never send to a server, so the container holds bytes it cannot read.


4. Getting started

On Unraid, install Excalidraw from Community Applications. Anywhere else:

docker run -d --name excalidraw   -p 8443:443   -v /path/to/config:/config   --restart unless-stopped   ghcr.io/junkerderprovinz/excalidraw:latest

Then open https://your-server:8443 and accept the certificate once. Use the HTTPS port: over plain HTTP the browser withholds the cryptography a live session needs, and starting one fails. /config holds the database and the certificate, so backing it up backs up everything.

Behind a reverse proxy, point it at port 80 of the container, allow WebSocket upgrades on /socket.io/ and a body size of 64 MB.

Other Docker hosts

compose.yaml runs Excalidraw on any Linux server with Docker. Put it in a folder of its own and start it with docker compose up -d. The folders are created next to the file.

  • Synology: in Container Manager, create a project from the file (DSM 7.2 or newer).
  • Proxmox: run it in a VM or an LXC container that has Docker.
  • MOS: install Excalidraw from the MOS Hub.
  • ZimaOS and CasaOS: add the community store and install Excalidraw from it.
  • umbrelOS: add the community app store and install Excalidraw from it.

5. How AI is used here

One knight builds this, and AI is one of the tools I work with, the same way I work with an editor or a compiler. It helps me write code and documentation and it checks my work, and that saves me a good many evenings. It does not make the decisions, though. I read and understand everything before it ships, and if something here breaks, that is on me and not on the tool.

You do not have to take my word for it. The code is open and every release note is written by hand. The issue tracker shows how problems actually get handled, including the ones I got wrong the first time. If you find something that is not right, open an issue and I will look at it.


6. Support this project

Questions via the support thread, bugs, ideas and feature requests via GitHub issues.

A one-knight job: I build it, keep it running, work through the issues and add what people ask for, until nothing is missing. It is free, with no accounts, no telemetry, no ads and no paid tier. No asterisk anywhere. Nothing readable ever leaves your own walls. Forged on evenings and weekends, with heart and stubbornness.

If it has earned a place on your server or computer, toss a coin to your knight: it helps cover the costs and keeps the project alive. It also makes this knight's heart beat a little faster. Three ways below, whichever suits you.

Buy me a coffee   PayPal   Donate with crypto


Excalidraw is MIT-licensed and belongs to the Excalidraw team. This image is not affiliated with or endorsed by Excalidraw.

Download Statistics

5,221
Total Downloads

Related apps

Details

Repository
junkerderprovinz/excalidraw:latest
Last Updated2026-10-02
First Seen2026-09-05

Runtime arguments

Web UI
https://[IP]:[PORT:443]/
Network
bridge
Shell
sh
Privileged
false
Extra Params
--restart=unless-stopped

Template configuration

WebUI Port (HTTPS)Porttcp

The port to open in your browser. HTTPS is required for live collaboration, because browsers only provide the cryptography it needs over a secure connection. The certificate is self-signed and generated on first start, so your browser asks you to accept it once.

Target
443
Default
8443
Value
8443
WebUI Port (HTTP)Porttcp

For a reverse proxy that terminates TLS in front of the container, or for solo drawing where no session is ever started. Opened directly in a browser, this port cannot run live collaboration, because the cryptography it needs is only available over HTTPS.

Target
80
Default
8080
Value
8080
AppData (/config)Pathrw

Holds the drawings database (shared links, live sessions, pasted images) and the self-signed certificate. This is the only thing worth backing up.

Target
/config
Default
/mnt/user/appdata/excalidraw
Value
/mnt/user/appdata/excalidraw
Shape libraryVariable

Set to true to allow the shape library to load from libraries.excalidraw.com. That is a public catalogue of drawings other people published, so nothing of yours is sent, but your browser does contact Excalidraw's server. Left false, the library button reports an error and nothing leaves your network.

Target
ENABLE_LIBRARY
Default
false
Value
false
Text to diagramVariable

Set to true to allow the text-to-diagram feature, which sends what you typed to Excalidraw's AI service. Left false, the feature reports an error and your text stays here.

Target
ENABLE_AI
Default
false
Value
false
Time zoneVariable

Time zone used for the container log.

Target
TZ
Default
Europe/Berlin
Value
Europe/Berlin