Glassy runs as a single Docker image. One container, one database file, one config. No external dependencies, no Redis, no S3, no managed database. This makes self-hosting straightforward — whether you want data sovereignty for regulated content, a homelab setup, or just prefer owning your infrastructure. See our pricing page for Clear tier details, which includes self-host rights.
What you need
- A server, VM, or your own machine with Docker and Docker Compose installed
- 1 GB RAM minimum (2 GB recommended for local AI workloads)
- An active Glassy membership (Clear or Pro) — sign up here
- A domain name with DNS pointing to your server (optional — only for HTTPS via Caddy)
- 15 minutes
Step 1: Create the compose file
Create a directory for your Glassy deployment and add a
docker-compose.yml:
services:
glassy:
image: ghcr.io/0reliance/glassy-dash:latest
ports:
- "${APP_PORT:-3000}:8080"
volumes:
- glassy-data:/app/data
env_file: .env
environment:
- INSTANCE_ID=self_hosted
- ENABLE_MCP_SERVER=true
- ENABLE_AGENT_GATEWAY=true
extra_hosts:
- "host.docker.internal:host-gateway"
restart: unless-stopped
volumes:
glassy-data:
The INSTANCE_ID=self_hosted flag
tells Glassy it is running as a self-hosted appliance — no Pro upsells, no marketing surfaces,
all features unlocked, registration permanently disabled. The
/app/data
volume persists your SQLite database and uploaded files.
APP_PORT defaults to 3000 —
change it in .env if that port is in use.
Step 2: Set your secrets
Copy .env.example to
.env and fill in four
required fields: your Glassy membership email, a pairing token from the cloud dashboard, a JWT secret,
and an API key encryption key (generate each secret with
openssl rand -hex 32).
All secrets stay on your server.
Your .env file:
GLASSY_MEMBER_EMAIL=your@glassy-account-email
# Pairing token from Settings → Self-hosting on app.glassy.fyi.
# Prevents anyone who merely knows your email from spinning up an
# unlocked instance using your membership.
GLASSY_SELFHOST_TOKEN=
JWT_SECRET=generate-a-long-random-string-here
API_KEY_ENCRYPTION_KEY=generate-another-random-string-here
ENABLE_MCP_SERVER=true
ENABLE_AGENT_GATEWAY=true Step 3: Start the container
docker compose up -d
Glassy will start on port 3000 (or whatever APP_PORT you set). The first run creates the SQLite database, verifies your membership, runs migrations,
and seeds your admin account automatically. You should see the login page at
http://localhost:3000.
Step 4: Add HTTPS with a reverse proxy
For production use, put a reverse proxy in front of Glassy. Caddy is the simplest option — it provisions and renews TLS certificates automatically:
services:
caddy:
image: caddy:2
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy-data:/data
restart: unless-stopped
glassy:
# ... same as above, but remove the ports mapping
expose:
- "3000"
# ... rest of config
volumes:
glassy-data:
caddy-data:
And a minimal Caddyfile:
glassy.yourdomain.com {
reverse_proxy glassy:3000
}
Set TRUST_PROXY=2 in your
Glassy env so it correctly reads client IPs from the Caddy headers. Restart and you have HTTPS.
Step 5: Sign in to your account
On first boot, the appliance verifies your membership email and pairing token against the cloud, then creates your admin account automatically and prints the initial password to the logs. Retrieve it with either of these commands:
docker compose logs glassy | grep -A2 "Default admin created" Or, if the logs have rotated, read the persisted password file directly — it survives container recreation and is deleted automatically after your first password change:
docker exec glassy cat /app/data/.initial_admin_password
Sign in at http://localhost:3000
with your membership email and that password. The password change is forced on
first login — you are immediately prompted to set a permanent password before you can use the
workspace. Registration is permanently disabled on the self-hosted appliance — this is a single-owner
instance. If port 3000 is in use, set APP_PORT
in .env to use a different port.
What you get
- MCP server — enabled by default, query your knowledge base from Claude, Cursor, Windsurf, OpenCode, Hermes, Openclaw, Pi, or any MCP-compatible AI agent
- Browser extension — connect the Glassy Companion to your self-hosted instance
- Obsidian sync — connect your vault for two-way sync
- Local AI — WebGPU models run in the browser, no GPU on the server needed
- Voice Studio — transcription runs locally via Whisper WASM
- RSS reader — subscribe to feeds and auto-capture articles
- All features unlocked — Clear instance means no tier restrictions
Backups
Your entire Glassy state is in two places: the SQLite database file and the uploaded files directory,
both inside the /data volume.
To back up:
docker compose exec glassy sqlite3 /data/glassy.db ".backup '/data/backup.db'"
docker cp $(docker compose ps -q glassy):/data ./glassy-backup Or simply snapshot the volume. The database is a single file — you can copy it while the container is running using SQLite's online backup.
Updating
docker compose pull
docker compose up -d Glassy runs migrations automatically on startup. Pull the new image and restart. That is it.
Why self-host?
The hosted Glassy at `app.glassy.fyi` works great for most users. But self-hosting makes sense when:
- Your content is regulated (HIPAA, GDPR data residency, attorney-client privilege)
- You want the MCP server accessible from your internal network only
- You run a homelab and prefer owning your infrastructure
- You want storage without tier limits
- You are a Clear subscriber and want the self-hosted experience
The Docker image is the same one that runs the hosted service. No feature gating, no telemetry, no phone-home. Your Glassy, your server, your data.