Documentation
Everything you need to run, configure and contribute to adminer-node.
Quick Start
No installation required. Run directly with npx:
# Runs on http://127.0.0.1:8080 and opens your browser
npx adminer-node
CLI Options
npx adminer-node [options]
--port <port> Port to listen on (default: 8080)
--host <host> Host to bind to (default: 127.0.0.1)
--no-open Do not open browser automatically
--driver <driver> Pre-select driver: mysql | pgsql | sqlite
--help Show help and exit
Installation
npx (recommended)
npx adminer-node
Global install
npm install -g adminer-node
adminer-node
Local project
npm install adminer-node
npx adminer-node
Docker โ Quick Run
docker run -p 8080:8080 javimosch/adminer-node:latest
Open http://localhost:8080 in your browser.
Docker Compose
Save as compose.yml and run docker compose up:
services:
adminer-node:
image: javimosch/adminer-node:latest
ports:
- "8080:8080"
environment:
- PORT=8080
- HOST=0.0.0.0
restart: unless-stopped
To also spin up a local MariaDB:
services:
adminer-node:
image: javimosch/adminer-node:latest
ports: ["8080:8080"]
environment: { HOST: 0.0.0.0, PORT: 8080 }
mariadb:
image: mariadb:11
environment:
MARIADB_ROOT_PASSWORD: secret
MARIADB_DATABASE: mydb
ports: ["3306:3306"]
Build & Push (maintainers)
# Build + push to Docker Hub in one step
npm run deploy
# Individual steps
npm run docker:build
npm run docker:push
npm run docker:run # quick local test
Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT | 8080 | HTTP port the server listens on |
HOST | 127.0.0.1 | Host/interface to bind (0.0.0.0 for Docker) |
MySQL / MariaDB
Select MySQL / MariaDB on the login screen. Connection fields:
- Server โ hostname or IP (e.g.
127.0.0.1ormariadbin Docker Compose) - Username โ database user (e.g.
root) - Password โ database password
- Database โ optional, leave blank to browse all databases
Supported features: browse, edit, create table, alter table, indexes, foreign keys, SQL editor, export dump, variables, process list.
PostgreSQL
Select PostgreSQL on the login screen. Connection fields:
- Server โ
hostname:port(default port5432) - Username โ database role
- Password โ role password
- Database โ PostgreSQL database name
Supported features: schemas, sequences, materialized views, custom types, extensions.
SQLite
Select SQLite on the login screen. The Server field is the file path:
/path/to/database.dbโ open an existing file:memory:โ create a temporary in-memory database
Username and password are not required for SQLite โ leave them blank.
SQL Editor
Navigate to any database and click SQL Command. The editor supports:
- Multi-statement execution (semicolon-separated)
- Result tables for
SELECTqueries - Affected row count for
INSERT/UPDATE/DELETE - Error messages with the failing statement highlighted
Table Browser
Click a table name in the sidebar to browse its data. Features:
- Paginated rows (configurable page size)
- Column sorting (click header)
- Search / filter rows
- Edit / delete individual rows
- Insert new rows
Row Editor
Click Edit on any row to open the row editor. Inputs are type-aware:
ENUM/SETโ rendered as<select>TEXT/BLOBโ rendered as<textarea>DATE/DATETIMEโ rendered as date/datetime inputsBOOLEANโ rendered as checkbox- NULL toggle on every nullable field
Export / Dump
Navigate to a database or table and click Export. Options:
- Format โ SQL (with CREATE TABLE + INSERT) or CSV
- Scope โ full database or individual tables
- Data style โ INSERT, or structure-only (no data)
Security
- AES-256-GCM โ session passwords are encrypted server-side; never stored in plaintext
- CSRF protection โ every mutating request requires a token verified server-side
- Brute-force protection โ IP-based rate limiting on login attempts
- Security headers โ
X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy,Content-Security-Policy - Local-only by default โ server binds to
127.0.0.1; setHOST=0.0.0.0explicitly for Docker/remote access
Config File
adminer-node automatically loads ~/.config/adminer-node/config.json on startup. You can also specify a custom path:
npx adminer-node --config /path/to/config.json
# or via environment variable
ADMINER_CONFIG=/path/to/config.json npx adminer-node
Priority order (highest wins): CLI flags โ environment variables โ config file โ defaults.
Saved Connections
Define connection presets in your config file. They appear as one-click cards on the home screen. The password is stored only on the server โ it is never sent to the browser.
{
"connections": [
{
"id": "prod-mysql",
"label": "Production MySQL",
"driver": "mysql",
"server": "db.example.com",
"username": "app",
"password": "s3cr3t",
"db": "myapp"
},
{
"id": "local-sqlite",
"label": "Dev SQLite",
"driver": "sqlite",
"server": "/home/user/dev.db",
"username": "",
"password": ""
}
]
}
Connection fields:
| Field | Required | Description |
|---|---|---|
id | No | Unique ID for auto-connect API. Defaults to array index. |
label | Yes | Display name shown on the home screen card |
driver | Yes | mysql | pgsql | sqlite |
server | Yes | Host/IP (MySQL/PgSQL) or file path (SQLite) |
username | No | Empty string for SQLite |
password | No | Empty string for SQLite |
db | No | Default database to select after login |
Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT / ADMINER_PORT | 8080 | HTTP port |
HOST / ADMINER_HOST | 127.0.0.1 | Bind host (0.0.0.0 for Docker) |
ADMINER_DRIVER | โ | Pre-select driver on login form |
ADMINER_NO_OPEN=1 | โ | Disable auto browser open |
ADMINER_CONFIG | โ | Path to config JSON file |
ADMINER_CONNECTIONS | โ | JSON array of connection presets |
ADMINER_BASIC_USER | โ | HTTP Basic Auth username |
ADMINER_BASIC_PASS | โ | HTTP Basic Auth password |
Example โ inject connections via environment (useful in CI/CD or Docker Compose):
ADMINER_CONNECTIONS='[{"label":"App DB","driver":"mysql","server":"127.0.0.1","username":"root","password":"secret","db":"app"}]' \
npx adminer-node
HTTP Basic Auth
Add an extra layer of protection when exposing adminer-node on a public URL (e.g. behind a reverse proxy). Basic Auth is checked before the DB login form.
โ ๏ธ Always use HTTPS when enabling Basic Auth on a public URL.
Via config file
{
"basicAuth": {
"username": "admin",
"password": "changeme",
"realm": "My Adminer"
}
}
Via environment variables
ADMINER_BASIC_USER=admin ADMINER_BASIC_PASS=changeme npx adminer-node
The /health endpoint is always exempt from Basic Auth so Docker health checks keep working.
Docker + Pre-configured Connections
Via environment variable
services:
adminer-node:
image: javimosch/adminer-node:latest
ports: ["8080:8080"]
environment:
HOST: 0.0.0.0
ADMINER_BASIC_USER: admin
ADMINER_BASIC_PASS: changeme
ADMINER_CONNECTIONS: '[{"label":"App DB","driver":"mysql","server":"mariadb","username":"root","password":"secret","db":"app"}]'
depends_on: [mariadb]
mariadb:
image: mariadb:11
environment:
MARIADB_ROOT_PASSWORD: secret
MARIADB_DATABASE: app
Via mounted config file
services:
adminer-node:
image: javimosch/adminer-node:latest
ports: ["8080:8080"]
environment:
HOST: 0.0.0.0
ADMINER_CONFIG: /config/adminer-node.json
volumes:
- ./adminer-node.json:/config/adminer-node.json:ro
REST API Reference
All API routes are under /api/. Authenticated routes require a valid session cookie.
| Method | Path | Description |
|---|---|---|
| GET | /api/drivers | List available drivers |
| GET | /api/status | Server status & auth state |
| POST | /api/auth/login | Login (sets session cookie) |
| POST | /api/auth/logout | Logout (clears session) |
| GET | /api/databases | List databases |
| POST | /api/databases | Create database |
| DELETE | /api/databases/:db | Drop database |
| GET | /api/tables/:db | List tables in a database |
| GET | /api/tables/:db/:table/structure | Table fields, indexes, FKs |
| POST | /api/tables/:db | Create table |
| DELETE | /api/tables/:db/:table | Drop table |
| GET | /api/select/:db/:table | Browse rows (paginated) |
| POST | /api/edit/:db/:table | Insert row |
| PUT | /api/edit/:db/:table | Update row |
| DELETE | /api/edit/:db/:table | Delete row |
| POST | /api/sql/:db | Execute SQL statement(s) |
| GET | /api/dump/:db | Export SQL dump |
| GET | /api/variables | Server variables |
| GET | /api/users | List database users (MySQL) |
| GET | /api/connections | List saved connection presets (passwords omitted) |
| POST | /api/connections/:id/connect | Auto-login using a saved preset (password stays server-side) |
| GET | /health | Health check โ always public, used by Docker healthcheck |
Dev Setup
git clone https://github.com/javimosch/adminer-node.git
cd adminer-node
npm install
npm run dev # starts with --watch for hot reload
Architecture
adminer-node is a full-stack Node.js application with zero framework dependencies:
- Server โ
src/server.jsuses Node.js built-inhttpmodule with a custom router (src/router.js) - Auth โ
src/auth.jshandles sessions, CSRF tokens and brute-force protection - Drivers โ
src/drivers/{mysql,pgsql,sqlite}.jsimplement a commonBaseDriverinterface - API handlers โ
src/api/*.jsone file per feature domain - Frontend โ
public/app/โ Vue 3 components loaded via CDN importmap, hash-based routing, no bundler - Styling โ Tailwind CSS + DaisyUI via CDN, dark theme by default
Every file is kept under 500 lines of code for maintainability.
Contributing
Contributions are welcome! Please open an issue or pull request on GitHub.
- Follow the existing file structure and 500 LOC limit per file
- Add new drivers in
src/drivers/extendingBaseDriver - Add new API routes in
src/api/and register insrc/server.js - Add new views in
public/app/views/and register inpublic/app/router.js