I couldn't find any guide to self-host Drizzle Studio, so I figured it out myselfβand now I'm sharing it with you pals. Here is a step-by-step guide to host Drizzle Studio with:
- π Basic Auth
- π HTTPS using Let's Encrypt
- π§ UI served at
/studio/ - β No CORS issues
- π API served from the same origin
Install the following dependencies:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejssudo npm i -g pm2sudo apt install nginxsudo apt install certbot python3-certbot-nginxsudo apt install apache2-utilsSet an A record in your DNS provider (e.g., Cloudflare, Namecheap):
example.com β YOUR_SERVER_IP
or you can bypass any external DNS/CDN and test directly against your origin
echo "127.0.0.1 example.com" | sudo tee -a /etc/hosts
pm2 start "npx drizzle-kit studio --host 127.0.0.1 --port 4983" \
--name drizzle-studio --interpreter bash
pm2 saveTest it locally:
curl -k https://127.0.0.1:4983/init
# Expected: 404 or small JSONsudo htpasswd -c /etc/nginx/.htpasswd studioadminEnter and confirm a password.
sudo certbot --nginx -d example.comCertificates will be stored at:
/etc/letsencrypt/live/example.com/
# 0) HTTP β HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
# 1) HTTPS (UI + API, same origin, Basic-Auth)
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# ---------- Basic-Auth ----------
auth_basic "Drizzle Studio";
auth_basic_user_file /etc/nginx/.htpasswd;
# DNS for local.drizzle.studio (used by proxy_pass)
resolver 1.1.1.1 8.8.8.8 ipv6=off valid=60s;
# βββββββββββββββββββββββββββββββββ UI βββββββββββββββββββββββββββ
# A) root path β GET/HEAD redirect, everything else β back-end
location = / {
if ($request_method ~ ^(GET|HEAD)$) {
return 302 /studio/?host=$host&port=443;
}
# POST /, OPTIONS / β¦ β Drizzle back-end
proxy_pass http://127.0.0.1:4983;
include snippets/drizzle-proxy-headers.conf;
}
# B) every /studio/** file β CDN
location ^~ /studio/ {
rewrite ^/studio/(.*)$ /$1 break; # strip /studio/ prefix
proxy_pass https://local.drizzle.studio;
include snippets/drizzle-cdn-headers.conf;
}
# C) Cloudflare RUM ping
location ^~ /cdn-cgi/ {
proxy_pass https://local.drizzle.studio;
include snippets/drizzle-cdn-headers.conf;
}
# βββββββββββββββββββββββββββββ API βββββββββββββββββββββββββββββ
# everything NOT /studio/** and NOT /cdn-cgi/** β back-end
location / {
proxy_pass http://127.0.0.1:4983;
include snippets/drizzle-proxy-headers.conf;
}
}proxy_ssl_verify off;
proxy_ssl_server_name on;
proxy_ssl_name local.drizzle.studio;
proxy_set_header Host local.drizzle.studio;proxy_ssl_verify off;
proxy_ssl_server_name on;
proxy_ssl_name local.drizzle.studio;
proxy_http_version 1.1;
proxy_set_header Host local.drizzle.studio;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";sudo ln -s /etc/nginx/sites-available/drizzle.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx- Open an incognito tab
- Visit
https://example.com - Enter Basic Auth credentials
- You should be redirected to:
https://example.com/studio/?host=example.com&port=443 - The Studio UI should appear
| Problem | Fix |
|---|---|
502 Bad Gateway |
Drizzle Studio not running, wrong port, or missing proxy_ssl_* |
| Redirect loop | Only GET/HEAD on / should redirect. Others must proxy. |
| MIME error for JS | Ensure /studio/** proxies to CDN, not redirected |
Requests to localhost:4983 |
Clear browser local storage, ensure URL has ?host=example.com |
- Only expose Studio with at least Basic Auth or IP allow-list
- Keep port 4983 bound to 127.0.0.1
- Certbot auto-renews your certs via systemd timer
Your Drizzle Studio OSS is now available at:
https://example.com/studio/?host=example.com&port=443