Neko is an open-source virtual browser platform that runs inside Docker and streams an interactive browser session to multiple users over WebRTC, with synchronized audio/video and admin-controlled input handoff. This guide deploys Neko using Docker Compose with Traefik handling automatic HTTPS, and persistent Firefox profile storage. By the end, you'll have a shared virtual browser session running securely at your domain.
Set Up the Directory Structure
1. Create the project directory with a Firefox profile subdirectory:
$ mkdir -p ~/neko/profile
$ cd ~/neko
2. Create the environment file:
$ nano .env
DOMAIN=neko.example.com
LETSENCRYPT_EMAIL=admin@example.com
NEKO_ADMIN_PASSWORD=StrongAdminPassword123
NEKO_USER_PASSWORD=StrongUserPassword456
3. Set ownership on the profile directory, Neko runs as UID 1000:
$ sudo chown -R 1000:1000 ~/neko/profile
Deploy with Docker Compose
1. Create the Docker Compose manifest:
$ nano docker-compose.yaml
services:
traefik:
image: traefik:v3.6
container_name: traefik
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
restart: unless-stopped
neko:
image: ghcr.io/m1k1o/neko/firefox:3
container_name: neko
shm_size: "2gb"
expose:
- "8080"
ports:
- "52000-52100:52000-52100/udp"
volumes:
- "./profile:/home/neko/.mozilla/firefox/profile.default"
environment:
NEKO_MEMBER_PROVIDER: "multiuser"
NEKO_MEMBER_MULTIUSER_USER_PASSWORD: "${NEKO_USER_PASSWORD}"
NEKO_MEMBER_MULTIUSER_ADMIN_PASSWORD: "${NEKO_ADMIN_PASSWORD}"
NEKO_SERVER_PROXY: "true"
NEKO_DESKTOP_SCREEN: "1280x720@30"
NEKO_WEBRTC_EPR: "52000-52100"
NEKO_WEBRTC_ICELITE: "true"
labels:
- "traefik.enable=true"
- "traefik.http.routers.neko.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.neko.entrypoints=websecure"
- "traefik.http.routers.neko.tls.certresolver=letsencrypt"
- "traefik.http.services.neko.loadbalancer.server.port=8080"
restart: unless-stopped
volumes:
letsencrypt:
The shm_size: "2gb" allocation is required, Firefox rendering crashes or freezes without enough shared memory. NEKO_WEBRTC_EPR opens the UDP port range WebRTC media travels over; NEKO_WEBRTC_ICELITE suits servers with a public IP and direct inbound UDP.
2. Start the services:
$ docker compose up -d
3. Verify both services are running:
$ docker compose ps
$ docker compose logs
Access Neko
- Open
https://neko.example.com. - Enter a display name and the admin password from
.env, then click CONNECT. - The Firefox window loads in the center with a control bar below. Connected users appear as avatars; a green badge marks whoever holds control.
- The side panel has Chat (activity log) and Settings (scroll sensitivity, keyboard layout, autoplay).
Run a Collaborative Session
- Share the URL and the user password (not the admin one) with participants.
- Each participant enters a display name + password and clicks CONNECT — their avatar appears at the bottom.
- Navigate to any URL in the address bar. WebRTC streams it to everyone with minimal delay.
- Right-click a user's avatar to Give Controls, Kick, or Ban IP (kick/ban are admin-only).
Next Steps
Neko is running and streaming a shared browser session over HTTPS. From here you can:
- Swap the Firefox image for Chromium or a custom browser image
- Add a TURN server for participants behind restrictive NATs
- Scale to multiple rooms by running additional Neko containers on different subdomains
For the full guide with additional tips, visit the original article on Vultr Docs.
Top comments (0)