Skip to content

Commit 4f2376a

Browse files
authored
Merge pull request #68 from libredb/dev
fix(docker): writable data volume for non-root user (0.9.22) + Railway template docs
2 parents 564414d + d59ed4e commit 4f2376a

9 files changed

Lines changed: 199 additions & 52 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,4 @@ npmjs-token
103103
.npmrc
104104

105105
.token
106+
.sonar-token

Dockerfile

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,17 @@ COPY --from=builder /usr/src/app/node_modules/file-uri-to-path ./node_modules/fi
6464
RUN addgroup --system --gid 1001 nodejs && \
6565
adduser --system --uid 1001 nextjs && \
6666
chown -R nextjs:nodejs /app
67-
USER nextjs
67+
68+
# gosu lets the entrypoint drop from root to the app user after fixing the
69+
# permissions of a mounted (often root-owned) data volume.
70+
RUN apt-get update && apt-get install -y --no-install-recommends gosu && \
71+
rm -rf /var/lib/apt/lists/*
72+
73+
# Entrypoint makes the SQLite data dir writable by `nextjs` then drops privileges.
74+
# The container starts as root only long enough to chown the volume mount; the
75+
# app process itself runs as the non-root `nextjs` user.
76+
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
77+
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
6878

6979
# Render uses PORT env variable, default to 3000
7080
EXPOSE 3000/tcp
@@ -73,4 +83,5 @@ ENV HOSTNAME="0.0.0.0"
7383

7484
# server.js is created by next build from the standalone output
7585
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
86+
ENTRYPOINT ["docker-entrypoint.sh"]
7687
CMD ["node", "server.js"]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ Deploy your own instance of LibreDB Studio with a single click on Koyeb, Render,
359359
[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?name=libredb-studio&type=docker&image=ghcr.io%2Flibredb%2Flibredb-studio%3Alatest&instance_type=free&regions=fra&instances_min=0&autoscaling_sleep_idle_delay=3900&env%5BADMIN_EMAIL%5D=admin%40libredb.org&env%5BADMIN_PASSWORD%5D=LibreDB.2026&env%5BJWT_SECRET%5D=your_secure_pass%3D&env%5BLLM_API_KEY%5D=your_GEMINI_API_KEY&env%5BLLM_MODEL%5D=gemini-2.5-flash&env%5BLLM_PROVIDER%5D=gemini&env%5BNEXT_PUBLIC_AUTH_PROVIDER%5D=local&env%5BSTORAGE_PROVIDER%5D=postgres&env%5BSTORAGE_POSTGRES_URL%5D=postgresql%3A%2F%2Fdb_user%3Adb_pass%40your_host.eu-central-1.pg.koyeb.app%2Flibredb_storage&env%5BUSER_EMAIL%5D=user%40libredb.org&env%5BUSER_PASSWORD%5D=LibreDB.2026&ports=3000%3Bhttp%3B%2F&hc_protocol%5B3000%5D=tcp&hc_grace_period%5B3000%5D=5&hc_interval%5B3000%5D=30&hc_restart_limit%5B3000%5D=3&hc_timeout%5B3000%5D=5&hc_path%5B3000%5D=%2F&hc_method%5B3000%5D=get)
360360
361361
[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/libredb/libredb-studio)
362-
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/new/template/CODE?utm_medium=integration&utm_source=button&utm_campaign=libredb-studio)
362+
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/libredb-studio?referralCode=bGijnc&utm_medium=integration&utm_source=template&utm_campaign=generic)
363363
364364
365365
### Environment Variables

deploy/railway/PUBLISH.md

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,111 @@
11
# Publishing the LibreDB Studio Railway Template
22

3-
A Railway **marketplace template** is built in the visual composer, not from a
4-
repo file. This is the exact checklist to create and publish it. The values to
5-
enter are in [`template.json`](./template.json).
3+
A Railway **marketplace template** is built in the visual template editor, not
4+
from a repo file. This is the exact checklist to create and publish it. The
5+
values to enter are in [`template.json`](./template.json).
66

7-
## 1. Open the composer
7+
## 1. Open the template editor
88

9-
- Go to https://railway.com/compose (or Workspace → **Templates****New Template**).
9+
- Go to your **Workspace → Templates** page: <https://railway.com/workspace/templates>
10+
- Click **New Template**. This opens the template editor (a canvas, like a project).
1011

1112
## 2. Add the Studio service
1213

13-
- Click **Add New → Docker Image**.
14-
- Image: `ghcr.io/libredb/libredb-studio:0.9.19` (pinned — never `:latest`).
14+
- In the editor, click **+ New** (top-right), or open the command palette
15+
(`⌘K` / `Ctrl+K`) → **+ New Service****Docker Image**.
16+
- Image: `ghcr.io/libredb/libredb-studio:0.9.22` (pinned — never `:latest`).
1517
- Rename the service to `libredb-studio`.
1618

17-
## 3. Configure the service (match `template.json`)
18-
19-
- **Variables** tab — add each variable from `template.json`. For the generated
20-
ones, type the function literally:
21-
- `JWT_SECRET` = `${{ secret(48) }}`
22-
- `ADMIN_PASSWORD` = `${{ secret(16) }}`
23-
- `USER_PASSWORD` = `${{ secret(16) }}`
24-
- `ADMIN_EMAIL` = `admin@libredb.org`, `USER_EMAIL` = `user@libredb.org`
25-
- `NEXT_PUBLIC_AUTH_PROVIDER` = `local`
26-
- `STORAGE_PROVIDER` = `sqlite`, `STORAGE_SQLITE_PATH` = `/app/data/libredb-storage.db`
27-
- `PORT` = `3000`
28-
- `LLM_PROVIDER`, `LLM_API_KEY`, `LLM_MODEL`, `LLM_API_URL` = leave blank
29-
- **Settings** tab — enable **Public Networking**, target port `3000`; set
30-
**Healthcheck Path** to `/api/db/health`.
31-
- **Volume** — select the service, open its **Volumes** section, and add a volume with mount path `/app/data`.
32-
33-
## 4. Create the template
19+
## 3. Variables
20+
21+
Fastest path: **Variables → Raw Editor → ENV**, paste the values below, **Update
22+
Variables**, then add a **description** to each (the publish form asks for one).
23+
The `${{ secret(...) }}` values are auto-generated per deploy.
24+
25+
### Pre-configured variables (defaults — entered for the deployer)
26+
27+
| Variable | Value | Description |
28+
|----------|-------|-------------|
29+
| `JWT_SECRET` | `${{ secret(48) }}` | Secret key used to sign login session tokens. Auto-generated — keep it. |
30+
| `ADMIN_EMAIL` | `admin@libredb.org` | Login email for the ADMIN account (full access incl. maintenance tools). |
31+
| `ADMIN_PASSWORD` | `${{ secret(16) }}` | Password for the admin account. Auto-generated; find it in Variables after deploy. |
32+
| `USER_EMAIL` | `user@libredb.org` | Login email for the standard, query-only account. |
33+
| `USER_PASSWORD` | `${{ secret(16) }}` | Password for the standard user. Auto-generated; find it in Variables after deploy. |
34+
| `NEXT_PUBLIC_AUTH_PROVIDER` | `local` | Auth mode: 'local' (email/password). Set 'oidc' for SSO (needs the OIDC_* optional vars). |
35+
| `STORAGE_PROVIDER` | `sqlite` | Server-side storage for saved connections & settings: 'local' (browser only, no server persistence) \| 'sqlite' (file on the volume) \| 'postgres' (multi-node). Keep 'sqlite'. |
36+
| `STORAGE_SQLITE_PATH` | `/app/data/libredb-storage.db` | SQLite file path on the mounted volume (/app/data). Keep the default. |
37+
| `PORT` | `3000` | Port the app listens on. Must match the HTTP Proxy Port. Leave as 3000. |
38+
39+
### Optional variables (add via "+ New Variable" and mark **Optional**)
40+
41+
> ⚠️ Mark each of these **Optional** in the editor. A non-optional variable left
42+
> empty becomes a **required** field the deployer must fill, which breaks the
43+
> one-click flow. Optional vars let people enable AI / SSO / Postgres only if they want.
44+
45+
| Variable | Example | Description |
46+
|----------|---------|-------------|
47+
| `LLM_PROVIDER` | `gemini` | Optional AI query assistance: gemini \| openai \| ollama \| custom. Omit to keep AI off. |
48+
| `LLM_API_KEY` | `AIza… / sk-…` | API key for the chosen AI provider (Gemini/OpenAI). Not needed for a local Ollama. |
49+
| `LLM_MODEL` | `gemini-2.5-flash` | AI model name; provider default used if empty (e.g. gpt-4o-mini, llama3.1). |
50+
| `LLM_API_URL` | `http://host:11434/v1` | Base URL for ollama/custom AI providers only. Not needed for gemini/openai. |
51+
| `OIDC_ISSUER` | `https://tenant.auth0.com` | OIDC issuer URL for SSO. Required when NEXT_PUBLIC_AUTH_PROVIDER=oidc. |
52+
| `OIDC_CLIENT_ID` | | OIDC application client ID (SSO). |
53+
| `OIDC_CLIENT_SECRET` | | OIDC application client secret (SSO). |
54+
| `OIDC_SCOPE` | `openid profile email` | OIDC scopes. Defaults to 'openid profile email' if empty. |
55+
| `OIDC_ROLE_CLAIM` | `realm_access.roles` | Claim path holding user roles, used for admin mapping. |
56+
| `OIDC_ADMIN_ROLES` | `admin` | Comma-separated role values mapped to admin. Defaults to 'admin'. |
57+
| `STORAGE_POSTGRES_URL` | `postgresql://user:pass@host:5432/db` | PostgreSQL URL for multi-node storage. Also set STORAGE_PROVIDER=postgres. |
58+
59+
## 4. Settings (service)
60+
61+
- **Networking** — set **HTTP Proxy Port** to `3000` (enables public HTTP access).
62+
- **Deploy** — set **Healthcheck Path** to `/api/db/health` (Restart Policy
63+
`On Failure` is a sensible default).
64+
- **Volume** — NOT in the Settings panel. Close the settings modal, then on the
65+
editor **canvas right-click the `libredb-studio` service → Attach Volume**, and
66+
set the mount path to `/app/data`.
67+
68+
## 5. Create the template
3469

3570
- Click **Create Template**. Railway gives it an unlisted URL and a unique code
3671
(e.g. `ZweBXA`).
3772

38-
## 5. Smoke-test before publishing
73+
## 6. Smoke-test before publishing
3974

4075
- Deploy the unlisted template into a throwaway project.
4176
- Open the public domain; confirm `/api/db/health` is green and the login page loads.
4277
- Log in as `admin@libredb.org` with the generated `ADMIN_PASSWORD` (Variables tab).
4378
- Add a saved connection, then **Redeploy** the service and confirm the
4479
connection is still there (SQLite volume persistence).
4580

46-
## 6. Publish
81+
## 7. Publish
4782

4883
- Click **Publish** (or Workspace → Templates → **Publish** next to it).
49-
- Fill the form: display name **LibreDB Studio**, the description and tags from
50-
`template.json`, the logo (`libredb-studio.png`), category Database/Developer Tools.
84+
- Fill the form: display name **LibreDB Studio**, a short description (≤75 chars,
85+
e.g. `Open-source web SQL IDE with AI — PostgreSQL, MySQL, Mongo, Redis & more`),
86+
tags from `template.json`, the logo (`libredb-studio.png`), category
87+
Database/Developer Tools.
88+
- **Template Overview** (the long marketplace README field): paste the contents
89+
of [`TEMPLATE_OVERVIEW.md`](./TEMPLATE_OVERVIEW.md).
5190
- Submit. The template is now in the marketplace and eligible for Railway's template kickback (revenue-share) program.
5291

53-
## 7. Wire up the Deploy button
92+
## 8. Wire up the Deploy button
5493

55-
- Copy the template code from the published URL
56-
(`https://railway.com/new/template/<CODE>`).
57-
- Replace `CODE` in:
94+
- After publishing, the marketplace URL has the form
95+
`https://railway.com/deploy/<template-name>?referralCode=<code>` (the
96+
`referralCode` is how Railway attributes deploys/kickbacks to you).
97+
- Put the **Deploy on Railway** button (image `https://railway.com/button.svg`)
98+
with that URL in:
5899
- root `README.md` (the `## ⚡ One-Click Deploy` section)
59100
- `deploy/railway/README.md`
60-
- Commit the change.
101+
- Current published link:
102+
`https://railway.com/deploy/libredb-studio?referralCode=bGijnc&utm_medium=integration&utm_source=template&utm_campaign=generic`
61103

62104
## Maintaining the template
63105

64106
On a new Studio release:
65107

66108
1. Bump the image tag in `deploy/railway/template.json` and
67109
`deploy/railway/README.md`.
68-
2. In the composer / published template, update the image tag and re-publish
69-
(Docker-image templates are **not** auto-updated by Railway).
110+
2. In the template editor / published template, update the image tag and
111+
re-publish (Docker-image templates are **not** auto-updated by Railway).

deploy/railway/README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ This folder is the **source of truth** for deploying LibreDB Studio on
55

66
| File | Purpose |
77
|------|---------|
8-
| `template.json` | Reviewable serialization of the composer service config (image, env vars, volume, healthcheck). Railway does not ingest it directly — see note below. |
8+
| `template.json` | Reviewable serialization of the template service config (image, env vars, volume, healthcheck). Railway does not ingest it directly — see note below. |
99
| `README.md` | This file — install + post-install instructions. |
10-
| `PUBLISH.md` | Step-by-step checklist to create and publish the template in the Railway composer. |
10+
| `PUBLISH.md` | Step-by-step checklist to create and publish the template in Railway's template editor. |
11+
| `TEMPLATE_OVERVIEW.md` | Marketplace overview/README pasted into the publish form's "Template Overview" field. |
1112
| `libredb-studio.png` | 256×256 app logo. |
1213

1314
> **Why no `railway.json` in the repo?** Railway config-as-code only controls how
@@ -17,18 +18,18 @@ This folder is the **source of truth** for deploying LibreDB Studio on
1718
> config file. A `railway.toml` would only cause a redundant rebuild of an image
1819
> CI already publishes.
1920
20-
## Deploy (once published)
21+
## Deploy
2122

22-
Click the button (replace `CODE` with the published template code):
23+
Click the button to deploy from the Railway template marketplace:
2324

24-
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/new/template/CODE?utm_medium=integration&utm_source=button&utm_campaign=libredb-studio)
25+
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/libredb-studio?referralCode=bGijnc&utm_medium=integration&utm_source=template&utm_campaign=generic)
2526

2627
Or browse the Railway template marketplace and search **LibreDB Studio**.
2728

2829
## Deploy (manual — works today, before publishing)
2930

3031
Railway dashboard → **New Project**, then in the project view click **+ New → Docker Image**
31-
enter `ghcr.io/libredb/libredb-studio:0.9.19`, then configure the service to
32+
enter `ghcr.io/libredb/libredb-studio:0.9.22`, then configure the service to
3233
match [`template.json`](./template.json):
3334

3435
- **Networking:** enable a public domain, target port `3000`.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Deploy and Host libredb-studio on Railway
2+
3+
LibreDB Studio is an open-source, web-based SQL IDE for cloud-native teams. Query PostgreSQL, MySQL, SQLite, Oracle, SQL Server, MongoDB, and Redis from your browser — with AI-powered query assistance (natural-language-to-SQL, explain, and fix), an ERD viewer, schema diff, and a data profiler. No desktop client required.
4+
5+
## About Hosting libredb-studio
6+
7+
Hosting LibreDB Studio means running a single stateless Next.js container that serves the web IDE and proxies queries to the databases you connect to. This template runs the prebuilt `ghcr.io/libredb/libredb-studio` image on port 3000 with a healthcheck at `/api/db/health` — no build step required. Saved connections and settings are persisted with SQLite on an attached Railway volume (`/app/data`), so they survive restarts and redeploys. Authentication is JWT-based; a strong `JWT_SECRET` and admin/user passwords are auto-generated per deploy. Optional add-ons — AI providers (Gemini, OpenAI, Ollama, custom), OIDC SSO, or a PostgreSQL storage backend — are enabled later via environment variables.
8+
9+
## Common Use Cases
10+
11+
- Give a team a browser-based SQL console for cloud databases, with no desktop client to install or update.
12+
- Spin up an admin/query UI right next to a Railway PostgreSQL or MySQL database in the same project.
13+
- Use AI assistance to write, explain, and fix SQL across multiple database engines from one interface.
14+
15+
## Dependencies for libredb-studio Hosting
16+
17+
- A database to connect to — PostgreSQL, MySQL, SQLite, Oracle, SQL Server, MongoDB, or Redis (bring your own, or add a Railway database to the project).
18+
- A persistent volume mounted at `/app/data` for the SQLite-backed store of saved connections and settings (included in this template).
19+
20+
### Deployment Dependencies
21+
22+
- Source & docs: https://github.com/libredb/libredb-studio
23+
- Container image (GHCR): https://github.com/libredb/libredb-studio/pkgs/container/libredb-studio
24+
- README / configuration: https://github.com/libredb/libredb-studio#readme
25+
26+
### Implementation Details
27+
28+
After the service is healthy, open its public domain and log in with the **admin** account (`admin@libredb.org`) — the generated `ADMIN_PASSWORD` is shown in the service's **Variables** tab. A standard query-only user (`user@libredb.org`) is also created.
29+
30+
To query a database hosted on Railway, add one to the project (**+ New → Database → PostgreSQL/MySQL**) and create a connection in Studio using the database's provided variables (`PGHOST`, `PGPORT`, `PGUSER`, `PGPASSWORD`, `PGDATABASE`).
31+
32+
Optional environment variables enable extra features:
33+
34+
```bash
35+
# AI query assistance
36+
LLM_PROVIDER=gemini # gemini | openai | ollama | custom
37+
LLM_API_KEY=your_api_key
38+
LLM_MODEL=gemini-2.5-flash
39+
40+
# SSO (OIDC) — Auth0, Keycloak, Okta, Azure AD
41+
NEXT_PUBLIC_AUTH_PROVIDER=oidc
42+
OIDC_ISSUER=https://your-tenant.example.com
43+
OIDC_CLIENT_ID=...
44+
OIDC_CLIENT_SECRET=...
45+
```
46+
47+
## Why Deploy libredb-studio on Railway?
48+
49+
<!-- Recommended: Keep this section as shown below -->
50+
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
51+
52+
By deploying libredb-studio on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
53+
<!-- End recommended section -->

0 commit comments

Comments
 (0)