---
title: "Deploy mssql2019"
description: "Microsoft SQL Server 2019 with persistent storage and TCP access"
category: "Storage"
url: https://railway.com/deploy/mssql2019
---

# Deploy mssql2019

Microsoft SQL Server 2019 with persistent storage and TCP access

**[Deploy mssql2019 on Railway](https://railway.com/template/mssql2019)**

- **Creator:** Nameless 's Projects
- **Category:** Storage

## Template content

### mssql-2019

- **Source:** https://github.com/lNamelessl/mssql2019

## Documentation

# mssql2019 — SQL Server 2019 on Railway

[![Deploy on Railway](https://railway.com/button.svg)](https://railway.app/new?github_url=https://github.com/lNamelessl/mssql2019)

A reusable [Railway](https://railway.app) template that runs **Microsoft SQL Server 2019** (Linux, `mcr.microsoft.com/mssql/server:2019-latest`) as a normal Railway service, working out of the box on a one-click deploy — no password juggling, no crash loops.

Verified running `Microsoft SQL Server 2019 (RTM-CU32-GDR) - 15.0.4480.2 (X64)` on Railway (EU West), queried successfully over TCP with `sqlcmd`.

&gt; A SQL Server 2022 variant of this template lives at [`mssql2022`](https://github.com/lNamelessl/mssql2022).

## What you get

- SQL Server 2019 (Developer edition by default) listening on TCP `1433`
- Zero-config first boot: if no SA password is provided, a strong one is generated and printed to the deploy logs
- Handles Railway's runtime quirks that crash-loop a vanilla SQL Server deployment (see [Storage on Railway — important](#storage-on-railway--important) and [How it works](#how-it-works))
- Connect from any MSSQL client: SSMS, Azure Data Studio, `sqlcmd`, or any driver (ODBC, JDBC, pyodbc, `mssql` npm package, Entity Framework, Prisma, etc.)

What this means in practice:

- **Great for**: development databases, staging/preview instances, CI databases, learning and prototyping — anywhere a disposable, fully-managed SQL Server is useful.
- **Not for**: primary production data. If you need persistence, run SQL Server somewhere with real block storage, or use a managed offering.

**Do not attach a Railway volume at `/var/opt/mssql`** — it is the one configuration that always crash-loops. The entrypoint detects this and prints a warning to the deploy logs.

## Deploying

1. Click the deploy button above (or go to ).
2. Add a **TCP Proxy** under Service → Settings → Networking to reach SQL Server from your machine (public endpoint like `.proxy.rlwy.net:`).
3. Deploy. Optionally set the variables below before the first deploy.

### Environment variables

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `MSSQL_SA_PASSWORD` | No | auto-generated | SA password. Only applies on **first initialization**. Must satisfy SQL Server complexity rules (8–128 chars, 3 of: uppercase, lowercase, digit, symbol). |
| `ACCEPT_EULA` | No | `Y` | SQL Server EULA acceptance. Baked in as a default; override if you need to. |
| `MSSQL_PID` | No | `Developer` | Edition: `Developer`, `Express`, `Standard`, `Enterprise`, or a product key. |
| `MSSQL_COLLATION` | No | server default | Collation, applied on first initialization (e.g. `SQL_Latin1_General_CP1_CI_AS`). |
| `MSSQL_DEBUG` | No | unset | Set to `1` to print data-directory layout and disk diagnostics to the deploy logs before startup. |

### SA password behavior

SQL Server only reads the SA password when it initializes an **empty** data directory — this is official image behavior, not a template limitation. The entrypoint handles it as follows:

1. If `MSSQL_SA_PASSWORD` (or legacy `SA_PASSWORD`) is set, it is used for initialization and saved to `/var/opt/mssql/.sa_password`.
2. If no password is provided, a strong one is generated, saved, and printed to the deploy logs (visible under the deployment's **Deployments → View Logs**).
3. On container restarts the stored password is reused. On a redeploy the filesystem starts fresh, the server re-initializes, and — if no password variable is set — a new password is generated and printed; you can't get locked out.
4. Weak passwords are rejected at boot with a clear error message instead of an opaque crash loop.

The generated password is stored in plaintext at `/var/opt/mssql/.sa_password` inside the container.

### Resource sizing

SQL Server 2019 wants a minimum of ~2 GB of memory. On Railway, give the service at least **2 GB RAM** (Service → Settings → Resources) for reliable operation.

## Connecting

After adding a TCP proxy, connect with any client using the public hostname and port Railway assigns (e.g. `mono-packed-macaque.proxy.rlwy.net:31234`):

```bash
# sqlcmd
sqlcmd -S .proxy.rlwy.net, -U sa -P '' -C -Q "SELECT @@VERSION"

# connection string
Server=.proxy.rlwy.net,;Database=master;User Id=sa;Password=;Encrypt=True;TrustServerCertificate=True;
```

Modern drivers (Microsoft.Data.SqlClient, ODBC Driver 18+, pyodbc 18+) default to encryption and will complain about the server's self-signed certificate — set `TrustServerCertificate=True` (or `Encrypt=False` / sqlcmd `-No`) unless you bring your own certificate.

From inside the container you can always reach the server at `localhost:1433`.

## How it works

- `Dockerfile` — based on `mcr.microsoft.com/mssql/server:2019-latest`, bakes in EULA acceptance and Developer edition defaults, installs `entrypoint.sh`, exposes `1433`.
- `entrypoint.sh` — resolves and validates the SA password, persists it for container restarts, prints the previous boot's crash reason and cleans up stale crash dumps (they are multi-gigabyte and will fill the disk), warns if a volume is mounted at the data path, then `exec`s `sqlservr` as PID 1 so it shuts down cleanly on `SIGTERM`. It runs sqlservr as root — the configuration verified under Railway's gVisor runtime.

## Local testing

```bash
docker build -t mssql2019 .
docker run -d --name mssql2019-test -p 1433:1433 mssql2019
docker logs -f mssql2019-test   # shows the generated SA password
```

Then connect with `sqlcmd -S localhost,1433 -U sa -P '' -C`.

## License

[MIT](LICENSE)


# Deploy and Host

SQL Server 2019 on Railway — a one-click template that runs Microsoft SQL Server 2019 (Linux, the official `mcr.microsoft.com/mssql/server:2019-latest` image) as a Railway service listening on TCP 1433, hardened for Railway's runtime so it actually starts and stays up instead of crash-looping like a vanilla deployment. Verified end-to-end on Railway: the server initializes cleanly, accepts queries from `sqlcmd` over TCP, and reports `Microsoft SQL Server 2019 (RTM-CU32-GDR) - 15.0.4480.2 (X64)`.

[![Deploy on Railway](https://railway.com/button.svg)](https://railway.app/new?github_url=https://github.com/lNamelessl/mssql2019)



## About Hosting

You are hosting one service:

- **mssql** — SQL Server 2019 (Developer edition by default) from the official Microsoft Docker image, listening on TCP 1433, with its data on the container filesystem.

Configured environment variables: `ACCEPT_EULA=Y` (EULA acceptance), `MSSQL_PID=Developer` (free for development/testing; switch to `Express`, `Standard`, `Enterprise`, or a product key), and optionally `MSSQL_SA_PASSWORD` (SA password, applied on first initialization) and `MSSQL_COLLATION` (server collation).

After deploying: copy the SA password from the deploy logs (or set `MSSQL_SA_PASSWORD` yourself before the first deploy), add a TCP Proxy under Settings → Networking to get a public endpoint like `.proxy.rlwy.net:`, and connect with any MSSQL client — SSMS, Azure Data Studio, `sqlcmd`, ODBC/JDBC, pyodbc, Entity Framework, Prisma, or the `mssql` npm package. Give the service at least 2 GB of RAM; SQL Server will not run comfortably below that.

**Storage note:** SQL Server on Railway uses the container filesystem, which is ephemeral — databases live until the service is redeployed. Railway runs containers under gVisor, and SQL Server crashes mid-initialization when its state is placed on a Railway volume, so persistent storage is not possible for SQL Server on this platform today. Ideal for development, staging/preview, CI, and learning workloads; not for primary production data.

## Why Deploy

Deploying the official SQL Server image manually on Railway fails in boring ways, and this template fixes all of them:

1. **Volumes crash-loop under gVisor** — Railway executes containers under gVisor, and SQL Server's process abstraction layer stack-overflows mid-initialization when its data or registry hives sit on a Railway volume (see gVisor issue #11112). The template keeps SQL Server state on the container filesystem, the configuration verified to work, and warns loudly in the logs if a volume is mounted at the data path.
2. **SA password requirements** — SQL Server refuses to initialize with a weak or missing SA password. The template validates passwords before boot (a clear error instead of an opaque crash loop) and auto-generates a compliant one when none is set.
3. **Crash dump hygiene** — a fatal error makes sqlservr write multi-gigabyte dumps into its log directory, which fills the disk and keeps the server from ever starting again. Oversized dumps are cleaned up at boot, and a previous boot's crash reason is printed to the deploy logs.
4. **Clean shutdown** — sqlservr runs as PID 1, so redeploys shut the server down cleanly instead of killing it hard.

## Common Use Cases

- **Backends that require MSSQL** — .NET/Entity Framework, legacy ASP.NET, or any stack whose ORM speaks TDS and needs real SQL Server (not a Postgres shim).
- **SQL Server–specific features** — T-SQL, stored procedures, temporal tables, and MSSQL-only query behavior for development and testing.
- **Staging and preview databases** — spin up disposable SQL Server instances per project or per pull request, without standing up a Windows VM.
- **Learning and prototyping** — a full SQL Server 2019 Developer edition in the cloud for practicing T-SQL, SSMS connections, or BI tooling against a real instance.

## Dependencies for
Applications

### Deployment Dependencies

- A Railway account with a plan that provides at least 2 GB of RAM for the service.
- No external services, APIs, or accounts are required — SQL Server is fully self-contained.
- The image `mcr.microsoft.com/mssql/server:2019-latest` is pulled from Microsoft's public registry at build time.


## Similar templates

- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.
- [Redis](https://railway.com/deploy/redis-1) — Self Host Latest Redis with Railway
- [EasyImg](https://railway.com/deploy/easyimg) — Simple self-hostable Nuxt.js personal image hosting system.

Open this page in a browser: https://railway.com/deploy/mssql2019
