We wanted a team whiteboard we owned, so we forked Excalidraw and ran it ourselves
A self-hosted, rebranded Excalidraw with real-time collaboration, running on our own VPS at whiteboard.autosterea.com. No SaaS seats, no drawings leaving our server.
The problem
The team needed a shared whiteboard for sketching diagrams and planning flows. Buying seats on a SaaS whiteboard means a recurring bill and your work living on someone else's servers. Excalidraw is the best open-source canvas there is, but the public app is wired to funnel you toward a paid product and there is no team password on it. We wanted the tool, on our own box, with our name on it, locked behind a password, for the cost of a server we already run.
What we built
The modules of the system.
The canvas
The full Excalidraw drawing surface: hand-drawn shapes, arrows, text, frames, images, libraries. The same tool the team already knows, just wearing our name. The welcome screen reads 'Sketch, plan, collaborate.' and the Excalidraw+ upsells, social links, and sign-in prompts are gone.
Real-time collaboration
Multiple people draw on the same board at once. A Socket.IO collaboration server (excalidraw-room) runs on the VPS at port 5102 and relays edits between everyone connected. End-to-end encryption is preserved, so the server passes traffic without reading the contents.
Password gate
A single cookie-based login page guards the whole site. Type the team password once, get a 30-day cookie, and nginx lets you through. No per-user accounts to manage, no SaaS seats to provision.
Autosterea skin
Logo swapped for the Autosterea 'A' triangle, the signature Excalidraw purple replaced with Celadon Green across light and dark mode, favicon and PWA icons replaced, and the install-as-app name set to 'Autosterea Whiteboard.' Installs to a desktop or phone like a native app.
How it fits together
Three moving parts on one DigitalOcean droplet (Ubuntu 24.04, 2GB RAM). First, a static frontend: we build the rebranded Excalidraw app locally with yarn, then SCP the output to /srv/whiteboard/public, where nginx serves it as plain files. Second, the collaboration server: excalidraw-room (a small Node Socket.IO service) runs as a systemd unit on 127.0.0.1:5102, kept alive and auto-restarted by systemd. Third, nginx out front: it terminates TLS (Let's Encrypt via Certbot, auto-renewing), serves the static files, reverse-proxies the /socket.io/ WebSocket traffic to the collab server, and enforces the cookie login by bouncing anyone without the wb_token cookie to the login page. The droplet also hosts two unrelated apps (tasker prod and dev on ports 5100 and 5101), so the whole thing was built to be light: no Docker, no database, just Node, systemd, and nginx sharing a small box.
Under the hood
The decisions that mattered.
Cookie login, because corporate browsers killed the popup
The first cut used HTTP Basic Auth, the one-line nginx way to password-protect a site. It worked on our machines and died in the field: corporate browsers (a teammate on the Boeing network) block the Basic Auth credential popup entirely, so the site was simply unreachable for them. We swapped it for a real login page. auth.html takes the password, sets a 30-day wb_token cookie, and nginx checks for that cookie on every request, redirecting to the login page when it is missing. The password lives as a hash in the page, and rotating it is two edits (the hash in auth.html plus the cookie token). One shared password, zero user accounts to administer, and it works behind locked-down corporate proxies.
Recoloring a whole design system without forking the design system
Excalidraw's identity is that purple (#6965db). Rather than hunt down every component, we retargeted the CSS custom properties at the root of theme.scss: --color-primary, its darker, darkest, light, and hover variants, --color-selection, --color-brand-active, and the logo icon color all point at Celadon Green (#23827E) and its tints. We did it for both light and dark mode (dark mode gets lighter teal variants like #5cc4bf so it reads on a dark canvas). Because the entire UI already pulls from those variables, the rebrand cascaded everywhere (buttons, selections, active states) from a handful of lines instead of a thousand-file diff.
Stripped the SaaS funnel, kept the license honest
Upstream Excalidraw is the front door for a paid product, so the open-source app is sprinkled with Excalidraw+ promos, a sign-in and sign-up menu, social links, and an analytics hook. For an internal tool those are noise, and the redirect to Excalidraw+ is actively wrong. We made ExcalidrawPlusPromoBanner return null, pulled the upsell and auth items out of the main menu and welcome screen, removed analytics and the Plus redirect from index.html, and trimmed the help dialog's external links down to an Autosterea link. Excalidraw is MIT licensed, so we kept attribution honest with a small 'Powered by Excalidraw' credit in the footer. Take what is useful, remove the funnel, credit the source.
Build locally, ship the artifact, never build on the box
A 2GB VPS running three apps cannot afford a yarn build (the toolchain alone would risk running out of memory and taking down the neighbors). So the deploy is deliberately dumb: build the static frontend on a real machine, then SCP the artifact to /srv/whiteboard/public. The collab server is the upstream excalidraw-room cloned on the box and run under systemd, so it almost never needs to change. Frontend changes never touch the server process, and server restarts never touch the frontend. The small box stays calm because the heavy work happens somewhere else. We did have to bump Vite 5 to 6 to keep the local build happy on Node 24.
Release log
What we shipped.
Cloned excalidraw/excalidraw, swapped the logo for the Autosterea 'A' triangle, recolored the theme to Celadon Green across light and dark mode, replaced favicons and PWA icons, and stripped the Excalidraw+ promos, sign-in menu, social links, and analytics.
Upgraded Vite 5 to 6 for Node 24 compatibility and settled on the build-locally-then-SCP workflow so the small VPS never has to compile.
Cloned excalidraw-room on the VPS, wrapped it in a systemd unit on 127.0.0.1:5102, and wired nginx to proxy /socket.io/ WebSocket traffic to it for real-time multi-user editing.
Pointed whiteboard.autosterea.com at the droplet and issued an auto-renewing Let's Encrypt certificate via Certbot.
Replaced HTTP Basic Auth (blocked by corporate browser proxies) with a cookie-based login page that nginx enforces, giving a 30-day session from one shared password.
The outcome
The team has a fast, branded, real-time whiteboard at whiteboard.autosterea.com that runs on infrastructure we already pay for, with no per-seat SaaS bill and no drawings leaving our own server. It rides on a 2GB box alongside two other live apps without straining it, the password gate works even behind locked-down corporate networks, and the artifact-based deploy means updates are a build and an SCP away. A small, sharp internal tool that proves the pattern we use everywhere: take the best open-source engine, make it ours, and operate it.
Put your business on autopilot