CUBRID
Overview
CUBRID is an open-source relational database management system built for high-concurrency transactional workloads. Its SQL is deliberately compatible with Oracle and MySQL, so much existing SQL, tooling and application code moves across with little or no rewriting. It ships with native drivers for JDBC, ODBC, PHP, Python, Ruby, Perl and C.
The SecureAnyCloud image delivers CUBRID 11.4.6 (build 11.4.6.1963) on Ubuntu 24.04. It generates a unique DBA password on the first boot of your VM and keeps the database closed to the network. It is backed by 24/7 SecureAnyCloud support.
What you get:
- CUBRID 11.4.6.1963 from the official vendor download channel, pinned and verified by both the vendor's published MD5 and a SHA-256 recorded when this image was built.
- A durable database area at
/var/lib/cubrid/databases, owned by the unprivilegedcubridservice account and kept outside the software tree. - A per-VM DBA password written to
/root/cubrid-credentials.txt, readable only by root. - The database ports closed to the network by a packet filter, with SSH as the only way in.
- On-VM self-tests that prove the security posture at any time.
Network exposure
The database is not reachable from outside your VM as shipped. This is deliberate, and it follows from two properties of CUBRID itself.
First, CUBRID offers no way to bind its listeners to a particular address. Both the master process and the broker bind all interfaces, and no configuration parameter changes that. Second, the port that its command-line client uses, 1523, carries traffic in the clear.
CUBRID does have a broker TLS option, but it does not complete a standard TLS handshake. The only certificate it ships has a private key that is published in the upstream source repository, and it offers no minimum-protocol setting.
So this image closes both database ports at the instance rather than publish a port that cannot be properly secured. It gives you an SSH tunnel as the remote path, which provides modern, verified encryption.
Step 8 shows the tunnel. Step 11 shows how to open the port directly if your deployment genuinely calls for it.
Default credentials
A stock CUBRID database is created with two accounts, DBA and PUBLIC, and both have an empty password. PUBLIC is the more dangerous of the two, because it is the account the client uses when you do not name one. A stock database therefore admits anyone who types nothing.
This image never creates the accounts that way. No database exists in the image. On your VM's first boot, a database is created with a password generated for that instance, set at the moment the account catalogue is created.
The CUBRID tool that does this reports success even when it fails. For that reason, first boot proves on the live database that an empty password is refused, and refuses to finish if it is not.
Prerequisites
- An Azure subscription.
- SSH access to the VM (port 22). This is also how you reach the database.
- The CUBRID drivers on your application host, if you plan to connect an application.
Deploy from the Azure Marketplace
Search the Azure Marketplace for CUBRID Database on Ubuntu 24.04 LTS by SecureAnyCloud. Choose Standard_B2ms or larger, and allow inbound port 22.
CUBRID's stock configuration asks for a 512 MB data buffer and a 256 MB log buffer, so Standard_B2ms (2 vCPU, 8 GiB) gives real headroom. Move up to the memory-optimised sizes as your working set grows.
Deploy from the Azure CLI
Create the VM from the command line. Replace the example resource group and VM name with your own:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:cubrid-ubuntu-24-04:default:latest
az vm create \
--resource-group my-resource-group \
--name my-cubrid \
--image sac1647283583153:cubrid-ubuntu-24-04:default:latest \
--size Standard_B2ms \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardNo extra ports are needed. You reach the database through the SSH connection you already have.
Retrieve this instance's DBA password
Every VM launched from this image generates its own credentials on first boot and writes them to a root-only file. Nothing is shared between deployments. Read the file:
sudo cat /root/cubrid-credentials.txtThe file shows the DBA user, its password, the database name and this VM's public address.
The PUBLIC account was given the same per-instance password at creation, so it is not an unauthenticated way in. If your application does not use it, give it its own password or revoke it.
Confirm the database is running
Check that the services are active and print the server version:
systemctl is-active cubrid nftables
sudo -u cubrid env CUBRID=/opt/cubrid LD_LIBRARY_PATH=/opt/cubrid/lib /opt/cubrid/bin/cubrid_rel | head -2Both units report active and the server reports CUBRID 11.4.6 (11.4.6.1963-0e7d3c1).
Then check what is listening and what is reachable:
sudo ss -Hltn | awk '{print $4}' | sort -u sudo nft list table inet sac_cubridCUBRID listens on 1523 and 30000, but the packet filter drops both from anywhere except this VM itself. Only 22 is open to the network.
Run SQL on the VM
The image ships a small helper that runs SQL as DBA with this instance's own password. The helper reads the password from the root-only credentials file, so it never appears on a command line, where it would land in the shell history and the process list.
sudo /usr/local/sbin/cubrid-sql.sh "SELECT 'connected' AS status, CURRENT_USER AS whoami FROM db_root;"To use CUBRID's own csql client directly, run it as the service account with its environment set. Substitute the password from Step 3:
sudo -u cubrid env CUBRID=/opt/cubrid CUBRID_DATABASES=/var/lib/cubrid/databases \
LD_LIBRARY_PATH=/opt/cubrid/lib:/opt/cubrid/cci/lib PATH=/opt/cubrid/bin:/usr/bin:/bin \
/opt/cubrid/bin/csql -C -u dba -p "<CUBRID_DBA_PASSWORD>" cubriddbcsql has no password file and no password environment variable, so -p is the only non-interactive way to supply a password. It scrubs the value out of its own process listing, but the value still reaches your shell history. This is why the cubrid-sql.sh helper above exists.
Create a table and insert data
CUBRID uses standard SQL for schema definition. Create the table:
sudo /usr/local/sbin/cubrid-sql.sh " DROP TABLE IF EXISTS quarterly_sales; CREATE TABLE quarterly_sales ( id INTEGER PRIMARY KEY, sold_at DATE, region VARCHAR(32), product VARCHAR(64), qty INTEGER, amount DECIMAL(12,2) );"Insert six rows:
sudo /usr/local/sbin/cubrid-sql.sh " INSERT INTO quarterly_sales VALUES (1, DATE'2026-01-15', 'EMEA', 'widget', 10, 199.50); INSERT INTO quarterly_sales VALUES (2, DATE'2026-01-16', 'AMER', 'widget', 4, 79.80); INSERT INTO quarterly_sales VALUES (3, DATE'2026-01-16', 'EMEA', 'gadget', 7, 349.00); INSERT INTO quarterly_sales VALUES (4, DATE'2026-02-02', 'APAC', 'widget', 12, 239.40); INSERT INTO quarterly_sales VALUES (5, DATE'2026-02-11', 'EMEA', 'gadget', 3, 149.55); INSERT INTO quarterly_sales VALUES (6, DATE'2026-02-19', 'AMER', 'sprocket', 20, 880.00);"Confirm that the rows landed:
sudo /usr/local/sbin/cubrid-sql.sh "SELECT COUNT(*) AS rows_loaded FROM quarterly_sales;"Run a query
Run an aggregation with a window function over it. This is the kind of standard SQL that moves across from Oracle or MySQL unchanged:
sudo /usr/local/sbin/cubrid-sql.sh " SELECT region, SUM(amount) AS revenue, SUM(qty) AS units, RANK() OVER (ORDER BY SUM(amount) DESC) AS rnk FROM quarterly_sales GROUP BY region ORDER BY revenue DESC;"AMER totals 959.80, EMEA 698.05 and APAC 239.40.
Transactions behave as you would expect. Pass -n to run the statements in one transaction that is not auto-committed, so the ROLLBACK is meaningful. Autocommit is a csql setting rather than a SQL statement, so SET AUTOCOMMIT OFF will not do it:
sudo /usr/local/sbin/cubrid-sql.sh -n " INSERT INTO quarterly_sales VALUES (99, DATE'2026-03-01', 'EMEA', 'probe', 1, 1.00); ROLLBACK; SELECT 'ROLLBACK_DISCARDED' AS verdict FROM db_root WHERE NOT EXISTS (SELECT 1 FROM quarterly_sales WHERE id = 99);"The row is gone, so the query returns ROLLBACK_DISCARDED.
Connect an application over an SSH tunnel
The SSH tunnel is the supported remote path. From your workstation, forward the broker port over SSH and point your application at localhost:
ssh -L 30000:127.0.0.1:30000 azureuser@<CUBRID_PUBLIC_IP>With the tunnel open, a JDBC application connects to the database as if it were local:
jdbc:cubrid:127.0.0.1:30000:cubriddb:dba:<CUBRID_DBA_PASSWORD>:A Python application that uses the CUBRID driver connects the same way:
import CUBRIDdb conn = CUBRIDdb.connect('CUBRID:127.0.0.1:30000:cubriddb:::', 'dba', '<CUBRID_DBA_PASSWORD>') cur = conn.cursor() cur.execute("SELECT region, SUM(amount) FROM quarterly_sales GROUP BY region") print(cur.fetchall())SSH encrypts everything on that connection, and no database port is exposed to the network.
Verify the security posture
The image ships self-tests that you can re-run at any time. Each check is first proven against a known-bad input, so a check that always passes cannot go unnoticed. Run them all:
sudo /usr/local/sbin/cubrid-selftest.shOr run the checks individually:
sudo /usr/local/sbin/cubrid-port-check.sh
sudo /usr/local/sbin/cubrid-daemon-check.sh
sudo /usr/local/sbin/cubrid-verify-auth.sh /root/cubrid-credentials.txtcubrid-verify-auth.sh confirms that DBA and PUBLIC with empty passwords are both refused, that weak and guessable values are refused, and that this VM's own password returns real rows.
You can also confirm directly that an empty password is refused:
sudo /usr/local/sbin/cubrid-sql.sh -u dba -p "" "SELECT 'should not appear' FROM db_root;" 2>&1 | grep -c "Incorrect or missing password" || trueThe command prints 1, which is CUBRID's own refusal.
The CUBRID Manager administration service can create and delete databases and browse your data. It is never started on this image. Confirm that nothing is listening on its port:
sudo ss -Hltn | awk '{print $4}' | grep -c ':8001$' || trueThe command prints 0.
Back up and restore
cubrid backupdb writes a consistent backup of a running database:
sudo -u cubrid env CUBRID=/opt/cubrid CUBRID_DATABASES=/var/lib/cubrid/databases \
LD_LIBRARY_PATH=/opt/cubrid/lib PATH=/opt/cubrid/bin:/usr/bin:/bin \
/opt/cubrid/bin/cubrid backupdb -D /var/lib/cubrid/databases cubriddb && \
sudo ls -lh /var/lib/cubrid/databases/cubriddb_bk* 2>/dev/null | head -3To restore, stop the database, run cubrid restoredb against the backup, and start the database again. Copy backups off the VM, for example to Azure Blob Storage, as part of your own retention policy.
Open the database port deliberately
If your deployment genuinely needs the broker port reachable from another host, open it in two places: the instance's packet filter and the Azure network security group. Read the caveats first.
Understand what you are exposing. CUBRID's broker traffic is not encrypted unless you enable its own TLS and install your own certificate. The certificate that CUBRID ships has a private key that is published in the upstream source repository, so it protects nothing. Restrict the source address range, and prefer the SSH tunnel in Step 8 wherever you can.
# 1. On the VM: allow the broker port from your address range only.
sudo nft insert rule inet sac_cubrid input ip saddr 203.0.113.0/24 tcp dport 30000 accept
# Make it survive a reboot by adding the same rule to:
# /etc/nftables.d/sac-cubrid.nft
# 2. In Azure: allow it inbound to the VM, again scoped to your range.
az vm open-port --resource-group my-resource-group --name my-cubrid \
--port 30000 --priority 1001
# 3. Permit the client address in CUBRID's own broker ACL, which denies # every remote address by default: # /opt/cubrid/conf/cubrid_broker_acl # then reload:
sudo systemctl restart cubridRotate the DBA password
A password change must refuse a weak value. CUBRID also silently refuses anything over 31 bytes while still reporting success, so the block below checks both conditions before it changes anything.
sudo bash -c ' set -u CREDS=/root/cubrid-credentials.txt OLDPW=$(grep "^CUBRID_DBA_PASSWORD=" "$CREDS" | cut -d= -f2-) reject() { case "$1" in ""|dba|DBA|admin|password|changeme|cubrid) return 0 ;; esac [ ${#1} -lt 16 ] && return 0 [ ${#1} -gt 31 ] && return 0 return 1 } # 1. Weak values, and an over-length value, must all be REFUSED. for candidate in "" "dba" "password" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; do if reject "$candidate"; then echo "REFUSED an unacceptable password as expected" else echo "PROBLEM: an unacceptable password was accepted"; exit 1 fi done # 2. A real rotation with a strong value inside CUBRID s 31-byte limit. NEWPW=$(openssl rand -base64 33 | tr -d "\n/+=" | cut -c1-28) if reject "$NEWPW"; then echo "PROBLEM: generated password judged unacceptable"; exit 1; fi /usr/local/sbin/cubrid-sql.sh "ALTER USER dba PASSWORD '"'"'$NEWPW'"'"';" >/dev/null # 3. Record the new password so the VM stays consistent. sed -i "s|^CUBRID_DBA_PASSWORD=.*|CUBRID_DBA_PASSWORD=$NEWPW|" "$CREDS" # 4. Prove the new credential works. /usr/local/sbin/cubrid-sql.sh "SELECT '"'"'rotated'"'"' AS status FROM db_root;" echo "password rotation complete" 'Clean up the example table
Drop the example table when you are done:
sudo /usr/local/sbin/cubrid-sql.sh "DROP TABLE IF EXISTS quarterly_sales;"Support
SecureAnyCloud provides 24/7 support for this image. We help with deployment, upgrades, network exposure and TLS, schema design, data migration from Oracle and MySQL, backup strategy, query tuning and scaling.
CUBRID is a registered trademark of CUBRID Corporation. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on Azure
Launch CUBRID 11.4.6 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