Introduction

When most developers think of Microsoft SQL Server, they immediately picture a Windows Server environment, a hefty licensing bill, and a GUI-heavy setup experience. But here is something that still surprises a lot of engineers: SQL Server runs beautifully on Ubuntu Linux, and Microsoft offers a completely free edition called SQL Server Express that you can use in real projects without paying a single rupee in licensing costs.

I have worked with teams that spent weeks debating between PostgreSQL and SQL Server for a new backend project purely because they assumed SQL Server meant Windows. Once they realized SQL Server had a native Linux package, the whole conversation changed. The tooling, the T-SQL syntax, the stored procedures, the integration with .NET and Entity Framework — all of it works exactly the same on Ubuntu as it does on Windows Server.

That said, installing SQL Server on Ubuntu and doing it properly are two different things. Most tutorials stop at the installation step and leave you with a default setup that has no password policies, no firewall rules, and no service hardening. That is not acceptable for a production or even a staging environment.

In this guide, we will go through the complete process: updating your Ubuntu server, adding Microsoft's official repository, installing the free SQL Server Express edition, running the setup wizard, creating login accounts, assigning permissions, enabling remote access safely, and covering the daily commands that actually matter in a DevOps workflow.


Step 1: Update Ubuntu Server

This step is non-negotiable. Before you touch any repository or install any package, bring your system fully up to date. Outdated system packages cause dependency conflicts during SQL Server installation, and debugging those conflicts wastes hours of your time.

Run the following:

sudo apt update
sudo apt upgrade -y

If your server has not been updated in a while and this pulls in a significant number of kernel-level upgrades, go ahead and reboot before continuing:

sudo reboot

After the reboot, SSH back in and you are ready for the next step. Cloud VPS environments like DigitalOcean, AWS EC2, or Azure VM benefit especially from this because the base images often ship with packages that are several months old.


Step 2: Add Microsoft Repository and Install SQL Server

Microsoft maintains an official APT repository for SQL Server on Linux. You should always install from there rather than relying on third-party packages or whatever happens to be in the Ubuntu default repositories. The official package gives you proper systemd integration, correct file permissions, and access to security patches directly from Microsoft.

First, install the required prerequisites:

sudo apt install curl gnupg2 -y

Import Microsoft's signing key:

curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -

Now register the SQL Server 2022 repository for Ubuntu 22.04:

curl https://packages.microsoft.com/config/ubuntu/22.04/mssql-server-2022.list | \
sudo tee /etc/apt/sources.list.d/mssql-server-2022.list
Note: If you are running Ubuntu 20.04, replace 22.04 with 20.04 in the URL above.

Update the package cache to include the new repository:

sudo apt update

Now install SQL Server:

sudo apt install mssql-server -y

This will download the SQL Server engine. Installation time depends on your server's internet connection, but expect anywhere from two to five minutes. The package is considerably larger than a typical Linux utility.


Step 3: Run the SQL Server Setup Wizard

After installation, SQL Server does not start automatically. You need to run the configuration wizard first. This is where you choose your edition and set the system administrator password.

Run the setup tool:

sudo /opt/mssql/bin/mssql-conf setup

The wizard will ask you to select an edition. For the free version, choose option 3 for Express:

Choose an edition of SQL Server:
  1) Evaluation (free, no production use rights, 180-day limit)
  2) Developer (free, no production use rights)
  3) Express (free)
  4) Web (paid)
  5) Standard (paid)
  6) Enterprise (paid)
  7) Enterprise Core (paid)
  8) I bought a license through a retail sales channel and have a product key.
 
Enter your choice [1-8]: 3

Accept the license terms, then set a strong SA (System Administrator) password when prompted:

Enter the SQL Server system administrator password: ************
Confirm the SQL Server system administrator password: ************
Important: The SA account is the most powerful account in SQL Server. Use a password with mixed case, numbers, and special characters. Something like Admin@Sql#2026 works — weak passwords will be rejected by the password policy engine.

Once setup completes, SQL Server will start automatically.


Step 4: Verify the SQL Server Service

Before doing anything else, confirm the service is actually running. Do not skip this step — there are a handful of common reasons why SQL Server fails to start on a fresh Ubuntu install, and catching them now saves debugging later.

sudo systemctl status mssql-server

You want to see:

Active: active (running)

Enable it to start on boot:

sudo systemctl enable mssql-server

If the service is not running, check the error log immediately:

sudo journalctl -u mssql-server --no-pager | tail -30

A very common issue is insufficient RAM. SQL Server requires at least 2 GB of memory to start. On small VPS instances with 1 GB RAM, the service silently fails to initialize. If you are on a constrained server, you can lower the memory floor — but understand this is not suitable for production workloads:

sudo /opt/mssql/bin/mssql-conf set memory.memorylimitmb 1024
sudo systemctl restart mssql-server

Step 5: Install SQL Server Command-Line Tools

The SQL Server engine and the client tools are separate packages on Linux. To interact with your server from the terminal — run queries, create users, check databases — you need to install sqlcmd and bcp.

Register the tools repository:

curl https://packages.microsoft.com/config/ubuntu/22.04/prod.list | \
sudo tee /etc/apt/sources.list.d/msprod.list
sudo apt update

Install the tools (accept the EULA when prompted):

sudo apt install mssql-tools18 unixodbc-dev -y

Add the tools to your system PATH so you can call sqlcmd from anywhere:

echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc
source ~/.bashrc

Test your connection to verify everything is working:

sqlcmd -S localhost -U SA -P "Admin@Sql#2026" -No

If you see the 1> prompt, you are connected. Type EXIT to leave. The -No flag disables certificate validation for local connections; in production with a proper TLS certificate, remove this flag.


Step 6: Create a SQL Login and Assign Roles

Using the SA account for everything is a serious security mistake. The SA account has full, unrestricted access to every database and system function. In a real deployment, you create dedicated SQL logins with scoped permissions.

Connect as SA and run the following T-SQL to create an admin-level login:

sqlcmd -S localhost -U SA -P "Admin@Sql#2026" -No -Q "
CREATE LOGIN dbAdmin WITH PASSWORD = 'DbAdmin@Secure!99';
ALTER SERVER ROLE sysadmin ADD MEMBER dbAdmin;
GO"

What does this do?

  • CREATE LOGIN — Creates a SQL Server authentication login (not a Windows account).
  • sysadmin — Grants full server-level administration rights, equivalent to the SA account. Use this only for your DBA or DevOps admin accounts, never for application service accounts.

For most use cases, you will want your DevOps admin to have sysadmin access, while application service accounts should have nothing beyond what is strictly required for their specific database. We handle that in the next step.


Step 7: Create an Application Database and Dedicated User

Your backend application — whether it is a .NET API, a Python Flask service, or a Node.js server — should never connect to SQL Server using the SA account or your admin login. Create a dedicated database user with minimal permissions.

First, create the application database:

sqlcmd -S localhost -U SA -P "Admin@Sql#2026" -No -Q "
CREATE DATABASE AppProductionDB;
GO"

Now create a login and map it to a database user with read/write permissions only:

sqlcmd -S localhost -U SA -P "Admin@Sql#2026" -No -Q "
CREATE LOGIN appServiceUser WITH PASSWORD = 'AppUser@Service#2026';
USE AppProductionDB;
CREATE USER appServiceUser FOR LOGIN appServiceUser;
ALTER ROLE db_datareader ADD MEMBER appServiceUser;
ALTER ROLE db_datawriter ADD MEMBER appServiceUser;
GO"

Here is what each role means:

  • db_datareader — Can read all data from all tables in the database. Good for reporting services.
  • db_datawriter — Can insert, update, and delete data. Combined with db_datareader, this covers most standard application needs.
  • db_owner — Full control over the database, including schema changes. Use only for migration tooling, not runtime application users.

Your application's connection string should now use appServiceUser — not SA, not dbAdmin. This way, if your application is ever compromised, the attacker cannot touch other databases or server-level settings.


Step 8: Configure Remote Access Securely

By default, SQL Server listens on port 1433 on all interfaces. If your backend API runs on a separate server, you need to open firewall access — but only to that specific server, never to the entire internet.

First, confirm SQL Server is actually listening on port 1433:

ss -tlnp | grep 1433

Now configure UFW to allow incoming connections only from your application server's private IP:

sudo ufw allow from 10.116.0.5 to any port 1433
sudo ufw enable
sudo ufw status
Never run sudo ufw allow 1433 without specifying a source IP. That opens port 1433 to the entire internet — automated scanners will hit it within minutes. Always restrict to private VPC IP addresses.

If you are in a cloud environment like AWS or Azure, also configure your security group or network security group to allow TCP 1433 inbound only from your application server's private IP, in addition to the OS-level firewall rule above. Defense in depth.


Step 9: Essential DevOps SQL Server Commands

These are the commands you will find yourself using regularly once SQL Server is running in your environment:

  • List all databases:
    sqlcmd -S localhost -U SA -P "yourpassword" -No -Q "SELECT name FROM sys.databases; GO"
  • Check active connections:
    sqlcmd -S localhost -U SA -P "yourpassword" -No -Q "SELECT * FROM sys.dm_exec_sessions WHERE is_user_process = 1; GO"
  • Backup a database to disk:
    sqlcmd -S localhost -U SA -P "yourpassword" -No -Q "BACKUP DATABASE AppProductionDB TO DISK = '/var/opt/mssql/backups/AppProductionDB.bak'; GO"
  • Restore a database from backup:
    sqlcmd -S localhost -U SA -P "yourpassword" -No -Q "RESTORE DATABASE AppProductionDB FROM DISK = '/var/opt/mssql/backups/AppProductionDB.bak' WITH REPLACE; GO"
  • View SQL Server error log:
    sudo cat /var/opt/mssql/log/errorlog
  • Check SQL Server version:
    sqlcmd -S localhost -U SA -P "yourpassword" -No -Q "SELECT @@VERSION; GO"

Create the backups directory if it does not exist yet:

sudo mkdir -p /var/opt/mssql/backups
sudo chown mssql:mssql /var/opt/mssql/backups

Common SQL Server Deployment Mistakes

Mistake Impact The DevOps Fix
Using SA for Application Connections A compromised app gives attackers full server access. Create a dedicated login with db_datareader + db_datawriter only.
Opening Port 1433 Publicly Automated brute-force attacks within minutes of exposure. Use ufw allow from <private_ip> — never allow globally.
Skipping Memory Configuration SQL Server silently crashes on servers with less than 2 GB RAM. Set memory.memorylimitmb via mssql-conf for low-memory environments.
No Backup Strategy Data loss after hardware failure, accidental deletion, or corruption. Schedule nightly BACKUP DATABASE jobs via cron and store offsite.
Using Evaluation Edition in Production Evaluation expires after 180 days, taking your application down with it. Use Express Edition (free, no expiry) for small workloads, or purchase a license for larger ones.

Frequently Asked Questions (FAQ)

What are the limitations of SQL Server Express compared to Standard or Enterprise?

SQL Server Express is free with no expiration, which makes it genuinely useful. The main constraints are a 10 GB maximum database size per database, a limit of 1 GB of RAM used by the database engine, and a cap of 4 CPU cores. For small to mid-size applications — internal tools, small SaaS products, personal projects — these limits rarely become a problem. Once you grow past them, you migrate to Standard or Enterprise edition.

Can I connect to this SQL Server instance using SSMS on Windows?

Yes. SQL Server Management Studio (SSMS) running on a Windows machine can connect to a SQL Server instance running on Ubuntu just like any other remote server. Use your Ubuntu server's IP address as the server name, SQL Server Authentication as the login type, and the SA credentials. Make sure port 1433 is accessible from your Windows machine's IP through the firewall.

Why is my service failing to start after I configure mssql-conf?

The most common reason is a memory configuration that is set too low for SQL Server to initialize. The engine needs enough headroom to load its internal structures at startup. Check the error log at /var/opt/mssql/log/errorlog for a clear message. If you see memory-related errors, bump memory.memorylimitmb up to at least 1024 and restart the service.

How do I use SQL Server with a .NET or Entity Framework application?

Use the Microsoft.Data.SqlClient NuGet package. Your connection string will follow the format: Server=your_ubuntu_ip,1433;Database=AppProductionDB;User Id=appServiceUser;Password=yourpassword;TrustServerCertificate=True;. The TrustServerCertificate=True flag handles the self-signed certificate situation on a fresh install. For production, configure a proper TLS certificate and remove that flag.


Conclusion

Installing Microsoft SQL Server on Ubuntu does not have to be a Windows-or-nothing decision anymore. The free Express Edition gives you a real, production-capable relational database engine on Linux with zero licensing cost — and the setup process, while slightly more involved than installing PostgreSQL, is entirely manageable once you understand each step and why it matters.

The key things to take away from this guide: always install from Microsoft's official repository, run the setup wizard to choose the Express edition, create dedicated service accounts rather than using SA for everything, lock down port 1433 to specific private IPs only, and build a backup routine from day one rather than after something goes wrong.

Whether you are running a .NET backend, a Python microservice, or a Node.js API, SQL Server on Ubuntu gives you the full power of T-SQL, robust transaction support, and excellent tooling — all on a Linux server you are probably already comfortable managing.

f X W