Deployment guide

SQL Server 2025 Developer

Overview

This image runs Microsoft SQL Server 2025 Developer Edition on Ubuntu 24.04 LTS on the Azure Marketplace. SQL Server is installed from Microsoft's official package repository at packages.microsoft.com, together with the sqlcmd and bcp command-line tools.

On the first boot of every virtual machine, a one-time service gives the sa login a new random password, creates a SecureAnyCloud database and a SecureAnyCloud login, and writes the details to a root-only file. No two virtual machines share an SA password.

This guide was verified on a virtual machine deployed from the public Marketplace image (sac1647283583153:mssql-2025-developer-ubuntu-24-04:default:latest, image version 1.0.20260426), with every command run as azureuser.

Licensing

Microsoft licenses Developer Edition for development and testing only, not for production. There is no product key to enter. The image is ready for development, prototyping, load testing and QA. In SQL Server 2025, Developer Edition reports itself as Enterprise Developer Edition, the Enterprise feature set for non-production use.

To run production workloads, you need your own SQL Server 2025 Standard or Enterprise license. Change the edition with sudo /opt/mssql/bin/mssql-conf set-edition. SQL Server is a trademark of Microsoft Corporation.

What's included

What you get:

  • Microsoft SQL Server 2025 (mssql-server 17.0.4035.5, CU4, on the image version above), running as the mssql-server systemd service
  • mssql-tools18 (18.6.2.1): sqlcmd and bcp in /opt/mssql-tools18/bin, which is on every user's PATH
  • SQL Server listening on TCP port 1433 on all interfaces, with encrypted connections by default (a self-generated certificate)
  • mssql-firstboot.service, which sets the per-VM SA password and creates the SecureAnyCloud database and login on the first boot only, then records that it has run in /var/opt/mssql/.firstboot-done
  • The credentials file /stage/scripts/mssql-credentials.log, mode 600, owned by root
  • Microsoft's mssql-server-2025 and prod apt repositories, so SQL Server 2025 cumulative updates arrive through apt
  • Ubuntu 24.04 LTS with the Azure Linux Agent, chrony for time sync and Ubuntu's unattended security upgrades
  • Platform: Microsoft Azure (Gen2, Hyper-V)
  • Default user: azureuser (or the administrator name you choose)
  • SQL Server port: 1433
  • Credentials file: /stage/scripts/mssql-credentials.log

Prerequisites

Before you deploy, make sure you have:

  • An active Microsoft Azure subscription
  • Access to the Azure Portal, or the Azure CLI on your workstation
  • An SSH key pair for Linux virtual machine access
  • A virtual network plan that names the application subnets that need to reach SQL Server on port 1433

Choose a virtual machine size that suits your workload. SQL Server sizes its memory use to the virtual machine, so pick a size with enough memory for your working set.

1

Deploy the Virtual Machine

Option A: Azure Portal

  • Open the Ubuntu 24.04 VM with SQL Server 2025 Developer listing on the Azure Marketplace. Choose Get it now, then Create.
  • Configure the basics:
  • Subscription: select your Azure subscription.
  • Resource Group: create a new group or select an existing one.
  • Virtual Machine Name: enter a name for your VM.
  • Region: select your preferred Azure region.
  • Size: select a size for your workload.
  • Under Administrator Account, select SSH public key and enter your key.
  • Under Inbound Port Rules, allow SSH (port 22), ideally from your own network only. Do not open port 1433 to the internet.
  • On the Networking tab, choose the virtual network your application servers use.
  • Select Review + Create, then Create.

Option B: Azure CLI

The image carries a Marketplace purchase plan, so accept its terms once per subscription. Then create a network security group that allows SSH from your own network only, and create the virtual machine.

Replace <your-ip> with your workstation's public address and <your-vm-size> with the size you chose:

az vm image terms accept --urn sac1647283583153:mssql-2025-developer-ubuntu-24-04:default:latest
az network nsg create --resource-group myResourceGroup --name my-ssh-only-nsg
az network nsg rule create --resource-group myResourceGroup --nsg-name my-ssh-only-nsg \
  --name allow-ssh --priority 100 --protocol Tcp --destination-port-ranges 22 \
  --source-address-prefixes <your-ip>/32 --access Allow
az vm create \
  --resource-group myResourceGroup \
  --name my-mssql-vm \
  --image sac1647283583153:mssql-2025-developer-ubuntu-24-04:default:latest \
  --size <your-vm-size> \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --nsg my-ssh-only-nsg \
  --public-ip-sku Standard \
  --storage-sku StandardSSD_LRS \
  --query publicIpAddress -o tsv

The command prints the virtual machine's public IP address. To keep the database server off the internet entirely, add --public-ip-address "". Then reach the server through Azure Bastion, a VPN or a jump host on the same virtual network.

Step 9 shows how to let your application servers reach port 1433.

2

Connect via SSH

Run this command on your own workstation:

ssh azureuser@<vm-ip>

There is no password to enter. If SSH asks for one, your client is offering a different key from the one you supplied when you created the VM.

The first boot finishes within a minute or two of the virtual machine starting. Wait for it with:

sudo cloud-init status --wait

It prints status: done when the first boot has finished.

3

Check the Server

Confirm that both services are active once the first boot has finished:

systemctl is-active mssql-server mssql-firstboot

Expected output:

active active

Check for the marker file that the first-boot service leaves when it has run:

sudo test -f /var/opt/mssql/.firstboot-done && echo FIRSTBOOT_DONE

Confirm that SQL Server listens on port 1433 on all interfaces:

sudo ss -Htlnp '( sport = :1433 )' | awk '{print $4, $6}'

Expected output:

0.0.0.0:1433 users:(("sqlservr",pid=...,fd=...)) *:1433 users:(("sqlservr",pid=...,fd=...))

SQL Server also listens on the loopback address only, on ports 1431 and 1434, for its own local use. The network security group decides who can reach port 1433 from outside. The deployment above allows only SSH.

4

The Credentials File

The first boot writes the logins to a root-only file. Check its permissions:

sudo stat -c '%a %U:%G %n' /stage/scripts/mssql-credentials.log

Expected output:

600 root:root /stage/scripts/mssql-credentials.log

To see the file, run sudo cat /stage/scripts/mssql-credentials.log. It holds SA_USER=sa, the SA password, SAC_USER=sac, the SecureAnyCloud password and SAC_DATABASE=sac.

The comment lines at the top of the file mention a Standard license key. They do not apply to this Developer Edition image (see Licensing above). Store the values in your secret store.

5

Connect with sqlcmd

sqlcmd is already on your PATH. Load the SA password into the SQLCMDPASSWORD environment variable, which sqlcmd reads. The password then never appears on a command line or in the process list:

export SQLCMDPASSWORD="$(sudo awk -F= '$1=="SA_PASSWORD"{print $2}' /stage/scripts/mssql-credentials.log)" sqlcmd -S localhost -U sa -C -Q "SELECT @@VERSION;"

Expected output (first lines):

Microsoft SQL Server 2025 (RTM-CU4) (KB5081495) - 17.0.4035.5 (X64) Mar 29 2026 15:22:28 Copyright (C) 2025 Microsoft Corporation Enterprise Developer Edition (64-bit) on Linux (Ubuntu 24.04.4 LTS) <X64>

The -C flag tells sqlcmd to trust the server's self-generated certificate. sqlcmd 18 encrypts every connection by default. Without -C (or a certificate your clients trust), it stops with certificate verify failed:self-signed certificate.

Confirm the edition:

sqlcmd -S localhost -U sa -C -h -1 -W -Q "SELECT SERVERPROPERTY('Edition');"

Expected output:

Enterprise Developer Edition (64-bit)

Check that the connection is encrypted:

sqlcmd -S localhost -U sa -C -h -1 -W -Q "SELECT net_transport, encrypt_option, auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@SPID;"

Expected output:

TCP TRUE SQL
6

The SecureAnyCloud Database and Login

The first boot creates a SecureAnyCloud database (full recovery model, compatibility level 170) and a SecureAnyCloud login that is db_owner of it. Verify both:

sqlcmd -S localhost -U sa -C -h -1 -W -Q "SELECT name, recovery_model_desc, compatibility_level FROM sys.databases WHERE name = 'sac';" sqlcmd -S localhost -U sa -C -d sac -h -1 -W -Q "SELECT m.name, r.name FROM sys.database_role_members rm JOIN sys.database_principals r ON r.principal_id = rm.role_principal_id JOIN sys.database_principals m ON m.principal_id = rm.member_principal_id;"

Expected output:

sac FULL 170 dbo db_owner sac db_owner

Before you first use the SecureAnyCloud login, set its password to the per-VM value in the credentials file, signing in as SA. On the current image the login does not yet accept that value, so this step is required. The password is passed to sqlcmd on standard input, never on a command line:

CL_PASS="$(sudo awk -F= '$1=="SAC_PASSWORD"{print $2}' /stage/scripts/mssql-credentials.log)" printf "ALTER LOGIN [sac] WITH PASSWORD = N'%s';\nGO\n" "$CL_PASS" | sqlcmd -S localhost -U sa -C -b -i /dev/stdin unset CL_PASS

Then run a round trip as the SecureAnyCloud login:

SQLCMDPASSWORD="$(sudo awk -F= '$1=="SAC_PASSWORD"{print $2}' /stage/scripts/mssql-credentials.log)" \
  sqlcmd -S localhost -U sac -C -d sac -h -1 -W \
  -Q "CREATE TABLE ##probe (id INT, val NVARCHAR(64)); INSERT INTO ##probe VALUES (1, N'sac-ok'); SELECT val FROM ##probe WHERE id = 1; DROP TABLE IF EXISTS ##probe;"

The output includes sac-ok.

7

Try the SQL Server 2025 Features

SQL Server 2025 adds a native VECTOR type with VECTOR_DISTANCE, regular expression functions such as REGEXP_LIKE, and JSON constructors such as JSON_OBJECT. Try them with a quick test in the SecureAnyCloud database:

sqlcmd -S localhost -U sa -C -d sac -h -1 -W -Q " CREATE TABLE dbo.docs (id INT PRIMARY KEY, title NVARCHAR(100), embedding VECTOR(3)); INSERT INTO dbo.docs VALUES (1, N'Azure VM guide', '[0.1,0.9,0.2]'), (2, N'SQL Server notes', '[0.8,0.1,0.3]'), (3, N'Ubuntu tips', '[0.2,0.8,0.1]'); SELECT TOP 2 id, title, CAST(VECTOR_DISTANCE('cosine', embedding, CAST('[0.1,0.9,0.1]' AS VECTOR(3))) AS DECIMAL(6,4)) AS dist FROM dbo.docs ORDER BY dist; SELECT id, title FROM dbo.docs WHERE REGEXP_LIKE(title, '^(Azure|Ubuntu)'); SELECT JSON_OBJECT('id': id, 'title': title) FROM dbo.docs WHERE id = 2; DROP TABLE dbo.docs;"

Expected output:

1 Azure VM guide .0058 3 Ubuntu tips .0089 1 Azure VM guide 3 Ubuntu tips {"id":2,"title":"SQL Server notes"}
8

Back Up a Database

SQL Server writes backups as the mssql user, so back up to a directory that user owns, such as the default data directory:

sqlcmd -S localhost -U sa -C -Q "BACKUP DATABASE sac TO DISK = N'/var/opt/mssql/data/sac.bak' WITH INIT, COMPRESSION; RESTORE VERIFYONLY FROM DISK = N'/var/opt/mssql/data/sac.bak';"

Expected output (last lines):

BACKUP DATABASE successfully processed ... pages in ... seconds (...). The backup set on file 1 is valid.

Copy backups off the virtual machine, for example to Azure Blob Storage, so they survive the loss of the disk.

9

Reach SQL Server from Your Applications

SQL Server listens on port 1433 on every interface, but the network security group from Step 1 allows only SSH. To let your application servers connect, add a rule that allows port 1433 from their subnet only:

az network nsg rule create --resource-group myResourceGroup --nsg-name my-ssh-only-nsg \
  --name allow-sql-from-apps --priority 110 --protocol Tcp --destination-port-ranges 1433 \
  --source-address-prefixes <app-subnet-cidr> --access Allow

Applications then connect to the virtual machine's private IP address on port 1433 with a SQL login, for example sqlcmd -S <private-ip>,1433 -U SecureAnyCloud -C -d SecureAnyCloud (with the password in SQLCMDPASSWORD).

SQL Server Management Studio and other TDS clients connect the same way. They must trust the server certificate, as -C does. Alternatively, install a certificate of your own with mssql-conf set network.tlscert.

To work from your own workstation without opening port 1433, open an SSH tunnel and point your client at localhost,14330:

ssh -N -L 14330:localhost:1433 azureuser@<vm-ip>

Do not open port 1433 to the internet.

10

Server Components

Key components and their paths:

  • SQL Server engine: /opt/mssql/bin/sqlservr
  • Configuration tool: /opt/mssql/bin/mssql-conf
  • Configuration file: /var/opt/mssql/mssql.conf
  • sqlcmd and bcp: /opt/mssql-tools18/bin/
  • Data directory: /var/opt/mssql/data/
  • Error log: /var/opt/mssql/log/errorlog
  • Service unit: /usr/lib/systemd/system/mssql-server.service
  • First-boot unit: /etc/systemd/system/mssql-firstboot.service
  • First-boot script: /usr/local/sbin/mssql-firstboot.sh
  • First-boot marker: /var/opt/mssql/.firstboot-done
  • Credentials file: /stage/scripts/mssql-credentials.log

The data and log files live on the OS disk. For larger databases, attach a data disk and mount it. Then move the default data and log directories to it with mssql-conf set filelocation.defaultdatadir and filelocation.defaultlogdir.

SQL Server Agent is not enabled on this image. Turn it on with sudo /opt/mssql/bin/mssql-conf set sqlagent.enabled true, then run sudo systemctl restart mssql-server.

Check the installed package versions:

dpkg -l mssql-server mssql-tools18 | awk '/^ii/{print $2, $3}'
11

Manage the Service

sudo systemctl status mssql-server --no-pager sudo systemctl restart mssql-server
sudo tail -n 50 /var/opt/mssql/log/errorlog
12

Keep It Updated

Ubuntu's unattended upgrades install Ubuntu security updates automatically. SQL Server comes from Microsoft's own repository, so update it yourself when a new cumulative update is available:

sudo apt-get update apt-cache policy mssql-server
sudo apt-get install --only-upgrade mssql-server

The upgrade restarts SQL Server. Take a backup first and run the upgrade during a quiet period.

13

Troubleshooting

sqlcmd says certificate verify failed:self-signed certificate

  • Add -C to trust the server's certificate, or install a certificate your clients trust (Step 9).

Login failed for user 'SecureAnyCloud'

  • Set the SecureAnyCloud password from the credentials file as SA (Step 6), then try again.
  • Find the reason in the error log: sudo grep "Login failed" /var/opt/mssql/log/errorlog | tail -5

Cannot connect on port 1433 from another host

  • Check the service and listener (Step 3).
  • Check that the network security group allows 1433 from your client's subnet (Step 9).

The first boot did not finish

Check the first-boot service and its journal:

  • sudo systemctl status mssql-firstboot --no-pager
  • sudo journalctl -u mssql-firstboot --no-pager -n 50

The server name looks wrong

  • SELECT @@SERVERNAME reports the name of the machine the image was built on, while SERVERPROPERTY('MachineName') reports your virtual machine's name.
  • Features that depend on the server name, such as replication, need the server renamed first. Follow Microsoft's procedure for renaming a SQL Server host.
14

Security Recommendations

  • Keep port 1433 private. Keep it closed to the internet and allow it only from your application subnets.
  • Set the SecureAnyCloud password early. Set the login's password (Step 6) before port 1433 is reachable from any other host.
  • Use one login per application. Grant only the permissions each application needs, and do not connect applications as SA.
  • Rotate the SA password. Change it on a schedule with ALTER LOGIN [sa] WITH PASSWORD = ..., or disable SA once named administrator logins exist.
  • Keep passwords off the command line. Use SQLCMDPASSWORD or a secret store rather than -P.
  • Back up regularly. Take regular backups and copy them off the virtual machine.
  • Remove the credentials file when you no longer need it. Once the passwords are in your secret store, delete the file with sudo shred -u /stage/scripts/mssql-credentials.log.

Support

SecureAnyCloud provides 24/7 support for this image, with a guaranteed 24-hour response.

  • Email: sales@secureanycloud.com
  • Website: secureanycloud.com

Deploy on Azure

Launch SQL Server 2025 Developer 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