MsSQL
Specific configuration for MsSQL.
Add this database from the dashboard
Since Dashboard 1.29.0 and Agent 1.19.0, you can add this database directly from the dashboard (Add database on the agent page), without editing any file. See Adding a Database. The settings described below also apply to the dashboard form.
MsSQL is fully supported by the Portabase agent. By default it uses Microsoft's sqlpackage tool. For applications that need a native backup, the bak format runs BACKUP DATABASE instead.
DACPAC backups since Agent 1.22.0 and Dashboard 1.32.0
Backups are DACPAC files by default (sqlpackage /Action:Extract with all table data). The previous format, BACPAC (/Action:Export), is validated against Azure SQL Database rules and fails on on-premise servers that hold Windows principals such as NT AUTHORITY\SYSTEM (Error SQL71627). BACPAC remains available per database through the backup_format option.
Native .bak backups and safer restores since Agent 1.26.0 and Dashboard 1.36.0
The bak format adds native BACKUP DATABASE backups, for applications that reference other databases or are written to during backups. For every format, a failed restore now leaves the target database as it was. See Restore.
MsSQL has strict password complexity requirements. Your password must be at least 8 characters long and contain characters from three of the following four categories: Latin uppercase letters, Latin lowercase letters, digits (0 through 9), and non-alphanumeric characters (e.g., !, $, #, %). Failure to meet these requirements will cause the container to crash.
Configuration
When running portabase agent db add, select mssql as the database type.
Options
The following optional fields can be set under an options key in the database configuration. From the dashboard, they are the Backup format, Folder on SQL Server, Folder on the agent and Verify backup fields of the database form. The last three appear when you choose bak.
| Option | Type | Default | Description |
|---|---|---|---|
backup_format | string | "dacpac" | Format of new backups: dacpac, bacpac or bak. See Backup formats below. If the value is absent or unrecognized, the agent uses dacpac and logs a warning. Agents older than 1.22.0 ignore this option and always produce BACPAC. Agents older than 1.26.0 do not know bak and produce a DACPAC. |
bak_server_path | string | none | Required with bak. The shared folder as SQL Server sees it, for example D:\PortabaseBackups or \\nas\sql-backups. |
bak_agent_path | string | none | Required with bak. The same folder as the agent sees it, for example /mnt/sql-backups. |
bak_verify | boolean | false | With bak, runs RESTORE VERIFYONLY ... WITH CHECKSUM after each backup. This reads the whole backup again on SQL Server. |
{
"name": "Database - MsSQL",
"database": "myappdb",
"type": "mssql",
"username": "sa",
"password": "Password!Strong1",
"port": 1433,
"host": "db-mssql",
"generated_id": "...",
"options": {
"backup_format": "bacpac"
}
}Backup formats
dacpac (default) | bacpac | bak | |
|---|---|---|---|
| Method | sqlpackage Extract with all table data | sqlpackage Export | BACKUP DATABASE on SQL Server |
| Content | Schema, data, database users, roles and permissions | Schema, data, database users and permissions | The whole database, indexes included |
| Server logins | Not included | Not included | Not included |
| Windows principals | Supported | Fails with SQL71627 | Supported |
| References to another database | Backup succeeds. Restore fails if the referenced database is missing | Backup fails with SQL71561 or SQL71562 | Backup and restore both succeed |
| Writes during the backup | Not consistent | Not consistent | Consistent, a single point in time |
| Setup | None | None | A folder shared with SQL Server |
| Azure SQL Database | Yes | Yes | No |
dacpac needs no setup and stays the default. Choose bak when the database references another database or master, when it is written to during backups, or when your application's vendor requires native backups. Use bacpac only when you need that file, for example to import it into Azure SQL Database from the Azure portal.
DACPAC and BACPAC are not transactionally consistent
sqlpackage reads tables one at a time. If the application writes during the backup, related rows in different tables can disagree in the backup, even when the application wrote them in one transaction, and nothing reports it. Back up during a quiet period, or use bak.
Native .bak backups
With backup_format set to bak, the agent asks SQL Server to write the backup into a shared folder:
BACKUP DATABASE [myappdb] TO DISK = '<bak_server_path>/<generated_id>.bak'
WITH COPY_ONLY, FORMAT, CHECKSUM, COMPRESSIONThe agent then archives the file from that folder, sends it to your storages like any other backup, and removes it from the folder.
| Option | Why |
|---|---|
COPY_ONLY | Does not disturb your own backups: your differential backups keep their base. |
FORMAT | Replaces a file left by an interrupted run. |
CHECKSUM | Stops the backup if SQL Server finds a corrupt page, so corruption shows up as a failed job. |
COMPRESSION | Used when your edition supports it. Otherwise, on Express for example, the backup runs again without it and the job log says so. |
Shared folder
SQL Server writes the file on its own machine, so the agent must be able to reach that folder. You provide the folder and set two paths, because each side sees it differently.
- The SQL Server service account must be able to write there.
- The agent must be able to read, write and delete there. On Linux, SQL Server creates the file as
0640 mssql:root. The agent image runs as root and can read it.
If the two paths do not point to the same folder, the job fails and the error names both. At most one file per database can stay behind if the agent cannot delete it, and the next backup overwrites it.
For a SQL Server on Windows, share the folder and mount it into the agent:
services:
agent:
image: portabase/agent:latest
# ... agent configuration ...
volumes:
- sql-backups:/mnt/sql-backups
volumes:
sql-backups:
driver: local
driver_opts:
type: cifs
device: //sqlhost/PortabaseBackups
o: "username=portabase,password=${SHARE_PASSWORD},uid=0,gid=0"{
"options": {
"backup_format": "bak",
"bak_server_path": "D:\\PortabaseBackups",
"bak_agent_path": "/mnt/sql-backups"
}
}With the CLI, -o bak_agent_path=/mnt/sql-backups mounts that host folder into the agent at the same path. Mount the share on the host first.
Related databases
Applications that spread their data across several databases need them backed up close together. Put them in the same project and set the schedule on the project: all of them start at the same time, unless MAX_CONCURRENT_BACKUPS makes them wait. To restore them together, select them on the project page and use Restore latest.
Each backup is consistent on its own, but the set is not one point in time across databases.
Limits
- Azure SQL Database and Managed Instance cannot back up to disk: the job fails with the server's error. Use
dacpacorbacpacthere. - A
.bakfile does not restore onto an older SQL Server version. The restore is refused before anything changes. - Server logins are not in the backup. Database users restored onto another server need matching logins.
DB_CHAININGandTRUSTWORTHYare OFF after a restore. If your application relies on them, set them again.- The transaction log is not truncated. In the
FULLrecovery model, log backups remain your responsibility. - Size. A
.bakkeeps indexes and pages, so it is usually larger than a DACPAC of the same database.
Restore
A restore replaces the target database. The method follows the file extension, not the backup_format option, so a database can restore any of its older backups.
| File | How the target is replaced |
|---|---|
.dacpac, .bacpac | sqlpackage builds the backup in a temporary side database named <target>_restore_<generated_id>_<run> (/Action:Publish or /Action:Import). The target stays online with its current data. Once that succeeds, the agent disconnects the sessions, drops the target and renames the side database. If the target does not exist, sqlpackage restores straight into it. |
.bak | SQL Server checks that it can read the file, then runs RESTORE DATABASE ... WITH REPLACE from the shared folder. The database options above must be set on the target. Each file keeps its path when the target already has it, and otherwise goes to the instance's default data or log folder. |
The restore is refused before anything changes when:
- the file is not a
.dacpac,.bacpacor.bak; - the target is a system database (
master,tempdb,model,msdb); - for
.dacpacand.bacpac, the configured login cannot create databases or replace the target. It needssysadminordbcreator, orCREATE ANY DATABASEtogether withdb_ownerof the target, or, on Azure SQL Database, the server admin or thedbmanagerrole; - for
.bak, the shared folder options are missing, or SQL Server cannot read the file.
If sqlpackage fails, the side database is removed and the target is left untouched. A side database left by an interrupted run is removed by the next restore of that database.
What to expect with .dacpac and .bacpac
- Free space. The server holds the target and the restored copy at the same time. Without enough room the restore fails and the target stays as it was. To restore anyway, drop the target by hand first, and the restore then goes straight in.
- File names. After a restore over an existing database, its files and logical names keep the side database's name, for example
myappdb_restore_..._Primary.mdf. The database itself has the right name. - Server logins referenced by database users must exist on the target server. Logins are not part of the backup, so restoring onto another server (for example a backup holding Windows principals onto SQL Server on Linux) fails if they are missing. The target is left untouched.
- Azure SQL Database. The restored database gets the default service objective and is no longer part of its elastic pool, and the side database is billed while it exists.
- Rename failure. If the final rename fails after the target was dropped, the job error names the side database, which holds the restored data. Rename it by hand. The next restore removes it.
- Agents older than 1.26.0 drop the target first, with no way back: if
sqlpackagefails, the target database is gone. Upgrade before restoring anything you cannot lose.
Importing a Backup
Since Dashboard 1.32.0, the Import dialog accepts a raw .dacpac or .bacpac file, or a .tar.gz archive containing one. Since Dashboard 1.36.0, it also accepts .bak. The file keeps its extension, which tells the agent how to restore it. Any other file name is rejected.
Uploads are limited to 2 GB, which a .bak can exceed. Backups taken by the agent have no such limit. Restoring a .bak needs the shared folder options on the target database, whatever its backup_format.
Docker Compose Example
Here is how to configure a MsSQL service alongside the agent.
services:
db-mssql:
container_name: db-mssql
image: mcr.microsoft.com/azure-sql-edge:latest
ports:
- "1433:1433"
environment:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Password!Strong1"
volumes:
- mssql-data:/var/opt/mssql
networks:
- portabase
healthcheck:
test: ["CMD-SHELL", "cat /proc/net/tcp6 | grep -q '059901' || exit 1"]
interval: 10s
timeout: 5s
retries: 20
agent:
image: portabase/agent:latest
# ... agent configuration ...
depends_on:
- db-mssql
networks:
- portabase
networks:
portabase:
external: true
volumes:
mssql-data:If you use localhost as the host (because the agent is on the host machine and not in Docker, or via host-gateway), ensure your database is listening on all interfaces (0.0.0.0) or is accessible from the agent.
Last updated on