Deployment guide

H2 Database

Overview

This guide covers the deployment and configuration of H2 Database Engine on Ubuntu 24.04 on Azure, using SecureAnyCloud Azure Marketplace images. H2 is a fast, compact relational database written entirely in Java. This image runs H2 as a server. One JVM (org.h2.tools.Server) exposes an H2 TCP server for JDBC clients and the built-in H2 Web Console for interactive SQL.

H2 is dual licensed under the Mozilla Public License 2.0 or the Eclipse Public License 1.0.

The image installs the official h2-2.4.240.jar (pinned and sha256-verified) from Maven Central and runs it as the unprivileged h2 system user. Both the TCP server and the Web Console bind to loopback only and are never exposed directly to the network. nginx on port 80 fronts the console with HTTP Basic Auth.

At first boot, h2-database-firstboot.service generates three secrets that are unique to each VM: the nginx console password, the H2 sa database password, and the console web admin password. It then creates the application database, proves the whole gate, and writes the secrets to /root/h2-database-credentials.txt (mode 0600, root only). There is no default or blank login baked into the image.

What you get:

  • H2 Database Engine 2.4.240 (official h2-2.4.240.jar, pinned and sha256-verified from Maven Central)
  • h2.service systemd unit running one JVM with the H2 TCP server (127.0.0.1:9092) and Web Console (127.0.0.1:8082), bound to loopback with a hardened service sandbox and -ifExists so that only existing databases may be opened
  • h2-database-firstboot.service systemd oneshot that generates the per-VM console, sa and web admin passwords, creates the application database, proves the authentication gate and a full SQL round trip, and writes /root/h2-database-credentials.txt
  • nginx on port 80 reverse proxying to the loopback-bound Web Console, with HTTP Basic Auth and an unauthenticated /healthz for load balancer probes
  • An application database appdb with a small sample CUSTOMERS table, so the console has content to explore on first boot
  • Ubuntu 24.04 LTS base, patched at build time
  • Azure Linux Agent for cloud integration and SSH key injection
  • 24/7 SecureAnyCloud support with a guaranteed 24 hour response SLA

Prerequisites

  • An active Azure subscription, an SSH public key, and a VNet plus subnet in the target region
  • A subscription to the H2 Database Engine on Ubuntu 24.04 listing on Azure Marketplace

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for evaluation, development and test workloads. For heavier use, raise the JVM heap in /etc/systemd/system/h2.service and choose Standard_D2s_v5 or larger.

1

Deploy from the Azure Portal

Search for H2 Database in Marketplace, select the SecureAnyCloud publisher entry, and click Create.

Configure the network security group (NSG) rules to allow TCP 22 from your management IP and TCP 80 from your client IPs. The H2 TCP server and Web Console are bound to loopback, so only nginx on port 80 is exposed.

The console is protected by HTTP Basic Auth. For any deployment beyond a private network, put a TLS-terminating reverse proxy in front of port 80, so that credentials and SQL are encrypted in transit.

2

Deploy from the Azure CLI

RG="h2-prod"; LOCATION="eastus"; VM_NAME="h2-01" IMAGE_URN="sac1647283583153:h2-database:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name h2-vnet --address-prefix 10.90.0.0/16 --subnet-name h2-subnet --subnet-prefix 10.90.1.0/24 az network nsg create -g "$RG" --name h2-nsg az network nsg rule create -g "$RG" --nsg-name h2-nsg --name allow-ssh --priority 100 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name h2-nsg --name allow-http --priority 110 \
  --source-address-prefixes "<your-client-cidr>" --destination-port-ranges 80 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:h2-database:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
  --size Standard_B2s --admin-username azureuser --ssh-key-values "$SSH_KEY" \
  --vnet-name h2-vnet --subnet h2-subnet --nsg h2-nsg --public-ip-sku Standard
3

Connect via SSH

ssh azureuser@<vm-ip>

The default administrator account is azureuser. It authenticates with the SSH key that you supplied at deployment.

4

Verify the H2 Service

Confirm that H2 and nginx are running:

systemctl is-active h2 nginx

Both units report active. h2.service runs the single JVM that hosts the TCP server and the Web Console, and nginx fronts the console on port 80.

5

Inspect the Listeners

Confirm that nginx owns the public port while H2 stays on loopback:

sudo ss -tlnp | grep -E ':80 |:8082 |:9092 '

nginx listens on 0.0.0.0:80, while the H2 Web Console (8082) and TCP server (9092) listen on 127.0.0.1 only. They are unreachable from the network except through the authenticated nginx front end.

6

Retrieve the Credentials

The per-VM secrets are generated at first boot and stored in a root-only file:

sudo cat /root/h2-database-credentials.txt

The file shows the console sign-in user and password, the JDBC URL with the sa database user and password, and the console web admin password:

H2_CONSOLE_URL=http://<vm-ip>/ H2_CONSOLE_USERNAME=admin H2_CONSOLE_PASSWORD=<H2_CONSOLE_PASSWORD> H2_JDBC_URL=jdbc:h2:tcp://localhost:9092/appdb H2_DB_USER=sa H2_DB_PASSWORD=<H2_DB_PASSWORD> H2_WEB_ADMIN_PASSWORD=<H2_WEB_ADMIN_PASSWORD>
7

Verify Access Control over HTTP

The console is reached only through the authenticated nginx proxy, and the database rejects a blank sa password. Confirm all three behaviours:

CP=$(sudo grep '^H2_CONSOLE_PASSWORD=' /root/h2-database-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'no creds: %{http_code}\n' http://127.0.0.1/ curl -s -o /dev/null -w 'with console password: %{http_code}\n' -u "admin:$CP" http://127.0.0.1/
JAR=$(ls /opt/h2/h2-*.jar) java -cp "$JAR" org.h2.tools.Shell -url jdbc:h2:tcp://localhost:9092/appdb -user sa -password '' -sql 'SELECT 1' 2>&1 | grep -m1 -o 'Wrong user name or password.*' || true

The unauthenticated request returns 401, the authenticated console returns 200, and the blank sa password is rejected with Wrong user name or password [28000-240]. The unauthenticated /healthz endpoint stays open for load balancer probes.

8

Query the Database from the Command Line

Use the bundled H2 Shell tool with the per-VM sa password to query the sample table:

DBPW=$(sudo grep '^H2_DB_PASSWORD=' /root/h2-database-credentials.txt | cut -d= -f2-)
JAR=$(ls /opt/h2/h2-*.jar) java -cp "$JAR" org.h2.tools.Shell -url jdbc:h2:tcp://localhost:9092/appdb -user sa -password "$DBPW" \
  -sql 'SELECT ID, NAME, EMAIL FROM CUSTOMERS ORDER BY ID;'

The sample CUSTOMERS table returns three rows. The same JDBC URL and the sa password connect any application running on the VM.

9

Open the H2 Web Console

Open http://<vm-ip>/ from your workstation. The NSG must allow TCP 80. Your browser prompts for HTTP Basic Auth. Sign in with user admin and the H2_CONSOLE_PASSWORD from the credentials file.

The H2 login form appears. Enter the JDBC URL jdbc:h2:tcp://localhost:9092/appdb, the user sa, and the H2_DB_PASSWORD, and then click Connect:

10

Explore the Console

Once connected, the console shows the schema tree on the left (the appdb database, the CUSTOMERS table, INFORMATION_SCHEMA and Users) and the SQL editor on the right, with the H2 version and sample commands:

11

Run a Query

Type a SQL statement into the editor and press Run (or Ctrl+Enter). The result grid appears below the editor:

12

Explore the Schema

Expand a table in the schema tree to inspect its columns and types without writing any SQL:

13

Connect Your Application over JDBC

The H2 TCP server is bound to loopback for safety. An application running on the same VM connects directly with the JDBC URL jdbc:h2:tcp://localhost:9092/appdb, the user sa, and the per-VM password.

To reach the database from your workstation, forward the port over SSH rather than exposing it:

ssh -L 9092:127.0.0.1:9092 azureuser@<vm-ip>

Then point a local JDBC client at jdbc:h2:tcp://localhost:9092/appdb. For a production application tier, open TCP 9092 in the NSG restricted to your application subnets only. Prefer a TLS terminator in front of the console on port 443.

14

Server Components

h2.service runs org.h2.tools.Server as the h2 user with -Dh2.bindAddress=127.0.0.1, -tcp -tcpPort 9092, -web -webPort 8082, -baseDir /var/lib/h2/data and -ifExists. Both servers accept only local connections.

h2-database-firstboot.service is a oneshot that generates the per-VM secrets, creates appdb with the sa password, sets the console web admin password in /var/lib/h2/.h2.server.properties, seeds the nginx Basic Auth file, and proves the gate before it writes the sentinel /var/lib/sac/data/h2-database-firstboot.done.

nginx listens on port 80, serves an unauthenticated /healthz, and reverse-proxies everything else to 127.0.0.1:8082 behind HTTP Basic Auth (/etc/nginx/.h2.htpasswd, bcrypt, user admin).

The database files live in /var/lib/h2/data.

15

Managing the Service

systemctl status h2
sudo systemctl restart h2
sudo journalctl -u h2 -n 50 --no-pager

To change the JVM heap, edit ExecStart in /etc/systemd/system/h2.service, and then run sudo systemctl daemon-reload && sudo systemctl restart h2.

16

Security Recommendations

Keep the servers on loopback. Do not add -webAllowOthers or -tcpAllowOthers to h2.service. The Web Console can connect to arbitrary JDBC URLs and read files, so it must never be exposed to the network directly. nginx plus the per-VM Basic Auth password is the only front door.

Add TLS. Put a TLS-terminating reverse proxy (or nginx with a certificate) in front of port 80 on 443, so that the console password and SQL are encrypted in transit.

Restrict the NSG. Allow TCP 22 and TCP 80 only from the addresses that need them. If you must reach JDBC from outside the VM, open TCP 9092 only to your application subnets.

Rotate secrets. The per-VM passwords in /root/h2-database-credentials.txt are unique to this VM. To rotate them, change the sa password with ALTER USER SA SET PASSWORD '...', update the nginx password with sudo htpasswd -B /etc/nginx/.h2.htpasswd admin, and reset the console web admin password from the console Preferences page.

17

Support and Licensing

H2 Database Engine is dual licensed under the Mozilla Public License 2.0 or the Eclipse Public License 1.0. This image bundles the unmodified official h2-2.4.240.jar from Maven Central. SecureAnyCloud provides the packaging, hardening and first boot automation, plus 24/7 support with a guaranteed 24 hour response SLA.

This listing is not affiliated with or endorsed by the H2 project.

Deploy on Azure

Find H2 Database Engine on Ubuntu 24.04 LTS on the Azure Marketplace by SecureAnyCloud, or visit secureanycloud.com for the full catalogue.

Need Help?

Email sales@secureanycloud.com for deployment help, JDBC integration questions or anything else. SecureAnyCloud support responds within 24 hours.

Deploy on Azure

Launch H2 Database Engine on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure