Explore, edit, and investigate data faster and more securely with a better database tool
Get started: Self-hostable version (great for teams) | Desktop app version (great for personal use)
Backdoor is a database querying and editing tool for you and your team.
- π₯ Easy to setup: -- Takes minutes to set up for you and your team to edit, explore, and investigate data quickly.
- π΅ Cost Saving: -- Reduces the need to build an admin dashboard. Saves weeks and months in effort.
- π Secure: -- Supports masked users, so you don't have to share the database credentials. The best security practices are implemented e.g. encrypted cookies with AES-256 and proof-of-work captcha.
- β¨ Modern UI: -- Exploring and investigating large data is a breeze and enjoyable. Offers modern UI with infinitely scrollable table.
![]() |
![]() |
![]() |
|---|---|---|
![]() |
![]() |
![]() |
| Database | Status |
|---|---|
| PostgreSQL | β Supported |
| ClickHouse | β Supported |
| SQLite | β Supported |
| DuckDB | π Coming Soon |
| MySQL | π Coming Soon |
| Oracle | π Coming Soon |
| MS SQL Server | π Coming Soon |
| IBM DB2 | π Coming Soon |
| MariaDB | π Coming Soon |
| Platform | Direct Download | App Store |
|---|---|---|
| MacOS (Apple Silicon) | π’ Link | |
| Windows | π’ Link | |
| Linux | π‘ In Progress | N/A |
| MacOS (Intel) | π Coming Soon | π Coming Soon |
Please see our Privacy Policy
There are 3 ways:
- Run as a standalone: JAR file, Docker, and Render.com.
- Embed into your Java application and serve on a specific port.
- Embed into your Java application and serve on your main port but at a specific path.
Backdoor is based on Embeddable Java Web Framework and published as a fat jar. Therefore, there is no external dependency. Its jar is self-contained and suitable for embedding into your JVM application.
Use Docker
The docker image is here: https://hub.docker.com/repository/docker/tanin47/backdoor
docker run -p 9999:9999 \
--entrypoint "" \
--pull always \
tanin47/backdoor:web-2.7.0 \
java -jar backdoor-2.7.0.jar \
-port 9999 \
-url "postgres://127.0.0.1:5432/backdoor_test,jdbc:ch://localhost:8123?user=backdoor&password=test_ch" \
-secret-key SbZlbmJIXh \
-user test_user:test_pass,another_user:another_pass
Run from the JAR file
First, you can download the backdoor-VERSION.jar file from
the Maven Central page.
Then, you can run the command below:
java -jar backdoor-2.7.0.jar \
-port 9999 \
-url "postgres://127.0.0.1:5432/backdoor_test,jdbc:ch://localhost:8123?user=backdoor&password=test_ch" \
-secret-key SbZlbmJIXh \
-user test_user:test_pass,another_user:another_pass
You can visit http://localhost:9999 and login with a Postgres user, a ClickHouse user, or a masked user (e.g.
test_user and another_user).
See FAQ for how authentication works.
Use Render.com
The file render.yaml shows a blueprint example of how to run Backdoor on Render.
Add the dependency to your project:
<dependency>
<groupId>io.github.tanin47</groupId>
<artifactId>backdoor</artifactId>
<version>2.7.0</version>
</dependency>
Then, initialize Backdoor when your Java application starts:
var server = new BackdoorServerBuilder()
.addDatabaseConfig("postgres", "postgres://127.0.0.1:5432/backdoor_test", null, null)
.addDatabaseConfig("clickhouse", "jdbc:ch://localhost:8123", "backdoor", "test_ch")
.withPort(9999)
.withSecretKey("SbZlbmJIXh")
.addUser("test_user", "test_pass")
.addUser("another_user", "another_pass")
.build();
server.start();
Then, when your Java application stops, make sure to stop Backdoor with:
server.stop();
First, you must follow the steps above in order to serve Backdoor at a specific internal port.
Then, you can designate a specific path and use the below code to proxy requests to Backdoor:
var client = HttpClient.newHttpClient();
var httpRequest = HttpRequest
.newBuilder()
.uri(URI.create("http://localhost:9999" + path))
.method("GET", HttpRequest.BodyPublishers.ofByteArray(new byte[0])) // Set the method and body in bytes
.headers(/* ... */) // Forward the headers as-is.
.build();
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofByteArray());
The above code uses the HTTP client offered by Java. It doesn't require any external dependency.
- Support multi-databases.
- Edit a field, delete a row, sort, and filter
- Rename and drop table
- Run arbitrary SQLs
- Activity history (through regular logs).
- Support its own users, so you don't have to share the database credentials.
- Support database users e.g. logging in with Postgres or ClickHouse users.
While Backdoor comes with strong security limiting the session lengths and deterring brute-force attacks through a Proof-of-Work Captcha through altcha, you can add more layers of security. Here are 2 more ways:
You can block your port using a firewall and use SSH tunneling to allow you to connect to a Backdoor instance.
You can run: ssh -L <local_port>:<remote_backdoor_host>:<remote_backdoor_port> <user>@<ssh_server> and visit:
http://localhost:<local_port> to access Backdoor.
Your company might already use VPN. It's a great option to connect to a server that hosts a Backdoor instance.
The setup might be complicated and overkilled, so I'd recommend using this option if your company already have a VPN. Tailscale is one example that provides a company VPN.
Backdoor supports masked users and database users.
- Masked users are the users you set on Backdoor through
BackdoorServerBuilder.addUser(..)or-user. - Database users are the users that you set on the databases e.g. Postgres users, ClickHouse users.
These 2 types of users work in conjunction with the database configurations as follows:
- Any 2 type of users can login into the dashboard.
- Any logged-in user can access any database whose config contains valid credentials.
- If a database config doesn't contain credentials, then the logged-in user can click on the "locked" database to provide valid credentials for that database.
With these combinations, you can configure the authentication to fit your needs.
For simplicity, I'd recommend using masked users and providing valid credentials in all database configurations.
Backdoor uses java.util.logging. The default logging config is at
./src/main/java/resources/backdoor_default_logging.properties.
If you have your own log config file, you can load it using:
try (var configFile = YourClass.class.getResourceAsStream("/YOUR_LOG_CONFIG_FILE")) {
LogManager.getLogManager().readConfiguration(configFile);
logger.info("The log config) has been loaded.");
} catch (IOException e) {
logger.warning("Could not load the log config file: "+e.getMessage());
}
- Run
npm installto install all dependencies. - Change the target database URL in
tanin.backdoor.BackdoorServier.main(..) - Run
./gradlew runin order to run the web server. - On a separate terminal, run
npm run hmrin order to hot-reload the frontend code changes.
- Run
./setup/setup_db.shin order to set the postgres database. - Set up the ClickHouse instance as follows:
- The HTTP port is 8123
- The database
backdoor_testis created. - The username is
backdoor_test. - The password is
test_ch
- Run
npm installto install all dependencies. - On a separate terminal, run
npm run hmr. - Run
./gradlew testin order to run all the tests.
This flow has been set up as the Github Actions workflow: publish-jar.
- Run
./gradlew clean publish. It is IMPORTANT to include clean.
The far JAR is built at ./build/libs/backdoor-VERSION.jar
You can run your server with: java -jar ./build/libs/backdoor-VERSION.jar
To publish to a Maven repository, please follow the below steps:
- Set up
~/.jreleaser/config.tomlwithJRELEASER_MAVENCENTRAL_USERNAMEandJRELEASER_MAVENCENTRAL_PASSWORD - Run
./gradlew jreleaserDeploy
This flow has been set up as a part of the Github Actions workflow: create-release-web.
- Run
docker buildx build --platform linux/amd64,linux/arm64 -t backdoor:web-2.7.0 . - Test locally with:
docker run -p 9090:9090 --entrypoint "" backdoor:web-2.7.0 java -jar backdoor-2.7.0.jar -port 9090 - Run:
docker tag backdoor:web-2.7.0 tanin47/backdoor:web-2.7.0 - Run:
docker push tanin47/backdoor:web-2.7.0 - Go to Render.com, sync the blueprint, and test that it works
- Create an empty release with a new tag. The tag must follow the format:
web-X.Y.Z. - Go to Actions and wait for the
create-release-web(which is triggered automatically) workflow to finish. - Test the docker with
docker run -p 9090:9090 --entrypoint "" tanin47/backdoor:web-2.7.0 java -jar backdoor-2.7.0.jar -port 9090. - Go to Actions and trigger the workflow
publish-web-jaron the tagweb-X.Y.Zin order to publish the JAR to Central Sonatype.
- Create an empty release with a new tag. The tag must follow the format:
desktop-X.Y.Z. - Go to Actions and wait for the
create-release-desktop(which is triggered automatically) workflow to finish. - Download the DMG and test it locally.
- Go to Actions and trigger the workflow
publish-desktop-testflighton the tagdesktop-X.Y.Zin order to publish the JAR to Central Sonatype.






